LCOV - code coverage report
Current view: top level - media/server/service/source - SessionServerManager.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 125 125
Test Date: 2025-02-18 13:13:53 Functions: 100.0 % 15 15

            Line data    Source code
       1              : /*
       2              :  * If not stated otherwise in this file or this component's LICENSE file the
       3              :  * following copyright and licenses apply:
       4              :  *
       5              :  * Copyright 2022 Sky UK
       6              :  *
       7              :  * Licensed under the Apache License, Version 2.0 (the "License");
       8              :  * you may not use this file except in compliance with the License.
       9              :  * You may obtain a copy of the License at
      10              :  *
      11              :  * http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  * Unless required by applicable law or agreed to in writing, software
      14              :  * distributed under the License is distributed on an "AS IS" BASIS,
      15              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  * See the License for the specific language governing permissions and
      17              :  * limitations under the License.
      18              :  */
      19              : 
      20              : #include "SessionServerManager.h"
      21              : #include "IApplicationManagementServer.h"
      22              : #include "IIpcFactory.h"
      23              : #include "ISessionManagementServer.h"
      24              : #include "RialtoServerLogging.h"
      25              : 
      26              : #include <algorithm>
      27              : #include <stdexcept>
      28              : #include <utility>
      29              : 
      30              : namespace
      31              : {
      32            5 : inline bool isNumber(const std::string &text)
      33              : {
      34           10 :     return std::find_if(text.begin(), text.end(), [](const auto &letter) { return !std::isdigit(letter); }) == text.end();
      35              : }
      36              : } // namespace
      37              : 
      38              : namespace firebolt::rialto::server::service
      39              : {
      40           26 : SessionServerManager::SessionServerManager(const ipc::IIpcFactory &ipcFactory, IPlaybackService &playbackService,
      41              :                                            ICdmService &cdmService, IControlService &controlService,
      42           26 :                                            std::unique_ptr<IHeartbeatProcedureFactory> &&heartbeatProcedureFactory)
      43           26 :     : m_playbackService{playbackService}, m_cdmService{cdmService}, m_controlService{controlService},
      44           26 :       m_heartbeatProcedureFactory{std::move(heartbeatProcedureFactory)},
      45           26 :       m_applicationManagementServer{ipcFactory.createApplicationManagementServer(*this)},
      46           26 :       m_sessionManagementServer{ipcFactory.createSessionManagementServer(playbackService, cdmService, controlService)},
      47           52 :       m_isServiceRunning{true}, m_currentState{common::SessionServerState::UNINITIALIZED}
      48              : {
      49           26 :     RIALTO_SERVER_LOG_INFO("Starting Rialto Server Service");
      50              : }
      51              : 
      52           52 : SessionServerManager::~SessionServerManager()
      53              : {
      54           26 :     RIALTO_SERVER_LOG_INFO("Stopping Rialto Server Service");
      55              : 
      56              :     // The following reset() will ensure that the thread ApplicationManagementServer::m_ipcServerThread
      57              :     // isn't currently calling any methods within this class (while it is being destructed)
      58              :     // Particularly, the mentioned thread is responsible for calling the method
      59              :     // SessionServerManager::switchToNotRunning() which then triggers a call to this destuctor
      60              :     // after it calls stopService()
      61           26 :     m_applicationManagementServer.reset();
      62              : 
      63           26 :     stopService();
      64           52 : }
      65              : 
      66            7 : bool SessionServerManager::initialize(int argc, char *argv[])
      67              : try
      68              : {
      69            7 :     if (argc != 2)
      70              :     {
      71            2 :         RIALTO_SERVER_LOG_ERROR("Wrong number of arguments. Rialto Server Service will close now.");
      72            2 :         return false;
      73              :     }
      74            5 :     std::string socketStr{argv[1]};
      75            5 :     if (!isNumber(socketStr))
      76              :     {
      77            1 :         RIALTO_SERVER_LOG_ERROR("Rialto App Management socket is not a number.");
      78            1 :         return false;
      79              :     }
      80            4 :     if (!m_applicationManagementServer->initialize(std::stoi(socketStr)))
      81              :     {
      82            1 :         RIALTO_SERVER_LOG_ERROR("Initialization of Application Management server failed.");
      83            1 :         return false;
      84              :     }
      85            2 :     m_applicationManagementServer->start();
      86            2 :     return m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::UNINITIALIZED);
      87            5 : }
      88            1 : catch (const std::exception &e)
      89              : {
      90            1 :     RIALTO_SERVER_LOG_ERROR("Exception caught during service initialization: %s", e.what());
      91            1 :     return false;
      92              : }
      93              : 
      94            1 : void SessionServerManager::startService()
      95              : {
      96            1 :     std::unique_lock<std::mutex> lock{m_serviceMutex};
      97            3 :     m_serviceCv.wait(lock, [this]() { return !m_isServiceRunning; });
      98            1 : }
      99              : 
     100           30 : void SessionServerManager::stopService()
     101              : {
     102           30 :     std::unique_lock<std::mutex> lock{m_serviceMutex};
     103           30 :     if (m_isServiceRunning)
     104              :     {
     105           26 :         m_isServiceRunning = false;
     106           26 :         m_serviceCv.notify_one();
     107              :     }
     108           30 : }
     109              : 
     110            3 : bool SessionServerManager::setConfiguration(const std::string &socketName, const common::SessionServerState &state,
     111              :                                             const common::MaxResourceCapabilitites &maxResource,
     112              :                                             const std::string &clientDisplayName, unsigned int socketPermissions,
     113              :                                             const std::string &socketOwner, const std::string &socketGroup,
     114              :                                             const std::string &appName)
     115              : {
     116            3 :     if (!m_sessionManagementServer->initialize(socketName, socketPermissions, socketOwner, socketGroup))
     117              :     {
     118            1 :         RIALTO_SERVER_LOG_ERROR("SetConfiguration failed - SessionManagementServer failed to initialize");
     119            1 :         return false;
     120              :     }
     121            2 :     m_sessionManagementServer->start();
     122            2 :     m_playbackService.setMaxPlaybacks(maxResource.maxPlaybacks);
     123            2 :     m_playbackService.setMaxWebAudioPlayers(maxResource.maxWebAudioPlayers);
     124            2 :     m_playbackService.setClientDisplayName(clientDisplayName);
     125            2 :     m_playbackService.setResourceManagerAppName(appName);
     126            2 :     return setState(state);
     127              : }
     128              : 
     129           21 : bool SessionServerManager::setState(const common::SessionServerState &state)
     130              : {
     131           21 :     switch (state)
     132              :     {
     133            7 :     case common::SessionServerState::ACTIVE:
     134              :     {
     135            7 :         return switchToActive();
     136              :     }
     137            7 :     case common::SessionServerState::INACTIVE:
     138              :     {
     139            7 :         return switchToInactive();
     140              :     }
     141            5 :     case common::SessionServerState::NOT_RUNNING:
     142              :     {
     143            5 :         return switchToNotRunning();
     144              :     }
     145            2 :     default:
     146              :     {
     147            2 :         RIALTO_SERVER_LOG_ERROR("SetState failed - unsupported state");
     148            2 :         m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::ERROR);
     149              :     }
     150              :     }
     151            2 :     return false;
     152              : }
     153              : 
     154            1 : void SessionServerManager::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels,
     155              :                                         RIALTO_DEBUG_LEVEL sessionServerLogLevels, RIALTO_DEBUG_LEVEL ipcLogLevels,
     156              :                                         RIALTO_DEBUG_LEVEL serverManagerLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels)
     157              : {
     158            1 :     firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_DEFAULT, defaultLogLevels);
     159            1 :     firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_CLIENT, clientLogLevels);
     160            1 :     firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_SERVER, sessionServerLogLevels);
     161            1 :     firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, ipcLogLevels);
     162            1 :     firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_SERVER_MANAGER, serverManagerLogLevels);
     163            1 :     firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_COMMON, commonLogLevels);
     164            1 :     m_sessionManagementServer->setLogLevels(defaultLogLevels, clientLogLevels, ipcLogLevels, commonLogLevels);
     165              : }
     166              : 
     167            2 : bool SessionServerManager::ping(std::int32_t id, const std::shared_ptr<IAckSender> &ackSender)
     168              : {
     169            2 :     auto heartbeatProcedure{m_heartbeatProcedureFactory->createHeartbeatProcedure(ackSender, id)};
     170              : 
     171              :     // Check all rialto server internal threads
     172            2 :     m_cdmService.ping(heartbeatProcedure);
     173            2 :     m_playbackService.ping(heartbeatProcedure);
     174              : 
     175              :     // Check all Rialto Clients
     176            4 :     return m_controlService.ping(heartbeatProcedure);
     177            2 : }
     178              : 
     179            7 : bool SessionServerManager::switchToActive()
     180              : {
     181            7 :     if (m_currentState.load() == common::SessionServerState::ACTIVE)
     182              :     {
     183            1 :         RIALTO_SERVER_LOG_DEBUG("Session server already in Active state.");
     184            1 :         return true;
     185              :     }
     186            6 :     if (!m_playbackService.switchToActive())
     187              :     {
     188            1 :         RIALTO_SERVER_LOG_ERROR("Player service failed to switch to active state");
     189            1 :         return false;
     190              :     }
     191            5 :     if (!m_cdmService.switchToActive())
     192              :     {
     193            1 :         RIALTO_SERVER_LOG_ERROR("Cdm service failed to switch to active state");
     194            1 :         m_playbackService.switchToInactive();
     195            1 :         return false;
     196              :     }
     197            4 :     if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::ACTIVE))
     198              :     {
     199            3 :         m_controlService.setApplicationState(ApplicationState::RUNNING);
     200            3 :         m_currentState.store(common::SessionServerState::ACTIVE);
     201            3 :         return true;
     202              :     }
     203            1 :     m_playbackService.switchToInactive();
     204            1 :     m_cdmService.switchToInactive();
     205            1 :     return false;
     206              : }
     207              : 
     208            7 : bool SessionServerManager::switchToInactive()
     209              : {
     210            7 :     if (m_currentState.load() == common::SessionServerState::INACTIVE)
     211              :     {
     212            1 :         RIALTO_SERVER_LOG_DEBUG("Session server already in Inactive state.");
     213            1 :         return true;
     214              :     }
     215            6 :     m_playbackService.switchToInactive();
     216            6 :     m_cdmService.switchToInactive();
     217            6 :     if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::INACTIVE))
     218              :     {
     219            3 :         m_controlService.setApplicationState(ApplicationState::INACTIVE);
     220            3 :         m_currentState.store(common::SessionServerState::INACTIVE);
     221            3 :         return true;
     222              :     }
     223            3 :     if (m_currentState.load() == common::SessionServerState::ACTIVE)
     224              :     {
     225            1 :         if (!m_playbackService.switchToActive())
     226              :         {
     227            1 :             RIALTO_SERVER_LOG_WARN("Player service failed to switch to active state");
     228              :         }
     229            1 :         if (!m_cdmService.switchToActive())
     230              :         {
     231            1 :             RIALTO_SERVER_LOG_WARN("Cdm service failed to switch to active state");
     232              :         }
     233              :     }
     234            3 :     return false;
     235              : }
     236              : 
     237            5 : bool SessionServerManager::switchToNotRunning()
     238              : {
     239            5 :     if (m_currentState.load() == common::SessionServerState::NOT_RUNNING)
     240              :     {
     241            1 :         RIALTO_SERVER_LOG_DEBUG("Session server already in NotRunning state.");
     242            1 :         return true;
     243              :     }
     244              :     // Free resources before sending notification to ServerManager
     245            4 :     m_playbackService.switchToInactive();
     246            4 :     m_cdmService.switchToInactive();
     247            4 :     m_controlService.setApplicationState(ApplicationState::UNKNOWN);
     248              : 
     249            4 :     bool result{true};
     250            4 :     if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::NOT_RUNNING))
     251              :     {
     252            3 :         m_currentState.store(common::SessionServerState::NOT_RUNNING);
     253              :     }
     254              :     else
     255              :     {
     256            1 :         result = false;
     257              :     }
     258              : 
     259              :     // stopService() needs to be the last command of this method.
     260              :     // It triggers destruction of SessionServerManager and therefore
     261              :     // some member variables may not be valid after this command
     262            4 :     stopService(); // This HAS TO BE LAST (see above)
     263            4 :     return result;
     264              : }
     265              : } // namespace firebolt::rialto::server::service
        

Generated by: LCOV version 2.0-1