diff options
author | Thorbjørn Lindeijer <thorbjorn@lindeijer.nl> | 2012-04-14 12:59:54 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <thorbjorn@lindeijer.nl> | 2012-05-05 22:51:32 +0200 |
commit | bb9a9b9b0f4ec7cc6a9ca3a6bd2dc35b0b6541e7 (patch) | |
tree | 503dcb475ece8e72e2fbef2e78e82b2a881e6d23 /src/net | |
parent | 05669aae551820f2183984d1c706d3a82eb37be6 (diff) | |
download | manaserv-bb9a9b9b0f4ec7cc6a9ca3a6bd2dc35b0b6541e7.tar.gz manaserv-bb9a9b9b0f4ec7cc6a9ca3a6bd2dc35b0b6541e7.tar.bz2 manaserv-bb9a9b9b0f4ec7cc6a9ca3a6bd2dc35b0b6541e7.tar.xz manaserv-bb9a9b9b0f4ec7cc6a9ca3a6bd2dc35b0b6541e7.zip |
Added debugging mode to the protocol
Allows inspection of message data. It is off by default since it consumes
additional bandwidth, but it can be turned on using the net_debugMode option
in manaserv.xml.
Currently the option only affects outgoing data for each host individually.
In particular, enabling this debug mode for the server does not automatically
make the client annotate its messages.
Reviewed-by: Erik Schilling
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/connectionhandler.cpp | 6 | ||||
-rw-r--r-- | src/net/messagein.cpp | 166 | ||||
-rw-r--r-- | src/net/messagein.h | 10 | ||||
-rw-r--r-- | src/net/messageout.cpp | 78 | ||||
-rw-r--r-- | src/net/messageout.h | 64 |
5 files changed, 245 insertions, 79 deletions
diff --git a/src/net/connectionhandler.cpp b/src/net/connectionhandler.cpp index e9ec1944..5aaf90e0 100644 --- a/src/net/connectionhandler.cpp +++ b/src/net/connectionhandler.cpp @@ -75,12 +75,12 @@ void ConnectionHandler::stopListen() currentPeer < &host->peers[host->peerCount]; ++currentPeer) { - if (currentPeer->state == ENET_PEER_STATE_CONNECTED) - { + if (currentPeer->state == ENET_PEER_STATE_CONNECTED) + { enet_peer_disconnect(currentPeer, 0); enet_host_flush(host); enet_peer_reset(currentPeer); - } + } } enet_host_destroy(host); // FIXME: memory leak on NetComputers diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp index 022ac465..b797f0a0 100644 --- a/src/net/messagein.cpp +++ b/src/net/messagein.cpp @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2004-2010 The Mana World Development Team + * Copyright (C) 2010-2012 The Mana Developers * * This file is part of The Mana Server. * @@ -30,23 +31,47 @@ #include "net/messagein.h" #include "utils/logger.h" -MessageIn::MessageIn(const char *data, int length): +// Not enabled by default since this will cause assertions on message errors, +// which may also originate from the client. +//#define DEBUG_NETWORK + +#ifdef DEBUG_NETWORK +#include <cassert> +#define ASSERT_IF(x) assert(x); if (x) +#else +#define ASSERT_IF(x) if (x) +#endif + +MessageIn::MessageIn(const char *data, unsigned short 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; } int MessageIn::readInt8() { int value = -1; - if (mPos < mLength) + + if (!readValueType(ManaServ::Int8)) + return value; + + ASSERT_IF (mPos < mLength) { value = (unsigned char) mData[mPos]; } - else LOG_DEBUG("Unable to read 1 byte in " << this->getId() << "!"); + else + { + LOG_DEBUG("Unable to read 1 byte in " << mId << "!"); + } + mPos += 1; return value; } @@ -54,13 +79,21 @@ int MessageIn::readInt8() int MessageIn::readInt16() { int value = -1; - if (mPos + 2 <= mLength) + + if (!readValueType(ManaServ::Int16)) + return value; + + ASSERT_IF (mPos + 2 <= mLength) { uint16_t t; memcpy(&t, mData + mPos, 2); - value = (unsigned short) ENET_NET_TO_HOST_16(t); + value = (short) ENET_NET_TO_HOST_16(t); } - else LOG_DEBUG("Unable to read 2 bytes in " << this->getId() << "!"); + else + { + LOG_DEBUG("Unable to read 2 bytes in " << mId << "!"); + } + mPos += 2; return value; } @@ -68,20 +101,32 @@ int MessageIn::readInt16() int MessageIn::readInt32() { int value = -1; - if (mPos + 4 <= mLength) + + if (!readValueType(ManaServ::Int32)) + return value; + + ASSERT_IF (mPos + 4 <= mLength) { uint32_t t; memcpy(&t, mData + mPos, 4); value = ENET_NET_TO_HOST_32(t); } - else LOG_DEBUG("Unable to read 4 bytes in " << this->getId() << "!"); + else + { + LOG_DEBUG("Unable to read 4 bytes in " << mId << "!"); + } + mPos += 4; return value; } double MessageIn::readDouble() { - double value; + double value = -1; + + if (!readValueType(ManaServ::Double)) + return value; + #ifdef USE_NATIVE_DOUBLE if (mPos + sizeof(double) <= mLength) memcpy(&value, mData + mPos, sizeof(double)); @@ -96,6 +141,24 @@ double MessageIn::readDouble() std::string MessageIn::readString(int length) { + if (!readValueType(ManaServ::String)) + return std::string(); + + if (mDebugMode) + { + int fixedLength = readInt16(); +#ifdef DEBUG_NETWORK + assert(fixedLength == length); +#endif + if (fixedLength != length) + { + LOG_DEBUG("Expected string of length " << length << + " but received length " << fixedLength); + mPos = mLength + 1; + return std::string(); + } + } + // Get string length if (length < 0) { @@ -113,17 +176,96 @@ std::string MessageIn::readString(int length) const char *stringBeg = mData + mPos; const char *stringEnd = (const char *)memchr(stringBeg, '\0', length); std::string readString(stringBeg, - stringEnd ? stringEnd - stringBeg : length); + stringEnd ? stringEnd - stringBeg : length); mPos += length; return readString; } +bool MessageIn::readValueType(ManaServ::ValueType type) +{ + if (!mDebugMode) // Verification not possible + return true; + + ASSERT_IF (mPos < mLength) + { + int t = (unsigned char) mData[mPos]; + ++mPos; + + ASSERT_IF (t == type) + { + return true; + } + else + { + LOG_DEBUG("Attempt to read " << type << " but got " << t); + } + } + else + { + LOG_DEBUG("Attempt to read " << type << " but no more data available"); + } + + return false; +} + std::ostream& operator <<(std::ostream &os, const MessageIn &msg) { os << std::setw(6) << std::hex << std::showbase << std::internal - << std::setfill('0') << msg.getId() - << std::dec << " (" << msg.getLength() << " B)"; + << std::setfill('0') << msg.getId() << std::dec; + + if (!msg.mDebugMode) + { + os << " (" << msg.getLength() << " B)"; + } + else + { + os << " { "; + + MessageIn m(msg.mData, msg.mLength); + + while (m.getUnreadLength() > 0) + { + if (m.mPos > 3) + os << ", "; + + unsigned char valueType = m.mData[m.mPos]; + switch (valueType) + { + case ManaServ::Int8: + os << "B " << m.readInt8(); + break; + case ManaServ::Int16: + os << "W " << m.readInt16(); + break; + case ManaServ::Int32: + os << "D " << m.readInt32(); + break; + case ManaServ::String: { + // Peak ahead at a possible fixed length + unsigned short pos = m.mPos; + m.mPos++; + int length = m.readInt16(); + m.mPos = pos; + + if (length < 0) + os << "S " << m.readString(); + else + os << "S[" << length << "] " << m.readString(length); + break; + } + case ManaServ::Double: + os << "d " << m.readDouble(); + break; + default: + os << "??? }"; + return os; // Stop after error + } + } + + os << " }"; + } + return os; } diff --git a/src/net/messagein.h b/src/net/messagein.h index dd82ce51..6d9e3bd0 100644 --- a/src/net/messagein.h +++ b/src/net/messagein.h @@ -21,6 +21,8 @@ #ifndef MESSAGEIN_H #define MESSAGEIN_H +#include "common/manaserv_protocol.h" + #include <iosfwd> /** @@ -35,7 +37,7 @@ class MessageIn * @param data the message data * @param length the length of the data */ - MessageIn(const char *data, int length); + MessageIn(const char *data, unsigned short length); /** * Returns the message ID. @@ -70,9 +72,12 @@ class MessageIn int getUnreadLength() const { return mLength - mPos; } private: + bool readValueType(ManaServ::ValueType type); + const char *mData; /**< Packet data */ unsigned short mLength; /**< Length of data in bytes */ unsigned short mId; /**< The message ID. */ + bool mDebugMode; /**< Includes debugging information. */ /** * Actual position in the packet. From 0 to packet->length. A value @@ -82,6 +87,9 @@ class MessageIn /** * Streams message ID and length to the given output stream. + * + * When the message includes debugging information, prints out + * the message contents instead of the length. */ friend std::ostream& operator <<(std::ostream &os, const MessageIn &msg); diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp index a5b0a53c..d39fd23e 100644 --- a/src/net/messageout.cpp +++ b/src/net/messageout.cpp @@ -18,6 +18,9 @@ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>. */ +#include "net/messageout.h" +#include "net/messagein.h" + #include <cstring> #include <iomanip> #include <iostream> @@ -28,28 +31,26 @@ #include <string> #include <enet/enet.h> -#include "net/messageout.h" - /** Initial amount of bytes allocated for the messageout data buffer. */ const unsigned int INITIAL_DATA_CAPACITY = 16; /** Factor by which the messageout data buffer is increased when too small. */ const unsigned int CAPACITY_GROW_FACTOR = 2; -MessageOut::MessageOut(): - mPos(0) -{ - mData = (char*) malloc(INITIAL_DATA_CAPACITY); - mDataSize = INITIAL_DATA_CAPACITY; -} +static bool debugModeEnabled = false; MessageOut::MessageOut(int id): - mPos(0) + mPos(0), + mDebugMode(false) { mData = (char*) malloc(INITIAL_DATA_CAPACITY); mDataSize = INITIAL_DATA_CAPACITY; + if (debugModeEnabled) + id |= ManaServ::XXMSG_DEBUG_FLAG; + writeInt16(id); + mDebugMode = debugModeEnabled; } MessageOut::~MessageOut() @@ -57,15 +58,7 @@ MessageOut::~MessageOut() free(mData); } -void MessageOut::clear() -{ - mData = (char *) realloc(mData, INITIAL_DATA_CAPACITY); - mDataSize = INITIAL_DATA_CAPACITY; - mPos = 0; -} - -void -MessageOut::expand(size_t bytes) +void MessageOut::expand(size_t bytes) { if (bytes > mDataSize) { @@ -81,6 +74,9 @@ MessageOut::expand(size_t bytes) void MessageOut::writeInt8(int value) { + if (mDebugMode) + writeValueType(ManaServ::Int8); + expand(mPos + 1); mData[mPos] = value; mPos += 1; @@ -88,6 +84,9 @@ void MessageOut::writeInt8(int value) void MessageOut::writeInt16(int value) { + if (mDebugMode) + writeValueType(ManaServ::Int16); + expand(mPos + 2); uint16_t t = ENET_HOST_TO_NET_16(value); memcpy(mData + mPos, &t, 2); @@ -96,6 +95,9 @@ void MessageOut::writeInt16(int value) void MessageOut::writeInt32(int value) { + if (mDebugMode) + writeValueType(ManaServ::Int32); + expand(mPos + 4); uint32_t t = ENET_HOST_TO_NET_32(value); memcpy(mData + mPos, &t, 4); @@ -104,6 +106,9 @@ void MessageOut::writeInt32(int value) void MessageOut::writeDouble(double value) { + if (mDebugMode) + writeValueType(ManaServ::Double); + #ifdef USE_NATIVE_DOUBLE expand(mPos + sizeof(double)); memcpy(mData + mPos, &value, sizeof(double)); @@ -121,19 +126,14 @@ void MessageOut::writeDouble(double value) #endif } -void MessageOut::writeCoordinates(int x, int y) +void MessageOut::writeString(const std::string &string, int length) { - expand(mPos + 3); - char *p = mData + mPos; - p[0] = x & 0x00FF; - p[1] = ((x & 0x0700) >> 8) | ((y & 0x001F) << 3); - p[2] = (y & 0x07E0) >> 5; - mPos += 3; -} + if (mDebugMode) + { + writeValueType(ManaServ::String); + writeInt16(length); + } -void -MessageOut::writeString(const std::string &string, int length) -{ int stringLength = string.length(); if (length < 0) { @@ -149,7 +149,7 @@ MessageOut::writeString(const std::string &string, int length) expand(mPos + length); // Write the actual string - memcpy(mData + mPos, string.c_str(), stringLength); + memcpy(mData + mPos, string.data(), stringLength); if (length > stringLength) { @@ -159,15 +159,20 @@ MessageOut::writeString(const std::string &string, int length) mPos += length; } +void MessageOut::writeValueType(ManaServ::ValueType type) +{ + expand(mPos + 1); + mData[mPos] = type; + mPos += 1; +} + std::ostream& operator <<(std::ostream &os, const MessageOut &msg) { if (msg.getLength() >= 2) { - unsigned short id = ENET_NET_TO_HOST_16(*(short*) msg.mData); - os << std::setw(6) << std::hex << std::showbase << std::internal - << std::setfill('0') << id - << std::dec << " (" << msg.getLength() << " B)"; + MessageIn m(msg.mData, msg.mPos); + os << m; } else { @@ -176,3 +181,8 @@ operator <<(std::ostream &os, const MessageOut &msg) } return os; } + +void MessageOut::setDebugModeEnabled(bool enabled) +{ + debugModeEnabled = enabled; +} diff --git a/src/net/messageout.h b/src/net/messageout.h index 1f071f72..a39e306b 100644 --- a/src/net/messageout.h +++ b/src/net/messageout.h @@ -21,6 +21,8 @@ #ifndef MESSAGEOUT_H #define MESSAGEOUT_H +#include "common/manaserv_protocol.h" + #include <iosfwd> /** @@ -30,27 +32,28 @@ class MessageOut { public: /** - * Default constructor. - */ - MessageOut(); - - /** - * Constructor that takes a message ID. + * Constructor. + * + * @param id the message ID */ MessageOut(int id); ~MessageOut(); /** - * Clears current message. + * Writes an 8-bit integer to the message. */ - void clear(); + void writeInt8(int value); - void writeInt8(int value); /**< Writes an integer on one byte. */ - - void writeInt16(int value); /**< Writes an integer on two bytes. */ + /** + * Writes an 16-bit integer to the message. + */ + void writeInt16(int value); - void writeInt32(int value); /**< Writes an integer on four bytes. */ + /** + * Writes an 32-bit integer to the message. + */ + void writeInt32(int value); /** * Writes a double. HACKY and should *not* be used for client @@ -59,40 +62,43 @@ class MessageOut void writeDouble(double value); /** - * Writes a 3-byte block containing tile-based coordinates. - */ - void writeCoordinates(int x, int y); - - /** * Writes a string. If a fixed length is not given (-1), it is stored * as a short at the start of the string. */ - void - writeString(const std::string &string, int length = -1); + void writeString(const std::string &string, int length = -1); /** * Returns the content of the message. */ - char* - getData() const { return mData; } + char *getData() const { return mData; } /** * Returns the length of the data. */ - unsigned int - getLength() const { return mPos; } + unsigned int getLength() const { return mPos; } + + /** + * Sets whether the debug mode is enabled. In debug mode, the internal + * data of the message is annotated so that the message contents can + * be printed. + * + * Debug mode is disabled by default. + */ + static void setDebugModeEnabled(bool enabled); private: /** * Ensures the capacity of the data buffer is large enough to hold the * given amount of bytes. */ - void - expand(size_t size); + void expand(size_t size); + + void writeValueType(ManaServ::ValueType type); - char *mData; /**< Data building up. */ - unsigned int mPos; /**< Position in the data. */ - unsigned int mDataSize; /**< Allocated datasize. */ + char *mData; /**< Data building up. */ + unsigned int mPos; /**< Position in the data. */ + unsigned int mDataSize; /**< Allocated datasize. */ + bool mDebugMode; /**< Include debugging information. */ /** * Streams message ID and length to the given output stream. @@ -101,4 +107,4 @@ class MessageOut const MessageOut &msg); }; -#endif //MESSAGEOUT_H +#endif // MESSAGEOUT_H |