foxygit / doom Log in
commit 380080a32ed57ecec1ddb48bccfd80446ac6a53f
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Fri Oct 6 17:06:05 2006 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Fri Oct 6 17:06:05 2006 +0000

    Send deh/wad md5sums to players at the waiting screen. Display a warning
    on the waiting screen if the checksums differ from the other players.

    Subversion-branch: /trunk/chocolate-doom
    Subversion-revision: 689
---
 src/net_client.c | 41 ++++++++++++++++++++++++++++++++---------
 src/net_client.h | 10 +++++++++-
 src/net_gui.c    | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/net_server.c | 37 ++++++++++++++++++++++++++++++-------
 4 files changed, 121 insertions(+), 18 deletions(-)

diff --git a/src/net_client.c b/src/net_client.c
index 9a90b7e3..6147a727 100644
--- a/src/net_client.c
+++ b/src/net_client.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*-
 //-----------------------------------------------------------------------------
 //
-// $Id: net_client.c 688 2006-10-06 07:02:42Z fraggle $
+// $Id: net_client.c 689 2006-10-06 17:06:05Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -223,11 +223,15 @@ static net_clientstate_t client_state;
 static net_addr_t *server_addr;
 static net_context_t *client_context;

-// TRUE if the client code is in use
+// true if the client code is in use

 boolean net_client_connected;

-// if TRUE, this client is the controller of the game
+// true if we have received waiting data from the server
+
+boolean net_client_received_wait_data;
+
+// if true, this client is the controller of the game

 boolean net_client_controller = false;

@@ -240,6 +244,12 @@ int net_clients_in_game;
 char net_player_addresses[MAXPLAYERS][MAXPLAYERNAME];
 char net_player_names[MAXPLAYERS][MAXPLAYERNAME];

+// MD5 checksums of the wad directory and dehacked data that the server
+// has sent to us.
+
+md5_digest_t net_server_wad_md5sum;
+md5_digest_t net_server_deh_md5sum;
+
 // Player number

 int net_player_number;
@@ -274,8 +284,8 @@ static unsigned int gamedata_recv_time;

 // Hash checksums of our wad directory and dehacked data.

-static md5_digest_t wad_md5sum;
-static md5_digest_t deh_md5sum;
+md5_digest_t net_local_wad_md5sum;
+md5_digest_t net_local_deh_md5sum;

 // Average time between sending our ticcmd and receiving from the server

@@ -631,6 +641,7 @@ static void NET_CL_ParseWaitingData(net_packet_t *packet)
     signed int player_number;
     char *player_names[MAXPLAYERS];
     char *player_addr[MAXPLAYERS];
+    md5_digest_t wad_md5sum, deh_md5sum;
     size_t i;

     if (!NET_ReadInt8(packet, &num_players)
@@ -671,6 +682,12 @@ static void NET_CL_ParseWaitingData(net_packet_t *packet)
         }
     }

+    if (!NET_ReadMD5Sum(packet, wad_md5sum)
+     || !NET_ReadMD5Sum(packet, deh_md5sum))
+    {
+        return;
+    }
+
     net_clients_in_game = num_players;
     net_client_controller = is_controller != 0;
     net_player_number = player_number;
@@ -682,6 +699,11 @@ static void NET_CL_ParseWaitingData(net_packet_t *packet)
         strncpy(net_player_addresses[i], player_addr[i], MAXPLAYERNAME);
         net_player_addresses[i][MAXPLAYERNAME-1] = '\0';
     }
+
+    memcpy(net_server_wad_md5sum, wad_md5sum, sizeof(md5_digest_t));
+    memcpy(net_server_deh_md5sum, deh_md5sum, sizeof(md5_digest_t));
+
+    net_client_received_wait_data = true;
 }

 static void NET_CL_ParseGameStart(net_packet_t *packet)
@@ -1164,8 +1186,8 @@ static void NET_CL_SendSYN(void)
     NET_WriteInt16(packet, gamemission);
     NET_WriteInt8(packet, lowres_turn);
     NET_WriteInt8(packet, drone);
