Dump binary message to file, with timestamp.
| 4268 | |
| 4269 | // Dump binary message to file, with timestamp. |
| 4270 | static void CaptureMessageToFile(const CAddress& addr, |
| 4271 | const std::string& msg_type, |
| 4272 | std::span<const unsigned char> data, |
| 4273 | bool is_incoming) |
| 4274 | { |
| 4275 | // Note: This function captures the message at the time of processing, |
| 4276 | // not at socket receive/send time. |
| 4277 | // This ensures that the messages are always in order from an application |
| 4278 | // layer (processing) perspective. |
| 4279 | auto now = GetTime<std::chrono::microseconds>(); |
| 4280 | |
| 4281 | // Windows folder names cannot include a colon |
| 4282 | std::string clean_addr = addr.ToStringAddrPort(); |
| 4283 | std::replace(clean_addr.begin(), clean_addr.end(), ':', '_'); |
| 4284 | |
| 4285 | fs::path base_path = gArgs.GetDataDirNet() / "message_capture" / fs::u8path(clean_addr); |
| 4286 | fs::create_directories(base_path); |
| 4287 | |
| 4288 | fs::path path = base_path / (is_incoming ? "msgs_recv.dat" : "msgs_sent.dat"); |
| 4289 | AutoFile f{fsbridge::fopen(path, "ab")}; |
| 4290 | |
| 4291 | ser_writedata64(f, now.count()); |
| 4292 | f << std::span{msg_type}; |
| 4293 | for (auto i = msg_type.length(); i < CMessageHeader::MESSAGE_TYPE_SIZE; ++i) { |
| 4294 | f << uint8_t{'\0'}; |
| 4295 | } |
| 4296 | uint32_t size = data.size(); |
| 4297 | ser_writedata32(f, size); |
| 4298 | f << data; |
| 4299 | |
| 4300 | if (f.fclose() != 0) { |
| 4301 | throw std::ios_base::failure( |
| 4302 | strprintf("Error closing %s after write, file contents are likely incomplete", fs::PathToString(path))); |
| 4303 | } |
| 4304 | } |
| 4305 | |
| 4306 | std::function<void(const CAddress& addr, |
| 4307 | const std::string& msg_type, |
nothing calls this directly
no test coverage detected