#include "pch.h" #include "tunnel.h" #include "protocol.h" #include "globalcfg.h" #include "httplib.h" #include "misc.h" #include "usrerr.h" #include #include #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 (UsedSCGProxy()) { TCHAR scgProxyUrl[MAX_PATH]; StringCbPrintf(scgProxyUrl, MAX_PATH, TEXT("http://127.0.0.1:%d"), GetGlobalCfgInfo()->scgProxy.scgGwPort); SPDLOG_DEBUG(TEXT("Control Server Used Proxy: {0} --> {1}"), pUserSvrUrl, scgProxyUrl); g_tunnelHttpCtx = new httplib::Client(scgProxyUrl); } else { g_tunnelHttpCtx = new httplib::Client(pUserSvrUrl); SPDLOG_DEBUG(TEXT("Control Server Unused Proxy: {0}"), 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_keep_alive(true); g_tunnelHttpCtx->set_post_connect_cb([](socket_t sock) { if (UsedSCGProxy()) { int ret; unsigned char vmid[4]; unsigned char *p; const unsigned int id = htonl(GetGlobalCfgInfo()->curConnVmId); const auto svrId = static_cast(GetGlobalCfgInfo()->userCfg.cliConfig.scgCtrlAppId); unsigned char scgProxy[] = {0x01, // VERSION 0x00, // Length 0 0x0B, // Length 1 0xF0, // ++++++ INFO[0] TYPE 0x00, // INFO[0] LENGTH 0 0x04, // INFO[0] LENGTH 1 0, // INFO[0] VMID[0] 0, // INFO[0] VMID[1] 0, // INFO[0] VMID[2] 0, // INFO[0] VMID[3] 0xF1, // INFO[1] TYPE 0x00, // INFO[1] LENGTH 0 0x01, // INFO[1] LENGTH 1 svrId}; // ------ INFO[1] SCG Service ID p = scgProxy; memcpy(vmid, &id, 4); scgProxy[6] = vmid[0]; scgProxy[7] = vmid[1]; scgProxy[8] = vmid[2]; scgProxy[9] = vmid[3]; if (GetGlobalCfgInfo()->logLevel == spdlog::level::trace) { std::array arr; std::copy(std::begin(scgProxy), std::end(scgProxy), std::begin(arr)); SPDLOG_DEBUG(TEXT("TCP Proxy SCG Payload: {0:Xa}"), spdlog::to_hex(arr)); } ret = send(sock, reinterpret_cast(p), sizeof(scgProxy), 0); while (ret < static_cast(sizeof(scgProxy))) { p += ret; ret += send(sock, reinterpret_cast(p), sizeof(scgProxy), 0); } SPDLOG_DEBUG(TEXT("Service Connected To SCG Server({1}/{2}): {0}"), sock, GetGlobalCfgInfo()->curConnVmId, svrId); } }); } SPDLOG_DEBUG(TEXT("Connect to Tunnel Control Service: {0}"), pUserSvrUrl); return ERR_SUCCESS; } template 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 g_httpCtx->set_keep_alive(true); g_httpCtx->enable_server_certificate_verification(false); } } if (aigc::JsonHelper::ObjectToJson(*pReqParams, json)) { *pOutJson = _strdup(json.c_str()); return ERR_SUCCESS; } return -ERR_JSON_CREATE; } template int DecodeProtocolResponse(T *pResponse, const TCHAR *pJson) { if (aigc::JsonHelper::JsonToObject(*pResponse, pJson)) { return ERR_SUCCESS; } return -ERR_JSON_DECODE; } template int ProtolPostMessage(const TCHAR *pUrlPath, ProtocolRequest *pReq, ProtocolResponse *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 *pReq params error")); return -ERR_INPUT_PARAMS; } if (pRsp == nullptr) { SPDLOG_ERROR(TEXT("Input ProtocolResponse *pRsp params error")); return -ERR_INPUT_PARAMS; } ret = CreateProtocolRequest(pReq, &pJson); if (ret != ERR_SUCCESS) { if (pJson) { free(pJson); } return ret; } if (platformServer) { std::string timestamp = std::to_string(time(nullptr)) + "000"; TCHAR hashValeu[MAX_PATH] = {0}; TCHAR hashBuf[1024] = {}; StringCbPrintf(hashBuf, 1024, TEXT("%s|%s|%s|%s"), GetGlobalCfgInfo()->clientId, GetGlobalCfgInfo()->clientSecret, timestamp.c_str(), pJson); if (lstrlen(GetGlobalCfgInfo()->clientSecret) > 0 && CalcHmacHash(HASH_SHA256, reinterpret_cast(hashBuf), lstrlen(hashBuf), reinterpret_cast(GetGlobalCfgInfo()->clientSecret), lstrlen(GetGlobalCfgInfo()->clientSecret), hashValeu, true) == ERR_SUCCESS) { const httplib::Headers headers = { {"gzs-client-id", GetGlobalCfgInfo()->clientId}, {"gzs-sign", hashValeu }, {"gzs-timestamp", timestamp }, }; res = g_httpCtx->Post(pUrlPath, headers, pJson, HTTP_JSON_CONTENT); } else { 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; } #if 0 template int PlatformProtolGetMessage(const TCHAR *pUrlPath, T1 *pRsp) { httplib::Result res; TCHAR *pJson = nullptr; std::string timestamp = std::to_string(time(nullptr)) + "000"; TCHAR hashValeu[MAX_PATH] = {0}; TCHAR hashBuf[1024] = {}; if (lstrlen(GetGlobalCfgInfo()->platformServerUrl) == 0) { SPDLOG_ERROR(TEXT("Platform Server URL uninitialize.")); return -ERR_SYSTEM_UNINITIALIZE; } if (pRsp == nullptr) { SPDLOG_ERROR(TEXT("Input ProtocolResponse *pRsp params error")); return -ERR_INPUT_PARAMS; } StringCbPrintf(hashBuf, 1024, TEXT("%s|%s|%s|%s"), GetGlobalCfgInfo()->clientId, GetGlobalCfgInfo()->clientSecret, timestamp.c_str(), pJson); if (lstrlen(GetGlobalCfgInfo()->clientSecret) > 0 && CalcHmacHash(HASH_SHA256, reinterpret_cast(hashBuf), lstrlen(hashBuf), reinterpret_cast(GetGlobalCfgInfo()->clientSecret), lstrlen(GetGlobalCfgInfo()->clientSecret), hashValeu, true) == ERR_SUCCESS) { const httplib::Headers headers = { {"gzs-client-id", GetGlobalCfgInfo()->clientId}, {"gzs-sign", hashValeu }, {"gzs-timestamp", timestamp }, }; res = g_httpCtx->Get(pUrlPath, headers); } else { res = g_httpCtx->Get(pUrlPath); } 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(T1).name()); return -ERR_JSON_DECODE; } return ERR_SUCCESS; } #endif #if !USER_REAL_PLATFORM template int PlatformProtolPostMessage(const TCHAR *pUrlPath, T1 *pReq, T2 *pRsp) { int ret; httplib::Result res; TCHAR *pJson = nullptr; std::string timestamp = std::to_string(time(nullptr)) + "000"; TCHAR hashValeu[MAX_PATH] = {0}; TCHAR hashBuf[1024] = {}; 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 *pReq params error")); return -ERR_INPUT_PARAMS; } if (pRsp == nullptr) { SPDLOG_ERROR(TEXT("Input ProtocolResponse *pRsp params error")); return -ERR_INPUT_PARAMS; } ret = CreateProtocolRequest(pReq, &pJson); if (ret != ERR_SUCCESS) { if (pJson) { free(pJson); } return ret; } StringCbPrintf(hashBuf, 1024, TEXT("%s|%s|%s|%s"), GetGlobalCfgInfo()->clientId, GetGlobalCfgInfo()->clientSecret, timestamp.c_str(), pJson); if (lstrlen(GetGlobalCfgInfo()->clientSecret) > 0 && CalcHmacHash(HASH_SHA256, reinterpret_cast(hashBuf), lstrlen(hashBuf), reinterpret_cast(GetGlobalCfgInfo()->clientSecret), lstrlen(GetGlobalCfgInfo()->clientSecret), hashValeu, true) == ERR_SUCCESS) { if (typeid(T1) == typeid(PlatformReqClientCfgParms)) { const auto *p = reinterpret_cast(pReq); const httplib::Headers headers = { {"gzs-client-id", GetGlobalCfgInfo()->clientId }, {"gzs-sign", hashValeu }, {"gzs-timestamp", timestamp }, {"Authorization", ("Bearer " + p->token).c_str()}, }; res = g_httpCtx->Post(pUrlPath, headers, pJson, HTTP_JSON_CONTENT); } else { const httplib::Headers headers = { {"gzs-client-id", GetGlobalCfgInfo()->clientId}, {"gzs-sign", hashValeu }, {"gzs-timestamp", timestamp }, }; res = g_httpCtx->Post(pUrlPath, headers, pJson, HTTP_JSON_CONTENT); } } else { if (typeid(T1) == typeid(PlatformReqClientCfgParms)) { const auto *p = reinterpret_cast(pReq); const httplib::Headers headers = { {"Authorization", ("Bearer " + p->token).c_str()}, }; res = g_httpCtx->Post(pUrlPath, headers, pJson, HTTP_JSON_CONTENT); } else { res = g_httpCtx->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; } SPDLOG_DEBUG(TEXT("+++++ Http Request {0}\n---- Http Response {1}"), pJson, res->body.c_str()); 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; } 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; } #endif template int ProtolPostMessage(const TCHAR *pUrlPath, ProtocolRequest *pReq, ProtocolResponse *pRsp, bool platformServer); template int ProtolPostMessage(const TCHAR *pUrlPath, ProtocolRequest *pReq, ProtocolResponse *pRsp, bool platformServer); template int ProtolPostMessage(const TCHAR *pUrlPath, ProtocolRequest *pReq, ProtocolResponse *pRsp, bool platformServer); template int ProtolPostMessage(const TCHAR *pUrlPath, ProtocolRequest *pReq, ProtocolResponse *pRsp, bool platformServer); template int ProtolPostMessage(const TCHAR *pUrlPath, ProtocolRequest *pReq, ProtocolResponse *pRsp, bool platformServer); #if !USER_REAL_PLATFORM template int PlatformProtolPostMessage(const TCHAR *pUrlPath, PlatformReqServerCfgParms *pReq, PlatformRspServerCfgParams *pRsp); template int PlatformProtolPostMessage(const TCHAR *pUrlPath, PlatformReqClientCfgParms *pReq, PlatformRspClientCfgParams *pRsp); //template int PlatformProtolGetMessage(const TCHAR *pUrlPath, PlatformRspUserClientCfgParams *pRsp); #endif