diff options
Diffstat (limited to 'src/server/sv_rankings.c')
-rw-r--r-- | src/server/sv_rankings.c | 1538 |
1 files changed, 0 insertions, 1538 deletions
diff --git a/src/server/sv_rankings.c b/src/server/sv_rankings.c deleted file mode 100644 index 7846cccf..00000000 --- a/src/server/sv_rankings.c +++ /dev/null @@ -1,1538 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. -Copyright (C) 2000-2006 Tim Angus - -This file is part of Tremulous. - -Tremulous is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Tremulous is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Tremulous; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// sv_rankings.c -- global rankings interface - -#include "server.h" -#include "..\rankings\1.0\gr\grapi.h" -#include "..\rankings\1.0\gr\grlog.h" - -typedef struct -{ - GR_CONTEXT context; - uint64_t game_id; - uint64_t match; - uint64_t player_id; - GR_PLAYER_TOKEN token; - grank_status_t grank_status; - grank_status_t final_status; // status to set after cleanup - uint32_t grank; // global rank - char name[32]; -} ranked_player_t; - -static int s_rankings_contexts = 0; -static qboolean s_rankings_active = qfalse; -static GR_CONTEXT s_server_context = 0; -static uint64_t s_server_match = 0; -static char* s_rankings_game_key = NULL; -static uint64_t s_rankings_game_id = 0; -static ranked_player_t* s_ranked_players = NULL; -static qboolean s_server_quitting = qfalse; -static const char s_ascii_encoding[] = - "0123456789abcdef" - "ghijklmnopqrstuv" - "wxyzABCDEFGHIJKL" - "MNOPQRSTUVWXYZ[]"; - -// private functions -static void SV_RankNewGameCBF( GR_NEWGAME* gr_newgame, void* cbf_arg ); -static void SV_RankUserCBF( GR_LOGIN* gr_login, void* cbf_arg ); -static void SV_RankJoinGameCBF( GR_JOINGAME* gr_joingame, void* cbf_arg ); -static void SV_RankSendReportsCBF( GR_STATUS* gr_status, void* cbf_arg ); -static void SV_RankCleanupCBF( GR_STATUS* gr_status, void* cbf_arg ); -static void SV_RankCloseContext( ranked_player_t* ranked_player ); -static int SV_RankAsciiEncode( char* dest, const unsigned char* src, - int src_len ); -static int SV_RankAsciiDecode( unsigned char* dest, const char* src, - int src_len ); -static void SV_RankEncodeGameID( uint64_t game_id, char* result, - int len ); -static uint64_t SV_RankDecodePlayerID( const char* string ); -static void SV_RankDecodePlayerKey( const char* string, GR_PLAYER_TOKEN key ); -static char* SV_RankStatusString( GR_STATUS status ); -static void SV_RankError( const char* fmt, ... ); -static char SV_RankGameKey[64]; - -/* -================ -SV_RankBegin -================ -*/ -void SV_RankBegin( char *gamekey ) -{ - GR_INIT init; - GR_STATUS status; - - assert( s_rankings_contexts == 0 ); - assert( !s_rankings_active ); - assert( s_ranked_players == NULL ); - - if( sv_enableRankings->integer == 0 ) - { - s_rankings_active = qfalse; - if( sv_rankingsActive->integer == 1 ) - { - Cvar_Set( "sv_rankingsActive", "0" ); - } - return; - } - - // only allow official game key on pure servers - if( strcmp(gamekey, GR_GAMEKEY) == 0 ) - { -/* - if( Cvar_VariableValue("sv_pure") != 1 ) - { - Cvar_Set( "sv_enableRankings", "0" ); - return; - } -*/ - - // substitute game-specific game key - switch( (int)Cvar_VariableValue("g_gametype") ) - { - case GT_FFA: - gamekey = "Q3 Free For All"; - break; - case GT_TOURNAMENT: - gamekey = "Q3 Tournament"; - break; - case GT_TEAM: - gamekey = "Q3 Team Deathmatch"; - break; - case GT_CTF: - gamekey = "Q3 Capture the Flag"; - break; - case GT_1FCTF: - gamekey = "Q3 One Flag CTF"; - break; - case GT_OBELISK: - gamekey = "Q3 Overload"; - break; - case GT_HARVESTER: - gamekey = "Q3 Harvester"; - break; - default: - break; - } - } - s_rankings_game_key = gamekey; - - // initialize rankings - GRankLogLevel( GRLOG_OFF ); - memset(SV_RankGameKey,0,sizeof(SV_RankGameKey)); - strncpy(SV_RankGameKey,gamekey,sizeof(SV_RankGameKey)-1); - init = GRankInit( 1, SV_RankGameKey, GR_OPT_POLL, GR_OPT_END ); - s_server_context = init.context; - s_rankings_contexts++; - Com_DPrintf( "SV_RankBegin(); GR_GAMEKEY is %s\n", gamekey ); - Com_DPrintf( "SV_RankBegin(); s_rankings_contexts=%d\n",s_rankings_contexts ); - Com_DPrintf( "SV_RankBegin(); s_server_context=%d\n",init.context ); - - // new game - if(!strlen(Cvar_VariableString( "sv_leagueName" ))) - { - status = GRankNewGameAsync - ( - s_server_context, - SV_RankNewGameCBF, - NULL, - GR_OPT_LEAGUENAME, - (void*)(Cvar_VariableString( "sv_leagueName" )), - GR_OPT_END - ); - } - else - { - status = GRankNewGameAsync - ( - s_server_context, - SV_RankNewGameCBF, - NULL, - GR_OPT_END - ); - } - - if( status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankBegin: Expected GR_STATUS_PENDING, got %s", - SV_RankStatusString( status ) ); - return; - } - - // logging - if( com_developer->value ) - { - GRankLogLevel( GRLOG_TRACE ); - } - - // allocate rankings info for each player - s_ranked_players = Z_Malloc( sv_maxclients->value * - sizeof(ranked_player_t) ); - memset( (void*)s_ranked_players, 0 ,sv_maxclients->value - * sizeof(ranked_player_t)); -} - -/* -================ -SV_RankEnd -================ -*/ -void SV_RankEnd( void ) -{ - GR_STATUS status; - int i; - - Com_DPrintf( "SV_RankEnd();\n" ); - - if( !s_rankings_active ) - { - // cleanup after error during game - if( s_ranked_players != NULL ) - { - for( i = 0; i < sv_maxclients->value; i++ ) - { - if( s_ranked_players[i].context != 0 ) - { - SV_RankCloseContext( &(s_ranked_players[i]) ); - } - } - } - if( s_server_context != 0 ) - { - SV_RankCloseContext( NULL ); - } - - return; - } - - for( i = 0; i < sv_maxclients->value; i++ ) - { - if( s_ranked_players[i].grank_status == QGR_STATUS_ACTIVE ) - { - SV_RankUserLogout( i ); - Com_DPrintf( "SV_RankEnd: SV_RankUserLogout %d\n",i ); - } - } - - assert( s_server_context != 0 ); - - // send match reports, proceed to SV_RankSendReportsCBF - status = GRankSendReportsAsync - ( - s_server_context, - 0, - SV_RankSendReportsCBF, - NULL, - GR_OPT_END - ); - - if( status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankEnd: Expected GR_STATUS_PENDING, got %s", - SV_RankStatusString( status ) ); - } - - s_rankings_active = qfalse; - Cvar_Set( "sv_rankingsActive", "0" ); -} - -/* -================ -SV_RankPoll -================ -*/ -void SV_RankPoll( void ) -{ - GRankPoll(); -} - -/* -================ -SV_RankCheckInit -================ -*/ -qboolean SV_RankCheckInit( void ) -{ - return (s_rankings_contexts > 0); -} - -/* -================ -SV_RankActive -================ -*/ -qboolean SV_RankActive( void ) -{ - return s_rankings_active; -} - -/* -================= -SV_RankUserStatus -================= -*/ -grank_status_t SV_RankUserStatus( int index ) -{ - if( !s_rankings_active ) - { - return GR_STATUS_ERROR; - } - - assert( s_ranked_players != NULL ); - assert( index >= 0 ); - assert( index < sv_maxclients->value ); - - return s_ranked_players[index].grank_status; -} - -/* -================ -SV_RankUserGRank -================ -*/ -int SV_RankUserGrank( int index ) -{ - if( !s_rankings_active ) - { - return 0; - } - - assert( s_ranked_players != NULL ); - assert( index >= 0 ); - assert( index < sv_maxclients->value ); - - return s_ranked_players[index].grank; -} - -/* -================ -SV_RankUserReset -================ -*/ -void SV_RankUserReset( int index ) -{ - if( !s_rankings_active ) - { - return; - } - - assert( s_ranked_players != NULL ); - assert( index >= 0 ); - assert( index < sv_maxclients->value ); - - switch( s_ranked_players[index].grank_status ) - { - case QGR_STATUS_SPECTATOR: - case QGR_STATUS_NO_USER: - case QGR_STATUS_BAD_PASSWORD: - case QGR_STATUS_USER_EXISTS: - case QGR_STATUS_NO_MEMBERSHIP: - case QGR_STATUS_TIMEOUT: - case QGR_STATUS_ERROR: - s_ranked_players[index].grank_status = QGR_STATUS_NEW; - break; - default: - break; - } -} - -/* -================ -SV_RankUserSpectate -================ -*/ -void SV_RankUserSpectate( int index ) -{ - if( !s_rankings_active ) - { - return; - } - - assert( s_ranked_players != NULL ); - assert( index >= 0 ); - assert( index < sv_maxclients->value ); - - // GRANK_FIXME - check current status? - s_ranked_players[index].grank_status = QGR_STATUS_SPECTATOR; -} - -/* -================ -SV_RankUserCreate -================ -*/ -void SV_RankUserCreate( int index, char* username, char* password, - char* email ) -{ - GR_INIT init; - GR_STATUS status; - - assert( index >= 0 ); - assert( index < sv_maxclients->value ); - assert( username != NULL ); - assert( password != NULL ); - assert( email != NULL ); - assert( s_ranked_players ); - assert( s_ranked_players[index].grank_status != QGR_STATUS_ACTIVE ); - - Com_DPrintf( "SV_RankUserCreate( %d, %s, \"****\", %s );\n", index, - username, email ); - - if( !s_rankings_active ) - { - Com_DPrintf( "SV_RankUserCreate: Not ready to create\n" ); - s_ranked_players[index].grank_status = QGR_STATUS_ERROR; - return; - } - - if( s_ranked_players[index].grank_status == QGR_STATUS_ACTIVE ) - { - Com_DPrintf( "SV_RankUserCreate: Got Create from active player\n" ); - return; - } - - // get a separate context for the new user - init = GRankInit( 0, SV_RankGameKey, GR_OPT_POLL, GR_OPT_END ); - s_ranked_players[index].context = init.context; - s_rankings_contexts++; - Com_DPrintf( "SV_RankUserCreate(); s_rankings_contexts=%d\n",s_rankings_contexts ); - Com_DPrintf( "SV_RankUserCreate(); s_ranked_players[%d].context=%d\n",index,init.context ); - - // attempt to create a new account, proceed to SV_RankUserCBF - status = GRankUserCreateAsync - ( - s_ranked_players[index].context, - username, - password, - email, - SV_RankUserCBF, - (void*)&s_ranked_players[index], - GR_OPT_END - ); - - if( status == GR_STATUS_PENDING ) - { - s_ranked_players[index].grank_status = QGR_STATUS_PENDING; - s_ranked_players[index].final_status = QGR_STATUS_NEW; - } - else - { - SV_RankError( "SV_RankUserCreate: Expected GR_STATUS_PENDING, got %s", - SV_RankStatusString( status ) ); - } -} - -/* -================ -SV_RankUserLogin -================ -*/ -void SV_RankUserLogin( int index, char* username, char* password ) -{ - GR_INIT init; - GR_STATUS status; - - assert( index >= 0 ); - assert( index < sv_maxclients->value ); - assert( username != NULL ); - assert( password != NULL ); - assert( s_ranked_players ); - assert( s_ranked_players[index].grank_status != QGR_STATUS_ACTIVE ); - - Com_DPrintf( "SV_RankUserLogin( %d, %s, \"****\" );\n", index, username ); - - if( !s_rankings_active ) - { - Com_DPrintf( "SV_RankUserLogin: Not ready for login\n" ); - s_ranked_players[index].grank_status = QGR_STATUS_ERROR; - return; - } - - if( s_ranked_players[index].grank_status == QGR_STATUS_ACTIVE ) - { - Com_DPrintf( "SV_RankUserLogin: Got Login from active player\n" ); - return; - } - - // get a separate context for the new user - init = GRankInit( 0, SV_RankGameKey, GR_OPT_POLL, GR_OPT_END ); - s_ranked_players[index].context = init.context; - s_rankings_contexts++; - Com_DPrintf( "SV_RankUserLogin(); s_rankings_contexts=%d\n",s_rankings_contexts ); - Com_DPrintf( "SV_RankUserLogin(); s_ranked_players[%d].context=%d\n",index,init.context ); - - // login user, proceed to SV_RankUserCBF - status = GRankUserLoginAsync - ( - s_ranked_players[index].context, - username, - password, - SV_RankUserCBF, - (void*)&s_ranked_players[index], - GR_OPT_END - ); - - if( status == GR_STATUS_PENDING ) - { - s_ranked_players[index].grank_status = QGR_STATUS_PENDING; - s_ranked_players[index].final_status = QGR_STATUS_NEW; - } - else - { - SV_RankError( "SV_RankUserLogin: Expected GR_STATUS_PENDING, got %s", - SV_RankStatusString( status ) ); - } -} - -/* -=================== -SV_RankUserValidate -=================== -*/ -qboolean SV_RankUserValidate( int index, const char* player_id, const char* key, int token_len, int rank, char* name ) -{ - GR_INIT init; - GR_STATUS status; - qboolean rVal; - ranked_player_t* ranked_player; - int i; - - assert( s_ranked_players ); - assert( s_ranked_players[index].grank_status != QGR_STATUS_ACTIVE ); - - rVal = qfalse; - - if( !s_rankings_active ) - { - Com_DPrintf( "SV_RankUserValidate: Not ready to validate\n" ); - s_ranked_players[index].grank_status = QGR_STATUS_ERROR; - return rVal; - } - - ranked_player = &(s_ranked_players[index]); - - if ( (player_id != NULL) && (key != NULL)) - { - // the real player_id and key is set when SV_RankJoinGameCBF - // is called we do this so that SV_RankUserValidate - // can be shared by both server side login and client side login - - // for client side logined in players - // server is creating GR_OPT_PLAYERCONTEXT - init = GRankInit( 0, SV_RankGameKey, GR_OPT_POLL, GR_OPT_END ); - ranked_player->context = init.context; - s_rankings_contexts++; - Com_DPrintf( "SV_RankUserValidate(); s_rankings_contexts=%d\n",s_rankings_contexts ); - Com_DPrintf( "SV_RankUserValidate(); s_ranked_players[%d].context=%d\n",index,init.context ); - - // uudecode player id and player token - ranked_player->player_id = SV_RankDecodePlayerID(player_id); - Com_DPrintf( "SV_RankUserValidate(); ranked_player->player_id =%u\n", (uint32_t)ranked_player->player_id ); - SV_RankDecodePlayerKey(key, ranked_player->token); - - // save name and check for duplicates - Q_strncpyz( ranked_player->name, name, sizeof(ranked_player->name) ); - for( i = 0; i < sv_maxclients->value; i++ ) - { - if( (i != index) && (s_ranked_players[i].grank_status == QGR_STATUS_ACTIVE) && - (strcmp( s_ranked_players[i].name, name ) == 0) ) - { - Com_DPrintf( "SV_RankUserValidate: Duplicate login\n" ); - ranked_player->grank_status = QGR_STATUS_NO_USER; - ranked_player->final_status = QGR_STATUS_NEW; - ranked_player->grank = 0; - return qfalse; - } - } - - // then validate - status = GRankPlayerValidate( - s_server_context, - ranked_player->player_id, - ranked_player->token, - token_len, - GR_OPT_PLAYERCONTEXT, - ranked_player->context, - GR_OPT_END); - } - else - { - // make server side login (bots) happy - status = GR_STATUS_OK; - } - - if (status == GR_STATUS_OK) - { - ranked_player->grank_status = QGR_STATUS_ACTIVE; - ranked_player->final_status = QGR_STATUS_NEW; - ranked_player->grank = rank; - rVal = qtrue; - } - else if (status == GR_STATUS_INVALIDUSER) - { - ranked_player->grank_status = QGR_STATUS_INVALIDUSER; - ranked_player->final_status = QGR_STATUS_NEW; - ranked_player->grank = 0; - rVal = qfalse; - } - else - { - SV_RankError( "SV_RankUserValidate: Unexpected status %s", - SV_RankStatusString( status ) ); - s_ranked_players[index].grank_status = QGR_STATUS_ERROR; - ranked_player->grank = 0; - } - - return rVal; -} - -/* -================ -SV_RankUserLogout -================ -*/ -void SV_RankUserLogout( int index ) -{ - GR_STATUS status; - GR_STATUS cleanup_status; - - if( !s_rankings_active ) - { - return; - } - - assert( index >= 0 ); - assert( index < sv_maxclients->value ); - assert( s_ranked_players ); - - if( s_ranked_players[index].context == 0 ) { - return; - } - - Com_DPrintf( "SV_RankUserLogout( %d );\n", index ); - - // masqueraded player may not be active yet, if they fail validation, - // but still they have a context needs to be cleaned - // what matters is the s_ranked_players[index].context - - // send reports, proceed to SV_RankSendReportsCBF - status = GRankSendReportsAsync - ( - s_ranked_players[index].context, - 0, - SV_RankSendReportsCBF, - (void*)&s_ranked_players[index], - GR_OPT_END - ); - - if( status == GR_STATUS_PENDING ) - { - s_ranked_players[index].grank_status = QGR_STATUS_PENDING; - s_ranked_players[index].final_status = QGR_STATUS_NEW; - } - else - { - SV_RankError( "SV_RankUserLogout: Expected GR_STATUS_PENDING, got %s", - SV_RankStatusString( status ) ); - - cleanup_status = GRankCleanupAsync - ( - s_ranked_players[index].context, - 0, - SV_RankCleanupCBF, - (void*)&s_ranked_players[index], - GR_OPT_END - ); - - if( cleanup_status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankUserLogout: Expected " - "GR_STATUS_PENDING from GRankCleanupAsync, got %s", - SV_RankStatusString( cleanup_status ) ); - SV_RankCloseContext( &(s_ranked_players[index]) ); - } - } -} - -/* -================ -SV_RankReportInt -================ -*/ -void SV_RankReportInt( int index1, int index2, int key, int value, - qboolean accum ) -{ - GR_STATUS status; - GR_CONTEXT context; - uint64_t match; - uint64_t user1; - uint64_t user2; - int opt_accum; - - if( !s_rankings_active ) - { - return; - } - - assert( index1 >= -1 ); - assert( index1 < sv_maxclients->value ); - assert( index2 >= -1 ); - assert( index2 < sv_maxclients->value ); - assert( s_ranked_players ); - -// Com_DPrintf( "SV_RankReportInt( %d, %d, %d, %d, %d );\n", index1, index2, -// key, value, accum ); - - // get context, match, and player_id for player index1 - if( index1 == -1 ) - { - context = s_server_context; - match = s_server_match; - user1 = 0; - } - else - { - if( s_ranked_players[index1].grank_status != QGR_STATUS_ACTIVE ) - { - Com_DPrintf( "SV_RankReportInt: Expecting QGR_STATUS_ACTIVE" - " Got Unexpected status %d for player %d\n", - s_ranked_players[index1].grank_status, index1 ); - return; - } - - context = s_ranked_players[index1].context; - match = s_ranked_players[index1].match; - user1 = s_ranked_players[index1].player_id; - } - - // get player_id for player index2 - if( index2 == -1 ) - { - user2 = 0; - } - else - { - if( s_ranked_players[index2].grank_status != QGR_STATUS_ACTIVE ) - { - Com_DPrintf( "SV_RankReportInt: Expecting QGR_STATUS_ACTIVE" - " Got Unexpected status %d for player %d\n", - s_ranked_players[index2].grank_status, index2 ); - return; - } - - user2 = s_ranked_players[index2].player_id; - } - - opt_accum = accum ? GR_OPT_ACCUM : GR_OPT_END; - - status = GRankReportInt - ( - context, - match, - user1, - user2, - key, - value, - opt_accum, - GR_OPT_END - ); - - if( status != GR_STATUS_OK ) - { - SV_RankError( "SV_RankReportInt: Unexpected status %s", - SV_RankStatusString( status ) ); - } - - if( user2 != 0 ) - { - context = s_ranked_players[index2].context; - match = s_ranked_players[index2].match; - - status = GRankReportInt - ( - context, - match, - user1, - user2, - key, - value, - opt_accum, - GR_OPT_END - ); - - if( status != GR_STATUS_OK ) - { - SV_RankError( "SV_RankReportInt: Unexpected status %s", - SV_RankStatusString( status ) ); - } - } -} - -/* -================ -SV_RankReportStr -================ -*/ -void SV_RankReportStr( int index1, int index2, int key, char* value ) -{ - GR_STATUS status; - GR_CONTEXT context; - uint64_t match; - uint64_t user1; - uint64_t user2; - - if( !s_rankings_active ) - { - return; - } - - assert( index1 >= -1 ); - assert( index1 < sv_maxclients->value ); - assert( index2 >= -1 ); - assert( index2 < sv_maxclients->value ); - assert( s_ranked_players ); - -// Com_DPrintf( "SV_RankReportStr( %d, %d, %d, \"%s\" );\n", index1, index2, -// key, value ); - - // get context, match, and player_id for player index1 - if( index1 == -1 ) - { - context = s_server_context; - match = s_server_match; - user1 = 0; - } - else - { - if( s_ranked_players[index1].grank_status != QGR_STATUS_ACTIVE ) - { - Com_DPrintf( "SV_RankReportStr: Unexpected status %d\n", - s_ranked_players[index1].grank_status ); - return; - } - - context = s_ranked_players[index1].context; - match = s_ranked_players[index1].match; - user1 = s_ranked_players[index1].player_id; - } - - // get player_id for player index2 - if( index2 == -1 ) - { - user2 = 0; - } - else - { - if( s_ranked_players[index2].grank_status != QGR_STATUS_ACTIVE ) - { - Com_DPrintf( "SV_RankReportStr: Unexpected status %d\n", - s_ranked_players[index2].grank_status ); - return; - } - - user2 = s_ranked_players[index2].player_id; - } - - status = GRankReportStr - ( - context, - match, - user1, - user2, - key, - value, - GR_OPT_END - ); - - if( status != GR_STATUS_OK ) - { - SV_RankError( "SV_RankReportStr: Unexpected status %s", - SV_RankStatusString( status ) ); - } - - if( user2 != 0 ) - { - context = s_ranked_players[index2].context; - match = s_ranked_players[index2].match; - - status = GRankReportStr - ( - context, - match, - user1, - user2, - key, - value, - GR_OPT_END - ); - - if( status != GR_STATUS_OK ) - { - SV_RankError( "SV_RankReportInt: Unexpected status %s", - SV_RankStatusString( status ) ); - } - } -} - -/* -================ -SV_RankQuit -================ -*/ -void SV_RankQuit( void ) -{ - int i; - int j = 0; - // yuck - - while( s_rankings_contexts > 1 ) - { - assert(s_ranked_players); - if( s_ranked_players != NULL ) - { - for( i = 0; i < sv_maxclients->value; i++ ) - { - // check for players that weren't yet active in SV_RankEnd - if( s_ranked_players[i].grank_status == QGR_STATUS_ACTIVE ) - { - SV_RankUserLogout( i ); - Com_DPrintf( "SV_RankQuit: SV_RankUserLogout %d\n",i ); - } - else - { - if( s_ranked_players[i].context ) - { - GR_STATUS cleanup_status; - cleanup_status = GRankCleanupAsync - ( - s_ranked_players[i].context, - 0, - SV_RankCleanupCBF, - (void*)&(s_ranked_players[i]), - GR_OPT_END - ); - - if( cleanup_status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankQuit: Expected " - "GR_STATUS_PENDING from GRankCleanupAsync, got %s", - SV_RankStatusString( cleanup_status ) ); - } - } - } - } - } - SV_RankPoll(); - - // should've finished by now - assert( (j++) < 68 ); - } -} - -/* -============================================================================== - -Private Functions - -============================================================================== -*/ - -/* -================= -SV_RankNewGameCBF -================= -*/ -static void SV_RankNewGameCBF( GR_NEWGAME* gr_newgame, void* cbf_arg ) -{ - GR_MATCH match; - int i; - - assert( gr_newgame != NULL ); - assert( cbf_arg == NULL ); - - Com_DPrintf( "SV_RankNewGameCBF( %08X, %08X );\n", gr_newgame, cbf_arg ); - - if( gr_newgame->status == GR_STATUS_OK ) - { - char info[MAX_INFO_STRING]; - char gameid[sizeof(s_ranked_players[i].game_id) * 4 / 3 + 2]; - - // save game id - s_rankings_game_id = gr_newgame->game_id; - - // encode gameid - memset(gameid,0,sizeof(gameid)); - SV_RankEncodeGameID(s_rankings_game_id,gameid,sizeof(gameid)); - - // set CS_GRANK rankingsGameID to pass to client - memset(info,0,sizeof(info)); - Info_SetValueForKey( info, "rankingsGameKey", s_rankings_game_key ); - Info_SetValueForKey( info, "rankingsGameID", gameid ); - SV_SetConfigstring( CS_GRANK, info ); - - // initialize client status - for( i = 0; i < sv_maxclients->value; i++ ) - s_ranked_players[i].grank_status = QGR_STATUS_NEW; - - // start new match - match = GRankStartMatch( s_server_context ); - s_server_match = match.match; - - // ready to go - s_rankings_active = qtrue; - Cvar_Set( "sv_rankingsActive", "1" ); - - } - else if( gr_newgame->status == GR_STATUS_BADLEAGUE ) - { - SV_RankError( "SV_RankNewGameCBF: Invalid League name\n" ); - } - else - { - //GRank handle new game failure - // force SV_RankEnd() to run - //SV_RankEnd(); - SV_RankError( "SV_RankNewGameCBF: Unexpected status %s", - SV_RankStatusString( gr_newgame->status ) ); - } -} - -/* -================ -SV_RankUserCBF -================ -*/ -static void SV_RankUserCBF( GR_LOGIN* gr_login, void* cbf_arg ) -{ - ranked_player_t* ranked_player; - GR_STATUS join_status; - GR_STATUS cleanup_status; - - assert( gr_login != NULL ); - assert( cbf_arg != NULL ); - - Com_DPrintf( "SV_RankUserCBF( %08X, %08X );\n", gr_login, cbf_arg ); - - ranked_player = (ranked_player_t*)cbf_arg; - assert(ranked_player); - assert( ranked_player->context ); - - switch( gr_login->status ) - { - case GR_STATUS_OK: - // attempt to join the game, proceed to SV_RankJoinGameCBF - join_status = GRankJoinGameAsync - ( - ranked_player->context, - s_rankings_game_id, - SV_RankJoinGameCBF, - cbf_arg, - GR_OPT_END - ); - - if( join_status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankUserCBF: Expected GR_STATUS_PENDING " - "from GRankJoinGameAsync, got %s", - SV_RankStatusString( join_status ) ); - } - break; - case GR_STATUS_NOUSER: - Com_DPrintf( "SV_RankUserCBF: Got status %s\n", - SV_RankStatusString( gr_login->status ) ); - ranked_player->final_status = QGR_STATUS_NO_USER; - break; - case GR_STATUS_BADPASSWORD: - Com_DPrintf( "SV_RankUserCBF: Got status %s\n", - SV_RankStatusString( gr_login->status ) ); - ranked_player->final_status = QGR_STATUS_BAD_PASSWORD; - break; - case GR_STATUS_TIMEOUT: - Com_DPrintf( "SV_RankUserCBF: Got status %s\n", - SV_RankStatusString( gr_login->status ) ); - ranked_player->final_status = QGR_STATUS_TIMEOUT; - break; - default: - Com_DPrintf( "SV_RankUserCBF: Unexpected status %s\n", - SV_RankStatusString( gr_login->status ) ); - ranked_player->final_status = QGR_STATUS_ERROR; - break; - } - - if( ranked_player->final_status != QGR_STATUS_NEW ) - { - // login or create failed, so clean up before the next attempt - cleanup_status = GRankCleanupAsync - ( - ranked_player->context, - 0, - SV_RankCleanupCBF, - (void*)ranked_player, - GR_OPT_END - ); - - if( cleanup_status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankUserCBF: Expected GR_STATUS_PENDING " - "from GRankCleanupAsync, got %s", - SV_RankStatusString( cleanup_status ) ); - SV_RankCloseContext( ranked_player ); - } - } -} - -/* -================ -SV_RankJoinGameCBF -================ -*/ -static void SV_RankJoinGameCBF( GR_JOINGAME* gr_joingame, void* cbf_arg ) -{ - ranked_player_t* ranked_player; - GR_MATCH match; - GR_STATUS cleanup_status; - - assert( gr_joingame != NULL ); - assert( cbf_arg != NULL ); - - Com_DPrintf( "SV_RankJoinGameCBF( %08X, %08X );\n", gr_joingame, cbf_arg ); - - ranked_player = (ranked_player_t*)cbf_arg; - - assert( ranked_player ); - assert( ranked_player->context != 0 ); - - if( gr_joingame->status == GR_STATUS_OK ) - { - int i; - // save user id - ranked_player->player_id = gr_joingame->player_id; - memcpy(ranked_player->token,gr_joingame->token, - sizeof(GR_PLAYER_TOKEN)) ; - match = GRankStartMatch( ranked_player->context ); - ranked_player->match = match.match; - ranked_player->grank = gr_joingame->rank; - - // find the index and call SV_RankUserValidate - for (i=0;i<sv_maxclients->value;i++) - if ( ranked_player == &s_ranked_players[i] ) - SV_RankUserValidate(i,NULL,NULL,0, gr_joingame->rank,ranked_player->name); - } - else - { - //GRand handle join game failure - SV_RankError( "SV_RankJoinGameCBF: Unexpected status %s", - SV_RankStatusString( gr_joingame->status ) ); - - cleanup_status = GRankCleanupAsync - ( - ranked_player->context, - 0, - SV_RankCleanupCBF, - cbf_arg, - GR_OPT_END - ); - - if( cleanup_status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankJoinGameCBF: Expected " - "GR_STATUS_PENDING from GRankCleanupAsync, got %s", - SV_RankStatusString( cleanup_status ) ); - SV_RankCloseContext( ranked_player ); - } - } -} - -/* -================ -SV_RankSendReportsCBF -================ -*/ -static void SV_RankSendReportsCBF( GR_STATUS* status, void* cbf_arg ) -{ - ranked_player_t* ranked_player; - GR_CONTEXT context; - GR_STATUS cleanup_status; - - assert( status != NULL ); - // NULL cbf_arg means server is sending match reports - - Com_DPrintf( "SV_RankSendReportsCBF( %08X, %08X );\n", status, cbf_arg ); - - ranked_player = (ranked_player_t*)cbf_arg; - if( ranked_player == NULL ) - { - Com_DPrintf( "SV_RankSendReportsCBF: server\n" ); - context = s_server_context; - } - else - { - Com_DPrintf( "SV_RankSendReportsCBF: player\n" ); - context = ranked_player->context; - } - - //assert( context != 0 ); - if( *status != GR_STATUS_OK ) - { - SV_RankError( "SV_RankSendReportsCBF: Unexpected status %s", - SV_RankStatusString( *status ) ); - } - - if( context == 0 ) - { - Com_DPrintf( "SV_RankSendReportsCBF: WARNING: context == 0" ); - SV_RankCloseContext( ranked_player ); - } - else - { - cleanup_status = GRankCleanupAsync - ( - context, - 0, - SV_RankCleanupCBF, - cbf_arg, - GR_OPT_END - ); - - if( cleanup_status != GR_STATUS_PENDING ) - { - SV_RankError( "SV_RankSendReportsCBF: Expected " - "GR_STATUS_PENDING from GRankCleanupAsync, got %s", - SV_RankStatusString( cleanup_status ) ); - SV_RankCloseContext( ranked_player ); - } - } -} - -/* -================ -SV_RankCleanupCBF -================ -*/ -static void SV_RankCleanupCBF( GR_STATUS* status, void* cbf_arg ) -{ - ranked_player_t* ranked_player; - ranked_player = (ranked_player_t*)cbf_arg; - - assert( status != NULL ); - // NULL cbf_arg means server is cleaning up - - Com_DPrintf( "SV_RankCleanupCBF( %08X, %08X );\n", status, cbf_arg ); - - if( *status != GR_STATUS_OK ) - { - SV_RankError( "SV_RankCleanupCBF: Unexpected status %s", - SV_RankStatusString( *status ) ); - } - - SV_RankCloseContext( ranked_player ); -} - -/* -================ -SV_RankCloseContext -================ -*/ -static void SV_RankCloseContext( ranked_player_t* ranked_player ) -{ - if( ranked_player == NULL ) - { - // server cleanup - if( s_server_context == 0 ) - { - return; - } - s_server_context = 0; - s_server_match = 0; - } - else - { - // player cleanup - if( s_ranked_players == NULL ) - { - return; - } - if( ranked_player->context == 0 ) - { - return; - } - ranked_player->context = 0; - ranked_player->match = 0; - ranked_player->player_id = 0; - memset( ranked_player->token, 0, sizeof(GR_PLAYER_TOKEN) ); - ranked_player->grank_status = ranked_player->final_status; - ranked_player->final_status = QGR_STATUS_NEW; - ranked_player->name[0] = '\0'; - } - - assert( s_rankings_contexts > 0 ); - s_rankings_contexts--; - Com_DPrintf( "SV_RankCloseContext: s_rankings_contexts = %d\n", - s_rankings_contexts ); - - if( s_rankings_contexts == 0 ) - { - GRankLogLevel( GRLOG_OFF ); - - if( s_ranked_players != NULL ) - { - Z_Free( s_ranked_players ); - s_ranked_players = NULL; - } - - s_rankings_active = qfalse; - Cvar_Set( "sv_rankingsActive", "0" ); - } -} - -/* -================ -SV_RankAsciiEncode - -Encodes src_len bytes of binary data from the src buffer as ASCII text, -using 6 bits per character. The result string is null-terminated and -stored in the dest buffer. - -The dest buffer must be at least (src_len * 4) / 3 + 2 bytes in length. - -Returns the length of the result string, not including the null. -================ -*/ -static int SV_RankAsciiEncode( char* dest, const unsigned char* src, - int src_len ) -{ - unsigned char bin[3]; - unsigned char txt[4]; - int dest_len = 0; - int i; - int j; - int num_chars; - - assert( dest != NULL ); - assert( src != NULL ); - - for( i = 0; i < src_len; i += 3 ) - { - // read three bytes of input - for( j = 0; j < 3; j++ ) - { - bin[j] = (i + j < src_len) ? src[i + j] : 0; - } - - // get four 6-bit values from three bytes - txt[0] = bin[0] >> 2; - txt[1] = ((bin[0] << 4) | (bin[1] >> 4)) & 63; - txt[2] = ((bin[1] << 2) | (bin[2] >> 6)) & 63; - txt[3] = bin[2] & 63; - - // store ASCII encoding of 6-bit values - num_chars = (i + 2 < src_len) ? 4 : ((src_len - i) * 4) / 3 + 1; - for( j = 0; j < num_chars; j++ ) - { - dest[dest_len++] = s_ascii_encoding[txt[j]]; - } - } - - dest[dest_len] = '\0'; - - return dest_len; -} - -/* -================ -SV_RankAsciiDecode - -Decodes src_len characters of ASCII text from the src buffer, stores -the binary result in the dest buffer. - -The dest buffer must be at least (src_len * 3) / 4 bytes in length. - -Returns the length of the binary result, or zero for invalid input. -================ -*/ -static int SV_RankAsciiDecode( unsigned char* dest, const char* src, - int src_len ) -{ - static unsigned char s_inverse_encoding[256]; - static char s_init = 0; - - unsigned char bin[3]; - unsigned char txt[4]; - int dest_len = 0; - int i; - int j; - int num_bytes; - - assert( dest != NULL ); - assert( src != NULL ); - - if( !s_init ) - { - // initialize lookup table for decoding - memset( s_inverse_encoding, 255, sizeof(s_inverse_encoding) ); - for( i = 0; i < 64; i++ ) - { - s_inverse_encoding[s_ascii_encoding[i]] = i; - } - s_init = 1; - } - - for( i = 0; i < src_len; i += 4 ) - { - // read four characters of input, decode them to 6-bit values - for( j = 0; j < 4; j++ ) - { - txt[j] = (i + j < src_len) ? s_inverse_encoding[src[i + j]] : 0; - if (txt[j] == 255) - { - return 0; // invalid input character - } - } - - // get three bytes from four 6-bit values - bin[0] = (txt[0] << 2) | (txt[1] >> 4); - bin[1] = (txt[1] << 4) | (txt[2] >> 2); - bin[2] = (txt[2] << 6) | txt[3]; - - // store binary data - num_bytes = (i + 3 < src_len) ? 3 : ((src_len - i) * 3) / 4; - for( j = 0; j < num_bytes; j++ ) - { - dest[dest_len++] = bin[j]; - } - } - - return dest_len; -} - -/* -================ -SV_RankEncodeGameID -================ -*/ -static void SV_RankEncodeGameID( uint64_t game_id, char* result, - int len ) -{ - assert( result != NULL ); - - if( len < ( ( sizeof(game_id) * 4) / 3 + 2) ) - { - Com_DPrintf( "SV_RankEncodeGameID: result buffer too small\n" ); - result[0] = '\0'; - } - else - { - qint64 gameid = LittleLong64(*(qint64*)&game_id); - SV_RankAsciiEncode( result, (unsigned char*)&gameid, - sizeof(qint64) ); - } -} - -/* -================ -SV_RankDecodePlayerID -================ -*/ -static uint64_t SV_RankDecodePlayerID( const char* string ) -{ - unsigned char buffer[9]; - int len; - qint64 player_id; - - assert( string != NULL ); - - len = strlen (string) ; - Com_DPrintf( "SV_RankDecodePlayerID: string length %d\n",len ); - SV_RankAsciiDecode( buffer, string, len ); - player_id = LittleLong64(*(qint64*)buffer); - return *(uint64_t*)&player_id; -} - -/* -================ -SV_RankDecodePlayerKey -================ -*/ -static void SV_RankDecodePlayerKey( const char* string, GR_PLAYER_TOKEN key ) -{ - unsigned char buffer[1400]; - int len; - assert( string != NULL ); - - len = strlen (string) ; - Com_DPrintf( "SV_RankDecodePlayerKey: string length %d\n",len ); - - memset(key,0,sizeof(GR_PLAYER_TOKEN)); - memset(buffer,0,sizeof(buffer)); - memcpy( key, buffer, SV_RankAsciiDecode( buffer, string, len ) ); -} - -/* -================ -SV_RankStatusString -================ -*/ -static char* SV_RankStatusString( GR_STATUS status ) -{ - switch( status ) - { - case GR_STATUS_OK: return "GR_STATUS_OK"; - case GR_STATUS_ERROR: return "GR_STATUS_ERROR"; - case GR_STATUS_BADPARAMS: return "GR_STATUS_BADPARAMS"; - case GR_STATUS_NETWORK: return "GR_STATUS_NETWORK"; - case GR_STATUS_NOUSER: return "GR_STATUS_NOUSER"; - case GR_STATUS_BADPASSWORD: return "GR_STATUS_BADPASSWORD"; - case GR_STATUS_BADGAME: return "GR_STATUS_BADGAME"; - case GR_STATUS_PENDING: return "GR_STATUS_PENDING"; - case GR_STATUS_BADDOMAIN: return "GR_STATUS_BADDOMAIN"; - case GR_STATUS_DOMAINLOCK: return "GR_STATUS_DOMAINLOCK"; - case GR_STATUS_TIMEOUT: return "GR_STATUS_TIMEOUT"; - case GR_STATUS_INVALIDUSER: return "GR_STATUS_INVALIDUSER"; - case GR_STATUS_INVALIDCONTEXT: return "GR_STATUS_INVALIDCONTEXT"; - default: return "(UNKNOWN)"; - } -} - -/* -================ -SV_RankError -================ -*/ -static void SV_RankError( const char* fmt, ... ) -{ - va_list arg_ptr; - char text[1024]; - - va_start( arg_ptr, fmt ); - Q_vsnprintf(text, sizeof(text), fmt, arg_ptr ); - va_end( arg_ptr ); - - Com_DPrintf( "****************************************\n" ); - Com_DPrintf( "SV_RankError: %s\n", text ); - Com_DPrintf( "****************************************\n" ); - - s_rankings_active = qfalse; - Cvar_Set( "sv_rankingsActive", "0" ); - // FIXME - attempt clean shutdown? -} - |