3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #ifndef CONNECTION_HEADER
21 #define CONNECTION_HEADER
23 #include "irrlichttypes_bloated.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"
44 class NotFoundException : public BaseException
47 NotFoundException(const char *s):
52 class PeerNotFoundException : public BaseException
55 PeerNotFoundException(const char *s):
60 class ConnectionException : public BaseException
63 ConnectionException(const char *s):
68 class ConnectionBindFailed : public BaseException
71 ConnectionBindFailed(const char *s):
76 class InvalidIncomingDataException : public BaseException
79 InvalidIncomingDataException(const char *s):
84 class InvalidOutgoingDataException : public BaseException
87 InvalidOutgoingDataException(const char *s):
92 class NoIncomingDataException : public BaseException
95 NoIncomingDataException(const char *s):
100 class ProcessedSilentlyException : public BaseException
103 ProcessedSilentlyException(const char *s):
108 class ProcessedQueued : public BaseException
111 ProcessedQueued(const char *s):
116 class IncomingDataCorruption : public BaseException
119 IncomingDataCorruption(const char *s):
124 typedef enum MTProtocols {
127 MTP_MINETEST_RELIABLE_UDP
130 #define SEQNUM_MAX 65535
131 inline bool seqnum_higher(u16 totest, u16 base)
135 if ((totest - base) > (SEQNUM_MAX/2))
142 if ((base - totest) > (SEQNUM_MAX/2))
149 inline bool seqnum_in_window(u16 seqnum, u16 next,u16 window_size)
151 u16 window_start = next;
152 u16 window_end = ( next + window_size ) % (SEQNUM_MAX+1);
154 if (window_start < window_end)
156 return ((seqnum >= window_start) && (seqnum < window_end));
160 return ((seqnum < window_end) || (seqnum >= window_start));
164 struct BufferedPacket
166 BufferedPacket(u8 *a_data, u32 a_size):
169 BufferedPacket(u32 a_size):
170 data(a_size), time(0.0), totaltime(0.0), absolute_send_time(-1),
173 Buffer<u8> data; // Data of the packet, including headers
174 float time = 0.0f; // Seconds from buffering the packet or re-sending
175 float totaltime = 0.0f; // Seconds from buffering the packet
176 u64 absolute_send_time = -1;
177 Address address; // Sender or destination
178 unsigned int resend_count = 0;
181 // This adds the base headers to the data and makes a packet out of it
182 BufferedPacket makePacket(Address &address, u8 *data, u32 datasize,
183 u32 protocol_id, u16 sender_peer_id, u8 channel);
184 BufferedPacket makePacket(Address &address, SharedBuffer<u8> &data,
185 u32 protocol_id, u16 sender_peer_id, u8 channel);
187 // Add the TYPE_ORIGINAL header to the data
188 SharedBuffer<u8> makeOriginalPacket(
189 SharedBuffer<u8> data);
191 // Split data in chunks and add TYPE_SPLIT headers to them
192 std::list<SharedBuffer<u8> > makeSplitPacket(
193 SharedBuffer<u8> data,
197 // Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
198 // Increments split_seqnum if a split packet is made
199 std::list<SharedBuffer<u8> > makeAutoSplitPacket(
200 SharedBuffer<u8> data,
204 // Add the TYPE_RELIABLE header to the data
205 SharedBuffer<u8> makeReliablePacket(
206 SharedBuffer<u8> data,
209 struct IncomingSplitPacket
211 IncomingSplitPacket() {}
212 // Key is chunk number, value is data without headers
213 std::map<u16, SharedBuffer<u8> > chunks;
215 float time = 0.0f; // Seconds from adding
216 bool reliable = false; // If true, isn't deleted on timeout
220 return (chunks.size() == chunk_count);
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?
231 [4] u16 sender_peer_id
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
239 The lower the number, the higher the priority is.
240 Only channels 0, 1 and 2 exist.
242 #define BASE_HEADER_SIZE 7
243 #define CHANNEL_COUNT 3
247 CONTROL: This is a packet used by the protocol.
248 - When this is processed, nothing is handed to the user.
252 controltype and data description:
255 CONTROLTYPE_SET_PEER_ID
258 - There is no actual reply, but this can be sent in a reliable
259 packet to get a reply
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
270 ORIGINAL: This is a plain packet with no control and no error
272 - When this is processed, it is directly handed to the user.
276 #define TYPE_ORIGINAL 1
277 #define ORIGINAL_HEADER_SIZE 1
279 SPLIT: These are sequences of packets forming one bigger piece of
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.
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.
305 #define TYPE_RELIABLE 3
306 #define RELIABLE_HEADER_SIZE 3
307 #define SEQNUM_INITIAL 65500
310 A buffer which stores reliable packets and sorts them internally
311 for fast access to the smallest one.
314 typedef std::list<BufferedPacket>::iterator RPBSearchResult;
316 class ReliablePacketBuffer
319 ReliablePacketBuffer() {};
321 bool getFirstSeqnum(u16& result);
323 BufferedPacket popFirst();
324 BufferedPacket popSeqnum(u16 seqnum);
325 void insert(BufferedPacket &p,u16 next_expected);
327 void incrementTimeouts(float dtime);
328 std::list<BufferedPacket> getTimedOuts(float timeout,
329 unsigned int max_packets);
333 bool containsPacket(u16 seqnum);
334 RPBSearchResult notFound();
339 RPBSearchResult findPacket(u16 seqnum);
341 std::list<BufferedPacket> m_list;
344 u16 m_oldest_non_answered_ack;
346 std::mutex m_list_mutex;
350 A buffer for reconstructing split packets
353 class IncomingSplitBuffer
356 ~IncomingSplitBuffer();
358 Returns a reference counted buffer of length != 0 when a full split
359 packet is constructed. If not, returns one of length 0.
361 SharedBuffer<u8> insert(BufferedPacket &p, bool reliable);
363 void removeUnreliableTimedOuts(float dtime, float timeout);
367 std::map<u16, IncomingSplitPacket*> m_buf;
369 std::mutex m_map_mutex;
372 struct OutgoingPacket
376 SharedBuffer<u8> data;
380 OutgoingPacket(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_,
381 bool reliable_,bool ack_=false):
383 channelnum(channelnum_),
391 enum ConnectionCommandType{
396 CONNCMD_DISCONNECT_PEER,
401 CONCMD_DISABLE_LEGACY
404 struct ConnectionCommand
406 enum ConnectionCommandType type = CONNCMD_NONE;
408 u16 peer_id = PEER_ID_INEXISTENT;
411 bool reliable = false;
414 ConnectionCommand() {}
416 void serve(Address address_)
418 type = CONNCMD_SERVE;
421 void connect(Address address_)
423 type = CONNCMD_CONNECT;
428 type = CONNCMD_DISCONNECT;
430 void disconnect_peer(u16 peer_id_)
432 type = CONNCMD_DISCONNECT_PEER;
436 void send(u16 peer_id_, u8 channelnum_, NetworkPacket* pkt, bool reliable_);
438 void ack(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_)
442 channelnum = channelnum_;
447 void createPeer(u16 peer_id_, const SharedBuffer<u8> &data_)
449 type = CONCMD_CREATE_PEER;
457 void disableLegacy(u16 peer_id_, const SharedBuffer<u8> &data_)
459 type = CONCMD_DISABLE_LEGACY;
468 /* maximum window size to use, 0xFFFF is theoretical maximum don't think about
469 * touching it, the less you're away from it the more likely data corruption
472 #define MAX_RELIABLE_WINDOW_SIZE 0x8000
473 /* starting value for window size */
474 #define MIN_RELIABLE_WINDOW_SIZE 0x40
480 u16 readNextIncomingSeqNum();
481 u16 incNextIncomingSeqNum();
483 u16 getOutgoingSequenceNumber(bool& successfull);
484 u16 readOutgoingSequenceNumber();
485 bool putBackSequenceNumber(u16);
487 u16 readNextSplitSeqNum();
488 void setNextSplitSeqNum(u16 seqnum);
490 // This is for buffering the incoming packets that are coming in
492 ReliablePacketBuffer incoming_reliables;
493 // This is for buffering the sent packets so that the sender can
494 // re-send them if no ACK is received
495 ReliablePacketBuffer outgoing_reliables_sent;
497 //queued reliable packets
498 std::queue<BufferedPacket> queued_reliables;
500 //queue commands prior splitting to packets
501 std::deque<ConnectionCommand> queued_commands;
503 IncomingSplitBuffer incoming_splits;
508 void UpdatePacketLossCounter(unsigned int count);
509 void UpdatePacketTooLateCounter();
510 void UpdateBytesSent(unsigned int bytes,unsigned int packages=1);
511 void UpdateBytesLost(unsigned int bytes);
512 void UpdateBytesReceived(unsigned int bytes);
514 void UpdateTimers(float dtime, bool legacy_peer);
516 const float getCurrentDownloadRateKB()
517 { MutexAutoLock lock(m_internal_mutex); return cur_kbps; };
518 const float getMaxDownloadRateKB()
519 { MutexAutoLock lock(m_internal_mutex); return max_kbps; };
521 const float getCurrentLossRateKB()
522 { MutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; };
523 const float getMaxLossRateKB()
524 { MutexAutoLock lock(m_internal_mutex); return max_kbps_lost; };
526 const float getCurrentIncomingRateKB()
527 { MutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; };
528 const float getMaxIncomingRateKB()
529 { MutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; };
531 const float getAvgDownloadRateKB()
532 { MutexAutoLock lock(m_internal_mutex); return avg_kbps; };
533 const float getAvgLossRateKB()
534 { MutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; };
535 const float getAvgIncomingRateKB()
536 { MutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; };
538 const unsigned int getWindowSize() const { return window_size; };
540 void setWindowSize(unsigned int size) { window_size = size; };
542 std::mutex m_internal_mutex;
543 int window_size = MIN_RELIABLE_WINDOW_SIZE;
545 u16 next_incoming_seqnum = SEQNUM_INITIAL;
547 u16 next_outgoing_seqnum = SEQNUM_INITIAL;
548 u16 next_outgoing_split_seqnum = SEQNUM_INITIAL;
550 unsigned int current_packet_loss = 0;
551 unsigned int current_packet_too_late = 0;
552 unsigned int current_packet_successfull = 0;
553 float packet_loss_counter = 0.0f;
555 unsigned int current_bytes_transfered = 0;
556 unsigned int current_bytes_received = 0;
557 unsigned int current_bytes_lost = 0;
558 float max_kbps = 0.0f;
559 float cur_kbps = 0.0f;
560 float avg_kbps = 0.0f;
561 float max_incoming_kbps = 0.0f;
562 float cur_incoming_kbps = 0.0f;
563 float avg_incoming_kbps = 0.0f;
564 float max_kbps_lost = 0.0f;
565 float cur_kbps_lost = 0.0f;
566 float avg_kbps_lost = 0.0f;
567 float bpm_counter = 0.0f;
569 unsigned int rate_samples = 0;
581 PeerChange(PeerChangeType t, u16 _peer_id, bool _timeout):
582 type(t), peer_id(_peer_id), timeout(_timeout) {}
583 PeerChange() = delete;
597 virtual ~PeerHandler()
602 This is called after the Peer has been inserted into the
603 Connection's peer container.
605 virtual void peerAdded(Peer *peer) = 0;
607 This is called before the Peer has been removed from the
608 Connection's peer container.
610 virtual void deletingPeer(Peer *peer, bool timeout) = 0;
617 PeerHelper(Peer* peer);
620 PeerHelper& operator=(Peer* peer);
621 Peer* operator->() const;
623 Peer* operator&() const;
624 bool operator!=(void* ptr);
627 Peer *m_peer = nullptr;
652 friend class PeerHelper;
654 Peer(Address address_,u16 id_,Connection* connection) :
656 m_connection(connection),
658 m_last_timeout_check(porting::getTimeMs())
663 MutexAutoLock usage_lock(m_exclusive_access_mutex);
664 FATAL_ERROR_IF(m_usage != 0, "Reference counting failure");
667 // Unique id of the peer
672 virtual void PutReliableSendCommand(ConnectionCommand &c,
673 unsigned int max_packet_size) {};
675 virtual bool getAddress(MTProtocols type, Address& toset) = 0;
677 bool isPendingDeletion()
678 { MutexAutoLock lock(m_exclusive_access_mutex); return m_pending_deletion; };
681 {MutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter = 0.0; };
683 bool isTimedOut(float timeout);
685 unsigned int m_increment_packets_remaining = 9;
686 unsigned int m_increment_bytes_remaining = 0;
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,
694 fprintf(stderr,"Peer: addSplitPacket called, this is supposed to be never called!\n");
695 return SharedBuffer<u8>(0);
698 virtual bool Ping(float dtime, SharedBuffer<u8>& data) { return false; };
700 virtual float getStat(rtt_stat_type type) const {
703 return m_rtt.min_rtt;
705 return m_rtt.max_rtt;
707 return m_rtt.avg_rtt;
709 return m_rtt.jitter_min;
711 return m_rtt.jitter_max;
713 return m_rtt.jitter_avg;
718 virtual void reportRTT(float rtt) {};
720 void RTTStatistics(float rtt,
721 const std::string &profiler_id = "",
722 unsigned int num_samples = 1000);
727 std::mutex m_exclusive_access_mutex;
729 bool m_pending_deletion = false;
731 Connection* m_connection;
733 // Address of the peer
737 float m_ping_timer = 0.0f;
741 float jitter_min = FLT_MAX;
742 float jitter_max = 0.0f;
743 float jitter_avg = -1.0f;
744 float min_rtt = FLT_MAX;
745 float max_rtt = 0.0f;
746 float avg_rtt = -1.0f;
752 float m_last_rtt = -1.0f;
754 // current usage count
755 unsigned int m_usage = 0;
757 // Seconds from last receive
758 float m_timeout_counter = 0.0f;
760 u64 m_last_timeout_check;
763 class UDPPeer : public Peer
767 friend class PeerHelper;
768 friend class ConnectionReceiveThread;
769 friend class ConnectionSendThread;
770 friend class Connection;
772 UDPPeer(u16 a_id, Address a_address, Connection* connection);
773 virtual ~UDPPeer() {};
775 void PutReliableSendCommand(ConnectionCommand &c,
776 unsigned int max_packet_size);
778 bool getAddress(MTProtocols type, Address& toset);
780 void setNonLegacyPeer();
783 { return m_legacy_peer; }
785 u16 getNextSplitSequenceNumber(u8 channel);
786 void setNextSplitSequenceNumber(u8 channel, u16 seqnum);
788 SharedBuffer<u8> addSpiltPacket(u8 channel,
789 BufferedPacket toadd,
795 Calculates avg_rtt and resend_timeout.
796 rtt=-1 only recalculates resend_timeout
798 void reportRTT(float rtt);
800 void RunCommandQueues(
801 unsigned int max_packet_size,
802 unsigned int maxcommands,
803 unsigned int maxtransfer);
805 float getResendTimeout()
806 { MutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; }
808 void setResendTimeout(float timeout)
809 { MutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; }
810 bool Ping(float dtime,SharedBuffer<u8>& data);
812 Channel channels[CHANNEL_COUNT];
813 bool m_pending_disconnect = false;
815 // This is changed dynamically
816 float resend_timeout = 0.5;
818 bool processReliableSendCommand(
819 ConnectionCommand &c,
820 unsigned int max_packet_size);
822 bool m_legacy_peer = true;
829 enum ConnectionEventType{
831 CONNEVENT_DATA_RECEIVED,
832 CONNEVENT_PEER_ADDED,
833 CONNEVENT_PEER_REMOVED,
834 CONNEVENT_BIND_FAILED,
837 struct ConnectionEvent
839 enum ConnectionEventType type = CONNEVENT_NONE;
842 bool timeout = false;
847 std::string describe()
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";
861 return "Invalid ConnectionEvent";
864 void dataReceived(u16 peer_id_, const SharedBuffer<u8> &data_)
866 type = CONNEVENT_DATA_RECEIVED;
870 void peerAdded(u16 peer_id_, Address address_)
872 type = CONNEVENT_PEER_ADDED;
876 void peerRemoved(u16 peer_id_, bool timeout_, Address address_)
878 type = CONNEVENT_PEER_REMOVED;
885 type = CONNEVENT_BIND_FAILED;
889 class ConnectionSendThread : public Thread {
892 friend class UDPPeer;
894 ConnectionSendThread(unsigned int max_packet_size, float timeout);
900 void setParent(Connection* parent) {
901 assert(parent != NULL); // Pre-condition
902 m_connection = parent;
905 void setPeerTimeout(float peer_timeout)
906 { m_timeout = peer_timeout; }
909 void runTimeouts (float dtime);
910 void rawSend (const BufferedPacket &packet);
911 bool rawSendAsPacket(u16 peer_id, u8 channelnum,
912 SharedBuffer<u8> data, bool reliable);
914 void processReliableCommand (ConnectionCommand &c);
915 void processNonReliableCommand (ConnectionCommand &c);
916 void serve (Address bind_address);
917 void connect (Address address);
919 void disconnect_peer(u16 peer_id);
920 void send (u16 peer_id, u8 channelnum,
921 SharedBuffer<u8> data);
922 void sendReliable (ConnectionCommand &c);
923 void sendToAll (u8 channelnum,
924 SharedBuffer<u8> data);
925 void sendToAllReliable(ConnectionCommand &c);
927 void sendPackets (float dtime);
929 void sendAsPacket (u16 peer_id, u8 channelnum,
930 SharedBuffer<u8> data,bool ack=false);
932 void sendAsPacketReliable(BufferedPacket& p, Channel* channel);
934 bool packetsQueued();
936 Connection *m_connection = nullptr;
937 unsigned int m_max_packet_size;
939 std::queue<OutgoingPacket> m_outgoing_queue;
940 Semaphore m_send_sleep_semaphore;
942 unsigned int m_iteration_packets_avaialble;
943 unsigned int m_max_commands_per_iteration = 1;
944 unsigned int m_max_data_packets_per_iteration;
945 unsigned int m_max_packets_requeued = 256;
948 class ConnectionReceiveThread : public Thread {
950 ConnectionReceiveThread(unsigned int max_packet_size);
954 void setParent(Connection *parent) {
955 assert(parent); // Pre-condition
956 m_connection = parent;
962 // Returns next data from a buffer if possible
963 // If found, returns true; if not, false.
964 // If found, sets peer_id and dst
965 bool getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst);
967 bool checkIncomingBuffers(Channel *channel, u16 &peer_id,
968 SharedBuffer<u8> &dst);
971 Processes a packet with the basic header stripped out.
973 packetdata: Data in packet (with no base headers)
974 peer_id: peer id of the sender of the packet in question
975 channelnum: channel on which the packet was sent
976 reliable: true if recursing into a reliable packet
978 SharedBuffer<u8> processPacket(Channel *channel,
979 SharedBuffer<u8> packetdata, u16 peer_id,
980 u8 channelnum, bool reliable);
983 Connection *m_connection = nullptr;
989 friend class ConnectionSendThread;
990 friend class ConnectionReceiveThread;
992 Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6,
993 PeerHandler *peerhandler);
997 ConnectionEvent waitEvent(u32 timeout_ms);
998 void putCommand(ConnectionCommand &c);
1000 void SetTimeoutMs(int timeout) { m_bc_receive_timeout = timeout; }
1001 void Serve(Address bind_addr);
1002 void Connect(Address address);
1005 void Receive(NetworkPacket* pkt);
1006 void Send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
1007 u16 GetPeerID() { return m_peer_id; }
1008 Address GetPeerAddress(u16 peer_id);
1009 float getPeerStat(u16 peer_id, rtt_stat_type type);
1010 float getLocalStat(rate_stat_type type);
1011 const u32 GetProtocolID() const { return m_protocol_id; };
1012 const std::string getDesc();
1013 void DisconnectPeer(u16 peer_id);
1016 PeerHelper getPeer(u16 peer_id);
1017 PeerHelper getPeerNoEx(u16 peer_id);
1018 u16 lookupPeer(Address& sender);
1020 u16 createPeer(Address& sender, MTProtocols protocol, int fd);
1021 UDPPeer* createServerPeer(Address& sender);
1022 bool deletePeer(u16 peer_id, bool timeout);
1024 void SetPeerID(u16 id) { m_peer_id = id; }
1026 void sendAck(u16 peer_id, u8 channelnum, u16 seqnum);
1028 void PrintInfo(std::ostream &out);
1031 std::list<u16> getPeerIDs()
1033 MutexAutoLock peerlock(m_peers_mutex);
1037 UDPSocket m_udpSocket;
1038 MutexedQueue<ConnectionCommand> m_command_queue;
1040 void putEvent(ConnectionEvent &e);
1043 { m_sendThread.Trigger(); }
1045 std::list<Peer*> getPeers();
1047 MutexedQueue<ConnectionEvent> m_event_queue;
1052 std::map<u16, Peer*> m_peers;
1053 std::list<u16> m_peer_ids;
1054 std::mutex m_peers_mutex;
1056 ConnectionSendThread m_sendThread;
1057 ConnectionReceiveThread m_receiveThread;
1059 std::mutex m_info_mutex;
1061 // Backwards compatibility
1062 PeerHandler *m_bc_peerhandler;
1063 int m_bc_receive_timeout = 0;
1065 bool m_shutting_down = false;
1067 u16 m_next_remote_peer_id = 2;