FeatherMC/src/network/TCPClient.cpp

68 lines
2.2 KiB
C++

#include "TCPClient.h"
#include "TCPListener.h"
#include "NetworkManager.h"
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include "logging/Logger.h"
#include <cinttypes>
namespace Feather::Network
{
TCPClient::TCPClient(TCPListener* parent, SocketHandle socket, SocketAddress&& addr)
: m_parent(parent)
, 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_address(std::move(addr))
{
bufferevent_setcb(m_bufferEvent,
[](bufferevent* be, void* self) { static_cast<TCPClient*>(self)->ReadCallback(); },
[](bufferevent* be, void* self) { static_cast<TCPClient*>(self)->WriteCallback(); },
[](bufferevent* be, int16_t event, void* self) { static_cast<TCPClient*>(self)->EventCallback(event); },
this);
bufferevent_enable(m_bufferEvent, EV_READ | EV_WRITE);
}
TCPClient::~TCPClient()
{
bufferevent_free(m_bufferEvent);
}
void TCPClient::ReadCallback()
{
evbuffer* buffer = bufferevent_get_input(m_bufferEvent);
const size_t size = evbuffer_get_length(buffer);
auto [data, lock] = m_data.borrow();
const size_t offset = data.size();
data.resize(offset + size);
if (evbuffer_remove(buffer, &data[offset], size) != size)
{
Log::Error("Failed to remove data from buffer.");
return;
}
}
void TCPClient::WriteCallback()
{
}
void TCPClient::EventCallback(int16_t event)
{
if (event & BEV_EVENT_ERROR)
{
const char* errorString = evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR());
Log::Error("TCPClient: {}", errorString);
}
if (event & BEV_EVENT_EOF)
m_parent->OnClientDisconnected(this);
}
void TCPClient::Write(const uint8_t* data, size_t size)
{
if (bufferevent_write(m_bufferEvent, data, size) != 0)
Log::Error("Failed to write to socket, size: " PRIuPTR ".", size);
}
}