From 6927411cf443acba24d08b4b88cebadd7ab6a715 Mon Sep 17 00:00:00 2001
From: Pierre Lespagnol <pierre.lespagnol@savoirfairelinux.com>
Date: Wed, 2 Dec 2020 16:43:42 -0500
Subject: [PATCH] conference: add kick participant for moderator

Change-Id: Ieb4be786a286ce52501b270e473308ad1fd5ba23
---
 bin/dbus/cx.ring.Ring.CallManager.xml |  6 ++++++
 bin/dbus/dbuscallmanager.cpp          |  5 +++++
 bin/dbus/dbuscallmanager.h            |  1 +
 bin/nodejs/callmanager.i              |  1 +
 configure.ac                          |  2 +-
 src/client/callmanager.cpp            |  7 +++++++
 src/conference.cpp                    | 23 +++++++++++++++++++++++
 src/conference.h                      |  1 +
 src/dring/callmanager_interface.h     |  1 +
 src/manager.cpp                       | 18 ++++++++++++++++++
 src/manager.h                         |  1 +
 11 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/bin/dbus/cx.ring.Ring.CallManager.xml b/bin/dbus/cx.ring.Ring.CallManager.xml
index 4c9acb4dda..b6cd4d539e 100644
--- a/bin/dbus/cx.ring.Ring.CallManager.xml
+++ b/bin/dbus/cx.ring.Ring.CallManager.xml
@@ -270,6 +270,12 @@
             <arg type="b" name="isParticipant" direction="out"/>
         </method>
 
+        <method name="hangupParticipant" tp:name-for-bindings="hangupParticipant">
+            <tp:added version="9.8.0"/>
+            <arg type="s" name="confId" direction="in"/>
+            <arg type="s" name="peerId" direction="in"/>
+        </method>
+
         <method name="addParticipant" tp:name-for-bindings="addParticipant">
             <tp:added version="0.9.7"/>
             <tp:docstring>
diff --git a/bin/dbus/dbuscallmanager.cpp b/bin/dbus/dbuscallmanager.cpp
index 2fbe410b7d..4b74d76b59 100644
--- a/bin/dbus/dbuscallmanager.cpp
+++ b/bin/dbus/dbuscallmanager.cpp
@@ -310,3 +310,8 @@ DBusCallManager::muteParticipant(const std::string& confId, const std::string& p
     DRing::muteParticipant(confId, peerId, state);
 }
 
+void
+DBusCallManager::hangupParticipant(const std::string& confId, const std::string& peerId)
+{
+    DRing::hangupParticipant(confId, peerId);
+}
\ No newline at end of file
diff --git a/bin/dbus/dbuscallmanager.h b/bin/dbus/dbuscallmanager.h
index 5d27a1a294..7df54d4fb0 100644
--- a/bin/dbus/dbuscallmanager.h
+++ b/bin/dbus/dbuscallmanager.h
@@ -103,6 +103,7 @@ class DRING_PUBLIC DBusCallManager :
         void stopSmartInfo();
         void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
         void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
+        void hangupParticipant(const std::string& confId, const std::string& peerId);
 };
 
 #endif // __RING_CALLMANAGER_H__
diff --git a/bin/nodejs/callmanager.i b/bin/nodejs/callmanager.i
index 12f10cad92..cd74578acf 100644
--- a/bin/nodejs/callmanager.i
+++ b/bin/nodejs/callmanager.i
@@ -92,6 +92,7 @@ std::map<std::string, std::string> getConferenceDetails(const std::string& callI
 std::vector<std::map<std::string, std::string>> getConferenceInfos(const std::string& confId);
 void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
 void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
+void hangupParticipant(const std::string& confId, const std::string& peerId);
 
 /* File Playback methods */
 bool startRecordedFilePlayback(const std::string& filepath);
diff --git a/configure.ac b/configure.ac
index a1b6815223..a7ddebe3dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Jami - configure.ac for automake 1.9 and autoconf 2.59
 
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ([2.65])
-AC_INIT([Jami Daemon],[9.7.0],[ring@gnu.org],[jami])
+AC_INIT([Jami Daemon],[9.8.0],[ring@gnu.org],[jami])
 
 AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2020]])
 AC_REVISION([$Revision$])
