]> git.lizzy.rs Git - dragonfireclient.git/blob - src/connection.h
disconnect method to connection to be used instead of just timing out
[dragonfireclient.git] / src / connection.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef CONNECTION_HEADER
21 #define CONNECTION_HEADER
22
23 #include <iostream>
24 #include <fstream>
25 #include "debug.h"
26 #include "common_irrlicht.h"
27 #include "socket.h"
28 #include "utility.h"
29 #include "exceptions.h"
30 #include "constants.h"
31
32 namespace con
33 {
34
35 /*
36         Exceptions
37 */
38 class NotFoundException : public BaseException
39 {
40 public:
41         NotFoundException(const char *s):
42                 BaseException(s)
43         {}
44 };
45
46 class PeerNotFoundException : public BaseException
47 {
48 public:
49         PeerNotFoundException(const char *s):
50                 BaseException(s)
51         {}
52 };
53
54 class ConnectionException : public BaseException
55 {
56 public:
57         ConnectionException(const char *s):
58                 BaseException(s)
59         {}
60 };
61
62 /*class ThrottlingException : public BaseException
63 {
64 public:
65         ThrottlingException(const char *s):
66                 BaseException(s)
67         {}
68 };*/
69
70 class InvalidIncomingDataException : public BaseException
71 {
72 public:
73         InvalidIncomingDataException(const char *s):
74                 BaseException(s)
75         {}
76 };
77
78 class InvalidOutgoingDataException : public BaseException
79 {
80 public:
81         InvalidOutgoingDataException(const char *s):
82                 BaseException(s)
83         {}
84 };
85
86 class NoIncomingDataException : public BaseException
87 {
88 public:
89         NoIncomingDataException(const char *s):
90                 BaseException(s)
91         {}
92 };
93
94 class ProcessedSilentlyException : public BaseException
95 {
96 public:
97         ProcessedSilentlyException(const char *s):
98                 BaseException(s)
99         {}
100 };
101
102 class GotSplitPacketException
103 {
104         SharedBuffer<u8> m_data;
105 public:
106         GotSplitPacketException(SharedBuffer<u8> data):
107                 m_data(data)
108         {}
109         SharedBuffer<u8> getData()
110         {
111                 return m_data;
112         }
113 };
114
115 inline u16 readPeerId(u8 *packetdata)
116 {
117         return readU16(&packetdata[4]);
118 }
119 inline u8 readChannel(u8 *packetdata)
120 {
121         return readU8(&packetdata[6]);
122 }
123
124 #define SEQNUM_MAX 65535
125 inline bool seqnum_higher(u16 higher, u16 lower)
126 {
127         if(lower > higher && lower - higher > SEQNUM_MAX/2){
128                 return true;
129         }
130         return (higher > lower);
131 }
132
133 struct BufferedPacket
134 {
135         BufferedPacket(u8 *a_data, u32 a_size):
136                 data(a_data, a_size), time(0.0), totaltime(0.0)
137         {}
138         BufferedPacket(u32 a_size):
139                 data(a_size), time(0.0), totaltime(0.0)
140         {}
141         SharedBuffer<u8> data; // Data of the packet, including headers
142         float time; // Seconds from buffering the packet or re-sending
143         float totaltime; // Seconds from buffering the packet
144         Address address; // Sender or destination
145 };
146
147 // This adds the base headers to the data and makes a packet out of it
148 BufferedPacket makePacket(Address &address, u8 *data, u32 datasize,
149                 u32 protocol_id, u16 sender_peer_id, u8 channel);
150 BufferedPacket makePacket(Address &address, SharedBuffer<u8> &data,
151                 u32 protocol_id, u16 sender_peer_id, u8 channel);
152
153 // Add the TYPE_ORIGINAL header to the data
154 SharedBuffer<u8> makeOriginalPacket(
155                 SharedBuffer<u8> data);
156
157 // Split data in chunks and add TYPE_SPLIT headers to them
158 core::list<SharedBuffer<u8> > makeSplitPacket(
159                 SharedBuffer<u8> data,
160                 u32 chunksize_max,
161                 u16 seqnum);
162
163 // Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
164 // Increments split_seqnum if a split packet is made
165 core::list<SharedBuffer<u8> > makeAutoSplitPacket(
166                 SharedBuffer<u8> data,
167                 u32 chunksize_max,
168                 u16 &split_seqnum);
169
170 // Add the TYPE_RELIABLE header to the data
171 SharedBuffer<u8> makeReliablePacket(
172                 SharedBuffer<u8> data,
173                 u16 seqnum);
174
175 struct IncomingSplitPacket
176 {
177         IncomingSplitPacket()
178         {
179                 time = 0.0;
180                 reliable = false;
181         }
182         // Key is chunk number, value is data without headers
183         core::map<u16, SharedBuffer<u8> > chunks;
184         u32 chunk_count;
185         float time; // Seconds from adding
186         bool reliable; // If true, isn't deleted on timeout
187
188         bool allReceived()
189         {
190                 return (chunks.size() == chunk_count);
191         }
192 };
193
194 /*
195 === NOTES ===
196
197 A packet is sent through a channel to a peer with a basic header:
198 TODO: Should we have a receiver_peer_id also?
199         Header (7 bytes):
200         [0] u32 protocol_id
201         [4] u16 sender_peer_id
202         [6] u8 channel
203 sender_peer_id:
204         Unique to each peer.
205         value 0 is reserved for making new connections
206         value 1 is reserved for server
207 channel:
208         The lower the number, the higher the priority is.
209         Only channels 0, 1 and 2 exist.
210 */
211 #define BASE_HEADER_SIZE 7
212 #define PEER_ID_NEW 0
213 #define PEER_ID_SERVER 1
214 #define CHANNEL_COUNT 3
215 /*
216 Packet types:
217
218 CONTROL: This is a packet used by the protocol.
219 - When this is processed, nothing is handed to the user.
220         Header (2 byte):
221         [0] u8 type
222         [1] u8 controltype
223 controltype and data description:
224         CONTROLTYPE_ACK
225                 [2] u16 seqnum
226         CONTROLTYPE_SET_PEER_ID
227                 [2] u16 peer_id_new
228         CONTROLTYPE_PING
229         - There is no actual reply, but this can be sent in a reliable
230           packet to get a reply
231         CONTROLTYPE_DISCO
232 */
233 #define TYPE_CONTROL 0
234 #define CONTROLTYPE_ACK 0
235 #define CONTROLTYPE_SET_PEER_ID 1
236 #define CONTROLTYPE_PING 2
237 #define CONTROLTYPE_DISCO 3
238 /*
239 ORIGINAL: This is a plain packet with no control and no error
240 checking at all.
241 - When this is processed, it is directly handed to the user.
242         Header (1 byte):
243         [0] u8 type
244 */
245 #define TYPE_ORIGINAL 1
246 #define ORIGINAL_HEADER_SIZE 1
247 /*
248 SPLIT: These are sequences of packets forming one bigger piece of
249 data.
250 - When processed and all the packet_nums 0...packet_count-1 are
251   present (this should be buffered), the resulting data shall be
252   directly handed to the user.
253 - If the data fails to come up in a reasonable time, the buffer shall
254   be silently discarded.
255 - These can be sent as-is or atop of a RELIABLE packet stream.
256         Header (7 bytes):
257         [0] u8 type
258         [1] u16 seqnum
259         [3] u16 chunk_count
260         [5] u16 chunk_num
261 */
262 #define TYPE_SPLIT 2
263 /*
264 RELIABLE: Delivery of all RELIABLE packets shall be forced by ACKs,
265 and they shall be delivered in the same order as sent. This is done
266 with a buffer in the receiving and transmitting end.
267 - When this is processed, the contents of each packet is recursively
268   processed as packets.
269         Header (3 bytes):
270         [0] u8 type
271         [1] u16 seqnum
272
273 */
274 #define TYPE_RELIABLE 3
275 #define RELIABLE_HEADER_SIZE 3
276 //#define SEQNUM_INITIAL 0x10
277 #define SEQNUM_INITIAL 65500
278
279 /*
280         A buffer which stores reliable packets and sorts them internally
281         for fast access to the smallest one.
282 */
283
284 typedef core::list<BufferedPacket>::Iterator RPBSearchResult;
285
286 class ReliablePacketBuffer
287 {
288 public:
289         
290         void print();
291         bool empty();
292         u32 size();
293         RPBSearchResult findPacket(u16 seqnum);
294         RPBSearchResult notFound();
295         u16 getFirstSeqnum();
296         BufferedPacket popFirst();
297         BufferedPacket popSeqnum(u16 seqnum);
298         void insert(BufferedPacket &p);
299         void incrementTimeouts(float dtime);
300         void resetTimedOuts(float timeout);
301         bool anyTotaltimeReached(float timeout);
302         core::list<BufferedPacket> getTimedOuts(float timeout);
303
304 private:
305         core::list<BufferedPacket> m_list;
306 };
307
308 /*
309         A buffer for reconstructing split packets
310 */
311
312 class IncomingSplitBuffer
313 {
314 public:
315         ~IncomingSplitBuffer();
316         /*
317                 This will throw a GotSplitPacketException when a full
318                 split packet is constructed.
319         */
320         void insert(BufferedPacket &p, bool reliable);
321         
322         void removeUnreliableTimedOuts(float dtime, float timeout);
323         
324 private:
325         // Key is seqnum
326         core::map<u16, IncomingSplitPacket*> m_buf;
327 };
328
329 class Connection;
330
331 struct Channel
332 {
333         Channel();
334         ~Channel();
335         /*
336                 Processes a packet with the basic header stripped out.
337                 Parameters:
338                         packetdata: Data in packet (with no base headers)
339                         con: The connection to which the channel is associated
340                              (used for sending back stuff (ACKs))
341                         peer_id: peer id of the sender of the packet in question
342                         channelnum: channel on which the packet was sent
343                         reliable: true if recursing into a reliable packet
344         */
345         SharedBuffer<u8> ProcessPacket(
346                         SharedBuffer<u8> packetdata,
347                         Connection *con,
348                         u16 peer_id,
349                         u8 channelnum,
350                         bool reliable=false);
351         
352         // Returns next data from a buffer if possible
353         // throws a NoIncomingDataException if no data is available
354         // If found, sets peer_id
355         SharedBuffer<u8> CheckIncomingBuffers(Connection *con,
356                         u16 &peer_id);
357
358         u16 next_outgoing_seqnum;
359         u16 next_incoming_seqnum;
360         u16 next_outgoing_split_seqnum;
361         
362         // This is for buffering the incoming packets that are coming in
363         // the wrong order
364         ReliablePacketBuffer incoming_reliables;
365         // This is for buffering the sent packets so that the sender can
366         // re-send them if no ACK is received
367         ReliablePacketBuffer outgoing_reliables;
368
369         IncomingSplitBuffer incoming_splits;
370 };
371
372 class Peer;
373
374 class PeerHandler
375 {
376 public:
377         PeerHandler()
378         {
379         }
380         virtual ~PeerHandler()
381         {
382         }
383         
384         /*
385                 This is called after the Peer has been inserted into the
386                 Connection's peer container.
387         */
388         virtual void peerAdded(Peer *peer) = 0;
389         /*
390                 This is called before the Peer has been removed from the
391                 Connection's peer container.
392         */
393         virtual void deletingPeer(Peer *peer, bool timeout) = 0;
394 };
395
396 class Peer
397 {
398 public:
399
400         Peer(u16 a_id, Address a_address);
401         virtual ~Peer();
402         
403         /*
404                 Calculates avg_rtt and resend_timeout.
405
406                 rtt=-1 only recalculates resend_timeout
407         */
408         void reportRTT(float rtt);
409
410         Channel channels[CHANNEL_COUNT];
411
412         // Address of the peer
413         Address address;
414         // Unique id of the peer
415         u16 id;
416         // Seconds from last receive
417         float timeout_counter;
418         // Ping timer
419         float ping_timer;
420         // This is changed dynamically
421         float resend_timeout;
422         // Updated when an ACK is received
423         float avg_rtt;
424         // This is set to true when the peer has actually sent something
425         // with the id we have given to it
426         bool has_sent_with_id;
427         
428 private:
429 };
430
431 class Connection
432 {
433 public:
434         Connection(
435                 u32 protocol_id,
436                 u32 max_packet_size,
437                 float timeout,
438                 PeerHandler *peerhandler
439         );
440         ~Connection();
441         void setTimeoutMs(int timeout){ m_socket.setTimeoutMs(timeout); }
442         // Start being a server
443         void Serve(unsigned short port);
444         // Connect to a server
445         void Connect(Address address);
446         bool Connected();
447
448         void Disconnect();
449
450         // Sets peer_id
451         SharedBuffer<u8> GetFromBuffers(u16 &peer_id);
452
453         // The peer_id of sender is stored in peer_id
454         // Return value: I guess this always throws an exception or
455         //               actually gets data
456         // May call PeerHandler methods
457         u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
458         
459         // These will automatically package the data as an original or split
460         void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
461         void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
462         // Send data as a packet; it will be wrapped in base header and
463         // optionally to a reliable packet.
464         void SendAsPacket(u16 peer_id, u8 channelnum,
465                         SharedBuffer<u8> data, bool reliable);
466         // Sends a raw packet
467         void RawSend(const BufferedPacket &packet);
468         
469         // May call PeerHandler methods
470         void RunTimeouts(float dtime);
471
472         // Can throw a PeerNotFoundException
473         Peer* GetPeer(u16 peer_id);
474         // returns NULL if failed
475         Peer* GetPeerNoEx(u16 peer_id);
476         core::list<Peer*> GetPeers();
477         
478         // Calls PeerHandler::deletingPeer
479         // Returns false if peer was not found
480         bool deletePeer(u16 peer_id);
481
482         void SetPeerID(u16 id){ m_peer_id = id; }
483         u16 GetPeerID(){ return m_peer_id; }
484         u32 GetProtocolID(){ return m_protocol_id; }
485
486         // For debug printing
487         void PrintInfo(std::ostream &out);
488         void PrintInfo();
489         u16 m_indentation;
490
491 private:
492         u32 m_protocol_id;
493         float m_timeout;
494         PeerHandler *m_peerhandler;
495         core::map<u16, Peer*> m_peers;
496         u16 m_peer_id;
497         //bool m_waiting_new_peer_id;
498         u32 m_max_packet_size;
499         UDPSocket m_socket;
500 };
501
502 } // namespace
503
504 #endif
505