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