-    NET_WriteMD5Sum(packet, wad_md5sum);
-    NET_WriteMD5Sum(packet, deh_md5sum);
+    NET_WriteMD5Sum(packet, net_local_wad_md5sum);
+    NET_WriteMD5Sum(packet, net_local_deh_md5sum);
     NET_WriteString(packet, net_player_name);
     NET_Conn_SendPacket(&client_connection, packet);
     NET_FreePacket(packet);
@@ -1189,8 +1211,8 @@ boolean NET_CL_Connect(net_addr_t *addr)

     // Read checksums of our WAD directory and dehacked information

-    W_Checksum(wad_md5sum);
-    DEH_Checksum(deh_md5sum);
+    W_Checksum(net_local_wad_md5sum);
+    DEH_Checksum(net_local_deh_md5sum);

     // create a new network I/O context and add just the
     // necessary module
@@ -1207,6 +1229,7 @@ boolean NET_CL_Connect(net_addr_t *addr)
     NET_AddModule(client_context, addr->module);

     net_client_connected = true;
+    net_client_received_wait_data = false;

     // Initialise connection

diff --git a/src/net_client.h b/src/net_client.h
index 56c327c8..abc0f5bd 100644
--- a/src/net_client.h
+++ b/src/net_client.h
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*-
 //-----------------------------------------------------------------------------
 //
-// $Id: net_client.h 680 2006-09-29 21:25:13Z fraggle $
+// $Id: net_client.h 689 2006-10-06 17:06:05Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -70,6 +70,7 @@
 #include "doomdef.h"
 #include "doomtype.h"
 #include "d_ticcmd.h"
+#include "md5.h"
 #include "net_defs.h"

 #define MAXPLAYERNAME 30
@@ -83,6 +84,7 @@ void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic);
 void NET_Init(void);

 extern boolean net_client_connected;
+extern boolean net_client_received_wait_data;
 extern boolean net_client_controller;
 extern int net_clients_in_game;
 extern boolean net_waiting_for_start;
@@ -93,5 +95,11 @@ extern char *net_player_name;
 extern boolean net_cl_new_sync;
 extern boolean drone;

+extern md5_digest_t net_server_wad_md5sum;
+extern md5_digest_t net_server_deh_md5sum;
+extern md5_digest_t net_local_wad_md5sum;
+extern md5_digest_t net_local_deh_md5sum;
+
+
 #endif /* #ifndef NET_CLIENT_H */

diff --git a/src/net_gui.c b/src/net_gui.c
index ede55cbb..9e98739d 100644
--- a/src/net_gui.c
+++ b/src/net_gui.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*-
 //-----------------------------------------------------------------------------
 //
-// $Id: net_gui.c 579 2006-08-31 18:12:25Z fraggle $
+// $Id: net_gui.c 689 2006-10-06 17:06:05Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -93,6 +93,7 @@
 static txt_window_t *window;
 static txt_label_t *player_labels[MAXPLAYERS];
 static txt_label_t *ip_labels[MAXPLAYERS];
+static boolean had_warning;

 static void EscapePressed(TXT_UNCAST_ARG(widget), void *unused)
 {
@@ -112,6 +113,8 @@ static void BuildGUI(void)
     txt_window_action_t *cancel;
     int i;

+    had_warning = false;
+
     TXT_SetDesktopTitle(PACKAGE_STRING);

     window = TXT_NewWindow("Waiting for game start...");
@@ -186,6 +189,51 @@ static void UpdateGUI(void)
     TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, startgame);
 }

