New PROTOCOL_VERSION scheme (allow client to support a range of versions)
authorPerttu Ahola <celeron55@gmail.com>
Mon, 26 Nov 2012 07:49:07 +0000 (09:49 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 26 Nov 2012 07:49:07 +0000 (09:49 +0200)
src/client.cpp
src/clientserver.h
src/server.cpp

index f72c4b654aad51ab34ab648d38852471b3779b42..f6e97c52ec32c8879b3ee912405da035761a4d26 100644 (file)
@@ -499,8 +499,9 @@ void Client::step(float dtime)
                        // [2] u8 SER_FMT_VER_HIGHEST
                        // [3] u8[20] player_name
                        // [23] u8[28] password (new in some version)
-                       // [51] u16 client network protocol version (new in some version)
-                       SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2);
+                       // [51] u16 minimum supported network protocol version (added sometime)
+                       // [53] u16 maximum supported network protocol version (added later than the previous one)
+                       SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2);
                        writeU16(&data[0], TOSERVER_INIT);
                        writeU8(&data[2], SER_FMT_VER_HIGHEST);
 
@@ -513,8 +514,8 @@ void Client::step(float dtime)
                        memset((char*)&data[23], 0, PASSWORD_SIZE);
                        snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
                        
-                       // This should be incremented in each version
-                       writeU16(&data[51], PROTOCOL_VERSION);
+                       writeU16(&data[51], CLIENT_PROTOCOL_VERSION_MIN);
+                       writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX);
 
                        // Send as unreliable
                        Send(0, data, false);
index ba535a66be36d57cdf0225b1f9430a269933b8ec..b7e64d2951ff722de34ddeac326d8845c6cd84a3 100644 (file)
@@ -75,8 +75,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
                GENERIC_CMD_SET_ATTACHMENT
 */
 
-#define PROTOCOL_VERSION 14
+// Server always only supports one version
+#define SERVER_PROTOCOL_VERSION 14
 
+// Client can support older versions too
+#define CLIENT_PROTOCOL_VERSION_MIN 13
+#define CLIENT_PROTOCOL_VERSION_MAX SERVER_PROTOCOL_VERSION
+
+// Constant that differentiates the protocol from random data and other protocols
 #define PROTOCOL_ID 0x4f457403
 
 #define PASSWORD_SIZE 28       // Maximum password length. Allows for
@@ -350,7 +356,8 @@ enum ToServerCommand
                [2] u8 SER_FMT_VER_HIGHEST
                [3] u8[20] player_name
                [23] u8[28] password (new in some version)
-               [51] u16 client network protocol version (new in some version)
+               [51] u16 minimum supported network protocol version (added sometime)
+               [53] u16 maximum supported network protocol version (added later than the previous one)
        */
 
        TOSERVER_INIT2 = 0x11,
index ac243a29cfa4c44bad6b42ab82483fc20392f8ac..f4da73fa5273c67cef00ba58f03ee53ac5ba3bb1 100644 (file)
@@ -2037,11 +2037,22 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        Read and check network protocol version
                */
 
-               u16 net_proto_version = 0;
+               u16 min_net_proto_version = 0;
                if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
-               {
-                       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)
+               u16 max_net_proto_version = min_net_proto_version;
+               if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2)
+                       max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]);
+
+               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;
+
+               verbosestream<<"Server: "<<peer_id<<" Protocol version: min: "
+                               <<min_net_proto_version<<", max: "<<max_net_proto_version
+                               <<", chosen: "<<net_proto_version<<std::endl;
 
                getClient(peer_id)->net_proto_version = net_proto_version;
 
@@ -2059,7 +2070,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                
                if(g_settings->getBool("strict_protocol_version_checking"))
                {
-                       if(net_proto_version != PROTOCOL_VERSION)
+                       if(net_proto_version != SERVER_PROTOCOL_VERSION)
                        {
                                actionstream<<"Server: A mismatched client tried to connect"
                                                <<" from "<<addr_s<<std::endl;
@@ -2068,7 +2079,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                                L"Server version is ")
                                                + narrow_to_wide(VERSION_STRING) + L",\n"
                                                + L"server's PROTOCOL_VERSION is "
-                                               + narrow_to_wide(itos(PROTOCOL_VERSION))
+                                               + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION))
                                                + L", client's PROTOCOL_VERSION is "
                                                + narrow_to_wide(itos(net_proto_version))
                                );
@@ -2310,7 +2321,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                }
                
                // Warnings about protocol version can be issued here
-               if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION)
+               if(getClient(peer_id)->net_proto_version < SERVER_PROTOCOL_VERSION)
                {
                        SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER!");
                }