From 2a85888262da036cecf2d767eb07e53205e1860e Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Tue, 7 Mar 2017 13:37:52 +0000 Subject: res_pjsip_transport_websocket: Add support for IPv6. This change adds a PJSIP patch (which has been contributed upstream) to allow the registration of IPv6 transport types. Using this the res_pjsip_transport_websocket module now registers an IPv6 Websocket transport and uses it for the corresponding traffic. ASTERISK-26685 Change-Id: Id1f9126f995b31dc38db8fdb58afd289b4ad1647 --- res/res_pjsip.c | 22 ++++---- res/res_pjsip_outbound_registration.c | 18 +++---- res/res_pjsip_transport_websocket.c | 30 ++++++----- ...14-Add-pjsip-transport-register-type-ipv6.patch | 62 ++++++++++++++++++++++ 4 files changed, 100 insertions(+), 32 deletions(-) create mode 100644 third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 54a0a5f39..347658f9c 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -2755,7 +2755,7 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u pj_str_t tmp, local_addr; pjsip_uri *uri; pjsip_sip_uri *sip_uri; - pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED; + pjsip_transport_type_e type; int local_port; char default_user[PJSIP_MAX_URL_SIZE]; @@ -2775,21 +2775,21 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u sip_uri = pjsip_uri_get_uri(uri); /* Determine the transport type to use */ + type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) { - type = PJSIP_TRANSPORT_TLS; + if (type == PJSIP_TRANSPORT_UNSPECIFIED + || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) { + type = PJSIP_TRANSPORT_TLS; + } } else if (!sip_uri->transport_param.slen) { type = PJSIP_TRANSPORT_UDP; - } else { - type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); - } - - if (type == PJSIP_TRANSPORT_UNSPECIFIED) { + } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) { return -1; } /* If the host is IPv6 turn the transport into an IPv6 version */ - if (pj_strchr(&sip_uri->host, ':') && type < PJSIP_TRANSPORT_START_OTHER) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + if (pj_strchr(&sip_uri->host, ':')) { + type |= PJSIP_TRANSPORT_IPV6; } if (!ast_strlen_zero(domain)) { @@ -2813,8 +2813,8 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u } /* If IPv6 was specified in the transport, set the proper type */ - if (pj_strchr(&local_addr, ':') && type < PJSIP_TRANSPORT_START_OTHER) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + if (pj_strchr(&local_addr, ':')) { + type |= PJSIP_TRANSPORT_IPV6; } from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c index 7a0b60ac8..ee1894ffb 100644 --- a/res/res_pjsip_outbound_registration.c +++ b/res/res_pjsip_outbound_registration.c @@ -1087,7 +1087,7 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c pj_str_t tmp, local_addr; pjsip_uri *uri; pjsip_sip_uri *sip_uri; - pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED; + pjsip_transport_type_e type; int local_port; pj_strdup_with_null(pool, &tmp, target); @@ -1099,20 +1099,20 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c sip_uri = pjsip_uri_get_uri(uri); + type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) { - type = PJSIP_TRANSPORT_TLS; + if (type == PJSIP_TRANSPORT_UNSPECIFIED + || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) { + type = PJSIP_TRANSPORT_TLS; + } } else if (!sip_uri->transport_param.slen) { type = PJSIP_TRANSPORT_UDP; - } else { - type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); - } - - if (type == PJSIP_TRANSPORT_UNSPECIFIED) { + } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) { return -1; } if (pj_strchr(&sip_uri->host, ':')) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + type |= PJSIP_TRANSPORT_IPV6; } if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), @@ -1121,7 +1121,7 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c } if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + type |= PJSIP_TRANSPORT_IPV6; } contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c index ff8e346f4..1b9d616de 100644 --- a/res/res_pjsip_transport_websocket.c +++ b/res/res_pjsip_transport_websocket.c @@ -39,6 +39,7 @@ #include "asterisk/taskprocessor.h" static int transport_type_wss; +static int transport_type_wss_ipv6; /*! * \brief Wrapper for pjsip_transport, for storing the WebSocket session @@ -198,15 +199,20 @@ static int transport_create(void *data) newtransport->transport.type_name, ws_addr_str); pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr); - newtransport->transport.key.rem_addr.addr.sa_family = pj_AF_INET(); - newtransport->transport.key.type = transport_type_wss; + if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) { + newtransport->transport.key.type = transport_type_wss_ipv6; + newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN); + pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0); + } else { + newtransport->transport.key.type = transport_type_wss; + newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN); + pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0); + } newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr); pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr); - newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, newtransport->transport.addr_len+4); - pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, newtransport->transport.addr_len+4, 0); newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr); newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr); @@ -271,8 +277,6 @@ static int transport_read(void *data) rdata->pkt_info.zero = 0; pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ast_sockaddr_stringify(ast_websocket_remote_address(session))), &rdata->pkt_info.src_addr); - rdata->pkt_info.src_addr.addr.sa_family = pj_AF_INET(); - rdata->pkt_info.src_addr_len = sizeof(rdata->pkt_info.src_addr); pj_ansi_strcpy(rdata->pkt_info.src_name, ast_sockaddr_stringify_host(ast_websocket_remote_address(session))); @@ -395,7 +399,7 @@ static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata) long type = rdata->tp_info.transport->key.type; - if (type != (long) transport_type_wss) { + if (type != (long) transport_type_wss && type != (long) transport_type_wss_ipv6) { return PJ_FALSE; } @@ -451,15 +455,17 @@ static int load_module(void) CHECK_PJSIP_MODULE_LOADED(); /* - * We only need one transport type defined. Firefox and Chrome - * do not support anything other than secure websockets anymore. + * We only need one transport type name (ws) defined. Firefox + * and Chrome do not support anything other than secure websockets + * anymore. * * Also we really cannot have two transports with the same name - * because it would be ambiguous. Outgoing requests may try to - * find the transport by name and pjproject only finds the first - * one registered. + * and address family because it would be ambiguous. Outgoing + * requests may try to find the transport by name and pjproject + * only finds the first one registered. */ pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE, "ws", 5060, &transport_type_wss); + pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_IPV6, "ws", 5060, &transport_type_wss_ipv6); if (ast_sip_register_service(&websocket_module) != PJ_SUCCESS) { return AST_MODULE_LOAD_DECLINE; diff --git a/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch b/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch new file mode 100644 index 000000000..796473a3c --- /dev/null +++ b/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch @@ -0,0 +1,62 @@ +From daeb0956524606b597704a90b54d81340e10b3e4 Mon Sep 17 00:00:00 2001 +From: Joshua Colp +Date: Tue, 7 Mar 2017 12:32:49 +0000 +Subject: [PATCH] Add support for registering IPv6 transport type. + +This change allows an IPv6 transport type to be registered +and used. The IPv4 transport is found (if available) and the +IPv4 flag added to its type to match how the finding of +IPv6 transport types works. +--- + pjsip/src/pjsip/sip_transport.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c +index 7df6138..ce72814 100644 +--- a/pjsip/src/pjsip/sip_transport.c ++++ b/pjsip/src/pjsip/sip_transport.c +@@ -236,6 +236,7 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag, + int *p_tp_type) + { + unsigned i; ++ pjsip_transport_type_e parent = 0; + + PJ_ASSERT_RETURN(tp_flag && tp_name && def_port, PJ_EINVAL); + PJ_ASSERT_RETURN(pj_ansi_strlen(tp_name) < +@@ -243,6 +244,11 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag, + PJ_ENAMETOOLONG); + + for (i=1; i