summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsua-lib
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsua-lib')
-rw-r--r--pjsip/src/pjsua-lib/pjsua_acc.c56
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c73
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c35
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c55
-rw-r--r--pjsip/src/pjsua-lib/pjsua_pres.c44
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, &reg_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();