]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7587 Add ipv6 support to Verto / Websockets
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 28 May 2015 23:02:21 +0000 (18:02 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 1 Jun 2015 18:39:47 +0000 (13:39 -0500)
conf/vanilla/autoload_configs/verto.conf.xml
src/include/switch_core_media.h
src/include/switch_rtp.h
src/mod/endpoints/mod_verto/mcast/mcast.c
src/mod/endpoints/mod_verto/mcast/mcast.h
src/mod/endpoints/mod_verto/mod_verto.c
src/mod/endpoints/mod_verto/mod_verto.h
src/mod/endpoints/mod_verto/ws.c
src/switch_core.c
src/switch_core_media.c
src/switch_utils.c

index a62fd706d742de49522f953ec54e11a845efed85..b69777ac0a1a1b11bdd16e63c57d72e8bf353723 100644 (file)
@@ -5,9 +5,9 @@
   </settings>
 
   <profiles>
-    <profile name="mine">
-      <param name="bind-local" value="0.0.0.0:8081"/>
-      <param name="bind-local" value="0.0.0.0:8082" secure="true"/>
+    <profile name="default-v4">
+      <param name="bind-local" value="$${local_ip_v4}:8081"/>
+      <param name="bind-local" value="$${local_ip_v4}:8082" secure="true"/>
       <param name="force-register-domain" value="$${domain}"/>
       <param name="secure-combined" value="$${certs_dir}/wss.pem"/>
       <param name="secure-chain" value="$${certs_dir}/wss.pem"/>
       <param name="local-network" value="localnet.auto"/>
       <param name="outbound-codec-string" value="opus,vp8"/>
       <param name="inbound-codec-string" value="opus,vp8"/>
-      <param name="apply-candidate-acl" value="wan.auto"/>
+      <param name="apply-candidate-acl" value="wan_v4.auto"/>
+      <param name="timer-name" value="soft"/>
+      
+    </profile>
+
+    <profile name="default-v6">
+      <param name="bind-local" value="[$${local_ip_v6}]:8081"/>
+      <param name="bind-local" value="[$${local_ip_v6}]:8082" secure="true"/>
+      <param name="force-register-domain" value="$${domain}"/>
+      <param name="secure-combined" value="$${certs_dir}/wss.pem"/>
+      <param name="secure-chain" value="$${certs_dir}/wss.pem"/>
+      <param name="userauth" value="true"/>
+      <!-- setting this to true will allow anyone to register even with no account so use with care -->
+      <param name="blind-reg" value="false"/>
+      <param name="mcast-ip" value="ff02::1"/>
+      <param name="mcast-port" value="1337"/>
+      <param name="rtp-ip" value="$${local_ip_v6}"/>
+      <!--  <param name="ext-rtp-ip" value=""/> -->
+      <param name="local-network" value="localnet.auto"/>
+      <param name="outbound-codec-string" value="opus,vp8"/>
+      <param name="inbound-codec-string" value="opus,vp8"/>
+      <param name="apply-candidate-acl" value="wan_v6.auto"/>
       <param name="timer-name" value="soft"/>
       
     </profile>
index 37631fce70869e1ba8e559b335243ac4933bb11b..bc258172252e22b9ff7379134dd26be037e848a9 100644 (file)
@@ -125,6 +125,9 @@ typedef struct switch_core_media_params_s {
 
        char *extrtpip;
        char *rtpip;
+       char *rtpip4;
+       char *rtpip6;
+       
 
        char *remote_ip;
        int remote_port;
index 6dfa1e253171e9771bc2c950ece215baa4402b66..4bb140c83d22ba9b98720e495ea2d37f93fca4a8 100644 (file)
@@ -105,6 +105,7 @@ typedef struct ice_s {
        icand_t cands[MAX_CAND][2];
        int cand_idx;
        int chosen[2];
+       int is_chosen[2];
        char *ufrag;
        char *pwd;
        char *options;
index e37ac08efc8cb2c86f601be9a4c47ba17899a2e1..617553bcc474ff257154688b06ac1262d2fa1e2e 100644 (file)
 int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, mcast_flag_t flags)
 {
        uint32_t one = 1;
+       int family = AF_INET;
 
        memset(handle, 0, sizeof(*handle));
        
-       if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0 ) {
-               return -1;
+       if (strchr(host, ':')) { 
+               family = AF_INET6;
        }
        
-       handle->send_addr.sin_family = AF_INET;
-       handle->send_addr.sin_addr.s_addr = inet_addr(host);
-       handle->send_addr.sin_port = htons(port);
+       if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(family, SOCK_DGRAM, 0)) <= 0 ) {
+               return -1;
+       }
+
+       if (family == AF_INET6) {
+               handle->send_addr6.sin6_family = AF_INET6;
+               handle->send_addr6.sin6_port = htons(port);
+               inet_pton(AF_INET6, host, &(handle->send_addr6.sin6_addr));
+               handle->family = AF_INET6;
+       } else {
+               handle->send_addr.sin_family = AF_INET;
+               handle->send_addr.sin_addr.s_addr = inet_addr(host);
+               handle->send_addr.sin_port = htons(port);
+               handle->family = AF_INET;
+       }
        
        if ( setsockopt(handle->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) != 0 ) {
                close(handle->sock);
@@ -76,28 +89,61 @@ int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle,
        
 
        if ((flags & MCAST_RECV)) {
-               struct ip_mreq mreq;
-
-               handle->recv_addr.sin_family = AF_INET;
-               handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-               handle->recv_addr.sin_port = htons(port);
-
-               mreq.imr_multiaddr.s_addr = inet_addr(host);
-               mreq.imr_interface.s_addr = htonl(INADDR_ANY);
-
-               if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) {
-                       close(handle->sock);
-                       handle->sock = -1;
-                       return -1;
-               }
-
-               if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr, sizeof(handle->recv_addr)) < 0) {
-                       close(handle->sock);
-                       handle->sock = -1;
-                       return -1;
+               if (handle->family == AF_INET) {
+                       struct ip_mreq mreq;
+                       
+                       handle->recv_addr.sin_family = AF_INET;
+                       handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+                       handle->recv_addr.sin_port = htons(port);
+
+                       mreq.imr_multiaddr.s_addr = inet_addr(host);
+                       mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+
+                       if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) {
+                               close(handle->sock);
+                               handle->sock = -1;
+                               return -1;
+                       }
+
+                       if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr, sizeof(handle->recv_addr)) < 0) {
+                               close(handle->sock);
+                               handle->sock = -1;
+                               return -1;
+                       }
+
+               } else {
+                       struct ipv6_mreq mreq;
+                       struct addrinfo addr_criteria;
+                       struct addrinfo *mcast_addr;
+                       char service[80] = "";
+                       
+                       memset(&addr_criteria, 0, sizeof(addr_criteria));
+                       addr_criteria.ai_family = AF_UNSPEC;
+                       addr_criteria.ai_socktype = SOCK_DGRAM;
+                       addr_criteria.ai_protocol = IPPROTO_UDP;
+                       addr_criteria.ai_flags |= AI_NUMERICHOST;
+                       
+                       snprintf(service, sizeof(service), "%d", port);
+                       getaddrinfo(host, service, &addr_criteria, &mcast_addr);
+
+                       
+                       memset(&handle->recv_addr6, 0, sizeof(handle->recv_addr6));
+                       handle->recv_addr6.sin6_family = AF_INET6;
+                       handle->recv_addr6.sin6_port = htons(port);
+                       inet_pton(AF_INET6, "::0", &(handle->recv_addr6.sin6_addr));
+
+                       memcpy(&mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *)mcast_addr->ai_addr)->sin6_addr,  sizeof(struct in6_addr));
+                                                                                        
+                       mreq.ipv6mr_interface = 0;
+                       setsockopt(handle->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq));
+
+                       if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr6, sizeof(handle->recv_addr6)) < 0) {
+                               printf("FUCK (%s) %s\n", host, strerror(errno));
+                               close(handle->sock);
+                               handle->sock = -1;
+                               return -1;
+                       }
                }
