Skip to content

Commit

Permalink
Merge pull request #10 from o8x/core
Browse files Browse the repository at this point in the history
Core
  • Loading branch information
o8x authored Aug 23, 2024
2 parents 6d0019b + 5dbad7a commit bd1f39d
Show file tree
Hide file tree
Showing 13 changed files with 514 additions and 150 deletions.
17 changes: 15 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_VERBOSE_MAKEFILE ON)

# 无法自动加载时,设置 QT 目录
#set(Qt6_DIR $ENV{HOME}/Qt6/6.7.2/macos/lib/cmake/Qt6)

Expand Down Expand Up @@ -49,15 +51,26 @@ add_executable(${PROJECT_NAME}
src/trayicon.cpp
include/conf.h
src/conf.cpp
include/dissectors/icmp.h
src/dissectors/icmp.cpp
)

if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUG_BUILD)
endif ()

if (CMAKE_BUILD_TYPE STREQUAL "Release")
# 为 release 模式设置优化选型
# -O3:开启最高级别的优化
# -march=native:针对构建机器的本地架构进行优化(这可能会生成仅在类似机器上运行良好的代码)
# -ffast-math:允许编译器在浮点数运算中使用可能违反 IEEE 标准的优化,能显著提高执行速度,但可能会破坏浮点数的精确度或兼容性
# -DNDEBUG:定义 NDEBUG 宏,这通常会关闭 assert() 语句(如果你在使用它们的话)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -march=native -ffast-math -DNDEBUG")
endif ()

# qt core
find_package(Qt6 COMPONENTS Core Gui Widgets Charts PrintSupport REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt::Core Qt::Gui Qt::Charts Qt::Widgets Qt::PrintSupport)
find_package(Qt6 COMPONENTS Core Gui Widgets PrintSupport REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt::Core Qt::Gui Qt::Widgets Qt::PrintSupport)
# glog
find_package(glog CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE glog::glog)
Expand Down
2 changes: 2 additions & 0 deletions hack/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ cd ..

mv ${CMAKE_BUILD_DIR}/*.dmg .
rm -rf ${CMAKE_BUILD_DIR}

echo -e "use Console.app to watch WireDolphin Log"
30 changes: 30 additions & 0 deletions include/dissectors/icmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#define ICMP_TYPE_ECHO_REQUEST 8
#define ICMP_TYPE_ECHO_REPLY 0
#define ICMP_TYPE_UNREACHABLE 3
#define ICMP_TYPE_SOURCE_CLOSED 4
#include <iostream>

using namespace std;

/**
* +0------7-------15---------------31
* | Type | Code | Checksum |
* +--------------------------------+
* | Message Body |
* | (Variable length) |
* +--------------------------------+
*/
typedef struct icmp_header {
u_char type;
u_char code;
} ICMP_HEADER;

