NetTunnelWindows/NetTunnelSDK/protocol/protocol.cpp

213 lines
8.0 KiB
C++

#include "pch.h"
#include "tunnel.h"
#include "protocol.h"
#include "globalcfg.h"
#include "httplib.h"
#include "usrerr.h"
#include <strsafe.h>
#define HTTP_JSON_CONTENT TEXT("application/json")
static httplib::Client *g_httpCtx = nullptr;
static httplib::Client *g_tunnelHttpCtx = nullptr;
int InitControlServer(const TCHAR *pUserSvrUrl) {
if (g_tunnelHttpCtx) {
delete g_tunnelHttpCtx;
g_tunnelHttpCtx = nullptr;
}
if (GetGlobalCfgInfo()->scgProxy.scgGwPort > 0) {
TCHAR scgProxyUrl[MAX_PATH];
StringCbPrintf(scgProxyUrl, MAX_PATH, TEXT("http://127.0.0.1:%d"), GetGlobalCfgInfo()->scgProxy.scgGwPort);
g_tunnelHttpCtx = new httplib::Client(pUserSvrUrl);
} else {
g_tunnelHttpCtx = new httplib::Client(pUserSvrUrl);
}
if (g_tunnelHttpCtx) {
g_tunnelHttpCtx->set_connection_timeout(0, 1000000); // 1 second
g_tunnelHttpCtx->set_read_timeout(5, 0); // 5 seconds
g_tunnelHttpCtx->set_write_timeout(5, 0); // 5 seconds
g_tunnelHttpCtx->set_post_connect_cb([](socket_t sock) {
if (UsedSCGProxy()) {
int ret;
unsigned char vmid[4];
const unsigned int id = htonl(GetGlobalCfgInfo()->curConnVmId);
unsigned char scgProxy[] = {0x01, // VERSION
0x09, // Length
0xF0, // ++++++ INFO[0] TYPE
0x04, // INFO[0] LENGTH
0, // INFO[0] VMID[0]
0, // INFO[0] VMID[1]
0, // INFO[0] VMID[2]
0, // INFO[0] VMID[3]
0xF1, // INFO[1] TYPE
0x01, // INFO[1] LENGTH
0x07}; // ------ INFO[1] SCG Service ID
unsigned char *p = scgProxy;
memcpy(vmid, &id, 4);
scgProxy[4] = vmid[0];
scgProxy[5] = vmid[1];
scgProxy[6] = vmid[2];
scgProxy[7] = vmid[3];
ret = send(sock, reinterpret_cast<const char *>(p), sizeof(scgProxy), 0);
while (ret < static_cast<int>(sizeof(scgProxy))) {
p += ret;
ret += send(sock, reinterpret_cast<const char *>(p), sizeof(scgProxy), 0);
}
SPDLOG_DEBUG(TEXT("Service Connected To SCG Server: {0}"), sock);
}
});
}
SPDLOG_DEBUG(TEXT("Connect to Tunnel Control Service: {0}"), pUserSvrUrl);
return ERR_SUCCESS;
}
template<class T> int CreateProtocolRequest(T *pReqParams, TCHAR **pOutJson) {
std::string json;
if (!g_httpCtx && lstrlen(GetGlobalCfgInfo()->platformServerUrl) > 0) {
g_httpCtx = new httplib::Client(GetGlobalCfgInfo()->platformServerUrl);
if (g_httpCtx) {
g_httpCtx->set_connection_timeout(0, 300000); // 300 milliseconds
g_httpCtx->set_read_timeout(5, 0); // 5 seconds
g_httpCtx->set_write_timeout(5, 0); // 5 seconds
}
}
if (aigc::JsonHelper::ObjectToJson(*pReqParams, json)) {
*pOutJson = _strdup(json.c_str());
return ERR_SUCCESS;
}
return -ERR_JSON_CREATE;
}
template<class T> int DecodeProtocolResponse(T *pResponse, const TCHAR *pJson) {
if (aigc::JsonHelper::JsonToObject(*pResponse, pJson)) {
return ERR_SUCCESS;
}
return -ERR_JSON_DECODE;
}
template<class T1, class T2>
int ProtolPostMessage(const TCHAR *pUrlPath,
ProtocolRequest<T1> *pReq,
ProtocolResponse<T2> *pRsp,
bool platformServer) {
int ret;
httplib::Result res;
TCHAR *pJson = nullptr;
if (lstrlen(GetGlobalCfgInfo()->platformServerUrl) == 0) {
SPDLOG_ERROR(TEXT("Platform Server URL uninitialize."));
return -ERR_SYSTEM_UNINITIALIZE;
}
if (pReq == nullptr) {
SPDLOG_ERROR(TEXT("Input pToken params error"));
SPDLOG_ERROR(TEXT("Input ProtocolRequest<T1> *pReq params error"));
return -ERR_INPUT_PARAMS;
}
if (pRsp == nullptr) {
SPDLOG_ERROR(TEXT("Input ProtocolResponse<T2> *pRsp params error"));
return -ERR_INPUT_PARAMS;
}
ret = CreateProtocolRequest(pReq, &pJson);
if (ret != ERR_SUCCESS) {
if (pJson) {
free(pJson);
}
return ret;
}
if (platformServer) {
res = g_httpCtx->Post(pUrlPath, pJson, HTTP_JSON_CONTENT);
} else {
if (g_tunnelHttpCtx == nullptr) {
free(pJson);
SPDLOG_ERROR(TEXT("Server Control Service don't connected(g_tunnelHttpCtx is not initialize)."));
return -ERR_SYSTEM_UNINITIALIZE;
}
res = g_tunnelHttpCtx->Post(pUrlPath, pJson, HTTP_JSON_CONTENT);
}
if (res.error() != httplib::Error::Success) {
SPDLOG_ERROR(TEXT("[{0}]:Post Data {1} error: {2}"), pUrlPath, pJson, httplib::to_string(res.error()));
free(pJson);
return -ERR_HTTP_POST_DATA;
}
if (res->status != 200) {
SPDLOG_ERROR(TEXT("[{0}]:Post Data {1} server return HTTP error: {2}"), pUrlPath, pJson, res->status);
free(pJson);
return -ERR_HTTP_SERVER_RSP;
}
SPDLOG_DEBUG(TEXT("+++++ Http Request {0}\n---- Http Response {1}"), pJson, res->body.c_str());
free(pJson);
if (lstrlen(res->body.c_str()) == 0) {
SPDLOG_ERROR(TEXT("Server response empty message"));
return -ERR_READ_FILE;
}
if (DecodeProtocolResponse(pRsp, res->body.c_str()) != ERR_SUCCESS) {
SPDLOG_ERROR(TEXT("Decode JSON {0} to ProtocolResponse<{1}> error"), res->body, typeid(T2).name());
return -ERR_JSON_DECODE;
}
return ERR_SUCCESS;
}
int ProtoGetUserConfigure(const TCHAR *pUser, const TCHAR *pToken) {
int ret;
ProtocolRequest<ReqGetUserCfgParams> req;
ProtocolResponse<RspUserSevrCfgParams> rsp;
ret = ProtolPostMessage(GET_SERVERCFG_PATH, &req, &rsp);
return ret;
}
template int ProtolPostMessage(const TCHAR *pUrlPath,
ProtocolRequest<ReqGetUserCfgParams> *pReq,
ProtocolResponse<RspUserSevrCfgParams> *pRsp,
bool platformServer);
template int ProtolPostMessage(const TCHAR *pUrlPath,
ProtocolRequest<ReqGetUserCfgParams> *pReq,
ProtocolResponse<RspUsrCliConfigParams> *pRsp,
bool platformServer);
template int ProtolPostMessage(const TCHAR *pUrlPath,
ProtocolRequest<ReqUserSetCliCfgParams> *pReq,
ProtocolResponse<RspUserSetCliCfgParams> *pRsp,
bool platformServer);
template int ProtolPostMessage(const TCHAR *pUrlPath,
ProtocolRequest<ReqStartTunnelParams> *pReq,
ProtocolResponse<ResponseStatus> *pRsp,
bool platformServer);
template int ProtolPostMessage(const TCHAR *pUrlPath,
ProtocolRequest<ReqHeartParams> *pReq,
ProtocolResponse<RspHeartParams> *pRsp,
bool platformServer);