-               
-
        }
 
        handle->ttl = 1;
@@ -155,7 +201,11 @@ ssize_t mcast_socket_send(mcast_handle_t *handle, void *data, size_t datalen)
                datalen = sizeof(handle->buffer);
        }
 
-       return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr, sizeof(handle->send_addr));
+       if (handle->family == AF_INET6) {
+               return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr6, sizeof(handle->send_addr6));
+       } else {
+               return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr, sizeof(handle->send_addr));
+       }
 }
 
 ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, int ms)
@@ -175,6 +225,9 @@ ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, in
                }
        }
 
-       
-       return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen);
+       if (handle->family == AF_INET6) {
+               return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr6, &addrlen);
+       } else {
+               return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen);
+       }
 }
index 915f803fe8152c84d5a12436a59dd766e6c2a233..bc9114abcee03daa3dd92a818a20caff864eacba 100644 (file)
@@ -71,6 +71,9 @@ typedef struct {
        unsigned char ttl;
        struct sockaddr_in send_addr;
        struct sockaddr_in recv_addr;
+       struct sockaddr_in6 send_addr6;
+       struct sockaddr_in6 recv_addr6;
+       int family;
        unsigned char buffer[65536];
        int ready;
 } mcast_handle_t;
index 1d422a53ad6d673ccfe9a287155ff1f6e5f8e89e..57faa8e38a79af359cdabdbe0116bc2c333b2e30 100644 (file)
@@ -1803,12 +1803,6 @@ error:
 
 static void client_run(jsock_t *jsock)
 {
-
-    jsock->local_addr.sin_family = AF_INET;
-    jsock->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-    jsock->local_addr.sin_port = 0;
-
-
        if (ws_init(&jsock->ws, jsock->client_socket, (jsock->ptype & PTYPE_CLIENT_SSL) ? jsock->profile->ssl_ctx : NULL, 0, 1, !!jsock->profile->vhosts) < 0) {
                if (jsock->profile->vhosts) {
                        http_run(jsock);
@@ -2259,10 +2253,30 @@ static void verto_set_media_options(verto_pvt_t *tech_pvt, verto_profile_t *prof
 {
        uint32_t i;
 
-       tech_pvt->mparams->rtpip = switch_core_session_strdup(tech_pvt->session, profile->rtpip[profile->rtpip_cur++]);
+       if (!zstr(profile->rtpip[profile->rtpip_cur])) {
+               tech_pvt->mparams->rtpip4 = switch_core_session_strdup(tech_pvt->session, profile->rtpip[profile->rtpip_cur++]);
+               tech_pvt->mparams->rtpip = tech_pvt->mparams->rtpip4;
+               if (profile->rtpip_cur == profile->rtpip_index) {
+                       profile->rtpip_cur = 0;
+               }
+       }
 
-       if (profile->rtpip_cur == profile->rtpip_index) {
-               profile->rtpip_cur = 0;
+       if (!zstr(profile->rtpip6[profile->rtpip_cur6])) {
+               tech_pvt->mparams->rtpip6 = switch_core_session_strdup(tech_pvt->session, profile->rtpip6[profile->rtpip_cur6++]);
+
+               if (zstr(tech_pvt->mparams->rtpip)) {
+                       tech_pvt->mparams->rtpip = tech_pvt->mparams->rtpip6;
+               }
+               
+               if (profile->rtpip_cur6 == profile->rtpip_index6) {
+                       profile->rtpip_cur6 = 0;
+               }
+       }
+
+       if (zstr(tech_pvt->mparams->rtpip)) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "%s has no media ip, check your configuration\n", 
+                                                 switch_channel_get_name(tech_pvt->channel));
+               switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL);
        }
 
        tech_pvt->mparams->extrtpip = tech_pvt->mparams->extsipip = profile->extrtpip;
@@ -3376,7 +3390,7 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
                                                                                                        switch_either(jsock->dialplan, jsock->profile->dialplan),
                                                                                                        caller_id_name,
                                                                                                        caller_id_number,
-                                                                                                       inet_ntoa(jsock->remote_addr.sin_addr),
+                                                                                                       jsock->remote_host,
                                                                                                        cJSON_GetObjectCstr(dialog, "ani"),
                                                                                                        cJSON_GetObjectCstr(dialog, "aniii"),
                                                                                                        cJSON_GetObjectCstr(dialog, "rdnis"), 
@@ -3778,7 +3792,7 @@ static void jrpc_init(void)
 
 
 
-static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
+static int start_jsock(verto_profile_t *profile, ws_socket_t sock, int family)
 {
        jsock_t *jsock = NULL;
        int flag = 1;
@@ -3798,11 +3812,20 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
 
        jsock = (jsock_t *) switch_core_alloc(pool, sizeof(*jsock));
        jsock->pool = pool;
+       jsock->family = family;
+
+       if (family == PF_INET) {
+               len = sizeof(jsock->remote_addr);
 
-    len = sizeof(jsock->remote_addr);
+               if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) {
+                       die("ACCEPT FAILED\n");
+               }
+       } else {
+               len = sizeof(jsock->remote_addr6);
 
-       if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) {
-               die("ACCEPT FAILED\n");
+               if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr6, &len)) < 0) {
+                       die("ACCEPT FAILED\n");
+               }
        }
        
        for (i = 0; i < profile->i; i++) {
@@ -3818,7 +3841,15 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
        jsock->profile = profile;
        
        if (zstr(jsock->name)) {
-               jsock->name = switch_core_sprintf(pool, "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port));
+               if (family == PF_INET) {
+                       jsock->remote_port = ntohs(jsock->remote_addr.sin_port);
+                       inet_ntop(AF_INET, &jsock->remote_addr.sin_addr, jsock->remote_host, sizeof(jsock->remote_host));
+                       jsock->name = switch_core_sprintf(pool, "%s:%d", jsock->remote_host, jsock->remote_port);
+               } else {
+                       jsock->remote_port = ntohs(jsock->remote_addr6.sin6_port);
+                       inet_ntop(AF_INET6, &jsock->remote_addr6.sin6_addr, jsock->remote_host, sizeof(jsock->remote_host));
+                       jsock->name = switch_core_sprintf(pool, "%s:%d", jsock->remote_host, jsock->remote_port);
+               }
        }
        
        jsock->ptype = ptype;
@@ -3826,7 +3857,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Client Connect.\n", jsock->name);
        if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_CLIENT_CONNECT) == SWITCH_STATUS_SUCCESS) {
                switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_profile_name", profile->name);
-               switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port));
+               switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", "%s:%d", jsock->remote_host, jsock->remote_port);
                switch_event_fire(&s_event);
        }
 
