DEADSOFTWARE

added network packet dumping
[d2df-sdl.git] / src / game / g_net.pas
index a1c07701018a99b84c38dcf198214d923bbd0e77..944ce6f6727eb3746ff56c901238e6ccecbaa035 100644 (file)
@@ -1,12 +1,28 @@
+(* Copyright (C)  DooM 2D:Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$MODE DELPHI}
 unit g_net;
 
 interface
 
 uses
-  e_log, e_fixedbuffer, ENet, ENetTypes, ENetPlatform, Classes;
+  e_log, e_fixedbuffer, ENet, Classes;
 
 const
-  NET_PROTOCOL_VER = 164;
+  NET_PROTOCOL_VER = 171;
 
   NET_MAXCLIENTS = 24;
   NET_CHANS = 11;
@@ -47,6 +63,7 @@ const
   NET_STATE_GAME = 2;
 
   BANLIST_FILENAME = 'banlist.txt';
+  NETDUMP_FILENAME = 'netdump';
 
 type
   TNetClient = record
@@ -70,6 +87,7 @@ type
 var
   NetInitDone:     Boolean = False;
   NetMode:         Byte = NET_NONE;
+  NetDump:         Boolean = False;
 
   NetServerName:   string = 'Unnamed Server';
   NetPassword:     string = '';
@@ -122,6 +140,8 @@ var
 
   NetGotEverything: Boolean = False;
 
+  NetDumpFile: TStream;
+
 function  g_Net_Init(): Boolean;
 procedure g_Net_Cleanup();
 procedure g_Net_Free();
@@ -156,12 +176,17 @@ function  g_Net_UnbanHost(IP: LongWord): Boolean; overload;
 procedure g_Net_UnbanNonPermHosts();
 procedure g_Net_SaveBanList();
 
+procedure g_Net_DumpStart();
+procedure g_Net_DumpSendBuffer();
+procedure g_Net_DumpRecvBuffer(Buf: penet_uint8; Len: LongWord);
+procedure g_Net_DumpEnd();
+
 implementation
 
 uses
   SysUtils,
   e_input, g_nethandler, g_netmsg, g_netmaster, g_player, g_window, g_console,
-  g_main, g_game, g_language, g_weapons;
+  g_main, g_game, g_language, g_weapons, utils;
 
 
 { /// SERVICE FUNCTIONS /// }
@@ -279,6 +304,9 @@ begin
   NetTimeToReliable := 0;
 
   NetMode := NET_NONE;
+
+  if NetDump then
+    g_Net_DumpEnd();
 end;
 
 procedure g_Net_Free();
@@ -346,6 +374,9 @@ begin
 
   NetMode := NET_SERVER;
   e_Buffer_Clear(@NetOut);
+
+  if NetDump then
+    g_Net_DumpStart();
 end;
 
 procedure g_Net_Host_Die();
@@ -412,9 +443,10 @@ begin
     P := enet_packet_create(Addr(NetOut.Data), NetOut.Len, F);
     if not Assigned(P) then Exit;
 
-    enet_host_widecast(NetHost, Chan, P);
+    enet_host_broadcast(NetHost, Chan, P);
   end;
 
+  if NetDump then g_Net_DumpSendBuffer();
   g_Net_Flush();
   e_Buffer_Clear(@NetOut);
 end;
@@ -423,14 +455,15 @@ procedure g_Net_Host_CheckPings();
 var
   ClAddr: ENetAddress;
   Buf: ENetBuffer;
-  Len, ClTime: Integer;
-  Ping: array [0..5] of Byte;
+  Len: Integer;
+  ClTime: Int64;
+  Ping: array [0..9] of Byte;
   NPl: Byte;
 begin
   if NetPongSock = ENET_SOCKET_NULL then Exit;
 
   Buf.data := Addr(Ping[0]);
-  Buf.dataLength := 6;
+  Buf.dataLength := 2+8;
 
   Ping[0] := 0;
 
@@ -439,7 +472,7 @@ begin
 
   if (Ping[0] = Ord('D')) and (Ping[1] = Ord('F')) then
   begin
-    ClTime := Integer(Addr(Ping[2])^);
+    ClTime := Int64(Addr(Ping[2])^);
 
     e_Buffer_Clear(@NetOut);
     e_Buffer_Write(@NetOut, Byte(Ord('D')));
@@ -529,13 +562,14 @@ begin
         if ID > High(NetClients) then Exit;
         TC := @NetClients[ID];
 
+        if NetDump then g_Net_DumpRecvBuffer(NetEvent.packet^.data, NetEvent.packet^.dataLength);
         g_Net_HostMsgHandler(TC, NetEvent.packet);
       end;
 
       ENET_EVENT_TYPE_DISCONNECT:
       begin
         ID := Byte(NetEvent.peer^.data^);
-        if ID > High(NetClients) then Exit;     
+        if ID > High(NetClients) then Exit;
         TC := @NetClients[ID];
         if TC = nil then Exit;
 
@@ -633,6 +667,7 @@ begin
   if not Assigned(P) then Exit;
 
   enet_peer_send(NetPeer, Chan, P);
+  if NetDump then g_Net_DumpSendBuffer();
   g_Net_Flush();
   e_Buffer_Clear(@NetOut);
 end;
@@ -644,7 +679,10 @@ begin
   begin
     case NetEvent.kind of
       ENET_EVENT_TYPE_RECEIVE:
+      begin
+        if NetDump then g_Net_DumpRecvBuffer(NetEvent.packet^.data, NetEvent.packet^.dataLength);
         g_Net_ClientMsgHandler(NetEvent.packet);
+      end;
 
       ENET_EVENT_TYPE_DISCONNECT:
       begin
@@ -663,7 +701,10 @@ begin
   begin
     case NetEvent.kind of
       ENET_EVENT_TYPE_RECEIVE:
+      begin
+        if NetDump then g_Net_DumpRecvBuffer(NetEvent.packet^.data, NetEvent.packet^.dataLength);
         g_Net_ClientLightMsgHandler(NetEvent.packet);
+      end;
 
       ENET_EVENT_TYPE_DISCONNECT:
       begin
@@ -740,12 +781,14 @@ begin
         enet_peer_timeout(NetPeer, ENET_PEER_TIMEOUT_LIMIT * 2, ENET_PEER_TIMEOUT_MINIMUM * 2, ENET_PEER_TIMEOUT_MAXIMUM * 2);
         NetClientIP := IP;
         NetClientPort := Port;
+        if NetDump then
+          g_Net_DumpStart();
         Exit;
       end;
     end;
 
     ProcessLoading();
-    
+
     e_PollInput();
 
     if e_KeyPressed(IK_ESCAPE) or e_KeyPressed(IK_SPACE) then
@@ -860,7 +903,7 @@ begin
   begin
     P := enet_packet_create(@Data[0], dataLength, F);
     if not Assigned(P) then Exit;
-    enet_host_widecast(NetHost, Chan, P);
+    enet_host_broadcast(NetHost, Chan, P);
   end;
 
   enet_host_flush(NetHost);
@@ -1031,4 +1074,35 @@ begin
   CloseFile(F);
 end;
 
+procedure g_Net_DumpStart();
+begin
+  if NetMode = NET_SERVER then
+    NetDumpFile := createDiskFile(NETDUMP_FILENAME + '_server')
+  else
+    NetDumpFile := createDiskFile(NETDUMP_FILENAME + '_client');
+end;
+
+procedure g_Net_DumpSendBuffer();
+begin
+  writeInt(NetDumpFile, gTime);
+  writeInt(NetDumpFile, LongWord(NetOut.Len));
+  writeInt(NetDumpFile, Byte(1));
+  NetDumpFile.WriteBuffer(NetOut.Data[0], NetOut.Len);
+end;
+
+procedure g_Net_DumpRecvBuffer(Buf: penet_uint8; Len: LongWord);
+begin
+  if (Buf = nil) or (Len = 0) then Exit;
+  writeInt(NetDumpFile, gTime);
+  writeInt(NetDumpFile, Len);
+  writeInt(NetDumpFile, Byte(0));
+  NetDumpFile.WriteBuffer(Buf^, Len);
+end;
+
+procedure g_Net_DumpEnd();
+begin
+  NetDumpFile.Free();
+  NetDumpFile := nil;
+end;
+
 end.