]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
ice tweaks
authorAnthony Minessale <anthm@freeswitch.org>
Sat, 26 Jan 2013 23:53:15 +0000 (17:53 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 1 Apr 2013 02:27:22 +0000 (21:27 -0500)
src/include/switch_rtp.h
src/switch_core_media.c
src/switch_rtp.c

index aaa8be38f83eb16f3ffc395309d661518a4823c2..253677d84785324f2eb6f42ebfa7d031ed5b76af 100644 (file)
@@ -72,6 +72,40 @@ struct switch_rtp_crypto_key {
 };
 typedef struct switch_rtp_crypto_key switch_rtp_crypto_key_t;
 
+typedef enum {
+       IPR_RTP,
+       IPR_RTCP
+} ice_proto_t;
+
+
+
+typedef struct icand_s {
+       char *foundation;
+       int component_id;
+       char *transport;
+       uint32_t priority;
+       char *con_addr;
+       switch_port_t con_port;
+       char *cand_type;
+       char *raddr;
+       switch_port_t rport;
+       char *generation;
+       uint8_t ready;
+} icand_t;
+
+#define MAX_CAND 25
+typedef struct ice_s {
+
+       icand_t cands[2][MAX_CAND];
+       int cand_idx;
+       int chosen;
+       char *ufrag;
+       char *pwd;
+       char *options;
+
+} ice_t;
+
+
 
 
 SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session,
@@ -220,10 +254,8 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session);
   \return SWITCH_STATUS_SUCCESS
 */
 SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin, 
