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 : bool isLDL, 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 20 : request.set_is_ldl(isLDL);
366 :
367 40 : firebolt::rialto::CreateKeySessionResponse response;
368 : // Default error status to FAIL
369 20 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
370 :
371 40 : auto ipcController = m_ipc.createRpcController();
372 20 : auto blockingClosure = m_ipc.createBlockingClosure();
373 20 : m_mediaKeysStub->createKeySession(ipcController.get(), &request, &response, blockingClosure.get());
374 :
375 : // wait for the call to complete
376 20 : blockingClosure->wait();
377 :
378 : MediaKeyErrorStatus status =
379 40 : getMediaKeyErrorStatusFromResponse("createKeySession", ipcController, response.error_status());
380 20 : if (MediaKeyErrorStatus::OK == status)
381 : {
382 18 : keySessionId = response.key_session_id();
383 18 : m_mediaKeysIpcClient = client;
384 : }
385 :
386 20 : return status;
387 : }
388 :
389 5 : MediaKeyErrorStatus MediaKeysIpc::generateRequest(int32_t keySessionId, InitDataType initDataType,
390 : const std::vector<uint8_t> &initData)
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 8 : firebolt::rialto::GenerateRequestRequest request;
419 4 : request.set_media_keys_handle(m_mediaKeysHandle);
420 4 : request.set_key_session_id(keySessionId);
421 4 : request.set_init_data_type(protoInitDataType);
422 :
423 16 : for (auto it = initData.begin(); it != initData.end(); it++)
424 : {
425 12 : request.add_init_data(*it);
426 : }
427 :
428 8 : firebolt::rialto::GenerateRequestResponse response;
429 : // Default error status to FAIL
430 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
431 :
432 8 : auto ipcController = m_ipc.createRpcController();
433 4 : auto blockingClosure = m_ipc.createBlockingClosure();
434 4 : m_mediaKeysStub->generateRequest(ipcController.get(), &request, &response, blockingClosure.get());
435 :
436 : // wait for the call to complete
437 4 : blockingClosure->wait();
438 :
439 12 : return getMediaKeyErrorStatusFromResponse("generateRequest", ipcController, response.error_status());
440 : }
441 :
442 5 : MediaKeyErrorStatus MediaKeysIpc::loadSession(int32_t keySessionId)
443 : {
444 5 : if (!reattachChannelIfRequired())
445 : {
446 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
447 1 : return MediaKeyErrorStatus::FAIL;
448 : }
449 :
450 4 : firebolt::rialto::LoadSessionRequest request;
451 4 : request.set_media_keys_handle(m_mediaKeysHandle);
452 4 : request.set_key_session_id(keySessionId);
453 :
454 4 : firebolt::rialto::LoadSessionResponse response;
455 : // Default error status to FAIL
456 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
457 :
458 4 : auto ipcController = m_ipc.createRpcController();
459 4 : auto blockingClosure = m_ipc.createBlockingClosure();
460 4 : m_mediaKeysStub->loadSession(ipcController.get(), &request, &response, blockingClosure.get());
461 :
462 : // wait for the call to complete
463 4 : blockingClosure->wait();
464 :
465 8 : return getMediaKeyErrorStatusFromResponse("loadSession", ipcController, response.error_status());
466 4 : }
467 :
468 5 : MediaKeyErrorStatus MediaKeysIpc::updateSession(int32_t keySessionId, const std::vector<uint8_t> &responseData)
469 : {
470 5 : if (!reattachChannelIfRequired())
471 : {
472 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
473 1 : return MediaKeyErrorStatus::FAIL;
474 : }
475 :
476 4 : firebolt::rialto::UpdateSessionRequest request;
477 4 : request.set_media_keys_handle(m_mediaKeysHandle);
478 4 : request.set_key_session_id(keySessionId);
479 :
480 16 : for (auto it = responseData.begin(); it != responseData.end(); it++)
481 : {
482 12 : request.add_response_data(*it);
483 : }
484 :
485 4 : firebolt::rialto::UpdateSessionResponse response;
486 : // Default error status to FAIL
487 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
488 :
489 4 : auto ipcController = m_ipc.createRpcController();
490 4 : auto blockingClosure = m_ipc.createBlockingClosure();
491 4 : m_mediaKeysStub->updateSession(ipcController.get(), &request, &response, blockingClosure.get());
492 :
493 : // wait for the call to complete
494 4 : blockingClosure->wait();
495 :
496 8 : return getMediaKeyErrorStatusFromResponse("updateSession", ipcController, response.error_status());
497 4 : }
498 :
499 5 : MediaKeyErrorStatus MediaKeysIpc::setDrmHeader(int32_t keySessionId, const std::vector<uint8_t> &requestData)
500 : {
501 5 : if (!reattachChannelIfRequired())
502 : {
503 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
504 1 : return MediaKeyErrorStatus::FAIL;
505 : }
506 :
507 4 : firebolt::rialto::SetDrmHeaderRequest request;
508 4 : request.set_media_keys_handle(m_mediaKeysHandle);
509 4 : request.set_key_session_id(keySessionId);
510 16 : for (const auto &requestDataItem : requestData)
511 : {
512 12 : request.add_request_data(requestDataItem);
513 : }
514 :
515 4 : firebolt::rialto::SetDrmHeaderResponse response;
516 : // Default error status to FAIL
517 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
518 :
519 4 : auto ipcController = m_ipc.createRpcController();
520 4 : auto blockingClosure = m_ipc.createBlockingClosure();
521 4 : m_mediaKeysStub->setDrmHeader(ipcController.get(), &request, &response, blockingClosure.get());
522 :
523 : // wait for the call to complete
524 4 : blockingClosure->wait();
525 :
526 8 : return getMediaKeyErrorStatusFromResponse("setDrmHeader", ipcController, response.error_status());
527 4 : }
528 :
529 5 : MediaKeyErrorStatus MediaKeysIpc::closeKeySession(int32_t keySessionId)
530 : {
531 5 : if (!reattachChannelIfRequired())
532 : {
533 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
534 1 : return MediaKeyErrorStatus::FAIL;
535 : }
536 :
537 : // Reset client
538 4 : m_mediaKeysIpcClient.reset();
539 :
540 4 : firebolt::rialto::CloseKeySessionRequest request;
541 4 : request.set_media_keys_handle(m_mediaKeysHandle);
542 4 : request.set_key_session_id(keySessionId);
543 :
544 4 : firebolt::rialto::CloseKeySessionResponse response;
545 : // Default error status to FAIL
546 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
547 :
548 4 : auto ipcController = m_ipc.createRpcController();
549 4 : auto blockingClosure = m_ipc.createBlockingClosure();
550 4 : m_mediaKeysStub->closeKeySession(ipcController.get(), &request, &response, blockingClosure.get());
551 :
552 : // wait for the call to complete
553 4 : blockingClosure->wait();
554 :
555 8 : return getMediaKeyErrorStatusFromResponse("closeKeySession", ipcController, response.error_status());
556 4 : }
557 :
558 5 : MediaKeyErrorStatus MediaKeysIpc::removeKeySession(int32_t keySessionId)
559 : {
560 5 : if (!reattachChannelIfRequired())
561 : {
562 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
563 1 : return MediaKeyErrorStatus::FAIL;
564 : }
565 :
566 4 : firebolt::rialto::RemoveKeySessionRequest request;
567 4 : request.set_media_keys_handle(m_mediaKeysHandle);
568 4 : request.set_key_session_id(keySessionId);
569 :
570 4 : firebolt::rialto::RemoveKeySessionResponse response;
571 : // Default error status to FAIL
572 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
573 :
574 4 : auto ipcController = m_ipc.createRpcController();
575 4 : auto blockingClosure = m_ipc.createBlockingClosure();
576 4 : m_mediaKeysStub->removeKeySession(ipcController.get(), &request, &response, blockingClosure.get());
577 :
578 : // wait for the call to complete
579 4 : blockingClosure->wait();
580 :
581 8 : return getMediaKeyErrorStatusFromResponse("removeKeySession", ipcController, response.error_status());
582 4 : }
583 :
584 5 : MediaKeyErrorStatus MediaKeysIpc::deleteDrmStore()
585 : {
586 5 : if (!reattachChannelIfRequired())
587 : {
588 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
589 1 : return MediaKeyErrorStatus::FAIL;
590 : }
591 :
592 4 : firebolt::rialto::DeleteDrmStoreRequest request;
593 4 : request.set_media_keys_handle(m_mediaKeysHandle);
594 :
595 4 : firebolt::rialto::DeleteDrmStoreResponse response;
596 : // Default error status to FAIL
597 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
598 :
599 4 : auto ipcController = m_ipc.createRpcController();
600 4 : auto blockingClosure = m_ipc.createBlockingClosure();
601 4 : m_mediaKeysStub->deleteDrmStore(ipcController.get(), &request, &response, blockingClosure.get());
602 :
603 : // wait for the call to complete
604 4 : blockingClosure->wait();
605 :
606 8 : return getMediaKeyErrorStatusFromResponse("deleteDrmStore", ipcController, response.error_status());
607 4 : }
608 :
609 5 : MediaKeyErrorStatus MediaKeysIpc::deleteKeyStore()
610 : {
611 5 : if (!reattachChannelIfRequired())
612 : {
613 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
614 1 : return MediaKeyErrorStatus::FAIL;
615 : }
616 :
617 4 : firebolt::rialto::DeleteKeyStoreRequest request;
618 4 : request.set_media_keys_handle(m_mediaKeysHandle);
619 :
620 4 : firebolt::rialto::DeleteKeyStoreResponse response;
621 : // Default error status to FAIL
622 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
623 :
624 4 : auto ipcController = m_ipc.createRpcController();
625 4 : auto blockingClosure = m_ipc.createBlockingClosure();
626 4 : m_mediaKeysStub->deleteKeyStore(ipcController.get(), &request, &response, blockingClosure.get());
627 :
628 : // wait for the call to complete
629 4 : blockingClosure->wait();
630 :
631 8 : return getMediaKeyErrorStatusFromResponse("deleteKeyStore", ipcController, response.error_status());
632 4 : }
633 :
634 5 : MediaKeyErrorStatus MediaKeysIpc::getDrmStoreHash(std::vector<unsigned char> &drmStoreHash)
635 : {
636 5 : if (!reattachChannelIfRequired())
637 : {
638 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
639 1 : return MediaKeyErrorStatus::FAIL;
640 : }
641 :
642 4 : firebolt::rialto::GetDrmStoreHashRequest request;
643 4 : request.set_media_keys_handle(m_mediaKeysHandle);
644 :
645 4 : firebolt::rialto::GetDrmStoreHashResponse response;
646 : // Default error status to FAIL
647 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
648 :
649 4 : auto ipcController = m_ipc.createRpcController();
650 4 : auto blockingClosure = m_ipc.createBlockingClosure();
651 4 : m_mediaKeysStub->getDrmStoreHash(ipcController.get(), &request, &response, blockingClosure.get());
652 :
653 : // wait for the call to complete
654 4 : blockingClosure->wait();
655 :
656 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
657 : {
658 4 : drmStoreHash = std::vector<unsigned char>(response.drm_store_hash().begin(), response.drm_store_hash().end());
659 : }
660 :
661 8 : return getMediaKeyErrorStatusFromResponse("getDrmStoreHash", ipcController, response.error_status());
662 4 : }
663 :
664 5 : MediaKeyErrorStatus MediaKeysIpc::getKeyStoreHash(std::vector<unsigned char> &keyStoreHash)
665 : {
666 5 : if (!reattachChannelIfRequired())
667 : {
668 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
669 1 : return MediaKeyErrorStatus::FAIL;
670 : }
671 :
672 4 : firebolt::rialto::GetKeyStoreHashRequest request;
673 4 : request.set_media_keys_handle(m_mediaKeysHandle);
674 :
675 4 : firebolt::rialto::GetKeyStoreHashResponse response;
676 : // Default error status to FAIL
677 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
678 :
679 4 : auto ipcController = m_ipc.createRpcController();
680 4 : auto blockingClosure = m_ipc.createBlockingClosure();
681 4 : m_mediaKeysStub->getKeyStoreHash(ipcController.get(), &request, &response, blockingClosure.get());
682 :
683 : // wait for the call to complete
684 4 : blockingClosure->wait();
685 :
686 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
687 : {
688 4 : keyStoreHash = std::vector<unsigned char>(response.key_store_hash().begin(), response.key_store_hash().end());
689 : }
690 :
691 8 : return getMediaKeyErrorStatusFromResponse("getKeyStoreHash", ipcController, response.error_status());
692 4 : }
693 :
694 5 : MediaKeyErrorStatus MediaKeysIpc::getLdlSessionsLimit(uint32_t &ldlLimit)
695 : {
696 5 : if (!reattachChannelIfRequired())
697 : {
698 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
699 1 : return MediaKeyErrorStatus::FAIL;
700 : }
701 :
702 4 : firebolt::rialto::GetLdlSessionsLimitRequest request;
703 4 : request.set_media_keys_handle(m_mediaKeysHandle);
704 :
705 4 : firebolt::rialto::GetLdlSessionsLimitResponse response;
706 : // Default error status to FAIL
707 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
708 :
709 4 : auto ipcController = m_ipc.createRpcController();
710 4 : auto blockingClosure = m_ipc.createBlockingClosure();
711 4 : m_mediaKeysStub->getLdlSessionsLimit(ipcController.get(), &request, &response, blockingClosure.get());
712 :
713 : // wait for the call to complete
714 4 : blockingClosure->wait();
715 :
716 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
717 : {
718 2 : ldlLimit = response.ldl_limit();
719 : }
720 :
721 8 : return getMediaKeyErrorStatusFromResponse("getLdlSessionsLimit", ipcController, response.error_status());
722 4 : }
723 :
724 5 : MediaKeyErrorStatus MediaKeysIpc::getLastDrmError(int32_t keySessionId, uint32_t &errorCode)
725 : {
726 5 : if (!reattachChannelIfRequired())
727 : {
728 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
729 1 : return MediaKeyErrorStatus::FAIL;
730 : }
731 :
732 4 : firebolt::rialto::GetLastDrmErrorRequest request;
733 4 : request.set_media_keys_handle(m_mediaKeysHandle);
734 4 : request.set_key_session_id(keySessionId);
735 :
736 4 : firebolt::rialto::GetLastDrmErrorResponse response;
737 : // Default error status to FAIL
738 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
739 :
740 4 : auto ipcController = m_ipc.createRpcController();
741 4 : auto blockingClosure = m_ipc.createBlockingClosure();
742 4 : m_mediaKeysStub->getLastDrmError(ipcController.get(), &request, &response, blockingClosure.get());
743 :
744 : // wait for the call to complete
745 4 : blockingClosure->wait();
746 :
747 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
748 : {
749 2 : errorCode = response.error_code();
750 : }
751 :
752 8 : return getMediaKeyErrorStatusFromResponse("getLastDrmError", ipcController, response.error_status());
753 4 : }
754 :
755 5 : MediaKeyErrorStatus MediaKeysIpc::getDrmTime(uint64_t &drmTime)
756 : {
757 5 : if (!reattachChannelIfRequired())
758 : {
759 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
760 1 : return MediaKeyErrorStatus::FAIL;
761 : }
762 :
763 4 : firebolt::rialto::GetDrmTimeRequest request;
764 4 : request.set_media_keys_handle(m_mediaKeysHandle);
765 :
766 4 : firebolt::rialto::GetDrmTimeResponse response;
767 : // Default error status to FAIL
768 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
769 :
770 4 : auto ipcController = m_ipc.createRpcController();
771 4 : auto blockingClosure = m_ipc.createBlockingClosure();
772 4 : m_mediaKeysStub->getDrmTime(ipcController.get(), &request, &response, blockingClosure.get());
773 :
774 : // wait for the call to complete
775 4 : blockingClosure->wait();
776 :
777 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
778 : {
779 2 : drmTime = response.drm_time();
780 : }
781 :
782 8 : return getMediaKeyErrorStatusFromResponse("getDrmTime", ipcController, response.error_status());
783 4 : }
784 :
785 5 : MediaKeyErrorStatus MediaKeysIpc::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId)
786 : {
787 5 : if (!reattachChannelIfRequired())
788 : {
789 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
790 1 : return MediaKeyErrorStatus::FAIL;
791 : }
792 :
793 4 : firebolt::rialto::GetCdmKeySessionIdRequest request;
794 4 : request.set_media_keys_handle(m_mediaKeysHandle);
795 4 : request.set_key_session_id(keySessionId);
796 :
797 4 : firebolt::rialto::GetCdmKeySessionIdResponse response;
798 : // Default error status to FAIL
799 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
800 :
801 4 : auto ipcController = m_ipc.createRpcController();
802 4 : auto blockingClosure = m_ipc.createBlockingClosure();
803 4 : m_mediaKeysStub->getCdmKeySessionId(ipcController.get(), &request, &response, blockingClosure.get());
804 :
805 : // wait for the call to complete
806 4 : blockingClosure->wait();
807 :
808 4 : cdmKeySessionId = response.cdm_key_session_id();
809 :
810 8 : return getMediaKeyErrorStatusFromResponse("getCdmKeySessionId", ipcController, response.error_status());
811 4 : }
812 :
813 5 : MediaKeyErrorStatus MediaKeysIpc::releaseKeySession(int32_t keySessionId)
814 : {
815 5 : if (!reattachChannelIfRequired())
816 : {
817 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
818 1 : return MediaKeyErrorStatus::FAIL;
819 : }
820 :
821 : // Reset client
822 4 : m_mediaKeysIpcClient.reset();
823 :
824 4 : firebolt::rialto::ReleaseKeySessionRequest request;
825 4 : request.set_media_keys_handle(m_mediaKeysHandle);
826 4 : request.set_key_session_id(keySessionId);
827 :
828 4 : firebolt::rialto::ReleaseKeySessionResponse response;
829 : // Default error status to FAIL
830 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
831 :
832 4 : auto ipcController = m_ipc.createRpcController();
833 4 : auto blockingClosure = m_ipc.createBlockingClosure();
834 4 : m_mediaKeysStub->releaseKeySession(ipcController.get(), &request, &response, blockingClosure.get());
835 :
836 : // wait for the call to complete
837 4 : blockingClosure->wait();
838 :
839 8 : return getMediaKeyErrorStatusFromResponse("releaseKeySession", ipcController, response.error_status());
840 4 : }
841 :
842 3 : void MediaKeysIpc::onLicenseRequest(const std::shared_ptr<firebolt::rialto::LicenseRequestEvent> &event)
843 : {
844 3 : std::shared_ptr<IMediaKeysClient> mediaKeysIpcClient = m_mediaKeysIpcClient.lock();
845 :
846 : /* Ignore event if not for this session or no client */
847 3 : if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient))
848 : {
849 1 : std::vector<unsigned char> messageVector = std::vector<unsigned char>{event->license_request_message().begin(),
850 2 : event->license_request_message().end()};
851 1 : mediaKeysIpcClient->onLicenseRequest(event->key_session_id(), messageVector, event->url());
852 : }
853 3 : }
854 :
855 6 : void MediaKeysIpc::onLicenseRenewal(const std::shared_ptr<firebolt::rialto::LicenseRenewalEvent> &event)
856 : {
857 6 : std::shared_ptr<IMediaKeysClient> mediaKeysIpcClient = m_mediaKeysIpcClient.lock();
858 :
859 : /* Ignore event if not for this session or no client */
860 6 : if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient))
861 : {
862 2 : std::vector<unsigned char> messageVector = std::vector<unsigned char>{event->license_renewal_message().begin(),
863 4 : event->license_renewal_message().end()};
864 2 : mediaKeysIpcClient->onLicenseRenewal(event->key_session_id(), messageVector);
865 : }
866 6 : }
867 :
868 3 : void MediaKeysIpc::onKeyStatusesChanged(const std::shared_ptr<firebolt::rialto::KeyStatusesChangedEvent> &event)
869 : {
870 3 : std::shared_ptr<IMediaKeysClient> mediaKeysIpcClient = m_mediaKeysIpcClient.lock();
871 :
872 : /* Ignore event if not for this session or no client */
873 3 : if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient))
874 : {
875 1 : KeyStatusVector keyStatuses;
876 4 : for (auto it = event->key_statuses().begin(); it != event->key_statuses().end(); it++)
877 : {
878 6 : std::vector<unsigned char> keyVector = std::vector<unsigned char>{it->key_id().begin(), it->key_id().end()};
879 3 : KeyStatus keyStatus = convertKeyStatus(it->key_status());
880 3 : keyStatuses.push_back(std::make_pair(keyVector, keyStatus));
881 : }
882 1 : mediaKeysIpcClient->onKeyStatusesChanged(event->key_session_id(), keyStatuses);
883 : }
884 3 : }
885 :
886 : MediaKeyErrorStatus
887 84 : MediaKeysIpc::getMediaKeyErrorStatusFromResponse(const std::string methodName,
888 : const std::shared_ptr<google::protobuf::RpcController> &controller,
889 : ProtoMediaKeyErrorStatus status)
890 : {
891 84 : if (controller->Failed())
892 : {
893 17 : RIALTO_CLIENT_LOG_ERROR("%s failed due to '%s'", methodName.c_str(), controller->ErrorText().c_str());
894 17 : return MediaKeyErrorStatus::FAIL;
895 : }
896 67 : MediaKeyErrorStatus returnStatus = convertMediaKeyErrorStatus(status);
897 67 : if (MediaKeyErrorStatus::OK != returnStatus)
898 : {
899 17 : RIALTO_CLIENT_LOG_ERROR("%s failed due to MediaKeyErrorStatus '%s'", methodName.c_str(), toString(returnStatus));
900 17 : return returnStatus;
901 : }
902 :
903 50 : return returnStatus;
904 : }
905 :
906 5 : MediaKeyErrorStatus MediaKeysIpc::getMetricSystemData(std::vector<uint8_t> &buffer)
907 : {
908 5 : if (!reattachChannelIfRequired())
909 : {
910 1 : RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
911 1 : return MediaKeyErrorStatus::FAIL;
912 : }
913 :
914 4 : firebolt::rialto::GetMetricSystemDataRequest request;
915 4 : request.set_media_keys_handle(m_mediaKeysHandle);
916 :
917 4 : firebolt::rialto::GetMetricSystemDataResponse response;
918 : // Default error status to FAIL
919 4 : response.set_error_status(ProtoMediaKeyErrorStatus::FAIL);
920 :
921 4 : auto ipcController = m_ipc.createRpcController();
922 4 : auto blockingClosure = m_ipc.createBlockingClosure();
923 4 : m_mediaKeysStub->getMetricSystemData(ipcController.get(), &request, &response, blockingClosure.get());
924 :
925 : // wait for the call to complete
926 4 : blockingClosure->wait();
927 :
928 4 : if (ProtoMediaKeyErrorStatus::OK == response.error_status())
929 : {
930 4 : buffer = std::vector<uint8_t>(response.buffer().begin(), response.buffer().end());
931 : }
932 :
933 8 : return getMediaKeyErrorStatusFromResponse("getMetricSystemData", ipcController, response.error_status());
934 4 : }
935 :
936 : }; // namespace firebolt::rialto::client
|