From 4f67b5f1110b56d79fd50847a4bbca194725c895 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Fri, 27 Feb 2015 17:47:32 -0500
Subject: [PATCH] sipcall: call media start/stop only after SDP negotiation is
 done

This patch makes also ICE ready non-blocking.

Refs #67233
Refs #67319

Change-Id: I0bc515078dd4276220430007845df040f27a5cc7
---
 daemon/src/sip/sipcall.cpp | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp
index 43d2191965..1a55a5e4b8 100644
--- a/daemon/src/sip/sipcall.cpp
+++ b/daemon/src/sip/sipcall.cpp
@@ -276,10 +276,6 @@ void SIPCall::answer()
         throw std::runtime_error("Could not send invite request answer (200 OK)");
     }
 
-    if (iceTransport_->isStarted())
-        waitForIceNegotiation(DEFAULT_ICE_NEGO_TIMEOUT);
-    startAllMedia();
-
     setConnectionState(CONNECTED);
     setState(ACTIVE);
 }
@@ -665,9 +661,6 @@ void
 SIPCall::onAnswered()
 {
     if (getConnectionState() != Call::CONNECTED) {
-        if (iceTransport_->isStarted())
-            waitForIceNegotiation(DEFAULT_ICE_NEGO_TIMEOUT);
-        startAllMedia();
         setConnectionState(Call::CONNECTED);
         setState(Call::ACTIVE);
         Manager::instance().peerAnsweredCall(*this);
@@ -818,16 +811,28 @@ SIPCall::stopAllMedia()
 void
 SIPCall::onMediaUpdate()
 {
+    stopAllMedia();
     openPortsUPnP();
 
-    // Handle possible ICE transport
-    if (!startIce())
-        RING_WARN("ICE not started");
-
-    if (getState() == ACTIVE) {
-        // TODO apply changes without restarting everything
-        RING_WARN("Restarting medias");
-        stopAllMedia();
+    if (startIce()) {
+        auto this_ = std::static_pointer_cast<SIPCall>(shared_from_this());
+        auto iceTimeout = std::chrono::steady_clock::now() + std::chrono::seconds {10};
+        Manager::instance().addTask([=] {
+            /* First step: wait for an ICE transport for SIP channel */
+            if (this_->iceTransport_->isFailed() or std::chrono::steady_clock::now() >= iceTimeout) {
+                RING_DBG("ice init failed (or timeout)");
+                this_->setConnectionState(Call::DISCONNECTED);
+                Manager::instance().callFailure(*this_); // signal client
+                this_->removeCall();
+                return false;
+            }
+            if (not this_->iceTransport_->isRunning())
+                return true;
+            startAllMedia();
+            return false;
+        });
+    } else {
+        RING_WARN("Starting medias without ICE");
         startAllMedia();
     }
 }
-- 
GitLab