From f867eb26dc4c93221e488bca5f9fa197cca1c3d6 Mon Sep 17 00:00:00 2001
From: Pierre Nicolas <pierre.nicolas@savoirfairelinux.com>
Date: Thu, 13 Jun 2024 16:24:02 -0400
Subject: [PATCH] namedirectory: ignore lookup result if name already
 registered

Fix a race condition occurring when doing simultaneously lookup and register.

GitLab: #1012
Change-Id: I9fddebb43a06875a1d027ad4c79edb27a39e5eb5
---
 src/jamidht/namedirectory.cpp | 25 ++++++++++++++++++++++++-
 src/jamidht/namedirectory.h   |  4 ++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/jamidht/namedirectory.cpp b/src/jamidht/namedirectory.cpp
index 2b95521e51..9ec7fdd252 100644
--- a/src/jamidht/namedirectory.cpp
+++ b/src/jamidht/namedirectory.cpp
@@ -168,7 +168,16 @@ NameDirectory::lookupAddress(const std::string& addr, LookupCallback cb)
         request->add_on_done_callback(
             [this, cb = std::move(cb), addr](const dht::http::Response& response) {
                 if (response.status_code >= 400 && response.status_code < 500) {
-                    cb("", Response::notFound);
+                    std::string regName, regAddr;
+                    {
+                        std::lock_guard l(cacheLock_);
+                        regName = registeredName_;
+                        regAddr = registeredAddr_;
+                    }
+                    if (not regAddr.empty() and addr == regAddr)
+                        cb(regName, Response::found);
+                    else
+                        cb("", Response::notFound);
                 } else if (response.status_code != 200) {
                     JAMI_ERR("Address lookup for %s failed with code=%i",
                              addr.c_str(),
@@ -356,6 +365,14 @@ NameDirectory::registerName(const std::string& addr,
             cb(RegistrationResponse::alreadyTaken, name);
         return;
     }
+    {
+        std::lock_guard l(cacheLock_);
+        if (isRegisteringName_) {
+            cb(RegistrationResponse::error, name);
+            return;
+        }
+        isRegisteringName_ = true;
+    }
     std::string body = fmt::format("{{\"addr\":\"{}\",\"owner\":\"{}\",\"signature\":\"{}\",\"publickey\":\"{}\"}}",
         addr,
         owner,
@@ -373,6 +390,10 @@ NameDirectory::registerName(const std::string& addr,
 
         request->add_on_done_callback(
             [this, name, addr, cb = std::move(cb)](const dht::http::Response& response) {
+                {
+                    std::lock_guard l(cacheLock_);
+                    isRegisteringName_ = false;
+                }
                 if (response.status_code == 400) {
                     cb(RegistrationResponse::incompleteRequest, name);
                     JAMI_ERR("RegistrationResponse::incompleteRequest");
@@ -411,6 +432,8 @@ NameDirectory::registerName(const std::string& addr,
                              success ? "success" : "failure");
                     if (success) {
                         std::lock_guard l(cacheLock_);
+                        registeredAddr_ = addr;
+                        registeredName_ = name;
                         addrCache_.emplace(name, addr);
                         nameCache_.emplace(addr, name);
                     }
diff --git a/src/jamidht/namedirectory.h b/src/jamidht/namedirectory.h
index 2d7a862ab5..a20c6b95a5 100644
--- a/src/jamidht/namedirectory.h
+++ b/src/jamidht/namedirectory.h
@@ -117,6 +117,10 @@ private:
     std::mutex requestsMtx_ {};
     std::set<std::shared_ptr<dht::http::Request>> requests_;
 
+    bool isRegisteringName_ {false};
+    std::string registeredAddr_ {};
+    std::string registeredName_ {};
+
     std::map<std::string, std::string> nameCache_ {};
     std::map<std::string, std::string> addrCache_ {};
 
-- 
GitLab