@@ -3873,7 +3904,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
        return -1;
 }
 
-static ws_socket_t prepare_socket(int ip, uint16_t port
+static ws_socket_t prepare_socket(ips_t *ips
 {
        ws_socket_t sock = ws_sock_invalid;
 #ifndef WIN32
@@ -3881,29 +3912,48 @@ static ws_socket_t prepare_socket(int ip, uint16_t port)
 #else
        char reuse_addr = 1;
 #endif
+       int family;
        struct sockaddr_in addr;
+       struct sockaddr_in6 addr6;
+
+       if (strchr(ips->local_ip, ':')) {
+               family = PF_INET6;
+       } else {
+               family = PF_INET;
+       }
 
-       if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+       if ((sock = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
                die("Socket Error!\n");
        }
        
        if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) < 0 ) {
                die("Socket setsockopt Error!\n");
        }
-       
-       memset(&addr, 0, sizeof(addr));
-       addr.sin_family = AF_INET;
-    addr.sin_addr.s_addr = ip;
-    addr.sin_port = htons(port);
-       
-    if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-               die("Bind Error!\n");
-       }
 
+       if (family == PF_INET) {
+               memset(&addr, 0, sizeof(addr));
+               addr.sin_family = AF_INET;
+               addr.sin_addr.s_addr = inet_addr(ips->local_ip);
+               addr.sin_port = htons(ips->local_port);
+               if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+                       die("Bind Error!\n");
+               }
+       } else {
+               memset(&addr6, 0, sizeof(addr6));
+               addr6.sin6_family = AF_INET6;
+               addr6.sin6_port = htons(ips->local_port);
+               inet_pton(AF_INET6, ips->local_ip, &(addr6.sin6_addr));
+               if (bind(sock, (struct sockaddr *) &addr6, sizeof(addr6)) < 0) {
+                       die("Bind Error!\n");
+               }
+       }
+       
     if (listen(sock, MAXPENDING) < 0) {
                die("Listen error\n");
        }
 
