Work on refactoring networking system
This commit is contained in:
parent
31ebec99c5
commit
8423980536
|
@ -4,3 +4,9 @@ constexpr unsigned long long operator"" KB(unsigned long long l)
|
|||
{
|
||||
return l * 1024;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define abstract __declspec(novtable)
|
||||
#else
|
||||
#define abstract
|
||||
#endif
|
|
@ -5,7 +5,7 @@ namespace Feather
|
|||
{
|
||||
DedicatedServer::DedicatedServer(ServerProperties* properties) :
|
||||
m_properties(properties),
|
||||
m_listener(properties->serverPort.GetValue()),
|
||||
m_listener(properties->serverPort.GetValue(), this),
|
||||
m_status()
|
||||
{
|
||||
m_status.descriptionText = properties->motd.GetValue();
|
||||
|
@ -20,4 +20,16 @@ namespace Feather
|
|||
DedicatedServer::~DedicatedServer()
|
||||
{
|
||||
}
|
||||
|
||||
void DedicatedServer::OnClientConnect(Network::TCPClient&& client)
|
||||
{
|
||||
auto [clients, lock] = m_clients.borrow();
|
||||
clients.emplace_back(std::move(client));
|
||||
}
|
||||
|
||||
void DedicatedServer::OnClientDisconnect(Network::TCPClient& client)
|
||||
{
|
||||
auto [clients, lock] = m_clients.borrow();
|
||||
//clients.erase(std::remove(clients.begin(), clients.end(), client), clients.end());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,26 @@
|
|||
|
||||
#include "network/TCPListener.h"
|
||||
#include "network/ServerStatus.h"
|
||||
|
||||
#include "network/IListenerInterface.h"
|
||||
|
||||
namespace Feather
|
||||
{
|
||||
class ServerProperties;
|
||||
|
||||
class DedicatedServer
|
||||
class DedicatedServer final : public Network::IListenerInterface
|
||||
{
|
||||
public:
|
||||
DedicatedServer(ServerProperties* properties);
|
||||
~DedicatedServer();
|
||||
|
||||
void OnClientConnect(Network::TCPClient&& client) override;
|
||||
void OnClientDisconnect(Network::TCPClient& client) override;
|
||||
|
||||
private:
|
||||
ServerProperties* m_properties;
|
||||
Network::TCPListener m_listener;
|
||||
Network::ServerStatus m_status;
|
||||
|
||||
LockableVector<Network::TCPClient> m_clients;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace Feather
|
||||
{
|
||||
template <typename T>
|
||||
class Lockable {
|
||||
public:
|
||||
auto borrow() { return std::pair< T&, std::lock_guard<std::mutex>>{object, mutex}; }
|
||||
auto borrow() const { return std::pair<const T&, std::lock_guard<std::mutex>>{object, mutex}; }
|
||||
|
||||
private:
|
||||
T object;
|
||||
mutable std::mutex mutex;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using LockableVector = Lockable<std::vector<T>>;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "NetworkMessage.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
using std::queue;
|
||||
|
||||
namespace Feather::Network
|
||||
{
|
||||
class ClientHandle
|
||||
{
|
||||
private:
|
||||
friend class TCPListener;
|
||||
|
||||
queue<NetworkMessage*> m_queue;
|
||||
|
||||
public:
|
||||
void SendPacket(NetworkMessage* msg)
|
||||
{
|
||||
m_queue.push(msg);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Common.h"
|
||||
|
||||
namespace Feather::Network
|
||||
{
|
||||
class TCPClient;
|
||||
|
||||
class abstract IListenerInterface
|
||||
{
|
||||
public:
|
||||
virtual void OnClientConnect(TCPClient&& client) = 0;
|
||||
virtual void OnClientDisconnect(TCPClient& client) = 0;
|
||||
};
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
#if 0
|
||||
#include "Protocol.h"
|
||||
#include "PacketReader.h"
|
||||
#include "PacketTypes.h"
|
||||
|
@ -106,4 +107,5 @@ R"({
|
|||
// TODO: validate state here
|
||||
m_state = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,12 +1,11 @@
|
|||
|
||||
#include "../Common.h"
|
||||
#include "../Lockable.h"
|
||||
|
||||
#include "Protocol.h"
|
||||
#include "TCPListener.h"
|
||||
#include "NetworkManager.h"
|
||||
#include "NetworkMessage.h"
|
||||
#include "PacketReader.h"
|
||||
#include "ClientHandle.h"
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/listener.h>
|
||||
|
@ -106,24 +105,13 @@ namespace Feather::Network
|
|||
bool m_ipv6;
|
||||
};
|
||||
|
||||
class TCPListenerClient final : public ClientHandle
|
||||
class TCPListenerClient
|
||||
{
|
||||
private:
|
||||
friend class TCPListener;
|
||||
|
||||
// Protocol for this specific client
|
||||
Protocol m_protocol;
|
||||
|
||||
TCPListener *m_parent;
|
||||
bufferevent *m_bufferEvent;
|
||||
|
||||
std::vector<uint8_t> m_incomingData;
|
||||
std::mutex m_mutex;
|
||||
public:
|
||||
TCPListenerClient(TCPListener* parent, evutil_socket_t socket)
|
||||
: m_parent(parent)
|
||||
, m_protocol(this)
|
||||
, m_bufferEvent(bufferevent_socket_new(NetworkManager::Instance().GetEventBase(), socket, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS))
|
||||
, m_buffer(evbuffer_new())
|
||||
{
|
||||
printf("Created TCPListenerClient\n");
|
||||
bufferevent_setcb(m_bufferEvent,
|
||||
|
@ -136,87 +124,71 @@ namespace Feather::Network
|
|||
|
||||
~TCPListenerClient()
|
||||
{
|
||||
evbuffer_free(m_buffer);
|
||||
bufferevent_free(m_bufferEvent);
|
||||
}
|
||||
|
||||
void ReadCallback()
|
||||
{
|
||||
printf("Read callback!\n");
|
||||
auto lock = std::unique_lock(m_mutex);
|
||||
|
||||
uint8_t data[1KB];
|
||||
size_t length;
|
||||
|
||||
size_t originalSize = m_incomingData.size();
|
||||
|
||||
// TODO: could switch to bufferevent_read_buffer and use evbuffer to avoid copies
|
||||
while ((length = bufferevent_read(m_bufferEvent, data, sizeof(data))) > 0)
|
||||
if (bufferevent_read_buffer(m_bufferEvent, m_buffer) != 0)
|
||||
{
|
||||
size_t oldSize = m_incomingData.size();
|
||||
m_incomingData.resize(oldSize + length);
|
||||
std::memcpy(&m_incomingData[oldSize], data, length);
|
||||
printf("fuck");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* dataPtr = &(m_incomingData.data()[originalSize]);
|
||||
PacketReader reader(dataPtr);
|
||||
|
||||
m_protocol.HandlePacket(reader);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WritePingMessage(T& message, std::string json)
|
||||
{
|
||||
// Packet ID
|
||||
message.WriteVarInt(0);
|
||||
// JSON Contents
|
||||
message.WriteString(json.c_str(), static_cast<int32_t>(json.length()));
|
||||
}
|
||||
DEFINE_MESSAGE_WRAPPER(WritePingMessage);
|
||||
|
||||
bool SendShitTest()
|
||||
{
|
||||
auto lock = std::unique_lock(m_mutex);
|
||||
const std::string json_template =
|
||||
R"({
|
||||
"version": {
|
||||
"name": "1.16.1",
|
||||
"protocol": 736
|
||||
},
|
||||
"players": {
|
||||
"max": 10,
|
||||
"online": 10,
|
||||
"sample": [
|
||||
const size_t size = evbuffer_get_length(m_buffer);
|
||||
auto [data, lock] = m_data.borrow();
|
||||
data.resize(size);
|
||||
if (evbuffer_remove(m_buffer, data.data(), size) != size)
|
||||
{
|
||||
"name": "thinkofdeath",
|
||||
"id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"
|
||||
printf("fuck");
|
||||
return;
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"text": "Hello Nukem!"
|
||||
}
|
||||
})";
|
||||
|
||||
auto message = WritePingMessage(json_template);
|
||||
|
||||
bufferevent_write(m_bufferEvent, message.GetData(), message.GetDataSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteCallback()
|
||||
{
|
||||
printf("Write callback!\n");
|
||||
|
||||
//SendShitTest();
|
||||
}
|
||||
|
||||
void EventCallback(short event)
|
||||
{
|
||||
printf("Event! %d\n", event);
|
||||
}
|
||||
|
||||
const LockableVector<uint8_t>& GetData() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
private:
|
||||
TCPListener* m_parent;
|
||||
|
||||
bufferevent* m_bufferEvent;
|
||||
evbuffer* m_buffer;
|
||||
|
||||
LockableVector<uint8_t> m_data;
|
||||
};
|
||||
|
||||
TCPListener::TCPListener(uint16_t port)
|
||||
TCPClient::TCPClient(std::unique_ptr<TCPListenerClient>&& client)
|
||||
: m_client(std::move(client))
|
||||
{
|
||||
}
|
||||
|
||||
TCPClient::TCPClient(TCPClient&& client)
|
||||
: m_client(std::move(client.m_client))
|
||||
{
|
||||
}
|
||||
|
||||
TCPClient::~TCPClient()
|
||||
{
|
||||
}
|
||||
|
||||
const LockableVector<uint8_t>& TCPClient::GetData() const
|
||||
{
|
||||
return m_client->GetData();
|
||||
}
|
||||
|
||||
TCPListener::TCPListener(uint16_t port, IListenerInterface* callbacks)
|
||||
: m_callbacks(callbacks)
|
||||
{
|
||||
// Setup the listen socket.
|
||||
auto socket = std::make_unique<TCPSocket>();
|
||||
|
@ -239,7 +211,7 @@ R"({
|
|||
auto ListenerCallback = [](evconnlistener* evListener, evutil_socket_t socket, sockaddr* addr, int len, void* self)
|
||||
{
|
||||
TCPListener* listener = static_cast<TCPListener*>(self);
|
||||
listener->m_clients.emplace_back(std::make_unique<TCPListenerClient>(listener, socket));
|
||||
listener->m_callbacks->OnClientConnect(std::make_unique<TCPListenerClient>(listener, socket));
|
||||
};
|
||||
|
||||
if (!socket->Listen(ListenerCallback, this))
|
||||
|
@ -250,20 +222,5 @@ R"({
|
|||
|
||||
TCPListener::~TCPListener()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TCPListener::DispatchQueuedPackets()
|
||||
{
|
||||
for (const auto& client : m_clients)
|
||||
{
|
||||
while (!client->m_queue.empty())
|
||||
{
|
||||
NetworkMessage *msg = client->m_queue.front();
|
||||
printf("Writing packet of size %u\n", uint32_t(msg->GetDataSize()));
|
||||
bufferevent_write(client->m_bufferEvent, msg->GetData(), msg->GetDataSize());
|
||||
client->m_queue.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include "Lockable.h"
|
||||
#include "IListenerInterface.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Feather::Network
|
||||
{
|
||||
class Protocol;
|
||||
|
||||
class TCPSocket;
|
||||
class TCPListenerClient;
|
||||
|
||||
class TCPClient
|
||||
{
|
||||
public:
|
||||
TCPClient(std::unique_ptr<TCPListenerClient>&& client);
|
||||
TCPClient(TCPClient&& client);
|
||||
~TCPClient();
|
||||
|
||||
const LockableVector<uint8_t>& GetData() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<TCPListenerClient> m_client;
|
||||
};
|
||||
|
||||
class TCPListener
|
||||
{
|
||||
public:
|
||||
TCPListener(uint16_t port);
|
||||
TCPListener(uint16_t port, IListenerInterface* callbacks);
|
||||
~TCPListener();
|
||||
|
||||
void DispatchQueuedPackets();
|
||||
|
||||
private:
|
||||
IListenerInterface* m_callbacks;
|
||||
std::unique_ptr<TCPSocket> m_socket;
|
||||
|
||||
std::vector<std::unique_ptr<TCPListenerClient>> m_clients;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue