Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
5 changes: 3 additions & 2 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
uses: jidicula/clang-format-action@v4.11.0
with:
check-path: 'src'
exclude-regex: 'src/utils/argparse.h'
exclude-regex: 'argparse.h'

linux:
runs-on: ubuntu-latest
Expand All @@ -28,7 +28,7 @@ jobs:
runs-on: macos-latest
steps:
- name: depends
run: brew update && brew install fmt poco spdlog
run: brew update && brew install fmt poco spdlog nlohmann-json
- name: checkout
uses: actions/checkout@v4
- name: build
Expand Down Expand Up @@ -57,6 +57,7 @@ jobs:
mingw-w64-x86_64-gcc
mingw-w64-x86_64-spdlog
mingw-w64-x86_64-poco
mingw-w64-x86_64-nlohmann-json
- name: checkout
uses: actions/checkout@v4
- name: cache
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
mingw-w64-x86_64-gcc
mingw-w64-x86_64-spdlog
mingw-w64-x86_64-poco
mingw-w64-x86_64-nlohmann-json
- name: checkout
uses: actions/checkout@v4
- name: cache
Expand All @@ -75,7 +76,7 @@ jobs:
mkdir artifact
cp candy.cfg artifact
cp build/src/tun/wintun/bin/amd64/wintun.dll artifact
scripts/search-deps.sh build/src/main/candy.exe artifact
scripts/search-deps.sh build/candy-cli/candy.exe artifact
- name: set release package name
shell: bash
if: github.event_name == 'release'
Expand Down
49 changes: 17 additions & 32 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
cmake_minimum_required(VERSION 3.16)
project(Candy VERSION 6.1.0)

project(candy LANGUAGES C CXX VERSION 6.0.5)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

option(CANDY_NOEXE "Don't build executable")
option(CANDY_DEVEL "Build development library")
option(CANDY_STATIC "Static linking dependent libraries")
add_compile_definitions(CANDY_VERSION="${PROJECT_VERSION}")

set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(CMAKE_SKIP_BUILD_RPATH TRUE)

if (${CANDY_STATIC})
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CANDY_STATIC_OPENSSL 1)
set(CANDY_STATIC_FMT 1)
set(CANDY_STATIC_SPDLOG 1)
set(CANDY_STATIC_NLOHMANN_JSON 1)
set(CANDY_STATIC_POCO 1)
endif()

find_package(PkgConfig REQUIRED)
include(${CMAKE_SOURCE_DIR}/cmake/Fetch.cmake)

if (${CANDY_STATIC_OPENSSL})
execute_process(
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/openssl
)
execute_process(
COMMAND ${CMAKE_COMMAND} -DTARGET_OPENSSL=${TARGET_OPENSSL} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/openssl
COMMAND ${CMAKE_COMMAND} -DTARGET_OPENSSL=${TARGET_OPENSSL} ${CMAKE_SOURCE_DIR}/cmake/openssl
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/openssl
RESULT_VARIABLE result
)
Expand Down Expand Up @@ -63,18 +64,10 @@ else()
find_package(OpenSSL REQUIRED)
endif()

if (${CANDY_STATIC_FMT})
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Fetch.cmake)
Fetch(fmt "https://github.com/fmtlib/fmt.git" "10.2.1")
endif()

if (${CANDY_STATIC_SPDLOG})
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Fetch.cmake)
Fetch(spdlog "https://github.com/gabime/spdlog.git" "v1.14.1")
Fetch(spdlog "https://github.com/gabime/spdlog.git" "v1.15.3")
else()
pkg_check_modules(SPDLOG REQUIRED spdlog)
add_definitions(${SPDLOG_CFLAGS})
include_directories(${SPDLOG_INCLUDEDIR})
find_package(spdlog REQUIRED)
endif()

if (${CANDY_STATIC_POCO})
Expand All @@ -93,24 +86,16 @@ if (${CANDY_STATIC_POCO})
set(ENABLE_ACTIVERECORD_COMPILER OFF CACHE BOOL "" FORCE)
set(ENABLE_ZIP OFF CACHE BOOL "" FORCE)
set(ENABLE_JWT OFF CACHE BOOL "" FORCE)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Fetch.cmake)
Fetch(poco "https://github.com/pocoproject/poco.git" "poco-1.13.3-release")
else()
find_package(Poco REQUIRED COMPONENTS Foundation XML JSON Net NetSSL)
endif()