+       ips->family = family;
+
        return sock;
 
  error:
@@ -3979,7 +4029,7 @@ static int profile_one_loop(verto_profile_t *profile)
                        if (profile->mcast_ip && pfds[x].sock == (switch_os_socket_t)profile->mcast_sub.sock) {
                                handle_mcast_sub(profile);
                        } else {
-                               start_jsock(profile, pfds[x].sock);
+                               start_jsock(profile, pfds[x].sock, profile->ip[x].family);
                        }
                }
        }
@@ -3991,52 +4041,6 @@ static int profile_one_loop(verto_profile_t *profile)
 }
 
 
-static int runtime(verto_profile_t *profile)
-{
-       int i;
-
-       for (i = 0; i < profile->i; i++) {
-               if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) {
-                       die("Client Socket Error!\n");
-               }
-       }
-       
-       if (profile->mcast_ip) {
-               if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) {
-                       die("mcast recv socket create");
-               }
-               
-               if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) {
-                       mcast_socket_close(&profile->mcast_sub);
-                       die("mcast send socket create");
-               }
-
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1);
-       }
-       
-       
-       while(profile->running) {
-               if (profile_one_loop(profile) < 0) {
-                       goto error;
-               }
-       }
-
-       if (profile->mcast_sub.sock > -1) {
-               mcast_socket_close(&profile->mcast_sub);
-       }
-
-       if (profile->mcast_pub.sock > -1) {
-               mcast_socket_close(&profile->mcast_pub);
-       }
-
-       return 0;
-
- error:
-
-       return -1;
-
-}
-
 static void kill_profile(verto_profile_t *profile)
 {
        jsock_t *p;
@@ -4092,6 +4096,58 @@ static void kill_profiles(void)
 }
 
 
+static int runtime(verto_profile_t *profile)
+{
+       int i;
+       int r = 0;
+
+       for (i = 0; i < profile->i; i++) {
+               //if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) {
+               if ((profile->server_socket[i] = prepare_socket(&profile->ip[i])) < 0) {
+                       die("Client Socket Error!\n");
+               }
+       }
+       
+       if (profile->mcast_ip) {
+               if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) {
+                       r = -1;
+                       die("mcast recv socket create\n");
+               }
+               
+               if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) {
+                       mcast_socket_close(&profile->mcast_sub);
+                       r = -1;
+                       die("mcast send socket create\n");
+               }
+
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1);
+       }
+       
+       
+       while(profile->running) {
+               if (profile_one_loop(profile) < 0) {
+                       goto error;
+               }
+       }
+
+ error:
+
+       if (profile->mcast_sub.sock > -1) {
+               mcast_socket_close(&profile->mcast_sub);
+       }
+
+       if (profile->mcast_pub.sock > -1) {
+               mcast_socket_close(&profile->mcast_pub);
+       }
+
+       if (r) {
+               kill_profile(profile);
+       }
+
+       return r;
+       
+}
+
 static void do_shutdown(void)
 {
        globals.running = 0;
@@ -4105,20 +4161,35 @@ static void do_shutdown(void)
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Done\n");
 }
 
