diff options
Diffstat (limited to 'src/net/messagein.cpp')
-rw-r--r-- | src/net/messagein.cpp | 166 |
1 files changed, 154 insertions, 12 deletions
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; } |