2020-08-02 00:53:56 +01:00
|
|
|
|
#include "TCPListener.h"
|
|
|
|
|
#include "TCPSocket.h"
|
2020-08-01 04:38:20 +01:00
|
|
|
|
#include "TCPClient.h"
|
2020-08-02 00:53:56 +01:00
|
|
|
|
#include "IListenerInterface.h"
|
2020-07-25 04:57:54 +01:00
|
|
|
|
|
2020-08-02 00:53:56 +01:00
|
|
|
|
#include "logging/Logger.h"
|
2020-07-25 03:01:16 +01:00
|
|
|
|
|
|
|
|
|
namespace Feather::Network
|
|
|
|
|
{
|
2020-07-29 01:46:31 +01:00
|
|
|
|
TCPListener::TCPListener(uint16_t port, IListenerInterface* callbacks)
|
|
|
|
|
: m_callbacks(callbacks)
|
2020-07-25 03:01:16 +01:00
|
|
|
|
{
|
|
|
|
|
// Setup the listen socket.
|
|
|
|
|
auto socket = std::make_unique<TCPSocket>();
|
|
|
|
|
|
|
|
|
|
if (!socket->IsValid())
|
2020-08-01 07:35:18 +01:00
|
|
|
|
{
|
2020-08-07 06:23:12 +01:00
|
|
|
|
Log::Error("Socket failed to be created.");
|
2020-07-25 03:01:16 +01:00
|
|
|
|
return;
|
2020-08-01 07:35:18 +01:00
|
|
|
|
}
|
2020-07-25 03:01:16 +01:00
|
|
|
|
|
|
|
|
|
if (!socket->MarkReusable())
|
2020-08-01 07:35:18 +01:00
|
|
|
|
{
|
2020-08-07 06:23:12 +01:00
|
|
|
|
Log::Error("Failed to mark socket as resuable.");
|
2020-07-25 03:01:16 +01:00
|
|
|
|
return;
|
2020-08-01 07:35:18 +01:00
|
|
|
|
}
|
2020-07-25 03:01:16 +01:00
|
|
|
|
|
|
|
|
|
if (socket->IsIPV6() && !socket->MarkDualBind())
|
2020-08-01 07:35:18 +01:00
|
|
|
|
{
|
2020-08-07 06:23:12 +01:00
|
|
|
|
Log::Error("Failed to mark IPv6 socket as dual-bind.");
|
2020-07-25 03:01:16 +01:00
|
|
|
|
return;
|
2020-08-01 07:35:18 +01:00
|
|
|
|
}
|
2020-07-25 03:01:16 +01:00
|
|
|
|
|
|
|
|
|
if (!socket->Bind(port))
|
2020-08-01 07:35:18 +01:00
|
|
|
|
{
|
2020-08-07 06:23:12 +01:00
|
|
|
|
Log::Error("Failed to bind socket to port {}.", port);
|
2020-07-25 03:01:16 +01:00
|
|
|
|
return;
|
2020-08-01 07:35:18 +01:00
|
|
|
|
}
|
2020-07-25 03:01:16 +01:00
|
|
|
|
|
|
|
|
|
if (!socket->MarkNonBlocking())
|
2020-08-01 07:35:18 +01:00
|
|
|
|
{
|
2020-08-07 06:23:12 +01:00
|
|
|
|
Log::Error("Failed to mark socket as non-blocking.");
|
2020-07-25 03:01:16 +01:00
|
|
|
|
return;
|
2020-08-01 07:35:18 +01:00
|
|
|
|
}
|
2020-07-25 03:01:16 +01:00
|
|
|
|
|
2020-08-01 06:48:14 +01:00
|
|
|
|
auto ListenerCallback = [](evconnlistener* evListener, SocketHandle socket, sockaddr* addr, int len, void* self)
|
2020-07-25 04:57:54 +01:00
|
|
|
|
{
|
|
|
|
|
TCPListener* listener = static_cast<TCPListener*>(self);
|
2020-08-02 00:35:54 +01:00
|
|
|
|
listener->OnClientConnect(std::make_unique<TCPClient>(listener, socket, addr));
|
2020-07-25 04:57:54 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!socket->Listen(ListenerCallback, this))
|
2020-08-01 07:35:18 +01:00
|
|
|
|
{
|
2020-08-07 06:23:12 +01:00
|
|
|
|
Log::Error("Failed to start listening on socket.");
|
2020-07-25 03:01:16 +01:00
|
|
|
|
return;
|
2020-08-01 07:35:18 +01:00
|
|
|
|
}
|
2020-07-25 03:01:16 +01:00
|
|
|
|
|
|
|
|
|
m_socket = std::move(socket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TCPListener::~TCPListener()
|
|
|
|
|
{
|
2020-07-28 05:45:03 +01:00
|
|
|
|
}
|
2020-08-01 04:54:31 +01:00
|
|
|
|
|
2020-08-02 00:55:09 +01:00
|
|
|
|
bool TCPListener::IsValid() const
|
|
|
|
|
{
|
|
|
|
|
return m_socket != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-01 06:48:14 +01:00
|
|
|
|
void TCPListener::OnClientConnect(TCPClientHandle&& client)
|
|
|
|
|
{
|
|
|
|
|
m_callbacks->OnClientConnect(std::move(client));
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-01 04:54:31 +01:00
|
|
|
|
void TCPListener::OnClientDisconnected(const TCPClient* client)
|
|
|
|
|
{
|
|
|
|
|
m_callbacks->OnClientDisconnect(client);
|
|
|
|
|
}
|
2020-08-01 00:57:33 +01:00
|
|
|
|
}
|