Open source Star Ruler 2 source code!

This commit is contained in:
Lucas de Vries
2018-07-17 14:15:37 +02:00
commit cc307720ff
4342 changed files with 2365070 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <network/address.h>
#include <network/client.h>
#include <network/connection.h>
#include <network/init.h>
#include <network/lobby.h>
#include <network/message.h>
#include <network/message_handler.h>
#include <network/message_types.h>
#include <network/sequence.h>
#include <network/server.h>
#include <network/time.h>
#include <network/transport.h>
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <string>
#include <stdint.h>
#include <functional>
#ifdef _MSC_VER
//Yay more shitty compiler implementation
//assumptions because windows sucks.
struct sockaddr;
struct sockaddr_storage;
struct addrinfo;
typedef int socklen_t;
#else
#include <sys/socket.h>
#include <netdb.h>
#endif
namespace net {
enum AddressType {
AT_IPv4,
AT_IPv6,
AT_INVALID,
};
struct Address {
AddressType type;
int port;
union {
int adr4;
uint8_t adr6[16];
size_t adr6Hash;
};
Address();
Address(const std::string& hostname, int port, AddressType type = AT_IPv4);
Address(int ip4, int port);
Address(uint8_t* ip6, int port);
std::string toString(bool showPort = true) const;
void to_sockaddr(sockaddr_storage& adr, socklen_t* size = 0) const;
void from_sockaddr(sockaddr_storage& adr);
bool operator<(const Address& other) const;
bool operator==(const Address& other) const;
bool ipEquals(const Address& other) const;
};
struct addrinfo* lookup(const std::string& hostname, int port = 0, AddressType type = AT_IPv4);
};
namespace std {
template<>
struct hash<net::Address> {
size_t operator() (const net::Address& addr) const {
return addr.type == net::AT_IPv4 ? (size_t)addr.adr4 : addr.adr6Hash;
}
};
};
+97
View File
@@ -0,0 +1,97 @@
#pragma once
#include <network/message.h>
#include <network/message_handler.h>
#include <network/connection.h>
#include <functional>
#include <unordered_map>
namespace net {
struct LobbyHeartbeat;
struct LobbyPunchthrough;
/*
* Client
* ------
* Connects to a server at an address, and handles incoming
* messages from the server to the client.
*/
class Client : public MessageHandler {
public:
typedef std::function<void(Client&,Message&)> clMessageHandler;
Address address;
bool established;
std::string hostname;
bool hasConnection;
bool resolved;
//Connect to the server on address, if makeConnection is true,
//establish a connection, otherwise send only connectionless messages
Client(Address connectTo, bool makeConnection = true);
Client(const std::string& hostname, int port, bool makeConnection = true, AddressType type = AT_IPv4);
~Client();
//Handlers for any messages that are sent to this client
void resolve();
void handle(uint8_t type, clMessageHandler func);
void handleClear(uint8_t type);
//Send and get ping for the connection
void sendPing();
unsigned getLastPing();
//Shortcut for sending messages to the server
Client& operator<<(Message& msg);
Connection* getConnection();
//Overrides to add functionality to MessageHandler
virtual void handleMessage(Transport* transport, Address addr, Message* msg);
virtual bool mainTick();
virtual void stop();
private:
threads::Mutex handlerMutex;
std::unordered_map<uint8_t, clMessageHandler> handlers;
Transport* trans;
Connection* conn;
friend LobbyHeartbeat;
friend LobbyPunchthrough;
};
/*
* BroadcastClient
* ---------------
* Can broadcast messages and interact with replies to broadcasts.
*/
class BroadcastClient : public MessageHandler {
public:
typedef std::function<void(BroadcastClient&,Address,Message&)> bcMessageHandler;
//Connect to the server on address, if makeConnection is true,
//establish a connection, otherwise send only connectionless messages
BroadcastClient(int Port, AddressType Type = AT_IPv4);
~BroadcastClient();
//Handlers for any messages that are sent to this client
void handle(uint8_t type, bcMessageHandler func);
void handleClear(uint8_t type);
//Send messages to an address over the transport
void send(Message& msg, Address addr);
//Broadcast messages on the port
void broadcast(Message& msg);
//Overrides to add functionality to MessageHandler
virtual void handleMessage(Transport* transport, Address addr, Message* msg);
private:
threads::Mutex handlerMutex;
std::unordered_map<uint8_t, bcMessageHandler> handlers;
int port;
Transport trans;
};
};
+164
View File
@@ -0,0 +1,164 @@
#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;
};
};
+13
View File
@@ -0,0 +1,13 @@
#pragma once
namespace net {
typedef void (*netErrorCallback)(const char* message, int code);
void setErrorCallback(netErrorCallback cb);
void netError(const char* err, int code);
bool prepare();
void clear();
};
+142
View File
@@ -0,0 +1,142 @@
#pragma once
#include <network/message.h>
#include <network/client.h>
#include <network/server.h>
#include <unordered_map>
#include <set>
#include "threads.h"
namespace net {
#ifndef NET_LOBBY_HEARTBEAT_INTERVAL
#define NET_LOBBY_HEARTBEAT_INTERVAL 1000
#endif
#ifndef NET_LOBBY_HEARTBEAT_TIMEOUT
#define NET_LOBBY_HEARTBEAT_TIMEOUT 5000
#endif
#ifndef NET_LOBBY_QUERY_TIMEOUT
#define NET_LOBBY_QUERY_TIMEOUT 3000
#endif
enum LobbyMessage {
LM_Heartbeat = MT_Application,
LM_Query,
LM_Result,
LM_Results_End,
LM_Identify,
};
enum LobbyFilterMode {
LFM_Ignore,
LFM_True,
LFM_False,
};
struct Game {
Address address;
std::string name, mod;
unsigned short players, maxPlayers;
bool started, isLocal, password, listed;
int punchPort, version;
Game() : players(0), maxPlayers(0), started(false), isLocal(false), listed(true), password(false), punchPort(-1), version(0) {
}
void write(Message& msg);
void read(Message& msg);
};
struct LobbyQuery {
typedef std::function<void(Game&)> ResultHandler;
Client client;
BroadcastClient broadcast;
int broadcastPort;
ResultHandler handler;
threads::Signal running;
bool active;
bool doUpdate;
bool queryServer;
bool queryBroadcast;
std::set<Address> handled_lobbies;
unsigned short receivedFromServer;
unsigned short totalFromServer;
LobbyQuery(Address ServerAddress, int BroadcastPort = -1);
LobbyQuery(const std::string& hostname, int port, int BroadcastPort = -1, AddressType type = AT_IPv4);
void bind();
~LobbyQuery();
LobbyFilterMode full, started;
std::string name, mod;
bool updating;
void refresh(bool queryServer = true, bool queryBroadcast = true);
void update(bool clear);
void stop();
};
struct LobbyPunchthrough {
Client* client;
threads::Signal running;
Address lobbyAddress;
bool active;
uint64_t interval;
bool established;
LobbyPunchthrough(Address ServerAddress, Client* client);
void stop();
void heartbeat();
~LobbyPunchthrough();
};
struct LobbyHeartbeat : public Game {
Client client;
Transport* transport;
Server broadcast;
int broadcastPort;
threads::Signal running;
int fullCounter;
bool active;
uint64_t interval;
bool identified;
unsigned externalIP;
unsigned short externalPort;
LobbyHeartbeat(Address ServerAddress, int BroadcastPort = -1);
void enablePunchthrough(Server* server);
void run(bool doQuery = true, bool doBroadcast = true);
void stop();
void heartbeat();
void identRequest();
~LobbyHeartbeat();
};
struct LobbyServer {
struct GameDesc : public Game {
time lastHeartbeat;
};
Server server;
threads::ReadWriteMutex mutex;
threads::Signal running;
std::map<Address, GameDesc> games;
bool active, logging;
LobbyServer(int port, const std::string& address = "", bool logging = true);
void listen(int port, const std::string& address = "");
void runThreads(int workerThreads = 4);
void stop();
~LobbyServer();
};
};
+331
View File
@@ -0,0 +1,331 @@
#pragma once
#include <string>
#include <cstring>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <network/message_types.h>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
namespace net {
//Message
//======
//Handles memory between the Network and Application
//
//Use 'message >> variable' to read from the Message
//Use 'message << variable' to write to the Message
//
//To send a message,
//Message msg(MessageType);
//msg << data;
class MessageReadError {
};
typedef unsigned msize_t;
struct Message {
//Prepares a message for sending
Message();
Message(uint8_t type, uint8_t flags = 0);
Message(uint8_t* data, msize_t bytes);
Message(Message& other);
void setType(uint8_t type);
uint8_t getType() const;
uint8_t getFlags() const;
void setFlags(uint8_t flags);
bool hasFlags() const;
bool getFlag(uint8_t flag) const;
bool hasID() const;
unsigned short getID() const;
void setID(unsigned short id);
unsigned short getSeqID() const;
void setSeqID(unsigned short id);
msize_t size() const;
//Reserve space on the message for filling in later
msize_t reserve(size_t bytes);
template<class T>
msize_t reserve() {
return reserve(sizeof(T));
}
template<class T>
void fill(msize_t pos, const T& value) {
memcpy(buffer->data() + pos, (void*)&value, sizeof(T));
}
template<class T>
bool canRead() const {
return used_bytes * 8 + used_bits >= (read_bytes + sizeof(T)) * 8 + read_bits;
}
//Easy write functions (msg << data)
template<class T>
void write(T value) {
writeBits((uint8_t*)&value, sizeof(T) * 8);
}
void write(void* ptr, unsigned bytes) {
writeBits((uint8_t*)ptr, bytes * 8);
}
void read(void* ptr, unsigned bytes) {
readBits((uint8_t*)ptr, bytes * 8);
}
template<class T>
Message& operator<<(const T& value) {
writeBits((uint8_t*)&value, sizeof(T) * 8);
return *this;
}
Message& operator<<(bool bit);
Message& operator<<(const char* str);
Message& operator<<(const std::string& str);
//Easy read functions (msg >> data)
template<class T>
Message& operator>>(T& value) {
readBits((uint8_t*)&value, sizeof(T) * 8);
return *this;
}
Message& operator>>(bool& bit);
Message& operator>>(char*& str);
Message& operator>>(std::string& str);
//Writing and reading vectors
template<class T>
Message& operator<<(const std::vector<T>& arr) {
*this << (unsigned short)arr.size();
for(auto it = arr.begin(), end = arr.end(); it != end; ++it)
*this << *it;
return *this;
}
template<class T>
Message& operator>>(const std::vector<T>& arr) {
unsigned short size;
*this >> size;
arr.reserve(size);
for(unsigned short i = 0; i < size; ++i) {
T elem;
*this >> elem;
arr.push_back(elem);
}
return *this;
}
//Writing and reading lists
template<class T>
Message& operator<<(const std::list<T>& arr) {
*this << (unsigned short)arr.size();
for(auto it = arr.begin(), end = arr.end(); it != end; ++it)
*this << *it;
return *this;
}
template<class T>
Message& operator>>(const std::list<T>& arr) {
unsigned short size;
*this >> size;
arr.reserve(size);
for(unsigned short i = 0; i < size; ++i) {
T elem;
*this >> elem;
arr.push_back(elem);
}
return *this;
}
//Writing and reading maps
template<class K, class V>
Message& operator<<(const std::map<K,V>& mp) {
*this << (unsigned short)mp.size();
for(auto it = mp.begin(), end = mp.end(); it != end; ++it) {
*this << it->first;
*this << it->second;
}
return *this;
}
template<class K, class V>
Message& operator>>(const std::map<K,V>& mp) {
unsigned short size;
*this >> size;
for(unsigned short i = 0; i < size; ++i) {
K key; V value;
*this >> key;
*this >> value;
mp[key] = value;
}
return *this;
}
//Writing and reading unordered maps
template<class K, class V>
Message& operator<<(const std::unordered_map<K,V>& mp) {
*this << (unsigned short)mp.size();
for(auto it = mp.begin(), end = mp.end(); it != end; ++it) {
*this << it->first;
*this << it->second;
}
return *this;
}
template<class K, class V>
Message& operator>>(const std::unordered_map<K,V>& mp) {
unsigned short size;
*this >> size;
for(unsigned short i = 0; i < size; ++i) {
K key; V value;
*this >> key;
*this >> value;
mp[key] = value;
}
return *this;
}
template<class T>
T readIn() {
T v;
*this >> v;
return v;
}
void writeSmall(unsigned value);
unsigned readSmall();
void writeSignedSmall(int value);
int readSignedSmall();
void writeBitValue(unsigned value, uint8_t bits);
unsigned readBitValue(uint8_t bits);
void writeLimited(unsigned value, unsigned limit);
void writeLimited(unsigned value, unsigned min, unsigned max);
unsigned readLimited(unsigned limit);
unsigned readLimited(unsigned min, unsigned max);
void writeFixed(double value, double min, double max, uint8_t bits = 16);
double readFixed(double min, double max, uint8_t bits = 16);
//Writes a vec3 to a much smaller version without sacrificing signicant quality
void writeSmallVec3(double x, double y, double z);
void readSmallVec3(double& x, double& y, double& z);
//Writes a vec3 to a smaller version without sacrificing noticeable quality
void writeMedVec3(double x, double y, double z);
void readMedVec3(double& x, double& y, double& z);
//Writes a direction (unit vector) in a very small size
void writeDirection(double x, double y, double z, unsigned acc = 12);
void readDirection(double& x, double& y, double& z, unsigned acc = 12);
//Writes a rotation (unit quaterniond) in a very small size
void writeRotation(double x, double y, double z, double w);
void readRotation(double& x, double& y, double& z, double& w);
void finalize();
void writeAlign();
void writeBits(uint8_t* ptr, unsigned bits);
void readAlign();
void readBits(uint8_t* ptr, unsigned bits);
void writeBit(bool bit);
void write1();
void write0();
bool readBit();
~Message();
bool hasError() const;
void clear();
void dump();
void reset();
void advance(unsigned bits);
void rewind();
void rewind(unsigned bytes, unsigned bits = 0);
struct Position {
msize_t bytes;
uint8_t bits;
};
Position getReadPosition();
Position getWritePosition();
void setReadPosition(Position pos);
void setWritePosition(Position pos);
void copyTo(Message& to, msize_t fromPos = 0, msize_t toPos = 0) const;
void move(Message& other);
void operator=(const Message& other);
uint8_t& operator[](msize_t byte);
const uint8_t& operator[](msize_t byte) const;
void getAsPacket(char*& pBytes, msize_t& bytes);
void setPacket(char* pBytes, msize_t bytes);
private:
void allocate(msize_t size);
//Prepares the write stage for the addition of <bytes> bytes
void _prepwrite(msize_t bytes);
struct Buffer {
//Values in every message
uint8_t type : 8;
//Not all types have flags, but most do
uint8_t flags : 8;
//Optional values, check the flags first
unsigned short id : 16;
unsigned short seqID : 16;
uint8_t* data();
static Buffer* create(msize_t bytes);
static Buffer* copyPacket(uint8_t* pBytes, msize_t bytes);
static void resize(Buffer*& buff, msize_t prevSize, msize_t bytes);
}* buffer;
msize_t allocated;
msize_t used_bytes;
uint8_t used_bits;
msize_t read_bytes;
uint8_t read_bits;
bool HasID, readError;
};
};
@@ -0,0 +1,54 @@
#pragma once
#include "threads.h"
#include <network/message.h>
#include <network/transport.h>
#include <queue>
#include <vector>
#include <functional>
namespace net {
#ifndef NET_SELECT_TIMEOUT
#define NET_SELECT_TIMEOUT 0
#endif
#ifndef NET_IDLE_SLEEP
#define NET_IDLE_SLEEP 1
#endif
class MessageHandler {
struct QueuedMessage {
Transport* transport;
Address addr;
Message* msg;
};
threads::Mutex queueMutex;
threads::Mutex transportMutex;
std::queue<QueuedMessage> messageQueue;
std::vector<Transport*> transports;
public:
threads::Signal threadsRunning;
bool active;
std::function<void(bool)> threadInit;
std::function<void(bool)> threadExit;
MessageHandler();
virtual ~MessageHandler();
void addTransport(Transport* transport);
void clearTransports();
virtual void queueMessage(Transport* transport, Address addr, Message* msg);
virtual void handleMessage(Transport* transport, Address addr, Message* msg);
virtual bool queueTick();
virtual bool mainTick();
virtual void runThreads(int workerThreads = 4);
virtual void stop();
};
};
@@ -0,0 +1,59 @@
#pragma once
#include <limits.h>
namespace net {
enum MessageType : unsigned char {
//Builtin message types
MT_Invalid = 0,
MT_Connect,
MT_Disconnect,
MT_Close_Sequence,
MT_Ping,
MT_Pong,
MT_Ack,
MT_SeqAck,
MT_Fragment,
MT_LastFragment,
MT_Punchthrough,
//The application starts defining message types here
MT_Application = 0x10,
};
enum DisconnectReason : unsigned char {
DR_Timeout,
DR_Error,
DR_Close,
DR_Kick,
DR_Version,
DR_Password,
DR_NULL
};
const bool MessageHasFlags[] = {
false, //MT_Invalid
true, //MT_Connect
true, //MT_Disconnect
true, //MT_Close_Sequence
false, //MT_Ping
false, //MT_Pong
false, //MT_Ack
false, //MT_SeqAck
true, //MT_Fragment
true, //MT_LastFragment
false, //MT_Punchthrough
};
const int MessageFlagsAll = sizeof(MessageHasFlags) / sizeof(bool);
enum MessageFlags : unsigned char {
MF_Reliable = 0x1,
MF_Sequenced = 0x2,
MF_Acknowledged = 0x80,
MF_Managed = MF_Reliable | MF_Sequenced,
};
};
+74
View File
@@ -0,0 +1,74 @@
#pragma once
#include <network/message.h>
#include <network/client.h>
#include <network/message_handler.h>
#include <network/connection.h>
#include <network/time.h>
#include <unordered_map>
#include <unordered_set>
namespace net {
//Handles queueing and resending outgoing messages
struct OutSequence {
Connection& conn;
unsigned short id;
unsigned short nextOutgoingID;
unsigned short nextAck;
unsigned resendPeriod;
bool closed;
struct MessageAwaitingAck {
Message* msg;
time lastResend;
bool sent;
};
void queue(Message* mess);
std::list<Message*> queuedMessages;
std::unordered_set<unsigned short> waitingAcks;
OutSequence(Connection& connection);
void handleAck(unsigned short num);
//Tries to pull a message from the sequence.
// If it succeeds, the requester owns the message
// Otherwise, returns a nullptr
Message* getNextMessage();
OutSequence& operator<<(Message& message);
void close();
};
//Handles receiving and reordering incoming messages
struct InSequence {
Connection& conn;
unsigned short id;
bool closed;
std::unordered_map<unsigned short, Message*> unhandledMessages;
unsigned short nextHandleID;
unsigned short handlingID;
InSequence(Connection& connection, unsigned short id);
bool preHandle(MessageHandler& handler, Message* msg);
void postHandle(MessageHandler& handler, Message* msg);
void process(MessageHandler& handler, time& now);
};
//Wrapper class to easily create new outgoing sequences and
//close them when the wrapper goes out of scope
struct Sequence {
OutSequence* ws;
Sequence(Client& client);
Sequence(Connection& connection);
~Sequence();
unsigned short id();
Sequence& operator<<(Message& message);
};
};
+75
View File
@@ -0,0 +1,75 @@
#pragma once
#include <network/message.h>
#include <network/message_handler.h>
#include <network/transport.h>
#include <network/connection.h>
#include <vector>
#include <map>
#include <unordered_map>
#include <functional>
#include "threads.h"
namespace net {
/*
* Server
* ------
* Handles incoming connections and messages from
* listening on one or multiple addresses/ports.
*/
class Server : public MessageHandler {
public:
typedef std::function<void(Server&,Connection&,Message&)> connMessageHandler;
typedef std::function<void(Server&,Transport&,Address,Message&)> genMessageHandler;
typedef std::function<void(Connection&)> connFunction;
Server();
~Server();
//Listen on everything associated with the passed address and port
Server(int port, const std::string& address = "", bool broadcast = false);
void listen(int port, const std::string& address = "", bool broadcast = false);
//Handlers for messages that arrive on a specific connection
void connHandle(uint8_t type, connMessageHandler func);
void connHandleClear(uint8_t type);
//Handlers for connection-less messages arriving on a transport
void genHandle(uint8_t type, genMessageHandler func);
void genHandleClear(uint8_t type);
//Send to the connection with the given id
void send(int connId, Message& message);
//Send to all active connections
void sendAll(Message& message);
//Send a ping to all connected clients
void pingAll();
//Find the connection with the given id
// NOTE: Grabs the connection before returning it
Connection* getConnectionByID(int id);
void doAll(connFunction func);
//Kick a connection
void kick(Connection& conn, DisconnectReason reason = DR_Kick);
virtual void handleMessage(Transport* transport, Address addr, Message* msg);
virtual bool mainTick();
virtual void stop();
private:
threads::Mutex connMutex;
threads::Mutex handlerMutex;
unsigned nextConnectionID;
std::unordered_map<Address, Connection*> connections;
std::unordered_map<int, Connection*> connectionIDs;
std::unordered_map<uint8_t, connMessageHandler> connHandlers;
std::unordered_map<uint8_t, genMessageHandler> genHandlers;
};
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#ifdef __GNUC__
#include <sys/time.h>
#endif
namespace net {
#ifdef __GNUC__
typedef unsigned int time;
#else
typedef unsigned int time;
#endif
void time_now(time& time);
uint64_t time_diff(time& from, time& to);
void time_add(time& base, int64_t add_ms);
};
@@ -0,0 +1,44 @@
#pragma once
#include <network/address.h>
#include <network/message.h>
#include "threads.h"
#include <queue>
namespace net {
class MessageHandler;
class Transport {
mutable threads::atomic_int references;
threads::Mutex queueMutex;
std::queue<std::pair<Message*,Address>> queuedSends;
std::queue<std::pair<Message*,int>> queuedBroadcasts;
int sockfd;
public:
bool active;
bool canBroadcast;
AddressType type;
int rate;
Transport(AddressType Type = AT_IPv4);
~Transport();
void grab() const;
void drop() const;
void listen(Address& addr, bool rcvBroadcast = false);
void process();
void close();
bool send(Message& msg, Address& adr, bool queue = true);
bool broadcast(Message& msg, int port, bool queue = true);
bool receive(Message& msg, Address& adr);
static int RATE_LIMIT;
friend class MessageHandler;
};
};