1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef ENGINE_SHARED_NETWORK_H
4#define ENGINE_SHARED_NETWORK_H
5
6#include "ringbuffer.h"
7#include "stun.h"
8
9#include <base/net.h>
10#include <base/types.h>
11
12#include <array>
13#include <optional>
14
15class CHuffman;
16class CNetBan;
17class CPacker;
18
19/*
20
21CURRENT:
22 packet header: 3 bytes
23 unsigned char flags_ack; // 6bit flags, 2bit ack
24 0.6: ORNCaaAA
25 0.6.5: ORNCT-AA
26 0.7: --NORCAA
27
28 O = flag compression
29 R = flag resend
30 N = flag connless
31 C = flag control
32 T = flag token (0.6.5 only not supported by ddnet)
33 - = unused, should be zero
34 a = should be zero otherwise it messes up the ack number
35 A = bit of ack number
36
37
38 unsigned char ack; // 8 bit ack
39 unsigned char num_chunks; // 8 bit chunks
40
41 (unsigned char padding[3]) // 24 bit extra in case it's a connection less packet
42 // this is to make sure that it's compatible with the
43 // old protocol
44
45 chunk header: 2-3 bytes
46 unsigned char flags_size; // 2bit flags, 6 bit size
47 unsigned char size_seq; // 4bit size, 4bit seq
48 (unsigned char seq;) // 8bit seq, if vital flag is set
49*/
50
51enum
52{
53 NETSENDFLAG_VITAL = 1 << 0,
54 NETSENDFLAG_CONNLESS = 1 << 1,
55 NETSENDFLAG_FLUSH = 1 << 2,
56 NETSENDFLAG_EXTENDED = 1 << 3,
57};
58
59enum
60{
61 NETSTATE_OFFLINE = 0,
62 NETSTATE_CONNECTING,
63 NETSTATE_ONLINE,
64};
65
66enum
67{
68 NET_MAX_PACKETSIZE = 1400,
69 NET_MAX_CONNLESS_PAYLOAD = NET_MAX_PACKETSIZE - 6,
70 /**
71 * The maximum size of a chunk within a connection-oriented packet.
72 *
73 * This is 1023 because the size is packed into 10 bits in the chunk header.
74 */
75 NET_MAX_CHUNK_SIZE = 1023,
76 NET_MAX_CHUNKHEADERSIZE = 3,
77 NET_PACKETHEADERSIZE = 3,
78 NET_CONNLESS_EXTRA_SIZE = 4,
79 NET_MAX_CLIENTS = 128,
80 NET_MAX_CONSOLE_CLIENTS = 4,
81 NET_MAX_SEQUENCE = 1 << 10,
82 NET_MAX_PACKET_CHUNKS = 0xFF,
83
84 NET_PACKETFLAG_UNUSED = 1 << 0,
85 NET_PACKETFLAG_TOKEN = 1 << 1,
86 NET_PACKETFLAG_CONTROL = 1 << 2,
87 NET_PACKETFLAG_CONNLESS = 1 << 3,
88 NET_PACKETFLAG_RESEND = 1 << 4,
89 NET_PACKETFLAG_COMPRESSION = 1 << 5,
90 // NOT SENT VIA THE NETWORK DIRECTLY:
91 NET_PACKETFLAG_EXTENDED = 1 << 6,
92
93 NET_CHUNKFLAG_VITAL = 1,
94 NET_CHUNKFLAG_RESEND = 2,
95
96 NET_CTRLMSG_KEEPALIVE = 0,
97 NET_CTRLMSG_CONNECT = 1,
98 NET_CTRLMSG_CONNECTACCEPT = 2,
99 NET_CTRLMSG_ACCEPT = 3,
100 NET_CTRLMSG_CLOSE = 4,
101
102 NET_CONN_BUFFERSIZE = 1024 * 32,
103
104 NET_CONNLIMIT_IPS = 16,
105
106 NET_TOKENCACHE_ADDRESSEXPIRY = 64,
107 NET_TOKENCACHE_PACKETEXPIRY = 5,
108};
109enum
110{
111 NET_TOKEN_MAX = 0xffffffff,
112 NET_TOKEN_NONE = NET_TOKEN_MAX,
113 NET_TOKEN_MASK = NET_TOKEN_MAX,
114
115 NET_TOKENREQUEST_DATASIZE = 512,
116};
117
118typedef int SECURITY_TOKEN;
119typedef unsigned int TOKEN;
120
121SECURITY_TOKEN ToSecurityToken(const unsigned char *pData);
122void WriteSecurityToken(unsigned char *pData, SECURITY_TOKEN Token);
123
124extern const unsigned char SECURITY_TOKEN_MAGIC[4];
125
126enum
127{
128 NET_SECURITY_TOKEN_UNKNOWN = -1,
129 NET_SECURITY_TOKEN_UNSUPPORTED = 0,
130};
131
132typedef int (*NETFUNC_DELCLIENT)(int ClientId, const char *pReason, void *pUser);
133typedef int (*NETFUNC_NEWCLIENT_CON)(int ClientId, void *pUser);
134typedef int (*NETFUNC_NEWCLIENT)(int ClientId, void *pUser, bool Sixup);
135typedef int (*NETFUNC_NEWCLIENT_NOAUTH)(int ClientId, void *pUser);
136typedef int (*NETFUNC_CLIENTREJOIN)(int ClientId, void *pUser);
137
138struct CNetChunk
139{
140 // -1 means that it's a stateless packet
141 // 0 on the client means the server
142 int m_ClientId;
143 NETADDR m_Address; // only used when client_id == -1
144 int m_Flags;
145 int m_DataSize;
146 const void *m_pData;
147 // only used if the flags contain NETSENDFLAG_EXTENDED and NETSENDFLAG_CONNLESS
148 unsigned char m_aExtraData[NET_CONNLESS_EXTRA_SIZE];
149
150 void AssertSizeSanity() const;
151};
152
153class CNetChunkHeader
154{
155public:
156 int m_Flags;
157 int m_Size;
158 int m_Sequence;
159
160 unsigned char *Pack(unsigned char *pData, int Split = 4) const;
161 unsigned char *Unpack(unsigned char *pData, int Split = 4);
162};
163
164class CNetChunkResend
165{
166public:
167 int m_Flags;
168 int m_DataSize;
169 unsigned char *m_pData;
170
171 int m_Sequence;
172 int64_t m_LastSendTime;
173 int64_t m_FirstSendTime;
174};
175
176class CNetPacketConstruct
177{
178public:
179 int m_Flags;
180 int m_Ack;
181 int m_NumChunks;
182 int m_DataSize;
183 unsigned char m_aChunkData[NET_MAX_PACKETSIZE - NET_PACKETHEADERSIZE];
184 unsigned char m_aExtraData[NET_CONNLESS_EXTRA_SIZE];
185};
186
187enum class CONNECTIVITY
188{
189 UNKNOWN,
190 CHECKING,
191 UNREACHABLE,
192 REACHABLE,
193 ADDRESS_KNOWN,
194};
195
196class CStun
197{
198 class CProtocol
199 {
200 int m_Index;
201 NETSOCKET m_Socket;
202 CStunData m_Stun;
203 bool m_HaveStunServer = false;
204 NETADDR m_StunServer;
205 bool m_HaveAddr = false;
206 NETADDR m_Addr;
207 int64_t m_LastResponse = -1;
208 int64_t m_NextTry = -1;
209 int m_NumUnsuccessfulTries = -1;
210
211 public:
212 CProtocol(int Index, NETSOCKET Socket);
213 void FeedStunServer(NETADDR StunServer);
214 void Refresh();
215 void Update();
216 bool OnPacket(NETADDR Addr, unsigned char *pData, int DataSize);
217 CONNECTIVITY GetConnectivity(NETADDR *pGlobalAddr);
218 };
219 CProtocol m_aProtocols[2];
220
221public:
222 CStun(NETSOCKET Socket);
223 void FeedStunServer(NETADDR StunServer);
224 void Refresh();
225 void Update();
226 bool OnPacket(NETADDR Addr, unsigned char *pData, int DataSize);
227 CONNECTIVITY GetConnectivity(int NetType, NETADDR *pGlobalAddr);
228};
229
230class CNetConnection
231{
232 // TODO: is this needed because this needs to be aware of
233 // the ack sequencing number and is also responsible for updating
234 // that. this should be fixed.
235 friend class CPacketChunkUnpacker;
236
237public:
238 enum class EState
239 {
240 OFFLINE,
241 WANT_TOKEN,
242 CONNECT,
243 PENDING,
244 ONLINE,
245 ERROR,
246 };
247
248 SECURITY_TOKEN m_SecurityToken;
249
250private:
251 unsigned short m_Sequence;
252 unsigned short m_Ack;
253 unsigned short m_PeerAck;
254 EState m_State = EState::OFFLINE;
255 int m_RemoteClosed;
256 bool m_BlockCloseMsg;
257 bool m_UnknownSeq;
258
259 CStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> m_Buffer;
260
261 int64_t m_LastUpdateTime;
262 int64_t m_LastRecvTime;
263 int64_t m_LastSendTime;
264
265 char m_aErrorString[256];
266
267 CNetPacketConstruct m_Construct;
268
269 NETADDR m_aConnectAddrs[16];
270 int m_NumConnectAddrs;
271 NETADDR m_PeerAddr;
272 NETSOCKET m_Socket;
273 NETSTATS m_Stats;
274
275 std::array<char, NETADDR_MAXSTRSIZE> m_aPeerAddrStr;
276 std::array<char, NETADDR_MAXSTRSIZE> m_aPeerAddrStrNoPort;
277 // client 0.7
278 static TOKEN GenerateToken7(const NETADDR *pPeerAddr);
279 class CNetBase *m_pNetBase;
280 bool IsSixup() const { return m_Sixup; }
281
282 //
283 bool IsPeerAddress(const NETADDR &Addr) const;
284 void SetPeerAddr(const NETADDR *pAddr);
285 void ClearPeerAddr();
286 void ResetStats();
287 void SetError(const char *pString);
288 void AckChunks(int Ack);
289
290 int QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence);
291 void SendConnect();
292 void SendControl(int ControlMsg, const void *pExtra, int ExtraSize);
293 void SendControlWithToken7(int ControlMsg, SECURITY_TOKEN ResponseToken);
294 void ResendChunk(CNetChunkResend *pResend);
295 void Resend();
296
297public:
298 bool m_TimeoutProtected;
299 bool m_TimeoutSituation;
300
301 void SetToken7(TOKEN Token);
302
303 void Reset(bool Rejoin = false);
304 void Init(NETSOCKET Socket, bool BlockCloseMsg);
305 int Connect(const NETADDR *pAddr, int NumAddrs);
306 int Connect7(const NETADDR *pAddr, int NumAddrs);
307 void Disconnect(const char *pReason);
308
309 int Update();
310 int Flush();
311
312 int Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_TOKEN SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED, SECURITY_TOKEN ResponseToken = NET_SECURITY_TOKEN_UNSUPPORTED);
313 int QueueChunk(int Flags, int DataSize, const void *pData);
314
315 const char *ErrorString();
316 void SignalResend();
317 EState State() const { return m_State; }
318 const NETADDR *PeerAddress() const { return &m_PeerAddr; }
319 const std::array<char, NETADDR_MAXSTRSIZE> &PeerAddressString(bool IncludePort) const
320 {
321 return IncludePort ? m_aPeerAddrStr : m_aPeerAddrStrNoPort;
322 }
323 void ConnectAddresses(const NETADDR **ppAddrs, int *pNumAddrs) const
324 {
325 *ppAddrs = m_aConnectAddrs;
326 *pNumAddrs = m_NumConnectAddrs;
327 }
328
329 void ResetErrorString() { m_aErrorString[0] = 0; }
330 const char *ErrorString() const { return m_aErrorString; }
331
332 // Needed for GotProblems in NetClient
333 int64_t LastRecvTime() const { return m_LastRecvTime; }
334 int64_t ConnectTime() const { return m_LastUpdateTime; }
335
336 int AckSequence() const { return m_Ack; }
337 int SeqSequence() const { return m_Sequence; }
338 int SecurityToken() const { return m_SecurityToken; }
339 CStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> *ResendBuffer() { return &m_Buffer; }
340
341 void ResumeConnection(const NETADDR *pAddr, int Sequence, int Ack, SECURITY_TOKEN SecurityToken, CStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> *pResendBuffer, bool Sixup);
342
343 // anti spoof
344 void DirectInit(const NETADDR &Addr, SECURITY_TOKEN SecurityToken, SECURITY_TOKEN Token, bool Sixup);
345 void SetUnknownSeq() { m_UnknownSeq = true; }
346 void SetSequence(int Sequence) { m_Sequence = Sequence; }
347
348 bool m_Sixup;
349 SECURITY_TOKEN m_Token;
350};
351
352class CConsoleNetConnection
353{
354public:
355 enum class EState
356 {
357 OFFLINE,
358 ONLINE,
359 ERROR,
360 };
361
362private:
363 EState m_State;
364
365 NETADDR m_PeerAddr;
366 std::array<char, NETADDR_MAXSTRSIZE> m_aPeerAddrStr;
367 NETSOCKET m_Socket;
368
369 char m_aBuffer[NET_MAX_PACKETSIZE];
370 int m_BufferOffset;
371
372 char m_aErrorString[256];
373
374 bool m_LineEndingDetected;
375 char m_aLineEnding[3];
376
377 void SetPeerAddr(const NETADDR *pAddr);
378 void ClearPeerAddr();
379
380public:
381 int Init(NETSOCKET Socket, const NETADDR *pAddr);
382 void Disconnect(const char *pReason);
383
384 EState State() const { return m_State; }
385 const NETADDR *PeerAddress() const { return &m_PeerAddr; }
386 const std::array<char, NETADDR_MAXSTRSIZE> &PeerAddressString() const { return m_aPeerAddrStr; }
387 const char *ErrorString() const { return m_aErrorString; }
388
389 void Reset();
390 int Update();
391 int Send(const char *pLine);
392 int Recv(char *pLine, int MaxLength);
393};
394
395/**
396 * Accepts a non-control packet containing one or more chunks and unpacks each chunk individually.
397 * After a packet has been fed into the unpacker by calling @link FeedPacket @endlink, all chunks have
398 * to be unpacked by calling @link UnpackNextChunk @endlink until the function returns `false`, before
399 * the unpacker can be fed another packet.
400 */
401class CPacketChunkUnpacker
402{
403public:
404 void FeedPacket(const NETADDR &Addr, const CNetPacketConstruct &Packet, CNetConnection *pConnection, int ClientId);
405 bool UnpackNextChunk(CNetChunk *pChunk);
406 void Reset();
407
408private:
409 bool m_Valid = false;
410 NETADDR m_Addr;
411 CNetConnection *m_pConnection;
412 int m_CurrentChunk;
413 int m_ClientId;
414 CNetPacketConstruct m_Data;
415};
416
417// server side
418class CNetServer
419{
420 struct CSlot
421 {
422 public:
423 CNetConnection m_Connection;
424 };
425
426 struct CSpamConn
427 {
428 NETADDR m_Addr;
429 int64_t m_Time;
430 int m_Conns;
431 };
432
433 NETADDR m_Address;
434 NETSOCKET m_Socket;
435 CNetBan *m_pNetBan;
436 CSlot m_aSlots[NET_MAX_CLIENTS];
437 int m_MaxClients = NET_MAX_CLIENTS;
438 int m_MaxClientsPerIp;
439
440 bool m_FlushBatch = false;
441 bool m_aFlushPending[NET_MAX_CLIENTS] = {};
442
443 NETFUNC_NEWCLIENT m_pfnNewClient;
444 NETFUNC_NEWCLIENT_NOAUTH m_pfnNewClientNoAuth;
445 NETFUNC_DELCLIENT m_pfnDelClient;
446 NETFUNC_CLIENTREJOIN m_pfnClientRejoin;
447 void *m_pUser;
448
449 unsigned char m_aSecurityTokenSeed[16];
450
451 // vanilla connect flood detection
452 int64_t m_VConnFirst;
453 int m_VConnNum;
454
455 CSpamConn m_aSpamConns[NET_CONNLIMIT_IPS];
456
457 CPacketChunkUnpacker m_PacketChunkUnpacker;
458 CNetPacketConstruct m_RecvBuffer;
459
460 void OnTokenCtrlMsg(NETADDR &Addr, int ControlMsg, const CNetPacketConstruct &Packet);
461 int OnSixupCtrlMsg(NETADDR &Addr, CNetChunk *pChunk, int ControlMsg, const CNetPacketConstruct &Packet, SECURITY_TOKEN &ResponseToken, SECURITY_TOKEN Token);
462 void OnPreConnMsg(NETADDR &Addr, CNetPacketConstruct &Packet);
463 void OnConnCtrlMsg(NETADDR &Addr, int ClientId, int ControlMsg, const CNetPacketConstruct &Packet);
464 bool ClientExists(const NETADDR &Addr) { return GetClientSlot(Addr) != -1; }
465 int GetClientSlot(const NETADDR &Addr);
466 void SendControl(NETADDR &Addr, int ControlMsg, const void *pExtra, int ExtraSize, SECURITY_TOKEN SecurityToken);
467
468 int TryAcceptClient(NETADDR &Addr, SECURITY_TOKEN SecurityToken, bool VanillaAuth = false, bool Sixup = false, SECURITY_TOKEN Token = 0);
469 int NumClientsWithAddr(NETADDR Addr);
470 bool Connlimit(NETADDR Addr);
471 void SendMsgs(NETADDR &Addr, const CPacker **ppMsgs, int Num);
472
473public:
474 int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
475 int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_NEWCLIENT_NOAUTH pfnNewClientNoAuth, NETFUNC_CLIENTREJOIN pfnClientRejoin, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
476
477 //
478 bool Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIp);
479 void Close();
480
481 //
482 int Recv(CNetChunk *pChunk, SECURITY_TOKEN *pResponseToken);
483 int Send(CNetChunk *pChunk);
484 void Update();
485
486 // While a flush batch is open, sends requesting MSGFLAG_FLUSH only queue
487 // their chunk and mark the connection; EndFlushBatch() then flushes each
488 // marked connection once. Used to coalesce the flushes triggered while
489 // draining a burst of incoming packets into one packet per recipient.
490 void BeginFlushBatch() { m_FlushBatch = true; }
491 void EndFlushBatch();
492
493 //
494 void Drop(int ClientId, const char *pReason);
495
496 // status requests
497 const NETADDR *ClientAddr(int ClientId) const { return m_aSlots[ClientId].m_Connection.PeerAddress(); }
498 const std::array<char, NETADDR_MAXSTRSIZE> &ClientAddrString(int ClientId, bool IncludePort) const { return m_aSlots[ClientId].m_Connection.PeerAddressString(IncludePort); }
499 bool HasSecurityToken(int ClientId) const { return m_aSlots[ClientId].m_Connection.SecurityToken() != NET_SECURITY_TOKEN_UNSUPPORTED; }
500 NETADDR Address() const { return m_Address; }
501 NETSOCKET Socket() const { return m_Socket; }
502 CNetBan *NetBan() const { return m_pNetBan; }
503 int NetType() const { return net_socket_type(sock: m_Socket); }
504 int MaxClients() const { return m_MaxClients; }
505
506 void SendTokenSixup(NETADDR &Addr, SECURITY_TOKEN Token);
507
508 //
509 void SetMaxClientsPerIp(int Max);
510 bool HasErrored(int ClientId);
511 void ResumeOldConnection(int ClientId, int OrigId);
512 void IgnoreTimeouts(int ClientId);
513
514 void ResetErrorString(int ClientId);
515 const char *ErrorString(int ClientId);
516
517 // anti spoof
518 SECURITY_TOKEN GetGlobalToken();
519 SECURITY_TOKEN GetToken(const NETADDR &Addr);
520 SECURITY_TOKEN GetVanillaToken(const NETADDR &Addr);
521};
522
523class CNetConsole
524{
525 struct CSlot
526 {
527 CConsoleNetConnection m_Connection;
528 };
529
530 NETSOCKET m_Socket;
531 CNetBan *m_pNetBan;
532 CSlot m_aSlots[NET_MAX_CONSOLE_CLIENTS];
533
534 NETFUNC_NEWCLIENT_CON m_pfnNewClient;
535 NETFUNC_DELCLIENT m_pfnDelClient;
536 void *m_pUser;
537
538public:
539 void SetCallbacks(NETFUNC_NEWCLIENT_CON pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
540
541 //
542 bool Open(NETADDR BindAddr, CNetBan *pNetBan);
543 void Close();
544
545 //
546 int Recv(char *pLine, int MaxLength, int *pClientId = nullptr);
547 int Send(int ClientId, const char *pLine);
548 void Update();
549
550 //
551 int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr);
552 void Drop(int ClientId, const char *pReason);
553
554 // status requests
555 const NETADDR *ClientAddr(int ClientId) const { return m_aSlots[ClientId].m_Connection.PeerAddress(); }
556 const std::array<char, NETADDR_MAXSTRSIZE> &ClientAddrString(int ClientId) const { return m_aSlots[ClientId].m_Connection.PeerAddressString(); }
557 CNetBan *NetBan() const { return m_pNetBan; }
558};
559
560class CNetTokenCache
561{
562public:
563 void Init(NETSOCKET Socket);
564 void SendPacketConnless(CNetChunk *pChunk);
565 void FetchToken(NETADDR *pAddr);
566 void AddToken(const NETADDR *pAddr, TOKEN Token);
567 TOKEN GetToken(const NETADDR *pAddr);
568 TOKEN GenerateToken();
569 void Update();
570
571private:
572 class CConnlessPacketInfo
573 {
574 public:
575 NETADDR m_Addr;
576 int m_DataSize;
577 unsigned char m_aData[NET_MAX_CONNLESS_PAYLOAD];
578 int64_t m_Expiry;
579 };
580
581 class CAddressInfo
582 {
583 public:
584 NETADDR m_Addr;
585 TOKEN m_Token;
586 int64_t m_Expiry;
587 };
588
589 NETSOCKET m_Socket;
590 std::vector<CAddressInfo> m_TokenCache;
591 std::vector<CConnlessPacketInfo> m_ConnlessPackets;
592};
593
594// client side
595class CNetClient
596{
597 CNetConnection m_Connection;
598 CPacketChunkUnpacker m_PacketChunkUnpacker;
599 CNetPacketConstruct m_RecvBuffer;
600 CNetTokenCache m_TokenCache;
601
602 CStun *m_pStun = nullptr;
603
604public:
605 NETSOCKET m_Socket = nullptr;
606 // openness
607 bool Open(NETADDR BindAddr);
608 void Close();
609
610 // connection state
611 void Disconnect(const char *pReason);
612 void Connect(const NETADDR *pAddr, int NumAddrs);
613 void Connect7(const NETADDR *pAddr, int NumAddrs);
614
615 // communication
616 int Recv(CNetChunk *pChunk, SECURITY_TOKEN *pResponseToken, bool Sixup);
617 int Send(CNetChunk *pChunk);
618
619 // pumping
620 void Update();
621 int Flush();
622
623 void ResetErrorString();
624
625 // error and state
626 int NetType() const { return net_socket_type(sock: m_Socket); }
627 int State();
628 const NETADDR *ServerAddress() const { return m_Connection.PeerAddress(); }
629 void ConnectAddresses(const NETADDR **ppAddrs, int *pNumAddrs) const { m_Connection.ConnectAddresses(ppAddrs, pNumAddrs); }
630 bool GotProblems(int64_t MaxLatency) const;
631 const char *ErrorString() const;
632
633 // stun
634 void FeedStunServer(NETADDR StunServer);
635 void RefreshStun();
636 CONNECTIVITY GetConnectivity(int NetType, NETADDR *pGlobalAddr);
637};
638
639// TODO: both, fix these. This feels like a junk class for stuff that doesn't fit anywhere
640class CNetBase
641{
642 static IOHANDLE ms_DataLogSent;
643 static IOHANDLE ms_DataLogRecv;
644 static CHuffman ms_Huffman;
645
646public:
647 static void OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv);
648 static void CloseLog();
649 static void Init();
650 static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize);
651 static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize);
652
653 static bool IsValidConnectionOrientedPacket(const CNetPacketConstruct *pPacket);
654
655 static void SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize, SECURITY_TOKEN SecurityToken, bool Sixup = false);
656 static void SendControlMsgWithToken7(NETSOCKET Socket, NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended);
657 static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize, bool Extended, unsigned char aExtra[NET_CONNLESS_EXTRA_SIZE]);
658 static void SendPacketConnlessWithToken7(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize, SECURITY_TOKEN Token, SECURITY_TOKEN ResponseToken);
659 static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket, SECURITY_TOKEN SecurityToken, bool Sixup = false);
660
661 static std::optional<int> UnpackPacketFlags(unsigned char *pBuffer, int Size);
662 static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket, bool &Sixup, SECURITY_TOKEN *pSecurityToken = nullptr, SECURITY_TOKEN *pResponseToken = nullptr);
663
664 // The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not
665 static bool IsSeqInBackroom(int Seq, int Ack);
666};
667
668#endif
669