/** @file JCDownloadMgr.cpp @brief @author hugao @version 1.0 @date 2016_5_11 */ #include "../downloadMgr/JCDownloadMgr.h" #include "../misc/JCThreadPool.h" #include #ifndef THIN_COMMON_WITHOUT_DOWNLOAD #include "../downloadMgr/JCCurlWrap.h" #endif #include "../util/Log.h" #include #include "../util/JCCommonMethod.h" #include #include "../util/JCLayaUrl.h" #include #include #define TIMEOUTTRYNUM 40 #define CONNECTERRTRYNUM 80 #define P_NOPOSTDATA nullptr #define P_NOTIMEOUT 0 #define P_NOCONNTIMEOUT 0 #define P_PRIORITY_NORMAL 0 #define P_PRIORITY_LOW 1 #define P_NOLOCALFILE nullptr #include #include #include #include namespace laya{ typedef std::recursive_mutex _mutex_t; static std::uint32_t _l_ServerStop = 0; int JCDownloadMgr::s_nNoResponseTimeout = 15000; int JCDownloadMgr::s_nConnTimeout = 0; int JCDownloadMgr::s_nOptTimeout = 0; bool JCDownloadMgr::s_bEncodeURI=true; bool JCDownloadMgr::m_bCancelTask = false; JCDownloadMgr* gDownloadMgr = NULL; int _OnProgress(unsigned int total, unsigned int now, float p_fSpeed, void* p_userData); std::string JCDownloadMgr::s_curlProxyString = ""; #ifndef THIN_COMMON_WITHOUT_DOWNLOAD class _QueryBase { public: virtual ~_QueryBase() { int a = 10; }; //false则重试。自己内部做sleep virtual bool run(Curl* pCurl) { return true; }; }; class _QueryDownload:public _QueryBase { protected: const char* mpPostData = nullptr; int mnPostDataLen = 0; public: short mnOptTimeout=0; short mnConnTimeout = 0; unsigned int mnTryNum = 0; bool mbOnlyHeader = false; //只下载header bool mbChkRemote = false; std::string mUrl; std::vector mHeaders; JCDownloadMgr::onProgressFunc mOnProg; JCDownloadMgr::onEndFunc mOnEnd; //注意:传过来的指针不可以保存。 std::string mstrLocalFile; //直接写文件 _QueryDownload(const char* pszUrl) { if(pszUrl) mUrl = pszUrl; } void setPostData(const char* pData, int nLen) { if (mpPostData)delete[] mpPostData; mpPostData = new char[nLen]; memcpy((void*)mpPostData, pData, nLen); mnPostDataLen = nLen; } virtual bool run(Curl* pCurl) { if (JCDownloadMgr::m_bCancelTask) { return true; } pCurl->setProgressCB(_OnProgress, this); unsigned char *pContentBuff = nullptr; size_t iContentBuffSize = 0; bool bBigFile = mstrLocalFile.length() > 0; LOGI("Download [%c%c]:%s", mbOnlyHeader ? 'H' : ' ', bBigFile ? 'B' : ' ', mUrl.c_str()); // 下载文件 JCUrl url(mUrl.c_str()); std::string encodeUrl = mUrl;// url.encode(); bool bHasQuery = url.m_Query.length() > 0; char *pszUrlBuff = gDownloadMgr->getFinalUrl(encodeUrl.c_str()); __Buffer* _pContentBuffer = NULL; pCurl->query(pszUrlBuff, &_pContentBuffer, mpPostData, mnPostDataLen, mbOnlyHeader, mnOptTimeout, mnConnTimeout, mHeaders, bBigFile ? mstrLocalFile.c_str() : nullptr, bBigFile); if (_pContentBuffer) { iContentBuffSize = _pContentBuffer->GetDataSize(); pContentBuff = (unsigned char*)_pContentBuffer->SwapBuff(0, 0); } if(mpPostData) delete mpPostData; mpPostData = NULL; if (mOnEnd) { if (pCurl->m_nCurlRet != CURLE_OK) { //curl 执行失败 static std::string nullstr; JCBuffer jb; mOnEnd(jb, pCurl->m_strLocalAddr, pCurl->m_strSvAddr, pCurl->m_nCurlRet, pCurl->m_nResponseCode, nullstr); } else { //bool bHttpOK = pCurl->m_nResponseCode >= 200 && pCurl->m_nResponseCode < 300; LOGI("Download end:%d", pCurl->m_nResponseCode); if (bBigFile || iContentBuffSize <= 0) {//大文件没有buffer JCBuffer jb; mOnEnd(jb, pCurl->m_strLocalAddr, pCurl->m_strSvAddr, CURLE_OK, pCurl->m_nResponseCode, pCurl->m_strResponseHead); } else { if(pContentBuff && iContentBuffSize>0){ int sz = iContentBuffSize; unsigned char* posthandleData = pContentBuff; gDownloadMgr->postDownload(pszUrlBuff, posthandleData, sz); iContentBuffSize = sz; if (posthandleData != pContentBuff) { delete[] pContentBuff; pContentBuff = posthandleData; } } JCBuffer buf((void*)pContentBuff, iContentBuffSize, false, true); mOnEnd(buf, pCurl->m_strLocalAddr, pCurl->m_strSvAddr, CURLE_OK, pCurl->m_nResponseCode, pCurl->m_strResponseHead); } } } delete[] pszUrlBuff; return true; } }; int _OnProgress(unsigned int total, unsigned int now, float p_fSpeed, void* p_userData) { if (!gDownloadMgr) return 1; if (gDownloadMgr->m_bCancelTask) return 1; _QueryDownload* pQ = (_QueryDownload*)p_userData; if (pQ && pQ->mOnProg) { return pQ->mOnProg(total, now, p_fSpeed); } return 0; } class _QueryFunction :public _QueryBase { public: std::function mTask; virtual bool run(Curl* pCurl) { unsigned char *pContentBuff = nullptr; size_t iContentBuffSize = 0; mTask(pCurl, &pContentBuff, &iContentBuffSize); //TODO 要回调么 return true; } }; //设置cookie file class _QuerySetCookieFile :public _QueryBase { public: //设置cookie文件。注意不一定什么时候执行,最好是在所有下载开始之前 std::string m_strSetCookieFile; _QuerySetCookieFile(const char* pszCF) { m_strSetCookieFile = pszCF; } virtual bool run(Curl* pCurl) { pCurl->setCookieFile(m_strSetCookieFile.c_str()); //请求设置cookie文件 return true; } }; //等待清空队列。 class _QueryWaitEmpty :public _QueryBase { protected: #ifdef WIN32 std::atomic_uint32_t* mpNum = nullptr; public: _QueryWaitEmpty(std::atomic_uint32_t* pNum) { mpNum = pNum; } #else std::atomic_uint* mpNum = nullptr; public: _QueryWaitEmpty(std::atomic_uint* pNum) { mpNum = pNum; } #endif virtual bool run(Curl* pCurl) { if(mpNum) (*mpNum)--; //请求停止 return true; } }; #endif //设置代理 class _QuerySetProxy :public _QueryBase { protected: std::string strProxy ; public: _QuerySetProxy(const char* pProxy) { if(pProxy) strProxy = pProxy; } virtual bool run(Curl* pCurl) { if (strProxy.length() > 0) { pCurl->setProxyString(strProxy.c_str()); } return true; } }; void JCDownloadMgr::defCompleteFunc(JCBuffer&,const std::string&, const std::string&, int,int,const std::string&){}; int JCDownloadMgr::defProgressFunc(unsigned int, unsigned int,float){return 0;} JCDownloadMgr* JCDownloadMgr::getInstance(){ if( gDownloadMgr == NULL){ gDownloadMgr = new JCDownloadMgr(); //gDownloadMgr->init(2); //线程数目 } return gDownloadMgr; } void JCDownloadMgr::delInstance(){ if(gDownloadMgr){ delete gDownloadMgr; gDownloadMgr = NULL; } } JCDownloadMgr::JCDownloadMgr(){ //_l_PoolQuery = new JCThreadPoolSingle<_Query_t *>(); m_nTryNumOpt = TIMEOUTTRYNUM; m_nTryNumConn = CONNECTERRTRYNUM; m_nStopNum = 0; m_nDownloadTailType = 0; //缺省为不加随机数,防止瞬间回流造成服务器的负载太大。 m_nThreadNum = 0; m_pCurDownloadingUrl=NULL; m_nTimeout = 0; } JCDownloadMgr::~JCDownloadMgr(){ _l_ServerStop = 1; clearAllAsyncTask(); //因为可能已经关掉了,没必要再跑一次 if(!m_bCancelTask) stopCurTask(); //if(m_pCurDownloadingUrl) // delete [] m_pCurDownloadingUrl; /* _l_PoolQuery->Stop(); if( _l_PoolQuery ){ delete _l_PoolQuery ; _l_PoolQuery = NULL; } */ } void JCDownloadMgr::setOpt_optTimeout( int p_nTimeout){ m_nTimeout = p_nTimeout; } void JCDownloadMgr::setOpt_progCB(onProgressFunc p_ProgCb){ m_funcProgress = p_ProgCb; } void JCDownloadMgr::setOpt_completeCB(onEndFunc p_CompleteCb){ m_funcComplete = p_CompleteCb; } void JCDownloadMgr::setCookieFile( const char* p_pszCookieFile ){ #ifndef THIN_COMMON_WITHOUT_DOWNLOAD m_strCookieFile = p_pszCookieFile; int num = m_ThreadPool.getThreadNum(); for( int i=0; i p_vHeaders, //size()==0则忽略 const char* p_pLocalFile, //一边下载,一边保存,一般用在大文件下载,0则忽略 bool p_bChkRemoteChange //检查远端文件是否改变了,大文件用 ) { #ifndef THIN_COMMON_WITHOUT_DOWNLOAD m_bCancelTask = false; if (0 != p_pszURL) { if (strlen(p_pszURL) <= 0) { LOGE("Error! downloadMgr::download url len=0"); return; } static int nTh = 0; int nThNum = m_ThreadPool.getThreadNum();// _l_PoolQuery->GetSize(); if (nThNum <= 0) return; _QueryDownload* pQuery = new _QueryDownload(p_pszURL); pQuery->mOnEnd = p_CompleteCb; pQuery->mOnProg = p_ProgCb; pQuery->mnOptTimeout = p_nTimeout>0?p_nTimeout:s_nOptTimeout; pQuery->mnConnTimeout = p_nConnTimeout > 0 ? p_nConnTimeout : s_nConnTimeout; pQuery->mHeaders = p_vHeaders; pQuery->mbOnlyHeader = p_bOnlyHeader; if(p_pPostData) pQuery->setPostData(p_pPostData, p_nPostLen); if (p_pLocalFile) { pQuery->mstrLocalFile = p_pLocalFile; } if (p_nPriority == 1 || nThNum == 1) m_ThreadPool.sendToThread(pQuery, 0); else { nTh %= (nThNum - 1); m_ThreadPool.sendToThread(pQuery, nTh + 1); } nTh++; } #endif } void JCDownloadMgr::download(const char* p_pszURL){ #ifndef THIN_COMMON_WITHOUT_DOWNLOAD download(p_pszURL,P_PRIORITY_NORMAL, defProgressFunc,defCompleteFunc, P_NOPOSTDATA,0, false, P_NOTIMEOUT,P_NOCONNTIMEOUT, Curl::NoHeader, P_NOLOCALFILE, false); #endif } void JCDownloadMgr::download(const char* p_pszURL, int p_nPriority, onProgressFunc p_ProgCb, onEndFunc p_CompleteCb , int p_nOptTimeout ){ #ifndef THIN_COMMON_WITHOUT_DOWNLOAD download(p_pszURL, p_nPriority, p_ProgCb, p_CompleteCb, P_NOPOSTDATA, 0, false, p_nOptTimeout, P_NOCONNTIMEOUT, Curl::NoHeader, P_NOLOCALFILE, false); #endif } void JCDownloadMgr::download(const char* p_pszURL, int p_nPriority, onProgressFunc p_ProgCb, onEndFunc p_CompleteCb, int p_nOptTimeout, int p_nConnTimeout) { #ifndef THIN_COMMON_WITHOUT_DOWNLOAD download(p_pszURL, p_nPriority, p_ProgCb, p_CompleteCb, P_NOPOSTDATA, 0, false, p_nOptTimeout, p_nConnTimeout, Curl::NoHeader, P_NOLOCALFILE, false); #endif } void JCDownloadMgr::download(const char* p_pszURL, int p_nPriority, onProgressFunc p_ProgCb, onEndFunc p_CompleteCb , int p_nOptTimeout, std::vector& p_headers){ download(p_pszURL, p_nPriority, p_ProgCb, p_CompleteCb, P_NOPOSTDATA, 0, false, p_nOptTimeout, P_NOCONNTIMEOUT, p_headers, P_NOLOCALFILE, false); } void JCDownloadMgr::downloadBigFile(const char* p_pszURL, const char* p_pszLocal, onProgressFunc p_ProgCb, onEndFunc p_CompleteCb, int p_nTryNum, int p_nOptTimeout) { #ifndef THIN_COMMON_WITHOUT_DOWNLOAD download(p_pszURL, P_PRIORITY_NORMAL, p_ProgCb, p_CompleteCb, P_NOPOSTDATA, 0, false, p_nOptTimeout, P_NOCONNTIMEOUT, Curl::NoHeader, p_pszLocal, true); #endif } void JCDownloadMgr::postToDownloadThread(std::function task, int p_nPriority) { #ifndef THIN_COMMON_WITHOUT_DOWNLOAD _QueryFunction *pQuery = new _QueryFunction(); pQuery->mTask = task; static int nTh = 0; int nThNum= m_ThreadPool.getThreadNum();// _l_PoolQuery->GetSize(); if (nThNum <= 0) return; if( p_nPriority==1 || nThNum==1) m_ThreadPool.sendToThread(pQuery, 0); else { nTh %= (nThNum - 1); m_ThreadPool.sendToThread(pQuery, nTh+1); } nTh++; #endif } void JCDownloadMgr::getHeader(const char* p_pszUrl, onEndFunc p_CompleteCb, int p_nTryNum, int p_nOptTimeout) { #ifndef THIN_COMMON_WITHOUT_DOWNLOAD download(p_pszUrl, P_PRIORITY_NORMAL, defProgressFunc, p_CompleteCb, P_NOPOSTDATA, 0, true, p_nOptTimeout, P_NOCONNTIMEOUT, Curl::NoHeader, P_NOLOCALFILE, false); #endif } void JCDownloadMgr::postData(const char* p_pszURL,const char* p_Buffer, int p_nLength, onEndFunc p_completeCb){ std::vector headers; postData(p_pszURL,p_Buffer,p_nLength,p_completeCb,headers); } void JCDownloadMgr::postData(const char* p_pszURL,const char* p_Buffer, int p_nLength, onEndFunc p_completeCb, std::vector& p_headers){ #ifndef THIN_COMMON_WITHOUT_DOWNLOAD m_bCancelTask = false; _QueryDownload* pQuery = new _QueryDownload(p_pszURL); pQuery->mOnEnd = p_completeCb; pQuery->setPostData(p_Buffer, p_nLength); pQuery->mHeaders = p_headers; m_ThreadPool.sendToThread(pQuery,0); #endif } void JCDownloadMgr::clearAllAsyncTask(){ int num = m_ThreadPool.getThreadNum(); for( int i=0; iClearDataOfThread(i); m_ThreadPool.ClearDataOfThread(i); } } void JCDownloadMgr::stopCurTask(){ #ifndef THIN_COMMON_WITHOUT_DOWNLOAD m_bCancelTask = true; //等待所有的线程完成 int num = m_ThreadPool.getThreadNum(); for( int i=0; i0 && tmGetCurms()-st<3000){ left = m_nStopNum; } LOGI("stopCurTask end stopnum=%d",(int)m_nStopNum); #endif } void JCDownloadMgr::setProxyString(const char* pProxy) { int nThNum = m_ThreadPool.getThreadNum();// _l_PoolQuery->GetSize(); if (nThNum <= 0) return; for (int i = 0; i < nThNum; i++) { _QuerySetProxy *pQuery = new _QuerySetProxy(pProxy); m_ThreadPool.sendToThread(pQuery, i); } } void JCDownloadMgr::init( int p_nWorkThreadNum ){ #ifndef THIN_COMMON_WITHOUT_DOWNLOAD Curl::global_init(); #endif //等10ms是为了防止上一个线程还没有起来(假如存在的话)。 //否则:这里设置了_l_ServerStop=true会被线程起来后_l_ServerStop=false冲掉。 std::this_thread::sleep_for(std::chrono::milliseconds(10)); _l_ServerStop = true;//这个是为了能让之前的线程正确退出。 m_nThreadNum = p_nWorkThreadNum; //m_pCurDownloadingUrl = new char* [p_nWorkThreadNum]; //memset(m_pCurDownloadingUrl,0,p_nWorkThreadNum*sizeof(char*)); m_ThreadPool.setThreadName("download thread"); m_ThreadPool.init(p_nWorkThreadNum, std::bind(&JCDownloadMgr::__WorkThread, this)); /* _l_PoolQuery->Stop(); //TODO 如果加上stop会导致死锁。 for(int i=0;iCreateThread( std::bind(&downloadMgr::__WorkThread, this) ); } */ } inline void _addsplitchar(std::string& str){ if( str.at(0)=='/'){} else if(str.at(0)=='\\') str.at(0)='/'; else str=std::string("/")+str; if( str.at(str.length()-1)=='/'){} else if(str.at(str.length()-1)=='\\') str.at(str.length()-1)='/'; else str+="/"; } void JCDownloadMgr::setFinalReplacePath(const char* p_pszPath, const char* p_pszReplace){ m_strStubPath = p_pszPath?p_pszPath:""; m_strStubReplace = p_pszReplace?p_pszReplace:""; if(m_strStubPath.length()>0){ _addsplitchar(m_strStubPath); _addsplitchar(m_strStubReplace); } LOGI("setFinalReplacePath:%s,%s", m_strStubPath.c_str(), m_strStubReplace.c_str()); } void JCDownloadMgr::setDownloadTail(int type, const char* p_strTail){ if(type<0||type>2) type=1; m_nDownloadTailType = type; if( m_nDownloadTailType==2){ if(p_strTail) m_strDownloadTail = p_strTail; else m_nDownloadTailType=1; } } void JCDownloadMgr::__WorkThread(){ #ifndef THIN_COMMON_WITHOUT_DOWNLOAD _l_ServerStop = false; _QueryBase *pQuery; #ifdef WIN32 srand(timeGetTime()); #else //TODO 随机数种子 在线程中访问全局随机数可能有问题 #endif Curl _lCurl; if( !_lCurl.Init() ){ printf("Curl init failed, thread exit\n"); return; } for(;0==_l_ServerStop;){ pQuery = 0; //现在的waitdata返回false不再表示要退出。 //if( !m_ThreadPool.waitData(&pQuery ) ) // break; //if( !_l_PoolQuery->WaitData( &pQuery ) ) // break; void* pThread = m_ThreadPool.getCurThread(); int nID = m_ThreadPool.getCurThreadNo(pThread); if( !m_ThreadPool.waitData(pThread,&pQuery ) ){ continue; } if( 0 != pQuery ){ while (! pQuery->run(&_lCurl)) { LOGI("processQuery 再次尝试"); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } delete pQuery; } } _lCurl.Release(); #endif } char* JCDownloadMgr::getFinalUrl(const char* p_pszUrl){ size_t iSize = strlen(p_pszUrl); char *pszUrlBuff = new char[iSize+512];//这里大小会有问题么 const char* pQuery = strchr(p_pszUrl,'?'); bool bQuery = pQuery!=0; //扩展名 std::string pathNoExt; //没有扩展名,没有query的部分 std::string ext; const char* pExtDot = NULL; const char* pExtEnd = NULL; int extreplaceSz = m_vExtReplace.size(); if(extreplaceSz==0 && m_strStubPath.length()==0 ){ //简单情况 strcpy(pszUrlBuff,p_pszUrl); }else{ //if(extreplaceSz) { int urllen = strlen(p_pszUrl); pExtEnd = pQuery?(pQuery-1):(p_pszUrl+urllen-1); char* pCurDt=(char*)pExtEnd; while(pCurDt>p_pszUrl){ if(*pCurDt=='/'||*pCurDt==':'||*pCurDt=='\\') break; //没有扩展名 if(*pCurDt=='.'){ pExtDot=pCurDt; } pCurDt--; } if( pExtDot==pExtEnd) pExtDot=NULL; if( pExtDot ){ pathNoExt.append(p_pszUrl,(pExtDot-p_pszUrl)); ext.append(pExtDot+1,(pExtEnd-pExtDot)); for( int i=0; i=3){ const char* pPos = strstr(pPathNoExt,m_strStubPath.c_str()); if(pPos){//&&(!bQuery||pPosquery( pszUrlBuff, &pResBuffer, Curl::__Type_GET ); if( ecode == Curl::EC_DownloadTimeout||ecode==Curl::EC_PartialFile){ LOGW("download timeout. i=%d",i); int UNK=0; std::this_thread::sleep_for(std::chrono::milliseconds(100)); }else if(ecode==Curl::EC_Success){ *p_piSize = pResBuffer->GetDataSize(); *p_ppBuff = (unsigned char *)pResBuffer->SwapBuff( 0, 0 ); if( *p_piSize>0 && (void*)*p_ppBuff ){ int bufsz = (int)*p_piSize; unsigned char* pBuff = *p_ppBuff; postDownload(pszUrlBuff, pBuff, bufsz); *p_piSize = bufsz; if( *p_ppBuff != pBuff){ delete [] *p_ppBuff; *p_ppBuff = pBuff; } } break; }else if(ecode==Curl::EC_ConnectError){ if( i==0){trynum=m_nTryNumConn; } int UNK=0; LOGW("connect timeout ! i=%d,trynum=%d,m_bCanceltask=%d", i, trynum, m_bCancelTask); std::this_thread::sleep_for(std::chrono::milliseconds(100)); }else if(ecode==Curl::EC_404){ LOGE("download err:404"); *p_ppBuff=0; *p_piSize=0; break; }else if(ecode==Curl::EC_Cancel){ *p_ppBuff=0; *p_piSize=0; break; } else{ //其他错误 LOGE("download unk error!"); break; } } delete [] pszUrlBuff; return ecode; */ return 0; } int JCDownloadMgr::__DownloadHeader(void *p_pCurl, const char *p_pszUrl, unsigned char **p_ppBuff, size_t *p_piSize,bool p_bHaveQuery, int p_nOptTimeout, int p_nTryNum) { /* TODO 打开 Curl * pCurl = (Curl*)p_pCurl; *p_ppBuff = 0; *p_piSize = 0; __Buffer *pResBuffer = NULL; char *pszUrlBuff = getFinalUrl(p_pszUrl); LOGI("流程:DownloadHeader:%s", pszUrlBuff); //JCErrorHandleInterface* pEH = getErrorHandler(); int i = 0; Curl::ErrorCode ecode = Curl::EC_Unknown; int trynum = p_nTryNum; for (; idownloadHeader(pszUrlBuff, &pResBuffer, p_nOptTimeout); if (ecode == Curl::EC_DownloadTimeout || ecode == Curl::EC_PartialFile) { LOGW("download timeout. i=%d", i); int UNK = 0; //if (pEH) pEH->networkSlowly((float)UNK,pCurl->m_nResponseCode); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } else if (ecode == Curl::EC_Success) { *p_piSize = pResBuffer->GetDataSize(); *p_ppBuff = (unsigned char *)pResBuffer->SwapBuff(0, 0); break; } else if (ecode == Curl::EC_ConnectError) { if (i == 0) { trynum = m_nTryNumConn; } int UNK = 0; LOGW("connect timeout ! i=%d,trynum=%d,m_bCanceltask=%d", i, trynum, m_bCancelTask); //if (pEH) pEH->networkSlowly((float)UNK,pCurl->m_nResponseCode); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } else if (ecode == Curl::EC_404) { LOGE("download err:404"); break; } else if (ecode == Curl::EC_Cancel) { break; } else { //其他错误 LOGE("download unk error!"); break; } } delete[] pszUrlBuff; return ecode; */ return 0; } int JCDownloadMgr::__DownloadBigFile(void *p_pCurl, const char *p_pszUrl, const char* p_pszLocal, bool p_bHaveQuery, int p_nOptTimeout, int p_nTryNum){ /* Curl * pCurl = (Curl*)p_pCurl; char *pszUrlBuff = getFinalUrl(p_pszUrl); LOGI("流程:DownloadFile:%s",pszUrlBuff); int i=0; Curl::ErrorCode ecode=Curl::EC_Unknown; int trynum = p_nTryNum; for(;idownloadBigFile(pszUrlBuff, p_pszLocal, p_nOptTimeout ); if( ecode == Curl::EC_DownloadTimeout||ecode==Curl::EC_PartialFile){ LOGW("download timeout. i=%d",i); int UNK=0; //JCErrorHandleInterface* pEH = getErrorHandler(); //if (pEH) pEH->networkSlowly((float)UNK,pCurl->m_nResponseCode); std::this_thread::sleep_for(std::chrono::milliseconds(100)); }else if(ecode==Curl::EC_Success){ break; }else if(ecode==Curl::EC_ConnectError){ if( i==0){trynum=m_nTryNumConn; } int UNK=0; LOGW("connect timeout ! i=%d,trynum=%d,m_bCanceltask=%d", i, trynum, m_bCancelTask); //JCErrorHandleInterface* pEH = getErrorHandler(); //if (pEH) // pEH->networkSlowly((float)UNK, pCurl->m_nResponseCode); std::this_thread::sleep_for(std::chrono::milliseconds(100)); }else if(ecode==Curl::EC_404){ LOGE("download err:404"); break; }else if(ecode==Curl::EC_Cancel){ break; } else{ //其他错误 LOGE("download unk error!"); break; } } delete [] pszUrlBuff; return ecode; */ return 0; } bool JCDownloadMgr::postDownload(const char* p_pszUrl, unsigned char*& p_pBuff, int& p_nLen ){ if( !p_pszUrl) return true; std::string ext = getLowercaseExtOfUrl(p_pszUrl); maskinfo mi = getMaskInfo(ext.c_str()); if(mi.key) maskBuffer(mi, (char*)p_pBuff, p_nLen ); return true; } void JCDownloadMgr::setDownloadReplaceExt(const char* p_pszOrigin, const char* p_pszNew ){ if(p_pszOrigin==NULL || p_pszNew==NULL) return; for(int i=0,sz=m_vExtReplace.size(); ip_nLen?p_nLen:p_mask.len; unsigned char key = p_mask.key&0xff; for( int i=0; i