diff options
Diffstat (limited to 'pjsip/src')
-rw-r--r-- | pjsip/src/pjsip/sip_transaction.c | 122 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_util_statefull.c | 6 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 53 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 4 |
4 files changed, 121 insertions, 64 deletions
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c index 911cd6c3..9934e0dd 100644 --- a/pjsip/src/pjsip/sip_transaction.c +++ b/pjsip/src/pjsip/sip_transaction.c @@ -132,6 +132,8 @@ typedef struct tsx_lock_data { /* Timer timeout value constants */ static const pj_time_val t1_timer_val = { PJSIP_T1_TIMEOUT/1000, PJSIP_T1_TIMEOUT%1000 }; +static const pj_time_val t2_timer_val = { PJSIP_T2_TIMEOUT/1000, + PJSIP_T2_TIMEOUT%1000 }; static const pj_time_val t4_timer_val = { PJSIP_T4_TIMEOUT/1000, PJSIP_T4_TIMEOUT%1000 }; static const pj_time_val td_timer_val = { PJSIP_TD_TIMEOUT/1000, @@ -1396,23 +1398,6 @@ PJ_DEF(pj_status_t) pjsip_tsx_set_transport(pjsip_transaction *tsx, /* - * Set the UAC absolute transaction timeout. - */ -PJ_DEF(pj_status_t) pjsip_tsx_set_uac_timeout(pjsip_transaction *tsx, - unsigned msec_time, - pjsip_tsx_timeout_policy policy) -{ - PJ_ASSERT_RETURN(tsx && tsx->role==PJSIP_ROLE_UAC && - tsx->state==PJSIP_TSX_STATE_NULL, PJ_EINVALIDOP); - - tsx->msec_timeout = msec_time; - tsx->timeout_policy = policy; - - return PJ_SUCCESS; -} - - -/* * Set transaction status code and reason. */ static void tsx_set_status_code(pjsip_transaction *tsx, @@ -1809,9 +1794,13 @@ static void tsx_resched_retransmission( pjsip_transaction *tsx ) pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); - msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; + if (tsx->role==PJSIP_ROLE_UAC && tsx->status_code >= 100) + msec_time = PJSIP_T2_TIMEOUT; + else + msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; if (tsx->role == PJSIP_ROLE_UAC) { + pj_assert(tsx->status_code < 200); /* Retransmission for non-INVITE transaction caps-off at T2 */ if (msec_time>PJSIP_T2_TIMEOUT && tsx->method.id!=PJSIP_INVITE_METHOD) msec_time = PJSIP_T2_TIMEOUT; @@ -1913,22 +1902,10 @@ static pj_status_t tsx_on_state_null( pjsip_transaction *tsx, } /* Start Timer B (or called timer F for non-INVITE) for transaction - * timeout. If user has configured the timeout value with - * pjsip_tsx_set_uac_timeout(), use the timeout value there. + * timeout. */ - if (tsx->msec_timeout > 0) { - pj_time_val timeout; - - timeout.sec = tsx->msec_timeout / 1000; - timeout.msec = tsx->msec_timeout % 1000; - - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, - &timeout); - - } else { - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, - &timeout_timer_val); - } + pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, + &timeout_timer_val); /* Start Timer A (or timer E) for retransmission only if unreliable * transport is being used. @@ -2005,26 +1982,53 @@ static pj_status_t tsx_on_state_calling( pjsip_transaction *tsx, if (msg->type != PJSIP_RESPONSE_MSG) return PJSIP_ENOTRESPONSEMSG; - /* Cancel retransmission timer A. */ - if (tsx->retransmit_timer._timer_id != -1) { - pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer); - tsx->retransmit_timer._timer_id = -1; - } - tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); - + code = msg->line.status.code; - /* Cancel timer B (transaction timeout) but look at the timeout policy - * as set by pjsip_tsx_set_uac_timeout(). + /* If the response is final, cancel both retransmission and timeout + * timer. */ - code = msg->line.status.code; - if ((code==100 && tsx->timeout_policy==PJSIP_TSX_IGNORE_100) || - (code<200 && tsx->timeout_policy==PJSIP_TSX_IGNORE_1xx)) - { - /* Don't cancel the timeout timer */ - } - else { - pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); + if (code >= 200) { + if (tsx->retransmit_timer._timer_id != -1) { + pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer); + tsx->retransmit_timer._timer_id = -1; + } + + if (tsx->timeout_timer._timer_id != -1) { + pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); + tsx->timeout_timer._timer_id = -1; + } + + } else { + /* Cancel retransmit timer (for non-INVITE transaction, the + * retransmit timer will be rescheduled at T2. + */ + if (tsx->retransmit_timer._timer_id != -1) { + pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer); + tsx->retransmit_timer._timer_id = -1; + } + + /* For provisional response, only cancel retransmit when this + * is an INVITE transaction. For non-INVITE, section 17.1.2.1 + * of RFC 3261 says that: + * - retransmit timer is set to T2 + * - timeout timer F is not deleted. + */ + if (tsx->method.id == PJSIP_INVITE_METHOD) { + + /* Cancel timeout timer */ + pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); + + } else { + if (!tsx->is_reliable) { + pjsip_endpt_schedule_timer(tsx->endpt, + &tsx->retransmit_timer, + &t2_timer_val); + } + } } + + tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); + /* Discard retransmission message if it is not INVITE. * The INVITE tdata is needed in case we have to generate ACK for @@ -2367,7 +2371,17 @@ static pj_status_t tsx_on_state_proceeding_uac(pjsip_transaction *tsx, &msg->line.status.reason); } else { - tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); + if (event->body.timer.entry == &tsx->retransmit_timer) { + /* Retransmit message. */ + pj_status_t status; + + status = tsx_retransmit( tsx, 1 ); + + return status; + + } else { + tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); + } } if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 100)) { @@ -2406,6 +2420,12 @@ static pj_status_t tsx_on_state_proceeding_uac(pjsip_transaction *tsx, pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout); + /* Cancel retransmission timer */ + if (tsx->retransmit_timer._timer_id != -1) { + pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer); + tsx->retransmit_timer._timer_id = -1; + } + /* Move state to Completed, inform TU. */ tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); diff --git a/pjsip/src/pjsip/sip_util_statefull.c b/pjsip/src/pjsip/sip_util_statefull.c index 8ea63fda..27ce550a 100644 --- a/pjsip/src/pjsip/sip_util_statefull.c +++ b/pjsip/src/pjsip/sip_util_statefull.c @@ -94,6 +94,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, /* Check that transaction layer module is registered to endpoint */ PJ_ASSERT_RETURN(mod_stateful_util.id != -1, PJ_EINVALIDOP); + PJ_UNUSED_ARG(timeout); status = pjsip_tsx_create_uac(&mod_stateful_util, tdata, &tsx); if (status != PJ_SUCCESS) { @@ -105,11 +106,6 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, tsx_data->token = token; tsx_data->cb = cb; - if (timeout >= 0) { - status = pjsip_tsx_set_uac_timeout(tsx, timeout, PJSIP_TSX_IGNORE_1xx); - pj_assert(status == PJ_SUCCESS); - } - tsx->mod_data[mod_stateful_util.id] = tsx_data; status = pjsip_tsx_send_msg(tsx, NULL); diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index dd0b2622..96ca174a 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -678,14 +678,34 @@ static void stun_dns_srv_resolver_cb(void *user_data, * it with gethostbyname() */ if (pjsua_var.ua_cfg.stun_host.slen) { + pj_str_t str_host, str_port; + int port; pj_hostent he; - pjsua_var.stun_status = pj_gethostbyname(&pjsua_var.ua_cfg.stun_host, &he); + str_port.ptr = pj_strchr(&pjsua_var.ua_cfg.stun_host, ':'); + if (str_port.ptr != NULL) { + str_host.ptr = pjsua_var.ua_cfg.stun_host.ptr; + str_host.slen = (str_port.ptr - str_host.ptr); + str_port.ptr++; + str_port.slen = pjsua_var.ua_cfg.stun_host.slen - + str_host.slen - 1; + port = (int)pj_strtoul(&str_port); + if (port < 1 || port > 65535) { + pjsua_perror(THIS_FILE, "Invalid STUN server", PJ_EINVAL); + pjsua_var.stun_status = PJ_EINVAL; + return; + } + } else { + str_host = pjsua_var.ua_cfg.stun_host; + port = 3478; + } + + pjsua_var.stun_status = pj_gethostbyname(&str_host, &he); if (pjsua_var.stun_status == PJ_SUCCESS) { pj_sockaddr_in_init(&pjsua_var.stun_srv.ipv4, NULL, 0); pjsua_var.stun_srv.ipv4.sin_addr = *(pj_in_addr*)he.h_addr; - pjsua_var.stun_srv.ipv4.sin_port = pj_htons((pj_uint16_t)3478); + pjsua_var.stun_srv.ipv4.sin_port = pj_htons((pj_uint16_t)port); PJ_LOG(3,(THIS_FILE, "STUN server %.*s resolved, address is %s:%d", @@ -772,14 +792,35 @@ pj_status_t pjsua_resolve_stun_server(pj_bool_t wait) * gethostbyname(). */ else if (pjsua_var.ua_cfg.stun_host.slen) { + pj_str_t str_host, str_port; + int port; pj_hostent he; - pjsua_var.stun_status = pj_gethostbyname(&pjsua_var.ua_cfg.stun_host, &he); + str_port.ptr = pj_strchr(&pjsua_var.ua_cfg.stun_host, ':'); + if (str_port.ptr != NULL) { + str_host.ptr = pjsua_var.ua_cfg.stun_host.ptr; + str_host.slen = (str_port.ptr - str_host.ptr); + str_port.ptr++; + str_port.slen = pjsua_var.ua_cfg.stun_host.slen - + str_host.slen - 1; + port = (int)pj_strtoul(&str_port); + if (port < 1 || port > 65535) { + pjsua_perror(THIS_FILE, "Invalid STUN server", PJ_EINVAL); + pjsua_var.stun_status = PJ_EINVAL; + return pjsua_var.stun_status; + } + } else { + str_host = pjsua_var.ua_cfg.stun_host; + port = 3478; + } + + + pjsua_var.stun_status = pj_gethostbyname(&str_host, &he); if (pjsua_var.stun_status == PJ_SUCCESS) { pj_sockaddr_in_init(&pjsua_var.stun_srv.ipv4, NULL, 0); pjsua_var.stun_srv.ipv4.sin_addr = *(pj_in_addr*)he.h_addr; - pjsua_var.stun_srv.ipv4.sin_port = pj_htons((pj_uint16_t)3478); + pjsua_var.stun_srv.ipv4.sin_port = pj_htons((pj_uint16_t)port); PJ_LOG(3,(THIS_FILE, "STUN server %.*s resolved, address is %s:%d", @@ -1055,8 +1096,8 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr, * STUN is specified, resolve the address with STUN. */ status = pjstun_get_mapped_addr(&pjsua_var.cp.factory, 1, &sock, - &stun_srv, 3478, - &stun_srv, 3478, + &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), + &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), p_pub_addr); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error contacting STUN server", status); diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 66efe68c..09c65cbf 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -289,8 +289,8 @@ static pj_status_t create_rtp_rtcp_sock(const pjsua_transport_config *cfg, stun_srv = pj_str(ip_addr); status=pjstun_get_mapped_addr(&pjsua_var.cp.factory, 2, sock, - &stun_srv, 3478, - &stun_srv, 3478, + &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), + &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), mapped_addr); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "STUN resolve error", status); |