diff options
Diffstat (limited to 'pjsip/src/pjsua-lib')
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_acc.c | 56 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_call.c | 73 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 35 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 55 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_pres.c | 44 |
5 files changed, 203 insertions, 60 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index 9bcd1ddd..226f5d1f 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -470,9 +470,10 @@ PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg, (int)cfg->id.slen, cfg->id.ptr, id)); /* If accounts has registration enabled, start registration */ - if (pjsua_var.acc[id].cfg.reg_uri.slen) - pjsua_acc_set_registration(id, PJ_TRUE); - else { + if (pjsua_var.acc[id].cfg.reg_uri.slen) { + if (pjsua_var.acc[id].cfg.register_on_acc_add) + pjsua_acc_set_registration(id, PJ_TRUE); + } else { /* Otherwise subscribe to MWI, if it's enabled */ if (pjsua_var.acc[id].cfg.mwi_enabled) pjsua_start_mwi(&pjsua_var.acc[id]); @@ -603,7 +604,7 @@ PJ_DEF(pj_status_t) pjsua_acc_del(pjsua_acc_id acc_id) } /* Delete server presence subscription */ - pjsua_pres_delete_acc(acc_id); + pjsua_pres_delete_acc(acc_id, 0); /* Release account pool */ if (pjsua_var.acc[acc_id].pool) { @@ -833,7 +834,7 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, if (acc->cfg.publish_enabled != cfg->publish_enabled) { acc->cfg.publish_enabled = cfg->publish_enabled; if (!acc->cfg.publish_enabled) - pjsua_pres_unpublish(acc); + pjsua_pres_unpublish(acc, 0); else update_reg = PJ_TRUE; } @@ -992,6 +993,7 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, acc->cfg.unreg_timeout = cfg->unreg_timeout; acc->cfg.allow_contact_rewrite = cfg->allow_contact_rewrite; acc->cfg.reg_retry_interval = cfg->reg_retry_interval; + acc->cfg.reg_first_retry_interval = cfg->reg_first_retry_interval; acc->cfg.drop_calls_on_reg_fail = cfg->drop_calls_on_reg_fail; if (acc->cfg.reg_delay_before_refresh != cfg->reg_delay_before_refresh) { acc->cfg.reg_delay_before_refresh = cfg->reg_delay_before_refresh; @@ -1393,7 +1395,7 @@ static pj_bool_t acc_check_nat_addr(pjsua_acc *acc, tp->type_name, (int)acc->cfg.contact_uri_params.slen, acc->cfg.contact_uri_params.ptr, - ob, + (acc->cfg.use_rfc5626? ob: ""), (int)acc->cfg.contact_params.slen, acc->cfg.contact_params.ptr); if (len < 1) { @@ -1691,11 +1693,14 @@ static void regc_cb(struct pjsip_regc_cbparam *param) pjsua_acc *acc = (pjsua_acc*) param->token; - if (param->regc != acc->regc) + PJSUA_LOCK(); + + if (param->regc != acc->regc) { + PJSUA_UNLOCK(); return; + } pj_log_push_indent(); - PJSUA_LOCK(); /* * Print registration status. @@ -2054,7 +2059,7 @@ PJ_DEF(pj_status_t) pjsua_acc_set_registration( pjsua_acc_id acc_id, goto on_return; } - pjsua_pres_unpublish(&pjsua_var.acc[acc_id]); + pjsua_pres_unpublish(&pjsua_var.acc[acc_id], 0); status = pjsip_regc_unregister(pjsua_var.acc[acc_id].regc, &tdata); } @@ -2070,6 +2075,10 @@ PJ_DEF(pj_status_t) pjsua_acc_set_registration( pjsua_acc_id acc_id, pjsip_regc_get_info(pjsua_var.acc[acc_id].regc, ®_info); pjsua_var.acc[acc_id].auto_rereg.reg_tp = reg_info.transport; + + if (pjsua_var.ua_cfg.cb.on_reg_started) { + (*pjsua_var.ua_cfg.cb.on_reg_started)(acc_id, renew); + } } if (status != PJ_SUCCESS) { @@ -2529,10 +2538,11 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool, /* Create the contact header */ contact->ptr = (char*)pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE, - "%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s%s>%.*s", + "%s%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s%s>%.*s", + (acc->display.slen?"\"" : ""), (int)acc->display.slen, acc->display.ptr, - (acc->display.slen?" " : ""), + (acc->display.slen?"\" " : ""), (secure ? PJSUA_SECURE_SCHEME : "sip"), (int)acc->user_part.slen, acc->user_part.ptr, @@ -2545,7 +2555,7 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool, transport_param, (int)acc->cfg.contact_uri_params.slen, acc->cfg.contact_uri_params.ptr, - ob, + (acc->cfg.use_rfc5626? ob: ""), (int)acc->cfg.contact_params.slen, acc->cfg.contact_params.ptr); @@ -2687,10 +2697,11 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uas_contact( pj_pool_t *pool, /* Create the contact header */ contact->ptr = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE, - "%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s>%.*s", + "%s%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s>%.*s", + (acc->display.slen?"\"" : ""), (int)acc->display.slen, acc->display.ptr, - (acc->display.slen?" " : ""), + (acc->display.slen?"\" " : ""), (secure ? PJSUA_SECURE_SCHEME : "sip"), (int)acc->user_part.slen, acc->user_part.ptr, @@ -2807,8 +2818,23 @@ static void schedule_reregistration(pjsua_acc *acc) acc->auto_rereg.timer.user_data = acc; /* Reregistration attempt. The first attempt will be done immediately. */ - delay.sec = acc->auto_rereg.attempt_cnt? acc->cfg.reg_retry_interval : 0; + delay.sec = acc->auto_rereg.attempt_cnt? acc->cfg.reg_retry_interval : + acc->cfg.reg_first_retry_interval; delay.msec = 0; + + /* Randomize interval by +/- 10 secs */ + if (delay.sec >= 10) { + delay.msec = -10000 + (pj_rand() % 20000); + } else { + delay.sec = 0; + delay.msec = (pj_rand() % 10000); + } + pj_time_val_normalize(&delay); + + PJ_LOG(4,(THIS_FILE, + "Scheduling re-registration retry for acc %d in %u seconds..", + acc->index, delay.sec)); + pjsua_schedule_timer(&acc->auto_rereg.timer, &delay); } diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index ad96a4d6..02a78b93 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -971,7 +971,7 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) /* Verify that we can handle the request. */ options |= PJSIP_INV_SUPPORT_100REL; options |= PJSIP_INV_SUPPORT_TIMER; - if (pjsua_var.acc[acc_id].cfg.require_100rel) + if (pjsua_var.acc[acc_id].cfg.require_100rel == PJSUA_100REL_MANDATORY) options |= PJSIP_INV_REQUIRE_100REL; if (pjsua_var.media_cfg.enable_ice) options |= PJSIP_INV_SUPPORT_ICE; @@ -1047,6 +1047,19 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) options &= ~(PJSIP_INV_SUPPORT_TIMER); } + /* If 100rel is optional and UAC supports it, use it. */ + if ((options & PJSIP_INV_REQUIRE_100REL)==0 && + pjsua_var.acc[acc_id].cfg.require_100rel == PJSUA_100REL_OPTIONAL) + { + const pj_str_t token = { "100rel", 6}; + pjsip_dialog_cap_status cap_status; + + cap_status = pjsip_dlg_remote_has_cap(dlg, PJSIP_H_SUPPORTED, NULL, + &token); + if (cap_status == PJSIP_DIALOG_CAP_SUPPORTED) + options |= PJSIP_INV_REQUIRE_100REL; + } + /* Create invite session: */ status = pjsip_inv_create_uas( dlg, rdata, NULL, options, &inv); if (status != PJ_SUCCESS) { @@ -1288,6 +1301,7 @@ pj_status_t acquire_call(const char *title, pj_time_val time_start, timeout; pj_gettimeofday(&time_start); + timeout.sec = 0; timeout.msec = PJSUA_ACQUIRE_CALL_TIMEOUT; pj_time_val_normalize(&timeout); @@ -1356,20 +1370,24 @@ pj_status_t acquire_call(const char *title, PJ_DEF(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id) { pjsua_call *call; - pjsua_conf_port_id port_id; - pjsip_dialog *dlg; - pj_status_t status; + pjsua_conf_port_id port_id = PJSUA_INVALID_ID; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); - status = acquire_call("pjsua_call_get_conf_port()", call_id, &call, &dlg); - if (status != PJ_SUCCESS) - return PJSUA_INVALID_ID; + /* Use PJSUA_LOCK() instead of acquire_call(): + * https://trac.pjsip.org/repos/ticket/1371 + */ + PJSUA_LOCK(); + if (!pjsua_call_is_active(call_id)) + goto on_return; + + call = &pjsua_var.calls[call_id]; port_id = call->media[call->audio_idx].strm.a.conf_slot; - pjsip_dlg_dec_lock(dlg); +on_return: + PJSUA_UNLOCK(); return port_id; } @@ -1383,18 +1401,23 @@ PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id, pjsua_call_info *info) { pjsua_call *call; - pjsip_dialog *dlg; unsigned mi; - pj_status_t status; PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, PJ_EINVAL); pj_bzero(info, sizeof(*info)); - status = acquire_call("pjsua_call_get_info()", call_id, &call, &dlg); - if (status != PJ_SUCCESS) { - return status; + /* Use PJSUA_LOCK() instead of acquire_call(): + * https://trac.pjsip.org/repos/ticket/1371 + */ + PJSUA_LOCK(); + + call = &pjsua_var.calls[call_id]; + + if (!call->inv) { + PJSUA_UNLOCK(); + return PJSIP_ESESSIONTERMINATED; } /* id and role */ @@ -1520,7 +1543,7 @@ PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id, PJ_TIME_VAL_SUB(info->total_duration, call->start_time); } - pjsip_dlg_dec_lock(dlg); + PJSUA_UNLOCK(); return PJ_SUCCESS; } @@ -1961,10 +1984,14 @@ PJ_DEF(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id, /* Add additional headers etc */ pjsua_process_msg_data( tdata, msg_data); + /* Record the tx_data to keep track the operation */ + call->hold_msg = (void*) tdata; + /* Send the request */ status = pjsip_inv_send_msg( call->inv, tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); + call->hold_msg = NULL; goto on_return; } @@ -2531,14 +2558,15 @@ PJ_DEF(void) pjsua_call_hangup_all(void) PJ_LOG(4,(THIS_FILE, "Hangup all calls..")); pj_log_push_indent(); - PJSUA_LOCK(); + // This may deadlock, see https://trac.pjsip.org/repos/ticket/1305 + //PJSUA_LOCK(); for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { if (pjsua_var.calls[i].inv) pjsua_call_hangup(i, 0, NULL, NULL); } - PJSUA_UNLOCK(); + //PJSUA_UNLOCK(); pj_log_pop_indent(); } @@ -3971,9 +3999,22 @@ static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, &tsx->status_text); } } + } else if (tsx->role == PJSIP_ROLE_UAC && + tsx->last_tx == (pjsip_tx_data*)call->hold_msg && + tsx->state >= PJSIP_TSX_STATE_COMPLETED) + { + /* Monitor the status of call hold request */ + call->hold_msg = NULL; + if (tsx->status_code/100 != 2) { + /* Outgoing call hold failed */ + call->local_hold = PJ_FALSE; + PJ_LOG(3,(THIS_FILE, "Error putting call %d on hold (reason=%d)", + call->index, tsx->status_code)); + } } on_return: + PJSUA_UNLOCK(); pj_log_pop_indent(); } diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 31133b2c..52054226 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -234,6 +234,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg) pj_list_init(&cfg->reg_hdr_list); pj_list_init(&cfg->sub_hdr_list); cfg->call_hold_type = PJSUA_CALL_HOLD_TYPE_DEFAULT; + cfg->register_on_acc_add = PJ_TRUE; } PJ_DEF(void) pjsua_buddy_config_default(pjsua_buddy_config *cfg) @@ -1340,7 +1341,7 @@ pj_status_t resolve_stun_server(pj_bool_t wait) /* * Destroy pjsua. */ -PJ_DEF(pj_status_t) pjsua_destroy(void) +PJ_DEF(pj_status_t) pjsua_destroy2(unsigned flags) { int i; /* Must be signed */ @@ -1365,12 +1366,14 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) if (pjsua_var.endpt) { unsigned max_wait; - PJ_LOG(4,(THIS_FILE, "Shutting down...")); + PJ_LOG(4,(THIS_FILE, "Shutting down, flags=%d...", flags)); pj_log_push_indent(); /* Terminate all calls. */ - pjsua_call_hangup_all(); + if ((flags & PJSUA_DESTROY_NO_TX_MSG) == 0) { + pjsua_call_hangup_all(); + } /* Set all accounts to offline */ for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { @@ -1381,10 +1384,10 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) } /* Terminate all presence subscriptions. */ - pjsua_pres_shutdown(); + pjsua_pres_shutdown(flags); /* Destroy media (to shutdown media transports etc) */ - pjsua_media_subsys_destroy(); + pjsua_media_subsys_destroy(flags); /* Wait for sometime until all publish client sessions are done * (ticket #364) @@ -1398,6 +1401,11 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) max_wait = pjsua_var.acc[i].cfg.unpublish_max_wait_time_msec; } + /* No waiting if RX is disabled */ + if (flags & PJSUA_DESTROY_NO_RX_MSG) { + max_wait = 0; + } + /* Second stage, wait for unpublications to complete */ for (i=0; i<(int)(max_wait/50); ++i) { unsigned j; @@ -1427,7 +1435,8 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) if (!pjsua_var.acc[i].valid) continue; - if (pjsua_var.acc[i].regc) { + if (pjsua_var.acc[i].regc && (flags & PJSUA_DESTROY_NO_TX_MSG)==0) + { pjsua_acc_set_registration(i, PJ_FALSE); } } @@ -1452,6 +1461,11 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) max_wait = pjsua_var.acc[i].cfg.unreg_timeout; } + /* No waiting if RX is disabled */ + if (flags & PJSUA_DESTROY_NO_RX_MSG) { + max_wait = 0; + } + /* Second stage, wait for unregistrations to complete */ for (i=0; i<(int)(max_wait/50); ++i) { unsigned j; @@ -1472,8 +1486,9 @@ PJ_DEF(pj_status_t) pjsua_destroy(void) /* Wait for some time to allow unregistration and ICE/TURN * transports shutdown to complete: */ - if (i < 20) + if (i < 20 && (flags & PJSUA_DESTROY_NO_RX_MSG) == 0) { busy_sleep(1000 - i*50); + } PJ_LOG(4,(THIS_FILE, "Destroying...")); @@ -1560,6 +1575,12 @@ PJ_DEF(pjsua_state) pjsua_get_state(void) return pjsua_var.state; } +PJ_DEF(pj_status_t) pjsua_destroy(void) +{ + return pjsua_destroy2(0); +} + + /** * Application is recommended to call this function after all initialization * is done, so that the library can do additional checking set up diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index e7743659..60aebbeb 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -396,7 +396,7 @@ pj_status_t pjsua_media_subsys_start(void) /* * Destroy pjsua media subsystem. */ -pj_status_t pjsua_media_subsys_destroy(void) +pj_status_t pjsua_media_subsys_destroy(unsigned flags) { unsigned i; @@ -441,6 +441,10 @@ pj_status_t pjsua_media_subsys_destroy(void) pjsua_media_channel_deinit(i); } if (call_med->tp && call_med->tp_auto_del) { + /* TODO: check if we're not allowed to send to network in the + * "flags", and if so do not do TURN allocation... + */ + PJ_UNUSED_ARG(flags); pjmedia_transport_close(call_med->tp); } call_med->tp = NULL; @@ -1294,11 +1298,18 @@ static pj_status_t call_media_init_cb(pjsua_call_media *call_med, if (call_med->tp_st == PJSUA_MED_TP_CREATING) set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); + if (!call_med->tp_orig && + pjsua_var.ua_cfg.cb.on_create_media_transport) + { + call_med->use_custom_med_tp = PJ_TRUE; + } else + call_med->use_custom_med_tp = PJ_FALSE; + #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) /* This function may be called when SRTP transport already exists * (e.g: in re-invite, update), don't need to destroy/re-create. */ - if (!call_med->tp_orig || call_med->tp == call_med->tp_orig) { + if (!call_med->tp_orig) { pjmedia_srtp_setting srtp_opt; pjmedia_transport *srtp = NULL; @@ -1314,7 +1325,7 @@ static pj_status_t call_media_init_cb(pjsua_call_media *call_med, /* Always create SRTP adapter */ pjmedia_srtp_setting_default(&srtp_opt); srtp_opt.close_member_tp = PJ_TRUE; - /* If media session has been ever established, let's use remote's + /* If media session has been ever established, let's use remote's * preference in SRTP usage policy, especially when it is stricter. */ if (call_med->rem_srtp_use > acc->cfg.use_srtp) @@ -1519,9 +1530,25 @@ static pj_status_t media_channel_init_cb(pjsua_call_id call_id, call->async_call.dlg->pool); } - status = pjmedia_transport_media_create( - call_med->tp, tmp_pool, - 0, call->async_call.rem_sdp, mi); + if (call_med->use_custom_med_tp) { + unsigned custom_med_tp_flags = 0; + + /* Use custom media transport returned by the application */ + call_med->tp = + (*pjsua_var.ua_cfg.cb.on_create_media_transport) + (call_id, mi, call_med->tp, + custom_med_tp_flags); + if (!call_med->tp) { + status = + PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE); + } + } + + if (call_med->tp) { + status = pjmedia_transport_media_create( + call_med->tp, tmp_pool, + 0, call->async_call.rem_sdp, mi); + } if (status != PJ_SUCCESS) { call->med_ch_info.status = status; call->med_ch_info.med_idx = mi; @@ -2104,6 +2131,7 @@ static void stop_media_session(pjsua_call_id call_id) PJ_LOG(4,(THIS_FILE, "Media session call%02d:%d is destroyed", call_id, mi)); + call_med->prev_state = call_med->state; call_med->state = PJSUA_CALL_MEDIA_NONE; } @@ -2133,12 +2161,19 @@ pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id) PJ_LOG(4,(THIS_FILE, "Call %d: deinitializing media..", call_id)); pj_log_push_indent(); + for (mi=0; mi<call->med_cnt; ++mi) { + pjsua_call_media *call_med = &call->media[mi]; + + if (call_med->type == PJMEDIA_TYPE_AUDIO && call_med->strm.a.stream) + pjmedia_stream_send_rtcp_bye(call_med->strm.a.stream); + } + stop_media_session(call_id); for (mi=0; mi<call->med_cnt; ++mi) { pjsua_call_media *call_med = &call->media[mi]; - if (call_med->tp_st > PJSUA_MED_TP_IDLE) { + if (call_med->tp_st > PJSUA_MED_TP_IDLE) { pjmedia_transport_media_stop(call_med->tp); set_media_tp_state(call_med, PJSUA_MED_TP_IDLE); } @@ -2153,6 +2188,7 @@ pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id) pjmedia_transport_close(call_med->tp); call_med->tp = call_med->tp_orig = NULL; } + call_med->tp_orig = NULL; } check_snd_dev_idle(); @@ -2206,6 +2242,8 @@ static pj_status_t audio_channel_update(pjsua_call_media *call_med, if (status != PJ_SUCCESS) goto on_return; + si->rtcp_sdes_bye_disabled = PJ_TRUE; + /* Check if no media is active */ if (si->dir == PJMEDIA_DIR_NONE) { /* Call media state */ @@ -2296,6 +2334,9 @@ static pj_status_t audio_channel_update(pjsua_call_media *call_med, goto on_return; } + if (call_med->prev_state == PJSUA_CALL_MEDIA_NONE) + pjmedia_stream_send_rtcp_sdes(call_med->strm.a.stream); + /* If DTMF callback is installed by application, install our * callback to the session. */ diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c index 88ea317f..c78e8b5c 100644 --- a/pjsip/src/pjsua-lib/pjsua_pres.c +++ b/pjsip/src/pjsua-lib/pjsua_pres.c @@ -1320,13 +1320,17 @@ pj_status_t pjsua_pres_init_acc(int acc_id) /* Unpublish presence publication */ -void pjsua_pres_unpublish(pjsua_acc *acc) +void pjsua_pres_unpublish(pjsua_acc *acc, unsigned flags) { if (acc->publish_sess) { pjsua_acc_config *acc_cfg = &acc->cfg; acc->online_status = PJ_FALSE; - send_publish(acc->index, PJ_FALSE); + + if ((flags & PJSUA_DESTROY_NO_TX_MSG) == 0) { + send_publish(acc->index, PJ_FALSE); + } + /* By ticket #364, don't destroy the session yet (let the callback destroy it) if (acc->publish_sess) { @@ -1339,7 +1343,7 @@ void pjsua_pres_unpublish(pjsua_acc *acc) } /* Terminate server subscription for the account */ -void pjsua_pres_delete_acc(int acc_id) +void pjsua_pres_delete_acc(int acc_id, unsigned flags) { pjsua_acc *acc = &pjsua_var.acc[acc_id]; pjsua_srv_pres *uapres; @@ -1361,11 +1365,15 @@ void pjsua_pres_delete_acc(int acc_id) pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status; pjsip_pres_set_status(uapres->sub, &pres_status); - if (pjsip_pres_notify(uapres->sub, - PJSIP_EVSUB_STATE_TERMINATED, NULL, - &reason, &tdata)==PJ_SUCCESS) - { - pjsip_pres_send_request(uapres->sub, tdata); + if ((flags & PJSUA_DESTROY_NO_TX_MSG) == 0) { + if (pjsip_pres_notify(uapres->sub, + PJSIP_EVSUB_STATE_TERMINATED, NULL, + &reason, &tdata)==PJ_SUCCESS) + { + pjsip_pres_send_request(uapres->sub, tdata); + } + } else { + pjsip_pres_terminate(uapres->sub, PJ_FALSE); } uapres = next; @@ -1376,7 +1384,7 @@ void pjsua_pres_delete_acc(int acc_id) pj_list_init(&acc->pres_srv_list); /* Terminate presence publication, if any */ - pjsua_pres_unpublish(acc); + pjsua_pres_unpublish(acc, flags); } @@ -2251,6 +2259,10 @@ static void pres_timer_cb(pj_timer_heap_t *th, for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { pjsua_acc *acc = &pjsua_var.acc[i]; + /* Acc may not be ready yet, otherwise assertion will happen */ + if (!pjsua_acc_is_valid(i)) + continue; + /* Retry PUBLISH */ if (acc->cfg.publish_enabled && acc->publish_sess==NULL) pjsua_pres_init_publish_acc(acc->index); @@ -2324,7 +2336,7 @@ pj_status_t pjsua_pres_start(void) /* * Shutdown presence. */ -void pjsua_pres_shutdown(void) +void pjsua_pres_shutdown(unsigned flags) { unsigned i; @@ -2339,18 +2351,20 @@ void pjsua_pres_shutdown(void) for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { if (!pjsua_var.acc[i].valid) continue; - pjsua_pres_delete_acc(i); + pjsua_pres_delete_acc(i, flags); } for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) { pjsua_var.buddy[i].monitor = 0; } - refresh_client_subscriptions(); + if ((flags & PJSUA_DESTROY_NO_TX_MSG) == 0) { + refresh_client_subscriptions(); - for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { - if (pjsua_var.acc[i].valid) - pjsua_pres_update_acc(i, PJ_FALSE); + for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) { + if (pjsua_var.acc[i].valid) + pjsua_pres_update_acc(i, PJ_FALSE); + } } pj_log_pop_indent(); |