summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsip')
-rw-r--r--pjsip/src/pjsip/sip_auth_client.c17
-rw-r--r--pjsip/src/pjsip/sip_auth_server.c47
-rw-r--r--pjsip/src/pjsip/sip_config.c4
-rw-r--r--pjsip/src/pjsip/sip_dialog.c23
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c160
-rw-r--r--pjsip/src/pjsip/sip_parser.c11
-rw-r--r--pjsip/src/pjsip/sip_tel_uri.c6
-rw-r--r--pjsip/src/pjsip/sip_transaction.c43
-rw-r--r--pjsip/src/pjsip/sip_transport.c243
-rw-r--r--pjsip/src/pjsip/sip_transport_tcp.c174
-rw-r--r--pjsip/src/pjsip/sip_transport_tls.c191
-rw-r--r--pjsip/src/pjsip/sip_ua_layer.c50
-rw-r--r--pjsip/src/pjsip/sip_uri.c7
-rw-r--r--pjsip/src/pjsip/sip_util_proxy.c4
14 files changed, 701 insertions, 279 deletions
diff --git a/pjsip/src/pjsip/sip_auth_client.c b/pjsip/src/pjsip/sip_auth_client.c
index ae850b1..0facc7b 100644
--- a/pjsip/src/pjsip/sip_auth_client.c
+++ b/pjsip/src/pjsip/sip_auth_client.c
@@ -1,4 +1,4 @@
-/* $Id: sip_auth_client.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/* $Id: sip_auth_client.c 4322 2013-01-17 10:09:09Z bennylp $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -920,13 +920,13 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess,
* or add an empty authorization header.
*/
unsigned i;
- char *uri_str;
- int len;
+ pj_str_t uri;
- uri_str = (char*)pj_pool_alloc(tdata->pool, PJSIP_MAX_URL_SIZE);
- len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, tdata->msg->line.req.uri,
- uri_str, PJSIP_MAX_URL_SIZE);
- if (len < 1 || len >= PJSIP_MAX_URL_SIZE)
+ uri.ptr = (char*)pj_pool_alloc(tdata->pool, PJSIP_MAX_URL_SIZE);
+ uri.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI,
+ tdata->msg->line.req.uri,
+ uri.ptr, PJSIP_MAX_URL_SIZE);
+ if (uri.slen < 1 || uri.slen >= PJSIP_MAX_URL_SIZE)
return PJSIP_EURITOOLONG;
for (i=0; i<sess->cred_cnt; ++i) {
@@ -946,8 +946,7 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess,
&c->username);
pj_strdup(tdata->pool, &hs->credential.digest.realm,
&c->realm);
- pj_strdup2(tdata->pool, &hs->credential.digest.uri,
- uri_str);
+ pj_strdup(tdata->pool, &hs->credential.digest.uri, &uri);
pj_strdup(tdata->pool, &hs->credential.digest.algorithm,
&sess->pref.algorithm);
diff --git a/pjsip/src/pjsip/sip_auth_server.c b/pjsip/src/pjsip/sip_auth_server.c
index 248e6cc..c38b40c 100644
--- a/pjsip/src/pjsip/sip_auth_server.c
+++ b/pjsip/src/pjsip/sip_auth_server.c
@@ -1,4 +1,4 @@
-/* $Id: sip_auth_server.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: sip_auth_server.c 4214 2012-07-25 14:29:28Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -40,6 +40,7 @@ PJ_DEF(pj_status_t) pjsip_auth_srv_init( pj_pool_t *pool,
{
PJ_ASSERT_RETURN(pool && auth_srv && realm && lookup, PJ_EINVAL);
+ pj_bzero(auth_srv, sizeof(*auth_srv));
pj_strdup( pool, &auth_srv->realm, realm);
auth_srv->lookup = lookup;
auth_srv->is_proxy = (options & PJSIP_AUTH_SRV_IS_PROXY);
@@ -47,6 +48,26 @@ PJ_DEF(pj_status_t) pjsip_auth_srv_init( pj_pool_t *pool,
return PJ_SUCCESS;
}
+/*
+ * Initialize server authorization session data structure to serve the
+ * specified realm and to use lookup_func function to look for the credential
+ * info.
+ */
+PJ_DEF(pj_status_t) pjsip_auth_srv_init2(
+ pj_pool_t *pool,
+ pjsip_auth_srv *auth_srv,
+ const pjsip_auth_srv_init_param *param)
+{
+ PJ_ASSERT_RETURN(pool && auth_srv && param, PJ_EINVAL);
+
+ pj_bzero(auth_srv, sizeof(*auth_srv));
+ pj_strdup( pool, &auth_srv->realm, param->realm);
+ auth_srv->lookup2 = param->lookup2;
+ auth_srv->is_proxy = (param->options & PJSIP_AUTH_SRV_IS_PROXY);
+
+ return PJ_SUCCESS;
+}
+
/* Verify incoming Authorization/Proxy-Authorization header against the
* specified credential.
@@ -148,11 +169,25 @@ PJ_DEF(pj_status_t) pjsip_auth_srv_verify( pjsip_auth_srv *auth_srv,
}
/* Find the credential information for the account. */
- status = (*auth_srv->lookup)(rdata->tp_info.pool, &auth_srv->realm,
- &acc_name, &cred_info);
- if (status != PJ_SUCCESS) {
- *status_code = PJSIP_SC_FORBIDDEN;
- return status;
+ if (auth_srv->lookup2) {
+ pjsip_auth_lookup_cred_param param;
+
+ pj_bzero(&param, sizeof(param));
+ param.realm = auth_srv->realm;
+ param.acc_name = acc_name;
+ param.rdata = rdata;
+ status = (*auth_srv->lookup2)(rdata->tp_info.pool, &param, &cred_info);
+ if (status != PJ_SUCCESS) {
+ *status_code = PJSIP_SC_FORBIDDEN;
+ return status;
+ }
+ } else {
+ status = (*auth_srv->lookup)(rdata->tp_info.pool, &auth_srv->realm,
+ &acc_name, &cred_info);
+ if (status != PJ_SUCCESS) {
+ *status_code = PJSIP_SC_FORBIDDEN;
+ return status;
+ }
}
/* Authenticate with the specified credential. */
diff --git a/pjsip/src/pjsip/sip_config.c b/pjsip/src/pjsip/sip_config.c
index 8742c8a..92b8805 100644
--- a/pjsip/src/pjsip/sip_config.c
+++ b/pjsip/src/pjsip/sip_config.c
@@ -1,4 +1,4 @@
-/* $Id: sip_config.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/* $Id: sip_config.c 4285 2012-10-19 04:23:57Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -26,6 +26,8 @@ pjsip_cfg_t pjsip_sip_cfg_var =
/* Global settings */
{
PJSIP_ALLOW_PORT_IN_FROMTO_HDR,
+ PJSIP_ACCEPT_REPLACE_IN_EARLY_STATE,
+ 0,
0,
PJSIP_DONT_SWITCH_TO_TCP
},
diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c
index 008cad2..0e70d33 100644
--- a/pjsip/src/pjsip/sip_dialog.c
+++ b/pjsip/src/pjsip/sip_dialog.c
@@ -1,4 +1,4 @@
-/* $Id: sip_dialog.c 4173 2012-06-20 10:39:05Z ming $ */
+/* $Id: sip_dialog.c 4208 2012-07-18 07:52:33Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -206,8 +206,8 @@ PJ_DEF(pj_status_t) pjsip_dlg_create_uac( pjsip_user_agent *ua,
pj_create_unique_string(dlg->pool, &dlg->local.info->tag);
/* Calculate hash value of local tag. */
- dlg->local.tag_hval = pj_hash_calc(0, dlg->local.info->tag.ptr,
- dlg->local.info->tag.slen);
+ dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL,
+ &dlg->local.info->tag);
/* Randomize local CSeq. */
dlg->local.first_cseq = pj_rand() & 0x7FFF;
@@ -374,8 +374,7 @@ PJ_DEF(pj_status_t) pjsip_dlg_create_uas( pjsip_user_agent *ua,
pj_strdup(dlg->pool, &dlg->local.info_str, &tmp);
/* Calculate hash value of local tag. */
- dlg->local.tag_hval = pj_hash_calc(0, dlg->local.info->tag.ptr,
- dlg->local.info->tag.slen);
+ dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL, &dlg->local.info->tag);
/* Randomize local cseq */
@@ -522,8 +521,7 @@ PJ_DEF(pj_status_t) pjsip_dlg_create_uas( pjsip_user_agent *ua,
++dlg->tsx_count;
/* Calculate hash value of remote tag. */
- dlg->remote.tag_hval = pj_hash_calc(0, dlg->remote.info->tag.ptr,
- dlg->remote.info->tag.slen);
+ dlg->remote.tag_hval = pj_hash_calc_tolower(0, NULL, &dlg->remote.info->tag);
/* Update remote capabilities info */
pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg, PJ_TRUE);
@@ -596,8 +594,11 @@ PJ_DEF(pj_status_t) pjsip_dlg_set_via_sent_by( pjsip_dialog *dlg,
if (!via_addr)
pj_bzero(&dlg->via_addr, sizeof(dlg->via_addr));
- else
- dlg->via_addr = *via_addr;
+ else {
+ if (pj_strcmp(&dlg->via_addr.host, &via_addr->host))
+ pj_strdup(dlg->pool, &dlg->via_addr.host, &via_addr->host);
+ dlg->via_addr.port = via_addr->port;
+ }
dlg->via_tp = via_tp;
return PJ_SUCCESS;
@@ -1814,7 +1815,7 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata )
res_code > 100 &&
res_code/100 <= 2 &&
pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) &&
- pj_strcmp(&dlg->remote.info->tag, &rdata->msg_info.to->tag)))
+ pj_stricmp(&dlg->remote.info->tag, &rdata->msg_info.to->tag)))
{
pjsip_contact_hdr *contact;
@@ -1823,7 +1824,7 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata )
* with To-tag or forking, apply strict update.
*/
pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg,
- pj_strcmp(&dlg->remote.info->tag,
+ pj_stricmp(&dlg->remote.info->tag,
&rdata->msg_info.to->tag));
/* Update To tag. */
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index 2510d14..ae55990 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -1,4 +1,4 @@
-/* $Id: sip_endpoint.c 4154 2012-06-05 10:41:17Z bennylp $ */
+/* $Id: sip_endpoint.c 4411 2013-03-04 04:34:38Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -812,6 +812,104 @@ PJ_DEF(pj_timer_heap_t*) pjsip_endpt_get_timer_heap(pjsip_endpoint *endpt)
return endpt->timer_heap;
}
+/* Init with default */
+PJ_DEF(void) pjsip_process_rdata_param_default(pjsip_process_rdata_param *p)
+{
+ pj_bzero(p, sizeof(*p));
+}
+
+/* Distribute rdata */
+PJ_DEF(pj_status_t) pjsip_endpt_process_rx_data( pjsip_endpoint *endpt,
+ pjsip_rx_data *rdata,
+ pjsip_process_rdata_param *p,
+ pj_bool_t *p_handled)
+{
+ pjsip_msg *msg;
+ pjsip_process_rdata_param def_prm;
+ pjsip_module *mod;
+ pj_bool_t handled = PJ_FALSE;
+ unsigned i;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(endpt && rdata, PJ_EINVAL);
+
+ if (p==NULL) {
+ p = &def_prm;
+ pjsip_process_rdata_param_default(p);
+ }
+
+ msg = rdata->msg_info.msg;
+
+ if (p_handled)
+ *p_handled = PJ_FALSE;
+
+ if (!p->silent) {
+ PJ_LOG(5, (THIS_FILE, "Distributing rdata to modules: %s",
+ pjsip_rx_data_get_info(rdata)));
+ pj_log_push_indent();
+ }
+
+ LOCK_MODULE_ACCESS(endpt);
+
+ /* Find start module */
+ if (p->start_mod) {
+ mod = (pjsip_module*)
+ pj_list_find_node(&endpt->module_list, p->start_mod);
+ if (!mod) {
+ status = PJ_ENOTFOUND;
+ goto on_return;
+ }
+ } else {
+ mod = endpt->module_list.next;
+ }
+
+ /* Start after the specified index */
+ for (i=0; i < p->idx_after_start && mod != &endpt->module_list; ++i) {
+ mod = mod->next;
+ }
+
+ /* Start with the specified priority */
+ while (mod != &endpt->module_list && mod->priority < (int)p->start_prio) {
+ mod = mod->next;
+ }
+
+ if (mod == &endpt->module_list) {
+ status = PJ_ENOTFOUND;
+ goto on_return;
+ }
+
+ /* Distribute */
+ if (msg->type == PJSIP_REQUEST_MSG) {
+ do {
+ if (mod->on_rx_request)
+ handled = (*mod->on_rx_request)(rdata);
+ if (handled)
+ break;
+ mod = mod->next;
+ } while (mod != &endpt->module_list);
+ } else {
+ do {
+ if (mod->on_rx_response)
+ handled = (*mod->on_rx_response)(rdata);
+ if (handled)
+ break;
+ mod = mod->next;
+ } while (mod != &endpt->module_list);
+ }
+
+ status = PJ_SUCCESS;
+
+on_return:
+ if (p_handled)
+ *p_handled = handled;
+
+ UNLOCK_MODULE_ACCESS(endpt);
+ if (!p->silent) {
+ pj_log_pop_indent();
+ }
+ return status;
+}
+
/*
* This is the callback that is called by the transport manager when it
* receives a message from the network.
@@ -820,7 +918,8 @@ static void endpt_on_rx_msg( pjsip_endpoint *endpt,
pj_status_t status,
pjsip_rx_data *rdata )
{
- pjsip_msg *msg = rdata->msg_info.msg;
+ pjsip_process_rdata_param proc_prm;
+ pj_bool_t handled = PJ_FALSE;
if (status != PJ_SUCCESS) {
char info[30];
@@ -927,57 +1026,20 @@ static void endpt_on_rx_msg( pjsip_endpoint *endpt,
}
#endif
+ pjsip_process_rdata_param_default(&proc_prm);
+ proc_prm.silent = PJ_TRUE;
- /* Distribute to modules, starting from modules with highest priority */
- LOCK_MODULE_ACCESS(endpt);
-
- if (msg->type == PJSIP_REQUEST_MSG) {
- pjsip_module *mod;
- pj_bool_t handled = PJ_FALSE;
-
- mod = endpt->module_list.next;
- while (mod != &endpt->module_list) {
- if (mod->on_rx_request)
- handled = (*mod->on_rx_request)(rdata);
- if (handled)
- break;
- mod = mod->next;
- }
-
- /* No module is able to handle the request. */
- if (!handled) {
- PJ_TODO(ENDPT_RESPOND_UNHANDLED_REQUEST);
- PJ_LOG(4,(THIS_FILE, "Message %s from %s:%d was dropped/unhandled by"
- " any modules",
- pjsip_rx_data_get_info(rdata),
- rdata->pkt_info.src_name,
- rdata->pkt_info.src_port));
- }
-
- } else {
- pjsip_module *mod;
- pj_bool_t handled = PJ_FALSE;
+ pjsip_endpt_process_rx_data(endpt, rdata, &proc_prm, &handled);
- mod = endpt->module_list.next;
- while (mod != &endpt->module_list) {
- if (mod->on_rx_response)
- handled = (*mod->on_rx_response)(rdata);
- if (handled)
- break;
- mod = mod->next;
- }
-
- if (!handled) {
- PJ_LOG(4,(THIS_FILE, "Message %s from %s:%d was dropped/unhandled"
- " by any modules",
- pjsip_rx_data_get_info(rdata),
- rdata->pkt_info.src_name,
- rdata->pkt_info.src_port));
- }
+ /* No module is able to handle the message */
+ if (!handled) {
+ PJ_LOG(4,(THIS_FILE, "%s from %s:%d was dropped/unhandled by"
+ " any modules",
+ pjsip_rx_data_get_info(rdata),
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port));
}
- UNLOCK_MODULE_ACCESS(endpt);
-
/* Must clear mod_data before returning rdata to transport, since
* rdata may be reused.
*/
diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c
index 2d46fe9..26f4aca 100644
--- a/pjsip/src/pjsip/sip_parser.c
+++ b/pjsip/src/pjsip/sip_parser.c
@@ -1,4 +1,4 @@
-/* $Id: sip_parser.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: sip_parser.c 4288 2012-10-26 09:30:37Z bennylp $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -1522,8 +1522,15 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner,
/* Get the SIP-URL */
has_bracket = (*scanner->curptr == '<');
- if (has_bracket)
+ if (has_bracket) {
pj_scan_get_char(scanner);
+ } else if (name_addr->display.slen) {
+ /* Must have bracket now (2012-10-26).
+ * Allowing (invalid) name-addr to pass URI verification will
+ * cause us to send invalid URI to the wire.
+ */
+ PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
+ }
name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE );
if (has_bracket) {
if (pj_scan_get_char(scanner) != '>')
diff --git a/pjsip/src/pjsip/sip_tel_uri.c b/pjsip/src/pjsip/sip_tel_uri.c
index 4120ae0..b98db57 100644
--- a/pjsip/src/pjsip/sip_tel_uri.c
+++ b/pjsip/src/pjsip/sip_tel_uri.c
@@ -1,4 +1,4 @@
-/* $Id: sip_tel_uri.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: sip_tel_uri.c 4322 2013-01-17 10:09:09Z bennylp $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -182,7 +182,7 @@ static pj_ssize_t tel_uri_print( pjsip_uri_context_e context,
{
int printed;
char *startbuf = buf;
- char *endbuf = buf+size;
+ char *endbuf = buf+size-1;
const pjsip_parser_const_t *pc = pjsip_parser_const();
PJ_UNUSED_ARG(context);
@@ -217,6 +217,8 @@ static pj_ssize_t tel_uri_print( pjsip_uri_context_e context,
return -1;
buf += printed;
+ *buf = '\0';
+
return (buf-startbuf);
}
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index 4b3dd12..1321d9f 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -1,4 +1,4 @@
-/* $Id: sip_transaction.c 4165 2012-06-14 09:04:20Z bennylp $ */
+/* $Id: sip_transaction.c 4208 2012-07-18 07:52:33Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -403,7 +403,7 @@ PJ_DEF(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key,
*/
const pj_str_t *branch = &rdata->msg_info.via->branch_param;
- if (pj_strncmp(branch,&rfc3261_branch,PJSIP_RFC3261_BRANCH_LEN)==0) {
+ if (pj_strnicmp(branch,&rfc3261_branch,PJSIP_RFC3261_BRANCH_LEN)==0) {
/* Create transaction key. */
return create_tsx_key_3261(pool, key, role, method, branch);
@@ -548,10 +548,10 @@ static pj_status_t mod_tsx_layer_register_tsx( pjsip_transaction *tsx)
* Do not use PJ_ASSERT_RETURN since it evaluates the expression
* twice!
*/
- if(pj_hash_get(mod_tsx_layer.htable,
- tsx->transaction_key.ptr,
- tsx->transaction_key.slen,
- NULL))
+ if(pj_hash_get_lower(mod_tsx_layer.htable,
+ tsx->transaction_key.ptr,
+ tsx->transaction_key.slen,
+ NULL))
{
pj_mutex_unlock(mod_tsx_layer.mutex);
PJ_LOG(2,(THIS_FILE,
@@ -568,11 +568,13 @@ static pj_status_t mod_tsx_layer_register_tsx( pjsip_transaction *tsx)
/* Register the transaction to the hash table. */
#ifdef PRECALC_HASH
- pj_hash_set( tsx->pool, mod_tsx_layer.htable, tsx->transaction_key.ptr,
- tsx->transaction_key.slen, tsx->hashed_key, tsx);
+ pj_hash_set_lower( tsx->pool, mod_tsx_layer.htable,
+ tsx->transaction_key.ptr,
+ tsx->transaction_key.slen, tsx->hashed_key, tsx);
#else
- pj_hash_set( tsx->pool, mod_tsx_layer.htable, tsx->transaction_key.ptr,
- tsx->transaction_key.slen, 0, tsx);
+ pj_hash_set_lower( tsx->pool, mod_tsx_layer.htable,
+ tsx->transaction_key.ptr,
+ tsx->transaction_key.slen, 0, tsx);
#endif
/* Unlock mutex. */
@@ -604,11 +606,11 @@ static void mod_tsx_layer_unregister_tsx( pjsip_transaction *tsx)
/* Register the transaction to the hash table. */
#ifdef PRECALC_HASH
- pj_hash_set( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr,
- tsx->transaction_key.slen, tsx->hashed_key, NULL);
+ pj_hash_set_lower( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr,
+ tsx->transaction_key.slen, tsx->hashed_key, NULL);
#else
- pj_hash_set( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr,
- tsx->transaction_key.slen, 0, NULL);
+ pj_hash_set_lower( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr,
+ tsx->transaction_key.slen, 0, NULL);
#endif
TSX_TRACE_((THIS_FILE,
@@ -651,7 +653,8 @@ PJ_DEF(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key,
pj_mutex_lock(mod_tsx_layer.mutex);
tsx = (pjsip_transaction*)
- pj_hash_get( mod_tsx_layer.htable, key->ptr, key->slen, &hval );
+ pj_hash_get_lower( mod_tsx_layer.htable, key->ptr, key->slen,
+ &hval );
pj_mutex_unlock(mod_tsx_layer.mutex);
TSX_TRACE_((THIS_FILE,
@@ -785,7 +788,7 @@ static pj_bool_t mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata)
pj_mutex_lock( mod_tsx_layer.mutex );
tsx = (pjsip_transaction*)
- pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen, &hval );
+ pj_hash_get_lower( mod_tsx_layer.htable, key.ptr, key.slen, &hval );
TSX_TRACE_((THIS_FILE,
@@ -834,7 +837,7 @@ static pj_bool_t mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata)
pj_mutex_lock( mod_tsx_layer.mutex );
tsx = (pjsip_transaction*)
- pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen, &hval );
+ pj_hash_get_lower( mod_tsx_layer.htable, key.ptr, key.slen, &hval );
TSX_TRACE_((THIS_FILE,
@@ -1299,8 +1302,7 @@ PJ_DEF(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user,
/* Calculate hashed key value. */
#ifdef PRECALC_HASH
- tsx->hashed_key = pj_hash_calc(0, tsx->transaction_key.ptr,
- tsx->transaction_key.slen);
+ tsx->hashed_key = pj_hash_calc_tolower(0, NULL, &tsx->transaction_key);
#endif
PJ_LOG(6, (tsx->obj_name, "tsx_key=%.*s", tsx->transaction_key.slen,
@@ -1432,8 +1434,7 @@ PJ_DEF(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user,
/* Calculate hashed key value. */
#ifdef PRECALC_HASH
- tsx->hashed_key = pj_hash_calc(0, tsx->transaction_key.ptr,
- tsx->transaction_key.slen);
+ tsx->hashed_key = pj_hash_calc_tolower(0, NULL, &tsx->transaction_key);
#endif
/* Duplicate branch parameter for transaction. */
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 4d8b77e..1598241 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -1,4 +1,4 @@
-/* $Id: sip_transport.c 4094 2012-04-26 09:31:00Z bennylp $ */
+/* $Id: sip_transport.c 4295 2012-11-06 05:22:11Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -24,6 +24,7 @@
#include <pjsip/sip_private.h>
#include <pjsip/sip_errno.h>
#include <pjsip/sip_module.h>
+#include <pj/addr_resolv.h>
#include <pj/except.h>
#include <pj/os.h>
#include <pj/log.h>
@@ -197,6 +198,13 @@ struct transport_names_t
"TCP IPv6 transport",
PJSIP_TRANSPORT_RELIABLE
},
+ {
+ PJSIP_TRANSPORT_TLS6,
+ 5061,
+ {"TLS", 3},
+ "TLS IPv6 transport",
+ PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE
+ },
};
static void tp_state_callback(pjsip_transport *tp,
@@ -594,6 +602,89 @@ PJ_DEF(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata)
return rdata->msg_info.info;
}
+/* Clone pjsip_rx_data. */
+PJ_DEF(pj_status_t) pjsip_rx_data_clone( const pjsip_rx_data *src,
+ unsigned flags,
+ pjsip_rx_data **p_rdata)
+{
+ pj_pool_t *pool;
+ pjsip_rx_data *dst;
+ pjsip_hdr *hdr;
+
+ PJ_ASSERT_RETURN(src && flags==0 && p_rdata, PJ_EINVAL);
+
+ pool = pj_pool_create(src->tp_info.pool->factory,
+ "rtd%p",
+ PJSIP_POOL_RDATA_LEN,
+ PJSIP_POOL_RDATA_INC,
+ NULL);
+ if (!pool)
+ return PJ_ENOMEM;
+
+ dst = PJ_POOL_ZALLOC_T(pool, pjsip_rx_data);
+
+ /* Parts of tp_info */
+ dst->tp_info.pool = pool;
+ dst->tp_info.transport = (pjsip_transport*)src->tp_info.transport;
+
+ /* pkt_info can be memcopied */
+ pj_memcpy(&dst->pkt_info, &src->pkt_info, sizeof(src->pkt_info));
+
+ /* msg_info needs deep clone */
+ dst->msg_info.msg_buf = dst->pkt_info.packet;
+ dst->msg_info.len = src->msg_info.len;
+ dst->msg_info.msg = pjsip_msg_clone(pool, src->msg_info.msg);
+ pj_list_init(&dst->msg_info.parse_err);
+
+#define GET_MSG_HDR2(TYPE, type, var) \
+ case PJSIP_H_##TYPE: \
+ if (!dst->msg_info.var) { \
+ dst->msg_info.var = (pjsip_##type##_hdr*)hdr; \
+ } \
+ break
+#define GET_MSG_HDR(TYPE, var_type) GET_MSG_HDR2(TYPE, var_type, var_type)
+
+ hdr = dst->msg_info.msg->hdr.next;
+ while (hdr != &dst->msg_info.msg->hdr) {
+ switch (hdr->type) {
+ GET_MSG_HDR(CALL_ID, cid);
+ GET_MSG_HDR(FROM, from);
+ GET_MSG_HDR(TO, to);
+ GET_MSG_HDR(VIA, via);
+ GET_MSG_HDR(CSEQ, cseq);
+ GET_MSG_HDR(MAX_FORWARDS, max_fwd);
+ GET_MSG_HDR(ROUTE, route);
+ GET_MSG_HDR2(RECORD_ROUTE, rr, record_route);
+ GET_MSG_HDR(CONTENT_TYPE, ctype);
+ GET_MSG_HDR(CONTENT_LENGTH, clen);
+ GET_MSG_HDR(REQUIRE, require);
+ GET_MSG_HDR(SUPPORTED, supported);
+ default:
+ break;
+ }
+ hdr = hdr->next;
+ }
+
+#undef GET_MSG_HDR
+#undef GET_MSG_HDR2
+
+ *p_rdata = dst;
+
+ /* Finally add transport ref */
+ return pjsip_transport_add_ref(dst->tp_info.transport);
+}
+
+/* Free previously cloned pjsip_rx_data. */
+PJ_DEF(pj_status_t) pjsip_rx_data_free_cloned(pjsip_rx_data *rdata)
+{
+ PJ_ASSERT_RETURN(rdata, PJ_EINVAL);
+
+ pjsip_transport_dec_ref(rdata->tp_info.transport);
+ pj_pool_release(rdata->tp_info.pool);
+
+ return PJ_SUCCESS;
+}
+
/*****************************************************************************
*
* TRANSPORT KEY
@@ -1080,6 +1171,10 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_unregister_tpfactory( pjsip_tpmgr *mgr,
return PJ_SUCCESS;
}
+PJ_DECL(void) pjsip_tpmgr_fla2_param_default(pjsip_tpmgr_fla2_param *prm)
+{
+ pj_bzero(prm, sizeof(*prm));
+}
/*****************************************************************************
*
@@ -1138,7 +1233,27 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
return PJ_SUCCESS;
}
+/* Get the interface to send packet to the specified address */
+static pj_status_t get_net_interface(pjsip_transport_type_e tp_type,
+ const pj_str_t *dst,
+ pj_str_t *itf_str_addr)
+{
+ int af;
+ pj_sockaddr itf_addr;
+ pj_status_t status;
+
+ af = (tp_type & PJSIP_TRANSPORT_IPV6)? PJ_AF_INET6 : PJ_AF_INET;
+ status = pj_getipinterface(af, dst, &itf_addr, PJ_FALSE, NULL);
+ if (status != PJ_SUCCESS)
+ return status;
+ /* Print address */
+ pj_sockaddr_print(&itf_addr, itf_str_addr->ptr,
+ PJ_INET6_ADDRSTRLEN, 0);
+ itf_str_addr->slen = pj_ansi_strlen(itf_str_addr->ptr);
+
+ return PJ_SUCCESS;
+}
/*
* Find out the appropriate local address info (IP address and port) to
@@ -1149,46 +1264,66 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
* In this implementation, it will only select the transport based on
* the transport type in the request.
*/
-PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
+PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr2(pjsip_tpmgr *tpmgr,
pj_pool_t *pool,
- pjsip_transport_type_e type,
- const pjsip_tpselector *sel,
- pj_str_t *ip_addr,
- int *port)
+ pjsip_tpmgr_fla2_param *prm)
{
+ char tmp_buf[PJ_INET6_ADDRSTRLEN+10];
+ pj_str_t tmp_str;
pj_status_t status = PJSIP_EUNSUPTRANSPORT;
unsigned flag;
/* Sanity checks */
- PJ_ASSERT_RETURN(tpmgr && pool && ip_addr && port, PJ_EINVAL);
+ PJ_ASSERT_RETURN(tpmgr && pool && prm, PJ_EINVAL);
- ip_addr->slen = 0;
- *port = 0;
+ pj_strset(&tmp_str, tmp_buf, 0);
+ prm->ret_addr.slen = 0;
+ prm->ret_port = 0;
+ prm->ret_tp = NULL;
- flag = pjsip_transport_get_flag_from_type(type);
+ flag = pjsip_transport_get_flag_from_type(prm->tp_type);
- if (sel && sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
- sel->u.transport)
+ if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
+ prm->tp_sel->u.transport)
{
- pj_strdup(pool, ip_addr, &sel->u.transport->local_name.host);
- *port = sel->u.transport->local_name.port;
+ const pjsip_transport *tp = prm->tp_sel->u.transport;
+ if (prm->local_if) {
+ status = get_net_interface((pjsip_transport_type_e)tp->key.type,
+ &prm->dst_host, &tmp_str);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+ pj_strdup(pool, &prm->ret_addr, &tmp_str);
+ prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
+ prm->ret_tp = tp;
+ } else {
+ pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
+ prm->ret_port = (pj_uint16_t)tp->local_name.port;
+ }
status = PJ_SUCCESS;
- } else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
- sel->u.listener)
+ } else if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_LISTENER &&
+ prm->tp_sel->u.listener)
{
- pj_strdup(pool, ip_addr, &sel->u.listener->addr_name.host);
- *port = sel->u.listener->addr_name.port;
+ if (prm->local_if) {
+ status = get_net_interface(prm->tp_sel->u.listener->type,
+ &prm->dst_host, &tmp_str);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+ pj_strdup(pool, &prm->ret_addr, &tmp_str);
+ } else {
+ pj_strdup(pool, &prm->ret_addr,
+ &prm->tp_sel->u.listener->addr_name.host);
+ }
+ prm->ret_port = (pj_uint16_t)prm->tp_sel->u.listener->addr_name.port;
status = PJ_SUCCESS;
} else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
-
pj_sockaddr remote;
int addr_len;
pjsip_transport *tp;
pj_bzero(&remote, sizeof(remote));
- if (type & PJSIP_TRANSPORT_IPV6) {
+ if (prm->tp_type & PJSIP_TRANSPORT_IPV6) {
addr_len = sizeof(pj_sockaddr_in6);
remote.addr.sa_family = pj_AF_INET6();
} else {
@@ -1196,13 +1331,23 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
remote.addr.sa_family = pj_AF_INET();
}
- status = pjsip_tpmgr_acquire_transport(tpmgr, type, &remote,
+ status = pjsip_tpmgr_acquire_transport(tpmgr, prm->tp_type, &remote,
addr_len, NULL, &tp);
if (status == PJ_SUCCESS) {
- pj_strdup(pool, ip_addr, &tp->local_name.host);
- *port = tp->local_name.port;
- status = PJ_SUCCESS;
+ if (prm->local_if) {
+ status = get_net_interface((pjsip_transport_type_e)
+ tp->key.type,
+ &prm->dst_host, &tmp_str);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+ pj_strdup(pool, &prm->ret_addr, &tmp_str);
+ prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
+ prm->ret_tp = tp;
+ } else {
+ pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
+ prm->ret_port = (pj_uint16_t)tp->local_name.port;
+ }
pjsip_transport_dec_ref(tp);
}
@@ -1215,22 +1360,66 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
f = tpmgr->factory_list.next;
while (f != &tpmgr->factory_list) {
- if (f->type == type)
+ if (f->type == prm->tp_type)
break;
f = f->next;
}
if (f != &tpmgr->factory_list) {
- pj_strdup(pool, ip_addr, &f->addr_name.host);
- *port = f->addr_name.port;
+ if (prm->local_if) {
+ status = get_net_interface(f->type, &prm->dst_host,
+ &tmp_str);
+ if (status == PJ_SUCCESS) {
+ pj_strdup(pool, &prm->ret_addr, &tmp_str);
+ } else {
+ /* It could fail "normally" on certain cases, e.g.
+ * when connecting to IPv6 link local address, it
+ * will wail with EINVAL.
+ * In this case, fallback to use the default interface
+ * rather than failing the call.
+ */
+ PJ_PERROR(5,(THIS_FILE, status, "Warning: unable to "
+ "determine local interface"));
+ pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
+ status = PJ_SUCCESS;
+ }
+ } else {
+ pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
+ }
+ prm->ret_port = (pj_uint16_t)f->addr_name.port;
status = PJ_SUCCESS;
}
pj_lock_release(tpmgr->lock);
}
+on_return:
return status;
}
+PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
+ pj_pool_t *pool,
+ pjsip_transport_type_e type,
+ const pjsip_tpselector *sel,
+ pj_str_t *ip_addr,
+ int *port)
+{
+ pjsip_tpmgr_fla2_param prm;
+ pj_status_t status;
+
+ pjsip_tpmgr_fla2_param_default(&prm);
+ prm.tp_type = type;
+ prm.tp_sel = sel;
+
+ status = pjsip_tpmgr_find_local_addr2(tpmgr, pool, &prm);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ *ip_addr = prm.ret_addr;
+ *port = prm.ret_port;
+
+ return PJ_SUCCESS;
+}
+
/*
* Return number of transports currently registered to the transport
* manager.
diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c
index 141434b..808cee9 100644
--- a/pjsip/src/pjsip/sip_transport_tcp.c
+++ b/pjsip/src/pjsip/sip_transport_tcp.c
@@ -1,4 +1,4 @@
-/* $Id: sip_transport_tcp.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: sip_transport_tcp.c 4294 2012-11-06 05:02:10Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -57,6 +57,7 @@ struct tcp_listener
pjsip_endpoint *endpt;
pjsip_tpmgr *tpmgr;
pj_activesock_t *asock;
+ pj_sockaddr bound_addr;
pj_qos_type qos_type;
pj_qos_params qos_params;
};
@@ -73,6 +74,7 @@ struct delayed_tdata
{
PJ_DECL_LIST_MEMBER(struct delayed_tdata);
pjsip_tx_data_op_key *tdata_op_key;
+ pj_time_val timeout;
};
@@ -140,8 +142,8 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
static pj_status_t tcp_create(struct tcp_listener *listener,
pj_pool_t *pool,
pj_sock_t sock, pj_bool_t is_server,
- const pj_sockaddr_in *local,
- const pj_sockaddr_in *remote,
+ const pj_sockaddr *local,
+ const pj_sockaddr *remote,
struct tcp_transport **p_tcp);
@@ -158,10 +160,10 @@ static void tcp_perror(const char *sender, const char *title,
static void sockaddr_to_host_port( pj_pool_t *pool,
pjsip_host_port *host_port,
- const pj_sockaddr_in *addr )
+ const pj_sockaddr *addr )
{
host_port->host.ptr = (char*) pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+4);
- pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 2);
+ pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 0);
host_port->host.slen = pj_ansi_strlen(host_port->host.ptr);
host_port->port = pj_sockaddr_get_port(addr);
}
@@ -266,17 +268,21 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start3(
listener = PJ_POOL_ZALLOC_T(pool, struct tcp_listener);
listener->factory.pool = pool;
- listener->factory.type = PJSIP_TRANSPORT_TCP;
- listener->factory.type_name = "tcp";
+ listener->factory.type = cfg->af==pj_AF_INET() ? PJSIP_TRANSPORT_TCP :
+ PJSIP_TRANSPORT_TCP6;
+ listener->factory.type_name = (char*)
+ pjsip_transport_get_type_name(listener->factory.type);
listener->factory.flag =
- pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TCP);
+ pjsip_transport_get_flag_from_type(listener->factory.type);
listener->qos_type = cfg->qos_type;
pj_memcpy(&listener->qos_params, &cfg->qos_params,
sizeof(cfg->qos_params));
pj_ansi_strcpy(listener->factory.obj_name, "tcplis");
+ if (listener->factory.type==PJSIP_TRANSPORT_TCP6)
+ pj_ansi_strcat(listener->factory.obj_name, "6");
- status = pj_lock_create_recursive_mutex(pool, "tcplis",
+ status = pj_lock_create_recursive_mutex(pool, listener->factory.obj_name,
&listener->factory.lock);
if (status != PJ_SUCCESS)
goto on_error;
@@ -292,6 +298,11 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start3(
2, listener->factory.obj_name,
"SIP TCP listener socket");
+ /* Bind address may be different than factory.local_addr because
+ * factory.local_addr will be resolved below.
+ */
+ pj_sockaddr_cp(&listener->bound_addr, &cfg->bind_addr);
+
/* Bind socket */
listener_addr = &listener->factory.local_addr;
pj_sockaddr_cp(listener_addr, &cfg->bind_addr);
@@ -326,19 +337,18 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start3(
if (!pj_sockaddr_has_addr(listener_addr)) {
pj_sockaddr hostip;
- status = pj_gethostip(pj_AF_INET(), &hostip);
+ status = pj_gethostip(listener->bound_addr.addr.sa_family,
+ &hostip);
if (status != PJ_SUCCESS)
goto on_error;
- pj_memcpy(pj_sockaddr_get_addr(listener_addr),
- pj_sockaddr_get_addr(&hostip),
- pj_sockaddr_get_addr_len(&hostip));
+ pj_sockaddr_copy_addr(listener_addr, &hostip);
}
/* Save the address name */
sockaddr_to_host_port(listener->factory.pool,
&listener->factory.addr_name,
- (pj_sockaddr_in*)listener_addr);
+ listener_addr);
}
/* If port is zero, get the bound port */
@@ -535,8 +545,8 @@ static void tcp_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e);
static pj_status_t tcp_create( struct tcp_listener *listener,
pj_pool_t *pool,
pj_sock_t sock, pj_bool_t is_server,
- const pj_sockaddr_in *local,
- const pj_sockaddr_in *remote,
+ const pj_sockaddr *local,
+ const pj_sockaddr *remote,
struct tcp_transport **p_tcp)
{
struct tcp_transport *tcp;
@@ -544,6 +554,7 @@ static pj_status_t tcp_create( struct tcp_listener *listener,
pj_activesock_cfg asock_cfg;
pj_activesock_cb tcp_callback;
const pj_str_t ka_pkt = PJSIP_TCP_KEEP_ALIVE_DATA;
+ char print_addr[PJ_INET6_ADDRSTRLEN+10];
pj_status_t status;
@@ -579,18 +590,21 @@ static pj_status_t tcp_create( struct tcp_listener *listener,
goto on_error;
}
- tcp->base.key.type = PJSIP_TRANSPORT_TCP;
- pj_memcpy(&tcp->base.key.rem_addr, remote, sizeof(pj_sockaddr_in));
- tcp->base.type_name = "tcp";
- tcp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TCP);
+ tcp->base.key.type = listener->factory.type;
+ pj_sockaddr_cp(&tcp->base.key.rem_addr, remote);
+ tcp->base.type_name = (char*)pjsip_transport_get_type_name(
+ (pjsip_transport_type_e)tcp->base.key.type);
+ tcp->base.flag = pjsip_transport_get_flag_from_type(
+ (pjsip_transport_type_e)tcp->base.key.type);
tcp->base.info = (char*) pj_pool_alloc(pool, 64);
- pj_ansi_snprintf(tcp->base.info, 64, "TCP to %s:%d",
- pj_inet_ntoa(remote->sin_addr),
- (int)pj_ntohs(remote->sin_port));
+ pj_ansi_snprintf(tcp->base.info, 64, "%s to %s",
+ tcp->base.type_name,
+ pj_sockaddr_print(remote, print_addr,
+ sizeof(print_addr), 3));
- tcp->base.addr_len = sizeof(pj_sockaddr_in);
- pj_memcpy(&tcp->base.local_addr, local, sizeof(pj_sockaddr_in));
+ tcp->base.addr_len = pj_sockaddr_get_len(remote);
+ pj_sockaddr_cp(&tcp->base.local_addr, local);
sockaddr_to_host_port(pool, &tcp->base.local_name, local);
sockaddr_to_host_port(pool, &tcp->base.remote_name, remote);
tcp->base.dir = is_server? PJSIP_TP_DIR_INCOMING : PJSIP_TP_DIR_OUTGOING;
@@ -601,7 +615,6 @@ static pj_status_t tcp_create( struct tcp_listener *listener,
tcp->base.do_shutdown = &tcp_shutdown;
tcp->base.destroy = &tcp_destroy_transport;
-
/* Create active socket */
pj_activesock_cfg_default(&asock_cfg);
asock_cfg.async_cnt = 1;
@@ -649,6 +662,9 @@ on_error:
/* Flush all delayed transmision once the socket is connected. */
static void tcp_flush_pending_tx(struct tcp_transport *tcp)
{
+ pj_time_val now;
+
+ pj_gettickcount(&now);
pj_lock_acquire(tcp->base.lock);
while (!pj_list_empty(&tcp->delayed_list)) {
struct delayed_tdata *pending_tx;
@@ -663,12 +679,20 @@ static void tcp_flush_pending_tx(struct tcp_transport *tcp)
tdata = pending_tx->tdata_op_key->tdata;
op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;
+ if (pending_tx->timeout.sec > 0 &&
+ PJ_TIME_VAL_GT(now, pending_tx->timeout))
+ {
+ continue;
+ }
+
/* send! */
size = tdata->buf.cur - tdata->buf.start;
status = pj_activesock_send(tcp->asock, op_key, tdata->buf.start,
&size, 0);
if (status != PJ_EPENDING) {
+ pj_lock_release(tcp->base.lock);
on_data_sent(tcp->asock, op_key, size);
+ pj_lock_acquire(tcp->base.lock);
}
}
@@ -791,7 +815,7 @@ static pj_status_t tcp_start_read(struct tcp_transport *tcp)
{
pj_pool_t *pool;
pj_ssize_t size;
- pj_sockaddr_in *rem_addr;
+ pj_sockaddr *rem_addr;
void *readbuf[1];
pj_status_t status;
@@ -814,11 +838,11 @@ static pj_status_t tcp_start_read(struct tcp_transport *tcp)
sizeof(pj_ioqueue_op_key_t));
tcp->rdata.pkt_info.src_addr = tcp->base.key.rem_addr;
- tcp->rdata.pkt_info.src_addr_len = sizeof(pj_sockaddr_in);
- rem_addr = (pj_sockaddr_in*) &tcp->base.key.rem_addr;
- pj_ansi_strcpy(tcp->rdata.pkt_info.src_name,
- pj_inet_ntoa(rem_addr->sin_addr));
- tcp->rdata.pkt_info.src_port = pj_ntohs(rem_addr->sin_port);
+ tcp->rdata.pkt_info.src_addr_len = sizeof(tcp->rdata.pkt_info.src_addr);
+ rem_addr = &tcp->base.key.rem_addr;
+ pj_sockaddr_print(rem_addr, tcp->rdata.pkt_info.src_name,
+ sizeof(tcp->rdata.pkt_info.src_name), 0);
+ tcp->rdata.pkt_info.src_port = pj_sockaddr_get_port(rem_addr);
size = sizeof(tcp->rdata.pkt_info.packet);
readbuf[0] = tcp->rdata.pkt_info.packet;
@@ -848,23 +872,25 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
struct tcp_listener *listener;
struct tcp_transport *tcp;
pj_sock_t sock;
- pj_sockaddr_in local_addr;
+ pj_sockaddr local_addr;
pj_status_t status;
/* Sanity checks */
PJ_ASSERT_RETURN(factory && mgr && endpt && rem_addr &&
addr_len && p_transport, PJ_EINVAL);
- /* Check that address is a sockaddr_in */
- PJ_ASSERT_RETURN(rem_addr->addr.sa_family == pj_AF_INET() &&
- addr_len == sizeof(pj_sockaddr_in), PJ_EINVAL);
+ /* Check that address is a sockaddr_in or sockaddr_in6*/
+ PJ_ASSERT_RETURN((rem_addr->addr.sa_family == pj_AF_INET() &&
+ addr_len == sizeof(pj_sockaddr_in)) ||
+ (rem_addr->addr.sa_family == pj_AF_INET6() &&
+ addr_len == sizeof(pj_sockaddr_in6)), PJ_EINVAL);
listener = (struct tcp_listener*)factory;
-
/* Create socket */
- status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
+ status = pj_sock_socket(rem_addr->addr.sa_family, pj_SOCK_STREAM(),
+ 0, &sock);
if (status != PJ_SUCCESS)
return status;
@@ -874,15 +900,20 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
2, listener->factory.obj_name,
"outgoing SIP TCP socket");
- /* Bind to any port */
- status = pj_sock_bind_in(sock, 0, 0);
+ /* Bind to listener's address and any port */
+ pj_bzero(&local_addr, sizeof(local_addr));
+ pj_sockaddr_cp(&local_addr, &listener->bound_addr);
+ pj_sockaddr_set_port(&local_addr, 0);
+
+ status = pj_sock_bind(sock, &local_addr,
+ pj_sockaddr_get_len(&local_addr));
if (status != PJ_SUCCESS) {
pj_sock_close(sock);
return status;
}
/* Get the local port */
- addr_len = sizeof(pj_sockaddr_in);
+ addr_len = sizeof(local_addr);
status = pj_sock_getsockname(sock, &local_addr, &addr_len);
if (status != PJ_SUCCESS) {
pj_sock_close(sock);
@@ -890,12 +921,13 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
}
/* Initially set the address from the listener's address */
- local_addr.sin_addr.s_addr =
- ((pj_sockaddr_in*)&listener->factory.local_addr)->sin_addr.s_addr;
+ if (!pj_sockaddr_has_addr(&local_addr)) {
+ pj_sockaddr_copy_addr(&local_addr, &listener->factory.local_addr);
+ }
/* Create the transport descriptor */
status = tcp_create(listener, NULL, sock, PJ_FALSE, &local_addr,
- (pj_sockaddr_in*)rem_addr, &tcp);
+ rem_addr, &tcp);
if (status != PJ_SUCCESS)
return status;
@@ -903,7 +935,7 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
/* Start asynchronous connect() operation */
tcp->has_pending_connect = PJ_TRUE;
status = pj_activesock_start_connect(tcp->asock, tcp->base.pool, rem_addr,
- sizeof(pj_sockaddr_in));
+ addr_len);
if (status == PJ_SUCCESS) {
on_connect_complete(tcp->asock, PJ_SUCCESS);
} else if (status != PJ_EPENDING) {
@@ -915,18 +947,17 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
/* Update (again) local address, just in case local address currently
* set is different now that asynchronous connect() is started.
*/
- addr_len = sizeof(pj_sockaddr_in);
+ addr_len = sizeof(local_addr);
if (pj_sock_getsockname(sock, &local_addr, &addr_len)==PJ_SUCCESS) {
- pj_sockaddr_in *tp_addr = (pj_sockaddr_in*)&tcp->base.local_addr;
+ pj_sockaddr *tp_addr = &tcp->base.local_addr;
/* Some systems (like old Win32 perhaps) may not set local address
* properly before socket is fully connected.
*/
- if (tp_addr->sin_addr.s_addr != local_addr.sin_addr.s_addr &&
- local_addr.sin_addr.s_addr != 0)
+ if (pj_sockaddr_cmp(tp_addr, &local_addr) &&
+ pj_sockaddr_get_port(&local_addr) != 0)
{
- tp_addr->sin_addr.s_addr = local_addr.sin_addr.s_addr;
- tp_addr->sin_port = local_addr.sin_port;
+ pj_sockaddr_cp(tp_addr, &local_addr);
sockaddr_to_host_port(tcp->base.pool, &tcp->base.local_name,
&local_addr);
}
@@ -962,6 +993,7 @@ static pj_bool_t on_accept_complete(pj_activesock_t *asock,
struct tcp_transport *tcp;
char addr[PJ_INET6_ADDRSTRLEN+10];
pjsip_tp_state_callback state_cb;
+ pj_sockaddr tmp_src_addr;
pj_status_t status;
PJ_UNUSED_ARG(src_addr_len);
@@ -985,13 +1017,19 @@ static pj_bool_t on_accept_complete(pj_activesock_t *asock,
2, listener->factory.obj_name,
"incoming SIP TCP socket");
+ /* tcp_create() expect pj_sockaddr, so copy src_addr to temporary var,
+ * just in case.
+ */
+ pj_bzero(&tmp_src_addr, sizeof(tmp_src_addr));
+ pj_sockaddr_cp(&tmp_src_addr, src_addr);
+
/*
* Incoming connection!
* Create TCP transport for the new socket.
*/
status = tcp_create( listener, NULL, sock, PJ_TRUE,
- (const pj_sockaddr_in*)&listener->factory.local_addr,
- (const pj_sockaddr_in*)src_addr, &tcp);
+ &listener->factory.local_addr,
+ &tmp_src_addr, &tcp);
if (status == PJ_SUCCESS) {
status = tcp_start_read(tcp);
if (status != PJ_SUCCESS) {
@@ -1095,9 +1133,9 @@ static pj_status_t tcp_send_msg(pjsip_transport *transport,
PJ_ASSERT_RETURN(tdata->op_key.tdata == NULL, PJSIP_EPENDINGTX);
/* Check the address is supported */
- PJ_ASSERT_RETURN(rem_addr && addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL);
-
-
+ PJ_ASSERT_RETURN(rem_addr && (addr_len==sizeof(pj_sockaddr_in) ||
+ addr_len==sizeof(pj_sockaddr_in6)),
+ PJ_EINVAL);
/* Init op key. */
tdata->op_key.tdata = tdata;
@@ -1122,10 +1160,19 @@ static pj_status_t tcp_send_msg(pjsip_transport *transport,
/*
* connect() is still in progress. Put the transmit data to
* the delayed list.
+ * Starting from #1583 (https://trac.pjsip.org/repos/ticket/1583),
+ * we also add timeout value for the transmit data. When the
+ * connect() is completed, the timeout value will be checked to
+ * determine whether the transmit data needs to be sent.
*/
- delayed_tdata = PJ_POOL_ALLOC_T(tdata->pool,
- struct delayed_tdata);
+ delayed_tdata = PJ_POOL_ZALLOC_T(tdata->pool,
+ struct delayed_tdata);
delayed_tdata->tdata_op_key = &tdata->op_key;
+ if (tdata->msg && tdata->msg->type == PJSIP_REQUEST_MSG) {
+ pj_gettickcount(&delayed_tdata->timeout);
+ delayed_tdata->timeout.msec += pjsip_cfg()->tsx.td;
+ pj_time_val_normalize(&delayed_tdata->timeout);
+ }
pj_list_push_back(&tcp->delayed_list, delayed_tdata);
status = PJ_EPENDING;
@@ -1269,7 +1316,7 @@ static pj_bool_t on_connect_complete(pj_activesock_t *asock,
pj_status_t status)
{
struct tcp_transport *tcp;
- pj_sockaddr_in addr;
+ pj_sockaddr addr;
int addrlen;
pjsip_tp_state_callback state_cb;
@@ -1314,15 +1361,14 @@ static pj_bool_t on_connect_complete(pj_activesock_t *asock,
* set is different now that the socket is connected (could happen
* on some systems, like old Win32 probably?).
*/
- addrlen = sizeof(pj_sockaddr_in);
+ addrlen = sizeof(addr);
if (pj_sock_getsockname(tcp->sock, &addr, &addrlen)==PJ_SUCCESS) {
- pj_sockaddr_in *tp_addr = (pj_sockaddr_in*)&tcp->base.local_addr;
+ pj_sockaddr *tp_addr = &tcp->base.local_addr;
if (pj_sockaddr_has_addr(&addr) &&
- tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr)
+ pj_sockaddr_cmp(&addr, tp_addr) != 0)
{
- tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr;
- tp_addr->sin_port = addr.sin_port;
+ pj_sockaddr_cp(tp_addr, &addr);
sockaddr_to_host_port(tcp->base.pool, &tcp->base.local_name,
tp_addr);
}
diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c
index 878b6db..2f244cc 100644
--- a/pjsip/src/pjsip/sip_transport_tls.c
+++ b/pjsip/src/pjsip/sip_transport_tls.c
@@ -1,4 +1,4 @@
-/* $Id: sip_transport_tls.c 4146 2012-05-30 06:35:59Z nanang $ */
+/* $Id: sip_transport_tls.c 4411 2013-03-04 04:34:38Z nanang $ */
/*
* Copyright (C) 2009-2011 Teluu Inc. (http://www.teluu.com)
*
@@ -55,6 +55,7 @@ struct tls_listener
pjsip_endpoint *endpt;
pjsip_tpmgr *tpmgr;
pj_ssl_sock_t *ssock;
+ pj_sockaddr bound_addr;
pj_ssl_cert_t *cert;
pjsip_tls_setting tls_setting;
};
@@ -71,6 +72,7 @@ struct delayed_tdata
{
PJ_DECL_LIST_MEMBER(struct delayed_tdata);
pjsip_tx_data_op_key *tdata_op_key;
+ pj_time_val timeout;
};
@@ -146,8 +148,8 @@ static pj_status_t tls_create(struct tls_listener *listener,
pj_pool_t *pool,
pj_ssl_sock_t *ssock,
pj_bool_t is_server,
- const pj_sockaddr_in *local,
- const pj_sockaddr_in *remote,
+ const pj_sockaddr *local,
+ const pj_sockaddr *remote,
const pj_str_t *remote_name,
struct tls_transport **p_tls);
@@ -165,10 +167,10 @@ static void tls_perror(const char *sender, const char *title,
static void sockaddr_to_host_port( pj_pool_t *pool,
pjsip_host_port *host_port,
- const pj_sockaddr_in *addr )
+ const pj_sockaddr *addr )
{
host_port->host.ptr = (char*) pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+4);
- pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 2);
+ pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 0);
host_port->host.slen = pj_ansi_strlen(host_port->host.ptr);
host_port->port = pj_sockaddr_get_port(addr);
}
@@ -234,29 +236,50 @@ static void tls_init_shutdown(struct tls_transport *tls, pj_status_t status)
*/
PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
const pjsip_tls_setting *opt,
- const pj_sockaddr_in *local,
+ const pj_sockaddr_in *local_in,
const pjsip_host_port *a_name,
unsigned async_cnt,
pjsip_tpfactory **p_factory)
{
+ pj_sockaddr local;
+
+ if (local_in)
+ pj_sockaddr_cp(&local, local_in);
+
+ return pjsip_tls_transport_start2(endpt, opt, (local_in? &local : NULL),
+ a_name, async_cnt, p_factory);
+}
+
+PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt,
+ const pjsip_tls_setting *opt,
+ const pj_sockaddr *local,
+ const pjsip_host_port *a_name,
+ unsigned async_cnt,
+ pjsip_tpfactory **p_factory)
+{
pj_pool_t *pool;
+ pj_bool_t is_ipv6;
+ int af;
struct tls_listener *listener;
pj_ssl_sock_param ssock_param;
- pj_sockaddr_in *listener_addr;
+ pj_sockaddr *listener_addr;
pj_bool_t has_listener;
pj_status_t status;
/* Sanity check */
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
+ is_ipv6 = (local && local->addr.sa_family == pj_AF_INET6());
+ af = is_ipv6 ? pj_AF_INET6() : pj_AF_INET();
+
/* Verify that address given in a_name (if any) is valid */
if (a_name && a_name->host.slen) {
- pj_sockaddr_in tmp;
+ pj_sockaddr tmp;
- status = pj_sockaddr_in_init(&tmp, &a_name->host,
- (pj_uint16_t)a_name->port);
- if (status != PJ_SUCCESS || tmp.sin_addr.s_addr == PJ_INADDR_ANY ||
- tmp.sin_addr.s_addr == PJ_INADDR_NONE)
+ status = pj_sockaddr_init(af, &tmp, &a_name->host,
+ (pj_uint16_t)a_name->port);
+ if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) ||
+ (!is_ipv6 && tmp.ipv4.sin_addr.s_addr == PJ_INADDR_NONE))
{
/* Invalid address */
return PJ_EINVAL;
@@ -269,19 +292,25 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
listener = PJ_POOL_ZALLOC_T(pool, struct tls_listener);
listener->factory.pool = pool;
- listener->factory.type = PJSIP_TRANSPORT_TLS;
- listener->factory.type_name = "tls";
+ if (is_ipv6)
+ listener->factory.type = PJSIP_TRANSPORT_TLS6;
+ else
+ listener->factory.type = PJSIP_TRANSPORT_TLS;
+ listener->factory.type_name = (char*)
+ pjsip_transport_get_type_name(listener->factory.type);
listener->factory.flag =
- pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TLS);
+ pjsip_transport_get_flag_from_type(listener->factory.type);
pj_ansi_strcpy(listener->factory.obj_name, "tlslis");
+ if (is_ipv6)
+ pj_ansi_strcat(listener->factory.obj_name, "6");
if (opt)
pjsip_tls_setting_copy(pool, &listener->tls_setting, opt);
else
pjsip_tls_setting_default(&listener->tls_setting);
- status = pj_lock_create_recursive_mutex(pool, "tlslis",
+ status = pj_lock_create_recursive_mutex(pool, listener->factory.obj_name,
&listener->factory.lock);
if (status != PJ_SUCCESS)
goto on_error;
@@ -291,6 +320,7 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
/* Build SSL socket param */
pj_ssl_sock_param_default(&ssock_param);
+ ssock_param.sock_af = af;
ssock_param.cb.on_accept_complete = &on_accept_complete;
ssock_param.cb.on_data_read = &on_data_read;
ssock_param.cb.on_data_sent = &on_data_sent;
@@ -337,12 +367,17 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
if (status != PJ_SUCCESS)
goto on_error;
- listener_addr = (pj_sockaddr_in*)&listener->factory.local_addr;
+ /* Bind address may be different than factory.local_addr because
+ * factory.local_addr will be resolved below.
+ */
+ listener_addr = &listener->factory.local_addr;
if (local) {
pj_sockaddr_cp((pj_sockaddr_t*)listener_addr,
(const pj_sockaddr_t*)local);
+ pj_sockaddr_cp(&listener->bound_addr, local);
} else {
- pj_sockaddr_in_init(listener_addr, NULL, 0);
+ pj_sockaddr_init(af, listener_addr, NULL, 0);
+ pj_sockaddr_init(af, &listener->bound_addr, NULL, 0);
}
/* Check if certificate/CA list for SSL socket is set */
@@ -400,14 +435,14 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
/* If the address returns 0.0.0.0, use the default
* interface address as the transport's address.
*/
- if (listener_addr->sin_addr.s_addr == 0) {
+ if (!pj_sockaddr_has_addr(listener_addr)) {
pj_sockaddr hostip;
- status = pj_gethostip(pj_AF_INET(), &hostip);
+ status = pj_gethostip(af, &hostip);
if (status != PJ_SUCCESS)
goto on_error;
- listener_addr->sin_addr.s_addr = hostip.ipv4.sin_addr.s_addr;
+ pj_sockaddr_copy_addr(listener_addr, &hostip);
}
/* Save the address name */
@@ -417,7 +452,7 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
/* If port is zero, get the bound port */
if (listener->factory.addr_name.port == 0) {
- listener->factory.addr_name.port = pj_ntohs(listener_addr->sin_port);
+ listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr);
}
pj_ansi_snprintf(listener->factory.obj_name,
@@ -534,13 +569,14 @@ static pj_status_t tls_create( struct tls_listener *listener,
pj_pool_t *pool,
pj_ssl_sock_t *ssock,
pj_bool_t is_server,
- const pj_sockaddr_in *local,
- const pj_sockaddr_in *remote,
+ const pj_sockaddr *local,
+ const pj_sockaddr *remote,
const pj_str_t *remote_name,
struct tls_transport **p_tls)
{
struct tls_transport *tls;
const pj_str_t ka_pkt = PJSIP_TLS_KEEP_ALIVE_DATA;
+ char print_addr[PJ_INET6_ADDRSTRLEN+10];
pj_status_t status;
@@ -578,17 +614,21 @@ static pj_status_t tls_create( struct tls_listener *listener,
if (remote_name)
pj_strdup(pool, &tls->remote_name, remote_name);
- tls->base.key.type = PJSIP_TRANSPORT_TLS;
- pj_memcpy(&tls->base.key.rem_addr, remote, sizeof(pj_sockaddr_in));
- tls->base.type_name = "tls";
- tls->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TLS);
+ tls->base.key.type = listener->factory.type;
+ pj_sockaddr_cp(&tls->base.key.rem_addr, remote);
+ tls->base.type_name = (char*)pjsip_transport_get_type_name(
+ (pjsip_transport_type_e)tls->base.key.type);
+ tls->base.flag = pjsip_transport_get_flag_from_type(
+ (pjsip_transport_type_e)tls->base.key.type);
tls->base.info = (char*) pj_pool_alloc(pool, 64);
- pj_ansi_snprintf(tls->base.info, 64, "TLS to %s:%d",
- pj_inet_ntoa(remote->sin_addr),
- (int)pj_ntohs(remote->sin_port));
+ pj_ansi_snprintf(tls->base.info, 64, "%s to %s",
+ tls->base.type_name,
+ pj_sockaddr_print(remote, print_addr,
+ sizeof(print_addr), 3));
- tls->base.addr_len = sizeof(pj_sockaddr_in);
+
+ tls->base.addr_len = pj_sockaddr_get_len(remote);
tls->base.dir = is_server? PJSIP_TP_DIR_INCOMING : PJSIP_TP_DIR_OUTGOING;
/* Set initial local address */
@@ -599,11 +639,10 @@ static pj_status_t tls_create( struct tls_listener *listener,
pj_sockaddr_cp(&tls->base.local_addr, local);
}
- sockaddr_to_host_port(pool, &tls->base.local_name,
- (pj_sockaddr_in*)&tls->base.local_addr);
+ sockaddr_to_host_port(pool, &tls->base.local_name, &tls->base.local_addr);
if (tls->remote_name.slen) {
tls->base.remote_name.host = tls->remote_name;
- tls->base.remote_name.port = pj_sockaddr_in_get_port(remote);
+ tls->base.remote_name.port = pj_sockaddr_get_port(remote);
} else {
sockaddr_to_host_port(pool, &tls->base.remote_name, remote);
}
@@ -647,6 +686,9 @@ on_error:
/* Flush all delayed transmision once the socket is connected. */
static void tls_flush_pending_tx(struct tls_transport *tls)
{
+ pj_time_val now;
+
+ pj_gettickcount(&now);
pj_lock_acquire(tls->base.lock);
while (!pj_list_empty(&tls->delayed_list)) {
struct delayed_tdata *pending_tx;
@@ -661,13 +703,21 @@ static void tls_flush_pending_tx(struct tls_transport *tls)
tdata = pending_tx->tdata_op_key->tdata;
op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;
+ if (pending_tx->timeout.sec > 0 &&
+ PJ_TIME_VAL_GT(now, pending_tx->timeout))
+ {
+ continue;
+ }
+
/* send! */
size = tdata->buf.cur - tdata->buf.start;
status = pj_ssl_sock_send(tls->ssock, op_key, tdata->buf.start,
&size, 0);
if (status != PJ_EPENDING) {
+ pj_lock_release(tls->base.lock);
on_data_sent(tls->ssock, op_key, size);
+ pj_lock_acquire(tls->base.lock);
}
}
pj_lock_release(tls->base.lock);
@@ -784,7 +834,7 @@ static pj_status_t tls_start_read(struct tls_transport *tls)
{
pj_pool_t *pool;
pj_ssize_t size;
- pj_sockaddr_in *rem_addr;
+ pj_sockaddr *rem_addr;
void *readbuf[1];
pj_status_t status;
@@ -807,11 +857,11 @@ static pj_status_t tls_start_read(struct tls_transport *tls)
sizeof(pj_ioqueue_op_key_t));
tls->rdata.pkt_info.src_addr = tls->base.key.rem_addr;
- tls->rdata.pkt_info.src_addr_len = sizeof(pj_sockaddr_in);
- rem_addr = (pj_sockaddr_in*) &tls->base.key.rem_addr;
- pj_ansi_strcpy(tls->rdata.pkt_info.src_name,
- pj_inet_ntoa(rem_addr->sin_addr));
- tls->rdata.pkt_info.src_port = pj_ntohs(rem_addr->sin_port);
+ tls->rdata.pkt_info.src_addr_len = sizeof(tls->rdata.pkt_info.src_addr);
+ rem_addr = &tls->base.key.rem_addr;
+ pj_sockaddr_print(rem_addr, tls->rdata.pkt_info.src_name,
+ sizeof(tls->rdata.pkt_info.src_name), 0);
+ tls->rdata.pkt_info.src_port = pj_sockaddr_get_port(rem_addr);
size = sizeof(tls->rdata.pkt_info.packet);
readbuf[0] = tls->rdata.pkt_info.packet;
@@ -844,7 +894,7 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
pj_pool_t *pool;
pj_ssl_sock_t *ssock;
pj_ssl_sock_param ssock_param;
- pj_sockaddr_in local_addr;
+ pj_sockaddr local_addr;
pj_str_t remote_name;
pj_status_t status;
@@ -852,9 +902,11 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
PJ_ASSERT_RETURN(factory && mgr && endpt && rem_addr &&
addr_len && p_transport, PJ_EINVAL);
- /* Check that address is a sockaddr_in */
- PJ_ASSERT_RETURN(rem_addr->addr.sa_family == pj_AF_INET() &&
- addr_len == sizeof(pj_sockaddr_in), PJ_EINVAL);
+ /* Check that address is a sockaddr_in or sockaddr_in6*/
+ PJ_ASSERT_RETURN((rem_addr->addr.sa_family == pj_AF_INET() &&
+ addr_len == sizeof(pj_sockaddr_in)) ||
+ (rem_addr->addr.sa_family == pj_AF_INET6() &&
+ addr_len == sizeof(pj_sockaddr_in6)), PJ_EINVAL);
listener = (struct tls_listener*)factory;
@@ -871,6 +923,8 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
/* Build SSL socket param */
pj_ssl_sock_param_default(&ssock_param);
+ ssock_param.sock_af = (factory->type & PJSIP_TRANSPORT_IPV6) ?
+ pj_AF_INET6() : pj_AF_INET();
ssock_param.cb.on_connect_complete = &on_connect_complete;
ssock_param.cb.on_data_read = &on_data_read;
ssock_param.cb.on_data_sent = &on_data_sent;
@@ -921,12 +975,14 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
return status;
}
- /* Initially set bind address to PJ_INADDR_ANY port 0 */
- pj_sockaddr_in_init(&local_addr, NULL, 0);
+ /* Initially set bind address to listener's bind address */
+ pj_sockaddr_init(listener->bound_addr.addr.sa_family,
+ &local_addr, NULL, 0);
+ pj_sockaddr_copy_addr(&local_addr, &listener->bound_addr);
/* Create the transport descriptor */
status = tls_create(listener, pool, ssock, PJ_FALSE, &local_addr,
- (pj_sockaddr_in*)rem_addr, &remote_name, &tls);
+ rem_addr, &remote_name, &tls);
if (status != PJ_SUCCESS)
return status;
@@ -973,7 +1029,7 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
}
sockaddr_to_host_port(tls->base.pool, &tls->base.local_name,
- (pj_sockaddr_in*)&tls->base.local_addr);
+ &tls->base.local_addr);
}
PJ_LOG(4,(tls->base.obj_name,
@@ -1007,6 +1063,7 @@ static pj_bool_t on_accept_complete(pj_ssl_sock_t *ssock,
pj_ssl_sock_info ssl_info;
char addr[PJ_INET6_ADDRSTRLEN+10];
pjsip_tp_state_callback state_cb;
+ pj_sockaddr tmp_src_addr;
pj_bool_t is_shutdown;
pj_status_t status;
@@ -1034,13 +1091,17 @@ static pj_bool_t on_accept_complete(pj_ssl_sock_t *ssock,
return PJ_TRUE;
}
+ /* Copy to larger buffer, just in case */
+ pj_bzero(&tmp_src_addr, sizeof(tmp_src_addr));
+ pj_sockaddr_cp(&tmp_src_addr, src_addr);
+
/*
* Incoming connection!
* Create TLS transport for the new socket.
*/
status = tls_create( listener, NULL, new_ssock, PJ_TRUE,
- (const pj_sockaddr_in*)&listener->factory.local_addr,
- (const pj_sockaddr_in*)src_addr, NULL, &tls);
+ &listener->factory.local_addr,
+ &tmp_src_addr, NULL, &tls);
if (status != PJ_SUCCESS)
return PJ_TRUE;
@@ -1190,9 +1251,9 @@ static pj_status_t tls_send_msg(pjsip_transport *transport,
PJ_ASSERT_RETURN(tdata->op_key.tdata == NULL, PJSIP_EPENDINGTX);
/* Check the address is supported */
- PJ_ASSERT_RETURN(rem_addr && addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL);
-
-
+ PJ_ASSERT_RETURN(rem_addr && (addr_len==sizeof(pj_sockaddr_in) ||
+ addr_len==sizeof(pj_sockaddr_in6)),
+ PJ_EINVAL);
/* Init op key. */
tdata->op_key.tdata = tdata;
@@ -1217,10 +1278,19 @@ static pj_status_t tls_send_msg(pjsip_transport *transport,
/*
* connect() is still in progress. Put the transmit data to
* the delayed list.
+ * Starting from #1583 (https://trac.pjsip.org/repos/ticket/1583),
+ * we also add timeout value for the transmit data. When the
+ * connect() is completed, the timeout value will be checked to
+ * determine whether the transmit data needs to be sent.
*/
- delayed_tdata = PJ_POOL_ALLOC_T(tdata->pool,
- struct delayed_tdata);
+ delayed_tdata = PJ_POOL_ZALLOC_T(tdata->pool,
+ struct delayed_tdata);
delayed_tdata->tdata_op_key = &tdata->op_key;
+ if (tdata->msg && tdata->msg->type == PJSIP_REQUEST_MSG) {
+ pj_gettickcount(&delayed_tdata->timeout);
+ delayed_tdata->timeout.msec += pjsip_cfg()->tsx.td;
+ pj_time_val_normalize(&delayed_tdata->timeout);
+ }
pj_list_push_back(&tls->delayed_list, delayed_tdata);
status = PJ_EPENDING;
@@ -1365,7 +1435,7 @@ static pj_bool_t on_connect_complete(pj_ssl_sock_t *ssock,
{
struct tls_transport *tls;
pj_ssl_sock_info ssl_info;
- pj_sockaddr_in addr, *tp_addr;
+ pj_sockaddr addr, *tp_addr;
pjsip_tp_state_callback state_cb;
pj_bool_t is_shutdown;
@@ -1403,12 +1473,11 @@ static pj_bool_t on_connect_complete(pj_ssl_sock_t *ssock,
* set is different now that the socket is connected (could happen
* on some systems, like old Win32 probably?).
*/
- tp_addr = (pj_sockaddr_in*)&tls->base.local_addr;
+ tp_addr = &tls->base.local_addr;
pj_sockaddr_cp((pj_sockaddr_t*)&addr,
(pj_sockaddr_t*)&ssl_info.local_addr);
- if (tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr) {
- tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr;
- tp_addr->sin_port = addr.sin_port;
+ if (pj_sockaddr_cmp(tp_addr, &addr) != 0) {
+ pj_sockaddr_cp(tp_addr, &addr);
sockaddr_to_host_port(tls->base.pool, &tls->base.local_name,
tp_addr);
}
diff --git a/pjsip/src/pjsip/sip_ua_layer.c b/pjsip/src/pjsip/sip_ua_layer.c
index 7128891..723c061 100644
--- a/pjsip/src/pjsip/sip_ua_layer.c
+++ b/pjsip/src/pjsip/sip_ua_layer.c
@@ -1,4 +1,4 @@
-/* $Id: sip_ua_layer.c 3664 2011-07-19 03:42:28Z nanang $ */
+/* $Id: sip_ua_layer.c 4208 2012-07-18 07:52:33Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -302,9 +302,10 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dlg( pjsip_user_agent *ua,
struct dlg_set *dlg_set;
dlg_set = (struct dlg_set*)
- pj_hash_get( mod_ua.dlg_table, dlg->local.info->tag.ptr,
- dlg->local.info->tag.slen,
- &dlg->local.tag_hval);
+ pj_hash_get_lower( mod_ua.dlg_table,
+ dlg->local.info->tag.ptr,
+ dlg->local.info->tag.slen,
+ &dlg->local.tag_hval);
if (dlg_set) {
/* This is NOT the first dialog in the dialog set.
@@ -326,9 +327,11 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dlg( pjsip_user_agent *ua,
dlg->dlg_set = dlg_set;
/* Register the dialog set in the hash table. */
- pj_hash_set_np(mod_ua.dlg_table,
- dlg->local.info->tag.ptr, dlg->local.info->tag.slen,
- dlg->local.tag_hval, dlg_set->ht_entry, dlg_set);
+ pj_hash_set_np_lower(mod_ua.dlg_table,
+ dlg->local.info->tag.ptr,
+ dlg->local.info->tag.slen,
+ dlg->local.tag_hval, dlg_set->ht_entry,
+ dlg_set);
}
} else {
@@ -341,9 +344,10 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dlg( pjsip_user_agent *ua,
dlg->dlg_set = dlg_set;
- pj_hash_set_np(mod_ua.dlg_table,
- dlg->local.info->tag.ptr, dlg->local.info->tag.slen,
- dlg->local.tag_hval, dlg_set->ht_entry, dlg_set);
+ pj_hash_set_np_lower(mod_ua.dlg_table,
+ dlg->local.info->tag.ptr,
+ dlg->local.info->tag.slen,
+ dlg->local.tag_hval, dlg_set->ht_entry, dlg_set);
}
/* Unlock user agent. */
@@ -387,8 +391,9 @@ PJ_DEF(pj_status_t) pjsip_ua_unregister_dlg( pjsip_user_agent *ua,
/* If dialog list is empty, remove the dialog set from the hash table. */
if (pj_list_empty(&dlg_set->dlg_list)) {
- pj_hash_set(NULL, mod_ua.dlg_table, dlg->local.info->tag.ptr,
- dlg->local.info->tag.slen, dlg->local.tag_hval, NULL);
+ pj_hash_set_lower(NULL, mod_ua.dlg_table, dlg->local.info->tag.ptr,
+ dlg->local.info->tag.slen, dlg->local.tag_hval,
+ NULL);
/* Return dlg_set to free nodes. */
pj_list_push_back(&mod_ua.free_dlgset_nodes, dlg_set);
@@ -449,8 +454,8 @@ PJ_DEF(pjsip_dialog*) pjsip_ua_find_dialog(const pj_str_t *call_id,
/* Lookup the dialog set. */
dlg_set = (struct dlg_set*)
- pj_hash_get(mod_ua.dlg_table, local_tag->ptr, local_tag->slen,
- NULL);
+ pj_hash_get_lower(mod_ua.dlg_table, local_tag->ptr,
+ local_tag->slen, NULL);
if (dlg_set == NULL) {
/* Not found */
pj_mutex_unlock(mod_ua.mutex);
@@ -462,7 +467,7 @@ PJ_DEF(pjsip_dialog*) pjsip_ua_find_dialog(const pj_str_t *call_id,
*/
dlg = dlg_set->dlg_list.next;
while (dlg != (pjsip_dialog*)&dlg_set->dlg_list) {
- if (pj_strcmp(&dlg->remote.info->tag, remote_tag) == 0)
+ if (pj_stricmp(&dlg->remote.info->tag, remote_tag) == 0)
break;
dlg = dlg->next;
}
@@ -563,7 +568,8 @@ static struct dlg_set *find_dlg_set_for_msg( pjsip_rx_data *rdata )
/* Lookup the dialog set. */
dlg_set = (struct dlg_set*)
- pj_hash_get(mod_ua.dlg_table, tag->ptr, tag->slen, NULL);
+ pj_hash_get_lower(mod_ua.dlg_table, tag->ptr, tag->slen,
+ NULL);
return dlg_set;
}
}
@@ -624,7 +630,7 @@ retry_on_deadlock:
dlg = dlg_set->dlg_list.next;
while (dlg != (pjsip_dialog*)&dlg_set->dlg_list) {
- if (pj_strcmp(&dlg->remote.info->tag, from_tag) == 0)
+ if (pj_stricmp(&dlg->remote.info->tag, from_tag) == 0)
break;
dlg = dlg->next;
@@ -761,10 +767,10 @@ retry_on_deadlock:
/* Get the dialog set. */
dlg_set = (struct dlg_set*)
- pj_hash_get(mod_ua.dlg_table,
- rdata->msg_info.from->tag.ptr,
- rdata->msg_info.from->tag.slen,
- NULL);
+ pj_hash_get_lower(mod_ua.dlg_table,
+ rdata->msg_info.from->tag.ptr,
+ rdata->msg_info.from->tag.slen,
+ NULL);
if (!dlg_set) {
/* Unlock dialog hash table. */
@@ -812,7 +818,7 @@ retry_on_deadlock:
break;
/* Otherwise find the one with matching To tag. */
- if (pj_strcmp(to_tag, &dlg->remote.info->tag) == 0)
+ if (pj_stricmp(to_tag, &dlg->remote.info->tag) == 0)
break;
dlg = dlg->next;
diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c
index fba163c..4d54e2e 100644
--- a/pjsip/src/pjsip/sip_uri.c
+++ b/pjsip/src/pjsip/sip_uri.c
@@ -1,4 +1,4 @@
-/* $Id: sip_uri.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: sip_uri.c 4228 2012-08-13 07:26:03Z bennylp $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -269,7 +269,10 @@ static pj_ssize_t pjsip_url_print( pjsip_uri_context_e context,
/* Print "user:password@", if any. */
if (url->user.slen) {
- copy_advance_escape(buf, url->user, pc->pjsip_USER_SPEC);
+ const pj_cis_t *spec = pjsip_cfg()->endpt.allow_tx_hash_in_uri ?
+ &pc->pjsip_USER_SPEC_LENIENT :
+ &pc->pjsip_USER_SPEC;
+ copy_advance_escape(buf, url->user, *spec);
if (url->passwd.slen) {
*buf++ = ':';
copy_advance_escape(buf, url->passwd, pc->pjsip_PASSWD_SPEC);
diff --git a/pjsip/src/pjsip/sip_util_proxy.c b/pjsip/src/pjsip/sip_util_proxy.c
index 7a34534..02069b9 100644
--- a/pjsip/src/pjsip/sip_util_proxy.c
+++ b/pjsip/src/pjsip/sip_util_proxy.c
@@ -1,4 +1,4 @@
-/* $Id: sip_util_proxy.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: sip_util_proxy.c 4208 2012-07-18 07:52:33Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -345,7 +345,7 @@ PJ_DEF(pj_str_t) pjsip_calculate_branch_id( pjsip_rx_data *rdata )
/* If incoming request does not have RFC 3261 branch value, create
* a branch value from GUID .
*/
- if (pj_strncmp(&rdata->msg_info.via->branch_param,
+ if (pj_strnicmp(&rdata->msg_info.via->branch_param,
&rfc3261_branch, PJSIP_RFC3261_BRANCH_LEN) != 0 )
{
pj_str_t tmp;