Ranged support of protocol version on server side

This commit is contained in:
Perttu Ahola 2012-11-26 23:58:27 +02:00
parent 23913f26cd
commit 8ccdd3bdb4
4 changed files with 38 additions and 14 deletions

View File

@ -75,14 +75,19 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
GENERIC_CMD_SET_ANIMATION GENERIC_CMD_SET_ANIMATION
GENERIC_CMD_SET_BONE_POSITION GENERIC_CMD_SET_BONE_POSITION
GENERIC_CMD_SET_ATTACHMENT GENERIC_CMD_SET_ATTACHMENT
PROTOCOL_VERSION 15:
Serialization format changes
*/ */
// Server always only supports one version #define LATEST_PROTOCOL_VERSION 15
#define SERVER_PROTOCOL_VERSION 14
// Client can support older versions too // Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 14
#define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
// Client's supported network protocol range
#define CLIENT_PROTOCOL_VERSION_MIN 13 #define CLIENT_PROTOCOL_VERSION_MIN 13
#define CLIENT_PROTOCOL_VERSION_MAX SERVER_PROTOCOL_VERSION #define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
// Constant that differentiates the protocol from random data and other protocols // Constant that differentiates the protocol from random data and other protocols
#define PROTOCOL_ID 0x4f457403 #define PROTOCOL_ID 0x4f457403

View File

@ -2042,14 +2042,26 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2) if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]); min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
// Use min if version field doesn't exist (backwards compatibility) // Use same version as minimum and maximum if maximum version field
// doesn't exist (backwards compatibility)
u16 max_net_proto_version = min_net_proto_version; u16 max_net_proto_version = min_net_proto_version;
if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2) if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2)
max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]); max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]);
// Start with client's maximum version
u16 net_proto_version = max_net_proto_version; u16 net_proto_version = max_net_proto_version;
if(max_net_proto_version != SERVER_PROTOCOL_VERSION && min_net_proto_version <= SERVER_PROTOCOL_VERSION)
net_proto_version = SERVER_PROTOCOL_VERSION; // Figure out a working version if it is possible at all
if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN ||
min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX)
{
// If maximum is larger than our maximum, go with our maximum
if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
net_proto_version = SERVER_PROTOCOL_VERSION_MAX;
// Else go with client's maximum
else
net_proto_version = max_net_proto_version;
}
verbosestream<<"Server: "<<peer_id<<" Protocol version: min: " verbosestream<<"Server: "<<peer_id<<" Protocol version: min: "
<<min_net_proto_version<<", max: "<<max_net_proto_version <<min_net_proto_version<<", max: "<<max_net_proto_version
@ -2071,7 +2083,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(g_settings->getBool("strict_protocol_version_checking")) if(g_settings->getBool("strict_protocol_version_checking"))
{ {
if(net_proto_version != SERVER_PROTOCOL_VERSION) if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN ||
net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
{ {
actionstream<<"Server: A mismatched client tried to connect" actionstream<<"Server: A mismatched client tried to connect"
<<" from "<<addr_s<<std::endl; <<" from "<<addr_s<<std::endl;
@ -2080,9 +2093,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
L"Server version is ") L"Server version is ")
+ narrow_to_wide(VERSION_STRING) + L",\n" + narrow_to_wide(VERSION_STRING) + L",\n"
+ L"server's PROTOCOL_VERSION is " + L"server's PROTOCOL_VERSION is "
+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION)) + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN))
+ L"..."
+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX))
+ L", client's PROTOCOL_VERSION is " + L", client's PROTOCOL_VERSION is "
+ narrow_to_wide(itos(net_proto_version)) + narrow_to_wide(itos(min_net_proto_version))
+ L"..."
+ narrow_to_wide(itos(max_net_proto_version))
); );
return; return;
} }
@ -2324,9 +2341,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
} }
// Warnings about protocol version can be issued here // Warnings about protocol version can be issued here
if(getClient(peer_id)->net_proto_version < SERVER_PROTOCOL_VERSION) if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
{ {
SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER!"); SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD "
L"AND MAY NOT FULLY WORK WITH THIS SERVER!");
} }
/* /*

View File

@ -602,7 +602,7 @@ private:
static void SendItemDef(con::Connection &con, u16 peer_id, static void SendItemDef(con::Connection &con, u16 peer_id,
IItemDefManager *itemdef); IItemDefManager *itemdef);
static void SendNodeDef(con::Connection &con, u16 peer_id, static void SendNodeDef(con::Connection &con, u16 peer_id,
INodeDefManager *nodedef); INodeDefManager *nodedef, u16 protocol_version);
/* /*
Non-static send methods. Non-static send methods.

View File

@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h" #include "util/numeric.h"
#include "util/serialize.h" #include "util/serialize.h"
#include "noise.h" // PseudoRandom used for random data for compression #include "noise.h" // PseudoRandom used for random data for compression
#include "clientserver.h" // LATEST_PROTOCOL_VERSION
/* /*
Asserts that the exception occurs Asserts that the exception occurs
@ -324,7 +325,7 @@ struct TestNodedefSerialization: public TestBase
f.tiledef[i].name = "default_stone.png"; f.tiledef[i].name = "default_stone.png";
f.is_ground_content = true; f.is_ground_content = true;
std::ostringstream os(std::ios::binary); std::ostringstream os(std::ios::binary);
f.serialize(os); f.serialize(os, LATEST_PROTOCOL_VERSION);
verbosestream<<"Test ContentFeatures size: "<<os.str().size()<<std::endl; verbosestream<<"Test ContentFeatures size: "<<os.str().size()<<std::endl;
std::istringstream is(os.str(), std::ios::binary); std::istringstream is(os.str(), std::ios::binary);
ContentFeatures f2; ContentFeatures f2;