]> git.lizzy.rs Git - minetest.git/blob - src/connection.h
Fix serializing of signed numbers in serializeStructToString
[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         u16 m_list_size;
343
344         u16 m_oldest_non_answered_ack;
345
346         JMutex m_list_mutex;
347
348         unsigned int writeptr;
349 };
350
351 /*
352         A buffer for reconstructing split packets
353 */
354
355 class IncomingSplitBuffer
356 {
357 public:
358         ~IncomingSplitBuffer();
359         /*
360                 Returns a reference counted buffer of length != 0 when a full split
361                 packet is constructed. If not, returns one of length 0.
362         */
363         SharedBuffer<u8> insert(BufferedPacket &p, bool reliable);
364         
365         void removeUnreliableTimedOuts(float dtime, float timeout);
366         
367 private:
368         // Key is seqnum
369         std::map<u16, IncomingSplitPacket*> m_buf;
370
371         JMutex m_map_mutex;
372 };
373
374 struct OutgoingPacket
375 {
376         u16 peer_id;
377         u8 channelnum;
378         SharedBuffer<u8> data;
379         bool reliable;
380         bool ack;
381
382         OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_,
383                         bool reliable_,bool ack_=false):
384                 peer_id(peer_id_),
385                 channelnum(channelnum_),
386                 data(data_),
387                 reliable(reliable_),
388                 ack(ack_)
389         {
390         }
391 };
392
393 enum ConnectionCommandType{
394         CONNCMD_NONE,
395         CONNCMD_SERVE,
396         CONNCMD_CONNECT,
397         CONNCMD_DISCONNECT,
398         CONNCMD_DISCONNECT_PEER,
399         CONNCMD_SEND,
400         CONNCMD_SEND_TO_ALL,
401         CONCMD_ACK,
402         CONCMD_CREATE_PEER,
403         CONCMD_DISABLE_LEGACY
404 };
405
406 struct ConnectionCommand
407 {
408         enum ConnectionCommandType type;
409         Address address;
410         u16 peer_id;
411         u8 channelnum;
412         Buffer<u8> data;
413         bool reliable;
414         bool raw;
415
416         ConnectionCommand(): type(CONNCMD_NONE), peer_id(PEER_ID_INEXISTENT), reliable(false), raw(false) {}
417
418         void serve(Address address_)
419         {
420                 type = CONNCMD_SERVE;
421                 address = address_;
422         }
423         void connect(Address address_)
424         {
425                 type = CONNCMD_CONNECT;
426                 address = address_;
427         }
428         void disconnect()
429         {
430                 type = CONNCMD_DISCONNECT;
431         }
432         void disconnect_peer(u16 peer_id_)
433         {
434                 type = CONNCMD_DISCONNECT_PEER;
435                 peer_id = peer_id_;
436         }
437         void send(u16 peer_id_, u8 channelnum_,
438                         SharedBuffer<u8> data_, bool reliable_)
439         {
440                 type = CONNCMD_SEND;
441                 peer_id = peer_id_;
442                 channelnum = channelnum_;
443                 data = data_;
444                 reliable = reliable_;
445         }
446         void sendToAll(u8 channelnum_, SharedBuffer<u8> data_, bool reliable_)
447         {
448                 type = CONNCMD_SEND_TO_ALL;
449                 channelnum = channelnum_;
450                 data = data_;
451                 reliable = reliable_;
452         }
453
454         void ack(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_)
455         {
456                 type = CONCMD_ACK;
457                 peer_id = peer_id_;
458                 channelnum = channelnum_;
459                 data = data_;
460                 reliable = false;
461         }
462
463         void createPeer(u16 peer_id_, SharedBuffer<u8> data_)
464         {
465                 type = CONCMD_CREATE_PEER;
466                 peer_id = peer_id_;
467                 data = data_;
468                 channelnum = 0;
469                 reliable = true;
470                 raw = true;
471         }
472
473         void disableLegacy(u16 peer_id_, SharedBuffer<u8> data_)
474         {
475                 type = CONCMD_DISABLE_LEGACY;
476                 peer_id = peer_id_;
477                 data = data_;
478                 channelnum = 0;
479                 reliable = true;
480                 raw = true;
481         }
482 };
483
484 class Channel
485 {
486
487 public:
488         u16 readNextIncomingSeqNum();
489         u16 incNextIncomingSeqNum();
490
491         u16 getOutgoingSequenceNumber(bool& successfull);
492         u16 readOutgoingSequenceNumber();
493         bool putBackSequenceNumber(u16);
494
495         u16 readNextSplitSeqNum();
496         void setNextSplitSeqNum(u16 seqnum);
497         
498         // This is for buffering the incoming packets that are coming in
499         // the wrong order
500         ReliablePacketBuffer incoming_reliables;
501         // This is for buffering the sent packets so that the sender can
502         // re-send them if no ACK is received
503         ReliablePacketBuffer outgoing_reliables_sent;
504
505         //queued reliable packets
506         Queue<BufferedPacket> queued_reliables;
507
508         //queue commands prior splitting to packets
509         Queue<ConnectionCommand> queued_commands;
510
511         IncomingSplitBuffer incoming_splits;
512
513         Channel();
514         ~Channel();
515
516         void UpdatePacketLossCounter(unsigned int count);
517         void UpdatePacketTooLateCounter();
518         void UpdateBytesSent(unsigned int bytes,unsigned int packages=1);
519         void UpdateBytesLost(unsigned int bytes);
520
521         void UpdateTimers(float dtime);
522
523         const float getCurrentDownloadRateKB()
524                 { JMutexAutoLock lock(m_internal_mutex); return cur_kbps; };
525         const float getMaxDownloadRateKB()
526                 { JMutexAutoLock lock(m_internal_mutex); return max_kbps; };
527
528         const float getCurrentLossRateKB()
529                 { JMutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; };
530         const float getMaxLossRateKB()
531                 { JMutexAutoLock lock(m_internal_mutex); return max_kbps_lost; };
532
533         const float getAvgDownloadRateKB()
534                 { JMutexAutoLock lock(m_internal_mutex); return avg_kbps; };
535         const float getAvgLossRateKB()
536                 { JMutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; };
537
538         const unsigned int getWindowSize() const { return window_size; };
539
540         void setWindowSize(unsigned int size) { window_size = size; };
541 private:
542         JMutex m_internal_mutex;
543         unsigned int window_size;
544
545         u16 next_incoming_seqnum;
546
547         u16 next_outgoing_seqnum;
548         u16 next_outgoing_split_seqnum;
549
550         unsigned int current_packet_loss;
551         unsigned int current_packet_too_late;
552         unsigned int current_packet_successfull;
553         float packet_loss_counter;
554
555         unsigned int current_bytes_transfered;
556         unsigned int current_bytes_lost;
557         float max_kbps;
558         float cur_kbps;
559         float avg_kbps;
560         float max_kbps_lost;
561         float cur_kbps_lost;
562         float avg_kbps_lost;
563         float bpm_counter;
564 };
565
566 class Peer;
567
568 enum PeerChangeType
569 {
570         PEER_ADDED,
571         PEER_REMOVED
572 };
573 struct PeerChange
574 {
575         PeerChangeType type;
576         u16 peer_id;
577         bool timeout;
578 };
579
580 class PeerHandler
581 {
582 public:
583
584         PeerHandler()
585         {
586         }
587         virtual ~PeerHandler()
588         {
589         }
590
591         /*
592                 This is called after the Peer has been inserted into the
593                 Connection's peer container.
594         */
595         virtual void peerAdded(Peer *peer) = 0;
596         /*
597                 This is called before the Peer has been removed from the
598                 Connection's peer container.
599         */
600         virtual void deletingPeer(Peer *peer, bool timeout) = 0;
601 };
602
603 class PeerHelper
604 {
605 public:
606         PeerHelper();
607         PeerHelper(Peer* peer);
608         ~PeerHelper();
609
610         PeerHelper&   operator=(Peer* peer);
611         Peer*         operator->() const;
612         bool          operator!();
613         Peer*         operator&() const;
614         bool          operator!=(void* ptr);
615
616 private:
617         Peer* m_peer;
618 };
619
620 class Connection;
621
622 typedef enum rtt_stat_type {
623         MIN_RTT,
624         MAX_RTT,
625         AVG_RTT,
626         MIN_JITTER,
627         MAX_JITTER,
628         AVG_JITTER
629 } rtt_stat_type;
630
631 class Peer {
632         public:
633                 friend class PeerHelper;
634
635                 Peer(Address address_,u16 id_,Connection* connection) :
636                         id(id_),
637                         m_increment_packets_remaining(9),
638                         m_increment_bytes_remaining(0),
639                         m_pending_deletion(false),
640                         m_connection(connection),
641                         address(address_),
642                         m_ping_timer(0.0),
643                         m_last_rtt(-1.0),
644                         m_usage(0),
645                         m_timeout_counter(0.0),
646                         m_last_timeout_check(porting::getTimeMs()),
647                         m_has_sent_with_id(false)
648                 {
649                         m_rtt.avg_rtt = -1.0;
650                         m_rtt.jitter_avg = -1.0;
651                         m_rtt.jitter_max = 0.0;
652                         m_rtt.max_rtt = 0.0;
653                         m_rtt.jitter_min = FLT_MAX;
654                         m_rtt.min_rtt = FLT_MAX;
655                 };
656
657                 virtual ~Peer() {
658                         JMutexAutoLock usage_lock(m_exclusive_access_mutex);
659                         assert(m_usage == 0);
660                 };
661
662                 // Unique id of the peer
663                 u16 id;
664
665                 void Drop();
666
667                 virtual void PutReliableSendCommand(ConnectionCommand &c,
668                                                 unsigned int max_packet_size) {};
669
670                 virtual bool isActive() { return false; };
671
672                 virtual bool getAddress(MTProtocols type, Address& toset) = 0;
673
674                 void ResetTimeout()
675                         {JMutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; };
676
677                 bool isTimedOut(float timeout);
678
679                 void setSentWithID()
680                 { JMutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; };
681
682                 bool hasSentWithID()
683                 { JMutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; };
684
685                 unsigned int m_increment_packets_remaining;
686                 unsigned int m_increment_bytes_remaining;
687
688                 virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
689                 virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
690                 virtual SharedBuffer<u8> addSpiltPacket(u8 channel,
691                                                                                                 BufferedPacket toadd,
692                                                                                                 bool reliable)
693                                 {
694                                         fprintf(stderr,"Peer: addSplitPacket called, this is supposed to be never called!\n");
695                                         return SharedBuffer<u8>(0);
696                                 };
697
698                 virtual bool Ping(float dtime, SharedBuffer<u8>& data) { return false; };
699
700                 virtual float getStat(rtt_stat_type type) const {
701                         switch (type) {
702                                 case MIN_RTT:
703                                         return m_rtt.min_rtt;
704                                 case MAX_RTT:
705                                         return m_rtt.max_rtt;
706                                 case AVG_RTT:
707                                         return m_rtt.avg_rtt;
708                                 case MIN_JITTER:
709                                         return m_rtt.jitter_min;
710                                 case MAX_JITTER:
711                                         return m_rtt.jitter_max;
712                                 case AVG_JITTER:
713                                         return m_rtt.jitter_avg;
714                         }
715                         return -1;
716                 }
717         protected:
718                 virtual void reportRTT(float rtt) {};
719
720                 void RTTStatistics(float rtt,
721                                                         std::string profiler_id="",
722                                                         unsigned int num_samples=1000);
723
724                 bool IncUseCount();
725                 void DecUseCount();
726
727                 JMutex m_exclusive_access_mutex;
728
729                 bool m_pending_deletion;
730
731                 Connection* m_connection;
732
733                 // Address of the peer
734                 Address address;
735
736                 // Ping timer
737                 float m_ping_timer;
738         private:
739
740                 struct rttstats {
741                         float jitter_min;
742                         float jitter_max;
743                         float jitter_avg;
744                         float min_rtt;
745                         float max_rtt;
746                         float avg_rtt;
747                 };
748
749                 rttstats m_rtt;
750                 float    m_last_rtt;
751
752                 // current usage count
753                 unsigned int m_usage;
754
755                 // Seconds from last receive
756                 float m_timeout_counter;
757
758                 u32 m_last_timeout_check;
759
760                 bool m_has_sent_with_id;
761 };
762
763 class UDPPeer : public Peer
764 {
765 public:
766
767         friend class PeerHelper;
768         friend class ConnectionReceiveThread;
769         friend class ConnectionSendThread;
770
771         UDPPeer(u16 a_id, Address a_address, Connection* connection);
772         virtual ~UDPPeer() {};
773
774         void PutReliableSendCommand(ConnectionCommand &c,
775                                                         unsigned int max_packet_size);
776
777         bool isActive()
778         { return ((hasSentWithID()) && (!m_pending_deletion)); };
779
780         bool getAddress(MTProtocols type, Address& toset);
781
782         void setNonLegacyPeer();
783
784         bool getLegacyPeer()
785         { return m_legacy_peer; }
786
787         u16 getNextSplitSequenceNumber(u8 channel);
788         void setNextSplitSequenceNumber(u8 channel, u16 seqnum);
789
790         SharedBuffer<u8> addSpiltPacket(u8 channel,
791                                                                         BufferedPacket toadd,
792                                                                         bool reliable);
793
794
795 protected:
796         /*
797                 Calculates avg_rtt and resend_timeout.
798                 rtt=-1 only recalculates resend_timeout
799         */
800         void reportRTT(float rtt);
801
802         void RunCommandQueues(
803                                         unsigned int max_packet_size,
804                                         unsigned int maxcommands,
805                                         unsigned int maxtransfer);
806
807         float getResendTimeout()
808                 { JMutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; }
809
810         void setResendTimeout(float timeout)
811                 { JMutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; }
812         bool Ping(float dtime,SharedBuffer<u8>& data);
813
814         Channel channels[CHANNEL_COUNT];
815         bool m_pending_disconnect;
816 private:
817         // This is changed dynamically
818         float resend_timeout;
819
820         bool processReliableSendCommand(
821                                         ConnectionCommand &c,
822                                         unsigned int max_packet_size);
823
824         bool m_legacy_peer;
825 };
826
827 /*
828         Connection
829 */
830
831 enum ConnectionEventType{
832         CONNEVENT_NONE,
833         CONNEVENT_DATA_RECEIVED,
834         CONNEVENT_PEER_ADDED,
835         CONNEVENT_PEER_REMOVED,
836         CONNEVENT_BIND_FAILED,
837 };
838
839 struct ConnectionEvent
840 {
841         enum ConnectionEventType type;
842         u16 peer_id;
843         Buffer<u8> data;
844         bool timeout;
845         Address address;
846
847         ConnectionEvent(): type(CONNEVENT_NONE) {}
848
849         std::string describe()
850         {
851                 switch(type){
852                 case CONNEVENT_NONE:
853                         return "CONNEVENT_NONE";
854                 case CONNEVENT_DATA_RECEIVED:
855                         return "CONNEVENT_DATA_RECEIVED";
856                 case CONNEVENT_PEER_ADDED:
857                         return "CONNEVENT_PEER_ADDED";
858                 case CONNEVENT_PEER_REMOVED:
859                         return "CONNEVENT_PEER_REMOVED";
860                 case CONNEVENT_BIND_FAILED:
861                         return "CONNEVENT_BIND_FAILED";
862                 }
863                 return "Invalid ConnectionEvent";
864         }
865         
866         void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
867         {
868                 type = CONNEVENT_DATA_RECEIVED;
869                 peer_id = peer_id_;
870                 data = data_;
871         }
872         void peerAdded(u16 peer_id_, Address address_)
873         {
874                 type = CONNEVENT_PEER_ADDED;
875                 peer_id = peer_id_;
876                 address = address_;
877         }
878         void peerRemoved(u16 peer_id_, bool timeout_, Address address_)
879         {
880                 type = CONNEVENT_PEER_REMOVED;
881                 peer_id = peer_id_;
882                 timeout = timeout_;
883                 address = address_;
884         }
885         void bindFailed()
886         {
887                 type = CONNEVENT_BIND_FAILED;
888         }
889 };
890
891 class ConnectionSendThread : public JThread {
892
893 public:
894         friend class UDPPeer;
895
896         ConnectionSendThread(Connection* parent,
897                                                         unsigned int max_packet_size, float timeout);
898
899         void * Thread       ();
900
901         void Trigger();
902
903         void setPeerTimeout(float peer_timeout)
904                 { m_timeout = peer_timeout; }
905
906 private:
907         void runTimeouts    (float dtime);
908         void rawSend        (const BufferedPacket &packet);
909         bool rawSendAsPacket(u16 peer_id, u8 channelnum,
910                                                         SharedBuffer<u8> data, bool reliable);
911
912         void processReliableCommand (ConnectionCommand &c);
913         void processNonReliableCommand (ConnectionCommand &c);
914         void serve          (Address bind_address);
915         void connect        (Address address);
916         void disconnect     ();
917         void disconnect_peer(u16 peer_id);
918         void send           (u16 peer_id, u8 channelnum,
919                                                         SharedBuffer<u8> data);
920         void sendReliable   (ConnectionCommand &c);
921         void sendToAll      (u8 channelnum,
922                                                         SharedBuffer<u8> data);
923         void sendToAllReliable(ConnectionCommand &c);
924
925         void sendPackets    (float dtime);
926
927         void sendAsPacket   (u16 peer_id, u8 channelnum,
928                                                         SharedBuffer<u8> data,bool ack=false);
929
930         void sendAsPacketReliable(BufferedPacket& p, Channel* channel);
931
932         bool packetsQueued();
933
934         Connection*           m_connection;
935         unsigned int          m_max_packet_size;
936         float                 m_timeout;
937         Queue<OutgoingPacket> m_outgoing_queue;
938         JSemaphore            m_send_sleep_semaphore;
939
940         unsigned int          m_iteration_packets_avaialble;
941         unsigned int          m_max_commands_per_iteration;
942         unsigned int          m_max_data_packets_per_iteration;
943         unsigned int          m_max_packets_requeued;
944 };
945
946 class ConnectionReceiveThread : public JThread {
947 public:
948         ConnectionReceiveThread(Connection* parent,
949                                                         unsigned int max_packet_size);
950
951         void * Thread       ();
952
953 private:
954         void receive        ();
955
956         // Returns next data from a buffer if possible
957         // If found, returns true; if not, false.
958         // If found, sets peer_id and dst
959         bool getFromBuffers (u16 &peer_id, SharedBuffer<u8> &dst);
960
961         bool checkIncomingBuffers(Channel *channel, u16 &peer_id,
962                                                         SharedBuffer<u8> &dst);
963
964         /*
965                 Processes a packet with the basic header stripped out.
966                 Parameters:
967                         packetdata: Data in packet (with no base headers)
968                         peer_id: peer id of the sender of the packet in question
969                         channelnum: channel on which the packet was sent
970                         reliable: true if recursing into a reliable packet
971         */
972         SharedBuffer<u8> processPacket(Channel *channel,
973                                                         SharedBuffer<u8> packetdata, u16 peer_id,
974                                                         u8 channelnum, bool reliable);
975
976
977         Connection*           m_connection;
978         unsigned int          m_max_packet_size;
979 };
980
981 class Connection
982 {
983 public:
984         friend class ConnectionSendThread;
985         friend class ConnectionReceiveThread;
986
987         Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6);
988         Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6,
989                         PeerHandler *peerhandler);
990         ~Connection();
991
992         /* Interface */
993         ConnectionEvent getEvent();
994         ConnectionEvent waitEvent(u32 timeout_ms);
995         void putCommand(ConnectionCommand &c);
996         
997         void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; }
998         void Serve(Address bind_addr);
999         void Connect(Address address);
1000         bool Connected();
1001         void Disconnect();
1002         u32 Receive(u16 &peer_id, SharedBuffer<u8> &data);
1003         void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
1004         void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
1005         u16 GetPeerID(){ return m_peer_id; }
1006         Address GetPeerAddress(u16 peer_id);
1007         float GetPeerAvgRTT(u16 peer_id);
1008         const u32 GetProtocolID() const { return m_protocol_id; };
1009         const std::string getDesc();
1010         void DisconnectPeer(u16 peer_id);
1011
1012 protected:
1013         PeerHelper getPeer(u16 peer_id);
1014         PeerHelper getPeerNoEx(u16 peer_id);
1015         u16   lookupPeer(Address& sender);
1016
1017         u16 createPeer(Address& sender, MTProtocols protocol, int fd);
1018         UDPPeer*  createServerPeer(Address& sender);
1019         bool deletePeer(u16 peer_id, bool timeout);
1020
1021         void SetPeerID(u16 id){ m_peer_id = id; }
1022
1023         void sendAck(u16 peer_id, u8 channelnum, u16 seqnum);
1024
1025         void PrintInfo(std::ostream &out);
1026         void PrintInfo();
1027
1028         std::list<u16> getPeerIDs();
1029
1030         UDPSocket m_udpSocket;
1031         MutexedQueue<ConnectionCommand> m_command_queue;
1032
1033         void putEvent(ConnectionEvent &e);
1034
1035         void TriggerSend()
1036                 { m_sendThread.Trigger(); }
1037 private:
1038         std::list<Peer*> getPeers();
1039
1040         MutexedQueue<ConnectionEvent> m_event_queue;
1041
1042         u16 m_peer_id;
1043         u32 m_protocol_id;
1044         
1045         std::map<u16, Peer*> m_peers;
1046         JMutex m_peers_mutex;
1047
1048         ConnectionSendThread m_sendThread;
1049         ConnectionReceiveThread m_receiveThread;
1050
1051         JMutex m_info_mutex;
1052
1053         // Backwards compatibility
1054         PeerHandler *m_bc_peerhandler;
1055         int m_bc_receive_timeout;
1056
1057         bool m_shutting_down;
1058
1059         u16 m_next_remote_peer_id;
1060 };
1061
1062 } // namespace
1063
1064 #endif
1065