]> git.lizzy.rs Git - minetest.git/blob - src/network/connection.h
Various network performance improvements (#8125)
[minetest.git] / src / network / connection.h
1 /*
2 Minetest
3 Copyright (C) 2013 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 Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser 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 #pragma once
21
22 #include "irrlichttypes_bloated.h"
23 #include "peerhandler.h"
24 #include "socket.h"
25 #include "constants.h"
26 #include "util/pointer.h"
27 #include "util/container.h"
28 #include "util/thread.h"
29 #include "util/numeric.h"
30 #include "networkprotocol.h"
31 #include <iostream>
32 #include <fstream>
33 #include <list>
34 #include <map>
35
36 class NetworkPacket;
37
38 namespace con
39 {
40
41 class ConnectionReceiveThread;
42 class ConnectionSendThread;
43
44 typedef enum MTProtocols {
45         MTP_PRIMARY,
46         MTP_UDP,
47         MTP_MINETEST_RELIABLE_UDP
48 } MTProtocols;
49
50 #define MAX_UDP_PEERS 65535
51
52 #define SEQNUM_MAX 65535
53
54 inline bool seqnum_higher(u16 totest, u16 base)
55 {
56         if (totest > base)
57         {
58                 if ((totest - base) > (SEQNUM_MAX/2))
59                         return false;
60
61                 return true;
62         }
63
64         if ((base - totest) > (SEQNUM_MAX/2))
65                 return true;
66
67         return false;
68 }
69
70 inline bool seqnum_in_window(u16 seqnum, u16 next,u16 window_size)
71 {
72         u16 window_start = next;
73         u16 window_end   = ( next + window_size ) % (SEQNUM_MAX+1);
74
75         if (window_start < window_end) {
76                 return ((seqnum >= window_start) && (seqnum < window_end));
77         }
78
79
80         return ((seqnum < window_end) || (seqnum >= window_start));
81 }
82
83 static inline float CALC_DTIME(u64 lasttime, u64 curtime)
84 {
85         float value = ( curtime - lasttime) / 1000.0;
86         return MYMAX(MYMIN(value,0.1),0.0);
87 }
88
89 struct BufferedPacket
90 {
91         BufferedPacket(u8 *a_data, u32 a_size):
92                 data(a_data, a_size)
93         {}
94         BufferedPacket(u32 a_size):
95                 data(a_size)
96         {}
97         Buffer<u8> data; // Data of the packet, including headers
98         float time = 0.0f; // Seconds from buffering the packet or re-sending
99         float totaltime = 0.0f; // Seconds from buffering the packet
100         u64 absolute_send_time = -1;
101         Address address; // Sender or destination
102         unsigned int resend_count = 0;
103 };
104
105 // This adds the base headers to the data and makes a packet out of it
106 BufferedPacket makePacket(Address &address, const SharedBuffer<u8> &data,
107                 u32 protocol_id, session_t sender_peer_id, u8 channel);
108
109 // Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
110 // Increments split_seqnum if a split packet is made
111 void makeAutoSplitPacket(const SharedBuffer<u8> &data, u32 chunksize_max,
112                 u16 &split_seqnum, std::list<SharedBuffer<u8>> *list);
113
114 // Add the TYPE_RELIABLE header to the data
115 SharedBuffer<u8> makeReliablePacket(const SharedBuffer<u8> &data, u16 seqnum);
116
117 struct IncomingSplitPacket
118 {
119         IncomingSplitPacket(u32 cc, bool r):
120                 chunk_count(cc), reliable(r) {}
121
122         IncomingSplitPacket() = delete;
123
124         // Key is chunk number, value is data without headers
125         std::map<u16, SharedBuffer<u8>> chunks;
126         u32 chunk_count;
127         float time = 0.0f; // Seconds from adding
128         bool reliable = false; // If true, isn't deleted on timeout
129
130         bool allReceived() const
131         {
132                 return (chunks.size() == chunk_count);
133         }
134 };
135
136 /*
137 === NOTES ===
138
139 A packet is sent through a channel to a peer with a basic header:
140 TODO: Should we have a receiver_peer_id also?
141         Header (7 bytes):
142         [0] u32 protocol_id
143         [4] session_t sender_peer_id
144         [6] u8 channel
145 sender_peer_id:
146         Unique to each peer.
147         value 0 (PEER_ID_INEXISTENT) is reserved for making new connections
148         value 1 (PEER_ID_SERVER) is reserved for server
149         these constants are defined in constants.h
150 channel:
151         The lower the number, the higher the priority is.
152         Only channels 0, 1 and 2 exist.
153 */
154 #define BASE_HEADER_SIZE 7
155 #define CHANNEL_COUNT 3
156 /*
157 Packet types:
158
159 CONTROL: This is a packet used by the protocol.
160 - When this is processed, nothing is handed to the user.
161         Header (2 byte):
162         [0] u8 type
163         [1] u8 controltype
164 controltype and data description:
165         CONTROLTYPE_ACK
166                 [2] u16 seqnum
167         CONTROLTYPE_SET_PEER_ID
168                 [2] session_t peer_id_new
169         CONTROLTYPE_PING
170         - There is no actual reply, but this can be sent in a reliable
171           packet to get a reply
172         CONTROLTYPE_DISCO
173 */
174 //#define TYPE_CONTROL 0
175 #define CONTROLTYPE_ACK 0
176 #define CONTROLTYPE_SET_PEER_ID 1
177 #define CONTROLTYPE_PING 2
178 #define CONTROLTYPE_DISCO 3
179
180 /*
181 ORIGINAL: This is a plain packet with no control and no error
182 checking at all.
183 - When this is processed, it is directly handed to the user.
184         Header (1 byte):
185         [0] u8 type
186 */
187 //#define TYPE_ORIGINAL 1
188 #define ORIGINAL_HEADER_SIZE 1
189 /*
190 SPLIT: These are sequences of packets forming one bigger piece of
191 data.
192 - When processed and all the packet_nums 0...packet_count-1 are
193   present (this should be buffered), the resulting data shall be
194   directly handed to the user.
195 - If the data fails to come up in a reasonable time, the buffer shall
196   be silently discarded.
197 - These can be sent as-is or atop of a RELIABLE packet stream.
198         Header (7 bytes):
199         [0] u8 type
200         [1] u16 seqnum
201         [3] u16 chunk_count
202         [5] u16 chunk_num
203 */
204 //#define TYPE_SPLIT 2
205 /*
206 RELIABLE: Delivery of all RELIABLE packets shall be forced by ACKs,
207 and they shall be delivered in the same order as sent. This is done
208 with a buffer in the receiving and transmitting end.
209 - When this is processed, the contents of each packet is recursively
210   processed as packets.
211         Header (3 bytes):
212         [0] u8 type
213         [1] u16 seqnum
214
215 */
216 //#define TYPE_RELIABLE 3
217 #define RELIABLE_HEADER_SIZE 3
218 #define SEQNUM_INITIAL 65500
219
220 enum PacketType: u8 {
221         PACKET_TYPE_CONTROL = 0,
222         PACKET_TYPE_ORIGINAL = 1,
223         PACKET_TYPE_SPLIT = 2,
224         PACKET_TYPE_RELIABLE = 3,
225         PACKET_TYPE_MAX
226 };
227 /*
228         A buffer which stores reliable packets and sorts them internally
229         for fast access to the smallest one.
230 */
231
232 typedef std::list<BufferedPacket>::iterator RPBSearchResult;
233
234 class ReliablePacketBuffer
235 {
236 public:
237         ReliablePacketBuffer() = default;
238
239         bool getFirstSeqnum(u16& result);
240
241         BufferedPacket popFirst();
242         BufferedPacket popSeqnum(u16 seqnum);
243         void insert(BufferedPacket &p,u16 next_expected);
244
245         void incrementTimeouts(float dtime);
246         std::list<BufferedPacket> getTimedOuts(float timeout,
247                         unsigned int max_packets);
248
249         void print();
250         bool empty();
251         bool containsPacket(u16 seqnum);
252         RPBSearchResult notFound();
253         u32 size();
254
255
256 private:
257         RPBSearchResult findPacket(u16 seqnum);
258
259         std::list<BufferedPacket> m_list;
260         u32 m_list_size = 0;
261
262         u16 m_oldest_non_answered_ack;
263
264         std::mutex m_list_mutex;
265 };
266
267 /*
268         A buffer for reconstructing split packets
269 */
270
271 class IncomingSplitBuffer
272 {
273 public:
274         ~IncomingSplitBuffer();
275         /*
276                 Returns a reference counted buffer of length != 0 when a full split
277                 packet is constructed. If not, returns one of length 0.
278         */
279         SharedBuffer<u8> insert(const BufferedPacket &p, bool reliable);
280
281         void removeUnreliableTimedOuts(float dtime, float timeout);
282
283 private:
284         // Key is seqnum
285         std::map<u16, IncomingSplitPacket*> m_buf;
286
287         std::mutex m_map_mutex;
288 };
289
290 struct OutgoingPacket
291 {
292         session_t peer_id;
293         u8 channelnum;
294         SharedBuffer<u8> data;
295         bool reliable;
296         bool ack;
297
298         OutgoingPacket(session_t peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_,
299                         bool reliable_,bool ack_=false):
300                 peer_id(peer_id_),
301                 channelnum(channelnum_),
302                 data(data_),
303                 reliable(reliable_),
304                 ack(ack_)
305         {
306         }
307 };
308
309 enum ConnectionCommandType{
310         CONNCMD_NONE,
311         CONNCMD_SERVE,
312         CONNCMD_CONNECT,
313         CONNCMD_DISCONNECT,
314         CONNCMD_DISCONNECT_PEER,
315         CONNCMD_SEND,
316         CONNCMD_SEND_TO_ALL,
317         CONCMD_ACK,
318         CONCMD_CREATE_PEER
319 };
320
321 struct ConnectionCommand
322 {
323         enum ConnectionCommandType type = CONNCMD_NONE;
324         Address address;
325         session_t peer_id = PEER_ID_INEXISTENT;
326         u8 channelnum = 0;
327         Buffer<u8> data;
328         bool reliable = false;
329         bool raw = false;
330
331         ConnectionCommand() = default;
332         ConnectionCommand &operator=(const ConnectionCommand &other)
333         {
334                 type = other.type;
335                 address = other.address;
336                 peer_id = other.peer_id;
337                 channelnum = other.channelnum;
338                 // We must copy the buffer here to prevent race condition
339                 data = SharedBuffer<u8>(*other.data, other.data.getSize());
340                 reliable = other.reliable;
341                 raw = other.raw;
342                 return *this;
343         }
344
345         void serve(Address address_)
346         {
347                 type = CONNCMD_SERVE;
348                 address = address_;
349         }
350         void connect(Address address_)
351         {
352                 type = CONNCMD_CONNECT;
353                 address = address_;
354         }
355         void disconnect()
356         {
357                 type = CONNCMD_DISCONNECT;
358         }
359         void disconnect_peer(session_t peer_id_)
360         {
361                 type = CONNCMD_DISCONNECT_PEER;
362                 peer_id = peer_id_;
363         }
364
365         void send(session_t peer_id_, u8 channelnum_, NetworkPacket *pkt, bool reliable_);
366
367         void ack(session_t peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_)
368         {
369                 type = CONCMD_ACK;
370                 peer_id = peer_id_;
371                 channelnum = channelnum_;
372                 data = data_;
373                 reliable = false;
374         }
375
376         void createPeer(session_t peer_id_, const SharedBuffer<u8> &data_)
377         {
378                 type = CONCMD_CREATE_PEER;
379                 peer_id = peer_id_;
380                 data = data_;
381                 channelnum = 0;
382                 reliable = true;
383                 raw = true;
384         }
385 };
386
387 /* maximum window size to use, 0xFFFF is theoretical maximum  don't think about
388  * touching it, the less you're away from it the more likely data corruption
389  * will occur
390  */
391 #define MAX_RELIABLE_WINDOW_SIZE 0x8000
392         /* starting value for window size */
393 #define MIN_RELIABLE_WINDOW_SIZE 0x40
394
395 class Channel
396 {
397
398 public:
399         u16 readNextIncomingSeqNum();
400         u16 incNextIncomingSeqNum();
401
402         u16 getOutgoingSequenceNumber(bool& successfull);
403         u16 readOutgoingSequenceNumber();
404         bool putBackSequenceNumber(u16);
405
406         u16 readNextSplitSeqNum();
407         void setNextSplitSeqNum(u16 seqnum);
408
409         // This is for buffering the incoming packets that are coming in
410         // the wrong order
411         ReliablePacketBuffer incoming_reliables;
412         // This is for buffering the sent packets so that the sender can
413         // re-send them if no ACK is received
414         ReliablePacketBuffer outgoing_reliables_sent;
415
416         //queued reliable packets
417         std::queue<BufferedPacket> queued_reliables;
418
419         //queue commands prior splitting to packets
420         std::deque<ConnectionCommand> queued_commands;
421
422         IncomingSplitBuffer incoming_splits;
423
424         Channel() = default;
425         ~Channel() = default;
426
427         void UpdatePacketLossCounter(unsigned int count);
428         void UpdatePacketTooLateCounter();
429         void UpdateBytesSent(unsigned int bytes,unsigned int packages=1);
430         void UpdateBytesLost(unsigned int bytes);
431         void UpdateBytesReceived(unsigned int bytes);
432
433         void UpdateTimers(float dtime);
434
435         const float getCurrentDownloadRateKB()
436                 { MutexAutoLock lock(m_internal_mutex); return cur_kbps; };
437         const float getMaxDownloadRateKB()
438                 { MutexAutoLock lock(m_internal_mutex); return max_kbps; };
439
440         const float getCurrentLossRateKB()
441                 { MutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; };
442         const float getMaxLossRateKB()
443                 { MutexAutoLock lock(m_internal_mutex); return max_kbps_lost; };
444
445         const float getCurrentIncomingRateKB()
446                 { MutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; };
447         const float getMaxIncomingRateKB()
448                 { MutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; };
449
450         const float getAvgDownloadRateKB()
451                 { MutexAutoLock lock(m_internal_mutex); return avg_kbps; };
452         const float getAvgLossRateKB()
453                 { MutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; };
454         const float getAvgIncomingRateKB()
455                 { MutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; };
456
457         const unsigned int getWindowSize() const { return window_size; };
458
459         void setWindowSize(unsigned int size) { window_size = size; };
460 private:
461         std::mutex m_internal_mutex;
462         int window_size = MIN_RELIABLE_WINDOW_SIZE;
463
464         u16 next_incoming_seqnum = SEQNUM_INITIAL;
465
466         u16 next_outgoing_seqnum = SEQNUM_INITIAL;
467         u16 next_outgoing_split_seqnum = SEQNUM_INITIAL;
468
469         unsigned int current_packet_loss = 0;
470         unsigned int current_packet_too_late = 0;
471         unsigned int current_packet_successful = 0;
472         float packet_loss_counter = 0.0f;
473
474         unsigned int current_bytes_transfered = 0;
475         unsigned int current_bytes_received = 0;
476         unsigned int current_bytes_lost = 0;
477         float max_kbps = 0.0f;
478         float cur_kbps = 0.0f;
479         float avg_kbps = 0.0f;
480         float max_incoming_kbps = 0.0f;
481         float cur_incoming_kbps = 0.0f;
482         float avg_incoming_kbps = 0.0f;
483         float max_kbps_lost = 0.0f;
484         float cur_kbps_lost = 0.0f;
485         float avg_kbps_lost = 0.0f;
486         float bpm_counter = 0.0f;
487
488         unsigned int rate_samples = 0;
489 };
490
491 class Peer;
492
493 class PeerHelper
494 {
495 public:
496         PeerHelper() = default;
497         PeerHelper(Peer* peer);
498         ~PeerHelper();
499
500         PeerHelper&   operator=(Peer* peer);
501         Peer*         operator->() const;
502         bool          operator!();
503         Peer*         operator&() const;
504         bool          operator!=(void* ptr);
505
506 private:
507         Peer *m_peer = nullptr;
508 };
509
510 class Connection;
511
512 typedef enum {
513         CUR_DL_RATE,
514         AVG_DL_RATE,
515         CUR_INC_RATE,
516         AVG_INC_RATE,
517         CUR_LOSS_RATE,
518         AVG_LOSS_RATE,
519 } rate_stat_type;
520
521 class Peer {
522         public:
523                 friend class PeerHelper;
524
525                 Peer(Address address_,u16 id_,Connection* connection) :
526                         id(id_),
527                         m_connection(connection),
528                         address(address_),
529                         m_last_timeout_check(porting::getTimeMs())
530                 {
531                 };
532
533                 virtual ~Peer() {
534                         MutexAutoLock usage_lock(m_exclusive_access_mutex);
535                         FATAL_ERROR_IF(m_usage != 0, "Reference counting failure");
536                 };
537
538                 // Unique id of the peer
539                 u16 id;
540
541                 void Drop();
542
543                 virtual void PutReliableSendCommand(ConnectionCommand &c,
544                                                 unsigned int max_packet_size) {};
545
546                 virtual bool getAddress(MTProtocols type, Address& toset) = 0;
547
548                 bool isPendingDeletion()
549                 { MutexAutoLock lock(m_exclusive_access_mutex); return m_pending_deletion; };
550
551                 void ResetTimeout()
552                         {MutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter = 0.0; };
553
554                 bool isTimedOut(float timeout);
555
556                 unsigned int m_increment_packets_remaining = 9;
557                 unsigned int m_increment_bytes_remaining = 0;
558
559                 virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
560                 virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
561                 virtual SharedBuffer<u8> addSplitPacket(u8 channel, const BufferedPacket &toadd,
562                                 bool reliable)
563                 {
564                         fprintf(stderr,"Peer: addSplitPacket called, this is supposed to be never called!\n");
565                         return SharedBuffer<u8>(0);
566                 };
567
568                 virtual bool Ping(float dtime, SharedBuffer<u8>& data) { return false; };
569
570                 virtual float getStat(rtt_stat_type type) const {
571                         switch (type) {
572                                 case MIN_RTT:
573                                         return m_rtt.min_rtt;
574                                 case MAX_RTT:
575                                         return m_rtt.max_rtt;
576                                 case AVG_RTT:
577                                         return m_rtt.avg_rtt;
578                                 case MIN_JITTER:
579                                         return m_rtt.jitter_min;
580                                 case MAX_JITTER:
581                                         return m_rtt.jitter_max;
582                                 case AVG_JITTER:
583                                         return m_rtt.jitter_avg;
584                         }
585                         return -1;
586                 }
587         protected:
588                 virtual void reportRTT(float rtt) {};
589
590                 void RTTStatistics(float rtt,
591                                                         const std::string &profiler_id = "",
592                                                         unsigned int num_samples = 1000);
593
594                 bool IncUseCount();
595                 void DecUseCount();
596
597                 std::mutex m_exclusive_access_mutex;
598
599                 bool m_pending_deletion = false;
600
601                 Connection* m_connection;
602
603                 // Address of the peer
604                 Address address;
605
606                 // Ping timer
607                 float m_ping_timer = 0.0f;
608         private:
609
610                 struct rttstats {
611                         float jitter_min = FLT_MAX;
612                         float jitter_max = 0.0f;
613                         float jitter_avg = -1.0f;
614                         float min_rtt = FLT_MAX;
615                         float max_rtt = 0.0f;
616                         float avg_rtt = -1.0f;
617
618                         rttstats() = default;
619                 };
620
621                 rttstats m_rtt;
622                 float m_last_rtt = -1.0f;
623
624                 // current usage count
625                 unsigned int m_usage = 0;
626
627                 // Seconds from last receive
628                 float m_timeout_counter = 0.0f;
629
630                 u64 m_last_timeout_check;
631 };
632
633 class UDPPeer : public Peer
634 {
635 public:
636
637         friend class PeerHelper;
638         friend class ConnectionReceiveThread;
639         friend class ConnectionSendThread;
640         friend class Connection;
641
642         UDPPeer(u16 a_id, Address a_address, Connection* connection);
643         virtual ~UDPPeer() = default;
644
645         void PutReliableSendCommand(ConnectionCommand &c,
646                                                         unsigned int max_packet_size);
647
648         bool getAddress(MTProtocols type, Address& toset);
649
650         u16 getNextSplitSequenceNumber(u8 channel);
651         void setNextSplitSequenceNumber(u8 channel, u16 seqnum);
652
653         SharedBuffer<u8> addSplitPacket(u8 channel, const BufferedPacket &toadd,
654                 bool reliable);
655
656 protected:
657         /*
658                 Calculates avg_rtt and resend_timeout.
659                 rtt=-1 only recalculates resend_timeout
660         */
661         void reportRTT(float rtt);
662
663         void RunCommandQueues(
664                                         unsigned int max_packet_size,
665                                         unsigned int maxcommands,
666                                         unsigned int maxtransfer);
667
668         float getResendTimeout()
669                 { MutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; }
670
671         void setResendTimeout(float timeout)
672                 { MutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; }
673         bool Ping(float dtime,SharedBuffer<u8>& data);
674
675         Channel channels[CHANNEL_COUNT];
676         bool m_pending_disconnect = false;
677 private:
678         // This is changed dynamically
679         float resend_timeout = 0.5;
680
681         bool processReliableSendCommand(
682                                         ConnectionCommand &c,
683                                         unsigned int max_packet_size);
684 };
685
686 /*
687         Connection
688 */
689
690 enum ConnectionEventType{
691         CONNEVENT_NONE,
692         CONNEVENT_DATA_RECEIVED,
693         CONNEVENT_PEER_ADDED,
694         CONNEVENT_PEER_REMOVED,
695         CONNEVENT_BIND_FAILED,
696 };
697
698 struct ConnectionEvent
699 {
700         enum ConnectionEventType type = CONNEVENT_NONE;
701         session_t peer_id = 0;
702         Buffer<u8> data;
703         bool timeout = false;
704         Address address;
705
706         ConnectionEvent() = default;
707
708         std::string describe()
709         {
710                 switch(type) {
711                 case CONNEVENT_NONE:
712                         return "CONNEVENT_NONE";
713                 case CONNEVENT_DATA_RECEIVED:
714                         return "CONNEVENT_DATA_RECEIVED";
715                 case CONNEVENT_PEER_ADDED:
716                         return "CONNEVENT_PEER_ADDED";
717                 case CONNEVENT_PEER_REMOVED:
718                         return "CONNEVENT_PEER_REMOVED";
719                 case CONNEVENT_BIND_FAILED:
720                         return "CONNEVENT_BIND_FAILED";
721                 }
722                 return "Invalid ConnectionEvent";
723         }
724
725         void dataReceived(session_t peer_id_, const SharedBuffer<u8> &data_)
726         {
727                 type = CONNEVENT_DATA_RECEIVED;
728                 peer_id = peer_id_;
729                 data = data_;
730         }
731         void peerAdded(session_t peer_id_, Address address_)
732         {
733                 type = CONNEVENT_PEER_ADDED;
734                 peer_id = peer_id_;
735                 address = address_;
736         }
737         void peerRemoved(session_t peer_id_, bool timeout_, Address address_)
738         {
739                 type = CONNEVENT_PEER_REMOVED;
740                 peer_id = peer_id_;
741                 timeout = timeout_;
742                 address = address_;
743         }
744         void bindFailed()
745         {
746                 type = CONNEVENT_BIND_FAILED;
747         }
748 };
749
750 class PeerHandler;
751
752 class Connection
753 {
754 public:
755         friend class ConnectionSendThread;
756         friend class ConnectionReceiveThread;
757
758         Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6,
759                         PeerHandler *peerhandler);
760         ~Connection();
761
762         /* Interface */
763         ConnectionEvent waitEvent(u32 timeout_ms);
764         void putCommand(ConnectionCommand &c);
765
766         void SetTimeoutMs(u32 timeout) { m_bc_receive_timeout = timeout; }
767         void Serve(Address bind_addr);
768         void Connect(Address address);
769         bool Connected();
770         void Disconnect();
771         void Receive(NetworkPacket* pkt);
772         void Send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable);
773         session_t GetPeerID() const { return m_peer_id; }
774         Address GetPeerAddress(session_t peer_id);
775         float getPeerStat(session_t peer_id, rtt_stat_type type);
776         float getLocalStat(rate_stat_type type);
777         const u32 GetProtocolID() const { return m_protocol_id; };
778         const std::string getDesc();
779         void DisconnectPeer(session_t peer_id);
780
781 protected:
782         PeerHelper getPeerNoEx(session_t peer_id);
783         u16   lookupPeer(Address& sender);
784
785         u16 createPeer(Address& sender, MTProtocols protocol, int fd);
786         UDPPeer*  createServerPeer(Address& sender);
787         bool deletePeer(session_t peer_id, bool timeout);
788
789         void SetPeerID(session_t id) { m_peer_id = id; }
790
791         void sendAck(session_t peer_id, u8 channelnum, u16 seqnum);
792
793         void PrintInfo(std::ostream &out);
794
795         std::list<session_t> getPeerIDs()
796         {
797                 MutexAutoLock peerlock(m_peers_mutex);
798                 return m_peer_ids;
799         }
800
801         UDPSocket m_udpSocket;
802         MutexedQueue<ConnectionCommand> m_command_queue;
803
804         void putEvent(ConnectionEvent &e);
805
806         void TriggerSend();
807 private:
808         MutexedQueue<ConnectionEvent> m_event_queue;
809
810         session_t m_peer_id = 0;
811         u32 m_protocol_id;
812
813         std::map<session_t, Peer *> m_peers;
814         std::list<session_t> m_peer_ids;
815         std::mutex m_peers_mutex;
816
817         std::unique_ptr<ConnectionSendThread> m_sendThread;
818         std::unique_ptr<ConnectionReceiveThread> m_receiveThread;
819
820         std::mutex m_info_mutex;
821
822         // Backwards compatibility
823         PeerHandler *m_bc_peerhandler;
824         u32 m_bc_receive_timeout = 0;
825
826         bool m_shutting_down = false;
827
828         session_t m_next_remote_peer_id = 2;
829 };
830
831 } // namespace