diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample index 26a70d2e16cc05fea59693df27f9172adc041780..a2664e41a1160c93bb4d16169533ec8748535636 100644 --- a/configs/samples/rtp.conf.sample +++ b/configs/samples/rtp.conf.sample @@ -118,13 +118,19 @@ rtpend=20000 ; ; The format for these overrides is: ; -; <local address> => <advertised address> +; <local address> => <advertised address>,[include_local_address] ; ; The following will replace 192.168.1.10 with 1.2.3.4 during ICE ; negotiation: ; ;192.168.1.10 => 1.2.3.4 ; +; The following will include BOTH 192.168.1.10 and 1.2.3.4 during ICE +; negotiation instead of replacing 192.168.1.10. This can make it easier +; to serve both local and remote clients. +; +;192.168.1.10 => 1.2.3.4,include_local_address +; ; You can define an override for more than 1 interface if you have a multihomed ; server. Any local interface that is not matched will be passed through ; unaltered. Both IPv4 and IPv6 addresses are supported. diff --git a/doc/CHANGES-staging/rtp_ice_include_local_address.txt b/doc/CHANGES-staging/rtp_ice_include_local_address.txt new file mode 100644 index 0000000000000000000000000000000000000000..e5a65e5f869bc1ea5d083f2bfb2411e1b562e08c --- /dev/null +++ b/doc/CHANGES-staging/rtp_ice_include_local_address.txt @@ -0,0 +1,5 @@ +Subject: RTP/ICE + +You can now indicate that you'd like an ice_host_candidate's local address +to be published as well as the mapped address. See the sample rtp.conf +for more information. diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index c4df6a40fd8eb490bd26f5cba2497237b035e951..c2e2a0560f493116ae84c99d71baf8ea4902d292 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -252,6 +252,7 @@ static AST_LIST_HEAD_STATIC(ioqueues, ast_rtp_ioqueue_thread); struct ast_ice_host_candidate { pj_sockaddr local; pj_sockaddr advertised; + unsigned int include_local; AST_RWLIST_ENTRY(ast_ice_host_candidate) next; }; @@ -615,21 +616,26 @@ static void host_candidate_overrides_clear(void) } /*! \brief Applies the ICE host candidate mapping */ -static void host_candidate_overrides_apply(unsigned int count, pj_sockaddr addrs[]) +static unsigned int host_candidate_overrides_apply(unsigned int count, unsigned int max_count, pj_sockaddr addrs[]) { int pos; struct ast_ice_host_candidate *candidate; + unsigned int added = 0; AST_RWLIST_RDLOCK(&host_candidates); for (pos = 0; pos < count; pos++) { AST_LIST_TRAVERSE(&host_candidates, candidate, next) { if (!pj_sockaddr_cmp(&candidate->local, &addrs[pos])) { pj_sockaddr_copy_addr(&addrs[pos], &candidate->advertised); + if (candidate->include_local && (count + (++added)) <= max_count) { + pj_sockaddr_cp(&addrs[count + (added - 1)], &candidate->local); + } break; } } } AST_RWLIST_UNLOCK(&host_candidates); + return added; } /*! \brief Helper function which updates an ast_sockaddr with the candidate used for the component */ @@ -3303,6 +3309,7 @@ static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct { pj_sockaddr address[PJ_ICE_MAX_CAND]; unsigned int count = PJ_ARRAY_SIZE(address), pos = 0; + unsigned int max_count = PJ_ARRAY_SIZE(address); int basepos = -1; /* Add all the local interface IP addresses */ @@ -3314,7 +3321,7 @@ static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct pj_enum_ip_interface(pj_AF_INET6(), &count, address); } - host_candidate_overrides_apply(count, address); + count += host_candidate_overrides_apply(count, max_count, address); for (pos = 0; pos < count; pos++) { if (!rtp_address_is_ice_blacklisted(&address[pos])) { @@ -8640,6 +8647,8 @@ static int rtp_reload(int reload) for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) { struct ast_sockaddr local_addr, advertised_addr; pj_str_t address; + unsigned int include_local_address = 0; + char *sep; ast_sockaddr_setnull(&local_addr); ast_sockaddr_setnull(&advertised_addr); @@ -8649,6 +8658,14 @@ static int rtp_reload(int reload) continue; } + sep = strchr(var->value,','); + if (sep) { + *sep = '\0'; + sep++; + sep = ast_skip_blanks(sep); + include_local_address = strcmp(sep, "include_local_address") == 0; + } + if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) { ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value); continue; @@ -8659,6 +8676,8 @@ static int rtp_reload(int reload) break; } + candidate->include_local = include_local_address; + pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&address, ast_sockaddr_stringify(&local_addr)), &candidate->local); pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&address, ast_sockaddr_stringify(&advertised_addr)), &candidate->advertised);