LCOV - code coverage report
Current view: top level - src - conference_protocol.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 41.2 % 85 35
Test Date: 2026-06-13 09:18:46 Functions: 18.2 % 11 2

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3              :  *
       4              :  *  This program is free software: you can redistribute it and/or modify
       5              :  *  it under the terms of the GNU General Public License as published by
       6              :  *  the Free Software Foundation, either version 3 of the License, or
       7              :  *  (at your option) any later version.
       8              :  *
       9              :  *  This program is distributed in the hope that it will be useful,
      10              :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12              :  *  GNU General Public License for more details.
      13              :  *
      14              :  *  You should have received a copy of the GNU General Public License
      15              :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16              :  */
      17              : 
      18              : #include "conference_protocol.h"
      19              : 
      20              : #include "logger.h"
      21              : #include "string_utils.h"
      22              : 
      23              : namespace jami {
      24              : 
      25              : namespace ProtocolKeys {
      26              : 
      27              : constexpr static const char* PROTOVERSION = "version";
      28              : constexpr static const char* LAYOUT = "layout";
      29              : // V0
      30              : constexpr static const char* HANDRAISED = "handRaised";
      31              : constexpr static const char* HANDSTATE = "handState";
      32              : constexpr static const char* ACTIVEPART = "activeParticipant";
      33              : constexpr static const char* MUTEPART = "muteParticipant";
      34              : constexpr static const char* MUTESTATE = "muteState";
      35              : constexpr static const char* HANGUPPART = "hangupParticipant";
      36              : // V1
      37              : constexpr static const char* DEVICES = "devices";
      38              : constexpr static const char* MEDIAS = "medias";
      39              : constexpr static const char* RAISEHAND = "raiseHand";
      40              : constexpr static const char* HANGUP = "hangup";
      41              : constexpr static const char* ACTIVE = "active";
      42              : constexpr static const char* MUTEAUDIO = "muteAudio";
      43              : // Future
      44              : constexpr static const char* MUTEVIDEO = "muteVideo";
      45              : constexpr static const char* VOICEACTIVITY = "voiceActivity";
      46              : 
      47              : } // namespace ProtocolKeys
      48              : 
      49              : void
      50            6 : ConfProtocolParser::parse()
      51              : {
      52            6 :     if (data_.isMember(ProtocolKeys::PROTOVERSION)) {
      53            6 :         uint32_t version = data_[ProtocolKeys::PROTOVERSION].asUInt();
      54            6 :         if (version_)
      55            6 :             version_(version);
      56            6 :         if (version == 1) {
      57            6 :             parseV1();
      58              :         } else {
      59            0 :             JAMI_WARNING("Unsupported protocol version {}", version);
      60              :         }
      61              :     } else {
      62            0 :         parseV0();
      63              :     }
      64            6 : }
      65              : 
      66              : void
      67            0 : ConfProtocolParser::parseV0()
      68              : {
      69            0 :     if (!checkAuthorization_ || !raiseHandUri_ || !setLayout_ || !setActiveParticipant_ || !muteParticipant_
      70            0 :         || !kickParticipant_) {
      71            0 :         JAMI_ERROR("Missing methods for ConfProtocolParser");
      72            0 :         return;
      73              :     }
      74              :     // Check if all lambdas set
      75            0 :     auto isPeerModerator = checkAuthorization_(peerId_);
      76            0 :     if (data_.isMember(ProtocolKeys::HANDRAISED)) {
      77            0 :         auto state = data_[ProtocolKeys::HANDSTATE].asString() == TRUE_STR;
      78            0 :         auto uri = data_[ProtocolKeys::HANDRAISED].asString();
      79            0 :         if (peerId_ == uri) {
      80              :             // In this case, the user want to change their state
      81            0 :             raiseHandUri_(uri, state);
      82            0 :         } else if (!state && isPeerModerator) {
      83              :             // In this case a moderator can lower the hand
      84            0 :             raiseHandUri_(uri, state);
      85              :         }
      86            0 :     }
      87            0 :     if (!isPeerModerator) {
      88            0 :         JAMI_WARNING("Received conference order from a non-moderator ({})", peerId_);
      89            0 :         return;
      90              :     }
      91            0 :     if (data_.isMember(ProtocolKeys::LAYOUT)) {
      92            0 :         setLayout_(data_[ProtocolKeys::LAYOUT].asInt());
      93              :     }
      94            0 :     if (data_.isMember(ProtocolKeys::ACTIVEPART)) {
      95            0 :         setActiveParticipant_(data_[ProtocolKeys::ACTIVEPART].asString());
      96              :     }
      97            0 :     if (data_.isMember(ProtocolKeys::MUTEPART) && data_.isMember(ProtocolKeys::MUTESTATE)) {
      98            0 :         muteParticipant_(data_[ProtocolKeys::MUTEPART].asString(),
      99            0 :                          data_[ProtocolKeys::MUTESTATE].asString() == TRUE_STR);
     100              :     }
     101            0 :     if (data_.isMember(ProtocolKeys::HANGUPPART)) {
     102            0 :         kickParticipant_(data_[ProtocolKeys::HANGUPPART].asString());
     103              :     }
     104              : }
     105              : 
     106              : void
     107            6 : ConfProtocolParser::parseV1()
     108              : {
     109           12 :     if (!checkAuthorization_ || !setLayout_ || !raiseHand_ || !hangupParticipant_ || !muteStreamAudio_
     110           12 :         || !setActiveStream_) {
     111            0 :         JAMI_ERROR("Missing methods for ConfProtocolParser");
     112            0 :         return;
     113              :     }
     114              : 
     115            6 :     auto isPeerModerator = checkAuthorization_(peerId_);
     116           30 :     for (Json::Value::const_iterator itr = data_.begin(); itr != data_.end(); itr++) {
     117           12 :         auto key = itr.key();
     118           12 :         if (key == ProtocolKeys::LAYOUT) {
     119              :             // Note: can be removed soon
     120            0 :             if (isPeerModerator)
     121            0 :                 setLayout_(itr->asInt());
     122           12 :         } else if (key == ProtocolKeys::PROTOVERSION) {
     123            6 :             continue;
     124              :         } else {
     125            6 :             auto accValue = *itr;
     126            6 :             if (accValue.isMember(ProtocolKeys::DEVICES)) {
     127            6 :                 auto accountUri = key.asString();
     128            6 :                 for (Json::Value::const_iterator itrd = accValue[ProtocolKeys::DEVICES].begin();
     129           12 :                      itrd != accValue[ProtocolKeys::DEVICES].end();
     130            6 :                      itrd++) {
     131            6 :                     auto deviceId = itrd.key().asString();
     132            6 :                     const auto& deviceValue = *itrd;
     133            6 :                     if (deviceValue.isMember(ProtocolKeys::RAISEHAND)) {
     134            6 :                         auto newState = deviceValue[ProtocolKeys::RAISEHAND].asBool();
     135            6 :                         if (peerId_ == accountUri || (!newState && isPeerModerator))
     136            5 :                             raiseHand_(deviceId, newState);
     137              :                     }
     138            6 :                     if (isPeerModerator && deviceValue.isMember(ProtocolKeys::HANGUP)) {
     139            0 :                         hangupParticipant_(accountUri, deviceId);
     140              :                     }
     141            6 :                     if (deviceValue.isMember(ProtocolKeys::MEDIAS)) {
     142            0 :                         for (Json::Value::const_iterator itrm = accValue[ProtocolKeys::MEDIAS].begin();
     143            0 :                              itrm != accValue[ProtocolKeys::MEDIAS].end();
     144            0 :                              itrm++) {
     145            0 :                             auto streamId = itrm.key().asString();
     146            0 :                             const auto& mediaVal = *itrm;
     147            0 :                             if (mediaVal.isMember(ProtocolKeys::VOICEACTIVITY)) {
     148            0 :                                 voiceActivity_(streamId, mediaVal[ProtocolKeys::VOICEACTIVITY].asBool());
     149              :                             }
     150            0 :                             if (isPeerModerator) {
     151            0 :                                 if (mediaVal.isMember(ProtocolKeys::MUTEVIDEO) && !muteStreamVideo_) {
     152              :                                     // Note: For now, it's not implemented so not set
     153            0 :                                     muteStreamVideo_(accountUri,
     154              :                                                      deviceId,
     155              :                                                      streamId,
     156            0 :                                                      mediaVal[ProtocolKeys::MUTEVIDEO].asBool());
     157              :                                 }
     158            0 :                                 if (mediaVal.isMember(ProtocolKeys::MUTEAUDIO)) {
     159            0 :                                     muteStreamAudio_(accountUri,
     160              :                                                      deviceId,
     161              :                                                      streamId,
     162            0 :                                                      mediaVal[ProtocolKeys::MUTEAUDIO].asBool());
     163              :                                 }
     164            0 :                                 if (mediaVal.isMember(ProtocolKeys::ACTIVE)) {
     165            0 :                                     setActiveStream_(streamId, mediaVal[ProtocolKeys::ACTIVE].asBool());
     166              :                                 }
     167              :                             }
     168            0 :                         }
     169              :                     }
     170            6 :                 }
     171            6 :             }
     172            6 :         }
     173           12 :     }
     174              : }
     175              : 
     176              : } // namespace jami
        

Generated by: LCOV version 2.0-1