diff --git a/CMakeLists.txt b/CMakeLists.txt index c3e4f454..20054c8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,6 @@ set(CMAKE_SKIP_BUILD_RPATH TRUE) if (${CANDY_STATIC}) set(CANDY_STATIC_OPENSSL 1) - set(CANDY_STATIC_SPDLOG 1) - set(CANDY_STATIC_NLOHMANN_JSON 1) set(CANDY_STATIC_POCO 1) endif() @@ -64,12 +62,6 @@ else() find_package(OpenSSL REQUIRED) endif() -if (${CANDY_STATIC_SPDLOG}) - Fetch(spdlog "https://github.com/gabime/spdlog.git" "v1.15.3") -else() - find_package(spdlog REQUIRED) -endif() - if (${CANDY_STATIC_POCO}) set(ENABLE_DATA OFF CACHE BOOL "" FORCE) set(ENABLE_DATA_MYSQL OFF CACHE BOOL "" FORCE) diff --git a/candy-cli/CMakeLists.txt b/candy-cli/CMakeLists.txt index 4e09471a..63d1da26 100644 --- a/candy-cli/CMakeLists.txt +++ b/candy-cli/CMakeLists.txt @@ -8,7 +8,6 @@ target_include_directories(candy-cli PUBLIC 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 Poco::JSON) target_link_libraries(candy-cli PRIVATE Candy::Library) diff --git a/candy-cli/src/config.cc b/candy-cli/src/config.cc index fc56ff87..b5eada23 100644 --- a/candy-cli/src/config.cc +++ b/candy-cli/src/config.cc @@ -2,7 +2,14 @@ #include "config.h" #include "argparse.h" #include "candy/candy.h" +#include "utils/log.h" +#include +#include +#include #include +#include +#include +#include #include #include #include @@ -10,7 +17,6 @@ #include #include #include -#include #include #include @@ -53,8 +59,7 @@ int arguments::parse(int argc, char *argv[]) { program.add_argument("-w", "--websocket") .help("WebSocket signaling address (e.g. \"ws://host:port/ws\").\n" "Client supports ws:// and wss://; server supports ws:// only.") - .metavar("") - .required(); + .metavar(""); program.add_argument("-p", "--password") .help("pre-shared key for authentication and P2P encryption.\n" @@ -192,11 +197,23 @@ int arguments::parse(int argc, char *argv[]) { exit(1); } + // Set up default console channel with pattern if (this->noTimestamp) { - spdlog::set_pattern("[%^%l%$] %v"); + Poco::AutoPtr pFormatter = new Poco::PatternFormatter("[%q] %t"); + Poco::AutoPtr pFormattingChannel = new Poco::FormattingChannel(pFormatter); + Poco::AutoPtr pConsoleChannel = new Poco::ConsoleChannel; + pFormattingChannel->setChannel(pConsoleChannel); + Poco::Logger::root().setChannel(pFormattingChannel); + } else { + Poco::AutoPtr pFormatter = new Poco::PatternFormatter("%Y-%m-%d %H:%M:%S [%q] %t"); + Poco::AutoPtr pFormattingChannel = new Poco::FormattingChannel(pFormatter); + Poco::AutoPtr pConsoleChannel = new Poco::ConsoleChannel; + pFormattingChannel->setChannel(pConsoleChannel); + Poco::Logger::root().setChannel(pFormattingChannel); } + if (this->debug) { - spdlog::set_level(spdlog::level::debug); + Poco::Logger::root().setLevel(Poco::Message::PRIO_DEBUG); } return 0; } catch (const std::exception &e) { @@ -235,11 +252,11 @@ void arguments::parseFile(std::string cfgFile) { if (handler != cfgHandlers.end()) { handler->second(trim(cfg.second)); } else { - spdlog::warn("unknown config: {}={}", cfg.first, cfg.second); + candy::logger().warning(Poco::format("unknown config: %s=%s", cfg.first, cfg.second)); } } } catch (std::exception &e) { - spdlog::error("parse config file failed: {}", e.what()); + candy::logger().error(Poco::format("parse config file failed: %s", std::string(e.what()))); exit(1); } } @@ -276,7 +293,7 @@ int saveTunAddress(const std::string &name, const std::string &cidr) { } return 0; } catch (std::exception &e) { - spdlog::critical("save latest address failed: {}", e.what()); + candy::logger().fatal(Poco::format("save latest address failed: %s", std::string(e.what()))); return -1; } } @@ -329,7 +346,7 @@ std::string initVirtualMac() { } return vmac; } catch (std::exception &e) { - spdlog::critical("init vmac failed: {}", e.what()); + candy::logger().fatal(Poco::format("init vmac failed: %s", std::string(e.what()))); return ""; } } diff --git a/candy-cli/src/main.cc b/candy-cli/src/main.cc index 4e94df00..cd03bacc 100644 --- a/candy-cli/src/main.cc +++ b/candy-cli/src/main.cc @@ -1,7 +1,7 @@ #include "candy/candy.h" #include "config.h" #include -#include +#include int main(int argc, char *argv[]) { arguments args; diff --git a/candy-service/CMakeLists.txt b/candy-service/CMakeLists.txt index 33720d36..20f5f700 100644 --- a/candy-service/CMakeLists.txt +++ b/candy-service/CMakeLists.txt @@ -8,7 +8,6 @@ target_include_directories(candy-service PUBLIC set_target_properties(candy-service PROPERTIES OUTPUT_NAME "candy-service") -target_link_libraries(candy-service PRIVATE spdlog::spdlog) target_link_libraries(candy-service PRIVATE Poco::Foundation Poco::Net Poco::JSON Poco::Util) target_link_libraries(candy-service PRIVATE Threads::Threads) target_link_libraries(candy-service PRIVATE Candy::Library) diff --git a/candy-service/src/main.cc b/candy-service/src/main.cc index c15d0b72..dce03b55 100644 --- a/candy-service/src/main.cc +++ b/candy-service/src/main.cc @@ -1,8 +1,16 @@ #include "candy/client.h" +#include "utils/log.h" +#include +#include #include #include +#include +#include +#include #include #include +#include +#include #include #include #include @@ -10,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -20,8 +29,6 @@ #include #include #include -#include -#include #include #include @@ -222,12 +229,38 @@ class CandyServiceApp : public Poco::Util::ServerApplication { if (!logdir.empty()) { Poco::File(logdir).createDirectories(); - auto logger = spdlog::rotating_logger_mt("app", logdir + "/app.log", 10 * 1024 * 1024, 5, true); - spdlog::set_default_logger(logger); + Poco::AutoPtr pFileChannel = new Poco::FileChannel(logdir + "/app.log"); + pFileChannel->setProperty("rotation", "10 M"); + pFileChannel->setProperty("archive", "number"); + pFileChannel->setProperty("purgeCount", "5"); + Poco::AutoPtr pFormatter = new Poco::PatternFormatter("%Y-%m-%d %H:%M:%S [%q] %t"); + Poco::AutoPtr pFormattingChannel = new Poco::FormattingChannel(pFormatter); + pFormattingChannel->setChannel(pFileChannel); + Poco::Logger::root().setChannel(pFormattingChannel); + } else { + Poco::AutoPtr pFormatter = new Poco::PatternFormatter("%Y-%m-%d %H:%M:%S [%q] %t"); + Poco::AutoPtr pFormattingChannel = new Poco::FormattingChannel(pFormatter); + Poco::AutoPtr pConsoleChannel = new Poco::ConsoleChannel; + pFormattingChannel->setChannel(pConsoleChannel); + Poco::Logger::root().setChannel(pFormattingChannel); } if (!loglevel.empty()) { - spdlog::set_level(spdlog::level::from_str(loglevel)); + if (loglevel == "debug") { + Poco::Logger::root().setLevel(Poco::Message::PRIO_DEBUG); + } else if (loglevel == "information" || loglevel == "info") { + Poco::Logger::root().setLevel(Poco::Message::PRIO_INFORMATION); + } else if (loglevel == "warning" || loglevel == "warn") { + Poco::Logger::root().setLevel(Poco::Message::PRIO_WARNING); + } else if (loglevel == "error") { + Poco::Logger::root().setLevel(Poco::Message::PRIO_ERROR); + } else if (loglevel == "fatal" || loglevel == "critical") { + Poco::Logger::root().setLevel(Poco::Message::PRIO_FATAL); + } else if (loglevel == "trace") { + Poco::Logger::root().setLevel(Poco::Message::PRIO_TRACE); + } else { + candy::logger().warning(Poco::format("unknown log level: %s", loglevel)); + } } if (bindAddress.empty()) { @@ -247,10 +280,10 @@ class CandyServiceApp : public Poco::Util::ServerApplication { Poco::Net::HTTPServer server(new JSONRequestHandlerFactory, socket, params); server.start(); - spdlog::info("bind: {}:{}", bindAddress, port); + candy::logger().information(Poco::format("bind: %s:%d", bindAddress, port)); waitForTerminationRequest(); - spdlog::info("exit signal detected"); + candy::logger().information("exit signal detected"); server.stop(); diff --git a/candy/CMakeLists.txt b/candy/CMakeLists.txt index dedc0e25..0cf000c5 100644 --- a/candy/CMakeLists.txt +++ b/candy/CMakeLists.txt @@ -15,7 +15,6 @@ else() target_link_libraries(candy-library PRIVATE OpenSSL::SSL OpenSSL::Crypto) endif() -target_link_libraries(candy-library PRIVATE spdlog::spdlog) target_link_libraries(candy-library PRIVATE Poco::Foundation Poco::JSON Poco::Net Poco::NetSSL) target_link_libraries(candy-library PRIVATE Threads::Threads) diff --git a/candy/src/candy/client.cc b/candy/src/candy/client.cc index 401c2ebb..004c712a 100644 --- a/candy/src/candy/client.cc +++ b/candy/src/candy/client.cc @@ -2,6 +2,8 @@ #include "candy/client.h" #include "core/client.h" #include "utils/atomic.h" +#include "utils/log.h" +#include #include #include #include @@ -9,7 +11,6 @@ #include #include #include -#include namespace candy { namespace client { @@ -56,7 +57,7 @@ std::optional> try_create_instance(const std::string & std::unique_lock lock(instance_mutex); auto it = instance_map.find(id); if (it != instance_map.end()) { - spdlog::warn("instance already exists: id={}", id); + candy::logger().warning(Poco::format("instance already exists: id=%s", id)); return std::nullopt; } auto manager = std::make_shared(); @@ -83,7 +84,7 @@ bool run(const std::string &id, const Poco::JSON::Object &config) { return oss.str(); }; - spdlog::info("run enter: id={} config={}", id, toString(config)); + candy::logger().information(Poco::format("run enter: id=%s config=%s", id, toString(config))); while ((*instance)->is_running()) { std::this_thread::sleep_for(std::chrono::seconds(1)); auto client = (*instance)->create_client(); @@ -100,7 +101,7 @@ bool run(const std::string &id, const Poco::JSON::Object &config) { client->setLocalhost(config.getValue("localhost")); client->run(); } - spdlog::info("run exit: id={} ", id); + candy::logger().information(Poco::format("run exit: id=%s ", id)); return try_erase_instance(id); } @@ -109,7 +110,7 @@ bool shutdown(const std::string &id) { std::shared_lock lock(instance_mutex); auto it = instance_map.find(id); if (it == instance_map.end()) { - spdlog::warn("instance not found: id={}", id); + candy::logger().warning(Poco::format("instance not found: id=%s", id)); return false; } if (auto instance = it->second) { diff --git a/candy/src/core/net.cc b/candy/src/core/net.cc index 3e31fed9..07e0b805 100644 --- a/candy/src/core/net.cc +++ b/candy/src/core/net.cc @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT #include "core/net.h" +#include "utils/log.h" +#include #include #include #include @@ -151,7 +153,7 @@ int Address::fromCidr(const std::string &cidr) { host.fromString(cidr.substr(0UL, pos)); mask.fromPrefix(std::stoi(cidr.substr(pos + 1))); } catch (std::exception &e) { - spdlog::warn("address parse cidr failed: {}: {}", e.what(), cidr); + candy::logger().warning(Poco::format("address parse cidr failed: %s: %s", std::string(e.what()), cidr)); return -1; } return 0; diff --git a/candy/src/core/net.h b/candy/src/core/net.h index 3e7a2ec7..cc831d07 100644 --- a/candy/src/core/net.h +++ b/candy/src/core/net.h @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -90,7 +89,6 @@ struct __attribute__((packed)) SysRouteEntry { IP4 nexthop; }; -/* 用于表示地址和掩码的组合,用于判断主机是否属于某个网络 */ class Address { public: Address(); @@ -100,10 +98,8 @@ class Address { IP4 &Mask(); IP4 Net(); - // 当前网络内的下一个地址 Address Next(); - // 判断是否是有效的主机地址 bool isValid(); int fromCidr(const std::string &cidr); diff --git a/candy/src/peer/manager.cc b/candy/src/peer/manager.cc index dd785e4f..73c2219f 100644 --- a/candy/src/peer/manager.cc +++ b/candy/src/peer/manager.cc @@ -4,14 +4,15 @@ #include "core/message.h" #include "core/net.h" #include "peer/message.h" +#include "utils/hex.h" +#include "utils/log.h" #include "utils/time.h" +#include #include #include #include #include #include -#include -#include namespace candy { @@ -58,19 +59,19 @@ int PeerManager::run(Client *client) { this->localP2PDisabled = false; if (this->stun.update()) { - spdlog::critical("update stun failed"); + candy::logger().fatal("update stun failed"); return -1; } this->msgThread = std::thread([&] { - spdlog::debug("start thread: peer manager msg"); + candy::logger().debug("start thread: peer manager msg"); while (getClient().isRunning()) { if (handlePeerQueue()) { break; } } getClient().shutdown(); - spdlog::debug("stop thread: peer manager msg"); + candy::logger().debug("stop thread: peer manager msg"); }); return 0; @@ -133,14 +134,16 @@ int PeerManager::handlePeerQueue() { handlePubInfo(std::move(msg)); break; default: - spdlog::warn("unexcepted peer message type: {}", static_cast(msg.kind)); + candy::logger().warning(Poco::format("unexcepted peer message type: %d", static_cast(msg.kind))); break; } } catch (const Poco::Exception &e) { - spdlog::warn("peer manager handle queue failed: msg_kind={}, error={}", static_cast(msg.kind), e.message()); + candy::logger().warning( + Poco::format("peer manager handle queue failed: msg_kind=%d, error=%s", static_cast(msg.kind), e.message())); return 0; } catch (const std::exception &e) { - spdlog::warn("peer manager handle queue failed: msg_kind={}, error={}", static_cast(msg.kind), e.what()); + candy::logger().warning(Poco::format("peer manager handle queue failed: msg_kind=%d, error=%s", + static_cast(msg.kind), std::string(e.what()))); return 0; } return 0; @@ -208,7 +211,7 @@ int PeerManager::handlePacket(Msg msg) { int PeerManager::handleTunAddr(Msg msg) { if (this->tunAddr.fromCidr(msg.data)) { - spdlog::error("set tun addr failed: {}", msg.data); + candy::logger().error(Poco::format("set tun addr failed: %s", msg.data)); return -1; } @@ -243,7 +246,7 @@ int PeerManager::handleTryP2P(Msg msg) { } } - spdlog::warn("can not find peer: {}", src.toString()); + candy::logger().warning(Poco::format("can not find peer: %s", src.toString())); return 0; } @@ -251,7 +254,8 @@ int PeerManager::handlePubInfo(Msg msg) { auto info = (CoreMsg::PubInfo *)(msg.data.data()); if (info->src == getClient().address() || info->dst != getClient().address()) { - spdlog::warn("invalid public info: src=[{}] dst=[{}]", info->src.toString(), info->dst.toString()); + candy::logger().warning( + Poco::format("invalid public info: src=[%s] dst=[%s]", info->src.toString(), info->dst.toString())); return 0; } @@ -275,11 +279,12 @@ int PeerManager::handlePubInfo(Msg msg) { } } } catch (const Poco::Exception &e) { - spdlog::warn("peer manager handle pubinfo failed: src={}, ip={}, port={}, error={}", info->src.toString(), - info->ip.toString(), info->port, e.message()); + candy::logger().warning(Poco::format("peer manager handle pubinfo failed: src=%s, ip=%s, port=%hu, error=%s", + info->src.toString(), info->ip.toString(), info->port, e.message())); return 0; } catch (const std::exception &e) { - spdlog::warn("peer manager handle pubinfo failed: src={}, error={}", info->src.toString(), e.what()); + candy::logger().warning( + Poco::format("peer manager handle pubinfo failed: src=%s, error=%s", info->src.toString(), std::string(e.what()))); return 0; } @@ -294,12 +299,12 @@ int PeerManager::startTickThread() { iface.type() != iface.NI_TYPE_OTHER) { auto firstAddress = iface.firstAddress(Poco::Net::IPAddress::IPv4); memcpy(&this->localhost, firstAddress.addr(), sizeof(this->localhost)); - spdlog::debug("localhost: {}", this->localhost.toString()); + candy::logger().debug(Poco::format("localhost: %s", this->localhost.toString())); break; } } } catch (std::exception &e) { - spdlog::warn("local ip failed: {}", e.what()); + candy::logger().warning(Poco::format("local ip failed: %s", std::string(e.what()))); } } @@ -307,7 +312,7 @@ int PeerManager::startTickThread() { return -1; } this->tickThread = std::thread([&] { - spdlog::debug("start thread: peer manager tick"); + candy::logger().debug("start thread: peer manager tick"); try { while (getClient().isRunning()) { auto wake_time = std::chrono::system_clock::now() + std::chrono::seconds(1); @@ -318,10 +323,10 @@ int PeerManager::startTickThread() { } getClient().shutdown(); } catch (const std::exception &e) { - spdlog::error("tick thread exception: {}", e.what()); + candy::logger().error(Poco::format("tick thread exception: %s", std::string(e.what()))); getClient().shutdown(); } - spdlog::debug("stop thread: peer manager tick"); + candy::logger().debug("stop thread: peer manager tick"); }); return 0; } @@ -355,23 +360,23 @@ int PeerManager::initSocket() { this->socket.bind(SocketAddress(AddressFamily::IPv4, this->listenPort)); this->socket.setSendBufferSize(16 * 1024 * 1024); this->socket.setReceiveBufferSize(16 * 1024 * 1024); - spdlog::debug("listen port: {}", this->socket.address().port()); + candy::logger().debug(Poco::format("listen port: %u", this->socket.address().port())); } catch (Poco::Net::NetException &e) { - spdlog::critical("peer socket init failed: {}: {}", e.what(), e.message()); + candy::logger().fatal(Poco::format("peer socket init failed: %s: %s", std::string(e.what()), e.message())); return -1; } this->decryptCtx = std::shared_ptr(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free); this->pollThread = std::thread([&]() { - spdlog::debug("start thread: peer manager poll"); + candy::logger().debug("start thread: peer manager poll"); while (getClient().isRunning()) { if (poll()) { break; } } getClient().shutdown(); - spdlog::debug("stop thread: peer manager poll"); + candy::logger().debug("stop thread: peer manager poll"); }); return 0; } @@ -380,21 +385,21 @@ void PeerManager::sendStunRequest() { try { StunRequest request; if (sendTo(&request, sizeof(request), this->stun.address) != sizeof(request)) { - spdlog::warn("the stun request was not completely sent"); + candy::logger().warning("the stun request was not completely sent"); } } catch (std::exception &e) { - spdlog::debug("send stun request failed: {}", e.what()); + candy::logger().debug(Poco::format("send stun request failed: %s", std::string(e.what()))); } } void PeerManager::handleStunResponse(std::string buffer) { if (buffer.length() < sizeof(StunResponse)) { - spdlog::debug("invalid stun response length: {}", buffer.length()); + candy::logger().debug(Poco::format("invalid stun response length: %zu", buffer.length())); return; } auto response = (StunResponse *)buffer.c_str(); if (ntoh(response->type) != 0x0101) { - spdlog::debug("invalid stun reponse type: {}", ntoh(response->type)); + candy::logger().debug(Poco::format("invalid stun reponse type: %hu", ntoh(response->type))); return; } @@ -425,7 +430,7 @@ void PeerManager::handleStunResponse(std::string buffer) { pos += 2 + ntoh(*(uint16_t *)(attr + pos)); } if (!ip || !port) { - spdlog::warn("stun response parse failed: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("stun response parse failed: %s", to_hex(buffer))); return; } @@ -459,14 +464,14 @@ void PeerManager::handleMessage(std::string buffer, const SocketAddress &address } break; default: - spdlog::info("udp4 unknown message: {}", address.toString()); + candy::logger().information(Poco::format("udp4 unknown message: %s", address.toString())); break; } } void PeerManager::handleHeartbeatMessage(std::string buffer, const SocketAddress &address) { if (buffer.size() < sizeof(PeerMsg::Heartbeat)) { - spdlog::debug("udp4 heartbeat failed: len {} address {}", buffer.length(), address.toString()); + candy::logger().debug(Poco::format("udp4 heartbeat failed: len %zu address %s", buffer.length(), address.toString())); return; } @@ -474,7 +479,7 @@ void PeerManager::handleHeartbeatMessage(std::string buffer, const SocketAddress std::shared_lock lock(this->ipPeerMutex); auto it = this->ipPeerMap.find(heartbeat->tunip); if (it == this->ipPeerMap.end()) { - spdlog::debug("udp4 heartbeat find peer failed: tun ip {}", heartbeat->tunip.toString()); + candy::logger().debug(Poco::format("udp4 heartbeat find peer failed: tun ip %s", heartbeat->tunip.toString())); return; } it->second.handleHeartbeatMessage(address, heartbeat->ack); @@ -482,7 +487,7 @@ void PeerManager::handleHeartbeatMessage(std::string buffer, const SocketAddress void PeerManager::handleForwardMessage(std::string buffer, const SocketAddress &address) { if (buffer.size() < sizeof(PeerMsg::Forward)) { - spdlog::warn("invalid forward message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid forward message: %s", to_hex(buffer))); return; } buffer.erase(0, 1); @@ -496,7 +501,7 @@ void PeerManager::handleForwardMessage(std::string buffer, const SocketAddress & void PeerManager::handleDelayMessage(std::string buffer, const SocketAddress &address) { if (buffer.size() < sizeof(PeerMsg::Delay)) { - spdlog::warn("invalid delay message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid delay message: %s", to_hex(buffer))); return; } @@ -532,7 +537,7 @@ void PeerManager::handleRouteMessage(std::string buffer, const SocketAddress &ad } if (buffer.size() < sizeof(PeerMsg::Route)) { - spdlog::warn("invalid delay message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid delay message: %s", to_hex(buffer))); return; } auto header = (PeerMsg::Route *)buffer.data(); @@ -564,7 +569,7 @@ int PeerManager::poll() { } catch (Poco::Net::ConnectionResetException &e) { // 忽略 UDP 的连接 Reset, Windows 特有的问题 } catch (std::exception &e) { - spdlog::warn("peer_manager poll failed: {}", e.what()); + candy::logger().warning(Poco::format("peer_manager poll failed: %s", std::string(e.what()))); return -1; } return 0; @@ -579,12 +584,12 @@ std::optional PeerManager::decrypt(const std::string &ciphertext) { unsigned char tag[AES_256_GCM_TAG_LEN] = {0}; if (this->key.size() != AES_256_GCM_KEY_LEN) { - spdlog::debug("invalid key length: {}", this->key.size()); + candy::logger().debug(Poco::format("invalid key length: %zu", this->key.size())); return std::nullopt; } if (ciphertext.size() < AES_256_GCM_IV_LEN + AES_256_GCM_TAG_LEN) { - spdlog::debug("invalid ciphertext length: {}", ciphertext.size()); + candy::logger().debug(Poco::format("invalid ciphertext length: %zu", ciphertext.size())); return std::nullopt; } @@ -592,7 +597,7 @@ std::optional PeerManager::decrypt(const std::string &ciphertext) { auto ctx = this->decryptCtx.get(); if (!EVP_CIPHER_CTX_reset(ctx)) { - spdlog::debug("decrypt reset cipher context failed"); + candy::logger().debug("decrypt reset cipher context failed"); return std::nullopt; } @@ -602,25 +607,25 @@ std::optional PeerManager::decrypt(const std::string &ciphertext) { enc += AES_256_GCM_IV_LEN + AES_256_GCM_TAG_LEN; if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, (unsigned char *)key.data(), iv)) { - spdlog::debug("initialize cipher context failed"); + candy::logger().debug("initialize cipher context failed"); return std::nullopt; } if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_256_GCM_IV_LEN, NULL)) { - spdlog::debug("set iv length failed"); + candy::logger().debug("set iv length failed"); return std::nullopt; } if (!EVP_DecryptUpdate(ctx, plaintext, &len, enc, ciphertext.size() - AES_256_GCM_IV_LEN - AES_256_GCM_TAG_LEN)) { - spdlog::debug("decrypt update failed"); + candy::logger().debug("decrypt update failed"); return std::nullopt; } if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_256_GCM_TAG_LEN, tag)) { - spdlog::debug("set tag failed"); + candy::logger().debug("set tag failed"); return std::nullopt; } plaintextLen = len; if (!EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) { - spdlog::debug("decrypt final failed"); + candy::logger().debug("decrypt final failed"); return std::nullopt; } @@ -636,10 +641,10 @@ int PeerManager::sendTo(const void *buffer, int length, const SocketAddress &add try { return this->socket.sendTo(buffer, length, address); } catch (const Poco::Net::NetException &e) { - spdlog::debug("socket sendTo failed: {}", e.message()); + candy::logger().debug(Poco::format("socket sendTo failed: %s", e.message())); return -1; } catch (const std::exception &e) { - spdlog::debug("socket sendTo failed: {}", e.what()); + candy::logger().debug(Poco::format("socket sendTo failed: %s", std::string(e.what()))); return -1; } } @@ -658,7 +663,7 @@ Client &PeerManager::getClient() { void PeerManager::showRtChange(const PeerRouteEntry &entry) { std::string rtt = (entry.rtt == RTT_LIMIT) ? "[deleted]" : std::to_string(entry.rtt); - spdlog::debug("route: dst={} next={} delay={}", entry.dst.toString(), entry.next.toString(), rtt); + candy::logger().debug(Poco::format("route: dst=%s next=%s delay=%s", entry.dst.toString(), entry.next.toString(), rtt)); } int PeerManager::sendRtMessage(IP4 dst, int32_t rtt) { diff --git a/candy/src/peer/manager.h b/candy/src/peer/manager.h index 823b4a65..ecc7ad51 100644 --- a/candy/src/peer/manager.h +++ b/candy/src/peer/manager.h @@ -6,6 +6,8 @@ #include "core/net.h" #include "peer/message.h" #include "peer/peer.h" +#include "utils/log.h" +#include #include #include #include @@ -44,7 +46,7 @@ struct Stun { } return 0; } catch (std::exception &e) { - spdlog::warn("set stun server address failed: {}", e.what()); + candy::logger().warning(Poco::format("set stun server address failed: %s", std::string(e.what()))); return -1; } } @@ -82,7 +84,6 @@ class PeerManager { int updateRtTable(PeerRouteEntry entry); private: - // 处理来自消息队列的数据 int handlePeerQueue(); int handlePacket(Msg msg); int handleTunAddr(Msg msg); @@ -131,7 +132,6 @@ class PeerManager { std::mutex decryptCtxMutex; std::string key; - // 默认监听端口,如果不配置,随机监听 uint16_t listenPort = 0; public: diff --git a/candy/src/peer/peer.cc b/candy/src/peer/peer.cc index f32931d9..b52f9491 100644 --- a/candy/src/peer/peer.cc +++ b/candy/src/peer/peer.cc @@ -4,14 +4,15 @@ #include "core/message.h" #include "peer/manager.h" #include "peer/peer.h" +#include "utils/log.h" #include "utils/time.h" +#include #include #include #include #include #include #include -#include namespace { @@ -23,7 +24,7 @@ bool isLocalNetwork(const SocketAddress &addr) { if (ip.isV4()) { return ip.isSiteLocal() || ip.isLinkLocal() || ip.isSiteLocalMC(); } else if (ip.isV6()) { - spdlog::error("unexpected ipv6 local address"); + candy::logger().error("unexpected ipv6 local address"); } return false; @@ -65,7 +66,7 @@ std::optional Peer::encrypt(const std::string &plaintext) { unsigned char tag[AES_256_GCM_TAG_LEN] = {0}; if (!RAND_bytes(iv, AES_256_GCM_IV_LEN)) { - spdlog::debug("generate random iv failed"); + candy::logger().debug("generate random iv failed"); return std::nullopt; } @@ -73,29 +74,29 @@ std::optional Peer::encrypt(const std::string &plaintext) { auto ctx = this->encryptCtx.get(); if (!EVP_CIPHER_CTX_reset(ctx)) { - spdlog::debug("encrypt reset cipher context failed"); + candy::logger().debug("encrypt reset cipher context failed"); return std::nullopt; } if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, (unsigned char *)key.data(), iv)) { - spdlog::debug("encrypt initialize cipher context failed"); + candy::logger().debug("encrypt initialize cipher context failed"); return std::nullopt; } if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_256_GCM_IV_LEN, NULL)) { - spdlog::debug("set iv length failed"); + candy::logger().debug("set iv length failed"); return std::nullopt; } if (!EVP_EncryptUpdate(ctx, ciphertext, &len, (unsigned char *)plaintext.data(), plaintext.size())) { - spdlog::debug("encrypt update failed"); + candy::logger().debug("encrypt update failed"); return std::nullopt; } ciphertextLen = len; if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) { - spdlog::debug("encrypt final failed"); + candy::logger().debug("encrypt final failed"); return std::nullopt; } ciphertextLen += len; if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_256_GCM_TAG_LEN, tag)) { - spdlog::debug("get tag failed"); + candy::logger().debug("get tag failed"); return std::nullopt; } @@ -131,7 +132,7 @@ bool Peer::updateState(PeerState state) { return false; } - spdlog::debug("state: {} {} => {}", this->addr.toString(), stateString(), stateString(state)); + candy::logger().debug(Poco::format("state: %s %s => %s", this->addr.toString(), stateString(), stateString(state))); if (state == PeerState::INIT || state == PeerState::WAITING || state == PeerState::FAILED) { resetState(); @@ -182,7 +183,8 @@ void Peer::handlePubInfo(IP4 ip, uint16_t port, bool local) { this->wide = SocketAddress(ip.toString(), port); } catch (const Poco::Exception &e) { - spdlog::warn("peer handle pubinfo failed: ip={}, port={}, error={}", ip.toString(), port, e.message()); + candy::logger().warning( + Poco::format("peer handle pubinfo failed: ip=%s, port=%hu, error=%s", ip.toString(), port, e.message())); return; } @@ -269,7 +271,7 @@ void Peer::tick() { void Peer::handleHeartbeatMessage(const SocketAddress &address, uint8_t heartbeatAck) { if (this->state == PeerState::INIT || this->state == PeerState::WAITING || this->state == PeerState::FAILED) { - spdlog::debug("heartbeat peer state invalid: {} {}", this->addr.toString(), stateString()); + candy::logger().debug(Poco::format("heartbeat peer state invalid: %s %s", this->addr.toString(), stateString())); return; } @@ -306,7 +308,7 @@ int Peer::send(const std::string &buffer) { } } } catch (std::exception &e) { - spdlog::debug("peer send failed: {}", e.what()); + candy::logger().debug(Poco::format("peer send failed: %s", std::string(e.what()))); } return -1; } diff --git a/candy/src/tun/linux.cc b/candy/src/tun/linux.cc index 809de314..f41857f4 100644 --- a/candy/src/tun/linux.cc +++ b/candy/src/tun/linux.cc @@ -4,13 +4,14 @@ #include "core/net.h" #include "tun/tun.h" +#include "utils/log.h" +#include #include #include #include #include #include #include -#include #include #include #include @@ -47,19 +48,19 @@ class LinuxTun { int up() { this->tunFd = open("/dev/net/tun", O_RDWR); if (this->tunFd < 0) { - spdlog::critical("open /dev/net/tun failed: {}", strerror(errno)); + candy::logger().fatal(Poco::format("open /dev/net/tun failed: %s", strerror(errno))); close(this->tunFd); return -1; } int flags = fcntl(this->tunFd, F_GETFL, 0); if (flags < 0) { - spdlog::error("get tun flags failed: {}", strerror(errno)); + candy::logger().error(Poco::format("get tun flags failed: %s", strerror(errno))); close(this->tunFd); return -1; } flags |= O_NONBLOCK; if (fcntl(this->tunFd, F_SETFL, flags) < 0) { - spdlog::error("set non-blocking tun failed: {}", strerror(errno)); + candy::logger().error(Poco::format("set non-blocking tun failed: %s", strerror(errno))); close(this->tunFd); return -1; } @@ -70,7 +71,7 @@ class LinuxTun { strncpy(ifr.ifr_name, this->name.c_str(), IFNAMSIZ); ifr.ifr_flags = IFF_TUN | IFF_NO_PI; if (ioctl(this->tunFd, TUNSETIFF, &ifr) == -1) { - spdlog::critical("set tun interface failed: {}", strerror(errno)); + candy::logger().fatal(Poco::format("set tun interface failed: %s", strerror(errno))); close(this->tunFd); return -1; } @@ -81,7 +82,7 @@ class LinuxTun { addr->sin_family = AF_INET; int sockfd = socket(addr->sin_family, SOCK_DGRAM, 0); if (sockfd == -1) { - spdlog::critical("create socket failed"); + candy::logger().fatal("create socket failed"); close(this->tunFd); return -1; } @@ -89,7 +90,7 @@ class LinuxTun { // 设置地址 addr->sin_addr.s_addr = this->ip; if (ioctl(sockfd, SIOCSIFADDR, (caddr_t)&ifr) == -1) { - spdlog::critical("set ip address failed: ip {}", this->ip.toString()); + candy::logger().fatal(Poco::format("set ip address failed: ip %s", this->ip.toString())); close(sockfd); close(this->tunFd); return -1; @@ -98,7 +99,7 @@ class LinuxTun { // 设置掩码 addr->sin_addr.s_addr = this->mask; if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t)&ifr) == -1) { - spdlog::critical("set mask failed: mask {}", this->mask.toString()); + candy::logger().fatal(Poco::format("set mask failed: mask %s", this->mask.toString())); close(sockfd); close(this->tunFd); return -1; @@ -107,7 +108,7 @@ class LinuxTun { // 设置 MTU ifr.ifr_mtu = this->mtu; if (ioctl(sockfd, SIOCSIFMTU, (caddr_t)&ifr) == -1) { - spdlog::critical("set mtu failed: mtu {}", this->mtu); + candy::logger().fatal(Poco::format("set mtu failed: mtu %d", this->mtu)); close(sockfd); close(this->tunFd); return -1; @@ -115,14 +116,14 @@ class LinuxTun { // 设置 flags if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1) { - spdlog::critical("get interface flags failed"); + candy::logger().fatal("get interface flags failed"); close(sockfd); close(this->tunFd); return -1; } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1) { - spdlog::critical("set interface flags failed"); + candy::logger().fatal("set interface flags failed"); close(sockfd); close(this->tunFd); return -1; @@ -156,7 +157,7 @@ class LinuxTun { select(this->tunFd + 1, &set, NULL, NULL, &timeout); return 0; } - spdlog::warn("tun read failed: {}", strerror(errno)); + candy::logger().warning(Poco::format("tun read failed: %s", strerror(errno))); return -1; } @@ -167,7 +168,7 @@ class LinuxTun { int setSysRtTable(IP4 dst, IP4 mask, IP4 nexthop) { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { - spdlog::error("set route failed: create socket failed"); + candy::logger().error("set route failed: create socket failed"); return -1; } @@ -189,7 +190,7 @@ class LinuxTun { route.rt_flags = RTF_UP | RTF_GATEWAY; if (ioctl(sockfd, SIOCADDRT, &route) == -1) { - spdlog::error("set route failed: ioctl failed"); + candy::logger().error("set route failed: ioctl failed"); close(sockfd); return -1; } @@ -234,7 +235,7 @@ int Tun::setAddress(const std::string &cidr) { if (address.fromCidr(cidr)) { return -1; } - spdlog::info("client address: {}", address.toCidr()); + candy::logger().information(Poco::format("client address: %s", address.toCidr())); tun = std::any_cast>(this->impl); if (tun->setIP(address.Host())) { return -1; diff --git a/candy/src/tun/macos.cc b/candy/src/tun/macos.cc index 08cec1b2..895c1189 100644 --- a/candy/src/tun/macos.cc +++ b/candy/src/tun/macos.cc @@ -11,11 +11,12 @@ #include #include // clang-format on +#include "utils/hex.h" +#include "utils/log.h" +#include #include #include #include -#include -#include #include #include #include @@ -56,18 +57,18 @@ class MacTun { // 创建设备,操作系统不允许自定义设备名,只能由内核分配 this->tunFd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); if (this->tunFd < 0) { - spdlog::critical("create socket failed: {}", strerror(errno)); + candy::logger().fatal(Poco::format("create socket failed: %s", strerror(errno))); return -1; } int flags = fcntl(this->tunFd, F_GETFL, 0); if (flags < 0) { - spdlog::error("get tun flags failed: {}", strerror(errno)); + candy::logger().error(Poco::format("get tun flags failed: %s", strerror(errno))); close(this->tunFd); return -1; } flags |= O_NONBLOCK; if (fcntl(this->tunFd, F_SETFL, flags) < 0) { - spdlog::error("set non-blocking tun failed: {}", strerror(errno)); + candy::logger().error(Poco::format("set non-blocking tun failed: %s", strerror(errno))); close(this->tunFd); return -1; } @@ -76,7 +77,7 @@ class MacTun { memset(&info, 0, sizeof(info)); strncpy(info.ctl_name, UTUN_CONTROL_NAME, MAX_KCTL_NAME); if (ioctl(this->tunFd, CTLIOCGINFO, &info) == -1) { - spdlog::critical("get control id failed: {}", strerror(errno)); + candy::logger().fatal(Poco::format("get control id failed: %s", strerror(errno))); close(this->tunFd); return -1; } @@ -89,19 +90,19 @@ class MacTun { ctl.sc_id = info.ctl_id; ctl.sc_unit = 0; if (connect(this->tunFd, (struct sockaddr *)&ctl, sizeof(ctl)) == -1) { - spdlog::critical("connect to control failed: {}", strerror(errno)); + candy::logger().fatal(Poco::format("connect to control failed: %s", strerror(errno))); close(this->tunFd); return -1; } socklen_t ifname_len = sizeof(ifname); if (getsockopt(this->tunFd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, ifname, &ifname_len) == -1) { - spdlog::critical("get interface name failed: {}", strerror(errno)); + candy::logger().fatal(Poco::format("get interface name failed: %s", strerror(errno))); close(this->tunFd); return -1; } - spdlog::debug("created utun interface: {}", ifname); + candy::logger().debug(Poco::format("created utun interface: %s", ifname)); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); @@ -113,7 +114,7 @@ class MacTun { addr->sin_family = AF_INET; int sockfd = socket(addr->sin_family, SOCK_DGRAM, 0); if (sockfd == -1) { - spdlog::critical("create socket failed"); + candy::logger().fatal("create socket failed"); close(this->tunFd); return -1; } @@ -135,8 +136,8 @@ class MacTun { ((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_addr.s_addr = (this->ip & this->mask); if (ioctl(sockfd, SIOCAIFADDR, (void *)&areq) == -1) { - spdlog::critical("set ip mask failed: {}: ip {} mask {}", strerror(errno), this->ip.toString(), - this->mask.toString()); + candy::logger().fatal(Poco::format("set ip mask failed: %s: ip %s mask %s", strerror(errno), this->ip.toString(), + this->mask.toString())); close(sockfd); close(this->tunFd); return -1; @@ -145,7 +146,7 @@ class MacTun { // 设置 MTU ifr.ifr_mtu = this->mtu; if (ioctl(sockfd, SIOCSIFMTU, &ifr) == -1) { - spdlog::critical("set mtu failed: mtu {}", this->mtu); + candy::logger().fatal(Poco::format("set mtu failed: mtu %d", this->mtu)); close(sockfd); close(this->tunFd); return -1; @@ -153,14 +154,14 @@ class MacTun { // 设置 flags if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1) { - spdlog::critical("get interface flags failed"); + candy::logger().fatal("get interface flags failed"); close(sockfd); close(this->tunFd); return -1; } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1) { - spdlog::critical("set interface flags failed"); + candy::logger().fatal("set interface flags failed"); close(sockfd); close(this->tunFd); return -1; @@ -205,7 +206,7 @@ class MacTun { return 0; } - spdlog::warn("tun read failed: error {}", n); + candy::logger().warning(Poco::format("tun read failed: error %d", n)); return -1; } @@ -240,11 +241,11 @@ class MacTun { int routefd = socket(AF_ROUTE, SOCK_RAW, 0); if (routefd < 0) { - spdlog::error("create route fd failed: {}", strerror(routefd)); + candy::logger().error(Poco::format("create route fd failed: %s", strerror(routefd))); return -1; } if (::write(routefd, &msg, sizeof(msg)) == -1) { - spdlog::error("add route failed: {}", strerror(errno)); + candy::logger().error(Poco::format("add route failed: %s", strerror(errno))); close(routefd); return -1; } @@ -291,7 +292,7 @@ int Tun::setAddress(const std::string &cidr) { if (address.fromCidr(cidr)) { return -1; } - spdlog::info("client address: {}", address.toCidr()); + candy::logger().information(Poco::format("client address: %s", address.toCidr())); tun = std::any_cast>(this->impl); if (tun->setIP(address.Host())) { return -1; diff --git a/candy/src/tun/tun.cc b/candy/src/tun/tun.cc index dde55652..767ae459 100644 --- a/candy/src/tun/tun.cc +++ b/candy/src/tun/tun.cc @@ -3,16 +3,18 @@ #include "core/client.h" #include "core/message.h" #include "core/net.h" +#include "utils/hex.h" +#include "utils/log.h" +#include #include #include -#include namespace candy { int Tun::run(Client *client) { this->client = client; this->msgThread = std::thread([&] { - spdlog::debug("start thread: tun msg"); + candy::logger().debug("start thread: tun msg"); try { while (getClient().isRunning()) { if (handleTunQueue()) { @@ -21,10 +23,10 @@ int Tun::run(Client *client) { } getClient().shutdown(); } catch (const std::exception &e) { - spdlog::error("tun msg thread exception: {}", e.what()); + candy::logger().error(Poco::format("tun msg thread exception: %s", std::string(e.what()))); getClient().shutdown(); } - spdlog::debug("stop thread: tun msg"); + candy::logger().debug("stop thread: tun msg"); }); return 0; } @@ -100,7 +102,7 @@ int Tun::handleTunQueue() { handleSysRt(std::move(msg)); break; default: - spdlog::warn("unexcepted tun message type: {}", static_cast(msg.kind)); + candy::logger().warning(Poco::format("unexcepted tun message type: %d", static_cast(msg.kind))); break; } return 0; @@ -108,7 +110,7 @@ int Tun::handleTunQueue() { int Tun::handlePacket(Msg msg) { if (msg.data.size() < sizeof(IP4Header)) { - spdlog::warn("invalid IPv4 packet: {:n}", spdlog::to_hex(msg.data)); + candy::logger().warning(Poco::format("invalid IPv4 packet: %s", to_hex(msg.data))); return 0; } IP4Header *header = (IP4Header *)msg.data.data(); @@ -126,12 +128,12 @@ int Tun::handleTunAddr(Msg msg) { } if (up()) { - spdlog::critical("tun up failed"); + candy::logger().fatal("tun up failed"); return -1; } this->tunThread = std::thread([&] { - spdlog::debug("start thread: tun"); + candy::logger().debug("start thread: tun"); try { while (getClient().isRunning()) { if (handleTunDevice()) { @@ -139,14 +141,14 @@ int Tun::handleTunAddr(Msg msg) { } } getClient().shutdown(); - spdlog::debug("stop thread: tun"); + candy::logger().debug("stop thread: tun"); if (down()) { - spdlog::critical("tun down failed"); + candy::logger().fatal("tun down failed"); return; } } catch (const std::exception &e) { - spdlog::error("tun thread exception: {}", e.what()); + candy::logger().error(Poco::format("tun thread exception: %s", std::string(e.what()))); getClient().shutdown(); } }); @@ -157,7 +159,8 @@ int Tun::handleTunAddr(Msg msg) { int Tun::handleSysRt(Msg msg) { SysRouteEntry *rt = (SysRouteEntry *)msg.data.data(); if (rt->nexthop != getIP()) { - spdlog::info("route: {}/{} via {}", rt->dst.toString(), rt->mask.toPrefix(), rt->nexthop.toString()); + candy::logger().information( + Poco::format("route: %s/%d via %s", rt->dst.toString(), rt->mask.toPrefix(), rt->nexthop.toString())); if (setSysRtTable(*rt)) { return -1; } diff --git a/candy/src/tun/windows.cc b/candy/src/tun/windows.cc index ecde72ab..703659bf 100644 --- a/candy/src/tun/windows.cc +++ b/candy/src/tun/windows.cc @@ -7,8 +7,6 @@ #include "utils/codecvt.h" #include #include -#include -#include #include #include // clang-format off @@ -28,6 +26,9 @@ #pragma GCC diagnostic ignored "-Wunknown-pragmas" #include #pragma GCC diagnostic pop +#include "utils/hex.h" +#include "utils/log.h" +#include namespace candy { @@ -57,7 +58,7 @@ class Holder { Holder() { this->wintun = LoadLibraryExW(L"wintun.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); if (!this->wintun) { - spdlog::critical("load wintun.dll failed"); + candy::logger().fatal("load wintun.dll failed"); return; } #pragma GCC diagnostic push @@ -70,7 +71,7 @@ class Holder { #undef X #pragma GCC diagnostic pop { - spdlog::critical("get function from wintun.dll failed"); + candy::logger().fatal("get function from wintun.dll failed"); FreeLibrary(this->wintun); this->wintun = NULL; return; @@ -116,7 +117,7 @@ class WindowsTun { int up() { if (!Holder::Ok()) { - spdlog::critical("init wintun failed"); + candy::logger().fatal("init wintun failed"); return -1; } @@ -127,7 +128,7 @@ class WindowsTun { memcpy(&Guid, hash, sizeof(Guid)); this->adapter = WintunCreateAdapter(UTF8ToUTF16(this->name).c_str(), L"Candy", &Guid); if (!this->adapter) { - spdlog::critical("create wintun adapter failed: {}", GetLastError()); + candy::logger().fatal(Poco::format("create wintun adapter failed: %lu", GetLastError())); return -1; } int Error; @@ -140,7 +141,7 @@ class WindowsTun { AddressRow.DadState = IpDadStatePreferred; Error = CreateUnicastIpAddressEntry(&AddressRow); if (Error != ERROR_SUCCESS) { - spdlog::critical("create unicast ip address entry failed: {}", Error); + candy::logger().fatal(Poco::format("create unicast ip address entry failed: %d", Error)); return -1; } @@ -149,7 +150,7 @@ class WindowsTun { Interface.InterfaceLuid = AddressRow.InterfaceLuid; Error = GetIpInterfaceEntry(&Interface); if (Error != NO_ERROR) { - spdlog::critical("get ip interface entry failed: {}", Error); + candy::logger().fatal(Poco::format("get ip interface entry failed: %d", Error)); return -1; } this->ifindex = Interface.InterfaceIndex; @@ -157,13 +158,13 @@ class WindowsTun { Interface.NlMtu = this->mtu; Error = SetIpInterfaceEntry(&Interface); if (Error != NO_ERROR) { - spdlog::critical("set ip interface entry failed: {}", Error); + candy::logger().fatal(Poco::format("set ip interface entry failed: %d", Error)); return -1; } this->session = WintunStartSession(this->adapter, WINTUN_MIN_RING_CAPACITY); if (!this->session) { - spdlog::critical("start wintun session failed: {}", GetLastError()); + candy::logger().fatal(Poco::format("start wintun session failed: %lu", GetLastError())); return -1; } return 0; @@ -199,7 +200,7 @@ class WindowsTun { WaitForSingleObject(WintunGetReadWaitEvent(this->session), 1000); return 0; } - spdlog::error("wintun read failed: {}", GetLastError()); + candy::logger().error(Poco::format("wintun read failed: %lu", GetLastError())); } return -1; } @@ -215,7 +216,7 @@ class WindowsTun { if (GetLastError() == ERROR_BUFFER_OVERFLOW) { return 0; } - spdlog::error("wintun write failed: {}", GetLastError()); + candy::logger().error(Poco::format("wintun write failed: %lu", GetLastError())); } return -1; } @@ -242,7 +243,7 @@ class WindowsTun { if (result == NO_ERROR) { routes.push(route); } else { - spdlog::error("add route failed: {}", result); + candy::logger().error(Poco::format("add route failed: %lu", result)); } return 0; @@ -288,7 +289,7 @@ int Tun::setAddress(const std::string &cidr) { if (address.fromCidr(cidr)) { return -1; } - spdlog::info("client address: {}", address.toCidr()); + candy::logger().information(Poco::format("client address: %s", address.toCidr())); tun = std::any_cast>(this->impl); if (tun->setIP(address.Host())) { return -1; diff --git a/candy/src/utils/hex.h b/candy/src/utils/hex.h new file mode 100644 index 00000000..bae2ed48 --- /dev/null +++ b/candy/src/utils/hex.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +#ifndef CANDY_UTILS_HEX_H +#define CANDY_UTILS_HEX_H + +#include +#include +#include + +namespace candy { + +inline std::string to_hex(const std::string &buffer) { + std::ostringstream oss; + oss << std::hex << std::setfill('0'); + for (unsigned char c : buffer) { + oss << std::setw(2) << static_cast(c); + } + return oss.str(); +} + +} // namespace candy + +#endif diff --git a/candy/src/utils/log.h b/candy/src/utils/log.h new file mode 100644 index 00000000..ef6cab0d --- /dev/null +++ b/candy/src/utils/log.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +#ifndef CANDY_UTILS_LOG_H +#define CANDY_UTILS_LOG_H + +#include + +namespace candy { + +inline Poco::Logger &logger() { + return Poco::Logger::root(); +} + +} // namespace candy + +#endif diff --git a/candy/src/utils/time.cc b/candy/src/utils/time.cc index e2915d4e..82fa8677 100644 --- a/candy/src/utils/time.cc +++ b/candy/src/utils/time.cc @@ -6,8 +6,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/candy/src/websocket/client.cc b/candy/src/websocket/client.cc index 1bb818a5..4bd1bea8 100644 --- a/candy/src/websocket/client.cc +++ b/candy/src/websocket/client.cc @@ -4,8 +4,11 @@ #include "core/message.h" #include "core/net.h" #include "core/version.h" +#include "utils/hex.h" +#include "utils/log.h" #include "utils/time.h" #include "websocket/message.h" +#include #include #include #include @@ -13,8 +16,6 @@ #include #include #include -#include -#include namespace candy { @@ -56,7 +57,7 @@ int WebSocketClient::run(Client *client) { this->client = client; if (connect()) { - spdlog::critical("websocket client connect failed"); + candy::logger().fatal("websocket client connect failed"); return -1; } @@ -68,28 +69,28 @@ int WebSocketClient::run(Client *client) { } this->msgThread = std::thread([&] { - spdlog::debug("start thread: websocket client msg"); + candy::logger().debug("start thread: websocket client msg"); try { while (getClient().isRunning()) { handleWsQueue(); } getClient().shutdown(); } catch (const std::exception &e) { - spdlog::error("websocket msg thread exception: {}", e.what()); + candy::logger().error(Poco::format("websocket msg thread exception: %s", std::string(e.what()))); getClient().shutdown(); } - spdlog::debug("stop thread: websocket client msg"); + candy::logger().debug("stop thread: websocket client msg"); }); this->wsThread = std::thread([&] { - spdlog::debug("start thread: websocket client ws"); + candy::logger().debug("start thread: websocket client ws"); while (getClient().isRunning()) { if (handleWsConn()) { break; } } getClient().shutdown(); - spdlog::debug("stop thread: websocket client ws"); + candy::logger().debug("stop thread: websocket client ws"); }); return 0; @@ -120,7 +121,7 @@ void WebSocketClient::handleWsQueue() { handleDiscovery(std::move(msg)); break; default: - spdlog::warn("unexcepted websocket message type: {}", static_cast(msg.kind)); + candy::logger().warning(Poco::format("unexcepted websocket message type: %d", static_cast(msg.kind))); break; } } @@ -162,7 +163,7 @@ int WebSocketClient::handleWsConn() { if (!this->ws->poll(Poco::Timespan(1, 0), Poco::Net::Socket::SELECT_READ | Poco::Net::Socket::SELECT_ERROR)) { if (bootTime() - this->timestamp > 30000) { - spdlog::warn("websocket pong timeout"); + candy::logger().warning("websocket pong timeout"); return -1; } if (bootTime() - this->timestamp > 15000) { @@ -172,14 +173,14 @@ int WebSocketClient::handleWsConn() { } if (this->ws->getError()) { - spdlog::warn("websocket connection error: {}", this->ws->getError()); + candy::logger().warning(Poco::format("websocket connection error: %d", this->ws->getError())); return -1; } buffer.resize(1500); int length = this->ws->receiveFrame(buffer.data(), buffer.size(), flags); if (length == 0 && flags == 0) { - spdlog::info("abnormal disconnect"); + candy::logger().information("abnormal disconnect"); return -1; } if ((flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) == Poco::Net::WebSocket::FRAME_OP_PING) { @@ -193,7 +194,7 @@ int WebSocketClient::handleWsConn() { return 0; } if ((flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) == Poco::Net::WebSocket::FRAME_OP_CLOSE) { - spdlog::info("websocket close: {}", buffer); + candy::logger().information(Poco::format("websocket close: %s", buffer)); return -1; } if (length > 0) { @@ -204,7 +205,7 @@ int WebSocketClient::handleWsConn() { } return 0; } catch (std::exception &e) { - spdlog::warn("handle ws conn failed: {}", e.what()); + candy::logger().warning(Poco::format("handle ws conn failed: %s", std::string(e.what()))); return -1; } } @@ -231,14 +232,14 @@ void WebSocketClient::handleWsMsg(std::string buffer) { handleGeneralMsg(std::move(buffer)); break; default: - spdlog::debug("unknown websocket message kind: {}", msgKind); + candy::logger().debug(Poco::format("unknown websocket message kind: %u", msgKind)); break; } } void WebSocketClient::handleForwardMsg(std::string buffer) { if (buffer.size() < sizeof(WsMsg::Forward)) { - spdlog::warn("invalid forward message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid forward message: %s", to_hex(buffer))); return; } // 移除一个字节的类型 @@ -253,7 +254,7 @@ void WebSocketClient::handleForwardMsg(std::string buffer) { void WebSocketClient::handleExptTunMsg(std::string buffer) { if (buffer.size() < sizeof(WsMsg::ExptTun)) { - spdlog::warn("invalid expt tun message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid expt tun message: %s", to_hex(buffer))); return; } WsMsg::ExptTun *header = (WsMsg::ExptTun *)buffer.data(); @@ -264,7 +265,7 @@ void WebSocketClient::handleExptTunMsg(std::string buffer) { void WebSocketClient::handleUdp4ConnMsg(std::string buffer) { if (buffer.size() < sizeof(WsMsg::Conn)) { - spdlog::warn("invalid udp4conn message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid udp4conn message: %s", to_hex(buffer))); return; } WsMsg::Conn *header = (WsMsg::Conn *)buffer.data(); @@ -274,7 +275,7 @@ void WebSocketClient::handleUdp4ConnMsg(std::string buffer) { void WebSocketClient::handleDiscoveryMsg(std::string buffer) { if (buffer.size() < sizeof(WsMsg::Discovery)) { - spdlog::warn("invalid discovery message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid discovery message: %s", to_hex(buffer))); return; } WsMsg::Discovery *header = (WsMsg::Discovery *)buffer.data(); @@ -286,7 +287,7 @@ void WebSocketClient::handleDiscoveryMsg(std::string buffer) { void WebSocketClient::handleRouteMsg(std::string buffer) { if (buffer.size() < sizeof(WsMsg::SysRoute)) { - spdlog::warn("invalid route message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid route message: %s", to_hex(buffer))); return; } WsMsg::SysRoute *header = (WsMsg::SysRoute *)buffer.data(); @@ -299,7 +300,7 @@ void WebSocketClient::handleRouteMsg(std::string buffer) { void WebSocketClient::handleGeneralMsg(std::string buffer) { if (buffer.size() < sizeof(WsMsg::ConnLocal)) { - spdlog::warn("invalid udp4conn local message: {:n}", spdlog::to_hex(buffer)); + candy::logger().warning(Poco::format("invalid udp4conn local message: %s", to_hex(buffer))); return; } WsMsg::ConnLocal *header = (WsMsg::ConnLocal *)buffer.data(); @@ -322,7 +323,7 @@ void WebSocketClient::sendFrame(const void *buffer, int length, int flags) { try { this->ws->sendFrame(buffer, length, flags); } catch (std::exception &e) { - spdlog::critical("websocket send frame failed: {}", e.what()); + candy::logger().fatal(Poco::format("websocket send frame failed: %s", std::string(e.what()))); } } } @@ -378,7 +379,7 @@ int WebSocketClient::connect() { try { uri = std::make_shared(wsServerUri); } catch (std::exception &e) { - spdlog::critical("invalid websocket server: {}: {}", wsServerUri, e.what()); + candy::logger().fatal(Poco::format("invalid websocket server: %s: %s", wsServerUri, std::string(e.what()))); return -1; } @@ -395,17 +396,17 @@ int WebSocketClient::connect() { Poco::Net::HTTPClientSession cs(uri->getHost(), uri->getPort()); this->ws = std::make_shared(cs, request, response); } else { - spdlog::critical("invalid websocket scheme: {}", wsServerUri); + candy::logger().fatal(Poco::format("invalid websocket scheme: %s", wsServerUri)); return -1; } // Blocking mode may cause receiveFrame to hang and use 100% CPU this->ws->setBlocking(false); this->timestamp = bootTime(); - this->pingMessage = fmt::format("candy::{}::{}::{}", CANDY_SYSTEM, CANDY_VERSION, hostName()); - spdlog::debug("client info: {}", this->pingMessage); + this->pingMessage = "candy::" + std::string(CANDY_SYSTEM) + "::" + std::string(CANDY_VERSION) + "::" + hostName(); + candy::logger().debug(Poco::format("client info: %s", this->pingMessage)); return 0; } catch (std::exception &e) { - spdlog::critical("websocket connect failed: {}", e.what()); + candy::logger().fatal(Poco::format("websocket connect failed: %s", std::string(e.what()))); return -1; } } @@ -418,7 +419,7 @@ int WebSocketClient::disconnect() { this->ws.reset(); } } catch (std::exception &e) { - spdlog::debug("websocket disconnect failed: {}", e.what()); + candy::logger().debug(Poco::format("websocket disconnect failed: %s", std::string(e.what()))); } return 0; } diff --git a/candy/src/websocket/message.cc b/candy/src/websocket/message.cc index 83320262..e9138e85 100644 --- a/candy/src/websocket/message.cc +++ b/candy/src/websocket/message.cc @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT #include "websocket/message.h" +#include "utils/log.h" #include "utils/time.h" +#include #include namespace candy { @@ -24,7 +26,7 @@ bool Auth::check(const std::string &password) { int64_t localTime = unixTime(); int64_t remoteTime = ntoh(this->timestamp); if (std::abs(localTime - remoteTime) > 300) { - spdlog::warn("auth header timestamp check failed: server {} client {}", localTime, remoteTime); + candy::logger().warning(Poco::format("auth header timestamp check failed: server %Ld client %Ld", localTime, remoteTime)); } uint8_t reported[SHA256_DIGEST_LENGTH]; @@ -33,7 +35,7 @@ bool Auth::check(const std::string &password) { updateHash(password); if (std::memcmp(reported, this->hash, SHA256_DIGEST_LENGTH)) { - spdlog::warn("auth header hash check failed"); + candy::logger().warning("auth header hash check failed"); return false; } return true; @@ -60,7 +62,8 @@ bool ExptTun::check(const std::string &password) { int64_t localTime = unixTime(); int64_t remoteTime = ntoh(this->timestamp); if (std::abs(localTime - remoteTime) > 300) { - spdlog::warn("expected address header timestamp check failed: server {} client {}", localTime, remoteTime); + candy::logger().warning( + Poco::format("expected address header timestamp check failed: server %Ld client %Ld", localTime, remoteTime)); } uint8_t reported[SHA256_DIGEST_LENGTH]; @@ -69,7 +72,7 @@ bool ExptTun::check(const std::string &password) { updateHash(password); if (std::memcmp(reported, this->hash, SHA256_DIGEST_LENGTH)) { - spdlog::warn("expected address header hash check failed"); + candy::logger().warning("expected address header hash check failed"); return false; } return true; @@ -101,7 +104,8 @@ bool VMac::check(const std::string &password) { int64_t localTime = unixTime(); int64_t remoteTime = ntoh(this->timestamp); if (std::abs(localTime - remoteTime) > 300) { - spdlog::warn("vmac message timestamp check failed: server {} client {}", localTime, remoteTime); + candy::logger().warning( + Poco::format("vmac message timestamp check failed: server %Ld client %Ld", localTime, remoteTime)); } uint8_t reported[SHA256_DIGEST_LENGTH]; @@ -110,7 +114,7 @@ bool VMac::check(const std::string &password) { updateHash(password); if (std::memcmp(reported, this->hash, SHA256_DIGEST_LENGTH)) { - spdlog::warn("vmac message hash check failed"); + candy::logger().warning("vmac message hash check failed"); return false; } return true; diff --git a/candy/src/websocket/server.cc b/candy/src/websocket/server.cc index 459a20ec..6bfb7325 100644 --- a/candy/src/websocket/server.cc +++ b/candy/src/websocket/server.cc @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT #include "websocket/server.h" #include "core/net.h" +#include "utils/hex.h" +#include "utils/log.h" #include "utils/time.h" #include "websocket/message.h" +#include #include #include #include @@ -16,8 +19,6 @@ #include #include #include -#include -#include #include /** @@ -72,14 +73,14 @@ int WebSocketServer::setWebSocket(const std::string &uri) { try { Poco::URI parser(uri); if (parser.getScheme() != "ws") { - spdlog::critical("websocket server only support ws"); + candy::logger().fatal("websocket server only support ws"); return -1; } this->host = parser.getHost(); this->port = parser.getPort(); return 0; } catch (std::exception &e) { - spdlog::critical("invalid websocket uri: {}: {}", uri, e.what()); + candy::logger().fatal(Poco::format("invalid websocket uri: %s: %s", uri, std::string(e.what()))); return -1; } } @@ -108,20 +109,21 @@ int WebSocketServer::setSdwan(const std::string &sdwan) { std::stringstream ss(route); // dev if (!std::getline(ss, addr, ',') || rt.dev.fromCidr(addr) || rt.dev.Host() != rt.dev.Net()) { - spdlog::critical("invalid route device: {}", route); + candy::logger().fatal(Poco::format("invalid route device: %s", route)); return -1; } // dst if (!std::getline(ss, addr, ',') || rt.dst.fromCidr(addr) || rt.dst.Host() != rt.dst.Net()) { - spdlog::critical("invalid route dest: {}", route); + candy::logger().fatal(Poco::format("invalid route dest: %s", route)); return -1; } // next if (!std::getline(ss, addr, ',') || rt.next.fromString(addr)) { - spdlog::critical("invalid route nexthop: {}", route); + candy::logger().fatal(Poco::format("invalid route nexthop: %s", route)); return -1; } - spdlog::info("route: dev={} dst={} next={}", rt.dev.toCidr(), rt.dst.toCidr(), rt.next.toString()); + candy::logger().information( + Poco::format("route: dev=%s dst=%s next=%s", rt.dev.toCidr(), rt.dst.toCidr(), rt.next.toString())); this->routes.push_back(rt); } return 0; @@ -170,14 +172,14 @@ void WebSocketServer::handleMsg(WsCtx &ctx) { void WebSocketServer::handleAuthMsg(WsCtx &ctx) { if (ctx.buffer.length() < sizeof(WsMsg::Auth)) { - spdlog::warn("invalid auth message: len {}", ctx.buffer.length()); + candy::logger().warning(Poco::format("invalid auth message: len %zu", ctx.buffer.length())); ctx.status = -1; return; } WsMsg::Auth *header = (WsMsg::Auth *)ctx.buffer.data(); if (!header->check(this->password)) { - spdlog::warn("auth header check failed: buffer {:n}", spdlog::to_hex(ctx.buffer)); + candy::logger().warning(Poco::format("auth header check failed: buffer %s", to_hex(ctx.buffer))); ctx.status = -1; return; } @@ -189,9 +191,9 @@ void WebSocketServer::handleAuthMsg(WsCtx &ctx) { auto it = ipCtxMap.find(header->ip); if (it != ipCtxMap.end()) { it->second->status = -1; - spdlog::info("reconnect: {}", it->second->ip.toString()); + candy::logger().information(Poco::format("reconnect: %s", it->second->ip.toString())); } else { - spdlog::info("connect: {}", ctx.ip.toString()); + candy::logger().information(Poco::format("connect: %s", ctx.ip.toString())); } ipCtxMap[header->ip] = &ctx; } @@ -201,13 +203,13 @@ void WebSocketServer::handleAuthMsg(WsCtx &ctx) { void WebSocketServer::handleForwardMsg(WsCtx &ctx) { if (ctx.ip.empty()) { - spdlog::debug("unauthorized forward websocket client"); + candy::logger().debug("unauthorized forward websocket client"); ctx.status = -1; return; } if (ctx.buffer.length() < sizeof(WsMsg::Forward)) { - spdlog::debug("invalid forawrd message: len {}", ctx.buffer.length()); + candy::logger().debug(Poco::format("invalid forawrd message: len %zu", ctx.buffer.length())); ctx.status = -1; return; } @@ -257,30 +259,31 @@ void WebSocketServer::handleForwardMsg(WsCtx &ctx) { return; } - spdlog::debug("forward failed: source {} dest {}", header->iph.saddr.toString(), header->iph.daddr.toString()); + candy::logger().debug( + Poco::format("forward failed: source %s dest %s", header->iph.saddr.toString(), header->iph.daddr.toString())); return; } void WebSocketServer::handleExptTunMsg(WsCtx &ctx) { if (ctx.buffer.length() < sizeof(WsMsg::ExptTun)) { - spdlog::warn("invalid dynamic address message: len {}", ctx.buffer.length()); + candy::logger().warning(Poco::format("invalid dynamic address message: len %zu", ctx.buffer.length())); ctx.status = -1; return; } WsMsg::ExptTun *header = (WsMsg::ExptTun *)ctx.buffer.data(); if (!header->check(this->password)) { - spdlog::warn("dynamic address header check failed: buffer {:n}", spdlog::to_hex(ctx.buffer)); + candy::logger().warning(Poco::format("dynamic address header check failed: buffer %s", to_hex(ctx.buffer))); ctx.status = -1; return; } if (this->dhcp.empty()) { - spdlog::warn("unable to allocate dynamic address"); + candy::logger().warning("unable to allocate dynamic address"); ctx.status = -1; return; } Address exptTun; if (exptTun.fromCidr(header->cidr)) { - spdlog::warn("dynamic address header cidr invalid: buffer {:n}", spdlog::to_hex(ctx.buffer)); + candy::logger().warning(Poco::format("dynamic address header cidr invalid: buffer %s", to_hex(ctx.buffer))); ctx.status = -1; return; } @@ -302,7 +305,7 @@ void WebSocketServer::handleExptTunMsg(WsCtx &ctx) { do { exptTun = exptTun.Next(); if (exptTun.Host() == this->dhcp.Host()) { - spdlog::warn("all addresses in the network are assigned"); + candy::logger().warning("all addresses in the network are assigned"); ctx.status = -1; return; } @@ -317,27 +320,29 @@ void WebSocketServer::handleExptTunMsg(WsCtx &ctx) { void WebSocketServer::handleUdp4ConnMsg(WsCtx &ctx) { if (ctx.ip.empty()) { - spdlog::debug("unauthorized peer websocket client"); + candy::logger().debug("unauthorized peer websocket client"); ctx.status = -1; return; } if (ctx.buffer.length() < sizeof(WsMsg::Conn)) { - spdlog::warn("invalid peer conn message: len {}", ctx.buffer.length()); + candy::logger().warning(Poco::format("invalid peer conn message: len %zu", ctx.buffer.length())); ctx.status = -1; return; } WsMsg::Conn *header = (WsMsg::Conn *)ctx.buffer.data(); if (ctx.ip != header->src) { - spdlog::debug("peer source address does not match: auth {} source {}", ctx.ip.toString(), header->src.toString()); + candy::logger().debug( + Poco::format("peer source address does not match: auth %s source %s", ctx.ip.toString(), header->src.toString())); ctx.status = -1; return; } std::shared_lock lock(this->ipCtxMutex); auto it = this->ipCtxMap.find(header->dst); if (it == this->ipCtxMap.end()) { - spdlog::debug("peer dest address not logged in: source {} dst {}", header->src.toString(), header->dst.toString()); + candy::logger().debug( + Poco::format("peer dest address not logged in: source %s dst %s", header->src.toString(), header->dst.toString())); return; } it->second->sendFrame(ctx.buffer); @@ -346,14 +351,14 @@ void WebSocketServer::handleUdp4ConnMsg(WsCtx &ctx) { void WebSocketServer::handleVMacMsg(WsCtx &ctx) { if (ctx.buffer.length() < sizeof(WsMsg::VMac)) { - spdlog::warn("invalid vmac message: len {}", ctx.buffer.length()); + candy::logger().warning(Poco::format("invalid vmac message: len %zu", ctx.buffer.length())); ctx.status = -1; return; } WsMsg::VMac *header = (WsMsg::VMac *)ctx.buffer.data(); if (!header->check(this->password)) { - spdlog::warn("vmac message check failed: buffer {:n}", spdlog::to_hex(ctx.buffer)); + candy::logger().warning(Poco::format("vmac message check failed: buffer %s", to_hex(ctx.buffer))); ctx.status = -1; return; } @@ -364,20 +369,21 @@ void WebSocketServer::handleVMacMsg(WsCtx &ctx) { void WebSocketServer::handleDiscoveryMsg(WsCtx &ctx) { if (ctx.ip.empty()) { - spdlog::debug("unauthorized discovery websocket client"); + candy::logger().debug("unauthorized discovery websocket client"); ctx.status = -1; return; } if (ctx.buffer.length() < sizeof(WsMsg::Discovery)) { - spdlog::debug("invalid discovery message: len {}", ctx.buffer.length()); + candy::logger().debug(Poco::format("invalid discovery message: len %zu", ctx.buffer.length())); ctx.status = -1; return; } WsMsg::Discovery *header = (WsMsg::Discovery *)ctx.buffer.data(); if (ctx.ip != header->src) { - spdlog::debug("discovery source address does not match: auth {} source {}", ctx.ip.toString(), header->src.toString()); + candy::logger().debug(Poco::format("discovery source address does not match: auth %s source %s", ctx.ip.toString(), + header->src.toString())); ctx.status = -1; return; } @@ -400,13 +406,13 @@ void WebSocketServer::handleDiscoveryMsg(WsCtx &ctx) { void WebSocketServer::HandleGeneralMsg(WsCtx &ctx) { if (ctx.ip.empty()) { - spdlog::debug("unauthorized general websocket client"); + candy::logger().debug("unauthorized general websocket client"); ctx.status = -1; return; } if (ctx.buffer.length() < sizeof(WsMsg::General)) { - spdlog::debug("invalid general message: len {}", ctx.buffer.length()); + candy::logger().debug(Poco::format("invalid general message: len %zu", ctx.buffer.length())); ctx.status = -1; return; } @@ -414,7 +420,8 @@ void WebSocketServer::HandleGeneralMsg(WsCtx &ctx) { WsMsg::General *header = (WsMsg::General *)ctx.buffer.data(); if (ctx.ip != header->src) { - spdlog::debug("general source address does not match: auth {} source {}", ctx.ip.toString(), header->src.toString()); + candy::logger().debug( + Poco::format("general source address does not match: auth %s source %s", ctx.ip.toString(), header->src.toString())); ctx.status = -1; return; } @@ -474,10 +481,10 @@ int WebSocketServer::listen() { WebSocketHandler wsHandler = [this](Poco::Net::WebSocket &ws) { handleWebsocket(ws); }; this->httpServer = std::make_shared(new HTTPRequestHandlerFactory(wsHandler), socket, params); this->httpServer->start(); - spdlog::info("listen on: {}:{}", host, port); + candy::logger().information(Poco::format("listen on: %s:%d", host, port)); return 0; } catch (std::exception &e) { - spdlog::critical("listen failed: {}", e.what()); + candy::logger().fatal(Poco::format("listen failed: %s", std::string(e.what()))); return -1; } } @@ -523,7 +530,7 @@ void WebSocketServer::handleWebsocket(Poco::Net::WebSocket &ws) { continue; } catch (std::exception &e) { // 未知异常,退出这个客户端 - spdlog::debug("handle websocket failed: {}", e.what()); + candy::logger().debug(Poco::format("handle websocket failed: %s", std::string(e.what()))); break; } } @@ -533,7 +540,7 @@ void WebSocketServer::handleWebsocket(Poco::Net::WebSocket &ws) { auto it = ipCtxMap.find(ctx.ip); if (it != ipCtxMap.end() && it->second == &ctx) { ipCtxMap.erase(it); - spdlog::info("disconnect: {}", ctx.ip.toString()); + candy::logger().information(Poco::format("disconnect: %s", ctx.ip.toString())); } } } diff --git a/candy/src/websocket/server.h b/candy/src/websocket/server.h index 945b2767..d6cfec0e 100644 --- a/candy/src/websocket/server.h +++ b/candy/src/websocket/server.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace candy { diff --git a/dockerfile b/dockerfile index 9147d600..b70f7d75 100644 --- a/dockerfile +++ b/dockerfile @@ -1,9 +1,9 @@ FROM alpine AS base RUN apk update -RUN apk add spdlog openssl poco +RUN apk add openssl poco FROM base AS build -RUN apk add git cmake ninja pkgconf g++ spdlog-dev openssl-dev poco-dev linux-headers +RUN apk add git cmake ninja pkgconf g++ openssl-dev poco-dev linux-headers COPY . candy RUN cd candy && cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo && cmake --build build && cmake --install build