1397 lines
34 KiB
C
1397 lines
34 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <libuv_dbus.h>
|
|
#include <curl/curl.h>
|
|
#include <uthash/uthash.h>
|
|
#include <uthash/utstring.h>
|
|
#include <unistd.h>
|
|
#include <uuid/uuid.h>
|
|
#include <quickmail.h>
|
|
#include <uthash/utlist.h>
|
|
|
|
#include "log.h"
|
|
#include "inet_api.h"
|
|
|
|
#define MAX_TIMEOUT_VALUE (10)
|
|
#define SSL_CA_FILE ("/etc/ssl/certs/ca-certificates.crt")
|
|
|
|
typedef enum
|
|
{
|
|
INET_HTTP_DOWNLOAD_FILE = 0,
|
|
INET_HTTP_WEBSERVICE_POST,
|
|
} INET_ACCESS_TYPE;
|
|
|
|
typedef struct
|
|
{
|
|
uv_poll_t uvPool;
|
|
curl_socket_t sock;
|
|
} CURL_CONTEXT_DATA, *PCURL_CONTEXT_DATA;
|
|
|
|
typedef struct
|
|
{
|
|
char* pReqUrl;
|
|
char sPath[MAX_PATH];
|
|
char sDlPath[MAX_PATH];
|
|
char* pTaskUuid;
|
|
INET_ACCESS_TYPE type;
|
|
unsigned int dlSize;
|
|
unsigned int lastTm;
|
|
unsigned int createTm;
|
|
uv_fs_t uvFsOpen;
|
|
uv_fs_t uvFsWrite;
|
|
uv_fs_t uvFsDataSync;
|
|
uv_fs_t uvFsClose;
|
|
uv_buf_t uvFsBuf;
|
|
OnProgressNotify onPrgCb;
|
|
OnHttpResponse onRspCb;
|
|
int isCancel;
|
|
CURL* pCurl;
|
|
void* pData;
|
|
int errCode;
|
|
} HTTP_REQ_PARAMS, *PHTTP_REQ_PARAMS;
|
|
|
|
typedef struct
|
|
{
|
|
char *pTaskUuid;
|
|
unsigned int uRetryTimes;
|
|
PHTTP_REQ_PARAMS pCurlItem;
|
|
|
|
UT_hash_handle hh; ///< UT Hash handle
|
|
} CURL_HANDLE_TBL, *PCURL_HANDLE_TBL;
|
|
|
|
static uv_timer_t g_uvCurlTm;
|
|
static uv_timer_t g_uvDlTm;
|
|
static CURLM* g_pCurl = NULL;
|
|
static uv_loop_t* g_pMainLoop = NULL;
|
|
static PCURL_HANDLE_TBL g_ReqHandleTbl = NULL;
|
|
static uv_rwlock_t g_uvHashRwLock;
|
|
static unsigned g_TotalDownloads = 0;
|
|
|
|
static void __addReqIdToTable(const char* pTaskUuid, PHTTP_REQ_PARAMS pParams)
|
|
{
|
|
PCURL_HANDLE_TBL pItem = NULL;
|
|
|
|
HASH_FIND_STR(g_ReqHandleTbl, pTaskUuid, pItem);
|
|
|
|
if(pItem == NULL)
|
|
{
|
|
pItem = (PCURL_HANDLE_TBL)malloc(sizeof(CURL_HANDLE_TBL));
|
|
|
|
memset(pItem, 0, sizeof(CURL_HANDLE_TBL));
|
|
pItem->pTaskUuid = (char*)pTaskUuid;
|
|
|
|
uv_rwlock_wrlock(&g_uvHashRwLock);
|
|
HASH_ADD_STR(g_ReqHandleTbl, pTaskUuid, pItem);
|
|
uv_rwlock_wrunlock(&g_uvHashRwLock);
|
|
}
|
|
|
|
pItem->pCurlItem = pParams;
|
|
pItem->uRetryTimes++;
|
|
}
|
|
|
|
static void __removeReqIdFromTable(const char* pTaskUuid)
|
|
{
|
|
PCURL_HANDLE_TBL pItem = NULL;
|
|
|
|
uv_rwlock_wrlock(&g_uvHashRwLock);
|
|
HASH_FIND_STR(g_ReqHandleTbl, pTaskUuid, pItem);
|
|
if(pItem != NULL)
|
|
{
|
|
HASH_DEL(g_ReqHandleTbl, pItem);
|
|
|
|
if(pItem->pTaskUuid)
|
|
{
|
|
free(pItem->pTaskUuid);
|
|
}
|
|
|
|
free(pItem);
|
|
}
|
|
uv_rwlock_wrunlock(&g_uvHashRwLock);
|
|
}
|
|
|
|
static void __cancelDownloadTask(PHTTP_REQ_PARAMS pItem)
|
|
{
|
|
if(pItem)
|
|
{
|
|
pItem->isCancel = TRUE;
|
|
}
|
|
}
|
|
|
|
static void __uvFsCloseCb(uv_fs_t *puvFs)
|
|
{
|
|
PHTTP_REQ_PARAMS pParams = (PHTTP_REQ_PARAMS)puvFs->data;
|
|
|
|
if(puvFs->result < 0)
|
|
{
|
|
LOG_EX(LOG_Error, "[%s] Error: %d\n", __FUNCTION__, puvFs->result);
|
|
}
|
|
|
|
uv_fs_req_cleanup(puvFs);
|
|
|
|
if(pParams->type == INET_HTTP_DOWNLOAD_FILE)
|
|
{
|
|
if(strcmp(pParams->sDlPath, pParams->sPath) != 0)
|
|
{
|
|
CopyFile(pParams->sDlPath, pParams->sPath);
|
|
unlink(pParams->sDlPath);
|
|
}
|
|
|
|
if(pParams->errCode == CURLE_ABORTED_BY_CALLBACK)
|
|
{
|
|
pParams->errCode = CURLE_OPERATION_TIMEDOUT;
|
|
}
|
|
|
|
if(pParams->onRspCb && pParams->isCancel == FALSE)
|
|
{
|
|
pParams->onRspCb(NULL, pParams->dlSize, pParams->pReqUrl, pParams->sPath,
|
|
pParams->pTaskUuid, -pParams->errCode, pParams->pData);
|
|
}
|
|
}
|
|
|
|
__removeReqIdFromTable(pParams->pTaskUuid);
|
|
|
|
if(pParams->pReqUrl)
|
|
{
|
|
free(pParams->pReqUrl);
|
|
pParams->pReqUrl = NULL;
|
|
}
|
|
|
|
free(pParams);
|
|
pParams = NULL;
|
|
}
|
|
|
|
static void __uvFsDataSyncCb(uv_fs_t *puvFs)
|
|
{
|
|
PHTTP_REQ_PARAMS pParams = (PHTTP_REQ_PARAMS)puvFs->data;
|
|
|
|
if(puvFs->result < 0)
|
|
{
|
|
LOG_EX(LOG_Error, "[%s] Error: %d\n", __FUNCTION__, puvFs->result);
|
|
}
|
|
|
|
uv_fs_req_cleanup(puvFs);
|
|
|
|
uv_fs_close(g_pMainLoop, &pParams->uvFsClose, pParams->uvFsOpen.result, __uvFsCloseCb);
|
|
}
|
|
|
|
static PCURL_CONTEXT_DATA __createCurlContext(curl_socket_t sock)
|
|
{
|
|
PCURL_CONTEXT_DATA pContext = (PCURL_CONTEXT_DATA)malloc(sizeof(CURL_CONTEXT_DATA));
|
|
|
|
pContext->sock = sock;
|
|
|
|
if(uv_poll_init_socket(g_pMainLoop, &pContext->uvPool, sock) != 0)
|
|
{
|
|
LOG_EX(LOG_Error, "uv_poll_init_socket Error\n");
|
|
}
|
|
|
|
pContext->uvPool.data = pContext;
|
|
|
|
return (pContext);
|
|
}
|
|
|
|
static void __uvCloseCb(uv_handle_t *puvPoll)
|
|
{
|
|
PCURL_CONTEXT_DATA pContext = (PCURL_CONTEXT_DATA)puvPoll->data;
|
|
free(pContext);
|
|
}
|
|
|
|
static void __destoryCurlContext(PCURL_CONTEXT_DATA pContext)
|
|
{
|
|
uv_close((uv_handle_t *)&pContext->uvPool, __uvCloseCb);
|
|
}
|
|
|
|
static void __checkMultiInfoTimeout(void)
|
|
{
|
|
PHTTP_REQ_PARAMS pReq;
|
|
CURLMsg *pMsg = NULL;
|
|
int iPending;
|
|
|
|
while((pMsg = curl_multi_info_read(g_pCurl, &iPending)))
|
|
{
|
|
switch(pMsg->msg)
|
|
{
|
|
case CURLMSG_DONE:
|
|
curl_easy_getinfo(pMsg->easy_handle, CURLINFO_PRIVATE, (void*)&pReq);
|
|
|
|
LOG_EX(LOG_Debug, "Cleanup CURL: %p\n", pMsg->easy_handle);
|
|
|
|
curl_multi_remove_handle(g_pCurl, pMsg->easy_handle);
|
|
curl_easy_cleanup(pMsg->easy_handle);
|
|
|
|
if(pReq)
|
|
{
|
|
if(pReq->type == INET_HTTP_DOWNLOAD_FILE)
|
|
{
|
|
uv_fs_close(g_pMainLoop, &pReq->uvFsDataSync, pReq->uvFsOpen.result, NULL);
|
|
}
|
|
|
|
if(pReq->onRspCb && pReq->isCancel == FALSE)
|
|
{
|
|
pReq->onRspCb(NULL, 0, pReq->pReqUrl, pReq->sPath, pReq->pTaskUuid,
|
|
-CURLE_OPERATION_TIMEDOUT, pReq->pData);
|
|
}
|
|
|
|
if(pReq->pReqUrl)
|
|
{
|
|
free(pReq->pReqUrl);
|
|
pReq->pReqUrl = NULL;
|
|
}
|
|
|
|
__removeReqIdFromTable(pReq->pTaskUuid);
|
|
|
|
free(pReq);
|
|
pReq = NULL;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
LOG_EX(LOG_Error, "pMsg->msg(%d) != CURLMSG_DONE\n", pMsg->msg);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void __checkMultiInfo(void)
|
|
{
|
|
PHTTP_REQ_PARAMS pReq;
|
|
CURLMsg *pMsg = NULL;
|
|
int iPending;
|
|
|
|
while((pMsg = curl_multi_info_read(g_pCurl, &iPending)))
|
|
{
|
|
switch(pMsg->msg)
|
|
{
|
|
case CURLMSG_DONE:
|
|
curl_easy_getinfo(pMsg->easy_handle, CURLINFO_PRIVATE, (void*)&pReq);
|
|
|
|
curl_multi_remove_handle(g_pCurl, pMsg->easy_handle);
|
|
LOG_EX(LOG_Debug, "Cleanup CURL: %p\n", pMsg->easy_handle);
|
|
curl_easy_cleanup(pMsg->easy_handle);
|
|
|
|
if(pReq)
|
|
{
|
|
if(pReq->type == INET_HTTP_DOWNLOAD_FILE)
|
|
{
|
|
if(pMsg->data.result != CURLE_OK)
|
|
{
|
|
pReq->errCode = pMsg->data.result;
|
|
}
|
|
else
|
|
{
|
|
pReq->errCode = 0;
|
|
}
|
|
|
|
uv_fs_fdatasync(g_pMainLoop, &pReq->uvFsDataSync, pReq->uvFsOpen.result, __uvFsDataSyncCb);
|
|
}
|
|
else if(pReq->type == INET_HTTP_WEBSERVICE_POST)
|
|
{
|
|
if(pMsg->data.result != CURLE_OK)
|
|
{
|
|
if(pReq->onRspCb && pReq->isCancel == FALSE)
|
|
{
|
|
pReq->onRspCb(pReq->uvFsBuf.base, pReq->dlSize, pReq->pReqUrl, pReq->sPath,
|
|
pReq->pTaskUuid, -pMsg->data.result, pReq->pData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pReq->onRspCb && pReq->isCancel == FALSE)
|
|
{
|
|
pReq->onRspCb(pReq->uvFsBuf.base, pReq->dlSize, pReq->pReqUrl, pReq->sPath,
|
|
pReq->pTaskUuid, 0, pReq->pData);
|
|
}
|
|
}
|
|
|
|
if(pReq->uvFsBuf.base)
|
|
{
|
|
free(pReq->uvFsBuf.base);
|
|
}
|
|
|
|
if(pReq->pReqUrl)
|
|
{
|
|
free(pReq->pReqUrl);
|
|
pReq->pReqUrl = NULL;
|
|
}
|
|
|
|
__removeReqIdFromTable(pReq->pTaskUuid);
|
|
|
|
free(pReq);
|
|
pReq = NULL;
|
|
}
|
|
else
|
|
{
|
|
if(pMsg->data.result != CURLE_OK)
|
|
{
|
|
if(pReq->onRspCb && pReq->isCancel == FALSE){
|
|
pReq->onRspCb(NULL, 0, pReq->pReqUrl, pReq->sPath, pReq->pTaskUuid, -pMsg->data.result, pReq->pData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pReq->onRspCb && pReq->isCancel == FALSE)
|
|
{
|
|
pReq->onRspCb(NULL, 0, pReq->pReqUrl, pReq->sPath, pReq->pTaskUuid, 0, pReq->pData);
|
|
}
|
|
}
|
|
|
|
if(pReq->pReqUrl)
|
|
{
|
|
free(pReq->pReqUrl);
|
|
pReq->pReqUrl = NULL;
|
|
}
|
|
|
|
__removeReqIdFromTable(pReq->pTaskUuid);
|
|
|
|
free(pReq);
|
|
pReq = NULL;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
LOG_EX(LOG_Error, "pMsg->msg(%d) != CURLMSG_DONE\n", pMsg->msg);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void __onDlTmoutCb(uv_timer_t *pufTimer)
|
|
{
|
|
PCURL_HANDLE_TBL pItem = NULL, pTemp = NULL;
|
|
unsigned int curTm = (unsigned int)LIBUV_CURRENT_TIME_S();
|
|
|
|
HASH_ITER(hh, g_ReqHandleTbl, pItem, pTemp)
|
|
{
|
|
int dlTime;
|
|
|
|
if(pItem->pCurlItem->isCancel)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
dlTime = curTm - pItem->pCurlItem->createTm;
|
|
|
|
// 下载时间大于10s且平均下载速度小于10K/s超时
|
|
if((dlTime * 10000 > pItem->pCurlItem->dlSize) && dlTime > 10)
|
|
{
|
|
LOG_EX(LOG_Error, "Download Speed less than 10k/s: %s (%uK/%ds)\n",
|
|
pItem->pTaskUuid, pItem->pCurlItem->dlSize / 1000, dlTime);
|
|
|
|
__cancelDownloadTask(pItem->pCurlItem);
|
|
if(pItem->pCurlItem->onRspCb)
|
|
{
|
|
pItem->pCurlItem->onRspCb(NULL,
|
|
pItem->pCurlItem->dlSize,
|
|
pItem->pCurlItem->pReqUrl,
|
|
pItem->pCurlItem->sPath,
|
|
pItem->pCurlItem->pTaskUuid,
|
|
-CURLE_OPERATION_TIMEDOUT,
|
|
pItem->pCurlItem->pData);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// 10秒内没有下载任何数据超时
|
|
if(pItem->pCurlItem->lastTm > 0)
|
|
{
|
|
if(curTm > pItem->pCurlItem->lastTm + MAX_TIMEOUT_VALUE)
|
|
{
|
|
LOG_EX(LOG_Error, "Download Timeout: %s\n", pItem->pTaskUuid);
|
|
__cancelDownloadTask(pItem->pCurlItem);
|
|
if(pItem->pCurlItem->onRspCb)
|
|
{
|
|
pItem->pCurlItem->onRspCb(NULL,
|
|
pItem->pCurlItem->dlSize,
|
|
pItem->pCurlItem->pReqUrl,
|
|
pItem->pCurlItem->sPath,
|
|
pItem->pCurlItem->pTaskUuid,
|
|
-CURLE_OPERATION_TIMEDOUT,
|
|
pItem->pCurlItem->pData);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 下载最长时间设置为1800秒(30分钟)
|
|
if(dlTime > 1800)
|
|
{
|
|
LOG_EX(LOG_Error, "Download More than 1800 seconds: %s (%uK/%ds)\n",
|
|
pItem->pTaskUuid, pItem->pCurlItem->dlSize/1000, dlTime);
|
|
__cancelDownloadTask(pItem->pCurlItem);
|
|
if(pItem->pCurlItem->onRspCb)
|
|
{
|
|
pItem->pCurlItem->onRspCb(NULL,
|
|
pItem->pCurlItem->dlSize,
|
|
pItem->pCurlItem->pReqUrl,
|
|
pItem->pCurlItem->sPath,
|
|
pItem->pCurlItem->pTaskUuid,
|
|
-CURLE_OPERATION_TIMEDOUT,
|
|
pItem->pCurlItem->pData);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void __onTimeoutCb(uv_timer_t *pufTimer)
|
|
{
|
|
int iRun;
|
|
|
|
curl_multi_socket_action(g_pCurl, CURL_SOCKET_TIMEOUT, 0, &iRun);
|
|
|
|
__checkMultiInfoTimeout();
|
|
}
|
|
|
|
static int __curlTimerCb(CURLM *multi, /* multi handle */
|
|
long timeout_ms, /* see above */
|
|
void *userp) /* private callback pointer */
|
|
{
|
|
if(timeout_ms <= 0)
|
|
{
|
|
timeout_ms = 1;
|
|
}
|
|
|
|
uv_timer_start(&g_uvCurlTm, __onTimeoutCb, timeout_ms, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void __curlPollCb(uv_poll_t *pPoll, int status, int events)
|
|
{
|
|
int iRun;
|
|
int flags;
|
|
PCURL_CONTEXT_DATA pContext = NULL;
|
|
|
|
uv_timer_stop(&g_uvCurlTm);
|
|
|
|
if(events & UV_READABLE)
|
|
{
|
|
flags = CURL_CSELECT_IN;
|
|
}
|
|
else if(events & UV_WRITABLE)
|
|
{
|
|
flags = CURL_CSELECT_OUT;
|
|
}
|
|
|
|
pContext = (PCURL_CONTEXT_DATA)pPoll;
|
|
curl_multi_socket_action(g_pCurl, pContext->sock, flags, &iRun);
|
|
__checkMultiInfo();
|
|
}
|
|
|
|
static int __curlSockCb(CURL *easy, /* easy handle */
|
|
curl_socket_t s, /* socket */
|
|
int what, /* describes the socket */
|
|
void *userp, /* private callback pointer */
|
|
void *socketp) /* private socket pointer */
|
|
{
|
|
PCURL_CONTEXT_DATA pContext = NULL;
|
|
|
|
if(what == CURL_POLL_IN || what == CURL_POLL_OUT)
|
|
{
|
|
if(socketp)
|
|
{
|
|
pContext = (PCURL_CONTEXT_DATA)socketp;
|
|
}
|
|
else
|
|
{
|
|
pContext = __createCurlContext(s);
|
|
}
|
|
|
|
curl_multi_assign(g_pCurl, s, (void *)pContext);
|
|
}
|
|
|
|
switch(what)
|
|
{
|
|
case CURL_POLL_IN:
|
|
uv_poll_start(&pContext->uvPool, UV_READABLE, __curlPollCb);
|
|
break;
|
|
|
|
case CURL_POLL_OUT:
|
|
uv_poll_start(&pContext->uvPool, UV_WRITABLE, __curlPollCb);
|
|
break;
|
|
|
|
case CURL_POLL_REMOVE:
|
|
if(socketp)
|
|
{
|
|
uv_poll_stop(&((PCURL_CONTEXT_DATA)socketp)->uvPool);
|
|
__destoryCurlContext((PCURL_CONTEXT_DATA)socketp);
|
|
curl_multi_assign(g_pCurl, s, NULL);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return (0);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static size_t __writeDataCb(void *pData, size_t size, size_t nmemb, void *pParams)
|
|
{
|
|
PHTTP_REQ_PARAMS pReq = (PHTTP_REQ_PARAMS)pParams;
|
|
int iMemSize = size * nmemb;
|
|
|
|
//print_hex_dump_bytes("OTA", DUMP_PREFIX_ADDRESS, pData, size * nmemb);
|
|
|
|
if(pReq->isCancel)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
pReq->lastTm = LIBUV_CURRENT_TIME_S();
|
|
|
|
if(pReq->type == INET_HTTP_DOWNLOAD_FILE)
|
|
{
|
|
int wr = 0;
|
|
|
|
pReq->uvFsBuf = uv_buf_init(pData, iMemSize);
|
|
|
|
wr = uv_fs_write(g_pMainLoop, &pReq->uvFsWrite, pReq->uvFsOpen.result, &pReq->uvFsBuf, 1, -1, NULL);
|
|
|
|
if(wr > 0)
|
|
{
|
|
pReq->dlSize += wr;
|
|
}
|
|
}
|
|
else if(pReq->type == INET_HTTP_WEBSERVICE_POST)
|
|
{
|
|
int newSize = 0;
|
|
|
|
if(pReq->uvFsBuf.base == NULL && pReq->uvFsBuf.len == 0)
|
|
{
|
|
newSize = iMemSize + 1;
|
|
//fprintf(stdout, "size = %d, newsize = %d, dlsize = %d\n", iMemSize, newSize, pReq->dlSize);
|
|
pReq->uvFsBuf.base = malloc(newSize);
|
|
memcpy(pReq->uvFsBuf.base, pData, iMemSize);
|
|
}
|
|
else
|
|
{
|
|
newSize = pReq->dlSize + iMemSize + 1;
|
|
//fprintf(stdout, "::size = %d, newsize = %d, dlsize = %d\n", iMemSize, newSize, pReq->dlSize);
|
|
pReq->uvFsBuf.base = realloc(pReq->uvFsBuf.base, newSize);
|
|
memcpy(pReq->uvFsBuf.base + pReq->dlSize, pData, iMemSize);
|
|
}
|
|
|
|
pReq->uvFsBuf.base[pReq->dlSize] = 0;
|
|
pReq->dlSize += iMemSize;
|
|
}
|
|
|
|
return (size * nmemb);
|
|
}
|
|
|
|
static int __progressCb(void* pData,
|
|
double total,
|
|
double now,
|
|
double ultotal,
|
|
double ulnow)
|
|
{
|
|
PHTTP_REQ_PARAMS pParams = (PHTTP_REQ_PARAMS)pData;
|
|
|
|
if(pParams->onPrgCb)
|
|
{
|
|
if(pParams->type == INET_HTTP_DOWNLOAD_FILE)
|
|
{
|
|
pParams->onPrgCb(pParams->pReqUrl, pParams->pTaskUuid, (unsigned char)(now * 100.0 / total), pParams->pData);
|
|
}
|
|
}
|
|
|
|
if(pParams->isCancel)
|
|
{
|
|
LOG_EX(LOG_Debug, "Cancel Download: %s\n", pParams->pTaskUuid);
|
|
return (-CURLE_OPERATION_TIMEDOUT);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static size_t __getRemoteSizeCb(void *pData, size_t size, size_t nmemb, void *pParams)
|
|
{
|
|
return (size * nmemb);
|
|
}
|
|
|
|
static int __iNetGetRemoteSize(const char* pURL, unsigned int reqId)
|
|
{
|
|
double size = 0.0;
|
|
CURL *pCurl = curl_easy_init();
|
|
CURLcode res;
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_URL, pURL);
|
|
curl_easy_setopt(pCurl, CURLOPT_NOBODY, 1L);
|
|
curl_easy_setopt(pCurl, CURLOPT_HEADERFUNCTION, __getRemoteSizeCb);
|
|
curl_easy_setopt(pCurl, CURLOPT_FOLLOWLOCATION, 1L);
|
|
|
|
curl_easy_perform(pCurl);
|
|
|
|
res = curl_easy_getinfo(pCurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &size);
|
|
|
|
if(res != CURLE_OK)
|
|
{
|
|
return (-1);
|
|
}
|
|
|
|
curl_easy_cleanup(pCurl);
|
|
|
|
return (int)(size);
|
|
}
|
|
|
|
#if 0
|
|
static const char* __restartDlFileAsync(PHTTP_REQ_PARAMS pParams)
|
|
{
|
|
CURL *pCurl = curl_easy_init();
|
|
|
|
pParams->type = INET_HTTP_DOWNLOAD_FILE;
|
|
pParams->dlSize = 0;
|
|
pParams->pCurl = pCurl;
|
|
pParams->lastTm = 0;
|
|
|
|
uv_fs_open(g_pMainLoop,
|
|
&pParams->uvFsOpen,
|
|
pParams->sDlPath,
|
|
O_RDWR | O_CREAT | O_TRUNC,
|
|
S_IRUSR | S_IWUSR,
|
|
NULL);
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, __writeDataCb);
|
|
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, pParams);
|
|
curl_easy_setopt(pCurl, CURLOPT_PRIVATE, pParams);
|
|
curl_easy_setopt(pCurl, CURLOPT_URL, pParams->pReqUrl);
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 0L);
|
|
curl_easy_setopt(pCurl, CURLOPT_PROGRESSFUNCTION, __progressCb);
|
|
curl_easy_setopt(pCurl, CURLOPT_PROGRESSDATA, pParams);
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_LOW_SPEED_LIMIT, 10000L); // 10K bytes
|
|
curl_easy_setopt(pCurl, CURLOPT_LOW_SPEED_TIME, 10L); // 30 seconds
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 10L);
|
|
|
|
#ifdef SKIP_PEER_VERIFICATION
|
|
/*
|
|
* If you want to connect to a site who isn't using a certificate that is
|
|
* signed by one of the certs in the CA bundle you have, you can skip the
|
|
* verification of the server's certificate. This makes the connection
|
|
* A LOT LESS SECURE.
|
|
*
|
|
* If you have a CA cert for the server stored someplace else than in the
|
|
* default bundle, then the CURLOPT_CAPATH option might come handy for
|
|
* you.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
#else
|
|
curl_easy_setopt(pCurl, CURLOPT_CAINFO, SSL_CA_FILE);
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L);
|
|
#endif
|
|
|
|
#ifdef SKIP_HOSTNAME_VERIFICATION
|
|
/*
|
|
* If the site you're connecting to uses a different host name that what
|
|
* they have mentioned in their server certificate's commonName (or
|
|
* subjectAltName) fields, libcurl will refuse to connect. You can skip
|
|
* this check, but this will make the connection less secure.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
#endif
|
|
|
|
//LOG_EX(LOG_Debug, "Total Size = %d\n", __iNetGetRemoteSize(pURL, 0));
|
|
|
|
curl_multi_add_handle(g_pCurl, pCurl);
|
|
|
|
__addReqIdToTable(pParams->pTaskUuid, pCurl);
|
|
|
|
return (pParams->pTaskUuid);
|
|
}
|
|
#endif
|
|
|
|
const char* InetHttpDlFileAsync(const char *pURL,
|
|
const char *pPath,
|
|
OnHttpResponse onRespCb,
|
|
OnProgressNotify onProgressCb,
|
|
void* pData)
|
|
{
|
|
CURLMcode ret;
|
|
uuid_t msgId;
|
|
char strMsgId[64];
|
|
PHTTP_REQ_PARAMS pParams = NULL;
|
|
CURL *pCurl = NULL;
|
|
unsigned long long uMemFreeSize = GetPartitionFreeSize("/tmp/");
|
|
|
|
if(pURL == NULL || strlen(pURL) == 0 || onRespCb == NULL)
|
|
{
|
|
free(pParams);
|
|
return (NULL);
|
|
}
|
|
|
|
LOG_EX(LOG_Debug, "Begin Download: %s --> %s\n", pURL, pPath);
|
|
|
|
pParams = (PHTTP_REQ_PARAMS)malloc(sizeof(HTTP_REQ_PARAMS));
|
|
|
|
memset(pParams, 0, sizeof(HTTP_REQ_PARAMS));
|
|
|
|
pCurl = curl_easy_init();
|
|
|
|
pParams->onRspCb = onRespCb;
|
|
pParams->pReqUrl = (char *)malloc(strlen(pURL) + 1);
|
|
pParams->type = INET_HTTP_DOWNLOAD_FILE;
|
|
pParams->dlSize = 0;
|
|
pParams->onPrgCb = onProgressCb;
|
|
pParams->pData = pData;
|
|
pParams->pCurl = pCurl;
|
|
pParams->lastTm = 0;
|
|
pParams->isCancel = FALSE;
|
|
pParams->createTm = (unsigned int)LIBUV_CURRENT_TIME_S();
|
|
|
|
memset(pParams->pReqUrl, 0, strlen(pURL) + 1);
|
|
strcpy(pParams->pReqUrl, pURL);
|
|
|
|
uuid_generate_random(msgId);
|
|
memset(strMsgId, 0, 64);
|
|
uuid_unparse_lower(msgId, strMsgId);
|
|
pParams->pTaskUuid = strdup(strMsgId);
|
|
|
|
if(pPath == NULL)
|
|
{
|
|
sprintf(pParams->sPath, "./%s", basename_v2(pURL));
|
|
}
|
|
else
|
|
{
|
|
strcpy(pParams->sPath, pPath);
|
|
}
|
|
|
|
// Memory Free More Than 100M, Download Temp File To Memory
|
|
if(uMemFreeSize >= 100 * 1024 * 1024 &&
|
|
strncmp(pParams->sPath, "/tmp/", 5) != 0)
|
|
{
|
|
int ret = system("mkdir /tmp/dl -p");
|
|
sprintf(pParams->sDlPath, "/tmp/dl/%s_%s.dl", basename_v2(pParams->sPath), pParams->pTaskUuid);
|
|
}
|
|
else
|
|
{
|
|
strcpy(pParams->sDlPath, pParams->sPath);
|
|
}
|
|
|
|
pParams->uvFsDataSync.data = pParams;
|
|
pParams->uvFsClose.data = pParams;
|
|
|
|
uv_fs_open(g_pMainLoop,
|
|
&pParams->uvFsOpen,
|
|
pParams->sDlPath,
|
|
O_RDWR | O_CREAT | O_TRUNC,
|
|
S_IRUSR | S_IWUSR,
|
|
NULL);
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, __writeDataCb);
|
|
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, pParams);
|
|
curl_easy_setopt(pCurl, CURLOPT_PRIVATE, pParams);
|
|
curl_easy_setopt(pCurl, CURLOPT_URL, pURL);
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 0L);
|
|
curl_easy_setopt(pCurl, CURLOPT_PROGRESSFUNCTION, __progressCb);
|
|
curl_easy_setopt(pCurl, CURLOPT_PROGRESSDATA, pParams);
|
|
|
|
//curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 1800L); // Max download times (30 minutes)1800s
|
|
curl_easy_setopt(pCurl, CURLOPT_LOW_SPEED_LIMIT, 10000L); // 10K bytes
|
|
curl_easy_setopt(pCurl, CURLOPT_LOW_SPEED_TIME, 10L); // 30 seconds
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 10L);
|
|
//curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT_MS, 10L);
|
|
|
|
|
|
//curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1L);
|
|
|
|
#ifdef SKIP_PEER_VERIFICATION
|
|
/*
|
|
* If you want to connect to a site who isn't using a certificate that is
|
|
* signed by one of the certs in the CA bundle you have, you can skip the
|
|
* verification of the server's certificate. This makes the connection
|
|
* A LOT LESS SECURE.
|
|
*
|
|
* If you have a CA cert for the server stored someplace else than in the
|
|
* default bundle, then the CURLOPT_CAPATH option might come handy for
|
|
* you.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
#else
|
|
curl_easy_setopt(pCurl, CURLOPT_CAINFO, SSL_CA_FILE);
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L);
|
|
#endif
|
|
|
|
#ifdef SKIP_HOSTNAME_VERIFICATION
|
|
/*
|
|
* If the site you're connecting to uses a different host name that what
|
|
* they have mentioned in their server certificate's commonName (or
|
|
* subjectAltName) fields, libcurl will refuse to connect. You can skip
|
|
* this check, but this will make the connection less secure.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
#endif
|
|
|
|
LOG_EX(LOG_Debug, "Download(%u): %s --> %p\n", g_TotalDownloads++, pParams->pTaskUuid, pCurl);
|
|
ret = curl_multi_add_handle(g_pCurl, pCurl);
|
|
if(ret == CURLE_OK)
|
|
{
|
|
__addReqIdToTable(pParams->pTaskUuid, pParams);
|
|
return (pParams->pTaskUuid);
|
|
}
|
|
else
|
|
{
|
|
free(pParams->pTaskUuid);
|
|
LOG_EX(LOG_Error, "Add Handle Error: %d\n", ret);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int InetCancelDownload(const char *pTaskUuid)
|
|
{
|
|
if(pTaskUuid && strlen(pTaskUuid) > 0)
|
|
{
|
|
PCURL_HANDLE_TBL pItem = NULL;
|
|
|
|
HASH_FIND_STR(g_ReqHandleTbl, pTaskUuid, pItem);
|
|
|
|
if(pItem != NULL && pItem->pCurlItem->isCancel != TRUE)
|
|
{
|
|
__cancelDownloadTask(pItem->pCurlItem);
|
|
if(pItem->pCurlItem->onRspCb)
|
|
{
|
|
pItem->pCurlItem->onRspCb(NULL,
|
|
pItem->pCurlItem->dlSize,
|
|
pItem->pCurlItem->pReqUrl,
|
|
pItem->pCurlItem->sPath,
|
|
pItem->pCurlItem->pTaskUuid,
|
|
-CURLE_OPERATION_TIMEDOUT,
|
|
pItem->pCurlItem->pData);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static size_t __uploadCb(char *d, size_t n, size_t l, void *p)
|
|
{
|
|
return n*l;
|
|
}
|
|
|
|
#ifdef LIBCURL_DEBUG
|
|
struct data {
|
|
char trace_ascii; /* 1 or 0 */
|
|
};
|
|
|
|
static
|
|
void dump(const char *text,
|
|
FILE *stream, unsigned char *ptr, size_t size,
|
|
char nohex)
|
|
{
|
|
size_t i;
|
|
size_t c;
|
|
|
|
unsigned int width = 0x10;
|
|
|
|
if(nohex)
|
|
/* without the hex output, we can fit more on screen */
|
|
width = 0x40;
|
|
|
|
fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
|
|
text, (long)size, (long)size);
|
|
|
|
for(i = 0; i<size; i += width) {
|
|
|
|
fprintf(stream, "%4.4lx: ", (long)i);
|
|
|
|
if(!nohex) {
|
|
/* hex not disabled, show it */
|
|
for(c = 0; c < width; c++)
|
|
if(i + c < size)
|
|
fprintf(stream, "%02x ", ptr[i + c]);
|
|
else
|
|
fputs(" ", stream);
|
|
}
|
|
|
|
for(c = 0; (c < width) && (i + c < size); c++) {
|
|
/* check for 0D0A; if found, skip past and start a new line of output */
|
|
if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
|
|
ptr[i + c + 1] == 0x0A) {
|
|
i += (c + 2 - width);
|
|
break;
|
|
}
|
|
fprintf(stream, "%c",
|
|
(ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
|
|
/* check again for 0D0A, to avoid an extra \n if it's at width */
|
|
if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
|
|
ptr[i + c + 2] == 0x0A) {
|
|
i += (c + 3 - width);
|
|
break;
|
|
}
|
|
}
|
|
fputc('\n', stream); /* newline */
|
|
}
|
|
fflush(stream);
|
|
}
|
|
|
|
static
|
|
int my_trace(CURL *handle, curl_infotype type,
|
|
char *data, size_t size,
|
|
void *userp)
|
|
{
|
|
struct data *config = (struct data *)userp;
|
|
const char *text;
|
|
(void)handle; /* prevent compiler warning */
|
|
|
|
switch(type) {
|
|
case CURLINFO_TEXT:
|
|
fprintf(stderr, "== Info: %s", data);
|
|
/* FALLTHROUGH */
|
|
default: /* in case a new one is introduced to shock us */
|
|
return 0;
|
|
|
|
case CURLINFO_HEADER_OUT:
|
|
text = "=> Send header";
|
|
break;
|
|
case CURLINFO_DATA_OUT:
|
|
text = "=> Send data";
|
|
break;
|
|
case CURLINFO_SSL_DATA_OUT:
|
|
text = "=> Send SSL data";
|
|
break;
|
|
case CURLINFO_HEADER_IN:
|
|
text = "<= Recv header";
|
|
break;
|
|
case CURLINFO_DATA_IN:
|
|
text = "<= Recv data";
|
|
break;
|
|
case CURLINFO_SSL_DATA_IN:
|
|
text = "<= Recv SSL data";
|
|
break;
|
|
}
|
|
|
|
dump(text, stderr, (unsigned char *)data, size, config->trace_ascii);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int InetHttpUploadFileSync(const char *pURL, const char* pPath, void* pAttachInfo)
|
|
{
|
|
CURL *pCurl = NULL;
|
|
int rc = 0;
|
|
CURLcode ret;
|
|
struct curl_httppost *pPost = NULL, *pLastPtr = NULL;
|
|
|
|
#ifdef LIBCURL_DEBUG
|
|
struct data config;
|
|
config.trace_ascii = 1; /* enable ascii tracing */
|
|
#endif
|
|
|
|
if(pURL == NULL || strlen(pURL) == 0)
|
|
{
|
|
LOG_EX(LOG_Error, "Url: %s(%p)\n", SAFE_STRING_VALUE(pURL), pURL);
|
|
return -ERR_INPUT_PARAMS;
|
|
}
|
|
|
|
if(pPath == NULL || strlen(pPath) == 0)
|
|
{
|
|
LOG_EX(LOG_Error, "Url: %s(%p)\n", SAFE_STRING_VALUE(pPath), pPath);
|
|
return -ERR_INPUT_PARAMS;
|
|
}
|
|
|
|
curl_formadd(&pPost, &pLastPtr,
|
|
CURLFORM_COPYNAME, "file",
|
|
CURLFORM_FILE, pPath,
|
|
CURLFORM_END);
|
|
|
|
if(pAttachInfo)
|
|
{
|
|
PHTTP_POST_ATTACH pDevInfoArray = (PHTTP_POST_ATTACH)pAttachInfo;
|
|
PHTTP_POST_ATTACH pItem = NULL, pTmp = NULL;
|
|
|
|
LL_FOREACH_SAFE(pDevInfoArray, pItem, pTmp)
|
|
{
|
|
curl_formadd(&pPost, &pLastPtr,
|
|
CURLFORM_COPYNAME, pItem->keyName,
|
|
CURLFORM_COPYCONTENTS, pItem->keyValue,
|
|
CURLFORM_END);
|
|
}
|
|
}
|
|
|
|
pCurl = curl_easy_init();
|
|
|
|
if(pCurl == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "curl_easy_init() Error\n");
|
|
return -ERR_MALLOC_MEMORY;
|
|
}
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_ACCEPT_ENCODING, "gzip, deflate");
|
|
curl_easy_setopt(pCurl, CURLOPT_POST, 1L);
|
|
curl_easy_setopt(pCurl, CURLOPT_URL, pURL);
|
|
curl_easy_setopt(pCurl, CURLOPT_HTTPPOST, pPost);
|
|
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, __uploadCb);
|
|
curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 10L);
|
|
#ifdef LIBCURL_DEBUG
|
|
curl_easy_setopt(pCurl, CURLOPT_DEBUGFUNCTION, my_trace);
|
|
curl_easy_setopt(pCurl, CURLOPT_DEBUGDATA, &config);
|
|
#endif
|
|
|
|
#ifdef SKIP_PEER_VERIFICATION
|
|
/*
|
|
* If you want to connect to a site who isn't using a certificate that is
|
|
* signed by one of the certs in the CA bundle you have, you can skip the
|
|
* verification of the server's certificate. This makes the connection
|
|
* A LOT LESS SECURE.
|
|
*
|
|
* If you have a CA cert for the server stored someplace else than in the
|
|
* default bundle, then the CURLOPT_CAPATH option might come handy for
|
|
* you.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
#else
|
|
curl_easy_setopt(pCurl, CURLOPT_CAINFO, SSL_CA_FILE);
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L);
|
|
#endif
|
|
|
|
#ifdef SKIP_HOSTNAME_VERIFICATION
|
|
/*
|
|
* If the site you're connecting to uses a different host name that what
|
|
* they have mentioned in their server certificate's commonName (or
|
|
* subjectAltName) fields, libcurl will refuse to connect. You can skip
|
|
* this check, but this will make the connection less secure.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
#endif
|
|
|
|
|
|
#ifdef LIBCURL_DEBUG
|
|
curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1L);
|
|
#else
|
|
curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 0L);
|
|
#endif
|
|
|
|
ret = curl_easy_perform(pCurl);
|
|
|
|
if(ret != CURLE_OK)
|
|
{
|
|
LOG_EX(LOG_Error, "Upload %s File %s Error %s(%d)\n", pURL, pPath, curl_easy_strerror(ret), ret);
|
|
rc = -ERR_NETWORK_SEND;
|
|
}
|
|
|
|
curl_easy_cleanup(pCurl);
|
|
curl_formfree(pPost);
|
|
|
|
return rc;
|
|
}
|
|
|
|
const char* InetHttpWebServicePostAsync(const char *pURL, const char* pPost, OnHttpResponse onRespCb, void* pData)
|
|
{
|
|
uuid_t msgId;
|
|
char strMsgId[64];
|
|
PHTTP_REQ_PARAMS pParams = (PHTTP_REQ_PARAMS)malloc(sizeof(HTTP_REQ_PARAMS));
|
|
CURL *pCurl = NULL;
|
|
|
|
if(pURL == NULL || strlen(pURL) == 0 || onRespCb == NULL)
|
|
{
|
|
free(pParams);
|
|
return (NULL);
|
|
}
|
|
|
|
memset(pParams, 0, sizeof(HTTP_REQ_PARAMS));
|
|
|
|
pCurl = curl_easy_init();
|
|
|
|
pParams->onRspCb = onRespCb;
|
|
pParams->pReqUrl = (char *)malloc(strlen(pURL) + 1);
|
|
pParams->type = INET_HTTP_WEBSERVICE_POST;
|
|
pParams->dlSize = 0;
|
|
pParams->pData = pData;
|
|
pParams->pCurl = pCurl;
|
|
pParams->lastTm = 0;
|
|
pParams->isCancel = FALSE;
|
|
|
|
memset(pParams->pReqUrl, 0, strlen(pURL) + 1);
|
|
strcpy(pParams->pReqUrl, pURL);
|
|
|
|
uuid_generate_random(msgId);
|
|
memset(strMsgId, 0, 64);
|
|
uuid_unparse_lower(msgId, strMsgId);
|
|
pParams->pTaskUuid = strdup(strMsgId);
|
|
|
|
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, __writeDataCb);
|
|
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, pParams);
|
|
curl_easy_setopt(pCurl, CURLOPT_PRIVATE, pParams);
|
|
curl_easy_setopt(pCurl, CURLOPT_URL, pURL);
|
|
curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 1L);
|
|
curl_easy_setopt(pCurl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
|
|
|
if(pPost != NULL && strlen(pPost) > 0)
|
|
{
|
|
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, pPost);
|
|
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE, (long)strlen(pPost));
|
|
}
|
|
|
|
#ifdef SKIP_PEER_VERIFICATION
|
|
/*
|
|
* If you want to connect to a site who isn't using a certificate that is
|
|
* signed by one of the certs in the CA bundle you have, you can skip the
|
|
* verification of the server's certificate. This makes the connection
|
|
* A LOT LESS SECURE.
|
|
*
|
|
* If you have a CA cert for the server stored someplace else than in the
|
|
* default bundle, then the CURLOPT_CAPATH option might come handy for
|
|
* you.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
#else
|
|
curl_easy_setopt(pCurl, CURLOPT_CAINFO, SSL_CA_FILE);
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L);
|
|
#endif
|
|
|
|
#ifdef SKIP_HOSTNAME_VERIFICATION
|
|
/*
|
|
* If the site you're connecting to uses a different host name that what
|
|
* they have mentioned in their server certificate's commonName (or
|
|
* subjectAltName) fields, libcurl will refuse to connect. You can skip
|
|
* this check, but this will make the connection less secure.
|
|
*/
|
|
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
#endif
|
|
|
|
curl_multi_add_handle(g_pCurl, pCurl);
|
|
|
|
__addReqIdToTable(pParams->pTaskUuid, pParams);
|
|
|
|
return (pParams->pTaskUuid);
|
|
}
|
|
|
|
#if 0
|
|
static void __curlTaskRuntimeCb(void *pParams)
|
|
{
|
|
PCURL_HANDLE_TBL pItem = NULL, pTmpItem = NULL;
|
|
|
|
while(TRUE)
|
|
{
|
|
uv_rwlock_rdlock(&g_uvHashRwLock);
|
|
|
|
HASH_ITER(hh, g_ReqHandleTbl, pItem, pTmpItem)
|
|
{
|
|
if(pItem->pCurlItem->type == INET_HTTP_DOWNLOAD_FILE
|
|
&& pItem->pCurlItem->lastTm > 0)
|
|
{
|
|
//unsigned int tmNow = LIBUV_CURRENT_TIME_S();
|
|
|
|
if(pItem->pCurlItem->lastTm > 0)
|
|
{
|
|
//curl_multi_cleanup(pItem->pCurlItem->pCurl);
|
|
curl_multi_remove_handle(g_pCurl, pItem->pCurlItem->pCurl);
|
|
|
|
if(pItem->uRetryTimes >= 3)
|
|
{
|
|
if(pItem->pCurlItem->onRspCb)
|
|
{
|
|
if(strcmp(pItem->pCurlItem->sPath, pItem->pCurlItem->sDlPath) != 0)
|
|
{
|
|
unlink(pItem->pCurlItem->sDlPath);
|
|
}
|
|
|
|
pItem->pCurlItem->onRspCb(NULL,
|
|
pItem->pCurlItem->dlSize,
|
|
pItem->pCurlItem->pReqUrl,
|
|
pItem->pCurlItem->sPath,
|
|
pItem->pCurlItem->pTaskUuid,
|
|
TRUE,
|
|
pItem->pCurlItem->pData);
|
|
}
|
|
|
|
if(pItem->pCurlItem->pReqUrl)
|
|
{
|
|
free(pItem->pCurlItem->pReqUrl);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__restartDlFileAsync(pItem->pCurlItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
uv_rwlock_rdunlock(&g_uvHashRwLock);
|
|
usleep(100000);
|
|
}
|
|
|
|
pthread_detach(pthread_self());
|
|
}
|
|
#endif
|
|
|
|
static int __getUsernameFromMail(const char *pMailAddr, char **pUsername)
|
|
{
|
|
char *pTail;
|
|
|
|
if(pMailAddr == NULL || pUsername == NULL || strlen(pMailAddr) == 0)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Params Error: pMailAddr = [%s], pUsername = %p\n",
|
|
pMailAddr ? pMailAddr : "NULL", pUsername);
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
*pUsername = (char *)malloc(strlen(pMailAddr) + 1);
|
|
|
|
if(*pUsername == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Error Malloc Memory\n");
|
|
*pUsername = "";
|
|
return (-ERR_MALLOC_MEMORY);
|
|
}
|
|
|
|
memset(*pUsername, 0, strlen(pMailAddr) + 1);
|
|
|
|
pTail = strchr(pMailAddr, '@');
|
|
|
|
if(pTail == NULL)
|
|
{
|
|
strcpy(*pUsername, pMailAddr);
|
|
}
|
|
else
|
|
{
|
|
memcpy(*pUsername, pMailAddr, pTail - pMailAddr);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int InetSmtpSendEmail(const char* pFrom,
|
|
const char* pTo[],
|
|
const char* pCc[],
|
|
const char* pTitle,
|
|
const char* pMessage,
|
|
const char* pAttach[],
|
|
PSMTP_MAIL_CONFIG pConfig)
|
|
{
|
|
const char *pErrMsg = NULL;
|
|
quickmail pMail;
|
|
|
|
if(pConfig == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Param pConfig = NULL\n");
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pConfig->pPassword == NULL || strlen(pConfig->pPassword) == 0)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Param Error: pConfig->pPassword = [%s]\n", pConfig->pPassword ? pConfig->pPassword : "NULL");
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pConfig->pUserName == NULL || strlen(pConfig->pUserName) == 0)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Param Error: pConfig->pUserName = [%s]\n", pConfig->pUserName ? pConfig->pUserName : "NULL");
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pConfig->pSmtpServer == NULL || strlen(pConfig->pSmtpServer) == 0)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Param Error: pConfig->pUserName = [%s]\n", pConfig->pSmtpServer ? pConfig->pSmtpServer : "NULL");
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pFrom == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Param pFrom = NULL\n");
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pTo == NULL && pCc == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Param pTo = %p, pCc = %p\n", pTo, pCc);
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pTitle == NULL)
|
|
{
|
|
pTitle = "";
|
|
}
|
|
|
|
if(pMessage == NULL)
|
|
{
|
|
pMessage = "";
|
|
}
|
|
|
|
quickmail_initialize();
|
|
|
|
pMail = quickmail_create(pFrom, pTitle);
|
|
|
|
if(pMail == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Create Quickmail Object Error\n");
|
|
return (-ERR_MALLOC_MEMORY);
|
|
}
|
|
|
|
for(const char **pValue = pTo; pTo && *pValue; pValue++)
|
|
{
|
|
quickmail_add_to(pMail, *pValue);
|
|
}
|
|
|
|
for(const char **pValue = pCc; pCc && *pValue; pValue++)
|
|
{
|
|
quickmail_add_cc(pMail, *pValue);
|
|
}
|
|
|
|
quickmail_add_header(pMail, "Importance: Low");
|
|
quickmail_add_header(pMail, "X-Priority: 5");
|
|
quickmail_add_header(pMail, "X-MSMail-Priority: Low");
|
|
quickmail_add_body_memory(pMail, "text/html", (char*)pMessage, strlen(pMessage), 0);
|
|
|
|
for(const char **pValue = pAttach; pAttach && *pValue; pValue++)
|
|
{
|
|
quickmail_add_attachment_file(pMail, *pValue, NULL);
|
|
}
|
|
|
|
//quickmail_set_debug_log(pMail, stderr);
|
|
|
|
pErrMsg = quickmail_send(pMail, pConfig->pSmtpServer, pConfig->smtpPort, pConfig->pUserName, pConfig->pPassword);
|
|
|
|
if(pErrMsg != NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Send Mail Error: %s\n", pErrMsg);
|
|
return (-ERR_SEND_MAIL);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int InetInit(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
ret = curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
if(ret != 0)
|
|
{
|
|
LOG_EX(LOG_Error, "curl init error: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
g_pMainLoop = DBusLibuvGetRuntime()->pLoop;
|
|
|
|
uv_timer_init(g_pMainLoop, &g_uvCurlTm);
|
|
uv_timer_init(g_pMainLoop, &g_uvDlTm);
|
|
|
|
g_pCurl = curl_multi_init();
|
|
|
|
curl_multi_setopt(g_pCurl, CURLMOPT_SOCKETFUNCTION, __curlSockCb);
|
|
curl_multi_setopt(g_pCurl, CURLMOPT_TIMERFUNCTION, __curlTimerCb);
|
|
|
|
uv_rwlock_init(&g_uvHashRwLock);
|
|
|
|
uv_timer_start(&g_uvDlTm, __onDlTmoutCb, 1000, 1000);
|
|
|
|
return (0);
|
|
}
|
|
|
|
void InetUnInit(void)
|
|
{
|
|
curl_multi_cleanup(g_pCurl);
|
|
curl_global_cleanup();
|
|
}
|
|
|