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 "MediaKeysIpc.h"
21 : #include "RialtoClientLogging.h"
22 :
23 : namespace
24 : {
25 : firebolt::rialto::MediaKeyErrorStatus
26 67 : convertMediaKeyErrorStatus(const firebolt::rialto::ProtoMediaKeyErrorStatus &errorStatus)
27 : {
28 67 : switch (errorStatus)
29 : {
30 50 : case firebolt::rialto::ProtoMediaKeyErrorStatus::OK:
31 : {
32 50 : return firebolt::rialto::MediaKeyErrorStatus::OK;
33 : }
34 17 : case firebolt::rialto::ProtoMediaKeyErrorStatus::BAD_SESSION_ID:
35 : {
36 17 : return firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID;
37 : }
38 0 : case firebolt::rialto::ProtoMediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED:
39 : {
40 0 : return firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED;
41 : }
42 0 : case firebolt::rialto::ProtoMediaKeyErrorStatus::BUFFER_TOO_SMALL:
43 : {
44 0 : return firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL;
45 : }
46 0 : case firebolt::rialto::ProtoMediaKeyErrorStatus::NOT_SUPPORTED:
47 : {
48 0 : return firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED;
49 : }
50 0 : case firebolt::rialto::ProtoMediaKeyErrorStatus::INVALID_STATE:
51 : {
52 0 : return firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE;
53 : }
54 0 : case firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL:
55 : {
56 0 : return firebolt::rialto::MediaKeyErrorStatus::FAIL;
57 : }
58 : }
59 0 : return firebolt::rialto::MediaKeyErrorStatus::FAIL;
60 : }
61 :
62 3 : firebolt::rialto::KeyStatus convertKeyStatus(const firebolt::rialto::KeyStatusesChangedEvent_KeyStatus &protoKeyStatus)
63 : {
64 3 : switch (protoKeyStatus)
65 : {
66 1 : case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_USABLE:
67 : {
68 1 : return firebolt::rialto::KeyStatus::USABLE;
69 : }
70 1 : case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_EXPIRED:
71 : {
72 1 : return firebolt::rialto::KeyStatus::EXPIRED;
73 : }
74 1 : case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_OUTPUT_RESTRICTED:
75 : {
76 1 : return firebolt::rialto::KeyStatus::OUTPUT_RESTRICTED;
77 : }
78 0 : case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_PENDING:
79 : {
80 0 : return firebolt::rialto::KeyStatus::PENDING;
81 : }
82 0 : case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_INTERNAL_ERROR:
83 : {
84 0 : return firebolt::rialto::KeyStatus::INTERNAL_ERROR;
85 : }
86 0 : case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_RELEASED:
87 : {
88 0 : return firebolt::rialto::KeyStatus::RELEASED;
89 : }
90 : }
91 0 : return firebolt::rialto::KeyStatus::INTERNAL_ERROR;
92 : }
93 :
94 17 : const char *toString(const firebolt::rialto::MediaKeyErrorStatus &errorStatus)
95 : {
96 17 : switch (errorStatus)
97 : {
98 0 : case firebolt::rialto::MediaKeyErrorStatus::OK:
99 : {
100 0 : return "OK";
101 : }
102 17 : case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID:
103 : {
104 17 : return "BAD_SESSION_ID";
105 : }
106 0 : case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED:
107 : {
108 0 : return "INTERFACE_NOT_IMPLEMENTED";
109 : }
110 0 : case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL:
111 : {
112 0 : return "BUFFER_TOO_SMALL";
113 : }
114 0 : case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED:
115 : {
116 0 : return "NOT_SUPPORTED";
117 : }
118 0 : case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE:
119 : {
120 0 : return "INVALID_STATE";
121 : }
122 0 : case firebolt::rialto::MediaKeyErrorStatus::FAIL:
123 : {
124 0 : return "FAIL";
125 : }
126 : }
127 0 : return "UNKNOWN";
128 : }
129 : } // namespace
130 :
131 : namespace firebolt::rialto::client
132 : {
133 0 : std::shared_ptr<IMediaKeysIpcFactory> IMediaKeysIpcFactory::createFactory()
134 : {
135 0 : std::shared_ptr<IMediaKeysIpcFactory> factory;
136 :
137 : try
138 : {
139 0 : factory = std::make_shared<MediaKeysIpcFactory>();
140 : }
141 0 : catch (const std::exception &e)
142 : {
143 0 : RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys ipc factory, reason: %s", e.what());
144 : }
145 :
146 0 : return factory;
147 : }
148 :
149 0 : std::unique_ptr<IMediaKeys> MediaKeysIpcFactory::createMediaKeysIpc(const std::string &keySystem) const
150 : {
151 0 : std::unique_ptr<IMediaKeys> mediaKeysIpc;
152 : try
153 : {
154 : mediaKeysIpc =
155 0 : std::make_unique<client::MediaKeysIpc>(keySystem, IIpcClientAccessor::instance().getIpcClient(),
156 0 : firebolt::rialto::common::IEventThreadFactory::createFactory());
157 : }
158 0 : catch (const std::exception &e)
159 : {
160 0 : RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys ipc, reason: %s", e.what());
161 : }
162 :
163 0 : return mediaKeysIpc;
164 : }
165 :
166 106 : MediaKeysIpc::MediaKeysIpc(const std::string &keySystem, IIpcClient &ipcClient,
167 106 : const std::shared_ptr<common::IEventThreadFactory> &eventThreadFactory)
168 318 : : IpcModule(ipcClient), m_eventThread(eventThreadFactory->createEventThread("rialto-media-keys-events"))
169 : {
170 106 : RIALTO_CLIENT_LOG_DEBUG("entry:");
171 :
172 106 : if (!attachChannel())
173 : {
174 3 : throw std::runtime_error("Failed attach to the ipc channel");
175 : }
176 :
177 103 : if (!createMediaKeys(keySystem))
178 : {
179 1 : detachChannel();
180 1 : throw std::runtime_error("Could not create the media keys instance");
181 : }
182 122 : }
183 :
184 204 : MediaKeysIpc::~MediaKeysIpc()
185 : {
186 102 : RIALTO_CLIENT_LOG_DEBUG("entry:");
187 :
188 102 : destroyMediaKeys();
189 :
190 102 : detachChannel();
191 :
192 102 : m_eventThread.reset();
193 204 : }
194 :
195 140 : bool MediaKeysIpc::createRpcStubs(const std::shared_ptr<ipc::IChannel> &ipcChannel)
196 : {
197 140 : m_mediaKeysStub = std::make_unique<::firebolt::rialto::MediaKeysModule_Stub>(ipcChannel.get());
198 140 : if (!m_mediaKeysStub)
199 : {
200 0 : return false;
201 : }
202 140 : return true;
203 : }
204 :
205 140 : bool MediaKeysIpc::subscribeToEvents(const std::shared_ptr<ipc::IChannel> &ipcChannel)
206 : {
207 140 : if (!ipcChannel)
208 : {
209 0 : return false;
210 : }
211 :
212 280 : int eventTag = ipcChannel->subscribe<firebolt::rialto::LicenseRequestEvent>(
213 140 : [this](const std::shared_ptr<firebolt::rialto::LicenseRequestEvent> &event)
214 143 : { m_eventThread->add(&MediaKeysIpc::onLicenseRequest, this, event); });
215 140 : if (eventTag < 0)
216 0 : return false;
217 140 : m_eventTags.push_back(eventTag);
218 :
219 280 : eventTag = ipcChannel->subscribe<firebolt::rialto::LicenseRenewalEvent>(
220 140 : [this](const std::shared_ptr<firebolt::rialto::LicenseRenewalEvent> &event)
221 6 : { m_eventThread->add(&MediaKeysIpc::onLicenseRenewal, this, event); });
222 140 : if (eventTag < 0)
223 1 : return false;
224 139 : m_eventTags.push_back(eventTag);
225 :
226 278 : eventTag = ipcChannel->subscribe<firebolt::rialto::KeyStatusesChangedEvent>(
227 139 : [this](const std::shared_ptr<firebolt::rialto::KeyStatusesChangedEvent> &event)
228 3 : { m_eventThread->add(&MediaKeysIpc::onKeyStatusesChanged, this, event); });
229 139 : if (eventTag < 0)
230 0 : return false;
231 139 : m_eventTags.push_back(eventTag);
232 :
233 139 : return true;
234 : }
235 :
236 103 : bool MediaKeysIpc::createMediaKeys(const std::string &keySystem)
237 : {
238 103 : if (!reattachChannelIfRequired())
239 : {
240 0 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
241 0 : return false;
242 : }
243 :
244 103 : firebolt::rialto::CreateMediaKeysRequest request;
245 :
246 : request.set_key_system(keySystem);
247 :
248 103 : firebolt::rialto::CreateMediaKeysResponse response;
249 103 : auto ipcController = m_ipc.createRpcController();
250 103 : auto blockingClosure = m_ipc.createBlockingClosure();
251 103 : m_mediaKeysStub->createMediaKeys(ipcController.get(), &request, &response, blockingClosure.get());
252 :
253 : // wait for the call to complete
254 103 : blockingClosure->wait();
255 :
256 : // check the result
257 103 : if (ipcController->Failed())
258 : {
259 1 : RIALTO_CLIENT_LOG_ERROR("failed to create media keys due to '%s'", ipcController->ErrorText().c_str());
260 1 : return false;
261 : }
262 :
263 102 : m_mediaKeysHandle = response.media_keys_handle();
264 :
265 102 : return true;
266 103 : }
267 :
268 102 : void MediaKeysIpc::destroyMediaKeys()
269 : {
270 102 : if (!reattachChannelIfRequired())
271 : {
272 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
273 1 : return;
274 : }
275 :
276 101 : firebolt::rialto::DestroyMediaKeysRequest request;
277 101 : request.set_media_keys_handle(m_mediaKeysHandle);
278 :
279 101 : firebolt::rialto::DestroyMediaKeysResponse response;
280 101 : auto ipcController = m_ipc.createRpcController();
281 101 : auto blockingClosure = m_ipc.createBlockingClosure();
282 101 : m_mediaKeysStub->destroyMediaKeys(ipcController.get(), &request, &response, blockingClosure.get());
283 :
284 : // wait for the call to complete
285 101 : blockingClosure->wait();
286 :
287 : // check the result
288 101 : if (ipcController->Failed())
289 : {
290 1 : RIALTO_CLIENT_LOG_ERROR("failed to destroy media keys due to '%s'", ipcController->ErrorText().c_str());
291 : }
292 101 : }
293 :
294 0 : MediaKeyErrorStatus MediaKeysIpc::selectKeyId(int32_t keySessionId, const std::vector<uint8_t> &keyId)
295 : {
296 0 : RIALTO_CLIENT_LOG_ERROR("Not Implemented");
297 0 : return MediaKeyErrorStatus::FAIL;
298 : }
299 :
300 5 : bool MediaKeysIpc::containsKey(int32_t keySessionId, const std::vector<uint8_t> &keyId)
301 : {
302 5 : if (!reattachChannelIfRequired())
303 : {
304 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
305 1 : return false;
306 : }
307 :
308 4 : firebolt::rialto::ContainsKeyRequest request;
309 4 : request.set_media_keys_handle(m_mediaKeysHandle);
310 4 : request.set_key_session_id(keySessionId);
311 16 : for (const auto &keyIdItem : keyId)
312 : {
313 12 : request.add_key_id(keyIdItem);
314 : }
315 :
316 4 : firebolt::rialto::ContainsKeyResponse response;
317 : // Default return value to false
318 4 : response.set_contains_key(false);
319 :
320 4 : auto ipcController = m_ipc.createRpcController();
321 4 : auto blockingClosure = m_ipc.createBlockingClosure();
322 4 : m_mediaKeysStub->containsKey(ipcController.get(), &request, &response, blockingClosure.get());
323 :
324 : // wait for the call to complete
325 4 : blockingClosure->wait();
326 :
327 4 : if (ipcController->Failed())
328 : {
329 1 : RIALTO_CLIENT_LOG_ERROR("containsKey failed due to '%s'", ipcController->ErrorText().c_str());
330 1 : return false;
331 : }
332 :
333 3 : return response.contains_key();
334 4 : }
335 :
336 21 : MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr<IMediaKeysClient> client,
337 : int32_t &keySessionId)
338 : {
339 21 : if (!reattachChannelIfRequired())
340 : {
341 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
342 1 : return MediaKeyErrorStatus::FAIL;
343 : }
344 :
345 20 : CreateKeySessionRequest_KeySessionType protoSessionType = CreateKeySessionRequest_KeySessionType_UNKNOWN;
346 20 : switch (sessionType)
347 : {
348 0 : case KeySessionType::TEMPORARY:
349 0 : protoSessionType = CreateKeySessionRequest_KeySessionType_TEMPORARY;
350 0 : break;
351 20 : case KeySessionType::PERSISTENT_LICENCE:
352 20 : protoSessionType = CreateKeySessionRequest_KeySessionType_PERSISTENT_LICENCE;
353 20 : break;
354 0 : case KeySessionType::PERSISTENT_RELEASE_MESSAGE:
355 0 : protoSessionType = CreateKeySessionRequest_KeySessionType_PERSISTENT_RELEASE_MESSAGE;
356 0 : break;
357 0 : default:
358 0 : RIALTO_CLIENT_LOG_WARN("Recieved unknown key session type");
359 0 : break;
360 : }
361 :
362 40 : firebolt::rialto::CreateKeySessionRequest request;
363 20 : request.set_media_keys_handle(m_mediaKeysHandle);
364 20 : request.set_session_type(protoSessionType);
365 :
366 40 : firebolt::rialto::CreateKeySessionResponse response;
367 : // Default error status to FAIL
368 20 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
369 :
370 40 : auto ipcController = m_ipc.createRpcController();
371 20 : auto blockingClosure = m_ipc.createBlockingClosure();
372 20 : m_mediaKeysStub->createKeySession(ipcController.get(), &request, &response, blockingClosure.get());
373 :
374 : // wait for the call to complete
375 20 : blockingClosure->wait();
376 :
377 : MediaKeyErrorStatus status =
378 40 : getMediaKeyErrorStatusFromResponse("createKeySession", ipcController, response.error_status());
379 20 : if (MediaKeyErrorStatus::OK == status)
380 : {
381 18 : keySessionId = response.key_session_id();
382 18 : m_mediaKeysIpcClient = client;
383 : }
384 :
385 20 : return status;
386 : }
387 :
388 5 : MediaKeyErrorStatus MediaKeysIpc::generateRequest(int32_t keySessionId, InitDataType initDataType,
389 : const std::vector<uint8_t> &initData,
390 : const LimitedDurationLicense &ldlState)
391 : {
392 5 : if (!reattachChannelIfRequired())
393 : {
394 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
395 1 : return MediaKeyErrorStatus::FAIL;
396 : }
397 :
398 4 : GenerateRequestRequest_InitDataType protoInitDataType = GenerateRequestRequest_InitDataType_UNKNOWN;
399 4 : switch (initDataType)
400 : {
401 0 : case InitDataType::CENC:
402 0 : protoInitDataType = GenerateRequestRequest_InitDataType_CENC;
403 0 : break;
404 4 : case InitDataType::KEY_IDS:
405 4 : protoInitDataType = GenerateRequestRequest_InitDataType_KEY_IDS;
406 4 : break;
407 0 : case InitDataType::WEBM:
408 0 : protoInitDataType = GenerateRequestRequest_InitDataType_WEBM;
409 0 : break;
410 0 : case InitDataType::DRMHEADER:
411 0 : protoInitDataType = GenerateRequestRequest_InitDataType_DRMHEADER;
412 0 : break;
413 0 : default:
414 0 : RIALTO_CLIENT_LOG_WARN("Recieved unknown init data type");
415 0 : break;
416 : }
417 :
418 4 : GenerateRequestRequest_LimitedDurationLicense protoLimitedDurationLicense{
419 : GenerateRequestRequest_LimitedDurationLicense_NOT_SPECIFIED};
420 4 : switch (ldlState)
421 : {
422 4 : case LimitedDurationLicense::NOT_SPECIFIED:
423 4 : protoLimitedDurationLicense = GenerateRequestRequest_LimitedDurationLicense_NOT_SPECIFIED;
424 4 : break;
425 0 : case LimitedDurationLicense::ENABLED:
426 0 : protoLimitedDurationLicense = GenerateRequestRequest_LimitedDurationLicense_ENABLED;
427 0 : break;
428 0 : case LimitedDurationLicense::DISABLED:
429 0 : protoLimitedDurationLicense = GenerateRequestRequest_LimitedDurationLicense_DISABLED;
430 0 : break;
431 0 : default:
432 0 : RIALTO_CLIENT_LOG_WARN("Received unknown limited duration license state");
433 0 : break;
434 : }
435 :
436 8 : firebolt::rialto::GenerateRequestRequest request;
437 4 : request.set_media_keys_handle(m_mediaKeysHandle);
438 4 : request.set_key_session_id(keySessionId);
439 4 : request.set_init_data_type(protoInitDataType);
440 4 : request.set_ldl_state(protoLimitedDurationLicense);
441 :
442 16 : for (auto it = initData.begin(); it != initData.end(); it++)
443 : {
444 12 : request.add_init_data(*it);
445 : }
446 :
447 8 : firebolt::rialto::GenerateRequestResponse response;
448 : // Default error status to FAIL
449 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
450 :
451 8 : auto ipcController = m_ipc.createRpcController();
452 4 : auto blockingClosure = m_ipc.createBlockingClosure();
453 4 : m_mediaKeysStub->generateRequest(ipcController.get(), &request, &response, blockingClosure.get());
454 :
455 : // wait for the call to complete
456 4 : blockingClosure->wait();
457 :
458 12 : return getMediaKeyErrorStatusFromResponse("generateRequest", ipcController, response.error_status());
459 : }
460 :
461 5 : MediaKeyErrorStatus MediaKeysIpc::loadSession(int32_t keySessionId)
462 : {
463 5 : if (!reattachChannelIfRequired())
464 : {
465 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
466 1 : return MediaKeyErrorStatus::FAIL;
467 : }
468 :
469 4 : firebolt::rialto::LoadSessionRequest request;
470 4 : request.set_media_keys_handle(m_mediaKeysHandle);
471 4 : request.set_key_session_id(keySessionId);
472 :
473 4 : firebolt::rialto::LoadSessionResponse response;
474 : // Default error status to FAIL
475 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
476 :
477 4 : auto ipcController = m_ipc.createRpcController();
478 4 : auto blockingClosure = m_ipc.createBlockingClosure();
479 4 : m_mediaKeysStub->loadSession(ipcController.get(), &request, &response, blockingClosure.get());
480 :
481 : // wait for the call to complete
482 4 : blockingClosure->wait();
483 :
484 8 : return getMediaKeyErrorStatusFromResponse("loadSession", ipcController, response.error_status());
485 4 : }
486 :
487 5 : MediaKeyErrorStatus MediaKeysIpc::updateSession(int32_t keySessionId, const std::vector<uint8_t> &responseData)
488 : {
489 5 : if (!reattachChannelIfRequired())
490 : {
491 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
492 1 : return MediaKeyErrorStatus::FAIL;
493 : }
494 :
495 4 : firebolt::rialto::UpdateSessionRequest request;
496 4 : request.set_media_keys_handle(m_mediaKeysHandle);
497 4 : request.set_key_session_id(keySessionId);
498 :
499 16 : for (auto it = responseData.begin(); it != responseData.end(); it++)
500 : {
501 12 : request.add_response_data(*it);
502 : }
503 :
504 4 : firebolt::rialto::UpdateSessionResponse response;
505 : // Default error status to FAIL
506 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
507 :
508 4 : auto ipcController = m_ipc.createRpcController();
509 4 : auto blockingClosure = m_ipc.createBlockingClosure();
510 4 : m_mediaKeysStub->updateSession(ipcController.get(), &request, &response, blockingClosure.get());
511 :
512 : // wait for the call to complete
513 4 : blockingClosure->wait();
514 :
515 8 : return getMediaKeyErrorStatusFromResponse("updateSession", ipcController, response.error_status());
516 4 : }
517 :
518 5 : MediaKeyErrorStatus MediaKeysIpc::setDrmHeader(int32_t keySessionId, const std::vector<uint8_t> &requestData)
519 : {
520 5 : if (!reattachChannelIfRequired())
521 : {
522 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
523 1 : return MediaKeyErrorStatus::FAIL;
524 : }
525 :
526 4 : firebolt::rialto::SetDrmHeaderRequest request;
527 4 : request.set_media_keys_handle(m_mediaKeysHandle);
528 4 : request.set_key_session_id(keySessionId);
529 16 : for (const auto &requestDataItem : requestData)
530 : {
531 12 : request.add_request_data(requestDataItem);
532 : }
533 :
534 4 : firebolt::rialto::SetDrmHeaderResponse response;
535 : // Default error status to FAIL
536 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
537 :
538 4 : auto ipcController = m_ipc.createRpcController();
539 4 : auto blockingClosure = m_ipc.createBlockingClosure();
540 4 : m_mediaKeysStub->setDrmHeader(ipcController.get(), &request, &response, blockingClosure.get());
541 :
542 : // wait for the call to complete
543 4 : blockingClosure->wait();
544 :
545 8 : return getMediaKeyErrorStatusFromResponse("setDrmHeader", ipcController, response.error_status());
546 4 : }
547 :
548 5 : MediaKeyErrorStatus MediaKeysIpc::closeKeySession(int32_t keySessionId)
549 : {
550 5 : if (!reattachChannelIfRequired())
551 : {
552 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
553 1 : return MediaKeyErrorStatus::FAIL;
554 : }
555 :
556 : // Reset client
557 4 : m_mediaKeysIpcClient.reset();
558 :
559 4 : firebolt::rialto::CloseKeySessionRequest request;
560 4 : request.set_media_keys_handle(m_mediaKeysHandle);
561 4 : request.set_key_session_id(keySessionId);
562 :
563 4 : firebolt::rialto::CloseKeySessionResponse response;
564 : // Default error status to FAIL
565 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
566 :
567 4 : auto ipcController = m_ipc.createRpcController();
568 4 : auto blockingClosure = m_ipc.createBlockingClosure();
569 4 : m_mediaKeysStub->closeKeySession(ipcController.get(), &request, &response, blockingClosure.get());
570 :
571 : // wait for the call to complete
572 4 : blockingClosure->wait();
573 :
574 8 : return getMediaKeyErrorStatusFromResponse("closeKeySession", ipcController, response.error_status());
575 4 : }
576 :
577 5 : MediaKeyErrorStatus MediaKeysIpc::removeKeySession(int32_t keySessionId)
578 : {
579 5 : if (!reattachChannelIfRequired())
580 : {
581 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
582 1 : return MediaKeyErrorStatus::FAIL;
583 : }
584 :
585 4 : firebolt::rialto::RemoveKeySessionRequest request;
586 4 : request.set_media_keys_handle(m_mediaKeysHandle);
587 4 : request.set_key_session_id(keySessionId);
588 :
589 4 : firebolt::rialto::RemoveKeySessionResponse response;
590 : // Default error status to FAIL
591 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
592 :
593 4 : auto ipcController = m_ipc.createRpcController();
594 4 : auto blockingClosure = m_ipc.createBlockingClosure();
595 4 : m_mediaKeysStub->removeKeySession(ipcController.get(), &request, &response, blockingClosure.get());
596 :
597 : // wait for the call to complete
598 4 : blockingClosure->wait();
599 :
600 8 : return getMediaKeyErrorStatusFromResponse("removeKeySession", ipcController, response.error_status());
601 4 : }
602 :
603 5 : MediaKeyErrorStatus MediaKeysIpc::deleteDrmStore()
604 : {
605 5 : if (!reattachChannelIfRequired())
606 : {
607 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
608 1 : return MediaKeyErrorStatus::FAIL;
609 : }
610 :
611 4 : firebolt::rialto::DeleteDrmStoreRequest request;
612 4 : request.set_media_keys_handle(m_mediaKeysHandle);
613 :
614 4 : firebolt::rialto::DeleteDrmStoreResponse response;
615 : // Default error status to FAIL
616 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
617 :
618 4 : auto ipcController = m_ipc.createRpcController();
619 4 : auto blockingClosure = m_ipc.createBlockingClosure();
620 4 : m_mediaKeysStub->deleteDrmStore(ipcController.get(), &request, &response, blockingClosure.get());
621 :
622 : // wait for the call to complete
623 4 : blockingClosure->wait();
624 :
625 8 : return getMediaKeyErrorStatusFromResponse("deleteDrmStore", ipcController, response.error_status());
626 4 : }
627 :
628 5 : MediaKeyErrorStatus MediaKeysIpc::deleteKeyStore()
629 : {
630 5 : if (!reattachChannelIfRequired())
631 : {
632 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
633 1 : return MediaKeyErrorStatus::FAIL;
634 : }
635 :
636 4 : firebolt::rialto::DeleteKeyStoreRequest request;
637 4 : request.set_media_keys_handle(m_mediaKeysHandle);
638 :
639 4 : firebolt::rialto::DeleteKeyStoreResponse response;
640 : // Default error status to FAIL
641 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
642 :
643 4 : auto ipcController = m_ipc.createRpcController();
644 4 : auto blockingClosure = m_ipc.createBlockingClosure();
645 4 : m_mediaKeysStub->deleteKeyStore(ipcController.get(), &request, &response, blockingClosure.get());
646 :
647 : // wait for the call to complete
648 4 : blockingClosure->wait();
649 :
650 8 : return getMediaKeyErrorStatusFromResponse("deleteKeyStore", ipcController, response.error_status());
651 4 : }
652 :
653 5 : MediaKeyErrorStatus MediaKeysIpc::getDrmStoreHash(std::vector<unsigned char> &drmStoreHash)
654 : {
655 5 : if (!reattachChannelIfRequired())
656 : {
657 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
658 1 : return MediaKeyErrorStatus::FAIL;
659 : }
660 :
661 4 : firebolt::rialto::GetDrmStoreHashRequest request;
662 4 : request.set_media_keys_handle(m_mediaKeysHandle);
663 :
664 4 : firebolt::rialto::GetDrmStoreHashResponse response;
665 : // Default error status to FAIL
666 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
667 :
668 4 : auto ipcController = m_ipc.createRpcController();
669 4 : auto blockingClosure = m_ipc.createBlockingClosure();
670 4 : m_mediaKeysStub->getDrmStoreHash(ipcController.get(), &request, &response, blockingClosure.get());
671 :
672 : // wait for the call to complete
673 4 : blockingClosure->wait();
674 :
675 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
676 : {
677 4 : drmStoreHash = std::vector<unsigned char>(response.drm_store_hash().begin(), response.drm_store_hash().end());
678 : }
679 :
680 8 : return getMediaKeyErrorStatusFromResponse("getDrmStoreHash", ipcController, response.error_status());
681 4 : }
682 :
683 5 : MediaKeyErrorStatus MediaKeysIpc::getKeyStoreHash(std::vector<unsigned char> &keyStoreHash)
684 : {
685 5 : if (!reattachChannelIfRequired())
686 : {
687 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
688 1 : return MediaKeyErrorStatus::FAIL;
689 : }
690 :
691 4 : firebolt::rialto::GetKeyStoreHashRequest request;
692 4 : request.set_media_keys_handle(m_mediaKeysHandle);
693 :
694 4 : firebolt::rialto::GetKeyStoreHashResponse response;
695 : // Default error status to FAIL
696 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
697 :
698 4 : auto ipcController = m_ipc.createRpcController();
699 4 : auto blockingClosure = m_ipc.createBlockingClosure();
700 4 : m_mediaKeysStub->getKeyStoreHash(ipcController.get(), &request, &response, blockingClosure.get());
701 :
702 : // wait for the call to complete
703 4 : blockingClosure->wait();
704 :
705 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
706 : {
707 4 : keyStoreHash = std::vector<unsigned char>(response.key_store_hash().begin(), response.key_store_hash().end());
708 : }
709 :
710 8 : return getMediaKeyErrorStatusFromResponse("getKeyStoreHash", ipcController, response.error_status());
711 4 : }
712 :
713 5 : MediaKeyErrorStatus MediaKeysIpc::getLdlSessionsLimit(uint32_t &ldlLimit)
714 : {
715 5 : if (!reattachChannelIfRequired())
716 : {
717 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
718 1 : return MediaKeyErrorStatus::FAIL;
719 : }
720 :
721 4 : firebolt::rialto::GetLdlSessionsLimitRequest request;
722 4 : request.set_media_keys_handle(m_mediaKeysHandle);
723 :
724 4 : firebolt::rialto::GetLdlSessionsLimitResponse response;
725 : // Default error status to FAIL
726 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
727 :
728 4 : auto ipcController = m_ipc.createRpcController();
729 4 : auto blockingClosure = m_ipc.createBlockingClosure();
730 4 : m_mediaKeysStub->getLdlSessionsLimit(ipcController.get(), &request, &response, blockingClosure.get());
731 :
732 : // wait for the call to complete
733 4 : blockingClosure->wait();
734 :
735 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
736 : {
737 2 : ldlLimit = response.ldl_limit();
738 : }
739 :
740 8 : return getMediaKeyErrorStatusFromResponse("getLdlSessionsLimit", ipcController, response.error_status());
741 4 : }
742 :
743 5 : MediaKeyErrorStatus MediaKeysIpc::getLastDrmError(int32_t keySessionId, uint32_t &errorCode)
744 : {
745 5 : if (!reattachChannelIfRequired())
746 : {
747 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
748 1 : return MediaKeyErrorStatus::FAIL;
749 : }
750 :
751 4 : firebolt::rialto::GetLastDrmErrorRequest request;
752 4 : request.set_media_keys_handle(m_mediaKeysHandle);
753 4 : request.set_key_session_id(keySessionId);
754 :
755 4 : firebolt::rialto::GetLastDrmErrorResponse response;
756 : // Default error status to FAIL
757 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
758 :
759 4 : auto ipcController = m_ipc.createRpcController();
760 4 : auto blockingClosure = m_ipc.createBlockingClosure();
761 4 : m_mediaKeysStub->getLastDrmError(ipcController.get(), &request, &response, blockingClosure.get());
762 :
763 : // wait for the call to complete
764 4 : blockingClosure->wait();
765 :
766 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
767 : {
768 2 : errorCode = response.error_code();
769 : }
770 :
771 8 : return getMediaKeyErrorStatusFromResponse("getLastDrmError", ipcController, response.error_status());
772 4 : }
773 :
774 5 : MediaKeyErrorStatus MediaKeysIpc::getDrmTime(uint64_t &drmTime)
775 : {
776 5 : if (!reattachChannelIfRequired())
777 : {
778 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
779 1 : return MediaKeyErrorStatus::FAIL;
780 : }
781 :
782 4 : firebolt::rialto::GetDrmTimeRequest request;
783 4 : request.set_media_keys_handle(m_mediaKeysHandle);
784 :
785 4 : firebolt::rialto::GetDrmTimeResponse response;
786 : // Default error status to FAIL
787 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
788 :
789 4 : auto ipcController = m_ipc.createRpcController();
790 4 : auto blockingClosure = m_ipc.createBlockingClosure();
791 4 : m_mediaKeysStub->getDrmTime(ipcController.get(), &request, &response, blockingClosure.get());
792 :
793 : // wait for the call to complete
794 4 : blockingClosure->wait();
795 :
796 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
797 : {
798 2 : drmTime = response.drm_time();
799 : }
800 :
801 8 : return getMediaKeyErrorStatusFromResponse("getDrmTime", ipcController, response.error_status());
802 4 : }
803 :
804 5 : MediaKeyErrorStatus MediaKeysIpc::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId)
805 : {
806 5 : if (!reattachChannelIfRequired())
807 : {
808 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
809 1 : return MediaKeyErrorStatus::FAIL;
810 : }
811 :
812 4 : firebolt::rialto::GetCdmKeySessionIdRequest request;
813 4 : request.set_media_keys_handle(m_mediaKeysHandle);
814 4 : request.set_key_session_id(keySessionId);
815 :
816 4 : firebolt::rialto::GetCdmKeySessionIdResponse response;
817 : // Default error status to FAIL
818 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
819 :
820 4 : auto ipcController = m_ipc.createRpcController();
821 4 : auto blockingClosure = m_ipc.createBlockingClosure();
822 4 : m_mediaKeysStub->getCdmKeySessionId(ipcController.get(), &request, &response, blockingClosure.get());
823 :
824 : // wait for the call to complete
825 4 : blockingClosure->wait();
826 :
827 4 : cdmKeySessionId = response.cdm_key_session_id();
828 :
829 8 : return getMediaKeyErrorStatusFromResponse("getCdmKeySessionId", ipcController, response.error_status());
830 4 : }
831 :
832 5 : MediaKeyErrorStatus MediaKeysIpc::releaseKeySession(int32_t keySessionId)
833 : {
834 5 : if (!reattachChannelIfRequired())
835 : {
836 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
837 1 : return MediaKeyErrorStatus::FAIL;
838 : }
839 :
840 : // Reset client
841 4 : m_mediaKeysIpcClient.reset();
842 :
843 4 : firebolt::rialto::ReleaseKeySessionRequest request;
844 4 : request.set_media_keys_handle(m_mediaKeysHandle);
845 4 : request.set_key_session_id(keySessionId);
846 :
847 4 : firebolt::rialto::ReleaseKeySessionResponse response;
848 : // Default error status to FAIL
849 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
850 :
851 4 : auto ipcController = m_ipc.createRpcController();
852 4 : auto blockingClosure = m_ipc.createBlockingClosure();
853 4 : m_mediaKeysStub->releaseKeySession(ipcController.get(), &request, &response, blockingClosure.get());
854 :
855 : // wait for the call to complete
856 4 : blockingClosure->wait();
857 :
858 8 : return getMediaKeyErrorStatusFromResponse("releaseKeySession", ipcController, response.error_status());
859 4 : }
860 :
861 3 : void MediaKeysIpc::onLicenseRequest(const std::shared_ptr<firebolt::rialto::LicenseRequestEvent> &event)
862 : {
863 3 : std::shared_ptr<IMediaKeysClient> mediaKeysIpcClient = m_mediaKeysIpcClient.lock();
864 :
865 : /* Ignore event if not for this session or no client */
866 3 : if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient))
867 : {
868 1 : std::vector<unsigned char> messageVector = std::vector<unsigned char>{event->license_request_message().begin(),
869 2 : event->license_request_message().end()};
870 1 : mediaKeysIpcClient->onLicenseRequest(event->key_session_id(), messageVector, event->url());
871 : }
872 3 : }
873 :
874 6 : void MediaKeysIpc::onLicenseRenewal(const std::shared_ptr<firebolt::rialto::LicenseRenewalEvent> &event)
875 : {
876 6 : std::shared_ptr<IMediaKeysClient> mediaKeysIpcClient = m_mediaKeysIpcClient.lock();
877 :
878 : /* Ignore event if not for this session or no client */
879 6 : if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient))
880 : {
881 2 : std::vector<unsigned char> messageVector = std::vector<unsigned char>{event->license_renewal_message().begin(),
882 4 : event->license_renewal_message().end()};
883 2 : mediaKeysIpcClient->onLicenseRenewal(event->key_session_id(), messageVector);
884 : }
885 6 : }
886 :
887 3 : void MediaKeysIpc::onKeyStatusesChanged(const std::shared_ptr<firebolt::rialto::KeyStatusesChangedEvent> &event)
888 : {
889 3 : std::shared_ptr<IMediaKeysClient> mediaKeysIpcClient = m_mediaKeysIpcClient.lock();
890 :
891 : /* Ignore event if not for this session or no client */
892 3 : if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient))
893 : {
894 1 : KeyStatusVector keyStatuses;
895 4 : for (auto it = event->key_statuses().begin(); it != event->key_statuses().end(); it++)
896 : {
897 6 : std::vector<unsigned char> keyVector = std::vector<unsigned char>{it->key_id().begin(), it->key_id().end()};
898 3 : KeyStatus keyStatus = convertKeyStatus(it->key_status());
899 3 : keyStatuses.push_back(std::make_pair(keyVector, keyStatus));
900 : }
901 1 : mediaKeysIpcClient->onKeyStatusesChanged(event->key_session_id(), keyStatuses);
902 : }
903 3 : }
904 :
905 : MediaKeyErrorStatus
906 84 : MediaKeysIpc::getMediaKeyErrorStatusFromResponse(const std::string methodName,
907 : const std::shared_ptr<google::protobuf::RpcController> &controller,
908 : ProtoMediaKeyErrorStatus status)
909 : {
910 84 : if (controller->Failed())
911 : {
912 17 : RIALTO_CLIENT_LOG_ERROR("%s failed due to '%s'", methodName.c_str(), controller->ErrorText().c_str());
913 17 : return MediaKeyErrorStatus::FAIL;
914 : }
915 67 : MediaKeyErrorStatus returnStatus = convertMediaKeyErrorStatus(status);
916 67 : if (MediaKeyErrorStatus::OK != returnStatus)
917 : {
918 17 : RIALTO_CLIENT_LOG_ERROR("%s failed due to MediaKeyErrorStatus '%s'", methodName.c_str(), toString(returnStatus));
919 17 : return returnStatus;
920 : }
921 :
922 50 : return returnStatus;
923 : }
924 :
925 5 : MediaKeyErrorStatus MediaKeysIpc::getMetricSystemData(std::vector<uint8_t> &buffer)
926 : {
927 5 : if (!reattachChannelIfRequired())
928 : {
929 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
930 1 : return MediaKeyErrorStatus::FAIL;
931 : }
932 :
933 4 : firebolt::rialto::GetMetricSystemDataRequest request;
934 4 : request.set_media_keys_handle(m_mediaKeysHandle);
935 :
936 4 : firebolt::rialto::GetMetricSystemDataResponse response;
937 : // Default error status to FAIL
938 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
939 :
940 4 : auto ipcController = m_ipc.createRpcController();
941 4 : auto blockingClosure = m_ipc.createBlockingClosure();
942 4 : m_mediaKeysStub->getMetricSystemData(ipcController.get(), &request, &response, blockingClosure.get());
943 :
944 : // wait for the call to complete
945 4 : blockingClosure->wait();
946 :
947 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
948 : {
949 4 : buffer = std::vector<uint8_t>(response.buffer().begin(), response.buffer().end());
950 : }
951 :
952 8 : return getMediaKeyErrorStatusFromResponse("getMetricSystemData", ipcController, response.error_status());
953 4 : }
954 :
955 : }; // namespace firebolt::rialto::client
|