diff options
Diffstat (limited to 'pjsip/src/pjsip')
-rw-r--r-- | pjsip/src/pjsip/sip_auth_client.c | 17 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_auth_server.c | 47 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_config.c | 4 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_dialog.c | 23 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_endpoint.c | 160 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_parser.c | 11 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_tel_uri.c | 6 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transaction.c | 43 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transport.c | 243 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transport_tcp.c | 174 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transport_tls.c | 191 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_ua_layer.c | 50 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_uri.c | 7 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_util_proxy.c | 4 |
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(¶m, sizeof(param)); + param.realm = auth_srv->realm; + param.acc_name = acc_name; + param.rdata = rdata; + status = (*auth_srv->lookup2)(rdata->tp_info.pool, ¶m, &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; |