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