// Copyright (C) 2007 EQ2EMulator Development Team - GNU GPL v3+ License #pragma once #include #include #include #include #include "eq_packet.hpp" #include "../debug.hpp" #include "../types.hpp" #include "../servertalk.hpp" #include "../stream/eq_stream.hpp" using namespace std; class ServerPacket; // Function declarations void DumpPacketAscii(const uchar* buf, int32 size, int32 cols = 16, int32 skip = 0); void DumpPacketHex(const uchar* buf, int32 size, int32 cols = 16, int32 skip = 0); void DumpPacketBin(const void* data, int32 len); void DumpPacket(const uchar* buf, int32 size); void DumpPacket(const ServerPacket* pack, bool iShowInfo = false); void DumpPacketBin(const ServerPacket* pack); void DumpPacketBin(int32 data); void DumpPacketBin(int16 data); void DumpPacketBin(int8 data); // Outputs packet buffer as ASCII characters with formatted columns // Non-printable characters are displayed as dots void DumpPacketAscii(const uchar* buf, int32 size, int32 cols, int32 skip) { for(int32 i = skip; i < size; i++) { if ((i - skip) % cols == 0) { cout << endl << setw(3) << setfill(' ') << i - skip << ":"; } else if ((i - skip) % (cols / 2) == 0) { cout << " - "; } if (buf[i] > 32 && buf[i] < 127) { cout << buf[i]; } else { cout << '.'; } } cout << endl << endl; } // Outputs packet buffer as hexadecimal with ASCII representation sidebar // Includes offset addresses and formatted column layout void DumpPacketHex(const uchar* buf, int32 size, int32 cols, int32 skip) { if (size == 0 || size > 39565) return; char output[4]; int j = 0; auto ascii = std::make_unique(cols + 1); memset(ascii.get(), 0, cols + 1); int32 i; for(i = skip; i < size; i++) { if ((i - skip) % cols == 0) { if (i != skip) cout << " | " << ascii.get() << endl; cout << setw(4) << setfill(' ') << i - skip << ": "; memset(ascii.get(), 0, cols + 1); j = 0; } else if ((i - skip) % (cols / 2) == 0) { cout << "- "; } sprintf(output, "%02X ", static_cast(buf[i])); cout << output; if (buf[i] >= 32 && buf[i] < 127) { ascii[j++] = buf[i]; } else { ascii[j++] = '.'; } } int32 k = ((i - skip) - 1) % cols; if (k < 8) cout << " "; for (int32 h = k + 1; h < cols; h++) { cout << " "; } cout << " | " << ascii.get() << endl; } // Simple wrapper to dump packet in hexadecimal format void DumpPacket(const uchar* buf, int32 size) { DumpPacketHex(buf, size); } // Dumps ServerPacket with optional header information display // Shows opcode and size when iShowInfo is true void DumpPacket(const ServerPacket* pack, bool iShowInfo) { if (iShowInfo) { cout << "Dumping ServerPacket: 0x" << hex << setfill('0') << setw(4) << pack->opcode << dec; cout << " size:" << pack->size << endl; } DumpPacketHex(pack->pBuffer, pack->size); } // Wrapper to dump ServerPacket buffer in binary format void DumpPacketBin(const ServerPacket* pack) { DumpPacketBin(pack->pBuffer, pack->size); } // Dumps 32-bit integer in binary format void DumpPacketBin(int32 data) { DumpPacketBin(reinterpret_cast(&data), sizeof(int32)); } // Dumps 16-bit integer in binary format void DumpPacketBin(int16 data) { DumpPacketBin(reinterpret_cast(&data), sizeof(int16)); } // Dumps 8-bit integer in binary format void DumpPacketBin(int8 data) { DumpPacketBin(reinterpret_cast(&data), sizeof(int8)); } // Outputs data buffer in binary format with hexadecimal values sidebar // Each byte is displayed as 8 binary digits with offset addressing void DumpPacketBin(const void* iData, int32 len) { if (!len) return; const int8* data = static_cast(iData); int32 k = 0; for (k = 0; k < len; k++) { if (k % 4 == 0) { if (k != 0) { cout << " | " << hex << setw(2) << setfill('0') << static_cast(data[k-4]) << dec; cout << " " << hex << setw(2) << setfill('0') << static_cast(data[k-3]) << dec; cout << " " << hex << setw(2) << setfill('0') << static_cast(data[k-2]) << dec; cout << " " << hex << setw(2) << setfill('0') << static_cast(data[k-1]) << dec; cout << endl; } cout << setw(4) << setfill('0') << k << ":"; } else if (k % 2 == 0) cout << " "; cout << " "; // Output each bit of the byte for (int bit = 0; bit < 8; bit++) { cout << ((data[k] & (1 << bit)) ? "1" : "0"); } } // Handle final line formatting int8 tmp = (k % 4); if (!tmp) tmp = 4; if (tmp <= 3) cout << " "; if (tmp <= 2) cout << " "; if (tmp <= 1) cout << " "; cout << " | " << hex << setw(2) << setfill('0') << static_cast(data[k-4]) << dec; if (tmp > 1) cout << " " << hex << setw(2) << setfill('0') << static_cast(data[k-3]) << dec; if (tmp > 2) cout << " " << hex << setw(2) << setfill('0') << static_cast(data[k-2]) << dec; if (tmp > 3) cout << " " << hex << setw(2) << setfill('0') << static_cast(data[k-1]) << dec; cout << endl; }