From b2aac52d83d6e4fb46e2bef723647fa2bb1ad8be Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 13 Oct 2009 14:01:59 +0000 Subject: Ticket #364: Upon unregistration, (un)REGISTER should be sent only after (un)PUBLISH has completed successfully - wait for unpublication to complete or some delay expires, before sending unregistration - added unpublish_max_wait_time_msec field in account config to control how long to wait git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2942 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsua-lib/pjsua.h | 29 +++++++++++++++++++++++++++++ pjsip/src/pjsua-lib/pjsua_core.c | 39 +++++++++++++++++++++++++++++++++++++++ pjsip/src/pjsua-lib/pjsua_pres.c | 5 ++++- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index bb6558db..d6db65b9 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -1750,6 +1750,22 @@ PJ_DECL(pj_status_t) pjsua_transport_close( pjsua_transport_id id, #endif +/** + * Maximum time to wait for unpublication transaction(s) to complete + * during shutdown process, before sending unregistration. The library + * tries to wait for the unpublication (un-PUBLISH) to complete before + * sending REGISTER request to unregister the account, during library + * shutdown process. If the value is set too short, it is possible that + * the unregistration is sent before unpublication completes, causing + * unpublication request to fail. + * + * Default: 2000 (2 seconds) + */ +#ifndef PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC +# define PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC 2000 +#endif + + /** * This structure describes account configuration to be specified when * adding a new account with #pjsua_acc_add(). Application MUST initialize @@ -1801,6 +1817,19 @@ typedef struct pjsua_acc_config */ pjsip_publishc_opt publish_opt; + /** + * Maximum time to wait for unpublication transaction(s) to complete + * during shutdown process, before sending unregistration. The library + * tries to wait for the unpublication (un-PUBLISH) to complete before + * sending REGISTER request to unregister the account, during library + * shutdown process. If the value is set too short, it is possible that + * the unregistration is sent before unpublication completes, causing + * unpublication request to fail. + * + * Default: PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC + */ + unsigned unpublish_max_wait_time_msec; + /** * Authentication preference. */ diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index cc26bc87..39ad80d8 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -162,6 +162,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg) cfg->reg_timeout = PJSUA_REG_INTERVAL; pjsip_publishc_opt_default(&cfg->publish_opt); + cfg->unpublish_max_wait_time_msec = PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC; cfg->transport_id = PJSUA_INVALID_ID; cfg->allow_contact_rewrite = PJ_TRUE; cfg->require_100rel = pjsua_var.ua_cfg.require_100rel; @@ -1228,6 +1229,8 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) } if (pjsua_var.endpt) { + unsigned max_wait; + /* Terminate all calls. */ pjsua_call_hangup_all(); @@ -1242,6 +1245,42 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) /* Terminate all presence subscriptions. */ pjsua_pres_shutdown(); + /* Wait for sometime until all publish client sessions are done + * (ticket #364) + */ + /* First stage, get the maximum wait time */ + max_wait = 100; + for (i=0; i max_wait) + max_wait = pjsua_var.acc[i].cfg.unpublish_max_wait_time_msec; + } + + /* Second stage, wait for unpublications to complete */ + for (i=0; i<(int)(max_wait/50); ++i) { + unsigned j; + for (j=0; jexpiration == -1) { + if (param->expiration < 1) { /* Could happen if server "forgot" to include Expires header * in the response. We will not renew, so destroy the pubc. */ @@ -1201,10 +1201,13 @@ void pjsua_pres_delete_acc(int acc_id) if (acc->publish_sess) { acc->online_status = PJ_FALSE; send_publish(acc_id, PJ_FALSE); + /* By ticket #364, don't destroy the session yet (let the callback + destroy it) if (acc->publish_sess) { pjsip_publishc_destroy(acc->publish_sess); acc->publish_sess = NULL; } + */ acc_cfg->publish_enabled = PJ_FALSE; } } -- cgit v1.2.3