1 // SONIC ROBO BLAST 2
2 //-----------------------------------------------------------------------------
3 // Copyright (C) 1998-2000 by DooM Legacy Team.
4 // Copyright (C) 1999-2020 by Sonic Team Junior.
5 //
6 // This program is free software distributed under the
7 // terms of the GNU General Public License, version 2.
8 // See the 'LICENSE' file for more details.
9 //-----------------------------------------------------------------------------
10 /// \file  d_clisrv.h
11 /// \brief high level networking stuff
12 
13 #ifndef __D_CLISRV__
14 #define __D_CLISRV__
15 
16 #include "d_ticcmd.h"
17 #include "d_net.h"
18 #include "d_netcmd.h"
19 #include "d_net.h"
20 #include "tables.h"
21 #include "d_player.h"
22 #include "mserv.h"
23 
24 /*
25 The 'packet version' is used to distinguish packet formats.
26 This version is independent of VERSION and SUBVERSION. Different
27 applications may follow different packet versions.
28 */
29 #define PACKETVERSION 3
30 
31 // Network play related stuff.
32 // There is a data struct that stores network
33 //  communication related stuff, and another
34 //  one that defines the actual packets to
35 //  be transmitted.
36 
37 // Networking and tick handling related.
38 #define BACKUPTICS 1024
39 #define CLIENTBACKUPTICS 32
40 #define MAXTEXTCMD 256
41 //
42 // Packet structure
43 //
44 typedef enum
45 {
46 	PT_NOTHING,       // To send a nop through the network. ^_~
47 	PT_SERVERCFG,     // Server config used in start game
48 	                  // (must stay 1 for backwards compatibility).
49 	                  // This is a positive response to a CLIENTJOIN request.
50 	PT_CLIENTCMD,     // Ticcmd of the client.
51 	PT_CLIENTMIS,     // Same as above with but saying resend from.
52 	PT_CLIENT2CMD,    // 2 cmds in the packet for splitscreen.
53 	PT_CLIENT2MIS,    // Same as above with but saying resend from
54 	PT_NODEKEEPALIVE, // Same but without ticcmd and consistancy
55 	PT_NODEKEEPALIVEMIS,
56 	PT_SERVERTICS,    // All cmds for the tic.
57 	PT_SERVERREFUSE,  // Server refuses joiner (reason inside).
58 	PT_SERVERSHUTDOWN,
59 	PT_CLIENTQUIT,    // Client closes the connection.
60 
61 	PT_ASKINFO,       // Anyone can ask info of the server.
62 	PT_SERVERINFO,    // Send game & server info (gamespy).
63 	PT_PLAYERINFO,    // Send information for players in game (gamespy).
64 	PT_REQUESTFILE,   // Client requests a file transfer
65 	PT_ASKINFOVIAMS,  // Packet from the MS requesting info be sent to new client.
66 	                  // If this ID changes, update masterserver definition.
67 
68 	PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
69 	PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
70 	PT_RECEIVEDGAMESTATE,   // Thank you Server, I am ready to play again!
71 
72 	PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
73 	PT_ASKLUAFILE,     // Client telling the server they don't have the file
74 	PT_HASLUAFILE,     // Client telling the server they have the file
75 
76 	// Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility.
77 
78 	PT_CANFAIL,       // This is kind of a priority. Anything bigger than CANFAIL
79 	                  // allows HSendPacket(*, true, *, *) to return false.
80 	                  // In addition, this packet can't occupy all the available slots.
81 
82 	PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file.
83 	PT_FILEACK,
84 	PT_FILERECEIVED,
85 
86 	PT_TEXTCMD,       // Extra text commands from the client.
87 	PT_TEXTCMD2,      // Splitscreen text commands.
88 	PT_CLIENTJOIN,    // Client wants to join; used in start game.
89 	PT_NODETIMEOUT,   // Packet sent to self if the connection times out.
90 
91 	PT_LOGIN,         // Login attempt from the client.
92 
93 	PT_PING,          // Packet sent to tell clients the other client's latency to server.
94 	NUMPACKETTYPE
95 } packettype_t;
96 
97 #ifdef PACKETDROP
98 void Command_Drop(void);
99 void Command_Droprate(void);
100 #endif
101 #ifdef _DEBUG
102 void Command_Numnodes(void);
103 #endif
104 
105 #if defined(_MSC_VER)
106 #pragma pack(1)
107 #endif
108 
109 // Client to server packet
110 typedef struct
111 {
112 	UINT8 client_tic;
113 	UINT8 resendfrom;
114 	INT16 consistancy;
115 	ticcmd_t cmd;
116 } ATTRPACK clientcmd_pak;
117 
118 // Splitscreen packet
119 // WARNING: must have the same format of clientcmd_pak, for more easy use
120 typedef struct
121 {
122 	UINT8 client_tic;
123 	UINT8 resendfrom;
124 	INT16 consistancy;
125 	ticcmd_t cmd, cmd2;
126 } ATTRPACK client2cmd_pak;
127 
128 #ifdef _MSC_VER
129 #pragma warning(disable :  4200)
130 #endif
131 
132 // Server to client packet
133 // this packet is too large
134 typedef struct
135 {
136 	tic_t starttic;
137 	UINT8 numtics;
138 	UINT8 numslots; // "Slots filled": Highest player number in use plus one.
139 	ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
140 } ATTRPACK servertics_pak;
141 
142 typedef struct
143 {
144 	UINT8 version; // Different versions don't work
145 	UINT8 subversion; // Contains build version
146 
147 	// Server launch stuffs
148 	UINT8 serverplayer;
149 	UINT8 totalslotnum; // "Slots": highest player number in use plus one.
150 
151 	tic_t gametic;
152 	UINT8 clientnode;
153 	UINT8 gamestate;
154 
155 	UINT8 gametype;
156 	UINT8 modifiedgame;
157 
158 	char server_context[8]; // Unique context id, generated at server startup.
159 } ATTRPACK serverconfig_pak;
160 
161 typedef struct
162 {
163 	UINT8 fileid;
164 	UINT32 filesize;
165 	UINT8 iteration;
166 	UINT32 position;
167 	UINT16 size;
168 	UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH
169 } ATTRPACK filetx_pak;
170 
171 typedef struct
172 {
173 	UINT32 start;
174 	UINT32 acks;
175 } ATTRPACK fileacksegment_t;
176 
177 typedef struct
178 {
179 	UINT8 fileid;
180 	UINT8 iteration;
181 	UINT8 numsegments;
182 	fileacksegment_t segments[0];
183 } ATTRPACK fileack_pak;
184 
185 #ifdef _MSC_VER
186 #pragma warning(default : 4200)
187 #endif
188 
189 #define MAXAPPLICATION 16
190 
191 typedef struct
192 {
193 	UINT8 _255;/* see serverinfo_pak */
194 	UINT8 packetversion;
195 	char application[MAXAPPLICATION];
196 	UINT8 version; // Different versions don't work
197 	UINT8 subversion; // Contains build version
198 	UINT8 localplayers;
199 	UINT8 mode;
200 	char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
201 } ATTRPACK clientconfig_pak;
202 
203 #define MAXSERVERNAME 32
204 #define MAXFILENEEDED 915
205 // This packet is too large
206 typedef struct
207 {
208 	/*
209 	In the old packet, 'version' is the first field. Now that field is set
210 	to 255 always, so older versions won't be confused with the new
211 	versions or vice-versa.
212 	*/
213 	UINT8 _255;
214 	UINT8 packetversion;
215 	char  application[MAXAPPLICATION];
216 	UINT8 version;
217 	UINT8 subversion;
218 	UINT8 numberofplayer;
219 	UINT8 maxplayer;
220 	UINT8 refusereason; // 0: joinable, 1: joins disabled, 2: full
221 	char gametypename[24];
222 	UINT8 modifiedgame;
223 	UINT8 cheatsenabled;
224 	UINT8 isdedicated;
225 	UINT8 fileneedednum;
226 	tic_t time;
227 	tic_t leveltime;
228 	char servername[MAXSERVERNAME];
229 	char mapname[8];
230 	char maptitle[33];
231 	unsigned char mapmd5[16];
232 	UINT8 actnum;
233 	UINT8 iszone;
234 	UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
235 } ATTRPACK serverinfo_pak;
236 
237 typedef struct
238 {
239 	char reason[255];
240 } ATTRPACK serverrefuse_pak;
241 
242 typedef struct
243 {
244 	UINT8 version;
245 	tic_t time; // used for ping evaluation
246 } ATTRPACK askinfo_pak;
247 
248 typedef struct
249 {
250 	char clientaddr[22];
251 	tic_t time; // used for ping evaluation
252 } ATTRPACK msaskinfo_pak;
253 
254 // Shorter player information for external use.
255 typedef struct
256 {
257 	UINT8 num;
258 	char name[MAXPLAYERNAME+1];
259 	UINT8 address[4]; // sending another string would run us up against MAXPACKETLENGTH
260 	UINT8 team;
261 	UINT8 skin;
262 	UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused.
263 	UINT32 score;
264 	UINT16 timeinserver; // In seconds.
265 } ATTRPACK plrinfo;
266 
267 // Shortest player information for join during intermission.
268 typedef struct
269 {
270 	char name[MAXPLAYERNAME+1];
271 	UINT8 skin;
272 	UINT16 color;
273 	UINT32 pflags;
274 	UINT32 score;
275 	UINT8 ctfteam;
276 } ATTRPACK plrconfig;
277 
278 //
279 // Network packet data
280 //
281 typedef struct
282 {
283 	UINT32 checksum;
284 	UINT8 ack; // If not zero the node asks for acknowledgement, the receiver must resend the ack
285 	UINT8 ackreturn; // The return of the ack number
286 
287 	UINT8 packettype;
288 	UINT8 reserved; // Padding
289 	union
290 	{
291 		clientcmd_pak clientpak;            //         144 bytes
292 		client2cmd_pak client2pak;          //         200 bytes
293 		servertics_pak serverpak;           //      132495 bytes (more around 360, no?)
294 		serverconfig_pak servercfg;         //         773 bytes
295 		UINT8 textcmd[MAXTEXTCMD+1];        //       66049 bytes (wut??? 64k??? More like 257 bytes...)
296 		filetx_pak filetxpak;               //         139 bytes
297 		fileack_pak fileack;
298 		UINT8 filereceived;
299 		clientconfig_pak clientcfg;         //         136 bytes
300 		UINT8 md5sum[16];
301 		serverinfo_pak serverinfo;          //        1024 bytes
302 		serverrefuse_pak serverrefuse;      //       65025 bytes (somehow I feel like those values are garbage...)
303 		askinfo_pak askinfo;                //          61 bytes
304 		msaskinfo_pak msaskinfo;            //          22 bytes
305 		plrinfo playerinfo[MAXPLAYERS];     //         576 bytes(?)
306 		plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
307 		UINT32 pingtable[MAXPLAYERS+1];     //          68 bytes
308 	} u; // This is needed to pack diff packet types data together
309 } ATTRPACK doomdata_t;
310 
311 #if defined(_MSC_VER)
312 #pragma pack()
313 #endif
314 
315 #define MAXSERVERLIST (MAXNETNODES-1)
316 typedef struct
317 {
318 	SINT8 node;
319 	serverinfo_pak info;
320 } serverelem_t;
321 
322 extern serverelem_t serverlist[MAXSERVERLIST];
323 extern UINT32 serverlistcount;
324 extern INT32 mapchangepending;
325 
326 // Points inside doomcom
327 extern doomdata_t *netbuffer;
328 
329 extern consvar_t cv_showjoinaddress;
330 extern consvar_t cv_playbackspeed;
331 
332 #define BASEPACKETSIZE      offsetof(doomdata_t, u)
333 #define FILETXHEADER        offsetof(filetx_pak, data)
334 #define BASESERVERTICSSIZE  offsetof(doomdata_t, u.serverpak.cmds[0])
335 
336 #define KICK_MSG_GO_AWAY     1
337 #define KICK_MSG_CON_FAIL    2
338 #define KICK_MSG_PLAYER_QUIT 3
339 #define KICK_MSG_TIMEOUT     4
340 #define KICK_MSG_BANNED      5
341 #define KICK_MSG_PING_HIGH   6
342 #define KICK_MSG_CUSTOM_KICK 7
343 #define KICK_MSG_CUSTOM_BAN  8
344 #define KICK_MSG_KEEP_BODY   0x80
345 
346 typedef enum
347 {
348 	KR_KICK          = 1, //Kicked by server
349 	KR_PINGLIMIT     = 2, //Broke Ping Limit
350 	KR_SYNCH         = 3, //Synch Failure
351 	KR_TIMEOUT       = 4, //Connection Timeout
352 	KR_BAN           = 5, //Banned by server
353 	KR_LEAVE         = 6, //Quit the game
354 
355 } kickreason_t;
356 
357 /* the max number of name changes in some time period */
358 #define MAXNAMECHANGES (5)
359 #define NAMECHANGERATE (60*TICRATE)
360 
361 extern boolean server;
362 extern boolean serverrunning;
363 #define client (!server)
364 extern boolean dedicated; // For dedicated server
365 extern UINT16 software_MAXPACKETLENGTH;
366 extern boolean acceptnewnode;
367 extern SINT8 servernode;
368 
369 void Command_Ping_f(void);
370 extern tic_t connectiontimeout;
371 extern tic_t jointimeout;
372 extern UINT16 pingmeasurecount;
373 extern UINT32 realpingtable[MAXPLAYERS];
374 extern UINT32 playerpingtable[MAXPLAYERS];
375 extern tic_t servermaxping;
376 
377 extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout;
378 extern consvar_t cv_resynchattempts, cv_blamecfail;
379 extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
380 
381 // Used in d_net, the only dependence
382 tic_t ExpandTics(INT32 low, INT32 node);
383 void D_ClientServerInit(void);
384 
385 // Initialise the other field
386 void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum));
387 void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam);
388 void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player
389 void SendKick(UINT8 playernum, UINT8 msg);
390 
391 // Create any new ticcmds and broadcast to other players.
392 void NetUpdate(void);
393 
394 void SV_StartSinglePlayerServer(void);
395 boolean SV_SpawnServer(void);
396 void SV_StopServer(void);
397 void SV_ResetServer(void);
398 void CL_AddSplitscreenPlayer(void);
399 void CL_RemoveSplitscreenPlayer(void);
400 void CL_Reset(void);
401 void CL_ClearPlayer(INT32 playernum);
402 void CL_QueryServerList(msg_server_t *list);
403 void CL_UpdateServerList(boolean internetsearch, INT32 room);
404 // Is there a game running
405 boolean Playing(void);
406 
407 // Broadcasts special packets to other players
408 //  to notify of game exit
409 void D_QuitNetGame(void);
410 
411 //? How many ticks to run?
412 void TryRunTics(tic_t realtic);
413 
414 // extra data for lmps
415 // these functions scare me. they contain magic.
416 /*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum);
417 void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum);*/
418 
419 #ifndef NONET
420 // translate a playername in a player number return -1 if not found and
421 // print a error message in the console
422 SINT8 nametonum(const char *name);
423 #endif
424 
425 extern char motd[254], server_context[8];
426 extern UINT8 playernode[MAXPLAYERS];
427 
428 INT32 D_NumPlayers(void);
429 void D_ResetTiccmds(void);
430 
431 tic_t GetLag(INT32 node);
432 UINT8 GetFreeXCmdSize(void);
433 
434 void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
435 
436 extern UINT8 hu_redownloadinggamestate;
437 
438 extern UINT8 adminpassmd5[16];
439 extern boolean adminpasswordset;
440 #endif
441