diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 6a4373ea36e72a27dd7b9684aeb7448a3b849df8..8f4a6d90be19ac191972d1ab182cba87a2420491 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -69,7 +69,6 @@ set(LINPHONE_SOURCE_FILES_C lpconfig.c lsd.c misc.c - nat_policy.c payload_type.c player.c presence.c diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index bc85d78951cc2b72849d88aedb3116525f1b7b70..31f7e308966bed0f56ab764113eb253d379c307f 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -169,7 +169,6 @@ bool_t linphone_core_sound_resources_need_locking(LinphoneCore *lc, const Linpho #include "enum.h" #include "contact_providers_priv.h" -const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); static void toggle_video_preview(LinphoneCore *lc, bool_t val); @@ -5813,7 +5812,7 @@ void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf) { void linphone_core_set_stun_server(LinphoneCore *lc, const char *server) { if (lc->nat_policy != NULL) { linphone_nat_policy_set_stun_server(lc->nat_policy, server); - linphone_nat_policy_save_to_config(lc->nat_policy); + NatPolicy::toCpp(lc->nat_policy)->saveToConfig(); } else { linphone_config_set_string(lc->config, "net", "stun_server", server); } @@ -5852,31 +5851,6 @@ const char *linphone_core_get_nat_address(const LinphoneCore *lc) { return lc->net_conf.nat_address; } -const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc) { - struct sockaddr_storage ss; - socklen_t ss_len; - int error; - char ipstring [INET6_ADDRSTRLEN]; - - if (lc->net_conf.nat_address==NULL) return NULL; - - if (parse_hostname_to_addr (lc->net_conf.nat_address, &ss, &ss_len, 5060)<0) { - return lc->net_conf.nat_address; - } - - error = bctbx_getnameinfo((struct sockaddr *)&ss, ss_len, - ipstring, sizeof(ipstring), NULL, 0, NI_NUMERICHOST); - if (error) { - return lc->net_conf.nat_address; - } - - if (lc->net_conf.nat_address_ip!=NULL){ - ms_free(lc->net_conf.nat_address_ip); - } - lc->net_conf.nat_address_ip = ms_strdup (ipstring); - return lc->net_conf.nat_address_ip; -} - void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy pol) { LinphoneNatPolicy *nat_policy; char *stun_server = NULL; @@ -5968,8 +5942,8 @@ void linphone_core_set_nat_policy(LinphoneCore *lc, LinphoneNatPolicy *policy) { lc->nat_policy = policy; /*start an immediate (but asynchronous) resolution.*/ linphone_nat_policy_resolve_stun_server(policy); - linphone_config_set_string(lc->config, "net", "nat_policy_ref", lc->nat_policy->ref); - linphone_nat_policy_save_to_config(lc->nat_policy); + linphone_config_set_string(lc->config, "net", "nat_policy_ref", NatPolicy::toCpp(policy)->getRef().c_str()); + NatPolicy::toCpp(policy)->saveToConfig(); } lc->sal->enableNatHelper(!!linphone_config_get_int(lc->config, "net", "enable_nat_helper", 1)); @@ -7095,7 +7069,7 @@ void sip_config_uninit(LinphoneCore *lc) LinphoneAccount *acc = (LinphoneAccount *)(elem->data); Account::toCpp(acc)->unpublish(); /* to unpublish without changing the stored flag enable_publish */ LinphoneNatPolicy *policy = linphone_account_params_get_nat_policy(linphone_account_get_params(acc)); - if (policy) linphone_nat_policy_release(policy); + if (policy) NatPolicy::toCpp(policy)->release(); /* Do not unregister when push notifications are allowed, otherwise this clears tokens from the SIP server.*/ if (!linphone_account_params_get_push_notification_allowed(linphone_account_get_params(acc)) && !linphone_account_params_get_remote_push_notification_allowed(linphone_account_get_params(acc))) { @@ -7165,7 +7139,7 @@ void sip_config_uninit(LinphoneCore *lc) } #endif - if (lc->nat_policy) linphone_nat_policy_release(lc->nat_policy); + if (lc->nat_policy) NatPolicy::toCpp(lc->nat_policy)->release(); for (i = 0; i < 5 ; ++i) lc->sal->iterate(); /*make sure event are purged*/ lc->sal=NULL; diff --git a/coreapi/nat_policy.c b/coreapi/nat_policy.c deleted file mode 100644 index 9f92a016f40143b2abf5e1894f77622ede5c5683..0000000000000000000000000000000000000000 --- a/coreapi/nat_policy.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2010-2019 Belledonne Communications SARL. - * - * This file is part of Liblinphone. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "linphone/core.h" - -#include "c-wrapper/c-wrapper.h" - -// TODO: From coreapi. Remove me later. -#include "private.h" - -static LinphoneNatPolicy * _linphone_nat_policy_new_with_ref(LinphoneCore *lc, const char *ref) { - LinphoneNatPolicy *policy = belle_sip_object_new(LinphoneNatPolicy); - policy->lc = lc; - policy->ref = belle_sip_strdup(ref); - return policy; -} - -static LinphoneNatPolicy * linphone_nat_policy_new(LinphoneCore *lc) { - char ref[17] = { 0 }; - belle_sip_random_token(ref, 16); - return _linphone_nat_policy_new_with_ref(lc, ref); -} - -static void linphone_nat_policy_destroy(LinphoneNatPolicy *policy) { - if (policy->ref) belle_sip_free(policy->ref); - if (policy->stun_server) belle_sip_free(policy->stun_server); - if (policy->stun_server_username) belle_sip_free(policy->stun_server_username); - if (policy->resolver_results) belle_sip_object_unref(policy->resolver_results); - if (policy->stun_resolver_context) { - belle_sip_resolver_context_cancel(policy->stun_resolver_context); - belle_sip_object_unref(policy->stun_resolver_context); - } -} - - -/* Simply cancel pending DNS resoltion, as the core is going to shutdown.*/ -void linphone_nat_policy_release(LinphoneNatPolicy *policy){ - if (policy->stun_resolver_context) { - belle_sip_resolver_context_cancel(policy->stun_resolver_context); - belle_sip_object_unref(policy->stun_resolver_context); - policy->stun_resolver_context = NULL; - } -} - -bool_t linphone_nat_policy_stun_server_activated(LinphoneNatPolicy *policy) { - const char *server = linphone_nat_policy_get_stun_server(policy); - return (server != NULL) && (server[0] != '\0') - && ((linphone_nat_policy_stun_enabled(policy) == TRUE) || (linphone_nat_policy_turn_enabled(policy) == TRUE)); -} - - -static void _linphone_nat_policy_clone(LinphoneNatPolicy *policy, const LinphoneNatPolicy *other){ - policy->lc = other->lc; - policy->ref = belle_sip_strdup(other->ref); - policy->stun_server = belle_sip_strdup(other->stun_server); - policy->stun_server_username = belle_sip_strdup(other->stun_server_username); - /* don't clone the resolver context and results */ - policy->stun_enabled = other->stun_enabled; - policy->ice_enabled = other->ice_enabled; - policy->turn_enabled = other->turn_enabled; - policy->upnp_enabled = other->upnp_enabled; - policy->turn_udp_enabled = other->turn_udp_enabled; - policy->turn_tcp_enabled = other->turn_tcp_enabled; - policy->turn_tls_enabled = other->turn_tls_enabled; -} - - -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneNatPolicy); - -BELLE_SIP_INSTANCIATE_VPTR(LinphoneNatPolicy, belle_sip_object_t, - (belle_sip_object_destroy_t)linphone_nat_policy_destroy, - (belle_sip_object_clone_t)_linphone_nat_policy_clone, // clone - NULL, // marshal - FALSE -); - - -static void _linphone_nat_policy_save_to_config(const LinphoneNatPolicy *policy, LpConfig *config, int index) { - char *section; - bctbx_list_t *l = NULL; - - section = belle_sip_strdup_printf("nat_policy_%i", index); - linphone_config_set_string(config, section, "ref", policy->ref); - linphone_config_set_string(config, section, "stun_server", policy->stun_server); - linphone_config_set_string(config, section, "stun_server_username", policy->stun_server_username); - if (linphone_nat_policy_upnp_enabled(policy)) { - l = bctbx_list_append(l, (void *)"upnp"); - } else { - if (linphone_nat_policy_stun_enabled(policy)) l = bctbx_list_append(l, (void *)"stun"); - if (linphone_nat_policy_turn_enabled(policy)) l = bctbx_list_append(l, (void *)"turn"); - if (linphone_nat_policy_ice_enabled(policy)) l = bctbx_list_append(l, (void *)"ice"); - } - linphone_config_set_string_list(config, section, "protocols", l); - belle_sip_free(section); - bctbx_list_free(l); -} - -LinphoneNatPolicy *linphone_nat_policy_clone(const LinphoneNatPolicy *other){ - return (LinphoneNatPolicy*) belle_sip_object_clone(BELLE_SIP_OBJECT(other)); -} - -void linphone_nat_policy_save_to_config(const LinphoneNatPolicy *policy) { - LpConfig *config = policy->lc->config; - char *section; - int index; - bool_t finished = FALSE; - - for (index = 0; finished != TRUE; index++) { - section = belle_sip_strdup_printf("nat_policy_%i", index); - if (linphone_config_has_section(config, section)) { - const char *config_ref = linphone_config_get_string(config, section, "ref", NULL); - if ((config_ref != NULL) && (strcmp(config_ref, policy->ref) == 0)) { - _linphone_nat_policy_save_to_config(policy, config, index); - finished = TRUE; - } - } else { - _linphone_nat_policy_save_to_config(policy, config, index); - finished = TRUE; - } - belle_sip_free(section); - } -} - -LinphoneNatPolicy * linphone_nat_policy_ref(LinphoneNatPolicy *policy) { - belle_sip_object_ref(policy); - return policy; -} - -void linphone_nat_policy_unref(LinphoneNatPolicy *policy) { - belle_sip_object_unref(policy); -} - -void *linphone_nat_policy_get_user_data(const LinphoneNatPolicy *policy) { - return policy->user_data; -} - -void linphone_nat_policy_set_user_data(LinphoneNatPolicy *policy, void *ud) { - policy->user_data = ud; -} - - -void linphone_nat_policy_clear(LinphoneNatPolicy *policy) { - linphone_nat_policy_enable_stun(policy, FALSE); - linphone_nat_policy_enable_turn(policy, FALSE); - linphone_nat_policy_enable_ice(policy, FALSE); - linphone_nat_policy_enable_upnp(policy, FALSE); - linphone_nat_policy_set_stun_server(policy, NULL); - linphone_nat_policy_set_stun_server_username(policy, NULL); -} - -bool_t linphone_nat_policy_stun_enabled(const LinphoneNatPolicy *policy) { - return policy->stun_enabled; -} - -void linphone_nat_policy_enable_stun(LinphoneNatPolicy *policy, bool_t enable) { - policy->stun_enabled = enable; -} - -bool_t linphone_nat_policy_turn_enabled(const LinphoneNatPolicy *policy) { - return policy->turn_enabled; -} - -void linphone_nat_policy_enable_turn(LinphoneNatPolicy *policy, bool_t enable) { - policy->turn_enabled = enable; -} - -bool_t linphone_nat_policy_ice_enabled(const LinphoneNatPolicy *policy) { - return policy->ice_enabled; -} - -void linphone_nat_policy_enable_ice(LinphoneNatPolicy *policy, bool_t enable) { - policy->ice_enabled = enable; -} - -bool_t linphone_nat_policy_upnp_enabled(const LinphoneNatPolicy *policy) { - return policy->upnp_enabled; -} - -void linphone_nat_policy_enable_upnp(LinphoneNatPolicy *policy, bool_t enable) { - policy->upnp_enabled = enable; - if (enable) { - ms_warning("uPnP NAT policy is no longer supported"); - } -} - -const char * linphone_nat_policy_get_stun_server(const LinphoneNatPolicy *policy) { - return policy->stun_server; -} - -void linphone_nat_policy_set_stun_server(LinphoneNatPolicy *policy, const char *stun_server) { - char *new_stun_server = NULL; - - if (stun_server != NULL) new_stun_server = belle_sip_strdup(stun_server); - if (policy->stun_server != NULL) { - belle_sip_free(policy->stun_server); - policy->stun_server = NULL; - } - if (new_stun_server != NULL) { - policy->stun_server = new_stun_server; - } - if (policy->resolver_results) { - belle_sip_object_unref(policy->resolver_results); - policy->resolver_results = NULL; - } - if (policy->stun_resolver_context){ - belle_sip_resolver_context_cancel(policy->stun_resolver_context); - belle_sip_object_unref(policy->stun_resolver_context); - policy->stun_resolver_context = NULL; - - } - linphone_nat_policy_resolve_stun_server(policy); -} - -const char * linphone_nat_policy_get_stun_server_username(const LinphoneNatPolicy *policy) { - return policy->stun_server_username; -} - -void linphone_nat_policy_set_stun_server_username(LinphoneNatPolicy *policy, const char *username) { - char *new_username = NULL; - - if (username != NULL) new_username = belle_sip_strdup(username); - if (policy->stun_server_username != NULL) { - belle_sip_free(policy->stun_server_username); - policy->stun_server_username = NULL; - } - if (new_username != NULL) policy->stun_server_username = new_username; -} - -static void stun_server_resolved(void *data, belle_sip_resolver_results_t *results) { - LinphoneNatPolicy *policy = (LinphoneNatPolicy *)data; - - if (policy->resolver_results) { - belle_sip_object_unref(policy->resolver_results); - policy->resolver_results = NULL; - } - - if (belle_sip_resolver_results_get_addrinfos(results)) { - ms_message("Stun server resolution successful."); - belle_sip_object_ref(results); - policy->resolver_results = results; - } else { - ms_warning("Stun server resolution failed."); - } - if (policy->stun_resolver_context){ - belle_sip_object_unref(policy->stun_resolver_context); - policy->stun_resolver_context = NULL; - } -} - -void linphone_nat_policy_resolve_stun_server(LinphoneNatPolicy *policy) { - const char *service = NULL; - - if (linphone_nat_policy_stun_server_activated(policy) && (policy->lc->sal != NULL) && !policy->stun_resolver_context) { - char host[NI_MAXHOST]; - int port = 0; - linphone_parse_host_port(policy->stun_server, host, sizeof(host), &port); - if (linphone_nat_policy_turn_enabled(policy)) service = "turn"; - else if (linphone_nat_policy_stun_enabled(policy)) service = "stun"; - if (service != NULL) { - int family = AF_INET; - if (linphone_core_ipv6_enabled(policy->lc) == TRUE) family = AF_INET6; - ms_message("Starting stun server resolution [%s]", host); - if (port == 0) { - port = 3478; - policy->stun_resolver_context = policy->lc->sal->resolve(service, "udp", host, port, family, stun_server_resolved, policy); - } else { - policy->stun_resolver_context = policy->lc->sal->resolveA(host, port, family, stun_server_resolved, policy); - } - if (policy->stun_resolver_context) belle_sip_object_ref(policy->stun_resolver_context); - } - } -} - -const struct addrinfo * linphone_nat_policy_get_stun_server_addrinfo(LinphoneNatPolicy *policy) { - /* - * It is critical not to block for a long time if it can't be resolved, otherwise this stucks the main thread when making a call. - * On the contrary, a fully asynchronous call initiation is complex to develop. - * The compromise is then: - * - have a cache of the stun server addrinfo - * - this cached value is returned when it is non-null - * - an asynchronous resolution is asked each time this function is called to ensure frequent refreshes of the cached value. - * - if no cached value exists, block for a short time; this case must be unprobable because the resolution will be asked each - * time the stun server value is changed. - */ - if (linphone_nat_policy_stun_server_activated(policy) && (policy->resolver_results == NULL)) { - int wait_ms = 0; - int wait_limit = 1000; - linphone_nat_policy_resolve_stun_server(policy); - while ((policy->resolver_results == NULL) && (policy->stun_resolver_context != NULL) && (wait_ms < wait_limit)) { - policy->lc->sal->iterate(); - ms_usleep(50000); - wait_ms += 50; - } - } - return policy->resolver_results ? belle_sip_resolver_results_get_addrinfos(policy->resolver_results) : NULL; -} - -LinphoneNatPolicy * linphone_core_create_nat_policy(LinphoneCore *lc) { - return linphone_nat_policy_new(lc); -} - -LinphoneNatPolicy * linphone_config_create_nat_policy_from_section(const LinphoneConfig *config, const char* section) { - const char *config_ref = linphone_config_get_string(config, section, "ref", NULL); - const char *server = linphone_config_get_string(config, section, "stun_server", NULL); - const char *username = linphone_config_get_string(config, section, "stun_server_username", NULL); - bctbx_list_t *l = linphone_config_get_string_list(config, section, "protocols", NULL); - bool_t turn_enable_udp = linphone_config_get_bool(config, section, "turn_enable_udp", TRUE); - bool_t turn_enable_tcp = linphone_config_get_bool(config, section, "turn_enable_tcp", FALSE); - bool_t turn_enable_tls = linphone_config_get_bool(config, section, "turn_enable_tls", FALSE); - LinphoneNatPolicy *policy; - if (config_ref) - policy = _linphone_nat_policy_new_with_ref(NULL, config_ref); - else - policy = linphone_nat_policy_new(NULL); - - if (server != NULL) linphone_nat_policy_set_stun_server(policy, server); - if (username != NULL) linphone_nat_policy_set_stun_server_username(policy, username); - if (l != NULL) { - bool_t upnp_enabled = FALSE; - bctbx_list_t *elem; - for (elem = l; elem != NULL; elem = elem->next) { - const char *value = (const char *)elem->data; - if (strcmp(value, "stun") == 0) linphone_nat_policy_enable_stun(policy, TRUE); - else if (strcmp(value, "turn") == 0) linphone_nat_policy_enable_turn(policy, TRUE); - else if (strcmp(value, "ice") == 0) linphone_nat_policy_enable_ice(policy, TRUE); - else if (strcmp(value, "upnp") == 0) upnp_enabled = TRUE; - } - if (upnp_enabled) linphone_nat_policy_enable_upnp(policy, TRUE); - bctbx_list_free_with_data(l, (bctbx_list_free_func)ms_free); - } - linphone_nat_policy_enable_udp_turn_transport(policy, turn_enable_udp); - linphone_nat_policy_enable_tcp_turn_transport(policy, turn_enable_tcp); - linphone_nat_policy_enable_tls_turn_transport(policy, turn_enable_tls); - return policy; -} -LinphoneNatPolicy * linphone_core_create_nat_policy_from_config(LinphoneCore *lc, const char *ref) { - LpConfig *config = lc->config; - LinphoneNatPolicy *policy = NULL; - char *section; - int index; - bool_t finished = FALSE; - - for (index = 0; finished != TRUE; index++) { - section = belle_sip_strdup_printf("nat_policy_%i", index); - if (linphone_config_has_section(config, section)) { - const char *config_ref = linphone_config_get_string(config, section, "ref", NULL); - if ((config_ref != NULL) && (strcmp(config_ref, ref) == 0)) { - policy = linphone_config_create_nat_policy_from_section(config, section); - policy->lc = lc; - finished = TRUE; - } - } else finished = TRUE; - belle_sip_free(section); - } - return policy; -} - -void linphone_nat_policy_enable_udp_turn_transport(LinphoneNatPolicy *policy, bool_t enable) { - policy->turn_udp_enabled = enable; -} - -bool_t linphone_nat_policy_udp_turn_transport_enabled(LinphoneNatPolicy *policy) { - return policy->turn_udp_enabled; -} - -void linphone_nat_policy_enable_tcp_turn_transport(LinphoneNatPolicy *policy, bool_t enable) { - policy->turn_tcp_enabled = enable; -} - -bool_t linphone_nat_policy_tcp_turn_transport_enabled(LinphoneNatPolicy *policy) { - return policy->turn_tcp_enabled; -} - -void linphone_nat_policy_enable_tls_turn_transport(LinphoneNatPolicy *policy, bool_t enable) { - policy->turn_tls_enabled = enable; -} - -bool_t linphone_nat_policy_tls_turn_transport_enabled(LinphoneNatPolicy *policy) { - return policy->turn_tls_enabled; -} - -LinphoneCore *linphone_nat_policy_get_core(const LinphoneNatPolicy *policy) { - return policy->lc; -} diff --git a/coreapi/private_functions.h b/coreapi/private_functions.h index fcd3873d84202468b8f66635c736ea893a3cffb8..1039ebcf8d9ed2722857a639c4de11670434bc86 100644 --- a/coreapi/private_functions.h +++ b/coreapi/private_functions.h @@ -523,10 +523,6 @@ LinphoneContent *linphone_content_from_sal_body_handler(const SalBodyHandler *re void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); void linphone_core_register_offer_answer_providers(LinphoneCore *lc); -bool_t linphone_nat_policy_stun_server_activated(LinphoneNatPolicy *policy); -void linphone_nat_policy_release(LinphoneNatPolicy *policy); -void linphone_nat_policy_save_to_config(const LinphoneNatPolicy *policy); - void linphone_core_create_im_notif_policy(LinphoneCore *lc); LINPHONE_PUBLIC LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int index); @@ -708,7 +704,6 @@ LinphoneVideoDefinition * linphone_factory_find_supported_video_definition(const LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_name(const LinphoneFactory *factory, const char *name); const char* _linphone_config_load_from_xml_string(LpConfig *lpc, const char *buffer); -LinphoneNatPolicy * linphone_config_create_nat_policy_from_section(const LinphoneConfig *config, const char* section); void _linphone_config_apply_factory_config (LpConfig *config); SalCustomHeader *linphone_info_message_get_headers (const LinphoneInfoMessage *im); diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h index 25e7fcebf241979af3b48f5c02af82a83e99d705..90ec03a8ecf58e89e2bb9fbeaf5437e5d875f2a4 100644 --- a/coreapi/private_structs.h +++ b/coreapi/private_structs.h @@ -396,25 +396,7 @@ struct _LinphoneBuffer { BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneBuffer); -struct _LinphoneNatPolicy { - belle_sip_object_t base; - void *user_data; - LinphoneCore *lc; - belle_sip_resolver_context_t *stun_resolver_context; - belle_sip_resolver_results_t *resolver_results; - char *stun_server; - char *stun_server_username; - char *ref; - bool_t stun_enabled; - bool_t turn_enabled; - bool_t ice_enabled; - bool_t upnp_enabled; - bool_t turn_udp_enabled; - bool_t turn_tcp_enabled; - bool_t turn_tls_enabled; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneNatPolicy); + struct _LinphoneImNotifPolicy { belle_sip_object_t base; diff --git a/coreapi/tester_utils.cpp b/coreapi/tester_utils.cpp index 934e5758455f7ba7635c2b3fef44dfe1fd14029b..3a392afb09ce6b94ace3740e38e39e427edf9244 100644 --- a/coreapi/tester_utils.cpp +++ b/coreapi/tester_utils.cpp @@ -153,6 +153,11 @@ SalMediaDescription *_linphone_call_get_local_desc (const LinphoneCall *call) { Call::toCpp(call)->getActiveSession()))->getLocalDesc().get(); } +SalMediaDescription *_linphone_call_get_remote_desc (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast<LinphonePrivate::MediaSession>( + Call::toCpp(call)->getActiveSession()))->getRemoteDesc().get(); +} + SalMediaDescription *_linphone_call_get_result_desc (const LinphoneCall *call) { return L_GET_PRIVATE(static_pointer_cast<LinphonePrivate::MediaSession>( Call::toCpp(call)->getActiveSession()))->getResultDesc().get(); diff --git a/coreapi/tester_utils.h b/coreapi/tester_utils.h index 2fbb69495168e915d4937a15befd3f838f2d5fe3..1b378d7e3e7649a230502de762247bb42f35ff5f 100644 --- a/coreapi/tester_utils.h +++ b/coreapi/tester_utils.h @@ -42,6 +42,7 @@ LINPHONE_BEGIN_NAMESPACE class SalSubscribeOp; LINPHONE_END_NAMESPACE LINPHONE_PUBLIC LinphonePrivate::SalMediaDescription *_linphone_call_get_local_desc (const LinphoneCall *call); +LINPHONE_PUBLIC LinphonePrivate::SalMediaDescription *_linphone_call_get_remote_desc (const LinphoneCall *call); LINPHONE_PUBLIC LinphonePrivate::SalMediaDescription *_linphone_call_get_result_desc (const LinphoneCall *call); extern "C" { LINPHONE_PUBLIC LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, LinphonePrivate::SalEventOp *op, LinphoneSubscriptionDir dir, const char *name); diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index c51d5210e17e6f29d23d4dcffc20599006728870..4baed1a2ffa010e18aabfdc4824dcea3fa66df4e 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -48,7 +48,6 @@ set(ROOT_HEADER_FILES logging.h lpconfig.h misc.h - nat_policy.h payload_type.h player.h presence.h @@ -115,6 +114,7 @@ set(C_API_HEADER_FILES c-digest-authentication-policy.h c-types.h c-video-source-descriptor.h + c-nat-policy.h ) set(ENUMS_HEADER_FILES diff --git a/include/linphone/api/c-api.h b/include/linphone/api/c-api.h index 87829a2f1fb92cd39d8cb21ada7b4ff4db7c1a9c..3b817e552ded559b4cbc7b707cc071e6e05a6e9c 100644 --- a/include/linphone/api/c-api.h +++ b/include/linphone/api/c-api.h @@ -61,5 +61,6 @@ #include "linphone/api/c-digest-authentication-policy.h" #include "linphone/api/c-types.h" #include "linphone/api/c-video-source-descriptor.h" +#include "linphone/api/c-nat-policy.h" #endif // ifndef _L_C_API_H_ diff --git a/include/linphone/nat_policy.h b/include/linphone/api/c-nat-policy.h similarity index 81% rename from include/linphone/nat_policy.h rename to include/linphone/api/c-nat-policy.h index 5a4f13a4540a0a470e1e57b5e4dac5c1c9baebf5..59292741553b1964f1d124aed80e204255a13d0d 100644 --- a/include/linphone/nat_policy.h +++ b/include/linphone/api/c-nat-policy.h @@ -158,6 +158,48 @@ LINPHONE_PUBLIC const char * linphone_nat_policy_get_stun_server(const LinphoneN */ LINPHONE_PUBLIC void linphone_nat_policy_set_stun_server(LinphoneNatPolicy *policy, const char *stun_server); + +/** + * Get the mandatory v4 IP address to use with this NAT policy as server-reflexive candidate for ICE. + * Used when STUN or TURN are enabled. + * @param policy #LinphoneNatPolicy object @notnil + * @return the nat v4 address. @maybenil + */ +LINPHONE_PUBLIC const char * linphone_nat_policy_get_nat_v4_address(const LinphoneNatPolicy *policy); + +/** + * Set the mandatory v4 IP address to use with this NAT policy as server-reflexive candidate for ICE. + * The IP address is used only if no stun server is set for server-reflexive candidate gathering. + * Using this method is useful when Liblinphone is used in a server product, when the server + * does not own the public IP address. + * Used when STUN or TURN are enabled. + * @param policy #LinphoneNatPolicy object @notnil + * @param v4_address The STUN server to use with this NAT policy. @maybenil + */ +LINPHONE_PUBLIC void linphone_nat_policy_set_nat_v4_address(LinphoneNatPolicy *policy, const char *v4_address); + + +/** + * Get the mandatory v6 IP address to use with this NAT policy as server-reflexive candidate for ICE. + * Used when STUN or TURN are enabled. + * @param policy #LinphoneNatPolicy object @notnil + * @return the nat v4 address. @maybenil + */ +LINPHONE_PUBLIC const char * linphone_nat_policy_get_nat_v6_address(const LinphoneNatPolicy *policy); + +/** + * Set the mandatory v6 IP address to use with this NAT policy as server-reflexive candidate for ICE. + * The IP address is used only if no stun server is set for server-reflexive candidate gathering. + * Using this method is useful when Liblinphone is used in a server product, when the server + * does not own the public IP address. + * Used when STUN or TURN are enabled. + * @param policy #LinphoneNatPolicy object @notnil + * @param v4_address The STUN server to use with this NAT policy. @maybenil + */ +LINPHONE_PUBLIC void linphone_nat_policy_set_nat_v6_address(LinphoneNatPolicy *policy, const char *v4_address); + + + /** * Get the username used to authenticate with the STUN/TURN server. * The authentication will search for a #LinphoneAuthInfo with this username. @@ -205,7 +247,7 @@ LINPHONE_PUBLIC void linphone_nat_policy_enable_udp_turn_transport(LinphoneNatPo * @param policy #LinphoneNatPolicy object @notnil * @return Boolean value telling whether UDP TURN transport is enabled. */ -LINPHONE_PUBLIC bool_t linphone_nat_policy_udp_turn_transport_enabled(LinphoneNatPolicy *policy); +LINPHONE_PUBLIC bool_t linphone_nat_policy_udp_turn_transport_enabled(const LinphoneNatPolicy *policy); /** * Enable TCP TURN transport. @@ -221,7 +263,7 @@ LINPHONE_PUBLIC void linphone_nat_policy_enable_tcp_turn_transport(LinphoneNatPo * @param policy #LinphoneNatPolicy object @notnil * @return Boolean value telling whether TCP TURN transport is enabled. */ -LINPHONE_PUBLIC bool_t linphone_nat_policy_tcp_turn_transport_enabled(LinphoneNatPolicy *policy); +LINPHONE_PUBLIC bool_t linphone_nat_policy_tcp_turn_transport_enabled(const LinphoneNatPolicy *policy); /** * Enable TLS TURN transport. @@ -237,7 +279,7 @@ LINPHONE_PUBLIC void linphone_nat_policy_enable_tls_turn_transport(LinphoneNatPo * @param policy #LinphoneNatPolicy object @notnil * @return Boolean value telling whether TLS TURN transport is enabled. */ -LINPHONE_PUBLIC bool_t linphone_nat_policy_tls_turn_transport_enabled(LinphoneNatPolicy *policy); +LINPHONE_PUBLIC bool_t linphone_nat_policy_tls_turn_transport_enabled(const LinphoneNatPolicy *policy); /** * Returns the #LinphoneCore object managing this nat policy, if any. diff --git a/include/linphone/core.h b/include/linphone/core.h index b9ce6e1b2e02bc6038e221d71c977e38dceee4c6..c256075436fef2f5a6f0c2a42447fe4a2fdcdd57 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -54,7 +54,6 @@ #include "linphone/logging.h" #include "linphone/lpconfig.h" #include "linphone/misc.h" -#include "linphone/nat_policy.h" #include "linphone/payload_type.h" #include "linphone/player.h" #include "linphone/presence.h" @@ -2748,20 +2747,23 @@ LINPHONE_PUBLIC LinphoneUpnpState linphone_core_get_upnp_state(const LinphoneCor LINPHONE_PUBLIC const char * linphone_core_get_upnp_external_ipaddress(const LinphoneCore *core); /** - * Set the public IP address of NAT when using the firewall policy is set to use NAT. + * Deprecated. This function was used to force a given IP address to appear in SDP. + * Unfortunately, this cannot work as explained by https://www.rfc-editor.org/rfc/rfc5389#section-2 . * @param core #LinphoneCore object. @notnil * @param addr The public IP address of NAT to use. @maybenil + * @deprecated 12/10/2022 * @ingroup network_parameters */ -LINPHONE_PUBLIC void linphone_core_set_nat_address(LinphoneCore *core, const char *addr); +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_nat_address(LinphoneCore *core, const char *addr); /** - * Get the public IP address of NAT being used. + * Deprecated. Get the public IP address of NAT being used. * @param core #LinphoneCore object. @notnil * @return The public IP address of NAT being used. @maybenil + * @deprecated 12/10/2022 * @ingroup network_parameters */ -LINPHONE_PUBLIC const char *linphone_core_get_nat_address(const LinphoneCore *core); +LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_nat_address(const LinphoneCore *core); /** * Set the policy to use to pass through NATs/firewalls. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97c7553cad1e3cfbd3df28a839d7213ea5e08474..9cc76fdebdc86204a10992467dd4bea5fad9611e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -254,6 +254,7 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES logger/logger.h nat/ice-service.h nat/stun-client.h + nat/nat-policy.h object/app-data-container.h object/base-object-p.h object/base-object.h @@ -388,6 +389,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES c-wrapper/api/c-recorder-params.cpp c-wrapper/api/c-search-result.cpp c-wrapper/api/c-video-source-descriptor.cpp + c-wrapper/api/c-nat-policy.cpp c-wrapper/internal/c-sal.cpp c-wrapper/internal/c-tools.cpp call/call-log.cpp @@ -483,6 +485,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES logger/logger.cpp nat/ice-service.cpp nat/stun-client.cpp + nat/nat-policy.cpp object/app-data-container.cpp object/base-object.cpp object/clonable-object.cpp diff --git a/src/account/account-params.cpp b/src/account/account-params.cpp index ca4de70ac45dc3da4104bcf02cf15a959ad035be..f9968fe960c89544108461e58b1d9e9d8cbfeeef 100644 --- a/src/account/account-params.cpp +++ b/src/account/account-params.cpp @@ -23,7 +23,7 @@ #include "push-notification/push-notification-config.h" #include "c-wrapper/internal/c-tools.h" #include "linphone/api/c-address.h" -#include "linphone/nat_policy.h" +#include "nat/nat-policy.h" #include "linphone/types.h" #include "private.h" @@ -74,12 +74,24 @@ AccountParams::AccountParams (LinphoneCore *lc) { mPushNotificationAllowed = lc ? !!linphone_config_get_default_int(lc->config, "proxy", "push_notification_allowed", pushAllowedDefault) : pushAllowedDefault; mRemotePushNotificationAllowed = lc ? !!linphone_config_get_default_int(lc->config, "proxy", "remote_push_notification_allowed", remotePushAllowedDefault) : remotePushAllowedDefault; mRefKey = lc ? linphone_config_get_default_string(lc->config, "proxy", "refkey", "") : ""; + + /* CAUTION: the nat_policy_ref meaning in default values is different than in usual [nat_policy_%i] section. + * This is not consistent and error-prone. + * Normally, the nat_policy_ref refers to a "ref" entry within a [nat_policy_%i] section. + */ string natPolicyRef = lc ? linphone_config_get_default_string(lc->config, "proxy", "nat_policy_ref", "") : ""; if (!natPolicyRef.empty()) { - LinphoneNatPolicy *policy = linphone_config_create_nat_policy_from_section(lc->config, natPolicyRef.c_str()); - setNatPolicy(policy); - if (policy) { - linphone_nat_policy_unref(policy); + NatPolicy * policy = nullptr; + if (linphone_config_has_section(lc->config, natPolicyRef.c_str())){ + /* Odd method - to be deprecated, inconsistent */ + policy = new NatPolicy(L_GET_CPP_PTR_FROM_C_OBJECT(lc), NatPolicy::ConstructionMethod::FromSectionName, natPolicyRef); + }else{ + /* Usual method */ + policy = new NatPolicy(L_GET_CPP_PTR_FROM_C_OBJECT(lc), NatPolicy::ConstructionMethod::FromRefName, natPolicyRef); + } + if (policy){ + setNatPolicy(policy->toC()); + policy->unref(); } else { lError() << "Cannot create default nat policy with ref [" << natPolicyRef << "] for account [" << this << "]"; } @@ -853,8 +865,8 @@ void AccountParams::writeToConfigFile (LinphoneConfig *config, int index) { linphone_config_set_int(config, key, "publish_expires", mPublishExpires); if (mNatPolicy != NULL) { - linphone_config_set_string(config, key, "nat_policy_ref", mNatPolicy->ref); - linphone_nat_policy_save_to_config(mNatPolicy); + linphone_config_set_string(config, key, "nat_policy_ref", NatPolicy::toCpp(mNatPolicy)->getRef().c_str()); + NatPolicy::toCpp(mNatPolicy)->saveToConfig(); } linphone_config_set_string(config, key, "conference_factory_uri", mConferenceFactoryUri.c_str()); diff --git a/src/account/account.cpp b/src/account/account.cpp index 8069bea7b864718c2dced2dfaef979ffc691d7f5..159d45b49a6af6ade01dfe74d20c9882a5744c59 100644 --- a/src/account/account.cpp +++ b/src/account/account.cpp @@ -1186,7 +1186,6 @@ void Account::onAudioVideoConferenceFactoryAddressChanged (const LinphoneAddress } void Account::onNatPolicyChanged (LinphoneNatPolicy *policy) { - policy->lc = mCore; } LinphoneProxyConfig *Account::getConfig () const { diff --git a/src/c-wrapper/api/c-nat-policy.cpp b/src/c-wrapper/api/c-nat-policy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..066475e3597fc53e6ae1e9a05018dfba190d7118 --- /dev/null +++ b/src/c-wrapper/api/c-nat-policy.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2010-2019 Belledonne Communications SARL. + * + * This file is part of Liblinphone. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "linphone/api/c-nat-policy.h" +#include "nat/nat-policy.h" + + +using namespace ::LinphonePrivate; + +LinphoneNatPolicy * linphone_core_create_nat_policy(LinphoneCore *lc) { + return (new NatPolicy(L_GET_CPP_PTR_FROM_C_OBJECT(lc)))->toC(); +} + +LinphoneNatPolicy * linphone_core_create_nat_policy_from_config(LinphoneCore *core, const char *ref){ + return (new NatPolicy(L_GET_CPP_PTR_FROM_C_OBJECT(core), NatPolicy::ConstructionMethod::FromSectionName, ref))->toC(); +} + + +LinphoneNatPolicy *linphone_nat_policy_clone(const LinphoneNatPolicy *other){ + return (new NatPolicy(*NatPolicy::toCpp(other)))->toC(); +} + + +LinphoneNatPolicy * linphone_nat_policy_ref(LinphoneNatPolicy *policy) { + belle_sip_object_ref(policy); + return policy; +} + +void linphone_nat_policy_unref(LinphoneNatPolicy *policy) { + belle_sip_object_unref(policy); +} + +void *linphone_nat_policy_get_user_data(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->getUserData(); +} + +void linphone_nat_policy_set_user_data(LinphoneNatPolicy *policy, void *ud) { + NatPolicy::toCpp(policy)->setUserData(ud); +} + +void linphone_nat_policy_clear(LinphoneNatPolicy *policy) { + NatPolicy::toCpp(policy)->clear(); +} + +bool_t linphone_nat_policy_stun_enabled(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->stunEnabled() ? TRUE : FALSE; +} + +void linphone_nat_policy_enable_stun(LinphoneNatPolicy *policy, bool_t enable) { + NatPolicy::toCpp(policy)->enableStun(!!enable); +} + +bool_t linphone_nat_policy_turn_enabled(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->turnEnabled() ? TRUE : FALSE; +} + +void linphone_nat_policy_enable_turn(LinphoneNatPolicy *policy, bool_t enable) { + NatPolicy::toCpp(policy)->enableTurn(!!enable); +} + +bool_t linphone_nat_policy_ice_enabled(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->iceEnabled() ? TRUE : FALSE; +} + +void linphone_nat_policy_enable_ice(LinphoneNatPolicy *policy, bool_t enable) { + NatPolicy::toCpp(policy)->enableIce(!!enable); +} + +bool_t linphone_nat_policy_upnp_enabled(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->upnpEnabled() ? TRUE : FALSE; +} + +void linphone_nat_policy_enable_upnp(LinphoneNatPolicy *policy, bool_t enable) { + if (enable) { + ms_warning("uPnP NAT policy is no longer supported"); + } + NatPolicy::toCpp(policy)->enableUpnp(!!enable); +} + +const char * linphone_nat_policy_get_stun_server(const LinphoneNatPolicy *policy) { + return L_STRING_TO_C(NatPolicy::toCpp(policy)->getStunServer()); +} + +void linphone_nat_policy_resolve_stun_server(LinphoneNatPolicy *policy){ + NatPolicy::toCpp(policy)->resolveStunServer(); +} + +const struct addrinfo * linphone_nat_policy_get_stun_server_addrinfo(LinphoneNatPolicy *policy){ + return NatPolicy::toCpp(policy)->getStunServerAddrinfo(); +} + +void linphone_nat_policy_set_stun_server(LinphoneNatPolicy *policy, const char *stun_server) { + NatPolicy::toCpp(policy)->setStunServer(L_C_TO_STRING(stun_server)); +} + +const char * linphone_nat_policy_get_stun_server_username(const LinphoneNatPolicy *policy) { + return L_STRING_TO_C(NatPolicy::toCpp(policy)->getStunServerUsername()); +} + +void linphone_nat_policy_set_stun_server_username(LinphoneNatPolicy *policy, const char *username) { + NatPolicy::toCpp(policy)->setStunServerUsername(L_C_TO_STRING(username)); +} + + +void linphone_nat_policy_enable_udp_turn_transport(LinphoneNatPolicy *policy, bool_t enable) { + NatPolicy::toCpp(policy)->enableTurnUdp(!!enable); +} + +bool_t linphone_nat_policy_udp_turn_transport_enabled(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->turnUdpEnabled() ? TRUE : FALSE; +} + +void linphone_nat_policy_enable_tcp_turn_transport(LinphoneNatPolicy *policy, bool_t enable) { + NatPolicy::toCpp(policy)->enableTurnTcp(!!enable); +} + +bool_t linphone_nat_policy_tcp_turn_transport_enabled(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->turnTcpEnabled() ? TRUE : FALSE; +} + +void linphone_nat_policy_enable_tls_turn_transport(LinphoneNatPolicy *policy, bool_t enable) { + NatPolicy::toCpp(policy)->enableTurnTls(!!enable); +} + +bool_t linphone_nat_policy_tls_turn_transport_enabled(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->turnTlsEnabled() ? TRUE : FALSE; +} + +LinphoneCore *linphone_nat_policy_get_core(const LinphoneNatPolicy *policy) { + return NatPolicy::toCpp(policy)->getCore()->getCCore(); +} + +const char * linphone_nat_policy_get_nat_v4_address(const LinphoneNatPolicy *policy){ + return L_STRING_TO_C(NatPolicy::toCpp(policy)->getNatV4Address()); +} + +void linphone_nat_policy_set_nat_v4_address(LinphoneNatPolicy *policy, const char *v4_address){ + NatPolicy::toCpp(policy)->setNatV4Address(L_C_TO_STRING(v4_address)); +} + +const char * linphone_nat_policy_get_nat_v6_address(const LinphoneNatPolicy *policy){ + return L_STRING_TO_C(NatPolicy::toCpp(policy)->getNatV6Address()); +} + +void linphone_nat_policy_set_nat_v6_address(LinphoneNatPolicy *policy, const char *v6_address){ + NatPolicy::toCpp(policy)->setNatV6Address(L_C_TO_STRING(v6_address)); +} diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index 4c1ddc772a90bd0a7126080b3672af7d9e45bfb4..f892c1556e938c9fbfe9fa8fc092fad5c3a33a4c 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -260,7 +260,6 @@ BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch), BELLE_SIP_TYPE_ID(LinphoneLoggingService), BELLE_SIP_TYPE_ID(LinphoneLoggingServiceCbs), BELLE_SIP_TYPE_ID(LinphoneMagicSearchCbs), -BELLE_SIP_TYPE_ID(LinphoneNatPolicy), BELLE_SIP_TYPE_ID(LinphoneParticipant), BELLE_SIP_TYPE_ID(LinphoneParticipantDevice), BELLE_SIP_TYPE_ID(LinphoneParticipantDeviceCbs), diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h index 7f3e0d2cfae5415cbd3772ee7d1b5e7fa5067321..40342f185586a1dec906759445f471817feec3f2 100644 --- a/src/conference/session/media-session-p.h +++ b/src/conference/session/media-session-p.h @@ -84,6 +84,7 @@ public: IceService &getIceService() const { return streamsGroup->getIceService(); } std::shared_ptr<SalMediaDescription> getLocalDesc () const { return localDesc; } + std::shared_ptr<SalMediaDescription> getRemoteDesc() const { return streamsGroup->getCurrentOfferAnswerContext().remoteMediaDescription; } int setupEncryptionKey (SalSrtpCryptoAlgo & crypto, MSCryptoSuite suite, unsigned int tag) const; std::vector<SalSrtpCryptoAlgo> generateNewCryptoKeys() const; diff --git a/src/nat/ice-service.cpp b/src/nat/ice-service.cpp index fb992a14c66375d63c2a04116a2b714101dc2900..6a227b420a65480846c87c6953edeaf93d74dd63 100644 --- a/src/nat/ice-service.cpp +++ b/src/nat/ice-service.cpp @@ -286,6 +286,38 @@ int IceService::gatherLocalCandidates(){ return 0; } +void IceService::addPredefinedSflrxCandidates(const NatPolicy *natPolicy){ + if (!natPolicy) return; + bool ipv6Allowed = linphone_core_ipv6_enabled(getCCore()); + const string &ipv4 = natPolicy->getNatV4Address(); + const string &ipv6 = natPolicy->getNatV6Address(); + if (ipv4.empty() && ipv6.empty()) return; + const auto & streams = mStreamsGroup.getStreams(); + for (auto & stream : streams){ + if (!stream) continue; + size_t index = stream->getIndex(); + IceCheckList *cl = ice_session_check_list(mIceSession, (int)index); + if (cl && ice_check_list_state(cl) != ICL_Completed && !ice_check_list_candidates_gathered(cl)) { + if (!ipv4.empty()){ + ice_add_local_candidate(cl, "srflx", AF_INET, L_STRING_TO_C(ipv4), stream->getPortConfig().rtpPort, ICE_RTP_COMPONENT_ID, nullptr); + } + if (!ipv6.empty() && ipv6Allowed){ + ice_add_local_candidate(cl, "srflx", AF_INET6, L_STRING_TO_C(ipv6), stream->getPortConfig().rtpPort, ICE_RTP_COMPONENT_ID, nullptr); + } + if (!rtp_session_rtcp_mux_enabled(cl->rtp_session)) { + if (!ipv4.empty()){ + ice_add_local_candidate(cl, "srflx", AF_INET, L_STRING_TO_C(ipv4), stream->getPortConfig().rtcpPort, ICE_RTCP_COMPONENT_ID, nullptr); + } + if (!ipv6.empty() && ipv6Allowed){ + ice_add_local_candidate(cl, "srflx", AF_INET6, L_STRING_TO_C(ipv6), stream->getPortConfig().rtcpPort, ICE_RTCP_COMPONENT_ID, nullptr); + } + } + } + } + ice_session_set_base_for_srflx_candidates(mIceSession); + lInfo() << "Configuration-defined server reflexive candidates added to check lists."; +} + /** Return values: * 1: STUN gathering is started * 0: no STUN gathering is started, but it's ok to proceed with ICE anyway (with local candidates only or because STUN gathering was already done before) @@ -295,9 +327,10 @@ int IceService::gatherIceCandidates () { const struct addrinfo *ai = nullptr; int err = 0; - LinphoneNatPolicy *natPolicy = getMediaSessionPrivate().getNatPolicy(); - if (natPolicy && linphone_nat_policy_stun_server_activated(natPolicy)) { - ai = linphone_nat_policy_get_stun_server_addrinfo(natPolicy); + LinphoneNatPolicy *cNatPolicy = getMediaSessionPrivate().getNatPolicy(); + NatPolicy *natPolicy = cNatPolicy ? NatPolicy::toCpp(cNatPolicy) : nullptr; + if (natPolicy && natPolicy->stunServerActivated()) { + ai = natPolicy->getStunServerAddrinfo(); if (ai) ai = getIcePreferredStunServerAddrinfo(ai); else @@ -314,16 +347,16 @@ int IceService::gatherIceCandidates () { return -1; } - if (ai && natPolicy && linphone_nat_policy_stun_server_activated(natPolicy)) { - string server = linphone_nat_policy_get_stun_server(natPolicy); - lInfo() << "ICE: gathering candidates from [" << server << "] using " << (linphone_nat_policy_turn_enabled(natPolicy) ? "TURN" : "STUN"); + if (ai && natPolicy && natPolicy->stunServerActivated()) { + const string &server = natPolicy->getStunServer(); + lInfo() << "ICE: gathering candidates from [" << server << "] using " << (natPolicy->turnEnabled() ? "TURN" : "STUN"); // Gather local srflx candidates. - if (linphone_nat_policy_turn_enabled(natPolicy)) { + if (natPolicy->turnEnabled()) { ice_session_enable_turn(mIceSession, TRUE); - if (linphone_nat_policy_tls_turn_transport_enabled(natPolicy)) { + if (natPolicy->turnTlsEnabled()) { ice_session_set_turn_transport(mIceSession, "tls"); - } else if (linphone_nat_policy_tcp_turn_transport_enabled(natPolicy)) { + } else if (natPolicy->turnTcpEnabled()) { ice_session_set_turn_transport(mIceSession, "tcp"); } else { ice_session_set_turn_transport(mIceSession, "udp"); @@ -333,13 +366,14 @@ int IceService::gatherIceCandidates () { char host[NI_MAXHOST]; int port = 0; - linphone_parse_host_port(linphone_nat_policy_get_stun_server(natPolicy), host, sizeof(host), &port); + linphone_parse_host_port(server.c_str(), host, sizeof(host), &port); ice_session_set_turn_cn(mIceSession, host); } ice_session_set_stun_auth_requested_cb(mIceSession, MediaSessionPrivate::stunAuthRequestedCb, &getMediaSessionPrivate()); err = ice_session_gather_candidates(mIceSession, ai->ai_addr, (socklen_t)ai->ai_addrlen) ? 1 : 0; } else { - lInfo() << "ICE: bypass candidates gathering"; + lInfo() << "ICE: bypass server-reflexive candidates gathering"; + addPredefinedSflrxCandidates(natPolicy); } if (err == 0) gatheringFinished(); return err; diff --git a/src/nat/ice-service.h b/src/nat/ice-service.h index 9d2f4703cb8c09f2705316a38ddb04c6a606412d..914b7d72e568a5afbc422e2803cd8d1c75034194 100644 --- a/src/nat/ice-service.h +++ b/src/nat/ice-service.h @@ -24,6 +24,7 @@ #include "conference/session/call-session.h" #include "conference/session/media-description-renderer.h" +#include "nat/nat-policy.h" LINPHONE_BEGIN_NAMESPACE @@ -132,6 +133,7 @@ private: void checkSession(IceRole role, bool preferIpv6DefaultCandidates); int gatherIceCandidates (); int gatherLocalCandidates(); + void addPredefinedSflrxCandidates(const NatPolicy *natPolicy); bool hasRelayCandidates(const SalMediaDescription &md)const; void chooseDefaultCandidates(const OfferAnswerContext & ctx); StreamsGroup & mStreamsGroup; diff --git a/src/nat/nat-policy.cpp b/src/nat/nat-policy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5795e0cf7e17c43b834bdf90511756d7feb8dc0 --- /dev/null +++ b/src/nat/nat-policy.cpp @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2010-2022 Belledonne Communications SARL. + * + * This file is part of Liblinphone. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "nat-policy.h" + +#include <cstring> + +#include "private.h" + +LINPHONE_BEGIN_NAMESPACE + +NatPolicy::NatPolicy(const std::shared_ptr<Core> &core, NatPolicy::ConstructionMethod method, const std::string &value) : CoreAccessor(core){ + LpConfig *config = linphone_core_get_config(core->getCCore()); + if (method == ConstructionMethod::Default){ + mRef = value; + if (mRef.empty()){ + char ref[17] = { 0 }; + belle_sip_random_token(ref, 16); + mRef = ref; + } + }else if (method == ConstructionMethod::FromSectionName){ + initFromSection(config, value.c_str()); + } else if (method == ConstructionMethod::FromRefName){ + int index; + + for (index = 0; ; index++) { + std::ostringstream section; + section << "nat_policy_" << index; + if (linphone_config_has_section(config, section.str().c_str())) { + const char *config_ref = linphone_config_get_string(config, section.str().c_str(), "ref", NULL); + if ((config_ref != NULL) && (strcmp(config_ref, value.c_str()) == 0)) { + initFromSection(config, section.str().c_str()); + break; + } + } else { + lError() << "There is no NatPolicy with ref [" << value << "]"; + break; + } + } + } +} + +NatPolicy::NatPolicy(const NatPolicy &other): HybridObject<LinphoneNatPolicy, NatPolicy>(other), CoreAccessor(other.getCore()){ + mStunServer = other.mStunServer; + mStunServerUsername = other.mStunServerUsername; + mRef = other.mRef; + mStunEnabled = other.mStunEnabled; + mTurnEnabled = other.mTurnEnabled; + mIceEnabled = other.mIceEnabled; + mUpnpEnabled = other.mUpnpEnabled; + mTurnUdpEnabled = other.mTurnUdpEnabled; + mTurnTcpEnabled = false; + mTurnTlsEnabled = false; +} + +NatPolicy::~NatPolicy(){ + clearResolverContexts(); +} + +void NatPolicy::clearResolverContexts(){ + if (mStunResolverContext) { + belle_sip_resolver_context_cancel(mStunResolverContext); + belle_sip_object_unref(mStunResolverContext); + mStunResolverContext = nullptr; + } + if (mResolverResults){ + belle_sip_object_unref(mResolverResults); + mResolverResults = nullptr; + } +} + +/* Simply cancel pending DNS resoltion, as the core is going to shutdown.*/ +void NatPolicy::release(){ + clearResolverContexts(); +} + +bool NatPolicy::stunServerActivated() const{ + return !mStunServer.empty() && (mStunEnabled || mTurnEnabled); +} + +void NatPolicy::saveToConfig(LinphoneConfig *config, int index) const{ + char *section; + bctbx_list_t *l = NULL; + + section = belle_sip_strdup_printf("nat_policy_%i", index); + linphone_config_set_string(config, section, "ref", mRef.c_str()); + linphone_config_set_string(config, section, "stun_server", mStunServer.c_str()); + linphone_config_set_string(config, section, "stun_server_username", mStunServerUsername.c_str()); + if (mUpnpEnabled) { + l = bctbx_list_append(l, (void *)"upnp"); + } else { + if (mStunEnabled) l = bctbx_list_append(l, (void *)"stun"); + if (mTurnEnabled) l = bctbx_list_append(l, (void *)"turn"); + if (mIceEnabled) l = bctbx_list_append(l, (void *)"ice"); + } + linphone_config_set_string_list(config, section, "protocols", l); + belle_sip_free(section); + bctbx_list_free(l); +} + +void NatPolicy::saveToConfig() { + LinphoneConfig *config = linphone_core_get_config(getCore()->getCCore()); + char *section; + int index; + bool_t finished = FALSE; + + for (index = 0; finished != TRUE; index++) { + section = belle_sip_strdup_printf("nat_policy_%i", index); + if (linphone_config_has_section(config, section)) { + const char *config_ref = linphone_config_get_string(config, section, "ref", NULL); + if ((config_ref != NULL) && (strcmp(config_ref, mRef.c_str()) == 0)) { + saveToConfig(config, index); + finished = TRUE; + } + } else { + saveToConfig(config, index); + finished = TRUE; + } + belle_sip_free(section); + } +} + +void NatPolicy::clear(){ + clearResolverContexts(); + mStunServer.clear(); + mStunServerUsername.clear(); + mStunEnabled = false; + mTurnEnabled = false; + mIceEnabled = false; + mUpnpEnabled = false; + mTurnUdpEnabled = false; + mTurnTcpEnabled = false; + mTurnTlsEnabled = false; +} + +void NatPolicy::setStunServer(const std::string &stunServer){ + mStunServer = stunServer; + clearResolverContexts(); + resolveStunServer(); +} + +const std::string &NatPolicy::getStunServer()const{ + return mStunServer; +} + +void NatPolicy::setStunServerUsername(const std::string &stunServerUsername){ + mStunServerUsername = stunServerUsername; +} +const std::string &NatPolicy::getStunServerUsername()const{ + return mStunServerUsername; +} + +void NatPolicy::setNatV4Address(const std::string &natV4Address){ + mNatV4Address = natV4Address; +} + +const std::string & NatPolicy::getNatV4Address()const{ + return mNatV4Address; +} + +void NatPolicy::setNatV6Address(const std::string &natV6Address){ + mNatV6Address = natV6Address; +} +const std::string & NatPolicy::getNatV6Address()const{ + return mNatV6Address; +} + +void NatPolicy::stunServerResolved(belle_sip_resolver_results_t *results){ + if (mResolverResults) { + belle_sip_object_unref(mResolverResults); + mResolverResults = nullptr; + } + + if (belle_sip_resolver_results_get_addrinfos(results)) { + ms_message("Stun server resolution successful."); + belle_sip_object_ref(results); + mResolverResults = results; + } else { + ms_warning("Stun server resolution failed."); + } + if (mStunResolverContext){ + belle_sip_object_unref(mStunResolverContext); + mStunResolverContext = nullptr; + } + +} + +void NatPolicy::sStunServerResolved(void *data, belle_sip_resolver_results_t *results) { + NatPolicy *policy = static_cast<NatPolicy*>(data); + policy->stunServerResolved(results); +} + +void NatPolicy::resolveStunServer() { + LinphoneCore *lc = getCore()->getCCore(); + const char *service = NULL; + + if (stunServerActivated() && (lc->sal != NULL) && !mStunResolverContext) { + char host[NI_MAXHOST]; + int port = 0; + linphone_parse_host_port(mStunServer.c_str(), host, sizeof(host), &port); + if (mTurnEnabled) service = "turn"; + else if (mStunEnabled) service = "stun"; + if (service != NULL) { + int family = AF_INET; + if (linphone_core_ipv6_enabled(lc) == TRUE) family = AF_INET6; + ms_message("Starting stun server resolution [%s]", host); + if (port == 0) { + port = 3478; + mStunResolverContext = lc->sal->resolve(service, "udp", host, port, family, sStunServerResolved, this); + } else { + mStunResolverContext = lc->sal->resolveA(host, port, family, sStunServerResolved, this); + } + if (mStunResolverContext) belle_sip_object_ref(mStunResolverContext); + } + } +} + +const struct addrinfo * NatPolicy::getStunServerAddrinfo() { + /* + * It is critical not to block for a long time if it can't be resolved, otherwise this stucks the main thread when making a call. + * On the contrary, a fully asynchronous call initiation is complex to develop. + * The compromise is then: + * - have a cache of the stun server addrinfo + * - this cached value is returned when it is non-null + * - an asynchronous resolution is asked each time this function is called to ensure frequent refreshes of the cached value. + * - if no cached value exists, block for a short time; this case must be unprobable because the resolution will be asked each + * time the stun server value is changed. + */ + if (stunServerActivated() && (mResolverResults == nullptr)) { + int wait_ms = 0; + int wait_limit = 1000; + resolveStunServer(); + while ((mResolverResults == nullptr) && (mStunResolverContext != nullptr) && (wait_ms < wait_limit)) { + getCore()->getCCore()->sal->iterate(); + ms_usleep(10000); + wait_ms += 10; + } + } + return mResolverResults ? belle_sip_resolver_results_get_addrinfos(mResolverResults) : nullptr; +} + +void NatPolicy::initFromSection(const LinphoneConfig *config, const char* section) { + mRef = linphone_config_get_string(config, section, "ref", ""); + mStunServer = linphone_config_get_string(config, section, "stun_server", ""); + mStunServerUsername = linphone_config_get_string(config, section, "stun_server_username", ""); + mTurnUdpEnabled = !!linphone_config_get_bool(config, section, "turn_enable_udp", TRUE); + mTurnTcpEnabled = !!linphone_config_get_bool(config, section, "turn_enable_tcp", FALSE); + mTurnTlsEnabled = !!linphone_config_get_bool(config, section, "turn_enable_tls", FALSE); + bctbx_list_t *l = linphone_config_get_string_list(config, section, "protocols", NULL); + + if (l != NULL) { + bctbx_list_t *elem; + for (elem = l; elem != NULL; elem = elem->next) { + const char *value = (const char *)elem->data; + if (strcmp(value, "stun") == 0) enableStun(true); + else if (strcmp(value, "turn") == 0) enableTurn(true); + else if (strcmp(value, "ice") == 0) enableIce(true); + else if (strcmp(value, "upnp") == 0) mUpnpEnabled = true; + } + bctbx_list_free_with_data(l, (bctbx_list_free_func)ms_free); + } +} + + + + + +LINPHONE_END_NAMESPACE + diff --git a/src/nat/nat-policy.h b/src/nat/nat-policy.h new file mode 100644 index 0000000000000000000000000000000000000000..e3583f20e81b5bd9b6682c74db21e3f766752095 --- /dev/null +++ b/src/nat/nat-policy.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2010-2022 Belledonne Communications SARL. + * + * This file is part of Liblinphone. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef nat_policy_hh +#define nat_policy_hh + +#include "c-wrapper/c-wrapper.h" + + +LINPHONE_BEGIN_NAMESPACE + + + +class NatPolicy : public bellesip::HybridObject<LinphoneNatPolicy, NatPolicy>, public CoreAccessor{ +public: + enum class ConstructionMethod{ + Default, + FromSectionName, + FromRefName + }; + NatPolicy(const std::shared_ptr<Core> &core, ConstructionMethod method = ConstructionMethod::Default, const std::string &value = ""); + NatPolicy(const NatPolicy &other); + ~NatPolicy(); + + void setStunServer(const std::string &stunServer); + const std::string &getStunServer()const; + + void setStunServerUsername(const std::string &stunServerUsername); + const std::string &getStunServerUsername()const; + + void setNatV4Address(const std::string &natV4Address); + const std::string & getNatV4Address()const; + + void setNatV6Address(const std::string &natV6Address); + const std::string & getNatV6Address()const; + + void enableStun(bool enable){ mStunEnabled = enable; }; + bool stunEnabled() const { return mStunEnabled; }; + + void enableTurn(bool enable){ mTurnEnabled = enable; }; + bool turnEnabled() const { return mTurnEnabled; }; + + void enableIce(bool enable){ mIceEnabled = enable; }; + bool iceEnabled() const { return mIceEnabled; }; + + void enableUpnp(bool enable){ mUpnpEnabled = enable; }; + bool upnpEnabled() const { return mUpnpEnabled; }; + + void enableTurnUdp(bool enable){ mTurnUdpEnabled = enable; }; + bool turnUdpEnabled() const { return mTurnUdpEnabled; }; + + void enableTurnTcp(bool enable){ mTurnTcpEnabled = enable; }; + bool turnTcpEnabled() const { return mTurnTcpEnabled; }; + + void enableTurnTls(bool enable){ mTurnTlsEnabled = enable; }; + bool turnTlsEnabled() const { return mTurnTlsEnabled; }; + + void setUserData(void *d){ mUserData = d ;} + void *getUserData()const{ return mUserData; } + + const std::string &getRef()const{ return mRef; } + + const struct addrinfo * getStunServerAddrinfo(); + + void clear(); + void release(); + bool stunServerActivated()const; + void saveToConfig(); + void resolveStunServer(); +private: + void saveToConfig(LinphoneConfig *config, int index) const; + void initFromSection(const LinphoneConfig *config, const char* section); + static void sStunServerResolved(void *data, belle_sip_resolver_results_t *results); + void stunServerResolved(belle_sip_resolver_results_t *results); + void clearResolverContexts(); + void *mUserData = nullptr; + belle_sip_resolver_context_t *mStunResolverContext = nullptr; + belle_sip_resolver_results_t *mResolverResults = nullptr; + std::string mStunServer; + std::string mStunServerUsername; + std::string mRef; + std::string mNatV4Address; + std::string mNatV6Address; + bool mStunEnabled = false; + bool mTurnEnabled = false; + bool mIceEnabled = false; + bool mUpnpEnabled = false; + bool mTurnUdpEnabled = false; + bool mTurnTcpEnabled = false; + bool mTurnTlsEnabled = false; +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/src/sal/sal_stream_description.h b/src/sal/sal_stream_description.h index 1d6d81c2ea3921b1015fedc85591333e94442f13..3c6c42bc1a99a22d4c4efd3bc2226cc631d10169 100644 --- a/src/sal/sal_stream_description.h +++ b/src/sal/sal_stream_description.h @@ -144,6 +144,7 @@ class LINPHONE_PUBLIC SalStreamDescription { const std::string & getIceUfrag() const; const std::string & getIcePwd() const; bool getIceMismatch() const; + const std::vector<SalIceCandidate> & getIceCandidates()const{return ice_candidates; } const SalIceCandidate & getIceCandidateAtIndex(const std::size_t & idx) const; const SalIceRemoteCandidate & getIceRemoteCandidateAtIndex(const std::size_t & idx) const; diff --git a/src/utils/if-addrs.cpp b/src/utils/if-addrs.cpp index d70760fd62ca0b7925109fbe6bc797f7201d687f..5b5151959304680fe57da0e9a75d886c9031f482 100644 --- a/src/utils/if-addrs.cpp +++ b/src/utils/if-addrs.cpp @@ -137,7 +137,7 @@ public: } }; -void getAddress(IP_ADAPTER_UNICAST_ADDRESS * unicastAddress, std::list<AddressData> * pList){ +static void getAddress(IP_ADAPTER_UNICAST_ADDRESS * unicastAddress, std::list<AddressData> * pList){ SOCKET_ADDRESS * pAddr = &unicastAddress->Address; char szAddr[INET6_ADDRSTRLEN]; DWORD dwSize = INET6_ADDRSTRLEN; diff --git a/tester/call_ice_tester.cpp b/tester/call_ice_tester.cpp index d7233f180d9b322deb69ba320a05346ee7cef887..2e7489e30222509027891f6c6d12c5f6a2f0b93d 100644 --- a/tester/call_ice_tester.cpp +++ b/tester/call_ice_tester.cpp @@ -248,6 +248,69 @@ static bool_t is_matching_a_local_address(const std::string &ip, const bctbx_lis } +static bool assert_ice_candidate_presence(const LinphonePrivate::SalMediaDescription *md, const std::string &type, const std::string &addr){ + const LinphonePrivate::SalStreamDescription &st = md->getStreamIdx(0); + for (const auto & candidate : st.getIceCandidates()){ + if (candidate.addr == addr && candidate.type == type) return true; + } + return false; +} + +/* + * this test setups hardcoded non working server-reflexive address, to simulate what would happen in a server that is behind a nat. + */ +static void call_with_configured_sflrx_addresses(void){ + LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCall *pauline_call, *marie_call; + const char *mariev4 = "5.135.31.160"; + const char *mariev6 = "2001:41d0:303:3aee::1"; + const char *paulinev4 = "5.135.31.161"; + const char *paulinev6 = "2001:41d0:303:3aee::2"; + + LinphoneNatPolicy *pol = linphone_core_create_nat_policy(marie->lc); + linphone_nat_policy_enable_ice(pol, TRUE); + linphone_nat_policy_set_nat_v4_address(pol, mariev4); + linphone_nat_policy_set_nat_v6_address(pol, mariev6); + linphone_core_set_nat_policy(marie->lc, pol); + linphone_nat_policy_unref(pol); + + pol = linphone_core_create_nat_policy(pauline->lc); + linphone_nat_policy_enable_ice(pol, TRUE); + linphone_nat_policy_set_nat_v4_address(pol, paulinev4); + linphone_nat_policy_set_nat_v6_address(pol, paulinev6); + linphone_core_set_nat_policy(pauline->lc, pol); + linphone_nat_policy_unref(pol); + + marie_call = linphone_core_invite_address(marie->lc, pauline->identity); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1)); + pauline_call = linphone_core_get_current_call(pauline->lc); + + if (marie_call && pauline_call){ + linphone_call_accept(pauline_call); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); + /*check immmediately that the offer and answer have expected sflrx candidates.*/ + BC_ASSERT_TRUE(assert_ice_candidate_presence(_linphone_call_get_remote_desc(pauline_call), + "srflx", mariev4)); + BC_ASSERT_TRUE(assert_ice_candidate_presence(_linphone_call_get_remote_desc(marie_call), + "srflx", paulinev4)); + if (liblinphone_tester_ipv6_available()){ + BC_ASSERT_TRUE(assert_ice_candidate_presence(_linphone_call_get_remote_desc(pauline_call), + "srflx", mariev6)); + BC_ASSERT_TRUE(assert_ice_candidate_presence(_linphone_call_get_remote_desc(marie_call), + "srflx", paulinev6)); + } + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2)); + check_ice(marie, pauline, LinphoneIceStateHostConnection); + } + end_call(marie, pauline); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} /* * this test checks that default candidates are correct (c= line shall be set to the ICE default candidate). @@ -858,6 +921,7 @@ static test_t call_with_ice_tests[] = { TEST_ONE_TAG("Call with ICE with default default candidate", call_with_ice_with_default_candidate_relay_or_stun, "ICE"), TEST_ONE_TAG("Call with ICE without stun server", call_with_ice_without_stun, "ICE"), TEST_ONE_TAG("Call with ICE without stun server one side", call_with_ice_without_stun2, "ICE"), + TEST_ONE_TAG("Call with ICE and configured server-reflexive addresses", call_with_configured_sflrx_addresses, "ICE"), TEST_ONE_TAG("Call with ICE and stun server not responding", call_with_ice_stun_not_responding, "ICE"), TEST_ONE_TAG("Call with ICE ufrag and password set in SDP m line", call_with_ice_ufrag_and_password_set_in_sdp_m_line, "ICE"), TEST_ONE_TAG("Call with ICE ufrag and password set in SDP m line 2", call_with_ice_ufrag_and_password_set_in_sdp_m_line_2, "ICE"), diff --git a/tester/proxy_config_tester.c b/tester/proxy_config_tester.c index 49a8e8abb6f6c62d8285bba697e8516edc6fd323..2f059c390eb9ce5afd41ba47d1c8cc1d1e5cc8db 100644 --- a/tester/proxy_config_tester.c +++ b/tester/proxy_config_tester.c @@ -240,6 +240,7 @@ static void load_dynamic_proxy_config(void) { nat_policy = linphone_proxy_config_get_nat_policy(proxy); if (BC_ASSERT_PTR_NOT_NULL(nat_policy)) { + BC_ASSERT_STRING_EQUAL(linphone_nat_policy_get_stun_server(nat_policy), "stun.linphone.org"); BC_ASSERT_TRUE(linphone_nat_policy_ice_enabled(nat_policy)); BC_ASSERT_TRUE(linphone_nat_policy_stun_enabled(nat_policy)); BC_ASSERT_FALSE(linphone_nat_policy_turn_enabled(nat_policy));