68 lines
2.2 KiB
C++
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);
|
|
}
|
|
} |