From: hgn Date: Wed, 18 Jun 2025 23:35:23 +0000 (+0100) Subject: monitor page because yeah X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=4e7303371572508f7519a232020ec98786d3f434;p=carveJwlIkooP6JGAAIwe30JlM.git monitor page because yeah --- diff --git a/src/gameserver.c b/src/gameserver.c index 32c4fb6..942df60 100644 --- a/src/gameserver.c +++ b/src/gameserver.c @@ -20,6 +20,7 @@ volatile sig_atomic_t sig_stop; #include "vg/vg_console.h" #include "gameserver_replay.h" #include "gameserver_requests.h" +#include "gameserver_monitor.h" struct _gameserver _gameserver = { @@ -56,6 +57,7 @@ static void gameserver_send_to_client( i32 client_id, const void *pData, u32 cbD if( !client->steamid ) return; + _gameserver.bytes_send += cbData; SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( hSteamNetworkingSockets, client->connection, pData, cbData, nSendFlags, NULL ); } @@ -440,6 +442,7 @@ static void gameserver_rx_auth( SteamNetworkingMessage_t *msg ) vg_success( "User is authenticated! steamid %lu (%u) [%s]\n", steamid.m_unAll64Bits, msg->m_conn, client->admin? "Admin": "User" ); gameserver_player_join( client_id ); + _gs_monitor_playerjoin(); } /* @@ -692,6 +695,8 @@ static void gameserver_rx_300_400( SteamNetworkingMessage_t *msg ) static void process_network_message( SteamNetworkingMessage_t *msg ) { + _gameserver.bytes_recv += msg->m_cbSize; + if( msg->m_cbSize < sizeof(netmsg_blank) ) { vg_warn( "Discarding message (too small: %d)\n", msg->m_cbSize ); @@ -864,7 +869,7 @@ static int _rcon_edit_user( int argc, const char *argv[] ) } else { - vg_info( "Usage: edit_profile\n" + vg_info( "Usage: edit_user \n" " Options:\n" " +FLAG (LEGEND,EARLY,ADMIN)\n" " -FLAG\n" @@ -912,6 +917,16 @@ int main( int argc, const char *argv[] ) if( vg_long_opt( "replay-info", "Print replay info periodically" ) ) _gs_replay.print_info = 1; + if( (arg = vg_long_opt_arg( "journal", "Journal important events into file" )) ) + if( !_gs_monitor_start_journal( arg ) ) + return 0; + + if( (arg = vg_long_opt_arg( "status-html", "Record server status to HTML file" )) ) + _gs_monitor_start_html( arg ); + + if( (arg = vg_long_opt_arg( "status-interval", "Inverval which HTML page gets written" )) ) + _gs_monitor_set_interval( atof( arg ) ); + if( !_vg_opt_check() ) return 0; } @@ -976,6 +991,7 @@ int main( int argc, const char *argv[] ) poll_connections(); _gs_replay_server_tick(); _gs_requests_tick(); + _gs_monitor_tick(); usleep(10000); _gameserver.ticks ++; @@ -996,19 +1012,21 @@ int main( int argc, const char *argv[] ) } } -EE:vg_info( "Program ends\n" ); +EE:vg_info( "Server end\n" ); SteamAPI_ISteamNetworkingSockets_DestroyPollGroup( hSteamNetworkingSockets, _gameserver.client_group ); SteamAPI_ISteamNetworkingSockets_CloseListenSocket( hSteamNetworkingSockets, listener ); SteamGameServer_Shutdown(); E1:db_free(); -E0:return 0; +E0:_gs_monitor_cleanup(); + return 0; } #include "gameserver_replay.c" #include "gameserver_requests.c" #include "gameserver_database.c" +#include "gameserver_monitor.c" #include "vg/vg_async2.c" #include "vg/vg_mem_pool.c" #include "vg/vg_db.c" diff --git a/src/gameserver.h b/src/gameserver.h index 10bccec..123d2c9 100644 --- a/src/gameserver.h +++ b/src/gameserver.h @@ -25,7 +25,7 @@ struct _gameserver struct gameserver_client { - bool active, authenticated, admin; + bool active, admin; u32 version; HSteamNetConnection connection; char username[ NETWORK_USERNAME_MAX ]; @@ -50,6 +50,8 @@ struct _gameserver u64 ticks; u64 global_uid; + u64 bytes_recv, bytes_send, bytes_send1; + vg_async_queue tasks; pthread_t thread; } diff --git a/src/gameserver_monitor.c b/src/gameserver_monitor.c new file mode 100644 index 0000000..ed0e24a --- /dev/null +++ b/src/gameserver_monitor.c @@ -0,0 +1,222 @@ +struct +{ + const char *html_path; + u64 interval, timer; + bool joiner_notify; + + FILE *journal_fp; +} +_gs_monitor; + +struct task_monitor_write +{ + char buf[ 20000 ]; +}; + +void _monitor_write_task( vg_async_task *task ) +{ + THREAD_1; + struct task_monitor_write *info = (void *)task->data; + + FILE *fp = fopen( _gs_monitor.html_path, "w" ); + if( fp ) + { + fputs( info->buf, fp ); + fclose( fp ); + vg_low( "Written monitor HTML (%s)\n", _gs_monitor.html_path ); + } + else + vg_warn( "Failed to open '%s' (server monitor html path)\n" ); +} + +void _gs_monitor_tick(void) +{ + if( _gs_monitor.html_path ) + { + _gs_monitor.timer ++; + if( _gs_monitor.timer >= _gs_monitor.interval ) + { + if( _gs_monitor.interval < 10 ) + _gs_monitor_set_interval( 30.0f ); + + vg_async_task *task = vg_allocate_async_task( &_gs_db.tasks, sizeof(struct task_monitor_write), 0 ); + if( task ) + { + _gs_monitor.timer = 0; + struct task_monitor_write *info = (void *)task->data; + + vg_str str; + vg_strnull( &str, info->buf, sizeof(info->buf) ); + vg_strcat( &str, "\n" + " \n" + " \n" + " \n" + " \n" + "