set(CANDY_EXECUTE_NAME "candy")
set(CANDY_LIBRARY_NAME "libcandy")

add_compile_definitions(CANDY_VERSION="${PROJECT_VERSION}")
add_compile_options("-Wfatal-errors")

include_directories(${PROJECT_SOURCE_DIR}/src)
if (${CANDY_STATIC_NLOHMANN_JSON})
Fetch(nlohmann_json "https://github.com/nlohmann/json.git" "v3.11.3")
else()
find_package(nlohmann_json REQUIRED)
endif()

add_subdirectory(${PROJECT_SOURCE_DIR}/src/ffi)
add_subdirectory(${PROJECT_SOURCE_DIR}/src/main)
add_subdirectory(${PROJECT_SOURCE_DIR}/src/core)
add_subdirectory(${PROJECT_SOURCE_DIR}/src/websocket)
add_subdirectory(${PROJECT_SOURCE_DIR}/src/tun)
add_subdirectory(${PROJECT_SOURCE_DIR}/src/peer)
add_subdirectory(${PROJECT_SOURCE_DIR}/src/utils)
add_subdirectory(candy)
add_subdirectory(candy-cli)
20 changes: 20 additions & 0 deletions candy-cli/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
file(GLOB_RECURSE SOURCES "src/*.cc")
add_executable(candy_cli ${SOURCES})

target_include_directories(candy_library PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)

set_target_properties(candy_cli PROPERTIES
OUTPUT_NAME "candy"
)

target_link_libraries(candy_cli PRIVATE spdlog::spdlog)
target_link_libraries(candy_cli PRIVATE Poco::Foundation)
target_link_libraries(candy_cli PRIVATE nlohmann_json::nlohmann_json)
target_link_libraries(candy_cli PRIVATE Candy::Library)

install(TARGETS candy_cli)

add_executable(Candy::CLI ALIAS candy_cli)
File renamed without changes.
95 changes: 29 additions & 66 deletions src/main/config.cc → candy-cli/src/config.cc
Original file line number Diff line number Diff line change
@@ -1,60 +1,47 @@
// SPDX-License-Identifier: MIT
#include "main/config.h"
#include "core/version.h"
#include "utils/argparse.h"
#include "utils/random.h"
#include "config.h"
#include "argparse.h"
#include "candy/candy.h"
#include <Poco/Platform.h>
#include <Poco/String.h>
#include <filesystem>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#include <sstream>
#include <string>

void arguments::dump(const std::string &key, const std::string &value) {
if (!value.empty()) {
spdlog::debug("--{}={}", key, value);
}
}

void arguments::dump(const std::string &key, int value) {
if (value) {
spdlog::debug("--{}={}", key, value);
}
}

