-
Notifications
You must be signed in to change notification settings - Fork 167
/
net.h
431 lines (362 loc) · 11.7 KB
/
net.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
/*
*
* 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 2 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "maintypes.h"
#include "common.h"
#include "enums.h"
#include "netadr.h"
const int PROTOCOL_VERSION = 48;
// MAX_CHALLENGES is made large to prevent a denial
// of service attack that could cycle all of them
// out before legitimate users connected
#ifdef REHLDS_OPT_PEDANTIC
const int MAX_CHALLENGES = 64;
#else
const int MAX_CHALLENGES = 1024;
#endif // REHLDS_OPT_PEDANTIC
// Client connection is initiated by requesting a challenge value
// the server sends this value back
const char S2C_CHALLENGE = 'A'; // + challenge value
// Send a userid, client remote address, is this server secure and engine build number
const char S2C_CONNECTION = 'B';
// HLMaster rejected a server's connection because the server needs to be updated
const char M2S_REQUESTRESTART = 'O';
// Response details about each player on the server
const char S2A_PLAYERS = 'D';
// Number of rules + string key and string value pairs
const char S2A_RULES = 'E';
// info request
const char S2A_INFO = 'C'; // deprecated goldsrc response
const char S2A_INFO_DETAILED = 'm'; // New Query protocol, returns dedicated or not, + other performance info.
// send a log event as key value
const char S2A_LOGSTRING = 'R';
// Send a log string
const char S2A_LOGKEY = 'S';
// Basic information about the server
const char A2S_INFO = 'T';
// Details about each player on the server
const char A2S_PLAYER = 'U';
// The rules the server is using
const char A2S_RULES = 'V';
// Another user is requesting a challenge value from this machine
const char A2A_GETCHALLENGE = 'W'; // Request challenge # from another machine
// Generic Ping Request
const char A2A_PING = 'i'; // respond with an A2A_ACK
// Generic Ack
const char A2A_ACK = 'j'; // general acknowledgement without info
// Print to client console
const char A2A_PRINT = 'l'; // print a message on client
// Challenge response from master
const char M2A_CHALLENGE = 's'; // + challenge value
// 0 == regular, 1 == file stream
enum
{
FRAG_NORMAL_STREAM = 0,
FRAG_FILE_STREAM,
MAX_STREAMS
};
// Flow control bytes per second limits
const float MAX_RATE = 100000.0f;
const float MIN_RATE = 1000.0f;
// Default data rate
const float DEFAULT_RATE = 30000.0f;
// NETWORKING INFO
// Max size of udp packet payload
const int MAX_UDP_PACKET = 4010; // 9 bytes SPLITHEADER + 4000 payload?
// Max length of a reliable message
const int MAX_MSGLEN = 3990; // 10 reserved for fragheader?
// Max length of unreliable message
const int MAX_DATAGRAM = 4000;
// This is the packet payload without any header bytes (which are attached for actual sending)
const int NET_MAX_PAYLOAD = 65536;
// This is the payload plus any header info (excluding UDP header)
// Packet header is:
// 4 bytes of outgoing seq
// 4 bytes of incoming seq
// and for each stream
// {
// byte (on/off)
// int (fragment id)
// short (startpos)
// short (length)
// }
#define HEADER_BYTES (8 + MAX_STREAMS * 9)
// Pad this to next higher 16 byte boundary
// This is the largest packet that can come in/out over the wire, before processing the header
// bytes will be stripped by the networking channel layer
//#define NET_MAX_MESSAGE PAD_NUMBER( ( MAX_MSGLEN + HEADER_BYTES ), 16 )
// This is currently used value in the engine. TODO: define above gives 4016, check it why.
const int NET_MAX_MESSAGE = 4037;
typedef enum svc_commands_e
{
svc_bad,
svc_nop,
svc_disconnect,
svc_event,
svc_version,
svc_setview,
svc_sound,
svc_time,
svc_print,
svc_stufftext,
svc_setangle,
svc_serverinfo,
svc_lightstyle,
svc_updateuserinfo,
svc_deltadescription,
svc_clientdata,
svc_stopsound,
svc_pings,
svc_particle,
svc_damage,
svc_spawnstatic,
svc_event_reliable,
svc_spawnbaseline,
svc_temp_entity,
svc_setpause,
svc_signonnum,
svc_centerprint,
svc_killedmonster,
svc_foundsecret,
svc_spawnstaticsound,
svc_intermission,
svc_finale,
svc_cdtrack,
svc_restore,
svc_cutscene,
svc_weaponanim,
svc_decalname,
svc_roomtype,
svc_addangle,
svc_newusermsg,
svc_packetentities,
svc_deltapacketentities,
svc_choke,
svc_resourcelist,
svc_newmovevars,
svc_resourcerequest,
svc_customization,
svc_crosshairangle,
svc_soundfade,
svc_filetxferfailed,
svc_hltv,
svc_director,
svc_voiceinit,
svc_voicedata,
svc_sendextrainfo,
svc_timescale,
svc_resourcelocation,
svc_sendcvarvalue,
svc_sendcvarvalue2,
svc_exec,
svc_reserve60,
svc_reserve61,
svc_reserve62,
svc_reserve63,
// Let's just use an id of the first user message instead of the last svc_*
// This change makes code in `PF_MessageEnd_I` forward-compatible with future svc_* additions
#ifdef REHLDS_FIXES
svc_startofusermessages = svc_reserve63 + 1,
#else // REHLDS_FIXES
svc_startofusermessages = svc_exec,
#endif // REHLDS_FIXES
svc_endoflist = 255,
} svc_commands_t;
#ifdef REHLDS_FIXES
static_assert(svc_startofusermessages == 64, "svc_startofusermessages should be equal to 64 for backward and forward compatibility");
#endif // REHLDS_FIXES
typedef enum clc_commands_e
{
clc_bad,
clc_nop,
clc_move,
clc_stringcmd,
clc_delta,
clc_resourcelist,
clc_tmove,
clc_fileconsistency,
clc_voicedata,
clc_hltv,
clc_cvarvalue,
clc_cvarvalue2,
clc_endoflist = 255,
} clc_commands_t;
enum
{
FLOW_OUTGOING = 0,
FLOW_INCOMING,
MAX_FLOWS
};
// Message data
typedef struct flowstats_s
{
// Size of message sent/received
int size;
// Time that message was sent/received
double time;
} flowstats_t;
const int MAX_LATENT = 32;
typedef struct flow_s
{
// Data for last MAX_LATENT messages
flowstats_t stats[MAX_LATENT];
// Current message position
int current;
// Time when we should recompute k/sec data
double nextcompute;
// Average data
float kbytespersec;
float avgkbytespersec;
} flow_t;
const int FRAGMENT_C2S_MIN_SIZE = 16;
const int FRAGMENT_S2C_MIN_SIZE = 256;
const int FRAGMENT_S2C_MAX_SIZE = 1024;
const int CLIENT_FRAGMENT_SIZE_ONCONNECT = 128;
const int CUSTOMIZATION_MAX_SIZE = 20480;
#ifndef REHLDS_FIXES
// Size of fragmentation buffer internal buffers
const int FRAGMENT_MAX_SIZE = 1400;
const int MAX_FRAGMENTS = 25000;
#else
const int FRAGMENT_MAX_SIZE = 1024;
// Client sends normal fragments only while connecting
#define MAX_NORMAL_FRAGMENTS (NET_MAX_PAYLOAD / CLIENT_FRAGMENT_SIZE_ONCONNECT)
// While client is connecting it sending fragments with minimal size, also it transfers sprays with minimal fragments...
// But with sv_delayed_spray_upload it sends with cl_dlmax fragment size
#define MAX_FILE_FRAGMENTS (CUSTOMIZATION_MAX_SIZE / FRAGMENT_C2S_MIN_SIZE)
#endif
const int UDP_HEADER_SIZE = 28;
const int MAX_RELIABLE_PAYLOAD = 1200;
#define MAKE_FRAGID(id,count) ((( id & 0xffff) << 16) | (count & 0xffff))
#define FRAG_GETID(fragid) ((fragid >> 16) & 0xffff)
#define FRAG_GETCOUNT(fragid) (fragid & 0xffff)
// Generic fragment structure
typedef struct fragbuf_s
{
// Next buffer in chain
fragbuf_s *next;
// Id of this buffer
int bufferid;
// Message buffer where raw data is stored
sizebuf_t frag_message;
// The actual data sits here
byte frag_message_buf[FRAGMENT_MAX_SIZE];
// Is this a file buffer?
qboolean isfile;
// Is this file buffer from memory ( custom decal, etc. ).
qboolean isbuffer;
qboolean iscompressed;
// Name of the file to save out on remote host
char filename[MAX_PATH];
// Offset in file from which to read data
int foffset;
// Size of data to read at that offset
int size;
} fragbuf_t;
// Waiting list of fragbuf chains
typedef struct fragbufwaiting_s
{
// Next chain in waiting list
fragbufwaiting_s *next;
// Number of buffers in this chain
int fragbufcount;
// The actual buffers
fragbuf_t *fragbufs;
} fragbufwaiting_t;
// Network Connection Channel
typedef struct netchan_s
{
// NS_SERVER or NS_CLIENT, depending on channel.
netsrc_t sock;
// Address this channel is talking to.
netadr_t remote_address;
int player_slot;
// For timeouts. Time last message was received.
float last_received;
// Time when channel was connected.
float connect_time;
// Bandwidth choke
// Bytes per second
double rate;
// If realtime > cleartime, free to send next packet
double cleartime;
// Sequencing variables
//
// Increasing count of sequence numbers
int incoming_sequence;
// # of last outgoing message that has been ack'd.
int incoming_acknowledged;
// Toggles T/F as reliable messages are received.
int incoming_reliable_acknowledged;
// single bit, maintained local
int incoming_reliable_sequence;
// Message we are sending to remote
int outgoing_sequence;
// Whether the message contains reliable payload, single bit
int reliable_sequence;
// Outgoing sequence number of last send that had reliable data
int last_reliable_sequence;
void *connection_status;
int (*pfnNetchan_Blocksize)(void *);
// Staging and holding areas
sizebuf_t message;
byte message_buf[MAX_MSGLEN];
// Reliable message buffer. We keep adding to it until reliable is acknowledged. Then we clear it.
int reliable_length;
byte reliable_buf[MAX_MSGLEN];
// Waiting list of buffered fragments to go onto queue. Multiple outgoing buffers can be queued in succession.
fragbufwaiting_t *waitlist[MAX_STREAMS];
// Is reliable waiting buf a fragment?
int reliable_fragment[MAX_STREAMS];
// Buffer id for each waiting fragment
unsigned int reliable_fragid[MAX_STREAMS];
// The current fragment being set
fragbuf_t *fragbufs[MAX_STREAMS];
// The total number of fragments in this stream
int fragbufcount[MAX_STREAMS];
// Position in outgoing buffer where frag data starts
short int frag_startpos[MAX_STREAMS];
// Length of frag data in the buffer
short int frag_length[MAX_STREAMS];
// Incoming fragments are stored here
fragbuf_t *incomingbufs[MAX_STREAMS];
// Set to true when incoming data is ready
qboolean incomingready[MAX_STREAMS];
// Only referenced by the FRAG_FILE_STREAM component
// Name of file being downloaded
char incomingfilename[MAX_PATH];
void *tempbuffer;
int tempbuffersize;
// Incoming and outgoing flow metrics
flow_t flow[MAX_FLOWS];
} netchan_t;
#ifdef REHLDS_FIXES
#define Con_NetPrintf Con_DPrintf
#else // REHLDS_FIXES
#define Con_NetPrintf Con_Printf
#endif // REHLDS_FIXES