diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 7ee7180dde23e1b598b26e0386fb78113f29e595..775e785a7a0da83ca8aa626ee94bcb14fd802b8f 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -6007,9 +6007,8 @@ void linphone_core_enable_mic(LinphoneCore *lc, bool_t enable) { const bctbx_list_t *list; const bctbx_list_t *elem; - ms_message("linphone_core_enable_mic(): new state is [%s], current state is [%s]", - enable ? "enabled" : "disabled", - lc->sound_conf.mic_enabled ? "enabled" : "disabled"); + ms_message("linphone_core_enable_mic(): new state is [%s], current state is [%s]", enable ? "enabled" : "disabled", + lc->sound_conf.mic_enabled ? "enabled" : "disabled"); lc->sound_conf.mic_enabled = enable; /* this is a global switch read everywhere the microphone is used. */ /* apply to conference and calls */ if (linphone_core_is_in_conference(lc)) { @@ -6056,7 +6055,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); - NatPolicy::toCpp(lc->nat_policy)->saveToConfig(); + L_GET_PRIVATE_FROM_C_OBJECT(lc)->writeNatPolicyConfigurations(); } else { linphone_config_set_string(lc->config, "net", "stun_server", server); } @@ -6175,7 +6174,7 @@ void linphone_core_set_nat_policy(LinphoneCore *lc, LinphoneNatPolicy *policy) { /*start an immediate (but asynchronous) resolution.*/ linphone_nat_policy_resolve_stun_server(policy); linphone_config_set_string(lc->config, "net", "nat_policy_ref", NatPolicy::toCpp(policy)->getRef().c_str()); - NatPolicy::toCpp(policy)->saveToConfig(); + L_GET_PRIVATE_FROM_C_OBJECT(lc)->writeNatPolicyConfigurations(); } lc->sal->enableNatHelper(!!linphone_config_get_int(lc->config, "net", "enable_nat_helper", 1)); diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 77872e78845b3e9871c7bf43fa707ac2d7786ba3..bfa6e5824f75d350ac50fb3dd6b01ec313b7eb38 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -112,8 +112,10 @@ struct _LpConfig { BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneConfig); BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneConfig); +#ifndef _MSC_VER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" +#endif char *lp_realpath(const char *file, char *name) { #if defined(_WIN32) || defined(__QNX__) || defined(__ANDROID__) diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 674b902fba8caff64c02cfd3a97116c56c5dc6e5..f7b4692b6970e9c4020e51e7d0554a9a47c0ce04 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -44,6 +44,7 @@ #include "mediastreamer2/mediastream.h" +#include "core/core-p.h" #include "core/core.h" #include "enum.h" #include "private.h" @@ -81,6 +82,7 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc) { /*to ensure removed configs are erased:*/ linphone_proxy_config_write_to_config_file(lc->config, NULL, i); linphone_config_set_int(lc->config, "sip", "default_proxy", linphone_core_get_default_proxy_config_index(lc)); + L_GET_PRIVATE_FROM_C_OBJECT(lc)->writeNatPolicyConfigurations(); } static void linphone_proxy_config_init(LinphoneCore *lc, LinphoneProxyConfig *cfg) { diff --git a/src/account/account-params.cpp b/src/account/account-params.cpp index d0705720705debaa9728d54154ee7654a89cece5..e1a594181a43a0d98958ff4a300fd09ba2fdb388 100644 --- a/src/account/account-params.cpp +++ b/src/account/account-params.cpp @@ -108,8 +108,7 @@ AccountParams::AccountParams(LinphoneCore *lc) { natPolicyRef); } if (policy) { - setNatPolicy(policy->toC()); - policy->unref(); + setNatPolicy(policy->toSharedPtr()); } else { lError() << "Cannot create default nat policy with ref [" << natPolicyRef << "] for account [" << this << "]"; @@ -234,18 +233,19 @@ AccountParams::AccountParams(LinphoneCore *lc, int index) : AccountParams(lc) { const char *nat_policy_ref = linphone_config_get_string(config, key, "nat_policy_ref", NULL); if (nat_policy_ref != NULL) { - if (mNatPolicy) linphone_nat_policy_unref(mNatPolicy); /* 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. */ + LinphoneNatPolicy *natPolicy; if (linphone_config_has_section(config, nat_policy_ref)) { /* Odd method - to be deprecated, inconsistent */ - mNatPolicy = linphone_core_create_nat_policy_from_config(lc, nat_policy_ref); + natPolicy = linphone_core_create_nat_policy_from_config(lc, nat_policy_ref); } else { /* Usual method */ - mNatPolicy = linphone_core_create_nat_policy_from_ref(lc, nat_policy_ref); + natPolicy = linphone_core_create_nat_policy_from_ref(lc, nat_policy_ref); } + mNatPolicy = NatPolicy::toCpp(natPolicy)->toSharedPtr(); } mConferenceFactoryUri = @@ -323,7 +323,6 @@ AccountParams::~AccountParams() { if (mProxyAddress) linphone_address_unref(mProxyAddress); if (mRoutes) bctbx_list_free_with_data(mRoutes, (bctbx_list_free_func)linphone_address_unref); if (mRoutesString) bctbx_list_free_with_data(mRoutesString, (bctbx_list_free_func)bctbx_free); - if (mNatPolicy) linphone_nat_policy_unref(mNatPolicy); if (mPushNotificationConfig) mPushNotificationConfig->unref(); if (mAudioVideoConferenceFactoryAddress) linphone_address_unref(mAudioVideoConferenceFactoryAddress); if (mCustomContact) linphone_address_unref(mCustomContact); @@ -557,11 +556,7 @@ void AccountParams::setAvpfMode(LinphoneAVPFMode avpfMode) { mAvpfMode = avpfMode; } -void AccountParams::setNatPolicy(LinphoneNatPolicy *natPolicy) { - if (natPolicy != nullptr) { - linphone_nat_policy_ref(natPolicy); /* Prevent object destruction if the same policy is used */ - } - if (mNatPolicy != nullptr) linphone_nat_policy_unref(mNatPolicy); +void AccountParams::setNatPolicy(const shared_ptr<NatPolicy> &natPolicy) { mNatPolicy = natPolicy; } @@ -750,7 +745,7 @@ LinphoneAVPFMode AccountParams::getAvpfMode() const { return mAvpfMode; } -LinphoneNatPolicy *AccountParams::getNatPolicy() const { +shared_ptr<NatPolicy> AccountParams::getNatPolicy() const { return mNatPolicy; } @@ -916,8 +911,7 @@ 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", NatPolicy::toCpp(mNatPolicy)->getRef().c_str()); - NatPolicy::toCpp(mNatPolicy)->saveToConfig(); + linphone_config_set_string(config, key, "nat_policy_ref", mNatPolicy->getRef().c_str()); } linphone_config_set_string(config, key, "conference_factory_uri", mConferenceFactoryUri.c_str()); diff --git a/src/account/account-params.h b/src/account/account-params.h index 3bb7104e270509feb5c03b81216ba2df518f55ed..64a02dd0aa89af20ea7f605cc6c0b704fcf52be9 100644 --- a/src/account/account-params.h +++ b/src/account/account-params.h @@ -32,6 +32,7 @@ LINPHONE_BEGIN_NAMESPACE class PushNotificationConfig; +class NatPolicy; class AccountParams : public bellesip::HybridObject<LinphoneAccountParams, AccountParams>, public CustomParams { friend class Account; @@ -44,7 +45,6 @@ public: AccountParams *clone() const override; - // Setters void setExpires(int expires); void setQualityReportingInterval(int qualityReportingInterval); void setPublishExpires(int publishExpires); @@ -72,7 +72,7 @@ public: void setFileTranferServer(const std::string &fileTransferServer); void setPrivacy(LinphonePrivacyMask privacy); void setAvpfMode(LinphoneAVPFMode avpfMode); - void setNatPolicy(LinphoneNatPolicy *natPolicy); + void setNatPolicy(const std::shared_ptr<NatPolicy> &natPolicy); void setPushNotificationConfig(PushNotificationConfig *pushNotificationConfig); LinphoneStatus setIdentityAddress(const LinphoneAddress *identityAddress); LinphoneStatus setRoutes(const bctbx_list_t *routes); @@ -83,7 +83,6 @@ public: void setCustomContact(const LinphoneAddress *contact); void setLimeServerUrl(const std::string &url); - // Getters int getExpires() const; int getQualityReportingInterval() const; int getPublishExpires() const; @@ -117,7 +116,7 @@ public: LinphonePrivacyMask getPrivacy() const; LinphoneAddress *getIdentityAddress() const; LinphoneAVPFMode getAvpfMode() const; - LinphoneNatPolicy *getNatPolicy() const; + std::shared_ptr<NatPolicy> getNatPolicy() const; PushNotificationConfig *getPushNotificationConfig() const; const LinphoneAddress *getAudioVideoConferenceFactoryAddress() const; bool rtpBundleEnabled() const; @@ -182,7 +181,7 @@ private: LinphoneAVPFMode mAvpfMode; - LinphoneNatPolicy *mNatPolicy = nullptr; + std::shared_ptr<NatPolicy> mNatPolicy = nullptr; PushNotificationConfig *mPushNotificationConfig; diff --git a/src/account/account.cpp b/src/account/account.cpp index c4e49592615e314add5715cb689a7009d197e40c..1f14b7eb6bc49be3bbf3cf7eabe8314915c05039 100644 --- a/src/account/account.cpp +++ b/src/account/account.cpp @@ -1216,7 +1216,7 @@ void Account::onAudioVideoConferenceFactoryAddressChanged(const LinphoneAddress } } -void Account::onNatPolicyChanged(BCTBX_UNUSED(LinphoneNatPolicy *policy)) { +void Account::onNatPolicyChanged(BCTBX_UNUSED(const std::shared_ptr<NatPolicy> &policy)) { } LinphoneProxyConfig *Account::getConfig() const { diff --git a/src/account/account.h b/src/account/account.h index eddb76d7b7744d45114a555931982c65616b8a1c..4c7905a4cfff8ce2cc37a19afc1fd86bfd854189 100644 --- a/src/account/account.h +++ b/src/account/account.h @@ -141,7 +141,7 @@ private: void onInternationalPrefixChanged(); void onConferenceFactoryUriChanged(const std::string &conferenceFactoryUri); void onAudioVideoConferenceFactoryAddressChanged(const LinphoneAddress *audioVideoConferenceFactoryAddress); - void onNatPolicyChanged(LinphoneNatPolicy *policy); + void onNatPolicyChanged(const std::shared_ptr<NatPolicy> &policy); void onLimeServerUrlChanged(const std::string &limeServerUrl); bool customContactChanged(); std::list<SalAddress *> getOtherContacts(); diff --git a/src/c-wrapper/api/c-account-params.cpp b/src/c-wrapper/api/c-account-params.cpp index 244c84720f0d264d8abcb5d20355faf9fd7bc097..24f6e342294267509833f3285bf91c90e0b1270a 100644 --- a/src/c-wrapper/api/c-account-params.cpp +++ b/src/c-wrapper/api/c-account-params.cpp @@ -20,11 +20,13 @@ #include "linphone/api/c-account-params.h" #include "account/account-params.h" + #include "c-wrapper/c-wrapper.h" #include "c-wrapper/internal/c-tools.h" #include "linphone/api/c-address.h" #include "linphone/core.h" #include "linphone/lpconfig.h" +#include "nat/nat-policy.h" #include "push-notification/push-notification-config.h" // ============================================================================= @@ -295,11 +297,12 @@ void linphone_account_params_set_idkey(LinphoneAccountParams *params, const char } LinphoneNatPolicy *linphone_account_params_get_nat_policy(const LinphoneAccountParams *params) { - return AccountParams::toCpp(params)->getNatPolicy(); + auto pol = AccountParams::toCpp(params)->getNatPolicy(); + return pol ? pol->toC() : nullptr; } void linphone_account_params_set_nat_policy(LinphoneAccountParams *params, LinphoneNatPolicy *policy) { - AccountParams::toCpp(params)->setNatPolicy(policy); + AccountParams::toCpp(params)->setNatPolicy(policy ? NatPolicy::toCpp(policy)->getSharedFromThis() : nullptr); } void linphone_account_params_set_conference_factory_uri(LinphoneAccountParams *params, const char *uri) { @@ -421,4 +424,4 @@ void linphone_account_params_set_lime_server_url(LinphoneAccountParams *params, const char *linphone_account_params_get_lime_server_url(const LinphoneAccountParams *params) { return L_STRING_TO_C(AccountParams::toCpp(params)->getLimeServerUrl()); -} \ No newline at end of file +} diff --git a/src/core/core-p.h b/src/core/core-p.h index b851ab7e5899e154f925bafe433c4d26076b0b1e..0f105478af3c5ebacf649c92c212fa82dbf2e85c 100644 --- a/src/core/core-p.h +++ b/src/core/core-p.h @@ -180,6 +180,9 @@ public: /* called by linphone_core_set_video_device() to update the video device in the running call or conference.*/ void updateVideoDevice(); + /* centralized method to write down all NatPolicy used by Accounts or Core */ + void writeNatPolicyConfigurations(); + static const Utils::Version conferenceProtocolVersion; static const Utils::Version groupChatProtocolVersion; static const Utils::Version ephemeralProtocolVersion; diff --git a/src/core/core.cpp b/src/core/core.cpp index d55b15a8acebf2979b4aa2fc67c37bca860676c9..b5fb316d39a6fe0cf106fdf9fbbde33380ed0bb5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -190,6 +190,30 @@ void CorePrivate::unregisterListener(CoreListener *listener) { listeners.remove(listener); } +void CorePrivate::writeNatPolicyConfigurations() { + int index = 0; + LinphoneCore *lc = getCCore(); + + if (!linphone_core_ready(lc)) return; + + LinphoneConfig *config = linphone_core_get_config(lc); + + if (lc->nat_policy) { + NatPolicy::toCpp(lc->nat_policy)->saveToConfig(config, index); + ++index; + } + const bctbx_list_t *elem; + for (elem = linphone_core_get_account_list(lc); elem != nullptr; elem = elem->next) { + LinphoneAccount *account = (LinphoneAccount *)elem->data; + auto natPolicy = Account::toCpp(account)->getAccountParams()->getNatPolicy(); + if (natPolicy) { + natPolicy->saveToConfig(config, index); + ++index; + } + } + NatPolicy::clearConfigFromIndex(config, index); +} + void Core::onStopAsyncBackgroundTaskStarted() { L_D(); d->stopAsyncEndEnabled = false; diff --git a/src/nat/nat-policy.cpp b/src/nat/nat-policy.cpp index 621a30be67fb3a3b4507b10645008dc0f5bcb09e..ee26778f1ffb1e0a11aa30862adc260f7f7f1097 100644 --- a/src/nat/nat-policy.cpp +++ b/src/nat/nat-policy.cpp @@ -121,25 +121,22 @@ void NatPolicy::saveToConfig(LinphoneConfig *config, int index) const { 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::clearConfigFromIndex(LinphoneConfig *config, int index) { + int purged = 0; + while (true) { + std::ostringstream ostr; + ostr << "nat_policy_" << index; + if (linphone_config_has_section(config, ostr.str().c_str())) { + linphone_config_clean_section(config, ostr.str().c_str()); + ++purged; + } else break; + ++index; + } + /* Warn about suspicious number of orphan NatPolicy sections. + * A bug occured December 2022 caused a massive leak of nat_policy_X sections in configuration file. + */ + if (purged > 5) { + lWarning() << "Purged [" << purged << "] unused NatPolicy sections from config file."; } } diff --git a/src/nat/nat-policy.h b/src/nat/nat-policy.h index 1bf003f4109302a6b77f47722f82665f6ac76a3c..b5ea4d076ca63b33a9ef2a208f6bb27439ecc13e 100644 --- a/src/nat/nat-policy.h +++ b/src/nat/nat-policy.h @@ -111,11 +111,11 @@ public: void clear(); void release(); bool stunServerActivated() const; - void saveToConfig(); void resolveStunServer(); + void saveToConfig(LinphoneConfig *config, int index) const; + static void clearConfigFromIndex(LinphoneConfig *config, int index); 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); diff --git a/tester/tester.c b/tester/tester.c index 157c69681db95414392f7e75abb7d87cb220c6d0..ab702adce68e177d954a3b2e577193bcf7e60799 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -2690,6 +2690,25 @@ LinphoneCoreManager *linphone_core_manager_create_shared(const char *rc_file, return manager; } +static void check_orphan_nat_policy_section(LinphoneCoreManager *mgr) { + bctbx_list_t *l = linphone_config_get_sections_names_list(linphone_core_get_config(mgr->lc)); + bctbx_list_t *elem; + int nat_policy_count = 0; + int proxy_count = 0; + + for (elem = l; elem != NULL; elem = elem->next) { + const char *name = (const char *)elem->data; + if (strstr(name, "nat_policy_") == name) { + nat_policy_count++; + } else if (strstr(name, "proxy_") == name) { + proxy_count++; + } + } + /* There can't be more nat_policy_ section than proxy_? section + 1 */ + BC_ASSERT_LOWER(nat_policy_count, proxy_count + 1, int, "%i"); + bctbx_list_free(l); +} + void linphone_core_manager_stop(LinphoneCoreManager *mgr) { if (mgr->lc) { const char *record_file = linphone_core_get_record_file(mgr->lc); @@ -2702,7 +2721,7 @@ void linphone_core_manager_stop(LinphoneCoreManager *mgr) { } linphone_core_stop(mgr->lc); - + check_orphan_nat_policy_section(mgr); linphone_core_unref(mgr->lc); mgr->lc = NULL; }