diff --git a/src/client/callmanager.cpp b/src/client/callmanager.cpp
index 77d0f6bfe4..7979a0e658 100644
--- a/src/client/callmanager.cpp
+++ b/src/client/callmanager.cpp
@@ -358,4 +358,11 @@ muteParticipant(const std::string& confId,
 {
     jami::Manager::instance().muteParticipant(confId, peerId, state);
 }
+
+void
+hangupParticipant(const std::string& confId,
+             const std::string& participant)
+{
+    jami::Manager::instance().hangupParticipant(confId, participant);
+}
 } // namespace DRing
diff --git a/src/conference.cpp b/src/conference.cpp
index 8d3fb3e3a2..e860e519b9 100644
--- a/src/conference.cpp
+++ b/src/conference.cpp
@@ -571,6 +571,9 @@ Conference::onConfOrder(const std::string& callId, const std::string& confOrder)
         if (root.isMember("muteParticipant")  and root.isMember("muteState")) {
             muteParticipant(root["muteParticipant"].asString(), root["muteState"].asString() == "true");
         }
+        if (root.isMember("hangupParticipant")) {
+            hangupParticipant(root["hangupParticipant"].asString());
+        }
     }
 }
 
@@ -751,4 +754,24 @@ Conference::updateConferenceInfo(ConfInfo confInfo)
     sendConferenceInfos();
 }
 
+void
+Conference::hangupParticipant(const std::string& participant_id)
+{
+    if (isHost(participant_id)) {
+        Manager::instance().detachLocalParticipant(id_);
+        return;
+    }
+
+    for (const auto& p : participants_) {
+        if (auto call = Manager::instance().callFactory.getCall<SIPCall>(p)) {
+            std::string_view partURI = call->getPeerNumber();
+            partURI = string_remove_suffix(partURI, '@');
+            if (partURI == participant_id) {
+                Manager::instance().hangupCall(call->getCallId());
+                return;
+            }
+        }
+    }
+}
+
 } // namespace jami
diff --git a/src/conference.h b/src/conference.h
index 0f7cb02b51..cb7801a726 100644
--- a/src/conference.h
+++ b/src/conference.h
@@ -238,6 +238,7 @@ public:
 
     void setModerator(const std::string& uri, const bool& state);
     void muteParticipant(const std::string& uri, const bool& state, const std::string& mediaType = "MEDIA_TYPE_AUDIO");
+    void hangupParticipant(const std::string& participant_id);
 
 private:
     std::weak_ptr<Conference> weak()
diff --git a/src/dring/callmanager_interface.h b/src/dring/callmanager_interface.h
index c52d49e9b7..5ce6fb5dd6 100644
--- a/src/dring/callmanager_interface.h
+++ b/src/dring/callmanager_interface.h
@@ -79,6 +79,7 @@ DRING_PUBLIC std::vector<std::map<std::string, std::string>> getConferenceInfos(
     const std::string& confId);
 DRING_PUBLIC void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
 DRING_PUBLIC void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
+DRING_PUBLIC void hangupParticipant(const std::string& confId, const std::string& participant);
 
 /* Statistic related methods */
 DRING_PUBLIC void startSmartInfo(uint32_t refreshTimeMs);
diff --git a/src/manager.cpp b/src/manager.cpp
index 2d5989952a..b0f58a6706 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -1509,6 +1509,24 @@ Manager::setActiveParticipant(const std::string& confId, const std::string& part
     }
 }
 
+void
+Manager::hangupParticipant(const std::string& confId, const std::string& participant)
+{
+    if (auto conf = getConferenceFromID(confId)) {
+        conf->hangupParticipant(participant);
+    } else if (auto call = getCallFromCallID(confId)) {
+        std::map<std::string, std::string> messages;
+        Json::Value root;
+        root["hangupParticipant"] = participant;
+        Json::StreamWriterBuilder wbuilder;
+        wbuilder["commentStyle"] = "None";
+        wbuilder["indentation"] = "";
+        auto output = Json::writeString(wbuilder, root);
+        messages["application/confOrder+json"] = output;
+        call->sendTextMessage(messages, call->getPeerDisplayName());
+    }
+}
+
 bool
 Manager::detachLocalParticipant(const std::string& conf_id)
 {
diff --git a/src/manager.h b/src/manager.h
index 7e83fd8197..ae33a0fb2a 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -936,6 +936,7 @@ public:
 
     void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
     void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
+    void hangupParticipant(const std::string& confId, const std::string& participant);
 
 private:
     Manager();
-- 
GitLab