]> git.lizzy.rs Git - minetest.git/blob - src/connection.h
Revert binary database block position encoding
[minetest.git] / src / 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 #ifndef CONNECTION_HEADER
21 #define CONNECTION_HEADER
22
23 #include "irrlichttypes_bloated.h"
24 #include "socket.h"
25 #include "exceptions.h"
26 #include "constants.h"
27 #include "util/pointer.h"
28 #include "util/container.h"
29 #include "util/thread.h"
30 #include "util/numeric.h"
31 #include <iostream>
32 #include <fstream>
33 #include <list>
34 #include <map>
35
36 namespace con
37 {
38
39 /*
40         Exceptions
41 */
42 class NotFoundException : public BaseException
43 {
44 public:
45         NotFoundException(const char *s):
46                 BaseException(s)
47         {}
48 };
49
50 class PeerNotFoundException : public BaseException
51 {
52 public:
53         PeerNotFoundException(const char *s):
54                 BaseException(s)
55         {}
56 };
57
58 class ConnectionException : public BaseException
59 {
60 public:
61         ConnectionException(const char *s):
62                 BaseException(s)
63         {}
64 };
65
66 class ConnectionBindFailed : public BaseException
67 {
68 public:
69         ConnectionBindFailed(const char *s):
70                 BaseException(s)
71         {}
72 };
73
74 class InvalidIncomingDataException : public BaseException
75 {
76 public:
77         InvalidIncomingDataException(const char *s):
78                 BaseException(s)
79         {}
80 };
81
82 class InvalidOutgoingDataException : public BaseException
83 {
84 public:
85         InvalidOutgoingDataException(const char *s):
86                 BaseException(s)
87         {}
88 };
89
90 class NoIncomingDataException : public BaseException
91 {
92 public:
93         NoIncomingDataException(const char *s):
94                 BaseException(s)
95         {}
96 };
97
98 class ProcessedSilentlyException : public BaseException
99 {
100 public:
101         ProcessedSilentlyException(const char *s):
102                 BaseException(s)
103         {}
104 };
105
106 class ProcessedQueued : public BaseException
107 {
108 public:
109         ProcessedQueued(const char *s):
110                 BaseException(s)
111         {}
112 };
113
114 class IncomingDataCorruption : public BaseException
115 {
116 public:
117         IncomingDataCorruption(const char *s):
118                 BaseException(s)
119         {}
120 };
121
122 typedef enum MTProtocols {
123         PRIMARY,
124         UDP,
125         MINETEST_RELIABLE_UDP
126 } MTProtocols;
127
128 #define SEQNUM_MAX 65535
129 inline bool seqnum_higher(u16 totest, u16 base)
130 {
131         if (totest > base)
132         {
133                 if((totest - base) > (SEQNUM_MAX/2))
134                         return false;
135                 else
136                         return true;
137         }
138         else
139         {
140                 if((base - totest) > (SEQNUM_MAX/2))
141                         return true;
142                 else
143                         return false;
144         }
145 }
146
147 inline bool seqnum_in_window(u16 seqnum, u16 next,u16 window_size)
148 {
149         u16 window_start = next;
150         u16 window_end   = ( next + window_size ) % (SEQNUM_MAX+1);
151
152         if (window_start < window_end)
153         {
154                 return ((seqnum >= window_start) && (seqnum < window_end));
155         }
156         else
157         {
158                 return ((seqnum < window_end) || (seqnum >= window_start));
159         }
160 }
161
162 struct BufferedPacket
163 {
164         BufferedPacket(u8 *a_data, u32 a_size):
165                 data(a_data, a_size), time(0.0), totaltime(0.0), absolute_send_time(-1)
166         {}
167         BufferedPacket(u32 a_size):
168                 data(a_size), time(0.0), totaltime(0.0), absolute_send_time(-1)
169         {}
170         SharedBuffer<u8> data; // Data of the packet, including headers
171         float time; // Seconds from buffering the packet or re-sending
172         float totaltime; // Seconds from buffering the packet
173         unsigned int absolute_send_time;
174         Address address; // Sender or destination
175 };
176
177 // This adds the base headers to the data and makes a packet out of it
178 BufferedPacket makePacket(Address &address, u8 *data, u32 datasize,
179                 u32 protocol_id, u16 sender_peer_id, u8 channel);
180 BufferedPacket makePacket(Address &address, SharedBuffer<u8> &data,
181                 u32 protocol_id, u16 sender_peer_id, u8 channel);
182
183 // Add the TYPE_ORIGINAL header to the data
184 SharedBuffer<u8> makeOriginalPacket(
185                 SharedBuffer<u8> data);
186
187 // Split data in chunks and add TYPE_SPLIT headers to them
188 std::list<SharedBuffer<u8> > makeSplitPacket(
189                 SharedBuffer<u8> data,
190                 u32 chunksize_max,
191                 u16 seqnum);
192
193 // Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
194 // Increments split_seqnum if a split packet is made
195 std::list<SharedBuffer<u8> > makeAutoSplitPacket(
196                 SharedBuffer<u8> data,
197                 u32 chunksize_max,
198                 u16 &split_seqnum);
199
200 // Add the TYPE_RELIABLE header to the data
201 SharedBuffer<u8> makeReliablePacket(
202                 SharedBuffer<u8> data,
203                 u16 seqnum);
204
205 struct IncomingSplitPacket
206 {
207         IncomingSplitPacket()
208         {
209                 time = 0.0;
210                 reliable = false;
211         }
212         // Key is chunk number, value is data without headers
213         std::map<u16, SharedBuffer<u8> > chunks;
214         u32 chunk_count;
215         float time; // Seconds from adding
216         bool reliable; // If true, isn't deleted on timeout
217
218         bool allReceived()
219         {
220                 return (chunks.size() == chunk_count);
221         }
222 };
223
224 /*
225 === NOTES ===
226
227 A packet is sent through a channel to a peer with a basic header:
228 TODO: Should we have a receiver_peer_id also?
229         Header (7 bytes):
230         [0] u32 protocol_id
231         [4] u16 sender_peer_id
232         [6] u8 channel
233 sender_peer_id:
234         Unique to each peer.
235         value 0 (PEER_ID_INEXISTENT) is reserved for making new connections
236         value 1 (PEER_ID_SERVER) is reserved for server
237         these constants are defined in constants.h
238 channel:
239         The lower the number, the higher the priority is.
240         Only channels 0, 1 and 2 exist.
241 */
242 #define BASE_HEADER_SIZE 7
243 #define CHANNEL_COUNT 3
244 /*
245 Packet types:
246
247 CONTROL: This is a packet used by the protocol.
248 - When this is processed, nothing is handed to the user.
249         Header (2 byte):
250         [0] u8 type
251         [1] u8 controltype
252 controltype and data description:
253         CONTROLTYPE_ACK
254                 [2] u16 seqnum
255         CONTROLTYPE_SET_PEER_ID
256                 [2] u16 peer_id_new
257         CONTROLTYPE_PING
258         - There is no actual reply, but this can be sent in a reliable
259           packet to get a reply
260         CONTROLTYPE_DISCO
261 */
262 #define TYPE_CONTROL 0
263 #define CONTROLTYPE_ACK 0
264 #define CONTROLTYPE_SET_PEER_ID 1
265 #define CONTROLTYPE_PING 2
266 #define CONTROLTYPE_DISCO 3
267 #define CONTROLTYPE_ENABLE_BIG_SEND_WINDOW 4
268
269 /*
270 ORIGINAL: This is a plain packet with no control and no error
271 checking at all.
272 - When this is processed, it is directly handed to the user.
273         Header (1 byte):
274         [0] u8 type
275 */
276 #define TYPE_ORIGINAL 1
277 #define ORIGINAL_HEADER_SIZE 1
278 /*
279 SPLIT: These are sequences of packets forming one bigger piece of
280 data.
281 - When processed and all the packet_nums 0...packet_count-1 are
282   present (this should be buffered), the resulting data shall be
283   directly handed to the user.
284 - If the data fails to come up in a reasonable time, the buffer shall
285   be silently discarded.
286 - These can be sent as-is or atop of a RELIABLE packet stream.
287         Header (7 bytes):
288         [0] u8 type
289         [1] u16 seqnum
290         [3] u16 chunk_count
291         [5] u16 chunk_num
292 */
293 #define TYPE_SPLIT 2
294 /*
295 RELIABLE: Delivery of all RELIABLE packets shall be forced by ACKs,
296 and they shall be delivered in the same order as sent. This is done
297 with a buffer in the receiving and transmitting end.
298 - When this is processed, the contents of each packet is recursively
299   processed as packets.
300         Header (3 bytes):
301         [0] u8 type
302         [1] u16 seqnum
303
304 */
305 #define TYPE_RELIABLE 3
306 #define RELIABLE_HEADER_SIZE 3
307 #define SEQNUM_INITIAL 65500
308
309 /*
310         A buffer which stores reliable packets and sorts them internally
311         for fast access to the smallest one.
312 */
313
314 typedef std::list<BufferedPacket>::iterator RPBSearchResult;
315
316 class ReliablePacketBuffer
317 {
318 public:
319         ReliablePacketBuffer();
320
321         bool getFirstSeqnum(u16& result);
322
323         BufferedPacket popFirst();
324         BufferedPacket popSeqnum(u16 seqnum);
325         void insert(BufferedPacket &p,u16 next_expected);
326
327         void incrementTimeouts(float dtime);
328         std::list<BufferedPacket> getTimedOuts(float timeout,
329                         unsigned int max_packets);
330
331         void print();
332         bool empty();
333         bool containsPacket(u16 seqnum);
334         RPBSearchResult notFound();
335         u32 size();
336
337
338 private:
339         RPBSearchResult findPacket(u16 seqnum);
340
341         std::list<BufferedPacket> m_list;
342         u32 m_list_size;
343
344         u16 m_oldest_non_answered_ack;
345
346         JMutex m_list_mutex;
347 };
348
349 /*
350         A buffer for reconstructing split packets
351 */
352
353 class IncomingSplitBuffer
354 {
355 public:
356         ~IncomingSplitBuffer();
357         /*
358                 Returns a reference counted buffer of length != 0 when a full split
359                 packet is constructed. If not, returns one of length 0.
360         */
361         SharedBuffer<u8> insert(BufferedPacket &p, bool reliable);
362         
363         void removeUnreliableTimedOuts(float dtime, float timeout);
364         
365 private:
366         // Key is seqnum
367         std::map<u16, IncomingSplitPacket*> m_buf;
368
369         JMutex m_map_mutex;
370 };
371
372 struct OutgoingPacket
373 {
374         u16 peer_id;
375         u8 channelnum;
376         SharedBuffer<u8> data;
377         bool reliable;
378         bool ack;
379
380         OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_,
381                         bool reliable_,bool ack_=false):
382                 peer_id(peer_id_),
383                 channelnum(channelnum_),
384                 data(data_),
385                 reliable(reliable_),
386                 ack(ack_)
387         {
388         }
389 };
390
391 enum ConnectionCommandType{
392         CONNCMD_NONE,
393         CONNCMD_SERVE,
394         CONNCMD_CONNECT,
395         CONNCMD_DISCONNECT,
396         CONNCMD_DISCONNECT_PEER,
397         CONNCMD_SEND,
398         CONNCMD_SEND_TO_ALL,
399         CONCMD_ACK,
400         CONCMD_CREATE_PEER,
401         CONCMD_DISABLE_LEGACY
402 };
403
404 struct ConnectionCommand
405 {
406         enum ConnectionCommandType type;
407         Address address;
408         u16 peer_id;
409         u8 channelnum;
410         Buffer<u8> data;
411         bool reliable;
412         bool raw;
413
414         ConnectionCommand(): type(CONNCMD_NONE), peer_id(PEER_ID_INEXISTENT), reliable(false), raw(false) {}
415
416         void serve(Address address_)
417         {
418                 type = CONNCMD_SERVE;
419                 address = address_;
420         }
421         void connect(Address address_)
422         {
423                 type = CONNCMD_CONNECT;
424                 address = address_;
425         }
426         void disconnect()
427         {
428                 type = CONNCMD_DISCONNECT;
429         }
430         void disconnect_peer(u16 peer_id_)
431         {
432                 type = CONNCMD_DISCONNECT_PEER;
433                 peer_id = peer_id_;
434         }
435         void send(u16 peer_id_, u8 channelnum_,
436                         SharedBuffer<u8> data_, bool reliable_)
437         {
438                 type = CONNCMD_SEND;
439                 peer_id = peer_id_;
440                 channelnum = channelnum_;
441                 data = data_;
442                 reliable = reliable_;
443         }
444         void sendToAll(u8 channelnum_, SharedBuffer<u8> data_, bool reliable_)
445         {
446                 type = CONNCMD_SEND_TO_ALL;
447                 channelnum = channelnum_;
448                 data = data_;
449                 reliable = reliable_;
450         }
451
452         void ack(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_)
453         {
454                 type = CONCMD_ACK;
455                 peer_id = peer_id_;
456                 channelnum = channelnum_;
457                 data = data_;
458                 reliable = false;
459         }
460
461         void createPeer(u16 peer_id_, SharedBuffer<u8> data_)
462         {
463                 type = CONCMD_CREATE_PEER;
464                 peer_id = peer_id_;
465                 data = data_;
466                 channelnum = 0;
467                 reliable = true;
468                 raw = true;
469         }
470
471         void disableLegacy(u16 peer_id_, SharedBuffer<u8> data_)
472         {
473                 type = CONCMD_DISABLE_LEGACY;
474                 peer_id = peer_id_;
475                 data = data_;
476                 channelnum = 0;
477                 reliable = true;
478                 raw = true;
479         }
480 };
481
482 class Channel
483 {
484
485 public:
486         u16 readNextIncomingSeqNum();
487         u16 incNextIncomingSeqNum();
488
489         u16 getOutgoingSequenceNumber(bool& successfull);
490         u16 readOutgoingSequenceNumber();
491         bool putBackSequenceNumber(u16);
492
493         u16 readNextSplitSeqNum();
494         void setNextSplitSeqNum(u16 seqnum);
495         
496         // This is for buffering the incoming packets that are coming in
497         // the wrong order
498         ReliablePacketBuffer incoming_reliables;
499         // This is for buffering the sent packets so that the sender can
500         // re-send them if no ACK is received
501         ReliablePacketBuffer outgoing_reliables_sent;
502
503         //queued reliable packets
504         Queue<BufferedPacket> queued_reliables;
505
506         //queue commands prior splitting to packets
507         Queue<ConnectionCommand> queued_commands;
508
509         IncomingSplitBuffer incoming_splits;
510
511         Channel();
512         ~Channel();
513
514         void UpdatePacketLossCounter(unsigned int count);
515         void UpdatePacketTooLateCounter();
516         void UpdateBytesSent(unsigned int bytes,unsigned int packages=1);
517         void UpdateBytesLost(unsigned int bytes);
518
519         void UpdateTimers(float dtime);
520
521         const float getCurrentDownloadRateKB()
522                 { JMutexAutoLock lock(m_internal_mutex); return cur_kbps; };
523         const float getMaxDownloadRateKB()
524                 { JMutexAutoLock lock(m_internal_mutex); return max_kbps; };
525
526         const float getCurrentLossRateKB()
527                 { JMutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; };
528         const float getMaxLossRateKB()
529                 { JMutexAutoLock lock(m_internal_mutex); return max_kbps_lost; };
530
531         const float getAvgDownloadRateKB()
532                 { JMutexAutoLock lock(m_internal_mutex); return avg_kbps; };
533         const float getAvgLossRateKB()
534                 { JMutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; };
535
536         const unsigned int getWindowSize() const { return window_size; };
537
538         void setWindowSize(unsigned int size) { window_size = size; };
539 private:
540         JMutex m_internal_mutex;
541         unsigned int window_size;
542
543         u16 next_incoming_seqnum;
544
545         u16 next_outgoing_seqnum;
546         u16 next_outgoing_split_seqnum;
547
548         unsigned int current_packet_loss;
549         unsigned int current_packet_too_late;
550         unsigned int current_packet_successfull;
551         float packet_loss_counter;
552
553         unsigned int current_bytes_transfered;
554         unsigned int current_bytes_lost;
555         float max_kbps;
556         float cur_kbps;
557         float avg_kbps;
558         float max_kbps_lost;
559         float cur_kbps_lost;
560         float avg_kbps_lost;
561         float bpm_counter;
562 };
563
564 class Peer;
565
566 enum PeerChangeType
567 {
568         PEER_ADDED,
569         PEER_REMOVED
570 };
571 struct PeerChange
572 {
573         PeerChangeType type;
574         u16 peer_id;
575         bool timeout;
576 };
577
578 class PeerHandler
579 {
580 public:
581
582         PeerHandler()
583         {
584         }
585         virtual ~PeerHandler()
586         {
587         }
588
589         /*
590                 This is called after the Peer has been inserted into the
591                 Connection's peer container.
592         */
593         virtual void peerAdded(Peer *peer) = 0;
594         /*
595                 This is called before the Peer has been removed from the
596                 Connection's peer container.
597         */
598         virtual void deletingPeer(Peer *peer, bool timeout) = 0;
599 };
600
601 class PeerHelper
602 {
603 public:
604         PeerHelper();
605         PeerHelper(Peer* peer);
606         ~PeerHelper();
607
608         PeerHelper&   operator=(Peer* peer);
609         Peer*         operator->() const;
610         bool          operator!();
611         Peer*         operator&() const;
612         bool          operator!=(void* ptr);
613
614 private:
615         Peer* m_peer;
616 };
617
618 class Connection;
619
620 typedef enum rtt_stat_type {
621         MIN_RTT,
622         MAX_RTT,
623         AVG_RTT,
624         MIN_JITTER,
625         MAX_JITTER,
626         AVG_JITTER
627 } rtt_stat_type;
628
629 class Peer {
630         public:
631                 friend class PeerHelper;
632
633                 Peer(Address address_,u16 id_,Connection* connection) :
634                         id(id_),
635                         m_increment_packets_remaining(9),
636                         m_increment_bytes_remaining(0),
637                         m_pending_deletion(false),
638                         m_connection(connection),
639                         address(address_),
640                         m_ping_timer(0.0),
641                         m_last_rtt(-1.0),
642                         m_usage(0),
643                         m_timeout_counter(0.0),
644                         m_last_timeout_check(porting::getTimeMs()),
645                         m_has_sent_with_id(false)
646                 {
647                         m_rtt.avg_rtt = -1.0;
648                         m_rtt.jitter_avg = -1.0;
649                         m_rtt.jitter_max = 0.0;
650                         m_rtt.max_rtt = 0.0;
651                         m_rtt.jitter_min = FLT_MAX;
652                         m_rtt.min_rtt = FLT_MAX;
653                 };
654
655                 virtual ~Peer() {
656                         JMutexAutoLock usage_lock(m_exclusive_access_mutex);
657                         assert(m_usage == 0);
658                 };
659
660                 // Unique id of the peer
661                 u16 id;
662
663                 void Drop();
664
665                 virtual void PutReliableSendCommand(ConnectionCommand &c,
666                                                 unsigned int max_packet_size) {};
667
668                 virtual bool isActive() { return false; };
669
670                 virtual bool getAddress(MTProtocols type, Address& toset) = 0;
671
672                 void ResetTimeout()
673                         {JMutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; };
674
675                 bool isTimedOut(float timeout);
676
677                 void setSentWithID()
678                 { JMutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; };
679
680                 bool hasSentWithID()
681                 { JMutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; };
682
683                 unsigned int m_increment_packets_remaining;
684                 unsigned int m_increment_bytes_remaining;
685
686                 virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
687                 virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
688                 virtual SharedBuffer<u8> addSpiltPacket(u8 channel,
689                                                                                                 BufferedPacket toadd,
690                                                                                                 bool reliable)
691                                 {
692                                         fprintf(stderr,"Peer: addSplitPacket called, this is supposed to be never called!\n");
693                                         return SharedBuffer<u8>(0);
694                                 };
695
696                 virtual bool Ping(float dtime, SharedBuffer<u8>& data) { return false; };
697
698                 virtual float getStat(rtt_stat_type type) const {
699                         switch (type) {
700                                 case MIN_RTT:
701                                         return m_rtt.min_rtt;
702                                 case MAX_RTT:
703                                         return m_rtt.max_rtt;
704                                 case AVG_RTT:
705                                         return m_rtt.avg_rtt;
706                                 case MIN_JITTER:
707                                         return m_rtt.jitter_min;
708                                 case MAX_JITTER:
709                                         return m_rtt.jitter_max;
710                                 case AVG_JITTER:
711                                         return m_rtt.jitter_avg;
712                         }
713                         return -1;
714                 }
715         protected:
716                 virtual void reportRTT(float rtt) {};
717
718                 void RTTStatistics(float rtt,
719                                                         std::string profiler_id="",
720                                                         unsigned int num_samples=1000);
721
722                 bool IncUseCount();
723                 void DecUseCount();
724
725                 JMutex m_exclusive_access_mutex;
726
727                 bool m_pending_deletion;
728
729                 Connection* m_connection;
730
731                 // Address of the peer
732                 Address address;
733
734                 // Ping timer
735                 float m_ping_timer;
736         private:
737
738                 struct rttstats {
739                         float jitter_min;
740                         float jitter_max;
741                         float jitter_avg;
742                         float min_rtt;
743                         float max_rtt;
744                         float avg_rtt;
745                 };
746
747                 rttstats m_rtt;
748                 float    m_last_rtt;
749
750                 // current usage count
751                 unsigned int m_usage;
752
753                 // Seconds from last receive
754                 float m_timeout_counter;
755
756                 u32 m_last_timeout_check;
757
758                 bool m_has_sent_with_id;
759 };
760
761 class UDPPeer : public Peer
762 {
763 public:
764
765         friend class PeerHelper;
766         friend class ConnectionReceiveThread;
767         friend class ConnectionSendThread;
768
769         UDPPeer(u16 a_id, Address a_address, Connection* connection);
770         virtual ~UDPPeer() {};
771
772         void PutReliableSendCommand(ConnectionCommand &c,
773                                                         unsigned int max_packet_size);
774
775         bool isActive()
776         { return ((hasSentWithID()) && (!m_pending_deletion)); };
777
778         bool getAddress(MTProtocols type, Address& toset);
779
780         void setNonLegacyPeer();
781
782         bool getLegacyPeer()
783         { return m_legacy_peer; }
784
785         u16 getNextSplitSequenceNumber(u8 channel);
786         void setNextSplitSequenceNumber(u8 channel, u16 seqnum);
787
788         SharedBuffer<u8> addSpiltPacket(u8 channel,
789                                                                         BufferedPacket toadd,
790                                                                         bool reliable);
791
792
793 protected:
794         /*
795                 Calculates avg_rtt and resend_timeout.
796                 rtt=-1 only recalculates resend_timeout
797         */
798         void reportRTT(float rtt);
799
800         void RunCommandQueues(
801                                         unsigned int max_packet_size,
802                                         unsigned int maxcommands,
803                                         unsigned int maxtransfer);
804
805         float getResendTimeout()
806                 { JMutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; }
807
808         void setResendTimeout(float timeout)
809                 { JMutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; }
810         bool Ping(float dtime,SharedBuffer<u8>& data);
811
812         Channel channels[CHANNEL_COUNT];
813         bool m_pending_disconnect;
814 private:
815         // This is changed dynamically
816         float resend_timeout;
817
818         bool processReliableSendCommand(
819                                         ConnectionCommand &c,
820                                         unsigned int max_packet_size);
821
822         bool m_legacy_peer;
823 };
824
825 /*
826         Connection
827 */
828
829 enum ConnectionEventType{
830         CONNEVENT_NONE,
831         CONNEVENT_DATA_RECEIVED,
832         CONNEVENT_PEER_ADDED,
833         CONNEVENT_PEER_REMOVED,
834         CONNEVENT_BIND_FAILED,
835 };
836
837 struct ConnectionEvent
838 {
839         enum ConnectionEventType type;
840         u16 peer_id;
841         Buffer<u8> data;
842         bool timeout;
843         Address address;
844
845         ConnectionEvent(): type(CONNEVENT_NONE) {}
846
847         std::string describe()
848         {
849                 switch(type){
850                 case CONNEVENT_NONE:
851                         return "CONNEVENT_NONE";
852                 case CONNEVENT_DATA_RECEIVED:
853                         return "CONNEVENT_DATA_RECEIVED";
854                 case CONNEVENT_PEER_ADDED:
855                         return "CONNEVENT_PEER_ADDED";
856                 case CONNEVENT_PEER_REMOVED:
857                         return "CONNEVENT_PEER_REMOVED";
858                 case CONNEVENT_BIND_FAILED:
859                         return "CONNEVENT_BIND_FAILED";
860                 }
861                 return "Invalid ConnectionEvent";
862         }
863         
864         void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
865         {
866                 type = CONNEVENT_DATA_RECEIVED;
867                 peer_id = peer_id_;
868                 data = data_;
869         }
870         void peerAdded(u16 peer_id_, Address address_)
871         {
872                 type = CONNEVENT_PEER_ADDED;
873                 peer_id = peer_id_;
874                 address = address_;
875         }
876         void peerRemoved(u16 peer_id_, bool timeout_, Address address_)
877         {
878                 type = CONNEVENT_PEER_REMOVED;
879                 peer_id = peer_id_;
880                 timeout = timeout_;
881                 address = address_;
882         }
883         void bindFailed()
884         {
885                 type = CONNEVENT_BIND_FAILED;
886         }
887 };
888
889 class ConnectionSendThread : public JThread {
890
891 public:
892         friend class UDPPeer;
893
894         ConnectionSendThread(Connection* parent,
895                                                         unsigned int max_packet_size, float timeout);
896
897         void * Thread       ();
898
899         void Trigger();
900
901         void setPeerTimeout(float peer_timeout)
902                 { m_timeout = peer_timeout; }
903
904 private:
905         void runTimeouts    (float dtime);
906         void rawSend        (const BufferedPacket &packet);
907         bool rawSendAsPacket(u16 peer_id, u8 channelnum,
908                                                         SharedBuffer<u8> data, bool reliable);
909
910         void processReliableCommand (ConnectionCommand &c);
911         void processNonReliableCommand (ConnectionCommand &c);
912         void serve          (Address bind_address);
913         void connect        (Address address);
914         void disconnect     ();
915         void disconnect_peer(u16 peer_id);
916         void send           (u16 peer_id, u8 channelnum,
917                                                         SharedBuffer<u8> data);
918         void sendReliable   (ConnectionCommand &c);
919         void sendToAll      (u8 channelnum,
920                                                         SharedBuffer<u8> data);
921         void sendToAllReliable(ConnectionCommand &c);
922
923         void sendPackets    (float dtime);
924
925         void sendAsPacket   (u16 peer_id, u8 channelnum,
926                                                         SharedBuffer<u8> data,bool ack=false);
927
928         void sendAsPacketReliable(BufferedPacket& p, Channel* channel);
929
930         bool packetsQueued();
931
932         Connection*           m_connection;
933         unsigned int          m_max_packet_size;
934         float                 m_timeout;
935         Queue<OutgoingPacket> m_outgoing_queue;
936         JSemaphore            m_send_sleep_semaphore;
937
938         unsigned int          m_iteration_packets_avaialble;
939         unsigned int          m_max_commands_per_iteration;
940         unsigned int          m_max_data_packets_per_iteration;
941         unsigned int          m_max_packets_requeued;
942 };
943
944 class ConnectionReceiveThread : public JThread {
945 public:
946         ConnectionReceiveThread(Connection* parent,
947                                                         unsigned int max_packet_size);
948
949         void * Thread       ();
950
951 private:
952         void receive        ();
953
954         // Returns next data from a buffer if possible
955         // If found, returns true; if not, false.
956         // If found, sets peer_id and dst
957         bool getFromBuffers (u16 &peer_id, SharedBuffer<u8> &dst);
958
959         bool checkIncomingBuffers(Channel *channel, u16 &peer_id,
960                                                         SharedBuffer<u8> &dst);
961
962         /*
963                 Processes a packet with the basic header stripped out.
964                 Parameters:
965                         packetdata: Data in packet (with no base headers)
966                         peer_id: peer id of the sender of the packet in question
967                         channelnum: channel on which the packet was sent
968                         reliable: true if recursing into a reliable packet
969         */
970         SharedBuffer<u8> processPacket(Channel *channel,
971                                                         SharedBuffer<u8> packetdata, u16 peer_id,
972                                                         u8 channelnum, bool reliable);
973
974
975         Connection*           m_connection;
976 };
977
978 class Connection
979 {
980 public:
981         friend class ConnectionSendThread;
982         friend class ConnectionReceiveThread;
983
984         Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6);
985         Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6,
986                         PeerHandler *peerhandler);
987         ~Connection();
988
989         /* Interface */
990         ConnectionEvent getEvent();
991         ConnectionEvent waitEvent(u32 timeout_ms);
992         void putCommand(ConnectionCommand &c);
993         
994         void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; }
995         void Serve(Address bind_addr);
996         void Connect(Address address);
997         bool Connected();
998         void Disconnect();
999         u32 Receive(u16 &peer_id, SharedBuffer<u8> &data);
1000         void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
1001         void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
1002         u16 GetPeerID(){ return m_peer_id; }
1003         Address GetPeerAddress(u16 peer_id);
1004         float getPeerStat(u16 peer_id, rtt_stat_type type);
1005         const u32 GetProtocolID() const { return m_protocol_id; };
1006         const std::string getDesc();
1007         void DisconnectPeer(u16 peer_id);
1008
1009 protected:
1010         PeerHelper getPeer(u16 peer_id);
1011         PeerHelper getPeerNoEx(u16 peer_id);
1012         u16   lookupPeer(Address& sender);
1013
1014         u16 createPeer(Address& sender, MTProtocols protocol, int fd);
1015         UDPPeer*  createServerPeer(Address& sender);
1016         bool deletePeer(u16 peer_id, bool timeout);
1017
1018         void SetPeerID(u16 id){ m_peer_id = id; }
1019
1020         void sendAck(u16 peer_id, u8 channelnum, u16 seqnum);
1021
1022         void PrintInfo(std::ostream &out);
1023         void PrintInfo();
1024
1025         std::list<u16> getPeerIDs();
1026
1027         UDPSocket m_udpSocket;
1028         MutexedQueue<ConnectionCommand> m_command_queue;
1029
1030         void putEvent(ConnectionEvent &e);
1031
1032         void TriggerSend()
1033                 { m_sendThread.Trigger(); }
1034 private:
1035         std::list<Peer*> getPeers();
1036
1037         MutexedQueue<ConnectionEvent> m_event_queue;
1038
1039         u16 m_peer_id;
1040         u32 m_protocol_id;
1041         
1042         std::map<u16, Peer*> m_peers;
1043         JMutex m_peers_mutex;
1044
1045         ConnectionSendThread m_sendThread;
1046         ConnectionReceiveThread m_receiveThread;
1047
1048         JMutex m_info_mutex;
1049
1050         // Backwards compatibility
1051         PeerHandler *m_bc_peerhandler;
1052         int m_bc_receive_timeout;
1053
1054         bool m_shutting_down;
1055
1056         u16 m_next_remote_peer_id;
1057 };
1058
1059 } // namespace
1060
1061 #endif
1062