Files
starruler-linux/source/network/include/network/connection.h
T
2018-07-17 14:15:37 +02:00

165 lines
3.8 KiB
C++

#pragma once
#include "threads.h"
#include <network/transport.h>
#include <network/address.h>
#include <network/time.h>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <deque>
namespace net {
#ifndef NET_RESEND_TIME
#define NET_RESEND_TIME 100
#endif
#ifndef NET_RESEND_RELIABLE_TIME
#define NET_RESEND_RELIABLE_TIME 250
#endif
#ifndef NET_RESEND_PERIOD
#define NET_RESEND_PERIOD 5
#endif
#ifndef NET_SEQUENCE_FUTURE
#define NET_SEQUENCE_FUTURE 100
#endif
#ifndef NET_PING_INTERVAL
#define NET_PING_INTERVAL 1000
#endif
#ifndef NET_PING_TIMEOUT
#define NET_PING_TIMEOUT 5000
#endif
#ifndef NET_FRAGMENT_LIMIT
#define NET_FRAGMENT_LIMIT 1000
#endif
#ifndef NET_FRAGMENT_OVERHEAD
#define NET_FRAGMENT_OVERHEAD 10
#endif
#ifndef NET_FRAGMENT_TIMEOUT
#define NET_FRAGMENT_TIMEOUT 5000
#endif
struct OutSequence;
struct InSequence;
struct SeqAck {
unsigned short seqID;
unsigned short msgID;
};
class Connection {
//Connections can send messages reliable, that is,
//messages with flag MF_Reliable set will be resent until
//acknowledged by the other side
struct MessageAwaitingAck {
Message* msg;
time lastResend;
};
mutable threads::atomic_int references;
threads::Mutex ackMutex;
std::unordered_set<unsigned short> queuedAcks;
std::vector<SeqAck> queuedSeqAcks;
threads::Mutex reliableMutex;
std::list<Message*> queuedReliable;
std::unordered_set<unsigned short> handledMessages;
std::unordered_set<unsigned short> unorderedAcks;
unsigned short nextOutgoingID;
unsigned short nextAck;
unsigned nextReliablePeriod;
void handleAck(unsigned short id);
bool split(Message& msg);
void queueReliable(Message* msg, bool immediate = false);
bool shouldHandleID(unsigned short id);
threads::Mutex msgQueueLock;
std::list<Message*> queuedMessages;
void queue(Message* msg);
struct WindowPacket {
Message* msg;
time added, sent;
};
threads::Mutex windowMutex;
size_t windowBytes, windowUsed;
double windowLength, windowUpdate;
std::deque<WindowPacket> window;
//Connections also have sequences of ordered, reliable messages
threads::Mutex sequenceMutex;
unsigned nextSequenceID;
std::unordered_map<unsigned short, OutSequence*> outSequences;
std::unordered_map<unsigned short, InSequence*> inSequences;
//Connections handle message fragmentation transparently.
//Messages over the fragment limit are sent in multiple parts without
//any application interaction.
threads::Mutex fragmentMutex;
threads::atomic_int nextFragmentID;
struct Fragment {
std::vector<Message*> received;
unsigned fragmentCount;
time lastActivity;
};
std::unordered_map<unsigned, Fragment*> waitingFragments;
void handleFragment(MessageHandler& handler, Message* msg);
//Connections will keep themselves alive by pingponging, and time
//out if we get no messages or responses to our pings for a certain
//amount of time
unsigned pingPongWait;
time lastMessageReceived;
time lastPingSent;
time firstPingSent;
bool pingSent;
time lastProcessTime;
unsigned outBytes, inBytes;
public:
Transport& transport;
bool active;
Address address;
int id;
int availBytes;
void grab() const;
void drop() const;
unsigned ping;
void sendPing();
bool preHandle(MessageHandler& handler, Message* msg);
void postHandle(MessageHandler& handler, Message* msg);
void process(MessageHandler& handler);
//Returns the total amount of traffic in bytes since the last time getTraffic was called
void getTraffic(unsigned& in_bytes, unsigned& out_bytes, unsigned& queuedPackets);
OutSequence* sequence();
void queueSeqAck(unsigned short sequenceID, unsigned short messageID);
Connection(Transport& trans, Address addr);
Connection& operator<<(Message& msg);
//Sends a messsage through the pipe, immediately if possible
// Returns true if the message should be considered sent
bool send(Message& msg, bool isResend);
~Connection();
friend OutSequence;
};
};