LCOV - code coverage report
Current view: top level - serverManager/ipc/source - Client.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.8 % 155 119
Test Date: 2025-02-18 13:13:53 Functions: 100.0 % 14 14

            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 "Client.h"
      21              : #include "IIpcChannel.h"
      22              : #include "ISessionServerAppManager.h"
      23              : #include "IpcLoop.h"
      24              : #include "RialtoServerManagerLogging.h"
      25              : #include "Utils.h"
      26              : #include "servermanagermodule.pb.h"
      27              : #include <cstring>
      28              : #include <sys/socket.h>
      29              : #include <sys/wait.h>
      30              : #include <unistd.h>
      31              : 
      32              : namespace
      33              : {
      34            1 : firebolt::rialto::common::SessionServerState convert(const rialto::SessionServerState &sessionServerState)
      35              : {
      36            1 :     switch (sessionServerState)
      37              :     {
      38            0 :     case rialto::SessionServerState::UNINITIALIZED:
      39              :     {
      40            0 :         return firebolt::rialto::common::SessionServerState::UNINITIALIZED;
      41              :     }
      42            1 :     case rialto::SessionServerState::INACTIVE:
      43              :     {
      44            1 :         return firebolt::rialto::common::SessionServerState::INACTIVE;
      45              :     }
      46            0 :     case rialto::SessionServerState::ACTIVE:
      47              :     {
      48            0 :         return firebolt::rialto::common::SessionServerState::ACTIVE;
      49              :     }
      50            0 :     case rialto::SessionServerState::NOT_RUNNING:
      51              :     {
      52            0 :         return firebolt::rialto::common::SessionServerState::NOT_RUNNING;
      53              :     }
      54            0 :     case rialto::SessionServerState::ERROR:
      55              :     {
      56            0 :         return firebolt::rialto::common::SessionServerState::ERROR;
      57              :     }
      58              :     }
      59            0 :     return firebolt::rialto::common::SessionServerState::ERROR;
      60              : }
      61            4 : rialto::SessionServerState convert(const firebolt::rialto::common::SessionServerState &state)
      62              : {
      63            4 :     switch (state)
      64              :     {
      65            0 :     case firebolt::rialto::common::SessionServerState::UNINITIALIZED:
      66              :     {
      67            0 :         return rialto::SessionServerState::UNINITIALIZED;
      68              :     }
      69            4 :     case firebolt::rialto::common::SessionServerState::INACTIVE:
      70              :     {
      71            4 :         return rialto::SessionServerState::INACTIVE;
      72              :     }
      73            0 :     case firebolt::rialto::common::SessionServerState::ACTIVE:
      74              :     {
      75            0 :         return rialto::SessionServerState::ACTIVE;
      76              :     }
      77            0 :     case firebolt::rialto::common::SessionServerState::NOT_RUNNING:
      78              :     {
      79            0 :         return rialto::SessionServerState::NOT_RUNNING;
      80              :     }
      81            0 :     case firebolt::rialto::common::SessionServerState::ERROR:
      82              :     {
      83            0 :         return rialto::SessionServerState::ERROR;
      84              :     }
      85              :     }
      86            0 :     return rialto::SessionServerState::ERROR;
      87              : }
      88            2 : rialto::LogLevels convert(const rialto::servermanager::service::LoggingLevels &levels)
      89              : {
      90            2 :     rialto::LogLevels logLevels;
      91            2 :     if (rialto::servermanager::service::LoggingLevel::UNCHANGED != levels.defaultLoggingLevel)
      92              :     {
      93            0 :         logLevels.set_defaultloglevels(rialto::servermanager::common::convert(levels.defaultLoggingLevel));
      94              :     }
      95            2 :     if (rialto::servermanager::service::LoggingLevel::UNCHANGED != levels.clientLoggingLevel)
      96              :     {
      97            0 :         logLevels.set_clientloglevels(rialto::servermanager::common::convert(levels.clientLoggingLevel));
      98              :     }
      99            2 :     if (rialto::servermanager::service::LoggingLevel::UNCHANGED != levels.sessionServerLoggingLevel)
     100              :     {
     101            0 :         logLevels.set_sessionserverloglevels(rialto::servermanager::common::convert(levels.sessionServerLoggingLevel));
     102              :     }
     103            2 :     if (rialto::servermanager::service::LoggingLevel::UNCHANGED != levels.ipcLoggingLevel)
     104              :     {
     105            0 :         logLevels.set_ipcloglevels(rialto::servermanager::common::convert(levels.ipcLoggingLevel));
     106              :     }
     107            2 :     if (rialto::servermanager::service::LoggingLevel::UNCHANGED != levels.serverManagerLoggingLevel)
     108              :     {
     109            0 :         logLevels.set_servermanagerloglevels(rialto::servermanager::common::convert(levels.serverManagerLoggingLevel));
     110              :     }
     111            2 :     if (rialto::servermanager::service::LoggingLevel::UNCHANGED != levels.commonLoggingLevel)
     112              :     {
     113            0 :         logLevels.set_commonloglevels(rialto::servermanager::common::convert(levels.commonLoggingLevel));
     114              :     }
     115            2 :     return logLevels;
     116              : }
     117            2 : rialto::LogLevels getCurrentLogLevels()
     118              : {
     119            2 :     rialto::LogLevels logLevels;
     120            2 :     logLevels.set_defaultloglevels(firebolt::rialto::logging::getLogLevels(RIALTO_COMPONENT_DEFAULT));
     121            2 :     logLevels.set_clientloglevels(firebolt::rialto::logging::getLogLevels(RIALTO_COMPONENT_CLIENT));
     122            2 :     logLevels.set_sessionserverloglevels(firebolt::rialto::logging::getLogLevels(RIALTO_COMPONENT_SERVER));
     123            2 :     logLevels.set_ipcloglevels(firebolt::rialto::logging::getLogLevels(RIALTO_COMPONENT_IPC));
     124            2 :     logLevels.set_servermanagerloglevels(firebolt::rialto::logging::getLogLevels(RIALTO_COMPONENT_SERVER_MANAGER));
     125            2 :     logLevels.set_commonloglevels(firebolt::rialto::logging::getLogLevels(RIALTO_COMPONENT_COMMON));
     126            2 :     return logLevels;
     127              : }
     128              : } // namespace
     129              : 
     130              : namespace rialto::servermanager::ipc
     131              : {
     132           15 : Client::Client(std::unique_ptr<common::ISessionServerAppManager> &sessionServerAppManager, int serverId, int socket)
     133           15 :     : m_serverId{serverId}, m_sessionServerAppManager{sessionServerAppManager}, m_socket{socket}
     134              : {
     135           15 :     RIALTO_SERVER_MANAGER_LOG_INFO("Constructing client for serverId: %d", m_serverId);
     136              : }
     137              : 
     138           15 : Client::~Client()
     139              : {
     140           15 :     RIALTO_SERVER_MANAGER_LOG_INFO("Client for serverId: %d is destructed", m_serverId);
     141           15 :     m_serviceStub.reset();
     142           15 :     m_ipcLoop.reset();
     143              : }
     144              : 
     145           15 : bool Client::connect()
     146              : {
     147           15 :     m_ipcLoop = IpcLoop::create(m_socket, *this);
     148           15 :     if (!m_ipcLoop)
     149              :     {
     150            1 :         RIALTO_SERVER_MANAGER_LOG_ERROR("Failed to connect to rialto session server @ '%d'", m_socket);
     151            1 :         return false;
     152              :     }
     153           14 :     m_serviceStub = std::make_unique<::rialto::ServerManagerModule_Stub>(m_ipcLoop->channel());
     154           28 :     m_ipcLoop->channel()->subscribe<rialto::StateChangedEvent>(
     155           14 :         std::bind(&Client::onStateChangedEvent, this, std::placeholders::_1));
     156           14 :     m_ipcLoop->channel()->subscribe<rialto::AckEvent>(std::bind(&Client::onAckEvent, this, std::placeholders::_1));
     157           14 :     return true;
     158              : }
     159              : 
     160            2 : bool Client::performSetState(const firebolt::rialto::common::SessionServerState &state)
     161              : {
     162            2 :     if (!m_ipcLoop || !m_serviceStub)
     163              :     {
     164            0 :         RIALTO_SERVER_MANAGER_LOG_ERROR("failed to set status - client is not active for serverId: %d", m_serverId);
     165            0 :         return false;
     166              :     }
     167            2 :     rialto::SetStateRequest request;
     168            2 :     rialto::SetStateResponse response;
     169            2 :     request.set_sessionserverstate(convert(state));
     170            2 :     auto ipcController = m_ipcLoop->createRpcController();
     171            2 :     auto blockingClosure = m_ipcLoop->createBlockingClosure();
     172            2 :     m_serviceStub->setState(ipcController.get(), &request, &response, blockingClosure.get());
     173              :     // wait for the call to complete
     174            2 :     blockingClosure->wait();
     175              : 
     176              :     // check the result
     177            2 :     if (ipcController->Failed())
     178              :     {
     179            1 :         RIALTO_SERVER_MANAGER_LOG_ERROR("failed to set status due to '%s'", ipcController->ErrorText().c_str());
     180            1 :         return false;
     181              :     }
     182            1 :     return true;
     183            2 : }
     184              : 
     185            2 : bool Client::performSetConfiguration(const firebolt::rialto::common::SessionServerState &initialState,
     186              :                                      const std::string &socketName, const std::string &clientDisplayName,
     187              :                                      const firebolt::rialto::common::MaxResourceCapabilitites &maxResource,
     188              :                                      const unsigned int socketPermissions, const std::string &socketOwner,
     189              :                                      const std::string &socketGroup, const std::string &appName) const
     190              : {
     191            2 :     if (!m_ipcLoop || !m_serviceStub)
     192              :     {
     193            0 :         RIALTO_SERVER_MANAGER_LOG_ERROR("failed to set configuration - client is not active for serverId: %d",
     194              :                                         m_serverId);
     195            0 :         return false;
     196              :     }
     197            2 :     rialto::SetConfigurationRequest request;
     198            2 :     rialto::SetConfigurationResponse response;
     199            2 :     request.set_sessionmanagementsocketname(socketName);
     200            2 :     request.set_clientdisplayname(clientDisplayName);
     201            2 :     request.mutable_resources()->set_maxplaybacks(maxResource.maxPlaybacks);
     202            2 :     request.mutable_resources()->set_maxwebaudioplayers(maxResource.maxWebAudioPlayers);
     203            2 :     request.set_socketpermissions(socketPermissions);
     204            2 :     request.set_socketowner(socketOwner);
     205            2 :     request.set_socketgroup(socketGroup);
     206            2 :     request.set_appname(appName);
     207            2 :     *(request.mutable_loglevels()) = getCurrentLogLevels();
     208            2 :     request.set_initialsessionserverstate(convert(initialState));
     209            2 :     auto ipcController = m_ipcLoop->createRpcController();
     210            2 :     auto blockingClosure = m_ipcLoop->createBlockingClosure();
     211            2 :     m_serviceStub->setConfiguration(ipcController.get(), &request, &response, blockingClosure.get());
     212              :     // wait for the call to complete
     213            2 :     blockingClosure->wait();
     214              : 
     215              :     // check the result
     216            2 :     if (ipcController->Failed())
     217              :     {
     218            1 :         RIALTO_SERVER_MANAGER_LOG_ERROR("failed to set configuration due to '%s'", ipcController->ErrorText().c_str());
     219            1 :         return false;
     220              :     }
     221            1 :     return true;
     222            2 : }
     223              : 
     224            2 : bool Client::performPing(int pingId) const
     225              : {
     226            2 :     if (!m_ipcLoop || !m_serviceStub)
     227              :     {
     228            0 :         RIALTO_SERVER_MANAGER_LOG_ERROR("failed to ping - client is not active for serverId: %d", m_serverId);
     229            0 :         return false;
     230              :     }
     231            2 :     rialto::PingRequest request;
     232            2 :     rialto::PingResponse response;
     233            2 :     request.set_id(pingId);
     234            2 :     auto ipcController = m_ipcLoop->createRpcController();
     235            2 :     auto blockingClosure = m_ipcLoop->createBlockingClosure();
     236            2 :     m_serviceStub->ping(ipcController.get(), &request, &response, blockingClosure.get());
     237              :     // wait for the call to complete
     238            2 :     blockingClosure->wait();
     239              : 
     240              :     // check the result
     241            2 :     if (ipcController->Failed())
     242              :     {
     243            1 :         RIALTO_SERVER_MANAGER_LOG_ERROR("failed to ping due to '%s'", ipcController->ErrorText().c_str());
     244            1 :         return false;
     245              :     }
     246            1 :     return true;
     247            2 : }
     248              : 
     249            2 : bool Client::setLogLevels(const service::LoggingLevels &logLevels) const
     250              : {
     251            2 :     if (!m_ipcLoop || !m_serviceStub)
     252              :     {
     253            0 :         RIALTO_SERVER_MANAGER_LOG_WARN("failed to change log levels - client is not active for serverId: %d", m_serverId);
     254            0 :         return false;
     255              :     }
     256            2 :     rialto::SetLogLevelsRequest request;
     257            2 :     rialto::SetLogLevelsResponse response;
     258            2 :     *(request.mutable_loglevels()) = convert(logLevels);
     259            2 :     auto ipcController = m_ipcLoop->createRpcController();
     260            2 :     auto blockingClosure = m_ipcLoop->createBlockingClosure();
     261            2 :     m_serviceStub->setLogLevels(ipcController.get(), &request, &response, blockingClosure.get());
     262              :     // wait for the call to complete
     263            2 :     blockingClosure->wait();
     264              : 
     265              :     // check the result
     266            2 :     if (ipcController->Failed())
     267              :     {
     268            1 :         RIALTO_SERVER_MANAGER_LOG_WARN("failed to change log levels due to '%s'", ipcController->ErrorText().c_str());
     269            1 :         return false;
     270              :     }
     271            1 :     return true;
     272            2 : }
     273              : 
     274            1 : void Client::onDisconnected() const
     275              : {
     276            1 :     RIALTO_SERVER_MANAGER_LOG_WARN("Connection to serverId: %d broken, server probably crashed. Starting recovery",
     277              :                                    m_serverId);
     278            1 :     m_sessionServerAppManager->restartServer(m_serverId);
     279              : }
     280              : 
     281            1 : void Client::onStateChangedEvent(const std::shared_ptr<rialto::StateChangedEvent> &event) const
     282              : {
     283            1 :     RIALTO_SERVER_MANAGER_LOG_DEBUG("StateChangedEvent received for serverId: %d", m_serverId);
     284            1 :     if (!m_sessionServerAppManager || !event)
     285              :     {
     286            0 :         RIALTO_SERVER_MANAGER_LOG_WARN("Problem during StateChangedEvent processing");
     287            0 :         return;
     288              :     }
     289            1 :     m_sessionServerAppManager->onSessionServerStateChanged(m_serverId, convert(event->sessionserverstate()));
     290              : }
     291              : 
     292            1 : void Client::onAckEvent(const std::shared_ptr<rialto::AckEvent> &event) const
     293              : {
     294            1 :     RIALTO_SERVER_MANAGER_LOG_DEBUG("AckEvent received for serverId: %d", m_serverId);
     295            1 :     if (!m_sessionServerAppManager || !event)
     296              :     {
     297            0 :         RIALTO_SERVER_MANAGER_LOG_WARN("Problem during AckEvent processing");
     298            0 :         return;
     299              :     }
     300            1 :     m_sessionServerAppManager->onAck(m_serverId, event->id(), event->success());
     301              : }
     302              : } // namespace rialto::servermanager::ipc
        

Generated by: LCOV version 2.0-1