51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef CONNECTION_HEADER
-#define CONNECTION_HEADER
+#pragma once
#include "irrlichttypes_bloated.h"
+#include "peerhandler.h"
#include "socket.h"
-#include "exceptions.h"
#include "constants.h"
-#include "network/networkpacket.h"
#include "util/pointer.h"
#include "util/container.h"
#include "util/thread.h"
namespace con
{
-/*
- Exceptions
-*/
-class NotFoundException : public BaseException
-{
-public:
- NotFoundException(const char *s):
- BaseException(s)
- {}
-};
-
-class PeerNotFoundException : public BaseException
-{
-public:
- PeerNotFoundException(const char *s):
- BaseException(s)
- {}
-};
-
-class ConnectionException : public BaseException
-{
-public:
- ConnectionException(const char *s):
- BaseException(s)
- {}
-};
-
-class ConnectionBindFailed : public BaseException
-{
-public:
- ConnectionBindFailed(const char *s):
- BaseException(s)
- {}
-};
-
-class InvalidIncomingDataException : public BaseException
-{
-public:
- InvalidIncomingDataException(const char *s):
- BaseException(s)
- {}
-};
-
-class InvalidOutgoingDataException : public BaseException
-{
-public:
- InvalidOutgoingDataException(const char *s):
- BaseException(s)
- {}
-};
-
-class NoIncomingDataException : public BaseException
-{
-public:
- NoIncomingDataException(const char *s):
- BaseException(s)
- {}
-};
-
-class ProcessedSilentlyException : public BaseException
-{
-public:
- ProcessedSilentlyException(const char *s):
- BaseException(s)
- {}
-};
-
-class ProcessedQueued : public BaseException
-{
-public:
- ProcessedQueued(const char *s):
- BaseException(s)
- {}
-};
-
-class IncomingDataCorruption : public BaseException
-{
-public:
- IncomingDataCorruption(const char *s):
- BaseException(s)
- {}
-};
-
typedef enum MTProtocols {
MTP_PRIMARY,
MTP_UDP,
{
if ((totest - base) > (SEQNUM_MAX/2))
return false;
- else
- return true;
- }
- else
- {
- if ((base - totest) > (SEQNUM_MAX/2))
- return true;
- else
- 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)
- {
+ if (window_start < window_end) {
return ((seqnum >= window_start) && (seqnum < window_end));
}
- else
- {
- return ((seqnum < window_end) || (seqnum >= window_start));
- }
+
+
+ return ((seqnum < window_end) || (seqnum >= window_start));
}
struct BufferedPacket
{
BufferedPacket(u8 *a_data, u32 a_size):
- data(a_data, a_size), time(0.0), totaltime(0.0), absolute_send_time(-1),
- resend_count(0)
+ data(a_data, a_size)
{}
BufferedPacket(u32 a_size):
- data(a_size), time(0.0), totaltime(0.0), absolute_send_time(-1),
- resend_count(0)
+ data(a_size)
{}
Buffer<u8> data; // Data of the packet, including headers
- float time; // Seconds from buffering the packet or re-sending
- float totaltime; // Seconds from buffering the packet
- unsigned int absolute_send_time;
+ 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;
+ unsigned int resend_count = 0;
};
// This adds the base headers to the data and makes a packet out of it
// Add the TYPE_RELIABLE header to the data
SharedBuffer<u8> makeReliablePacket(
- SharedBuffer<u8> data,
+ const SharedBuffer<u8> &data,
u16 seqnum);
struct IncomingSplitPacket
{
- IncomingSplitPacket()
- {
- time = 0.0;
- reliable = false;
- }
+ IncomingSplitPacket() = default;
+
// Key is chunk number, value is data without headers
std::map<u16, SharedBuffer<u8> > chunks;
u32 chunk_count;
- float time; // Seconds from adding
- bool reliable; // If true, isn't deleted on timeout
+ float time = 0.0f; // Seconds from adding
+ bool reliable = false; // If true, isn't deleted on timeout
bool allReceived()
{
class ReliablePacketBuffer
{
public:
- ReliablePacketBuffer();
+ ReliablePacketBuffer() = default;
bool getFirstSeqnum(u16& result);
RPBSearchResult findPacket(u16 seqnum);
std::list<BufferedPacket> m_list;
- u32 m_list_size;
+ u32 m_list_size = 0;
u16 m_oldest_non_answered_ack;
- Mutex m_list_mutex;
+ std::mutex m_list_mutex;
};
/*
// Key is seqnum
std::map<u16, IncomingSplitPacket*> m_buf;
- Mutex m_map_mutex;
+ std::mutex m_map_mutex;
};
struct OutgoingPacket
bool reliable;
bool ack;
- OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_,
+ OutgoingPacket(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_,
bool reliable_,bool ack_=false):
peer_id(peer_id_),
channelnum(channelnum_),
struct ConnectionCommand
{
- enum ConnectionCommandType type;
+ enum ConnectionCommandType type = CONNCMD_NONE;
Address address;
- u16 peer_id;
+ u16 peer_id = PEER_ID_INEXISTENT;
u8 channelnum;
Buffer<u8> data;
- bool reliable;
- bool raw;
+ bool reliable = false;
+ bool raw = false;
- ConnectionCommand(): type(CONNCMD_NONE), peer_id(PEER_ID_INEXISTENT), reliable(false), raw(false) {}
+ ConnectionCommand() = default;
void serve(Address address_)
{
type = CONNCMD_DISCONNECT_PEER;
peer_id = peer_id_;
}
- void send(u16 peer_id_, u8 channelnum_,
- NetworkPacket* pkt, bool reliable_)
- {
- type = CONNCMD_SEND;
- peer_id = peer_id_;
- channelnum = channelnum_;
- data = pkt->oldForgePacket();
- reliable = reliable_;
- }
- void ack(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_)
+ void send(u16 peer_id_, u8 channelnum_, NetworkPacket* pkt, bool reliable_);
+
+ void ack(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_)
{
type = CONCMD_ACK;
peer_id = peer_id_;
reliable = false;
}
- void createPeer(u16 peer_id_, SharedBuffer<u8> data_)
+ void createPeer(u16 peer_id_, const SharedBuffer<u8> &data_)
{
type = CONCMD_CREATE_PEER;
peer_id = peer_id_;
raw = true;
}
- void disableLegacy(u16 peer_id_, SharedBuffer<u8> data_)
+ void disableLegacy(u16 peer_id_, const SharedBuffer<u8> &data_)
{
type = CONCMD_DISABLE_LEGACY;
peer_id = peer_id_;
}
};
+/* 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 */
+#define MIN_RELIABLE_WINDOW_SIZE 0x40
+
class Channel
{
IncomingSplitBuffer incoming_splits;
- Channel();
- ~Channel();
+ Channel() = default;
+ ~Channel() = default;
void UpdatePacketLossCounter(unsigned int count);
void UpdatePacketTooLateCounter();
void setWindowSize(unsigned int size) { window_size = size; };
private:
- Mutex m_internal_mutex;
- int window_size;
-
- u16 next_incoming_seqnum;
-
- u16 next_outgoing_seqnum;
- u16 next_outgoing_split_seqnum;
-
- unsigned int current_packet_loss;
- unsigned int current_packet_too_late;
- unsigned int current_packet_successfull;
- float packet_loss_counter;
-
- unsigned int current_bytes_transfered;
- unsigned int current_bytes_received;
- unsigned int current_bytes_lost;
- float max_kbps;
- float cur_kbps;
- float avg_kbps;
- float max_incoming_kbps;
- float cur_incoming_kbps;
- float avg_incoming_kbps;
- float max_kbps_lost;
- float cur_kbps_lost;
- float avg_kbps_lost;
- float bpm_counter;
-
- unsigned int rate_samples;
+ std::mutex m_internal_mutex;
+ int window_size = MIN_RELIABLE_WINDOW_SIZE;
+
+ u16 next_incoming_seqnum = SEQNUM_INITIAL;
+
+ u16 next_outgoing_seqnum = SEQNUM_INITIAL;
+ u16 next_outgoing_split_seqnum = SEQNUM_INITIAL;
+
+ unsigned int current_packet_loss = 0;
+ unsigned int current_packet_too_late = 0;
+ unsigned int current_packet_successfull = 0;
+ float packet_loss_counter = 0.0f;
+
+ unsigned int current_bytes_transfered = 0;
+ unsigned int current_bytes_received = 0;
+ unsigned int current_bytes_lost = 0;
+ float max_kbps = 0.0f;
+ float cur_kbps = 0.0f;
+ float avg_kbps = 0.0f;
+ float max_incoming_kbps = 0.0f;
+ float cur_incoming_kbps = 0.0f;
+ float avg_incoming_kbps = 0.0f;
+ float max_kbps_lost = 0.0f;
+ float cur_kbps_lost = 0.0f;
+ float avg_kbps_lost = 0.0f;
+ float bpm_counter = 0.0f;
+
+ unsigned int rate_samples = 0;
};
class Peer;
-enum PeerChangeType
-{
- PEER_ADDED,
- PEER_REMOVED
-};
-struct PeerChange
-{
- PeerChangeType type;
- u16 peer_id;
- bool timeout;
-};
-
-class PeerHandler
-{
-public:
-
- PeerHandler()
- {
- }
- virtual ~PeerHandler()
- {
- }
-
- /*
- This is called after the Peer has been inserted into the
- Connection's peer container.
- */
- virtual void peerAdded(Peer *peer) = 0;
- /*
- This is called before the Peer has been removed from the
- Connection's peer container.
- */
- virtual void deletingPeer(Peer *peer, bool timeout) = 0;
-};
-
class PeerHelper
{
public:
- PeerHelper();
+ PeerHelper() = default;
PeerHelper(Peer* peer);
~PeerHelper();
bool operator!=(void* ptr);
private:
- Peer* m_peer;
+ Peer *m_peer = nullptr;
};
class Connection;
-typedef enum {
- MIN_RTT,
- MAX_RTT,
- AVG_RTT,
- MIN_JITTER,
- MAX_JITTER,
- AVG_JITTER
-} rtt_stat_type;
-
typedef enum {
CUR_DL_RATE,
AVG_DL_RATE,
Peer(Address address_,u16 id_,Connection* connection) :
id(id_),
- m_increment_packets_remaining(9),
- m_increment_bytes_remaining(0),
- m_pending_deletion(false),
m_connection(connection),
address(address_),
- m_ping_timer(0.0),
- m_last_rtt(-1.0),
- m_usage(0),
- m_timeout_counter(0.0),
- m_last_timeout_check(porting::getTimeMs()),
- m_has_sent_with_id(false)
+ m_last_timeout_check(porting::getTimeMs())
{
- m_rtt.avg_rtt = -1.0;
- m_rtt.jitter_avg = -1.0;
- m_rtt.jitter_max = 0.0;
- m_rtt.max_rtt = 0.0;
- m_rtt.jitter_min = FLT_MAX;
- m_rtt.min_rtt = FLT_MAX;
};
virtual ~Peer() {
virtual void PutReliableSendCommand(ConnectionCommand &c,
unsigned int max_packet_size) {};
- virtual bool isActive() { return false; };
-
virtual bool getAddress(MTProtocols type, Address& toset) = 0;
+ bool isPendingDeletion()
+ { MutexAutoLock lock(m_exclusive_access_mutex); return m_pending_deletion; };
+
void ResetTimeout()
- {MutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; };
+ {MutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter = 0.0; };
bool isTimedOut(float timeout);
- void setSentWithID()
- { MutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; };
-
- bool hasSentWithID()
- { MutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; };
-
- unsigned int m_increment_packets_remaining;
- unsigned int m_increment_bytes_remaining;
+ unsigned int m_increment_packets_remaining = 9;
+ unsigned int m_increment_bytes_remaining = 0;
virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
virtual void reportRTT(float rtt) {};
void RTTStatistics(float rtt,
- std::string profiler_id="",
- unsigned int num_samples=1000);
+ const std::string &profiler_id = "",
+ unsigned int num_samples = 1000);
bool IncUseCount();
void DecUseCount();
- Mutex m_exclusive_access_mutex;
+ std::mutex m_exclusive_access_mutex;
- bool m_pending_deletion;
+ bool m_pending_deletion = false;
Connection* m_connection;
Address address;
// Ping timer
- float m_ping_timer;
+ float m_ping_timer = 0.0f;
private:
struct rttstats {
- float jitter_min;
- float jitter_max;
- float jitter_avg;
- float min_rtt;
- float max_rtt;
- float avg_rtt;
+ float jitter_min = FLT_MAX;
+ float jitter_max = 0.0f;
+ float jitter_avg = -1.0f;
+ float min_rtt = FLT_MAX;
+ float max_rtt = 0.0f;
+ float avg_rtt = -1.0f;
+
+ rttstats() = default;
};
rttstats m_rtt;
- float m_last_rtt;
+ float m_last_rtt = -1.0f;
// current usage count
- unsigned int m_usage;
+ unsigned int m_usage = 0;
// Seconds from last receive
- float m_timeout_counter;
-
- u32 m_last_timeout_check;
+ float m_timeout_counter = 0.0f;
- bool m_has_sent_with_id;
+ u64 m_last_timeout_check;
};
class UDPPeer : public Peer
friend class Connection;
UDPPeer(u16 a_id, Address a_address, Connection* connection);
- virtual ~UDPPeer() {};
+ virtual ~UDPPeer() = default;
void PutReliableSendCommand(ConnectionCommand &c,
unsigned int max_packet_size);
- bool isActive()
- { return ((hasSentWithID()) && (!m_pending_deletion)); };
-
bool getAddress(MTProtocols type, Address& toset);
void setNonLegacyPeer();
bool Ping(float dtime,SharedBuffer<u8>& data);
Channel channels[CHANNEL_COUNT];
- bool m_pending_disconnect;
+ bool m_pending_disconnect = false;
private:
// This is changed dynamically
- float resend_timeout;
+ float resend_timeout = 0.5;
bool processReliableSendCommand(
ConnectionCommand &c,
unsigned int max_packet_size);
- bool m_legacy_peer;
+ bool m_legacy_peer = true;
};
/*
struct ConnectionEvent
{
- enum ConnectionEventType type;
- u16 peer_id;
+ enum ConnectionEventType type = CONNEVENT_NONE;
+ u16 peer_id = 0;
Buffer<u8> data;
- bool timeout;
+ bool timeout = false;
Address address;
- ConnectionEvent(): type(CONNEVENT_NONE), peer_id(0),
- timeout(false) {}
+ ConnectionEvent() = default;
std::string describe()
{
return "Invalid ConnectionEvent";
}
- void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
+ void dataReceived(u16 peer_id_, const SharedBuffer<u8> &data_)
{
type = CONNEVENT_DATA_RECEIVED;
peer_id = peer_id_;
bool packetsQueued();
- Connection* m_connection;
+ Connection *m_connection = nullptr;
unsigned int m_max_packet_size;
float m_timeout;
std::queue<OutgoingPacket> m_outgoing_queue;
Semaphore m_send_sleep_semaphore;
unsigned int m_iteration_packets_avaialble;
- unsigned int m_max_commands_per_iteration;
+ unsigned int m_max_commands_per_iteration = 1;
unsigned int m_max_data_packets_per_iteration;
- unsigned int m_max_packets_requeued;
+ unsigned int m_max_packets_requeued = 256;
};
class ConnectionReceiveThread : public Thread {
u8 channelnum, bool reliable);
- Connection* m_connection;
+ Connection *m_connection = nullptr;
};
+class PeerHandler;
+
class Connection
{
public:
MutexedQueue<ConnectionEvent> m_event_queue;
- u16 m_peer_id;
+ u16 m_peer_id = 0;
u32 m_protocol_id;
std::map<u16, Peer*> m_peers;
std::list<u16> m_peer_ids;
- Mutex m_peers_mutex;
+ std::mutex m_peers_mutex;
ConnectionSendThread m_sendThread;
ConnectionReceiveThread m_receiveThread;
- Mutex m_info_mutex;
+ std::mutex m_info_mutex;
// Backwards compatibility
PeerHandler *m_bc_peerhandler;
- int m_bc_receive_timeout;
+ int m_bc_receive_timeout = 0;
- bool m_shutting_down;
+ bool m_shutting_down = false;
- u16 m_next_remote_peer_id;
+ u16 m_next_remote_peer_id = 2;
};
} // namespace
-
-#endif