// Echo Request/Reply
typedef struct icmp_echo {
icmp_header icmp_header;
u_char identifier[2];
u_char seq_number[2];
// char data[1500]; // 数据不定长,但不会超过MTU
} ICMP_ECHO;
11 changes: 6 additions & 5 deletions include/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,26 @@ class MainWindow : public QMainWindow {
explicit MainWindow(QWidget* parent = nullptr);
~MainWindow() override;
void changeInterfaceIndex(int index) const;
void freePackets();
void captureInterfaceStarted(string name, string message);
void captureInterfaceStopped(string name, string message) const;
void captureInterfaceStarted(packetsource_state state);
void captureInterfaceStopped(packetsource_state state) const;
void resetCapture();
void acceptPacket(int index, Packet* p) const;
void initSlots();
void loadOfflineFile() const;
void tableItemClicked(const QModelIndex& index);
void toggleStartBtn();
void initWidgets();
void updateCaptureStatusLabel() const;
void initInterfaceList();
void about();
void activateStatsWindow() const;
void saveAsPcap();
void initMenus();
void updateMajorView(size_t, size_t) const;

private:
Ui::MainWindow* ui;
pcap_if_t* allDevs = nullptr;
PacketSource* packetSource;
vector<Packet*> packets;
bool captureStart = false;
QLabel* interfaceStatusLabel = new QLabel("", this);
QLabel* captureStatusLabel = new QLabel("", this);
Expand All @@ -71,6 +70,8 @@ class MainWindow : public QMainWindow {
QMenu* helpMenu = nullptr;
QMenu* windowMenu = nullptr;
QAction* loadFileAct = nullptr;
QAction* saveAct = nullptr;
QAction* dumpFilename = nullptr;
QAction* aboutAct = nullptr;
QAction* statsAct = nullptr;
QAction* aboutQtAct = nullptr;
Expand Down
6 changes: 4 additions & 2 deletions include/packet.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <iostream>
#include <pcap.h>
#include <string>
#include <vector>
Expand All @@ -23,13 +22,15 @@ class Packet {
int ip_version = 0;
u_short type_flag {};
u_char payload[2048] = {};
pcap_pkthdr* header = nullptr;
ipv4_header* ipv4 = nullptr;
ipv6_header* ipv6 = nullptr;
tcp_header* tcp = nullptr;
arp_header* arp = nullptr;
udp_header* udp = nullptr;
tcp_flags* flags = nullptr;
string time;
timeval* time_ts = nullptr;
string link_src;
string link_dst;
string host_src;
Expand Down Expand Up @@ -62,6 +63,7 @@ class Packet {
[[nodiscard]] vector<int> get_color() const;
[[nodiscard]] arp_header* get_arp() const;
[[nodiscard]] udp_header* get_udp() const;
[[nodiscard]] pcap_pkthdr* get_header() const;
void set_udp(udp_header* udp);
void set_arp(arp_header* arp);
void set_port_src(int port_src);
Expand All @@ -79,7 +81,7 @@ class Packet {
void set_type(const string& type);
void set_len(int len, int caplen);
void set_info(const string& info);
void set_time(const string& time);
void set_header(pcap_pkthdr* hdr);
void set_type_flag(u_short);
void set_payload(const u_char** pkt_data);
};
102 changes: 88 additions & 14 deletions include/packetsource.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,107 @@
#include "packet.h"
#include <QThread>
#include <pcap.h>
#include <queue>

class PacketSource final : public QThread {
// 更新表格超时周期
#define DEFAULT_QUEUE_UPDATE_TIMEOUT_MS 10
// 数字越小,小流量更新频率越快,实时性越高
#define DEFAULT_PERIOD_AVERAGE 5
// 10ms 内更新 100 条,一秒就会更新1万条,表格可能来不及更新就会卡死
#define AVERAGE_PERIOD(v) \
(v > 100 ? v * 5 : (v > 50 ? v * 3 : (v > DEFAULT_PERIOD_AVERAGE ? v : DEFAULT_PERIOD_AVERAGE)))

typedef struct packetsource_state {
string interface_name;
string state;
string dump_filename;
} PACKETSOURCE_STATE;

class PacketSource final : public QObject {
Q_OBJECT

vector<Packet*>* packetsPtr;
/**
* 全局互斥锁
*/
std::mutex mtx;
/**
* 包队列
* 用于在捕获线程和渲染线程之间转移包
* 捕获后的包会先到该队列,每隔一段时间会被消费和传递到UI线程进行表格渲染
*/
std::queue<Packet*> bridge;
/*
* 存储捕获的所有的包
* 要在开始或重置时清空,否则将内存泄漏
*/
std::vector<Packet*> history;
/*
* 记录队列上一次被清空的时间
*/
std::chrono::steady_clock::time_point last_access;
/**
* 时间段内捕获的包的平均数
* 做到推送的行数不恒定,流量越大推送频率越低,但一次推送的数量越多
*/
int period_average = DEFAULT_PERIOD_AVERAGE;
/**
* 填充桥的线程
*/
std::thread fill_thread;
/**
* 消费桥的线程
* 都在析构和停止捕获时进行 join
*/
std::thread consume_thread;
/**
* 捕获的接口的 pcap 实例
*/
pcap_t* interface = nullptr;
/**
* 捕获的接口的设备实例,目前只是从里面取出名字,没有其他用途
*/
pcap_if_t* device = nullptr;
/**
* 当前一次捕获到的包暂存文件的文件名
* 当启动捕获时,该文件会被删除和重建
* 当选择 Menu 中的 Dump File 时将会被移动到用户选择的目录
*/
string dump_filename;
/**
* pcap 的写入 pcap 文件的句柄
*/
pcap_dumper_t* dump_handler = nullptr;
/**
* 如果当前并不是实时捕获,而是打开了一个文件,就会填充改文件名
*/
string filename;
/**
* 控制是否继续接收和处理包
*/
bool running = false;
void run() override;

void capture_packet();
void dump_flush(const pcap_pkthdr*, const u_char*) const;
static int parse_header(const u_char**, Packet*& p);
void consume_queue();

signals:
void listen_started(std::string name, std::string message) const;
void listen_stopped(std::string name, std::string message) const;
void listen_started(PACKETSOURCE_STATE) const;
void listen_stopped(PACKETSOURCE_STATE) const;
void captured(size_t, Packet*);
void capture_cycle_flush(size_t, size_t);

public:
explicit PacketSource(QObject* parent = nullptr, vector<Packet*>* packets = nullptr)
: QThread(parent)
, packetsPtr(packets)
{
}
explicit PacketSource();
~PacketSource();

void init(pcap_if_t* device, pcap_t* interface);
[[nodiscard]] string get_filename() const;
void free_wait();
void set_filename(const string& filename);
[[nodiscard]] pcap_t* get_interface() const;
void free();
void start_on_interface(pcap_if_t* device, pcap_t* interface);

[[nodiscard]] string get_filename() const;
[[nodiscard]] pcap_t* get_interface() const;void free_history();
[[nodiscard]] string get_dump_filename() const;
[[nodiscard]] size_t packet_count() const;
[[nodiscard]] Packet* peek(int index) const;
};
1 change: 1 addition & 0 deletions include/trayicon.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ class TrayIcon : public QWidget {
public:
explicit TrayIcon(QSystemTrayIcon* t, QWidget* wdi);
~TrayIcon();
void showMessage(const std::string& title, const std::string& message) const;
void onActivated(QSystemTrayIcon::ActivationReason reason) const;
};
12 changes: 11 additions & 1 deletion src/conf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,17 @@ void conf::create_core_config()
doc.InsertFirstChild(declaration);

auto logger = doc.NewElement("Logger");
logger->InsertNewChildElement("BaseDir")->SetText("../logs");

#ifdef __linux__
std::string logDir = "/var/log";
#elif __APPLE__
std::string home = QStandardPaths::standardLocations(QStandardPaths::HomeLocation)[0].toStdString();
std::string logDir = std::format("{}/Library/Logs/", home);
#else
std::string logDir = "../logs";
#endif

logger->InsertNewChildElement("BaseDir")->SetText(logDir.c_str());

auto* window = doc.NewElement("Window");
window->InsertNewChildElement("Width")->SetText(1700);
Expand Down
1 change: 1 addition & 0 deletions src/dissectors/icmp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "dissectors/icmp.h"
16 changes: 13 additions & 3 deletions src/packet/packet.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "packet.h"
#include <iostream>
#include "utils.h"

string Packet::get_link_src() const
{
Expand Down Expand Up @@ -72,9 +72,15 @@ void Packet::set_len(const int len, const int caplen)
return time;
}

void Packet::set_time(const string& time)
[[nodiscard]] pcap_pkthdr* Packet::get_header() const
{
this->time = time;
return header;
}

void Packet::set_header(pcap_pkthdr* hdr)
{
this->header = hdr;
this->time = format_timeval_to_string(hdr->ts);
}

void Packet::set_type_flag(u_short flag)
Expand Down Expand Up @@ -194,6 +200,10 @@ vector<int> Packet::get_color() const
return { 0, 250, 154 };
}

if (this->type == "ICMP") {
return { 211, 211, 211 };
}

if (this->flags != nullptr) {
/**
* 三次握手
Expand Down
Loading

0 comments on commit bd1f39d

Please sign in to comment.