mirror of
https://github.com/springzfx/cgproxy.git
synced 2026-05-26 18:15:30 +08:00
build library
This commit is contained in:
@@ -3,10 +3,22 @@ find_package(nlohmann_json REQUIRED)
|
|||||||
include_directories(${PROJECT_SOURCE_DIR})
|
include_directories(${PROJECT_SOURCE_DIR})
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
add_library(cgproxy-lib
|
||||||
|
SHARED
|
||||||
|
common.cpp
|
||||||
|
config.cpp
|
||||||
|
cgroup_attach.cpp
|
||||||
|
socket_server.cpp socket_client.cpp
|
||||||
|
)
|
||||||
|
set_target_properties(cgproxy-lib PROPERTIES LINKER_LANGUAGE CXX)
|
||||||
|
set_target_properties(cgproxy-lib PROPERTIES OUTPUT_NAME cgproxy)
|
||||||
|
target_link_libraries(cgproxy-lib nlohmann_json::nlohmann_json)
|
||||||
|
|
||||||
add_executable(cgproxyd cgproxyd.cpp)
|
add_executable(cgproxyd cgproxyd.cpp)
|
||||||
add_executable(cgproxy cgproxy.cpp)
|
add_executable(cgproxy cgproxy.cpp)
|
||||||
target_link_libraries(cgproxyd PRIVATE Threads::Threads nlohmann_json::nlohmann_json)
|
target_link_libraries(cgproxyd cgproxy-lib Threads::Threads nlohmann_json::nlohmann_json)
|
||||||
target_link_libraries(cgproxy PRIVATE nlohmann_json::nlohmann_json)
|
target_link_libraries(cgproxy cgproxy-lib nlohmann_json::nlohmann_json)
|
||||||
|
|
||||||
install(TARGETS cgproxyd DESTINATION /usr/bin PERMISSIONS ${basic_permission})
|
install(TARGETS cgproxyd DESTINATION /usr/bin PERMISSIONS ${basic_permission})
|
||||||
install(TARGETS cgproxy DESTINATION /usr/bin PERMISSIONS ${basic_permission})
|
install(TARGETS cgproxy DESTINATION /usr/bin PERMISSIONS ${basic_permission})
|
||||||
|
install(TARGETS cgproxy-lib DESTINATION /usr/lib PERMISSIONS ${basic_permission})
|
||||||
|
|||||||
84
src/cgroup_attach.cpp
Normal file
84
src/cgroup_attach.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#include "cgroup_attach.hpp"
|
||||||
|
|
||||||
|
namespace CGPROXY::CGROUP {
|
||||||
|
|
||||||
|
bool exist(string path) {
|
||||||
|
struct stat st;
|
||||||
|
if (stat(path.c_str(), &st) != -1) { return S_ISDIR(st.st_mode); }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validate(string pid, string cgroup) {
|
||||||
|
bool pid_v = validPid(pid);
|
||||||
|
bool cg_v = validCgroup(cgroup);
|
||||||
|
if (pid_v && cg_v) return true;
|
||||||
|
|
||||||
|
error("attach paramater validate error");
|
||||||
|
return_error
|
||||||
|
}
|
||||||
|
|
||||||
|
string get_cgroup2_mount_point(int &status) {
|
||||||
|
char cgroup2_mount_point[100] = "";
|
||||||
|
FILE *fp = popen("findmnt -t cgroup2 -n -o TARGET", "r");
|
||||||
|
int count = fscanf(fp, "%s", cgroup2_mount_point);
|
||||||
|
fclose(fp);
|
||||||
|
if (count == 0) {
|
||||||
|
error("cgroup2 not supported");
|
||||||
|
status = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
status = 0;
|
||||||
|
return cgroup2_mount_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
int attach(const string pid, const string cgroup_target) {
|
||||||
|
if (getuid() != 0) {
|
||||||
|
error("need root to attach cgroup");
|
||||||
|
return_error
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("attaching %s to %s", pid.c_str(), cgroup_target.c_str());
|
||||||
|
|
||||||
|
int status;
|
||||||
|
if (!validate(pid, cgroup_target))
|
||||||
|
return_error string cgroup_mount_point = get_cgroup2_mount_point(status);
|
||||||
|
if (status != 0)
|
||||||
|
return_error string cgroup_target_path = cgroup_mount_point + cgroup_target;
|
||||||
|
string cgroup_target_procs = cgroup_target_path + "/cgroup.procs";
|
||||||
|
|
||||||
|
// check if exist, we will create it if not exist
|
||||||
|
if (!exist(cgroup_target_path)) {
|
||||||
|
if (mkdir(cgroup_target_path.c_str(),
|
||||||
|
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) {
|
||||||
|
debug("created cgroup %s success", cgroup_target.c_str());
|
||||||
|
} else {
|
||||||
|
error("created cgroup %s failed, errno %d", cgroup_target.c_str(), errno);
|
||||||
|
return_error
|
||||||
|
}
|
||||||
|
// error("cgroup %s not exist",cgroup_target.c_str());
|
||||||
|
// return_error
|
||||||
|
}
|
||||||
|
|
||||||
|
// put pid to target cgroup
|
||||||
|
ofstream procs(cgroup_target_procs, ofstream::app);
|
||||||
|
if (!procs.is_open()) {
|
||||||
|
error("open file %s failed", cgroup_target_procs.c_str());
|
||||||
|
return_error
|
||||||
|
}
|
||||||
|
procs << pid.c_str() << endl;
|
||||||
|
procs.close();
|
||||||
|
|
||||||
|
// maybe there some write error, for example process pid may not exist
|
||||||
|
if (!procs) {
|
||||||
|
error("write %s to %s failed, maybe process %s not exist", pid.c_str(),
|
||||||
|
cgroup_target_procs.c_str(), pid.c_str());
|
||||||
|
return_error
|
||||||
|
}
|
||||||
|
return_success
|
||||||
|
}
|
||||||
|
|
||||||
|
int attach(const int pid, const string cgroup_target) {
|
||||||
|
return attach(to_str(pid), cgroup_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CGPROXY::CGROUP
|
||||||
@@ -16,84 +16,15 @@ using namespace std;
|
|||||||
|
|
||||||
namespace CGPROXY::CGROUP {
|
namespace CGPROXY::CGROUP {
|
||||||
|
|
||||||
bool exist(string path) {
|
bool exist(string path);
|
||||||
struct stat st;
|
|
||||||
if (stat(path.c_str(), &st) != -1) { return S_ISDIR(st.st_mode); }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validate(string pid, string cgroup) {
|
bool validate(string pid, string cgroup);
|
||||||
bool pid_v = validPid(pid);
|
|
||||||
bool cg_v = validCgroup(cgroup);
|
|
||||||
if (pid_v && cg_v) return true;
|
|
||||||
|
|
||||||
error("attach paramater validate error");
|
string get_cgroup2_mount_point(int &status);
|
||||||
return_error
|
|
||||||
}
|
|
||||||
|
|
||||||
string get_cgroup2_mount_point(int &status) {
|
int attach(const string pid, const string cgroup_target);
|
||||||
char cgroup2_mount_point[100] = "";
|
|
||||||
FILE *fp = popen("findmnt -t cgroup2 -n -o TARGET", "r");
|
|
||||||
int count = fscanf(fp, "%s", cgroup2_mount_point);
|
|
||||||
fclose(fp);
|
|
||||||
if (count == 0) {
|
|
||||||
error("cgroup2 not supported");
|
|
||||||
status = -1;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
status = 0;
|
|
||||||
return cgroup2_mount_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
int attach(const string pid, const string cgroup_target) {
|
int attach(const int pid, const string cgroup_target);
|
||||||
if (getuid() != 0) {
|
|
||||||
error("need root to attach cgroup");
|
|
||||||
return_error
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("attaching %s to %s", pid.c_str(), cgroup_target.c_str());
|
|
||||||
|
|
||||||
int status;
|
|
||||||
if (!validate(pid, cgroup_target))
|
|
||||||
return_error string cgroup_mount_point = get_cgroup2_mount_point(status);
|
|
||||||
if (status != 0)
|
|
||||||
return_error string cgroup_target_path = cgroup_mount_point + cgroup_target;
|
|
||||||
string cgroup_target_procs = cgroup_target_path + "/cgroup.procs";
|
|
||||||
|
|
||||||
// check if exist, we will create it if not exist
|
|
||||||
if (!exist(cgroup_target_path)) {
|
|
||||||
if (mkdir(cgroup_target_path.c_str(),
|
|
||||||
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) {
|
|
||||||
debug("created cgroup %s success", cgroup_target.c_str());
|
|
||||||
} else {
|
|
||||||
error("created cgroup %s failed, errno %d", cgroup_target.c_str(), errno);
|
|
||||||
return_error
|
|
||||||
}
|
|
||||||
// error("cgroup %s not exist",cgroup_target.c_str());
|
|
||||||
// return_error
|
|
||||||
}
|
|
||||||
|
|
||||||
// put pid to target cgroup
|
|
||||||
ofstream procs(cgroup_target_procs, ofstream::app);
|
|
||||||
if (!procs.is_open()) {
|
|
||||||
error("open file %s failed", cgroup_target_procs.c_str());
|
|
||||||
return_error
|
|
||||||
}
|
|
||||||
procs << pid.c_str() << endl;
|
|
||||||
procs.close();
|
|
||||||
|
|
||||||
// maybe there some write error, for example process pid may not exist
|
|
||||||
if (!procs) {
|
|
||||||
error("write %s to %s failed, maybe process %s not exist", pid.c_str(),
|
|
||||||
cgroup_target_procs.c_str(), pid.c_str());
|
|
||||||
return_error
|
|
||||||
}
|
|
||||||
return_success
|
|
||||||
}
|
|
||||||
|
|
||||||
int attach(const int pid, const string cgroup_target) {
|
|
||||||
return attach(to_str(pid), cgroup_target);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace CGPROXY::CGROUP
|
} // namespace CGPROXY::CGROUP
|
||||||
|
|
||||||
|
|||||||
33
src/common.cpp
Normal file
33
src/common.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
bool enable_debug = false;
|
||||||
|
|
||||||
|
string join2str(const vector<string> t, const char delm) {
|
||||||
|
string s;
|
||||||
|
for (const auto &e : t) e != *(t.end() - 1) ? s += e + delm : s += e;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
string join2str(const int argc, char **argv, const char delm) {
|
||||||
|
string s;
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
s += argv[i];
|
||||||
|
if (i != argc - 1) s += delm;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validCgroup(const string cgroup) {
|
||||||
|
return regex_match(cgroup, regex("^/[a-zA-Z0-9\\-_./@]*$"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validCgroup(const vector<string> cgroup) {
|
||||||
|
for (auto &e : cgroup) {
|
||||||
|
if (!regex_match(e, regex("^/[a-zA-Z0-9\\-_./@]*$"))) { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validPid(const string pid) { return regex_match(pid, regex("^[0-9]+$")); }
|
||||||
|
|
||||||
|
bool validPort(const int port) { return port > 0; }
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static bool enable_debug = false;
|
extern bool enable_debug;
|
||||||
|
|
||||||
#define error(...) \
|
#define error(...) \
|
||||||
{ \
|
{ \
|
||||||
@@ -57,34 +57,16 @@ template <typename... T> string to_str(T... args) {
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
string join2str(const vector<string> t, const char delm = ' ') {
|
string join2str(const vector<string> t, const char delm = ' ');
|
||||||
string s;
|
|
||||||
for (const auto &e : t) e != *(t.end() - 1) ? s += e + delm : s += e;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
string join2str(const int argc, char **argv, const char delm = ' ') {
|
string join2str(const int argc, char **argv, const char delm = ' ');
|
||||||
string s;
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
s += argv[i];
|
|
||||||
if (i != argc - 1) s += delm;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validCgroup(const string cgroup) {
|
bool validCgroup(const string cgroup);
|
||||||
return regex_match(cgroup, regex("^/[a-zA-Z0-9\\-_./@]*$"));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validCgroup(const vector<string> cgroup) {
|
bool validCgroup(const vector<string> cgroup);
|
||||||
for (auto &e : cgroup) {
|
|
||||||
if (!regex_match(e, regex("^/[a-zA-Z0-9\\-_./@]*$"))) { return false; }
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validPid(const string pid) { return regex_match(pid, regex("^[0-9]+$")); }
|
bool validPid(const string pid);
|
||||||
|
|
||||||
bool validPort(const int port) { return port > 0; }
|
bool validPort(const int port);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
120
src/config.cpp
Normal file
120
src/config.cpp
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#include "config.hpp"
|
||||||
|
|
||||||
|
#define add2json(v) j[#v] = v;
|
||||||
|
#define tryassign(v) \
|
||||||
|
try { \
|
||||||
|
j.at(#v).get_to(v); \
|
||||||
|
} catch (exception & e) {}
|
||||||
|
#define merge(v) \
|
||||||
|
{ \
|
||||||
|
v.erase(std::remove(v.begin(), v.end(), v##_preserved), v.end()); \
|
||||||
|
v.insert(v.begin(), v##_preserved); \
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CGPROXY::CONFIG {
|
||||||
|
|
||||||
|
void Config::toEnv() {
|
||||||
|
mergeReserved();
|
||||||
|
setenv("cgroup_proxy", join2str(cgroup_proxy, ':').c_str(), 1);
|
||||||
|
setenv("cgroup_noproxy", join2str(cgroup_noproxy, ':').c_str(), 1);
|
||||||
|
setenv("enable_gateway", to_str(enable_gateway).c_str(), 1);
|
||||||
|
setenv("port", to_str(port).c_str(), 1);
|
||||||
|
setenv("enable_dns", to_str(enable_dns).c_str(), 1);
|
||||||
|
setenv("enable_tcp", to_str(enable_tcp).c_str(), 1);
|
||||||
|
setenv("enable_udp", to_str(enable_udp).c_str(), 1);
|
||||||
|
setenv("enable_ipv4", to_str(enable_ipv4).c_str(), 1);
|
||||||
|
setenv("enable_ipv6", to_str(enable_ipv6).c_str(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Config::saveToFile(const string f) {
|
||||||
|
ofstream o(f);
|
||||||
|
if (!o.is_open()) return FILE_ERROR;
|
||||||
|
json j = toJson();
|
||||||
|
o << setw(4) << j << endl;
|
||||||
|
o.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
json Config::toJson() {
|
||||||
|
json j;
|
||||||
|
add2json(cgroup_proxy);
|
||||||
|
add2json(cgroup_noproxy);
|
||||||
|
add2json(enable_gateway);
|
||||||
|
add2json(port);
|
||||||
|
add2json(enable_dns);
|
||||||
|
add2json(enable_tcp);
|
||||||
|
add2json(enable_udp);
|
||||||
|
add2json(enable_ipv4);
|
||||||
|
add2json(enable_ipv6);
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Config::loadFromFile(const string f) {
|
||||||
|
debug("loading config: %s", f.c_str());
|
||||||
|
ifstream ifs(f);
|
||||||
|
if (ifs.is_open()) {
|
||||||
|
json j;
|
||||||
|
try {
|
||||||
|
ifs >> j;
|
||||||
|
} catch (exception &e) {
|
||||||
|
error("parse error: %s", f.c_str());
|
||||||
|
ifs.close();
|
||||||
|
return PARSE_ERROR;
|
||||||
|
}
|
||||||
|
ifs.close();
|
||||||
|
return loadFromJson(j);
|
||||||
|
} else {
|
||||||
|
error("open failed: %s", f.c_str());
|
||||||
|
return FILE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Config::loadFromJson(const json &j) {
|
||||||
|
if (!validateJson(j)) {
|
||||||
|
error("json validate fail");
|
||||||
|
return PARAM_ERROR;
|
||||||
|
}
|
||||||
|
tryassign(cgroup_proxy);
|
||||||
|
tryassign(cgroup_noproxy);
|
||||||
|
tryassign(enable_gateway);
|
||||||
|
tryassign(port);
|
||||||
|
tryassign(enable_dns);
|
||||||
|
tryassign(enable_tcp);
|
||||||
|
tryassign(enable_udp);
|
||||||
|
tryassign(enable_ipv4);
|
||||||
|
tryassign(enable_ipv6);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::mergeReserved() {
|
||||||
|
merge(cgroup_proxy);
|
||||||
|
merge(cgroup_noproxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Config::validateJson(const json &j) {
|
||||||
|
bool status = true;
|
||||||
|
const set<string> boolset = {"enable_gateway", "enable_dns", "enable_tcp",
|
||||||
|
"enable_udp", "enable_ipv4", "enable_ipv6"};
|
||||||
|
for (auto &[key, value] : j.items()) {
|
||||||
|
if (key == "cgroup_proxy" || key == "cgroup_noproxy") {
|
||||||
|
if (value.is_string() && !validCgroup((string)value)) status = false;
|
||||||
|
// TODO what if vector<int> etc.
|
||||||
|
if (value.is_array() && !validCgroup((vector<string>)value)) status = false;
|
||||||
|
if (!value.is_string() && !value.is_array()) status = false;
|
||||||
|
} else if (key == "port") {
|
||||||
|
if (!validPort(value)) status = false;
|
||||||
|
} else if (boolset.find(key) != boolset.end()) {
|
||||||
|
if (!value.is_boolean()) status = false;
|
||||||
|
} else {
|
||||||
|
error("unknown key: %s", key.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!status) {
|
||||||
|
error("invalid value for key: %s", key.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CGPROXY::CONFIG
|
||||||
125
src/config.hpp
125
src/config.hpp
@@ -16,7 +16,7 @@ using json = nlohmann::json;
|
|||||||
|
|
||||||
namespace CGPROXY::CONFIG {
|
namespace CGPROXY::CONFIG {
|
||||||
|
|
||||||
struct Config {
|
class Config {
|
||||||
public:
|
public:
|
||||||
const string cgroup_proxy_preserved = CGROUP_PROXY_PRESVERED;
|
const string cgroup_proxy_preserved = CGROUP_PROXY_PRESVERED;
|
||||||
const string cgroup_noproxy_preserved = CGROUP_NOPROXY_PRESVERED;
|
const string cgroup_noproxy_preserved = CGROUP_NOPROXY_PRESVERED;
|
||||||
@@ -33,122 +33,13 @@ private:
|
|||||||
bool enable_ipv6 = true;
|
bool enable_ipv6 = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void toEnv() {
|
void toEnv();
|
||||||
mergeReserved();
|
int saveToFile(const string f);
|
||||||
setenv("cgroup_proxy", join2str(cgroup_proxy, ':').c_str(), 1);
|
json toJson();
|
||||||
setenv("cgroup_noproxy", join2str(cgroup_noproxy, ':').c_str(), 1);
|
int loadFromFile(const string f);
|
||||||
setenv("enable_gateway", to_str(enable_gateway).c_str(), 1);
|
int loadFromJson(const json &j);
|
||||||
setenv("port", to_str(port).c_str(), 1);
|
void mergeReserved();
|
||||||
setenv("enable_dns", to_str(enable_dns).c_str(), 1);
|
bool validateJson(const json &j);
|
||||||
setenv("enable_tcp", to_str(enable_tcp).c_str(), 1);
|
|
||||||
setenv("enable_udp", to_str(enable_udp).c_str(), 1);
|
|
||||||
setenv("enable_ipv4", to_str(enable_ipv4).c_str(), 1);
|
|
||||||
setenv("enable_ipv6", to_str(enable_ipv6).c_str(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int saveToFile(const string f) {
|
|
||||||
ofstream o(f);
|
|
||||||
if (!o.is_open()) return FILE_ERROR;
|
|
||||||
json j = toJson();
|
|
||||||
o << setw(4) << j << endl;
|
|
||||||
o.close();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define add2json(v) j[#v] = v;
|
|
||||||
json toJson() {
|
|
||||||
json j;
|
|
||||||
add2json(cgroup_proxy);
|
|
||||||
add2json(cgroup_noproxy);
|
|
||||||
add2json(enable_gateway);
|
|
||||||
add2json(port);
|
|
||||||
add2json(enable_dns);
|
|
||||||
add2json(enable_tcp);
|
|
||||||
add2json(enable_udp);
|
|
||||||
add2json(enable_ipv4);
|
|
||||||
add2json(enable_ipv6);
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
#undef add2json
|
|
||||||
|
|
||||||
int loadFromFile(const string f) {
|
|
||||||
debug("loading config: %s", f.c_str());
|
|
||||||
ifstream ifs(f);
|
|
||||||
if (ifs.is_open()) {
|
|
||||||
json j;
|
|
||||||
try {
|
|
||||||
ifs >> j;
|
|
||||||
} catch (exception &e) {
|
|
||||||
error("parse error: %s", f.c_str());
|
|
||||||
ifs.close();
|
|
||||||
return PARSE_ERROR;
|
|
||||||
}
|
|
||||||
ifs.close();
|
|
||||||
return loadFromJson(j);
|
|
||||||
} else {
|
|
||||||
error("open failed: %s", f.c_str());
|
|
||||||
return FILE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define tryassign(v) \
|
|
||||||
try { \
|
|
||||||
j.at(#v).get_to(v); \
|
|
||||||
} catch (exception & e) {}
|
|
||||||
int loadFromJson(const json &j) {
|
|
||||||
if (!validateJson(j)) {
|
|
||||||
error("json validate fail");
|
|
||||||
return PARAM_ERROR;
|
|
||||||
}
|
|
||||||
tryassign(cgroup_proxy);
|
|
||||||
tryassign(cgroup_noproxy);
|
|
||||||
tryassign(enable_gateway);
|
|
||||||
tryassign(port);
|
|
||||||
tryassign(enable_dns);
|
|
||||||
tryassign(enable_tcp);
|
|
||||||
tryassign(enable_udp);
|
|
||||||
tryassign(enable_ipv4);
|
|
||||||
tryassign(enable_ipv6);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#undef assign
|
|
||||||
|
|
||||||
#define merge(v) \
|
|
||||||
{ \
|
|
||||||
v.erase(std::remove(v.begin(), v.end(), v##_preserved), v.end()); \
|
|
||||||
v.insert(v.begin(), v##_preserved); \
|
|
||||||
}
|
|
||||||
void mergeReserved() {
|
|
||||||
merge(cgroup_proxy);
|
|
||||||
merge(cgroup_noproxy);
|
|
||||||
}
|
|
||||||
#undef merge
|
|
||||||
|
|
||||||
bool validateJson(const json &j) {
|
|
||||||
bool status = true;
|
|
||||||
const set<string> boolset = {"enable_gateway", "enable_dns", "enable_tcp",
|
|
||||||
"enable_udp", "enable_ipv4", "enable_ipv6"};
|
|
||||||
for (auto &[key, value] : j.items()) {
|
|
||||||
if (key == "cgroup_proxy" || key == "cgroup_noproxy") {
|
|
||||||
if (value.is_string() && !validCgroup((string)value)) status = false;
|
|
||||||
// TODO what if vector<int> etc.
|
|
||||||
if (value.is_array() && !validCgroup((vector<string>)value)) status = false;
|
|
||||||
if (!value.is_string() && !value.is_array()) status = false;
|
|
||||||
} else if (key == "port") {
|
|
||||||
if (!validPort(value)) status = false;
|
|
||||||
} else if (boolset.find(key) != boolset.end()) {
|
|
||||||
if (!value.is_boolean()) status = false;
|
|
||||||
} else {
|
|
||||||
error("unknown key: %s", key.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!status) {
|
|
||||||
error("invalid value for key: %s", key.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CGPROXY::CONFIG
|
} // namespace CGPROXY::CONFIG
|
||||||
|
|||||||
41
src/socket_client.cpp
Normal file
41
src/socket_client.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "socket_client.hpp"
|
||||||
|
|
||||||
|
namespace CGPROXY::SOCKET {
|
||||||
|
|
||||||
|
void send(const char *msg, int &status) {
|
||||||
|
debug("send msg: %s", msg);
|
||||||
|
status = UNKNOWN_ERROR;
|
||||||
|
|
||||||
|
int flag;
|
||||||
|
int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
struct sockaddr_un unix_socket;
|
||||||
|
memset(&unix_socket, '\0', sizeof(struct sockaddr_un));
|
||||||
|
unix_socket.sun_family = AF_UNIX;
|
||||||
|
strncpy(unix_socket.sun_path, SOCKET_PATH, sizeof(unix_socket.sun_path) - 1);
|
||||||
|
|
||||||
|
flag = connect(sfd, (struct sockaddr *)&unix_socket, sizeof(struct sockaddr_un));
|
||||||
|
return_if_error(flag, "connect");
|
||||||
|
|
||||||
|
int msg_len = strlen(msg);
|
||||||
|
flag = write(sfd, &msg_len, sizeof(int));
|
||||||
|
return_if_error(flag, "write length");
|
||||||
|
flag = write(sfd, msg, msg_len * sizeof(char));
|
||||||
|
return_if_error(flag, "write msg");
|
||||||
|
|
||||||
|
flag = read(sfd, &status, sizeof(int));
|
||||||
|
return_if_error(flag, "read return value");
|
||||||
|
|
||||||
|
close(sfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(const string msg, int &status) {
|
||||||
|
int msg_len = msg.length();
|
||||||
|
char buff[msg_len];
|
||||||
|
msg.copy(buff, msg_len, 0);
|
||||||
|
buff[msg_len] = '\0';
|
||||||
|
send(buff, status);
|
||||||
|
debug("return status: %d", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CGPROXY::SOCKET
|
||||||
@@ -23,41 +23,8 @@ namespace CGPROXY::SOCKET {
|
|||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(const char *msg, int &status) {
|
void send(const char *msg, int &status);
|
||||||
debug("send msg: %s", msg);
|
void send(const string msg, int &status);
|
||||||
status = UNKNOWN_ERROR;
|
|
||||||
|
|
||||||
int flag;
|
|
||||||
int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
struct sockaddr_un unix_socket;
|
|
||||||
memset(&unix_socket, '\0', sizeof(struct sockaddr_un));
|
|
||||||
unix_socket.sun_family = AF_UNIX;
|
|
||||||
strncpy(unix_socket.sun_path, SOCKET_PATH, sizeof(unix_socket.sun_path) - 1);
|
|
||||||
|
|
||||||
flag = connect(sfd, (struct sockaddr *)&unix_socket, sizeof(struct sockaddr_un));
|
|
||||||
return_if_error(flag, "connect");
|
|
||||||
|
|
||||||
int msg_len = strlen(msg);
|
|
||||||
flag = write(sfd, &msg_len, sizeof(int));
|
|
||||||
return_if_error(flag, "write length");
|
|
||||||
flag = write(sfd, msg, msg_len * sizeof(char));
|
|
||||||
return_if_error(flag, "write msg");
|
|
||||||
|
|
||||||
flag = read(sfd, &status, sizeof(int));
|
|
||||||
return_if_error(flag, "read return value");
|
|
||||||
|
|
||||||
close(sfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(const string msg, int &status) {
|
|
||||||
int msg_len = msg.length();
|
|
||||||
char buff[msg_len];
|
|
||||||
msg.copy(buff, msg_len, 0);
|
|
||||||
buff[msg_len] = '\0';
|
|
||||||
send(buff, status);
|
|
||||||
debug("return status: %d", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace CGPROXY::SOCKET
|
} // namespace CGPROXY::SOCKET
|
||||||
#endif
|
#endif
|
||||||
54
src/socket_server.cpp
Normal file
54
src/socket_server.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include "socket_server.hpp"
|
||||||
|
|
||||||
|
namespace CGPROXY::SOCKET {
|
||||||
|
void SocketServer::socketListening(function<int(char *)> callback) {
|
||||||
|
debug("starting socket listening");
|
||||||
|
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (fs::exists(SOCKET_PATH) && unlink(SOCKET_PATH) == -1) {
|
||||||
|
error("%s exist, and can't unlink", SOCKET_PATH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(&unix_socket, '\0', sizeof(struct sockaddr_un));
|
||||||
|
unix_socket.sun_family = AF_UNIX;
|
||||||
|
strncpy(unix_socket.sun_path, SOCKET_PATH, sizeof(unix_socket.sun_path) - 1);
|
||||||
|
|
||||||
|
bind(sfd, (struct sockaddr *)&unix_socket, sizeof(struct sockaddr_un));
|
||||||
|
|
||||||
|
listen(sfd, LISTEN_BACKLOG);
|
||||||
|
chmod(SOCKET_PATH, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
close(cfd);
|
||||||
|
cfd = accept(sfd, NULL, NULL);
|
||||||
|
continue_if_error(cfd, "accept");
|
||||||
|
debug("accept connection: %d", cfd);
|
||||||
|
|
||||||
|
// read length
|
||||||
|
int msg_len;
|
||||||
|
flag = read(cfd, &msg_len, sizeof(int));
|
||||||
|
continue_if_error(flag, "read length");
|
||||||
|
// read msg
|
||||||
|
char msg[msg_len];
|
||||||
|
flag = read(cfd, msg, msg_len * sizeof(char));
|
||||||
|
continue_if_error(flag, "read msg");
|
||||||
|
msg[msg_len] = '\0';
|
||||||
|
// handle msg
|
||||||
|
int status = callback(msg);
|
||||||
|
// send back flag
|
||||||
|
flag = write(cfd, &status, sizeof(int));
|
||||||
|
continue_if_error(flag, "write back");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void *SocketServer::startThread(void *arg) {
|
||||||
|
thread_arg *p = (thread_arg *)arg;
|
||||||
|
SocketServer server;
|
||||||
|
server.socketListening(p->handle_msg);
|
||||||
|
return (void *)0;
|
||||||
|
}
|
||||||
|
SocketServer::~SocketServer() {
|
||||||
|
close(sfd);
|
||||||
|
close(cfd);
|
||||||
|
unlink(SOCKET_PATH);
|
||||||
|
}
|
||||||
|
} // namespace CGPROXY::SOCKET
|
||||||
@@ -34,58 +34,9 @@ public:
|
|||||||
int sfd = -1, cfd = -1, flag = -1;
|
int sfd = -1, cfd = -1, flag = -1;
|
||||||
struct sockaddr_un unix_socket;
|
struct sockaddr_un unix_socket;
|
||||||
|
|
||||||
void socketListening(function<int(char *)> callback) {
|
void socketListening(function<int(char *)> callback);
|
||||||
debug("starting socket listening");
|
~SocketServer();
|
||||||
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
static void *startThread(void *arg);
|
||||||
|
|
||||||
if (fs::exists(SOCKET_PATH) && unlink(SOCKET_PATH) == -1) {
|
|
||||||
error("%s exist, and can't unlink", SOCKET_PATH);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memset(&unix_socket, '\0', sizeof(struct sockaddr_un));
|
|
||||||
unix_socket.sun_family = AF_UNIX;
|
|
||||||
strncpy(unix_socket.sun_path, SOCKET_PATH, sizeof(unix_socket.sun_path) - 1);
|
|
||||||
|
|
||||||
bind(sfd, (struct sockaddr *)&unix_socket, sizeof(struct sockaddr_un));
|
|
||||||
|
|
||||||
listen(sfd, LISTEN_BACKLOG);
|
|
||||||
chmod(SOCKET_PATH, S_IRWXU | S_IRWXG | S_IRWXO);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
close(cfd);
|
|
||||||
cfd = accept(sfd, NULL, NULL);
|
|
||||||
continue_if_error(cfd, "accept");
|
|
||||||
debug("accept connection: %d", cfd);
|
|
||||||
|
|
||||||
// read length
|
|
||||||
int msg_len;
|
|
||||||
flag = read(cfd, &msg_len, sizeof(int));
|
|
||||||
continue_if_error(flag, "read length");
|
|
||||||
// read msg
|
|
||||||
char msg[msg_len];
|
|
||||||
flag = read(cfd, msg, msg_len * sizeof(char));
|
|
||||||
continue_if_error(flag, "read msg");
|
|
||||||
msg[msg_len] = '\0';
|
|
||||||
// handle msg
|
|
||||||
int status = callback(msg);
|
|
||||||
// send back flag
|
|
||||||
flag = write(cfd, &status, sizeof(int));
|
|
||||||
continue_if_error(flag, "write back");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~SocketServer() {
|
|
||||||
close(sfd);
|
|
||||||
close(cfd);
|
|
||||||
unlink(SOCKET_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *startThread(void *arg) {
|
|
||||||
thread_arg *p = (thread_arg *)arg;
|
|
||||||
SocketServer server;
|
|
||||||
server.socketListening(p->handle_msg);
|
|
||||||
return (void *)0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CGPROXY::SOCKET
|
} // namespace CGPROXY::SOCKET
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
// #include "common.h"
|
|
||||||
#include "config.hpp"
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CGPROXY::CONFIG;
|
|
||||||
|
|
||||||
int main() {
|
int main() { return 0; }
|
||||||
Config c;
|
|
||||||
c.saveToFile("./config.json");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user