#include "TCPListener.h" #include "TCPSocket.h" #include "TCPClient.h" #include "IListenerInterface.h" #include "logging/Logger.h" namespace Feather::Network { TCPListener::TCPListener(uint16_t port, IListenerInterface* callbacks) : m_callbacks(callbacks) { // Setup the listen socket. auto socket = std::make_unique(); if (!socket->IsValid()) { Log::Error("Socket failed to be created."); return; } if (!socket->MarkReusable()) { Log::Error("Failed to mark socket as resuable."); return; } if (socket->IsIPV6() && !socket->MarkDualBind()) { Log::Error("Failed to mark IPv6 socket as dual-bind."); return; } if (!socket->Bind(port)) { Log::Error("Failed to bind socket to port {}.", port); return; } if (!socket->MarkNonBlocking()) { Log::Error("Failed to mark socket as non-blocking."); return; } auto ListenerCallback = [](evconnlistener* evListener, SocketHandle socket, sockaddr* addr, int len, void* self) { TCPListener* listener = static_cast(self); listener->OnClientConnect(std::make_unique(listener, socket, addr)); }; if (!socket->Listen(ListenerCallback, this)) { Log::Error("Failed to start listening on socket."); return; } m_socket = std::move(socket); } TCPListener::~TCPListener() { } bool TCPListener::IsValid() const { return m_socket != nullptr; } void TCPListener::OnClientConnect(TCPClientHandle&& client) { m_callbacks->OnClientConnect(std::move(client)); } void TCPListener::OnClientDisconnected(const TCPClient* client) { m_callbacks->OnClientDisconnect(client); } }