639 lines
19 KiB
C
639 lines
19 KiB
C
#include <pthread.h>
|
|
#include <sys/prctl.h>
|
|
#include "curl_adaptor.h"
|
|
#include "utils_queue.h"
|
|
// #include "json_adaptor.h"
|
|
#include "rest_proxy.h"
|
|
#include "log.h"
|
|
|
|
SRestFulInfo g_restful;
|
|
|
|
typedef struct _STablCurl
|
|
{
|
|
ECurlType curlType;
|
|
char* curlFormat;
|
|
}STablCurl;
|
|
|
|
/* curl table */
|
|
STablCurl g_tab_url[] =
|
|
{
|
|
// {URL_FETCH_SUB, URLFetchSub},
|
|
{URL_FETCH_UPBalance, URLFetchUPBalance},
|
|
{URL_FETCH_InfoBalance, URLFetchInfoBalance},
|
|
{URL_FETCH_WalletBalance_Getsubsid, URLFetchWalletBalanceGetsubsid},
|
|
{URL_FETCH_WalletBalance, URLFetchWalletBalance},
|
|
{URL_RECHAGRGE_Getsubsid, URLRechargeGetsubsid},
|
|
{URL_RECHAGRGE, URLRecharge},
|
|
{URL_TRANS_GetsubsidSender, URLTransGetsubidSender},
|
|
{URL_TRANS_GetsubsidReceiver, URLTransGetsubidReceiver},
|
|
{URL_TRANS, URLTrans},
|
|
};
|
|
|
|
/* curl cache */
|
|
static const int CURL_MAX_CONN = 200;
|
|
static const int CURL_WAIT_TIME_US = 30*1000;
|
|
static const int CURL_CB_TIME_OUT_MS = 500;
|
|
|
|
static CURL_ADAPTOR_APP_CB g_curl_adaptor_app_cb;
|
|
|
|
static queueADT g_curl_queue;
|
|
static int g_curl_thread_running;
|
|
|
|
char *get_val_by_name(const char *str, const char *name, char dst_buf[], const int len)
|
|
{
|
|
char *p = strstr(str, name);
|
|
if(p)
|
|
{
|
|
char val[2][64] = {{0}};
|
|
sscanf(p, "%64[^:]: \"%64[^\"]", val[0], val[1]);
|
|
snprintf(dst_buf, len, "%s", val[1]);
|
|
LOG_D("[curl][recv] [%s]=>[%s],[%s]\n", str, val[0], val[1]);
|
|
|
|
return dst_buf;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int curl_adaptor_resolve_cb_walletbalance(const char *str, unsigned int *balance)
|
|
{
|
|
char *p_1 = NULL;
|
|
char *p_2 = NULL;
|
|
char *p_3 = NULL;
|
|
if( (p_1 = strstr(str, "balance") ) != NULL &&
|
|
(p_2 = strstr(p_1, ":") ) != NULL &&
|
|
(p_3 = strstr(p_2, "\"") ) != NULL)
|
|
{
|
|
char *p_4 = p_3 + 1;
|
|
char *p = p_4;
|
|
while(*p_4 != '"')
|
|
{
|
|
p_4++;
|
|
}
|
|
*p_4 = '\0';
|
|
|
|
*balance = atof(p) * 100;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
int curl_adaptor_resolve_cb_validitydate_mon(const char* str, int *mon)
|
|
{
|
|
static char *str_mon[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
|
int mon_num = sizeof(str_mon)/sizeof(str_mon[0]);
|
|
int i = 0;
|
|
for( ; i < mon_num; ++i)
|
|
{
|
|
if(strcmp(str, str_mon[i]) == 0)
|
|
{
|
|
*mon = i;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int curl_adaptor_resolve_cb_validitydate(const char *str, unsigned int *validitydate)
|
|
{
|
|
char data[48] = {0};
|
|
if(get_val_by_name(str, "validitydate", data, sizeof(data)) == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
char str_dd[8] = {0};
|
|
char str_mon[8] = {0};
|
|
char str_year[8]= {0};
|
|
char str_h[8] = {0};
|
|
char str_m[8] = {0};
|
|
char str_s[8] = {0};
|
|
|
|
int ret = sscanf(data, "%7[^-]-%7[^-]-%7[^ ] %7[^:]:%7[^:]:%7s",
|
|
str_dd, str_mon, str_year, str_h, str_m, str_s);
|
|
if(ret == 6 || ret == 3)
|
|
{
|
|
struct tm tm;
|
|
time_t time;
|
|
tm.tm_year = atoi(str_year) - 1900;
|
|
curl_adaptor_resolve_cb_validitydate_mon(str_mon, &tm.tm_mon);
|
|
tm.tm_mday = atoi(str_dd);
|
|
tm.tm_hour = atoi(str_h);
|
|
tm.tm_min = atoi(str_m);
|
|
tm.tm_sec = atoi(str_s);
|
|
|
|
time = mktime(&tm);
|
|
*validitydate = time;
|
|
|
|
LOG_D("[curl][recv] [%s-%s-%s %s:%s:%s]=>[%u]\n", str_year, str_mon, str_dd, str_h, str_m, str_s, *validitydate);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* function: handle receive http response and resovle the raw data
|
|
*/
|
|
static size_t curl_adaptor_resolve_cb(char *d, size_t n, size_t l, void *p)
|
|
{
|
|
char *p_find, *p_start;
|
|
SCurlAdaptor *curAdaptor = (SCurlAdaptor*)p;
|
|
|
|
switch(curAdaptor->urlType)
|
|
{
|
|
case URL_FETCH_UPBalance:
|
|
break;
|
|
case URL_FETCH_InfoBalance:
|
|
p_find = strstr(d, ":");
|
|
if(p_find == NULL)
|
|
{
|
|
curAdaptor->msg.query_res.result = FAILURE;
|
|
curAdaptor->msg.query_res.error_code = 0;
|
|
curAdaptor->msg.query_res.optional_flag = 0;
|
|
break;
|
|
}
|
|
p_find = p_start = strstr(p_find, "\"");
|
|
p_find++;
|
|
while((*p_find) != '\"')
|
|
{
|
|
p_find++;
|
|
}
|
|
*p_find = '\0';
|
|
curAdaptor->msg.query_res.balance = (unsigned int)(atoi(p_start+1));
|
|
curAdaptor->msg.query_res.result = SUCCESS;
|
|
curAdaptor->msg.query_res.error_code = 0;
|
|
curAdaptor->msg.query_res.optional_flag = 0;
|
|
break;
|
|
case URL_FETCH_WalletBalance_Getsubsid:
|
|
get_val_by_name(d, "subscriberId", curAdaptor->msg.query.subsid, RESTFUL_SUBSID_LEN);
|
|
break;
|
|
case URL_FETCH_WalletBalance:
|
|
{
|
|
int ret = 0;
|
|
|
|
if(d != NULL)
|
|
{
|
|
char *tmp = (char*)malloc(strlen(d) + 1);
|
|
// char tmp[512] = {0};
|
|
strcpy(tmp, d);
|
|
|
|
ret = curl_adaptor_resolve_cb_walletbalance(tmp, &curAdaptor->msg.query_res.balance);
|
|
if(ret != 0)
|
|
{
|
|
strcpy(tmp, d);
|
|
ret = curl_adaptor_resolve_cb_validitydate(tmp, &curAdaptor->msg.query_res.mo_expiry);
|
|
}
|
|
free(tmp);
|
|
}
|
|
if(ret != 0)
|
|
{
|
|
curAdaptor->msg.query_res.result = SUCCESS;
|
|
curAdaptor->msg.query_res.mt_expiry = curAdaptor->msg.query_res.mo_expiry;
|
|
}
|
|
else
|
|
{
|
|
curAdaptor->msg.query_res.result = FAILURE;
|
|
}
|
|
|
|
curAdaptor->msg.query_res.error_code = 0;
|
|
curAdaptor->msg.query_res.optional_flag = 0;
|
|
}
|
|
break;
|
|
case URL_RECHAGRGE_Getsubsid:
|
|
get_val_by_name(d, "subscriberId", curAdaptor->msg.topup.subsid, RESTFUL_SUBSID_LEN);
|
|
break;
|
|
case URL_RECHAGRGE:
|
|
{
|
|
curAdaptor->msg.topup_res.result = SUCCESS;
|
|
curAdaptor->msg.topup_res.error_code = 0;
|
|
curAdaptor->msg.topup_res.balance = 0;
|
|
curAdaptor->msg.topup_res.mo_expiry = 0;
|
|
curAdaptor->msg.topup_res.mt_expiry = 0;
|
|
curAdaptor->msg.topup_res.optional_flag = 0;
|
|
}
|
|
break;
|
|
case URL_TRANS_GetsubsidSender:
|
|
get_val_by_name(d, "subscriberId", curAdaptor->msg.transfer.subsid_sender, RESTFUL_SUBSID_LEN);
|
|
break;
|
|
case URL_TRANS_GetsubsidReceiver:
|
|
get_val_by_name(d, "subscriberId", curAdaptor->msg.transfer.subsid_receiver, RESTFUL_SUBSID_LEN);
|
|
break;
|
|
case URL_TRANS:
|
|
{
|
|
curAdaptor->msg.transfer_res.result = SUCCESS;
|
|
curAdaptor->msg.transfer_res.error_code = 0;
|
|
curAdaptor->msg.transfer_res.optional_flag = 0;
|
|
}
|
|
break;
|
|
case URL_PPC_OfferGetAllV2_1:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return n*l;
|
|
}
|
|
|
|
static void curl_adaptor_easy_init(CURLM *cm, const SCurlAdaptor* curAdaptor)
|
|
{
|
|
CURL *eh = curl_easy_init();
|
|
char userNamePasswordBuf[64] = {0};
|
|
|
|
/* 对于query、get-subscriberid来说,都是http-request操作,不用带参数 */
|
|
if(curAdaptor->urlType == URL_FETCH_WalletBalance ||
|
|
curAdaptor->urlType == URL_FETCH_WalletBalance_Getsubsid ||
|
|
curAdaptor->urlType == URL_RECHAGRGE_Getsubsid ||
|
|
curAdaptor->urlType == URL_TRANS_GetsubsidSender ||
|
|
curAdaptor->urlType == URL_TRANS_GetsubsidReceiver)
|
|
{
|
|
curl_easy_setopt(eh, CURLOPT_WRITEDATA, (void *)(curAdaptor));
|
|
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, curl_adaptor_resolve_cb);
|
|
// curl_easy_setopt(eh, CURLOPT_HEADER, 0L);
|
|
curl_easy_setopt(eh, CURLOPT_NOSIGNAL, 1);
|
|
curl_easy_setopt(eh, CURLOPT_URL, curAdaptor->urlBuf);
|
|
// 设置basic 向服务器提供验证信息
|
|
curl_easy_setopt(eh, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
|
snprintf(userNamePasswordBuf, sizeof(userNamePasswordBuf), "%s:%s",
|
|
g_rest_proxy_env.cnf.username, g_rest_proxy_env.cnf.password);
|
|
curl_easy_setopt(eh, CURLOPT_USERPWD, userNamePasswordBuf);
|
|
curl_easy_setopt(eh, CURLOPT_PRIVATE, curAdaptor);
|
|
// curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L);
|
|
curl_easy_setopt(eh, CURLOPT_TIMEOUT_MS, CURL_CB_TIME_OUT_MS);
|
|
|
|
curl_easy_setopt(eh, CURLOPT_FORBID_REUSE, 1);
|
|
|
|
LOG_D(" urlType:%d, curl:%s\n", curAdaptor->urlType, curAdaptor->urlBuf);
|
|
}
|
|
else if(curAdaptor->urlType == URL_RECHAGRGE ||
|
|
curAdaptor->urlType == URL_TRANS)
|
|
{
|
|
/* 对于topup来说,topup需要是http-post操作,且需要带额外参数.*/
|
|
/* 注意: 这里param是全局变量,多线程可能出错. 后续要分析下安全性. 2019/06/23 22:58:30 */
|
|
static char param[512] = {0};
|
|
|
|
// 设置问非0表示本次操作为post
|
|
curl_easy_setopt(eh, CURLOPT_POST, 1);
|
|
// url地址
|
|
curl_easy_setopt(eh, CURLOPT_URL,curAdaptor->urlBuf);
|
|
// 设置basic 向服务器提供验证信息
|
|
curl_easy_setopt(eh, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
|
|
|
snprintf(userNamePasswordBuf, sizeof(userNamePasswordBuf), "%s:%s",
|
|
g_rest_proxy_env.cnf.username, g_rest_proxy_env.cnf.password);
|
|
curl_easy_setopt(eh, CURLOPT_USERPWD, userNamePasswordBuf);
|
|
|
|
if(curAdaptor->urlType == URL_RECHAGRGE)
|
|
{
|
|
if(REST_PROXY_SUBSCRIBID_FLAG)
|
|
{
|
|
/* 配置为query/topup流程都要先获取subscriber-id的话, topup的参数格式是这样的: */
|
|
/* msisdn=90909093&&pin=39977093792343 */
|
|
snprintf(param, sizeof(param), "msisdn=%s&pin=%s",
|
|
curAdaptor->msg.topup.msisdn, curAdaptor->msg.topup.pin);
|
|
}
|
|
else
|
|
{
|
|
/* 配置为query/topup流程不用先获取subscriber-id,而是直接query/topup到self-http, topup的参数格式是这样的: */
|
|
/* char *post_para = "actor=4559936&pin=57160898969922&customerIp=10.60.1.42&voucherId=&subscriberId=4559936&subsystem=Selfcare&rechargeTransactiontId=1503&msisdn=6924559936" */
|
|
snprintf(param, sizeof(param), "actor=%s&pin=%s&customerIp=%s&voucherId=%s&subscriberId=%s&subsystem=%s&msisdn=%s",
|
|
curAdaptor->msg.topup.msisdn,
|
|
curAdaptor->msg.topup.pin,
|
|
g_rest_proxy_env.cnf.customer_ip,
|
|
"",
|
|
curAdaptor->msg.topup.msisdn,
|
|
g_rest_proxy_env.cnf.subsystem,
|
|
curAdaptor->msg.topup.msisdn);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
snprintf(param, sizeof(param), "gifteeSubscriptionIdentifier=%s&&gifterSubscriptionIdentifier=%s&&BankTypeToCredit=WalletBank;;%u&&Comments=Gift WalletBank of $%u from %s to %s",
|
|
curAdaptor->msg.transfer.msisdn_receiver,
|
|
curAdaptor->msg.transfer.msisdn_sender,
|
|
curAdaptor->msg.transfer.money,
|
|
curAdaptor->msg.transfer.money,
|
|
curAdaptor->msg.transfer.msisdn_sender,
|
|
curAdaptor->msg.transfer.msisdn_receiver);
|
|
}
|
|
|
|
|
|
// post参数
|
|
curl_easy_setopt(eh, CURLOPT_POSTFIELDS, param);
|
|
curl_easy_setopt(eh, CURLOPT_POSTFIELDSIZE, strlen(param) );
|
|
// 对返回的数据进行操作的函数地址
|
|
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, curl_adaptor_resolve_cb);
|
|
// 这是write_data的第四个参数值
|
|
curl_easy_setopt(eh, CURLOPT_WRITEDATA, curAdaptor);
|
|
curl_easy_setopt(eh, CURLOPT_PRIVATE, curAdaptor);
|
|
|
|
{
|
|
struct curl_slist *chunk = NULL;
|
|
/* Remove a header curl would otherwise add by itself */
|
|
chunk = curl_slist_append(chunk, "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2");
|
|
/* set our custom set of headers */
|
|
curl_easy_setopt(eh, CURLOPT_HTTPHEADER, chunk);
|
|
}
|
|
// 打印调试信息
|
|
// curl_easy_setopt(eh, CURLOPT_VERBOSE, 1);
|
|
// 将响应头信息和相应体一起传给write_data
|
|
curl_easy_setopt(eh, CURLOPT_HEADER, 1);
|
|
// 设置为非0,响应头信息location
|
|
// curl_easy_setopt(eh, CURLOPT_FOLLOWLOCATION, 1);
|
|
|
|
curl_easy_setopt(eh, CURLOPT_FORBID_REUSE, 1);
|
|
|
|
LOG_D(" urlType:%d, curl:%s param:%s\n", curAdaptor->urlType, curAdaptor->urlBuf, param);
|
|
}
|
|
|
|
curl_multi_add_handle(cm, eh);
|
|
|
|
}
|
|
|
|
int curl_adaptor_init_cb(CURL_ADAPTOR_APP_CB appCB)
|
|
{
|
|
g_curl_adaptor_app_cb = appCB;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
static int curl_adaptor_init_restfulInfo(const char* queryIP, unsigned int queryPort, const char* rechargeIP, unsigned int rechargePort)
|
|
{
|
|
strcpy(g_restful.queryIP, queryIP);
|
|
g_restful.queryPort = queryPort;
|
|
|
|
strcpy(g_restful.recharegeIP, rechargeIP);
|
|
g_restful.recharegePort = rechargePort;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int curl_adaptor_add(SCurlAdaptor* curAdaptor)
|
|
{
|
|
int len = 0;
|
|
int rc = FAILURE;
|
|
|
|
if(QueueIsFull(g_curl_queue))
|
|
{
|
|
rc = FAILURE;
|
|
goto END;
|
|
}
|
|
|
|
int urlType = curAdaptor->urlType;
|
|
switch(urlType)
|
|
{
|
|
case URL_FETCH_UPBalance:
|
|
case URL_FETCH_InfoBalance:
|
|
case URL_FETCH_WalletBalance_Getsubsid:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.queryIP, g_restful.queryPort);
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.query.msisdn);
|
|
}
|
|
break;
|
|
case URL_FETCH_WalletBalance:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.queryIP, g_restful.queryPort);
|
|
if(REST_PROXY_SUBSCRIBID_FLAG)
|
|
{
|
|
/* 配置为query/topup流程都要先获取subscriber-id. query/topup的时候要将subscriber-id送出去 */
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.query.subsid, curAdaptor->msg.query.msisdn);
|
|
}
|
|
else
|
|
{
|
|
/* 配置为query/topup流程不用先获取subscriber-id,不需要将subscriber-id送出去 */
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.query.msisdn);
|
|
}
|
|
}
|
|
break;
|
|
case URL_RECHAGRGE_Getsubsid:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.topup.msisdn);
|
|
}
|
|
break;
|
|
case URL_RECHAGRGE:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
|
|
if(REST_PROXY_SUBSCRIBID_FLAG)
|
|
{
|
|
/* 配置为query/topup流程都要先获取subscriber-id. query/topup的时候要将subscriber-id送出去 */
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.topup.subsid);
|
|
}
|
|
else
|
|
{
|
|
/* 配置为query/topup流程不用先获取subscriber-id,不需要将subscriber-id送出去 */
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.topup.msisdn);
|
|
}
|
|
}
|
|
break;
|
|
case URL_TRANS_GetsubsidSender:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.transfer.msisdn_sender);
|
|
|
|
}
|
|
break;
|
|
case URL_TRANS_GetsubsidReceiver:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType].curlFormat, curAdaptor->msg.transfer.msisdn_receiver);
|
|
|
|
}
|
|
break;
|
|
case URL_TRANS:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len, "%s",
|
|
g_tab_url[urlType].curlFormat/*, curAdaptor->msg.transfer.subsid_sender*/);
|
|
}
|
|
break;
|
|
case URL_PPC_OfferGetAllV2_1:
|
|
{
|
|
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
|
|
URLPrefix, g_restful.queryIP, g_restful.queryPort);
|
|
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
|
|
g_tab_url[urlType%URL_MAX_NUM].curlFormat, "-weekly,daily");
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
rc = FAILURE;
|
|
goto END;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(SUCCESS_QUEUE == QueueEnter(g_curl_queue, (queueElementT)curAdaptor) )
|
|
{
|
|
rc = SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
rc = FAILURE;
|
|
}
|
|
|
|
END:
|
|
return rc;
|
|
}
|
|
|
|
/* curl_multi_perform() + curl_multi_wait() */
|
|
int curl_adaptor_go(SCurlAdaptor *curlAdaptor)
|
|
{
|
|
CURLM *cm = NULL;
|
|
CURL *eh = NULL;
|
|
CURLMsg *msg = NULL;
|
|
CURLcode return_code = 0;
|
|
int still_running = 0, msgs_left = 0;
|
|
int http_status_code;
|
|
|
|
cm = curl_multi_init();
|
|
if(cm == NULL) return FAILURE;
|
|
/* we can optionally limit the total amount of connections this multi handle uses */
|
|
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)CURL_MAX_CONN);
|
|
curl_adaptor_easy_init(cm, curlAdaptor);
|
|
curl_multi_perform(cm, &still_running);
|
|
|
|
do
|
|
{
|
|
int numfds=0;
|
|
int res = curl_multi_wait(cm, NULL, 0, CURL_WAIT_TIME_US, &numfds);
|
|
if(res != CURLM_OK)
|
|
{
|
|
LOG_E("[curl][recv] error: curl_multi_wait() returned %d\n", res);
|
|
return FAILURE;
|
|
}
|
|
curl_multi_perform(cm, &still_running);
|
|
|
|
}while(still_running);
|
|
|
|
while((msg = curl_multi_info_read(cm, &msgs_left)))
|
|
{
|
|
if (msg->msg == CURLMSG_DONE)
|
|
{
|
|
curlAdaptor = NULL;
|
|
|
|
eh = msg->easy_handle;
|
|
return_code = msg->data.result;
|
|
curl_easy_getinfo(eh, CURLINFO_PRIVATE, &curlAdaptor);
|
|
if(return_code != CURLE_OK)
|
|
{
|
|
LOG_E("[curl][recv] error: curl_multi_info_read() returned %d\n", return_code);
|
|
|
|
g_curl_adaptor_app_cb(curlAdaptor, msg->data.result);
|
|
|
|
curl_multi_remove_handle(cm, eh);
|
|
curl_easy_cleanup(eh);
|
|
|
|
continue;
|
|
}
|
|
|
|
/* Get HTTP status code */
|
|
http_status_code = 0;
|
|
curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, &http_status_code);
|
|
if(http_status_code != 200)
|
|
{
|
|
LOG_E("[curl][recv] get of %p returned http status code %d\n", curlAdaptor, http_status_code);
|
|
}
|
|
|
|
g_curl_adaptor_app_cb(curlAdaptor, http_status_code);
|
|
|
|
curl_multi_remove_handle(cm, eh);
|
|
curl_easy_cleanup(eh);
|
|
}
|
|
else
|
|
{
|
|
LOG_E("[curl][recv] error: after curl_multi_info_read(), CURLMsg=%d\n", msg->msg);
|
|
}
|
|
}
|
|
|
|
curl_multi_cleanup(cm);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int curl_adaptor_init_queue()
|
|
{
|
|
g_curl_queue = QueueCreate(3000);
|
|
|
|
return g_curl_queue != NULL;
|
|
}
|
|
|
|
static void *curl_adaptor_thread(void *data)
|
|
{
|
|
prctl(PR_SET_NAME, "curl_queue");
|
|
|
|
SCurlAdaptor *curAdaptor;
|
|
|
|
while(g_curl_thread_running)
|
|
{
|
|
if( !QueueIsEmpty(g_curl_queue) )
|
|
{
|
|
curAdaptor = (SCurlAdaptor *)QueueDelete(g_curl_queue);
|
|
if(curAdaptor)
|
|
{
|
|
curl_adaptor_go(curAdaptor);
|
|
}
|
|
}
|
|
usleep(10);
|
|
}
|
|
pthread_exit(NULL);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int curl_adaptor_init_thread()
|
|
{
|
|
pthread_t handle;
|
|
g_curl_thread_running = 1;
|
|
if(pthread_create(&handle, NULL, curl_adaptor_thread, NULL))
|
|
{
|
|
printf("Thread create err !!!\n");
|
|
return FAILURE;
|
|
|
|
if ( pthread_detach(handle) )
|
|
{
|
|
printf("Thread detached err !!!\n");
|
|
return FAILURE;
|
|
}
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
int curl_adaptor_init(CURL_ADAPTOR_APP_CB appCB,
|
|
const char* queryIP,
|
|
unsigned int queryPort,
|
|
const char* rechargeIP,
|
|
unsigned int rechargePort)
|
|
{
|
|
curl_adaptor_init_queue();
|
|
curl_adaptor_init_thread();
|
|
curl_adaptor_init_cb(appCB);
|
|
curl_adaptor_init_restfulInfo(queryIP, queryPort, rechargeIP, rechargePort);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int curl_adaptor_fini()
|
|
{
|
|
g_curl_thread_running = 0;
|
|
|
|
QueueDestroy(g_curl_queue);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|