From 21408d4534b011674e30821eeb7b825ed2a4b038 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 26 Jan 2013 17:53:15 -0600 Subject: [PATCH] ice tweaks --- src/include/switch_rtp.h | 40 ++++- src/switch_core_media.c | 308 +++++++++++++++++++-------------------- src/switch_rtp.c | 162 +++++++++++--------- 3 files changed, 280 insertions(+), 230 deletions(-) diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index aaa8be38f8..253677d847 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -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) diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 50a5c2f7ad..1bd8c36b39 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -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]); - - - 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]); - - 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; - } - - engine->ice_in.cands[cid].ready++; - - break; - } + 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[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[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]); + } + + j += 2; + } + + 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) ); } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 919b396e36..0eff91c91e 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -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)) {