From c3f9ea3da67c30826f4c4ab0d91f8c974523af85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Thu, 22 Dec 2022 16:19:25 -0500
Subject: [PATCH] connectivity: avoid TLS handshake loop

Two points are changed in this patch:
+ In peer_channel, the wait return broken_pipe (because if stopped
it's like the write operation, the socket behind is being removed).
Moreover, sending E_INTERRUPTED while in the handshake will cause
gnutls to loop in server_hello.
+ In ConnectionManager, if the ICE is negotiated and started (which
can be the case for a server because the client will start to negotiate
and send the answer on the DHT, so negotiation can finish before getting
remote peers) we cancel the waitForResponse timer to avoid any cancellation
while in the handshake.

GitLab: #519
Change-Id: I530d9eba47aa918c90b6a151061556f4af636fb5
---
 src/connectivity/connectionmanager.cpp    | 5 +++++
 src/connectivity/transport/peer_channel.h | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/connectivity/connectionmanager.cpp b/src/connectivity/connectionmanager.cpp
index 67aaef92b6..65079a5c32 100644
--- a/src/connectivity/connectionmanager.cpp
+++ b/src/connectivity/connectionmanager.cpp
@@ -397,6 +397,11 @@ ConnectionManager::Impl::connectDeviceOnNegoDone(
         return false;
 
     std::unique_lock<std::mutex> lk {info->mutex_};
+    if (info->waitForAnswer_) {
+        // Negotiation is done and connected, go to handshake
+        // and avoid any cancellation at this point.
+        info->waitForAnswer_->cancel();
+    }
     auto& ice = info->ice_;
     if (!ice || !ice->isRunning()) {
         JAMI_ERR("No ICE detected or not running");
diff --git a/src/connectivity/transport/peer_channel.h b/src/connectivity/transport/peer_channel.h
index c47871310c..f86a5d3e32 100644
--- a/src/connectivity/transport/peer_channel.h
+++ b/src/connectivity/transport/peer_channel.h
@@ -44,7 +44,7 @@ public:
         std::unique_lock<std::mutex> lk {mutex_};
         cv_.wait_for(lk, timeout, [this] { return stop_ or not stream_.empty(); });
         if (stop_) {
-            ec = std::make_error_code(std::errc::interrupted);
+            ec = std::make_error_code(std::errc::broken_pipe);
             return -1;
         }
         ec.clear();
-- 
GitLab