-static void parse_ip(char *host, uint16_t *port, in_addr_t *addr, char *input)
+
+static void parse_ip(char *host, switch_size_t host_len, uint16_t *port, char *input)
 {
        char *p;
-       struct hostent *hent;
-
-       strncpy(host, input, 255);
-
-       host[255] = 0;
-
-       if ((p = strchr(host, ':')) != NULL) {
-               *p++  = '\0';
-               *port = (uint16_t)atoi(p);
+       //struct hostent *hent;
+
+       if ((p = strchr(input, '['))) {
+               char *end = switch_find_end_paren(p, '[', ']');
+               if (end) {
+                       p++;
+                       strncpy(host, p, end - p);
+                       if (*(end+1) == ':' && end + 2 < end_of_p(input)) {
+                               end += 2;
+                               if (end) {
+                                       *port = (uint16_t)atoi(end);
+                               }
+                       }
+               } else {
+                       strncpy(host, "::", host_len);
+               }
+       } else {
+               strncpy(host, input, host_len);
+               if ((p = strrchr(host, ':')) != NULL) {
+                       *p++  = '\0';
+                       *port = (uint16_t)atoi(p);
+               }
        }
 
+#if 0
        if ( host[0] < '0' || host[0] > '9' ) {
                // Non-numeric host (at least it doesn't start with one).  Convert it to ip addr first
                if ((hent = gethostbyname(host)) != NULL) {
@@ -4130,8 +4201,10 @@ static void parse_ip(char *host, uint16_t *port, in_addr_t *addr, char *input)
        } else {
                *addr = inet_addr(host);
        }
+#endif
 }
 
+
 static verto_profile_t *find_profile(const char *name)
 {
        verto_profile_t *p, *r = NULL;
@@ -4264,7 +4337,7 @@ static switch_status_t parse_config(const char *cf)
                                if (!strcasecmp(var, "bind-local")) {
                                        const char *secure = switch_xml_attr_soft(param, "secure");
                                        if (i < MAX_BIND) {
-                                               parse_ip(profile->ip[profile->i].local_ip, &profile->ip[profile->i].local_port, &profile->ip[profile->i].local_ip_addr, val);
+                                               parse_ip(profile->ip[profile->i].local_ip, sizeof(profile->ip[profile->i].local_ip), &profile->ip[profile->i].local_port, val);
                                                if (switch_true(secure)) {
                                                        profile->ip[profile->i].secure = 1;
                                                }
@@ -4316,10 +4389,18 @@ static switch_status_t parse_config(const char *cf)
                                        if (zstr(val)) {
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid RTP IP.\n");
                                        } else {
-                                               if (profile->rtpip_index < MAX_RTPIP -1) {
-                                                       profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val);
+                                               if (strchr(val, ':')) {
+                                                       if (profile->rtpip_index6 < MAX_RTPIP -1) {
+                                                               profile->rtpip6[profile->rtpip_index6++] = switch_core_strdup(profile->pool, val);
+                                                       } else {
+                                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n");
+                                                       }
                                                } else {
-                                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n");
+                                                       if (profile->rtpip_index < MAX_RTPIP -1) {
+                                                               profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val);
+                                                       } else {
+                                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n");
+                                                       }
                                                }
                                        }
                                } else if (!strcasecmp(var, "ext-rtp-ip")) {
index 11614926a6dfd20e4941739ed6258e844d83ae61..eccd09536980c9d6be53bb0140094d720b352018 100644 (file)
@@ -106,9 +106,8 @@ struct jsock_s {
        unsigned char buf[65535];
        char *name;
        jsock_type_t ptype;
-       struct sockaddr_in local_addr;
        struct sockaddr_in remote_addr;
-       struct sockaddr_in send_addr;
+       struct sockaddr_in6 remote_addr6;
 #ifndef WIN32
        struct passwd pw;
 #endif
@@ -132,6 +131,11 @@ struct jsock_s {
        char *dialplan;
        char *context;
        
+
+       char remote_host[256];
+       int remote_port;
+       int family;
+
        struct verto_profile_s *profile;
        switch_thread_rwlock_t *rwlock;
        
@@ -155,12 +159,12 @@ typedef struct jsock_s jsock_t;
 #define MAX_BIND 25
 #define MAX_RTPIP 25
 
-struct ips {
+typedef struct ips {
        char local_ip[256];
-       in_addr_t local_ip_addr;
        uint16_t local_port;
        int secure;
-};
+       int family;
+} ips_t;
 
 typedef enum {
        TFLAG_SENT_MEDIA = (1 << 0),
@@ -240,6 +244,10 @@ struct verto_profile_s {
        int rtpip_index;
        int rtpip_cur;
 
+       char *rtpip6[MAX_RTPIP];
+       int rtpip_index6;
+       int rtpip_cur6;
+
        char *cand_acl[SWITCH_MAX_CAND_ACL];
        uint32_t cand_acl_count;
 
index 8a46b65502e2cf40ab282309d70abbb53407f20d..6e9a69d025713d64670ee8f61ccaf349413bbcac 100644 (file)
@@ -691,6 +691,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
        ssize_t need = 2;
        char *maskp;
        int ll = 0;
+       int frag = 0;
 
  again:
        need = 2;
@@ -741,8 +742,16 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
        case WSOC_PING:
        case WSOC_PONG:
                {
-                       //int fin = (wsh->buffer[0] >> 7) & 1;
+                       int fin = (wsh->buffer[0] >> 7) & 1;
                        int mask = (wsh->buffer[1] >> 7) & 1;
+                       
+                       if (fin) {
+                               if (*oc == WSOC_CONTINUATION) {
+                                       frag = 1;
+                               } else {
+                                       frag = 0;
+                               }
+                       }
 
                        if (mask) {
                                need += 4;
@@ -837,6 +846,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
                                ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen);
                                goto again;
                        }
+
+                       if (frag) {
+                               goto again;
+                       }
                        
 
                        *(wsh->payload+wsh->rplen) = '\0';
index 753dfa5a2693309c27f6a90a7e6cfe4362748862..5ed8ad83a108f529aed7a15e6ed8e797f5488048 100644 (file)
@@ -1331,7 +1331,12 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
                        free(list_name_dup);
                } else {
                        switch_parse_cidr(list_name, &net, &mask, &bits);
-                       ok = switch_test_subnet(ip.v4, net.v4, mask.v4);
+
+                       if (ipv6) {
+                               ok = switch_testv6_subnet(ip, net, mask);
+                       } else {
+                               ok = switch_test_subnet(ip.v4, net.v4, mask.v4);
+                       }
                }
        }
        switch_mutex_unlock(runtime.global_mutex);
@@ -1395,6 +1400,26 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
        switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
        switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
 
+       tmp_name = "wan_v6.auto";
+       switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
+       switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE);
+       switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
+       switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
+
+
+       tmp_name = "wan_v4.auto";
+       switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
+       switch_network_list_add_cidr(rfc_list, "0.0.0.0/8", SWITCH_FALSE);
+       switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE);
+       switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE);
+       switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE);
+       switch_network_list_add_cidr(rfc_list, "169.254.0.0/16", SWITCH_FALSE);
+       switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE);
+       switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
+
+
        tmp_name = "nat.auto";
        switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
index 7a469575d4801d610ad27b5a056e3a483ed9e683..d20af51290a610869532c02f13ffe87336c05f13 100644 (file)
@@ -2885,6 +2885,8 @@ static void clear_ice(switch_core_session_t *session, switch_media_type_t type)
 
        engine->ice_in.chosen[0] = 0;
        engine->ice_in.chosen[1] = 0;
+       engine->ice_in.is_chosen[0] = 0;
+       engine->ice_in.is_chosen[1] = 0;
        engine->ice_in.cand_idx = 0;
        memset(&engine->ice_in, 0, sizeof(engine->ice_in));
        engine->remote_rtcp_port = 0;
@@ -3047,6 +3049,52 @@ SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session
        return r;
 }
 
