diff options
-rw-r--r-- | channels/chan_sip.c | 26 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 3 | ||||
-rw-r--r-- | configs/sip.conf.sample | 5 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 24 |
4 files changed, 52 insertions, 6 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 9c2d75d3f..867ee9a80 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -5468,6 +5468,7 @@ static void copy_socket_data(struct sip_socket *to_sock, const struct sip_socket static int dialog_initialize_rtp(struct sip_pvt *dialog) { struct ast_sockaddr bindaddr_tmp; + struct ast_rtp_engine_ice *ice; if (!sip_methods[dialog->method].need_rtp) { return 0; @@ -5478,11 +5479,20 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog) return -1; } + if (!ast_test_flag(&dialog->flags[2], SIP_PAGE3_ICE_SUPPORT) && (ice = ast_rtp_instance_get_ice(dialog->rtp))) { + ice->stop(dialog->rtp); + } + if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) || (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) { if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { return -1; } + + if (!ast_test_flag(&dialog->flags[2], SIP_PAGE3_ICE_SUPPORT) && (ice = ast_rtp_instance_get_ice(dialog->vrtp))) { + ice->stop(dialog->vrtp); + } + ast_rtp_instance_set_timeout(dialog->vrtp, dialog->rtptimeout); ast_rtp_instance_set_hold_timeout(dialog->vrtp, dialog->rtpholdtimeout); ast_rtp_instance_set_keepalive(dialog->vrtp, dialog->rtpkeepalive); @@ -5494,6 +5504,11 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog) if (!(dialog->trtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { return -1; } + + if (!ast_test_flag(&dialog->flags[2], SIP_PAGE3_ICE_SUPPORT) && (ice = ast_rtp_instance_get_ice(dialog->trtp))) { + ice->stop(dialog->trtp); + } + /* Do not timeout text as its not constant*/ ast_rtp_instance_set_keepalive(dialog->trtp, dialog->rtpkeepalive); @@ -12417,7 +12432,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int ast_verbose("Video is at %s\n", ast_sockaddr_stringify(&vdest)); } - if (!doing_directmedia) { + if (!doing_directmedia && ast_test_flag(&p->flags[2], SIP_PAGE3_ICE_SUPPORT)) { add_ice_to_sdp(p->vrtp, &a_video); } } @@ -12434,7 +12449,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&taddr)); } - if (!doing_directmedia) { + if (!doing_directmedia && ast_test_flag(&p->flags[2], SIP_PAGE3_ICE_SUPPORT)) { add_ice_to_sdp(p->trtp, &a_text); } } @@ -12533,7 +12548,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int if (min_text_packet_size) ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size); - if (!doing_directmedia) { + if (!doing_directmedia && ast_test_flag(&p->flags[2], SIP_PAGE3_ICE_SUPPORT)) { add_ice_to_sdp(p->rtp, &a_audio); } @@ -29752,6 +29767,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC); } else if (!strcasecmp(v->name, "avpf")) { ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_USE_AVPF); + } else if (!strcasecmp(v->name, "icesupport")) { + ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_ICE_SUPPORT); } } @@ -30285,6 +30302,7 @@ static int reload_config(enum channelreloadreason reason) ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */ ast_set_flag(&global_flags[0], SIP_DIRECT_MEDIA); /*!< Allow re-invites */ ast_set_flag(&global_flags[2], SIP_PAGE3_NAT_AUTO_RPORT); /*!< Default to nat=auto_force_rport */ + ast_set_flag(&global_flags[2], SIP_PAGE3_ICE_SUPPORT); /*!< Default to enabling ICE support */ ast_copy_string(default_engine, DEFAULT_ENGINE, sizeof(default_engine)); ast_copy_string(default_parkinglot, DEFAULT_PARKINGLOT, sizeof(default_parkinglot)); @@ -30841,6 +30859,8 @@ static int reload_config(enum channelreloadreason reason) } } else if (!strcasecmp(v->name, "snom_aoc_enabled")) { ast_set2_flag(&global_flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC); + } else if (!strcasecmp(v->name, "icesupport")) { + ast_set2_flag(&global_flags[2], ast_true(v->value), SIP_PAGE3_ICE_SUPPORT); } else if (!strcasecmp(v->name, "parkinglot")) { ast_copy_string(default_parkinglot, v->value, sizeof(default_parkinglot)); } diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index cf1e964d1..76766fb17 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -371,10 +371,11 @@ #define SIP_PAGE3_NAT_AUTO_COMEDIA (1 << 3) /*!< DGP: Set SIP_PAGE2_SYMMETRICRTP when NAT is detected */ #define SIP_PAGE3_DIRECT_MEDIA_OUTGOING (1 << 4) /*!< DP: Only send direct media reinvites on outgoing calls */ #define SIP_PAGE3_USE_AVPF (1 << 5) /*!< DGP: Support a minimal AVPF-compatible profile */ +#define SIP_PAGE3_ICE_SUPPORT (1 << 6) /*!< DGP: Enable ICE support */ #define SIP_PAGE3_FLAGS_TO_COPY \ (SIP_PAGE3_SNOM_AOC | SIP_PAGE3_SRTP_TAG_32 | SIP_PAGE3_NAT_AUTO_RPORT | SIP_PAGE3_NAT_AUTO_COMEDIA | \ - SIP_PAGE3_DIRECT_MEDIA_OUTGOING | SIP_PAGE3_USE_AVPF) + SIP_PAGE3_DIRECT_MEDIA_OUTGOING | SIP_PAGE3_USE_AVPF | SIP_PAGE3_ICE_SUPPORT) #define CHECK_AUTH_BUF_INITLEN 256 diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 8894a3931..c8b437acf 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -900,6 +900,11 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; this feature. ; ; subscribe_network_change_event = yes ; on by default +; +; ICE/STUN/TURN usage can be disabled globally or on a per-peer basis using the icesupport +; configuration option. When set to yes ICE support is enabled. When set to no it is disabled. +; +; icesupport = no ;----------------------------------- MEDIA HANDLING -------------------------------- ; By default, Asterisk tries to re-invite media streams to an optimal path. If there's diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index d18729ddf..97e63b48f 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -547,18 +547,32 @@ static void ast_rtp_ice_lite(struct ast_rtp_instance *instance) pj_ice_sess_change_role(rtp->ice, PJ_ICE_SESS_ROLE_CONTROLLING); } +static int ice_candidate_cmp(void *obj, void *arg, int flags) +{ + struct ast_rtp_engine_ice_candidate *candidate1 = obj, *candidate2 = arg; + + if ((strcmp(candidate1->foundation, candidate2->foundation)) || + (candidate1->id != candidate2->id) || + (ast_sockaddr_cmp(&candidate1->address, &candidate2->address)) || + (candidate1->type != candidate1->type)) { + return 0; + } + + return CMP_MATCH | CMP_STOP; +} + static void ast_rtp_ice_add_cand(struct ast_rtp *rtp, unsigned comp_id, unsigned transport_id, pj_ice_cand_type type, pj_uint16_t local_pref, const pj_sockaddr_t *addr, const pj_sockaddr_t *base_addr, const pj_sockaddr_t *rel_addr, int addr_len) { pj_str_t foundation; - struct ast_rtp_engine_ice_candidate *candidate; + struct ast_rtp_engine_ice_candidate *candidate, *existing; char address[PJ_INET6_ADDRSTRLEN]; pj_thread_register_check(); pj_ice_calc_foundation(rtp->ice->pool, &foundation, type, addr); - if (!rtp->local_candidates && !(rtp->local_candidates = ao2_container_alloc(1, NULL, NULL))) { + if (!rtp->local_candidates && !(rtp->local_candidates = ao2_container_alloc(1, NULL, ice_candidate_cmp))) { return; } @@ -586,6 +600,12 @@ static void ast_rtp_ice_add_cand(struct ast_rtp *rtp, unsigned comp_id, unsigned candidate->type = AST_RTP_ICE_CANDIDATE_TYPE_RELAYED; } + if ((existing = ao2_find(rtp->local_candidates, candidate, OBJ_POINTER))) { + ao2_ref(existing, -1); + ao2_ref(candidate, -1); + return; + } + if (pj_ice_sess_add_cand(rtp->ice, comp_id, transport_id, type, local_pref, &foundation, addr, addr, rel_addr, addr_len, NULL) != PJ_SUCCESS) { ao2_ref(candidate, -1); return; |