diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 19acf64324..76a47f5708 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -220,9 +220,10 @@ 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, switch_core_media_ice_type_t type, uint32_t priority); + 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, switch_core_media_ice_type_t type, uint32_t priority); + const char *password, const char *rpassword, + switch_core_media_ice_type_t type, uint32_t priority); /*! \brief Activate sending RTCP Sender Reports (SR's) diff --git a/src/include/switch_stun.h b/src/include/switch_stun.h index b48d376d6a..70547cfe4f 100644 --- a/src/include/switch_stun.h +++ b/src/include/switch_stun.h @@ -262,6 +262,7 @@ SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip, \param end pointer to the end of the buffer \return true or false depending on if there are any more attributes */ + #define switch_stun_packet_next_attribute(attribute, end) (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length(attribute))) && ((void *)attribute < end) && attribute->type && ((void *)(attribute + switch_stun_attribute_padded_length(attribute)) < end)) #define switch_stun_packet_next_attribute_hbo(attribute, end) (attribute && (attribute = (switch_stun_packet_attribute_t *) (attribute->value + switch_stun_attribute_padded_length_hbo(attribute))) && ((void *)attribute < end) && attribute->type && ((void *)(attribute + switch_stun_attribute_padded_length_hbo(attribute)) < end)) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index e4a2d6a5ee..b93e1ef6e3 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -817,13 +817,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); } - + if (tech_pvt->nh) { if (tech_pvt->mparams.local_sdp_str) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local SDP %s:\n%s\n", switch_channel_get_name(channel), tech_pvt->mparams.local_sdp_str); } } + } if (sofia_test_flag(tech_pvt, TFLAG_NAT) || diff --git a/src/switch_core.c b/src/switch_core.c index 64ad73c685..b98657c49e 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1228,6 +1228,7 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) 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_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); tmp_name = "nat.auto"; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 0940b2ae44..b6b4f6ec06 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -90,10 +90,7 @@ typedef struct codec_params_s { } codec_params_t; -typedef struct ice_s { - char *cand_acl[SWITCH_MAX_CAND_ACL]; - int cand_acl_count; - +typedef struct icand_s { char *foundation; int component_id; char *transport; @@ -104,12 +101,18 @@ typedef struct ice_s { 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; - uint8_t ready; + } ice_t; @@ -145,6 +148,9 @@ typedef struct switch_rtp_engine_s { codec_params_t codec_params; uint32_t timestamp_send; + char *cand_acl[SWITCH_MAX_CAND_ACL]; + int cand_acl_count; + ice_t ice_in; ice_t ice_out; @@ -1720,8 +1726,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_add_ice_acl(switch_core_sessio engine = &smh->engines[type]; - if (engine->ice_in.cand_acl_count < SWITCH_MAX_CAND_ACL) { - engine->ice_in.cand_acl[engine->ice_in.cand_acl_count++] = switch_core_session_strdup(session, acl_name); + if (engine->cand_acl_count < SWITCH_MAX_CAND_ACL) { + engine->cand_acl[engine->cand_acl_count++] = switch_core_session_strdup(session, acl_name); return SWITCH_STATUS_SUCCESS; } @@ -1759,18 +1765,18 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ { switch_rtp_engine_t *engine = &smh->engines[type]; sdp_attribute_t *attr; + int i = 0; for (attr = m->m_attributes; attr; attr = attr->a_next) { char *data; char *fields[15]; - int argc = 0, i = 0, j = 0; + int argc = 0, j = 0; + int cid = 0; if (zstr(attr->a_name)) { continue; } - printf("ICE [%s] [%s]\n", attr->a_name, attr->a_value); - if (!strcasecmp(attr->a_name, "ice-ufrag")) { engine->ice_in.ufrag = switch_core_session_strdup(smh->session, attr->a_value); } else if (!strcasecmp(attr->a_name, "ice-pwd")) { @@ -1779,7 +1785,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ engine->ice_in.options = switch_core_session_strdup(smh->session, attr->a_value); } else if (!strcasecmp(attr->a_name, "candidate")) { - if (!engine->ice_in.cand_acl_count) { + if (!engine->cand_acl_count) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "NO candidate ACL defined, skipping candidate check.\n"); return; } @@ -1798,62 +1804,63 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ continue; } - - printf("BAH %d [%s]\n", argc, data); + cid = atoi(fields[1]) - 1; - //del me for (i = 0; i < argc; i++) { - printf("CAND %d [%s]\n", i, fields[i]); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG1, "CAND %d [%s]\n", i, fields[i]); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, - "Checking Candidate proto: %s type: %s addr: %s\n", fields[2], fields[7], fields[4]); + "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->ice_in.cand_acl_count; i++) { - if (switch_check_network_list_ip(fields[4], engine->ice_in.cand_acl[i])) { + for (i = 0; i < engine->cand_acl_count; i++) { + if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "Choose Candidate proto: %s type: %s addr: %s\n", fields[2], fields[7], fields[4]); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, + "Choose Candidate cid: %d proto: %s type: %s addr: %s\n", cid+1, fields[2], fields[7], fields[4]); - engine->ice_in.foundation = switch_core_session_strdup(smh->session, fields[0]); - engine->ice_in.component_id = atoi(fields[1]); - engine->ice_in.transport = switch_core_session_strdup(smh->session, fields[2]); - engine->ice_in.priority = atoi(fields[3]); - engine->ice_in.con_addr = switch_core_session_strdup(smh->session, fields[4]); - engine->ice_in.con_port = atoi(fields[5]); + 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; + j = 6; - while(j < argc && fields[j+1]) { - if (!strcasecmp(fields[j], "typ")) { - engine->ice_in.cand_type = switch_core_session_strdup(smh->session, fields[j+1]); - } else if (!strcasecmp(fields[j], "raddr")) { - engine->ice_in.raddr = switch_core_session_strdup(smh->session, fields[j+1]); - } else if (!strcasecmp(fields[j], "rport")) { - engine->ice_in.rport = atoi(fields[j+1]); - } else if (!strcasecmp(fields[j], "generation")) { - engine->ice_in.generation = switch_core_session_strdup(smh->session, fields[j+1]); - } + 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 += 2; + } - engine->ice_in.ready++; + engine->ice_in.cands[cid].ready++; - break; + break; + } } } } - } - if (engine->ice_in.ready) { - if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) { - engine->ice_in.ready = 0; + for (i = 0; i < 2; i++) { + if (engine->ice_in.cands[i].ready) { + if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) { + engine->ice_in.cands[i].ready = 0; + } } } @@ -3194,29 +3201,29 @@ 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.foundation) { + if (!engine->ice_out.cands[0].foundation) { tmp[10] = '\0'; switch_stun_random_string(tmp, 10, "0123456789"); - engine->ice_out.foundation = switch_core_session_strdup(session, tmp); + engine->ice_out.cands[0].foundation = switch_core_session_strdup(session, tmp); } - engine->ice_out.transport = "udp"; + engine->ice_out.cands[0].transport = "udp"; - if (!engine->ice_out.component_id) { - engine->ice_out.component_id = 1; - engine->ice_out.priority = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - engine->ice_out.component_id); + 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 (ip) { - engine->ice_out.con_addr = switch_core_session_strdup(session, ip); + engine->ice_out.cands[0].con_addr = switch_core_session_strdup(session, ip); } if (port) { - engine->ice_out.con_port = port; + engine->ice_out.cands[0].con_port = port; } - engine->ice_out.generation = "0"; + engine->ice_out.cands[0].generation = "0"; //add rport stuff later - engine->ice_out.ready = 1; + engine->ice_out.cands[0].ready = 1; } @@ -3686,44 +3693,45 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc); - printf("xxxxxxWTF %d %d\n", a_engine->ice_out.ready , a_engine->ice_in.ready); - - if (a_engine->ice_in.ready) { + if (a_engine->ice_in.cands[0].ready) { gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, "", 0); 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, + #ifdef GOOGLE_ICE ICE_GOOGLE_JINGLE, 0 #else ICE_VANILLA | ICE_CONTROLLED, - a_engine->ice_out.priority + a_engine->ice_in.cands[0].priority #endif ); + if (a_engine->ice_in.cands[1].ready) { - - switch_rtp_activate_rtcp_ice(a_engine->rtp_session, - a_engine->ice_in.ufrag, - a_engine->ice_out.ufrag, - a_engine->ice_in.pwd, + 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, #ifdef GOOGLE_ICE - ICE_GOOGLE_JINGLE, - 0 + ICE_GOOGLE_JINGLE, + 0 #else ICE_VANILLA | ICE_CONTROLLED, - a_engine->ice_out.priority -1 + a_engine->ice_in.cands[1].priority #endif - ); + ); + } + } + - } - - video: @@ -4269,6 +4277,11 @@ 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) { + verbose_sdp = 1; + } + + fmtp_out = a_engine->codec_params.fmtp_out; username = smh->mparams->sdp_username; @@ -4413,58 +4426,6 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n"); - // if (smh->mparams->rtcp_audio_interval_msec) { - // switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", port + 1, family, ip); - //} - - //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", a_engine->ssrc); - - if (a_engine->ice_out.ready) { - char tmp1[11] = ""; - char tmp2[11] = ""; - uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1); - uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2); - uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1); - uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2); - - - - tmp1[10] = '\0'; - tmp2[10] = '\0'; - switch_stun_random_string(tmp1, 10, "0123456789"); - switch_stun_random_string(tmp2, 10, "0123456789"); - - ice_out = &a_engine->ice_out; - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\n", - tmp1, ice_out->transport, c1, - ice_out->con_addr, ice_out->con_port - ); - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx generation 0\n", - tmp2, ice_out->transport, c3, - ice_out->con_addr, ice_out->con_port - ); - -#if 1 - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", - tmp1, ice_out->transport, c2, - ice_out->con_addr, ice_out->con_port + 1 - ); - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\n", - tmp2, ice_out->transport, c4, - ice_out->con_addr, ice_out->con_port + 1 - ); -#endif - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\n", ice_out->ufrag); - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd); -#ifdef GOOGLE_ICE - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\n"); -#endif - } - rate = a_engine->codec_params.rm_rate; switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", a_engine->codec_params.agreed_pt, a_engine->codec_params.rm_encoding, rate); @@ -4511,6 +4472,64 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\n", sr); } + + + + // if (smh->mparams->rtcp_audio_interval_msec) { + // switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", port + 1, family, ip); + //} + + //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", a_engine->ssrc); + + if (a_engine->ice_out.cands[0].ready) { + char tmp1[11] = ""; + char tmp2[11] = ""; + uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1); + uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2); + uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1); + uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2); + + tmp1[10] = '\0'; + tmp2[10] = '\0'; + switch_stun_random_string(tmp1, 10, "0123456789"); + switch_stun_random_string(tmp2, 10, "0123456789"); + + ice_out = &a_engine->ice_out; + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\n", ice_out->ufrag); + 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 + ); + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx generation 0\n", + tmp2, ice_out->cands[0].transport, c3, + ice_out->cands[0].con_addr, ice_out->cands[0].con_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 + 1 + ); + + 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 + 1 + ); + + + +#ifdef GOOGLE_ICE + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\n"); +#endif + } + + + + if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key); //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n"); @@ -4640,6 +4659,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n"); + + // if (smh->mparams->rtcp_audio_interval_msec) { // switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", v_port + 1, family, ip); //} @@ -4648,18 +4669,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess const char *of; - if (v_engine->ice_out.ready) { + if (v_engine->ice_out.cands[0].ready) { ice_out = &v_engine->ice_out; - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s %d %s %u %s %d typ host generation 0\n", - ice_out->foundation, ice_out->component_id, ice_out->transport, ice_out->priority, - ice_out->con_addr, ice_out->con_port - ); - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\n", ice_out->ufrag); - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd); -#ifdef GOOGLE_ICE - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\n"); -#endif + // VID CANDS HERE } @@ -4744,8 +4757,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n"); } - - + if (local_sdp_video_zrtp_hash) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n", local_sdp_video_zrtp_hash); switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n", local_sdp_video_zrtp_hash); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index a7f25839d7..a961229d8e 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -55,7 +55,7 @@ #define WRITE_DEC(rtp_session) switch_mutex_unlock(rtp_session->write_mutex); rtp_session->writing-- - +#define RTP_DEFAULT_STUNCOUNT 100; #define rtp_header_len 12 #define RTP_START_PORT 16384 #define RTP_END_PORT 32768 @@ -164,6 +164,7 @@ typedef struct { char *ice_user; char *user_ice; char *pass; + char *rpass; uint32_t stuncount; uint32_t funny_stun; uint32_t default_stuncount; @@ -677,7 +678,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice) switch_stun_packet_attribute_add_controlling(packet); } - switch_stun_packet_attribute_add_integrity(packet, ice->pass); + switch_stun_packet_attribute_add_integrity(packet, ice->rpass); switch_stun_packet_attribute_add_fingerprint(packet); @@ -715,6 +716,8 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d char username[33] = { 0 }; unsigned char buf[512] = { 0 }; switch_size_t cpylen = len; + int xlen = 0; + int ok = 1; if (!switch_rtp_ready(rtp_session) || zstr(ice->user_ice) || zstr(ice->ice_user)) { return; @@ -727,23 +730,19 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d goto end; } - - if (cpylen > 512) { - cpylen = 512; + if (cpylen > sizeof(buf)) { + cpylen = sizeof(buf); } memcpy(buf, data, cpylen); - packet = switch_stun_packet_parse(buf, sizeof(buf)); + packet = switch_stun_packet_parse(buf, cpylen); if (!packet) { switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session"); - //int sbytes = (int) cpylen; - //int stat; - //if ((stat = srtp_unprotect(rtp_session->recv_ctx, buf, &sbytes)) || !(packet = switch_stun_packet_parse(buf, sizeof(buf)))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid STUN/ICE packet received\n"); - goto end; - //} + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid STUN/ICE packet received\n"); + goto end; + } #if 0 @@ -762,8 +761,6 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d switch_stun_packet_first_attribute(packet, attr); - - do { switch (attr->type) { case SWITCH_STUN_ATTR_MAPPED_ADDRESS: @@ -778,27 +775,41 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d switch_stun_packet_attribute_get_username(attr, username, 32); } break; + + case SWITCH_STUN_ATTR_PRIORITY: + { + uint32_t *val = (uint32_t *) attr->value; + ok = *val == ice->priority; + } + break; } - } while (switch_stun_packet_next_attribute(attr, end_buf)); - if ((packet->header.type == SWITCH_STUN_BINDING_REQUEST)) { - //if ((packet->header.type == SWITCH_STUN_BINDING_REQUEST) && !strcmp(ice->user_ice, username)) { + if (!switch_stun_packet_next_attribute(attr, end_buf)) { + break; + } + xlen += 4 + switch_stun_attribute_padded_length(attr); + } while (xlen <= packet->header.length); + + if (ice->type == ICE_GOOGLE_JINGLE && ok) { + ok = !strcmp(ice->user_ice, username); + } + + if ((packet->header.type == SWITCH_STUN_BINDING_REQUEST) && ok) { uint8_t stunbuf[512]; switch_stun_packet_t *rpacket; const char *remote_ip; switch_size_t bytes; char ipbuf[25]; - //int rtcp = 0; switch_sockaddr_t *from_addr = rtp_session->from_addr; switch_socket_t *sock_output = rtp_session->sock_output; if (ice == &rtp_session->rtcp_ice) { - //rtcp = 1; from_addr = rtp_session->rtcp_from_addr; sock_output = rtp_session->rtcp_sock_output; } - printf("STUN REQ\n"); + + rtp_session->ice.ready = 1; memset(stunbuf, 0, sizeof(stunbuf)); rpacket = switch_stun_packet_build_header(SWITCH_STUN_BINDING_RESPONSE, packet->header.id, stunbuf); @@ -811,11 +822,18 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d switch_stun_packet_attribute_add_binded_address(rpacket, (char *) remote_ip, switch_sockaddr_get_port(from_addr)); if ((ice->type & ICE_VANILLA)) { + + + //if (!(ice->type && ICE_CONTROLLED)) { + // switch_stun_packet_attribute_add_use_candidate(rpacket); + // switch_stun_packet_attribute_add_priority(rpacket, ice->priority); + //} + switch_stun_packet_attribute_add_integrity(rpacket, ice->pass); switch_stun_packet_attribute_add_fingerprint(rpacket); } - rtp_session->ice.ready = 1; + bytes = switch_stun_packet_length(rpacket); switch_socket_sendto(sock_output, from_addr, 0, (void *) rpacket, &bytes); @@ -1074,7 +1092,7 @@ static uint8_t get_next_write_ts(switch_rtp_t *rtp_session, uint32_t timestamp) static int check_srtp_and_ice(switch_rtp_t *rtp_session) { int ret = 0; - + int rtcp_ok = 1; if (rtp_session->flags[SWITCH_RTP_FLAG_AUTO_CNG] && rtp_session->send_msg.header.ts && @@ -1094,7 +1112,11 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session) } } - if (rtp_session->rtcp_sock_output && + if (rtp_session->rtcp_ice.ice_user && !rtp_session->rtcp_ice.ready) { + rtcp_ok = 0; + } + + if (rtp_session->rtcp_sock_output && rtcp_ok && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] && rtp_session->rtcp_interval && (rtp_session->stats.read_count % rtp_session->rtcp_interval) == 0) { struct switch_rtcp_senderinfo *sr = (struct switch_rtcp_senderinfo*) rtp_session->rtcp_send_msg.body; @@ -2422,7 +2444,7 @@ 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, switch_core_media_ice_type_t type, uint32_t priority) + const char *password, const char *rpassword, switch_core_media_ice_type_t type, uint32_t priority) { char ice_user[80]; char user_ice[80]; @@ -2439,12 +2461,18 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio 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 = ""; if (password) { rtp_session->ice.pass = switch_core_strdup(rtp_session->pool, password); } + + if (rpassword) { + rtp_session->ice.rpass = switch_core_strdup(rtp_session->pool, rpassword); + } - rtp_session->ice.default_stuncount = 25; + rtp_session->ice.default_stuncount = RTP_DEFAULT_STUNCOUNT; rtp_session->ice.stuncount = 0; if (rtp_session->ice.ice_user) { @@ -2458,7 +2486,7 @@ 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, switch_core_media_ice_type_t type, uint32_t priority) + const char *password, const char *rpassword, switch_core_media_ice_type_t type, uint32_t priority) { char ice_user[80]; char user_ice[80]; @@ -2475,11 +2503,18 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp_ice(switch_rtp_t *rtp_s 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); } - rtp_session->rtcp_ice.default_stuncount = 25; + + 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) { diff --git a/src/switch_stun.c b/src/switch_stun.c index 40b94423a0..08af2ae145 100644 --- a/src/switch_stun.c +++ b/src/switch_stun.c @@ -120,6 +120,7 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui switch_stun_packet_attribute_t *attr; uint32_t bytes_left = len; void *end_buf = buf + len; + int xlen = 0; if (len < SWITCH_STUN_PACKET_MIN_LEN) { return NULL; @@ -128,7 +129,8 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui packet = (switch_stun_packet_t *) buf; packet->header.type = ntohs(packet->header.type); packet->header.length = ntohs(packet->header.length); - bytes_left -= packet->header.length + 20; + bytes_left -= 20; + /* * Check packet type (RFC3489(bis?) values) @@ -182,12 +184,13 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui attr->type = ntohs(attr->type); bytes_left -= 4; /* attribute header consumed */ - if (!attr->length || switch_stun_attribute_padded_length(attr) > bytes_left) { + if (switch_stun_attribute_padded_length(attr) > bytes_left) { /* * Note we simply don't "break" here out of the loop anymore because * we don't want the upper layers to have to deal with attributes without a value * (or worse: invalid length) */ + return NULL; } /* @@ -202,6 +205,12 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui case SWITCH_STUN_ATTR_REFLECTED_FROM: case SWITCH_STUN_ATTR_ALTERNATE_SERVER: case SWITCH_STUN_ATTR_DESTINATION_ADDRESS: + case SWITCH_STUN_ATTR_PRIORITY: + { + uint32_t *u = (uint32_t *)attr->value; + *u = ntohl(*u); + } + break; case SWITCH_STUN_ATTR_SOURCE_ADDRESS2: { switch_stun_ip_t *ip; @@ -279,16 +288,18 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui break; default: - /* Mandatory attribute range? => invalid */ - //if (attr->type <= 0x7FFF) { - // return NULL; - //} break; } + bytes_left -= switch_stun_attribute_padded_length(attr); /* attribute value consumed, substract padded length */ + xlen += 4 + switch_stun_attribute_padded_length(attr); - } while (bytes_left >= SWITCH_STUN_ATTRIBUTE_MIN_LEN && switch_stun_packet_next_attribute(attr, end_buf)); - + attr = (switch_stun_packet_attribute_t *) (attr->value + switch_stun_attribute_padded_length(attr)); + if ((void *)attr > end_buf) { + break; + } + } while (xlen < packet->header.length); + if ((uint32_t) (packet->header.length + 20) > (uint32_t) (len - bytes_left)) { /* * the packet length is longer than the length of all attributes? @@ -296,10 +307,11 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui */ packet->header.length = (uint16_t) ((len - bytes_left) - 20); } - + return packet; } + SWITCH_DECLARE(const char *) switch_stun_value_to_name(int32_t type, uint32_t value) { uint32_t x = 0; @@ -460,16 +472,13 @@ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_xor_binded_address(swit SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_add_priority(switch_stun_packet_t *packet, uint32_t priority) { switch_stun_packet_attribute_t *attribute; - uint32_t *lame; + priority = htonl(priority); attribute = (switch_stun_packet_attribute_t *) ((uint8_t *) & packet->first_attribute + ntohs(packet->header.length)); attribute->type = htons(SWITCH_STUN_ATTR_PRIORITY); attribute->length = htons(4); memcpy(attribute->value, &priority, 4); - lame = (uint32_t *) attribute->value; - printf("FUCKER2 %u %u\n", *lame, priority); - packet->header.length += htons(sizeof(switch_stun_packet_attribute_t)) + attribute->length; return 1; }