+//?
+static switch_status_t ip_choose_family(switch_media_handle_t *smh, const char *ip)
+{
+       switch_status_t status = SWITCH_STATUS_FALSE;
+
+       if (zstr(ip)) {
+               return status;
+       }
+
+       if (strchr(ip, ':')) {
+               if (!zstr(smh->mparams->rtpip6)) {
+                       smh->mparams->rtpip = smh->mparams->rtpip6;
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v6\n", 
+                                                         switch_channel_get_name(smh->session->channel));
+                       status = SWITCH_STATUS_SUCCESS;
+               }
+       } else {
+               if (!zstr(smh->mparams->rtpip4)) {
+                       smh->mparams->rtpip = smh->mparams->rtpip4;
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v4\n", 
+                                                         switch_channel_get_name(smh->session->channel));
+                       status = SWITCH_STATUS_SUCCESS;
+               }
+       }
+
+       return status;
+}
+
+//?
+static switch_bool_t ip_possible(switch_media_handle_t *smh, const char *ip)
+{
+       switch_bool_t r = SWITCH_FALSE;
+
+       if (zstr(ip)) {
+               return r;
+       }
+
+       if (strchr(ip, ':')) {
+               r = (switch_bool_t) !zstr(smh->mparams->rtpip6);
+       } else {
+               r = (switch_bool_t) !zstr(smh->mparams->rtpip4);
+       }
+
+       return r;
+}
+
 //?
 static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m)
 {
@@ -3055,12 +3103,14 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
        int i = 0, got_rtcp_mux = 0;
        const char *val;
 
-       if (engine->ice_in.chosen[0] && engine->ice_in.chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) {
+       if (engine->ice_in.is_chosen[0] && engine->ice_in.is_chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) {
                return;
        }
 
        engine->ice_in.chosen[0] = 0;
        engine->ice_in.chosen[1] = 0;
+       engine->ice_in.is_chosen[0] = 0;
+       engine->ice_in.is_chosen[1] = 0;
        engine->ice_in.cand_idx = 0;
 
        if (m) {
@@ -3074,6 +3124,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
                char *fields[15];
                int argc = 0, j = 0;
                int cid = 0;
+               int pass_acl = 0;
 
                if (zstr(attr->a_name)) {
                        continue;
@@ -3150,55 +3201,61 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, 
                                                          "Checking Candidate cid: %d proto: %s type: %s addr: %s:%s\n", cid+1, fields[2], fields[7], fields[4], fields[5]);
-
-
-                       engine->ice_in.cand_idx++;
+                       
+                       pass_acl = 0;
 
                        for (i = 0; i < engine->cand_acl_count; i++) {
-                               if (!engine->ice_in.chosen[cid] && !strchr(fields[4], ':') && switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
-                                       engine->ice_in.chosen[cid] = engine->ice_in.cand_idx;
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
-                                                                         "Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", 
-                                                                         type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
-                                                                         cid+1, fields[2], fields[7], fields[4], fields[5]);
-                               } else {
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
-                                                                         "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", 
-                                                                         type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
-                                                                         cid+1, fields[2], fields[7], fields[4], fields[5]);
-                               }
-
-                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
-                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].component_id = atoi(fields[1]);
-                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].transport = switch_core_session_strdup(smh->session, fields[2]);
-                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]);
-                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]);
-                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]);
-
-
-                               j = 6;
-
-                               while(j < argc && fields[j+1]) {
-                                       if (!strcasecmp(fields[j], "typ")) {
-                                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);                                                   
-                                       } else if (!strcasecmp(fields[j], "raddr")) {
-                                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
-                                       } else if (!strcasecmp(fields[j], "rport")) {
-                                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].rport = (switch_port_t)atoi(fields[j+1]);
-                                       } else if (!strcasecmp(fields[j], "generation")) {
-                                               engine->ice_in.cands[engine->ice_in.cand_idx][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
-                                       }
-                                       
-                                       j += 2;
-                               } 
-                               
+                               if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
+                                       pass_acl = 1;
+                                       break;
+                               }
+                       }
 
