Clean up socket management

This commit is contained in:
HikikoMarmy
2025-07-03 18:16:11 +01:00
parent 0bbe5f1d1e
commit 414f3f9e8b
5 changed files with 68 additions and 106 deletions

View File

@@ -9,20 +9,16 @@
#include "../Game/RealmUserManager.h" #include "../Game/RealmUserManager.h"
#include "../Network/Events.h" #include "../Network/Events.h"
#include "../Network/Event/NotifyForcedLogout.h" #include "../../configuration.h"
#include "../../logging.h" #include "../../logging.h"
LobbyServer::LobbyServer() LobbyServer::LobbyServer()
{ {
m_running = false; m_running = false;
m_conSocket = INVALID_SOCKET; m_conSocket.reset();
m_rtaSocket = INVALID_SOCKET; m_rtaSocket.reset();
for( int i = 0; i < 8; i++ ) m_gatewaySockets.clear();
{
m_conGatewaySocket[ i ] = INVALID_SOCKET;
m_rtaGatewaySocket[ i ] = INVALID_SOCKET;
}
m_clientSockets.clear(); m_clientSockets.clear();
m_recvBuffer.resize( 1024 ); m_recvBuffer.resize( 1024 );
@@ -40,38 +36,39 @@ LobbyServer::~LobbyServer()
} }
} }
for( auto &sock : m_conGatewaySocket ) for( auto &socket : m_gatewaySockets )
{ {
if( sock != INVALID_SOCKET ) if( socket->fd != INVALID_SOCKET )
{ {
closesocket( sock ); closesocket( socket->fd );
}
}
for( auto &sock : m_rtaGatewaySocket )
{
if( sock != INVALID_SOCKET )
{
closesocket( sock );
} }
} }
} }
void LobbyServer::Start( std::string ip ) void LobbyServer::Start( std::string ip )
{ {
// Champions of Norrath Gateway Sockets
for( int i = 0; i < 8; i++ ) for( int i = 0; i < 8; i++ )
{ {
m_conGatewaySocket[ i ] = OpenNetworkSocket( ip, 40800 + i ); auto gatewaySocket = OpenListenerSocket( ip, 40800 + i, RealmGameType::CHAMPIONS_OF_NORRATH );
if( m_conGatewaySocket[ i ] == INVALID_SOCKET ) if( nullptr == gatewaySocket ) return;
return;
m_rtaGatewaySocket[ i ] = OpenNetworkSocket( ip, 40810 + i ); gatewaySocket->flag.is_gateway = true;
if( m_rtaGatewaySocket[ i ] == INVALID_SOCKET ) m_gatewaySockets.push_back( gatewaySocket );
return;
} }
m_conSocket = OpenNetworkSocket( ip, 40900 ); // Return to Arms Gateway Sockets
m_rtaSocket = OpenNetworkSocket( ip, 40910 ); for( int i = 0; i < 8; i++ )
{
auto gatewaySocket = OpenListenerSocket( ip, 40810 + i, RealmGameType::RETURN_TO_ARMS );
if( nullptr == gatewaySocket ) return;
gatewaySocket->flag.is_gateway = true;
m_gatewaySockets.push_back( gatewaySocket );
}
m_conSocket = OpenListenerSocket( ip, Config::con_lobby_port, RealmGameType::CHAMPIONS_OF_NORRATH );
m_rtaSocket = OpenListenerSocket( ip, Config::rta_lobby_port, RealmGameType::RETURN_TO_ARMS );
m_running = true; m_running = true;
m_thread = std::thread( &LobbyServer::Run, this ); m_thread = std::thread( &LobbyServer::Run, this );
@@ -95,13 +92,13 @@ void LobbyServer::Stop()
} }
} }
SOCKET LobbyServer::OpenNetworkSocket( std::string ip, int32_t port ) sptr_socket LobbyServer::OpenListenerSocket( std::string ip, int32_t port, RealmGameType type )
{ {
SOCKET sock = ::WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED ); SOCKET sock = ::WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED );
if( sock == INVALID_SOCKET ) if( sock == INVALID_SOCKET )
{ {
Log::Error( "WSASocket() failed on port {}", port ); Log::Error( "WSASocket() failed on port {}", port );
return INVALID_SOCKET; return nullptr;
} }
sockaddr_in service{}; sockaddr_in service{};
@@ -116,26 +113,33 @@ SOCKET LobbyServer::OpenNetworkSocket( std::string ip, int32_t port )
{ {
Log::Error( "Invalid IP address format: {}", ip ); Log::Error( "Invalid IP address format: {}", ip );
closesocket( sock ); closesocket( sock );
return INVALID_SOCKET; return nullptr;
} }
if( bind( sock, reinterpret_cast< SOCKADDR * >( &service ), sizeof( service ) ) == SOCKET_ERROR ) if( bind( sock, reinterpret_cast< SOCKADDR * >( &service ), sizeof( service ) ) == SOCKET_ERROR )
{ {
Log::Error( "bind() failed on port {}", port ); Log::Error( "bind() failed on port {}", port );
closesocket( sock ); closesocket( sock );
return INVALID_SOCKET; return nullptr;
} }
if( listen( sock, SOMAXCONN ) == SOCKET_ERROR ) if( listen( sock, SOMAXCONN ) == SOCKET_ERROR )
{ {
Log::Error( "listen() failed on port {}", port ); Log::Error( "listen() failed on port {}", port );
closesocket( sock ); closesocket( sock );
return INVALID_SOCKET; return nullptr;
} }
auto realmSocket = std::make_shared< RealmSocket >();
realmSocket->fd = sock;
realmSocket->remote_ip = ip;
realmSocket->remote_port = port;
realmSocket->gameType = type;
realmSocket->flag.is_listener = true;
Log::Info( "Socket Opened on {}:{}", ip, port ); Log::Info( "Socket Opened on {}:{}", ip, port );
return sock; return realmSocket;
} }
void LobbyServer::Run() void LobbyServer::Run()
@@ -150,22 +154,14 @@ void LobbyServer::Run()
FD_ZERO( &readSet ); FD_ZERO( &readSet );
FD_ZERO( &writeSet ); FD_ZERO( &writeSet );
FD_SET( m_conSocket, &readSet ); FD_SET( m_conSocket->fd, &readSet );
FD_SET( m_rtaSocket, &readSet ); FD_SET( m_rtaSocket->fd, &readSet );
for( const auto &sock : m_conGatewaySocket ) for( const auto &sock : m_gatewaySockets )
{ {
if( sock != INVALID_SOCKET ) if( sock != nullptr && sock->fd != INVALID_SOCKET )
{ {
FD_SET( sock, &readSet ); FD_SET( sock->fd, &readSet );
}
}
for( const auto &sock : m_rtaGatewaySocket )
{
if( sock != INVALID_SOCKET )
{
FD_SET( sock, &readSet );
} }
} }
@@ -185,30 +181,25 @@ void LobbyServer::Run()
continue; continue;
} }
for( auto &sock : m_conGatewaySocket ) for( auto &sock : m_gatewaySockets )
{ {
if( sock != INVALID_SOCKET && FD_ISSET( sock, &readSet ) ) if( sock == nullptr || sock->fd == INVALID_SOCKET )
continue;
if( FD_ISSET( sock->fd, &readSet ) )
{ {
AcceptGateway( sock, RealmGameType::CHAMPIONS_OF_NORRATH ); AcceptConnection( sock );
} }
} }
for( auto &sock : m_rtaGatewaySocket ) if( FD_ISSET( m_conSocket->fd, &readSet ) )
{ {
if( sock != INVALID_SOCKET && FD_ISSET( sock, &readSet ) ) AcceptConnection( m_conSocket );
{
AcceptGateway( sock, RealmGameType::RETURN_TO_ARMS );
}
} }
if( FD_ISSET( m_conSocket, &readSet ) ) if( FD_ISSET( m_rtaSocket->fd, &readSet ) )
{ {
AcceptClient( m_conSocket, RealmGameType::CHAMPIONS_OF_NORRATH ); AcceptConnection( m_rtaSocket );
}
if( FD_ISSET( m_rtaSocket, &readSet ) )
{
AcceptClient( m_rtaSocket, RealmGameType::RETURN_TO_ARMS );
} }
for( auto &client : m_clientSockets ) for( auto &client : m_clientSockets )
@@ -261,12 +252,12 @@ void LobbyServer::CheckSocketProblem()
} }
} }
void LobbyServer::AcceptGateway( SOCKET socket, RealmGameType gameType ) void LobbyServer::AcceptConnection( sptr_socket srcSocket )
{ {
sockaddr_in clientInfo{}; sockaddr_in clientInfo{};
int32_t addrSize = sizeof( clientInfo ); int32_t addrSize = sizeof( clientInfo );
SOCKET clientSocket = accept( socket, ( SOCKADDR * )&clientInfo, &addrSize ); SOCKET clientSocket = accept( srcSocket->fd, ( SOCKADDR * )&clientInfo, &addrSize );
if( clientSocket == INVALID_SOCKET ) if( clientSocket == INVALID_SOCKET )
{ {
Log::Error( "accept() failed" ); Log::Error( "accept() failed" );
@@ -274,6 +265,8 @@ void LobbyServer::AcceptGateway( SOCKET socket, RealmGameType gameType )
} }
auto new_socket = std::make_shared< RealmSocket >(); auto new_socket = std::make_shared< RealmSocket >();
auto gameType = srcSocket->gameType;
new_socket->fd = clientSocket; new_socket->fd = clientSocket;
new_socket->remote_addr = clientInfo; new_socket->remote_addr = clientInfo;
new_socket->remote_ip = Util::IPFromAddr( clientInfo ); new_socket->remote_ip = Util::IPFromAddr( clientInfo );
@@ -281,31 +274,11 @@ void LobbyServer::AcceptGateway( SOCKET socket, RealmGameType gameType )
new_socket->gameType = gameType; new_socket->gameType = gameType;
m_clientSockets.push_back( new_socket ); m_clientSockets.push_back( new_socket );
Log::Info( "New Gateway Client Connected : ({})", new_socket->remote_ip ); if( !srcSocket->flag.is_gateway )
}
void LobbyServer::AcceptClient( SOCKET socket, RealmGameType gameType )
{
sockaddr_in clientInfo{};
int32_t addrSize = sizeof( clientInfo );
SOCKET clientSocket = accept( socket, ( SOCKADDR * )&clientInfo, &addrSize );
if( clientSocket == INVALID_SOCKET )
{ {
Log::Error( "accept() failed" ); UserManager::Get().CreateUser( new_socket, gameType );
return;
} }
auto new_socket = std::make_shared< RealmSocket >();
new_socket->fd = clientSocket;
new_socket->remote_addr = clientInfo;
new_socket->remote_ip = Util::IPFromAddr( clientInfo );
new_socket->remote_port = ntohs( clientInfo.sin_port );
new_socket->gameType = gameType;
m_clientSockets.push_back( new_socket );
UserManager::Get().CreateUser( new_socket, gameType );
Log::Info( "New Client Connected : ({})", new_socket->remote_ip ); Log::Info( "New Client Connected : ({})", new_socket->remote_ip );
} }
@@ -445,14 +418,6 @@ void LobbyServer::HandleRequest( sptr_socket socket, sptr_byte_stream stream )
} }
auto request = it->second(); auto request = it->second();
//auto user = RealmUserManager::Get().FindUserBySocket( socket );
//
//if( user == nullptr )
//{
// Log::Error( "User not found!" );
// socket->flag.disconnected_wait = true;
// return;
//}
if( auto res = request->ProcessRequest( socket, stream ) ) if( auto res = request->ProcessRequest( socket, stream ) )
{ {

View File

@@ -41,25 +41,18 @@ public:
} }
private: private:
// These are the main sockets for the lobby server sptr_socket m_conSocket;
SOCKET m_conSocket; sptr_socket m_rtaSocket;
SOCKET m_rtaSocket; std::vector< sptr_socket > m_gatewaySockets;
// Gateway sockets. 1 port per region.
std::array< SOCKET, 8 > m_conGatewaySocket;
std::array< SOCKET, 8 > m_rtaGatewaySocket;
// Connected client sockets
std::vector< sptr_socket > m_clientSockets; std::vector< sptr_socket > m_clientSockets;
std::vector< uint8_t > m_recvBuffer; std::vector< uint8_t > m_recvBuffer;
SOCKET OpenNetworkSocket( std::string ip, int32_t port ); sptr_socket OpenListenerSocket( std::string ip, int32_t port, RealmGameType type );
void Run(); void Run();
void CheckSocketProblem(); void CheckSocketProblem();
void AcceptGateway( SOCKET socket, RealmGameType clientType ); void AcceptConnection( sptr_socket srcSocket );
void AcceptClient( SOCKET socket, RealmGameType clientType );
void ReadSocket( sptr_socket socket ); void ReadSocket( sptr_socket socket );
void WriteSocket( sptr_socket socket ); void WriteSocket( sptr_socket socket );
void HandleRequest( sptr_socket socket, sptr_byte_stream stream ); void HandleRequest( sptr_socket socket, sptr_byte_stream stream );

