transm/client/main.cpp

148 lines
4.5 KiB
C++

#include <CLI11.hpp>
#include <iostream>
#include <of_util.h>
#include <regex>
#include "client.h"
#include "config.h"
#include "version.h"
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#include <windows.h>
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
#endif
std::shared_ptr<CServerConfig> g_Config = nullptr;
int parse_cmd(int argc, char** argv, CmdParam& param)
{
std::string intro(
fmt::format("tsc cmd introduce, version: {}\nopensource: {}", VERSION_NUM, VERSION_URL));
CLI::App app(intro);
app.add_option("-n, --number", param.use_config, "使用服务器地址组(值为使用--show中显示的序号)");
app.add_option("-a, --append", param.appendValue, "添加服务器地址组(地址格式:127.0.0.1:9898:注释)");
app.add_flag("-s, --show", param.showValue, "查看服务器地址组");
app.add_option("-r, --remove", param.removeValue, "移除服务器地址组(值为使用--show中显示的序号)");
app.add_flag("-d, --direct", param.direct_use, "添加服务器时直接使用此服务器。");
if (argc == 1) {
std::cout << app.help() << std::endl;
return 0;
}
// 这里的 CLI11_PARSE 在程序没有输入或者仅输入--help(-h)时,会直接返回,后面代码都不会执行。
// 当有自定义的参数被输入时,后面代码会执行。
try {
CLI11_PARSE(app, argc, argv);
} catch (const CLI::ParseError& e) {
return app.exit(e);
}
param.parsed = true;
return 0;
}
bool exec_cmd(CmdParam& param, bool& run)
{
run = false;
// 如果是展示
if (param.showValue) {
std::vector<TransmSet> set;
if (!g_Config->read_ini(set)) {
return false;
}
for (const auto& item : set) {
TLOGI("{} => {}:{} {}", item.group, item.ip, item.port, item.comment);
}
return true;
}
if (param.use_config != -1) {
run = true;
return true;
}
if (!param.appendValue.empty() && !param.removeValue.empty()) {
TLOGW("append and remove can't simultaneous operate!");
return false;
}
if (!param.appendValue.empty()) {
std::regex pattern(R"((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d+)(?::(.*))?)");
std::smatch matches;
std::string ip, port, comment;
if (std::regex_match(param.appendValue, matches, pattern)) {
ip = matches[1].str();
port = matches[2].str();
comment = matches.size() > 3 ? matches[3].str() : "default";
}
auto id = g_Config->append_ini(ip, std::stol(port), comment);
if (id < 0) {
TLOGW("add {}:{} failed.", ip, port);
return false;
}
TLOGI("add {}:{} success.", ip, port);
param.use_config = id;
return true;
}
if (!param.removeValue.empty()) {
if (!g_Config->remove_ini(std::stol(param.removeValue))) {
TLOGW("remove config num=[{}] failed, please check!", param.removeValue);
return false;
}
TLOGI("remove config num=[{}] success!", param.removeValue);
return true;
}
TLOGW("not matched!", param.removeValue);
return false;
}
int main(int argc, char* argv[])
{
#ifdef _WIN32
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode;
GetConsoleMode(hConsole, &mode);
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hConsole, mode);
#endif
std::shared_ptr<int> deleter(new int(), [](int* p) {
fc_recovery_color();
delete p;
});
g_Config = std::make_shared<CServerConfig>();
if (!g_Config->baseInit()) {
return -1;
}
bool run = false;
CmdParam param;
parse_cmd(argc, argv, param);
if (!param.parsed) {
return 0;
}
if (!exec_cmd(param, run)) {
TLOGW("exec_cmd failed!");
return -1;
}
if (!run && !param.direct_use) {
return 0;
}
std::vector<TransmSet> set;
if (!g_Config->read_ini(set)) {
return -1;
}
TransmSet use;
if (!g_Config->get_ini(set, param.use_config, use)) {
TLOGW("Not found config by num:[{}]", param.use_config);
return -1;
}
TLOGI("Build At {} {} under {} on {}", __DATE__, __TIME__, VERSION_GIT_COMMIT, VERSION_GIT_BRANCH);
TLOGI("use ip => [{}], port => [{}]", use.ip, use.port);
CClient client;
client.run(use.ip, std::to_string(use.port));
TLOGI("exit ==========");
return 0;
}