| 3128 | } |
| 3129 | |
| 3130 | void CaptureMessageToFile(const CAddress& addr, |
| 3131 | const std::string& msg_type, |
| 3132 | Span<const unsigned char> data, |
| 3133 | bool is_incoming) |
| 3134 | { |
| 3135 | // Note: This function captures the message at the time of processing, |
| 3136 | // not at socket receive/send time. |
| 3137 | // This ensures that the messages are always in order from an application |
| 3138 | // layer (processing) perspective. |
| 3139 | auto now = GetTime<std::chrono::microseconds>(); |
| 3140 | |
| 3141 | // Windows folder names cannot include a colon |
| 3142 | std::string clean_addr = addr.ToString(); |
| 3143 | std::replace(clean_addr.begin(), clean_addr.end(), ':', '_'); |
| 3144 | |
| 3145 | fs::path base_path = gArgs.GetDataDirNet() / "message_capture" / clean_addr; |
| 3146 | fs::create_directories(base_path); |
| 3147 | |
| 3148 | fs::path path = base_path / (is_incoming ? "msgs_recv.dat" : "msgs_sent.dat"); |
| 3149 | CAutoFile f(fsbridge::fopen(path, "ab"), SER_DISK, CLIENT_VERSION); |
| 3150 | |
| 3151 | ser_writedata64(f, now.count()); |
| 3152 | f.write(MakeByteSpan(msg_type)); |
| 3153 | for (auto i = msg_type.length(); i < CMessageHeader::COMMAND_SIZE; ++i) { |
| 3154 | f << uint8_t{'\0'}; |
| 3155 | } |
| 3156 | uint32_t size = data.size(); |
| 3157 | ser_writedata32(f, size); |
| 3158 | f.write(AsBytes(data)); |
| 3159 | } |
| 3160 | |
| 3161 | std::function<void(const CAddress& addr, |
| 3162 | const std::string& msg_type, |
nothing calls this directly
no test coverage detected