diff options
Diffstat (limited to 'src/gui_main.cpp')
| -rw-r--r-- | src/gui_main.cpp | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/src/gui_main.cpp b/src/gui_main.cpp index 16ee769..8a7771a 100644 --- a/src/gui_main.cpp +++ b/src/gui_main.cpp @@ -23,6 +23,8 @@ #include <thread> #include "wireframe/capture_session.hpp" +#include "wireframe/net/tcp_reassembly.hpp" +#include "wireframe/packet_diagnostics.hpp" #include "wireframe/search.hpp" #include "wireframe/summarize.hpp" @@ -31,6 +33,11 @@ namespace { struct PacketRow { std::string summary; std::vector<unsigned char> data; + // -a only: computed once at consume time (reassembly needs + // in-order state across packets, unlike checksum status below, + // which is stateless and cheap enough to compute lazily when a row + // is selected instead of storing it on every row). + std::optional<std::string> reassembled_http; }; constexpr std::size_t kMaxRows = 5000; // cap memory; oldest rows scroll off @@ -52,7 +59,7 @@ struct SharedState { }; void consumer_loop(wireframe::CaptureSession& session, wireframe::CaptureQueue& queue, - SharedState& state) { + SharedState& state, wireframe::net::TcpReassembler* reassembler) { while (auto packet = queue.pop()) { std::span<const unsigned char> bytes{packet->data}; std::string summary = wireframe::summarize_packet(bytes, session.datalink()); @@ -62,8 +69,15 @@ void consumer_loop(wireframe::CaptureSession& session, wireframe::CaptureQueue& packet->original_len); } + std::optional<std::string> reassembled_http; + if (reassembler) { + reassembled_http = wireframe::reassembled_http_status(bytes, session.datalink(), + *reassembler); + } + std::lock_guard<std::mutex> lock(state.mutex); - state.rows.push_back({std::move(summary), std::move(packet->data)}); + state.rows.push_back({std::move(summary), std::move(packet->data), + std::move(reassembled_http)}); if (state.rows.size() > kMaxRows) state.rows.pop_front(); ++state.packet_count; } @@ -89,6 +103,11 @@ void print_usage(const char* argv0) { " -r <file> Replay a saved pcapng file instead of a live device\n" " -f <expr> Kernel-level capture filter (tcpdump/BPF syntax); also\n" " applies to what -w writes. Can't be combined with -r.\n" + " -c Show IPv4/TCP/UDP checksum validity for the selected packet.\n" + " Off by default - see the CLI's -h for why (checksum offload).\n" + " -a Reassemble TCP streams and show HTTP requests/responses\n" + " joined across segments for the selected packet, when its\n" + " segment contributed to one. In-order segments only.\n" " -h, --help Show this help and exit\n" "\n" "Examples:\n" @@ -109,6 +128,8 @@ int main(int argc, char** argv) { } wireframe::CaptureSessionOptions options; + bool enable_checksums = false; + bool enable_reassembly = false; for (int i = 1; i < argc; ++i) { if (std::strcmp(argv[i], "-w") == 0 && i + 1 < argc) { options.pcapng_output_path = argv[++i]; @@ -116,6 +137,10 @@ int main(int argc, char** argv) { options.filter_expr = argv[++i]; } else if (std::strcmp(argv[i], "-r") == 0 && i + 1 < argc) { options.replay_input_path = argv[++i]; + } else if (std::strcmp(argv[i], "-c") == 0) { + enable_checksums = true; + } else if (std::strcmp(argv[i], "-a") == 0) { + enable_reassembly = true; } else if (options.device.empty()) { options.device = argv[i]; } @@ -158,9 +183,10 @@ int main(int argc, char** argv) { wireframe::CaptureQueue queue(4096); SharedState state; + wireframe::net::TcpReassembler reassembler; std::thread capture_thread = session.start_capture_thread(queue); std::thread consumer_thread(consumer_loop, std::ref(session), std::ref(queue), - std::ref(state)); + std::ref(state), enable_reassembly ? &reassembler : nullptr); int selected_row = -1; bool quit = false; @@ -248,7 +274,18 @@ int main(int argc, char** argv) { { std::lock_guard<std::mutex> lock(state.mutex); if (selected_row >= 0 && selected_row < static_cast<int>(state.rows.size())) { - for (const auto& line : wireframe::hex_dump_lines(state.rows[selected_row].data)) { + const auto& row = state.rows[selected_row]; + if (enable_checksums) { + std::string status = wireframe::checksum_status(row.data, session.datalink()); + if (!status.empty()) { + ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "%s", status.c_str()); + } + } + if (row.reassembled_http) { + ImGui::TextColored(ImVec4(0.6f, 1.0f, 0.6f, 1.0f), "%s", + row.reassembled_http->c_str()); + } + for (const auto& line : wireframe::hex_dump_lines(row.data)) { ImGui::TextUnformatted(line.c_str()); } } else { |