LCOV - code coverage report
Current view: top level - media/server/ipc/source - SessionManagementServer.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.9 % 99 92
Test Date: 2025-02-18 13:13:53 Functions: 100.0 % 12 12

            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 "SessionManagementServer.h"
      21              : #include "IControlModuleService.h"
      22              : #include "IMediaKeysCapabilitiesModuleService.h"
      23              : #include "IMediaKeysModuleService.h"
      24              : #include "IMediaPipelineModuleService.h"
      25              : #include "IWebAudioPlayerModuleService.h"
      26              : #include "RialtoServerLogging.h"
      27              : #include <IIpcServerFactory.h>
      28              : #include <grp.h>
      29              : #include <pwd.h>
      30              : #include <sys/stat.h>
      31              : #include <sys/types.h>
      32              : #include <unistd.h>
      33              : 
      34              : namespace
      35              : {
      36              : constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner
      37              : constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group
      38              : } // namespace
      39              : namespace firebolt::rialto::server::ipc
      40              : {
      41           10 : SessionManagementServer::SessionManagementServer(
      42              :     std::weak_ptr<firebolt::rialto::wrappers::ILinuxWrapper> linuxWrapper,
      43              :     const std::shared_ptr<firebolt::rialto::ipc::IServerFactory> &ipcFactory,
      44              :     const std::shared_ptr<IMediaPipelineModuleServiceFactory> &mediaPipelineModuleFactory,
      45              :     const std::shared_ptr<IMediaPipelineCapabilitiesModuleServiceFactory> &mediaPipelineCapabilitiesModuleFactory,
      46              :     const std::shared_ptr<IMediaKeysModuleServiceFactory> &mediaKeysModuleFactory,
      47              :     const std::shared_ptr<IMediaKeysCapabilitiesModuleServiceFactory> &mediaKeysCapabilitiesModuleFactory,
      48              :     const std::shared_ptr<IWebAudioPlayerModuleServiceFactory> &webAudioPlayerModuleFactory,
      49              :     const std::shared_ptr<IControlModuleServiceFactory> &controlModuleFactory, service::IPlaybackService &playbackService,
      50           10 :     service::ICdmService &cdmService, service::IControlService &controlService)
      51           20 :     : m_isRunning{false}, m_mediaPipelineModule{mediaPipelineModuleFactory->create(
      52           10 :                               playbackService.getMediaPipelineService())},
      53           10 :       m_mediaPipelineCapabilitiesModule{
      54           10 :           mediaPipelineCapabilitiesModuleFactory->create(playbackService.getMediaPipelineService())},
      55           10 :       m_mediaKeysModule{mediaKeysModuleFactory->create(cdmService)},
      56           10 :       m_mediaKeysCapabilitiesModule{mediaKeysCapabilitiesModuleFactory->create(cdmService)},
      57           10 :       m_webAudioPlayerModule{webAudioPlayerModuleFactory->create(playbackService.getWebAudioPlayerService())},
      58           20 :       m_controlModule{controlModuleFactory->create(playbackService, controlService)}, m_linuxWrapper{linuxWrapper.lock()}
      59              : {
      60           10 :     m_ipcServer = ipcFactory->create();
      61              : }
      62              : 
      63           20 : SessionManagementServer::~SessionManagementServer()
      64              : {
      65           10 :     stop();
      66           10 :     if (m_ipcServerThread.joinable())
      67              :     {
      68            1 :         m_ipcServerThread.join();
      69              :     }
      70           20 : }
      71              : 
      72           16 : size_t SessionManagementServer::getBufferSizeForPasswordStructureCalls() const
      73              : {
      74              :     // Can return -1 on error
      75           16 :     return sysconf(_SC_GETPW_R_SIZE_MAX);
      76              : }
      77              : 
      78            8 : uid_t SessionManagementServer::getSocketOwnerId(const std::string &kSocketOwner) const
      79              : {
      80            8 :     uid_t ownerId = kNoOwnerChange;
      81            8 :     const size_t kBufferSize = getBufferSizeForPasswordStructureCalls();
      82            8 :     if (!kSocketOwner.empty() && kBufferSize > 0)
      83              :     {
      84            4 :         errno = 0;
      85            4 :         passwd passwordStruct{};
      86            4 :         passwd *passwordResult = nullptr;
      87            4 :         char buffer[kBufferSize];
      88              :         int result =
      89            4 :             m_linuxWrapper->getpwnam_r(kSocketOwner.c_str(), &passwordStruct, buffer, kBufferSize, &passwordResult);
      90            4 :         if (result == 0 && passwordResult)
      91              :         {
      92            2 :             ownerId = passwordResult->pw_uid;
      93              :         }
      94              :         else
      95              :         {
      96            2 :             RIALTO_SERVER_LOG_SYS_WARN(errno, "Failed to determine ownerId for '%s'", kSocketOwner.c_str());
      97              :         }
      98            4 :     }
      99            8 :     return ownerId;
     100              : }
     101              : 
     102            8 : gid_t SessionManagementServer::getSocketGroupId(const std::string &kSocketGroup) const
     103              : {
     104            8 :     gid_t groupId = kNoGroupChange;
     105            8 :     const size_t kBufferSize = getBufferSizeForPasswordStructureCalls();
     106            8 :     if (!kSocketGroup.empty() && kBufferSize > 0)
     107              :     {
     108            4 :         errno = 0;
     109            4 :         group groupStruct{};
     110            4 :         group *groupResult = nullptr;
     111            4 :         char buffer[kBufferSize];
     112            4 :         int result = m_linuxWrapper->getgrnam_r(kSocketGroup.c_str(), &groupStruct, buffer, kBufferSize, &groupResult);
     113            4 :         if (result == 0 && groupResult)
     114              :         {
     115            2 :             groupId = groupResult->gr_gid;
     116              :         }
     117              :         else
     118              :         {
     119            2 :             RIALTO_SERVER_LOG_SYS_WARN(errno, "Failed to determine groupId for '%s'", kSocketGroup.c_str());
     120              :         }
     121            4 :     }
     122            8 :     return groupId;
     123              : }
     124              : 
     125            9 : bool SessionManagementServer::initialize(const std::string &socketName, unsigned int socketPermissions,
     126              :                                          const std::string &socketOwner, const std::string &socketGroup)
     127              : {
     128            9 :     RIALTO_SERVER_LOG_INFO("Initializing Session Management Server. Socket name: '%s'", socketName.c_str());
     129            9 :     if (!m_ipcServer)
     130              :     {
     131            0 :         RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - Ipc server instance is NULL");
     132            0 :         return false;
     133              :     }
     134              : 
     135              :     // add a socket for clients and associate with a streamer object
     136           27 :     if (!m_ipcServer->addSocket(socketName,
     137           18 :                                 std::bind(&SessionManagementServer::onClientConnected, this, std::placeholders::_1),
     138           18 :                                 std::bind(&SessionManagementServer::onClientDisconnected, this, std::placeholders::_1)))
     139              :     {
     140            1 :         RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - can't add socket '%s' to the ipc "
     141              :                                 "server",
     142              :                                 socketName.c_str());
     143            1 :         return false;
     144              :     }
     145              : 
     146            8 :     errno = 0;
     147            8 :     if (m_linuxWrapper->chmod(socketName.c_str(), socketPermissions) != 0)
     148              :     {
     149            0 :         RIALTO_SERVER_LOG_SYS_WARN(errno, "Failed to change the permissions on the IPC socket");
     150              :     }
     151              : 
     152            8 :     uid_t ownerId = getSocketOwnerId(socketOwner);
     153            8 :     gid_t groupId = getSocketGroupId(socketGroup);
     154              : 
     155            8 :     if (ownerId != kNoOwnerChange || groupId != kNoGroupChange)
     156              :     {
     157            3 :         errno = 0;
     158            3 :         if (m_linuxWrapper->chown(socketName.c_str(), ownerId, groupId) != 0)
     159              :         {
     160            0 :             RIALTO_SERVER_LOG_SYS_WARN(errno, "Failed to change the owner/group for the IPC socket");
     161              :         }
     162              :     }
     163              : 
     164            8 :     return true;
     165              : }
     166              : 
     167            1 : void SessionManagementServer::start()
     168              : {
     169            1 :     if (m_isRunning.load())
     170              :     {
     171            0 :         RIALTO_SERVER_LOG_DEBUG("Server is already in running state");
     172            0 :         return;
     173              :     }
     174            1 :     RIALTO_SERVER_LOG_DEBUG("Starting Session Management Server event loop");
     175            1 :     m_isRunning.store(true);
     176            2 :     m_ipcServerThread = std::thread(
     177            2 :         [this]()
     178              :         {
     179            1 :             constexpr int kPollInterval{100};
     180            1 :             while (m_ipcServer->process() && m_isRunning.load())
     181              :             {
     182            0 :                 m_ipcServer->wait(kPollInterval);
     183              :             }
     184            1 :             RIALTO_SERVER_LOG_MIL("Session Management Server event loop finished.");
     185            1 :         });
     186              : }
     187              : 
     188           10 : void SessionManagementServer::stop()
     189              : {
     190           10 :     m_isRunning.store(false);
     191              : }
     192              : 
     193            1 : void SessionManagementServer::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels,
     194              :                                            RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels)
     195              : {
     196            1 :     m_setLogLevelsService.setLogLevels(defaultLogLevels, clientLogLevels, ipcLogLevels, commonLogLevels);
     197              : }
     198              : 
     199            2 : void SessionManagementServer::onClientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client)
     200              : {
     201            2 :     m_controlModule->clientConnected(client);
     202            2 :     m_mediaPipelineModule->clientConnected(client);
     203            2 :     m_mediaPipelineCapabilitiesModule->clientConnected(client);
     204            2 :     m_mediaKeysModule->clientConnected(client);
     205            2 :     m_mediaKeysCapabilitiesModule->clientConnected(client);
     206            2 :     m_webAudioPlayerModule->clientConnected(client);
     207            2 :     m_setLogLevelsService.clientConnected(client);
     208              : }
     209              : 
     210            1 : void SessionManagementServer::onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client)
     211              : {
     212            1 :     m_setLogLevelsService.clientDisconnected(client);
     213            1 :     m_mediaKeysCapabilitiesModule->clientDisconnected(client);
     214            1 :     m_mediaKeysModule->clientDisconnected(client);
     215            1 :     m_mediaPipelineCapabilitiesModule->clientDisconnected(client);
     216            1 :     m_mediaPipelineModule->clientDisconnected(client);
     217            1 :     m_webAudioPlayerModule->clientDisconnected(client);
     218            1 :     m_controlModule->clientDisconnected(client);
     219              : }
     220              : } // namespace firebolt::rialto::server::ipc
        

Generated by: LCOV version 2.0-1