From 2e90d8692f2d4493ec2b5c8dfd4b36fecfa8a268 Mon Sep 17 00:00:00 2001
From: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
Date: Thu, 27 Sep 2018 16:53:37 -0400
Subject: [PATCH] call state machine: fix SEARCHING state transition

The call state machine expects a two step state transition: the
daemon should first transition to a terminating state, and then to
OVER. This is almost always the case, expect for the SEARCHING state.

In fact this state is a bit special since it does not correspond to
any well defined daemon state. In order to avoid issues resulting
from an invalid SEARCHING -> ENDED transition, add a temporary state
transition to TERMINATING.

Change-Id: I074d9a1beba2e39ef3089733485b57311e834214
Gitlab: #392
Reviewed-by: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
---
 src/api/call.h       | 23 +++++++++++++++++++++++
 src/newcallmodel.cpp |  7 +++++++
 2 files changed, 30 insertions(+)

diff --git a/src/api/call.h b/src/api/call.h
index 99d3bbc3..a8e51ca1 100644
--- a/src/api/call.h
+++ b/src/api/call.h
@@ -161,6 +161,29 @@ canSendSIPMessage(const Info& call) {
     }
 }
 
+static inline bool
+isTerminating(const Status& status) {
+    switch(status)
+    {
+    case call::Status::INVALID:
+    case call::Status::INACTIVE:
+    case call::Status::ENDED:
+    case call::Status::PEER_BUSY:
+    case call::Status::TIMEOUT:
+    case call::Status::TERMINATING:
+        return true;
+    case call::Status::PAUSED:
+    case call::Status::IN_PROGRESS:
+    case call::Status::INCOMING_RINGING:
+    case call::Status::OUTGOING_RINGING:
+    case call::Status::CONNECTED:
+    case call::Status::CONNECTING:
+    case call::Status::SEARCHING:
+    default:
+        return false;
+    }
+}
+
 } // namespace call
 } // namespace api
 } // namespace lrc
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index af9af13f..d37f91d5 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -492,6 +492,13 @@ NewCallModelPimpl::slotCallStateChanged(const std::string& callId, const std::st
 
     auto status = call::to_status(state);
     auto& call = calls[callId];
+
+    if (status == call::Status::ENDED && !call::isTerminating(call->status)) {
+        call->status = call::Status::TERMINATING;
+        emit linked.callStatusChanged(callId);
+    }
+
+    // proper state transition
     auto previousStatus = call->status;
     call->status = status;
 
-- 
GitLab