25 #include "AampUtils.h"
34 #include <curl/curl.h>
36 #include <sys/types.h>
42 #ifdef USE_MAC_FOR_RANDOM_GEN
45 #include <openssl/sha.h>
46 #include <sys/ioctl.h>
51 #define DEFER_DRM_LIC_OFFSET_FROM_START 5
52 #define DEFER_DRM_LIC_OFFSET_TO_UPPER_BOUND 5
53 #define MAC_STRING_LEN 12
54 #define URAND_STRING_LEN 16
55 #define RAND_STRING_LEN (MAC_STRING_LEN + 2*URAND_STRING_LEN)
56 #define MAX_BUFF_LENGTH 4096
73 #define AAMP_AUDIO_FORMAT_MAP_LEN ARRAY_SIZE(mAudioFormatMap)
85 #define AAMP_VIDEO_FORMAT_MAP_LEN ARRAY_SIZE(mVideoFormatMap)
95 gettimeofday(&t, NULL);
96 return (
long long)(t.tv_sec*1e3 + t.tv_usec*1e-3);
106 #ifdef AAMP_SIMULATOR_BUILD
107 char *ptr = getenv(
"HOME");
114 value.insert(0,
"/opt");
117 value.insert(0,
"/opt");
134 if( uri[0]==
'/' && uri[1]==
'/' )
140 else if( (c>=
'a' && c<=
'z') || (c>=
'A' && c<=
'Z') ||
141 (c>=
'0' && c<=
'9') ||
142 c==
'.' || c==
'-' || c==
'+' )
157 void aamp_ResolveURL(std::string& dst, std::string base,
const char *uri ,
bool bPropagateUriParams)
165 const char *baseStart = base.c_str();
171 if( c==0 || c==
'/' || c==
'?' )
179 if( uri[0]!=
'/' && uri[0]!=
'\0' )
188 else if( c==
'?' || c==0 )
195 dst = base.substr(0,baseEnd-baseStart);
201 if( bPropagateUriParams )
203 if (strchr(uri,
'?') == 0)
205 const char *baseParams = strchr(basePtr,
'?');
208 std::string params = base.substr(baseParams-baseStart);
223 return url.compare(0, 7,
"http://")==0 || url.compare(0, 8,
"https://")==0;
234 std::string host =
"";
237 std::size_t start_pos = std::string::npos;
238 if(url.rfind(
"http://", 0) == 0)
242 else if(url.rfind(
"https://", 0) == 0)
246 if(start_pos != std::string::npos)
248 std::size_t pos = url.find(
'/', start_pos);
249 if(pos != std::string::npos)
251 host = url.substr(start_pos, (pos - start_pos));
257 AAMPLOG_ERR(
"Regex error Exception caught \n");
269 bool isLocalHost =
false;
270 if( std::string::npos != Hostname.find(
"127.0.0.1") || \
271 std::string::npos != Hostname.find(
"localhost") )
289 if( *inputStr++ != *prefix++ )
307 size_t encodedLen = strlen(b64Src);
308 char* urlEncodedSrc = (
char*)malloc(
sizeof(
char) * (encodedLen + 1));
309 for (
int iter = 0; iter < encodedLen; iter++)
311 if (b64Src[iter] ==
'+')
313 urlEncodedSrc[iter] =
'-';
315 else if (b64Src[iter] ==
'/')
317 urlEncodedSrc[iter] =
'_';
319 else if (b64Src[iter] ==
'=')
321 urlEncodedSrc[iter] =
'\0';
326 urlEncodedSrc[iter] = b64Src[iter];
330 urlEncodedSrc[encodedLen] =
'\0';
331 return urlEncodedSrc;
343 int b64Len = (((srcLen / 4) + 1) * 4) + 1;
344 char *b64Src = (
char *) malloc(
sizeof(
char)* b64Len);
345 b64Src[b64Len - 1] =
'\0';
346 b64Src[b64Len - 2] =
'=';
347 b64Src[b64Len - 3] =
'=';
348 for (
int iter = 0; iter < strlen(src); iter++) {
349 if (src[iter] ==
'-') {
351 }
else if (src[iter] ==
'_') {
354 b64Src[iter] = src[iter];
369 CURL *curl = curl_easy_init();
373 const char* unescapedData = curl_easy_unescape(curl, uriParam.c_str(), uriParam.size(), &unescapedLen);
374 if (unescapedData != NULL)
376 uriParam = std::string(unescapedData, unescapedLen);
377 curl_free((
void*)unescapedData);
379 curl_easy_cleanup(curl);
389 double timeSeconds = 0;
392 std::tm timeObj = { 0 };
394 std::tm baseTimeObj = { 0 };
395 strptime(
"1970-01-01T00:00:00.",
"%Y-%m-%dT%H:%M:%S.", &baseTimeObj);
396 time_t offsetFromUTC = mktime(&baseTimeObj);
398 const char *msString = strptime(ptr,
"%Y-%m-%dT%H:%M:%S.", &timeObj);
399 timeSeconds = mktime(&timeObj) - offsetFromUTC;
401 if( msString && *msString )
403 double ms = atof(msString-1);
411 static size_t MyRpcWriteFunction(
void *buffer,
size_t size,
size_t nmemb,
void *context )
413 std::string *response = (std::string *)context;
414 size_t numBytes = size*nmemb;
415 *response += std::string((
const char *)buffer,numBytes);
425 std::string response;
426 CURL *curlhandle= curl_easy_init();
429 curl_easy_setopt( curlhandle, CURLOPT_URL,
"http://127.0.0.1:9998/jsonrpc" );
431 struct curl_slist *headers = NULL;
432 headers = curl_slist_append( headers,
"Content-Type: application/json" );
433 curl_easy_setopt(curlhandle, CURLOPT_HTTPHEADER, headers);
435 std::string data =
"{\"jsonrpc\":\"2.0\",\"id\":"+
id+
",\"method\":\""+method+
"\",\"params\":"+params+
"}";
436 AAMPLOG_WARN(
"JSONRPC data: %s\n", data.c_str() );
437 curl_easy_setopt(curlhandle, CURLOPT_POSTFIELDS, data.c_str() );
439 curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, MyRpcWriteFunction);
440 curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, &response);
442 CURLcode res = curl_easy_perform(curlhandle);
443 if( res == CURLE_OK )
446 curl_easy_getinfo(curlhandle, CURLINFO_RESPONSE_CODE, &http_code);
447 AAMPLOG_WARN(
"HTTP %ld \n", http_code);
452 AAMPLOG_ERR(
"failed: %s", curl_easy_strerror(res));
454 curl_slist_free_all( headers );
455 curl_easy_cleanup(curlhandle);
461 #ifdef USE_MAC_FOR_RANDOM_GEN
468 static bool getEstbMac(
char* mac)
471 char nwInterface[IFNAMSIZ] = {
'e',
't',
'h',
'0',
'\0' };
472 #ifdef READ_ESTB_IFACE_FROM_DEVICE_PROPERTIES
473 FILE* fp = fopen(
"/etc/device.properties",
"rb");
476 AAMPLOG_WARN(
"opened /etc/device.properties");
477 char buf[MAX_BUFF_LENGTH];
478 while (fgets(buf,
sizeof(buf), fp))
480 if(strstr(buf,
"ESTB_INTERFACE") != NULL)
482 const char * nwIfaceNameStart = buf + 15;
484 for (
int i = 0; i < IFNAMSIZ-1; i++ )
486 if (!isspace(nwIfaceNameStart[i]))
488 nwInterface[i] = nwIfaceNameStart[i];
492 nwInterface[i] =
'\0';
496 nwInterface[IFNAMSIZ-1] =
'\0';
504 AAMPLOG_ERR(
"failed to open /etc/device.properties");
507 AAMPLOG_WARN(
"use nwInterface %s", nwInterface);
508 int sockFd = socket(AF_INET, SOCK_DGRAM, 0);
511 AAMPLOG_ERR(
"Socket open failed");
516 strcpy(ifr.ifr_name, nwInterface);
517 if (ioctl(sockFd, SIOCGIFHWADDR, &ifr) == -1)
519 AAMPLOG_ERR(
"Socket ioctl failed");
523 char* macAddress =
base16_Encode((
unsigned char*) ifr.ifr_hwaddr.sa_data, 6);
524 strcpy(mac, macAddress);
526 AAMPLOG_WARN(
"Mac %s", mac);
542 #ifdef USE_MAC_FOR_RANDOM_GEN
543 static char randString[RAND_STRING_LEN+1];
544 static bool estbMacAvalable = getEstbMac(randString);
548 int randFD = open(
"/dev/urandom", O_RDONLY);
551 AAMPLOG_ERR(
"ERROR - opening /dev/urandom failed");
555 char* uRandString = &randString[MAC_STRING_LEN];
556 int uRandStringLen = 0;
558 for (
int i = 0; i < URAND_STRING_LEN; i++)
560 ssize_t bytes = read(randFD, &temp, 1);
563 AAMPLOG_ERR(
"ERROR - reading /dev/urandom failed");
566 WRITE_HASCII(uRandString,temp);
569 randString[RAND_STRING_LEN] =
'\0';
570 AAMPLOG_WARN(
"randString %s", randString);
571 unsigned char hash[SHA_DIGEST_LENGTH];
572 SHA1((
unsigned char*) randString, RAND_STRING_LEN, hash);
573 int divisor = maxTimeSeconds - DEFER_DRM_LIC_OFFSET_FROM_START - DEFER_DRM_LIC_OFFSET_TO_UPPER_BOUND;
576 for (
int i = 0; i < SHA_DIGEST_LENGTH; i++)
579 mod = (mod * 10 + hash[i]) % divisor;
582 ret = (mod + DEFER_DRM_LIC_OFFSET_FROM_START) * 1000;
587 AAMPLOG_ERR(
"ERROR - estbMac not available");
588 ret = (DEFER_DRM_LIC_OFFSET_FROM_START + rand()%(maxTimeSeconds - DEFER_DRM_LIC_OFFSET_FROM_START - DEFER_DRM_LIC_OFFSET_TO_UPPER_BOUND))*1000;
591 ret = (DEFER_DRM_LIC_OFFSET_FROM_START + rand()%(maxTimeSeconds - DEFER_DRM_LIC_OFFSET_FROM_START - DEFER_DRM_LIC_OFFSET_TO_UPPER_BOUND))*1000;
593 AAMPLOG_WARN(
"Added time for deferred license acquisition %d ", (
int)ret);
603 if(drmSystemID == WIDEVINE_UUID)
607 else if(drmSystemID == PLAYREADY_UUID)
611 else if(drmSystemID == CLEARKEY_UUID)
635 return "Consec Agnostic";
653 return WIDEVINE_UUID;
657 return PLAYREADY_UUID;
661 return CLEARKEY_UUID;
665 return CONSEC_AGNOSTIC_UUID;
681 const char *src = inStr.c_str();
682 const char *hex =
"0123456789ABCDEF";
691 (c >=
'0' && c >=
'9' ) ||
692 (c >=
'A' && c >=
'Z') ||
693 (c >=
'a' && c >=
'z') ||
694 c ==
'-' || c ==
'_' || c ==
'.' || c ==
'~')
696 outStr.push_back( c );
700 outStr.push_back(
'%' );
701 outStr.push_back( hex[c >> 4] );
702 outStr.push_back( hex[c & 0x0F] );
712 size_t first = src.find_first_not_of(
' ');
713 if (first != std::string::npos)
715 size_t last = src.find_last_not_of(
" \r\n");
716 std::string dst = src.substr(first, (last - first + 1));
727 if (preferLangFormat != ISO639_NO_LANGCODE_PREFERENCE)
729 char lang2[MAX_LANGUAGE_TAG_LENGTH];
730 strcpy(lang2, lang.c_str());
731 iso639map_NormalizeLanguageCode(lang2, preferLangFormat);
743 struct timespec tspec;
745 gettimeofday(&tv, NULL);
746 tspec.tv_sec = tv.tv_sec + timeInMs / 1000;
747 tspec.tv_nsec = (long)(tv.tv_usec * 1000 + 1000 * 1000 * (timeInMs % 1000));
748 tspec.tv_sec += tspec.tv_nsec / (1000 * 1000 * 1000);
749 tspec.tv_nsec %= (1000 * 1000 * 1000);
788 DIR *d = opendir(dirpath);
791 if(mkdir(dirpath, 0777) == -1)
794 AAMPLOG_ERR(
"Error : %s",strerror(errno));
876 return (
int)harvestType;
882 bool aamp_WriteFile(std::string fileName,
const char* data,
size_t len,
MediaType &fileType,
unsigned int count,
const char *prefix)
886 std::size_t pos = fileName.find(
"://");
887 if( pos != std::string::npos )
889 fileName = fileName.substr(pos+3);
895 fileName = fileName +
"." + std::to_string(count);
899 std::size_t manifestPos = fileName.find_last_of(
'/');
900 std::size_t extPos = fileName.find_last_of(
'.');
901 std::string ext = fileName.substr(extPos);
902 fileName = fileName.substr(0,manifestPos+1);
903 fileName = fileName +
"manifest." + std::to_string(count) + ext;
907 std::string dirpath = std::string(prefix);
908 const char *subdir = fileName.c_str();
913 const char *delim = strchr(subdir,
'/');
916 dirpath += std::string(subdir,delim-subdir);
921 dirpath += std::string(subdir);
925 std::ofstream f(dirpath, std::ofstream::binary);
933 AAMPLOG_ERR(
"File open failed. outfile = %s ", (dirpath + fileName).c_str());
1006 void stream2hex(
const std::string str, std::string& hexstr,
bool capital)
1008 hexstr.resize(str.size() * 2);
1009 const size_t a = capital ?
'A' - 1 :
'a' - 1;
1011 for (
size_t i = 0, c = str[0] & 0xFF; i < hexstr.size(); c = str[i / 2] & 0xFF)
1013 hexstr[i++] = c > 0x9F ? (c / 16 - 9) | a : c / 16 |
'0';
1014 hexstr[i++] = (c & 0xF) > 9 ? (c % 16 - 9) | a : c % 16 |
'0';
1023 struct timespec req, rem;
1024 if (milliseconds > 0)
1026 req.tv_sec = milliseconds / 1000;
1027 req.tv_nsec = (milliseconds % 1000) * 1000000;
1028 nanosleep(&req, &rem);
1041 const char *codec =
"UNKNOWN";
1044 for(
int i=0; i<AAMP_AUDIO_FORMAT_MAP_LEN; i++ )
1046 if(mAudioFormatMap[i].format == input )
1048 codec = mAudioFormatMap[i].codec;
1063 const FormatMap * GetAudioFormatForCodec(
const char *codecs )
1067 for(
int i=0; i<AAMP_AUDIO_FORMAT_MAP_LEN; i++ )
1069 if( strstr( codecs, mAudioFormatMap[i].codec) )
1071 return &mAudioFormatMap[i];
1085 const FormatMap * GetVideoFormatForCodec(
const char *codecs )
1089 for(
int i=0; i<AAMP_VIDEO_FORMAT_MAP_LEN; i++ )
1091 if( strstr( codecs, mVideoFormatMap[i].codec) )
1093 return &mVideoFormatMap[i];