From df9ed1ab4364fe29bf260cae51827cc2722eff78 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Tue, 1 May 2012 22:38:07 +0200 Subject: Added debugging mode to the protocol This makes the client able to send and receive messages sent in debugging mode, where the contents of the messages are annotated. For messages sent from the client the debugging mode is currently always enabled. Later on this could be an internal option or controlled from the server side. Reviewed-by: Erik Schilling --- src/net/manaserv/manaserv_protocol.h | 27 +++++++++++++----- src/net/manaserv/messagein.cpp | 54 ++++++++++++++++++++++++++++++++++-- src/net/manaserv/messagein.h | 16 +++++++---- src/net/manaserv/messageout.cpp | 32 +++++++++++++++++++-- src/net/manaserv/messageout.h | 11 ++++++-- 5 files changed, 119 insertions(+), 21 deletions(-) diff --git a/src/net/manaserv/manaserv_protocol.h b/src/net/manaserv/manaserv_protocol.h index c8b16593..5f94b726 100644 --- a/src/net/manaserv/manaserv_protocol.h +++ b/src/net/manaserv/manaserv_protocol.h @@ -26,7 +26,19 @@ namespace ManaServ { enum { PROTOCOL_VERSION = 1, - SUPPORTED_DB_VERSION = 19 + SUPPORTED_DB_VERSION = 21 +}; + +/** + * The type of a value in a message. Prepended before each value when the + * protocol is running in debug mode. + */ +enum ValueType { + Int8, + Int16, + Int32, + String, + Double }; /** @@ -43,7 +55,7 @@ enum { * Components: B byte, W word, D double word, S variable-size string * C tile-based coordinates (B*3) * - * Hosts: P (player's client), A (account server), C (char server), + * Hosts: P (player's client), A (account server), C (chat server), * G (game server) * * TODO - Document specific error codes for each packet @@ -232,7 +244,7 @@ enum { // Inter-server GAMSG_REGISTER = 0x0500, // S address, W port, S password, D items db revision, { W map id }* - AGMSG_REGISTER_RESPONSE = 0x0501, // C item version, C password response, { S globalvar_key, S globalvar_value } + AGMSG_REGISTER_RESPONSE = 0x0501, // W item version, W password response, { S globalvar_key, S globalvar_value } AGMSG_ACTIVE_MAP = 0x0502, // W map id, W Number of mapvar_key mapvar_value sent, { S mapvar_key, S mapvar_value }, W Number of map items, { D item Id, W amount, W posX, W posY } AGMSG_PLAYER_ENTER = 0x0510, // B*32 token, D id, S name, serialised character data GAMSG_PLAYER_DATA = 0x0520, // D id, serialised character data @@ -252,7 +264,7 @@ enum { GAMSG_BAN_PLAYER = 0x0550, // D id, W duration GAMSG_CHANGE_PLAYER_LEVEL = 0x0555, // D id, W level GAMSG_CHANGE_ACCOUNT_LEVEL = 0x0556, // D id, W level - GAMSG_STATISTICS = 0x0560, // { W map id, W thing nb, W monster nb, W player nb, { D character id }* }* + GAMSG_STATISTICS = 0x0560, // { W map id, W entity nb, W monster nb, W player nb, { D character id }* }* CGMSG_CHANGED_PARTY = 0x0590, // D character id, D party id GCMSG_REQUEST_POST = 0x05A0, // D character id CGMSG_POST_RESPONSE = 0x05A1, // D receiver id, { S sender name, S letter, W num attachments { W attachment item id, W quantity } } @@ -263,7 +275,8 @@ enum { GAMSG_REMOVE_ITEM_ON_MAP = 0x0602, // D map id, D item id, W amount, W pos x, W pos y GAMSG_ANNOUNCE = 0x0603, // S text, W senderid, S sendername - XXMSG_INVALID = 0x7FFF + XXMSG_DEBUG_FLAG = 0x8000, // Message in debug mode + XXMSG_INVALID = 0x7FFF }; // Generic return values @@ -340,8 +353,8 @@ enum AttribmodResponseCode { ATTRIBMOD_DENIED }; -// Object type enumeration -enum ThingType +// Entity type enumeration +enum EntityType { // A simple item. OBJECT_ITEM = 0, diff --git a/src/net/manaserv/messagein.cpp b/src/net/manaserv/messagein.cpp index aeb02b8d..8065d313 100644 --- a/src/net/manaserv/messagein.cpp +++ b/src/net/manaserv/messagein.cpp @@ -29,15 +29,24 @@ namespace ManaServ { MessageIn::MessageIn(const char *data, unsigned int length): mData(data), mLength(length), + mDebugMode(false), mPos(0) { // Read the message ID mId = readInt16(); + + // Read and clear the debug flag + mDebugMode = mId & ManaServ::XXMSG_DEBUG_FLAG; + mId &= ~ManaServ::XXMSG_DEBUG_FLAG; } uint8_t MessageIn::readInt8() { uint8_t value = 0; + + if (!readValueType(ManaServ::Int8)) + return value; + if (mPos < mLength) { value = mData[mPos]; @@ -49,6 +58,10 @@ uint8_t MessageIn::readInt8() uint16_t MessageIn::readInt16() { uint16_t value = 0; + + if (!readValueType(ManaServ::Int16)) + return value; + if (mPos + 2 <= mLength) { uint16_t t; @@ -62,6 +75,10 @@ uint16_t MessageIn::readInt16() uint32_t MessageIn::readInt32() { uint32_t value = 0; + + if (!readValueType(ManaServ::Int32)) + return value; + if (mPos + 4 <= mLength) { uint32_t t; @@ -74,24 +91,55 @@ uint32_t MessageIn::readInt32() std::string MessageIn::readString(int length) { + if (!readValueType(ManaServ::String)) + return std::string(); + + if (mDebugMode) + { + int fixedLength = (int16_t) readInt16(); + if (fixedLength != length) + { + // String does not have the expected length + mPos = mLength + 1; + return std::string(); + } + } + // Get string length if (length < 0) + { length = readInt16(); + } // Make sure the string isn't erroneous if (length < 0 || mPos + length > mLength) { mPos = mLength + 1; - return ""; + return std::string(); } // Read the string - char const *stringBeg = mData + mPos; - char const *stringEnd = (char const *)memchr(stringBeg, '\0', length); + const char *stringBeg = mData + mPos; + const char *stringEnd = (const char *)memchr(stringBeg, '\0', length); std::string readString(stringBeg, stringEnd ? stringEnd - stringBeg : length); mPos += length; + return readString; } +bool MessageIn::readValueType(ManaServ::ValueType type) +{ + if (!mDebugMode) // Verification not possible + return true; + + if (mPos >= mLength) + return false; + + uint8_t t = mData[mPos]; + ++mPos; + + return t == type; +} + } // ManaServ diff --git a/src/net/manaserv/messagein.h b/src/net/manaserv/messagein.h index ef0c29bf..89ae5ed8 100644 --- a/src/net/manaserv/messagein.h +++ b/src/net/manaserv/messagein.h @@ -22,6 +22,8 @@ #ifndef NET_MANASERV_MESSAGEIN_H #define NET_MANASERV_MESSAGEIN_H +#include "net/manaserv/manaserv_protocol.h" + #include #include @@ -75,14 +77,16 @@ class MessageIn std::string readString(int length = -1); private: - const char *mData; /**< The message data. */ - unsigned int mLength; /**< The length of the data. */ - unsigned short mId; /**< The message ID. */ + bool readValueType(ManaServ::ValueType type); + + const char *mData; /**< The message data. */ + unsigned int mLength; /**< The length of the data. */ + unsigned short mId; /**< The message ID. */ + bool mDebugMode; /**< Includes debugging information. */ /** - * Actual position in the packet. From 0 to packet->length. - * A value bigger than packet->length means EOP was reached when - * reading it. + * Actual position in the packet. From 0 to packet->length. A value + * bigger than packet->length means EOP was reached when reading it. */ unsigned int mPos; }; diff --git a/src/net/manaserv/messageout.cpp b/src/net/manaserv/messageout.cpp index 7cecc03d..1197176f 100644 --- a/src/net/manaserv/messageout.cpp +++ b/src/net/manaserv/messageout.cpp @@ -29,10 +29,16 @@ namespace ManaServ { MessageOut::MessageOut(uint16_t id): mData(0), + mPos(0), mDataSize(0), - mPos(0) + mDebugMode(false) { + bool debug = true; + if (debug) + id |= ManaServ::XXMSG_DEBUG_FLAG; + writeInt16(id); + mDebugMode = debug; } MessageOut::~MessageOut() @@ -48,6 +54,9 @@ void MessageOut::expand(size_t bytes) void MessageOut::writeInt8(uint8_t value) { + if (mDebugMode) + writeValueType(ManaServ::Int8); + expand(1); mData[mPos] = value; mPos += 1; @@ -55,6 +64,9 @@ void MessageOut::writeInt8(uint8_t value) void MessageOut::writeInt16(uint16_t value) { + if (mDebugMode) + writeValueType(ManaServ::Int16); + expand(2); uint16_t t = ENET_HOST_TO_NET_16(value); memcpy(mData + mPos, &t, 2); @@ -63,6 +75,9 @@ void MessageOut::writeInt16(uint16_t value) void MessageOut::writeInt32(uint32_t value) { + if (mDebugMode) + writeValueType(ManaServ::Int32); + expand(4); uint32_t t = ENET_HOST_TO_NET_32(value); memcpy(mData + mPos, &t, 4); @@ -71,6 +86,12 @@ void MessageOut::writeInt32(uint32_t value) void MessageOut::writeString(const std::string &string, int length) { + if (mDebugMode) + { + writeValueType(ManaServ::String); + writeInt16(length); + } + int stringLength = string.length(); if (length < 0) { @@ -88,12 +109,19 @@ void MessageOut::writeString(const std::string &string, int length) // Write the actual string memcpy(mData + mPos, string.data(), stringLength); - // Pad remaining space with zeros if (length > stringLength) { + // Pad remaining space with zeros memset(mData + mPos + stringLength, '\0', length - stringLength); } mPos += length; } +void MessageOut::writeValueType(ManaServ::ValueType type) +{ + expand(1); + mData[mPos] = type; + mPos += 1; +} + } // namespace ManaServ diff --git a/src/net/manaserv/messageout.h b/src/net/manaserv/messageout.h index 9a87cf1c..d452f784 100644 --- a/src/net/manaserv/messageout.h +++ b/src/net/manaserv/messageout.h @@ -22,6 +22,8 @@ #ifndef NET_MANASERV_MESSAGEOUT_H #define NET_MANASERV_MESSAGEOUT_H +#include "net/manaserv/manaserv_protocol.h" + #include #include @@ -80,9 +82,12 @@ class MessageOut */ void expand(size_t size); - char *mData; /**< Data building up. */ - unsigned int mDataSize; /**< Size of data. */ - unsigned int mPos; /**< Position in the data. */ + void writeValueType(ManaServ::ValueType type); + + char *mData; /**< Data building up. */ + unsigned int mPos; /**< Position in the data. */ + unsigned int mDataSize; /**< Size of data. */ + bool mDebugMode; /**< Include debugging information. */ }; } // namespace ManaServ -- cgit v1.2.3-70-g09d2