Big network rewrites
Hook up protocol, lots of cleaning 🧹
This commit is contained in:
parent
aaf6abaf07
commit
0e0a8d89ed
|
@ -1,6 +1,9 @@
|
||||||
#include "DedicatedServer.h"
|
#include "DedicatedServer.h"
|
||||||
#include "config/ServerProperties.h"
|
#include "config/ServerProperties.h"
|
||||||
|
|
||||||
|
#include "Protocol.h"
|
||||||
|
#include "PacketReader.h"
|
||||||
|
|
||||||
namespace Feather
|
namespace Feather
|
||||||
{
|
{
|
||||||
DedicatedServer::DedicatedServer(ServerProperties* properties) :
|
DedicatedServer::DedicatedServer(ServerProperties* properties) :
|
||||||
|
@ -13,7 +16,17 @@ namespace Feather
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
auto [clients, clientsLock] = m_clients.borrow();
|
||||||
|
for (auto& client : clients)
|
||||||
|
{
|
||||||
|
Protocol protocol;
|
||||||
|
auto [data, clientLock] = client.GetTCPClient().GetData().borrow();
|
||||||
|
if (data.empty())
|
||||||
|
continue;
|
||||||
|
auto reader = PacketReader(data.data());
|
||||||
|
protocol.HandlePacket(client, reader);
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +43,6 @@ namespace Feather
|
||||||
void DedicatedServer::OnClientDisconnect(const Network::TCPClient& client)
|
void DedicatedServer::OnClientDisconnect(const Network::TCPClient& client)
|
||||||
{
|
{
|
||||||
auto [clients, lock] = m_clients.borrow();
|
auto [clients, lock] = m_clients.borrow();
|
||||||
clients.remove(client);
|
clients.remove_if([&](MinecraftClient& other) { return &other.GetTCPClient() == &client; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "network/TCPListener.h"
|
#include "MinecraftClient.h"
|
||||||
#include "network/ServerStatus.h"
|
#include "ServerStatus.h"
|
||||||
|
|
||||||
#include "network/IListenerInterface.h"
|
#include "network/IListenerInterface.h"
|
||||||
|
|
||||||
namespace Feather
|
namespace Feather
|
||||||
|
@ -20,8 +21,8 @@ namespace Feather
|
||||||
private:
|
private:
|
||||||
ServerProperties* m_properties;
|
ServerProperties* m_properties;
|
||||||
Network::TCPListener m_listener;
|
Network::TCPListener m_listener;
|
||||||
Network::ServerStatus m_status;
|
ServerStatus m_status;
|
||||||
|
|
||||||
LockableList<Network::TCPClient> m_clients;
|
LockableList<MinecraftClient> m_clients;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "MinecraftClient.h"
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
MinecraftClient::MinecraftClient(Network::TCPClient&& client)
|
||||||
|
: m_client (std::move(client))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftClient::~MinecraftClient()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftClient::SendMessage(const NetworkMessage& message)
|
||||||
|
{
|
||||||
|
m_client.Write(message.GetData(), message.GetDataSize());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "network/TCPListener.h"
|
||||||
|
#include "Protocol.h"
|
||||||
|
#include "NetworkMessage.h"
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
class MinecraftClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MinecraftClient(Network::TCPClient&& client);
|
||||||
|
~MinecraftClient();
|
||||||
|
|
||||||
|
inline Network::TCPClient& GetTCPClient() { return m_client; }
|
||||||
|
inline ProtocolContext& GetContext() { return m_context; }
|
||||||
|
|
||||||
|
void SendMessage(const NetworkMessage& message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Network::TCPClient m_client;
|
||||||
|
ProtocolContext m_context;
|
||||||
|
};
|
||||||
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#define VARINT_MAX_SIZE 5
|
#define VARINT_MAX_SIZE 5
|
||||||
|
|
||||||
namespace Feather::Network
|
namespace Feather
|
||||||
{
|
{
|
||||||
class NetworkMessageCounter
|
class NetworkMessageCounter
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -8,9 +8,8 @@
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
namespace Feather::Network
|
namespace Feather
|
||||||
{
|
{
|
||||||
|
|
||||||
// Class to read packet data, such as is produced by NetworkMessage
|
// Class to read packet data, such as is produced by NetworkMessage
|
||||||
class PacketReader
|
class PacketReader
|
||||||
{
|
{
|
||||||
|
@ -20,18 +19,25 @@ namespace Feather::Network
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T Peek()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<const T* const>(&m_data[m_offset]);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T Read()
|
inline T Read()
|
||||||
{
|
{
|
||||||
T value = *reinterpret_cast<const T *const>(&m_data[m_offset]);
|
T value = Peek<T>();
|
||||||
m_offset += sizeof(T);
|
m_offset += sizeof(T);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int ReadVarInt()
|
template <typename T = int32_t>
|
||||||
|
inline T ReadVarInt()
|
||||||
{
|
{
|
||||||
int numRead = 0;
|
int32_t numRead = 0;
|
||||||
int result = 0;
|
int32_t result = 0;
|
||||||
uint8_t read;
|
uint8_t read;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -47,7 +53,7 @@ namespace Feather::Network
|
||||||
}
|
}
|
||||||
} while ((read & 0b10000000) != 0);
|
} while ((read & 0b10000000) != 0);
|
||||||
|
|
||||||
return result;
|
return static_cast<T>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
string ReadString()
|
string ReadString()
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
enum class ServerboundHandholdingPacketId : int32_t
|
||||||
|
{
|
||||||
|
Handshake = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ServerboundStatusPacketId : int32_t
|
||||||
|
{
|
||||||
|
Request = 0,
|
||||||
|
Ping = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr uint8_t LegacyServerListPing = 0xFE;
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include "Protocol.h"
|
||||||
|
#include "PacketReader.h"
|
||||||
|
#include "PacketTypes.h"
|
||||||
|
#include "MinecraftClient.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// TODO Remove.
|
||||||
|
const std::string json_template =
|
||||||
|
R"({
|
||||||
|
"version": {
|
||||||
|
"name": "1.16.1",
|
||||||
|
"protocol": 736
|
||||||
|
},
|
||||||
|
"players": {
|
||||||
|
"max": 10,
|
||||||
|
"online": 10,
|
||||||
|
"sample": [
|
||||||
|
{
|
||||||
|
"name": "thinkofdeath",
|
||||||
|
"id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"text": "Hello Nukem!"
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
void Protocol::HandlePacket(MinecraftClient& client, PacketReader& packet)
|
||||||
|
{
|
||||||
|
auto& context = client.GetContext();
|
||||||
|
switch (context.GetState())
|
||||||
|
{
|
||||||
|
case ProtocolState::Handholding:
|
||||||
|
{
|
||||||
|
auto id = packet.ReadVarInt<ServerboundHandholdingPacketId>();
|
||||||
|
uint8_t legacyId = packet.Peek<uint8_t>();
|
||||||
|
if (id != ServerboundHandholdingPacketId::Handshake && legacyId != LegacyServerListPing)
|
||||||
|
{
|
||||||
|
printf("[Protocol] Client sent packet with non-zero ID 0x%x while state was HANDSHAKING\n", id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id != ServerboundHandholdingPacketId::Handshake)
|
||||||
|
{
|
||||||
|
// Legacy server ping.
|
||||||
|
// TODO: Do server list ping here.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clientProtocolVersion = packet.ReadVarInt();
|
||||||
|
string serverIp = packet.ReadString();
|
||||||
|
uint16_t port = packet.Read<uint16_t>();
|
||||||
|
|
||||||
|
// next desired state
|
||||||
|
ProtocolState intention = (ProtocolState)(packet.ReadVarInt());
|
||||||
|
|
||||||
|
printf("[Protocol] Client Intention Packet: version=%d, serverIp=%s, port=%u, intention=%d\n",
|
||||||
|
clientProtocolVersion,
|
||||||
|
serverIp.c_str(),
|
||||||
|
port,
|
||||||
|
intention
|
||||||
|
);
|
||||||
|
|
||||||
|
context.SetState(intention);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ProtocolState::Status:
|
||||||
|
{
|
||||||
|
auto id = packet.ReadVarInt<ServerboundStatusPacketId>();
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case ServerboundStatusPacketId::Request:
|
||||||
|
{
|
||||||
|
printf("[Protocol] Client sent STATUS_PING_REQUEST\n");
|
||||||
|
|
||||||
|
DynamicNetworkMessage msg(VARINT_MAX_SIZE + json_template.length());
|
||||||
|
// Packet ID
|
||||||
|
msg.WriteVarInt(0);
|
||||||
|
// JSON Contents
|
||||||
|
msg.WriteString(json_template.c_str(), static_cast<int32_t>(json_template.length()));
|
||||||
|
msg.Finalize();
|
||||||
|
client.SendMessage(msg);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerboundStatusPacketId::Ping:
|
||||||
|
{
|
||||||
|
int64_t timestamp = packet.Read<int64_t>();
|
||||||
|
printf("[Protocol] Client sent STATUS_PING: %lld\n", timestamp);
|
||||||
|
|
||||||
|
DynamicNetworkMessage msg(VARINT_MAX_SIZE + sizeof(int64_t));
|
||||||
|
|
||||||
|
msg.WriteVarInt(1);
|
||||||
|
msg.WriteLong(timestamp);
|
||||||
|
msg.Finalize();
|
||||||
|
|
||||||
|
client.SendMessage(msg);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NetworkMessage.h"
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
class PacketReader;
|
||||||
|
class MinecraftClient;
|
||||||
|
|
||||||
|
enum class ProtocolState
|
||||||
|
{
|
||||||
|
Handholding = -1,
|
||||||
|
Play = 0,
|
||||||
|
Status = 1,
|
||||||
|
Login = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProtocolContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline ProtocolState GetState() const
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetState(ProtocolState state)
|
||||||
|
{
|
||||||
|
printf("Setting state");
|
||||||
|
m_state = state;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ProtocolState m_state = ProtocolState::Handholding;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Protocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void HandlePacket(MinecraftClient& client, PacketReader& packet);
|
||||||
|
};
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
using string = std::string;
|
using string = std::string;
|
||||||
using stringstream = std::stringstream;
|
using stringstream = std::stringstream;
|
||||||
|
|
||||||
namespace Feather::Network
|
namespace Feather
|
||||||
{
|
{
|
||||||
class ServerStatus
|
class ServerStatus
|
||||||
{
|
{
|
|
@ -1,12 +1,13 @@
|
||||||
feather_src = [
|
feather_src = [
|
||||||
'Main.cpp',
|
'Main.cpp',
|
||||||
'DedicatedServer.cpp',
|
'DedicatedServer.cpp',
|
||||||
|
'MinecraftClient.cpp',
|
||||||
|
'Protocol.cpp',
|
||||||
|
|
||||||
'logging/Logger.cpp',
|
'logging/Logger.cpp',
|
||||||
|
|
||||||
'network/NetworkManager.cpp',
|
'network/NetworkManager.cpp',
|
||||||
'network/TCPListener.cpp',
|
'network/TCPListener.cpp',
|
||||||
'network/Protocol.cpp',
|
|
||||||
|
|
||||||
'util/StringUtil.cpp',
|
'util/StringUtil.cpp',
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Packets from Client -> Server
|
|
||||||
enum class ServerboundPacketType
|
|
||||||
{
|
|
||||||
STATUS_PING_REQUEST = 0,
|
|
||||||
STATUS_PING = 1
|
|
||||||
};
|
|
|
@ -1,111 +0,0 @@
|
||||||
#if 0
|
|
||||||
#include "Protocol.h"
|
|
||||||
#include "PacketReader.h"
|
|
||||||
#include "PacketTypes.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
namespace Feather::Network
|
|
||||||
{
|
|
||||||
void Protocol::HandlePacket(PacketReader& packet)
|
|
||||||
{
|
|
||||||
int id = packet.ReadVarInt();
|
|
||||||
printf("PacketReader[%u]: ID = %u\n", packet.Length(), id);
|
|
||||||
|
|
||||||
switch (m_state)
|
|
||||||
{
|
|
||||||
case ProtocolState::HANDSHAKING:
|
|
||||||
{
|
|
||||||
if (id != 0) {
|
|
||||||
// this could be, for example, Legacy Server List Ping 0xFE
|
|
||||||
printf("[Protocol] Client sent packet with non-zero ID 0x%x while state was HANDSHAKING\n", id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int clientProtocolVersion = packet.ReadVarInt();
|
|
||||||
string serverIp = packet.ReadString();
|
|
||||||
uint16_t port = packet.Read<uint16_t>();
|
|
||||||
|
|
||||||
// next desired state
|
|
||||||
ProtocolState intention = (ProtocolState)(packet.ReadVarInt());
|
|
||||||
|
|
||||||
printf("[Protocol] Client Intention Packet: version=%d, serverIp=%s, port=%u, intention=%d\n",
|
|
||||||
clientProtocolVersion,
|
|
||||||
serverIp.c_str(),
|
|
||||||
port,
|
|
||||||
intention
|
|
||||||
);
|
|
||||||
|
|
||||||
SetState(intention);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ProtocolState::STATUS:
|
|
||||||
{
|
|
||||||
ServerboundPacketType type = (ServerboundPacketType)id;
|
|
||||||
printf("[Protocol] [STATUS mode] Client sent packet ID %d (%d)\n", id, type);
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case ServerboundPacketType::STATUS_PING_REQUEST:
|
|
||||||
{
|
|
||||||
printf("[Protocol] Client sent STATUS_PING_REQUEST\n");
|
|
||||||
|
|
||||||
const std::string json_template =
|
|
||||||
R"({
|
|
||||||
"version": {
|
|
||||||
"name": "1.16.1",
|
|
||||||
"protocol": 736
|
|
||||||
},
|
|
||||||
"players": {
|
|
||||||
"max": 10,
|
|
||||||
"online": 10,
|
|
||||||
"sample": [
|
|
||||||
{
|
|
||||||
"name": "thinkofdeath",
|
|
||||||
"id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"text": "Hello Nukem!"
|
|
||||||
}
|
|
||||||
})";
|
|
||||||
|
|
||||||
/*DynamicNetworkMessage msg(VARINT_MAX_SIZE + json_template.length());
|
|
||||||
// Packet ID
|
|
||||||
msg.WriteVarInt(0);
|
|
||||||
// JSON Contents
|
|
||||||
msg.WriteString(json_template.c_str(), static_cast<int32_t>(json_template.length()));
|
|
||||||
m_client->SendPacket(&msg);*/
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ServerboundPacketType::STATUS_PING:
|
|
||||||
int64_t timestamp = packet.Read<int64_t>();
|
|
||||||
printf("[Protocol] Client sent STATUS_PING: %lld\n", timestamp);
|
|
||||||
|
|
||||||
/*DynamicNetworkMessage msg(VARINT_MAX_SIZE + sizeof(int64_t));
|
|
||||||
|
|
||||||
msg.WriteVarInt(1);
|
|
||||||
msg.WriteLong(timestamp);
|
|
||||||
|
|
||||||
m_client->SendPacket(&msg);*/
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Protocol::SetState(ProtocolState state)
|
|
||||||
{
|
|
||||||
printf("[Protocol] Switching state from %d to %d\n", m_state, state);
|
|
||||||
// TODO: validate state here
|
|
||||||
m_state = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,33 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "NetworkMessage.h"
|
|
||||||
#include "ClientHandle.h"
|
|
||||||
|
|
||||||
namespace Feather::Network
|
|
||||||
{
|
|
||||||
class PacketReader;
|
|
||||||
|
|
||||||
enum class ProtocolState
|
|
||||||
{
|
|
||||||
HANDSHAKING = -1,
|
|
||||||
PLAY = 0,
|
|
||||||
STATUS = 1,
|
|
||||||
LOGIN = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: This should become abstract so we can support multiple versions
|
|
||||||
class Protocol
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
ClientHandle* m_client;
|
|
||||||
ProtocolState m_state = ProtocolState::HANDSHAKING;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Protocol(ClientHandle* client) : m_client(client) {}
|
|
||||||
|
|
||||||
void HandlePacket(PacketReader& packet);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void SetState(ProtocolState state);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "../Lockable.h"
|
#include "../Lockable.h"
|
||||||
|
|
||||||
#include "TCPListener.h"
|
#include "TCPListener.h"
|
||||||
|
#include "IListenerInterface.h"
|
||||||
#include "NetworkManager.h"
|
#include "NetworkManager.h"
|
||||||
#include "NetworkMessage.h"
|
#include "NetworkMessage.h"
|
||||||
#include "PacketReader.h"
|
#include "PacketReader.h"
|
||||||
|
@ -154,7 +155,13 @@ namespace Feather::Network
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const LockableVector<uint8_t>& GetData() const
|
void Write(const uint8_t* data, size_t size)
|
||||||
|
{
|
||||||
|
if (bufferevent_write(m_bufferEvent, data, size) != 0)
|
||||||
|
printf("Fuck!");
|
||||||
|
}
|
||||||
|
|
||||||
|
LockableVector<uint8_t>& GetData()
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
@ -182,11 +189,16 @@ namespace Feather::Network
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const LockableVector<uint8_t>& TCPClient::GetData() const
|
LockableVector<uint8_t>& TCPClient::GetData()
|
||||||
{
|
{
|
||||||
return m_client->GetData();
|
return m_client->GetData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TCPClient::Write(const uint8_t* data, size_t size)
|
||||||
|
{
|
||||||
|
m_client->Write(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
TCPListener::TCPListener(uint16_t port, IListenerInterface* callbacks)
|
TCPListener::TCPListener(uint16_t port, IListenerInterface* callbacks)
|
||||||
: m_callbacks(callbacks)
|
: m_callbacks(callbacks)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Lockable.h"
|
#include "Lockable.h"
|
||||||
#include "IListenerInterface.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -11,6 +10,7 @@ namespace Feather::Network
|
||||||
{
|
{
|
||||||
class TCPSocket;
|
class TCPSocket;
|
||||||
class TCPListenerClient;
|
class TCPListenerClient;
|
||||||
|
class IListenerInterface;
|
||||||
|
|
||||||
class TCPClient
|
class TCPClient
|
||||||
{
|
{
|
||||||
|
@ -19,15 +19,12 @@ namespace Feather::Network
|
||||||
TCPClient(TCPClient&& client);
|
TCPClient(TCPClient&& client);
|
||||||
~TCPClient();
|
~TCPClient();
|
||||||
|
|
||||||
const LockableVector<uint8_t>& GetData() const;
|
LockableVector<uint8_t>& GetData();
|
||||||
|
void Write(const uint8_t* data, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<TCPListenerClient> m_client;
|
std::unique_ptr<TCPListenerClient> m_client;
|
||||||
};
|
};
|
||||||
// TODO: Can we eliminate the move constructor + overloads?
|
|
||||||
// Kinda unclean.
|
|
||||||
inline bool operator==(const TCPClient& a, const TCPClient& b) { return &a == &b; }
|
|
||||||
inline bool operator!=(const TCPClient& a, const TCPClient& b) { return &a != &b; }
|
|
||||||
|
|
||||||
class TCPListener
|
class TCPListener
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue