From dea87f5756797d630538a079db78b3a849449d2c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Thu, 28 Dec 2023 16:06:06 -0500
Subject: [PATCH] gitserver: shutdown socket if data are not sent correctly

Else, socket can hang for nothing.
Moreover, erasePending is moved for the close to be removed as
soon as possible.
This fix sporadic failures in ut_syncHistory
testSyncCreateAccountExportDeleteReimportOldBackup

Change-Id: If230a780d3db93c6b37269a254e339c873fabe92
---
 src/jamidht/conversation_module.cpp |  3 ++-
 src/jamidht/gitserver.cpp           | 39 ++++++++++++++++++++---------
 2 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp
index e2712371cf..279a2e6580 100644
--- a/src/jamidht/conversation_module.cpp
+++ b/src/jamidht/conversation_module.cpp
@@ -623,6 +623,7 @@ ConversationModule::Impl::fetchNewCommits(const std::string& peer,
                         }
 
                         {
+
                             std::lock_guard<std::mutex> lk(conv->mtx);
                             conv->pending.reset();
                             // Notify peers that a new commit is there (DRT)
@@ -744,7 +745,7 @@ ConversationModule::Impl::handlePendingConversation(const std::string& conversat
         }
         if (!commitId.empty())
             sendMessageNotification(*conversation, false, commitId);
-        lk.unlock();
+        erasePending(); // Will unlock
 
 #ifdef LIBJAMI_TESTABLE
         conversation->onBootstrapStatus(bootstrapCbTest_);
diff --git a/src/jamidht/gitserver.cpp b/src/jamidht/gitserver.cpp
index 78f9aa1514..a8762fb58f 100644
--- a/src/jamidht/gitserver.cpp
+++ b/src/jamidht/gitserver.cpp
@@ -51,6 +51,14 @@ public:
         , repository_(repository)
         , socket_(socket)
     {
+        // Check at least if repository is correct
+        git_repository* repo;
+        if (git_repository_open(&repo, repository_.c_str()) != 0) {
+            socket_->shutdown();
+            return;
+        }
+        git_repository_free(repo);
+
         socket_->setOnRecv([this](const uint8_t* buf, std::size_t len) {
             std::lock_guard<std::mutex> lk(destroyMtx_);
             if (isDestroying_)
@@ -204,7 +212,8 @@ GitServer::Impl::sendReferenceCapabilities(bool sendVersion)
     // https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L166
     git_repository* repo;
     if (git_repository_open(&repo, repository_.c_str()) != 0) {
-        JAMI_WARN("Couldn't open %s", repository_.c_str());
+        JAMI_WARNING("Couldn't open {}", repository_);
+        socket_->shutdown();
         return;
     }
     GitRepository rep {repo, git_repository_free};
@@ -221,14 +230,16 @@ GitServer::Impl::sendReferenceCapabilities(bool sendVersion)
                        packet.str().size(),
                        ec);
         if (ec) {
-            JAMI_WARN("Couldn't send data for %s: %s", repository_.c_str(), ec.message().c_str());
+            JAMI_WARNING("Couldn't send data for {}: {}", repository_, ec.message());
+            socket_->shutdown();
             return;
         }
     }
 
     git_oid commit_id;
     if (git_reference_name_to_id(&commit_id, rep.get(), "HEAD") < 0) {
-        JAMI_ERR("Cannot get reference for HEAD");
+        JAMI_ERROR("Cannot get reference for HEAD");
+        socket_->shutdown();
         return;
     }
     currentHead = git_oid_tostr_s(&commit_id);
@@ -246,7 +257,7 @@ GitServer::Impl::sendReferenceCapabilities(bool sendVersion)
         for (std::size_t i = 0; i < refs.count; ++i) {
             std::string ref = refs.strings[i];
             if (git_reference_name_to_id(&commit_id, rep.get(), ref.c_str()) < 0) {
-                JAMI_WARN("Cannot get reference for %s", ref.c_str());
+                JAMI_WARNING("Cannot get reference for {}", ref);
                 continue;
             }
             currentHead = git_oid_tostr_s(&commit_id);
@@ -263,7 +274,8 @@ GitServer::Impl::sendReferenceCapabilities(bool sendVersion)
     auto toSend = packet.str();
     socket_->write(reinterpret_cast<const unsigned char*>(toSend.c_str()), toSend.size(), ec);
     if (ec) {
-        JAMI_WARN("Couldn't send data for %s: %s", repository_.c_str(), ec.message().c_str());
+        JAMI_WARNING("Couldn't send data for {}: {}", repository_, ec.message());
+        socket_->shutdown();
     }
 }
 
@@ -280,7 +292,8 @@ GitServer::Impl::ACKCommon()
         auto toSend = packet.str();
         socket_->write(reinterpret_cast<const unsigned char*>(toSend.c_str()), toSend.size(), ec);
         if (ec) {
-            JAMI_WARN("Couldn't send data for %s: %s", repository_.c_str(), ec.message().c_str());
+            JAMI_WARNING("Couldn't send data for {}: {}", repository_, ec.message());
+            socket_->shutdown();
         }
     }
 }
