RDK Documentation (Open Sourced RDK Components)
AampDRMSessionManager.cpp
Go to the documentation of this file.
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 2018 RDK Management
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 
21 /**
22  * @file AampDRMSessionManager.cpp
23  * @brief Source file for DrmSessionManager.
24  */
25 
26 #include "AampDRMSessionManager.h"
27 #include "priv_aamp.h"
28 #include <pthread.h>
29 #include "_base64.h"
30 #include <iostream>
31 #include "AampMutex.h"
32 #include "AampDrmHelper.h"
33 #include "AampJsonObject.h"
34 #include "AampUtils.h"
35 #include "AampRfc.h"
36 #include <inttypes.h>
37 #ifdef USE_SECMANAGER
38 #include "AampSecManager.h"
39 #endif
40 
41 #include "AampCurlStore.h"
42 
43 //#define LOG_TRACE 1
44 #define LICENCE_REQUEST_HEADER_ACCEPT "Accept:"
45 
46 #define LICENCE_REQUEST_HEADER_CONTENT_TYPE "Content-Type:"
47 
48 #define LICENCE_RESPONSE_JSON_LICENCE_KEY "license"
49 #define DRM_METADATA_TAG_START "<ckm:policy xmlns:ckm=\"urn:ccp:ckm\">"
50 #define DRM_METADATA_TAG_END "</ckm:policy>"
51 #define SESSION_TOKEN_URL "http://localhost:50050/authService/getSessionToken"
52 
53 #define INVALID_SESSION_SLOT -1
54 #define DEFUALT_CDM_WAIT_TIMEOUT_MS 2000
55 
56 #define CURL_EASY_SETOPT(curl, CURLoption, option)\
57  if (curl_easy_setopt(curl, CURLoption, option) != 0) {\
58  AAMPLOG_WARN("Failed at curl_easy_setopt ");\
59  } //CID:128208 - checked return
60 
61 static const char *sessionTypeName[] = {"video", "audio", "subtitle", "aux-audio"};
62 
63 static pthread_mutex_t drmSessionMutex = PTHREAD_MUTEX_INITIALIZER;
64 
65 KeyID::KeyID() : creationTime(0), isFailedKeyId(false), isPrimaryKeyId(false), data()
66 {
67 }
68 
69 
70 void *CreateDRMSession(void *arg);
73 
74 #if defined(USE_SECCLIENT) || defined(USE_SECMANAGER)
75 /**
76  * @brief Get formatted URL of license server
77  *
78  * @param[in] url URL of license server
79  * @return formatted url for secclient license acqusition.
80  */
81 static string getFormattedLicenseServerURL(string url)
82 {
83  size_t startpos = 0;
84  size_t endpos, len;
85  endpos = len = url.size();
86 
87  if (memcmp(url.data(), "https://", 8) == 0)
88  {
89  startpos += 8;
90  }
91  else if (memcmp(url.data(), "http://", 7) == 0)
92  {
93  startpos += 7;
94  }
95 
96  if (startpos != 0)
97  {
98  endpos = url.find('/', startpos);
99  if (endpos != string::npos)
100  {
101  len = endpos - startpos;
102  }
103  }
104 
105  return url.substr(startpos, len);
106 }
107 #endif
108 
109 /**
110  * @brief AampDRMSessionManager constructor.
111  */
112 AampDRMSessionManager::AampDRMSessionManager(AampLogManager *logObj, int maxDrmSessions) : drmSessionContexts(NULL),
113  cachedKeyIDs(NULL), accessToken(NULL),
114  accessTokenLen(0), sessionMgrState(SessionMgrState::eSESSIONMGR_ACTIVE), accessTokenMutex(PTHREAD_MUTEX_INITIALIZER),
115  cachedKeyMutex(PTHREAD_MUTEX_INITIALIZER)
116  ,curlSessionAbort(false), mEnableAccessAtrributes(true)
117  ,mDrmSessionLock(), licenseRequestAbort(false)
118  ,mMaxDRMSessions(maxDrmSessions)
119  ,mLogObj(logObj)
120 #ifdef USE_SECMANAGER
121  ,mSessionId(AAMP_SECMGR_INVALID_SESSION_ID)
122 #endif
123 {
124  if(maxDrmSessions < 1)
125  {
126  mMaxDRMSessions = 1; // minimum of 1 drm session needed
127  }
128  else if(maxDrmSessions > MAX_DASH_DRM_SESSIONS)
129  {
130  mMaxDRMSessions = MAX_DASH_DRM_SESSIONS; // limit to 30
131  }
132  drmSessionContexts = new DrmSessionContext[mMaxDRMSessions];
133  cachedKeyIDs = new KeyID[mMaxDRMSessions];
134  AAMPLOG_INFO("AampDRMSessionManager MaxSession:%d",mMaxDRMSessions);
135  pthread_mutex_init(&mDrmSessionLock, NULL);
136 }
137 
138 /**
139  * @brief AampDRMSessionManager Destructor.
140  */
142 {
145  SAFE_DELETE_ARRAY(drmSessionContexts);
146  SAFE_DELETE_ARRAY(cachedKeyIDs);
147  pthread_mutex_destroy(&mDrmSessionLock);
148  pthread_mutex_destroy(&accessTokenMutex);
149  pthread_mutex_destroy(&cachedKeyMutex);
150 }
151 
152 /**
153  * @brief Clean up the memory used by session variables.
154  */
156 {
157  AAMPLOG_WARN(" AampDRMSessionManager:: Clearing session data");
158  for(int i = 0 ; i < mMaxDRMSessions; i++)
159  {
160  if (drmSessionContexts != NULL && drmSessionContexts[i].drmSession != NULL)
161  {
162 #ifdef USE_SECMANAGER
163  // Cached session is about to be destroyed, send release to SecManager
164  if (drmSessionContexts[i].drmSession->getSessionId() != AAMP_SECMGR_INVALID_SESSION_ID)
165  {
166  AampSecManager::GetInstance()->ReleaseSession(drmSessionContexts[i].drmSession->getSessionId());
167  }
168 #endif
169  SAFE_DELETE(drmSessionContexts[i].drmSession);
170  drmSessionContexts[i] = DrmSessionContext();
171  }
172 
173  if (cachedKeyIDs != NULL)
174  {
175  cachedKeyIDs[i] = KeyID();
176  }
177  }
178 }
179 
180 /**
181  * @brief Set Session manager state
182  */
184 {
185  sessionMgrState = state;
186 }
187 
188 /**
189  * @brief Get Session manager state
190  */
192 {
193  return sessionMgrState;
194 }
195 
196 /**
197  * @brief Set Session abort flag
198  */
200  curlSessionAbort = isAbort;
201 }
202 
203 /**
204  * @brief Get Session abort flag
205  */
207  return curlSessionAbort;
208 }
209 
210 /**
211  * @brief Get Session abort flag
212  */
214 {
215  setCurlAbort(isAbort);
216  licenseRequestAbort = isAbort;
217 }
218 
219 /**
220  * @brief Clean up the failed keyIds.
221  */
223 {
224  pthread_mutex_lock(&cachedKeyMutex);
225  for(int i = 0 ; i < mMaxDRMSessions; i++)
226  {
227  if(cachedKeyIDs[i].isFailedKeyId)
228  {
229  if(!cachedKeyIDs[i].data.empty())
230  {
231  cachedKeyIDs[i].data.clear();
232  }
233  cachedKeyIDs[i].isFailedKeyId = false;
234  cachedKeyIDs[i].creationTime = 0;
235  }
236  cachedKeyIDs[i].isPrimaryKeyId = false;
237  }
238  pthread_mutex_unlock(&cachedKeyMutex);
239 }
240 
241 /**
242  * @brief Clean up the memory for accessToken.
243  */
245 {
246  if(accessToken)
247  {
248  free(accessToken);
249  accessToken = NULL;
250  accessTokenLen = 0;
251  }
252 }
253 
254 /**
255  * @brief Clean up the Session Data if license key acquisition failed or if LicenseCaching is false.
256  */
257 void AampDRMSessionManager::clearDrmSession(bool forceClearSession)
258 {
259  for(int i = 0 ; i < mMaxDRMSessions; i++)
260  {
261  // Clear the session data if license key acquisition failed or if forceClearSession is true in the case of LicenseCaching is false.
262  if((cachedKeyIDs[i].isFailedKeyId || forceClearSession) && drmSessionContexts != NULL)
263  {
264  AampMutexHold sessionMutex(drmSessionContexts[i].sessionMutex);
265  if (drmSessionContexts[i].drmSession != NULL)
266  {
267  AAMPLOG_WARN("AampDRMSessionManager:: Clearing failed Session Data Slot : %d", i);
268 #ifdef USE_SECMANAGER
269  // Cached session is about to be destroyed, send release to SecManager
270  if (drmSessionContexts[i].drmSession->getSessionId() != AAMP_SECMGR_INVALID_SESSION_ID)
271  {
272  AampSecManager::GetInstance()->ReleaseSession(drmSessionContexts[i].drmSession->getSessionId());
273  }
274 #endif
275  SAFE_DELETE(drmSessionContexts[i].drmSession);
276  }
277  }
278  }
279 }
280 
281 
282 void AampDRMSessionManager::setVideoWindowSize(int width, int height)
283 {
284 #ifdef USE_SECMANAGER
285  AAMPLOG_WARN("In AampDRMSessionManager:: setting video windor size w:%d x h:%d mMaxDRMSessions=%d mSessionId=[%" PRId64 "]",width,height,mMaxDRMSessions,mSessionId);
286  if(mSessionId != AAMP_SECMGR_INVALID_SESSION_ID)
287  {
288  AAMPLOG_WARN("In AampDRMSessionManager:: valid session ID");
289  AampSecManager::GetInstance()->setVideoWindowSize(mSessionId, width, height);
290  }
291 #endif
292 }
293 
294 
295 void AampDRMSessionManager::setPlaybackSpeedState(int speed, double position, bool delayNeeded)
296 {
297 #ifdef USE_SECMANAGER
298  AAMPLOG_WARN("In AampDRMSessionManager::after calling setPlaybackSpeedState speed=%d position=%f mSessionId=[%" PRId64 "]",speed, position, mSessionId);
299  if(mSessionId != AAMP_SECMGR_INVALID_SESSION_ID)
300  {
301  AAMPLOG_WARN("In AampDRMSessionManager::valid session ID");
302  AampSecManager::GetInstance()->setPlaybackSpeedState(mSessionId, speed, position, delayNeeded);
303  }
304 #endif
305 }
306 
307 
309  void *clientp, // app-specific as optionally set with CURLOPT_PROGRESSDATA
310  double dltotal, // total bytes expected to download
311  double dlnow, // downloaded bytes so far
312  double ultotal, // total bytes expected to upload
313  double ulnow // uploaded bytes so far
314  )
315 {
316  int returnCode = 0 ;
317  AampDRMSessionManager *drmSessionManager = (AampDRMSessionManager *)clientp;
318  if(drmSessionManager->getCurlAbort())
319  {
320  logprintf("Aborting DRM curl operation.. - CURLE_ABORTED_BY_CALLBACK");
321  returnCode = -1; // Return non-zero for CURLE_ABORTED_BY_CALLBACK
322  //Reset the abort variable
323  drmSessionManager->setCurlAbort(false);
324  }
325 
326  return returnCode;
327 }
328 
329 /**
330  * @brief Curl write callback, used to get the curl o/p
331  * from DRM license, accessToken curl requests.
332  */
333 size_t AampDRMSessionManager::write_callback(char *ptr, size_t size,
334  size_t nmemb, void *userdata)
335 {
336  writeCallbackData *callbackData = (writeCallbackData*)userdata;
337  DrmData *data = (DrmData *)callbackData->data;
338  size_t numBytesForBlock = size * nmemb;
339  if(callbackData->mDRMSessionManager->getCurlAbort())
340  {
341  logprintf("Aborting DRM curl operation.. - CURLE_ABORTED_BY_CALLBACK");
342  numBytesForBlock = 0; // Will cause CURLE_WRITE_ERROR
343  //Reset the abort variable
344  callbackData->mDRMSessionManager->setCurlAbort(false);
345 
346  }
347  else if (data->getData().empty())
348  {
349  data->setData((unsigned char *)ptr, numBytesForBlock);
350  }
351  else
352  {
353  data->addData((unsigned char *)ptr, numBytesForBlock);
354  }
356  {
357  logprintf(" wrote %zu number of blocks", numBytesForBlock);
358  }
359  return numBytesForBlock;
360 }
361 
362 /**
363  * @brief Extract substring between (excluding) two string delimiters.
364  *
365  * @param[in] parentStr - Parent string from which substring is extracted.
366  * @param[in] startStr, endStr - String delimiters.
367  * @return Returns the extracted substring; Empty string if delimiters not found.
368  */
369 string _extractSubstring(string parentStr, string startStr, string endStr)
370 {
371  string ret = "";
372  int startPos = parentStr.find(startStr);
373  if(string::npos != startPos)
374  {
375  int offset = strlen(startStr.c_str());
376  int endPos = parentStr.find(endStr, startPos + offset + 1);
377  if(string::npos != endPos)
378  {
379  ret = parentStr.substr(startPos + offset, endPos - (startPos + offset));
380  }
381  }
382  return ret;
383 }
384 
385 /**
386  * @brief Get the accessToken from authService.
387  */
388 const char * AampDRMSessionManager::getAccessToken(int &tokenLen, long &error_code , bool bSslPeerVerify)
389 {
390  if(accessToken == NULL)
391  {
392  DrmData * tokenReply = new DrmData();
393  writeCallbackData *callbackData = new writeCallbackData();
394  callbackData->data = tokenReply;
395  callbackData->mDRMSessionManager = this;
396  CURLcode res;
397  long httpCode = -1;
398 
399  CURL *curl = curl_easy_init();;
400  CURL_EASY_SETOPT(curl, CURLOPT_NOSIGNAL, 1L);
401  CURL_EASY_SETOPT(curl, CURLOPT_WRITEFUNCTION, write_callback);
402  CURL_EASY_SETOPT(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
403  CURL_EASY_SETOPT(curl, CURLOPT_TIMEOUT, DEFAULT_CURL_TIMEOUT);
404  CURL_EASY_SETOPT(curl, CURLOPT_PROGRESSDATA, this);
405  CURL_EASY_SETOPT(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
406  CURL_EASY_SETOPT(curl, CURLOPT_FOLLOWLOCATION, 1L);
407  CURL_EASY_SETOPT(curl, CURLOPT_NOPROGRESS, 0L);
408  CURL_EASY_SETOPT(curl, CURLOPT_WRITEDATA, callbackData);
409  if(!bSslPeerVerify){
410  CURL_EASY_SETOPT(curl, CURLOPT_SSL_VERIFYPEER, 0L);
411  }
412  CURL_EASY_SETOPT(curl, CURLOPT_URL, SESSION_TOKEN_URL);
413 
414  res = curl_easy_perform(curl);
415 
416  if (res == CURLE_OK)
417  {
418  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
419  if (httpCode == 200 || httpCode == 206)
420  {
421  string tokenReplyStr = tokenReply->getData();
422  string tokenStatusCode = _extractSubstring(tokenReplyStr, "status\":", ",\"");
423  if(tokenStatusCode.length() == 0)
424  {
425  //StatusCode could be last element in the json
426  tokenStatusCode = _extractSubstring(tokenReplyStr, "status\":", "}");
427  }
428  if(tokenStatusCode.length() == 1 && tokenStatusCode.c_str()[0] == '0')
429  {
430  string token = _extractSubstring(tokenReplyStr, "token\":\"", "\"");
431  size_t len = token.length();
432  if(len > 0)
433  {
434  accessToken = (char*)malloc(len+1);
435  if(accessToken)
436  {
437  accessTokenLen = len;
438  memcpy( accessToken, token.c_str(), len );
439  accessToken[len] = 0x00;
440  AAMPLOG_WARN(" Received session token from auth service ");
441  }
442  else
443  {
444  AAMPLOG_WARN("accessToken is null"); //CID:83536 - Null Returns
445  }
446  }
447  else
448  {
449  AAMPLOG_WARN(" Could not get access token from session token reply");
450  error_code = (long)eAUTHTOKEN_TOKEN_PARSE_ERROR;
451  }
452  }
453  else
454  {
455  AAMPLOG_ERR(" Missing or invalid status code in session token reply");
456  error_code = (long)eAUTHTOKEN_INVALID_STATUS_CODE;
457  }
458  }
459  else
460  {
461  AAMPLOG_ERR(" Get Session token call failed with http error %d", httpCode);
462  error_code = httpCode;
463  }
464  }
465  else
466  {
467  AAMPLOG_ERR(" Get Session token call failed with curl error %d", res);
468  error_code = res;
469  }
470  SAFE_DELETE(tokenReply);
471  SAFE_DELETE(callbackData);
472  curl_easy_cleanup(curl);
473  }
474 
475  tokenLen = accessTokenLen;
476  return accessToken;
477 }
478 
479 /**
480  * @brief Get DRM license key from DRM server.
481  */
482 bool AampDRMSessionManager::IsKeyIdUsable(std::vector<uint8_t> keyIdArray)
483 {
484  bool ret = true;
485  pthread_mutex_lock(&cachedKeyMutex);
486  for (int sessionSlot = 0; sessionSlot < mMaxDRMSessions; sessionSlot++)
487  {
488  auto keyIDSlot = cachedKeyIDs[sessionSlot].data;
489  if (!keyIDSlot.empty() && keyIDSlot.end() != std::find(keyIDSlot.begin(), keyIDSlot.end(), keyIdArray))
490  {
491  std::string debugStr = AampLogManager::getHexDebugStr(keyIdArray);
492  AAMPLOG_INFO("Session created/inprogress with same keyID %s at slot %d", debugStr.c_str(), sessionSlot);
493  break;
494  }
495  }
496  pthread_mutex_unlock(&cachedKeyMutex);
497 
498  return ret;
499 }
500 
501 
502 #if defined(USE_SECCLIENT) || defined(USE_SECMANAGER)
503 
504 DrmData * AampDRMSessionManager::getLicenseSec(const AampLicenseRequest &licenseRequest, std::shared_ptr<AampDrmHelper> drmHelper,
505  const AampChallengeInfo& challengeInfo, PrivateInstanceAAMP* aampInstance, int32_t *httpCode, int32_t *httpExtStatusCode, DrmMetaDataEventPtr eventHandle)
506 {
507  DrmData *licenseResponse = nullptr;
508  const char *mediaUsage = "stream";
509  string contentMetaData = drmHelper->getDrmMetaData();
510  char *encodedData = base64_Encode(reinterpret_cast<const unsigned char*>(contentMetaData.c_str()), contentMetaData.length());
511  char *encodedChallengeData = base64_Encode(reinterpret_cast<const unsigned char*>(challengeInfo.data->getData().c_str()), challengeInfo.data->getDataLength());
512  //Calculate the lengths using the logic in base64_Encode
513  size_t encodedDataLen = ((contentMetaData.length() + 2) /3) * 4;
514  size_t encodedChallengeDataLen = ((challengeInfo.data->getDataLength() + 2) /3) * 4;
515 
516  const char *keySystem = drmHelper->ocdmSystemId().c_str();
517  const char *secclientSessionToken = challengeInfo.accessToken.empty() ? NULL : challengeInfo.accessToken.c_str();
518 
519  char *licenseResponseStr = NULL;
520  size_t licenseResponseLength = 2;
521  uint32_t refreshDuration = 3;
522  const char *requestMetadata[1][2];
523  uint8_t numberOfAccessAttributes = 0;
524  const char *accessAttributes[2][2] = {NULL, NULL, NULL, NULL};
525  std::string serviceZone, streamID;
526  if(aampInstance->mIsVSS)
527  {
528  if (aampInstance->GetEnableAccessAtrributesFlag())
529  {
530  serviceZone = aampInstance->GetServiceZone();
531  streamID = aampInstance->GetVssVirtualStreamID();
532  if (!serviceZone.empty())
533  {
534  accessAttributes[numberOfAccessAttributes][0] = VSS_SERVICE_ZONE_KEY_STR;
535  accessAttributes[numberOfAccessAttributes][1] = serviceZone.c_str();
536  numberOfAccessAttributes++;
537  }
538  if (!streamID.empty())
539  {
540  accessAttributes[numberOfAccessAttributes][0] = VSS_VIRTUAL_STREAM_ID_KEY_STR;
541  accessAttributes[numberOfAccessAttributes][1] = streamID.c_str();
542  numberOfAccessAttributes++;
543  }
544  }
545  AAMPLOG_INFO("accessAttributes : {\"%s\" : \"%s\", \"%s\" : \"%s\"}", accessAttributes[0][0], accessAttributes[0][1], accessAttributes[1][0], accessAttributes[1][1]);
546  }
547  std::string moneytracestr;
548  requestMetadata[0][0] = "X-MoneyTrace";
549  aampInstance->GetMoneyTraceString(moneytracestr);
550  requestMetadata[0][1] = moneytracestr.c_str();
551 
552  AAMPLOG_WARN("[HHH] Before calling SecClient_AcquireLicense-----------");
553  AAMPLOG_WARN("destinationURL is %s (drm server now used)", licenseRequest.url.c_str());
554  AAMPLOG_WARN("MoneyTrace[%s]", requestMetadata[0][1]);
555 #if USE_SECMANAGER
556  if(aampInstance->mConfig->IsConfigSet(eAAMPConfig_UseSecManager))
557  {
558  int32_t statusCode;
559  int32_t reasonCode;
560  int32_t businessStatus;
561  bool res = AampSecManager::GetInstance()->AcquireLicense(aampInstance, licenseRequest.url.c_str(),
562  requestMetadata,
563  ((numberOfAccessAttributes == 0) ? NULL : accessAttributes),
564  encodedData, encodedDataLen,
565  encodedChallengeData, encodedChallengeDataLen,
566  keySystem,
567  mediaUsage,
568  secclientSessionToken, challengeInfo.accessToken.length(),
569  &mSessionId,
570  &licenseResponseStr, &licenseResponseLength,
571  &statusCode, &reasonCode, &businessStatus);
572  if (res)
573  {
574  AAMPLOG_WARN("acquireLicense via SecManager SUCCESS!");
575  //TODO: Sort this out for backward compatibility
576  *httpCode = 200;
577  *httpExtStatusCode = 0;
578  if (licenseResponseStr)
579  {
580  licenseResponse = new DrmData((unsigned char *)licenseResponseStr, licenseResponseLength);
581  free(licenseResponseStr);
582  }
583  }
584  else
585  {
586  eventHandle->SetVerboseErrorCode( statusCode, reasonCode, businessStatus);
587  AAMPLOG_WARN("Verbose error set with class : %d, Reason Code : %d Business status: %d ", statusCode, reasonCode, businessStatus);
588  *httpCode = statusCode;
589  *httpExtStatusCode = reasonCode;
590 
591  AAMPLOG_ERR("acquireLicense via SecManager FAILED!, httpCode %d, httpExtStatusCode %d", *httpCode, *httpExtStatusCode);
592  //TODO: Sort this out for backward compatibility
593  }
594  }
595 #endif
596 #if USE_SECCLIENT
597 #if USE_SECMANAGER
598  else
599  {
600 #endif
601  int32_t sec_client_result = SEC_CLIENT_RESULT_FAILURE;
602  SecClient_ExtendedStatus statusInfo;
603  unsigned int attemptCount = 0;
604  int sleepTime ;
605  aampInstance->mConfig->GetConfigValue(eAAMPConfig_LicenseRetryWaitTime,sleepTime) ;
606  if(sleepTime<=0) sleepTime = 100;
607  while (attemptCount < MAX_LICENSE_REQUEST_ATTEMPTS)
608  {
609  attemptCount++;
610  sec_client_result = SecClient_AcquireLicense(licenseRequest.url.c_str(), 1,
611  requestMetadata, numberOfAccessAttributes,
612  ((numberOfAccessAttributes == 0) ? NULL : accessAttributes),
613  encodedData,
614  strlen(encodedData),
615  encodedChallengeData, strlen(encodedChallengeData), keySystem, mediaUsage,
616  secclientSessionToken,
617  &licenseResponseStr, &licenseResponseLength, &refreshDuration, &statusInfo);
618 
619  if (((sec_client_result >= 500 && sec_client_result < 600)||
620  (sec_client_result >= SEC_CLIENT_RESULT_HTTP_RESULT_FAILURE_TLS && sec_client_result <= SEC_CLIENT_RESULT_HTTP_RESULT_FAILURE_GENERIC ))
621  && attemptCount < MAX_LICENSE_REQUEST_ATTEMPTS)
622  {
623  AAMPLOG_ERR(" acquireLicense FAILED! license request attempt : %d; response code : sec_client %d", attemptCount, sec_client_result);
624  if (licenseResponseStr) SecClient_FreeResource(licenseResponseStr);
625  AAMPLOG_WARN(" acquireLicense : Sleeping %d milliseconds before next retry.", sleepTime);
626  mssleep(sleepTime);
627  }
628  else
629  {
630  break;
631  }
632  }
633 
634  AAMPLOG_TRACE("licenseResponse is %s", licenseResponseStr);
635  AAMPLOG_TRACE("licenseResponse len is %zd", licenseResponseLength);
636  AAMPLOG_TRACE("accessAttributesStatus is %d", statusInfo.accessAttributeStatus);
637  AAMPLOG_TRACE("refreshDuration is %d", refreshDuration);
638 
639  if (sec_client_result != SEC_CLIENT_RESULT_SUCCESS)
640  {
641  AAMPLOG_ERR(" acquireLicense FAILED! license request attempt : %d; response code : sec_client %d extStatus %d", attemptCount, sec_client_result, statusInfo.statusCode);
642 
643  eventHandle->ConvertToVerboseErrorCode( sec_client_result, statusInfo.statusCode);
644 
645  *httpCode = sec_client_result;
646  *httpExtStatusCode = statusInfo.statusCode;
647 
648  AAMPLOG_WARN("Converted the secclient httpCode : %d, httpExtStatusCode: %d to verbose error with class : %d, Reason Code : %d Business status: %d ", *httpCode, *httpExtStatusCode, eventHandle->getSecManagerClassCode(), eventHandle->getSecManagerReasonCode(), eventHandle->getBusinessStatus());
649  }
650  else
651  {
652  AAMPLOG_WARN(" acquireLicense SUCCESS! license request attempt %d; response code : sec_client %d", attemptCount, sec_client_result);
653  eventHandle->setAccessStatusValue(statusInfo.accessAttributeStatus);
654  licenseResponse = new DrmData((unsigned char *)licenseResponseStr, licenseResponseLength);
655  }
656  if (licenseResponseStr) SecClient_FreeResource(licenseResponseStr);
657 #if USE_SECMANAGER
658  }
659 #endif
660 #endif
661  free(encodedData);
662  free(encodedChallengeData);
663  return licenseResponse;
664 }
665 #endif
666 
667 /**
668  * @brief Get DRM license key from DRM server.
669  */
671  int32_t *httpCode, MediaType streamType, PrivateInstanceAAMP* aamp, bool isContentMetadataAvailable, std::string licenseProxy)
672 {
673  *httpCode = -1;
674  CURL *curl;
675  CURLcode res;
676  double totalTime = 0;
677  struct curl_slist *headers = NULL;
678  DrmData * keyInfo = new DrmData();
679  writeCallbackData *callbackData = new writeCallbackData();
680  callbackData->data = keyInfo;
681  callbackData->mDRMSessionManager = this;
682  long challengeLength = 0;
683  long long downloadTimeMS = 0;
684 
685  curl = CurlStore::GetCurlStoreInstance(aamp)->GetCurlHandle(aamp, licenseRequest.url, eCURLINSTANCE_AES);
686 
687  for (auto& header : licenseRequest.headers)
688  {
689  std::string customHeaderStr = header.first;
690  customHeaderStr.push_back(' ');
691  // For scenarios with multiple header values, its most likely a custom defined.
692  // Below code will have to extended to support the same (eg: money trace headers)
693  customHeaderStr.append(header.second.at(0));
694  headers = curl_slist_append(headers, customHeaderStr.c_str());
695  if (aamp->mConfig->IsConfigSet(eAAMPConfig_CurlLicenseLogging))
696  {
697  AAMPLOG_WARN(" CustomHeader :%s",customHeaderStr.c_str());
698  }
699  }
700 
701  AAMPLOG_WARN(" Sending license request to server : %s ", licenseRequest.url.c_str());
702  if (aamp->mConfig->IsConfigSet(eAAMPConfig_CurlLicenseLogging))
703  {
704  CURL_EASY_SETOPT(curl, CURLOPT_VERBOSE, 1L);
705  }
706  CURL_EASY_SETOPT(curl, CURLOPT_WRITEFUNCTION, write_callback);
707  CURL_EASY_SETOPT(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
708  CURL_EASY_SETOPT(curl, CURLOPT_PROGRESSDATA, this);
709  CURL_EASY_SETOPT(curl, CURLOPT_TIMEOUT, 5L);
710  CURL_EASY_SETOPT(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
711  CURL_EASY_SETOPT(curl, CURLOPT_FOLLOWLOCATION, 1L);
712  CURL_EASY_SETOPT(curl, CURLOPT_URL, licenseRequest.url.c_str());
713  CURL_EASY_SETOPT(curl, CURLOPT_WRITEDATA, callbackData);
715  CURL_EASY_SETOPT(curl, CURLOPT_SSL_VERIFYPEER, 0L);
716  }
717  else {
718  CURL_EASY_SETOPT(curl, CURLOPT_SSLVERSION, aamp->mSupportedTLSVersion);
719  CURL_EASY_SETOPT(curl, CURLOPT_SSL_VERIFYPEER, 1L);
720  }
721 
722  CURL_EASY_SETOPT(curl, CURLOPT_HTTPHEADER, headers);
723 
724  if(licenseRequest.method == AampLicenseRequest::POST)
725  {
726  challengeLength = licenseRequest.payload.size();
727  CURL_EASY_SETOPT(curl, CURLOPT_POSTFIELDSIZE, challengeLength);
728  CURL_EASY_SETOPT(curl, CURLOPT_POSTFIELDS,(uint8_t * )licenseRequest.payload.data());
729  }
730  else
731  {
732  CURL_EASY_SETOPT(curl, CURLOPT_HTTPGET, 1L);
733  }
734 
735  if (!licenseProxy.empty())
736  {
737  CURL_EASY_SETOPT(curl, CURLOPT_PROXY, licenseProxy.c_str());
738  /* allow whatever auth the proxy speaks */
739  CURL_EASY_SETOPT(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
740  }
741  unsigned int attemptCount = 0;
742  bool requestFailed = true;
743  /* Check whether stopped or not before looping - download will be disabled */
744  while(attemptCount < MAX_LICENSE_REQUEST_ATTEMPTS && !licenseRequestAbort)
745  {
746  bool loopAgain = false;
747  attemptCount++;
748  long long tStartTime = NOW_STEADY_TS_MS;
749  res = curl_easy_perform(curl);
750  long long tEndTime = NOW_STEADY_TS_MS;
751  long long downloadTimeMS = tEndTime - tStartTime;
752  /** Restrict further processing license if stop called in between */
753  if(licenseRequestAbort)
754  {
755  AAMPLOG_ERR(" Aborting License acquisition");
756  // Update httpCode as 42-curl abort, so that DRM error event will not be sent by upper layer
757  *httpCode = CURLE_ABORTED_BY_CALLBACK;
758  break;
759  }
760  if (res != CURLE_OK)
761  {
762  // To avoid scary logging
763  if (res != CURLE_ABORTED_BY_CALLBACK && res != CURLE_WRITE_ERROR)
764  {
765  if (res == CURLE_OPERATION_TIMEDOUT || res == CURLE_COULDNT_CONNECT)
766  {
767  // Retry for curl 28 and curl 7 errors.
768  loopAgain = true;
769 
770  SAFE_DELETE(keyInfo);
771  SAFE_DELETE(callbackData);
772  keyInfo = new DrmData();
773  callbackData = new writeCallbackData();
774  callbackData->data = keyInfo;
775  callbackData->mDRMSessionManager = this;
776  CURL_EASY_SETOPT(curl, CURLOPT_WRITEDATA, callbackData);
777  }
778  AAMPLOG_ERR(" curl_easy_perform() failed: %s", curl_easy_strerror(res));
779  AAMPLOG_ERR(" acquireLicense FAILED! license request attempt : %d; response code : curl %d", attemptCount, res);
780  }
781  *httpCode = res;
782  }
783  else
784  {
785  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, httpCode);
786  curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &totalTime);
787  if (*httpCode != 200 && *httpCode != 206)
788  {
789  int licenseRetryWaitTime;
790  aamp->mConfig->GetConfigValue(eAAMPConfig_LicenseRetryWaitTime,licenseRetryWaitTime) ;
791  AAMPLOG_ERR(" acquireLicense FAILED! license request attempt : %d; response code : http %d", attemptCount, *httpCode);
792  if(*httpCode >= 500 && *httpCode < 600
793  && attemptCount < MAX_LICENSE_REQUEST_ATTEMPTS && licenseRetryWaitTime > 0)
794  {
795  SAFE_DELETE(keyInfo);
796  SAFE_DELETE(callbackData);
797  keyInfo = new DrmData();
798  callbackData = new writeCallbackData();
799  callbackData->data = keyInfo;
800  callbackData->mDRMSessionManager = this;
801  CURL_EASY_SETOPT(curl, CURLOPT_WRITEDATA, callbackData);
802  AAMPLOG_WARN("acquireLicense : Sleeping %d milliseconds before next retry.",licenseRetryWaitTime);
803  mssleep(licenseRetryWaitTime);
804  }
805  }
806  else
807  {
808  AAMPLOG_WARN(" DRM Session Manager Received license data from server; Curl total time = %.1f", totalTime);
809  AAMPLOG_WARN(" acquireLicense SUCCESS! license request attempt %d; response code : http %d", attemptCount, *httpCode);
810  requestFailed = false;
811  }
812  }
813 
814  double total, connect, startTransfer, resolve, appConnect, preTransfer, redirect, dlSize;
815  long reqSize;
816  double totalPerformRequest = (double)(downloadTimeMS)/1000;
817 
818  curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &resolve);
819  curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &connect);
820  curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &appConnect);
821  curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &preTransfer);
822  curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &startTransfer);
823  curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &redirect);
824  curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dlSize);
825  curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &reqSize);
826 
828  std::string appName, timeoutClass;
829  if (!aamp->GetAppName().empty())
830  {
831  // append app name with class data
832  appName = aamp->GetAppName() + ",";
833  }
834  if (CURLE_OPERATION_TIMEDOUT == res || CURLE_PARTIAL_FILE == res || CURLE_COULDNT_CONNECT == res)
835  {
836  // introduce extra marker for connection status curl 7/18/28,
837  // example 18(0) if connection failure with PARTIAL_FILE code
838  timeoutClass = "(" + to_string(reqSize > 0) + ")";
839  }
840  AAMPLOG_WARN("HttpRequestEnd: %s%d,%d,%ld%s,%2.4f,%2.4f,%2.4f,%2.4f,%2.4f,%2.4f,%2.4f,%2.4f,%g,%ld,%.500s",
841  appName.c_str(), mediaType, streamType, *httpCode, timeoutClass.c_str(), totalPerformRequest, totalTime, connect, startTransfer, resolve, appConnect,
842  preTransfer, redirect, dlSize, reqSize, licenseRequest.url.c_str());
843 
844  if(!loopAgain)
845  break;
846  }
847 
848  if(*httpCode == -1)
849  {
850  AAMPLOG_WARN(" Updating Curl Abort Response Code");
851  // Update httpCode as 42-curl abort, so that DRM error event will not be sent by upper layer
852  *httpCode = CURLE_ABORTED_BY_CALLBACK;
853  }
854 
855  if(requestFailed && keyInfo != NULL)
856  {
857  SAFE_DELETE(keyInfo);
858  }
859 
860  SAFE_DELETE(callbackData);
861  curl_slist_free_all(headers);
862  CurlStore::GetCurlStoreInstance(aamp)->SaveCurlHandle(aamp, licenseRequest.url, eCURLINSTANCE_AES, curl);
863 
864  return keyInfo;
865 }
866 
867 /**
868  * @brief Creates and/or returns the DRM session corresponding to keyId (Present in initDataPtr)
869  * AampDRMSession manager has two static AampDrmSession objects.
870  * This method will return the existing DRM session pointer if any one of these static
871  * DRM session objects are created against requested keyId. Binds the oldest DRM Session
872  * with new keyId if no matching keyId is found in existing sessions.
873  * @return Pointer to DrmSession for the given PSSH data; NULL if session creation/mapping fails.
874  */
876  const char* systemId, MediaFormat mediaFormat, const unsigned char * initDataPtr,
877  uint16_t initDataLen, MediaType streamType,
878  PrivateInstanceAAMP* aamp, DrmMetaDataEventPtr e, const unsigned char* contentMetadataPtr,
879  bool isPrimarySession)
880 {
881  DrmInfo drmInfo;
882  std::shared_ptr<AampDrmHelper> drmHelper;
883  AampDrmSession *drmSession = NULL;
884 
885  drmInfo.method = eMETHOD_AES_128;
886  drmInfo.mediaFormat = mediaFormat;
887  drmInfo.systemUUID = systemId;
889 
890  if (!AampDrmHelperEngine::getInstance().hasDRM(drmInfo))
891  {
892  AAMPLOG_ERR(" Failed to locate DRM helper");
893  }
894  else
895  {
896  drmHelper = AampDrmHelperEngine::getInstance().createHelper(drmInfo,mLogObj);
897 
898  if(contentMetadataPtr)
899  {
900  std::string contentMetadataPtrString = reinterpret_cast<const char*>(contentMetadataPtr);
901  drmHelper->setDrmMetaData(contentMetadataPtrString);
902  }
903 
904  if (!drmHelper->parsePssh(initDataPtr, initDataLen))
905  {
906  AAMPLOG_ERR(" Failed to Parse PSSH from the DRM InitData");
907  e->setFailure(AAMP_TUNE_CORRUPT_DRM_METADATA);
908  }
909  else
910  {
911  drmSession = AampDRMSessionManager::createDrmSession(drmHelper, e, aamp, streamType);
912  }
913  }
914 
915  return drmSession;
916 }
917 
918 /**
919  * @brief Create DrmSession by using the AampDrmHelper object
920  */
921 AampDrmSession* AampDRMSessionManager::createDrmSession(std::shared_ptr<AampDrmHelper> drmHelper, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP* aampInstance, MediaType streamType)
922 {
923  if (!drmHelper || !eventHandle || !aampInstance)
924  {
925  /* This should never happen, since the caller should have already
926  ensure the provided DRMInfo is supported using hasDRM */
927  AAMPLOG_ERR(" Failed to create DRM Session invalid parameters ");
928  return nullptr;
929  }
930 
931  // Mutex lock to handle createDrmSession multi-thread calls to avoid timing issues observed in AXi6 as part of DELIA-43939 during Playready-4.0 testing.
932  AampMutexHold drmSessionLock(mDrmSessionLock);
933 
934  int cdmError = -1;
935  KeyState code = KEY_ERROR;
936 
937  if (SessionMgrState::eSESSIONMGR_INACTIVE == sessionMgrState)
938  {
939  AAMPLOG_ERR(" SessionManager state inactive, aborting request");
940  return nullptr;
941  }
942 
943  int selectedSlot = INVALID_SESSION_SLOT;
944 
945  AAMPLOG_INFO("StreamType :%d keySystem is %s",streamType, drmHelper->ocdmSystemId().c_str());
946 
947  /**
948  * Create drm session without primaryKeyId markup OR retrieve old DRM session.
949  */
950  code = getDrmSession(drmHelper, selectedSlot, eventHandle, aampInstance);
951 
952  /**
953  * KEY_READY code indicates that a previously created session is being reused.
954  */
955  if (code == KEY_READY)
956  {
957  return drmSessionContexts[selectedSlot].drmSession;
958  }
959 
960  if ((code != KEY_INIT) || (selectedSlot == INVALID_SESSION_SLOT))
961  {
962  AAMPLOG_WARN(" Unable to get DrmSession : Key State %d ", code);
963  return nullptr;
964  }
965 
966  std::vector<uint8_t> keyId;
967  drmHelper->getKey(keyId);
968  bool RuntimeDRMConfigSupported = aampInstance->mConfig->IsConfigSet(eAAMPConfig_RuntimeDRMConfig);
969  if(RuntimeDRMConfigSupported && aampInstance->IsEventListenerAvailable(AAMP_EVENT_CONTENT_PROTECTION_DATA_UPDATE) && (streamType < 4))
970  {
971  aampInstance->mcurrent_keyIdArray = keyId;
972  AAMPLOG_INFO("App registered the ContentProtectionDataEvent to send new drm config");
973  ContentProtectionDataUpdate(aampInstance, keyId, streamType);
974  aampInstance->mcurrent_keyIdArray.clear();
975  }
976 
977  code = initializeDrmSession(drmHelper, selectedSlot, eventHandle, aampInstance);
978  if (code != KEY_INIT)
979  {
980  AAMPLOG_WARN(" Unable to initialize DrmSession : Key State %d ", code);
981  AampMutexHold keymutex(cachedKeyMutex);
982  cachedKeyIDs[selectedSlot].isFailedKeyId = true;
983  return nullptr;
984  }
985 
986  if(aampInstance->mIsFakeTune)
987  {
988  AAMPLOG(mLogObj, eLOGLEVEL_FATAL, "FATAL", "Exiting fake tune after DRM initialization.");
989  AampMutexHold keymutex(cachedKeyMutex);
990  cachedKeyIDs[selectedSlot].isFailedKeyId = true;
991  return nullptr;
992  }
993 
994  code = acquireLicense(drmHelper, selectedSlot, cdmError, eventHandle, aampInstance, streamType);
995  if (code != KEY_READY)
996  {
997  AAMPLOG_WARN(" Unable to get Ready Status DrmSession : Key State %d ", code);
998  AampMutexHold keymutex(cachedKeyMutex);
999  cachedKeyIDs[selectedSlot].isFailedKeyId = true;
1000  return nullptr;
1001  }
1002 
1003 #ifdef USE_SECMANAGER
1004  // License acquisition was done, so mSessionId will be populated now
1005  if (mSessionId != AAMP_SECMGR_INVALID_SESSION_ID)
1006  {
1007  AAMPLOG_WARN(" Setting sessionId[%" PRId64 "] to current drmSession", mSessionId);
1008  drmSessionContexts[selectedSlot].drmSession->setSessionId(mSessionId);
1009  }
1010 #endif
1011 
1012  return drmSessionContexts[selectedSlot].drmSession;
1013 }
1014 
1015 /**
1016  * @brief Create a DRM Session using the Drm Helper
1017  * Determine a slot in the drmSession Contexts which can be used
1018  */
1019 KeyState AampDRMSessionManager::getDrmSession(std::shared_ptr<AampDrmHelper> drmHelper, int &selectedSlot, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP* aampInstance, bool isPrimarySession)
1020 {
1021  KeyState code = KEY_ERROR;
1022  bool keySlotFound = false;
1023  bool isCachedKeyId = false;
1024  unsigned char *keyId = NULL;
1025 
1026  std::vector<uint8_t> keyIdArray;
1027  std::map<int, std::vector<uint8_t>> keyIdArrays;
1028  drmHelper->getKeys(keyIdArrays);
1029 
1030  drmHelper->getKey(keyIdArray);
1031 
1032  //Need to Check , Are all Drm Schemes/Helpers capable of providing a non zero keyId?
1033  if (keyIdArray.empty())
1034  {
1035  eventHandle->setFailure(AAMP_TUNE_FAILED_TO_GET_KEYID);
1036  return code;
1037  }
1038 
1039  if (keyIdArrays.empty())
1040  {
1041  // Insert keyId into map
1042  keyIdArrays[0] = keyIdArray;
1043  }
1044 
1045  std::string keyIdDebugStr = AampLogManager::getHexDebugStr(keyIdArray);
1046 
1047  /* Slot Selection
1048  * Find drmSession slot by going through cached keyIds
1049  * Check if requested keyId is already cached
1050  */
1051  int sessionSlot = 0;
1052 
1053  {
1054  AampMutexHold keymutex(cachedKeyMutex);
1055 
1056  for (; sessionSlot < mMaxDRMSessions; sessionSlot++)
1057  {
1058  auto keyIDSlot = cachedKeyIDs[sessionSlot].data;
1059  if (!keyIDSlot.empty() && keyIDSlot.end() != std::find(keyIDSlot.begin(), keyIDSlot.end(), keyIdArray))
1060  {
1061  AAMPLOG_INFO("Session created/inprogress with same keyID %s at slot %d", keyIdDebugStr.c_str(), sessionSlot);
1062  keySlotFound = true;
1063  isCachedKeyId = true;
1064  break;
1065  }
1066  }
1067 
1068  if (!keySlotFound)
1069  {
1070  /* Key Id not in cached list so we need to find out oldest slot to use;
1071  * Oldest slot may be used by current playback which is marked primary
1072  * Avoid selecting that slot
1073  * */
1074  /*select the first slot that is not primary*/
1075  for (int index = 0; index < mMaxDRMSessions; index++)
1076  {
1077  if (!cachedKeyIDs[index].isPrimaryKeyId)
1078  {
1079  keySlotFound = true;
1080  sessionSlot = index;
1081  break;
1082  }
1083  }
1084 
1085  if (!keySlotFound)
1086  {
1087  AAMPLOG_WARN(" Unable to find keySlot for keyId %s ", keyIdDebugStr.c_str());
1088  return KEY_ERROR;
1089  }
1090 
1091  /*Check if there's an older slot */
1092  for (int index= sessionSlot + 1; index< mMaxDRMSessions; index++)
1093  {
1094  if (cachedKeyIDs[index].creationTime < cachedKeyIDs[sessionSlot].creationTime)
1095  {
1096  sessionSlot = index;
1097  }
1098  }
1099  AAMPLOG_WARN(" Selected slot %d for keyId %s", sessionSlot, keyIdDebugStr.c_str());
1100  }
1101  else
1102  {
1103  // Already same session Slot is marked failed , not to proceed again .
1104  if(cachedKeyIDs[sessionSlot].isFailedKeyId)
1105  {
1106  AAMPLOG_WARN(" Found FailedKeyId at sesssionSlot :%d, return key error",sessionSlot);
1107  return KEY_ERROR;
1108  }
1109  }
1110 
1111 
1112  if (!isCachedKeyId)
1113  {
1114  if(cachedKeyIDs[sessionSlot].data.size() != 0)
1115  {
1116  cachedKeyIDs[sessionSlot].data.clear();
1117  }
1118  cachedKeyIDs[sessionSlot].isFailedKeyId = false;
1119 
1120  std::vector<std::vector<uint8_t>> data;
1121  for(auto& keyId : keyIdArrays)
1122  {
1123  std::string debugStr = AampLogManager::getHexDebugStr(keyId.second);
1124  AAMPLOG_INFO("Insert[%d] - slot:%d keyID %s", keyId.first, sessionSlot, debugStr.c_str());
1125  data.push_back(keyId.second);
1126  }
1127 
1128  cachedKeyIDs[sessionSlot].data = data;
1129  }
1130  cachedKeyIDs[sessionSlot].creationTime = aamp_GetCurrentTimeMS();
1131  cachedKeyIDs[sessionSlot].isPrimaryKeyId = isPrimarySession;
1132  }
1133 
1134  selectedSlot = sessionSlot;
1135  const std::string systemId = drmHelper->ocdmSystemId();
1136  AampMutexHold sessionMutex(drmSessionContexts[sessionSlot].sessionMutex);
1137  if (drmSessionContexts[sessionSlot].drmSession != NULL)
1138  {
1139  if (drmHelper->ocdmSystemId() != drmSessionContexts[sessionSlot].drmSession->getKeySystem())
1140  {
1141  AAMPLOG_WARN("changing DRM session for %s to %s", drmSessionContexts[sessionSlot].drmSession->getKeySystem().c_str(), drmHelper->ocdmSystemId().c_str());
1142  }
1143  else if (cachedKeyIDs[sessionSlot].data.end() != std::find(cachedKeyIDs[sessionSlot].data.begin(), cachedKeyIDs[sessionSlot].data.end() ,drmSessionContexts[sessionSlot].data))
1144  {
1145  KeyState existingState = drmSessionContexts[sessionSlot].drmSession->getState();
1146  if (existingState == KEY_READY)
1147  {
1148  AAMPLOG_WARN("Found drm session READY with same keyID %s - Reusing drm session", keyIdDebugStr.c_str());
1149 #ifdef USE_SECMANAGER
1150  // Cached session is re-used, set its session ID to active.
1151  // State management will be done from getLicenseSec function in case of KEY_INIT
1152  if (drmSessionContexts[sessionSlot].drmSession->getSessionId() != AAMP_SECMGR_INVALID_SESSION_ID &&
1153  mSessionId == AAMP_SECMGR_INVALID_SESSION_ID)
1154  {
1155  // Set the drmSession's ID as mSessionId so that this code will not be repeated for multiple calls for createDrmSession
1156  mSessionId = drmSessionContexts[sessionSlot].drmSession->getSessionId();
1157  AampSecManager::GetInstance()->UpdateSessionState(drmSessionContexts[sessionSlot].drmSession->getSessionId(), true);
1158  }
1159 #endif
1160  return KEY_READY;
1161  }
1162  if (existingState == KEY_INIT)
1163  {
1164  AAMPLOG_WARN("Found drm session in INIT state with same keyID %s - Reusing drm session", keyIdDebugStr.c_str());
1165  return KEY_INIT;
1166  }
1167  else if (existingState <= KEY_READY)
1168  {
1169  if (drmSessionContexts[sessionSlot].drmSession->waitForState(KEY_READY, drmHelper->keyProcessTimeout()))
1170  {
1171  AAMPLOG_WARN("Waited for drm session READY with same keyID %s - Reusing drm session", keyIdDebugStr.c_str());
1172  return KEY_READY;
1173  }
1174  AAMPLOG_WARN("key was never ready for %s ", drmSessionContexts[sessionSlot].drmSession->getKeySystem().c_str());
1175  cachedKeyIDs[selectedSlot].isFailedKeyId = true;
1176  return KEY_ERROR;
1177  }
1178  else
1179  {
1180  AAMPLOG_WARN("existing DRM session for %s has error state %d", drmSessionContexts[sessionSlot].drmSession->getKeySystem().c_str(), existingState);
1181  cachedKeyIDs[selectedSlot].isFailedKeyId = true;
1182  return KEY_ERROR;
1183  }
1184  }
1185  else
1186  {
1187  AAMPLOG_WARN("existing DRM session for %s has different key in slot %d", drmSessionContexts[sessionSlot].drmSession->getKeySystem().c_str(), sessionSlot);
1188  }
1189  AAMPLOG_WARN("deleting existing DRM session for %s ", drmSessionContexts[sessionSlot].drmSession->getKeySystem().c_str());
1190 #ifdef USE_SECMANAGER
1191  // Cached session is about to be destroyed, send release to SecManager
1192  if (drmSessionContexts[sessionSlot].drmSession->getSessionId() != AAMP_SECMGR_INVALID_SESSION_ID)
1193  {
1194  AampSecManager::GetInstance()->ReleaseSession(drmSessionContexts[sessionSlot].drmSession->getSessionId());
1195  }
1196 #endif
1197  SAFE_DELETE(drmSessionContexts[sessionSlot].drmSession);
1198  }
1199 
1200  aampInstance->profiler.ProfileBegin(PROFILE_BUCKET_LA_PREPROC);
1201 
1202  drmSessionContexts[sessionSlot].drmSession = AampDrmSessionFactory::GetDrmSession(mLogObj, drmHelper, aampInstance);
1203  if (drmSessionContexts[sessionSlot].drmSession != NULL)
1204  {
1205  AAMPLOG_INFO("Created new DrmSession for DrmSystemId %s", systemId.c_str());
1206  drmSessionContexts[sessionSlot].data = keyIdArray;
1207  code = drmSessionContexts[sessionSlot].drmSession->getState();
1208  // exception : by default for all types of drm , outputprotection is not handled in player
1209  // for playready , its configured within player
1210  if (systemId == PLAYREADY_KEY_SYSTEM_STRING && aampInstance->mConfig->IsConfigSet(eAAMPConfig_EnablePROutputProtection))
1211  {
1212  drmSessionContexts[sessionSlot].drmSession->setOutputProtection(true);
1213  drmHelper->setOutputProtectionFlag(true);
1214  }
1215  }
1216  else
1217  {
1218  AAMPLOG_WARN("Unable to Get DrmSession for DrmSystemId %s", systemId.c_str());
1219  eventHandle->setFailure(AAMP_TUNE_DRM_INIT_FAILED);
1220  }
1221 
1222 #if defined(USE_OPENCDM_ADAPTER)
1223  drmSessionContexts[sessionSlot].drmSession->setKeyId(keyIdArray);
1224 #endif
1225 
1226  return code;
1227 }
1228 
1229 /**
1230  * @brief Initialize the Drm System with InitData(PSSH)
1231  */
1232 KeyState AampDRMSessionManager::initializeDrmSession(std::shared_ptr<AampDrmHelper> drmHelper, int sessionSlot, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP* aampInstance)
1233 {
1234  KeyState code = KEY_ERROR;
1235 
1236  std::vector<uint8_t> drmInitData;
1237  drmHelper->createInitData(drmInitData);
1238 
1239  AampMutexHold sessionMutex(drmSessionContexts[sessionSlot].sessionMutex);
1240  std::string customData = aampInstance->GetLicenseCustomData();
1241  AAMPLOG_INFO("DRM session Custom Data - %s ", customData.empty()?"NULL":customData.c_str());
1242  drmSessionContexts[sessionSlot].drmSession->generateAampDRMSession(drmInitData.data(), drmInitData.size(), customData);
1243 
1244  code = drmSessionContexts[sessionSlot].drmSession->getState();
1245  if (code != KEY_INIT)
1246  {
1247  AAMPLOG_ERR("DRM session was not initialized : Key State %d ", code);
1248  if (code == KEY_ERROR_EMPTY_SESSION_ID)
1249  {
1250  AAMPLOG_ERR("DRM session ID is empty: Key State %d ", code);
1251  eventHandle->setFailure(AAMP_TUNE_DRM_SESSIONID_EMPTY);
1252  }
1253  else
1254  {
1255  eventHandle->setFailure(AAMP_TUNE_DRM_DATA_BIND_FAILED);
1256  }
1257  }
1258 
1259  return code;
1260 }
1261 
1262 /**
1263  * @brief sent license challenge to the DRM server and provide the respone to CDM
1264  */
1265 KeyState AampDRMSessionManager::acquireLicense(std::shared_ptr<AampDrmHelper> drmHelper, int sessionSlot, int &cdmError,
1266  DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP* aampInstance, MediaType streamType)
1267 {
1268  shared_ptr<DrmData> licenseResponse;
1269  int32_t httpResponseCode = -1;
1270  int32_t httpExtendedStatusCode = -1;
1271  KeyState code = KEY_ERROR;
1272  if (drmHelper->isExternalLicense())
1273  {
1274  // External license, assuming the DRM system is ready to proceed
1275  code = KEY_PENDING;
1276  if(drmHelper->friendlyName().compare("Verimatrix") == 0)
1277  {
1278  licenseResponse = std::make_shared<DrmData>();
1279  drmHelper->transformLicenseResponse(licenseResponse);
1280  }
1281  aampInstance->profiler.ProfileEnd(PROFILE_BUCKET_LA_PREPROC);
1282  }
1283  else
1284  {
1285  AampMutexHold sessionMutex(drmSessionContexts[sessionSlot].sessionMutex);
1286 
1287  /**
1288  * Generate a License challenge from the CDM
1289  */
1290  AAMPLOG_INFO("Request to generate license challenge to the aampDRMSession(CDM)");
1291 
1292  AampChallengeInfo challengeInfo;
1293  challengeInfo.data.reset(drmSessionContexts[sessionSlot].drmSession->aampGenerateKeyRequest(challengeInfo.url, drmHelper->licenseGenerateTimeout()));
1294  code = drmSessionContexts[sessionSlot].drmSession->getState();
1295 
1296  if (code != KEY_PENDING)
1297  {
1298  AAMPLOG_ERR("Error in getting license challenge : Key State %d ", code);
1300  eventHandle->setFailure(AAMP_TUNE_DRM_CHALLENGE_FAILED);
1301  aampInstance->profiler.ProfileEnd(PROFILE_BUCKET_LA_PREPROC);
1302  }
1303  else
1304  {
1305  /** flag for authToken set externally by app **/
1306  bool usingAppDefinedAuthToken = !aampInstance->mSessionToken.empty();
1307  bool anonymouslicReq = aampInstance->mConfig->IsConfigSet(eAAMPConfig_AnonymousLicenseRequest);
1308  aampInstance->profiler.ProfileEnd(PROFILE_BUCKET_LA_PREPROC);
1309 
1310  if (!(drmHelper->getDrmMetaData().empty() || anonymouslicReq))
1311  {
1312  AampMutexHold accessTokenMutexHold(accessTokenMutex);
1313 
1314  int tokenLen = 0;
1315  long tokenError = 0;
1316  char *sessionToken = NULL;
1317  if(!usingAppDefinedAuthToken)
1318  { /* authToken not set externally by app */
1319  sessionToken = (char *)getAccessToken(tokenLen, tokenError , aampInstance->mConfig->IsConfigSet(eAAMPConfig_SslVerifyPeer));
1320  AAMPLOG_WARN("Access Token from AuthServer");
1321  }
1322  else
1323  {
1324  sessionToken = (char *)aampInstance->mSessionToken.c_str();
1325  tokenLen = aampInstance->mSessionToken.size();
1326  AAMPLOG_WARN("Got Access Token from External App");
1327  }
1328  if (NULL == sessionToken)
1329  {
1330  // Failed to get access token
1331  // licenseAnonymousRequest is not set, Report failure
1332  AAMPLOG_WARN("failed to get access token, Anonymous request not enabled");
1333  eventHandle->setFailure(AAMP_TUNE_FAILED_TO_GET_ACCESS_TOKEN);
1334  eventHandle->setResponseCode(tokenError);
1335  if(!licenseRequestAbort)
1336  {
1337  // report error
1338  return KEY_ERROR;
1339  }
1340  }
1341  else
1342  {
1343  AAMPLOG_INFO("access token is available");
1344  challengeInfo.accessToken = std::string(sessionToken, tokenLen);
1345  }
1346  }
1347  if(licenseRequestAbort)
1348  {
1349  AAMPLOG_ERR("Error!! License request was aborted. Resetting session slot %d", sessionSlot);
1350  eventHandle->setFailure(AAMP_TUNE_DRM_SELF_ABORT);
1351  eventHandle->setResponseCode(CURLE_ABORTED_BY_CALLBACK);
1352  return KEY_ERROR;
1353  }
1354 
1355  AampLicenseRequest licenseRequest;
1356  DRMSystems drmType = GetDrmSystem(drmHelper->getUuid());
1357  licenseRequest.url = aampInstance->GetLicenseServerUrlForDrm(drmType);
1358  licenseRequest.licenseAnonymousRequest = anonymouslicReq;
1359  drmHelper->generateLicenseRequest(challengeInfo, licenseRequest);
1360  if (code != KEY_PENDING || ((licenseRequest.method == AampLicenseRequest::POST) && (!challengeInfo.data.get())))
1361  {
1362  AAMPLOG_ERR("Error!! License challenge was not generated by the CDM : Key State %d", code);
1363  eventHandle->setFailure(AAMP_TUNE_DRM_CHALLENGE_FAILED);
1364  }
1365  else
1366  {
1367  /**
1368  * Configure the License acquisition parameters
1369  */
1370  std::string licenseServerProxy;
1371  bool isContentMetadataAvailable = configureLicenseServerParameters(drmHelper, licenseRequest, licenseServerProxy, challengeInfo, aampInstance);
1372 
1373  /**
1374  * Perform License acquistion by invoking http license request to license server
1375  */
1376  AAMPLOG_WARN("Request License from the Drm Server %s", licenseRequest.url.c_str());
1377  aampInstance->profiler.ProfileBegin(PROFILE_BUCKET_LA_NETWORK);
1378 
1379 #if defined(USE_SECCLIENT) || defined(USE_SECMANAGER)
1380  if (isContentMetadataAvailable)
1381  {
1382  eventHandle->setSecclientError(true);
1383  licenseResponse.reset(getLicenseSec(licenseRequest, drmHelper, challengeInfo, aampInstance, &httpResponseCode, &httpExtendedStatusCode, eventHandle));
1384 
1385  bool sec_accessTokenExpired = aampInstance->mConfig->IsConfigSet(eAAMPConfig_UseSecManager) && SECMANGER_DRM_FAILURE == httpResponseCode && SECMANGER_ACCTOKEN_EXPIRED == httpExtendedStatusCode;
1386  // Reload Expired access token only on http error code 412 with status code 401
1387  if (((412 == httpResponseCode && 401 == httpExtendedStatusCode) || sec_accessTokenExpired) && !usingAppDefinedAuthToken)
1388  {
1389  AAMPLOG_INFO("License Req failure by Expired access token httpResCode %d statusCode %d", httpResponseCode, httpExtendedStatusCode);
1390  if(accessToken)
1391  {
1392  free(accessToken);
1393  accessToken = NULL;
1394  accessTokenLen = 0;
1395  }
1396  int tokenLen = 0;
1397  long tokenError = 0;
1398  const char *sessionToken = getAccessToken(tokenLen, tokenError,aampInstance->mConfig->IsConfigSet(eAAMPConfig_SslVerifyPeer));
1399  if (NULL != sessionToken)
1400  {
1401  AAMPLOG_INFO("Requesting License with new access token");
1402  challengeInfo.accessToken = std::string(sessionToken, tokenLen);
1403  httpResponseCode = httpExtendedStatusCode = -1;
1404  licenseResponse.reset(getLicenseSec(licenseRequest, drmHelper, challengeInfo, aampInstance, &httpResponseCode, &httpExtendedStatusCode, eventHandle));
1405  }
1406  }
1407  }
1408  else
1409 #endif
1410  {
1411  if(usingAppDefinedAuthToken)
1412  {
1413  AAMPLOG_WARN("Ignore AuthToken Provided for non-ContentMetadata DRM license request");
1414  }
1415  eventHandle->setSecclientError(false);
1416  licenseResponse.reset(getLicense(licenseRequest, &httpResponseCode, streamType, aampInstance, isContentMetadataAvailable, licenseServerProxy));
1417  }
1418 
1419  }
1420  }
1421  }
1422 
1423  if (code == KEY_PENDING)
1424  {
1425  code = handleLicenseResponse(drmHelper, sessionSlot, cdmError, httpResponseCode, httpExtendedStatusCode, licenseResponse, eventHandle, aampInstance);
1426  }
1427 
1428  return code;
1429 }
1430 
1431 
1432 KeyState AampDRMSessionManager::handleLicenseResponse(std::shared_ptr<AampDrmHelper> drmHelper, int sessionSlot, int &cdmError, int32_t httpResponseCode, int32_t httpExtendedStatusCode, shared_ptr<DrmData> licenseResponse, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP* aamp)
1433 {
1434  if (!drmHelper->isExternalLicense())
1435  {
1436  if ((licenseResponse != NULL) && (licenseResponse->getDataLength() != 0))
1437  {
1438  aamp->profiler.ProfileEnd(PROFILE_BUCKET_LA_NETWORK);
1439 
1440 #if !defined(USE_SECCLIENT) && !defined(USE_SECMANAGER)
1441  if (!drmHelper->getDrmMetaData().empty())
1442  {
1443  /*
1444  Licence response from MDS server is in JSON form
1445  Licence to decrypt the data can be found by extracting the contents for JSON key licence
1446  Format : {"licence":"b64encoded licence","accessAttributes":"0"}
1447  */
1448  string jsonStr(licenseResponse->getData().c_str(), licenseResponse->getDataLength());
1449 
1450  try
1451  {
1452  AampJsonObject jsonObj(jsonStr);
1453 
1454  std::vector<uint8_t> keyData;
1455  if (!jsonObj.get(LICENCE_RESPONSE_JSON_LICENCE_KEY, keyData, AampJsonObject::ENCODING_BASE64))
1456  {
1457  AAMPLOG_WARN("Unable to retrieve license from JSON response", jsonStr.c_str());
1458  }
1459  else
1460  {
1461  licenseResponse = make_shared<DrmData>(keyData.data(), keyData.size());
1462  }
1463  }
1464  catch (AampJsonParseException& e)
1465  {
1466  AAMPLOG_WARN("Failed to parse JSON response", jsonStr.c_str());
1467  }
1468  }
1469 #endif
1470  AAMPLOG_INFO("license acquisition completed");
1471  drmHelper->transformLicenseResponse(licenseResponse);
1472  }
1473  else
1474  {
1475  aamp->profiler.ProfileError(PROFILE_BUCKET_LA_NETWORK, httpResponseCode);
1476  aamp->profiler.ProfileEnd(PROFILE_BUCKET_LA_NETWORK);
1477 
1478  AAMPLOG_ERR("Error!! Invalid License Response was provided by the Server");
1479 
1480  bool SecAuthFailure = false, SecTimeout = false;
1481 
1482  //Handle secmaanger specific error codes here
1484  {
1485  //The documentation for secmanager error codes are here
1486  //https://etwiki.sys.comcast.net/pages/viewpage.action?spaceKey=RDKV&title=AAMP+-+SecManagerApi
1487  eventHandle->setResponseCode(httpResponseCode);
1488  eventHandle->setSecManagerReasonCode(httpExtendedStatusCode);
1489  if(SECMANGER_DRM_FAILURE == httpResponseCode && SECMANGER_ENTITLEMENT_FAILURE == httpExtendedStatusCode)
1490  {
1491  if (eventHandle->getFailure() != AAMP_TUNE_FAILED_TO_GET_ACCESS_TOKEN)
1492  {
1493  eventHandle->setFailure(AAMP_TUNE_AUTHORISATION_FAILURE);
1494  }
1495  AAMPLOG_WARN("DRM session for %s, Authorisation failed", drmSessionContexts[sessionSlot].drmSession->getKeySystem().c_str());
1496  }
1497  else if(SECMANGER_DRM_FAILURE == httpResponseCode && SECMANGER_SERVICE_TIMEOUT == httpExtendedStatusCode)
1498  {
1499  eventHandle->setFailure(AAMP_TUNE_LICENCE_TIMEOUT);
1500  }
1501  else
1502  {
1503  eventHandle->setFailure(AAMP_TUNE_LICENCE_REQUEST_FAILED);
1504  }
1505  }
1506  else if (412 == httpResponseCode)
1507  {
1508  if (eventHandle->getFailure() != AAMP_TUNE_FAILED_TO_GET_ACCESS_TOKEN)
1509  {
1510  eventHandle->setFailure(AAMP_TUNE_AUTHORISATION_FAILURE);
1511  }
1512  AAMPLOG_WARN("DRM session for %s, Authorisation failed", drmSessionContexts[sessionSlot].drmSession->getKeySystem().c_str());
1513 
1514  }
1515  else if (CURLE_OPERATION_TIMEDOUT == httpResponseCode)
1516  {
1517  eventHandle->setFailure(AAMP_TUNE_LICENCE_TIMEOUT);
1518  }
1519  else if(CURLE_ABORTED_BY_CALLBACK == httpResponseCode || CURLE_WRITE_ERROR == httpResponseCode)
1520  {
1521  // Set failure reason as AAMP_TUNE_DRM_SELF_ABORT to avoid unnecessary error reporting.
1522  eventHandle->setFailure(AAMP_TUNE_DRM_SELF_ABORT);
1523  eventHandle->setResponseCode(httpResponseCode);
1524  }
1525  else
1526  {
1527  eventHandle->setFailure(AAMP_TUNE_LICENCE_REQUEST_FAILED);
1528  eventHandle->setResponseCode(httpResponseCode);
1529  }
1530  return KEY_ERROR;
1531  }
1532  }
1533 
1534  return processLicenseResponse(drmHelper, sessionSlot, cdmError, licenseResponse, eventHandle, aamp);
1535 }
1536 
1537 
1538 KeyState AampDRMSessionManager::processLicenseResponse(std::shared_ptr<AampDrmHelper> drmHelper, int sessionSlot, int &cdmError,
1539  shared_ptr<DrmData> licenseResponse, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP* aampInstance)
1540 {
1541  /**
1542  * Provide the acquired License response from the DRM license server to the CDM.
1543  * For DRMs with external license acquisition, we will provide a NULL response
1544  * for processing and the DRM session should await the key from the DRM implementation
1545  */
1546  AAMPLOG_INFO("Updating the license response to the aampDRMSession(CDM)");
1547  aampInstance->profiler.ProfileBegin(PROFILE_BUCKET_LA_POSTPROC);
1548  cdmError = drmSessionContexts[sessionSlot].drmSession->aampDRMProcessKey(licenseResponse.get(), drmHelper->keyProcessTimeout());
1549 
1550  aampInstance->profiler.ProfileEnd(PROFILE_BUCKET_LA_POSTPROC);
1551 
1552 
1553  KeyState code = drmSessionContexts[sessionSlot].drmSession->getState();
1554 
1555  if (code == KEY_ERROR)
1556  {
1557  if (AAMP_TUNE_FAILURE_UNKNOWN == eventHandle->getFailure())
1558  {
1559  // check if key failure is due to HDCP , if so report it appropriately instead of Failed to get keys
1560  if (cdmError == HDCP_OUTPUT_PROTECTION_FAILURE || cdmError == HDCP_COMPLIANCE_CHECK_FAILURE)
1561  {
1562  eventHandle->setFailure(AAMP_TUNE_HDCP_COMPLIANCE_ERROR);
1563  }
1564  else
1565  {
1566  eventHandle->setFailure(AAMP_TUNE_DRM_KEY_UPDATE_FAILED);
1567  }
1568  }
1569  }
1570  else if (code == KEY_PENDING)
1571  {
1572  AAMPLOG_ERR(" Failed to get DRM keys");
1573  if (AAMP_TUNE_FAILURE_UNKNOWN == eventHandle->getFailure())
1574  {
1575  eventHandle->setFailure(AAMP_TUNE_INVALID_DRM_KEY);
1576  }
1577  }
1578 
1579  return code;
1580 }
1581 
1582 /**
1583  * @brief Configure the Drm license server parameters for URL/proxy and custom http request headers
1584  */
1585 bool AampDRMSessionManager::configureLicenseServerParameters(std::shared_ptr<AampDrmHelper> drmHelper, AampLicenseRequest &licenseRequest,
1586  std::string &licenseServerProxy, const AampChallengeInfo& challengeInfo, PrivateInstanceAAMP* aampInstance)
1587 {
1588  string contentMetaData = drmHelper->getDrmMetaData();
1589  bool isContentMetadataAvailable = !contentMetaData.empty();
1590 
1591  if (!contentMetaData.empty())
1592  {
1593  if (!licenseRequest.url.empty())
1594  {
1595 #if defined(USE_SECCLIENT) || defined(USE_SECMANAGER)
1596  licenseRequest.url = getFormattedLicenseServerURL(licenseRequest.url);
1597 #endif
1598  }
1599  }
1600 
1601  // 1. Add any custom License Headers for with and without ContentMetadata license request
1602  // 2. In addition for ContentMetadata license, add additional headers if present
1603  {
1604  std::unordered_map<std::string, std::vector<std::string>> customHeaders;
1605  aampInstance->GetCustomLicenseHeaders(customHeaders);
1606 
1607  if (!customHeaders.empty())
1608  {
1609  // Override headers from the helper with custom headers
1610  licenseRequest.headers = customHeaders;
1611  }
1612 
1613  if (isContentMetadataAvailable)
1614  {
1615  std::string customData;
1616  if (customHeaders.empty())
1617  {
1618  // Not using custom headers, These headers will also override any headers from the helper
1619  licenseRequest.headers.clear();
1620  }
1621  // read License request Headers
1622  aampInstance->mConfig->GetConfigValue(eAAMPConfig_LRHAcceptValue,customData);
1623  if (!customData.empty())
1624  {
1625  licenseRequest.headers.insert({LICENCE_REQUEST_HEADER_ACCEPT, {customData.c_str()}});
1626  }
1627 
1628  // read license request content type
1629  aampInstance->mConfig->GetConfigValue(eAAMPConfig_LRHContentType,customData);
1630  if (!customData.empty())
1631  {
1632  licenseRequest.headers.insert({LICENCE_REQUEST_HEADER_CONTENT_TYPE, {customData.c_str()}});
1633  }
1634  }
1635  // license Server Proxy need to be applied for both request , with and without contentMetadata
1636  licenseServerProxy = aampInstance->GetLicenseReqProxy();
1637  }
1638 
1639  return isContentMetadataAvailable;
1640 }
1641 
1642 /**
1643  * @brief Resethe current seesion ID
1644  */
1646 {
1647 #ifdef USE_SECMANAGER
1648  if(AAMP_SECMGR_INVALID_SESSION_ID != mSessionId)
1649  {
1650  // Set current session to inactive
1651  AampSecManager::GetInstance()->UpdateSessionState(mSessionId, false);
1652  // Reset the session ID, the session ID is preserved within AampDrmSession instances
1653  mSessionId = AAMP_SECMGR_INVALID_SESSION_ID;
1654  }
1655 #endif
1656 }
1657 
1658 void AampDRMSessionManager::ContentProtectionDataUpdate(PrivateInstanceAAMP* aampInstance, std::vector<uint8_t> keyId, MediaType streamType)
1659 {
1660  std::string contentType = sessionTypeName[streamType];
1661  int iter1 = 0;
1662  bool DRM_Config_Available = false;
1663 
1664  while (iter1 < aampInstance->vDynamicDrmData.size())
1665  {
1666  DynamicDrmInfo dynamicDrmCache = aampInstance->vDynamicDrmData.at(iter1);
1667  if(keyId == dynamicDrmCache.keyID)
1668  {
1669  AAMPLOG_WARN("DrmConfig already present in cached data in slot : %d applying config",iter1);
1670  std::map<std::string,std::string>::iterator itr;
1671  for(itr = dynamicDrmCache.licenseEndPoint.begin();itr!=dynamicDrmCache.licenseEndPoint.end();itr++)
1672  {
1673  if(strcasecmp("com.microsoft.playready",itr->first.c_str())==0)
1674  {
1675  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_PRLicenseServerUrl,itr->second);
1676  }
1677  if(strcasecmp("com.widevine.alpha",itr->first.c_str())==0)
1678  {
1679  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_WVLicenseServerUrl,itr->second);
1680  }
1681  if(strcasecmp("org.w3.clearkey",itr->first.c_str())==0)
1682  {
1683  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_CKLicenseServerUrl,itr->second);
1684  }
1685  }
1686  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_AuthToken,dynamicDrmCache.authToken);
1687  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_CustomLicenseData,dynamicDrmCache.customData);
1688  DRM_Config_Available = true;
1689  break;
1690  }
1691  iter1++;
1692  }
1693  if(!DRM_Config_Available) {
1694  ContentProtectionDataEventPtr eventData = std::make_shared<ContentProtectionDataEvent>(keyId, contentType);
1695  std::string keyIdDebugStr = AampLogManager::getHexDebugStr(keyId);
1696  pthread_mutex_lock(&aampInstance->mDynamicDrmUpdateLock);
1697  int pthreadReturnValue = 0;
1698  struct timespec ts;
1699  int drmUpdateTimeout;
1700  aampInstance->mConfig->GetConfigValue(eAAMPConfig_ContentProtectionDataUpdateTimeout, drmUpdateTimeout);
1701  AAMPLOG_WARN("Timeout Wait for DRM config message from application :%d",drmUpdateTimeout);
1702  ts = aamp_GetTimespec(drmUpdateTimeout); /** max delay to update dynamic drm on key rotation **/
1703  AAMPLOG_INFO("Found new KeyId %s and not in drm config cache, sending ContentProtectionDataEvent to App", keyIdDebugStr.c_str());
1704  aampInstance->SendEvent(eventData);
1705  pthreadReturnValue = pthread_cond_timedwait(&aampInstance->mWaitForDynamicDRMToUpdate, &aampInstance->mDynamicDrmUpdateLock, &ts);
1706  if (ETIMEDOUT == pthreadReturnValue)
1707  {
1708  AAMPLOG_WARN("pthread_cond_timedwait returned TIMEOUT, Applying Default config");
1709  DynamicDrmInfo dynamicDrmCache = aampInstance->mDynamicDrmDefaultconfig;
1710  std::map<std::string,std::string>::iterator itr;
1711  for(itr = dynamicDrmCache.licenseEndPoint.begin();itr!=dynamicDrmCache.licenseEndPoint.end();itr++) {
1712  if(strcasecmp("com.microsoft.playready",itr->first.c_str())==0) {
1713  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_PRLicenseServerUrl,itr->second);
1714  }
1715  if(strcasecmp("com.widevine.alpha",itr->first.c_str())==0) {
1716  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_WVLicenseServerUrl,itr->second);
1717  }
1718  if(strcasecmp("org.w3.clearkey",itr->first.c_str())==0) {
1719  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_CKLicenseServerUrl,itr->second);
1720  }
1721  }
1722  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_AuthToken,dynamicDrmCache.authToken);
1723  aampInstance->mConfig->SetConfigValue(AAMP_APPLICATION_SETTING,eAAMPConfig_CustomLicenseData,dynamicDrmCache.customData);
1724  }
1725  else if (0 != pthreadReturnValue)
1726  {
1727  AAMPLOG_WARN("pthread_cond_timedwait returned %s ", strerror(pthreadReturnValue));
1728  }
1729  else{
1730  AAMPLOG_WARN("%s:%d [WARN] pthread_cond_timedwait(dynamicDrmUpdate) returned success!", __FUNCTION__, __LINE__);
1731  }
1732  pthread_mutex_unlock(&aampInstance->mDynamicDrmUpdateLock);
1733  }
1734 }
1735 
1736 /**
1737  * @brief Function to release the DrmSession if it running
1738  * @param[out] aamp private aamp instance
1739  * @return None.
1740  */
1742 
1743  if(aamp->drmSessionThreadStarted) //In the case of license rotation
1744  {
1745  void *value_ptr = NULL;
1746  int rc = pthread_join(aamp->createDRMSessionThreadID, &value_ptr);
1747  if (rc != 0)
1748  {
1749  AAMPLOG_WARN("pthread_join returned %d for createDRMSession Thread",
1750  rc);
1751  }
1752  aamp->drmSessionThreadStarted = false;
1753  AAMPLOG_WARN("DRMSession Thread Released");
1754  }
1755 }
1756 
1757 /**
1758  * @brief Function to spawn the DrmSession Thread based on the
1759  * preferred drm set.
1760  * @param[out] drmData private aamp instance
1761  * @return None.
1762  */
1764 {
1765  int iState = DRM_API_FAILED;
1766  do{
1767 
1768  /** API protection added **/
1769  if (NULL == drmData){
1770  AAMPLOG_ERR("Could not able to process with the NULL Drm data"
1771  );
1772  break;
1773  }
1774  /** Achieve single thread logic for DRM Session Creation **/
1776  AAMPLOG_INFO("Creating thread with sessionData = 0x%08x",
1777  drmData->sessionData );
1778  if(0 == pthread_create(&aamp->createDRMSessionThreadID, NULL,\
1779  CreateDRMSession, drmData->sessionData))
1780  {
1781  drmData->isProcessedLicenseAcquire = true;
1782  aamp->drmSessionThreadStarted = true;
1783  aamp->setCurrentDrm(drmData->sessionData->drmHelper);
1784  iState = DRM_API_SUCCESS;
1785  }
1786  else
1787  {
1788  AAMPLOG_ERR("pthread_create failed for CreateDRMSession : error code %d, %s",
1789  errno, strerror(errno));
1790  }
1791  }while(0);
1792 
1793  return iState;
1794 }
1795 
1796 /**
1797  * @brief Thread function to create DRM Session which would be invoked in thread from
1798  * HLS , PlayReady or from pipeline
1799  *
1800  * @param[out] arg - DrmSessionParams structure with filled data
1801  * @return None.
1802  */
1803 void *CreateDRMSession(void *arg)
1804 {
1805  if(aamp_pthread_setname(pthread_self(), "aampfMP4DRM"))
1806  {
1807  AAMPLOG_ERR("aamp_pthread_setname failed");
1808  }
1809  struct DrmSessionParams* sessionParams = (struct DrmSessionParams*)arg;
1810 
1811  if(sessionParams == nullptr) {
1812  AAMPLOG_ERR("sessionParams is null");
1813  return nullptr;
1814  }
1815  if(sessionParams->aamp == nullptr) {
1816  AAMPLOG_ERR("no aamp in sessionParams");
1817  return nullptr;
1818  } //CID:144411 - Reverse_inull
1819  AampDRMSessionManager* sessionManger = sessionParams->aamp->mDRMSessionManager;
1820 #if defined(USE_SECCLIENT) || defined(USE_SECMANAGER)
1821  bool isSecClientError = true;
1822 #else
1823  bool isSecClientError = false;
1824 #endif
1825 
1826  sessionParams->aamp->profiler.ProfileBegin(PROFILE_BUCKET_LA_TOTAL);
1827 
1828  DrmMetaDataEventPtr e = std::make_shared<DrmMetaDataEvent>(AAMP_TUNE_FAILURE_UNKNOWN, "", 0, 0, isSecClientError);
1829 
1830  AampDrmSession *drmSession = NULL;
1831  const char * systemId;
1832 
1833  if (sessionParams->aamp == nullptr) {
1834  AAMPLOG_ERR("no aamp in sessionParams");
1835  return nullptr;
1836  }
1837 
1838  if (sessionParams->aamp->mDRMSessionManager == nullptr) {
1839  AAMPLOG_ERR("no aamp->mDrmSessionManager in sessionParams");
1840  return nullptr;
1841  }
1842 
1843 
1844  if (sessionParams->drmHelper == nullptr)
1845  {
1846  AAMPTuneFailure failure = e->getFailure();
1847  AAMPLOG_ERR("Failed DRM Session Creation, no helper");
1848 
1849  sessionParams->aamp->SendDrmErrorEvent(e, false);
1850  sessionParams->aamp->profiler.SetDrmErrorCode((int)failure);
1851  sessionParams->aamp->profiler.ProfileError(PROFILE_BUCKET_LA_TOTAL, (int)failure);
1852  sessionParams->aamp->profiler.ProfileEnd(PROFILE_BUCKET_LA_TOTAL);
1853  }
1854  else
1855  {
1856  std::vector<uint8_t> data;
1857  systemId = sessionParams->drmHelper->getUuid().c_str();
1858  sessionParams->drmHelper->createInitData(data);
1859  sessionParams->aamp->mStreamSink->QueueProtectionEvent(systemId, data.data(), data.size(), sessionParams->stream_type);
1860  drmSession = sessionManger->createDrmSession(sessionParams->drmHelper, e, sessionParams->aamp, sessionParams->stream_type);
1861 
1862  if(NULL == drmSession)
1863  {
1864  AAMPLOG_ERR("Failed DRM Session Creation for systemId = %s", systemId);
1865  AAMPTuneFailure failure = e->getFailure();
1866  long responseCode = e->getResponseCode();
1867  bool selfAbort = (failure == AAMP_TUNE_DRM_SELF_ABORT);
1868  if (!selfAbort)
1869  {
1870  bool isRetryEnabled = (failure != AAMP_TUNE_AUTHORISATION_FAILURE)
1871  && (failure != AAMP_TUNE_LICENCE_REQUEST_FAILED)
1872  && (failure != AAMP_TUNE_LICENCE_TIMEOUT)
1873  && (failure != AAMP_TUNE_DEVICE_NOT_PROVISIONED)
1874  && (failure != AAMP_TUNE_HDCP_COMPLIANCE_ERROR);
1875  sessionParams->aamp->SendDrmErrorEvent(e, isRetryEnabled);
1876  }
1877  sessionParams->aamp->profiler.SetDrmErrorCode((int) failure);
1878  sessionParams->aamp->profiler.ProfileError(PROFILE_BUCKET_LA_TOTAL, (int) failure);
1879  sessionParams->aamp->profiler.ProfileEnd(PROFILE_BUCKET_LA_TOTAL);
1880  }
1881 
1882  else
1883  {
1884  if(e->getAccessStatusValue() != 3)
1885  {
1886  AAMPLOG_INFO("Sending DRMMetaData");
1887  sessionParams->aamp->SendDRMMetaData(e);
1888  }
1889  sessionParams->aamp->profiler.ProfileEnd(PROFILE_BUCKET_LA_TOTAL);
1890  }
1891  }
1892  if(sessionParams->aamp->mIsFakeTune)
1893  {
1894  sessionParams->aamp->SetState(eSTATE_COMPLETE);
1895  sessionParams->aamp->SendEvent(std::make_shared<AAMPEventObject>(AAMP_EVENT_EOS));
1896  }
1897  return NULL;
1898 }
1899 
1900 
AampDRMSessionManager.h
Header file for DRM session manager.
AampDRMSessionManager::getDrmSession
KeyState getDrmSession(std::shared_ptr< AampDrmHelper > drmHelper, int &selectedSlot, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP *aampInstance, bool isPrimarySession=false)
Create a DRM Session using the Drm Helper Determine a slot in the drmSession Contexts which can be us...
Definition: AampDRMSessionManager.cpp:1019
AampDrmSessionFactory::GetDrmSession
static AampDrmSession * GetDrmSession(AampLogManager *logObj, std::shared_ptr< AampDrmHelper > drmHelper, AampDrmCallbacks *drmCallbacks)
Creates an appropriate DRM session based on the given DrmHelper.
Definition: aampdrmsessionfactory.cpp:41
AampRfc.h
Aamp RFC header files.
PrivateInstanceAAMP::GetLicenseServerUrlForDrm
std::string GetLicenseServerUrlForDrm(DRMSystems type)
Get license server url for a drm type.
Definition: priv_aamp.cpp:9950
AampLogManager::trace
bool trace
Definition: AampLogManager.h:156
AampDRMSessionManager::AampDRMSessionManager
AampDRMSessionManager(const AampDRMSessionManager &)=delete
Copy constructor disabled.
eAAMPConfig_CurlLicenseLogging
@ eAAMPConfig_CurlLicenseLogging
Definition: AampConfig.h:144
_extractSubstring
string _extractSubstring(string parentStr, string startStr, string endStr)
Extract substring between (excluding) two string delimiters.
Definition: AampDRMSessionManager.cpp:369
AampConfig::logging
AampLogManager logging
Definition: AampConfig.h:462
PrivateInstanceAAMP::setCurrentDrm
void setCurrentDrm(std::shared_ptr< AampDrmHelper > drm)
Set DRM type.
Definition: priv_aamp.h:2484
eAAMPConfig_LicenseRetryWaitTime
@ eAAMPConfig_LicenseRetryWaitTime
Definition: AampConfig.h:227
AampDrmHelper.h
Implented DRM helper functionalities.
DrmData::addData
void addData(unsigned char *data, int dataLength)
Appends DrmData with given data.
Definition: AampDRMutils.cpp:103
DrmSessionDataInfo::isProcessedLicenseAcquire
bool isProcessedLicenseAcquire
Definition: AampDRMSessionManager.h:60
AampConfig::SetConfigValue
void SetConfigValue(ConfigPriority owner, AAMPConfigSettings cfg, const T &value)
SetConfigValue - Set function to set bool/int/long data type configuration.
Definition: AampConfig.cpp:830
AampDRMSessionManager::createDrmSession
AampDrmSession * createDrmSession(const char *systemId, MediaFormat mediaFormat, const unsigned char *initDataPtr, uint16_t dataLength, MediaType streamType, PrivateInstanceAAMP *aamp, DrmMetaDataEventPtr e, const unsigned char *contentMetadata=nullptr, bool isPrimarySession=false)
Creates and/or returns the DRM session corresponding to keyId (Present in initDataPtr) AampDRMSession...
Definition: AampDRMSessionManager.cpp:875
AampJsonParseException
Handles the exception for JSON parser.
Definition: AampJsonObject.h:252
eAAMPConfig_WVLicenseServerUrl
@ eAAMPConfig_WVLicenseServerUrl
Definition: AampConfig.h:300
AampDrmHelperEngine::getInstance
static AampDrmHelperEngine & getInstance()
Get an instance of the DRM Helper Engine.
Definition: AampDrmHelperFactory.cpp:37
SpawnDRMLicenseAcquireThread
int SpawnDRMLicenseAcquireThread(PrivateInstanceAAMP *aamp, DrmSessionDataInfo *drmData)
Function to spawn the DrmSession Thread based on the preferred drm set.
Definition: AampDRMSessionManager.cpp:1763
DrmSessionDataInfo
Drm Session Data Information for storing in a pool from parser.
Definition: AampDRMSessionManager.h:58
DrmData
To hold DRM key, license request etc.
Definition: AampDrmData.h:32
AampSecManager::ReleaseSession
void ReleaseSession(int64_t sessionId)
To notify SecManager to release a session.
Definition: AampSecManager.cpp:354
DrmSessionParams
Holds data regarding drm session.
Definition: AampDRMSessionManager.h:101
AAMP_TUNE_LICENCE_TIMEOUT
@ AAMP_TUNE_LICENCE_TIMEOUT
Definition: AampEvent.h:126
AAMP_TUNE_DRM_SELF_ABORT
@ AAMP_TUNE_DRM_SELF_ABORT
Definition: AampEvent.h:137
AampDRMSessionManager::setSessionMgrState
void setSessionMgrState(SessionMgrState state)
Set Session manager state.
Definition: AampDRMSessionManager.cpp:183
AAMP_TUNE_DRM_CHALLENGE_FAILED
@ AAMP_TUNE_DRM_CHALLENGE_FAILED
Definition: AampEvent.h:125
logprintf
void logprintf(const char *format,...)
Print logs to console / log fil.
Definition: aamplogging.cpp:432
AAMP_TUNE_FAILED_TO_GET_KEYID
@ AAMP_TUNE_FAILED_TO_GET_KEYID
Definition: AampEvent.h:131
DrmData::setData
void setData(unsigned char *data, int dataLength)
Updates DrmData with given data.
Definition: AampDRMutils.cpp:91
eAAMPConfig_LRHContentType
@ eAAMPConfig_LRHContentType
Definition: AampConfig.h:324
gpGlobalConfig
AampConfig * gpGlobalConfig
Global configuration.
Definition: main_aamp.cpp:48
PrivateInstanceAAMP::SetState
void SetState(PrivAAMPState state)
Set player state.
Definition: priv_aamp.cpp:7731
KEY_ERROR_EMPTY_SESSION_ID
@ KEY_ERROR_EMPTY_SESSION_ID
Definition: AampDrmSession.h:61
AampDRMSessionManager::getCurlAbort
bool getCurlAbort(void)
Get Session abort flag.
Definition: AampDRMSessionManager.cpp:206
eSESSIONMGR_ACTIVE
@ eSESSIONMGR_ACTIVE
Definition: AampDRMSessionManager.h:138
AampChallengeInfo::data
std::shared_ptr< DrmData > data
Definition: AampDrmHelper.h:46
AampJsonObject::ENCODING_BASE64
@ ENCODING_BASE64
Definition: AampJsonObject.h:49
AampDRMSessionManager
Controller for managing DRM sessions.
Definition: AampDRMSessionManager.h:145
ISCONFIGSET
#define ISCONFIGSET(x)
Definition: AampConfig.h:84
PROFILE_BUCKET_LA_POSTPROC
@ PROFILE_BUCKET_LA_POSTPROC
Definition: AampProfiler.h:70
AampChallengeInfo::accessToken
std::string accessToken
Definition: AampDrmHelper.h:49
AampDRMSessionManager::notifyCleanup
void notifyCleanup()
Resethe current seesion ID.
Definition: AampDRMSessionManager.cpp:1645
eAAMPConfig_AuthToken
@ eAAMPConfig_AuthToken
Definition: AampConfig.h:308
writeCallbackData
structure to hold DRM data to write
Definition: AampDRMSessionManager.h:366
AampDRMSessionManager::clearDrmSession
void clearDrmSession(bool forceClearSession=false)
Clean up the Session Data if license key acquisition failed or if LicenseCaching is false.
Definition: AampDRMSessionManager.cpp:257
PrivateInstanceAAMP::mDynamicDrmDefaultconfig
DynamicDrmInfo mDynamicDrmDefaultconfig
Definition: priv_aamp.h:1096
AampDRMSessionManager::getAccessToken
const char * getAccessToken(int &tokenLength, long &error_code, bool bSslPeerVerify)
Get the accessToken from authService.
Definition: AampDRMSessionManager.cpp:388
AampSecManager::setVideoWindowSize
bool setVideoWindowSize(int64_t sessionId, int64_t video_width, int64_t video_height)
To update session state to SecManager.
Definition: AampSecManager.cpp:388
AAMP_TUNE_FAILURE_UNKNOWN
@ AAMP_TUNE_FAILURE_UNKNOWN
Definition: AampEvent.h:147
AampMutexHold
auto Lock the provided mutex during the object scope
Definition: AampMutex.h:34
eCURLINSTANCE_AES
@ eCURLINSTANCE_AES
Definition: priv_aamp.h:164
AAMP_TUNE_DRM_INIT_FAILED
@ AAMP_TUNE_DRM_INIT_FAILED
Definition: AampEvent.h:122
AampDrmSession::setOutputProtection
void setOutputProtection(bool bValue)
Set the OutputProtection for DRM Session.
Definition: AampDrmSession.h:178
AAMP_TUNE_INVALID_DRM_KEY
@ AAMP_TUNE_INVALID_DRM_KEY
Definition: AampEvent.h:128
eAAMPConfig_EnablePROutputProtection
@ eAAMPConfig_EnablePROutputProtection
Definition: AampConfig.h:124
AampLogManager
AampLogManager Class.
Definition: AampLogManager.h:150
KEY_PENDING
@ KEY_PENDING
Definition: AampDrmSession.h:57
AampDRMSessionManager::getLicense
DrmData * getLicense(AampLicenseRequest &licRequest, int32_t *httpError, MediaType streamType, PrivateInstanceAAMP *aamp, bool isContentMetadataAvailable=false, std::string licenseProxy="")
Get DRM license key from DRM server.
Definition: AampDRMSessionManager.cpp:670
AAMP_TUNE_DRM_SESSIONID_EMPTY
@ AAMP_TUNE_DRM_SESSIONID_EMPTY
Definition: AampEvent.h:124
AAMPLOG
#define AAMPLOG(MYLOGOBJ, LEVEL, LEVELSTR, FORMAT,...)
Macro for validating the log level to be enabled.
Definition: AampLogManager.h:50
AampConfig::GetConfigValue
bool GetConfigValue(AAMPConfigSettings cfg, std::string &value)
GetConfigValue - Gets configuration for string data type.
Definition: AampConfig.cpp:748
AAMP_TUNE_AUTHORISATION_FAILURE
@ AAMP_TUNE_AUTHORISATION_FAILURE
Definition: AampEvent.h:118
base64_Encode
char * base64_Encode(const unsigned char *src, size_t len)
convert blob of binary data to ascii base64-encoded equivalent
Definition: _base64.cpp:37
AampDRMSessionManager::write_callback
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
Curl write callback, used to get the curl o/p from DRM license, accessToken curl requests.
Definition: AampDRMSessionManager.cpp:333
PrivateInstanceAAMP::IsEventListenerAvailable
bool IsEventListenerAvailable(AAMPEventType eventType)
IsEventListenerAvailable Check if Event is registered.
Definition: priv_aamp.cpp:2261
SessionMgrState
SessionMgrState
Enum to represent session manager state. Session manager would abort any createDrmSession request if ...
Definition: AampDRMSessionManager.h:136
DEFAULT_CURL_TIMEOUT
#define DEFAULT_CURL_TIMEOUT
Definition: priv_aamp.h:72
PrivateInstanceAAMP::SendDrmErrorEvent
void SendDrmErrorEvent(DrmMetaDataEventPtr event, bool isRetryEnabled)
Handles DRM errors and sends events to application if required.
Definition: priv_aamp.cpp:2269
AampLicenseRequest
Holds the data to get the License.
Definition: AampDrmHelper.h:57
ReleaseDRMLicenseAcquireThread
void ReleaseDRMLicenseAcquireThread(PrivateInstanceAAMP *aamp)
Function to release the DrmSession if it running.
Definition: AampDRMSessionManager.cpp:1741
eSESSIONMGR_INACTIVE
@ eSESSIONMGR_INACTIVE
Definition: AampDRMSessionManager.h:137
AampSecManager::UpdateSessionState
void UpdateSessionState(int64_t sessionId, bool active)
To update session state to SecManager.
Definition: AampSecManager.cpp:314
ProfileEventAAMP::ProfileError
void ProfileError(ProfilerBucketType type, int result=-1)
Marking error while executing a bucket.
Definition: AampProfiler.cpp:311
AampDRMSessionManager::getSessionMgrState
SessionMgrState getSessionMgrState()
Get Session manager state.
Definition: AampDRMSessionManager.cpp:191
StreamSink::QueueProtectionEvent
virtual void QueueProtectionEvent(const char *protSystemId, const void *ptr, size_t len, MediaType type)
Queue-up the protection event.
Definition: main_aamp.h:638
DrmInfo::systemUUID
std::string systemUUID
Definition: AampDrmInfo.h:89
AampDrmSession::aampDRMProcessKey
virtual int aampDRMProcessKey(DrmData *key, uint32_t timeout)=0
Updates the received key to DRM session.
DynamicDrmInfo
Definition: priv_aamp.h:366
AampSecManager.h
Class to communicate with SecManager Thunder plugin.
DrmInfo
DRM information required to decrypt.
Definition: AampDrmInfo.h:47
AampMutex.h
Helper class for scoped mutex lock.
AampDRMSessionManager::clearFailedKeyIds
void clearFailedKeyIds()
Clean up the failed keyIds.
Definition: AampDRMSessionManager.cpp:222
PROFILE_BUCKET_LA_PREPROC
@ PROFILE_BUCKET_LA_PREPROC
Definition: AampProfiler.h:68
AampDRMSessionManager::IsKeyIdUsable
bool IsKeyIdUsable(std::vector< uint8_t > keyIdArray)
Get DRM license key from DRM server.
Definition: AampDRMSessionManager.cpp:482
eAAMPConfig_AnonymousLicenseRequest
@ eAAMPConfig_AnonymousLicenseRequest
Definition: AampConfig.h:116
eAAMPConfig_CustomLicenseData
@ eAAMPConfig_CustomLicenseData
Definition: AampConfig.h:320
AampChallengeInfo::url
std::string url
Definition: AampDrmHelper.h:48
MediaType
MediaType
Media types.
Definition: AampMediaType.h:37
eAAMPConfig_LRHAcceptValue
@ eAAMPConfig_LRHAcceptValue
Definition: AampConfig.h:323
aamp_GetTimespec
struct timespec aamp_GetTimespec(int timeInMs)
To get the timespec.
Definition: AampUtils.cpp:741
DrmSessionDataInfo::sessionData
struct DrmSessionParams * sessionData
Definition: AampDRMSessionManager.h:59
PrivateInstanceAAMP::mSupportedTLSVersion
long mSupportedTLSVersion
Definition: priv_aamp.h:1088
AampJsonObject.h
File to handle Json format.
AampDRMSessionManager::configureLicenseServerParameters
bool configureLicenseServerParameters(std::shared_ptr< AampDrmHelper > drmHelper, AampLicenseRequest &licRequest, std::string &licenseServerProxy, const AampChallengeInfo &challengeInfo, PrivateInstanceAAMP *aampInstance)
Configure the Drm license server parameters for URL/proxy and custom http request headers.
Definition: AampDRMSessionManager.cpp:1585
PrivateInstanceAAMP::SendEvent
void SendEvent(AAMPEventPtr eventData, AAMPEventMode eventMode=AAMP_EVENT_DEFAULT_MODE)
Send event to listeners.
Definition: priv_aamp.cpp:2530
eAAMPConfig_CKLicenseServerUrl
@ eAAMPConfig_CKLicenseServerUrl
Definition: AampConfig.h:298
eAAMPConfig_RuntimeDRMConfig
@ eAAMPConfig_RuntimeDRMConfig
Definition: AampConfig.h:201
AAMP_EVENT_CONTENT_PROTECTION_DATA_UPDATE
@ AAMP_EVENT_CONTENT_PROTECTION_DATA_UPDATE
Definition: AampEvent.h:88
AAMP_TUNE_FAILED_TO_GET_ACCESS_TOKEN
@ AAMP_TUNE_FAILED_TO_GET_ACCESS_TOKEN
Definition: AampEvent.h:132
AAMP_TUNE_DRM_DATA_BIND_FAILED
@ AAMP_TUNE_DRM_DATA_BIND_FAILED
Definition: AampEvent.h:123
AampDrmSession
Base class for DRM sessions.
Definition: AampDrmSession.h:69
eMEDIATYPE_TELEMETRY_DRM
@ eMEDIATYPE_TELEMETRY_DRM
Definition: main_aamp.h:95
AampDrmSession::getState
virtual KeyState getState()=0
Get the current state of DRM Session.
_base64.h
base64 source Encoder/Decoder
AampDRMSessionManager::setCurlAbort
void setCurlAbort(bool isAbort)
Set Session abort flag.
Definition: AampDRMSessionManager.cpp:199
eAUTHTOKEN_INVALID_STATUS_CODE
@ eAUTHTOKEN_INVALID_STATUS_CODE
Definition: main_aamp.h:144
PROFILE_BUCKET_LA_NETWORK
@ PROFILE_BUCKET_LA_NETWORK
Definition: AampProfiler.h:69
AAMPTuneFailure
AAMPTuneFailure
AAMP playback error codes.
Definition: AampEvent.h:108
MediaTypeTelemetry
MediaTypeTelemetry
Media types for telemetry.
Definition: main_aamp.h:92
AampSecManager::GetInstance
static AampSecManager * GetInstance()
To get AampSecManager instance.
Definition: AampSecManager.cpp:35
PrivateInstanceAAMP::GetLicenseCustomData
std::string GetLicenseCustomData()
Get License Custom Data.
Definition: priv_aamp.cpp:11994
AAMP_EVENT_EOS
@ AAMP_EVENT_EOS
Definition: AampEvent.h:50
PrivateInstanceAAMP::GetAppName
std::string GetAppName()
Get the application name.
Definition: priv_aamp.cpp:9799
AAMP_TUNE_DEVICE_NOT_PROVISIONED
@ AAMP_TUNE_DEVICE_NOT_PROVISIONED
Definition: AampEvent.h:142
ProfileEventAAMP::ProfileBegin
void ProfileBegin(ProfilerBucketType type)
Marking the beginning of a bucket.
Definition: AampProfiler.cpp:297
eMETHOD_AES_128
@ eMETHOD_AES_128
Definition: AampDrmInfo.h:39
priv_aamp.h
Private functions and types used internally by AAMP.
AampDRMSessionManager::progress_callback
static int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
Definition: AampDRMSessionManager.cpp:308
AAMP_TUNE_LICENCE_REQUEST_FAILED
@ AAMP_TUNE_LICENCE_REQUEST_FAILED
Definition: AampEvent.h:127
eAAMPConfig_SslVerifyPeer
@ eAAMPConfig_SslVerifyPeer
Definition: AampConfig.h:126
AampDRMSessionManager::clearSessionData
void clearSessionData()
Clean up the memory used by session variables.
Definition: AampDRMSessionManager.cpp:155
AAMP_TUNE_CORRUPT_DRM_METADATA
@ AAMP_TUNE_CORRUPT_DRM_METADATA
Definition: AampEvent.h:134
CurlStore::GetCurlHandle
CURL * GetCurlHandle(void *pAamp, std::string url, AampCurlInstance startIdx)
Definition: AampCurlStore.cpp:276
KeyID
Structure to hold, keyId and session creation time for keyId.
Definition: AampDRMSessionManager.h:121
AAMPLOG_TRACE
#define AAMPLOG_TRACE(FORMAT,...)
AAMP logging defines, this can be enabled through setLogLevel() as per the need.
Definition: AampLogManager.h:83
eAAMPConfig_UseSecManager
@ eAAMPConfig_UseSecManager
Definition: AampConfig.h:190
AampDrmSession::getKeySystem
string getKeySystem()
Get the DRM System, ie, UUID for PlayReady WideVine etc..
Definition: AampDrmSession.cpp:47
eAAMPConfig_PropogateURIParam
@ eAAMPConfig_PropogateURIParam
Definition: AampConfig.h:152
KEY_INIT
@ KEY_INIT
Definition: AampDrmSession.h:56
PrivateInstanceAAMP
Class representing the AAMP player's private instance, which is not exposed to outside world.
Definition: priv_aamp.h:640
ProfileEventAAMP::SetDrmErrorCode
void SetDrmErrorCode(int errCode)
Setting DRM error code.
Definition: AampProfiler.h:280
AampSecManager::setPlaybackSpeedState
bool setPlaybackSpeedState(int64_t sessionId, int64_t playback_speed, int64_t playback_position, bool delayNeeded=false)
To set Playback Speed State to SecManager.
Definition: AampSecManager.cpp:425
CreateDRMSession
void * CreateDRMSession(void *arg)
Thread function to create DRM Session which would be invoked in thread from HLS , PlayReady or from p...
Definition: AampDRMSessionManager.cpp:1803
PrivateInstanceAAMP::mIsVSS
bool mIsVSS
Definition: priv_aamp.h:1021
AampLicenseRequest::POST
@ POST
Definition: AampDrmHelper.h:65
AampDRMSessionManager::initializeDrmSession
KeyState initializeDrmSession(std::shared_ptr< AampDrmHelper > drmHelper, int sessionSlot, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP *aampInstance)
Initialize the Drm System with InitData(PSSH)
Definition: AampDRMSessionManager.cpp:1232
CurlStore::GetCurlStoreInstance
static CurlStore * GetCurlStoreInstance(void *pContext)
Definition: AampCurlStore.cpp:514
AampDRMSessionManager::acquireLicense
KeyState acquireLicense(std::shared_ptr< AampDrmHelper > drmHelper, int sessionSlot, int &cdmError, DrmMetaDataEventPtr eventHandle, PrivateInstanceAAMP *aampInstance, MediaType streamType)
sent license challenge to the DRM server and provide the respone to CDM
Definition: AampDRMSessionManager.cpp:1265
AampCurlStore.h
Advanced Adaptive Media Player (AAMP) Curl store.
DrmSessionContext
To store drmSession and keyId data.
Definition: AampDRMSessionManager.h:69
DrmInfo::bPropagateUriParams
bool bPropagateUriParams
Definition: AampDrmInfo.h:82
KEY_READY
@ KEY_READY
Definition: AampDrmSession.h:58
AampDRMSessionManager::setLicenseRequestAbort
void setLicenseRequestAbort(bool isAbort)
Get Session abort flag.
Definition: AampDRMSessionManager.cpp:213
aamp_GetCurrentTimeMS
long long aamp_GetCurrentTimeMS(void)
Get current time from epoch is milliseconds.
Definition: AampUtils.cpp:92
AAMP_TUNE_DRM_KEY_UPDATE_FAILED
@ AAMP_TUNE_DRM_KEY_UPDATE_FAILED
Definition: AampEvent.h:141
PrivateInstanceAAMP::mcurrent_keyIdArray
std::vector< uint8_t > mcurrent_keyIdArray
Definition: priv_aamp.h:1095
PrivateInstanceAAMP::GetLicenseReqProxy
std::string GetLicenseReqProxy()
To get the proxy for license request.
Definition: priv_aamp.cpp:9089
ProfileEventAAMP::ProfileEnd
void ProfileEnd(ProfilerBucketType type)
Marking the end of a bucket.
Definition: AampProfiler.cpp:325
KeyState
KeyState
DRM session states.
Definition: AampDrmSession.h:54
eAUTHTOKEN_TOKEN_PARSE_ERROR
@ eAUTHTOKEN_TOKEN_PARSE_ERROR
Definition: main_aamp.h:143
PrivateInstanceAAMP::GetCustomLicenseHeaders
void GetCustomLicenseHeaders(std::unordered_map< std::string, std::vector< std::string >> &customHeaders)
To get any custom license HTTP headers that was set by application.
Definition: priv_aamp.cpp:9219
AampConfig::IsConfigSet
bool IsConfigSet(AAMPConfigSettings cfg)
Gets the boolean configuration value.
Definition: AampConfig.cpp:649
DRMSystems
DRMSystems
DRM system types.
Definition: AampDrmSystems.h:33
mssleep
void mssleep(int milliseconds)
Sleep for given milliseconds.
Definition: AampUtils.cpp:1021
DrmInfo::method
DrmMethod method
Definition: AampDrmInfo.h:79
AampLogManager::getHexDebugStr
static std::string getHexDebugStr(const std::vector< uint8_t > &data)
Get a hex string representation of a vector of bytes.
Definition: aamplogging.cpp:93
AampDrmSession::generateAampDRMSession
virtual void generateAampDRMSession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, std::string &customData)=0
Create drm session with given init data.
AampDRMSessionManager::clearAccessToken
void clearAccessToken()
Clean up the memory for accessToken.
Definition: AampDRMSessionManager.cpp:244
DrmData::getData
const std::string & getData()
Getter method for data.
Definition: AampDRMutils.cpp:75
AampDRMSessionManager::~AampDRMSessionManager
~AampDRMSessionManager()
AampDRMSessionManager Destructor.
Definition: AampDRMSessionManager.cpp:141
PROFILE_BUCKET_LA_TOTAL
@ PROFILE_BUCKET_LA_TOTAL
Definition: AampProfiler.h:67
PrivateInstanceAAMP::SendDRMMetaData
void SendDRMMetaData(DrmMetaDataEventPtr e)
Send DRM metadata event.
Definition: priv_aamp.cpp:2656
AampChallengeInfo
Aamp challenge info to get the License.
Definition: AampDrmHelper.h:44
DrmInfo::mediaFormat
MediaFormat mediaFormat
Definition: AampDrmInfo.h:80
PrivateInstanceAAMP::GetVssVirtualStreamID
std::string GetVssVirtualStreamID() const
pass virtual stream ID
Definition: priv_aamp.h:2770
MediaFormat
MediaFormat
Media format types.
Definition: AampDrmMediaFormat.h:32
AAMP_TUNE_HDCP_COMPLIANCE_ERROR
@ AAMP_TUNE_HDCP_COMPLIANCE_ERROR
Definition: AampEvent.h:143
PrivateInstanceAAMP::GetServiceZone
std::string GetServiceZone() const
pass service zone, extracted from locator &sz URI parameter
Definition: priv_aamp.h:2764
AampSecManager::AcquireLicense
bool AcquireLicense(PrivateInstanceAAMP *aamp, const char *licenseUrl, const char *moneyTraceMetdata[][2], const char *accessAttributes[][2], const char *contentMetadata, size_t contentMetadataLen, const char *licenseRequest, size_t licenseRequestLen, const char *keySystemId, const char *mediaUsage, const char *accessToken, size_t accessTokenLen, int64_t *sessionId, char **licenseResponse, size_t *licenseResponseLength, int32_t *statusCode, int32_t *reasonCode, int32_t *businessStatus)
To acquire license from SecManager.
Definition: AampSecManager.cpp:100
eSTATE_COMPLETE
@ eSTATE_COMPLETE
Definition: AampEvent.h:169
DRM_API_SUCCESS
#define DRM_API_SUCCESS
Macros to track the value of API success or failure.
Definition: AampDRMutils.h:44
eLOGLEVEL_FATAL
@ eLOGLEVEL_FATAL
Definition: AampLogManager.h:103
KEY_ERROR
@ KEY_ERROR
Definition: AampDrmSession.h:59
eAAMPConfig_ContentProtectionDataUpdateTimeout
@ eAAMPConfig_ContentProtectionDataUpdateTimeout
Definition: AampConfig.h:263
eAAMPConfig_PRLicenseServerUrl
@ eAAMPConfig_PRLicenseServerUrl
Definition: AampConfig.h:299
CurlStore::SaveCurlHandle
void SaveCurlHandle(void *pAamp, std::string url, AampCurlInstance startIdx, CURL *curl)
Definition: AampCurlStore.cpp:301
PrivateInstanceAAMP::mSessionToken
std::string mSessionToken
Definition: priv_aamp.h:1052
AampDrmHelperEngine::createHelper
std::shared_ptr< AampDrmHelper > createHelper(const struct DrmInfo &drmInfo, AampLogManager *logObj=NULL) const
Build a helper class to support the identified DRM.
Definition: AampDrmHelperFactory.cpp:69
AampJsonObject
Utility class to construct a JSON string.
Definition: AampJsonObject.h:37
GetDrmSystem
DRMSystems GetDrmSystem(std::string drmSystemID)
Get DRM system from ID.
Definition: AampUtils.cpp:601