LCOV - code coverage report
Current view: top level - src/jamidht - conversation.h (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 97.8 % 45 44
Test Date: 2026-07-06 08:25:38 Functions: 93.8 % 16 15

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3              :  *
       4              :  * This program is free software: you can redistribute it and/or modify
       5              :  * it under the terms of the GNU General Public License as published by
       6              :  * the Free Software Foundation, either version 3 of the License, or
       7              :  * (at your option) any later version.
       8              :  *
       9              :  * This program is distributed in the hope that it will be useful,
      10              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12              :  * GNU General Public License for more details.
      13              :  *
      14              :  * You should have received a copy of the GNU General Public License
      15              :  * along with this program. If not, see <https://www.gnu.org/licenses/>.
      16              :  */
      17              : 
      18              : #pragma once
      19              : 
      20              : #include "jamidht/commit_message.h"
      21              : #include "jamidht/conversationrepository.h"
      22              : #include "conversationrepository.h"
      23              : #include "swarm/swarm_protocol.h"
      24              : #include "jami/conversation_interface.h"
      25              : #include "jamidht/typers.h"
      26              : #include "string_utils.h"
      27              : #include "timestamp.h"
      28              : 
      29              : #include <json/json.h>
      30              : #include <msgpack.hpp>
      31              : 
      32              : #include <chrono>
      33              : #include <functional>
      34              : #include <string>
      35              : #include <vector>
      36              : #include <map>
      37              : #include <memory>
      38              : #include <set>
      39              : 
      40              : #include <asio.hpp>
      41              : 
      42              : namespace dhtnet {
      43              : class ChannelSocket;
      44              : } // namespace dhtnet
      45              : 
      46              : namespace jami {
      47              : 
      48              : namespace ConversationMapKeys {
      49              : static constexpr const char* ID {"id"};
      50              : static constexpr const char* CREATED {"created"};
      51              : static constexpr const char* REMOVED {"removed"};
      52              : static constexpr const char* ERASED {"erased"};
      53              : static constexpr const char* MEMBERS {"members"};
      54              : static constexpr const char* LAST_DISPLAYED {"lastDisplayed"};
      55              : static constexpr const char* RECEIVED {"received"};
      56              : static constexpr const char* DECLINED {"declined"};
      57              : static constexpr const char* FROM {"from"};
      58              : static constexpr const char* CONVERSATIONID {"conversationId"};
      59              : static constexpr const char* METADATAS {"metadatas"};
      60              : static constexpr const char* MODE {"mode"};
      61              : // Millisecond-resolution variants. Legacy keys above keep carrying seconds
      62              : // so that older devices (which ignore unknown keys) remain compatible.
      63              : static constexpr const char* CREATED_MS {"createdMs"};
      64              : static constexpr const char* REMOVED_MS {"removedMs"};
      65              : static constexpr const char* ERASED_MS {"erasedMs"};
      66              : static constexpr const char* RECEIVED_MS {"receivedMs"};
      67              : static constexpr const char* DECLINED_MS {"declinedMs"};
      68              : } // namespace ConversationMapKeys
      69              : 
      70              : namespace ConversationDirectories {
      71              : static constexpr std::string_view PREFERENCES {"preferences"};
      72              : static constexpr std::string_view STATUS {"status"};
      73              : static constexpr std::string_view SENDING {"sending"};
      74              : static constexpr std::string_view FETCHED {"fetched"};
      75              : static constexpr std::string_view ACTIVE_CALLS {"activeCalls"};
      76              : static constexpr std::string_view HOSTED_CALLS {"hostedCalls"};
      77              : static constexpr std::string_view CACHED {"cached"};
      78              : } // namespace ConversationDirectories
      79              : 
      80              : namespace ConversationPreferences {
      81              : static constexpr const char* HOST_CONFERENCES = "hostConferences";
      82              : }
      83              : 
      84              : class JamiAccount;
      85              : class ConversationRepository;
      86              : class TransferManager;
      87              : enum class ConversationMode;
      88              : 
      89              : /**
      90              :  * A ConversationRequest is a request which corresponds to a trust request, but for conversations
      91              :  * It's signed by the sender and contains the members list, the conversationId, and the metadatas
      92              :  * such as the conversation's vcard, etc. (TODO determine)
      93              :  * Transmitted via the UDP DHT
      94              :  */
      95              : struct ConversationRequest
      96              : {
      97              :     std::string conversationId;
      98              :     std::string from;
      99              :     std::map<std::string, std::string> metadatas;
     100              : 
     101              :     TimePoint received {};
     102              :     TimePoint declined {};
     103              : 
     104          324 :     ConversationRequest() = default;
     105              :     ConversationRequest(const Json::Value& json);
     106              : 
     107              :     Json::Value toJson() const;
     108              :     std::map<std::string, std::string> toMap() const;
     109              : 
     110              :     bool operator==(const ConversationRequest& o) const
     111              :     {
     112              :         auto m = toMap();
     113              :         auto om = o.toMap();
     114              :         return m.size() == om.size() && std::equal(m.begin(), m.end(), om.begin());
     115              :     }
     116              : 
     117          459 :     bool isOneToOne() const
     118              :     {
     119              :         try {
     120         1377 :             return metadatas.at("mode") == "0";
     121           70 :         } catch (...) {
     122           70 :         }
     123           70 :         return true;
     124              :     }
     125              : 
     126          169 :     ConversationMode mode() const
     127              :     {
     128              :         try {
     129          507 :             return to_enum<ConversationMode>(metadatas.at("mode"));
     130           50 :         } catch (...) {
     131           50 :         }
     132           50 :         return ConversationMode::ONE_TO_ONE;
     133              :     }
     134              : 
     135              :     // Hand-written msgpack serialization (replaces MSGPACK_DEFINE_MAP) to emit
     136              :     // dual keys: legacy seconds (received/declined) + milliseconds (receivedMs/declinedMs).
     137              :     // Readers prefer the ms keys and fall back to seconds * 1000.
     138              :     template<typename Packer>
     139          232 :     void msgpack_pack(Packer& pk) const
     140              :     {
     141          232 :         int64_t receivedSec = toSecondsSinceEpoch(received);
     142          232 :         int64_t declinedSec = toSecondsSinceEpoch(declined);
     143          232 :         int64_t receivedMs = toMillisecondsSinceEpoch(received);
     144          232 :         int64_t declinedMs = toMillisecondsSinceEpoch(declined);
     145              :         msgpack::type::make_define_map(ConversationMapKeys::FROM,
     146          232 :                                        from,
     147              :                                        ConversationMapKeys::CONVERSATIONID,
     148          232 :                                        conversationId,
     149              :                                        ConversationMapKeys::METADATAS,
     150          232 :                                        metadatas,
     151              :                                        ConversationMapKeys::RECEIVED,
     152              :                                        receivedSec,
     153              :                                        ConversationMapKeys::DECLINED,
     154              :                                        declinedSec,
     155              :                                        ConversationMapKeys::RECEIVED_MS,
     156              :                                        receivedMs,
     157              :                                        ConversationMapKeys::DECLINED_MS,
     158              :                                        declinedMs)
     159          232 :             .msgpack_pack(pk);
     160          232 :     }
     161              :     void msgpack_unpack(const msgpack::object& o);
     162              :     void msgpack_object(msgpack::object* o, msgpack::zone& z) const;
     163              : };
     164              : 
     165              : struct ConvInfo
     166              : {
     167              :     std::string id {};
     168              :     TimePoint created {};
     169              :     TimePoint removed {};
     170              :     TimePoint erased {};
     171              :     std::set<std::string> members;
     172              :     std::string lastDisplayed {};
     173              :     ConversationMode mode {0};
     174              : 
     175          630 :     ConvInfo() = default;
     176           30 :     ConvInfo(const ConvInfo&) = default;
     177            0 :     ConvInfo(ConvInfo&&) = default;
     178          539 :     ConvInfo(const std::string& id)
     179          539 :         : id(id) {};
     180              :     explicit ConvInfo(const Json::Value& json);
     181              : 
     182        17078 :     bool isRemoved() const { return removed >= created; }
     183              : 
     184         2823 :     ConvInfo& operator=(const ConvInfo&) = default;
     185          181 :     ConvInfo& operator=(ConvInfo&&) = default;
     186              : 
     187              :     Json::Value toJson() const;
     188              : 
     189              :     // Hand-written msgpack serialization (replaces MSGPACK_DEFINE_MAP) to emit
     190              :     // dual keys: legacy seconds (created/removed/erased) + milliseconds
     191              :     // (createdMs/removedMs/erasedMs). Readers prefer the ms keys and fall back
     192              :     // to seconds * 1000.
     193              :     template<typename Packer>
     194         2993 :     void msgpack_pack(Packer& pk) const
     195              :     {
     196         2993 :         int64_t createdSec = toSecondsSinceEpoch(created);
     197         2993 :         int64_t removedSec = toSecondsSinceEpoch(removed);
     198         2993 :         int64_t erasedSec = toSecondsSinceEpoch(erased);
     199         2992 :         int64_t createdMs = toMillisecondsSinceEpoch(created);
     200         2992 :         int64_t removedMs = toMillisecondsSinceEpoch(removed);
     201         2993 :         int64_t erasedMs = toMillisecondsSinceEpoch(erased);
     202              :         msgpack::type::make_define_map(ConversationMapKeys::ID,
     203         2993 :                                        id,
     204              :                                        ConversationMapKeys::CREATED,
     205              :                                        createdSec,
     206              :                                        ConversationMapKeys::REMOVED,
     207              :                                        removedSec,
     208              :                                        ConversationMapKeys::ERASED,
     209              :                                        erasedSec,
     210              :                                        ConversationMapKeys::MEMBERS,
     211         2993 :                                        members,
     212              :                                        ConversationMapKeys::LAST_DISPLAYED,
     213         2993 :                                        lastDisplayed,
     214              :                                        ConversationMapKeys::MODE,
     215         2993 :                                        mode,
     216              :                                        ConversationMapKeys::CREATED_MS,
     217              :                                        createdMs,
     218              :                                        ConversationMapKeys::REMOVED_MS,
     219              :                                        removedMs,
     220              :                                        ConversationMapKeys::ERASED_MS,
     221              :                                        erasedMs)
     222         2993 :             .msgpack_pack(pk);
     223         2993 :     }
     224              :     void msgpack_unpack(const msgpack::object& o);
     225              :     void msgpack_object(msgpack::object* o, msgpack::zone& z) const;
     226              : };
     227              : 
     228              : using OnPullCb = std::function<void(bool fetchOk)>;
     229              : using OnLoadMessages = std::function<void(std::vector<libjami::SwarmMessage>&& messages)>;
     230              : using OnCommitCb = std::function<void(const std::string&)>;
     231              : using OnDoneCb = std::function<void(bool, const std::string&)>;
     232              : using OnMembersChanged = std::function<void(const std::set<std::string>&)>;
     233              : using DeviceId = dht::PkId;
     234              : using GitSocketList = std::map<DeviceId, std::shared_ptr<dhtnet::ChannelSocket>>;
     235              : using ChannelCb = std::function<bool(const std::shared_ptr<dhtnet::ChannelSocket>&)>;
     236              : using NeedSocketCb
     237              :     = std::function<void(const std::string&, const std::string&, ChannelCb&&, const std::string&, bool noNewSocket)>;
     238              : 
     239              : class Conversation : public std::enable_shared_from_this<Conversation>
     240              : {
     241              : public:
     242              :     Conversation(const std::shared_ptr<JamiAccount>& account,
     243              :                  ConversationMode mode,
     244              :                  const std::string& otherMember = "");
     245              :     Conversation(const std::shared_ptr<JamiAccount>& account, const std::string& conversationId = "");
     246              :     Conversation(const std::shared_ptr<JamiAccount>& account,
     247              :                  const std::string& remoteDevice,
     248              :                  const std::string& conversationId);
     249              :     ~Conversation();
     250              : 
     251              :     /**
     252              :      * Print the state of the DRT linked to the conversation
     253              :      */
     254              :     void monitor();
     255              : 
     256              : #ifdef LIBJAMI_TEST
     257              :     enum class BootstrapStatus { FAILED, FALLBACK, SUCCESS };
     258              :     /**
     259              :      * Used by the tests to get whenever the DRT is connected/disconnected
     260              :      */
     261              :     void onBootstrapStatus(const std::function<void(std::string, BootstrapStatus)>& cb);
     262              : 
     263              :     std::vector<libjami::SwarmMessage> loadMessagesSync(const LogOptions& options);
     264              :     void announce(const std::vector<std::map<std::string, std::string>>& commits, bool commitFromSelf = false);
     265              :     void announce(const std::string& commitId, bool commitFromSelf = false);
     266              : #endif
     267              : 
     268              :     /**
     269              :      * Bootstrap swarm manager to other peers
     270              :      * @param onBootstrapped     Callback called when connection is established successfully
     271              :      * @param knownDevices       Optional list of live devices to seed the DRT with.
     272              :      *                           Normally empty: candidates are fed by the per-device
     273              :      *                           presence monitoring through addKnownDevices().
     274              :      */
     275              :     void bootstrap(std::function<void()> onBootstrapped, const std::vector<DeviceId>& knownDevices = {});
     276              : 
     277              :     /**
     278              :      * Add known devices to the swarm manager
     279              :      * @param devices
     280              :      * @param memberUri
     281              :      */
     282              :     void addKnownDevices(const std::vector<DeviceId>& devices, const std::string& memberUri);
     283              : 
     284              :     /**
     285              :      * Proactively connect a device in the swarm, bypassing DRT bucket checks.
     286              :      * Used when a TCP link to the device already exists.
     287              :      * @param deviceId
     288              :      */
     289              :     void connectNode(const DeviceId& deviceId);
     290              : 
     291              :     /**
     292              :      * Refresh active calls.
     293              :      * @note: If the host crash during a call, when initializing, we need to update
     294              :      * and commit all the crashed calls
     295              :      * @return  Commits added
     296              :      */
     297              :     std::vector<std::string> commitsEndedCalls();
     298              : 
     299              :     void onMembersChanged(OnMembersChanged&& cb);
     300              : 
     301              :     /**
     302              :      * Set the callback that will be called whenever a new socket will be needed
     303              :      * @param cb
     304              :      */
     305              :     void onNeedSocket(NeedSocketCb cb);
     306              :     /**
     307              :      * Add swarm connection to the DRT
     308              :      * @param channel       Related channel
     309              :      */
     310              :     void addSwarmChannel(std::shared_ptr<dhtnet::ChannelSocket> channel);
     311              : 
     312              :     /**
     313              :      * Get conversation's id
     314              :      * @return conversation Id
     315              :      */
     316              :     std::string id() const;
     317              : 
     318              :     // Member management
     319              :     /**
     320              :      * Add conversation member
     321              :      * @param uri   Member to add
     322              :      * @param cb    On done cb
     323              :      */
     324              :     void addMember(const std::string& contactUri, const OnDoneCb& cb = {});
     325              :     void removeMember(const std::string& contactUri, bool isDevice, const OnDoneCb& cb = {});
     326              :     /**
     327              :      * @param includeInvited        If we want invited members
     328              :      * @param includeLeft           If we want left members
     329              :      * @param includeBanned         If we want banned members
     330              :      * @return a vector of member details:
     331              :      * {
     332              :      *  "uri":"xxx",
     333              :      *  "role":"member/admin/invited",
     334              :      *  "lastDisplayed":"id"
     335              :      *  ...
     336              :      * }
     337              :      */
     338              :     std::vector<std::map<std::string, std::string>> getMembers(bool includeInvited = false,
     339              :                                                                bool includeLeft = false,
     340              :                                                                bool includeBanned = false) const;
     341              : 
     342              :     /**
     343              :      * @param filter           If we want to remove one member
     344              :      * @param filteredRoles    If we want to ignore some roles
     345              :      * @return members' uris
     346              :      */
     347              :     std::set<std::string> memberUris(std::string_view filter = {},
     348              :                                      const std::set<MemberRole>& filteredRoles = {MemberRole::INVITED,
     349              :                                                                                   MemberRole::LEFT,
     350              :                                                                                   MemberRole::BANNED}) const;
     351              : 
     352              :     std::vector<std::map<std::string, std::string>> getTrackedMembers() const;
     353              : 
     354              :     /**
     355              :      * Get peers to sync with. This is mostly managed by the DRT
     356              :      * @return some mobile nodes and all connected nodes
     357              :      */
     358              :     std::vector<NodeId> peersToSyncWith() const;
     359              :     /**
     360              :      * Check if we're at least connected to one node
     361              :      * @return if the DRT is connected
     362              :      */
     363              :     bool isBootstrapped() const;
     364              :     /**
     365              :      * Retrieve the uri from a deviceId
     366              :      * @note used by swarm manager (peersToSyncWith)
     367              :      * @param deviceId
     368              :      * @return corresponding issuer
     369              :      */
     370              :     std::string uriFromDevice(const std::string& deviceId) const;
     371              : 
     372              :     /**
     373              :      * Join a conversation
     374              :      * @return commit id to send
     375              :      */
     376              :     std::string join();
     377              : 
     378              :     /**
     379              :      * Test if an URI is a member
     380              :      * @param uri       URI to test
     381              :      * @return true if uri is a member
     382              :      */
     383              :     bool isMember(const std::string& uri, bool includeInvited = false) const;
     384              :     bool isMemberBanned(const std::string& uri) const;
     385              :     bool isDeviceBanned(const std::string& deviceId) const;
     386              : 
     387              :     /**
     388              :      * Check if a device is authorized to clone or interact with the conversation.
     389              :      * Assumption: the deviceId must already be a confirmed device of the user.
     390              :      * @param uri               URI of the user
     391              :      * @param deviceId          Device id to check
     392              :      * @param includeInvited    If true, consider invited members as authorized.
     393              :      */
     394              :     bool isPeerAuthorized(const std::string& uri, const std::string& deviceId, bool includeInvited = false) const;
     395              : 
     396              :     void createCommit(CommitMessage&& message, OnCommitCb&& onCommit = {}, OnDoneCb&& cb = {});
     397              : 
     398              :     /**
     399              :      * Get a range of messages
     400              :      * @param cb        The callback when loaded
     401              :      * @param options   The log options
     402              :      */
     403              :     void loadMessages(const OnLoadMessages& cb, const LogOptions& options);
     404              :     /**
     405              :      * For every loaded TEXT message that has no bodyOverwrite in pluginData, runs the plugin
     406              :      * ChatServicesManager transform to obtain one.  If the plugin produces a bodyOverwrite,
     407              :      * stores it in pluginData and emits SwarmMessageUpdated for the affected message
     408              :      * (edition commits signal the original message; originals signal themselves).
     409              :      * No-op when no plugin chat handlers are registered.
     410              :      */
     411              :     void loadMissingBodyOverwrites() const;
     412              :     /**
     413              :      * Drops all bodyOverwrite entries from the loaded message history, then calls
     414              :      * loadMissingBodyOverwrites() to re-derive them from scratch via the plugin transform.
     415              :      * Use when plugin chat handlers are reloaded or their transform logic has changed.
     416              :      */
     417              :     void reloadBodyOverwriteMessages() const;
     418              :     /**
     419              :      * Stores or clears the plugin-provided bodyOverwrite for a single message.
     420              :      * An empty bodyOverwrite sets the entry to "" (marks the message as processed with no
     421              :      * overwrite, preventing reprocessing); a non-empty value replaces it.
     422              :      * If messageId refers to an edition commit, SwarmMessageUpdated is emitted for the
     423              :      * original message (the one clients display); otherwise it is emitted for messageId itself.
     424              :      * @param messageId     Id of the message (original or edition commit) to update.
     425              :      * @param bodyOverwrite Plugin-transformed body text, or empty to clear the override.
     426              :      */
     427              :     void updateMessageBodyOverwrite(const std::string& messageId, const std::string& bodyOverwrite) const;
     428              :     /**
     429              :      * Removes all bodyOverwrite entries from every message in the loaded history and emits
     430              :      * SwarmMessageUpdated for each affected message so clients revert to the original
     431              :      * body.  Edition commits are resolved to their original message before signalling.
     432              :      */
     433              :     void clearBodyOverwrites() const;
     434              :     /**
     435              :      * Clear all cached messages
     436              :      */
     437              :     void clearCache();
     438              :     /**
     439              :      * Check if a commit exists in the repository
     440              :      * @param commitId The commit id to check
     441              :      * @return true if the commit was found, false if not or if an error occurred
     442              :      */
     443              :     bool hasCommit(const std::string& commitId) const;
     444              :     /**
     445              :      * Retrieve one commit
     446              :      * @param   commitId
     447              :      * @return  The commit if found
     448              :      */
     449              :     std::optional<ConversationCommit> getCommit(const std::string& commitId) const;
     450              :     /**
     451              :      * Get last commit id
     452              :      * @return last commit id
     453              :      */
     454              :     std::string lastCommitId() const;
     455              : 
     456              :     /**
     457              :      * Fetch and merge from peer
     458              :      * @param deviceId  Peer device
     459              :      * @param cb        On pulled callback
     460              :      * @param commitId  Commit id that triggered this fetch
     461              :      * @return true if callback will be called later
     462              :      */
     463              :     bool pull(const std::string& deviceId, OnPullCb&& cb, std::string commitId = "");
     464              :     /**
     465              :      * Fetch new commits and re-ask for waiting files
     466              :      * @param member
     467              :      * @param deviceId
     468              :      * @param cb        cf pull()
     469              :      * @param commitId  cf pull()
     470              :      */
     471              :     void sync(const std::string& member, const std::string& deviceId, OnPullCb&& cb, std::string commitId = "");
     472              : 
     473              :     /**
     474              :      * Generate an invitation to send to new contacts
     475              :      * @return the invite to send
     476              :      */
     477              :     std::map<std::string, std::string> generateInvitation() const;
     478              : 
     479              :     /**
     480              :      * Leave a conversation
     481              :      * @return commit id to send
     482              :      */
     483              :     std::string leave();
     484              : 
     485              :     /**
     486              :      * Set a conversation as removing (when loading convInfo and still not sync)
     487              :      * @todo: not a big fan to see this here. can be set in the constructor
     488              :      * cause it's used by jamiaccount when loading conversations
     489              :      */
     490              :     void setRemovingFlag();
     491              : 
     492              :     /**
     493              :      * Check if we are removing the conversation
     494              :      * @return true if left the room
     495              :      */
     496              :     bool isRemoving();
     497              : 
     498              :     /**
     499              :      * Erase all related datas
     500              :      */
     501              :     void erase();
     502              : 
     503              :     /**
     504              :      * Get conversation's mode
     505              :      * @return the mode
     506              :      */
     507              :     ConversationMode mode() const;
     508              : 
     509              :     /**
     510              :      * One to one util, get initial members
     511              :      * @return initial members
     512              :      */
     513              :     std::vector<std::string> getInitialMembers() const;
     514              :     bool isInitialMember(const std::string& uri) const;
     515              : 
     516              :     /**
     517              :      * Change repository's infos
     518              :      * @param map       New infos (supported keys: title, description, avatar)
     519              :      * @param cb        On commited
     520              :      */
     521              :     void updateInfos(const std::map<std::string, std::string>& map, const OnDoneCb& cb = {});
     522              : 
     523              :     /**
     524              :      * Change user's preferences
     525              :      * @param map       New preferences
     526              :      */
     527              :     void updatePreferences(const std::map<std::string, std::string>& map);
     528              : 
     529              :     /**
     530              :      * Retrieve current infos (title, description, avatar, mode)
     531              :      * @return infos
     532              :      */
     533              :     std::map<std::string, std::string> infos() const;
     534              :     /**
     535              :      * Retrieve current preferences (color, notification, etc)
     536              :      * @param includeLastModified       If we want to know when the preferences were modified
     537              :      * @return preferences
     538              :      */
     539              :     std::map<std::string, std::string> preferences(bool includeLastModified) const;
     540              :     std::vector<uint8_t> vCard() const;
     541              : 
     542              :     /////// File transfer
     543              : 
     544              :     /**
     545              :      * Access to transfer manager
     546              :      */
     547              :     std::shared_ptr<TransferManager> dataTransfer() const;
     548              : 
     549              :     /**
     550              :      * Choose if we can accept channel request
     551              :      * @param member        member to check
     552              :      * @param fileId        file transfer to check (needs to be waiting)
     553              :      * @param verifyShaSum  for debug only
     554              :      * @return if we accept the channel request
     555              :      */
     556              :     bool onFileChannelRequest(const std::string& member,
     557              :                               const std::string& fileId,
     558              :                               std::filesystem::path& path,
     559              :                               std::string& sha3sum) const;
     560              :     /**
     561              :      * Adds a file to the waiting list and ask members
     562              :      * @param interactionId     Related interaction id
     563              :      * @param fileId            Related id
     564              :      * @param path              Destination
     565              :      * @param member            Member if we know from who to pull file
     566              :      * @param deviceId          Device if we know from who to pull file
     567              :      * @return id of the file
     568              :      */
     569              :     bool downloadFile(const std::string& interactionId,
     570              :                       const std::string& fileId,
     571              :                       const std::string& path,
     572              :                       const std::string& member = "",
     573              :                       const std::string& deviceId = "");
     574              : 
     575              :     /**
     576              :      * Reset fetched information
     577              :      */
     578              :     void clearFetched();
     579              :     /**
     580              :      * Store information about who fetch or not. This simplify sync (sync when a device without the
     581              :      * last fetch is detected)
     582              :      * @param deviceId
     583              :      * @param commitId
     584              :      */
     585              :     void hasFetched(const std::string& deviceId, const std::string& commitId);
     586              : 
     587              :     /**
     588              :      * Store last read commit (returned in getMembers)
     589              :      * @param uri               Of the member
     590              :      * @param interactionId     Last interaction displayed
     591              :      * @return if updated
     592              :      */
     593              :     bool setMessageDisplayed(const std::string& uri, const std::string& interactionId);
     594              :     /**
     595              :      * Retrieve last displayed and fetch status per member
     596              :      * @return A map with the following structure:
     597              :      * {uri, {
     598              :      *          {"fetch", "commitId"},
     599              :      *          {"fetched_ts", "timestamp"},
     600              :      *          {"read", "commitId"},
     601              :      *          {"read_ts", "timestamp"}
     602              :      *       }
     603              :      * }
     604              :      */
     605              :     std::map<std::string, std::map<std::string, std::string>> messageStatus() const;
     606              :     /**
     607              :      * Update fetch/read status
     608              :      * @param messageStatus     A map with the following structure:
     609              :      * {uri, {
     610              :      *          {"fetch", "commitId"},
     611              :      *          {"fetched_ts", "timestamp"},
     612              :      *          {"read", "commitId"},
     613              :      *          {"read_ts", "timestamp"}
     614              :      *       }
     615              :      * }
     616              :      */
     617              :     void updateMessageStatus(const std::map<std::string, std::map<std::string, std::string>>& messageStatus);
     618              :     void onMessageStatusChanged(
     619              :         const std::function<void(const std::map<std::string, std::map<std::string, std::string>>&)>& cb);
     620              :     /**
     621              :      * Retrieve how many interactions there is from HEAD to interactionId
     622              :      * @param toId      "" for getting the whole history
     623              :      * @param fromId    "" => HEAD
     624              :      * @param authorURI author to stop counting
     625              :      * @return number of interactions since interactionId
     626              :      */
     627              :     uint32_t countInteractions(const std::string& toId,
     628              :                                const std::string& fromId = "",
     629              :                                const std::string& authorUri = "") const;
     630              :     /**
     631              :      * Search in the conversation via a filter
     632              :      * @param req       Id of the request
     633              :      * @param filter    Parameters for the search
     634              :      * @param flag      To check when search is finished
     635              :      * @note triggers messagesFound
     636              :      */
     637              :     void search(uint32_t req, const Filter& filter, const std::shared_ptr<std::atomic_int>& flag) const;
     638              :     /**
     639              :      * Host a conference in the conversation
     640              :      * @note the message must have "confId"
     641              :      * @note Update hostedCalls_ and commit in the conversation
     642              :      * @param message       message to commit
     643              :      * @param cb            callback triggered when committed
     644              :      */
     645              :     void hostConference(CommitMessage&& message, OnDoneCb&& cb = {});
     646              :     /**
     647              :      * Announce the end of a call
     648              :      * @note the message must have "confId"
     649              :      * @note called when conference is finished
     650              :      * @param message       message to commit
     651              :      * @param cb            callback triggered when committed
     652              :      */
     653              :     void removeActiveConference(CommitMessage&& message, OnDoneCb&& cb = {});
     654              :     /**
     655              :      * Check if we're currently hosting this conference
     656              :      * @param confId
     657              :      * @return true if hosting
     658              :      */
     659              :     bool isHosting(const std::string& confId) const;
     660              :     /**
     661              :      * Return current detected calls
     662              :      * @return a vector of map with the following keys: "id", "uri", "device"
     663              :      */
     664              :     std::vector<std::map<std::string, std::string>> currentCalls() const;
     665              : 
     666              :     /**
     667              :      * Git operations will need a ChannelSocket for cloning/fetching commits
     668              :      * Because libgit2 is a C library, we store the pointer in the corresponding conversation
     669              :      * and the GitTransport will inject to libgit2 whenever needed
     670              :      */
     671              :     std::shared_ptr<dhtnet::ChannelSocket> gitSocket(const DeviceId& deviceId) const;
     672              :     void addGitSocket(const DeviceId& deviceId, const std::shared_ptr<dhtnet::ChannelSocket>& socket);
     673              :     void removeGitSocket(const DeviceId& deviceId);
     674              : 
     675              :     /**
     676              :      * Stop SwarmManager, bootstrap and gitSockets
     677              :      */
     678              :     void shutdownConnections();
     679              : 
     680              :     /**
     681              :      * If we change from one network to one another, we will need to update the state of the connections
     682              :      */
     683              :     void connectivityChanged();
     684              : 
     685              :     /**
     686              :      * @return getAllNodes()    Nodes that are linked to the conversation
     687              :      */
     688              :     std::vector<jami::DeviceId> getDeviceIdList() const;
     689              : 
     690              :     /**
     691              :      * Get Typers object
     692              :      * @return Typers object
     693              :      */
     694              :     std::shared_ptr<Typers> typers() const;
     695              : 
     696              :     /**
     697              :      * Get connectivity information for the conversation
     698              :      * @return map of connectivity info
     699              :      */
     700              :     std::vector<std::map<std::string, std::string>> getConnectivity() const;
     701              : 
     702              : private:
     703              :     std::shared_ptr<Conversation> shared() { return std::static_pointer_cast<Conversation>(shared_from_this()); }
     704              :     std::shared_ptr<Conversation const> shared() const
     705              :     {
     706              :         return std::static_pointer_cast<Conversation const>(shared_from_this());
     707              :     }
     708         3640 :     std::weak_ptr<Conversation> weak() { return std::static_pointer_cast<Conversation>(shared_from_this()); }
     709            4 :     std::weak_ptr<Conversation const> weak() const
     710              :     {
     711            4 :         return std::static_pointer_cast<Conversation const>(shared_from_this());
     712              :     }
     713              : 
     714              :     // Private because of weak()
     715              :     class Impl;
     716              :     std::unique_ptr<Impl> pimpl_;
     717              : };
     718              : 
     719              : } // namespace jami
        

Generated by: LCOV version 2.0-1