-                                                                                                               const char *password, const char *rpassword, switch_core_media_ice_type_t type, uint32_t priority);
-SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp_ice(switch_rtp_t *rtp_session, char *login, char *rlogin, 
-                                                                                                                        const char *password, const char *rpassword, 
-                                                                                                                        switch_core_media_ice_type_t type, uint32_t priority);
+                                                                                                               const char *password, const char *rpassword, ice_proto_t proto,
+                                                                                                               switch_core_media_ice_type_t type, ice_t *ice_params);
 
 /*! 
   \brief Activate sending RTCP Sender Reports (SR's)
index 50a5c2f7ad26ad43a5209d0894854f0613cc5706..1bd8c36b39971730349fc70f11ea0dc15660ad63 100644 (file)
@@ -97,30 +97,6 @@ typedef struct codec_params_s {
 
 } codec_params_t;
 
-typedef struct icand_s {
-       char *foundation;
-       int component_id;
-       char *transport;
-       uint32_t priority;
-       char *con_addr;
-       switch_port_t con_port;
-       char *cand_type;
-       char *raddr;
-       switch_port_t rport;
-       char *generation;
-       uint8_t ready;
-} icand_t;
-
-typedef struct ice_s {
-
-       icand_t cands[2];
-       
-       char *ufrag;
-       char *pwd;
-       char *options;
-
-} ice_t;
-
 typedef struct switch_rtp_engine_s {
        switch_secure_settings_t ssec;
        switch_media_type_t type;
@@ -1803,6 +1779,10 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
        int i = 0, got_rtcp_mux = 0;
        char tmp[80] = "";
 
+       engine->ice_in.chosen = 0;
+       engine->ice_in.cand_idx = 0;
+       
+
        for (attr = m->m_attributes; attr; attr = attr->a_next) {
                char *data;
                char *fields[15];
@@ -1842,7 +1822,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 
                        argc = switch_split(data, ' ', fields);
                        
-                       if (argc < 5) {
+                       if (argc < 5 || engine->ice_in.cand_idx >= MAX_CAND) {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Invalid data\n");
                                continue;
                        }
@@ -1858,75 +1838,81 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
                                                          "Checking Candidate cid: %d proto: %s type: %s addr: %s\n", cid+1, fields[2], fields[7], fields[4]);
 
 
-                       if (cid < 2 && !engine->ice_in.cands[cid].ready) {
-                       
-                               for (i = 0; i < engine->cand_acl_count; i++) {
-                                       if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
+                       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\n", 
-                                                                                 type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
-                                                                                 cid+1, fields[2], fields[7], fields[4]);
+                       for (i = 0; i < engine->cand_acl_count; i++) {
+                               if (!engine->ice_in.chosen && switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
+                                       engine->ice_in.chosen = 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\n", 
+                                                                         type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
+                                                                         cid+1, fields[2], fields[7], 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\n", 
+                                                                         type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
+                                                                         cid+1, fields[2], fields[7], fields[4]);
+                               }
 
-                                       
-                                               engine->ice_in.cands[cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
-                                               engine->ice_in.cands[cid].component_id = atoi(fields[1]);
-                                               engine->ice_in.cands[cid].transport = switch_core_session_strdup(smh->session, fields[2]);
-                                               engine->ice_in.cands[cid].priority = atol(fields[3]);
-                                               engine->ice_in.cands[cid].con_addr = switch_core_session_strdup(smh->session, fields[4]);
-                                               engine->ice_in.cands[cid].con_port = atoi(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 = atoi(fields[5]);
                                                
-                                               j = 6;
-
-                                               while(j < argc && fields[j+1]) {
-                                                       if (!strcasecmp(fields[j], "typ")) {
-                                                               engine->ice_in.cands[cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);                                                    
-                                                       } else if (!strcasecmp(fields[j], "raddr")) {
-                                                               engine->ice_in.cands[cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
-                                                       } else if (!strcasecmp(fields[j], "rport")) {
-                                                               engine->ice_in.cands[cid].rport = atoi(fields[j+1]);
-                                                       } else if (!strcasecmp(fields[j], "generation")) {
-                                                               engine->ice_in.cands[cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
-                                                       }
-                                               
-                                                       j += 2;
-                                               } 
+                               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 = 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]);
+                                       }
                                        
-                                               engine->ice_in.cands[cid].ready++;
+                                       j += 2;
+                               } 
 
-                                               break;
-                                       }
+                               if (engine->ice_in.chosen) {
+                                       engine->ice_in.cands[engine->ice_in.chosen][cid].ready++;
                                }
+                               
+                               break;
                        }
                }
+               
        }
 
        for (i = 0; i < 2; i++) {
-               if (engine->ice_in.cands[i].ready) {
+               if (engine->ice_in.cands[engine->ice_in.chosen][i].ready) {
                        if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) {
-                               engine->ice_in.cands[i].ready = 0;
+                               engine->ice_in.cands[engine->ice_in.chosen][i].ready = 0;
                        }
                }
        }
 
 
-       if (engine->ice_in.cands[0].con_addr && engine->ice_in.cands[0].con_port) {
-               engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[0].con_addr);
-               engine->codec_params.remote_sdp_port = (switch_port_t) engine->ice_in.cands[0].con_port;
+       if (engine->ice_in.cands[engine->ice_in.chosen][0].con_addr && engine->ice_in.cands[engine->ice_in.chosen][0].con_port) {
+               engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen][0].con_addr);
+               engine->codec_params.remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen][0].con_port;
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
                                                  "setting remote %s addr to %s:%d based on candidate\n", type2str(type),
-                                                 engine->ice_in.cands[0].con_addr, engine->ice_in.cands[0].con_port);
+                                                 engine->ice_in.cands[engine->ice_in.chosen][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen][0].con_port);
 
                switch_snprintf(tmp, sizeof(tmp), "%d", engine->codec_params.remote_sdp_port);
                switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->codec_params.remote_sdp_ip);
                switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);                                     
        }
 
-       if (engine->ice_in.cands[1].con_port) {
+       if (engine->ice_in.cands[engine->ice_in.chosen][1].con_port) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
                                                  "setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type),
-                                                 engine->ice_in.cands[1].con_addr, engine->ice_in.cands[1].con_port);
-               engine->remote_rtcp_port = engine->ice_in.cands[1].con_port;
+                                                 engine->ice_in.cands[engine->ice_in.chosen][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen][1].con_port);
+               engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen][1].con_port;
        }
 
 
@@ -3327,31 +3313,31 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co
                engine->ice_out.pwd = switch_core_session_strdup(session, tmp); 
        }
 
-       if (!engine->ice_out.cands[0].foundation) {
+       if (!engine->ice_out.cands[0][0].foundation) {
                switch_stun_random_string(tmp, 10, "0123456789");
                tmp[10] = '\0';
-               engine->ice_out.cands[0].foundation = switch_core_session_strdup(session, tmp);
+               engine->ice_out.cands[0][0].foundation = switch_core_session_strdup(session, tmp);
        }
 
-       engine->ice_out.cands[0].transport = "udp";
+       engine->ice_out.cands[0][0].transport = "udp";
 
-       if (!engine->ice_out.cands[0].component_id) {
-               engine->ice_out.cands[0].component_id = 1;
-               engine->ice_out.cands[0].priority = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - engine->ice_out.cands[0].component_id);
+       if (!engine->ice_out.cands[0][0].component_id) {
+               engine->ice_out.cands[0][0].component_id = 1;
+               engine->ice_out.cands[0][0].priority = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - engine->ice_out.cands[0][0].component_id);
        }
 
        if (!zstr(ip)) {
-               engine->ice_out.cands[0].con_addr = switch_core_session_strdup(session, ip);
+               engine->ice_out.cands[0][0].con_addr = switch_core_session_strdup(session, ip);
        }
 
        if (port) {
-               engine->ice_out.cands[0].con_port = port;
+               engine->ice_out.cands[0][0].con_port = port;
        }
 
-       engine->ice_out.cands[0].generation = "0";
+       engine->ice_out.cands[0][0].generation = "0";
        //add rport stuff later
        
-       engine->ice_out.cands[0].ready = 1;
+       engine->ice_out.cands[0][0].ready = 1;
 
 
 }
@@ -3666,7 +3652,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                }
 
 
-               if (a_engine->ice_in.cands[0].ready) {
+               if (a_engine->ice_in.cands[a_engine->ice_in.chosen][0].ready) {
                        
                        gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
 
@@ -3677,14 +3663,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                                                        a_engine->ice_out.ufrag,
                                                                        a_engine->ice_out.pwd,
                                                                        a_engine->ice_in.pwd,
-
+                                                                       IPR_RTP,
 #ifdef GOOGLE_ICE
                                                                        ICE_GOOGLE_JINGLE,
-                                                                       0
+                                                                       NULL,
 #else
                                                                        switch_channel_direction(session->channel) == 
                                                                        SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
-                                                                       a_engine->ice_in.cands[0].priority
+                                                                       &a_engine->ice_in
 #endif
                                                                        );
 
@@ -3717,23 +3703,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                        }
 
 
-                       if (a_engine->ice_in.cands[1].ready) {
+                       if (a_engine->ice_in.cands[a_engine->ice_in.chosen][1].ready) {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
                                
-                               switch_rtp_activate_rtcp_ice(a_engine->rtp_session, 
-                                                                                        a_engine->ice_in.ufrag,
-                                                                                        a_engine->ice_out.ufrag,
-                                                                                        a_engine->ice_out.pwd,
-                                                                                        a_engine->ice_in.pwd,
+                               switch_rtp_activate_ice(a_engine->rtp_session, 
+                                                                               a_engine->ice_in.ufrag,
+                                                                               a_engine->ice_out.ufrag,
+                                                                               a_engine->ice_out.pwd,
+                                                                               a_engine->ice_in.pwd,
+                                                                               IPR_RTCP,
 #ifdef GOOGLE_ICE
-                                                                                        ICE_GOOGLE_JINGLE,
-                                                                                        0
+                                                                               ICE_GOOGLE_JINGLE,
+                                                                               NULL
 #else
-                                                                                        switch_channel_direction(session->channel) == 
-                                                                                        SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
-                                                                                        a_engine->ice_in.cands[1].priority
+                                                                               switch_channel_direction(session->channel) == 
+                                                                               SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
+                                                                               &a_engine->ice_in
 #endif
-                                                                                        );
+                                                                               );
                        }
 
                }
@@ -4047,7 +4034,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                }
 
                                
-                               if (v_engine->ice_in.cands[0].ready) {
+                               if (v_engine->ice_in.cands[v_engine->ice_in.chosen][0].ready) {
                                        
                                        gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
                                        
@@ -4058,13 +4045,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                                                                        v_engine->ice_out.ufrag,
                                                                                        v_engine->ice_out.pwd,
                                                                                        v_engine->ice_in.pwd,
-
+                                                                                       IPR_RTP,
 #ifdef GOOGLE_ICE
                                                                                        ICE_GOOGLE_JINGLE,
-                                                                                       0
+                                                                                       NULL
 #else
                                                                                        ICE_VANILLA | ICE_CONTROLLED,
-                                                                                       v_engine->ice_in.cands[0].priority
+                                                                                       &v_engine->ice_in
 #endif
                                                                                        );
                                        
@@ -4092,23 +4079,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                        }
                                        
 
-                                       if (v_engine->ice_in.cands[1].ready) {
+                                       if (v_engine->ice_in.cands[v_engine->ice_in.chosen][1].ready) {
                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
-                                               switch_rtp_activate_rtcp_ice(v_engine->rtp_session, 
-                                                                                                        v_engine->ice_in.ufrag,
-                                                                                                        v_engine->ice_out.ufrag,
-                                                                                                        v_engine->ice_out.pwd,
-                                                                                                        v_engine->ice_in.pwd,
+                                               switch_rtp_activate_ice(v_engine->rtp_session, 
+                                                                                               v_engine->ice_in.ufrag,
+                                                                                               v_engine->ice_out.ufrag,
+                                                                                               v_engine->ice_out.pwd,
+                                                                                               v_engine->ice_in.pwd,
+                                                                                               IPR_RTCP,
 #ifdef GOOGLE_ICE
-                                                                                                        ICE_GOOGLE_JINGLE,
-                                                                                                        0
+                                                                                               ICE_GOOGLE_JINGLE,
+                                                                                               NULL
 #else
-                                                                                                        switch_channel_direction(session->channel) == 
-                                                                                                        SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
-                                                                                                        
-                                                                                                        v_engine->ice_in.cands[1].priority
+                                                                                               switch_channel_direction(session->channel) == 
+                                                                                               SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
+                                                                                               
+                                                                                               &v_engine->ice_in
 #endif
-                                                                                                        );
+                                                                                               );
                                        }
                                        
                                
@@ -4319,7 +4307,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
 
        //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", a_engine->ssrc);
 
-       if (a_engine->ice_out.cands[0].ready) {
+       if (a_engine->ice_out.cands[0][0].ready) {
                char tmp1[11] = "";
                char tmp2[11] = "";
                uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1);
@@ -4346,34 +4334,34 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
                switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd);
 
                switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\n", 
-                                               tmp1, ice_out->cands[0].transport, c1,
-                                               ice_out->cands[0].con_addr, ice_out->cands[0].con_port
+                                               tmp1, ice_out->cands[0][0].transport, c1,
+                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
                                                );
 
-               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0].con_addr) && 
-                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0].con_addr)
-                       && a_engine->codec_params.local_sdp_port != ice_out->cands[0].con_port) {
+               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
+                       && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {
 
                        switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-                                                       tmp2, ice_out->cands[0].transport, c3,
-                                                       ice_out->cands[0].con_addr, ice_out->cands[0].con_port,
+                                                       tmp2, ice_out->cands[0][0].transport, c3,
+                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
                                                        a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port
                                                        );
                }
 
 
                switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
-                                               tmp1, ice_out->cands[0].transport, c2,
-                                                       ice_out->cands[0].con_addr, ice_out->cands[0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
+                                               tmp1, ice_out->cands[0][0].transport, c2,
+                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                );
 
-               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[1].con_addr) && 
-                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[1].con_addr)
-                       && a_engine->codec_params.local_sdp_port != ice_out->cands[1].con_port) {
+               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
+                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
+                       && a_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
                        
                        switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-                                                       tmp2, ice_out->cands[0].transport, c4,
-                                                       ice_out->cands[0].con_addr, ice_out->cands[0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
+                                                       tmp2, ice_out->cands[0][0].transport, c4,
+                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
                                                        a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                        );
                }
@@ -4559,7 +4547,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
        a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
        v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
 
-       if (a_engine->ice_out.cands[0].ready) {
+       if (a_engine->ice_out.cands[0][0].ready) {
                verbose_sdp = 1;
        }
 
@@ -4780,7 +4768,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
                //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", a_engine->ssrc);
 
-               if (a_engine->ice_out.cands[0].ready) {
+               if (a_engine->ice_out.cands[0][0].ready) {
                        char tmp1[11] = "";
                        char tmp2[11] = "";
                        uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1);
@@ -4805,17 +4793,17 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd);
 
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\n", 
-                                                       tmp1, ice_out->cands[0].transport, c1,
-                                                       ice_out->cands[0].con_addr, ice_out->cands[0].con_port
+                                                       tmp1, ice_out->cands[0][0].transport, c1,
+                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
                                                        );
 
-                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0].con_addr) && 
-                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0].con_addr)
-                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0].con_port) {
+                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
+                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {
 
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-                                                               tmp2, ice_out->cands[0].transport, c3,
-                                                               ice_out->cands[0].con_addr, ice_out->cands[0].con_port,
+                                                               tmp2, ice_out->cands[0][0].transport, c3,
+                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
                                                                a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port
                                                                );
                        }
@@ -4823,19 +4811,19 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
 
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
-                                                       tmp1, ice_out->cands[0].transport, c2,
-                                                       ice_out->cands[0].con_addr, ice_out->cands[0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
+                                                       tmp1, ice_out->cands[0][0].transport, c2,
+                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                        );
 
 
 
-                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0].con_addr) && 
-                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0].con_addr)
-                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0].con_port) {                       
+                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
+                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {                    
                                
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-                                                               tmp2, ice_out->cands[0].transport, c4,
-                                                               ice_out->cands[0].con_addr, ice_out->cands[0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
+                                                               tmp2, ice_out->cands[0][0].transport, c4,
+                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
                                                                a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                                );
                        }
@@ -5074,7 +5062,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
                        //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", v_engine->ssrc);
 
-                       if (v_engine->ice_out.cands[0].ready) {
+                       if (v_engine->ice_out.cands[0][0].ready) {
                                char tmp1[11] = "";
                                char tmp2[11] = "";
                                uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1);
@@ -5098,35 +5086,35 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd);
 
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\n", 
-                                                               tmp1, ice_out->cands[0].transport, c1,
-                                                               ice_out->cands[0].con_addr, ice_out->cands[0].con_port
+                                                               tmp1, ice_out->cands[0][0].transport, c1,
+                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
                                                                );
 
-                               if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0].con_addr) && 
-                                       strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[0].con_addr)
-                                       && v_engine->codec_params.local_sdp_port != ice_out->cands[0].con_port) {
+                               if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                                       strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
+                                       && v_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {
 
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-                                                                       tmp2, ice_out->cands[0].transport, c3,
-                                                                       ice_out->cands[0].con_addr, ice_out->cands[0].con_port,
+                                                                       tmp2, ice_out->cands[0][0].transport, c3,
+                                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
                                                                        v_engine->codec_params.local_sdp_ip, v_engine->codec_params.local_sdp_port
                                                                        );
                                }
 
 
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
-                                                               tmp1, ice_out->cands[0].transport, c2,
-                                                               ice_out->cands[0].con_addr, ice_out->cands[0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
+                                                               tmp1, ice_out->cands[0][0].transport, c2,
+                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
                                                                );
 
 
-                               if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[1].con_addr) && 
-                                       strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[1].con_addr)
-                                       && v_engine->codec_params.local_sdp_port != ice_out->cands[1].con_port) {
+                               if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
+                                       strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
+                                       && v_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
                                        
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\n", 
-                                                                       tmp2, ice_out->cands[0].transport, c4,
-                                                                       ice_out->cands[0].con_addr, ice_out->cands[0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
+                                                                       tmp2, ice_out->cands[0][0].transport, c4,
+                                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
                                                                        v_engine->codec_params.local_sdp_ip, v_engine->codec_params.local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
                                                                        );
                                }
index 919b396e365b20d2b67ccb05cf3af79e5034374a..0eff91c91e73a194de25a989ae5ca5f3b80c9a50 100644 (file)
@@ -55,7 +55,6 @@
 #define WRITE_INC(rtp_session)  switch_mutex_lock(rtp_session->write_mutex); rtp_session->writing++
 #define WRITE_DEC(rtp_session) switch_mutex_unlock(rtp_session->write_mutex); rtp_session->writing--
 
-
 #define RTP_DEFAULT_STUNCOUNT 25;
 #define rtp_header_len 12
 #define RTP_START_PORT 16384
@@ -170,7 +169,8 @@ typedef struct {
        uint32_t funny_stun;
        uint32_t default_stuncount;
        switch_core_media_ice_type_t type;
-       uint32_t priority;
+       ice_t *ice_params;
+       ice_proto_t proto;
        uint8_t sending;
        uint8_t ready;
        uint8_t rready;
@@ -675,7 +675,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
        if ((ice->type & ICE_VANILLA)) {
                char sw[128] = "";
 
-               switch_stun_packet_attribute_add_priority(packet, ice->priority);
+               switch_stun_packet_attribute_add_priority(packet, ice->ice_params->cands[ice->ice_params->chosen][ice->proto].priority);
 
                switch_snprintf(sw, sizeof(sw), "FreeSWITCH (%s)", SWITCH_VERSION_REVISION_HUMAN);
                switch_stun_packet_attribute_add_software(packet, sw, strlen(sw));
@@ -758,8 +758,6 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
        if (ice->sending && (packet->header.type == SWITCH_STUN_BINDING_RESPONSE || packet->header.type == SWITCH_STUN_BINDING_ERROR_RESPONSE)) {
                ice->sending = 0;
        }
-
-
 #endif 
 
        end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf));
@@ -786,7 +784,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
                case SWITCH_STUN_ATTR_PRIORITY:
                        {
                                pri = (uint32_t *) attr->value;
-                               ok = *pri == ice->priority;
+                               ok = *pri == ice->ice_params->cands[ice->ice_params->chosen][ice->proto].priority;
                        }
                        break;
                }
@@ -801,10 +799,76 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
                ok = !strcmp(ice->user_ice, username);
        }
 
+       if (ice->type == ICE_VANILLA) {
+               if (!ok && ice == &rtp_session->ice && pri && 
+                       *pri == rtp_session->rtcp_ice.ice_params->cands[rtp_session->rtcp_ice.ice_params->chosen][1].priority) {
+                       ice = &rtp_session->rtcp_ice;
+                       ok = 1;
+               }
+
+
+               if (!ok) {
+                       uint32_t elapsed = (unsigned int) ((switch_micro_time_now() - rtp_session->last_stun) / 1000);
+                       switch_rtp_ice_t *icep[2] = { &rtp_session->ice, &rtp_session->rtcp_ice };
+
+                       if (elapsed > 20000 && pri) {
+                               int i, j;
+                               uint32_t old;
+                               const char *tx_host;
+                               const char *old_host, *err = NULL;
+                               char bufa[30], bufb[30];
+                               char adj_port[6];
+                               switch_channel_t *channel = NULL;
+                               
+                               if (rtp_session->session) {
+                                       channel = switch_core_session_get_channel(rtp_session->session);
+                               }
+
+                               //ice->ice_params->cands[ice->ice_params->chosen][ice->proto].priority;
+                               for (j = 0; j < 2; j++) {
+                                       for (i = 0; i < icep[j]->ice_params->cand_idx; i++) {
+                                               if (icep[j]->ice_params->cands[i][icep[j]->proto].priority == *pri) {
+                                                       if (j == IPR_RTP) {
+                                                               icep[j]->ice_params->chosen = i;
+                                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Change candidate index to %d\n", i);
+                                                       }
+
+                                                       ice = icep[j];
+                                                       ok = 1;
+
+                                                       if (j != IPR_RTP) {
+                                                               break;
+                                                       }
+
+                                                       old = rtp_session->remote_port;
+                                                       
+                                                       tx_host = switch_get_addr(bufa, sizeof(bufa), rtp_session->from_addr);
+                                                       old_host = switch_get_addr(bufb, sizeof(bufb), rtp_session->remote_addr);
+                                                       
+                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO,
+                                                                                         "ICE Auto Changing port from %s:%u to %s:%u\n", old_host, old, tx_host,
+                                                                                         switch_sockaddr_get_port(rtp_session->from_addr));
+                                                       
+                                                       if (channel) {
+                                                               switch_channel_set_variable(channel, "remote_media_ip_reported", switch_channel_get_variable(channel, "remote_media_ip"));
+                                                               switch_channel_set_variable(channel, "remote_media_ip", tx_host);
+                                                               switch_snprintf(adj_port, sizeof(adj_port), "%u", switch_sockaddr_get_port(rtp_session->from_addr));
+                                                               switch_channel_set_variable(channel, "remote_media_port_reported", switch_channel_get_variable(channel, "remote_media_port"));
+                                                               switch_channel_set_variable(channel, "remote_media_port", adj_port);
+                                                               switch_channel_set_variable(channel, "rtp_auto_adjust", "true");
+                                                       }
+                                                       rtp_session->auto_adj_used = 1;
+                                                       
+                                                       switch_rtp_set_remote_address(rtp_session, tx_host, switch_sockaddr_get_port(rtp_session->from_addr), 0, SWITCH_FALSE, &err);
+                                                       switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
+                                                       
+                                               }
+                                       }
+                               }
+                       }
+               }
+
 
-       if (!ok && ice->type == ICE_VANILLA && ice == &rtp_session->ice && pri && *pri == rtp_session->rtcp_ice.priority) {
-               ice = &rtp_session->rtcp_ice;
-               ok = 1;
        }
 
        if (ok) {
@@ -2497,43 +2561,52 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_sessi
 }
 
 SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin, 
-                                                                                                               const char *password, const char *rpassword, switch_core_media_ice_type_t type, uint32_t priority)
+                                                                                                               const char *password, const char *rpassword, ice_proto_t proto, 
+                                                                                                               switch_core_media_ice_type_t type, ice_t *ice_params)
 {
        char ice_user[80];
        char user_ice[80];
-       
+       switch_rtp_ice_t *ice;
 
+       if (proto == IPR_RTP) {
+               ice = &rtp_session->ice;
+       } else {
+               ice = &rtp_session->rtcp_ice;
+       }
+
+       ice->proto = proto;
+       
        if ((type & ICE_VANILLA)) {
                switch_snprintf(ice_user, sizeof(ice_user), "%s:%s", login, rlogin);
                switch_snprintf(user_ice, sizeof(user_ice), "%s:%s", rlogin, login);
        } else {
                switch_snprintf(ice_user, sizeof(ice_user), "%s%s", login, rlogin);
                switch_snprintf(user_ice, sizeof(user_ice), "%s%s", rlogin, login);
-               rtp_session->ice.ready = rtp_session->ice.rready = 1;
+               ice->ready = ice->rready = 1;
        }
 
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_NOTICE, "Activating %s ICE: %s\n", rtp_type(rtp_session), ice_user);
 
 
-       rtp_session->ice.ice_user = switch_core_strdup(rtp_session->pool, ice_user);
-       rtp_session->ice.user_ice = switch_core_strdup(rtp_session->pool, user_ice);
-       rtp_session->ice.type = type;
-       rtp_session->ice.priority = priority;
-       rtp_session->ice.pass = "";
-       rtp_session->ice.rpass = "";
+       ice->ice_user = switch_core_strdup(rtp_session->pool, ice_user);
+       ice->user_ice = switch_core_strdup(rtp_session->pool, user_ice);
+       ice->type = type;
+       ice->ice_params = ice_params;
+       ice->pass = "";
+       ice->rpass = "";
 
        if (password) {
-               rtp_session->ice.pass = switch_core_strdup(rtp_session->pool, password);
+               ice->pass = switch_core_strdup(rtp_session->pool, password);
        }
 
        if (rpassword) {
-               rtp_session->ice.rpass = switch_core_strdup(rtp_session->pool, rpassword);
+               ice->rpass = switch_core_strdup(rtp_session->pool, rpassword);
        }
        
-       rtp_session->ice.default_stuncount = RTP_DEFAULT_STUNCOUNT;
-       rtp_session->ice.stuncount = 0;
+       ice->default_stuncount = RTP_DEFAULT_STUNCOUNT;
+       ice->stuncount = 0;
 
-       if (rtp_session->ice.ice_user) {
+       if (ice->ice_user) {
                if (ice_out(rtp_session, &rtp_session->ice) != SWITCH_STATUS_SUCCESS) {
                        return SWITCH_STATUS_FALSE;
                }
@@ -2543,49 +2616,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
 }
 
 
-SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp_ice(switch_rtp_t *rtp_session, char *login, char *rlogin, 
-                                                                                                                        const char *password, const char *rpassword, switch_core_media_ice_type_t type, uint32_t priority)
-{
-       char ice_user[80];
-       char user_ice[80];
-
-       if ((type & ICE_VANILLA)) {
-               switch_snprintf(ice_user, sizeof(ice_user), "%s:%s", login, rlogin);
-               switch_snprintf(user_ice, sizeof(user_ice), "%s:%s", rlogin, login);
-       } else {
-               switch_snprintf(ice_user, sizeof(ice_user), "%s%s", login, rlogin);
-               switch_snprintf(user_ice, sizeof(user_ice), "%s%s", rlogin, login);
-               rtp_session->rtcp_ice.ready = rtp_session->rtcp_ice.rready = 1;
-       }
-
-       rtp_session->rtcp_ice.ice_user = switch_core_strdup(rtp_session->pool, ice_user);
-       rtp_session->rtcp_ice.user_ice = switch_core_strdup(rtp_session->pool, user_ice);
-       rtp_session->rtcp_ice.type = type;
-       rtp_session->rtcp_ice.priority = priority;
-       rtp_session->rtcp_ice.pass = "";
-       rtp_session->rtcp_ice.rpass = "";
-
-       if (password) {
-               rtp_session->rtcp_ice.pass = switch_core_strdup(rtp_session->pool, password);
-       }
-
-       if (rpassword) {
-               rtp_session->rtcp_ice.rpass = switch_core_strdup(rtp_session->pool, rpassword);
-       }
-
-       rtp_session->rtcp_ice.default_stuncount = RTP_DEFAULT_STUNCOUNT;
-       rtp_session->rtcp_ice.stuncount = 0;
-       
-       if (rtp_session->rtcp_ice.ice_user) {
-               if (ice_out(rtp_session, &rtp_session->rtcp_ice) != SWITCH_STATUS_SUCCESS) {
-                       return SWITCH_STATUS_FALSE;
-               }
-       }
-
-       return SWITCH_STATUS_SUCCESS;
-}
-
-
 SWITCH_DECLARE(void) switch_rtp_flush(switch_rtp_t *rtp_session)
 {
        if (!switch_rtp_ready(rtp_session)) {