@@ -298,7 +311,8 @@ GitServer::Impl::ACKFirst()
         auto toSend = packet.str();
         socket_->write(reinterpret_cast<const unsigned char*>(toSend.c_str()), toSend.size(), ec);
         if (ec) {
-            JAMI_WARN("Couldn't send data for %s: %s", repository_.c_str(), ec.message().c_str());
+            JAMI_WARNING("Couldn't send data for {}: {}", repository_, ec.message());
+            socket_->shutdown();
             return false;
         }
     }
@@ -312,7 +326,8 @@ GitServer::Impl::NAK()
     // NAK
     socket_->write(reinterpret_cast<const unsigned char*>(NAK_PKT.data()), NAK_PKT.size(), ec);
     if (ec) {
-        JAMI_WARN("Couldn't send data for %s: %s", repository_.c_str(), ec.message().c_str());
+        JAMI_WARNING("Couldn't send data for {}: {}", repository_, ec.message());
+        socket_->shutdown();
         return false;
     }
     return true;
@@ -330,7 +345,7 @@ GitServer::Impl::sendPackData()
 
     git_packbuilder* pb_ptr;
     if (git_packbuilder_new(&pb_ptr, repo.get()) != 0) {
-        JAMI_WARN("Couldn't open packbuilder for %s", repository_.c_str());
+        JAMI_WARNING("Couldn't open packbuilder for {}", repository_);
         return;
     }
     GitPackBuilder pb {pb_ptr, git_packbuilder_free};
@@ -338,7 +353,7 @@ GitServer::Impl::sendPackData()
     std::string fetched = wantedReference_;
     git_oid oid;
     if (git_oid_fromstr(&oid, wantedReference_.c_str()) < 0) {
-        JAMI_ERR("Cannot get reference for commit %s", wantedReference_.c_str());
+        JAMI_ERROR("Cannot get reference for commit {}", wantedReference_);
         return;
     }
 
@@ -409,7 +424,7 @@ GitServer::Impl::sendPackData()
                        toSendStr.size(),
                        ec);
         if (ec) {
-            JAMI_WARN("Couldn't send data for %s: %s", repository_.c_str(), ec.message().c_str());
+            JAMI_WARNING("Couldn't send data for {}: {}", repository_, ec.message());
             git_buf_dispose(&data);
             return;
         }
@@ -420,7 +435,7 @@ GitServer::Impl::sendPackData()
     // And finish by a little FLUSH
     socket_->write(reinterpret_cast<const uint8_t*>(FLUSH_PKT.data()), FLUSH_PKT.size(), ec);
     if (ec) {
-        JAMI_WARN("Couldn't send data for %s: %s", repository_.c_str(), ec.message().c_str());
+        JAMI_WARNING("Couldn't send data for {}: {}", repository_, ec.message());
     }
 
     // Clear sent data
-- 
GitLab