From ce74752e9171ce21efa226e9435d66441a1b9a1c Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Mon, 21 Apr 2014 02:43:45 +0200 Subject: [PATCH] Common: Add a PCAP writer module --- Source/Core/Common/CMakeLists.txt | 1 + Source/Core/Common/Common.vcxproj | 2 + Source/Core/Common/Common.vcxproj.filters | 2 + Source/Core/Common/PcapFile.cpp | 66 +++++++++++++++++++++++ Source/Core/Common/PcapFile.h | 44 +++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 Source/Core/Common/PcapFile.cpp create mode 100644 Source/Core/Common/PcapFile.h diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 90385653f7..a9535a1799 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -14,6 +14,7 @@ set(SRCS BreakPoints.cpp MsgHandler.cpp NandPaths.cpp Network.cpp + PcapFile.cpp SettingsHandler.cpp SDCardUtil.cpp StringUtil.cpp diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 00bcb07c80..87c14c321c 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -78,6 +78,7 @@ + @@ -114,6 +115,7 @@ + diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 5f9b211828..bca6b0c68e 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -39,6 +39,7 @@ + @@ -86,6 +87,7 @@ + diff --git a/Source/Core/Common/PcapFile.cpp b/Source/Core/Common/PcapFile.cpp new file mode 100644 index 0000000000..9a28daca2d --- /dev/null +++ b/Source/Core/Common/PcapFile.cpp @@ -0,0 +1,66 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include + +#include "Common/CommonTypes.h" +#include "Common/FileUtil.h" +#include "Common/PcapFile.h" + +namespace { + +const u32 PCAP_MAGIC = 0xa1b2c3d4; +const u16 PCAP_VERSION_MAJOR = 2; +const u16 PCAP_VERSION_MINOR = 4; +const u32 PCAP_CAPTURE_LENGTH = 65535; + +// TODO(delroth): Make this configurable at PCAP creation time? +const u32 PCAP_DATA_LINK_TYPE = 147; // Reserved for internal use. + +// Designed to be directly written into the PCAP file. The PCAP format is +// endian independent, so this works just fine. +#pragma pack(push, 1) +struct PCAPHeader +{ + u32 magic_number; + u16 version_major; + u16 version_minor; + s32 tz_offset; // Offset in seconds from the GMT timezone. + u32 ts_accuracy; // In practice, 0. + u32 capture_length; // Size at which we truncate packets. + u32 data_link_type; +}; + +struct PCAPRecordHeader +{ + u32 ts_sec; + u32 ts_usec; + u32 size_in_file; // Size after eventual truncation. + u32 real_size; // Size before eventual truncation. +}; +#pragma pack(pop) + +} // namespace + +void PCAP::AddHeader() +{ + PCAPHeader hdr = { + PCAP_MAGIC, PCAP_VERSION_MAJOR, PCAP_VERSION_MINOR, + 0, 0, PCAP_CAPTURE_LENGTH, PCAP_DATA_LINK_TYPE + }; + m_fp->WriteBytes(&hdr, sizeof (hdr)); +} + +void PCAP::AddPacket(const u8* bytes, size_t size) +{ + std::chrono::system_clock::time_point now(std::chrono::system_clock::now()); + auto ts = now.time_since_epoch(); + PCAPRecordHeader rec_hdr = { + (u32)std::chrono::duration_cast(ts).count(), + (u32)(std::chrono::duration_cast(ts).count() % 1000000), + (u32)size, (u32)size + }; + m_fp->WriteBytes(&rec_hdr, sizeof (rec_hdr)); + m_fp->WriteBytes(bytes, size); +} diff --git a/Source/Core/Common/PcapFile.h b/Source/Core/Common/PcapFile.h new file mode 100644 index 0000000000..f3bc98d23c --- /dev/null +++ b/Source/Core/Common/PcapFile.h @@ -0,0 +1,44 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +// PCAP is a standard file format for network capture files. This also extends +// to any capture of packetized intercommunication data. This file provides a +// class called PCAP which is a very light wrapper around the file format, +// allowing only creating a new PCAP capture file and appending packets to it. +// +// Example use: +// PCAP pcap(new IOFile("test.pcap", "wb")); +// pcap.AddPacket(pkt); // pkt is automatically casted to u8* + +#pragma once + +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/FileUtil.h" + +class PCAP final : public NonCopyable +{ +public: + // Takes ownership of the file object. Assumes the file object is already + // opened in write mode. + explicit PCAP(File::IOFile* fp) : m_fp(fp) + { + AddHeader(); + } + + template + void AddPacket(const T& obj) + { + AddPacket(reinterpret_cast(&obj), sizeof (obj)); + } + + void AddPacket(const u8* bytes, size_t size); + +private: + void AddHeader(); + + std::unique_ptr m_fp; +};