-                               if (engine->ice_in.chosen[cid]) {
-                                       engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++;
+                       if (!engine->ice_in.is_chosen[cid] && ip_possible(smh, fields[4]) && pass_acl) {
+                               engine->ice_in.chosen[cid] = engine->ice_in.cand_idx;
+                               engine->ice_in.is_chosen[cid] = 1;
+                               
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
+                                                                 "Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", 
+                                                                 type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
+                                                                 cid+1, fields[2], fields[7], fields[4], fields[5]);
+                               ip_choose_family(smh, fields[4]);
+                       } else {
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
+                                                                 "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", 
+                                                                 type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
+                                                                 cid+1, fields[2], fields[7], fields[4], fields[5]);
+                       }
+
+                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
+                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].component_id = atoi(fields[1]);
+                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].transport = switch_core_session_strdup(smh->session, fields[2]);
+                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]);
+                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]);
+                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]);
+
+                       j = 6;
+
+                       while(j < argc && fields[j+1]) {
+                               if (!strcasecmp(fields[j], "typ")) {
+                                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);                                                   
+                               } else if (!strcasecmp(fields[j], "raddr")) {
+                                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
+                               } else if (!strcasecmp(fields[j], "rport")) {
+                                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].rport = (switch_port_t)atoi(fields[j+1]);
+                               } else if (!strcasecmp(fields[j], "generation")) {
+                                       engine->ice_in.cands[engine->ice_in.cand_idx][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
                                }
+                                       
+                               j += 2;
+                       } 
                                
-                               break;
+
+                       if (engine->ice_in.is_chosen[cid]) {
+                               engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++;
                        }
+
+                       engine->ice_in.cand_idx++;
                }
                
        }
@@ -3206,18 +3263,23 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
        /* still no candidates, so start searching for some based on sane deduction */
 
        /* look for candidates on the same network */
-       if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
-               for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) {
-                       if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && 
-                               !engine->ice_in.cands[i][0].rport && switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) {
+       if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
+               for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) {
+                       if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && 
+                               !engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr) &&
+                               switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) {
                                engine->ice_in.chosen[0] = i;
+                               engine->ice_in.is_chosen[0] = 1;
                                engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
+                               ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr);
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
                                                                  "No %s RTP candidate found; defaulting to the first local one.\n", type2str(type));
                        }
