ddnet/src/engine/client/fetcher.cpp

195 lines
5.4 KiB
C++
Raw Normal View History

#include <base/system.h>
#include <engine/storage.h>
#include <engine/shared/config.h>
2017-09-03 07:18:00 +00:00
#include <game/version.h>
#include "fetcher.h"
CFetchTask::CFetchTask(bool canTimeout, bool useDDNetCA)
{
m_pNext = NULL;
m_CanTimeout = canTimeout;
m_UseDDNetCA = useDDNetCA;
}
CFetcher::CFetcher()
{
m_pStorage = NULL;
m_pHandle = NULL;
m_Lock = lock_create();
sphore_init(&m_Queued);
m_pFirst = NULL;
m_pLast = NULL;
m_Running = true;
}
bool CFetcher::Init()
{
m_pStorage = Kernel()->RequestInterface<IStorage>();
if(!curl_global_init(CURL_GLOBAL_DEFAULT) && (m_pHandle = curl_easy_init()))
return true;
return false;
}
CFetcher::~CFetcher()
{
if(m_pThHandle)
{
m_Running = false;
sphore_signal(&m_Queued);
thread_wait(m_pThHandle);
}
lock_destroy(m_Lock);
sphore_destroy(&m_Queued);
if(m_pHandle)
curl_easy_cleanup(m_pHandle);
curl_global_cleanup();
}
2015-01-19 22:00:08 +00:00
void CFetcher::QueueAdd(CFetchTask *pTask, const char *pUrl, const char *pDest, int StorageType, void *pUser, COMPFUNC pfnCompCb, PROGFUNC pfnProgCb)
{
2015-08-29 20:39:44 +00:00
str_copy(pTask->m_aUrl, pUrl, sizeof(pTask->m_aUrl));
str_copy(pTask->m_aDest, pDest, sizeof(pTask->m_aDest));
pTask->m_StorageType = StorageType;
pTask->m_pfnProgressCallback = pfnProgCb;
pTask->m_pfnCompCallback = pfnCompCb;
pTask->m_pUser = pUser;
pTask->m_Size = pTask->m_Progress = 0;
pTask->m_Abort = false;
lock_wait(m_Lock);
if(!m_pThHandle)
{
m_pThHandle = thread_init(&FetcherThread, this);
}
2015-01-19 22:00:08 +00:00
if(!m_pFirst)
{
m_pFirst = pTask;
m_pLast = m_pFirst;
}
2015-01-19 22:00:08 +00:00
else
{
m_pLast->m_pNext = pTask;
m_pLast = pTask;
}
pTask->m_State = CFetchTask::STATE_QUEUED;
lock_unlock(m_Lock);
sphore_signal(&m_Queued);
}
2015-02-12 17:58:54 +00:00
void CFetcher::Escape(char *pBuf, size_t size, const char *pStr)
{
char *pEsc = curl_easy_escape(0, pStr, 0);
str_copy(pBuf, pEsc, size);
curl_free(pEsc);
}
void CFetcher::FetcherThread(void *pUser)
{
2015-01-19 22:00:08 +00:00
CFetcher *pFetcher = (CFetcher *)pUser;
dbg_msg("fetcher", "thread started...");
while(pFetcher->m_Running)
2015-01-19 22:00:08 +00:00
{
sphore_wait(&pFetcher->m_Queued);
lock_wait(pFetcher->m_Lock);
2015-01-19 22:00:08 +00:00
CFetchTask *pTask = pFetcher->m_pFirst;
if(pTask)
pFetcher->m_pFirst = pTask->m_pNext;
lock_unlock(pFetcher->m_Lock);
2015-01-19 22:00:08 +00:00
if(pTask)
{
2017-07-25 17:23:10 +00:00
dbg_msg("fetcher", "task got %s -> %s", pTask->m_aUrl, pTask->m_aDest);
2015-07-09 00:08:14 +00:00
pFetcher->FetchFile(pTask);
2015-03-28 22:46:43 +00:00
if(pTask->m_pfnCompCallback)
pTask->m_pfnCompCallback(pTask, pTask->m_pUser);
}
}
}
void CFetcher::FetchFile(CFetchTask *pTask)
{
char aPath[512];
if(pTask->m_StorageType == -2)
2015-08-29 20:39:44 +00:00
m_pStorage->GetBinaryPath(pTask->m_aDest, aPath, sizeof(aPath));
else
2015-08-29 20:39:44 +00:00
m_pStorage->GetCompletePath(pTask->m_StorageType, pTask->m_aDest, aPath, sizeof(aPath));
2015-08-29 20:40:10 +00:00
if(fs_makedir_rec_for(aPath) < 0)
dbg_msg("fetcher", "i/o error, cannot create folder for: %s", aPath);
2015-08-29 20:40:10 +00:00
IOHANDLE File = io_open(aPath, IOFLAG_WRITE);
2017-03-04 14:43:49 +00:00
if(!File)
{
dbg_msg("fetcher", "i/o error, cannot open file: %s", pTask->m_aDest);
2015-03-28 22:41:58 +00:00
pTask->m_State = CFetchTask::STATE_ERROR;
return;
}
char aErr[CURL_ERROR_SIZE];
curl_easy_setopt(m_pHandle, CURLOPT_ERRORBUFFER, aErr);
2015-02-05 18:41:48 +00:00
//curl_easy_setopt(m_pHandle, CURLOPT_VERBOSE, 1L);
if(pTask->m_CanTimeout)
{
curl_easy_setopt(m_pHandle, CURLOPT_CONNECTTIMEOUT_MS, (long)g_Config.m_ClHTTPConnectTimeoutMs);
curl_easy_setopt(m_pHandle, CURLOPT_LOW_SPEED_LIMIT, (long)g_Config.m_ClHTTPLowSpeedLimit);
curl_easy_setopt(m_pHandle, CURLOPT_LOW_SPEED_TIME, (long)g_Config.m_ClHTTPLowSpeedTime);
}
else
{
curl_easy_setopt(m_pHandle, CURLOPT_CONNECTTIMEOUT_MS, 0);
curl_easy_setopt(m_pHandle, CURLOPT_LOW_SPEED_LIMIT, 0);
curl_easy_setopt(m_pHandle, CURLOPT_LOW_SPEED_TIME, 0);
}
2015-01-19 23:01:30 +00:00
curl_easy_setopt(m_pHandle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(m_pHandle, CURLOPT_MAXREDIRS, 4L);
curl_easy_setopt(m_pHandle, CURLOPT_FAILONERROR, 1L);
if(pTask->m_UseDDNetCA)
{
char aCAFile[512];
m_pStorage->GetBinaryPath("data/ca-ddnet.pem", aCAFile, sizeof aCAFile);
curl_easy_setopt(m_pHandle, CURLOPT_CAINFO, aCAFile);
}
2015-08-29 20:39:44 +00:00
curl_easy_setopt(m_pHandle, CURLOPT_URL, pTask->m_aUrl);
curl_easy_setopt(m_pHandle, CURLOPT_WRITEDATA, File);
curl_easy_setopt(m_pHandle, CURLOPT_WRITEFUNCTION, &CFetcher::WriteToFile);
curl_easy_setopt(m_pHandle, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(m_pHandle, CURLOPT_PROGRESSDATA, pTask);
curl_easy_setopt(m_pHandle, CURLOPT_PROGRESSFUNCTION, &CFetcher::ProgressCallback);
curl_easy_setopt(m_pHandle, CURLOPT_NOSIGNAL, 1L);
2017-09-03 07:20:46 +00:00
curl_easy_setopt(m_pHandle, CURLOPT_USERAGENT, "DDNet " GAME_RELEASE_VERSION " (" CONF_PLATFORM_STRING "; " CONF_ARCH_STRING ")");
2017-02-21 16:10:08 +00:00
dbg_msg("fetcher", "downloading %s", pTask->m_aDest);
pTask->m_State = CFetchTask::STATE_RUNNING;
int ret = curl_easy_perform(m_pHandle);
2015-07-09 00:08:14 +00:00
io_close(File);
if(ret != CURLE_OK)
2015-01-19 22:00:08 +00:00
{
dbg_msg("fetcher", "task failed. libcurl error: %s", aErr);
pTask->m_State = (ret == CURLE_ABORTED_BY_CALLBACK) ? CFetchTask::STATE_ABORTED : CFetchTask::STATE_ERROR;
}
else
{
dbg_msg("fetcher", "task done %s", pTask->m_aDest);
pTask->m_State = CFetchTask::STATE_DONE;
}
}
size_t CFetcher::WriteToFile(char *pData, size_t size, size_t nmemb, void *pFile)
{
return io_write((IOHANDLE)pFile, pData, size*nmemb);
}
int CFetcher::ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr)
{
CFetchTask *pTask = (CFetchTask *)pUser;
pTask->m_Current = DlCurr;
2015-01-28 11:57:11 +00:00
pTask->m_Size = DlTotal;
2015-01-19 22:00:08 +00:00
pTask->m_Progress = (100 * DlCurr) / (DlTotal ? DlTotal : 1);
if(pTask->m_pfnProgressCallback)
pTask->m_pfnProgressCallback(pTask, pTask->m_pUser);
return pTask->m_Abort ? -1 : 0;
2015-01-19 21:19:27 +00:00
}