Written: JavaScript Disabled.

\n" + "

Notifications: None.

\n" + " \n" + " \n" + " \n" + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " \n" + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " \n" + " \n" + " \n" ); + + u32 online = 0, authenticated = 0, admins = 0; + for( u32 i=0; i< NETWORK_MAX_PLAYERS; i ++ ) + { + if( _gameserver.clients[i].active ) + online ++; + + if( _gameserver.clients[i].steamid ) + authenticated ++; + + if( _gameserver.clients[i].admin ) + admins ++; + } + + static u32 peak = 0; + if( authenticated > peak ) + peak = authenticated; + + vg_strcat( &str, " \n" + " \n" + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " \n" + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " " + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " " + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " " + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " " + " \n" + " \n" ); + + vg_strcat( &str, " \n" + " " + " \n" + " \n" ); + + vg_strcat( &str, "
ItemValue
Tick" ); + vg_strcatu64( &str, _gameserver.ticks ); + vg_strcat( &str, "
Global UID" ); + vg_strcatu64( &str, _gameserver.global_uid ); + vg_strcat( &str, "
Active Players" ); + vg_strcati32( &str, online ); + vg_strcat( &str, "
Peak Players" ); + vg_strcati32( &str, peak ); + vg_strcat( &str, "
Authenticated Players" ); + vg_strcati32( &str, authenticated ); + vg_strcat( &str, "
Admins" ); + vg_strcati32( &str, admins ); + vg_strcat( &str, "
Bytes send (channel 0)" ); + vg_strcatu64( &str, _gameserver.bytes_send ); + vg_strcat( &str, "
Bytes send (channel 1)" ); + vg_strcatu64( &str, _gameserver.bytes_send1 ); + vg_strcat( &str, "
Bytes recv (channel 0)" ); + vg_strcatu64( &str, _gameserver.bytes_recv ); + vg_strcat( &str, "
\n" + " \n" + " \n" + "\n" ); + + vg_async_task_dispatch( task, _monitor_write_task ); + } + } + } +} + +bool _gs_monitor_start_journal( const char *path ) +{ + _gs_monitor.journal_fp = fopen( path, "a+" ); + + if( !_gs_monitor.journal_fp ) + { + vg_error( "Failed to open journal for writing (%s)\n", path ); + return 0; + } + + return 1; +} + +void _gs_monitor_start_html( const char *path ) +{ + _gs_monitor.html_path = path; +} + +void _gs_monitor_set_interval( f64 seconds ) +{ + _gs_monitor.interval = seconds_to_server_ticks( seconds ); + _gs_monitor.timer = 0; +} + +void _gs_monitor_log_event( const char *event ) +{ + /* TODO */ +} + +void _gs_monitor_playerjoin(void) +{ + _gs_monitor.joiner_notify = 1; +} + +void _gs_monitor_cleanup(void) +{ + if( _gs_monitor.journal_fp ) + { + fclose( _gs_monitor.journal_fp ); + _gs_monitor.journal_fp = NULL; + } +} diff --git a/src/gameserver_monitor.h b/src/gameserver_monitor.h new file mode 100644 index 0000000..593da76 --- /dev/null +++ b/src/gameserver_monitor.h @@ -0,0 +1,8 @@ +#pragma once +void _gs_monitor_tick(void); +bool _gs_monitor_start_journal( const char *path ); +void _gs_monitor_start_html( const char *path ); +void _gs_monitor_set_interval( f64 seconds ); +void _gs_monitor_log_event( const char *event ); +void _gs_monitor_cleanup(void); +void _gs_monitor_playerjoin(void); diff --git a/src/gameserver_requests.c b/src/gameserver_requests.c index 50bf9ee..e167e21 100644 --- a/src/gameserver_requests.c +++ b/src/gameserver_requests.c @@ -489,6 +489,6 @@ void _gs_handle_request_message( u32 client_id, SteamNetworkingMessage_t *msg ) res->id = client_packet->id; res->status = error_status; SteamAPI_ISteamNetworkingSockets_SendMessages( hSteamNetworkingSockets, 1, &reply_msg, NULL ); - SteamAPI_SteamNetworkingMessage_t_Release( msg ); + _gameserver.bytes_send1 += size; }