#pragma once
-#include "irrlichttypes_bloated.h"
+#include "irrlichttypes.h"
#include "peerhandler.h"
#include "socket.h"
#include "constants.h"
#include "util/container.h"
#include "util/thread.h"
#include "util/numeric.h"
+#include "networkprotocol.h"
#include <iostream>
-#include <fstream>
-#include <list>
+#include <vector>
#include <map>
-class NetworkPacket;
-
-namespace con
-{
-
-class ConnectionReceiveThread;
-class ConnectionSendThread;
-
-typedef enum MTProtocols {
- MTP_PRIMARY,
- MTP_UDP,
- MTP_MINETEST_RELIABLE_UDP
-} MTProtocols;
-
#define MAX_UDP_PEERS 65535
-#define SEQNUM_MAX 65535
-
-inline bool seqnum_higher(u16 totest, u16 base)
-{
- if (totest > base)
- {
- if ((totest - base) > (SEQNUM_MAX/2))
- return false;
-
- return true;
- }
-
- if ((base - totest) > (SEQNUM_MAX/2))
- return true;
-
- return false;
-}
-
-inline bool seqnum_in_window(u16 seqnum, u16 next,u16 window_size)
-{
- u16 window_start = next;
- u16 window_end = ( next + window_size ) % (SEQNUM_MAX+1);
-
- if (window_start < window_end) {
- return ((seqnum >= window_start) && (seqnum < window_end));
- }
-
-
- return ((seqnum < window_end) || (seqnum >= window_start));
-}
-
-static inline float CALC_DTIME(u64 lasttime, u64 curtime)
-{
- float value = ( curtime - lasttime) / 1000.0;
- return MYMAX(MYMIN(value,0.1),0.0);
-}
-
-struct BufferedPacket
-{
- BufferedPacket(u8 *a_data, u32 a_size):
- data(a_data, a_size)
- {}
- BufferedPacket(u32 a_size):
- data(a_size)
- {}
- Buffer<u8> data; // Data of the packet, including headers
- float time = 0.0f; // Seconds from buffering the packet or re-sending
- float totaltime = 0.0f; // Seconds from buffering the packet
- u64 absolute_send_time = -1;
- Address address; // Sender or destination
- unsigned int resend_count = 0;
-};
-
-// This adds the base headers to the data and makes a packet out of it
-BufferedPacket makePacket(Address &address, const SharedBuffer<u8> &data,
- u32 protocol_id, u16 sender_peer_id, u8 channel);
-
-// Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
-// Increments split_seqnum if a split packet is made
-void makeAutoSplitPacket(const SharedBuffer<u8> &data, u32 chunksize_max,
- u16 &split_seqnum, std::list<SharedBuffer<u8>> *list);
-
-// Add the TYPE_RELIABLE header to the data
-SharedBuffer<u8> makeReliablePacket(const SharedBuffer<u8> &data, u16 seqnum);
-
-struct IncomingSplitPacket
-{
- IncomingSplitPacket(u32 cc, bool r):
- chunk_count(cc), reliable(r) {}
-
- IncomingSplitPacket() = delete;
-
- // Key is chunk number, value is data without headers
- std::map<u16, SharedBuffer<u8>> chunks;
- u32 chunk_count;
- float time = 0.0f; // Seconds from adding
- bool reliable = false; // If true, isn't deleted on timeout
-
- bool allReceived() const
- {
- return (chunks.size() == chunk_count);
- }
-};
-
/*
=== NOTES ===
A packet is sent through a channel to a peer with a basic header:
-TODO: Should we have a receiver_peer_id also?
Header (7 bytes):
[0] u32 protocol_id
- [4] u16 sender_peer_id
+ [4] session_t sender_peer_id
[6] u8 channel
sender_peer_id:
Unique to each peer.
value 1 (PEER_ID_SERVER) is reserved for server
these constants are defined in constants.h
channel:
- The lower the number, the higher the priority is.
- Only channels 0, 1 and 2 exist.
+ Channel numbers have no intrinsic meaning. Currently only 0, 1, 2 exist.
*/
#define BASE_HEADER_SIZE 7
#define CHANNEL_COUNT 3
+
/*
Packet types:
CONTROLTYPE_ACK
[2] u16 seqnum
CONTROLTYPE_SET_PEER_ID
- [2] u16 peer_id_new
+ [2] session_t peer_id_new
CONTROLTYPE_PING
- There is no actual reply, but this can be sent in a reliable
packet to get a reply
CONTROLTYPE_DISCO
*/
-//#define TYPE_CONTROL 0
-#define CONTROLTYPE_ACK 0
-#define CONTROLTYPE_SET_PEER_ID 1
-#define CONTROLTYPE_PING 2
-#define CONTROLTYPE_DISCO 3
-#define CONTROLTYPE_ENABLE_BIG_SEND_WINDOW 4
+enum ControlType : u8 {
+ CONTROLTYPE_ACK = 0,
+ CONTROLTYPE_SET_PEER_ID = 1,
+ CONTROLTYPE_PING = 2,
+ CONTROLTYPE_DISCO = 3,
+};
/*
ORIGINAL: This is a plain packet with no control and no error
*/
//#define TYPE_ORIGINAL 1
#define ORIGINAL_HEADER_SIZE 1
+
/*
SPLIT: These are sequences of packets forming one bigger piece of
data.
[5] u16 chunk_num
*/
//#define TYPE_SPLIT 2
+
/*
RELIABLE: Delivery of all RELIABLE packets shall be forced by ACKs,
and they shall be delivered in the same order as sent. This is done
//#define TYPE_RELIABLE 3
#define RELIABLE_HEADER_SIZE 3
#define SEQNUM_INITIAL 65500
+#define SEQNUM_MAX 65535
+
+class NetworkPacket;
+
+namespace con
+{
+
+class ConnectionReceiveThread;
+class ConnectionSendThread;
+
+typedef enum MTProtocols {
+ MTP_PRIMARY,
+ MTP_UDP,
+ MTP_MINETEST_RELIABLE_UDP
+} MTProtocols;
-enum PacketType: u8 {
+enum PacketType : u8 {
PACKET_TYPE_CONTROL = 0,
PACKET_TYPE_ORIGINAL = 1,
PACKET_TYPE_SPLIT = 2,
PACKET_TYPE_RELIABLE = 3,
PACKET_TYPE_MAX
};
+
+inline bool seqnum_higher(u16 totest, u16 base)
+{
+ if (totest > base)
+ {
+ if ((totest - base) > (SEQNUM_MAX/2))
+ return false;
+
+ return true;
+ }
+
+ if ((base - totest) > (SEQNUM_MAX/2))
+ return true;
+
+ return false;
+}
+
+inline bool seqnum_in_window(u16 seqnum, u16 next,u16 window_size)
+{
+ u16 window_start = next;
+ u16 window_end = ( next + window_size ) % (SEQNUM_MAX+1);
+
+ if (window_start < window_end) {
+ return ((seqnum >= window_start) && (seqnum < window_end));
+ }
+
+
+ return ((seqnum < window_end) || (seqnum >= window_start));
+}
+
+static inline float CALC_DTIME(u64 lasttime, u64 curtime)
+{
+ float value = ( curtime - lasttime) / 1000.0;
+ return MYMAX(MYMIN(value,0.1),0.0);
+}
+
+/*
+ Struct for all kinds of packets. Includes following data:
+ BASE_HEADER
+ u8[] packet data (usually copied from SharedBuffer<u8>)
+*/
+struct BufferedPacket {
+ BufferedPacket(u32 a_size)
+ {
+ m_data.resize(a_size);
+ data = &m_data[0];
+ }
+
+ DISABLE_CLASS_COPY(BufferedPacket)
+
+ u16 getSeqnum() const;
+
+ inline size_t size() const { return m_data.size(); }
+
+ u8 *data; // Direct memory access
+ float time = 0.0f; // Seconds from buffering the packet or re-sending
+ float totaltime = 0.0f; // Seconds from buffering the packet
+ u64 absolute_send_time = -1;
+ Address address; // Sender or destination
+ unsigned int resend_count = 0;
+
+private:
+ std::vector<u8> m_data; // Data of the packet, including headers
+};
+
+typedef std::shared_ptr<BufferedPacket> BufferedPacketPtr;
+
+
+// This adds the base headers to the data and makes a packet out of it
+BufferedPacketPtr makePacket(Address &address, const SharedBuffer<u8> &data,
+ u32 protocol_id, session_t sender_peer_id, u8 channel);
+
+// Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet
+// Increments split_seqnum if a split packet is made
+void makeAutoSplitPacket(const SharedBuffer<u8> &data, u32 chunksize_max,
+ u16 &split_seqnum, std::list<SharedBuffer<u8>> *list);
+
+// Add the TYPE_RELIABLE header to the data
+SharedBuffer<u8> makeReliablePacket(const SharedBuffer<u8> &data, u16 seqnum);
+
+struct IncomingSplitPacket
+{
+ IncomingSplitPacket(u32 cc, bool r):
+ chunk_count(cc), reliable(r) {}
+
+ IncomingSplitPacket() = delete;
+
+ float time = 0.0f; // Seconds from adding
+ u32 chunk_count;
+ bool reliable; // If true, isn't deleted on timeout
+
+ bool allReceived() const
+ {
+ return (chunks.size() == chunk_count);
+ }
+ bool insert(u32 chunk_num, SharedBuffer<u8> &chunkdata);
+ SharedBuffer<u8> reassemble();
+
+private:
+ // Key is chunk number, value is data without headers
+ std::map<u16, SharedBuffer<u8>> chunks;
+};
+
/*
A buffer which stores reliable packets and sorts them internally
for fast access to the smallest one.
*/
-typedef std::list<BufferedPacket>::iterator RPBSearchResult;
+typedef std::list<BufferedPacketPtr>::iterator RPBSearchResult;
class ReliablePacketBuffer
{
bool getFirstSeqnum(u16& result);
- BufferedPacket popFirst();
- BufferedPacket popSeqnum(u16 seqnum);
- void insert(BufferedPacket &p,u16 next_expected);
+ BufferedPacketPtr popFirst();
+ BufferedPacketPtr popSeqnum(u16 seqnum);
+ void insert(BufferedPacketPtr &p_ptr, u16 next_expected);
void incrementTimeouts(float dtime);
- std::list<BufferedPacket> getTimedOuts(float timeout,
- unsigned int max_packets);
+ std::list<ConstSharedPtr<BufferedPacket>> getTimedOuts(float timeout, u32 max_packets);
void print();
bool empty();
- bool containsPacket(u16 seqnum);
- RPBSearchResult notFound();
u32 size();
private:
- RPBSearchResult findPacket(u16 seqnum);
+ RPBSearchResult findPacketNoLock(u16 seqnum);
- std::list<BufferedPacket> m_list;
- u32 m_list_size = 0;
+ std::list<BufferedPacketPtr> m_list;
u16 m_oldest_non_answered_ack;
Returns a reference counted buffer of length != 0 when a full split
packet is constructed. If not, returns one of length 0.
*/
- SharedBuffer<u8> insert(const BufferedPacket &p, bool reliable);
+ SharedBuffer<u8> insert(BufferedPacketPtr &p_ptr, bool reliable);
void removeUnreliableTimedOuts(float dtime, float timeout);
std::mutex m_map_mutex;
};
-struct OutgoingPacket
-{
- u16 peer_id;
- u8 channelnum;
- SharedBuffer<u8> data;
- bool reliable;
- bool ack;
-
- OutgoingPacket(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_,
- bool reliable_,bool ack_=false):
- peer_id(peer_id_),
- channelnum(channelnum_),
- data(data_),
- reliable(reliable_),
- ack(ack_)
- {
- }
-};
-
enum ConnectionCommandType{
CONNCMD_NONE,
CONNCMD_SERVE,
CONNCMD_SEND,
CONNCMD_SEND_TO_ALL,
CONCMD_ACK,
- CONCMD_CREATE_PEER,
- CONCMD_DISABLE_LEGACY
+ CONCMD_CREATE_PEER
};
+struct ConnectionCommand;
+typedef std::shared_ptr<ConnectionCommand> ConnectionCommandPtr;
+
+// This is very similar to ConnectionEvent
struct ConnectionCommand
{
- enum ConnectionCommandType type = CONNCMD_NONE;
+ const ConnectionCommandType type;
Address address;
- u16 peer_id = PEER_ID_INEXISTENT;
+ session_t peer_id = PEER_ID_INEXISTENT;
u8 channelnum = 0;
- SharedBuffer<u8> data;
+ Buffer<u8> data;
bool reliable = false;
bool raw = false;
- ConnectionCommand() = default;
+ DISABLE_CLASS_COPY(ConnectionCommand);
- void serve(Address address_)
- {
- type = CONNCMD_SERVE;
- address = address_;
- }
- void connect(Address address_)
- {
- type = CONNCMD_CONNECT;
- address = address_;
- }
- void disconnect()
- {
- type = CONNCMD_DISCONNECT;
- }
- void disconnect_peer(u16 peer_id_)
- {
- type = CONNCMD_DISCONNECT_PEER;
- peer_id = peer_id_;
- }
-
- void send(u16 peer_id_, u8 channelnum_, NetworkPacket* pkt, bool reliable_);
+ static ConnectionCommandPtr serve(Address address);
+ static ConnectionCommandPtr connect(Address address);
+ static ConnectionCommandPtr disconnect();
+ static ConnectionCommandPtr disconnect_peer(session_t peer_id);
+ static ConnectionCommandPtr send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable);
+ static ConnectionCommandPtr ack(session_t peer_id, u8 channelnum, const Buffer<u8> &data);
+ static ConnectionCommandPtr createPeer(session_t peer_id, const Buffer<u8> &data);
- void ack(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_)
- {
- type = CONCMD_ACK;
- peer_id = peer_id_;
- channelnum = channelnum_;
- data = data_;
- reliable = false;
- }
-
- void createPeer(u16 peer_id_, const SharedBuffer<u8> &data_)
- {
- type = CONCMD_CREATE_PEER;
- peer_id = peer_id_;
- data = data_;
- channelnum = 0;
- reliable = true;
- raw = true;
- }
+private:
+ ConnectionCommand(ConnectionCommandType type_) :
+ type(type_) {}
- void disableLegacy(u16 peer_id_, const SharedBuffer<u8> &data_)
- {
- type = CONCMD_DISABLE_LEGACY;
- peer_id = peer_id_;
- data = data_;
- channelnum = 0;
- reliable = true;
- raw = true;
- }
+ static ConnectionCommandPtr create(ConnectionCommandType type);
};
-/* maximum window size to use, 0xFFFF is theoretical maximum don't think about
+/* maximum window size to use, 0xFFFF is theoretical maximum. don't think about
* touching it, the less you're away from it the more likely data corruption
* will occur
*/
#define MAX_RELIABLE_WINDOW_SIZE 0x8000
- /* starting value for window size */
+/* starting value for window size */
+#define START_RELIABLE_WINDOW_SIZE 0x400
+/* minimum value for window size */
#define MIN_RELIABLE_WINDOW_SIZE 0x40
class Channel
u16 readNextIncomingSeqNum();
u16 incNextIncomingSeqNum();
- u16 getOutgoingSequenceNumber(bool& successfull);
+ u16 getOutgoingSequenceNumber(bool& successful);
u16 readOutgoingSequenceNumber();
bool putBackSequenceNumber(u16);
ReliablePacketBuffer outgoing_reliables_sent;
//queued reliable packets
- std::queue<BufferedPacket> queued_reliables;
+ std::queue<BufferedPacketPtr> queued_reliables;
//queue commands prior splitting to packets
- std::deque<ConnectionCommand> queued_commands;
+ std::deque<ConnectionCommandPtr> queued_commands;
IncomingSplitBuffer incoming_splits;
void UpdateBytesLost(unsigned int bytes);
void UpdateBytesReceived(unsigned int bytes);
- void UpdateTimers(float dtime, bool legacy_peer);
+ void UpdateTimers(float dtime);
- const float getCurrentDownloadRateKB()
+ float getCurrentDownloadRateKB()
{ MutexAutoLock lock(m_internal_mutex); return cur_kbps; };
- const float getMaxDownloadRateKB()
+ float getMaxDownloadRateKB()
{ MutexAutoLock lock(m_internal_mutex); return max_kbps; };
- const float getCurrentLossRateKB()
+ float getCurrentLossRateKB()
{ MutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; };
- const float getMaxLossRateKB()
+ float getMaxLossRateKB()
{ MutexAutoLock lock(m_internal_mutex); return max_kbps_lost; };
- const float getCurrentIncomingRateKB()
+ float getCurrentIncomingRateKB()
{ MutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; };
- const float getMaxIncomingRateKB()
+ float getMaxIncomingRateKB()
{ MutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; };
- const float getAvgDownloadRateKB()
+ float getAvgDownloadRateKB()
{ MutexAutoLock lock(m_internal_mutex); return avg_kbps; };
- const float getAvgLossRateKB()
+ float getAvgLossRateKB()
{ MutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; };
- const float getAvgIncomingRateKB()
+ float getAvgIncomingRateKB()
{ MutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; };
- const unsigned int getWindowSize() const { return window_size; };
+ u16 getWindowSize() const { return m_window_size; };
+
+ void setWindowSize(long size)
+ {
+ m_window_size = (u16)rangelim(size, MIN_RELIABLE_WINDOW_SIZE, MAX_RELIABLE_WINDOW_SIZE);
+ }
- void setWindowSize(unsigned int size) { window_size = size; };
private:
std::mutex m_internal_mutex;
- int window_size = MIN_RELIABLE_WINDOW_SIZE;
+ u16 m_window_size = MIN_RELIABLE_WINDOW_SIZE;
u16 next_incoming_seqnum = SEQNUM_INITIAL;
unsigned int current_packet_loss = 0;
unsigned int current_packet_too_late = 0;
- unsigned int current_packet_successfull = 0;
+ unsigned int current_packet_successful = 0;
float packet_loss_counter = 0.0f;
unsigned int current_bytes_transfered = 0;
public:
friend class PeerHelper;
- Peer(Address address_,u16 id_,Connection* connection) :
+ Peer(Address address_,session_t id_,Connection* connection) :
id(id_),
m_connection(connection),
address(address_),
};
// Unique id of the peer
- u16 id;
+ const session_t id;
void Drop();
- virtual void PutReliableSendCommand(ConnectionCommand &c,
+ virtual void PutReliableSendCommand(ConnectionCommandPtr &c,
unsigned int max_packet_size) {};
virtual bool getAddress(MTProtocols type, Address& toset) = 0;
bool isTimedOut(float timeout);
- unsigned int m_increment_packets_remaining = 9;
- unsigned int m_increment_bytes_remaining = 0;
+ unsigned int m_increment_packets_remaining = 0;
virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
- virtual SharedBuffer<u8> addSplitPacket(u8 channel, const BufferedPacket &toadd,
+ virtual SharedBuffer<u8> addSplitPacket(u8 channel, BufferedPacketPtr &toadd,
bool reliable)
{
- fprintf(stderr,"Peer: addSplitPacket called, this is supposed to be never called!\n");
+ errorstream << "Peer::addSplitPacket called,"
+ << " this is supposed to be never called!" << std::endl;
return SharedBuffer<u8>(0);
};
bool IncUseCount();
void DecUseCount();
- std::mutex m_exclusive_access_mutex;
+ mutable std::mutex m_exclusive_access_mutex;
bool m_pending_deletion = false;
UDPPeer(u16 a_id, Address a_address, Connection* connection);
virtual ~UDPPeer() = default;
- void PutReliableSendCommand(ConnectionCommand &c,
+ void PutReliableSendCommand(ConnectionCommandPtr &c,
unsigned int max_packet_size);
bool getAddress(MTProtocols type, Address& toset);
- void setNonLegacyPeer();
-
- bool getLegacyPeer()
- { return m_legacy_peer; }
-
u16 getNextSplitSequenceNumber(u8 channel);
void setNextSplitSequenceNumber(u8 channel, u16 seqnum);
- SharedBuffer<u8> addSplitPacket(u8 channel, const BufferedPacket &toadd,
+ SharedBuffer<u8> addSplitPacket(u8 channel, BufferedPacketPtr &toadd,
bool reliable);
protected:
float resend_timeout = 0.5;
bool processReliableSendCommand(
- ConnectionCommand &c,
+ ConnectionCommandPtr &c_ptr,
unsigned int max_packet_size);
-
- bool m_legacy_peer = true;
};
/*
Connection
*/
-enum ConnectionEventType{
+enum ConnectionEventType {
CONNEVENT_NONE,
CONNEVENT_DATA_RECEIVED,
CONNEVENT_PEER_ADDED,
CONNEVENT_BIND_FAILED,
};
+struct ConnectionEvent;
+typedef std::shared_ptr<ConnectionEvent> ConnectionEventPtr;
+
+// This is very similar to ConnectionCommand
struct ConnectionEvent
{
- enum ConnectionEventType type = CONNEVENT_NONE;
- u16 peer_id = 0;
+ const ConnectionEventType type;
+ session_t peer_id = 0;
Buffer<u8> data;
bool timeout = false;
Address address;
- ConnectionEvent() = default;
+ // We don't want to copy "data"
+ DISABLE_CLASS_COPY(ConnectionEvent);
- std::string describe()
- {
- switch(type) {
- case CONNEVENT_NONE:
- return "CONNEVENT_NONE";
- case CONNEVENT_DATA_RECEIVED:
- return "CONNEVENT_DATA_RECEIVED";
- case CONNEVENT_PEER_ADDED:
- return "CONNEVENT_PEER_ADDED";
- case CONNEVENT_PEER_REMOVED:
- return "CONNEVENT_PEER_REMOVED";
- case CONNEVENT_BIND_FAILED:
- return "CONNEVENT_BIND_FAILED";
- }
- return "Invalid ConnectionEvent";
- }
+ static ConnectionEventPtr create(ConnectionEventType type);
+ static ConnectionEventPtr dataReceived(session_t peer_id, const Buffer<u8> &data);
+ static ConnectionEventPtr peerAdded(session_t peer_id, Address address);
+ static ConnectionEventPtr peerRemoved(session_t peer_id, bool is_timeout, Address address);
+ static ConnectionEventPtr bindFailed();
- void dataReceived(u16 peer_id_, const SharedBuffer<u8> &data_)
- {
- type = CONNEVENT_DATA_RECEIVED;
- peer_id = peer_id_;
- data = data_;
- }
- void peerAdded(u16 peer_id_, Address address_)
- {
- type = CONNEVENT_PEER_ADDED;
- peer_id = peer_id_;
- address = address_;
- }
- void peerRemoved(u16 peer_id_, bool timeout_, Address address_)
- {
- type = CONNEVENT_PEER_REMOVED;
- peer_id = peer_id_;
- timeout = timeout_;
- address = address_;
- }
- void bindFailed()
- {
- type = CONNEVENT_BIND_FAILED;
- }
+ const char *describe() const;
+
+private:
+ ConnectionEvent(ConnectionEventType type_) :
+ type(type_) {}
};
class PeerHandler;
~Connection();
/* Interface */
- ConnectionEvent waitEvent(u32 timeout_ms);
- void putCommand(ConnectionCommand &c);
+ ConnectionEventPtr waitEvent(u32 timeout_ms);
+
+ void putCommand(ConnectionCommandPtr c);
void SetTimeoutMs(u32 timeout) { m_bc_receive_timeout = timeout; }
void Serve(Address bind_addr);
bool Connected();
void Disconnect();
void Receive(NetworkPacket* pkt);
- void Send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
- u16 GetPeerID() { return m_peer_id; }
- Address GetPeerAddress(u16 peer_id);
- float getPeerStat(u16 peer_id, rtt_stat_type type);
+ bool TryReceive(NetworkPacket *pkt);
+ void Send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable);
+ session_t GetPeerID() const { return m_peer_id; }
+ Address GetPeerAddress(session_t peer_id);
+ float getPeerStat(session_t peer_id, rtt_stat_type type);
float getLocalStat(rate_stat_type type);
- const u32 GetProtocolID() const { return m_protocol_id; };
+ u32 GetProtocolID() const { return m_protocol_id; };
const std::string getDesc();
- void DisconnectPeer(u16 peer_id);
+ void DisconnectPeer(session_t peer_id);
protected:
- PeerHelper getPeerNoEx(u16 peer_id);
+ PeerHelper getPeerNoEx(session_t peer_id);
u16 lookupPeer(Address& sender);
u16 createPeer(Address& sender, MTProtocols protocol, int fd);
UDPPeer* createServerPeer(Address& sender);
- bool deletePeer(u16 peer_id, bool timeout);
-
- void SetPeerID(u16 id) { m_peer_id = id; }
+ bool deletePeer(session_t peer_id, bool timeout);
- void sendAck(u16 peer_id, u8 channelnum, u16 seqnum);
+ void SetPeerID(session_t id) { m_peer_id = id; }
- void PrintInfo(std::ostream &out);
+ void sendAck(session_t peer_id, u8 channelnum, u16 seqnum);
- std::list<u16> getPeerIDs()
+ std::vector<session_t> getPeerIDs()
{
MutexAutoLock peerlock(m_peers_mutex);
return m_peer_ids;
}
UDPSocket m_udpSocket;
- MutexedQueue<ConnectionCommand> m_command_queue;
+ // Command queue: user -> SendThread
+ MutexedQueue<ConnectionCommandPtr> m_command_queue;
- void putEvent(ConnectionEvent &e);
+ bool Receive(NetworkPacket *pkt, u32 timeout);
+
+ void putEvent(ConnectionEventPtr e);
void TriggerSend();
-private:
- std::list<Peer*> getPeers();
- MutexedQueue<ConnectionEvent> m_event_queue;
+ bool ConnectedToServer()
+ {
+ return getPeerNoEx(PEER_ID_SERVER) != nullptr;
+ }
+private:
+ // Event queue: ReceiveThread -> user
+ MutexedQueue<ConnectionEventPtr> m_event_queue;
- u16 m_peer_id = 0;
+ session_t m_peer_id = 0;
u32 m_protocol_id;
- std::map<u16, Peer*> m_peers;
- std::list<u16> m_peer_ids;
+ std::map<session_t, Peer *> m_peers;
+ std::vector<session_t> m_peer_ids;
std::mutex m_peers_mutex;
std::unique_ptr<ConnectionSendThread> m_sendThread;
std::unique_ptr<ConnectionReceiveThread> m_receiveThread;
- std::mutex m_info_mutex;
+ mutable std::mutex m_info_mutex;
// Backwards compatibility
PeerHandler *m_bc_peerhandler;
bool m_shutting_down = false;
- u16 m_next_remote_peer_id = 2;
+ session_t m_next_remote_peer_id = 2;
};
} // namespace