Fixed several bugs in PJSUA-API:
- in some condition, when outgoing call fails, call count
incorrectly decremented to -1
- introduce account priority in pjsua_acc_config, and
improve the account searching for incoming calls
- pjsua will hangup call after sending transfer/REFER request.
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@737 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 0a106f4..82e22ab 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -1020,10 +1020,25 @@
/**
+ * Default account priority.
+ */
+#ifndef PJSUA_DEFAULT_ACC_PRIORITY
+# define PJSUA_DEFAULT_ACC_PRIORITY 0
+#endif
+
+
+/**
* Account configuration.
*/
typedef struct pjsua_acc_config
{
+ /**
+ * Account priority, which is used to control the order of matching
+ * incoming/outgoing requests. The higher the number means the higher
+ * the priority is, and the account will be matched first.
+ */
+ int priority;
+
/**
* The full SIP URL for the account. The value can take name address or
* URL format, and will look something like "sip:account@serviceprovider".
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index 10e7663..ca9a51d 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -189,6 +189,7 @@
unsigned acc_cnt; /**< Number of accounts. */
pjsua_acc_id default_acc; /**< Default account ID */
pjsua_acc acc[PJSUA_MAX_ACC]; /**< Account array. */
+ pjsua_acc_id acc_ids[PJSUA_MAX_ACC]; /**< Acc sorted by prio*/
/* Calls: */
pjsua_config ua_cfg; /**< UA config. */
diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c
index d545bdf..5578e7f 100644
--- a/pjsip/src/pjsua-lib/pjsua_acc.c
+++ b/pjsip/src/pjsua-lib/pjsua_acc.c
@@ -229,6 +229,16 @@
/* Mark account as valid */
pjsua_var.acc[acc_id].valid = PJ_TRUE;
+ /* Insert account ID into account ID array, sorted by priority */
+ for (i=0; i<pjsua_var.acc_cnt; ++i) {
+ if ( pjsua_var.acc[pjsua_var.acc_ids[i]].cfg.priority <
+ pjsua_var.acc[acc_id].cfg.priority)
+ {
+ break;
+ }
+ }
+ pj_array_insert(pjsua_var.acc_ids, sizeof(pjsua_var.acc_ids[0]),
+ pjsua_var.acc_cnt, i, &acc_id);
return PJ_SUCCESS;
}
@@ -321,6 +331,9 @@
pjsua_acc_config_default(&cfg);
+ /* Lower the priority of local account */
+ --cfg.priority;
+
/* Build URI for the account */
pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE,
"<sip:%.*s:%d;transport=%s>",
@@ -340,6 +353,8 @@
*/
PJ_DEF(pj_status_t) pjsua_acc_del(pjsua_acc_id acc_id)
{
+ unsigned i;
+
PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc),
PJ_EINVAL);
PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP);
@@ -356,6 +371,17 @@
/* Invalidate */
pjsua_var.acc[acc_id].valid = PJ_FALSE;
+ /* Remove from array */
+ for (i=0; i<pjsua_var.acc_cnt; ++i) {
+ if (pjsua_var.acc_ids[i] == acc_id)
+ break;
+ }
+ if (i != pjsua_var.acc_cnt) {
+ pj_array_erase(pjsua_var.acc_ids, sizeof(pjsua_var.acc_ids[0]),
+ pjsua_var.acc_cnt, i);
+ --pjsua_var.acc_cnt;
+ }
+
PJ_TODO(may_need_to_scan_calls);
PJSUA_UNLOCK();
@@ -709,7 +735,7 @@
pj_str_t tmp;
pjsip_uri *uri;
pjsip_sip_uri *sip_uri;
- unsigned acc_id;
+ unsigned i;
PJSUA_LOCK();
@@ -719,74 +745,59 @@
uri = pjsip_parse_uri(pjsua_var.pool, tmp.ptr, tmp.slen, 0);
if (!uri) {
- acc_id = pjsua_var.default_acc;
- goto on_return;
+ PJSUA_UNLOCK();
+ return pjsua_var.default_acc;
}
if (!PJSIP_URI_SCHEME_IS_SIP(uri) &&
!PJSIP_URI_SCHEME_IS_SIPS(uri))
{
/* Return the first account with proxy */
- for (acc_id=0; acc_id<PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) {
- if (!pjsua_var.acc[acc_id].valid)
+ for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
+ if (!pjsua_var.acc[i].valid)
continue;
- if (!pj_list_empty(&pjsua_var.acc[acc_id].route_set))
+ if (!pj_list_empty(&pjsua_var.acc[i].route_set))
break;
}
- if (acc_id != PJ_ARRAY_SIZE(pjsua_var.acc)) {
+ if (i != PJ_ARRAY_SIZE(pjsua_var.acc)) {
/* Found rather matching account */
- goto on_return;
+ PJSUA_UNLOCK();
+ return 0;
}
/* Not found, use default account */
- acc_id = pjsua_var.default_acc;
- goto on_return;
+ PJSUA_UNLOCK();
+ return pjsua_var.default_acc;
}
sip_uri = pjsip_uri_get_uri(uri);
- /* See if default acc match */
- if (pjsua_var.default_acc != PJSUA_INVALID_ID &&
- pj_stricmp(&pjsua_var.acc[pjsua_var.default_acc].srv_domain, &sip_uri->host)==0 &&
- pjsua_var.acc[pjsua_var.default_acc].srv_port == sip_uri->port)
- {
- acc_id = pjsua_var.default_acc;
- } else {
- acc_id = PJ_ARRAY_SIZE(pjsua_var.acc);
- }
-
/* Find matching domain AND port */
- if (acc_id == PJ_ARRAY_SIZE(pjsua_var.acc)) {
- for (acc_id=0; acc_id<PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) {
- if (!pjsua_var.acc[acc_id].valid)
- continue;
- if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0 &&
- pjsua_var.acc[acc_id].srv_port == sip_uri->port)
- break;
+ for (i=0; i<pjsua_var.acc_cnt; ++i) {
+ unsigned acc_id = pjsua_var.acc_ids[i];
+ if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0 &&
+ pjsua_var.acc[acc_id].srv_port == sip_uri->port)
+ {
+ PJSUA_UNLOCK();
+ return acc_id;
}
}
/* If no match, try to match the domain part only */
- if (acc_id == PJ_ARRAY_SIZE(pjsua_var.acc)) {
- /* Just use default account */
- for (acc_id=0; acc_id<PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) {
- if (!pjsua_var.acc[acc_id].valid)
- continue;
- if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0)
- break;
+ for (i=0; i<pjsua_var.acc_cnt; ++i) {
+ unsigned acc_id = pjsua_var.acc_ids[i];
+ if (pj_stricmp(&pjsua_var.acc[acc_id].srv_domain, &sip_uri->host)==0)
+ {
+ PJSUA_UNLOCK();
+ return acc_id;
}
}
- if (acc_id == PJ_ARRAY_SIZE(pjsua_var.acc)) {
- /* Just use default account */
- acc_id = pjsua_var.default_acc;
- }
-on_return:
+ /* Still no match, just use default account */
PJSUA_UNLOCK();
-
- return acc_id;
+ return pjsua_var.default_acc;
}
@@ -798,7 +809,7 @@
{
pjsip_uri *uri;
pjsip_sip_uri *sip_uri;
- unsigned acc_id;
+ unsigned i;
uri = rdata->msg_info.to->uri;
@@ -815,8 +826,8 @@
sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri);
/* Find account which has matching username and domain. */
- for (acc_id=0; acc_id < pjsua_var.acc_cnt; ++acc_id) {
-
+ for (i=0; i < pjsua_var.acc_cnt; ++i) {
+ unsigned acc_id = pjsua_var.acc_ids[i];
pjsua_acc *acc = &pjsua_var.acc[acc_id];
if (pj_stricmp(&acc->user_part, &sip_uri->user)==0 &&
@@ -828,9 +839,9 @@
}
}
- /* No matching, try match domain part only. */
- for (acc_id=0; acc_id < pjsua_var.acc_cnt; ++acc_id) {
-
+ /* No matching account, try match domain part only. */
+ for (i=0; i < pjsua_var.acc_cnt; ++i) {
+ unsigned acc_id = pjsua_var.acc_ids[i];
pjsua_acc *acc = &pjsua_var.acc[acc_id];
if (pj_stricmp(&acc->srv_domain, &sip_uri->host)==0) {
@@ -840,6 +851,18 @@
}
}
+ /* No matching account, try match user part only. */
+ for (i=0; i < pjsua_var.acc_cnt; ++i) {
+ unsigned acc_id = pjsua_var.acc_ids[i];
+ pjsua_acc *acc = &pjsua_var.acc[acc_id];
+
+ if (pj_stricmp(&acc->user_part, &sip_uri->user)==0) {
+ /* Match ! */
+ PJSUA_UNLOCK();
+ return acc_id;
+ }
+ }
+
/* Still no match, use default account */
PJSUA_UNLOCK();
return pjsua_var.default_acc;
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index 35eee94..bb2ccd1 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -237,6 +237,9 @@
call = &pjsua_var.calls[call_id];
+ PJ_LOG(4,(THIS_FILE, "Making call with acc #%d to %.*s", acc_id,
+ (int)dest_uri->slen, dest_uri->ptr));
+
/* Mark call start time. */
pj_gettimeofday(&call->start_time);
@@ -316,6 +319,9 @@
pjsua_process_msg_data( tdata, msg_data);
+ /* Must increment call counter now */
+ ++pjsua_var.call_cnt;
+
/* Send initial INVITE: */
status = pjsip_inv_send_msg(inv, tdata);
@@ -333,8 +339,6 @@
/* Done. */
- ++pjsua_var.call_cnt;
-
if (p_call_id)
*p_call_id = call_id;
@@ -462,7 +466,7 @@
* call. We need the account to find which contact URI to put for
* the call.
*/
- acc_id = pjsua_acc_find_for_incoming(rdata);
+ acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata);
/* Get suitable Contact header */
status = pjsua_acc_create_uas_contact(rdata->tp_info.pool, &contact,