summaryrefslogtreecommitdiff
path: root/pjsip
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip')
-rw-r--r--pjsip/include/pjsip/sip_transaction.h59
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h3
-rw-r--r--pjsip/src/pjsip/sip_transaction.c122
-rw-r--r--pjsip/src/pjsip/sip_util_statefull.c6
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c53
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c4
6 files changed, 123 insertions, 124 deletions
diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h
index d3a4c3e8..1787f787 100644
--- a/pjsip/include/pjsip/sip_transaction.h
+++ b/pjsip/include/pjsip/sip_transaction.h
@@ -74,21 +74,6 @@ typedef enum pjsip_tsx_state_e
/**
- * Transaction timeout timer policy, to control the UAC transaction timeout
- * scheduling (see #pjsip_tsx_set_uac_timeout()).
- */
-typedef enum pjsip_tsx_timeout_policy
-{
- PJSIP_TSX_IGNORE_100 = 1, /**< To make the UAC transaction NOT to cancel
- the timeout timer when 100 response is
- received.*/
- PJSIP_TSX_IGNORE_1xx = 3 /**< To make the UAC transaction NOT to cancel
- the timeout timer when any 1xx responses
- are received. */
-} pjsip_tsx_timeout_policy;
-
-
-/**
* This structure describes SIP transaction object. The transaction object
* is used to handle both UAS and UAC transaction.
*/
@@ -145,9 +130,6 @@ struct pjsip_transaction
pj_timer_entry retransmit_timer;/**< Retransmit timer. */
pj_timer_entry timeout_timer; /**< Timeout timer. */
- unsigned msec_timeout; /**< User set timeout. */
- pjsip_tsx_timeout_policy timeout_policy; /**< Timeout policy. */
-
/** Module specific data. */
void *mod_data[PJSIP_MAX_MODULE];
};
@@ -248,47 +230,6 @@ PJ_DECL(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user,
PJ_DECL(pj_status_t) pjsip_tsx_set_transport(pjsip_transaction *tsx,
const pjsip_tpselector *sel);
-
-/**
- * Set the UAC absolute transaction timeout. Normally UAC transaction will
- * stop its timeout timer (timer B for INVITE and timer F for non-INVITE
- * transactions) after a provisional response is received.
- *
- * When this timer is set, the transaction's timer B and F will use this
- * value, and if the \a flag flag is set, the transaction will continue
- * the scheduling of the timeout timer even when provisional response has
- * been received.
- *
- * Note that this function MUST be called AFTER the transaction has been
- * created AND BEFORE any request is transmitted.
- *
- * @param tsx The client/UAC transaction.
- * @param msec_time The timeout value, in miliseconds. Currently this
- * value must be non-zero (value zero is reserved for
- * future use).
- * @param flag Option flags to control whether the transaction should
- * cancel the timeout timer on arrival of provisional
- * responses (which is yes according to RFC 3261).
- * The valid values are:
- * - PJSIP_TSX_IGNORE_100, to make the UAC transaction
- * NOT to cancel the timeout timer when 100 response
- * is received.
- * - PJSIP_TSX_IGNORE_1xx, to make the UAC transaction
- * NOT to cancel the timeout timer when any 1xx
- * responses are received.
- *
- * Note that regardless of the values in the \a flag
- * argument, the provisional response would still be
- * delivered to transaction user and it will still
- * affect the transaction state. The \a flag flag only
- * changes the behavior of the timeout timer of the
- * transaction.
- */
-PJ_DECL(pj_status_t) pjsip_tsx_set_uac_timeout(pjsip_transaction *tsx,
- unsigned msec_time,
- pjsip_tsx_timeout_policy flag);
-
-
/**
* Call this function to manually feed a message to the transaction.
* For UAS transaction, application MUST call this function after
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 10c19290..9f2450b0 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -913,7 +913,8 @@ typedef struct pjsua_config
pj_str_t stun_domain;
/**
- * Specify STUN server to be used.
+ * Specify STUN server to be used, in "HOST[:PORT]" format. If port is
+ * not specified, default port 3478 will be used.
*/
pj_str_t stun_host;
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);