summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2013-02-27 10:44:04 +0000
committerLiong Sauw Ming <ming@teluu.com>2013-02-27 10:44:04 +0000
commit836cece4d96f095cf538ca81aa97305f8ca6d147 (patch)
tree777604d33f4e41057789309b78382e2f1874f42e
parenta4693fb2dea21f4ca9ceb0fffd232188ea707a79 (diff)
Re #1563: Backported to 1.x
git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.x@4389 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsua-lib/pjsua_internal.h3
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c65
2 files changed, 49 insertions, 19 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index af6fd9f9..6171d86c 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -249,6 +249,9 @@ typedef struct pjsua_stun_resolve
PJ_DECL_LIST_MEMBER(struct pjsua_stun_resolve);
pj_pool_t *pool; /**< Pool */
+ int ref_cnt; /**< Reference count */
+ pj_bool_t destroy_flag; /**< To be destroyed */
+ pj_bool_t has_result;
unsigned count; /**< # of entries */
pj_str_t *srv; /**< Array of entries */
unsigned idx; /**< Current index */
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index 11eb38a1..7d8906ec 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -956,11 +956,17 @@ static void busy_sleep(unsigned msec)
} while (PJ_TIME_VAL_LT(now, timeout));
}
-/* Internal function to destroy STUN resolution session
- * (pj_stun_resolve).
- */
+static void stun_resolve_add_ref(pjsua_stun_resolve *sess)
+{
+ ++sess->ref_cnt;
+}
+
static void destroy_stun_resolve(pjsua_stun_resolve *sess)
{
+ sess->destroy_flag = PJ_TRUE;
+ if (sess->ref_cnt > 0)
+ return;
+
PJSUA_LOCK();
pj_list_erase(sess);
PJSUA_UNLOCK();
@@ -969,6 +975,14 @@ static void destroy_stun_resolve(pjsua_stun_resolve *sess)
pj_pool_release(sess->pool);
}
+static void stun_resolve_dec_ref(pjsua_stun_resolve *sess)
+{
+ --sess->ref_cnt;
+ if (sess->ref_cnt <= 0 && sess->destroy_flag)
+ destroy_stun_resolve(sess);
+}
+
+
/* This is the internal function to be called when STUN resolution
* session (pj_stun_resolve) has completed.
*/
@@ -976,11 +990,15 @@ static void stun_resolve_complete(pjsua_stun_resolve *sess)
{
pj_stun_resolve_result result;
+ if (sess->has_result)
+ goto on_return;
+
pj_bzero(&result, sizeof(result));
result.token = sess->token;
result.status = sess->status;
result.name = sess->srv[sess->idx];
pj_memcpy(&result.addr, &sess->addr, sizeof(result.addr));
+ sess->has_result = PJ_TRUE;
if (result.status == PJ_SUCCESS) {
char addr[PJ_INET6_ADDRSTRLEN+10];
@@ -996,8 +1014,11 @@ static void stun_resolve_complete(pjsua_stun_resolve *sess)
PJ_LOG(1,(THIS_FILE, "STUN resolution failed: %s", errmsg));
}
+ stun_resolve_add_ref(sess);
sess->cb(&result);
+ stun_resolve_dec_ref(sess);
+on_return:
if (!sess->blocking) {
destroy_stun_resolve(sess);
}
@@ -1059,22 +1080,27 @@ static pj_bool_t test_stun_on_status(pj_stun_sock *stun_sock,
*/
static void resolve_stun_entry(pjsua_stun_resolve *sess)
{
+ stun_resolve_add_ref(sess);
+
/* Loop while we have entry to try */
for (; sess->idx < sess->count; ++sess->idx) {
const int af = pj_AF_INET();
+ char target[64];
pj_str_t hostpart;
pj_uint16_t port;
pj_stun_sock_cb stun_sock_cb;
pj_assert(sess->idx < sess->count);
+ pj_ansi_snprintf(target, sizeof(target), "%.*s",
+ (int)sess->srv[sess->idx].slen,
+ sess->srv[sess->idx].ptr);
+
/* Parse the server entry into host:port */
sess->status = pj_sockaddr_parse2(af, 0, &sess->srv[sess->idx],
&hostpart, &port, NULL);
if (sess->status != PJ_SUCCESS) {
- PJ_LOG(2,(THIS_FILE, "Invalid STUN server entry %.*s",
- (int)sess->srv[sess->idx].slen,
- sess->srv[sess->idx].ptr));
+ PJ_LOG(2,(THIS_FILE, "Invalid STUN server entry %s", target));
continue;
}
@@ -1084,10 +1110,8 @@ static void resolve_stun_entry(pjsua_stun_resolve *sess)
pj_assert(sess->stun_sock == NULL);
- PJ_LOG(4,(THIS_FILE, "Trying STUN server %.*s (%d of %d)..",
- (int)sess->srv[sess->idx].slen,
- sess->srv[sess->idx].ptr,
- sess->idx+1, sess->count));
+ PJ_LOG(4,(THIS_FILE, "Trying STUN server %s (%d of %d)..",
+ target, sess->idx+1, sess->count));
/* Use STUN_sock to test this entry */
pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
@@ -1099,9 +1123,8 @@ static void resolve_stun_entry(pjsua_stun_resolve *sess)
char errmsg[PJ_ERR_MSG_SIZE];
pj_strerror(sess->status, errmsg, sizeof(errmsg));
PJ_LOG(4,(THIS_FILE,
- "Error creating STUN socket for %.*s: %s",
- (int)sess->srv[sess->idx].slen,
- sess->srv[sess->idx].ptr, errmsg));
+ "Error creating STUN socket for %s: %s",
+ target, errmsg));
continue;
}
@@ -1112,19 +1135,20 @@ static void resolve_stun_entry(pjsua_stun_resolve *sess)
char errmsg[PJ_ERR_MSG_SIZE];
pj_strerror(sess->status, errmsg, sizeof(errmsg));
PJ_LOG(4,(THIS_FILE,
- "Error starting STUN socket for %.*s: %s",
- (int)sess->srv[sess->idx].slen,
- sess->srv[sess->idx].ptr, errmsg));
+ "Error starting STUN socket for %s: %s",
+ target, errmsg));
- pj_stun_sock_destroy(sess->stun_sock);
- sess->stun_sock = NULL;
+ if (sess->stun_sock) {
+ pj_stun_sock_destroy(sess->stun_sock);
+ sess->stun_sock = NULL;
+ }
continue;
}
/* Done for now, testing will resume/complete asynchronously in
* stun_sock_cb()
*/
- return;
+ goto on_return;
}
if (sess->idx >= sess->count) {
@@ -1133,6 +1157,9 @@ static void resolve_stun_entry(pjsua_stun_resolve *sess)
sess->status = PJ_EUNKNOWN);
stun_resolve_complete(sess);
}
+
+on_return:
+ stun_resolve_dec_ref(sess);
}