void arguments::dump() {
spdlog::debug("================================");
dump("mode", this->mode);
dump("websocket", this->websocket);
dump("password", this->password);
dump("ntp", this->ntp);
dump("restart", this->restart);
dump("dhcp", this->dhcp);
dump("sdwan", this->sdwan);
dump("name", this->name);
dump("tun", this->tun);
dump("stun", this->stun);
dump("localhost", this->localhost);
dump("discovery", this->discovery);
dump("route", this->routeCost);
dump("mtu", this->mtu);
dump("port", this->port);
spdlog::debug("================================");
nlohmann::json arguments::json() {
nlohmann::json config = {
{"mode", this->mode},
{"websocket", this->websocket},
{"password", this->password},
{"dhcp", this->dhcp},
{"sdwan", this->sdwan},
{"name", this->name},
{"tun", this->tun},
{"stun", this->stun},
{"localhost", this->localhost},
{"discovery", this->discovery},
{"route", this->routeCost},
{"mtu", this->mtu},
{"port", this->port},
{"vmac", virtualMac(this->name)},
{"expt", loadTunAddress(this->name)},
};
return config;
}

int arguments::parse(int argc, char *argv[]) {
argparse::ArgumentParser program("candy", CANDY_VERSION);
argparse::ArgumentParser program("candy", candy::version());

program.add_argument("-c", "--config").help("config file path");
program.add_argument("-m", "--mode").help("working mode");
program.add_argument("-w", "--websocket").help("websocket address");
program.add_argument("-p", "--password").help("authorization password");
program.add_argument("--ntp").help("ntp server");
program.add_argument("-r", "--restart").help("restart interval").scan<'i', int>();
program.add_argument("-d", "--dhcp").help("dhcp address range");
program.add_argument("--sdwan").help("software-defined wide area network");
program.add_argument("-n", "--name").help("network interface name");
Expand All @@ -63,7 +50,7 @@ int arguments::parse(int argc, char *argv[]) {
program.add_argument("--port").help("p2p listen port").scan<'i', int>();
program.add_argument("--mtu").help("maximum transmission unit").scan<'i', int>();
program.add_argument("-r", "--route").help("routing cost").scan<'i', int>();
program.add_argument("-d", "--discovery").help("discovery interval").scan<'i', int>();
program.add_argument("--discovery").help("discovery interval").scan<'i', int>();
program.add_argument("--localhost").help("local ip");

program.add_argument("--no-timestamp").implicit_value(true);
Expand All @@ -82,8 +69,6 @@ int arguments::parse(int argc, char *argv[]) {
program.set_if_used("--mode", this->mode);
program.set_if_used("--websocket", this->websocket);
program.set_if_used("--password", this->password);
program.set_if_used("--ntp", this->ntp);
program.set_if_used("--restart", this->restart);
program.set_if_used("--no-timestamp", this->noTimestamp);
program.set_if_used("--debug", this->debug);
program.set_if_used("--dhcp", this->dhcp);
Expand Down Expand Up @@ -116,7 +101,6 @@ int arguments::parse(int argc, char *argv[]) {
}
if (this->debug) {
spdlog::set_level(spdlog::level::debug);
this->dump();
}
return 0;
} catch (const std::exception &e) {
Expand All @@ -131,9 +115,7 @@ void arguments::parseFile(std::string cfgFile) {
{"mode", [&](const std::string &value) { this->mode = value; }},
{"websocket", [&](const std::string &value) { this->websocket = value; }},
{"password", [&](const std::string &value) { this->password = value; }},
{"ntp", [&](const std::string &value) { this->ntp = value; }},
{"debug", [&](const std::string &value) { this->debug = (value == "true"); }},
{"restart", [&](const std::string &value) { this->restart = std::stoi(value); }},
{"dhcp", [&](const std::string &value) { this->dhcp = value; }},
{"sdwan", [&](const std::string &value) { this->sdwan = value; }},
{"tun", [&](const std::string &value) { this->tun = value; }},
Expand Down Expand Up @@ -216,13 +198,11 @@ std::string loadTunAddress(const std::string &name) {
return "0.0.0.0/0";
}

static const int VMAC_SIZE = 16;

std::string virtualMacHelper(std::string name = "") {
try {
std::string path = storageDirectory("vmac/");
path += name.empty() ? "__noname__" : name;
char buffer[VMAC_SIZE];
char buffer[candy::VMAC_SIZE];
std::stringstream ss;
std::ifstream ifs(path);
if (ifs.is_open()) {
Expand All @@ -245,14 +225,13 @@ std::string initVirtualMac() {
try {
std::string path = storageDirectory("vmac/__noname__");
std::filesystem::create_directories(std::filesystem::path(path).parent_path());
std::stringstream ss;
ss << Candy::randomHexString(VMAC_SIZE);
std::string vmac = candy::create_vmac();
std::ofstream ofs(path);
if (ofs.is_open()) {
ofs << ss.str();
ofs << vmac;
ofs.close();
}
return ss.str();
return vmac;
} catch (std::exception &e) {
spdlog::critical("init vmac failed: {}", e.what());
return "";
Expand All @@ -279,22 +258,6 @@ bool starts_with(const std::string &str, const std::string &prefix) {
return str.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), str.begin());
}

bool hasContainerVolume(const arguments &args) {
if (args.mode != "client") {
return true;
}
if (!std::filesystem::exists(storageDirectory("lost"))) {
return true;
}
if (starts_with(args.websocket, "wss://canets.org")) {
return false;
}
if (!args.tun.empty()) {
return true;
}
return false;
}

#if POCO_OS == POCO_OS_WINDOWS_NT
std::string storageDirectory(std::string subdir) {
return "C:/ProgramData/Candy/" + subdir;
Expand Down
Loading