LCOV - code coverage report
Current view: top level - src/jamidht - jamiaccount.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 31 36 86.1 %
Date: 2024-04-16 08:04:53 Functions: 20 23 87.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
       5             :  *  Author: Simon Désaulniers <simon.desaulniers@gmail.com>
       6             :  *  Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
       7             :  *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
       8             :  *
       9             :  *  This program is free software; you can redistribute it and/or modify
      10             :  *  it under the terms of the GNU General Public License as published by
      11             :  *  the Free Software Foundation; either version 3 of the License, or
      12             :  *  (at your option) any later version.
      13             :  *
      14             :  *  This program is distributed in the hope that it will be useful,
      15             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :  *  GNU General Public License for more details.
      18             :  *
      19             :  *  You should have received a copy of the GNU General Public License
      20             :  *  along with this program; if not, write to the Free Software
      21             :  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
      22             :  */
      23             : 
      24             : #pragma once
      25             : 
      26             : #ifdef HAVE_CONFIG_H
      27             : #include "config.h"
      28             : #endif
      29             : 
      30             : #include "sip/sipaccountbase.h"
      31             : #include "jami/datatransfer_interface.h"
      32             : #include "jamidht/conversation.h"
      33             : #include "data_transfer.h"
      34             : #include "uri.h"
      35             : #include "jamiaccount_config.h"
      36             : 
      37             : #include "noncopyable.h"
      38             : #include "ring_types.h" // enable_if_base_of
      39             : #include "scheduled_executor.h"
      40             : #include "gitserver.h"
      41             : #include "channel_handler.h"
      42             : #include "conversation_module.h"
      43             : #include "sync_module.h"
      44             : #include "conversationrepository.h"
      45             : 
      46             : #include <dhtnet/diffie-hellman.h>
      47             : #include <dhtnet/tls_session.h>
      48             : #include <dhtnet/multiplexed_socket.h>
      49             : #include <dhtnet/certstore.h>
      50             : #include <dhtnet/connectionmanager.h>
      51             : #include <dhtnet/upnp/mapping.h>
      52             : #include <dhtnet/ip_utils.h>
      53             : #include <dhtnet/fileutils.h>
      54             : 
      55             : #include <opendht/dhtrunner.h>
      56             : #include <opendht/default_types.h>
      57             : 
      58             : #include <pjsip/sip_types.h>
      59             : #include <json/json.h>
      60             : 
      61             : #include <chrono>
      62             : #include <functional>
      63             : #include <future>
      64             : #include <list>
      65             : #include <map>
      66             : #include <optional>
      67             : #include <vector>
      68             : #include <filesystem>
      69             : 
      70             : #if HAVE_RINGNS
      71             : #include "namedirectory.h"
      72             : #endif
      73             : 
      74             : namespace dev {
      75             : template<unsigned N>
      76             : class FixedHash;
      77             : using h160 = FixedHash<20>;
      78             : using Address = h160;
      79             : } // namespace dev
      80             : 
      81             : namespace jami {
      82             : 
      83             : class IceTransport;
      84             : struct Contact;
      85             : struct AccountArchive;
      86             : class DhtPeerConnector;
      87             : class AccountManager;
      88             : struct AccountInfo;
      89             : class SipTransport;
      90             : class ChanneledOutgoingTransfer;
      91             : class SyncModule;
      92             : struct TextMessageCtx;
      93             : 
      94             : using SipConnectionKey = std::pair<std::string /* uri */, DeviceId>;
      95             : 
      96             : static constexpr const char MIME_TYPE_IM_COMPOSING[] {"application/im-iscomposing+xml"};
      97             : 
      98             : /**
      99             :  * @brief Ring Account is build on top of SIPAccountBase and uses DHT to handle call connectivity.
     100             :  */
     101             : class JamiAccount : public SIPAccountBase
     102             : {
     103             : public:
     104             :     constexpr static auto ACCOUNT_TYPE = ACCOUNT_TYPE_JAMI;
     105             :     constexpr static const std::pair<uint16_t, uint16_t> DHT_PORT_RANGE {4000, 8888};
     106             :     constexpr static int ICE_STREAMS_COUNT {1};
     107             :     constexpr static int ICE_COMP_COUNT_PER_STREAM {1};
     108             : 
     109        3151 :     std::string_view getAccountType() const override { return ACCOUNT_TYPE; }
     110             : 
     111        4391 :     std::shared_ptr<JamiAccount> shared()
     112             :     {
     113        4391 :         return std::static_pointer_cast<JamiAccount>(shared_from_this());
     114             :     }
     115             :     std::shared_ptr<JamiAccount const> shared() const
     116             :     {
     117             :         return std::static_pointer_cast<JamiAccount const>(shared_from_this());
     118             :     }
     119       98673 :     std::weak_ptr<JamiAccount> weak()
     120             :     {
     121       98673 :         return std::static_pointer_cast<JamiAccount>(shared_from_this());
     122             :     }
     123             :     std::weak_ptr<JamiAccount const> weak() const
     124             :     {
     125             :         return std::static_pointer_cast<JamiAccount const>(shared_from_this());
     126             :     }
     127             : 
     128        3798 :     const std::filesystem::path& getPath() const { return idPath_; }
     129             : 
     130       82473 :     const JamiAccountConfig& config() const
     131             :     {
     132       82473 :         return *static_cast<const JamiAccountConfig*>(&Account::config());
     133             :     }
     134             : 
     135             :     void loadConfig() override;
     136             : 
     137             :     /**
     138             :      * Constructor
     139             :      * @param accountID The account identifier
     140             :      */
     141             :     JamiAccount(const std::string& accountId);
     142             : 
     143             :     ~JamiAccount() noexcept;
     144             : 
     145             :     /**
     146             :      * Retrieve volatile details such as recent registration errors
     147             :      * @return std::map< std::string, std::string > The account volatile details
     148             :      */
     149             :     virtual std::map<std::string, std::string> getVolatileAccountDetails() const override;
     150             : 
     151         770 :     std::unique_ptr<AccountConfig> buildConfig() const override
     152             :     {
     153         770 :         return std::make_unique<JamiAccountConfig>(getAccountID(), idPath_);
     154             :     }
     155             : 
     156             :     /**
     157             :      * Adds an account id to the list of accounts to track on the DHT for
     158             :      * buddy presence.
     159             :      *
     160             :      * @param buddy_id  The buddy id.
     161             :      */
     162             :     void trackBuddyPresence(const std::string& buddy_id, bool track);
     163             : 
     164             :     /**
     165             :      * Tells for each tracked account id if it has been seen online so far
     166             :      * in the last DeviceAnnouncement::TYPE.expiration minutes.
     167             :      *
     168             :      * @return map of buddy_uri to bool (online or not)
     169             :      */
     170             :     std::map<std::string, bool> getTrackedBuddyPresence() const;
     171             : 
     172             :     void setActiveCodecs(const std::vector<unsigned>& list) override;
     173             : 
     174             :     /**
     175             :      * Connect to the DHT.
     176             :      */
     177             :     void doRegister() override;
     178             : 
     179             :     /**
     180             :      * Disconnect from the DHT.
     181             :      */
     182             :     void doUnregister(std::function<void(bool)> cb = {}) override;
     183             : 
     184             :     /**
     185             :      * Set the registration state of the specified link
     186             :      * @param state The registration state of underlying VoIPLink
     187             :      */
     188             :     void setRegistrationState(RegistrationState state,
     189             :                               int detail_code = 0,
     190             :                               const std::string& detail_str = {}) override;
     191             : 
     192             :     /**
     193             :      * @return pj_str_t "From" uri based on account information.
     194             :      * From RFC3261: "The To header field first and foremost specifies the desired
     195             :      * logical" recipient of the request, or the address-of-record of the
     196             :      * user or resource that is the target of this request. [...]  As such, it is
     197             :      * very important that the From URI not contain IP addresses or the FQDN
     198             :      * of the host on which the UA is running, since these are not logical
     199             :      * names."
     200             :      */
     201             :     std::string getFromUri() const override;
     202             : 
     203             :     /**
     204             :      * This method adds the correct scheme, hostname and append
     205             :      * the ;transport= parameter at the end of the uri, in accordance with RFC3261.
     206             :      * It is expected that "port" is present in the internal hostname_.
     207             :      *
     208             :      * @return pj_str_t "To" uri based on @param username
     209             :      * @param username A string formatted as : "username"
     210             :      */
     211             :     std::string getToUri(const std::string& username) const override;
     212             : 
     213             :     /**
     214             :      * In the current version, "srv" uri is obtained in the preformated
     215             :      * way: hostname:port. This method adds the correct scheme and append
     216             :      * the ;transport= parameter at the end of the uri, in accordance with RFC3261.
     217             :      *
     218             :      * @return pj_str_t "server" uri based on @param hostPort
     219             :      * @param hostPort A string formatted as : "hostname:port"
     220             :      */
     221             :     std::string getServerUri() const { return ""; };
     222             : 
     223             :     void setIsComposing(const std::string& conversationUri, bool isWriting) override;
     224             : 
     225             :     bool setMessageDisplayed(const std::string& conversationUri,
     226             :                              const std::string& messageId,
     227             :                              int status) override;
     228             : 
     229             :     /**
     230             :      * Get the contact header for
     231             :      * @return The contact header based on account information
     232             :      */
     233             :     std::string getContactHeader(const std::shared_ptr<SipTransport>& sipTransport);
     234             : 
     235             :     /* Returns true if the username and/or hostname match this account */
     236             :     MatchRank matches(std::string_view username, std::string_view hostname) const override;
     237             : 
     238             :     /**
     239             :      * Create outgoing SIPCall.
     240             :      * @note Accepts several urls:
     241             :      *          + jami:uri for calling someone
     242             :      *          + swarm:id for calling a group (will host or join if an active call is detected)
     243             :      *          + rdv:id/uri/device/confId to join a specific conference hosted on (uri, device)
     244             :      * @param[in] toUrl The address to call
     245             :      * @param[in] mediaList list of medias
     246             :      * @return A shared pointer on the created call.
     247             :      */
     248             :     std::shared_ptr<Call> newOutgoingCall(std::string_view toUrl,
     249             :                                           const std::vector<libjami::MediaMap>& mediaList) override;
     250             : 
     251             :     /**
     252             :      * Create incoming SIPCall.
     253             :      * @param[in] from The origin of the call
     254             :      * @param mediaList A list of media
     255             :      * @param sipTr: SIP Transport
     256             :      * @return A shared pointer on the created call.
     257             :      */
     258             :     std::shared_ptr<SIPCall> newIncomingCall(
     259             :         const std::string& from,
     260             :         const std::vector<libjami::MediaMap>& mediaList,
     261             :         const std::shared_ptr<SipTransport>& sipTr = {}) override;
     262             : 
     263             :     void onTextMessage(const std::string& id,
     264             :                        const std::string& from,
     265             :                        const std::string& deviceId,
     266             :                        const std::map<std::string, std::string>& payloads) override;
     267             :     void loadConversation(const std::string& convId);
     268             : 
     269           0 :     virtual bool isTlsEnabled() const override { return true; }
     270         461 :     bool isSrtpEnabled() const override { return true; }
     271             : 
     272           0 :     virtual bool getSrtpFallback() const override { return false; }
     273             : 
     274             :     bool setCertificateStatus(const std::string& cert_id,
     275             :                               dhtnet::tls::TrustStore::PermissionStatus status);
     276             :     bool setCertificateStatus(const std::shared_ptr<crypto::Certificate>& cert,
     277             :                               dhtnet::tls::TrustStore::PermissionStatus status,
     278             :                               bool local = true);
     279             :     std::vector<std::string> getCertificatesByStatus(
     280             :         dhtnet::tls::TrustStore::PermissionStatus status);
     281             : 
     282             :     bool findCertificate(const std::string& id);
     283             :     bool findCertificate(
     284             :         const dht::InfoHash& h,
     285             :         std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb = {});
     286             :     bool findCertificate(
     287             :         const dht::PkId& h,
     288             :         std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb = {});
     289             : 
     290             :     /* contact requests */
     291             :     std::vector<std::map<std::string, std::string>> getTrustRequests() const;
     292             :     // Note: includeConversation used for compatibility test. Do not change
     293             :     bool acceptTrustRequest(const std::string& from, bool includeConversation = true);
     294             :     bool discardTrustRequest(const std::string& from);
     295             :     void declineConversationRequest(const std::string& conversationId);
     296             : 
     297             :     /**
     298             :      * Add contact to the account contact list.
     299             :      * Set confirmed if we know the contact also added us.
     300             :      */
     301             :     void addContact(const std::string& uri, bool confirmed = false);
     302             :     void removeContact(const std::string& uri, bool banned = true);
     303             :     std::vector<std::map<std::string, std::string>> getContacts(bool includeRemoved = false) const;
     304             : 
     305             :     /**
     306             :      * Replace in contact's details related conversation
     307             :      * @param uri           Of the contact
     308             :      * @param oldConv       Current conversation
     309             :      * @param newConv
     310             :      * @return if replaced
     311             :      */
     312             :     bool updateConvForContact(const std::string& uri,
     313             :                               const std::string& oldConv,
     314             :                               const std::string& newConv);
     315             : 
     316             :     ///
     317             :     /// Obtain details about one account contact in serializable form.
     318             :     ///
     319             :     std::map<std::string, std::string> getContactDetails(const std::string& uri) const;
     320             : 
     321             :     void sendTrustRequest(const std::string& to, const std::vector<uint8_t>& payload);
     322             :     void sendMessage(const std::string& to,
     323             :                      const std::string& deviceId,
     324             :                      const std::map<std::string, std::string>& payloads,
     325             :                      uint64_t id,
     326             :                      bool retryOnTimeout = true,
     327             :                      bool onlyConnected = false) override;
     328             : 
     329             :     uint64_t sendTextMessage(const std::string& to,
     330             :                              const std::string& deviceId,
     331             :                              const std::map<std::string, std::string>& payloads,
     332             :                              uint64_t refreshToken = 0,
     333             :                              bool onlyConnected = false) override;
     334             :     void sendInstantMessage(const std::string& convId,
     335             :                             const std::map<std::string, std::string>& msg);
     336             : 
     337             :     /**
     338             :      * Create and return ICE options.
     339             :      */
     340             :     dhtnet::IceTransportOptions getIceOptions() const noexcept override;
     341             :     dhtnet::IpAddr getPublishedIpAddress(uint16_t family = PF_UNSPEC) const override;
     342             : 
     343             :     /* Devices */
     344             :     void addDevice(const std::string& password);
     345             :     /**
     346             :      * Export the archive to a file
     347             :      * @param destinationPath
     348             :      * @param (optional) password, if not provided, will update the contacts only if the archive
     349             :      * doesn't have a password
     350             :      * @return if the archive was exported
     351             :      */
     352             :     bool exportArchive(const std::string& destinationPath,
     353             :                        std::string_view scheme = {},
     354             :                        const std::string& password = {});
     355             :     bool revokeDevice(const std::string& device,
     356             :                       std::string_view scheme = {},
     357             :                       const std::string& password = {});
     358             :     std::map<std::string, std::string> getKnownDevices() const;
     359             : 
     360             :     bool isPasswordValid(const std::string& password);
     361             :     std::vector<uint8_t> getPasswordKey(const std::string& password);
     362             : 
     363             :     bool changeArchivePassword(const std::string& password_old, const std::string& password_new);
     364             : 
     365             :     void connectivityChanged() override;
     366             : 
     367             :     // overloaded methods
     368             :     void flush() override;
     369             : 
     370             : #if HAVE_RINGNS
     371             :     void lookupName(const std::string& name);
     372             :     void lookupAddress(const std::string& address);
     373             :     void registerName(const std::string& name,
     374             :                       const std::string& scheme,
     375             :                       const std::string& password);
     376             : #endif
     377             :     bool searchUser(const std::string& nameQuery);
     378             : 
     379             :     /// \return true if the given DHT message identifier has been treated
     380             :     /// \note if message has not been treated yet this method store this id and returns true at
     381             :     /// further calls
     382             :     bool isMessageTreated(dht::Value::Id id);
     383             : 
     384         673 :     std::shared_ptr<dht::DhtRunner> dht() { return dht_; }
     385             : 
     386        2118 :     const dht::crypto::Identity& identity() const { return id_; }
     387             : 
     388             :     void forEachDevice(const dht::InfoHash& to,
     389             :                        std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)>&& op,
     390             :                        std::function<void(bool)>&& end = {});
     391             : 
     392             :     bool setPushNotificationToken(const std::string& pushDeviceToken = "") override;
     393             :     bool setPushNotificationTopic(const std::string& topic) override;
     394             :     bool setPushNotificationConfig(const std::map<std::string, std::string>& data) override;
     395             : 
     396             :     /**
     397             :      * To be called by clients with relevant data when a push notification is received.
     398             :      */
     399             :     void pushNotificationReceived(const std::string& from,
     400             :                                   const std::map<std::string, std::string>& data);
     401             : 
     402             :     std::string getUserUri() const override;
     403             : 
     404             :     /**
     405             :      * Get last messages (should be used to retrieve messages when launching the client)
     406             :      * @param base_timestamp
     407             :      */
     408             :     std::vector<libjami::Message> getLastMessages(const uint64_t& base_timestamp) override;
     409             : 
     410             :     /**
     411             :      * Start Publish the Jami Account onto the Network
     412             :      */
     413             :     void startAccountPublish();
     414             : 
     415             :     /**
     416             :      * Start Discovery the Jami Account from the Network
     417             :      */
     418             :     void startAccountDiscovery();
     419             : 
     420             :     void saveConfig() const override;
     421             : 
     422         782 :     inline void editConfig(std::function<void(JamiAccountConfig& conf)>&& edit)
     423             :     {
     424         782 :         Account::editConfig(
     425         782 :             [&](AccountConfig& conf) { edit(*static_cast<JamiAccountConfig*>(&conf)); });
     426         782 :     }
     427             : 
     428             :     /**
     429             :      * Get current discovered peers account id and display name
     430             :      */
     431             :     std::map<std::string, std::string> getNearbyPeers() const override;
     432             : 
     433             : #ifdef LIBJAMI_TESTABLE
     434           1 :     dhtnet::ConnectionManager& connectionManager() { return *connectionManager_; }
     435             : 
     436             :     /**
     437             :      * Only used for tests, disable sha3sum verification for transfers.
     438             :      * @param newValue
     439             :      */
     440           1 :     void noSha3sumVerification(bool newValue) { noSha3sumVerification_ = newValue; }
     441             : 
     442           2 :     void publishPresence(bool newValue) { publishPresence_ = newValue; }
     443             : #endif
     444             : 
     445             :     /**
     446             :      * This should be called before flushing the account.
     447             :      * ConnectionManager needs the account to exists
     448             :      */
     449             :     void shutdownConnections();
     450             : 
     451             :     std::string_view currentDeviceId() const;
     452             : 
     453             :     // Received a new commit notification
     454             : 
     455             :     bool handleMessage(const std::string& from,
     456             :                        const std::pair<std::string, std::string>& message) override;
     457             : 
     458             :     void monitor();
     459             :     // conversationId optional
     460             :     std::vector<std::map<std::string, std::string>> getConnectionList(
     461             :         const std::string& conversationId = "");
     462             :     std::vector<std::map<std::string, std::string>> getChannelList(const std::string& connectionId);
     463             : 
     464             :     // File transfer
     465             :     void sendFile(const std::string& conversationId,
     466             :                   const std::filesystem::path& path,
     467             :                   const std::string& name,
     468             :                   const std::string& replyTo);
     469             : 
     470             :     void transferFile(const std::string& conversationId,
     471             :                       const std::string& path,
     472             :                       const std::string& deviceId,
     473             :                       const std::string& fileId,
     474             :                       const std::string& interactionId,
     475             :                       size_t start = 0,
     476             :                       size_t end = 0,
     477             :                       const std::string& sha3Sum = "",
     478             :                       uint64_t lastWriteTime = 0,
     479             :                       std::function<void()> onFinished = {});
     480             : 
     481             :     void askForFileChannel(const std::string& conversationId,
     482             :                            const std::string& deviceId,
     483             :                            const std::string& interactionId,
     484             :                            const std::string& fileId,
     485             :                            size_t start = 0,
     486             :                            size_t end = 0);
     487             : 
     488             :     void askForProfile(const std::string& conversationId,
     489             :                        const std::string& deviceId,
     490             :                        const std::string& memberUri);
     491             : 
     492             :     /**
     493             :      * Retrieve linked transfer manager
     494             :      * @param id    conversationId or empty for fallback
     495             :      * @return linked transfer manager
     496             :      */
     497             :     std::shared_ptr<TransferManager> dataTransfer(const std::string& id = "");
     498             : 
     499             :     ConversationModule* convModule(bool noCreation = false);
     500             :     SyncModule* syncModule();
     501             : 
     502             :     /**
     503             :      * Check (via the cache) if we need to send our profile to a specific device
     504             :      * @param peerUri       Uri that will receive the profile
     505             :      * @param deviceId      Device that will receive the profile
     506             :      * @param sha3Sum       SHA3 hash of the profile
     507             :      */
     508             :     // Note: when swarm will be merged, this can be moved in transferManager
     509             :     bool needToSendProfile(const std::string& peerUri,
     510             :                            const std::string& deviceId,
     511             :                            const std::string& sha3Sum);
     512             :     /**
     513             :      * Send Profile via cached SIP connection
     514             :      * @param convId        Conversation's identifier (can be empty for self profile on sync)
     515             :      * @param peerUri       Uri that will receive the profile
     516             :      * @param deviceId      Device that will receive the profile
     517             :      */
     518             :     void sendProfile(const std::string& convId,
     519             :                      const std::string& peerUri,
     520             :                      const std::string& deviceId);
     521             :     /**
     522             :      * Send profile via cached SIP connection
     523             :      * @param peerUri       Uri that will receive the profile
     524             :      * @param deviceId      Device that will receive the profile
     525             :      */
     526             :     void sendProfile(const std::string& peerUri, const std::string& deviceId);
     527             :     /**
     528             :      * Clear sent profiles (because of a removed contact or new trust request)
     529             :      * @param peerUri       Uri used to clear cache
     530             :      */
     531             :     void clearProfileCache(const std::string& peerUri);
     532             : 
     533             :     std::filesystem::path profilePath() const;
     534             : 
     535       43999 :     const std::shared_ptr<AccountManager>& accountManager() { return accountManager_; }
     536             : 
     537          11 :     bool sha3SumVerify() const { return !noSha3sumVerification_; }
     538             : 
     539             :     /**
     540             :      * Change certificate's validity period
     541             :      * @param pwd       Password for the archive
     542             :      * @param id        Certificate to update ({} for updating the whole chain)
     543             :      * @param validity  New validity
     544             :      * @note forceReloadAccount may be necessary to retrigger the migration
     545             :      */
     546             :     bool setValidity(std::string_view scheme,
     547             :                      const std::string& pwd,
     548             :                      const dht::InfoHash& id,
     549             :                      int64_t validity);
     550             :     /**
     551             :      * Try to reload the account to force the identity to be updated
     552             :      */
     553             :     void forceReloadAccount();
     554             : 
     555             :     /**
     556             :      * Make sure appdata/contacts.yml contains correct informations
     557             :      * @param removedConv   The current removed conversations
     558             :      */
     559             :     void unlinkConversations(const std::set<std::string>& removedConv);
     560             : 
     561             :     bool isValidAccountDevice(const dht::crypto::Certificate& cert) const;
     562             : 
     563             :     /**
     564             :      * Join incoming call to hosted conference
     565             :      * @param callId        The call to join
     566             :      * @param destination   conversation/uri/device/confId to join
     567             :      */
     568             :     void handleIncomingConversationCall(const std::string& callId, const std::string& destination);
     569             : 
     570             :     /**
     571             :      * The DRT component is composed on some special nodes, that are usually present but not
     572             :      * connected. This kind of node corresponds to devices with push notifications & proxy and are
     573             :      * stored in the mobile nodes
     574             :      */
     575         376 :     bool isMobile() const { return config().proxyEnabled and not config().deviceKey.empty(); }
     576             : 
     577             : #ifdef LIBJAMI_TESTABLE
     578           1 :     std::map<Uri::Scheme, std::unique_ptr<ChannelHandlerInterface>>& channelHandlers()
     579             :     {
     580           1 :         return channelHandlers_;
     581             :     };
     582             : #endif
     583             : 
     584       51299 :     dhtnet::tls::CertificateStore& certStore() const { return *certStore_; }
     585             :     /**
     586             :      * Check if a Device is connected
     587             :      * @param deviceId
     588             :      * @return true if connected
     589             :      */
     590             :     bool isConnectedWith(const DeviceId& deviceId) const;
     591             : 
     592             :     /**
     593             :      * Send a presence note
     594             :      * @param note
     595             :      */
     596             :     void sendPresenceNote(const std::string& note);
     597             : 
     598             : private:
     599             :     NON_COPYABLE(JamiAccount);
     600             : 
     601             :     using clock = std::chrono::system_clock;
     602             :     using time_point = clock::time_point;
     603             : 
     604             :     /**
     605             :      * Private structures
     606             :      */
     607             :     struct PendingCall;
     608             :     struct PendingMessage;
     609             :     struct BuddyInfo;
     610             :     struct DiscoveredPeer;
     611             : 
     612           0 :     inline std::string getProxyConfigKey() const
     613             :     {
     614           0 :         const auto& conf = config();
     615           0 :         return dht::InfoHash::get(conf.proxyServer + conf.proxyListUrl).toString();
     616             :     }
     617             : 
     618             :     /**
     619             :      * Compute archive encryption key and DHT storage location from password and PIN.
     620             :      */
     621             :     static std::pair<std::vector<uint8_t>, dht::InfoHash> computeKeys(const std::string& password,
     622             :                                                                       const std::string& pin,
     623             :                                                                       bool previous = false);
     624             : 
     625             :     void trackPresence(const dht::InfoHash& h, BuddyInfo& buddy);
     626             : 
     627             :     void doRegister_();
     628             : 
     629         775 :     const dht::ValueType USER_PROFILE_TYPE = {9, "User profile", std::chrono::hours(24 * 7)};
     630             : 
     631             :     void startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::string& toUri);
     632             : 
     633             :     void onConnectedOutgoingCall(const std::shared_ptr<SIPCall>& call,
     634             :                                  const std::string& to_id,
     635             :                                  dhtnet::IpAddr target);
     636             : 
     637             :     /**
     638             :      * Start a SIP Call
     639             :      * @param call  The current call
     640             :      * @return true if all is correct
     641             :      */
     642             :     bool SIPStartCall(SIPCall& call, const dhtnet::IpAddr& target);
     643             : 
     644             :     /**
     645             :      * Update tracking info when buddy appears offline.
     646             :      */
     647             :     void onTrackedBuddyOffline(const dht::InfoHash&);
     648             : 
     649             :     /**
     650             :      * Update tracking info when buddy appears offline.
     651             :      */
     652             :     void onTrackedBuddyOnline(const dht::InfoHash&);
     653             : 
     654             :     /**
     655             :      * Maps require port via UPnP and other async ops
     656             :      */
     657             :     void registerAsyncOps();
     658             :     /**
     659             :      * Add port mapping callback function.
     660             :      */
     661             :     void onPortMappingAdded(uint16_t port_used, bool success);
     662             :     void forEachPendingCall(const DeviceId& deviceId,
     663             :                             const std::function<void(const std::shared_ptr<SIPCall>&)>& cb);
     664             : 
     665             :     void loadAccountFromDHT(const std::string& archive_password, const std::string& archive_pin);
     666             :     void loadAccount(const std::string& archive_password_scheme = {},
     667             :                      const std::string& archive_password = {},
     668             :                      const std::string& archive_pin = {},
     669             :                      const std::string& archive_path = {});
     670             : 
     671             :     std::vector<std::string> loadBootstrap() const;
     672             : 
     673             :     static std::pair<std::string, std::string> saveIdentity(const dht::crypto::Identity id,
     674             :                                                             const std::filesystem::path& path,
     675             :                                                             const std::string& name);
     676             : 
     677             :     void replyToIncomingIceMsg(const std::shared_ptr<SIPCall>&,
     678             :                                const std::shared_ptr<IceTransport>&,
     679             :                                const std::shared_ptr<IceTransport>&,
     680             :                                const dht::IceCandidates&,
     681             :                                const std::shared_ptr<dht::crypto::Certificate>& from_cert,
     682             :                                const dht::InfoHash& from);
     683             : 
     684             :     void loadCachedUrl(const std::string& url,
     685             :                        const std::filesystem::path& cachePath,
     686             :                        const std::chrono::seconds& cacheDuration,
     687             :                        std::function<void(const dht::http::Response& response)>);
     688             : 
     689             :     std::string getDhtProxyServer(const std::string& serverList);
     690             :     void loadCachedProxyServer(std::function<void(const std::string&)> cb);
     691             : 
     692             :     /**
     693             :      * The TLS settings, used only if tls is chosen as a sip transport.
     694             :      */
     695             :     void generateDhParams();
     696             : 
     697             :     void newOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, const Uri& uri);
     698             :     void newSwarmOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, const Uri& uri);
     699             :     std::shared_ptr<SIPCall> createSubCall(const std::shared_ptr<SIPCall>& mainCall);
     700             : 
     701             :     std::filesystem::path idPath_ {};
     702             :     std::filesystem::path cachePath_ {};
     703             :     std::filesystem::path dataPath_ {};
     704             : 
     705             : #if HAVE_RINGNS
     706             :     std::string registeredName_;
     707             : #endif
     708             :     std::shared_ptr<dht::Logger> logger_;
     709             :     std::shared_ptr<dhtnet::tls::CertificateStore> certStore_;
     710             : 
     711             :     std::shared_ptr<dht::DhtRunner> dht_ {};
     712             :     std::shared_ptr<AccountManager> accountManager_;
     713             :     dht::crypto::Identity id_ {};
     714             : 
     715             :     mutable std::mutex messageMutex_ {};
     716             :     std::map<dht::Value::Id, PendingMessage> sentMessages_;
     717             :     dhtnet::fileutils::IdList treatedMessages_;
     718             : 
     719             :     /* tracked buddies presence */
     720             :     mutable std::mutex buddyInfoMtx;
     721             :     std::map<dht::InfoHash, BuddyInfo> trackedBuddies_;
     722             : 
     723             :     mutable std::mutex dhtValuesMtx_;
     724             : 
     725             :     std::atomic_int syncCnt_ {0};
     726             : 
     727             :     /**
     728             :      * DHT port actually used.
     729             :      * This holds the actual DHT port, which might different from the port
     730             :      * set in the configuration. This can be the case if UPnP is used.
     731             :      */
     732         692 :     in_port_t dhtPortUsed()
     733             :     {
     734         692 :         return (upnpCtrl_ and dhtUpnpMapping_.isValid()) ? dhtUpnpMapping_.getExternalPort()
     735         692 :                                                          : config().dhtPort;
     736             :     }
     737             : 
     738             :     /* Current UPNP mapping */
     739             :     dhtnet::upnp::Mapping dhtUpnpMapping_ {dhtnet::upnp::PortType::UDP};
     740             : 
     741             :     /**
     742             :      * Proxy
     743             :      */
     744             :     std::string proxyServerCached_ {};
     745             : 
     746             :     /**
     747             :      * Optional: via_addr construct from received parameters
     748             :      */
     749             :     pjsip_host_port via_addr_ {};
     750             : 
     751             :     pjsip_transport* via_tp_ {nullptr};
     752             : 
     753             :     mutable std::mutex connManagerMtx_ {};
     754             :     std::unique_ptr<dhtnet::ConnectionManager> connectionManager_;
     755             : 
     756             :     std::mutex discoveryMapMtx_;
     757             :     std::shared_ptr<dht::PeerDiscovery> peerDiscovery_;
     758             :     std::map<dht::InfoHash, DiscoveredPeer> discoveredPeers_;
     759             :     std::map<std::string, std::string> discoveredPeerMap_;
     760             : 
     761             :     /**
     762             :      * Avoid to refresh the cache multiple times
     763             :      */
     764             :     std::atomic_bool isRefreshing_ {false};
     765             :     /**
     766             :      * This will cache the turn server resolution each time we launch
     767             :      * Jami, or for each connectivityChange()
     768             :      */
     769             :     // TODO move in separate class
     770             :     void testTurn(dhtnet::IpAddr server);
     771             :     void refreshTurnDelay(bool scheduleNext);
     772             : 
     773         775 :     std::chrono::seconds turnRefreshDelay_ {std::chrono::seconds(10)};
     774             : 
     775             :     std::set<std::shared_ptr<dht::http::Request>> requests_;
     776             : 
     777             :     mutable std::mutex sipConnsMtx_ {};
     778             :     struct SipConnection
     779             :     {
     780             :         std::shared_ptr<SipTransport> transport;
     781             :         // Needs to keep track of that channel to access underlying ICE
     782             :         // informations, as the SipTransport use a generic transport
     783             :         std::shared_ptr<dhtnet::ChannelSocket> channel;
     784             :     };
     785             :     // NOTE: here we use a vector to avoid race conditions. In fact the contact
     786             :     // can ask for a SIP channel when we are creating a new SIP Channel with this
     787             :     // peer too.
     788             :     std::map<SipConnectionKey, std::vector<SipConnection>> sipConns_;
     789             : 
     790             :     std::mutex pendingCallsMutex_;
     791             :     std::map<DeviceId, std::vector<std::shared_ptr<SIPCall>>> pendingCalls_;
     792             : 
     793             :     std::mutex onConnectionClosedMtx_ {};
     794             :     std::map<DeviceId, std::function<void(const DeviceId&, bool)>> onConnectionClosed_ {};
     795             :     /**
     796             :      * onConnectionClosed contains callbacks that need to be called if a sub call is failing
     797             :      * @param deviceId      The device we are calling
     798             :      * @param eraseDummy    Erase the dummy call (a temporary subcall that must be stop when we will
     799             :      * not create new subcalls)
     800             :      */
     801             :     void callConnectionClosed(const DeviceId& deviceId, bool eraseDummy);
     802             : 
     803             :     /**
     804             :      * Ask a device to open a channeled SIP socket
     805             :      * @param peerId             The contact who owns the device
     806             :      * @param deviceId           The device to ask
     807             :      * @param forceNewConnection If we want a new SIP connection
     808             :      * @param pc                 A pending call to stop if the request fails
     809             :      * @note triggers cacheSIPConnection
     810             :      */
     811             :     void requestSIPConnection(const std::string& peerId,
     812             :                               const DeviceId& deviceId,
     813             :                               const std::string& connectionType,
     814             :                               bool forceNewConnection = false,
     815             :                               const std::shared_ptr<SIPCall>& pc = {});
     816             :     /**
     817             :      * Store a new SIP connection into sipConnections_
     818             :      * @param channel   The new sip channel
     819             :      * @param peerId    The contact who owns the device
     820             :      * @param deviceId  Device linked to that transport
     821             :      */
     822             :     void cacheSIPConnection(std::shared_ptr<dhtnet::ChannelSocket>&& channel,
     823             :                             const std::string& peerId,
     824             :                             const DeviceId& deviceId);
     825             :     /**
     826             :      * Shutdown a SIP connection
     827             :      * @param channel   The channel to close
     828             :      * @param peerId    The contact who owns the device
     829             :      * @param deviceId  Device linked to that transport
     830             :      */
     831             :     void shutdownSIPConnection(const std::shared_ptr<dhtnet::ChannelSocket>& channel,
     832             :                                const std::string& peerId,
     833             :                                const DeviceId& deviceId);
     834             : 
     835             :     // File transfers
     836             :     std::mutex transfersMtx_ {};
     837             :     std::set<std::string> incomingFileTransfers_ {};
     838             : 
     839             :     /**
     840             :      * Helper used to send SIP messages on a channeled connection
     841             :      * @param conn      The connection used
     842             :      * @param to        Peer URI
     843             :      * @param ctx       Context passed to the send request
     844             :      * @param token     Token used
     845             :      * @param data      Message to send
     846             :      * @param cb        Callback to trigger when message is sent
     847             :      * @throw runtime_error if connection is invalid
     848             :      * @return if the request will be sent
     849             :      */
     850             :     bool sendSIPMessage(SipConnection& conn,
     851             :                         const std::string& to,
     852             :                         void* ctx,
     853             :                         uint64_t token,
     854             :                         const std::map<std::string, std::string>& data,
     855             :                         pjsip_endpt_send_callback cb);
     856             :     void onSIPMessageSent(const std::shared_ptr<TextMessageCtx>& ctx, int code);
     857             : 
     858             :     std::mutex gitServersMtx_ {};
     859             :     std::map<dht::Value::Id, std::unique_ptr<GitServer>> gitServers_ {};
     860             : 
     861             :     //// File transfer (for profiles)
     862             :     std::shared_ptr<TransferManager> nonSwarmTransferManager_;
     863             : 
     864             :     std::atomic_bool deviceAnnounced_ {false};
     865             : 
     866             :     bool noSha3sumVerification_ {false};
     867             :     bool publishPresence_ {true};
     868             : 
     869             :     std::map<Uri::Scheme, std::unique_ptr<ChannelHandlerInterface>> channelHandlers_ {};
     870             : 
     871             :     std::unique_ptr<ConversationModule> convModule_;
     872             :     std::mutex moduleMtx_;
     873             :     std::unique_ptr<SyncModule> syncModule_;
     874             : 
     875             :     std::mutex rdvMtx_;
     876             : 
     877             :     int dhtBoundPort_ {0};
     878             : 
     879             :     void initConnectionManager();
     880             : 
     881             :     enum class PresenceState : int {
     882             :         DISCONNECTED = 0,
     883             :         AVAILABLE,
     884             :         CONNECTED
     885             :     };
     886             :     std::map<std::string, PresenceState> presenceState_;
     887             :     std::string presenceNote_;
     888             : };
     889             : 
     890             : static inline std::ostream&
     891             : operator<<(std::ostream& os, const JamiAccount& acc)
     892             : {
     893             :     os << "[Account " << acc.getAccountID() << "] ";
     894             :     return os;
     895             : }
     896             : 
     897             : } // namespace jami

Generated by: LCOV version 1.14