protected econ authentication against brute force
[twcon.git] / src / engine / shared / network.h
blobd10c03b62335552ab57ab27ccc51b89be48088b0
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
6 #include "ringbuffer.h"
7 #include "huffman.h"
9 /*
11 CURRENT:
12 packet header: 3 bytes
13 unsigned char flags_ack; // 4bit flags, 4bit ack
14 unsigned char ack; // 8 bit ack
15 unsigned char num_chunks; // 8 bit chunks
17 (unsigned char padding[3]) // 24 bit extra incase it's a connection less packet
18 // this is to make sure that it's compatible with the
19 // old protocol
21 chunk header: 2-3 bytes
22 unsigned char flags_size; // 2bit flags, 6 bit size
23 unsigned char size_seq; // 4bit size, 4bit seq
24 (unsigned char seq;) // 8bit seq, if vital flag is set
27 enum
29 NETFLAG_ALLOWSTATELESS=1,
30 NETSENDFLAG_VITAL=1,
31 NETSENDFLAG_CONNLESS=2,
32 NETSENDFLAG_FLUSH=4,
34 NETSTATE_OFFLINE=0,
35 NETSTATE_CONNECTING,
36 NETSTATE_ONLINE,
38 NETBANTYPE_SOFT=1,
39 NETBANTYPE_DROP=2
43 enum
45 NET_VERSION = 2,
47 NET_MAX_PACKETSIZE = 1400,
48 NET_MAX_PAYLOAD = NET_MAX_PACKETSIZE-6,
49 NET_MAX_CHUNKHEADERSIZE = 5,
50 NET_PACKETHEADERSIZE = 3,
51 NET_MAX_CLIENTS = 16,
52 NET_MAX_CONSOLE_CLIENTS = 4,
53 NET_MAX_SEQUENCE = 1<<10,
54 NET_SEQUENCE_MASK = NET_MAX_SEQUENCE-1,
56 NET_CONNSTATE_OFFLINE=0,
57 NET_CONNSTATE_CONNECT=1,
58 NET_CONNSTATE_PENDING=2,
59 NET_CONNSTATE_ONLINE=3,
60 NET_CONNSTATE_ERROR=4,
62 NET_PACKETFLAG_CONTROL=1,
63 NET_PACKETFLAG_CONNLESS=2,
64 NET_PACKETFLAG_RESEND=4,
65 NET_PACKETFLAG_COMPRESSION=8,
67 NET_CHUNKFLAG_VITAL=1,
68 NET_CHUNKFLAG_RESEND=2,
70 NET_CTRLMSG_KEEPALIVE=0,
71 NET_CTRLMSG_CONNECT=1,
72 NET_CTRLMSG_CONNECTACCEPT=2,
73 NET_CTRLMSG_ACCEPT=3,
74 NET_CTRLMSG_CLOSE=4,
76 NET_SERVER_MAXBANS=1024,
78 NET_CONN_BUFFERSIZE=1024*32,
80 NET_ENUM_TERMINATOR
84 typedef int (*NETFUNC_DELCLIENT)(int ClientID, const char* pReason, void *pUser);
85 typedef int (*NETFUNC_NEWCLIENT)(int ClientID, void *pUser);
87 struct CNetChunk
89 // -1 means that it's a stateless packet
90 // 0 on the client means the server
91 int m_ClientID;
92 NETADDR m_Address; // only used when client_id == -1
93 int m_Flags;
94 int m_DataSize;
95 const void *m_pData;
98 class CNetChunkHeader
100 public:
101 int m_Flags;
102 int m_Size;
103 int m_Sequence;
105 unsigned char *Pack(unsigned char *pData);
106 unsigned char *Unpack(unsigned char *pData);
109 class CNetChunkResend
111 public:
112 int m_Flags;
113 int m_DataSize;
114 unsigned char *m_pData;
116 int m_Sequence;
117 int64 m_LastSendTime;
118 int64 m_FirstSendTime;
121 class CNetPacketConstruct
123 public:
124 int m_Flags;
125 int m_Ack;
126 int m_NumChunks;
127 int m_DataSize;
128 unsigned char m_aChunkData[NET_MAX_PAYLOAD];
132 class CNetConnection
134 // TODO: is this needed because this needs to be aware of
135 // the ack sequencing number and is also responible for updating
136 // that. this should be fixed.
137 friend class CNetRecvUnpacker;
138 private:
139 unsigned short m_Sequence;
140 unsigned short m_Ack;
141 unsigned m_State;
143 int m_Token;
144 int m_RemoteClosed;
146 TStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> m_Buffer;
148 int64 m_LastUpdateTime;
149 int64 m_LastRecvTime;
150 int64 m_LastSendTime;
152 char m_ErrorString[256];
154 CNetPacketConstruct m_Construct;
156 NETADDR m_PeerAddr;
157 NETSOCKET m_Socket;
158 NETSTATS m_Stats;
161 void Reset();
162 void ResetStats();
163 void SetError(const char *pString);
164 void AckChunks(int Ack);
166 int QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence);
167 void SendControl(int ControlMsg, const void *pExtra, int ExtraSize);
168 void ResendChunk(CNetChunkResend *pResend);
169 void Resend();
171 public:
172 void Init(NETSOCKET Socket);
173 int Connect(NETADDR *pAddr);
174 void Disconnect(const char *pReason);
176 int Update();
177 int Flush();
179 int Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr);
180 int QueueChunk(int Flags, int DataSize, const void *pData);
182 const char *ErrorString();
183 void SignalResend();
184 int State() const { return m_State; }
185 NETADDR PeerAddress() const { return m_PeerAddr; }
187 void ResetErrorString() { m_ErrorString[0] = 0; }
188 const char *ErrorString() const { return m_ErrorString; }
190 // Needed for GotProblems in NetClient
191 int64 LastRecvTime() const { return m_LastRecvTime; }
193 int AckSequence() const { return m_Ack; }
196 class CConsoleNetConnection
198 private:
199 int m_State;
201 NETADDR m_PeerAddr;
202 NETSOCKET m_Socket;
204 char m_aBuffer[NET_MAX_PACKETSIZE];
205 int m_BufferOffset;
207 char m_aErrorString[256];
209 bool m_LineEndingDetected;
210 char m_aLineEnding[3];
212 public:
213 void Init(NETSOCKET Socket, const NETADDR *pAddr);
214 void Disconnect(const char *pReason);
216 int State() const { return m_State; }
217 NETADDR PeerAddress() const { return m_PeerAddr; }
218 const char *ErrorString() const { return m_aErrorString; }
220 void Reset();
221 int Update();
222 int Send(const char *pLine);
223 int Recv(char *pLine, int MaxLength);
226 class CNetRecvUnpacker
228 public:
229 bool m_Valid;
231 NETADDR m_Addr;
232 CNetConnection *m_pConnection;
233 int m_CurrentChunk;
234 int m_ClientID;
235 CNetPacketConstruct m_Data;
236 unsigned char m_aBuffer[NET_MAX_PACKETSIZE];
238 CNetRecvUnpacker() { Clear(); }
239 void Clear();
240 void Start(const NETADDR *pAddr, CNetConnection *pConnection, int ClientID);
241 int FetchChunk(CNetChunk *pChunk);
244 // server side
245 class CNetServer
247 public:
248 struct CBanInfo
250 NETADDR m_Addr;
251 int m_Expires;
252 char m_Reason[128];
255 private:
256 struct CSlot
258 public:
259 CNetConnection m_Connection;
262 struct CBan
264 public:
265 CBanInfo m_Info;
267 // hash list
268 CBan *m_pHashNext;
269 CBan *m_pHashPrev;
271 // used or free list
272 CBan *m_pNext;
273 CBan *m_pPrev;
277 NETSOCKET m_Socket;
278 CSlot m_aSlots[NET_MAX_CLIENTS];
279 int m_MaxClients;
280 int m_MaxClientsPerIP;
282 CBan *m_aBans[256];
283 CBan m_BanPool[NET_SERVER_MAXBANS];
284 CBan *m_BanPool_FirstFree;
285 CBan *m_BanPool_FirstUsed;
287 NETFUNC_NEWCLIENT m_pfnNewClient;
288 NETFUNC_DELCLIENT m_pfnDelClient;
289 void *m_UserPtr;
291 CNetRecvUnpacker m_RecvUnpacker;
293 void BanRemoveByObject(CBan *pBan);
295 public:
296 int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
299 bool Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int Flags);
300 int Close();
303 int Recv(CNetChunk *pChunk);
304 int Send(CNetChunk *pChunk);
305 int Update();
308 int Drop(int ClientID, const char *pReason);
310 // banning
311 int BanAdd(NETADDR Addr, int Seconds, const char *pReason);
312 int BanRemove(NETADDR Addr);
313 int BanNum(); // caution, slow
314 int BanGet(int Index, CBanInfo *pInfo); // caution, slow
316 // status requests
317 NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
318 NETSOCKET Socket() const { return m_Socket; }
319 int NetType() { return m_Socket.type; }
320 int MaxClients() const { return m_MaxClients; }
323 void SetMaxClientsPerIP(int Max);
326 class CNetConsole
328 enum
330 MAX_BANS=128,
333 int FindBan(NETADDR Addr);
334 void UpdateBans();
336 struct CBanEntry
338 NETADDR m_Addr;
339 int m_Expires;
340 } m_aBans[MAX_BANS];
341 int m_NumBans;
343 struct CSlot
345 CConsoleNetConnection m_Connection;
348 NETSOCKET m_Socket;
349 CSlot m_aSlots[NET_MAX_CONSOLE_CLIENTS];
351 NETFUNC_NEWCLIENT m_pfnNewClient;
352 NETFUNC_DELCLIENT m_pfnDelClient;
353 void *m_UserPtr;
355 CNetRecvUnpacker m_RecvUnpacker;
357 public:
358 void SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
361 bool Open(NETADDR BindAddr, int Flags);
362 int Close();
365 int Recv(char *pLine, int MaxLength, int *pClientID = 0);
366 int Send(int ClientID, const char *pLine);
367 int Update();
370 int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr);
371 int Drop(int ClientID, const char *pReason);
373 bool AddBan(NETADDR Addr, int Seconds);
375 // status requests
376 NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
381 // client side
382 class CNetClient
384 NETADDR m_ServerAddr;
385 CNetConnection m_Connection;
386 CNetRecvUnpacker m_RecvUnpacker;
387 NETSOCKET m_Socket;
388 public:
389 // openness
390 bool Open(NETADDR BindAddr, int Flags);
391 int Close();
393 // connection state
394 int Disconnect(const char *Reason);
395 int Connect(NETADDR *Addr);
397 // communication
398 int Recv(CNetChunk *Chunk);
399 int Send(CNetChunk *Chunk);
401 // pumping
402 int Update();
403 int Flush();
405 int ResetErrorString();
407 // error and state
408 int NetType() { return m_Socket.type; }
409 int State();
410 int GotProblems();
411 const char *ErrorString();
416 // TODO: both, fix these. This feels like a junk class for stuff that doesn't fit anywere
417 class CNetBase
419 static IOHANDLE ms_DataLogSent;
420 static IOHANDLE ms_DataLogRecv;
421 static CHuffman ms_Huffman;
422 public:
423 static void OpenLog(IOHANDLE DataLogSent, IOHANDLE DataLogRecv);
424 static void CloseLog();
425 static void Init();
426 static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize);
427 static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize);
429 static void SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize);
430 static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize);
431 static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket);
432 static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket);
434 // The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not
435 static int IsSeqInBackroom(int Seq, int Ack);
439 #endif