Mod aaa-12 1. 增加HTTP访问网络失败处理。2. 更正ZTP认证服务器返回数据类型。

RCA:
SOL:
修改人:huangxin
检视人:huangxin
This commit is contained in:
huangxin 2019-12-03 11:05:13 +08:00
parent ac282c9fdb
commit 274428e9ce
9 changed files with 289 additions and 157 deletions

View File

@ -13,11 +13,13 @@
#define SSL_CA_FILE ("/etc/ssl/certs/ca-certificates.crt") #define SSL_CA_FILE ("/etc/ssl/certs/ca-certificates.crt")
#define CURL_TIMEOUT (5)
typedef struct { typedef struct {
char *pReqUrl; char *pReqUrl;
char sPath[MAX_PATH]; char sPath[MAX_PATH];
char sDlPath[MAX_PATH]; char sDlPath[MAX_PATH];
unsigned int reqResult[4096]; unsigned char reqResult[4096];
unsigned int dlSize; unsigned int dlSize;
OnHttpResponse onRspCb; OnHttpResponse onRspCb;
CURL *pCurl; CURL *pCurl;
@ -36,15 +38,20 @@ static size_t __writeDataCb(void *pData, size_t size, size_t nmemb, void *pParam
return (iMemSize); return (iMemSize);
} }
int http_post_request(const char *pURL, const char *pPost, OnHttpResponse onRespCb) int http_post_request_async(const char *pURL, const char *pPost, OnHttpResponse onRespCb)
{ {
long flag = (long)CURL_GLOBAL_ALL; long flag = (long)CURL_GLOBAL_ALL;
int value = 1; int value = 1, timeout = CURL_TIMEOUT;
CURL *pCurl = NULL; CURL *pCurl = NULL;
int ret = 0; int ret = 0;
struct curl_slist *pList; struct curl_slist *pList;
PHTTP_REQ_PARAMS pParams = NULL; 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)); pParams = (PHTTP_REQ_PARAMS)malloc(sizeof(HTTP_REQ_PARAMS));
if(pParams == NULL) { if(pParams == NULL) {
@ -72,13 +79,10 @@ int http_post_request(const char *pURL, const char *pPost, OnHttpResponse onResp
memset(pParams, 0, sizeof(HTTP_REQ_PARAMS)); memset(pParams, 0, sizeof(HTTP_REQ_PARAMS));
pParams->onRspCb = onRespCb; pParams->onRspCb = onRespCb;
pParams->pReqUrl = (char *)malloc(strlen(pURL) + 1); pParams->pReqUrl = strdup(pURL);
pParams->dlSize = 0; pParams->dlSize = 0;
pParams->pCurl = pCurl; pParams->pCurl = pCurl;
memset(pParams->pReqUrl, 0, strlen(pURL) + 1);
strcpy(pParams->pReqUrl, pURL);
pList = curl_slist_append(NULL, "Content-Type:application/json;charset=UTF-8"); pList = curl_slist_append(NULL, "Content-Type:application/json;charset=UTF-8");
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, __writeDataCb); curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, __writeDataCb);
@ -86,6 +90,7 @@ int http_post_request(const char *pURL, const char *pPost, OnHttpResponse onResp
curl_easy_setopt(pCurl, CURLOPT_PRIVATE, pParams); curl_easy_setopt(pCurl, CURLOPT_PRIVATE, pParams);
curl_easy_setopt(pCurl, CURLOPT_URL, pURL); curl_easy_setopt(pCurl, CURLOPT_URL, pURL);
curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, value); 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_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList); curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList);
@ -125,16 +130,19 @@ int http_post_request(const char *pURL, const char *pPost, OnHttpResponse onResp
ret = curl_easy_perform(pCurl); ret = curl_easy_perform(pCurl);
if(ret != CURLE_OK) { if(ret != CURLE_OK) {
LOG_EX(LOG_Error, "Http Post error: %u\n", ret); LOG_EX(LOG_Error, "Http Post error(%u): %s\n", ret, curl_easy_strerror(ret));
} }
curl_slist_free_all(pList); curl_slist_free_all(pList);
curl_easy_cleanup(pCurl); curl_easy_cleanup(pCurl);
curl_global_cleanup(); curl_global_cleanup();
if(onRespCb) { if(onRespCb && ret == CURLE_OK) {
onRespCb(pParams->reqResult, pParams->dlSize, pParams->pReqUrl, pParams->sPath, onRespCb(pParams->reqResult, pParams->dlSize, pParams->pReqUrl, pParams->sPath,
NULL, -pParams->errCode, pParams->pData); NULL, CURLE_OK, pParams->pData);
} else {
onRespCb(NULL, 0, pParams->pReqUrl, pParams->sPath,
NULL, -ret, pParams->pData);
} }
if(pParams->pReqUrl) { if(pParams->pReqUrl) {
@ -145,3 +153,118 @@ int http_post_request(const char *pURL, const char *pPost, OnHttpResponse onResp
return ret; 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;
}

View File

@ -24,6 +24,7 @@
#define ERR_SRCERR (15) #define ERR_SRCERR (15)
#define ERR_JSONERR (16) #define ERR_JSONERR (16)
#define ERR_USED (17) #define ERR_USED (17)
#define ERR_OUTSIZE (18)
#define ERR_READFILE (100) #define ERR_READFILE (100)
@ -34,45 +35,27 @@ static inline char *err2string(int err)
} }
switch(err) { switch(err) {
case ERR_OK: return "OK"; case ERR_OK: return (char*) "OK";
case ERR_ERR: return (char*) "Error";
case ERR_ERR: return "Error"; case ERR_UNKNOWN: return (char*) "Unkown";
case ERR_SYSERR: return (char*) "SystemError";
case ERR_UNKNOWN: return "Unkown"; case ERR_NOTFOUND: return (char*) "NotFound";
case ERR_TIMEOUT: return (char*) "Timeout";
case ERR_SYSERR: return "SystemError"; case ERR_NULLP: return (char*) "NullPointer" ;
case ERR_NOMEM: return (char*) "NotEnoughMemory";
case ERR_NOTFOUND: return "NotFound"; case ERR_CHKERR: return (char*) "CheckError";
case ERR_NOTSUPPORT: return (char*) "NotSupport";
case ERR_TIMEOUT: return "Timeout"; case ERR_INPUTERR: return (char*) "InputError";
case ERR_EXIST: return (char*) "AlreadyExist";
case ERR_NULLP: return "NullPointer" ; case ERR_FULL: return (char*) "Full";
case ERR_SENDERR: return (char*) "SendErr";
case ERR_NOMEM: return "NotEnoughMemory"; case ERR_NOCMID: return (char*) "CanNotFindConfig";
case ERR_SRCERR: return (char*) "ConfigSourceErr";
case ERR_CHKERR: return "CheckError"; case ERR_JSONERR: return (char*) "JsonFormatErr";
case ERR_USED: return (char*) "ItemUsed";
case ERR_NOTSUPPORT: return "NotSupport"; case ERR_READFILE: return (char*) "Read File Error";
case ERR_OUTSIZE: return (char*) "Out of memory size";
case ERR_INPUTERR: return "InputError"; default: return (char*) "Unknown err code";
case ERR_EXIST: return "AlreadyExist";
case ERR_FULL: return "Full";
case ERR_SENDERR: return "SendErr";
case ERR_NOCMID: return "CanNotFindConfig";
case ERR_SRCERR: return "ConfigSourceErr";
case ERR_JSONERR: return "JsonFormatErr";
case ERR_USED: return "ItemUsed";
case ERR_READFILE: return "Read File Error";
default: return "Unknown err code";
} }
} }

