summaryrefslogtreecommitdiff
path: root/src/net/messagein.cpp
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2012-04-14 12:59:54 +0200
committerThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2012-05-05 22:51:32 +0200
commitbb9a9b9b0f4ec7cc6a9ca3a6bd2dc35b0b6541e7 (patch)
tree503dcb475ece8e72e2fbef2e78e82b2a881e6d23 /src/net/messagein.cpp
parent05669aae551820f2183984d1c706d3a82eb37be6 (diff)
downloadmanaserv-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/messagein.cpp')
-rw-r--r--src/net/messagein.cpp166
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;
}