General cleanup.

This commit is contained in:
HikikoMarmy
2025-01-06 08:32:12 +00:00
parent ffbd9d802d
commit 2e82805920
10 changed files with 98 additions and 373 deletions

View File

@@ -5,15 +5,11 @@
// ║║║╚═╗║ ║ ║╚╗╔╝║╣ ╠╦╝╚╦╝ ╚═╗║╣ ╠╦╝╚╗╔╝║╣ ╠╦╝
// ═╩╝╩╚═╝╚═╝╚═╝ ╚╝ ╚═╝╩╚═ ╩ ╚═╝╚═╝╩╚═ ╚╝ ╚═╝╩╚═
#include "../global_define.h"
#include "../Lobby Server/Event/NotifyClientReqConnect.h"
DiscoveryServer::DiscoveryServer()
{
m_running = false;
m_sessionMap.clear();
m_recvBuffer.resize( 1024 );
}
@@ -24,9 +20,23 @@ DiscoveryServer::~DiscoveryServer()
void DiscoveryServer::Start( std::string ip, int32_t port )
{
if( false == OpenDiscoverySocket( ip, port ) )
m_socket = socket( AF_INET, SOCK_DGRAM, 0 );
if( m_socket == INVALID_SOCKET )
{
Log::Error( "Failed to open discovery socket." );
Log::Error( "Failed to create socket." );
return;
}
sockaddr_in serverInfo;
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr.s_addr = ADDR_ANY;// inet_addr( ip.c_str() );
serverInfo.sin_port = htons( port );
if( bind( m_socket, ( SOCKADDR * )&serverInfo, sizeof( serverInfo ) ) == SOCKET_ERROR )
{
Log::Error( "Failed to bind socket." );
closesocket( m_socket );
return;
}
@@ -48,43 +58,14 @@ void DiscoveryServer::Stop()
void DiscoveryServer::Run()
{
FD_SET readSet;
FD_SET writeSet;
timeval timeout = { 0, 1000 };
m_timer.Start();
while( m_running )
{
FD_ZERO( &readSet );
FD_ZERO( &writeSet );
FD_SET( m_socket, &readSet );
FD_SET( m_socket->fd, &readSet );
auto it = m_sessionMap.begin();
for( it; it != m_sessionMap.end(); )
{
auto &socket = it->second->m_socket;
//if( ::GetTickCount64() - socket->last_recv_time > 5001 )
//{
// Log::Debug( "Disconnect timeout socket." );
// it = m_sessionMap.erase( it );
// continue;
//}
if( socket->m_pendingWriteQueue.empty() )
{
it++;
continue;
}
FD_SET( socket->fd, &writeSet );
it++;
}
auto result = select( 0, &readSet, &writeSet, nullptr, &timeout );
auto result = select( 0, &readSet, nullptr, nullptr, &timeout );
if( result == SOCKET_ERROR )
{
@@ -92,172 +73,44 @@ void DiscoveryServer::Run()
break;
}
if( FD_ISSET( m_socket->fd, &readSet ) )
if( FD_ISSET( m_socket, &readSet ) )
{
ReadSocket( m_socket );
}
for( auto &session : m_sessionMap )
{
auto &socket = session.second->m_socket;
if( FD_ISSET( socket->fd, &writeSet ) )
{
WriteSocket( socket );
}
ReadSocket();
}
}
}
bool DiscoveryServer::OpenDiscoverySocket( std::string ip, int32_t port )
void DiscoveryServer::UpdateDiscoveryInfo( std::wstring sessionId, std::string ip, int32_t port )
{
SOCKET fd = socket( AF_INET, SOCK_DGRAM, 0 );
if( fd == INVALID_SOCKET )
{
Log::Error( "Failed to create socket." );
return false;
}
sockaddr_in serverInfo;
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr.s_addr = inet_addr( ip.c_str() );
serverInfo.sin_port = htons( port );
if( bind( fd, ( SOCKADDR * )&serverInfo, sizeof( serverInfo ) ) == SOCKET_ERROR )
{
Log::Error( "Failed to bind socket." );
closesocket( fd );
return false;
}
m_socket = std::make_shared< RealmUDPSocket >();
m_socket->local_address = serverInfo;
m_socket->fd = fd;
m_socket->port = port;
m_socket->flag.is_listener = true;
return true;
}
sptr_udp_socket DiscoveryServer::CreateDiscoverySocket( sockaddr_in *remoteAddr )
{
auto socket = std::make_shared< RealmUDPSocket >();
socket->fd = m_socket->fd;
socket->local_address = m_socket->local_address;
socket->remote_address = *remoteAddr;
socket->peer_ip_address = inet_ntoa( remoteAddr->sin_addr );
socket->peer_port = ntohs( remoteAddr->sin_port );
socket->last_recv_time = ::GetTickCount64();
Log::Debug( "Create new session socket for %s:%d", socket->peer_ip_address.c_str(), socket->peer_port );
return socket;
}
sptr_discovery_record DiscoveryServer::CreateNewDiscoveryRecord( sockaddr_in *clientAddr, std::wstring sessionId )
{
auto user = RealmUserManager::Get().GetUser( sessionId );
if( user == nullptr )
{
Log::Error( "User not found for discovery! [%S]", sessionId.c_str() );
return nullptr;
}
auto discoverySocket = CreateDiscoverySocket( clientAddr );
auto session = DiscoverySession::Create( discoverySocket );
session->m_ownerSessionId = sessionId;
m_sessionMap[ *clientAddr ] = session;
user->m_discoverySocket = discoverySocket;
Log::Debug( "Create new session for %s:%d", inet_ntoa( clientAddr->sin_addr ), clientAddr->sin_port );
return session;
}
sptr_discovery_record DiscoveryServer::GetDiscoveryRecord( sockaddr_in *clientAddr )
{
auto it = m_sessionMap.find( *clientAddr );
if( it == m_sessionMap.end() )
{
return nullptr;
}
return it->second;
}
std::wstring DiscoveryServer::GetSessionId( sptr_byte_stream stream )
{
uint32_t length = stream->read<uint32_t>();
auto decryptedBuffer = stream->read_encrypted_bytes( length );
std::wstring sessionId( length, '\0' );
std::memcpy( sessionId.data(), decryptedBuffer.data(), decryptedBuffer.size() );
return sessionId;
}
void DiscoveryServer::AcceptNewClient( sockaddr_in *clientAddr, sptr_byte_stream stream )
{
if( stream->data.size() < 36 )
{
Log::Error( "Invalid Discovery Handshake Packet" );
return;
}
//auto sessionId = GetSessionId( stream );
auto sessionId = stream->read_encrypted_utf16( false );
if( sessionId.empty() || sessionId.size() != 16 )
{
Log::Error( "Invalid session id." );
return;
}
auto record = CreateNewDiscoveryRecord( clientAddr, sessionId );
m_userDiscoveryInfo[ sessionId ] = { ip, port, GetTickCount64() };
if( record == nullptr )
{
Log::Error( "Failed to create new discovery record." );
return;
}
auto game = GameSessionManager::Get().FindGame( 0 );
auto &roomOwner = game->m_userList[ 0 ];
auto ipAddr = inet_ntoa( clientAddr->sin_addr );
auto port = ntohs( clientAddr->sin_port );
NotifyClientRequestConnect msg( ipAddr, port );
roomOwner->m_realmSocket->send( msg.Serialize() );
//auto &discovery = DiscoveryServer::Get();
SendDiscoveryClientHandshake( record, stream );
Log::Debug( "UpdateDiscoveryInfo : [%S] %s:%d", sessionId.c_str(), ip.c_str(), port );
}
void DiscoveryServer::ReadSocket( sptr_udp_socket socket )
std::optional<UserDiscoveryInfo> DiscoveryServer::GetDiscoveryInfo( const std::wstring &sessionId ) const
{
if( socket->flag.disconnected )
auto it = m_userDiscoveryInfo.find( sessionId );
if( it == m_userDiscoveryInfo.end() )
{
return;
return std::nullopt;
}
return it->second;
}
void DiscoveryServer::ReadSocket()
{
sockaddr_in clientAddr;
int clientAddrLen = sizeof( clientAddr );
// Receive data from the client
auto bytesReceived = recvfrom( socket->fd, ( char * )m_recvBuffer.data(), ( int )m_recvBuffer.size(), 0, ( struct sockaddr * )&clientAddr, &clientAddrLen );
auto bytesReceived = recvfrom( m_socket, ( char * )m_recvBuffer.data(), ( int )m_recvBuffer.size(), 0, ( struct sockaddr * )&clientAddr, &clientAddrLen );
if( bytesReceived == SOCKET_ERROR )
{
@@ -271,70 +124,35 @@ void DiscoveryServer::ReadSocket( sptr_udp_socket socket )
if( bytesReceived > 0 )
{
socket->last_recv_time = m_timer.GetElapsedTimeMilliseconds();
HandleRequest( &clientAddr, std::make_shared< ByteStream >( m_recvBuffer.data(), bytesReceived ) );
HandleDiscoveryUpdate( &clientAddr, std::make_shared< ByteStream >( m_recvBuffer.data(), bytesReceived ) );
}
}
void DiscoveryServer::WriteSocket( sptr_udp_socket socket )
void DiscoveryServer::HandleDiscoveryUpdate( sockaddr_in *clientAddr, sptr_byte_stream stream )
{
if( socket->flag.disconnected )
if( stream->get_length() != 52 )
{
Log::Error( "Invalid discovery update." );
return;
}
if( socket->m_pendingWriteQueue.empty() )
auto sessionId = stream->read_encrypted_utf16( false );
if( sessionId.empty() || sessionId.size() != 16 )
{
return;
}
auto &stream = socket->m_pendingWriteQueue.front();
auto bytesSent = sendto( socket->fd, ( char * )stream->data.data(), ( int )stream->data.size(), 0, ( struct sockaddr * )&socket->remote_address, sizeof(socket->remote_address));
if( bytesSent == SOCKET_ERROR )
{
return;
}
if( bytesSent > 0 )
{
socket->m_pendingWriteQueue.pop();
}
}
void DiscoveryServer::HandleRequest( sockaddr_in *clientAddr, sptr_byte_stream stream )
{
auto record = GetDiscoveryRecord( clientAddr );
if( record == nullptr )
{
AcceptNewClient( clientAddr, stream );
Log::Error( "Invalid session id." );
return;
}
auto remoteIp = inet_ntoa( clientAddr->sin_addr );
auto remotePort = clientAddr->sin_port;
Log::Debug( "%s:%d", remoteIp, remotePort );
//RealmUserManager::Get().UpdateUserDiscoveryInfo( sessionId, remoteIp, remotePort );
auto state = stream->read_u32();
switch( state )
{
case 12:
{
SendDiscoveryClientPing( record, stream );
} break;
default:
{
Log::Packet( stream->data, stream->data.size(), false );
} break;
}
UpdateDiscoveryInfo( sessionId, remoteIp, remotePort );
}
/*
void DiscoveryServer::SendDiscoveryClientHandshake( sptr_discovery_record record, sptr_byte_stream stream )
{
ByteStream response;
@@ -352,3 +170,4 @@ void DiscoveryServer::SendDiscoveryClientPing( sptr_discovery_record record, spt
record->m_socket->send( response );
}
*/

View File

@@ -6,6 +6,12 @@
#include "DiscoverySession.h"
struct UserDiscoveryInfo {
std::string m_ip;
int32_t m_port;
uint64_t m_lastUpdateTime;
};
class DiscoveryServer
{
public:
@@ -33,31 +39,21 @@ public:
return m_running;
}
private:
bool OpenDiscoverySocket( std::string ip, int32_t port );
sptr_udp_socket CreateDiscoverySocket( sockaddr_in *clientAddr );
sptr_discovery_record CreateNewDiscoveryRecord( sockaddr_in *clientAddr, std::wstring sessionId );
sptr_discovery_record GetDiscoveryRecord( sockaddr_in *clientAddr );
std::wstring GetSessionId( sptr_byte_stream stream );
void AcceptNewClient( sockaddr_in *clientAddr, sptr_byte_stream stream );
void ReadSocket( sptr_udp_socket socket );
void WriteSocket( sptr_udp_socket socket );
void HandleRequest( sockaddr_in *clientAddr, sptr_byte_stream stream );
void SendDiscoveryClientHandshake( sptr_discovery_record record, sptr_byte_stream stream );
void SendDiscoveryClientPing( sptr_discovery_record record, sptr_byte_stream stream );
void UpdateDiscoveryInfo( std::wstring sessionId, std::string ip, int32_t port );
std::optional<UserDiscoveryInfo> GetDiscoveryInfo( const std::wstring &sessionId ) const;
private:
void ReadSocket();
void HandleDiscoveryUpdate( sockaddr_in *clientAddr, sptr_byte_stream stream );
static inline std::unique_ptr< DiscoveryServer > m_instance;
static inline std::mutex m_mutex;
Timer m_timer;
std::atomic< bool > m_running;
std::thread m_thread;
sptr_udp_socket m_socket;
SOCKET m_socket;
std::vector< uint8_t > m_recvBuffer;
std::unordered_map< sockaddr_in, sptr_discovery_record, sockaddr_in_hash, sockaddr_in_equal> m_sessionMap;
std::unordered_map< std::wstring, UserDiscoveryInfo > m_userDiscoveryInfo;
};

View File

@@ -1,21 +1 @@
#include "../global_define.h"
#include "DiscoverySession.h"
DiscoverySession::DiscoverySession( sptr_udp_socket socket )
{
m_socket = socket;
m_ownerSessionId = L"";
m_userSessionIds.fill( L"" );
}
DiscoverySession::~DiscoverySession()
{
m_socket.reset();
m_ownerSessionId.clear();
m_userSessionIds.fill( L"" );
}
sptr_discovery_record DiscoverySession::Create( sptr_udp_socket socket )
{
return std::shared_ptr<DiscoverySession>( new DiscoverySession( socket ) );
}

View File

@@ -2,38 +2,4 @@
#include <memory>
#include <array>
#include <string>
struct sockaddr_in_hash {
std::size_t operator()( const sockaddr_in &addr ) const
{
std::size_t h1 = std::hash<int>()( addr.sin_family );
std::size_t h2 = std::hash<unsigned short>()( addr.sin_port );
std::size_t h3 = std::hash<unsigned long>()( addr.sin_addr.s_addr );
return h1 ^ ( h2 << 1 ) ^ ( h3 << 2 );
}
};
struct sockaddr_in_equal {
bool operator()( const sockaddr_in &lhs, const sockaddr_in &rhs ) const
{
return lhs.sin_family == rhs.sin_family &&
lhs.sin_port == rhs.sin_port &&
lhs.sin_addr.s_addr == rhs.sin_addr.s_addr;
}
};
class DiscoverySession {
public:
static std::shared_ptr< DiscoverySession > Create( sptr_udp_socket socket );
DiscoverySession( sptr_udp_socket socket );
~DiscoverySession();
sptr_udp_socket m_socket;
std::wstring m_ownerSessionId;
std::array< std::wstring, 4 > m_userSessionIds;
};
typedef std::shared_ptr< DiscoverySession > sptr_discovery_record;
#include <string>