View File

@@ -29,6 +29,7 @@
/* 0027 */ #include "Event/RequestGetEncryptionKey.h" /* 0027 */ #include "Event/RequestGetEncryptionKey.h"
/* 0041 */ #include "Event/NotifyForcedLogout.h"
/* 0042 */ #include "Event/RequestGetRules.h" /* 0042 */ #include "Event/RequestGetRules.h"
/* 0043 */ #include "Event/RequestGetServerAddress.h" /* 0043 */ #include "Event/RequestGetServerAddress.h"
/* 0044 */ #include "Event/RequestUpdateGameData.h" /* 0044 */ #include "Event/RequestUpdateGameData.h"

View File

@@ -14,6 +14,7 @@ RealmSocket::RealmSocket()
flag.disconnected_wait = 0; flag.disconnected_wait = 0;
flag.disconnected_forced = 0; flag.disconnected_forced = 0;
flag.is_listener = 0; flag.is_listener = 0;
flag.is_gateway = 0;
flag.want_more_read_data = 0; flag.want_more_read_data = 0;
flag.want_more_write_data = 0; flag.want_more_write_data = 0;
@@ -43,6 +44,7 @@ RealmSocket::~RealmSocket()
flag.disconnected_wait = 0; flag.disconnected_wait = 0;
flag.disconnected_forced = 0; flag.disconnected_forced = 0;
flag.is_listener = 0; flag.is_listener = 0;
flag.is_gateway = 0;
flag.want_more_read_data = 0; flag.want_more_read_data = 0;
flag.want_more_write_data = 0; flag.want_more_write_data = 0;

View File

@@ -40,6 +40,7 @@ public:
bool disconnected_wait; bool disconnected_wait;
bool disconnected_forced; bool disconnected_forced;
bool is_listener; bool is_listener;
bool is_gateway;
bool want_more_read_data; bool want_more_read_data;
bool want_more_write_data; bool want_more_write_data;
} flag; } flag;
@@ -51,8 +52,8 @@ public:
std::string remote_ip; std::string remote_ip;
uint32_t remote_port; uint32_t remote_port;
uint32_t last_write_position; uint32_t last_write_position;
uint64_t latency; uint64_t latency;
std::chrono::steady_clock::time_point last_recv_time; std::chrono::steady_clock::time_point last_recv_time;
std::chrono::steady_clock::time_point last_send_time; std::chrono::steady_clock::time_point last_send_time;