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 <stdexcept>
21 :
22 : #include "MediaKeysServerInternal.h"
23 : #include "RialtoServerLogging.h"
24 :
25 : namespace firebolt::rialto
26 : {
27 1 : const char *mediaKeyErrorStatusToString(const MediaKeyErrorStatus &status)
28 : {
29 1 : switch (status)
30 : {
31 0 : case firebolt::rialto::MediaKeyErrorStatus::OK:
32 0 : return "OK";
33 0 : case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID:
34 0 : return "BAD_SESSION_ID";
35 1 : case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED:
36 1 : return "INTERFACE_NOT_IMPLEMENTED";
37 0 : case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL:
38 0 : return "BUFFER_TOO_SMALL";
39 0 : case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED:
40 0 : return "NOT_SUPPORTED";
41 0 : default:
42 0 : return "FAIL";
43 : }
44 : }
45 :
46 1 : std::shared_ptr<IMediaKeysFactory> IMediaKeysFactory::createFactory()
47 : {
48 1 : return server::IMediaKeysServerInternalFactory::createFactory();
49 : }
50 : } // namespace firebolt::rialto
51 :
52 : namespace firebolt::rialto::server
53 : {
54 68 : int32_t generateSessionId()
55 : {
56 : static int32_t keySessionId{0};
57 68 : return keySessionId++;
58 : }
59 :
60 2 : std::shared_ptr<IMediaKeysServerInternalFactory> IMediaKeysServerInternalFactory::createFactory()
61 : {
62 2 : std::shared_ptr<IMediaKeysServerInternalFactory> factory;
63 :
64 : try
65 : {
66 2 : factory = std::make_shared<MediaKeysServerInternalFactory>();
67 : }
68 0 : catch (const std::exception &e)
69 : {
70 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the media keys factory, reason: %s", e.what());
71 : }
72 :
73 2 : return factory;
74 : }
75 :
76 1 : std::unique_ptr<IMediaKeys> MediaKeysServerInternalFactory::createMediaKeys(const std::string &keySystem) const
77 : {
78 1 : RIALTO_SERVER_LOG_ERROR("This function can't be used by rialto server. Please use createMediaKeysServerInternal");
79 1 : return nullptr;
80 : }
81 :
82 : std::unique_ptr<IMediaKeysServerInternal>
83 1 : MediaKeysServerInternalFactory::createMediaKeysServerInternal(const std::string &keySystem) const
84 : {
85 1 : std::unique_ptr<IMediaKeysServerInternal> mediaKeys;
86 : try
87 : {
88 2 : mediaKeys = std::make_unique<server::MediaKeysServerInternal>(keySystem,
89 3 : server::IMainThreadFactory::createFactory(),
90 3 : wrappers::IOcdmSystemFactory::createFactory(),
91 3 : server::IMediaKeySessionFactory::createFactory());
92 : }
93 1 : catch (const std::exception &e)
94 : {
95 1 : RIALTO_SERVER_LOG_ERROR("Failed to create the media keys, reason: %s", e.what());
96 : }
97 :
98 1 : return mediaKeys;
99 : }
100 : }; // namespace firebolt::rialto::server
101 :
102 : namespace firebolt::rialto::server
103 : {
104 73 : MediaKeysServerInternal::MediaKeysServerInternal(
105 : const std::string &keySystem, const std::shared_ptr<IMainThreadFactory> &mainThreadFactory,
106 : std::shared_ptr<firebolt::rialto::wrappers::IOcdmSystemFactory> ocdmSystemFactory,
107 73 : std::shared_ptr<IMediaKeySessionFactory> mediaKeySessionFactory)
108 73 : : m_mediaKeySessionFactory(mediaKeySessionFactory), m_keySystem(keySystem)
109 : {
110 73 : RIALTO_SERVER_LOG_DEBUG("entry:");
111 :
112 73 : m_mainThread = mainThreadFactory->getMainThread();
113 73 : if (!m_mainThread)
114 : {
115 1 : throw std::runtime_error("Failed to get the main thread");
116 : }
117 72 : m_mainThreadClientId = m_mainThread->registerClient();
118 :
119 72 : if (!ocdmSystemFactory)
120 : {
121 1 : throw std::runtime_error("No ocdmSystemFactory");
122 : }
123 :
124 71 : bool result = false;
125 71 : auto task = [&]()
126 : {
127 71 : m_ocdmSystem = ocdmSystemFactory->createOcdmSystem(keySystem);
128 71 : if (!m_ocdmSystem)
129 : {
130 1 : RIALTO_SERVER_LOG_ERROR("Ocdm system could not be created");
131 : }
132 : else
133 : {
134 70 : result = true;
135 : }
136 71 : };
137 :
138 71 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
139 71 : if (!result)
140 : {
141 1 : throw std::runtime_error("MediaKeys construction failed");
142 : }
143 88 : }
144 :
145 210 : MediaKeysServerInternal::~MediaKeysServerInternal()
146 : {
147 70 : RIALTO_SERVER_LOG_DEBUG("entry:");
148 :
149 70 : auto task = [&]()
150 : {
151 70 : m_ocdmSystem.reset();
152 :
153 70 : m_mainThread->unregisterClient(m_mainThreadClientId);
154 140 : };
155 :
156 70 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
157 140 : }
158 :
159 3 : MediaKeyErrorStatus MediaKeysServerInternal::selectKeyId(int32_t keySessionId, const std::vector<uint8_t> &keyId)
160 : {
161 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
162 :
163 : MediaKeyErrorStatus status;
164 3 : auto task = [&]() { status = selectKeyIdInternal(keySessionId, keyId); };
165 :
166 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
167 3 : return status;
168 : }
169 :
170 3 : MediaKeyErrorStatus MediaKeysServerInternal::selectKeyIdInternal(int32_t keySessionId, const std::vector<uint8_t> &keyId)
171 : {
172 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
173 3 : if (sessionIter == m_mediaKeySessions.end())
174 : {
175 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
176 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
177 : }
178 :
179 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->selectKeyId(keyId);
180 2 : if (MediaKeyErrorStatus::OK != status)
181 : {
182 1 : RIALTO_SERVER_LOG_ERROR("Failed to select key id");
183 1 : return status;
184 : }
185 :
186 1 : return status;
187 : }
188 :
189 3 : bool MediaKeysServerInternal::containsKey(int32_t keySessionId, const std::vector<uint8_t> &keyId)
190 : {
191 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
192 :
193 3 : bool result{false};
194 3 : auto task = [&]() { result = containsKeyInternal(keySessionId, keyId); };
195 :
196 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
197 3 : return result;
198 : }
199 :
200 3 : bool MediaKeysServerInternal::containsKeyInternal(int32_t keySessionId, const std::vector<uint8_t> &keyId)
201 : {
202 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
203 3 : if (sessionIter == m_mediaKeySessions.end())
204 : {
205 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
206 1 : return false;
207 : }
208 :
209 2 : return sessionIter->second.mediaKeySession->containsKey(keyId);
210 : }
211 :
212 68 : MediaKeyErrorStatus MediaKeysServerInternal::createKeySession(KeySessionType sessionType,
213 : std::weak_ptr<IMediaKeysClient> client, bool isLDL,
214 : int32_t &keySessionId)
215 : {
216 68 : RIALTO_SERVER_LOG_DEBUG("entry:");
217 :
218 : MediaKeyErrorStatus status;
219 68 : auto task = [&]() { status = createKeySessionInternal(sessionType, client, isLDL, keySessionId); };
220 :
221 68 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
222 68 : return status;
223 : }
224 :
225 68 : MediaKeyErrorStatus MediaKeysServerInternal::createKeySessionInternal(KeySessionType sessionType,
226 : std::weak_ptr<IMediaKeysClient> client,
227 : bool isLDL, int32_t &keySessionId)
228 : {
229 68 : int32_t keySessionIdTemp = generateSessionId();
230 : std::unique_ptr<IMediaKeySession> mediaKeySession =
231 136 : m_mediaKeySessionFactory->createMediaKeySession(m_keySystem, keySessionIdTemp, *m_ocdmSystem, sessionType,
232 136 : client, isLDL);
233 68 : if (!mediaKeySession)
234 : {
235 1 : RIALTO_SERVER_LOG_ERROR("Failed to create a new media key session");
236 1 : return MediaKeyErrorStatus::FAIL;
237 : }
238 67 : keySessionId = keySessionIdTemp;
239 67 : m_mediaKeySessions.emplace(std::make_pair(keySessionId, MediaKeySessionUsage{std::move(mediaKeySession)}));
240 :
241 67 : return MediaKeyErrorStatus::OK;
242 68 : }
243 :
244 3 : MediaKeyErrorStatus MediaKeysServerInternal::generateRequest(int32_t keySessionId, InitDataType initDataType,
245 : const std::vector<uint8_t> &initData)
246 : {
247 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
248 :
249 : MediaKeyErrorStatus status;
250 3 : auto task = [&]() { status = generateRequestInternal(keySessionId, initDataType, initData); };
251 :
252 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
253 3 : return status;
254 : }
255 :
256 3 : MediaKeyErrorStatus MediaKeysServerInternal::generateRequestInternal(int32_t keySessionId, InitDataType initDataType,
257 : const std::vector<uint8_t> &initData)
258 : {
259 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
260 3 : if (sessionIter == m_mediaKeySessions.end())
261 : {
262 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
263 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
264 : }
265 :
266 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->generateRequest(initDataType, initData);
267 2 : if (MediaKeyErrorStatus::OK != status)
268 : {
269 1 : RIALTO_SERVER_LOG_ERROR("Failed to generate request for the key session %d", keySessionId);
270 1 : return status;
271 : }
272 1 : return status;
273 : }
274 :
275 3 : MediaKeyErrorStatus MediaKeysServerInternal::loadSession(int32_t keySessionId)
276 : {
277 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
278 :
279 : MediaKeyErrorStatus status;
280 3 : auto task = [&]() { status = loadSessionInternal(keySessionId); };
281 :
282 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
283 3 : return status;
284 : }
285 :
286 3 : MediaKeyErrorStatus MediaKeysServerInternal::loadSessionInternal(int32_t keySessionId)
287 : {
288 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
289 3 : if (sessionIter == m_mediaKeySessions.end())
290 : {
291 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
292 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
293 : }
294 :
295 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->loadSession();
296 2 : if (MediaKeyErrorStatus::OK != status)
297 : {
298 1 : RIALTO_SERVER_LOG_ERROR("Failed to load the session %d", keySessionId);
299 1 : return status;
300 : }
301 1 : return status;
302 : }
303 :
304 3 : MediaKeyErrorStatus MediaKeysServerInternal::updateSession(int32_t keySessionId, const std::vector<uint8_t> &responseData)
305 : {
306 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
307 :
308 : MediaKeyErrorStatus status;
309 3 : auto task = [&]() { status = updateSessionInternal(keySessionId, responseData); };
310 :
311 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
312 3 : return status;
313 : }
314 :
315 3 : MediaKeyErrorStatus MediaKeysServerInternal::updateSessionInternal(int32_t keySessionId,
316 : const std::vector<uint8_t> &responseData)
317 : {
318 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
319 3 : if (sessionIter == m_mediaKeySessions.end())
320 : {
321 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
322 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
323 : }
324 :
325 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->updateSession(responseData);
326 2 : if (MediaKeyErrorStatus::OK != status)
327 : {
328 1 : RIALTO_SERVER_LOG_ERROR("Failed to update the session %d", keySessionId);
329 1 : return status;
330 : }
331 1 : return status;
332 : }
333 :
334 3 : MediaKeyErrorStatus MediaKeysServerInternal::setDrmHeader(int32_t keySessionId, const std::vector<uint8_t> &requestData)
335 : {
336 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
337 :
338 : MediaKeyErrorStatus status;
339 3 : auto task = [&]() { status = setDrmHeaderInternal(keySessionId, requestData); };
340 :
341 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
342 3 : return status;
343 : }
344 :
345 3 : MediaKeyErrorStatus MediaKeysServerInternal::setDrmHeaderInternal(int32_t keySessionId,
346 : const std::vector<uint8_t> &requestData)
347 : {
348 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
349 3 : if (sessionIter == m_mediaKeySessions.end())
350 : {
351 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
352 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
353 : }
354 :
355 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->setDrmHeader(requestData);
356 2 : if (MediaKeyErrorStatus::OK != status)
357 : {
358 1 : RIALTO_SERVER_LOG_ERROR("Failed to set drm header");
359 1 : return status;
360 : }
361 :
362 1 : return status;
363 : }
364 :
365 8 : MediaKeyErrorStatus MediaKeysServerInternal::closeKeySession(int32_t keySessionId)
366 : {
367 8 : RIALTO_SERVER_LOG_DEBUG("entry:");
368 :
369 : MediaKeyErrorStatus status;
370 8 : auto task = [&]() { status = closeKeySessionInternal(keySessionId); };
371 :
372 8 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
373 8 : return status;
374 : }
375 :
376 8 : MediaKeyErrorStatus MediaKeysServerInternal::closeKeySessionInternal(int32_t keySessionId)
377 : {
378 8 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
379 8 : if (sessionIter == m_mediaKeySessions.end())
380 : {
381 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
382 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
383 : }
384 :
385 7 : if (sessionIter->second.bufCounter == 0)
386 : {
387 3 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->closeKeySession();
388 3 : if (MediaKeyErrorStatus::OK != status)
389 : {
390 1 : RIALTO_SERVER_LOG_ERROR("Failed to close the key session %d", keySessionId);
391 1 : return status;
392 : }
393 2 : return status;
394 : }
395 :
396 4 : RIALTO_SERVER_LOG_INFO("Deferring closing of key session %d", keySessionId);
397 4 : sessionIter->second.shouldBeClosed = true;
398 4 : return MediaKeyErrorStatus::OK;
399 : }
400 :
401 11 : MediaKeyErrorStatus MediaKeysServerInternal::removeKeySession(int32_t keySessionId)
402 : {
403 11 : RIALTO_SERVER_LOG_DEBUG("entry:");
404 :
405 : MediaKeyErrorStatus status;
406 11 : auto task = [&]() { status = removeKeySessionInternal(keySessionId); };
407 :
408 11 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
409 11 : return status;
410 : }
411 :
412 11 : MediaKeyErrorStatus MediaKeysServerInternal::removeKeySessionInternal(int32_t keySessionId)
413 : {
414 11 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
415 11 : if (sessionIter == m_mediaKeySessions.end())
416 : {
417 4 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
418 4 : return MediaKeyErrorStatus::BAD_SESSION_ID;
419 : }
420 :
421 7 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->removeKeySession();
422 7 : if (MediaKeyErrorStatus::OK != status)
423 : {
424 1 : RIALTO_SERVER_LOG_ERROR("Failed to remove the key session %d", keySessionId);
425 1 : return status;
426 : }
427 6 : return status;
428 : }
429 :
430 2 : MediaKeyErrorStatus MediaKeysServerInternal::deleteDrmStore()
431 : {
432 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
433 :
434 : MediaKeyErrorStatus status;
435 2 : auto task = [&]() { status = m_ocdmSystem->deleteSecureStore(); };
436 :
437 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
438 2 : return status;
439 : }
440 :
441 2 : MediaKeyErrorStatus MediaKeysServerInternal::deleteKeyStore()
442 : {
443 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
444 :
445 : MediaKeyErrorStatus status;
446 2 : auto task = [&]() { status = m_ocdmSystem->deleteKeyStore(); };
447 :
448 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
449 2 : return status;
450 : }
451 :
452 2 : MediaKeyErrorStatus MediaKeysServerInternal::getDrmStoreHash(std::vector<unsigned char> &drmStoreHash)
453 : {
454 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
455 2 : constexpr size_t kHashSize{256};
456 2 : drmStoreHash.resize(kHashSize);
457 : MediaKeyErrorStatus status;
458 2 : auto task = [&]() { status = m_ocdmSystem->getSecureStoreHash(&drmStoreHash[0], kHashSize); };
459 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
460 2 : return status;
461 : }
462 :
463 2 : MediaKeyErrorStatus MediaKeysServerInternal::getKeyStoreHash(std::vector<unsigned char> &keyStoreHash)
464 : {
465 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
466 2 : constexpr size_t kHashSize{256};
467 2 : keyStoreHash.resize(kHashSize);
468 : MediaKeyErrorStatus status;
469 2 : auto task = [&]() { status = m_ocdmSystem->getKeyStoreHash(&keyStoreHash[0], kHashSize); };
470 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
471 2 : return status;
472 : }
473 :
474 2 : MediaKeyErrorStatus MediaKeysServerInternal::getLdlSessionsLimit(uint32_t &ldlLimit)
475 : {
476 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
477 :
478 : MediaKeyErrorStatus status;
479 2 : auto task = [&]() { status = m_ocdmSystem->getLdlSessionsLimit(&ldlLimit); };
480 :
481 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
482 2 : return status;
483 : }
484 :
485 3 : MediaKeyErrorStatus MediaKeysServerInternal::getLastDrmError(int32_t keySessionId, uint32_t &errorCode)
486 : {
487 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
488 :
489 : MediaKeyErrorStatus status;
490 3 : auto task = [&]() { status = getLastDrmErrorInternal(keySessionId, errorCode); };
491 :
492 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
493 3 : return status;
494 : }
495 :
496 3 : MediaKeyErrorStatus MediaKeysServerInternal::getLastDrmErrorInternal(int32_t keySessionId, uint32_t &errorCode)
497 : {
498 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
499 3 : if (sessionIter == m_mediaKeySessions.end())
500 : {
501 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
502 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
503 : }
504 :
505 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->getLastDrmError(errorCode);
506 2 : if (MediaKeyErrorStatus::OK != status)
507 : {
508 1 : RIALTO_SERVER_LOG_ERROR("Failed to get last drm error");
509 : }
510 :
511 2 : return status;
512 : }
513 :
514 2 : MediaKeyErrorStatus MediaKeysServerInternal::getDrmTime(uint64_t &drmTime)
515 : {
516 : MediaKeyErrorStatus status;
517 2 : auto task = [&]() { status = m_ocdmSystem->getDrmTime(&drmTime); };
518 :
519 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
520 2 : return status;
521 : }
522 :
523 3 : MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId)
524 : {
525 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
526 :
527 : MediaKeyErrorStatus status;
528 3 : auto task = [&]() { status = getCdmKeySessionIdInternal(keySessionId, cdmKeySessionId); };
529 :
530 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
531 3 : return status;
532 : }
533 :
534 7 : MediaKeyErrorStatus MediaKeysServerInternal::releaseKeySession(int32_t keySessionId)
535 : {
536 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
537 :
538 : MediaKeyErrorStatus status;
539 7 : auto task = [&]() { status = releaseKeySessionInternal(keySessionId); };
540 :
541 7 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
542 7 : return status;
543 : }
544 :
545 7 : MediaKeyErrorStatus MediaKeysServerInternal::releaseKeySessionInternal(int32_t keySessionId)
546 : {
547 7 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
548 7 : if (sessionIter == m_mediaKeySessions.end())
549 : {
550 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
551 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
552 : }
553 :
554 6 : if (sessionIter->second.bufCounter == 0)
555 : {
556 2 : m_mediaKeySessions.erase(sessionIter);
557 2 : return MediaKeyErrorStatus::OK;
558 : }
559 :
560 4 : RIALTO_SERVER_LOG_INFO("Deferring releasing of key session %d", keySessionId);
561 4 : sessionIter->second.shouldBeReleased = true;
562 4 : return MediaKeyErrorStatus::OK;
563 : }
564 :
565 3 : MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionIdInternal(int32_t keySessionId, std::string &cdmKeySessionId)
566 : {
567 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
568 3 : if (sessionIter == m_mediaKeySessions.end())
569 : {
570 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
571 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
572 : }
573 :
574 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->getCdmKeySessionId(cdmKeySessionId);
575 2 : if (MediaKeyErrorStatus::OK != status)
576 : {
577 1 : RIALTO_SERVER_LOG_ERROR("Failed to get cdm key session id");
578 1 : return status;
579 : }
580 :
581 1 : return status;
582 : }
583 :
584 3 : MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps)
585 : {
586 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
587 :
588 : MediaKeyErrorStatus status;
589 3 : auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); };
590 :
591 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
592 3 : return status;
593 : }
594 :
595 3 : MediaKeyErrorStatus MediaKeysServerInternal::decryptInternal(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps)
596 : {
597 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
598 3 : if (sessionIter == m_mediaKeySessions.end())
599 : {
600 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
601 1 : return MediaKeyErrorStatus::BAD_SESSION_ID;
602 : }
603 :
604 2 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->decrypt(encrypted, caps);
605 2 : if (MediaKeyErrorStatus::OK != status)
606 : {
607 1 : RIALTO_SERVER_LOG_ERROR("Failed to decrypt buffer.");
608 1 : return status;
609 : }
610 :
611 1 : return status;
612 : }
613 :
614 1 : bool MediaKeysServerInternal::hasSession(int32_t keySessionId) const
615 : {
616 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
617 :
618 : bool result;
619 1 : auto task = [&]() { result = m_mediaKeySessions.find(keySessionId) != m_mediaKeySessions.end(); };
620 :
621 1 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
622 1 : return result;
623 : }
624 :
625 3 : bool MediaKeysServerInternal::isNetflixPlayreadyKeySystem(int32_t keySessionId) const
626 : {
627 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
628 : bool result;
629 3 : auto task = [&]() { result = isNetflixPlayreadyKeySystemInternal(keySessionId); };
630 :
631 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
632 3 : return result;
633 : }
634 :
635 3 : bool MediaKeysServerInternal::isNetflixPlayreadyKeySystemInternal(int32_t keySessionId) const
636 : {
637 3 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
638 3 : if (sessionIter == m_mediaKeySessions.end())
639 : {
640 1 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
641 1 : return false;
642 : }
643 2 : return sessionIter->second.mediaKeySession->isNetflixPlayreadyKeySystem();
644 : }
645 :
646 12 : void MediaKeysServerInternal::incrementSessionIdUsageCounter(int32_t keySessionId)
647 : {
648 12 : RIALTO_SERVER_LOG_DEBUG("entry:");
649 12 : auto task = [&]() { incrementSessionIdUsageCounterInternal(keySessionId); };
650 :
651 12 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
652 : }
653 :
654 12 : void MediaKeysServerInternal::incrementSessionIdUsageCounterInternal(int32_t keySessionId)
655 : {
656 12 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
657 12 : if (sessionIter == m_mediaKeySessions.end())
658 : {
659 2 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
660 2 : return;
661 : }
662 :
663 10 : sessionIter->second.bufCounter++;
664 : }
665 :
666 8 : void MediaKeysServerInternal::decrementSessionIdUsageCounter(int32_t keySessionId)
667 : {
668 8 : RIALTO_SERVER_LOG_DEBUG("entry:");
669 8 : auto task = [&]() { decrementSessionIdUsageCounterInternal(keySessionId); };
670 :
671 8 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
672 : }
673 :
674 8 : void MediaKeysServerInternal::decrementSessionIdUsageCounterInternal(int32_t keySessionId)
675 : {
676 8 : auto sessionIter = m_mediaKeySessions.find(keySessionId);
677 8 : if (sessionIter == m_mediaKeySessions.end())
678 : {
679 2 : RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId);
680 2 : return;
681 : }
682 :
683 6 : if (sessionIter->second.bufCounter > 0)
684 : {
685 4 : sessionIter->second.bufCounter--;
686 : }
687 :
688 6 : if (sessionIter->second.bufCounter == 0)
689 : {
690 4 : if (sessionIter->second.shouldBeClosed)
691 : {
692 1 : RIALTO_SERVER_LOG_INFO("Deferred closing of mksId %d", keySessionId);
693 1 : MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->closeKeySession();
694 1 : if (MediaKeyErrorStatus::OK != status)
695 : {
696 0 : RIALTO_SERVER_LOG_ERROR("Failed to close the key session %d", keySessionId);
697 : }
698 : }
699 4 : if (sessionIter->second.shouldBeReleased)
700 : {
701 1 : m_mediaKeySessions.erase(sessionIter);
702 : }
703 : }
704 : }
705 :
706 1 : void MediaKeysServerInternal::ping(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
707 : {
708 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
709 1 : auto task = [&]() { heartbeatHandler.reset(); };
710 :
711 1 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
712 : }
713 :
714 4 : MediaKeyErrorStatus MediaKeysServerInternal::getMetricSystemData(std::vector<uint8_t> &buffer)
715 : {
716 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
717 :
718 4 : uint32_t bufferLength{1024};
719 4 : const uint32_t kMaxBufferLength{65536};
720 : MediaKeyErrorStatus status;
721 4 : buffer.resize(bufferLength);
722 :
723 11 : for (int attempts = 0; bufferLength <= kMaxBufferLength; ++attempts)
724 : {
725 11 : auto task = [&]() { status = m_ocdmSystem->getMetricSystemData(bufferLength, buffer); };
726 11 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
727 :
728 11 : if (status != MediaKeyErrorStatus::BUFFER_TOO_SMALL)
729 : {
730 3 : break;
731 : }
732 :
733 8 : if (bufferLength >= kMaxBufferLength)
734 : {
735 1 : RIALTO_SERVER_LOG_ERROR("Buffer size %u exceeds the maximum allowed size %u", bufferLength, kMaxBufferLength);
736 1 : return MediaKeyErrorStatus::BUFFER_TOO_SMALL;
737 : }
738 :
739 7 : RIALTO_SERVER_LOG_WARN("Buffer is too small, resizing from %u to %u", bufferLength, bufferLength * 2);
740 7 : bufferLength *= 2;
741 7 : buffer.resize(bufferLength);
742 : }
743 :
744 3 : if (status == MediaKeyErrorStatus::OK)
745 : {
746 : // If the buffer remains larger than bufferLength (due to a previous resize),
747 : // the client may have values in the extra space. So this resize would ensure the buffer is trimmed to the correct size.
748 2 : buffer.resize(bufferLength);
749 2 : RIALTO_SERVER_LOG_DEBUG("Successfully retrieved metric system data, final buffer length: %u", bufferLength);
750 : }
751 : else
752 : {
753 1 : RIALTO_SERVER_LOG_ERROR("Failed to retrieve metric system data, status: %s, last buffer length tried: %u",
754 : firebolt::rialto::mediaKeyErrorStatusToString(status), bufferLength);
755 : }
756 3 : return status;
757 : }
758 :
759 : }; // namespace firebolt::rialto::server
|