diff --git a/.gitignore b/.gitignore index 9e7c8b5..a4e834d 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,6 @@ Thumbs.db # Built data for installer creation installer/packages/net.candymade.nyatrace/data/ + +# macOS build +build/ diff --git a/ipdb.h b/ipdb.h index c34ff90..7afe4f7 100644 --- a/ipdb.h +++ b/ipdb.h @@ -3,7 +3,7 @@ #include -#include "libmaxminddb\maxminddb.h" +#include "libmaxminddb/maxminddb.h" // IPDB 类:操作基于 MMDB 的数据读取工作, // 以后可能会改成基于 web 请求的格式以优化封装体积 diff --git a/nyatrace.pro b/nyatrace.pro index 046f761..58cc7ae 100644 --- a/nyatrace.pro +++ b/nyatrace.pro @@ -16,8 +16,8 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs depr SOURCES += \ configs.cpp \ ipdb.cpp \ - libmaxminddb\data-pool.c \ - libmaxminddb\maxminddb.c \ + libmaxminddb/data-pool.c \ + libmaxminddb/maxminddb.c \ nyatrace_about.cpp \ nyatrace_configs.cpp \ nyatrace_gui.cpp \ @@ -35,10 +35,10 @@ HEADERS += \ data-pool.h \ ipdb.h \ ipdb_settings.h \ - libmaxminddb\data-pool.h \ - libmaxminddb\maxminddb-compat-util.h \ - libmaxminddb\maxminddb.h \ - libmaxminddb\maxminddb_config.h \ + libmaxminddb/data-pool.h \ + libmaxminddb/maxminddb-compat-util.h \ + libmaxminddb/maxminddb.h \ + libmaxminddb/maxminddb_config.h \ mode.h \ nyatrace_about.h \ nyatrace_configs.h \ diff --git a/nyatrace_gui.h b/nyatrace_gui.h index b876596..8d1a84f 100644 --- a/nyatrace_gui.h +++ b/nyatrace_gui.h @@ -40,9 +40,18 @@ private slots: // 界面 UI Ui::NyaTraceGUI *ui; +#ifdef Q_OS_WIN + // 一种数据结构。这个结构被用来存储被 WSAStartup 函数调用后返回的 Windows Sockets 数据 WSADATA wsa; +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + // 用于路由追踪的子线程 TracingCore * tracingThread; diff --git a/resolve_core.cpp b/resolve_core.cpp index 784859b..ffeba76 100644 --- a/resolve_core.cpp +++ b/resolve_core.cpp @@ -23,7 +23,7 @@ void ResolveCore::run() { sockaddr_storage targetIPAddress; // 用于存储目标地址 // 清空目标地址 - ZeroMemory(&targetIPAddress, sizeof(sockaddr_storage)); + memset(&targetIPAddress, 0, sizeof(sockaddr_storage)); if (ParseIPAddress(hostCharStr, targetIPAddress)) { // 解析成功,更新状态 @@ -64,7 +64,36 @@ void ResolveCore::run() { } } else { // 解析失败 + +#ifdef Q_OS_WIN + auto err = WSAGetLastError(); + +#endif +#ifdef Q_OS_UNIX + + QString err; + + switch (h_errno) { + case HOST_NOT_FOUND: + err = "找不到主机"; + break; + case NO_ADDRESS: + err = "没有查询到地址"; + break; + case NO_RECOVERY: + err = "无法恢复的解析错误"; + break; + case TRY_AGAIN: + err = "名称解析暂时不可用"; + break; + default: + err = "未知问题"; + break; + } + +#endif + qWarning() << "[Resolve Core]" << "Failed to resolve host with error: " << err; emit setMessage(QString("主机名解析失败,错误代码: %1 。").arg(err)); @@ -81,7 +110,7 @@ void ResolveCore::GetInfo(int id, sockaddr_storage * targetIPAddress) { // 查询 IP 对应的信息 char printIPAddress[INET6_ADDRSTRLEN]; // INET6_ADDRSTRLEN 大于 INET_ADDRSTRLEN ,所以可以兼容(虽然可能有点浪费) - ZeroMemory(printIPAddress, sizeof(printIPAddress)); + memset(printIPAddress, 0, sizeof(printIPAddress)); PrintIPAddress(targetIPAddress, printIPAddress); // 准备从 City 数据库中查询结果 diff --git a/tracing_core.cpp b/tracing_core.cpp index 206fd18..ede405d 100644 --- a/tracing_core.cpp +++ b/tracing_core.cpp @@ -5,9 +5,18 @@ #include "tracing_core.h" #include "tracing_utils.h" +#ifdef Q_OS_WIN + #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "ws2_32.lib") +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + /** * TracingCore * 执行追踪程序的核心,涉及到基础数据的转化、追踪线程的管理和对 UI 状态的更新 @@ -18,6 +27,8 @@ TracingCore::TracingCore() { qDebug() << "[Trace Core]" << "Tracing Core start constructing..."; +#ifdef Q_OS_WIN + // 载入依赖的动态链接库 hIcmpDll = LoadLibraryA("IPHLPAPI.DLL"); if (hIcmpDll == NULL) { @@ -46,6 +57,13 @@ TracingCore::TracingCore() { << "Failed to open ICMP6 handle"; } +#endif +#ifdef Q_OS_UNIX + + // TODO + +#endif + // 新建一个线程池 tracingPool = new QThreadPool; @@ -62,12 +80,21 @@ TracingCore::~TracingCore() { // 销毁线程池 delete tracingPool; +#ifdef Q_OS_WIN + // 回收资源 IcmpCloseHandle(hIcmp); IcmpCloseHandle(hIcmp6); // 释放动态链接库 FreeLibrary(hIcmpDll); + +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif } void TracingCore::run() { @@ -84,10 +111,10 @@ void TracingCore::run() { sockaddr_storage targetIPAddress; // 用于存储目标地址 // 清空目标地址 - ZeroMemory(&targetIPAddress, sizeof(sockaddr_storage)); + memset(&targetIPAddress, 0, sizeof(sockaddr_storage)); char printIPAddress[INET6_ADDRSTRLEN]; // INET6_ADDRSTRLEN 大于 INET_ADDRSTRLEN ,所以可以兼容(虽然可能有点浪费) - ZeroMemory(printIPAddress, sizeof(printIPAddress)); + memset(printIPAddress, 0, sizeof(printIPAddress)); if (ParseIPAddress(hostCharStr, targetIPAddress)) { // 解析成功,更新状态 @@ -115,7 +142,7 @@ void TracingCore::run() { sockaddr_storage sourceIPAddress; // 清空当前地址 - ZeroMemory(&sourceIPAddress, sizeof(sockaddr_storage)); + memset(&sourceIPAddress, 0, sizeof(sockaddr_storage)); // 相同传输协议栈 sourceIPAddress.ss_family = targetIPAddress.ss_family; @@ -125,7 +152,18 @@ void TracingCore::run() { case AF_INET: qDebug() << "[Trace Core]" << "Binding any outbound IPv4 address"; + +#ifdef Q_OS_WIN + ((sockaddr_in*)&sourceIPAddress)->sin_addr = in4addr_any; + +#endif +#ifdef Q_OS_UNIX + + ((sockaddr_in*)&sourceIPAddress)->sin_addr.s_addr = htonl(INADDR_ANY); + +#endif + break; case AF_INET6: qDebug() << "[Trace Core]" @@ -144,8 +182,19 @@ void TracingCore::run() { workers[i]->iTTL = i + 1; workers[i]->sourceIPAddress = &sourceIPAddress; workers[i]->targetIPAddress = &targetIPAddress; + +#ifdef Q_OS_WIN + workers[i]->hIcmp = hIcmp; workers[i]->hIcmp6 = hIcmp6; + +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + workers[i]->ipdb = ipdb; connect(workers[i], &TracingWorker::reportIPAndTimeConsumption, this, [=](const int hop, const unsigned long timeConsumption, const QString & ipAddress, const bool isValid, const bool isTargetHost) { diff --git a/tracing_core.h b/tracing_core.h index c2a70bd..a0d578e 100644 --- a/tracing_core.h +++ b/tracing_core.h @@ -21,6 +21,8 @@ class TracingCore : public QThread private: // 私有变量区 +#ifdef Q_OS_WIN + // 定义动态链接库 HMODULE hIcmpDll; @@ -33,6 +35,13 @@ class TracingCore : public QThread HANDLE hIcmp; HANDLE hIcmp6; +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + // 追踪线程的线程池 QThreadPool * tracingPool; diff --git a/tracing_defs.h b/tracing_defs.h index 83bdebb..a15a8d8 100644 --- a/tracing_defs.h +++ b/tracing_defs.h @@ -1,6 +1,10 @@ #ifndef TRACING_DEFS_H #define TRACING_DEFS_H +#include + +#ifdef Q_OS_WIN + #include // 类型定义 #include #include @@ -9,6 +13,27 @@ typedef HANDLE (WINAPI *lpIcmpCreateFile )(VOID); typedef BOOL (WINAPI *lpIcmpCloseHandle)(HANDLE IcmpHandle); +#endif +#ifdef Q_OS_UNIX + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#endif + // 常量定义 const int DEF_ICMP_DATA_SIZE = 32; // 默认ICMP数据部分长度 diff --git a/tracing_utils.cpp b/tracing_utils.cpp index a556eb6..2abc766 100644 --- a/tracing_utils.cpp +++ b/tracing_utils.cpp @@ -6,7 +6,7 @@ addrinfo * ResolveAllAddress(const char * hostname) { addrinfo * resolveResult = NULL; addrinfo resolveHints; - ZeroMemory(&resolveHints, sizeof(resolveHints)); + memset(&resolveHints, 0, sizeof(resolveHints)); resolveHints.ai_family = AF_UNSPEC; resolveHints.ai_socktype = SOCK_STREAM; @@ -21,8 +21,8 @@ addrinfo * ResolveAllAddress(const char * hostname) { bool ParseIPAddress(const char * ipStr, sockaddr_storage & targetIPAddress) { - IN_ADDR addr4; // IPv4 地址的暂存区域 - IN6_ADDR addr6; // IPv6 地址的暂存区域 + in_addr addr4; // IPv4 地址的暂存区域 + in6_addr addr6; // IPv6 地址的暂存区域 if (inet_pton(AF_INET, ipStr, &addr4) != 0) { // 输入是 IPv4 地址 diff --git a/tracing_utils.h b/tracing_utils.h index e02b14b..e371334 100644 --- a/tracing_utils.h +++ b/tracing_utils.h @@ -1,9 +1,19 @@ #ifndef TRACING_UTILS_H #define TRACING_UTILS_H -#include #include "tracing_defs.h" +#ifdef Q_OS_WIN + +#include + +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + addrinfo * ResolveAllAddress(const char * hostname); bool ParseIPAddress(const char * ipStr, sockaddr_storage & targetIPAddress); bool PrintIPAddress(sockaddr_storage * targetIPAddress, char * printIPAddress); diff --git a/tracing_worker.cpp b/tracing_worker.cpp index 8fe4d9e..7d4b3b8 100644 --- a/tracing_worker.cpp +++ b/tracing_worker.cpp @@ -15,7 +15,7 @@ TracingWorker::TracingWorker() { // 分配当前跳地址的存储空间 currentHopIPAddress = new sockaddr_storage; - ZeroMemory(currentHopIPAddress, sizeof(sockaddr_storage)); + memset(currentHopIPAddress, 0, sizeof(sockaddr_storage)); } @@ -69,6 +69,8 @@ void TracingWorker::run() { void TracingWorker::GetIPv4() { // 第一步:追踪 +#ifdef Q_OS_WIN + // ICMP 包发送缓冲区和接收缓冲区 IP_OPTION_INFORMATION IpOption; char SendData[DEF_ICMP_DATA_SIZE]; @@ -78,10 +80,17 @@ void TracingWorker::GetIPv4() { PICMP_ECHO_REPLY pEchoReply; // 初始化内存区间 - ZeroMemory(&IpOption,sizeof(IP_OPTION_INFORMATION)); - ZeroMemory(SendData, sizeof(SendData)); + memset(&IpOption, 0,sizeof(IP_OPTION_INFORMATION)); + memset(SendData, 0, sizeof(SendData)); pEchoReply = (PICMP_ECHO_REPLY)ReplyBuf; +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + // 设置 TTL IpOption.Ttl = iTTL; @@ -95,12 +104,22 @@ void TracingWorker::GetIPv4() { // 发送数据报并等待消息到达 if ( + +#ifdef Q_OS_WIN IcmpSendEcho2( hIcmp, NULL, NULL, NULL, ((sockaddr_in*)targetIPAddress)->sin_addr.s_addr, SendData, sizeof (SendData), &IpOption, ReplyBuf, sizeof(ReplyBuf), gCfg->GetTraceTimeout() ) != 0 + +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + ) { // 得到返回 ((sockaddr_in*)currentHopIPAddress)->sin_addr.s_addr = pEchoReply->Address; @@ -110,9 +129,21 @@ void TracingWorker::GetIPv4() { break; } else { // 出现错误 + +#ifdef Q_OS_WIN + + auto err = GetLastError(); + +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + qWarning() << "[Trace Worker]" << "ICMP send echo failed with error: " - << GetLastError(); + << err; // 这里可以无视条件回报,因为失败的请求一定不会被认为是目标主机 timeoutCount++; @@ -151,8 +182,8 @@ void TracingWorker::GetIPv6() { PICMPV6_ECHO_REPLY pEchoReply; // 初始化内存区间 - ZeroMemory(&IpOption,sizeof(IP_OPTION_INFORMATION)); - ZeroMemory(SendData, sizeof(SendData)); + memset(&IpOption, 0,sizeof(IP_OPTION_INFORMATION)); + memset(SendData, 0, sizeof(SendData)); pEchoReply = (PICMPV6_ECHO_REPLY)ReplyBuf; // 设置 TTL diff --git a/tracing_worker.h b/tracing_worker.h index 7dc05c8..dd04529 100644 --- a/tracing_worker.h +++ b/tracing_worker.h @@ -25,10 +25,19 @@ class TracingWorker : public QObject, public QRunnable // 目标主机地址 sockaddr_storage * targetIPAddress; +#ifdef Q_OS_WIN + // 定义动态链接库句柄 HANDLE hIcmp; HANDLE hIcmp6; +#endif +#ifdef Q_OS_UNIX + +// TODO + +#endif + // 用于读取 IP 对应数据的类操作接口 IPDB * ipdb;