High Level API - Fully Functional

This commit is contained in:
TheDoctor
2019-10-12 19:09:55 +01:00
parent 6db271bd7e
commit ad5ff5e53e
24 changed files with 1286 additions and 4 deletions

View File

@ -0,0 +1,33 @@
#pragma once
// i want to use bitshifting but i red in stackoverflow that casting doesnt generate overhead
// now ive hit a wall
// casting vs bitshifting
#include <cstdint>
#include <cstring>
namespace std
{
class BitConverter
{
public:
template<typename T>
inline static uint8_t *ToBytes(T value)
{
uint8_t *data = new uint8_t[sizeof(T)]();
memcpy(data, &value, sizeof(T));
return data;
}
template<typename T>
inline static T FromBytes(uint8_t *data)
{
if (!data)
throw std::invalid_argument("cant have null parameter -> BitConverter::FromBytes");
T value;
memcpy(&value, data, sizeof(T));
return value;
}
};
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "NetworkMessage.hpp"
namespace std::net
{
class DataReceivedEvent
{
public:
inline DataReceivedEvent(const NetworkMessage &msg)
{
SenderID = msg.GetSenderID();
DistributionMode = msg.GetDistributionMode();
DestinationID = msg.GetDestinationID();
Tag = msg.GetTag();
Data = msg.GetData<void>();
}
public:
uint32_t SenderID;
DistributionMode DistributionMode;
uint32_t DestinationID;
uint32_t Tag;
void *Data;
};
}

View File

@ -0,0 +1,36 @@
#pragma once
#include <string>
namespace std::net
{
class DisconnectedEvent // can be processed by client and server
{
private:
DisconnectedEvent();
public:
inline DisconnectedEvent(uint32_t id, char *reason, int32_t reason_id)
: m_reason(reason)
, m_clientID(id)
, m_reasonID(reason_id)
{
}
inline DisconnectedEvent(uint32_t id, const std::string &reason, int32_t reason_id)
: m_reason(reason)
, m_clientID(id)
, m_reasonID(reason_id)
{
}
inline const std::string &GetReason() const { return m_reason; }
inline int32_t GetReasonID() const { return m_reasonID; }
inline uint32_t GetID() const { return m_clientID; }
private:
std::string m_reason;
int32_t m_reasonID;
uint32_t m_clientID;
};
}

View File

@ -0,0 +1,10 @@
#pragma once
#include <cstdint>
enum class InternalTags : uint32_t
{
Disconnect = 0xFFFFFFFF,
Connect = 0xFFFFFFFE,
AssignID = 0xFFFFFFFD
};

View File

@ -0,0 +1,43 @@
#pragma once
#include <queue>
#include <mutex>
#include "NetworkMessage.hpp"
#include "NewConnectionEvent.hpp"
#include "DisconnectedEvent.hpp"
#include "DataReceivedEvent.hpp"
namespace std::net
{
class MessageQueue
{
public:
MessageQueue()
{
}
void EnqueueMessageToSend(const NetworkMessage &msg);
void EnqueueMessageReceived(const NetworkMessage &msg);
void EnqueueDisconnection(const NetworkMessage &msg);
void EnqueueConnection(const NetworkMessage &msg);
NetworkMessage DequeueMessageToSend();
uint32_t SendSize();
private:
std::deque<NetworkMessage> m_messagesToSend;
std::deque<NewConnectionEvent> m_connectionEvents;
std::deque<DisconnectedEvent> m_disconnectedEvents;
std::deque<DataReceivedEvent> m_dataReceivedEvents;
std::mutex m_sendMutex;
std::mutex m_receivedMutex;
std::mutex m_disconnectMutex;
std::mutex m_connectionMutex;
};
}

View File

@ -0,0 +1,12 @@
#pragma once
#include <cstdint>
namespace std::net
{
class NetworkHeader
{
public:
uint32_t Size;
};
}

View File

@ -0,0 +1,95 @@
#pragma once
#include "NetworkHeader.hpp"
#include "BitConverter.hpp"
#include <cstdint>
#include <cstring>
namespace std::net
{
enum class DistributionMode : uint8_t
{
ID,
Others,
OthersAndServer,
All,
AllAndMe,
Server
};
class NetworkMessage
{
public:
NetworkMessage()
{
}
NetworkMessage(uint32_t sender, DistributionMode mode, uint32_t destinationId, uint32_t tag, void *data, uint32_t dataSize)
: m_senderID(sender)
, m_distributionMode(mode)
, m_destinationID(destinationId)
, m_tag(tag)
, m_data(data)
, m_dataSize(dataSize)
{
}
uint32_t GetSenderID() const;
DistributionMode GetDistributionMode() const;
uint32_t GetDestinationID() const;
uint32_t GetTag() const;
private:
uint32_t m_senderID = 0;
DistributionMode m_distributionMode = DistributionMode::All;
uint32_t m_destinationID = 0;
uint32_t m_tag = 0;
void *m_data = 0;
uint32_t m_dataSize = 0;
public:
template<typename T>
void SetData(T *data)
{
m_data = data;
m_dataSize = sizeof(T);
}
template<typename T>
uint8_t * SerializeData(uint32_t &size)
{
int32_t sizeOfNetHeader = sizeof(NetworkHeader);
NetworkHeader header;
header.Size = 13 + sizeOfNetHeader + sizeof(T);
uint8_t *bytes = new uint8_t[header.Size];
memcpy(bytes, &header, sizeOfNetHeader);
uint8_t *sender = BitConverter::ToBytes<uint32_t>(m_senderID); // 4
uint8_t *destination = BitConverter::ToBytes<uint32_t>(m_destinationID); // 4
uint8_t *tag = BitConverter::ToBytes<uint32_t>(m_tag); // 4
memcpy(bytes + sizeOfNetHeader, sender, 4);
bytes[sizeOfNetHeader + 4] = (uint8_t)m_distributionMode;
memcpy(bytes + sizeOfNetHeader + 5, destination, 4);
memcpy(bytes + sizeOfNetHeader + 9, tag, 4);
memcpy(bytes + 13 + sizeOfNetHeader, m_data, sizeof(T));
size = header.Size;
return bytes;
}
uint8_t *SerializeData(uint32_t &size);
void Deserialize(uint8_t *data, uint32_t size);
template<typename T>
T *GetData() const
{
return (T*)m_data;
}
};
}

View File

@ -0,0 +1,18 @@
#pragma once
namespace std::net
{
class NewConnectionEvent
{
public:
inline NewConnectionEvent(uint32_t id, void *data)
: m_id(id)
, m_data(data)
{
}
private:
uint32_t m_id;
void *m_data;
};
}

26
include/HLAPI/Server.hpp Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <Net.hpp>
#include <memory>
namespace std::net
{
class TcpServer;
class MessageQueue;
class Server
{
public:
Server(uint32_t max_connections = 20, uint16_t port = DEFAULT_SERVER_PORT);
void Start();
void Stop();
private:
std::shared_ptr<std::net::TcpServer> m_tcpServer;
std::shared_ptr<MessageQueue> m_queue;
};
}

View File

@ -0,0 +1,40 @@
#pragma once
#include <functional>
#include "TcpClient.hpp"
#include "NetworkMessage.hpp"
namespace std::net
{
class TcpConnection
{
public:
friend class TcpConnectionHandler;
TcpConnection(TcpClient *client);
std::shared_ptr<TcpClient> GetClient();
uint32_t GetID();
void SetID(uint32_t id);
template<typename T>
void SendMessage(DistributionMode mode, uint32_t destinationId, uint32_t tag, void *data)
{
NetworkMessage msg(m_id, mode, destinationId, tag, data, sizeof(T));
}
void ReceiveData();
std::function<void(uint32_t, DistributionMode, uint32_t, uint32_t, void*)> DataReceivedEvent;
std::function<void(uint32_t, std::string, int32_t)> DisconnectedEvent;
std::function<void(uint32_t, void*)> NewConnectionEvent;
private:
bool sendMessage(NetworkMessage &msg);
std::shared_ptr<TcpClient> m_client;
uint32_t m_id;
};
}

View File

@ -0,0 +1,63 @@
#pragma once
#include <mutex>
#include <atomic>
#include <queue>
#include <TcpListener.hpp>
#include <TcpConnection.hpp>
//#include <BaseLibrary/SpinMutex.hpp>
namespace std::net
{
class MessageQueue;
class TcpConnection;
class Server;
namespace sockets
{
class TcpListener;
}
}
namespace std::net
{
class TcpConnectionHandler
{
friend class std::net::Server;
public:
TcpConnectionHandler(std::shared_ptr<TcpListener> listener_ptr);
~TcpConnectionHandler();
void Start();
void Stop();
void AddClient(std::shared_ptr<TcpConnection> &c);
void SetMaxConnections(uint32_t max_connections);
uint32_t GetAvailableID();
private:
void HandleReceiveMsgAndConns();
void HandleSend();
void HandleReceiveMsgAndConnsThreaded();
void HandleSendThreaded();
private:
std::vector<std::shared_ptr<TcpConnection>> m_list;
std::mutex m_listMutex;
uint32_t m_maxConnections;
std::thread m_receiveThread;
std::thread m_sendThread;
std::atomic_bool m_run;
std::shared_ptr<MessageQueue> m_queue;
std::shared_ptr<TcpListener> m_listenerPtr;
};
}

View File

@ -0,0 +1,31 @@
#pragma once
#include <atomic>
#include "TcpListener.hpp"
namespace std::net
{
class Server;
class TcpConnectionHandler;
class TcpServer
{
friend class std::net::Server;
public:
TcpServer(uint32_t max_connections, uint16_t port = DEFAULT_SERVER_PORT);
void Start();
void Stop();
private:
std::shared_ptr<TcpListener> listener;
uint32_t m_maxConnections;
uint16_t m_port;
std::atomic_bool m_run;
std::shared_ptr<std::net::TcpConnectionHandler> m_connectionHandler;
};
}