diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 41427dfc4a..6e6ec1b5de 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -2053,8 +2053,8 @@ const sipdns_tports[SIPDNS_TRANSPORTS] = { { "tcp", "5060", "_sip._tcp.", "SIP+D2T" }, { "sctp", "5060", "_sip._sctp.", "SIP+D2S" }, { "tls", "5061", "_sips._tcp.", "SIPS+D2T" }, - { "ws", "80", "_sips._ws.", "SIP+D2W" }, - { "wss", "443", "_sips._wss.", "SIPS+D2W" }, + { "ws", "5066", "_sips._ws.", "SIP+D2W" }, + { "wss", "5067", "_sips._wss.", "SIPS+D2W" }, }; static char const * const tports_sip[] = @@ -2064,7 +2064,7 @@ static char const * const tports_sip[] = static char const * const tports_sips[] = { - "tls", "ws", NULL + "tls", "wss", "ws", NULL }; static tport_stack_class_t nta_agent_class[1] = diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c index 5c4fd188da..6cbb4336ce 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c @@ -1346,11 +1346,13 @@ extern tport_vtable_t const tport_udp_vtable; extern tport_vtable_t const tport_tcp_vtable; extern tport_vtable_t const tport_tls_vtable; extern tport_vtable_t const tport_ws_vtable; +extern tport_vtable_t const tport_wss_vtable; extern tport_vtable_t const tport_sctp_vtable; extern tport_vtable_t const tport_udp_client_vtable; extern tport_vtable_t const tport_tcp_client_vtable; extern tport_vtable_t const tport_sctp_client_vtable; extern tport_vtable_t const tport_ws_client_vtable; +extern tport_vtable_t const tport_wss_client_vtable; extern tport_vtable_t const tport_tls_client_vtable; extern tport_vtable_t const tport_http_connect_vtable; extern tport_vtable_t const tport_threadpool_vtable; @@ -1363,6 +1365,8 @@ tport_vtable_t const *tport_vtables[TPORT_NUMBER_OF_TYPES + 1] = &tport_http_connect_vtable, &tport_ws_client_vtable, &tport_ws_vtable, + &tport_wss_client_vtable, + &tport_wss_vtable, #endif #if HAVE_TLS &tport_tls_client_vtable, diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c index 828b3f313c..28cdf69bd6 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c @@ -263,6 +263,10 @@ int tls_verify_cb(int ok, X509_STORE_CTX *store) return ok; } +void tls_init(void) { + ONCE_INIT(tls_init_once); +} + static int tls_init_context(tls_t *tls, tls_issues_t const *ti) { diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h index 702dcc9040..24c51800e2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h @@ -93,6 +93,7 @@ ssize_t tls_write(tls_t *tls, void *buf, size_t size); int tls_want_write(tls_t *tls, int events); int tls_events(tls_t const *tls, int flags); +void tls_init(void); SOFIA_END_DECLS diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c index 1f6206142a..a3349bd2e1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c @@ -36,6 +36,7 @@ #include "tport_internal.h" #include "tport_ws.h" +#include "tport_tls.h" #if HAVE_NETINET_TCP_H #include @@ -65,18 +66,27 @@ static char const __func__[] = "tport_type_ws"; #include #include +static int tport_ws_init_primary_secure(tport_primary_t *pri, + tp_name_t tpn[1], + su_addrinfo_t *ai, + tagi_t const *tags, + char const **return_culprit); + +static int tport_ws_setsndbuf(int socket, int atleast); +static void tport_ws_deinit_primary(tport_primary_t *pri); + tport_vtable_t const tport_ws_vtable = { /* vtp_name */ "ws", /* vtp_public */ tport_type_local, - /* vtp_pri_size */ sizeof (tport_primary_t), + /* vtp_pri_size */ sizeof (tport_ws_primary_t), /* vtp_init_primary */ tport_ws_init_primary, - /* vtp_deinit_primary */ NULL, + /* vtp_deinit_primary */ tport_ws_deinit_primary, /* vtp_wakeup_pri */ tport_accept, /* vtp_connect */ NULL, /* vtp_secondary_size */ sizeof (tport_ws_t), /* vtp_init_secondary */ tport_ws_init_secondary, - /* vtp_deinit_secondary */ NULL, + /* vtp_deinit_secondary */ tport_ws_deinit_secondary, /* vtp_shutdown */ NULL, /* vtp_set_events */ NULL, /* vtp_wakeup */ NULL, @@ -94,9 +104,9 @@ tport_vtable_t const tport_ws_client_vtable = { /* vtp_name */ "ws", /* vtp_public */ tport_type_client, - /* vtp_pri_size */ sizeof (tport_primary_t), + /* vtp_pri_size */ sizeof (tport_ws_primary_t), /* vtp_init_primary */ tport_ws_init_client, - /* vtp_deinit_primary */ NULL, + /* vtp_deinit_primary */ tport_ws_deinit_primary, /* vtp_wakeup_pri */ NULL, /* vtp_connect */ NULL, /* vtp_secondary_size */ sizeof (tport_ws_t), @@ -115,8 +125,64 @@ tport_vtable_t const tport_ws_client_vtable = /* vtp_secondary_timer */ tport_ws_timer, }; -static int tport_ws_setsndbuf(int socket, int atleast); +tport_vtable_t const tport_wss_vtable = +{ + /* vtp_name */ "wss", + /* vtp_public */ tport_type_local, + /* vtp_pri_size */ sizeof (tport_ws_primary_t), + /* vtp_init_primary */ tport_ws_init_primary_secure, + /* vtp_deinit_primary */ tport_ws_deinit_primary, + /* vtp_wakeup_pri */ tport_accept, + /* vtp_connect */ NULL, + /* vtp_secondary_size */ sizeof (tport_ws_t), + /* vtp_init_secondary */ tport_ws_init_secondary, + /* vtp_deinit_secondary */ tport_ws_deinit_secondary, + /* vtp_shutdown */ NULL, + /* vtp_set_events */ NULL, + /* vtp_wakeup */ NULL, + /* vtp_recv */ tport_recv_stream_ws, + /* vtp_send */ tport_send_stream_ws, + /* vtp_deliver */ NULL, + /* vtp_prepare */ NULL, + /* vtp_keepalive */ NULL, + /* vtp_stun_response */ NULL, + /* vtp_next_secondary_timer*/ tport_ws_next_timer, + /* vtp_secondary_timer */ tport_ws_timer, +}; +tport_vtable_t const tport_wss_client_vtable = +{ + /* vtp_name */ "wss", + /* vtp_public */ tport_type_client, + /* vtp_pri_size */ sizeof (tport_ws_primary_t), + /* vtp_init_primary */ tport_ws_init_client, + /* vtp_deinit_primary */ tport_ws_deinit_primary, + /* vtp_wakeup_pri */ NULL, + /* vtp_connect */ NULL, + /* vtp_secondary_size */ sizeof (tport_ws_t), + /* vtp_init_secondary */ tport_ws_init_secondary, + /* vtp_deinit_secondary */ NULL, + /* vtp_shutdown */ NULL, + /* vtp_set_events */ NULL, + /* vtp_wakeup */ NULL, + /* vtp_recv */ tport_recv_stream_ws, + /* vtp_send */ tport_send_stream_ws, + /* vtp_deliver */ NULL, + /* vtp_prepare */ NULL, + /* vtp_keepalive */ NULL, + /* vtp_stun_response */ NULL, + /* vtp_next_secondary_timer*/ tport_ws_next_timer, + /* vtp_secondary_timer */ tport_ws_timer, +}; + + +static void tport_ws_deinit_primary(tport_primary_t *pri) +{ + tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri; + if ( wspri->ssl_ctx ) { + SSL_CTX_free(wspri->ssl_ctx), wspri->ssl_ctx = NULL; + } +} /** Receive from stream. * @@ -134,11 +200,12 @@ int tport_recv_stream_ws(tport_t *self) msg_iovec_t iovec[msg_n_fragments] = {{ 0 }}; tport_ws_t *wstp = (tport_ws_t *)self; wsh_t *ws = wstp->ws; + tport_ws_primary_t *wspri = (tport_ws_primary_t *)self->tp_pri; uint8_t *data; ws_opcode_t oc; if ( !wstp->ws_initialized ) { - ws_init(ws, self->tp_socket, 65336, wstp->ws_secure); + ws_init(ws, self->tp_socket, 65336, wstp->ws_secure ? wspri->ssl_ctx : NULL); wstp->ws_initialized = 1; self->tp_pre_framed = 1; return 1; @@ -155,7 +222,7 @@ int tport_recv_stream_ws(tport_t *self) err = su_errno(); SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, (void *)self, su_strerror(err), err)); - return -1; + return 0;; } veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0); @@ -271,6 +338,36 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg, return size; } +static int tport_ws_init_primary_secure(tport_primary_t *pri, + tp_name_t tpn[1], + su_addrinfo_t *ai, + tagi_t const *tags, + char const **return_culprit) +{ + tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri; + const char *cert = "/ssl.pem"; + const char *key = "/ssl.pem"; + init_ssl(); + + // OpenSSL_add_all_algorithms(); /* load & register cryptos */ + // SSL_load_error_strings(); /* load all error messages */ + wspri->ssl_method = SSLv23_server_method(); /* create server instance */ + wspri->ssl_ctx = SSL_CTX_new(wspri->ssl_method); /* create context */ + wspri->ws_secure = 1; + + if ( !wspri->ssl_ctx ) return -1; + + /* set the local certificate from CertFile */ + SSL_CTX_use_certificate_file(wspri->ssl_ctx, cert, SSL_FILETYPE_PEM); + /* set the private key from KeyFile */ + SSL_CTX_use_PrivateKey_file(wspri->ssl_ctx, key, SSL_FILETYPE_PEM); + /* verify private key */ + if ( !SSL_CTX_check_private_key(wspri->ssl_ctx) ) { + return -1; + } + + return tport_ws_init_primary(pri, tpn, ai, tags, return_culprit); +} int tport_ws_init_primary(tport_primary_t *pri, tp_name_t tpn[1], @@ -305,6 +402,8 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted, char const **return_reason) { int one = 1; + tport_ws_primary_t *wspri = (tport_ws_primary_t *)self->tp_pri; + tport_ws_t *wstp = (tport_ws_t *)self; self->tp_has_connection = 1; @@ -314,9 +413,21 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted, if (!accepted) tport_ws_setsndbuf(socket, 64 * 1024); + if ( wspri->ws_secure ) wstp->ws_secure = 1; + return 0; } +static void tport_ws_deinit_secondary(tport_t *self) +{ + tport_ws_t *wstp = (tport_ws_t *)self; + + if (wstp->ws_initialized ) { + ws_close(wstp->ws, WS_NONE); + wstp->ws_initialized = 0; + } +} + static int tport_ws_setsndbuf(int socket, int atleast) { #if SU_HAVE_WINSOCK2 diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_ws.h b/libs/sofia-sip/libsofia-sip-ua/tport/tport_ws.h index 274bde97ae..c7d5d39b8f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_ws.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_ws.h @@ -62,6 +62,14 @@ typedef struct tport_ws_s { unsigned:0; } tport_ws_t; +typedef struct tport_ws_primary_s { + tport_primary_t wspri_pri[1]; + SSL_CTX *ssl_ctx; + const SSL_METHOD *ssl_method; + unsigned ws_secure:1; + unsigned :0; +} tport_ws_primary_t; + int tport_recv_stream_ws(tport_t *self); ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg, msg_iovec_t iov[], size_t iovused); @@ -82,6 +90,7 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted, int tport_ws_next_timer(tport_t *self, su_time_t *, char const **); void tport_ws_timer(tport_t *self, su_time_t); +static void tport_ws_deinit_secondary(tport_t *self); SOFIA_END_DECLS diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c index 4829de9a47..b612cf596f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c @@ -1,10 +1,13 @@ #include "ws.h" - +#include #define SHA1_HASH_SIZE 20 struct globals_s globals; #ifndef PTHREAD -void ssl_init() {} +void init_ssl(void) +{ + SSL_library_init(); +} #else static unsigned long pthreads_thread_id(void); static void pthreads_locking_callback(int mode, int type, const char *file, int line); @@ -67,18 +70,18 @@ void init_ssl(void) { SSL_library_init(); // OpenSSL_add_all_algorithms(); /* load & register cryptos */ // SSL_load_error_strings(); /* load all error messages */ - globals.ssl_method = SSLv23_server_method(); /* create server instance */ - globals.ssl_ctx = SSL_CTX_new(globals.ssl_method); /* create context */ - assert(globals.ssl_ctx); + //globals.ssl_method = SSLv23_server_method(); /* create server instance */ + //globals.ssl_ctx = SSL_CTX_new(globals.ssl_method); /* create context */ + //assert(globals.ssl_ctx); /* set the local certificate from CertFile */ - SSL_CTX_use_certificate_file(globals.ssl_ctx, globals.cert, SSL_FILETYPE_PEM); + //SSL_CTX_use_certificate_file(globals.ssl_ctx, globals.cert, SSL_FILETYPE_PEM); /* set the private key from KeyFile */ - SSL_CTX_use_PrivateKey_file(globals.ssl_ctx, globals.key, SSL_FILETYPE_PEM); + //SSL_CTX_use_PrivateKey_file(globals.ssl_ctx, globals.key, SSL_FILETYPE_PEM); /* verify private key */ - if ( !SSL_CTX_check_private_key(globals.ssl_ctx) ) { - abort(); - } + //if ( !SSL_CTX_check_private_key(globals.ssl_ctx) ) { + // abort(); + //} thread_setup(); @@ -212,12 +215,6 @@ int ws_handshake(wsh_t *wsh) if (wsh->sock == ws_sock_invalid) { return -3; } - - if (wsh->secure) { - wsh->ssl = SSL_new(globals.ssl_ctx); - SSL_set_fd(wsh->ssl, wsh->sock); - SSL_accept(wsh->ssl); - } while((bytes = ws_raw_read(wsh, wsh->buffer + wsh->datalen, wsh->buflen - wsh->datalen)) > 0) { wsh->datalen += bytes; @@ -288,7 +285,11 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes) ssize_t r; if (wsh->ssl) { - return SSL_read(wsh->ssl, data, bytes); + do { + r = SSL_read(wsh->ssl, data, bytes); + } while (r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_READ); + + return r; } do { @@ -307,7 +308,11 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes) size_t r; if (wsh->ssl) { - return SSL_write(wsh->ssl, data, bytes); + do { + r = SSL_write(wsh->ssl, data, bytes); + } while (r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE); + + return r; } do { @@ -321,7 +326,7 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes) return r; } -int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, int secure) +int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx) { memset(wsh, 0, sizeof(*wsh)); wsh->sock = sock; @@ -331,13 +336,24 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, int secure) } wsh->buflen = buflen; - wsh->secure = secure; + wsh->secure = ssl_ctx ? 1 : 0; if (!wsh->buffer) { wsh->buffer = malloc(wsh->buflen); assert(wsh->buffer); } + if (wsh->secure) { + int code; + wsh->ssl = SSL_new(ssl_ctx); + SSL_set_fd(wsh->ssl, wsh->sock); + + do { + code = SSL_accept(wsh->ssl); + } while (code == -1 && SSL_get_error(wsh->ssl, code) == SSL_ERROR_WANT_READ); + + } + while (!wsh->down && !wsh->handshake) { ws_handshake(wsh); } @@ -368,6 +384,11 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason) if (wsh->ssl) { + int code; + do { + code = SSL_shutdown(wsh->ssl); + } while (code == -1 && SSL_get_error(wsh->ssl, code) == SSL_ERROR_WANT_READ); + SSL_free(wsh->ssl); wsh->ssl = NULL; } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h index ce7e515efe..58c74eee83 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h @@ -68,7 +68,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes); ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes); ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data); ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes); -int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, int secure); +int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx); ssize_t ws_close(wsh_t *wsh, int16_t reason); void init_ssl(void); void deinit_ssl(void); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index f711d0eafa..67b66288d4 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1109,10 +1109,21 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand const char *agent = "unknown"; const char *pres_on_reg = NULL; int send_pres = 0; - int is_tls = 0, is_tcp = 0, is_ws = 0; + int is_tls = 0, is_tcp = 0, is_ws = 0, is_wss = 0; char expbuf[35] = ""; time_t reg_time = switch_epoch_time_now(NULL); - + const char *vproto = NULL; + const char *proto = "sip"; + + if (sip && sip->sip_via && (vproto = sip->sip_via->v_protocol)) { + if (!strcasecmp(vproto, "sip/2.0/ws")) { + is_ws = 1; + is_nat++; + } else if (!strcasecmp(vproto, "sip/2.0/wss")) { + is_wss = 1; + is_nat++; + } + } if (v_event && *v_event) pres_on_reg = switch_event_get_header(*v_event, "send-presence-on-register"); @@ -1177,24 +1188,28 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand const char *contact_host = contact->m_url->url_host; char *path_encoded = NULL; int path_encoded_len = 0; - const char *proto = "sip"; + if (switch_stristr("transport=tls", sip->sip_contact->m_url->url_params)) { is_tls += 1; is_nat++; } - if (switch_stristr("transport=ws", sip->sip_contact->m_url->url_params)) { + if (!is_wss && !is_ws && switch_stristr("transport=ws", sip->sip_contact->m_url->url_params)) { is_nat++; is_ws += 1; } - if (sip->sip_contact->m_url->url_type == url_sips && !switch_stristr("transport=ws", sip->sip_contact->m_url->url_params)) { + if (sip->sip_contact->m_url->url_type == url_sips) { proto = "sips"; is_tls += 2; is_nat++; } + if (is_wss) { + proto = "sips"; + } + if (switch_stristr("transport=tcp", sip->sip_contact->m_url->url_params)) { is_tcp = 1; is_nat++; @@ -1209,6 +1224,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand reg_desc = "Registered(TCP-NAT)"; } else if (is_ws) { reg_desc = "Registered(WS-NAT)"; + } else if (is_wss) { + reg_desc = "Registered(WSS-NAT)"; } else { reg_desc = "Registered(UDP-NAT)"; } @@ -1243,10 +1260,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } else if (is_nat) { char my_contact_str[1024]; if (sip->sip_contact->m_url->url_params) { - switch_snprintf(my_contact_str, sizeof(my_contact_str), "sip:%s@%s:%d;%s", + switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d;%s", proto, contact->m_url->url_user, url_ip, network_port, sip->sip_contact->m_url->url_params); } else { - switch_snprintf(my_contact_str, sizeof(my_contact_str), "sip:%s@%s:%d", contact->m_url->url_user, url_ip, network_port); + switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d", proto, contact->m_url->url_user, url_ip, network_port); } path_encoded_len = (int)(strlen(my_contact_str) * 3) + 1; @@ -1388,7 +1405,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand size_t path_encoded_len; char my_contact_str[1024]; - switch_snprintf(my_contact_str, sizeof(my_contact_str), "sip:%s@%s:%d", contact->m_url->url_user, url_ip, network_port); + switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d", proto, contact->m_url->url_user, url_ip, network_port); path_encoded_len = (strlen(my_contact_str) * 3) + 1; if (!switch_stristr("fs_path=", contact_str)) { @@ -1414,10 +1431,11 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-tls-connectile-dysfunction")) { if (contact->m_url->url_params) { - switch_snprintf(contact_str, sizeof(contact_str), "%s ", - display, contact->m_url->url_user, url_ip, network_port, contact->m_url->url_params, received_data); + switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s:%d;%s%s;fs_nat=yes>", + display, proto, contact->m_url->url_user, url_ip, network_port, contact->m_url->url_params, received_data); } else { - switch_snprintf(contact_str, sizeof(contact_str), "%s ", display, contact->m_url->url_user, url_ip, + switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s:%d%s;fs_nat=yes>", display, proto, + contact->m_url->url_user, url_ip, network_port, received_data); } if (switch_stristr(v_contact_str, "transport=tls")) { @@ -1623,7 +1641,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET); contact = sofia_glue_get_url_from_contact(contact_str, 1); - url = switch_mprintf("sofia/%q/sip:%q", profile->name, sofia_glue_strip_proto(contact)); + url = switch_mprintf("sofia/%q/%s:%q", profile->name, proto, sofia_glue_strip_proto(contact)); switch_core_add_registration(to_user, reg_host, call_id, url, (long) reg_time + (long) exptime + 60, network_ip, network_port_c, is_tls ? "tls" : is_tcp ? "tcp" : "udp", reg_meta); @@ -1773,7 +1791,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) && debounce_ok) { if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", mwi_user, mwi_host); + switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "%s:%s@%s", proto, mwi_user, mwi_host); switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name); switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id); } diff --git a/src/switch_core_media.c b/src/switch_core_media.c index ea6eff193e..5f73cb4958 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -1977,6 +1977,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s int total_codecs; switch_rtp_engine_t *a_engine, *v_engine; switch_media_handle_t *smh; + uint32_t near_rate = 0; + const switch_codec_implementation_t *mimp = NULL, *near_match = NULL; + int codec_ms = 0; + switch_assert(session); @@ -2353,11 +2357,8 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s for (map = m->m_rtpmaps; map; map = map->rm_next) { int32_t i; - uint32_t near_rate = 0; - const switch_codec_implementation_t *mimp = NULL, *near_match = NULL; const char *rm_encoding; uint32_t map_bit_rate = 0; - int codec_ms = 0; switch_codec_fmtp_t codec_fmtp = { 0 }; if (x++ < skip) { @@ -2411,9 +2412,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } if (zstr(map->rm_fmtp)) { - if (!strcasecmp(map->rm_encoding, "ilbc") || !strcasecmp(map->rm_encoding, "isac")) { + if (!strcasecmp(map->rm_encoding, "ilbc")) { codec_ms = 30; map_bit_rate = 13330; + } else if (!strcasecmp(map->rm_encoding, "isac")) { + codec_ms = 30; + map_bit_rate = 32000; } } else { if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) { @@ -2450,7 +2454,8 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s match = 0; } - if (match && map->rm_rate && codec_rate && map->rm_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") || !strcasecmp(map->rm_encoding, "pcmu"))) { + if (match && map->rm_rate && codec_rate && map->rm_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") || + !strcasecmp(map->rm_encoding, "pcmu"))) { /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n"); match = 0; @@ -2474,85 +2479,92 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } } - if (!match && near_match) { - const switch_codec_implementation_t *search[1]; - char *prefs[1]; - char tmp[80]; - int num; - - switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second, - codec_ms); - - prefs[0] = tmp; - num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1); - - if (num) { - mimp = search[0]; - } else { - mimp = near_match; - } - - if (!maxptime || mimp->microseconds_per_packet / 1000 <= maxptime) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh\n", - mimp->iananame, mimp->microseconds_per_packet / 1000, mimp->samples_per_second); - match = 1; - } else { - mimp = NULL; - match = 0; - } - - } - + if (!match && greedy) { skip++; continue; } - if (mimp) { - char tmp[50]; - const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_audio_codec_payload"); - - a_engine->codec_params.rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding); - a_engine->codec_params.iananame = switch_core_session_strdup(session, (char *) mimp->iananame); - a_engine->codec_params.pt = (switch_payload_t) map->rm_pt; - a_engine->codec_params.rm_rate = mimp->samples_per_second; - a_engine->codec_params.codec_ms = mimp->microseconds_per_packet / 1000; - a_engine->codec_params.bitrate = mimp->bits_per_second; - - - a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address); - a_engine->codec_params.remote_sdp_port = (switch_port_t) m->m_port; - a_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); - - a_engine->codec_params.agreed_pt = (switch_payload_t) map->rm_pt; - smh->num_negotiated_codecs = 0; - smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp; - switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port); - switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip); - switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); - a_engine->codec_params.recv_pt = (switch_payload_t)map->rm_pt; - - if (!switch_true(mirror) && - switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && - (!switch_channel_test_flag(session->channel, CF_REINVITE) || switch_media_handle_test_media_flag(smh, SCMF_RENEG_ON_REINVITE))) { - switch_core_media_get_offered_pt(session, mimp, &a_engine->codec_params.recv_pt); - } - - switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.recv_pt); - switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp); - - } - - if (match) { - if (switch_core_media_set_codec(session, 1, smh->mparams->codec_flags) == SWITCH_STATUS_SUCCESS) { - got_audio = 1; - check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, m); - } else { - match = 0; - } + if (match && mimp) { + break; } } + if (!match && near_match) { + const switch_codec_implementation_t *search[1]; + char *prefs[1]; + char tmp[80]; + int num; + + switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second, + codec_ms); + + prefs[0] = tmp; + num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1); + + if (num) { + mimp = search[0]; + } else { + mimp = near_match; + } + + if (!maxptime || mimp->microseconds_per_packet / 1000 <= maxptime) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh\n", + mimp->iananame, mimp->microseconds_per_packet / 1000, mimp->samples_per_second); + match = 1; + } else { + mimp = NULL; + match = 0; + } + + } + + if (mimp) { + char tmp[50]; + const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_audio_codec_payload"); + + a_engine->codec_params.rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding); + a_engine->codec_params.iananame = switch_core_session_strdup(session, (char *) mimp->iananame); + a_engine->codec_params.pt = (switch_payload_t) map->rm_pt; + a_engine->codec_params.rm_rate = mimp->samples_per_second; + a_engine->codec_params.codec_ms = mimp->microseconds_per_packet / 1000; + a_engine->codec_params.bitrate = mimp->bits_per_second; + + + a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address); + a_engine->codec_params.remote_sdp_port = (switch_port_t) m->m_port; + a_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); + + a_engine->codec_params.agreed_pt = (switch_payload_t) map->rm_pt; + smh->num_negotiated_codecs = 0; + smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp; + switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port); + switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip); + switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); + a_engine->codec_params.recv_pt = (switch_payload_t)map->rm_pt; + + if (!switch_true(mirror) && + switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && + (!switch_channel_test_flag(session->channel, CF_REINVITE) || switch_media_handle_test_media_flag(smh, SCMF_RENEG_ON_REINVITE))) { + switch_core_media_get_offered_pt(session, mimp, &a_engine->codec_params.recv_pt); + } + + switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.recv_pt); + switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp); + + } + + if (match) { + if (switch_core_media_set_codec(session, 1, smh->mparams->codec_flags) == SWITCH_STATUS_SUCCESS) { + got_audio = 1; + check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, m); + } else { + match = 0; + } + } + + + if (!best_te && (switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) || switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No 2833 in SDP. Liberal DTMF mode adding %d as telephone-event.\n", smh->mparams->te); @@ -6335,9 +6347,12 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size } if (zstr(map->rm_fmtp)) { - if (!strcasecmp(map->rm_encoding, "ilbc") || !strcasecmp(map->rm_encoding, "isac")) { + if (!strcasecmp(map->rm_encoding, "ilbc")) { ptime = codec_ms = 30; map_bit_rate = 13330; + } else if (!strcasecmp(map->rm_encoding, "isac")) { + ptime = codec_ms = 30; + map_bit_rate = 32000; } } else { if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {