NetTunnelWindows/NetTunnelSDK/ControlService.cpp

290 lines
11 KiB
C++

#include "pch.h"
#include "tunnel.h"
#include <spdlog/spdlog.h>
#include <objbase.h>
#include "globalcfg.h"
#include "httplib.h"
#include "misc.h"
#include "protocol.h"
#include "usrerr.h"
#include "user.h"
#include <strsafe.h>
static HANDLE g_ControlSvrThread = nullptr;
static httplib::Server g_httpServer;
static USER_SERVER_CONFIG g_UserSvrCfg;
/**
* @brief 连接到服务端控制服务
* @param pUserSvrUrl 服务端控制服务 URL 地址
*/
void ConnectServerControlService(const TCHAR *pUserSvrUrl) {
InitControlServer(pUserSvrUrl);
}
static void HttpResponseError(httplib::Response &pRes, int errCode, const TCHAR *pErrMessage) {
ProtocolResponse<ResponseStatus> rsp;
std::string json;
if (errCode != ERR_SUCCESS) {
rsp.msgContent.errCode = errCode;
}
if (pErrMessage && lstrlen(pErrMessage) > 0) {
rsp.msgContent.errMessage = pErrMessage;
} else {
if (errCode == ERR_SUCCESS) {
rsp.msgContent.errMessage = TEXT("OK");
}
}
if (aigc::JsonHelper::ObjectToJson(rsp, json)) {
pRes.set_content(json, TEXT("application/json"));
} else {
SPDLOG_ERROR(TEXT("ProtocolResponse<ResponseStatus> to json error"));
}
}
int CreateControlService(PUSER_SERVER_CONFIG pSvr) {
static WGSERVER_CONFIG g_curCliConfig = {};
static std::mutex g_InterfaceMutex;
DWORD dwStatus = 0;
// HTTP 服务已经运行
if (g_httpServer.is_running()) {
return ERR_SUCCESS;
}
// 线程已经运行
if (g_ControlSvrThread && GetExitCodeThread(g_ControlSvrThread, &dwStatus) && dwStatus == STILL_ACTIVE) {
return -ERR_ITEM_EXISTS;
}
if (pSvr == nullptr) {
SPDLOG_ERROR(TEXT("Input pSvr params error"));
return -ERR_INPUT_PARAMS;
}
if (pSvr->svrListenPort <= 0 || pSvr->svrListenPort >= 65535) {
SPDLOG_ERROR(TEXT("Input svrListenPort params error {0}"), pSvr->svrListenPort);
return -ERR_INPUT_PARAMS;
}
if (lstrlen(pSvr->svrPrivateKey) != lstrlen(TEXT("4PPcnW3wYewNpoXjNoY3hQuCnzTNq/E9hhfU9/U6QmY="))) {
SPDLOG_ERROR(TEXT("Input svrPrivateKey params length error {0}"), pSvr->svrPrivateKey);
return -ERR_INPUT_PARAMS;
}
if (lstrlen(pSvr->svrAddress) == 0) {
SPDLOG_ERROR(TEXT("Input svrAddress params error {0}"), pSvr->svrAddress);
return -ERR_INPUT_PARAMS;
}
// 保存参数
memcpy(&g_UserSvrCfg, pSvr, sizeof(USER_SERVER_CONFIG));
g_httpServer.set_exception_handler([](const auto &req, auto &res, std::exception_ptr ep) {
const auto fmt = TEXT("<h1>Error 500</h1><p>%s</p>");
char buf[BUFSIZ];
try {
std::rethrow_exception(ep);
}
catch (std::exception &e) {
StringCbPrintf(buf, BUFSIZ, fmt, e.what());
}
catch (...) { // See the following NOTE
StringCbPrintf(buf, BUFSIZ, fmt, TEXT("Unknown Exception"));
}
res.set_content(buf, TEXT("text/html"));
res.status = 500;
});
g_httpServer.set_error_handler([](const auto &req, auto &res) {
const auto fmt = TEXT("<p>Error Status: <span style='color:red;'>%d</span></p>");
char buf[BUFSIZ];
StringCbPrintf(buf, BUFSIZ, fmt, res.status);
res.set_content(buf, TEXT("text/html"));
});
g_httpServer.Post(SET_CLIENTHEART_PATH, [](const httplib::Request &req, httplib::Response &res) {
ProtocolResponse<RspHeartParams> rsp;
std::string json;
rsp.msgContent.errCode = ERR_SUCCESS;
rsp.msgContent.errMessage = TEXT("OK");
if (aigc::JsonHelper::ObjectToJson(rsp, json)) {
res.set_content(json, TEXT("application/json"));
} else {
SPDLOG_ERROR(TEXT("ProtocolResponse<ResponseStatus> to json error"));
}
});
g_httpServer.Post(SET_CLIENTSTART_TUNNEL, [](const httplib::Request &req, httplib::Response &res) {
ProtocolRequest<ReqStartTunnelParams> reqData;
if (aigc::JsonHelper::JsonToObject(reqData, req.body)) {
int ret;
bool isSvrStart = false;
g_InterfaceMutex.lock();
// Because of COM return CO_E_FIRST
CoInitialize(nullptr);
// 判断先前是否启动过服务
if ((ret = IsWireGuardServerRunning(GetGlobalCfgInfo()->userCfg.userName, &isSvrStart)) != ERR_SUCCESS) {
// 返回获取系统服务错误,是否未安装
HttpResponseError(res, ret, TEXT("Not found WireGuard application in system"));
SPDLOG_ERROR(TEXT("IsWireGuardServerInstalled error: {0}"), ret);
g_InterfaceMutex.unlock();
return;
}
// 当前服务状态和需要执行的操作不同
if (isSvrStart != reqData.msgContent.isStart) {
if (reqData.msgContent.isStart) {
// 启动服务
ret = WireGuardInstallDefaultServerService(true);
if (ret != ERR_SUCCESS) {
// 返回启动服务失败
SPDLOG_ERROR(TEXT("WireGuardInstallDefaultServerService error: {0}"), ret);
HttpResponseError(res, ret, TEXT("Start WireGuard Tunnel Service error."));
g_InterfaceMutex.unlock();
return;
}
} else {
if ((ret = WireGuardUnInstallServerService(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) {
// 返回停止服务失败
HttpResponseError(res, ret, TEXT("Stop pre running WireGuard service error"));
SPDLOG_ERROR(TEXT("WireGuardUnInstallServerService error: {0}"), ret);
g_InterfaceMutex.unlock();
return;
}
}
}
HttpResponseError(res, ERR_SUCCESS, nullptr);
g_InterfaceMutex.unlock();
}
});
g_httpServer.Post(SET_CLIENTCFG_PATH, [](const httplib::Request &req, httplib::Response &res) {
ProtocolRequest<ReqUserSetCliCfgParams> reqData;
if (aigc::JsonHelper::JsonToObject(reqData, req.body)) {
int ret;
bool isSvrStart = false;
g_InterfaceMutex.lock();
// Because of COM return CO_E_FIRST
CoInitialize(nullptr);
// 判断先前是否启动过服务
if ((ret = IsWireGuardServerRunning(GetGlobalCfgInfo()->userCfg.userName, &isSvrStart)) != ERR_SUCCESS) {
// 返回获取系统服务错误,是否未安装
HttpResponseError(res, ret, TEXT("Not found WireGuard application in system"));
SPDLOG_ERROR(TEXT("IsWireGuardServerInstalled error: {0}"), ret);
g_InterfaceMutex.unlock();
return;
}
if (isSvrStart) {
SPDLOG_DEBUG(TEXT("WireGuardUnInstallServerService: {0}"), GetGlobalCfgInfo()->userCfg.userName);
if ((ret = WireGuardUnInstallServerService(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) {
// 返回停止服务失败
HttpResponseError(res, ret, TEXT("Stop pre running WireGuard service error"));
SPDLOG_ERROR(TEXT("WireGuardUnInstallServerService error: {0}"), ret);
g_InterfaceMutex.unlock();
return;
}
}
memset(&g_curCliConfig, 0, sizeof(WGSERVER_CONFIG));
g_curCliConfig.ListenPort = g_UserSvrCfg.svrListenPort - 1;
StringCbCopy(g_curCliConfig.Name, 64, GetGlobalCfgInfo()->userCfg.userName);
StringCbCopy(g_curCliConfig.Address, 32, g_UserSvrCfg.svrAddress);
StringCbCopy(g_curCliConfig.PrivateKey, 64, g_UserSvrCfg.svrPrivateKey);
StringCbCopy(g_curCliConfig.CliPubKey, 64, reqData.msgContent.cliPublicKey.c_str());
StringCbPrintf(g_curCliConfig.AllowNet,
256,
TEXT("%s,%s"),
reqData.msgContent.cliNetwork.c_str(),
reqData.msgContent.cliTunnelAddr.c_str());
// 创建 WireGuard 配置文件
ret = WireGuardCreateServerConfig(&g_curCliConfig);
if (ret != ERR_SUCCESS) {
// 返回写入 WireGuard 配置文件错误
HttpResponseError(res, ret, TEXT("Create WireGuard service configure file error"));
SPDLOG_ERROR(TEXT("WireGuardCreateServerConfig error: {0}"), ret);
g_InterfaceMutex.unlock();
return;
}
#if 0
// 启动服务
ret = WireGuardInstallDefaultServerService(true);
if (ret != ERR_SUCCESS) {
// 返回启动服务失败
return;
}
// 设置路由表
#endif
// 返回成功
HttpResponseError(res, ERR_SUCCESS, nullptr);
g_InterfaceMutex.unlock();
}
});
SPDLOG_DEBUG(TEXT("Start HTTP Service at {0}"), pSvr->svrListenPort);
if (!g_httpServer.bind_to_port(TEXT("localhost"), pSvr->svrListenPort)) {
SPDLOG_ERROR(TEXT("Start HTTP Service at {0} error"), pSvr->svrListenPort);
return -ERR_SOCKET_BIND_PORT;
}
g_ControlSvrThread = CreateThread(
nullptr, // Thread attributes
0, // Stack size (0 = use default)
[](LPVOID lpParameter) {
if (!g_httpServer.listen_after_bind()) {
SPDLOG_ERROR(TEXT("Start HTTP Service at {0} error"));
}
SPDLOG_DEBUG(TEXT("Http service exit....."));
return static_cast<DWORD>(0);
}, // Thread start address
nullptr, // Parameter to pass to the thread
0, // Creation flags
nullptr); // Thread id
if (g_ControlSvrThread == nullptr) {
// Thread creation failed.
// More details can be retrieved by calling GetLastError()
return -ERR_CREATE_THREAD;
}
g_httpServer.wait_until_ready();
return ERR_SUCCESS;
}
int StopControlService() {
if (g_httpServer.is_running()) {
g_httpServer.stop();
}
if (g_ControlSvrThread) {
// Wait for thread to finish execution
if (WaitForSingleObject(g_ControlSvrThread, 10 * 1000) == WAIT_TIMEOUT) {
SPDLOG_ERROR(TEXT("Waitting HTTP Service clost timeout"));
return -ERROR_TIMEOUT;
}
CloseHandle(g_ControlSvrThread);
g_ControlSvrThread = nullptr;
}
return ERR_SUCCESS;
}