LCOV - code coverage report
Current view: top level - foo/src/client - configurationmanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 46 554 8.3 %
Date: 2026-02-28 10:41:24 Functions: 13 142 9.2 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #ifdef HAVE_CONFIG_H
      19             : #include "config.h"
      20             : #endif
      21             : 
      22             : #include "configurationmanager_interface.h"
      23             : #include "manager.h"
      24             : #include "logger.h"
      25             : #include "fileutils.h"
      26             : #include "sip/sipaccount.h"
      27             : #include "jamidht/jamiaccount.h"
      28             : #include "sip/sipaccount_config.h"
      29             : #include "jamidht/jamiaccount_config.h"
      30             : #include "audio/audiolayer.h"
      31             : #include "system_codec_container.h"
      32             : #include "account_const.h"
      33             : #include "client/jami_signal.h"
      34             : #include "audio/ringbufferpool.h"
      35             : #include "connectivity/security/tlsvalidator.h"
      36             : 
      37             : #include <dhtnet/ip_utils.h>
      38             : #include <dhtnet/upnp/upnp_context.h>
      39             : #include <dhtnet/certstore.h>
      40             : 
      41             : #ifdef __APPLE__
      42             : #include <TargetConditionals.h>
      43             : #endif
      44             : 
      45             : #ifdef _MSC_VER
      46             : #include "windirent.h"
      47             : #else
      48             : #include <dirent.h>
      49             : #endif
      50             : 
      51             : #include <cerrno>
      52             : #include <cstring>
      53             : 
      54             : #ifdef _WIN32
      55             : #undef interface
      56             : #endif
      57             : 
      58             : namespace libjami {
      59             : 
      60             : constexpr unsigned CODECS_NOT_LOADED = 0x1000; /** Codecs not found */
      61             : 
      62             : using jami::SIPAccount;
      63             : using jami::JamiAccount;
      64             : using jami::tls::TlsValidator;
      65             : using jami::AudioDeviceType;
      66             : 
      67             : void
      68           0 : registerConfHandlers(const std::map<std::string, std::shared_ptr<CallbackWrapperBase>>& handlers)
      69             : {
      70           0 :     registerSignalHandlers(handlers);
      71           0 : }
      72             : 
      73             : std::map<std::string, std::string>
      74           0 : getAccountDetails(const std::string& accountId)
      75             : {
      76           0 :     return jami::Manager::instance().getAccountDetails(accountId);
      77             : }
      78             : 
      79             : std::map<std::string, std::string>
      80           0 : getVolatileAccountDetails(const std::string& accountId)
      81             : {
      82           0 :     return jami::Manager::instance().getVolatileAccountDetails(accountId);
      83             : }
      84             : 
      85             : std::map<std::string, std::string>
      86           0 : validateCertificate(const std::string& accountId, const std::string& certificate)
      87             : {
      88             :     try {
      89           0 :         if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
      90           0 :             return TlsValidator {acc->certStore(), acc->certStore().getCertificate(certificate)}.getSerializedChecks();
      91           0 :     } catch (const std::runtime_error& e) {
      92           0 :         JAMI_WARN("Certificate loading failed: %s", e.what());
      93           0 :     }
      94           0 :     return {{Certificate::ChecksNames::EXIST, Certificate::CheckValuesNames::FAILED}};
      95             : }
      96             : 
      97             : std::map<std::string, std::string>
      98           0 : validateCertificatePath(const std::string& accountId,
      99             :                         const std::string& certificate,
     100             :                         const std::string& privateKey,
     101             :                         const std::string& privateKeyPass,
     102             :                         const std::string& caList)
     103             : {
     104             :     try {
     105           0 :         if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     106           0 :             return TlsValidator {acc->certStore(), certificate, privateKey, privateKeyPass, caList}.getSerializedChecks();
     107           0 :     } catch (const std::runtime_error& e) {
     108           0 :         JAMI_WARN("Certificate loading failed: %s", e.what());
     109           0 :         return {{Certificate::ChecksNames::EXIST, Certificate::CheckValuesNames::FAILED}};
     110           0 :     }
     111           0 :     return {};
     112             : }
     113             : 
     114             : std::map<std::string, std::string>
     115           0 : getCertificateDetails(const std::string& accountId, const std::string& certificate)
     116             : {
     117             :     try {
     118           0 :         if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     119           0 :             return TlsValidator {acc->certStore(), acc->certStore().getCertificate(certificate)}.getSerializedDetails();
     120           0 :     } catch (const std::runtime_error& e) {
     121           0 :         JAMI_WARN("Certificate loading failed: %s", e.what());
     122           0 :     }
     123           0 :     return {};
     124             : }
     125             : 
     126             : std::map<std::string, std::string>
     127           0 : getCertificateDetailsPath(const std::string& accountId,
     128             :                           const std::string& certificate,
     129             :                           const std::string& privateKey,
     130             :                           const std::string& privateKeyPassword)
     131             : {
     132             :     try {
     133           0 :         auto crt = std::make_shared<dht::crypto::Certificate>(jami::fileutils::loadFile(certificate));
     134           0 :         if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     135           0 :             TlsValidator validator {acc->certStore(), certificate, privateKey, privateKeyPassword};
     136           0 :             acc->certStore().pinCertificate(validator.getCertificate(), false);
     137           0 :             return validator.getSerializedDetails();
     138           0 :         }
     139           0 :     } catch (const std::runtime_error& e) {
     140           0 :         JAMI_WARN("Certificate loading failed: %s", e.what());
     141           0 :     }
     142           0 :     return {};
     143             : }
     144             : 
     145             : std::vector<std::string>
     146           0 : getPinnedCertificates(const std::string& accountId)
     147             : {
     148           0 :     if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     149           0 :         return acc->certStore().getPinnedCertificates();
     150           0 :     return {};
     151             : }
     152             : 
     153             : std::vector<std::string>
     154           0 : pinCertificate(const std::string& accountId, const std::vector<uint8_t>& certificate, bool local)
     155             : {
     156           0 :     if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     157           0 :         return acc->certStore().pinCertificate(certificate, local);
     158           0 :     return {};
     159             : }
     160             : 
     161             : void
     162           0 : pinCertificatePath(const std::string& accountId, const std::string& path)
     163             : {
     164           0 :     if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     165           0 :         acc->certStore().pinCertificatePath(path);
     166           0 : }
     167             : 
     168             : bool
     169           0 : unpinCertificate(const std::string& accountId, const std::string& certId)
     170             : {
     171           0 :     if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     172           0 :         return acc->certStore().unpinCertificate(certId);
     173           0 :     return {};
     174             : }
     175             : 
     176             : unsigned
     177           0 : unpinCertificatePath(const std::string& accountId, const std::string& path)
     178             : {
     179           0 :     if (const auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     180           0 :         return acc->certStore().unpinCertificatePath(path);
     181           0 :     return {};
     182             : }
     183             : 
     184             : bool
     185           0 : pinRemoteCertificate(const std::string& accountId, const std::string& certId)
     186             : {
     187           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     188           0 :         acc->dht()->findCertificate(dht::InfoHash(certId),
     189           0 :                                     [](const std::shared_ptr<dht::crypto::Certificate>& /*crt*/) {});
     190           0 :         return true;
     191           0 :     }
     192           0 :     return false;
     193             : }
     194             : 
     195             : bool
     196           0 : setCertificateStatus(const std::string& accountId, const std::string& certId, const std::string& ststr)
     197             : {
     198             :     try {
     199           0 :         if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     200           0 :             auto status = dhtnet::tls::TrustStore::statusFromStr(ststr.c_str());
     201           0 :             return acc->setCertificateStatus(certId, status);
     202           0 :         }
     203           0 :     } catch (const std::out_of_range& e) {
     204           0 :         JAMI_WARNING("Argument out of range when setting certificate status: {}", e);
     205           0 :     }
     206           0 :     return false;
     207             : }
     208             : 
     209             : std::vector<std::string>
     210           0 : getCertificatesByStatus(const std::string& accountId, const std::string& ststr)
     211             : {
     212           0 :     auto status = dhtnet::tls::TrustStore::statusFromStr(ststr.c_str());
     213           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     214           0 :         return acc->getCertificatesByStatus(status);
     215           0 :     return {};
     216             : }
     217             : 
     218             : void
     219          16 : setAccountDetails(const std::string& accountId, const std::map<std::string, std::string>& details)
     220             : {
     221          16 :     jami::Manager::instance().setAccountDetails(accountId, details);
     222          16 : }
     223             : 
     224             : void
     225           0 : setAccountActive(const std::string& accountId, bool enable, bool shutdownConnections)
     226             : {
     227           0 :     jami::Manager::instance().setAccountActive(accountId, enable, shutdownConnections);
     228           0 : }
     229             : 
     230             : void
     231           0 : loadAccountAndConversation(const std::string& accountId, bool loadAll, const std::string& convId)
     232             : {
     233           0 :     jami::Manager::instance().loadAccountAndConversation(accountId, loadAll, convId);
     234           0 : }
     235             : 
     236             : void
     237           0 : sendRegister(const std::string& accountId, bool enable)
     238             : {
     239           0 :     jami::Manager::instance().sendRegister(accountId, enable);
     240           0 : }
     241             : 
     242             : bool
     243           0 : isPasswordValid(const std::string& accountId, const std::string& password)
     244             : {
     245           0 :     if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(accountId))
     246           0 :         return acc->isPasswordValid(password);
     247           0 :     return false;
     248             : }
     249             : 
     250             : std::vector<uint8_t>
     251           0 : getPasswordKey(const std::string& accountID, const std::string& password)
     252             : {
     253           0 :     if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(accountID))
     254           0 :         return acc->getPasswordKey(password);
     255           0 :     return {};
     256             : }
     257             : 
     258             : void
     259           0 : registerAllAccounts()
     260             : {
     261           0 :     jami::Manager::instance().registerAccounts();
     262           0 : }
     263             : 
     264             : uint64_t
     265           0 : sendAccountTextMessage(const std::string& accountId,
     266             :                        const std::string& to,
     267             :                        const std::map<std::string, std::string>& payloads,
     268             :                        int32_t flags)
     269             : {
     270           0 :     bool onlyConnected = flags & 0x1;
     271           0 :     return jami::Manager::instance().sendTextMessage(accountId, to, payloads, onlyConnected);
     272             : }
     273             : 
     274             : std::vector<Message>
     275           0 : getLastMessages(const std::string& accountId, const uint64_t& base_timestamp)
     276             : {
     277           0 :     if (const auto acc = jami::Manager::instance().getAccount(accountId))
     278           0 :         return acc->getLastMessages(base_timestamp);
     279           0 :     return {};
     280             : }
     281             : 
     282             : std::map<std::string, std::string>
     283           0 : getNearbyPeers(const std::string& accountId)
     284             : {
     285           0 :     return jami::Manager::instance().getNearbyPeers(accountId);
     286             : }
     287             : 
     288             : void
     289           0 : updateProfile(const std::string& accountId,
     290             :               const std::string& displayName,
     291             :               const std::string& avatar,
     292             :               const std::string& fileType,
     293             :               int32_t flag)
     294             : {
     295           0 :     if (const auto acc = jami::Manager::instance().getAccount(accountId)) {
     296           0 :         acc->updateProfile(displayName, avatar, fileType, flag);
     297           0 :     }
     298           0 : }
     299             : 
     300             : int
     301           0 : getMessageStatus(uint64_t messageId)
     302             : {
     303           0 :     return jami::Manager::instance().getMessageStatus(messageId);
     304             : }
     305             : 
     306             : int
     307           0 : getMessageStatus(const std::string& accountId, uint64_t messageId)
     308             : {
     309           0 :     return jami::Manager::instance().getMessageStatus(accountId, messageId);
     310             : }
     311             : 
     312             : void
     313           5 : setIsComposing(const std::string& accountId, const std::string& conversationUri, bool isWriting)
     314             : {
     315           5 :     if (const auto acc = jami::Manager::instance().getAccount(accountId))
     316           5 :         acc->setIsComposing(conversationUri, isWriting);
     317           5 : }
     318             : 
     319             : bool
     320           2 : setMessageDisplayed(const std::string& accountId,
     321             :                     const std::string& conversationUri,
     322             :                     const std::string& messageId,
     323             :                     int status)
     324             : {
     325           2 :     if (const auto acc = jami::Manager::instance().getAccount(accountId))
     326           2 :         return acc->setMessageDisplayed(conversationUri, messageId, status);
     327           0 :     return false;
     328             : }
     329             : 
     330             : int32_t
     331           5 : addDevice(const std::string& accountId, const std::string& uri)
     332             : {
     333          20 :     JAMI_DEBUG("[LinkDevice {}] exportToPeer called.", accountId);
     334           5 :     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     335           5 :         return account->addDevice(uri);
     336           5 :     }
     337           0 :     return static_cast<int32_t>(jami::AccountManager::AddDeviceError::GENERIC);
     338             : }
     339             : 
     340             : bool
     341           0 : confirmAddDevice(const std::string& accountId, uint32_t op_id)
     342             : {
     343           0 :     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     344           0 :         return account->confirmAddDevice(op_id);
     345           0 :     }
     346           0 :     return false;
     347             : }
     348             : 
     349             : bool
     350           0 : cancelAddDevice(const std::string& accountId, uint32_t op_id)
     351             : {
     352           0 :     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     353           0 :         return account->cancelAddDevice(op_id);
     354           0 :     }
     355           0 :     return false;
     356             : }
     357             : 
     358             : bool
     359           0 : provideAccountAuthentication(const std::string& accountId,
     360             :                              const std::string& credentialsFromUser,
     361             :                              const std::string& scheme)
     362             : {
     363           0 :     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     364             :         // send the password to the channel for communicationg with the old device
     365           0 :         account->provideAccountAuthentication(credentialsFromUser, scheme);
     366           0 :         return true;
     367           0 :     }
     368           0 :     return false;
     369             : }
     370             : 
     371             : bool
     372           0 : exportToFile(const std::string& accountId,
     373             :              const std::string& destinationPath,
     374             :              const std::string& scheme,
     375             :              const std::string& password)
     376             : {
     377           0 :     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     378           0 :         return account->exportArchive(destinationPath, scheme, password);
     379           0 :     }
     380           0 :     return false;
     381             : }
     382             : 
     383             : bool
     384           0 : revokeDevice(const std::string& accountId,
     385             :              const std::string& deviceId,
     386             :              const std::string& scheme,
     387             :              const std::string& password)
     388             : {
     389           0 :     if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
     390           0 :         return account->revokeDevice(deviceId, scheme, password);
     391           0 :     }
     392           0 :     return false;
     393             : }
     394             : 
     395             : std::map<std::string, std::string>
     396           0 : getKnownRingDevices(const std::string& accountId)
     397             : {
     398           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     399           0 :         return acc->getKnownDevices();
     400           0 :     return {};
     401             : }
     402             : 
     403             : bool
     404           4 : changeAccountPassword(const std::string& accountId, const std::string& password_old, const std::string& password_new)
     405             : {
     406           4 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     407           4 :         return acc->changeArchivePassword(password_old, password_new);
     408           0 :     return false;
     409             : }
     410             : 
     411             : /* contacts */
     412             : 
     413             : void
     414           0 : addContact(const std::string& accountId, const std::string& uri)
     415             : {
     416           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     417           0 :         return acc->addContact(uri);
     418             : }
     419             : 
     420             : void
     421           0 : removeContact(const std::string& accountId, const std::string& uri, bool ban)
     422             : {
     423           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     424           0 :         return acc->removeContact(uri, ban);
     425             : }
     426             : 
     427             : std::map<std::string, std::string>
     428           0 : getContactDetails(const std::string& accountId, const std::string& uri)
     429             : {
     430           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     431           0 :         return acc->getContactDetails(uri);
     432           0 :     return {};
     433             : }
     434             : 
     435             : std::vector<std::map<std::string, std::string>>
     436           1 : getContacts(const std::string& accountId)
     437             : {
     438           1 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     439           1 :         return acc->getContacts();
     440           0 :     return {};
     441             : }
     442             : 
     443             : /* contact requests */
     444             : std::vector<std::map<std::string, std::string>>
     445           6 : getTrustRequests(const std::string& accountId)
     446             : {
     447           6 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     448           6 :         return acc->getTrustRequests();
     449           0 :     return {};
     450             : }
     451             : 
     452             : bool
     453           0 : acceptTrustRequest(const std::string& accountId, const std::string& from)
     454             : {
     455           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     456           0 :         return acc->acceptTrustRequest(from);
     457           0 :     return false;
     458             : }
     459             : 
     460             : bool
     461           0 : discardTrustRequest(const std::string& accountId, const std::string& from)
     462             : {
     463           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     464           0 :         return acc->discardTrustRequest(from);
     465           0 :     return false;
     466             : }
     467             : 
     468             : void
     469           0 : sendTrustRequest(const std::string& accountId, const std::string& to, const std::vector<uint8_t>& payload)
     470             : {
     471           0 :     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
     472           0 :         acc->sendTrustRequest(to, payload);
     473           0 : }
     474             : 
     475             : /// This function is used as a base for new accounts for clients that support it
     476             : std::map<std::string, std::string>
     477         307 : getAccountTemplate(const std::string& accountType)
     478             : {
     479         307 :     if (accountType == Account::ProtocolNames::RING)
     480         598 :         return jami::JamiAccountConfig().toMap();
     481           8 :     else if (accountType == Account::ProtocolNames::SIP)
     482          16 :         return jami::SipAccountConfig().toMap();
     483           0 :     return {};
     484             : }
     485             : 
     486             : std::string
     487           0 : addAccount(const std::map<std::string, std::string>& details, const std::string& accountId)
     488             : {
     489           0 :     return jami::Manager::instance().addAccount(details, accountId);
     490             : }
     491             : 
     492             : void
     493           0 : monitor(bool continuous)
     494             : {
     495           0 :     return jami::Manager::instance().monitor(continuous);
     496             : }
     497             : 
     498             : std::vector<std::map<std::string, std::string>>
     499           0 : getConnectionList(const std::string& accountId, const std::string& conversationId)
     500             : {
     501           0 :     return jami::Manager::instance().getConnectionList(accountId, conversationId);
     502             : }
     503             : 
     504             : std::vector<std::map<std::string, std::string>>
     505           0 : getChannelList(const std::string& accountId, const std::string& connectionId)
     506             : {
     507           0 :     return jami::Manager::instance().getChannelList(accountId, connectionId);
     508             : }
     509             : 
     510             : void
     511           0 : removeAccount(const std::string& accountId)
     512             : {
     513           0 :     return jami::Manager::instance().removeAccount(accountId, true); // with 'flush' enabled
     514             : }
     515             : 
     516             : std::vector<std::string>
     517           0 : getAccountList()
     518             : {
     519           0 :     return jami::Manager::instance().getAccountList();
     520             : }
     521             : 
     522             : /**
     523             :  * Send the list of all codecs loaded to the client through DBus.
     524             :  * Can stay global, as only the active codecs will be set per accounts
     525             :  */
     526             : std::vector<unsigned>
     527           0 : getCodecList()
     528             : {
     529           0 :     std::vector<unsigned> list {jami::getSystemCodecContainer()->getSystemCodecInfoIdList(jami::MEDIA_ALL)};
     530           0 :     if (list.empty())
     531           0 :         jami::emitSignal<ConfigurationSignal::Error>(CODECS_NOT_LOADED);
     532           0 :     return list;
     533           0 : }
     534             : 
     535             : std::vector<std::string>
     536           0 : getSupportedTlsMethod()
     537             : {
     538           0 :     return SIPAccount::getSupportedTlsProtocols();
     539             : }
     540             : 
     541             : std::vector<std::string>
     542           0 : getSupportedCiphers(const std::string& accountId)
     543             : {
     544           0 :     if (auto sipaccount = jami::Manager::instance().getAccount<SIPAccount>(accountId))
     545           0 :         return SIPAccount::getSupportedTlsCiphers();
     546           0 :     JAMI_ERR("SIP account %s doesn't exist", accountId.c_str());
     547           0 :     return {};
     548             : }
     549             : 
     550             : bool
     551           0 : setCodecDetails(const std::string& accountId, const unsigned& codecId, const std::map<std::string, std::string>& details)
     552             : {
     553           0 :     auto acc = jami::Manager::instance().getAccount(accountId);
     554           0 :     if (!acc) {
     555           0 :         JAMI_ERR("Unable to find account %s. Unable to set codec details", accountId.c_str());
     556           0 :         return false;
     557             :     }
     558             : 
     559           0 :     auto codec = acc->searchCodecById(codecId, jami::MEDIA_ALL);
     560           0 :     if (!codec) {
     561           0 :         JAMI_ERR("Unable to find codec %d", codecId);
     562           0 :         return false;
     563             :     }
     564             :     try {
     565           0 :         if (codec->mediaType & jami::MEDIA_AUDIO) {
     566           0 :             if (auto foundCodec = std::static_pointer_cast<jami::SystemAudioCodecInfo>(codec)) {
     567           0 :                 foundCodec->setCodecSpecifications(details);
     568           0 :                 jami::emitSignal<ConfigurationSignal::MediaParametersChanged>(accountId);
     569           0 :                 return true;
     570           0 :             }
     571             :         }
     572             : 
     573           0 :         if (codec->mediaType & jami::MEDIA_VIDEO) {
     574           0 :             if (auto foundCodec = std::static_pointer_cast<jami::SystemVideoCodecInfo>(codec)) {
     575           0 :                 foundCodec->setCodecSpecifications(details);
     576           0 :                 JAMI_WARN("parameters for %s changed ", foundCodec->name.c_str());
     577           0 :                 if (auto call = jami::Manager::instance().getCurrentCall()) {
     578           0 :                     if (call->getVideoCodec() == foundCodec) {
     579           0 :                         JAMI_WARN("%s running. Need to restart encoding", foundCodec->name.c_str());
     580           0 :                         call->restartMediaSender();
     581             :                     }
     582           0 :                 }
     583           0 :                 jami::emitSignal<ConfigurationSignal::MediaParametersChanged>(accountId);
     584           0 :                 return true;
     585           0 :             }
     586             :         }
     587           0 :     } catch (const std::exception& e) {
     588           0 :         JAMI_ERR("Unable to set codec specifications: %s", e.what());
     589           0 :     }
     590             : 
     591           0 :     return false;
     592           0 : }
     593             : 
     594             : std::map<std::string, std::string>
     595           0 : getCodecDetails(const std::string& accountId, const unsigned& codecId)
     596             : {
     597           0 :     auto acc = jami::Manager::instance().getAccount(accountId);
     598           0 :     if (!acc) {
     599           0 :         JAMI_ERR("Unable to find account %s return default codec details", accountId.c_str());
     600           0 :         return jami::Account::getDefaultCodecDetails(codecId);
     601             :     }
     602             : 
     603           0 :     auto codec = acc->searchCodecById(codecId, jami::MEDIA_ALL);
     604           0 :     if (!codec) {
     605           0 :         jami::emitSignal<ConfigurationSignal::Error>(CODECS_NOT_LOADED);
     606           0 :         return {};
     607             :     }
     608             : 
     609           0 :     if (codec->mediaType & jami::MEDIA_AUDIO)
     610           0 :         if (auto foundCodec = std::static_pointer_cast<jami::SystemAudioCodecInfo>(codec))
     611           0 :             return foundCodec->getCodecSpecifications();
     612             : 
     613           0 :     if (codec->mediaType & jami::MEDIA_VIDEO)
     614           0 :         if (auto foundCodec = std::static_pointer_cast<jami::SystemVideoCodecInfo>(codec))
     615           0 :             return foundCodec->getCodecSpecifications();
     616             : 
     617           0 :     jami::emitSignal<ConfigurationSignal::Error>(CODECS_NOT_LOADED);
     618           0 :     return {};
     619           0 : }
     620             : 
     621             : std::vector<unsigned>
     622           0 : getActiveCodecList(const std::string& accountId)
     623             : {
     624           0 :     if (auto acc = jami::Manager::instance().getAccount(accountId))
     625           0 :         return acc->getActiveCodecs();
     626           0 :     JAMI_ERR("Unable to find account %s, returning default", accountId.c_str());
     627           0 :     return jami::Account::getDefaultCodecsId();
     628             : }
     629             : 
     630             : void
     631           0 : setActiveCodecList(const std::string& accountId, const std::vector<unsigned>& list)
     632             : {
     633           0 :     if (auto acc = jami::Manager::instance().getAccount(accountId)) {
     634           0 :         acc->setActiveCodecs(list);
     635           0 :         jami::Manager::instance().saveConfig(acc);
     636             :     } else {
     637           0 :         JAMI_ERR("Unable to find account %s", accountId.c_str());
     638           0 :     }
     639           0 : }
     640             : 
     641             : std::vector<std::string>
     642           0 : getAudioPluginList()
     643             : {
     644           0 :     return {PCM_DEFAULT, PCM_DMIX_DSNOOP};
     645             : }
     646             : 
     647             : void
     648           0 : setAudioPlugin(const std::string& audioPlugin)
     649             : {
     650           0 :     return jami::Manager::instance().setAudioPlugin(audioPlugin);
     651             : }
     652             : 
     653             : std::vector<std::string>
     654           0 : getAudioOutputDeviceList()
     655             : {
     656           0 :     return jami::Manager::instance().getAudioOutputDeviceList();
     657             : }
     658             : 
     659             : std::vector<std::string>
     660           0 : getAudioInputDeviceList()
     661             : {
     662           0 :     return jami::Manager::instance().getAudioInputDeviceList();
     663             : }
     664             : 
     665             : void
     666           0 : setAudioOutputDevice(int32_t index)
     667             : {
     668           0 :     return jami::Manager::instance().setAudioDevice(index, AudioDeviceType::PLAYBACK);
     669             : }
     670             : 
     671             : void
     672           0 : setAudioInputDevice(int32_t index)
     673             : {
     674           0 :     return jami::Manager::instance().setAudioDevice(index, AudioDeviceType::CAPTURE);
     675             : }
     676             : 
     677             : void
     678           0 : setAudioRingtoneDevice(int32_t index)
     679             : {
     680           0 :     return jami::Manager::instance().setAudioDevice(index, AudioDeviceType::RINGTONE);
     681             : }
     682             : 
     683             : std::vector<std::string>
     684           0 : getCurrentAudioDevicesIndex()
     685             : {
     686           0 :     return jami::Manager::instance().getCurrentAudioDevicesIndex();
     687             : }
     688             : 
     689             : int32_t
     690           0 : getAudioInputDeviceIndex(const std::string& name)
     691             : {
     692           0 :     return jami::Manager::instance().getAudioInputDeviceIndex(name);
     693             : }
     694             : 
     695             : int32_t
     696           0 : getAudioOutputDeviceIndex(const std::string& name)
     697             : {
     698           0 :     return jami::Manager::instance().getAudioOutputDeviceIndex(name);
     699             : }
     700             : 
     701             : std::string
     702           0 : getCurrentAudioOutputPlugin()
     703             : {
     704           0 :     auto plugin = jami::Manager::instance().getCurrentAudioOutputPlugin();
     705           0 :     JAMI_DBG("Get audio plugin %s", plugin.c_str());
     706           0 :     return plugin;
     707           0 : }
     708             : 
     709             : std::string
     710           0 : getNoiseSuppressState()
     711             : {
     712           0 :     return jami::Manager::instance().getNoiseSuppressState();
     713             : }
     714             : 
     715             : void
     716           0 : setNoiseSuppressState(const std::string& state)
     717             : {
     718           0 :     jami::Manager::instance().setNoiseSuppressState(state);
     719           0 : }
     720             : 
     721             : std::string
     722           0 : getEchoCancellationState()
     723             : {
     724           0 :     return jami::Manager::instance().getEchoCancellationState();
     725             : }
     726             : 
     727             : void
     728           0 : setEchoCancellationState(const std::string& state)
     729             : {
     730           0 :     jami::Manager::instance().setEchoCancellationState(state);
     731           0 : }
     732             : 
     733             : bool
     734           0 : getVoiceActivityDetectionState()
     735             : {
     736           0 :     return jami::Manager::instance().getVoiceActivityDetectionState();
     737             : }
     738             : 
     739             : void
     740           0 : setVoiceActivityDetectionState(bool state)
     741             : {
     742           0 :     jami::Manager::instance().setVoiceActivityDetectionState(state);
     743           0 : }
     744             : 
     745             : bool
     746           0 : isAgcEnabled()
     747             : {
     748           0 :     return jami::Manager::instance().isAGCEnabled();
     749             : }
     750             : 
     751             : void
     752           0 : setAgcState(bool enabled)
     753             : {
     754           0 :     jami::Manager::instance().setAGCState(enabled);
     755           0 : }
     756             : 
     757             : std::string
     758           0 : getRecordPath()
     759             : {
     760           0 :     return jami::Manager::instance().audioPreference.getRecordPath();
     761             : }
     762             : 
     763             : void
     764           0 : setRecordPath(const std::string& recPath)
     765             : {
     766           0 :     jami::Manager::instance().audioPreference.setRecordPath(recPath);
     767           0 : }
     768             : 
     769             : bool
     770           0 : getIsAlwaysRecording()
     771             : {
     772           0 :     return jami::Manager::instance().getIsAlwaysRecording();
     773             : }
     774             : 
     775             : void
     776           0 : setIsAlwaysRecording(bool rec)
     777             : {
     778           0 :     jami::Manager::instance().setIsAlwaysRecording(rec);
     779           0 : }
     780             : 
     781             : bool
     782           0 : getRecordPreview()
     783             : {
     784             : #ifdef ENABLE_VIDEO
     785           0 :     return jami::Manager::instance().videoPreferences.getRecordPreview();
     786             : #else
     787             :     return false;
     788             : #endif
     789             : }
     790             : 
     791             : void
     792           0 : setRecordPreview(bool rec)
     793             : {
     794             : #ifdef ENABLE_VIDEO
     795           0 :     jami::Manager::instance().videoPreferences.setRecordPreview(rec);
     796           0 :     jami::Manager::instance().saveConfig();
     797             : #endif
     798           0 : }
     799             : 
     800             : int32_t
     801           0 : getRecordQuality()
     802             : {
     803             : #ifdef ENABLE_VIDEO
     804           0 :     return jami::Manager::instance().videoPreferences.getRecordQuality();
     805             : #else
     806             :     return 0;
     807             : #endif
     808             : }
     809             : 
     810             : void
     811           0 : setRecordQuality(int32_t quality)
     812             : {
     813             : #ifdef ENABLE_VIDEO
     814           0 :     jami::Manager::instance().videoPreferences.setRecordQuality(quality);
     815           0 :     jami::Manager::instance().saveConfig();
     816             : #endif
     817           0 : }
     818             : 
     819             : int32_t
     820           0 : getHistoryLimit()
     821             : {
     822           0 :     return jami::Manager::instance().getHistoryLimit();
     823             : }
     824             : 
     825             : void
     826           0 : setHistoryLimit(int32_t days)
     827             : {
     828           0 :     jami::Manager::instance().setHistoryLimit(days);
     829           0 : }
     830             : 
     831             : int32_t
     832           0 : getRingingTimeout()
     833             : {
     834           0 :     return static_cast<int32_t>(jami::Manager::instance().getRingingTimeout().count());
     835             : }
     836             : 
     837             : void
     838           0 : setRingingTimeout(int32_t timeout)
     839             : {
     840           0 :     jami::Manager::instance().setRingingTimeout(std::chrono::seconds(timeout));
     841           0 : }
     842             : 
     843             : std::vector<std::string>
     844           0 : getSupportedAudioManagers()
     845             : {
     846           0 :     return jami::AudioPreference::getSupportedAudioManagers();
     847             : }
     848             : 
     849             : bool
     850           0 : setAudioManager(const std::string& api)
     851             : {
     852           0 :     return jami::Manager::instance().setAudioManager(api);
     853             : }
     854             : 
     855             : std::string
     856           0 : getAudioManager()
     857             : {
     858           0 :     return jami::Manager::instance().getAudioManager();
     859             : }
     860             : 
     861             : void
     862           0 : setVolume(const std::string& device, double value)
     863             : {
     864           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver()) {
     865           0 :         JAMI_DBG("set volume for %s: %f", device.c_str(), value);
     866             : 
     867           0 :         if (device == "speaker")
     868           0 :             audiolayer->setPlaybackGain(value);
     869           0 :         else if (device == "mic")
     870           0 :             audiolayer->setCaptureGain(value);
     871             : 
     872           0 :         jami::emitSignal<ConfigurationSignal::VolumeChanged>(device, value);
     873             :     } else {
     874           0 :         JAMI_ERR("Audio layer not valid while updating volume");
     875           0 :     }
     876           0 : }
     877             : 
     878             : double
     879           0 : getVolume(const std::string& device)
     880             : {
     881           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver()) {
     882           0 :         if (device == "speaker")
     883           0 :             return audiolayer->getPlaybackGain();
     884           0 :         if (device == "mic")
     885           0 :             return audiolayer->getCaptureGain();
     886           0 :     }
     887             : 
     888           0 :     JAMI_ERR("Audio layer not valid while updating volume");
     889           0 :     return 0.0;
     890             : }
     891             : 
     892             : // FIXME: we should store "muteDtmf" instead of "playDtmf"
     893             : // in config and avoid negating like this
     894             : bool
     895           0 : isDtmfMuted()
     896             : {
     897           0 :     return not jami::Manager::instance().voipPreferences.getPlayDtmf();
     898             : }
     899             : 
     900             : void
     901           0 : muteDtmf(bool mute)
     902             : {
     903           0 :     jami::Manager::instance().voipPreferences.setPlayDtmf(not mute);
     904           0 : }
     905             : 
     906             : bool
     907           0 : isCaptureMuted()
     908             : {
     909           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver())
     910           0 :         return audiolayer->isCaptureMuted();
     911             : 
     912           0 :     JAMI_ERR("Audio layer not valid");
     913           0 :     return false;
     914             : }
     915             : 
     916             : void
     917           0 : muteCapture(bool mute)
     918             : {
     919           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver())
     920           0 :         return audiolayer->muteCapture(mute);
     921             : 
     922           0 :     JAMI_ERR("Audio layer not valid");
     923           0 :     return;
     924             : }
     925             : 
     926             : bool
     927           0 : isPlaybackMuted()
     928             : {
     929           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver())
     930           0 :         return audiolayer->isPlaybackMuted();
     931             : 
     932           0 :     JAMI_ERR("Audio layer not valid");
     933           0 :     return false;
     934             : }
     935             : 
     936             : void
     937           0 : mutePlayback(bool mute)
     938             : {
     939           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver())
     940           0 :         return audiolayer->mutePlayback(mute);
     941             : 
     942           0 :     JAMI_ERR("Audio layer not valid");
     943           0 :     return;
     944             : }
     945             : 
     946             : bool
     947           0 : isRingtoneMuted()
     948             : {
     949           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver())
     950           0 :         return audiolayer->isRingtoneMuted();
     951             : 
     952           0 :     JAMI_ERR("Audio layer not valid");
     953           0 :     return false;
     954             : }
     955             : 
     956             : void
     957           0 : muteRingtone(bool mute)
     958             : {
     959           0 :     if (auto audiolayer = jami::Manager::instance().getAudioDriver())
     960           0 :         return audiolayer->muteRingtone(mute);
     961             : 
     962           0 :     JAMI_ERR("Audio layer not valid");
     963           0 :     return;
     964             : }
     965             : 
     966             : void
     967           0 : setAccountsOrder(const std::string& order)
     968             : {
     969           0 :     jami::Manager::instance().setAccountsOrder(order);
     970           0 : }
     971             : 
     972             : std::string
     973           0 : getAddrFromInterfaceName(const std::string& interface)
     974             : {
     975           0 :     return dhtnet::ip_utils::getInterfaceAddr(interface, AF_INET);
     976             : }
     977             : 
     978             : std::vector<std::string>
     979           0 : getAllIpInterface()
     980             : {
     981           0 :     return dhtnet::ip_utils::getAllIpInterface();
     982             : }
     983             : 
     984             : std::vector<std::string>
     985           0 : getAllIpInterfaceByName()
     986             : {
     987           0 :     return dhtnet::ip_utils::getAllIpInterfaceByName();
     988             : }
     989             : 
     990             : std::vector<std::map<std::string, std::string>>
     991           0 : getCredentials(const std::string& accountId)
     992             : {
     993           0 :     if (auto sipaccount = jami::Manager::instance().getAccount<SIPAccount>(accountId))
     994           0 :         return sipaccount->getCredentials();
     995           0 :     return {};
     996             : }
     997             : 
     998             : void
     999           0 : setCredentials(const std::string& accountId, const std::vector<std::map<std::string, std::string>>& details)
    1000             : {
    1001           0 :     if (auto sipaccount = jami::Manager::instance().getAccount<SIPAccount>(accountId)) {
    1002           0 :         sipaccount->doUnregister();
    1003           0 :         sipaccount->editConfig([&](jami::SipAccountConfig& config) { config.setCredentials(details); });
    1004           0 :         sipaccount->loadConfig();
    1005           0 :         if (sipaccount->isEnabled())
    1006           0 :             sipaccount->doRegister();
    1007           0 :         jami::Manager::instance().saveConfig(sipaccount);
    1008           0 :     }
    1009           0 : }
    1010             : 
    1011             : void
    1012           0 : connectivityChanged()
    1013             : {
    1014           0 :     JAMI_WARN("received connectivity changed - attempting to re-connect enabled accounts");
    1015             : 
    1016             :     // reset the UPnP context
    1017             : #if !(defined(TARGET_OS_IOS) && TARGET_OS_IOS)
    1018             :     try {
    1019           0 :         jami::Manager::instance().upnpContext()->connectivityChanged();
    1020           0 :     } catch (std::runtime_error& e) {
    1021           0 :         JAMI_ERR("UPnP context error: %s", e.what());
    1022           0 :     }
    1023             : #endif
    1024             : 
    1025           0 :     for (const auto& account : jami::Manager::instance().getAllAccounts()) {
    1026           0 :         account->connectivityChanged();
    1027           0 :     }
    1028           0 : }
    1029             : 
    1030             : bool
    1031           3 : lookupName(const std::string& account, const std::string& nameserver, const std::string& name)
    1032             : {
    1033           3 :     if (account.empty()) {
    1034             :         auto cb =
    1035           0 :             [name](const std::string& regName, const std::string& address, jami::NameDirectory::Response response) {
    1036           0 :                 jami::emitSignal<libjami::ConfigurationSignal::RegisteredNameFound>("",
    1037           0 :                                                                                     name,
    1038             :                                                                                     (int) response,
    1039             :                                                                                     address,
    1040             :                                                                                     regName);
    1041           0 :             };
    1042           0 :         if (nameserver.empty())
    1043           0 :             jami::NameDirectory::lookupUri(name, "", cb);
    1044             :         else
    1045           0 :             jami::NameDirectory::instance(nameserver).lookupName(name, cb);
    1046           0 :         return true;
    1047           3 :     } else if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(account)) {
    1048           3 :         acc->lookupName(name);
    1049           3 :         return true;
    1050           3 :     }
    1051           0 :     JAMI_ERROR("lookupName: Unknown account: {}", account);
    1052           0 :     return false;
    1053             : }
    1054             : 
    1055             : bool
    1056           3 : lookupAddress(const std::string& account, const std::string& nameserver, const std::string& address)
    1057             : {
    1058           3 :     if (account.empty()) {
    1059           0 :         jami::NameDirectory::instance(nameserver)
    1060           0 :             .lookupAddress(address,
    1061           0 :                            [address](const std::string& regName,
    1062             :                                      const std::string& addr,
    1063             :                                      jami::NameDirectory::Response response) {
    1064           0 :                                jami::emitSignal<libjami::ConfigurationSignal::RegisteredNameFound>("",
    1065           0 :                                                                                                    address,
    1066             :                                                                                                    (int) response,
    1067             :                                                                                                    addr,
    1068             :                                                                                                    regName);
    1069           0 :                            });
    1070           0 :         return true;
    1071           3 :     } else if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(account)) {
    1072           3 :         acc->lookupAddress(address);
    1073           3 :         return true;
    1074           3 :     }
    1075           0 :     JAMI_ERROR("lookupAddress: Unknown account: {}", account);
    1076           0 :     return false;
    1077             : }
    1078             : 
    1079             : bool
    1080           0 : searchUser(const std::string& account, const std::string& query)
    1081             : {
    1082           0 :     if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(account)) {
    1083           0 :         return acc->searchUser(query);
    1084           0 :     }
    1085           0 :     return false;
    1086             : }
    1087             : 
    1088             : bool
    1089           1 : registerName(const std::string& account, const std::string& name, const std::string& scheme, const std::string& password)
    1090             : {
    1091           1 :     if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(account)) {
    1092           1 :         acc->registerName(name, scheme, password);
    1093           1 :         return true;
    1094           1 :     }
    1095           0 :     JAMI_ERROR("registerName: Unknown account: {}", account);
    1096           0 :     return false;
    1097             : }
    1098             : 
    1099             : void
    1100           0 : setPushNotificationToken(const std::string& token)
    1101             : {
    1102           0 :     for (const auto& account : jami::Manager::instance().getAllAccounts()) {
    1103           0 :         account->setPushNotificationToken(token);
    1104           0 :     }
    1105           0 : }
    1106             : 
    1107             : void
    1108           0 : setPushNotificationTopic(const std::string& topic)
    1109             : {
    1110           0 :     for (const auto& account : jami::Manager::instance().getAllAccounts()) {
    1111           0 :         account->setPushNotificationTopic(topic);
    1112           0 :     }
    1113           0 : }
    1114             : 
    1115             : void
    1116           0 : setPushNotificationConfig(const std::map<std::string, std::string>& data)
    1117             : {
    1118           0 :     for (const auto& account : jami::Manager::instance().getAllAccounts()) {
    1119           0 :         account->setPushNotificationConfig(data);
    1120           0 :     }
    1121           0 : }
    1122             : 
    1123             : void
    1124           0 : pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data)
    1125             : {
    1126             :     try {
    1127           0 :         auto it = data.find("to");
    1128           0 :         if (it != data.end()) {
    1129           0 :             if (auto account = jami::Manager::instance().getAccount<JamiAccount>(it->second))
    1130           0 :                 account->pushNotificationReceived(from, data);
    1131             :         }
    1132             : #if defined(__ANDROID__) || defined(ANDROID) || defined(__Apple__)
    1133             :         else {
    1134             :             for (const auto& sipAccount : jami::Manager::instance().getAllAccounts<SIPAccount>()) {
    1135             :                 sipAccount->pushNotificationReceived(from, data);
    1136             :             }
    1137             :         }
    1138             : #endif
    1139           0 :     } catch (const std::exception& e) {
    1140           0 :         JAMI_ERR("Error processing push notification: %s", e.what());
    1141           0 :     }
    1142           0 : }
    1143             : 
    1144             : bool
    1145           0 : isAudioMeterActive(const std::string& id)
    1146             : {
    1147           0 :     return jami::Manager::instance().getRingBufferPool().isAudioMeterActive(id);
    1148             : }
    1149             : 
    1150             : void
    1151           0 : setAudioMeterState(const std::string& id, bool state)
    1152             : {
    1153           0 :     jami::Manager::instance().getRingBufferPool().setAudioMeterState(id, state);
    1154           0 : }
    1155             : 
    1156             : void
    1157           0 : setDefaultModerator(const std::string& accountId, const std::string& peerURI, bool state)
    1158             : {
    1159           0 :     jami::Manager::instance().setDefaultModerator(accountId, peerURI, state);
    1160           0 : }
    1161             : 
    1162             : std::vector<std::string>
    1163           0 : getDefaultModerators(const std::string& accountId)
    1164             : {
    1165           0 :     return jami::Manager::instance().getDefaultModerators(accountId);
    1166             : }
    1167             : 
    1168             : void
    1169           0 : enableLocalModerators(const std::string& accountId, bool isModEnabled)
    1170             : {
    1171           0 :     jami::Manager::instance().enableLocalModerators(accountId, isModEnabled);
    1172           0 : }
    1173             : 
    1174             : bool
    1175           0 : isLocalModeratorsEnabled(const std::string& accountId)
    1176             : {
    1177           0 :     return jami::Manager::instance().isLocalModeratorsEnabled(accountId);
    1178             : }
    1179             : 
    1180             : void
    1181           0 : setAllModerators(const std::string& accountId, bool allModerators)
    1182             : {
    1183           0 :     jami::Manager::instance().setAllModerators(accountId, allModerators);
    1184           0 : }
    1185             : 
    1186             : bool
    1187           0 : isAllModerators(const std::string& accountId)
    1188             : {
    1189           0 :     return jami::Manager::instance().isAllModerators(accountId);
    1190             : }
    1191             : 
    1192             : void
    1193           0 : setResourceDirPath(const std::string& resourceDir)
    1194             : {
    1195           0 :     jami::fileutils::set_resource_dir_path(resourceDir);
    1196           0 : }
    1197             : 
    1198             : } // namespace libjami

Generated by: LCOV version 1.14