+static void CheckMD5Sums(void)
+{
+    boolean correct_wad, correct_deh;
+    txt_window_t *window;
+
+    if (!net_client_received_wait_data || had_warning)
+    {
+        return;
+    }
+
+    correct_wad = memcmp(net_local_wad_md5sum, net_server_wad_md5sum,
+                         sizeof(md5_digest_t)) == 0;
+    correct_deh = memcmp(net_local_deh_md5sum, net_server_deh_md5sum,
+                         sizeof(md5_digest_t)) == 0;
+
+    if (correct_wad && correct_deh)
+    {
+        return;
+    }
+
+    window = TXT_NewWindow("WARNING");
+
+    TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
+
+    if (!correct_wad)
+    {
+        TXT_AddWidget(window, TXT_NewLabel
+            ("Your WAD directory does not match other players in the game.\n"
+             "Check that you have loaded all the same WAD files as other\n"
+             "players.\n"));
+    }
+    if (!correct_deh)
+    {
+        TXT_AddWidget(window, TXT_NewLabel
+            ("Your dehacked signature does not match other players in the\n"
+             "game.  Check that you have loaded the same dehacked patches\n"
+             "as other players.\n"));
+    }
+
+    TXT_AddWidget(window, TXT_NewLabel
+            ("If you continue, this may cause your game to desync."));
+
+    had_warning = true;
+}
+
 void NET_WaitForStart(void)
 {
     TXT_Init();
@@ -197,6 +245,7 @@ void NET_WaitForStart(void)
     while (net_waiting_for_start)
     {
         UpdateGUI();
+        CheckMD5Sums();

         TXT_DispatchEvents();
         TXT_DrawDesktop();
diff --git a/src/net_server.c b/src/net_server.c
index 4628e7e7..478fbd6c 100644
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -1,7 +1,7 @@
 // Emacs style mode select   -*- C++ -*-
 //-----------------------------------------------------------------------------
 //
-// $Id: net_server.c 688 2006-10-06 07:02:42Z fraggle $
+// $Id: net_server.c 689 2006-10-06 17:06:05Z fraggle $
 //
 // Copyright(C) 2005 Simon Howard
 //
@@ -221,6 +221,11 @@ typedef struct

     boolean drone;

+    // MD5 hash sums of the client's WAD directory and dehacked data
+
+    md5_digest_t wad_md5sum;
+    md5_digest_t deh_md5sum;
+
 } net_client_t;

 // structure used for the recv window
@@ -252,7 +257,6 @@ static net_context_t *server_context;
 static int sv_gamemode;
 static int sv_gamemission;
 static net_gamesettings_t sv_settings;
-static md5_digest_t sv_wad_md5sum, sv_deh_md5sum;

 // receive window

@@ -686,10 +690,13 @@ static void NET_SV_ParseSYN(net_packet_t *packet,
         {
             sv_gamemode = cl_gamemode;
             sv_gamemission = cl_gamemission;
-            memcpy(sv_wad_md5sum, wad_md5sum, sizeof(md5_digest_t));
-            memcpy(sv_deh_md5sum, deh_md5sum, sizeof(md5_digest_t));
         }

+        // Save the MD5 checksums
+
+        memcpy(client->wad_md5sum, wad_md5sum, sizeof(md5_digest_t));
+        memcpy(client->deh_md5sum, deh_md5sum, sizeof(md5_digest_t));
+
         // Check the connecting client is playing the same game as all
         // the other clients

@@ -1265,11 +1272,14 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr)
 static void NET_SV_SendWaitingData(net_client_t *client)
 {
     net_packet_t *packet;
+    net_client_t *controller;
     int num_players;
     int i;

     NET_SV_AssignPlayers();

+    controller = NET_SV_Controller();
+
     num_players = NET_SV_NumPlayers();

     // time to send the client another status packet
@@ -1283,13 +1293,13 @@ static void NET_SV_SendWaitingData(net_client_t *client)

     // indicate whether the client is the controller

-    NET_WriteInt8(packet, NET_SV_Controller() == client);
+    NET_WriteInt8(packet, client == controller);

     // send the player number of this client

     NET_WriteInt8(packet, client->player_number);

-    // send the address of all players
+    // send the addresses of all players

     for (i=0; i<num_players; ++i)
     {
@@ -1305,7 +1315,20 @@ static void NET_SV_SendWaitingData(net_client_t *client)

         NET_WriteString(packet, addr);
     }
-
+
+    // Send the WAD and dehacked checksums of the controlling client.
+
+    if (controller != NULL)
+    {
+        NET_WriteMD5Sum(packet, controller->wad_md5sum);
+        NET_WriteMD5Sum(packet, controller->deh_md5sum);
+    }
+    else
+    {
+        NET_WriteMD5Sum(packet, client->wad_md5sum);
+        NET_WriteMD5Sum(packet, client->deh_md5sum);
+    }
+
     // send packet to client and free

     NET_Conn_SendPacket(&client->connection, packet);