28 #define CURL_EASY_SETOPT(curl, CURLoption, option)\
29 if (curl_easy_setopt(curl, CURLoption, option) != 0) {\
30 logprintf("Failed at curl_easy_setopt ");\
31 } //CID:132698,135078 - checked return
34 static pthread_mutex_t gCurlShMutex = PTHREAD_MUTEX_INITIALIZER;
43 static void curl_lock_callback(CURL *curl, curl_lock_data data, curl_lock_access access,
void *user_ptr)
45 pthread_mutex_t *pCurlShareLock = NULL;
55 case CURL_LOCK_DATA_DNS:
56 pCurlShareLock = &(locks->mDnsCurlShareMutex);
58 case CURL_LOCK_DATA_SSL_SESSION:
59 pCurlShareLock = &(locks->mSslCurlShareMutex);
63 pCurlShareLock = &(locks->mCurlSharedlock);
67 pthread_mutex_lock(pCurlShareLock);
71 pthread_mutex_lock(&gCurlShMutex);
85 pthread_mutex_t *pCurlShareLock = NULL;
94 case CURL_LOCK_DATA_DNS:
95 pCurlShareLock = &(locks->mDnsCurlShareMutex);
97 case CURL_LOCK_DATA_SSL_SESSION:
98 pCurlShareLock = &(locks->mSslCurlShareMutex);
102 pCurlShareLock = &(locks->mCurlSharedlock);
106 pthread_mutex_unlock(pCurlShareLock);
110 pthread_mutex_unlock(&gCurlShMutex);
122 static size_t write_callback(
char *ptr,
size_t size,
size_t nmemb,
void *userdata)
128 ret = context->aamp->HandleSSLWriteCallback( ptr, size, nmemb, userdata);
141 static size_t header_callback(
const char *ptr,
size_t size,
size_t nmemb,
void *user_data)
147 ret = context->aamp->HandleSSLHeaderCallback(ptr, size, nmemb, user_data);
174 ret = context->aamp->HandleSSLProgressCallback ( clientp, dltotal, dlnow, ultotal, ulnow );
190 CURLcode rc = CURLE_OK;
191 pthread_mutex_lock(&context->mLock);
192 if (!context->mDownloadsEnabled)
194 rc = CURLE_ABORTED_BY_CALLBACK ;
196 pthread_mutex_unlock(&context->mLock);
213 if(type == CURLINFO_TEXT || type == CURLINFO_HEADER_IN)
217 while( len>0 && data[len-1]<
' ' ) len--;
218 std::string printable(data,len);
222 AAMPLOG_WARN(
"curl: %s", printable.c_str() );
224 case CURLINFO_HEADER_IN:
225 AAMPLOG_WARN(
"curl header: %s", printable.c_str() );
242 if ( NULL == CurlSock || NULL == locks )
244 AAMPLOG_WARN(
"Failed to alloc memory for curl store");
249 CurlSock->pstShareLocks = locks;
250 CurlSock->mCurlStoreUserCount += 1;
253 CurlSock->mCurlShared = curl_share_init();
254 sh = curl_share_setopt(CurlSock->mCurlShared, CURLSHOPT_USERDATA, (
void*)locks);
255 sh = curl_share_setopt(CurlSock->mCurlShared, CURLSHOPT_LOCKFUNC,
curl_lock_callback);
257 sh = curl_share_setopt(CurlSock->mCurlShared, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
258 sh = curl_share_setopt(CurlSock->mCurlShared, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
266 umCurlSockDataStore[hostname]=CurlSock;
267 AAMPLOG_INFO(
"Curl store for %s created, Added shared ctx %p in curlstore %p, size:%lu maxsize:%d", hostname.c_str(),
268 CurlSock->mCurlShared, CurlSock, umCurlSockDataStore.size(),
MaxCurlSockStore);
282 std::string HostName;
291 curl = curl_easy_init();
306 std::string HostName;
315 curl_easy_cleanup(curl);
326 std::string UserAgentString;
327 UserAgentString=aamp->mConfig->GetUserAgentString();
329 CURL *curlEasyhdl = curl_easy_init();
332 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_VERBOSE, 1L);
334 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_NOSIGNAL, 1L);
337 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_HEADERFUNCTION,
header_callback);
338 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_WRITEFUNCTION,
write_callback);
341 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
342 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_FOLLOWLOCATION, 1L);
343 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_NOPROGRESS, 0L);
345 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_USERAGENT, UserAgentString.c_str());
346 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_ACCEPT_ENCODING,
"");
347 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_SSL_CTX_FUNCTION,
ssl_callback);
348 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_SSL_CTX_DATA, aamp);
349 long dns_cache_timeout = 3*60;
350 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_DNS_CACHE_TIMEOUT, dns_cache_timeout);
351 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_SHARE, aamp->mCurlShared);
356 if (!proxyName.empty())
359 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_PROXY, proxyName.c_str());
361 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
367 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_VERBOSE, 1);
377 bool isv6(::stat(
"/tmp/estb_ipv6", &tmpStat) == 0);
380 CURL_EASY_SETOPT(curlEasyhdl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
397 int instanceEnd = startIdx + instanceCount;
400 std::string HostName;
401 bool IsRemotehost =
true, CurlFdHost=
false;
404 if(RemoteHost.size())
406 HostName = RemoteHost;
419 AAMPLOG_INFO(
"Check curl store for host:%s inst:%d-%d Fds[%p:%p]\n", HostName.c_str(), startIdx, instanceEnd, aamp->curl[startIdx], aamp->curlhost[startIdx]->curl );
421 AAMPLOG_TRACE(
"From curl store for inst:%d-%d Fds[%p:%p] ShHdl:%p\n", startIdx, instanceEnd, aamp->curl[startIdx], aamp->curlhost[startIdx]->curl, aamp->mCurlShared );
425 if(NULL==aamp->mCurlShared)
427 aamp->mCurlShared = curl_share_init();
428 curl_share_setopt(aamp->mCurlShared, CURLSHOPT_USERDATA, (
void*)NULL);
431 curl_share_setopt(aamp->mCurlShared, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
435 curl_share_setopt(aamp->mCurlShared, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
441 if(eCURL_STORE_HOST_SOCK_AVAILABLE != CurlStoreErrCode)
443 CURL **CurlFd = NULL;
444 for (
unsigned int i = startIdx; i < instanceEnd; i++)
448 CurlFd = &aamp->curlhost[i]->curl;
452 CurlFd = &aamp->curl[i];
455 if (NULL == *CurlFd )
458 AAMPLOG_INFO(
"Created new curl handle:%p for inst:%d", *CurlFd, i );
471 int instanceEnd = startIdx + instanceCount;
472 std::string HostName;
473 bool IsRemotehost =
true, CurlFdHost=
false;
475 if(RemoteHost.size())
477 HostName = RemoteHost;
488 AAMPLOG_INFO(
"Store unused curl handle:%p in Curlstore for inst:%d-%d", aamp->curl[startIdx], startIdx, instanceEnd );
494 for (
unsigned int i = startIdx; i < instanceEnd; i++)
498 curl_easy_cleanup(aamp->curl[i]);
499 aamp->curl[i] = NULL;
506 CurlStore* CurlStore::CurlInstance = NULL;
507 pthread_mutex_t CurlStore::mCurlInstLock = PTHREAD_MUTEX_INITIALIZER;
518 pthread_mutex_lock(&mCurlInstLock);
519 if ( NULL == CurlInstance )
521 int MaxSockStoreSize=0;
524 if ( NULL == CurlInstance )
526 AAMPLOG_WARN(
"Failed to alloc mem for Curl instance");
537 pthread_mutex_unlock(&mCurlInstLock);
547 CURL *curlhdl = NULL;
550 for (
int i = instId; i < instId+1 && !CurlSock->mFreeQ.empty(); )
554 if( MaxAge > mObj.eHdlTimestamp )
556 CurlSock->mFreeQ.pop_front();
558 curl_easy_cleanup(mObj.curl);
563 if ( mObj.curlId == i )
565 CurlSock->mFreeQ.pop_front();
570 for(
auto it=CurlSock->mFreeQ.begin()+1; it!=CurlSock->mFreeQ.end(); ++it)
572 if (( MaxAge < it->eHdlTimestamp ) && ( it->curlId == i ))
575 CurlSock->mFreeQ.erase(it);
595 pthread_mutex_lock(&mCurlInstLock);
596 CurlSockDataIter it = umCurlSockDataStore.find(hostname);
598 if (it != umCurlSockDataStore.end())
600 int CurlFdCount=0,loop=0;
603 CurlSock->mCurlStoreUserCount += 1;
605 aamp->mCurlShared = CurlSock->mCurlShared;
607 for( loop = (
int)CurlIndex; loop < count; )
611 CurlFd=&aamp->curlhost[loop]->curl;
615 CurlFd=&aamp->curl[loop];
618 if (!CurlSock->mFreeQ.empty())
623 CURL_EASY_SETOPT(*CurlFd, CURLOPT_SSL_CTX_DATA, aamp);
628 ret = eCURL_STORE_SOCK_NOT_AVAILABLE;
635 ret = eCURL_STORE_SOCK_NOT_AVAILABLE;
640 AAMPLOG_INFO (
"%d fd(s) got from CurlStore User count:%d", CurlFdCount, CurlSock->mCurlStoreUserCount);
650 AAMPLOG_TRACE(
"Curl Inst %d for %s not in store", CurlIndex, hostname.c_str());
651 ret = eCURL_STORE_HOST_NOT_AVAILABLE;
657 aamp->mCurlShared = CurlSock->mCurlShared;
661 pthread_mutex_unlock(&mCurlInstLock);
675 pthread_mutex_lock(&mCurlInstLock);
676 CurlSockDataIter it = umCurlSockDataStore.find(hostname);
678 if (it != umCurlSockDataStore.end())
680 CurlSock = it->second;
681 CurlSock->mCurlStoreUserCount += 1;
685 for(
int loop = (
int)CurlIndex; loop < CurlIndex+1; )
687 if (!CurlSock->mFreeQ.empty())
693 ret = eCURL_STORE_SOCK_NOT_AVAILABLE;
700 ret = eCURL_STORE_SOCK_NOT_AVAILABLE;
708 AAMPLOG_TRACE(
"Curl Inst %d for %s not available", CurlIndex, hostname.c_str());
712 ret = eCURL_STORE_HOST_NOT_AVAILABLE;
717 *curl = curl_easy_init();
718 CURL_EASY_SETOPT(*curl, CURLOPT_SHARE, CurlSock->mCurlShared);
721 pthread_mutex_unlock(&mCurlInstLock);
734 pthread_mutex_lock(&mCurlInstLock);
735 CurlSockDataIter it = umCurlSockDataStore.find(hostname);
737 if(it != umCurlSockDataStore.end())
739 CurlSock = it->second;
741 CurlSock->mCurlStoreUserCount -= 1;
743 for(
int loop = (
int)CurlIndex; loop < count; ++loop)
748 mObj.curl = aamp->curlhost[loop]->curl;
749 aamp->curlhost[loop]->curl = NULL;
753 mObj.curl = aamp->curl[loop];
754 aamp->curl[loop] = NULL;
757 mObj.eHdlTimestamp = CurlSock->timestamp;
759 CurlSock->mFreeQ.push_back(mObj);
760 AAMPLOG_TRACE(
"Curl Inst %d CurlCtx:%p stored at %lu", loop, mObj.curl, CurlSock->mFreeQ.size());
763 AAMPLOG_TRACE (
"CurlStore User count:%d for:%s", CurlSock->mCurlStoreUserCount, hostname.c_str());
772 AAMPLOG_INFO(
"Host %s not in store, Curl Inst %d-%d", hostname.c_str(), CurlIndex,count);
775 pthread_mutex_unlock(&mCurlInstLock);
785 pthread_mutex_lock(&mCurlInstLock);
786 CurlSockDataIter it = umCurlSockDataStore.find(hostname);
787 if(it != umCurlSockDataStore.end())
789 CurlSock = it->second;
791 CurlSock->mCurlStoreUserCount -= 1;
795 mObj.eHdlTimestamp = CurlSock->timestamp;
796 mObj.curlId = (int)CurlIndex;
797 CurlSock->mFreeQ.push_back(mObj);
798 AAMPLOG_TRACE(
"Curl Inst %d for %s CurlCtx:%p stored at %lu, User:%d", CurlIndex, hostname.c_str(),
799 curl,CurlSock->mFreeQ.size(), CurlSock->mCurlStoreUserCount);
803 AAMPLOG_INFO(
"Host %s not in store, Curlfd:%p", hostname.c_str(), curl);
805 pthread_mutex_unlock(&mCurlInstLock);
816 CurlSockDataIter it=umCurlSockDataStore.begin();
817 CurlSockDataIter RemIt=umCurlSockDataStore.end();
819 for(; it != umCurlSockDataStore.end(); ++it )
822 if( !CurlSock->mCurlStoreUserCount && ( time > CurlSock->timestamp ) )
824 time = CurlSock->timestamp;
829 if( umCurlSockDataStore.end() != RemIt )
832 AAMPLOG_INFO(
"Removing host:%s lastused:%lld UserCount:%d", (RemIt->first).c_str(), RmCurlSock->timestamp, RmCurlSock->mCurlStoreUserCount);
834 for(
auto it = RmCurlSock->mFreeQ.begin(); it != RmCurlSock->mFreeQ.end(); )
838 curl_easy_cleanup(it->curl);
840 it=RmCurlSock->mFreeQ.erase(it);
842 std::deque<CurlHandleStruct>().swap(RmCurlSock->mFreeQ);
844 if(RmCurlSock->mCurlShared)
847 curl_share_cleanup(RmCurlSock->mCurlShared);
849 pthread_mutex_destroy(&locks->mCurlSharedlock);
850 pthread_mutex_destroy(&locks->mDnsCurlShareMutex);
851 pthread_mutex_destroy(&locks->mSslCurlShareMutex);
852 SAFE_DELETE(RmCurlSock->pstShareLocks);
855 SAFE_DELETE(RmCurlSock);
856 umCurlSockDataStore.erase(RemIt);
877 AAMPLOG_INFO(
"Curl Store Size:%lu, MaxSize:%d", umCurlSockDataStore.size(),
MaxCurlSockStore);
879 CurlSockDataIter it=umCurlSockDataStore.begin();
880 for(
int loop=1; it != umCurlSockDataStore.end(); ++it,++loop )
883 AAMPLOG_INFO(
"%d.Host:%s ShHdl:%p LastUsed:%lld UserCount:%d", loop, (it->first).c_str(), CurlSock->mCurlShared, CurlSock->timestamp, CurlSock->mCurlStoreUserCount);
884 AAMPLOG_INFO(
"%d.Total Curl fds:%lu,", loop, CurlSock->mFreeQ.size());
886 for(
auto it = CurlSock->mFreeQ.begin(); it != CurlSock->mFreeQ.end(); ++it)
888 AAMPLOG_TRACE(
"CurlFd:%p Time:%lld Inst:%d", it->curl, it->eHdlTimestamp, it->curlId);