summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2014-08-18 08:54:43 +0000
committerBenny Prijono <bennylp@teluu.com>2014-08-18 08:54:43 +0000
commitc38c8101be49bb4cb9cf95815f0c2ce955876c3b (patch)
tree7d8c20a74df8f5c1939498c9315271b7413472a7
parent6b29b9ed22824ecb99eafa500b22db20cc9f3d75 (diff)
Closed #1677: Contact uses source port in initial registration.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4888 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsip/sip_util.h15
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h13
-rw-r--r--pjsip/src/pjsip/sip_util.c18
-rw-r--r--pjsip/src/pjsua-lib/pjsua_acc.c117
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c1
5 files changed, 155 insertions, 9 deletions
diff --git a/pjsip/include/pjsip/sip_util.h b/pjsip/include/pjsip/sip_util.h
index 226dccd6..c8b43f35 100644
--- a/pjsip/include/pjsip/sip_util.h
+++ b/pjsip/include/pjsip/sip_util.h
@@ -371,6 +371,21 @@ PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
const pjsip_tx_data *tdata,
pjsip_tx_data **p_tdata);
+/**
+ * Get destination address and port and transport type information for the
+ * specified URI.
+ *
+ * @param target_uri The destination URI.
+ * @param request_uri Optional request URI to be considered. May be NULL.
+ * @param pool Pool to allocate memory from.
+ * @param dest_info To be filled with destination info.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_get_dest_info(const pjsip_uri *target_uri,
+ const pjsip_uri *request_uri,
+ pj_pool_t *pool,
+ pjsip_host_info *dest_info);
/**
* Find which destination to be used to send the request message, based
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index a86644c5..d83b05f8 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -3055,6 +3055,19 @@ typedef struct pjsua_acc_config
int contact_rewrite_method;
/**
+ * Specify if source TCP port should be used as the initial Contact
+ * address if TCP/TLS transport is used. Note that this feature will
+ * be automatically turned off when nameserver is configured because
+ * it may yield different destination address due to DNS SRV resolution.
+ * Also some platforms are unable to report the local address of the
+ * TCP socket when it is still connecting. In these cases, this
+ * feature will also be turned off.
+ *
+ * Default: PJ_TRUE (yes).
+ */
+ pj_bool_t contact_rewrite_use_src_port;
+
+ /**
* This option is used to overwrite the "sent-by" field of the Via header
* for outgoing messages with the same interface address as the one in
* the REGISTER request, as long as the request uses the same transport
diff --git a/pjsip/src/pjsip/sip_util.c b/pjsip/src/pjsip/sip_util.c
index d7cde6fe..21ea2375 100644
--- a/pjsip/src/pjsip/sip_util.c
+++ b/pjsip/src/pjsip/sip_util.c
@@ -801,10 +801,10 @@ on_missing_hdr:
/* Fill-up destination information from a target URI */
-static pj_status_t get_dest_info(const pjsip_uri *target_uri,
- const pjsip_uri *request_uri,
- pj_pool_t *pool,
- pjsip_host_info *dest_info)
+PJ_DEF(pj_status_t) pjsip_get_dest_info(const pjsip_uri *target_uri,
+ const pjsip_uri *request_uri,
+ pj_pool_t *pool,
+ pjsip_host_info *dest_info)
{
/* The target URI must be a SIP/SIPS URL so we can resolve it's address.
* Otherwise we're in trouble (i.e. there's no host part in tel: URL).
@@ -907,8 +907,8 @@ PJ_DEF(pj_status_t) pjsip_get_request_dest(const pjsip_tx_data *tdata,
target_uri = tdata->msg->line.req.uri;
}
- return get_dest_info(target_uri, tdata->msg->line.req.uri,
- (pj_pool_t*)tdata->pool, dest_info);
+ return pjsip_get_dest_info(target_uri, tdata->msg->line.req.uri,
+ (pj_pool_t*)tdata->pool, dest_info);
}
@@ -1011,8 +1011,8 @@ PJ_DEF(pj_status_t) pjsip_process_route_set(pjsip_tx_data *tdata,
}
/* Fill up the destination host/port from the URI. */
- status = get_dest_info(target_uri, new_request_uri, tdata->pool,
- dest_info);
+ status = pjsip_get_dest_info(target_uri, new_request_uri, tdata->pool,
+ dest_info);
if (status != PJ_SUCCESS)
return status;
@@ -1509,7 +1509,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_raw_to_uri(pjsip_endpoint *endpt,
}
/* Build destination info. */
- status = get_dest_info(uri, NULL, tdata->pool, &dest_info);
+ status = pjsip_get_dest_info(uri, NULL, tdata->pool, &dest_info);
if (status != PJ_SUCCESS) {
pjsip_tx_data_dec_ref(tdata);
return status;
diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c
index 1abaedd1..dbdb698c 100644
--- a/pjsip/src/pjsua-lib/pjsua_acc.c
+++ b/pjsip/src/pjsua-lib/pjsua_acc.c
@@ -2933,6 +2933,28 @@ PJ_DEF(pj_status_t) pjsua_acc_create_request(pjsua_acc_id acc_id,
return PJ_SUCCESS;
}
+/*
+ * Internal:
+ * determine if an address is a valid IP address, and if it is,
+ * return the IP version (4 or 6).
+ */
+static int get_ip_addr_ver(const pj_str_t *host)
+{
+ pj_in_addr dummy;
+ pj_in6_addr dummy6;
+
+ /* First check with inet_aton() */
+ if (pj_inet_aton(host, &dummy) > 0)
+ return 4;
+
+ /* Then check if this is an IPv6 address */
+ if (pj_inet_pton(pj_AF_INET6(), host, &dummy6) == PJ_SUCCESS)
+ return 6;
+
+ /* Not an IP address */
+ return 0;
+}
+
/* Get local transport address suitable to be used for Via or Contact address
* to send request to the specified destination URI.
*/
@@ -3014,9 +3036,104 @@ pj_status_t pjsua_acc_get_uac_addr(pjsua_acc_id acc_id,
if (status != PJ_SUCCESS)
return status;
+ /* Set this as default return value. This may be changed below
+ * for TCP/TLS
+ */
addr->host = tfla2_prm.ret_addr;
addr->port = tfla2_prm.ret_port;
+ /* For TCP/TLS, acc may request to specify source port */
+ if (acc->cfg.contact_rewrite_use_src_port) {
+ pjsip_host_info dinfo;
+ pjsip_transport *tp = NULL;
+ pj_addrinfo ai;
+ pj_bool_t log_written = PJ_FALSE;
+
+ status = pjsip_get_dest_info((pjsip_uri*)sip_uri, NULL,
+ pool, &dinfo);
+
+ if (status==PJ_SUCCESS && (dinfo.flag & PJSIP_TRANSPORT_RELIABLE)==0) {
+ /* Not TCP or TLS. No need to do this */
+ status = PJ_EINVALIDOP;
+ log_written = PJ_TRUE;
+ }
+
+ if (status==PJ_SUCCESS &&
+ get_ip_addr_ver(&dinfo.addr.host)==0 &&
+ pjsua_var.ua_cfg.nameserver_count)
+ {
+ /* If nameserver is configured, PJSIP will resolve destinations
+ * by their DNS SRV record first. On the other hand, we will
+ * resolve destination with DNS A record via pj_getaddrinfo().
+ * They may yield different IP addresses, hence causing different
+ * TCP/TLS connection to be created and hence different source
+ * address.
+ */
+ PJ_LOG(4,(THIS_FILE, "Warning: cannot use source TCP/TLS socket"
+ " address for Contact when nameserver is configured."));
+ status = PJ_ENOTSUP;
+ log_written = PJ_TRUE;
+ }
+
+ if (status == PJ_SUCCESS) {
+ unsigned cnt=1;
+ int af;
+
+ af = (dinfo.type & PJSIP_TRANSPORT_IPV6)? PJ_AF_INET6 : PJ_AF_INET;
+ status = pj_getaddrinfo(af, &dinfo.addr.host, &cnt, &ai);
+ }
+
+ if (status == PJ_SUCCESS) {
+ int addr_len = pj_sockaddr_get_len(&ai.ai_addr);
+ pj_uint16_t port = dinfo.addr.port;
+
+ if (port==0) {
+ port = (dinfo.flag & PJSIP_TRANSPORT_SECURE) ? 5061 : 5060;
+ }
+ pj_sockaddr_set_port(&ai.ai_addr, port);
+ status = pjsip_endpt_acquire_transport(pjsua_var.endpt,
+ dinfo.type,
+ &ai.ai_addr,
+ addr_len,
+ &tp_sel, &tp);
+ }
+
+ if (status == PJ_SUCCESS && (tp->local_name.port == 0 ||
+ tp->local_name.host.slen==0 ||
+ *tp->local_name.host.ptr=='0'))
+ {
+ /* Trap zero port or "0.0.0.0" address. */
+ /* The TCP/TLS transport is still connecting and unfortunately
+ * this OS doesn't report the bound local address in this state.
+ */
+ PJ_LOG(4,(THIS_FILE, "Unable to get transport local port "
+ "for Contact address (OS doesn't support)"));
+ status = PJ_ENOTSUP;
+ log_written = PJ_TRUE;
+ }
+
+ if (status == PJ_SUCCESS) {
+ /* Got the local transport address */
+ pj_strdup(pool, &addr->host, &tp->local_name.host);
+ addr->port = tp->local_name.port;
+ }
+
+ if (tp) {
+ /* Here the transport's ref counter WILL reach zero. But the
+ * transport will NOT get destroyed because it should have an
+ * idle timer.
+ */
+ pjsip_transport_dec_ref(tp);
+ tp = NULL;
+ }
+
+ if (status != PJ_SUCCESS && !log_written) {
+ PJ_PERROR(4,(THIS_FILE, status, "Unable to use source local "
+ "TCP socket address for Contact"));
+ }
+ status = PJ_SUCCESS;
+ }
+
if (p_tp_type)
*p_tp_type = tp_type;
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index d4fefe3c..056ff888 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -289,6 +289,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg)
cfg->srtp_optional_dup_offer = pjsua_var.ua_cfg.srtp_optional_dup_offer;
cfg->reg_retry_interval = PJSUA_REG_RETRY_INTERVAL;
cfg->contact_rewrite_method = PJSUA_CONTACT_REWRITE_METHOD;
+ cfg->contact_rewrite_use_src_port = PJ_TRUE;
cfg->use_rfc5626 = PJ_TRUE;
cfg->reg_use_proxy = PJSUA_REG_USE_OUTBOUND_PROXY |
PJSUA_REG_USE_ACC_PROXY;