summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip/sip_transport_tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsip/sip_transport_tls.c')
-rw-r--r--pjsip/src/pjsip/sip_transport_tls.c191
1 files changed, 130 insertions, 61 deletions
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);
}