diff options
author | Benny Prijono <bennylp@teluu.com> | 2009-10-14 01:58:04 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2009-10-14 01:58:04 +0000 |
commit | 2dd0fe09ceb1675de340d5d4ff84251b3697b435 (patch) | |
tree | 57bbbf8f79d24d908bc2aae95d9134e3cd37d72e | |
parent | b2aac52d83d6e4fb46e2bef723647fa2bb1ad8be (diff) |
Ticket #970: More gracefull PJSUA-LIB shutdown sequence. Enhancements:
- wait for unregistration to complete (or a preconfigured delay expires)
- new account config field to set the maximum delay to wait for unregistration
- rejects incoming requests (INVITE, SUBSCRIBE, and OPTIONS) when shutdown is in progress
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2943 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua.h | 19 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_call.c | 8 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 64 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 2 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_pres.c | 10 |
5 files changed, 83 insertions, 20 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index d6db65b9..c0eb8b25 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -1725,6 +1725,17 @@ PJ_DECL(pj_status_t) pjsua_transport_close( pjsua_transport_id id, /** + * Default maximum time to wait for account unregistration transactions to + * complete during library shutdown sequence. + * + * Default: 4000 (4 seconds) + */ +#ifndef PJSUA_UNREG_TIMEOUT +# define PJSUA_UNREG_TIMEOUT 4000 +#endif + + +/** * Default PUBLISH expiration */ #ifndef PJSUA_PUBLISH_EXPIRATION @@ -1919,6 +1930,14 @@ typedef struct pjsua_acc_config */ unsigned reg_timeout; + /** + * Specify the maximum time to wait for unregistration requests to + * complete during library shutdown sequence. + * + * Default: PJSUA_UNREG_TIMEOUT + */ + unsigned unreg_timeout; + /** * Number of credentials in the credential array. */ diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index c57873f6..a845940c 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -645,6 +645,14 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) if (dlg || tsx) return PJ_FALSE; + /* Don't want to accept the call if shutdown is in progress */ + if (pjsua_var.thread_quit_flag) { + pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, + PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL, + NULL, NULL); + return PJ_TRUE; + } + PJSUA_LOCK(); /* Find free call slot. */ diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 39ad80d8..0b6f48c7 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -161,6 +161,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg) pj_bzero(cfg, sizeof(*cfg)); cfg->reg_timeout = PJSUA_REG_INTERVAL; + cfg->unreg_timeout = PJSUA_UNREG_TIMEOUT; 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; @@ -305,6 +306,14 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata) return PJ_FALSE; } + /* Don't want to handle if shutdown is in progress */ + if (pjsua_var.thread_quit_flag) { + pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, + PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL, + NULL, NULL); + return PJ_TRUE; + } + /* Create basic response. */ status = pjsip_endpt_create_response(pjsua_var.endpt, rdata, 200, NULL, &tdata); @@ -1231,6 +1240,8 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) if (pjsua_var.endpt) { unsigned max_wait; + PJ_LOG(4,(THIS_FILE, "Shutting down...")); + /* Terminate all calls. */ pjsua_call_hangup_all(); @@ -1245,6 +1256,9 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) /* Terminate all presence subscriptions. */ pjsua_pres_shutdown(); + /* Destroy media (to shutdown media transports etc) */ + pjsua_media_subsys_destroy(); + /* Wait for sometime until all publish client sessions are done * (ticket #364) */ @@ -1290,10 +1304,6 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) pjsua_acc_set_registration(i, PJ_FALSE); } } - } - - /* Destroy endpoint. */ - if (pjsua_var.endpt) { /* Terminate any pending STUN resolution */ if (!pj_list_empty(&pjsua_var.stun_res)) { @@ -1305,23 +1315,40 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) } } - /* Wait for some time to allow unregistration and ICE/TURN - * transports shutdown to complete: - */ - PJ_LOG(4,(THIS_FILE, "Shutting down...")); - busy_sleep(1000); + /* Wait until all unregistrations are done (ticket #364) */ + /* First stage, get the maximum wait time */ + max_wait = 100; + for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { + if (!pjsua_var.acc[i].valid) + continue; + if (pjsua_var.acc[i].cfg.unreg_timeout > max_wait) + max_wait = pjsua_var.acc[i].cfg.unreg_timeout; + } + + /* Second stage, wait for unregistrations to complete */ + for (i=0; i<(int)(max_wait/50); ++i) { + unsigned j; + for (j=0; j<PJ_ARRAY_SIZE(pjsua_var.acc); ++j) { + if (!pjsua_var.acc[j].valid) + continue; - PJ_LOG(4,(THIS_FILE, "Destroying...")); + if (pjsua_var.acc[j].regc) + break; + } + if (j != PJ_ARRAY_SIZE(pjsua_var.acc)) + busy_sleep(50); + else + break; + } + /* Note variable 'i' is used below */ - /* Terminate all calls again, just in case there's new call - * picked up during busy_sleep() + /* Wait for some time to allow unregistration and ICE/TURN + * transports shutdown to complete: */ - pjsua_call_hangup_all(); + if (i < 20) + busy_sleep(1000 - i*50); - /* Destroy media after all polling is done, as there may be - * incoming request that needs handling (e.g. OPTIONS) - */ - pjsua_media_subsys_destroy(); + PJ_LOG(4,(THIS_FILE, "Destroying...")); /* Must destroy endpoint first before destroying pools in * buddies or accounts, since shutting down transaction layer @@ -1346,9 +1373,6 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) pjsua_var.acc[i].pool = NULL; } } - } else { - /* Destroy media */ - pjsua_media_subsys_destroy(); } /* Destroy mutex */ diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 243f4f65..01f33a1c 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -640,6 +640,8 @@ pj_status_t pjsua_media_subsys_destroy(void) { unsigned i; + PJ_LOG(4,(THIS_FILE, "Shutting down media..")); + close_snd_dev(); if (pjsua_var.mconf) { diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c index 4515636c..935a41e7 100644 --- a/pjsip/src/pjsua-lib/pjsua_pres.c +++ b/pjsip/src/pjsua-lib/pjsua_pres.c @@ -682,6 +682,14 @@ static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata) /* Incoming SUBSCRIBE: */ + /* Don't want to accept the request if shutdown is in progress */ + if (pjsua_var.thread_quit_flag) { + pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, + PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL, + NULL, NULL); + return PJ_TRUE; + } + PJSUA_LOCK(); /* Find which account for the incoming request. */ @@ -1721,6 +1729,8 @@ void pjsua_pres_shutdown(void) { unsigned i; + PJ_LOG(4,(THIS_FILE, "Shutting down presence..")); + if (pjsua_var.pres_timer.id != 0) { pjsip_endpt_cancel_timer(pjsua_var.endpt, &pjsua_var.pres_timer); pjsua_var.pres_timer.id = PJ_FALSE; |