From b16c6f96d7fc5aa9c5da46fe95f9173fc7f89bfe Mon Sep 17 00:00:00 2001 From: Adrien Beraud <adrien.beraud@savoirfairelinux.com> Date: Fri, 21 Mar 2025 10:47:45 -0400 Subject: [PATCH] contacts: allow to retrieve Contact object Change-Id: I9c095d814c4707448ecab56c494dcc683a537414 --- src/jamidht/account_manager.cpp | 39 ++++++++++++++------ src/jamidht/account_manager.h | 1 + src/jamidht/contact_list.cpp | 11 ++++++ src/jamidht/contact_list.h | 2 + src/jamidht/conversation_module.cpp | 16 +++----- src/jamidht/jamiaccount.cpp | 57 ++++++++++++++++------------- src/jamidht/jamiaccount.h | 1 + 7 files changed, 78 insertions(+), 49 deletions(-) diff --git a/src/jamidht/account_manager.cpp b/src/jamidht/account_manager.cpp index 60b5bb87d6..bc65a28447 100644 --- a/src/jamidht/account_manager.cpp +++ b/src/jamidht/account_manager.cpp @@ -345,19 +345,19 @@ AccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnouncedCb& dc return; auto conversationId = v.conversationId; // Check if there was an old active conversation. - auto details = info_->contacts->getContactDetails(peer_account); - auto oldConvIt = details.find(libjami::Account::TrustRequest::CONVERSATIONID); - if (oldConvIt != details.end() && oldConvIt->second != "") { - if (conversationId == oldConvIt->second) { - // Here, it's possible that we already have accepted the conversation - // but contact were offline and sync failed. - // So, retrigger the callback so upper layer will clone conversation if needed - // instead of getting stuck in sync. - info_->contacts->acceptConversation(conversationId, v.owner->getLongId().toString()); - return; + if (auto details = info_->contacts->getContactInfo(peer_account)) { + if (!details->conversationId.empty()) { + if (details->conversationId == conversationId) { + // Here, it's possible that we already have accepted the conversation + // but contact were offline and sync failed. + // So, retrigger the callback so upper layer will clone conversation if needed + // instead of getting stuck in sync. + info_->contacts->acceptConversation(conversationId, v.owner->getLongId().toString()); + return; + } + conversationId = details->conversationId; + JAMI_WARNING("Accept with old convId: {}", conversationId); } - conversationId = oldConvIt->second; - JAMI_WARNING("Accept with old convId: {}", conversationId); } sendTrustRequestConfirm(peer_account, conversationId); } @@ -588,6 +588,21 @@ AccountManager::getContactDetails(const std::string& uri) const return info_->contacts->getContactDetails(h); } +std::optional<Contact> +AccountManager::getContactInfo(const std::string& uri) const +{ + if (!info_) { + JAMI_ERROR("[Account {}] getContactInfo(): account not loaded", accountId_); + return {}; + } + dht::InfoHash h(uri); + if (not h) { + JAMI_ERROR("[Account {}] getContactInfo: invalid contact URI", accountId_); + return {}; + } + return info_->contacts->getContactInfo(h); +} + bool AccountManager::findCertificate( const dht::InfoHash& h, diff --git a/src/jamidht/account_manager.h b/src/jamidht/account_manager.h index a3b12b4c3b..631e585ac1 100644 --- a/src/jamidht/account_manager.h +++ b/src/jamidht/account_manager.h @@ -248,6 +248,7 @@ public: /** Obtain details about one account contact in serializable form. */ std::map<std::string, std::string> getContactDetails(const std::string& uri) const; + std::optional<Contact> getContactInfo(const std::string& uri) const; virtual bool findCertificate( const dht::InfoHash& h, diff --git a/src/jamidht/contact_list.cpp b/src/jamidht/contact_list.cpp index ac7916bf0c..1bd16213d7 100644 --- a/src/jamidht/contact_list.cpp +++ b/src/jamidht/contact_list.cpp @@ -172,6 +172,17 @@ ContactList::getContactDetails(const dht::InfoHash& h) const return details; } +std::optional<Contact> +ContactList::getContactInfo(const dht::InfoHash& h) const +{ + const auto c = contacts_.find(h); + if (c == std::end(contacts_)) { + JAMI_WARNING("[Account {}] [Contacts] Contact '{}' not found", accountId_, h.to_view()); + return {}; + } + return c->second; +} + const std::map<dht::InfoHash, Contact>& ContactList::getContacts() const { diff --git a/src/jamidht/contact_list.h b/src/jamidht/contact_list.h index 3084bee687..753f265139 100644 --- a/src/jamidht/contact_list.h +++ b/src/jamidht/contact_list.h @@ -66,6 +66,8 @@ public: /* Contacts */ std::map<std::string, std::string> getContactDetails(const dht::InfoHash&) const; + std::optional<Contact> getContactInfo(const dht::InfoHash&) const; + bool removeContact(const dht::InfoHash&, bool ban); bool removeContactConversation(const dht::InfoHash&); bool addContact(const dht::InfoHash&, diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp index 7d1f4b26c8..bab65b47d8 100644 --- a/src/jamidht/conversation_module.cpp +++ b/src/jamidht/conversation_module.cpp @@ -900,22 +900,16 @@ ConversationModule::Impl::getRequest(const std::string& id) const std::string ConversationModule::Impl::getOneToOneConversation(const std::string& uri) const noexcept { - auto details = accountManager_->getContactDetails(uri); - auto itRemoved = details.find("removed"); - // If contact is removed there is no conversation - if (itRemoved != details.end() && itRemoved->second != "0") { - auto itBanned = details.find("banned"); + if (auto details = accountManager_->getContactInfo(uri)) { + // If contact is removed there is no conversation // If banned, conversation is still on disk - if (itBanned == details.end() || itBanned->second == "0") { + if (details->removed != 0 && details->banned == 0) { // Check if contact is removed - auto itAdded = details.find("added"); - if (std::stoi(itRemoved->second) > std::stoi(itAdded->second)) + if (details->removed > details->added) return {}; } + return details->conversationId; } - auto it = details.find(libjami::Account::TrustRequest::CONVERSATIONID); - if (it != details.end()) - return it->second; return {}; } diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index bb2c6f0527..6c1798ce74 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -1815,33 +1815,31 @@ JamiAccount::onTrackedBuddyOnline(const dht::InfoHash& contactId) ""); } - auto details = getContactDetails(id); - auto it = details.find("confirmed"); - if (it == details.end() or it->second == "false") { - auto convId = convModule()->getOneToOneConversation(id); - if (convId.empty()) - return; - // In this case, the TrustRequest was sent but never confirmed (cause the contact was - // offline maybe) To avoid the contact to never receive the conv request, retry there - std::lock_guard lock(configurationMutex_); - if (accountManager_) { - // Retrieve cached payload for trust request. - auto requestPath = cachePath_ / "requests" / id; - std::vector<uint8_t> payload; - try { - payload = fileutils::loadFile(requestPath); - } catch (...) { - } - - if (payload.size() >= 64000) { - JAMI_WARNING( - "[Account {:s}] Trust request for contact {:s} is too big, reset payload", - getAccountID(), - id); - payload.clear(); + if (auto details = getContactInfo(id)) { + if (!details->confirmed) { + auto convId = convModule()->getOneToOneConversation(id); + if (convId.empty()) + return; + // In this case, the TrustRequest was sent but never confirmed (cause the contact was + // offline maybe) To avoid the contact to never receive the conv request, retry there + std::lock_guard lock(configurationMutex_); + if (accountManager_) { + // Retrieve cached payload for trust request. + auto requestPath = cachePath_ / "requests" / id; + std::vector<uint8_t> payload; + try { + payload = fileutils::loadFile(requestPath); + } catch (...) { + } + if (payload.size() >= 64000) { + JAMI_WARNING( + "[Account {:s}] Trust request for contact {:s} is too big, reset payload", + getAccountID(), + id); + payload.clear(); + } + accountManager_->sendTrustRequest(id, convId, payload); } - - accountManager_->sendTrustRequest(id, convId, payload); } } } @@ -2914,6 +2912,13 @@ JamiAccount::getContactDetails(const std::string& uri) const : std::map<std::string, std::string> {}; } +std::optional<Contact> +JamiAccount::getContactInfo(const std::string& uri) const +{ + std::lock_guard lock(configurationMutex_); + return accountManager_ ? accountManager_->getContactInfo(uri) : std::nullopt; +} + std::vector<std::map<std::string, std::string>> JamiAccount::getContacts(bool includeRemoved) const { diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h index d0049f6add..1e5fd5b9a4 100644 --- a/src/jamidht/jamiaccount.h +++ b/src/jamidht/jamiaccount.h @@ -305,6 +305,7 @@ public: /// Obtain details about one account contact in serializable form. /// std::map<std::string, std::string> getContactDetails(const std::string& uri) const; + std::optional<Contact> getContactInfo(const std::string& uri) const; void sendTrustRequest(const std::string& to, const std::vector<uint8_t>& payload); void sendMessage(const std::string& to, -- GitLab