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 "ControlModuleService.h"
21 : #include "ControlClientServerInternal.h"
22 : #include "IPlaybackService.h"
23 : #include "RialtoServerLogging.h"
24 : #include "SchemaVersion.h"
25 : #include <IIpcController.h>
26 : #include <algorithm>
27 : #include <cstdint>
28 :
29 : namespace
30 : {
31 3 : int generateControlId()
32 : {
33 : static int id{0};
34 3 : return id++;
35 : }
36 : } // namespace
37 :
38 : namespace firebolt::rialto::server::ipc
39 : {
40 1 : std::shared_ptr<IControlModuleServiceFactory> IControlModuleServiceFactory::createFactory()
41 : {
42 1 : std::shared_ptr<IControlModuleServiceFactory> factory;
43 :
44 : try
45 : {
46 1 : factory = std::make_shared<ControlModuleServiceFactory>();
47 : }
48 0 : catch (const std::exception &e)
49 : {
50 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the rialto control module service factory, reason: %s", e.what());
51 : }
52 :
53 1 : return factory;
54 : }
55 :
56 1 : std::shared_ptr<IControlModuleService> ControlModuleServiceFactory::create(service::IPlaybackService &playbackService,
57 : service::IControlService &controlService) const
58 : {
59 1 : std::shared_ptr<IControlModuleService> controlModule;
60 :
61 : try
62 : {
63 1 : controlModule = std::make_shared<ControlModuleService>(playbackService, controlService);
64 : }
65 0 : catch (const std::exception &e)
66 : {
67 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the rialto control module service, reason: %s", e.what());
68 : }
69 :
70 1 : return controlModule;
71 : }
72 :
73 13 : ControlModuleService::ControlModuleService(service::IPlaybackService &playbackService,
74 13 : service::IControlService &controlService)
75 13 : : m_playbackService{playbackService}, m_controlService{controlService}
76 : {
77 : }
78 :
79 13 : ControlModuleService::~ControlModuleService()
80 : {
81 18 : for (const auto &controlIds : m_controlIds)
82 : {
83 7 : for (int id : controlIds.second)
84 : {
85 2 : m_controlService.removeControl(id);
86 : }
87 : }
88 13 : }
89 :
90 7 : void ControlModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient)
91 : {
92 7 : RIALTO_SERVER_LOG_INFO("Client Connected!");
93 7 : m_controlIds.emplace(ipcClient, std::set<int>());
94 7 : ipcClient->exportService(shared_from_this());
95 : }
96 :
97 2 : void ControlModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient)
98 : {
99 2 : RIALTO_SERVER_LOG_INFO("Client disconnected!");
100 2 : auto controlIdsIter = m_controlIds.find(ipcClient);
101 2 : if (m_controlIds.end() != controlIdsIter)
102 : {
103 3 : for (int id : controlIdsIter->second)
104 : {
105 1 : m_controlService.removeControl(id);
106 : }
107 2 : m_controlIds.erase(controlIdsIter);
108 : }
109 : }
110 :
111 2 : void ControlModuleService::getSharedMemory(::google::protobuf::RpcController *controller,
112 : const ::firebolt::rialto::GetSharedMemoryRequest *request,
113 : ::firebolt::rialto::GetSharedMemoryResponse *response,
114 : ::google::protobuf::Closure *done)
115 : {
116 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
117 :
118 : int32_t fd;
119 : uint32_t size;
120 2 : if (!m_playbackService.getSharedMemory(fd, size))
121 : {
122 1 : RIALTO_SERVER_LOG_ERROR("getSharedMemory failed");
123 1 : controller->SetFailed("Operation failed");
124 1 : done->Run();
125 1 : return;
126 : }
127 1 : response->set_fd(fd);
128 1 : response->set_size(size);
129 1 : done->Run();
130 : }
131 :
132 5 : void ControlModuleService::registerClient(::google::protobuf::RpcController *controller,
133 : const ::firebolt::rialto::RegisterClientRequest *request,
134 : ::firebolt::rialto::RegisterClientResponse *response,
135 : ::google::protobuf::Closure *done)
136 : {
137 5 : RIALTO_SERVER_LOG_DEBUG("entry:");
138 5 : auto ipcController = dynamic_cast<firebolt::rialto::ipc::IController *>(controller);
139 5 : if (!ipcController)
140 : {
141 1 : RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object");
142 1 : controller->SetFailed("ipc library provided incompatible controller object");
143 1 : done->Run();
144 2 : return;
145 : }
146 4 : const auto kCurrentSchemaVersion{common::getCurrentSchemaVersion()};
147 4 : if (request->has_client_schema_version())
148 : {
149 2 : const firebolt::rialto::common::SchemaVersion kClientSchemaVersion{request->client_schema_version().major(),
150 4 : request->client_schema_version().minor(),
151 2 : request->client_schema_version().patch()};
152 2 : RIALTO_SERVER_LOG_DEBUG("Server schema version: %s, client schema version: %s",
153 : kCurrentSchemaVersion.str().c_str(), kClientSchemaVersion.str().c_str());
154 2 : if (!kCurrentSchemaVersion.isCompatible(kClientSchemaVersion))
155 : {
156 1 : RIALTO_SERVER_LOG_ERROR("Server and client schema versions not compatible");
157 1 : controller->SetFailed("Server and client schema versions not compatible");
158 1 : done->Run();
159 1 : return;
160 : }
161 : }
162 : else
163 : {
164 2 : RIALTO_SERVER_LOG_WARN("Client schema version not present in RegisterClientRequest message");
165 : }
166 3 : const int kControlId{generateControlId()};
167 3 : auto ipcClient = ipcController->getClient();
168 3 : auto controlClient{std::make_shared<ControlClientServerInternal>(kControlId, ipcClient)};
169 3 : m_controlService.addControl(kControlId, controlClient);
170 3 : m_controlIds[ipcClient].insert(kControlId);
171 3 : response->set_control_handle(kControlId);
172 3 : response->mutable_server_schema_version()->set_major(kCurrentSchemaVersion.major());
173 3 : response->mutable_server_schema_version()->set_minor(kCurrentSchemaVersion.minor());
174 3 : response->mutable_server_schema_version()->set_patch(kCurrentSchemaVersion.patch());
175 3 : done->Run();
176 : }
177 :
178 2 : void ControlModuleService::ack(::google::protobuf::RpcController *controller,
179 : const ::firebolt::rialto::AckRequest *request, ::firebolt::rialto::AckResponse *response,
180 : ::google::protobuf::Closure *done)
181 : {
182 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
183 2 : if (!m_controlService.ack(request->control_handle(), request->id()))
184 : {
185 1 : RIALTO_SERVER_LOG_ERROR("ack failed");
186 1 : controller->SetFailed("Operation failed");
187 1 : done->Run();
188 1 : return;
189 : }
190 1 : done->Run();
191 : }
192 : } // namespace firebolt::rialto::server::ipc
|