// // Created by xajhu on 2019/11/18 0018. // #include #include #include #include #include "common.h" #include "err_code.h" #include "log.h" #include "../include/restful.h" #define SSL_CA_FILE ("/etc/ssl/certs/ca-certificates.crt") #define CURL_TIMEOUT (5) typedef struct { char *pReqUrl; char sPath[MAX_PATH]; char sDlPath[MAX_PATH]; unsigned char reqResult[4096]; unsigned int dlSize; OnHttpResponse onRspCb; CURL *pCurl; int errCode; void* pData; } HTTP_REQ_PARAMS, *PHTTP_REQ_PARAMS; static size_t __writeDataCb(void *pData, size_t size, size_t nmemb, void *pParams) { PHTTP_REQ_PARAMS pReq = (PHTTP_REQ_PARAMS)pParams; size_t iMemSize = size * nmemb; memcpy(pReq->reqResult + pReq->dlSize, pData, iMemSize); pReq->dlSize += iMemSize; return (iMemSize); } int http_post_request_async(const char *pURL, const char *pPost, OnHttpResponse onRespCb) { long flag = (long)CURL_GLOBAL_ALL; int value = 1, timeout = CURL_TIMEOUT; CURL *pCurl = NULL; int ret = 0; struct curl_slist *pList; PHTTP_REQ_PARAMS pParams = NULL; if(pURL == NULL || strlen(pURL) == 0) { LOG_EX(LOG_Error, "Input URL error\n"); return -ERR_INPUTERR; } pParams = (PHTTP_REQ_PARAMS)malloc(sizeof(HTTP_REQ_PARAMS)); if(pParams == NULL) { LOG_EX(LOG_Error, "Malloc %u memory error\n", sizeof(HTTP_REQ_PARAMS)); return -ERR_NOMEM; } ret = curl_global_init(flag); if(ret != CURLE_OK) { LOG_EX(LOG_Error, "Init curl global error: %d\n", ret); free(pParams); return -ERR_ERR; } pCurl = curl_easy_init(); if(!pCurl) { LOG_EX(LOG_Error, "Init easy curl error: %d\n", ret); curl_global_cleanup(); free(pParams); return -ERR_ERR; } memset(pParams, 0, sizeof(HTTP_REQ_PARAMS)); pParams->onRspCb = onRespCb; pParams->pReqUrl = strdup(pURL); pParams->dlSize = 0; pParams->pCurl = pCurl; pList = curl_slist_append(NULL, "Content-Type:application/json;charset=UTF-8"); 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, value); curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, timeout); curl_easy_setopt(pCurl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList); if(pPost != NULL && strlen(pPost) > 0) { curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, pPost); curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE, (long)strlen(pPost)); pParams->pData = (void*)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, value); #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 ret = curl_easy_perform(pCurl); if(ret != CURLE_OK) { LOG_EX(LOG_Error, "Http Post error(%u): %s\n", ret, curl_easy_strerror(ret)); } curl_slist_free_all(pList); curl_easy_cleanup(pCurl); curl_global_cleanup(); if(onRespCb && ret == CURLE_OK) { onRespCb(pParams->reqResult, pParams->dlSize, pParams->pReqUrl, pParams->sPath, NULL, CURLE_OK, pParams->pData); } else { onRespCb(NULL, 0, pParams->pReqUrl, pParams->sPath, NULL, -ret, pParams->pData); } if(pParams->pReqUrl) { free(pParams->pReqUrl); } free(pParams); return ret; } int http_post_request(const char *pURL, const char *pPost, unsigned char* pBuf, unsigned int *pOutSize) { long flag = (long)CURL_GLOBAL_ALL; int value = 1, timeout = CURL_TIMEOUT; CURL *pCurl = NULL; int ret = 0; struct curl_slist *pList; PHTTP_REQ_PARAMS pParams = NULL; if(pURL == NULL || strlen(pURL) == 0 || pBuf == NULL || pOutSize == NULL) { LOG_EX(LOG_Error, "Input params error\n"); return -ERR_NOMEM; } pParams = (PHTTP_REQ_PARAMS)malloc(sizeof(HTTP_REQ_PARAMS)); if(pParams == NULL) { LOG_EX(LOG_Error, "Malloc %u memory error\n", sizeof(HTTP_REQ_PARAMS)); return -ERR_NOMEM; } ret = curl_global_init(flag); if(ret != CURLE_OK) { LOG_EX(LOG_Error, "Init curl global error: %d\n", ret); free(pParams); return -ERR_ERR; } pCurl = curl_easy_init(); if(!pCurl) { LOG_EX(LOG_Error, "Init easy curl error: %d\n", ret); curl_global_cleanup(); free(pParams); return -ERR_ERR; } memset(pParams, 0, sizeof(HTTP_REQ_PARAMS)); pParams->pReqUrl = strdup(pURL); pParams->dlSize = 0; pParams->pCurl = pCurl; pList = curl_slist_append(NULL, "Content-Type:application/json;charset=UTF-8"); 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, value); curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, timeout); curl_easy_setopt(pCurl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList); if(pPost != NULL && strlen(pPost) > 0) { curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, pPost); curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE, (long)strlen(pPost)); pParams->pData = (void*)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, value); #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 ret = curl_easy_perform(pCurl); if(ret != CURLE_OK) { LOG_EX(LOG_Error, "Http Post error(%u): %s\n", ret, curl_easy_strerror(ret)); } curl_slist_free_all(pList); curl_easy_cleanup(pCurl); curl_global_cleanup(); if(*pOutSize < pParams->dlSize) { ret = -ERR_OUTSIZE; } else { *pOutSize = pParams->dlSize; } memcpy(pBuf, pParams->reqResult, *pOutSize); if(pParams->pReqUrl) { free(pParams->pReqUrl); } free(pParams); return ret; }