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