-                       if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && 
-                               !engine->ice_in.cands[i][1].rport && switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) {
+                       if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && 
+                               !engine->ice_in.cands[i][1].rport && ip_possible(smh, engine->ice_in.cands[i][1].con_addr) &&
+                               switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) {
                                engine->ice_in.chosen[1] = i;
+                               engine->ice_in.is_chosen[1] = 1;
                                engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, 
                                                                  "No %s RTCP candidate found; defaulting to the first local one.\n", type2str(type));
@@ -3226,16 +3288,21 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
        }
 
        /* look for candidates with srflx */
-       if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
-               for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) {
-                       if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport) {
+       if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
+               for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) {
+                       if (!engine->ice_in.is_chosen[0] &&
+                               engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) {
                                engine->ice_in.chosen[0] = i;
+                               engine->ice_in.chosen[1] = 1;
                                engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
+                               ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr);
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
                                                                  "No %s RTP candidate found; defaulting to the first srflx one.\n", type2str(type));
                        }
-                       if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport) {
+                       if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport &&
+                               ip_possible(smh, engine->ice_in.cands[i][1].con_addr)) {
                                engine->ice_in.chosen[1] = i;
+                               engine->ice_in.is_chosen[1] = 1;
                                engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, 
                                                                  "No %s RTCP candidate found; defaulting to the first srflx one.\n", type2str(type));
@@ -3244,8 +3311,9 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
        }
 
        /* Got RTP but not RTCP, probably mux */
-       if (engine->ice_in.chosen[0] && !engine->ice_in.chosen[1] && got_rtcp_mux) {
+       if (engine->ice_in.is_chosen[0] && !engine->ice_in.is_chosen[1] && got_rtcp_mux) {
                engine->ice_in.chosen[1] = engine->ice_in.chosen[0];
+               engine->ice_in.is_chosen[1] = 1;
 
                memcpy(&engine->ice_in.cands[engine->ice_in.chosen[1]][1], &engine->ice_in.cands[engine->ice_in.chosen[0]][0], 
                           sizeof(engine->ice_in.cands[engine->ice_in.chosen[0]][0]));
@@ -3257,16 +3325,19 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
        }
 
        /* look for any candidates and hope for auto-adjust */
-       if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
-               for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) {
-                       if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1) {
+       if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
+               for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) {
+                       if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) {
                                engine->ice_in.chosen[0] = i;
+                               engine->ice_in.is_chosen[0] = 1;
                                engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
+                               ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr);
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
                                                                  "No %s RTP candidate found; defaulting to the first one.\n", type2str(type));
                        }
-                       if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2) {
+                       if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2) {
                                engine->ice_in.chosen[1] = i;
+                               engine->ice_in.is_chosen[1] = 1;
                                engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
                                                                  "No %s RTCP candidate found; defaulting to the first one.\n", type2str(type));
@@ -3274,6 +3345,13 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
                }
        }
 
+       if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
+               /* PUNT */
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n", 
+                                                 switch_channel_get_name(smh->session->channel));
+               return;
+       }
+
        for (i = 0; i < 2; i++) {
                if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
                        if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) {
@@ -5476,6 +5554,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_sessio
 SWITCH_DECLARE(switch_status_t) switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)
 {
        switch_status_t status = SWITCH_STATUS_SUCCESS;
+       switch_media_handle_t *smh;
+       
+       if (!(smh = session->media_handle)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (zstr(smh->mparams->rtpip)) {
+               
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no media ip\n", 
+                                                 switch_channel_get_name(smh->session->channel));
+               switch_channel_hangup(smh->session->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+
+               return SWITCH_STATUS_FALSE;
+       }
 
        if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) {
                if (video) {
@@ -6316,7 +6408,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
                                                          switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
                                                          switch_channel_get_name(session->channel),
-                                                         a_engine->cur_payload_map->remote_sdp_ip,
+                                                         a_engine->local_sdp_ip,
                                                          v_engine->local_sdp_port,
                                                          v_engine->cur_payload_map->remote_sdp_ip,
                                                          v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt,
index e53c66d079baa78c49d4edd2e06ae8c6e0854dcb..59b474045c2f5e52eae9915c093688c7d48c541a 100644 (file)
@@ -431,7 +431,8 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_netw
 
        for (node = list->node_head; node; node = node->next) {
                if (node->family == AF_INET) continue;
-               if (node->bits > bits && switch_testv6_subnet(ip, node->ip, node->mask)) {
+
+               if (node->bits >= bits && switch_testv6_subnet(ip, node->ip, node->mask)) {
                        if (node->ok) {
                                ok = SWITCH_TRUE;
                        } else {
@@ -457,7 +458,7 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_netwo
 
        for (node = list->node_head; node; node = node->next) {
                if (node->family == AF_INET6) continue; /* want AF_INET */
-               if (node->bits > bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4)) {
+               if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4)) {
                        if (node->ok) {
                                ok = SWITCH_TRUE;
                        } else {