LCOV - code coverage report
Current view: top level - foo/src/client - configurationmanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 58 549 10.6 %
Date: 2025-08-24 09:11:10 Functions: 16 132 12.1 %

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

Generated by: LCOV version 1.14