summaryrefslogtreecommitdiff
path: root/src/net
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
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')
-rw-r--r--src/net/connectionhandler.cpp6
-rw-r--r--src/net/messagein.cpp166
-rw-r--r--src/net/messagein.h10
-rw-r--r--src/net/messageout.cpp78
-rw-r--r--src/net/messageout.h64
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