Index: src/switch_apr.c =================================================================== --- src/switch_apr.c (revision 8886) +++ src/switch_apr.c (working copy) @@ -630,7 +630,7 @@ if (!in) { return ""; } - return get_addr(buf, len, &in->sa.sin.sin_addr); + return get_addr(buf, len, (struct sockaddr*)&in->sa, in->salen); } SWITCH_DECLARE(uint16_t) switch_sockaddr_get_port(switch_sockaddr_t *sa) Index: src/switch_rtp.c =================================================================== --- src/switch_rtp.c (revision 8886) +++ src/switch_rtp.c (working copy) @@ -121,7 +121,13 @@ }; struct switch_rtp { - switch_socket_t *sock; + /* + * Two sockets are needed because we might be transcoding protocol families + * (e.g. receive over IPv4 and send over IPv6). In case the protocol + * families are equal, sock_input == sock_output and only one socket is + * used. + */ + switch_socket_t *sock_input, *sock_output; switch_sockaddr_t *local_addr; rtp_msg_t send_msg; @@ -220,7 +226,7 @@ packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, buf); switch_stun_packet_attribute_add_username(packet, rtp_session->ice_user, 32); bytes = switch_stun_packet_length(packet); - switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) packet, &bytes); + switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) packet, &bytes); rtp_session->stuncount = 25; end: @@ -296,7 +302,7 @@ remote_ip = switch_get_addr(ipbuf, sizeof(ipbuf), rtp_session->from_addr); switch_stun_packet_attribute_add_binded_address(rpacket, (char *) remote_ip, switch_sockaddr_get_port(rtp_session->from_addr)); bytes = switch_stun_packet_length(rpacket); - switch_socket_sendto(rtp_session->sock, rtp_session->from_addr, 0, (void *) rpacket, &bytes); + switch_socket_sendto(rtp_session->sock_output, rtp_session->from_addr, 0, (void *) rpacket, &bytes); } end: @@ -440,11 +446,11 @@ goto done; } - if (rtp_session->sock) { + if (rtp_session->sock_input) { switch_rtp_kill_socket(rtp_session); } - if (switch_socket_create(&new_sock, AF_INET, SOCK_DGRAM, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) { + if (switch_socket_create(&new_sock, switch_sockaddr_get_family(rtp_session->local_addr), SOCK_DGRAM, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) { *err = "Socket Error!"; goto done; } @@ -483,12 +489,12 @@ #endif - old_sock = rtp_session->sock; - rtp_session->sock = new_sock; + old_sock = rtp_session->sock_input; + rtp_session->sock_input = new_sock; new_sock = NULL; if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK)) { - switch_socket_opt_set(rtp_session->sock, SWITCH_SO_NONBLOCK, TRUE); + switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, TRUE); switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK); } @@ -522,6 +528,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err) { switch_sockaddr_t *remote_addr; + switch_status_t status = SWITCH_STATUS_SUCCESS; *err = "Success"; if (switch_sockaddr_info_get(&remote_addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS || !remote_addr) { @@ -530,11 +537,32 @@ } switch_mutex_lock(rtp_session->write_mutex); + rtp_session->remote_addr = remote_addr; rtp_session->remote_port = port; + + if (rtp_session->sock_input && + switch_sockaddr_get_family(rtp_session->remote_addr) == + switch_sockaddr_get_family(rtp_session->local_addr)) { + rtp_session->sock_output = rtp_session->sock_input; + } + else { + if (rtp_session->sock_output && + rtp_session->sock_output != rtp_session->sock_input) { + switch_socket_close(rtp_session->sock_output); + } + if ((status = switch_socket_create(&rtp_session->sock_output, + switch_sockaddr_get_family(rtp_session->remote_addr), + SOCK_DGRAM, 0, rtp_session->pool)) != + SWITCH_STATUS_SUCCESS) + { + *err = "Socket Error!"; + } + } + switch_mutex_unlock(rtp_session->write_mutex); - return SWITCH_STATUS_SUCCESS; + return status; } SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session, @@ -829,9 +857,9 @@ switch_assert(rtp_session != NULL); switch_mutex_lock(rtp_session->flag_mutex); - if (rtp_session->sock) { + if (rtp_session->sock_input) { switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK); - switch_socket_sendto(rtp_session->sock, rtp_session->local_addr, 0, (void *) &o, &len); + switch_socket_sendto(rtp_session->sock_input, rtp_session->local_addr, 0, (void *) &o, &len); } switch_mutex_unlock(rtp_session->flag_mutex); } @@ -842,9 +870,13 @@ switch_mutex_lock(rtp_session->flag_mutex); if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO)) { switch_clear_flag(rtp_session, SWITCH_RTP_FLAG_IO); - if (rtp_session->sock) { - switch_socket_shutdown(rtp_session->sock, SWITCH_SHUTDOWN_READWRITE); + if (rtp_session->sock_input) { + switch_socket_shutdown(rtp_session->sock_input, SWITCH_SHUTDOWN_READWRITE); } + if (rtp_session->sock_output && + rtp_session->sock_output != rtp_session->sock_input) { + switch_socket_shutdown(rtp_session->sock_output, SWITCH_SHUTDOWN_READWRITE); + } } switch_mutex_unlock(rtp_session->flag_mutex); } @@ -858,7 +890,7 @@ } switch_mutex_lock(rtp_session->flag_mutex); - ret = (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO) && rtp_session->sock && rtp_session->remote_addr && rtp_session->ready == 2) ? 1 : 0; + ret = (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO) && rtp_session->sock_input && rtp_session->sock_output && rtp_session->remote_addr && rtp_session->ready == 2) ? 1 : 0; switch_mutex_unlock(rtp_session->flag_mutex); return ret; @@ -899,10 +931,15 @@ stfu_n_destroy(&(*rtp_session)->jb); } - sock = (*rtp_session)->sock; - (*rtp_session)->sock = NULL; + sock = (*rtp_session)->sock_input; + (*rtp_session)->sock_input = NULL; switch_socket_close(sock); + if ( (*rtp_session)->sock_output != sock ) { + sock = (*rtp_session)->sock_output; + (*rtp_session)->sock_output = NULL; + switch_socket_close(sock); + } if (switch_test_flag((*rtp_session), SWITCH_RTP_FLAG_VAD)) { switch_rtp_disable_vad(*rtp_session); @@ -932,7 +969,7 @@ SWITCH_DECLARE(switch_socket_t *) switch_rtp_get_rtp_socket(switch_rtp_t *rtp_session) { - return rtp_session->sock; + return rtp_session->sock_input; } SWITCH_DECLARE(void) switch_rtp_set_default_samples_per_interval(switch_rtp_t *rtp_session, uint16_t samples_per_interval) @@ -1096,7 +1133,7 @@ int do_cng = 0; bytes = sizeof(rtp_msg_t); - status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock, 0, (void *) &rtp_session->recv_msg, &bytes); + status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes); if (bytes < 0) { ret = (int) bytes; @@ -1184,7 +1221,7 @@ } if (rtp_session->invalid_handler) { - rtp_session->invalid_handler(rtp_session, rtp_session->sock, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr); + rtp_session->invalid_handler(rtp_session, rtp_session->sock_input, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr); } memset(data, 0, 2); @@ -1783,7 +1820,7 @@ bytes = sbytes; } - if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) { + if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) { rtp_session->seq--; ret = -1; goto end; @@ -1889,7 +1926,7 @@ return 0; } bytes = frame->packetlen; - if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) { + if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) { return -1; } return (int) bytes; @@ -1971,7 +2008,7 @@ bytes = sbytes; } - if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) &rtp_session->write_msg, &bytes) != SWITCH_STATUS_SUCCESS) { + if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) &rtp_session->write_msg, &bytes) != SWITCH_STATUS_SUCCESS) { rtp_session->seq--; ret = -1; goto end; Index: src/mod/endpoints/mod_sofia/sofia_reg.c =================================================================== --- src/mod/endpoints/mod_sofia/sofia_reg.c (revision 8886) +++ src/mod/endpoints/mod_sofia/sofia_reg.c (working copy) @@ -403,6 +403,7 @@ const char *rpid = "unknown"; const char *display = "\"user\""; char network_ip[80]; + char url_ip[80]; char *register_gateway = NULL; int network_port; const char *reg_desc = "Registered"; @@ -410,13 +411,19 @@ char *force_user; char received_data[128] = ""; char *path_val = NULL; - + su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua)); + /* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */ switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL); - get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr); - network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); + get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, + my_addrinfo->ai_addrlen); + network_port = get_port(my_addrinfo->ai_addr); + snprintf(url_ip, sizeof(url_ip), + my_addrinfo->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s", + network_ip); + expires = sip->sip_expires; authorization = sip->sip_authorization; contact = sip->sip_contact; @@ -466,7 +473,7 @@ } else { reg_desc = "Registered(UDP-NAT)"; } - contact_host = network_ip; + contact_host = url_ip; switch_snprintf(new_port, sizeof(new_port), ":%d", network_port); port = NULL; } else { @@ -501,7 +508,7 @@ } if (is_nat && (profile->pflags & PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) { - switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", network_ip, network_port); + switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", url_ip, network_port); } if (contact->m_url->url_params) { @@ -556,16 +563,16 @@ if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact"))) { if (*received_data && (profile->pflags & PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) { - switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", network_ip, network_port); + switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", url_ip, network_port); } 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, network_ip, network_port, contact->m_url->url_params, received_data); + display, 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, network_ip, + switch_snprintf(contact_str, sizeof(contact_str), "%s ", display, contact->m_url->url_user, url_ip, network_port, received_data); } if (strstr(v_contact_str, "tls")) { @@ -762,8 +769,9 @@ char *is_nat = NULL; - get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr); - network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); + get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, + my_addrinfo->ai_addrlen); + network_port = get_port(msg_addrinfo(nua_current_request(nua))->ai_addr); if (!(sip->sip_contact && sip->sip_contact->m_url)) { Index: src/mod/endpoints/mod_sofia/mod_sofia.c =================================================================== --- src/mod/endpoints/mod_sofia/mod_sofia.c (revision 8886) +++ src/mod/endpoints/mod_sofia/mod_sofia.c (working copy) @@ -926,7 +926,9 @@ char ref_to[128] = ""; if (!strstr(msg->string_arg, "sip:")) { - switch_snprintf(ref_to, sizeof(ref_to), "sip:%s@%s", msg->string_arg, tech_pvt->profile->sipip); + const char *format = strchr(tech_pvt->profile->sipip, ':') ? + "sip:%s@[%s]" : "sip:%s@%s"; + switch_snprintf(ref_to, sizeof(ref_to), format, msg->string_arg, tech_pvt->profile->sipip); } else { switch_set_string(ref_to, msg->string_arg); } Index: src/mod/endpoints/mod_sofia/sofia.c =================================================================== --- src/mod/endpoints/mod_sofia/sofia.c (revision 8886) +++ src/mod/endpoints/mod_sofia/sofia.c (working copy) @@ -215,7 +215,9 @@ if (authorization) { char network_ip[80]; - get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr); + su_addrinfo_t *addrinfo = msg_addrinfo(nua_current_request(nua)); + get_addr(network_ip, sizeof(network_ip), addrinfo->ai_addr, + addrinfo->ai_addrlen); auth_res = sofia_reg_parse_auth(profile, authorization, sip, (char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, NULL, 0, REG_INVITE, NULL); @@ -893,8 +895,13 @@ gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s;transport=%s", register_proxy, register_transport); gateway->register_from = switch_core_sprintf(gateway->pool, "", from_user, from_domain, register_transport); - gateway->register_contact = switch_core_sprintf(gateway->pool, "", extension, - profile->extsipip ? profile->extsipip : profile->sipip, + + const char *sipip = profile->extsipip ? profile->extsipip : + profile->sipip; + const char *format = strchr(sipip, ':') ? "" : + ""; + gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension, + sipip, sofia_glue_transport_has_tls(gateway->register_transport) ? profile->tls_sip_port : profile-> sip_port, params); @@ -1389,10 +1396,17 @@ profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip); } if (profile->extsipip) { - profile->url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->extsipip, profile->sip_port); + char *ipv6 = strchr(profile->extsipip, ':'); + profile->url = switch_core_sprintf(profile->pool, + "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "", + profile->extsipip, ipv6 ? "]" : "", + profile->sip_port); profile->bindurl = switch_core_sprintf(profile->pool, "%s;maddr=%s", profile->url, profile->sipip); } else { - profile->url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->sipip, profile->sip_port); + char *ipv6 = strchr(profile->sipip, ':'); + profile->url = switch_core_sprintf(profile->pool, + "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "", + profile->sipip, ipv6 ? "]" : "", profile->sip_port); profile->bindurl = profile->url; } @@ -1410,12 +1424,28 @@ } if (profile->extsipip) { - profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->extsipip, profile->tls_sip_port); - profile->tls_bindurl = - switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d;maddr=%s", profile->extsipip, profile->tls_sip_port, profile->sipip); + char *ipv6 = strchr(profile->extsipip, ':'); + profile->tls_url = switch_core_sprintf(profile->pool, + "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "", + profile->extsipip, ipv6 ? "]" : "", + profile->tls_sip_port); + profile->tls_bindurl = + switch_core_sprintf(profile->pool, + "sips:mod_sofia@%s%s%s:%d;maddr=%s", + ipv6 ? "[" : "", profile->extsipip, + ipv6 ? "]" : "", profile->tls_sip_port, + profile->sipip); } else { - profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port); - profile->tls_bindurl = switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port); + char *ipv6 = strchr(profile->sipip, ':'); + profile->tls_url = switch_core_sprintf(profile->pool, + "sip:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "", + profile->sipip, ipv6 ? "]" : "", + profile->tls_sip_port); + profile->tls_bindurl = + switch_core_sprintf(profile->pool, + "sips:mod_sofia@%s%s%s:%d", ipv6 ? "[" : "", + profile->sipip, ipv6 ? "]" : "", + profile->tls_sip_port); } if (profile->tls_bind_params) { @@ -2637,7 +2667,8 @@ return; } - get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr); + get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, + my_addrinfo->ai_addrlen); network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); if ((profile->pflags & PFLAG_AGGRESSIVE_NAT_DETECTION)) { @@ -2754,9 +2785,13 @@ char tmp[35] = ""; sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); - tech_pvt->record_route = switch_core_session_sprintf(session, "sip:%s@%s:%d;transport=%s", - sip->sip_contact->m_url->url_user, tech_pvt->remote_ip, - tech_pvt->remote_port, sofia_glue_transport2str(transport)); + const char *ipv6 = strchr(tech_pvt->remote_ip, ':'); + tech_pvt->record_route = switch_core_session_sprintf(session, + "sip:%s@%s%s%s:%d;transport=%s", + sip->sip_contact->m_url->url_user, ipv6 ? "[" : "", + tech_pvt->remote_ip, ipv6 ? "]" : "", tech_pvt->remote_port, + sofia_glue_transport2str(transport)); + switch_channel_set_variable(channel, "sip_received_ip", tech_pvt->remote_ip); snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_port); switch_channel_set_variable(channel, "sip_received_port", tmp); @@ -2887,7 +2922,11 @@ port = sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port; } - tech_pvt->to_uri = switch_core_session_sprintf(session, "sip:%s@%s:%d;transport=%s", user, host, port, sofia_glue_transport2str(transport)); + const char *ipv6 = strchr(host, ':'); + tech_pvt->to_uri = switch_core_session_sprintf(session, + "sip:%s@%s%s%s:%d;transport=%s", user, ipv6 ? "[" : "", + host, ipv6 ? "]" : "", port, + sofia_glue_transport2str(transport)); if (profile->ndlb & PFLAG_NDLB_TO_IN_200_CONTACT) { if (strchr(tech_pvt->to_uri, '>')) { Index: src/mod/endpoints/mod_sofia/sofia_presence.c =================================================================== --- src/mod/endpoints/mod_sofia/sofia_presence.c (revision 8886) +++ src/mod/endpoints/mod_sofia/sofia_presence.c (working copy) @@ -1209,7 +1209,8 @@ return; } - get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr); + get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, + my_addrinfo->ai_addrlen); network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port); tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END()); @@ -1279,11 +1280,18 @@ switch_snprintf(new_port, sizeof(new_port), ":%s", port); } + const char *ipv6 = strchr(contact_host, ':'); if (contact->m_url->url_params) { - contact_str = switch_mprintf("%s %s", - display, contact->m_url->url_user, contact_host, new_port, contact->m_url->url_params, is_nat ? ";nat" : ""); + contact_str = switch_mprintf("%s %s", + display, contact->m_url->url_user, + ipv6 ? "[" : "", contact_host, + ipv6 ? "]" : "", new_port, + contact->m_url->url_params, is_nat ? + ";nat" : ""); } else { - contact_str = switch_mprintf("%s %s", display, contact->m_url->url_user, contact_host, new_port, is_nat ? ";nat" : ""); + contact_str = switch_mprintf("%s %s", display, + contact->m_url->url_user, ipv6 ? "[" : "", contact_host, + ipv6 ? "]" : "", new_port, is_nat ? ";nat" : ""); } @@ -1398,7 +1406,10 @@ char *sticky = NULL; if (is_nat) { - sticky = switch_mprintf("sip:%s@%s:%d", contact_user, network_ip, network_port); + const char *ipv6 = strchr(network_ip, ':'); + sticky = switch_mprintf("sip:%s@%s%s%s:%d", contact_user, + ipv6 ? "[" : "", network_ip, ipv6 ? "]" : "", + network_port); } nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS(nua), SIPTAG_SUBSCRIPTION_STATE_STR(sstr), TAG_IF(sticky, NUTAG_PROXY(sticky)), Index: src/mod/endpoints/mod_sofia/sofia_glue.c =================================================================== --- src/mod/endpoints/mod_sofia/sofia_glue.c (revision 8886) +++ src/mod/endpoints/mod_sofia/sofia_glue.c (working copy) @@ -82,13 +82,14 @@ tech_pvt->session_id++; + const char *family = strchr(ip, ':') ? "IP6" : "IP4"; switch_snprintf(buf, sizeof(buf), "v=0\n" - "o=FreeSWITCH %010u %010u IN IP4 %s\n" + "o=FreeSWITCH %010u %010u IN %s %s\n" "s=FreeSWITCH\n" - "c=IN IP4 %s\n" "t=0 0\n" + "c=IN %s %s\n" "t=0 0\n" "a=%s\n" - "m=audio %d RTP/%sAVP", tech_pvt->owner_id, tech_pvt->session_id, ip, ip, sr, port, + "m=audio %d RTP/%sAVP", tech_pvt->owner_id, tech_pvt->session_id, family, ip, family, ip, sr, port, (!switch_strlen_zero(tech_pvt->local_crypto_key) && switch_test_flag(tech_pvt, TFLAG_SECURE)) ? "S" : ""); @@ -730,7 +731,8 @@ return SWITCH_STATUS_FALSE; } - if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str))) { + if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str)) || + (p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->remote_sdp_str))) { ip_ptr = p + 9; } @@ -833,7 +835,8 @@ len = strlen(tech_pvt->local_sdp_str) + 384; - if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->local_sdp_str))) { + if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->local_sdp_str)) || + (p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->local_sdp_str))) { ip_ptr = p + 9; } @@ -956,11 +959,13 @@ check_decode(cid_num, session); if (!tech_pvt->from_str) { - tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, "\"%s\" ", - cid_name, - cid_num, - !switch_strlen_zero(cid_num) ? "@" : "", - tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip); + const char* sipip = tech_pvt->profile->extsipip ? + tech_pvt->profile->extsipip : tech_pvt->profile->sipip; + const char* format = strchr(sipip, ':') ? + "\"%s\" " : "\"%s\" "; + tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, + format, cid_name, cid_num, + !switch_strlen_zero(cid_num) ? "@" : "", sipip); } if ((alertbuf = switch_channel_get_variable(channel, "alert_info"))) { @@ -1228,10 +1233,13 @@ caller_profile = switch_channel_get_caller_profile(channel); - if ((tech_pvt->from_str = switch_core_session_sprintf(session, "\"%s\" ", - caller_profile->caller_id_name, - caller_profile->caller_id_number, - tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip))) { + const char* sipip = tech_pvt->profile->extsipip ? + tech_pvt->profile->extsipip : tech_pvt->profile->sipip; + const char* format = strchr(sipip, ':') ? + "\"%s\" " : "\"%s\" "; + if ((tech_pvt->from_str = switch_core_session_sprintf(session, format, + caller_profile->caller_id_name, + caller_profile->caller_id_number, sipip))) { const char *rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER); @@ -1637,7 +1645,7 @@ } if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_audio_port, Index: src/include/switch_utils.h =================================================================== --- src/include/switch_utils.h (revision 8886) +++ src/include/switch_utils.h (working copy) @@ -118,11 +118,43 @@ \brief find the char representation of an ip adress \param buf the buffer to write the ip adress found into \param len the length of the buf - \param in the struct in_addr * to get the adress from + \param sa the struct sockaddr * to get the adress from + \param salen the length of sa \return the ip adress string */ -SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct in_addr *in); +SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, + struct sockaddr *sa, socklen_t salen); +/*! + \brief get the port number of an ip address + \param sa the struct sockaddr * to get the port from + \return the ip adress string +*/ +SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa); + +/*! + \brief flags to be used with switch_build_uri() + */ +enum switch_uri_flags { + SWITCH_URI_NUMERIC_HOST = 1, + SWITCH_URI_NUMERIC_PORT = 2, + SWITCH_URI_NO_SCOPE = 4, +}; + +/*! + \brief build a URI string from components + \param uri output string + \param size maximum size of output string (including trailing null) + \param scheme URI scheme + \param user user part or null if none + \param sa host address + \param flags logical OR-ed combination of flags from \ref switch_uri_flags + \return number of characters printed (not including the trailing null) + */ +SWITCH_DECLARE(int) switch_build_uri(char *uri, switch_size_t size, + const char *scheme, const char *user, const switch_sockaddr_t *sa, + int flags); + #define SWITCH_STATUS_IS_BREAK(x) (x == SWITCH_STATUS_BREAK || x == 730035 || x == 35) /*! Index: src/switch_utils.c =================================================================== --- src/switch_utils.c (revision 8886) +++ src/switch_utils.c (working copy) @@ -32,6 +32,7 @@ */ #include +#include #ifndef WIN32 #include #endif @@ -757,7 +758,8 @@ goto doh; } - switch_copy_string(buf, get_addr(abuf, sizeof(abuf), &iface_out.sin_addr), len); + switch_copy_string(buf, get_addr(abuf, sizeof(abuf), + (struct sockaddr*)&iface_out, sizeof(iface_out)), len); status = SWITCH_STATUS_SUCCESS; } break; @@ -768,20 +770,16 @@ memset(&remote, 0, sizeof(struct sockaddr_in6)); remote.sin6_family = AF_INET6; - switch_inet_pton(AF_INET6, buf, &remote.sin6_addr); + switch_inet_pton(AF_INET6, base, &remote.sin6_addr); remote.sin6_port = htons(4242); memset(&iface_out, 0, sizeof(iface_out)); tmp_socket = socket(AF_INET6, SOCK_DGRAM, 0); - if (setsockopt(tmp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) { + if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(remote)) == -1) { goto doh; } - if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(struct sockaddr_in)) == -1) { - goto doh; - } - ilen = sizeof(iface_out); if (getsockname(tmp_socket, (struct sockaddr *) &iface_out, &ilen) == -1) { goto doh; @@ -1054,16 +1052,64 @@ #endif -SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct in_addr *in) +SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, + struct sockaddr *sa, socklen_t salen) { switch_assert(buf); *buf = '\0'; - if (in) { - switch_inet_ntop(AF_INET, in, buf, len); + if (sa) { + getnameinfo(sa, salen, buf, len, NULL, 0, NI_NUMERICHOST); } return buf; } +SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa) +{ + unsigned short port = 0; + if (sa) { + switch (sa->sa_family) { + case AF_INET: + port = ntohs(((struct sockaddr_in*)sa)->sin_port); + break; + case AF_INET6: + port = ntohs(((struct sockaddr_in6*)sa)->sin6_port); + break; + } + } + return port; +} + +SWITCH_DECLARE(int) switch_build_uri(char *uri, switch_size_t size, + const char *scheme, const char *user, const switch_sockaddr_t *sa, + int flags) +{ + char host[NI_MAXHOST], serv[NI_MAXSERV]; + struct sockaddr_storage ss; + const struct sockaddr *addr; + const char *colon; + + if (flags & SWITCH_URI_NO_SCOPE && sa->family == AF_INET6) { + memcpy(&ss, &sa->sa, sa->salen); + ((struct sockaddr_in6*) &ss)->sin6_scope_id = 0; + addr = (const struct sockaddr*) &ss; + } else { + addr = (const struct sockaddr*) &sa->sa; + } + + if (getnameinfo(addr, sa->salen, host, sizeof(host), serv, sizeof(serv), + (flags & SWITCH_URI_NUMERIC_HOST) ? NI_NUMERICHOST : 0 | + (flags & SWITCH_URI_NUMERIC_PORT) ? NI_NUMERICSERV : 0) != 0) { + return 0; + } + + colon = strchr(host, ':'); + + return switch_snprintf(uri, size, "%s:%s%s%s%s%s%s%s", scheme, + user ? user : "", user ? "@" : "", + colon ? "[" : "", host, colon ? "]" : "", + serv[0] ? ":" : "", serv[0] ? serv : ""); +} + SWITCH_DECLARE(char) switch_rfc2833_to_char(int event) { if (event > -1 && event < (int32_t) sizeof(RFC2833_CHARS)) {