View File

@ -17,8 +17,8 @@ typedef struct {
typedef struct { typedef struct {
char *status; char *status;
unsigned int iptype; int iptype;
unsigned int ip; char *ip;
char *code; char *code;
} AUTH_ZTH_RSP, *PAUTH_ZTH_RSP; } AUTH_ZTH_RSP, *PAUTH_ZTH_RSP;

View File

@ -8,5 +8,7 @@
typedef void (*OnHttpResponse)(void *pData, unsigned int size, const char *pReqUrl, typedef void (*OnHttpResponse)(void *pData, unsigned int size, const char *pReqUrl,
const char *pDlPath, const char *pTaskUuid, int iFinished, void *pUserData); const char *pDlPath, const char *pTaskUuid, int iFinished, void *pUserData);
int http_post_request(const char *pURL, const char *pPost, OnHttpResponse onRespCb); int http_post_request_async(const char *pURL, const char *pPost, OnHttpResponse onRespCb);
int http_post_request(const char *pURL, const char *pPost, unsigned char* pBuf, unsigned int *pOutSize);
#endif //ZTP_CLIENT_RESTFUL_H #endif //ZTP_CLIENT_RESTFUL_H

View File

@ -67,13 +67,14 @@ static int __ztp_auth_decode(const char *pJsonS, void **pStruct)
pVal = cJSON_GetObjectItem(pRoot, "iptype"); pVal = cJSON_GetObjectItem(pRoot, "iptype");
if(cJSON_IsString(pVal)) { if(cJSON_IsString(pVal)) {
pData->iptype = (unsigned int)strtoul(pVal->valuestring, 0, 10); pData->iptype = (int)strtoul(pVal->valuestring, 0, 10);
} }
pVal = cJSON_GetObjectItem(pRoot, "ip"); pVal = cJSON_GetObjectItem(pRoot, "ip");
if(cJSON_IsString(pVal)) { if(cJSON_IsString(pVal)) {
pData->ip = (unsigned int)strtoul(pVal->valuestring, 0, 10); pData->ip = strdup(pVal->valuestring);
//(unsigned int)strtoul(pVal->valuestring, 0, 10);
} }
pVal = cJSON_GetObjectItem(pRoot, "code"); pVal = cJSON_GetObjectItem(pRoot, "code");

View File

@ -4,12 +4,12 @@ project(googletest-download NONE)
include(ExternalProject) include(ExternalProject)
ExternalProject_Add(googletest ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master GIT_TAG master
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""
INSTALL_COMMAND "" INSTALL_COMMAND ""
TEST_COMMAND "" TEST_COMMAND ""
) )

View File

@ -11,10 +11,9 @@ using namespace std;
extern "C" { extern "C" {
#include "err_code.h" #include "err_code.h"
#include "json_interface.h" #include "json_interface.h"
#include "restful.h"
} }
TEST(json_encode_test, retOK) TEST(json_test, encode)
{ {
int ret = 0; int ret = 0;
const char *pJson; const char *pJson;
@ -32,7 +31,7 @@ TEST(json_encode_test, retOK)
ASSERT_EQ(ERR_OK, ret); ASSERT_EQ(ERR_OK, ret);
} }
TEST(json_decode_test, retOK) TEST(json_test, decode)
{ {
#define JSON_STR ("{\"code\":\"fBBx8Q\",\"ip\":\"172.28.73.38\",\"iptype\":\"1\",\"status\":\"SUCCESS\"}") #define JSON_STR ("{\"code\":\"fBBx8Q\",\"ip\":\"172.28.73.38\",\"iptype\":\"1\",\"status\":\"SUCCESS\"}")
int ret = 0; int ret = 0;
@ -59,77 +58,6 @@ TEST(json_decode_test, retOK)
ASSERT_EQ(0, ret); ASSERT_EQ(0, ret);
} }
TEST(ztp_auth, success)
{
#define JSON_REQ ("{\"ESN\": \"tt21\"}")
#define REQ_URL ("http://172.28.73.43:8088/device/esn")
int ret;
int size = 4096;
char buf[4096];
PAUTH_ZTH_RSP pZTPRsp;
memset(buf, 0, 4096);
ret = http_post_request(REQ_URL, JSON_REQ, (unsigned char*)buf, &size);
EXPECT_EQ(ERR_OK, ret);
ret = Json2Struct(buf, &pZTPRsp, JE_AUTH_ZTP, false);
ASSERT_EQ(ERR_OK, ret);
ASSERT_STRCASEEQ(pZTPRsp->status, "SUCCESS");
if(pZTPRsp) {
if(pZTPRsp->status) {
free(pZTPRsp->status);
}
if(pZTPRsp->code) {
free(pZTPRsp->code);
}
if(pZTPRsp->ip) {
free(pZTPRsp->ip);
}
free(pZTPRsp);
}
}
TEST(ztp_auth, failed)
{
#define JSON_REQ_FAIL ("{\"ESN\": \"ace08484843\"}")
int ret;
int size = 4096;
char buf[4096];
PAUTH_ZTH_RSP pZTPRsp;
memset(buf, 0, 4096);
ret = http_post_request(REQ_URL, JSON_REQ_FAIL, (unsigned char*)buf, &size);
EXPECT_EQ(ERR_OK, ret);
ret = Json2Struct(buf, &pZTPRsp, JE_AUTH_ZTP, false);
ASSERT_EQ(ERR_OK, ret);
ASSERT_STRCASEEQ(pZTPRsp->status, "FAILED");
if(pZTPRsp) {
if(pZTPRsp->status) {
free(pZTPRsp->status);
}
if(pZTPRsp->code) {
free(pZTPRsp->code);
}
if(pZTPRsp->ip) {
free(pZTPRsp->ip);
}
free(pZTPRsp);
}
}
auto main(int argc, char *argv[]) -> int auto main(int argc, char *argv[]) -> int
{ {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);

View File

@ -0,0 +1,92 @@
//
// Created by xajhu on 2019/12/2 0002.
//
#include <iostream>
using namespace std;
#include "gtest/gtest.h"
extern "C" {
#include "err_code.h"
#include "json_interface.h"
#include "restful.h"
}
TEST(ztp_auth, authorized_success)
{
#define JSON_REQ ("{\"ESN\": \"tt21\"}")
#define REQ_URL ("http://172.28.73.43:8088/device/esn")
int ret;
unsigned int size = 4096;
char buf[4096];
PAUTH_ZTH_RSP pZTPRsp;
memset(buf, 0, 4096);
ret = http_post_request(REQ_URL, JSON_REQ, (unsigned char *)buf, &size);
EXPECT_EQ(ERR_OK, ret);
ret = Json2Struct(buf, &pZTPRsp, JE_AUTH_ZTP, false);
ASSERT_EQ(ERR_OK, ret);
ASSERT_STRCASEEQ(pZTPRsp->status, "SUCCESS") << "\nValue-->["
<< "status: " << pZTPRsp->status
<< ", code: " << pZTPRsp->code
<< ", ip: " << pZTPRsp->ip
<< ", iptype: " << pZTPRsp->iptype << "]" <<endl;
if(pZTPRsp) {
if(pZTPRsp->status) {
free(pZTPRsp->status);
}
if(pZTPRsp->code) {
free(pZTPRsp->code);
}
if(pZTPRsp->ip) {
free(pZTPRsp->ip);
}
free(pZTPRsp);
}
}
TEST(ztp_auth, unauthorized_failed)
{
#define JSON_REQ_FAIL ("{\"ESN\": \"ace08484843\"}")
int ret;
unsigned int size = 4096;
char buf[4096];
PAUTH_ZTH_RSP pZTPRsp;
memset(buf, 0, 4096);
ret = http_post_request(REQ_URL, JSON_REQ_FAIL, (unsigned char *)buf, &size);
EXPECT_EQ(ERR_OK, ret);
ret = Json2Struct(buf, &pZTPRsp, JE_AUTH_ZTP, false);
ASSERT_EQ(ERR_OK, ret);
ASSERT_STRCASEEQ(pZTPRsp->status, "FAILED");
if(pZTPRsp) {
if(pZTPRsp->status) {
free(pZTPRsp->status);
}
if(pZTPRsp->code) {
free(pZTPRsp->code);
}
if(pZTPRsp->ip) {
free(pZTPRsp->ip);
}
free(pZTPRsp);
}
}

View File

@ -28,33 +28,36 @@ void __onPost(void *pData, unsigned int size, const char *pReqUrl,
if(pUserData && strlen(pUserData) > 0) { if(pUserData && strlen(pUserData) > 0) {
LOG_EX(LOG_Info, "Post Data: [%s]\n", pUserData); LOG_EX(LOG_Info, "Post Data: [%s]\n", pUserData);
} }
LOG_EX(LOG_Info, "Post Result: [%s]\n", (char *)pData);
ret = Json2Struct(pData, &pZTPRsp, JE_AUTH_ZTP, FALSE); if(pData) {
LOG_EX(LOG_Info, "Post Result: [%s]\n", (char *)pData);
if(ret == ERR_OK && pZTPRsp) { ret = Json2Struct(pData, &pZTPRsp, JE_AUTH_ZTP, FALSE);
if(strcasecmp(pZTPRsp->status, "SUCCESS") == 0) {
LOG_EX(LOG_Debug, "Request OK\n"); if(ret == ERR_OK && pZTPRsp) {
if(strcasecmp(pZTPRsp->status, "SUCCESS") == 0) {
LOG_EX(LOG_Debug, "Request OK\n");
} else {
LOG_EX(LOG_Error, "Request Error\n");
}
} else { } else {
LOG_EX(LOG_Error, "Request Error\n"); LOG_EX(LOG_Error, "Decode JSON error: %d\n", ret);
}
} else {
LOG_EX(LOG_Error, "Decode JSON error: %d\n", ret);
}
if(pZTPRsp) {
if(pZTPRsp->status) {
free(pZTPRsp->status);
} }
if(pZTPRsp->code) { if(pZTPRsp) {
free(pZTPRsp->code); if(pZTPRsp->status) {
} free(pZTPRsp->status);
}
if(pZTPRsp->ip) { if(pZTPRsp->code) {
free(pZTPRsp->ip); free(pZTPRsp->code);
}
if(pZTPRsp->ip) {
free(pZTPRsp->ip);
}
free(pZTPRsp);
} }
free(pZTPRsp);
} }
} }