2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2010-05-29 07:25:38 +00:00
# include <base/system.h>
2011-02-27 14:03:57 +00:00
# include <engine/config.h>
# include <engine/console.h>
# include <engine/engine.h>
# include <engine/map.h>
# include <engine/masterserver.h>
# include <engine/server.h>
# include <engine/storage.h>
2010-05-29 07:25:38 +00:00
# include <engine/shared/compression.h>
# include <engine/shared/config.h>
# include <engine/shared/datafile.h>
2010-09-12 10:16:51 +00:00
# include <engine/shared/demo.h>
2011-03-31 13:13:49 +00:00
# include <engine/shared/mapchecker.h>
2011-02-27 14:03:57 +00:00
# include <engine/shared/network.h>
# include <engine/shared/packer.h>
# include <engine/shared/protocol.h>
# include <engine/shared/snapshot.h>
2010-05-29 07:25:38 +00:00
# include <mastersrv/mastersrv.h>
# include "register.h"
# include "server.h"
2010-10-10 13:36:58 +00:00
# if defined(CONF_FAMILY_WINDOWS)
2011-02-27 14:03:57 +00:00
# define _WIN32_WINNT 0x0501
# define WIN32_LEAN_AND_MEAN
2010-05-29 07:25:38 +00:00
# include <windows.h>
# endif
2011-04-09 06:41:31 +00:00
# include <string.h>
# include <banmaster/banmaster.h>
# include "../shared/linereader.h"
# include <vector>
2010-05-29 07:25:38 +00:00
2011-02-07 06:25:38 +00:00
static const char SERVER_BANMASTERFILE [ ] = " banmasters.cfg " ;
2010-05-29 07:25:38 +00:00
static const char * StrLtrim ( const char * pStr )
{
2010-08-12 14:12:25 +00:00
while ( * pStr & & * pStr > = 0 & & * pStr < = 32 )
2010-05-29 07:25:38 +00:00
pStr + + ;
return pStr ;
}
static void StrRtrim ( char * pStr )
{
int i = str_length ( pStr ) ;
while ( i > = 0 )
{
2010-08-12 14:12:25 +00:00
if ( pStr [ i ] < 0 | | pStr [ i ] > 32 )
2010-05-29 07:25:38 +00:00
break ;
pStr [ i ] = 0 ;
i - - ;
}
}
static int StrAllnum ( const char * pStr )
{
while ( * pStr )
{
if ( ! ( * pStr > = ' 0 ' & & * pStr < = ' 9 ' ) )
return 0 ;
pStr + + ;
}
return 1 ;
}
CSnapIDPool : : CSnapIDPool ( )
{
Reset ( ) ;
}
void CSnapIDPool : : Reset ( )
{
for ( int i = 0 ; i < MAX_IDS ; i + + )
{
m_aIDs [ i ] . m_Next = i + 1 ;
m_aIDs [ i ] . m_State = 0 ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
m_aIDs [ MAX_IDS - 1 ] . m_Next = - 1 ;
m_FirstFree = 0 ;
m_FirstTimed = - 1 ;
m_LastTimed = - 1 ;
m_Usage = 0 ;
m_InUsage = 0 ;
}
void CSnapIDPool : : RemoveFirstTimeout ( )
{
int NextTimed = m_aIDs [ m_FirstTimed ] . m_Next ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// add it to the free list
m_aIDs [ m_FirstTimed ] . m_Next = m_FirstFree ;
m_aIDs [ m_FirstTimed ] . m_State = 0 ;
m_FirstFree = m_FirstTimed ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// remove it from the timed list
m_FirstTimed = NextTimed ;
if ( m_FirstTimed = = - 1 )
m_LastTimed = - 1 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
m_Usage - - ;
}
int CSnapIDPool : : NewID ( )
{
int64 Now = time_get ( ) ;
// process timed ids
while ( m_FirstTimed ! = - 1 & & m_aIDs [ m_FirstTimed ] . m_Timeout < Now )
RemoveFirstTimeout ( ) ;
2010-10-10 13:36:58 +00:00
2011-02-12 10:40:36 +00:00
int ID = m_FirstFree ;
dbg_assert ( ID ! = - 1 , " id error " ) ;
if ( ID = = - 1 )
return ID ;
2010-05-29 07:25:38 +00:00
m_FirstFree = m_aIDs [ m_FirstFree ] . m_Next ;
2011-02-12 10:40:36 +00:00
m_aIDs [ ID ] . m_State = 1 ;
2010-05-29 07:25:38 +00:00
m_Usage + + ;
m_InUsage + + ;
2011-02-12 10:40:36 +00:00
return ID ;
2010-05-29 07:25:38 +00:00
}
void CSnapIDPool : : TimeoutIDs ( )
{
// process timed ids
while ( m_FirstTimed ! = - 1 )
RemoveFirstTimeout ( ) ;
}
2011-02-12 10:40:36 +00:00
void CSnapIDPool : : FreeID ( int ID )
2010-05-29 07:25:38 +00:00
{
2011-02-12 10:40:36 +00:00
if ( ID < 0 )
2010-12-16 02:29:08 +00:00
return ;
2011-02-12 10:40:36 +00:00
dbg_assert ( m_aIDs [ ID ] . m_State = = 1 , " id is not alloced " ) ;
2010-05-29 07:25:38 +00:00
m_InUsage - - ;
2011-02-12 10:40:36 +00:00
m_aIDs [ ID ] . m_State = 2 ;
m_aIDs [ ID ] . m_Timeout = time_get ( ) + time_freq ( ) * 5 ;
m_aIDs [ ID ] . m_Next = - 1 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( m_LastTimed ! = - 1 )
{
2011-02-12 10:40:36 +00:00
m_aIDs [ m_LastTimed ] . m_Next = ID ;
m_LastTimed = ID ;
2010-05-29 07:25:38 +00:00
}
else
{
2011-02-12 10:40:36 +00:00
m_FirstTimed = ID ;
m_LastTimed = ID ;
2010-05-29 07:25:38 +00:00
}
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
void CServer : : CClient : : Reset ( )
{
// reset input
for ( int i = 0 ; i < 200 ; i + + )
m_aInputs [ i ] . m_GameTick = - 1 ;
m_CurrentInput = 0 ;
mem_zero ( & m_LatestInput , sizeof ( m_LatestInput ) ) ;
m_Snapshots . PurgeAll ( ) ;
m_LastAckedSnapshot = - 1 ;
m_LastInputTick = - 1 ;
m_SnapRate = CClient : : SNAPRATE_INIT ;
m_Score = 0 ;
}
CServer : : CServer ( ) : m_DemoRecorder ( & m_SnapshotDelta )
{
m_TickSpeed = SERVER_TICK_SPEED ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
m_pGameServer = 0 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
m_CurrentGameTick = 0 ;
m_RunServer = 1 ;
m_pCurrentMapData = 0 ;
m_CurrentMapSize = 0 ;
2010-10-10 13:36:58 +00:00
2010-05-30 12:01:11 +00:00
m_MapReload = 0 ;
2010-05-29 07:25:38 +00:00
2011-02-12 10:40:36 +00:00
m_RconClientID = - 1 ;
2010-09-12 11:52:25 +00:00
2010-05-29 07:25:38 +00:00
Init ( ) ;
}
int CServer : : TrySetClientName ( int ClientID , const char * pName )
{
char aTrimmedName [ 64 ] ;
// trim the name
str_copy ( aTrimmedName , StrLtrim ( pName ) , sizeof ( aTrimmedName ) ) ;
StrRtrim ( aTrimmedName ) ;
2011-03-15 10:23:49 +00:00
// check if new and old name are the same
2011-04-06 15:53:05 +00:00
if ( m_aClients [ ClientID ] . m_aName [ 0 ] & & str_comp ( m_aClients [ ClientID ] . m_aName , aTrimmedName ) = = 0 )
2011-03-15 10:23:49 +00:00
return 0 ;
2011-01-06 03:46:10 +00:00
char aBuf [ 256 ] ;
2010-08-17 22:06:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " '%s' -> '%s' " , pName , aTrimmedName ) ;
2010-08-17 22:06:00 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " server " , aBuf ) ;
2010-05-29 07:25:38 +00:00
pName = aTrimmedName ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// check for empty names
if ( ! pName [ 0 ] )
return - 1 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// make sure that two clients doesn't have the same name
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
if ( i ! = ClientID & & m_aClients [ i ] . m_State > = CClient : : STATE_READY )
{
if ( str_comp ( pName , m_aClients [ i ] . m_aName ) = = 0 )
return - 1 ;
}
// set the client name
str_copy ( m_aClients [ ClientID ] . m_aName , pName , MAX_NAME_LENGTH ) ;
return 0 ;
}
void CServer : : SetClientName ( int ClientID , const char * pName )
{
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State < CClient : : STATE_READY )
return ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( ! pName )
return ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
char aNameTry [ MAX_NAME_LENGTH ] ;
str_copy ( aNameTry , pName , MAX_NAME_LENGTH ) ;
if ( TrySetClientName ( ClientID , aNameTry ) )
{
// auto rename
for ( int i = 1 ; ; i + + )
{
str_format ( aNameTry , MAX_NAME_LENGTH , " (%d)%s " , i , pName ) ;
if ( TrySetClientName ( ClientID , aNameTry ) = = 0 )
break ;
}
}
}
2011-03-15 10:23:49 +00:00
void CServer : : SetClientClan ( int ClientID , const char * pClan )
{
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State < CClient : : STATE_READY | | ! pClan )
return ;
str_copy ( m_aClients [ ClientID ] . m_aClan , pClan , MAX_CLAN_LENGTH ) ;
}
void CServer : : SetClientCountry ( int ClientID , int Country )
2010-05-29 07:25:38 +00:00
{
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State < CClient : : STATE_READY )
return ;
2011-03-15 10:23:49 +00:00
m_aClients [ ClientID ] . m_Country = Country ;
2010-05-29 07:25:38 +00:00
}
void CServer : : SetClientScore ( int ClientID , int Score )
{
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State < CClient : : STATE_READY )
return ;
m_aClients [ ClientID ] . m_Score = Score ;
}
void CServer : : Kick ( int ClientID , const char * pReason )
{
2010-09-12 10:07:10 +00:00
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State = = CClient : : STATE_EMPTY )
2010-09-12 11:52:25 +00:00
{
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " invalid client id to kick " ) ;
2010-05-29 07:25:38 +00:00
return ;
2010-09-12 11:52:25 +00:00
}
2011-02-12 10:40:36 +00:00
else if ( m_RconClientID = = ClientID )
2010-09-12 11:52:25 +00:00
{
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " you can't kick yourself " ) ;
return ;
2010-09-12 10:07:10 +00:00
}
2010-05-29 07:25:38 +00:00
2010-09-12 10:07:10 +00:00
m_NetServer . Drop ( ClientID , pReason ) ;
2010-05-29 07:25:38 +00:00
}
/*int CServer::Tick()
{
return m_CurrentGameTick ;
} */
int64 CServer : : TickStartTime ( int Tick )
{
return m_GameStartTime + ( time_freq ( ) * Tick ) / SERVER_TICK_SPEED ;
}
/*int CServer::TickSpeed()
{
return SERVER_TICK_SPEED ;
} */
int CServer : : Init ( )
{
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
m_aClients [ i ] . m_State = CClient : : STATE_EMPTY ;
m_aClients [ i ] . m_aName [ 0 ] = 0 ;
m_aClients [ i ] . m_aClan [ 0 ] = 0 ;
2011-03-15 10:23:49 +00:00
m_aClients [ i ] . m_Country = - 1 ;
2010-05-29 07:25:38 +00:00
m_aClients [ i ] . m_Snapshots . Init ( ) ;
}
m_CurrentGameTick = 0 ;
2010-12-06 02:27:35 +00:00
m_AnnouncementLastLine = 0 ;
2011-04-09 06:41:31 +00:00
memset ( m_aPrevStates , CClient : : STATE_EMPTY , MAX_CLIENTS * sizeof ( int ) ) ;
2010-05-29 07:25:38 +00:00
return 0 ;
}
2010-10-10 13:36:58 +00:00
int CServer : : IsAuthed ( int ClientID )
2010-06-02 02:42:17 +00:00
{
2010-10-10 13:36:58 +00:00
return m_aClients [ ClientID ] . m_Authed ;
2010-06-02 02:42:17 +00:00
}
2010-05-29 07:25:38 +00:00
int CServer : : GetClientInfo ( int ClientID , CClientInfo * pInfo )
{
dbg_assert ( ClientID > = 0 & & ClientID < MAX_CLIENTS , " client_id is not valid " ) ;
dbg_assert ( pInfo ! = 0 , " info can not be null " ) ;
if ( m_aClients [ ClientID ] . m_State = = CClient : : STATE_INGAME )
{
pInfo - > m_pName = m_aClients [ ClientID ] . m_aName ;
pInfo - > m_Latency = m_aClients [ ClientID ] . m_Latency ;
return 1 ;
}
return 0 ;
}
2011-03-28 18:11:28 +00:00
void CServer : : GetClientAddr ( int ClientID , char * pAddrStr , int Size )
2010-05-29 07:25:38 +00:00
{
if ( ClientID > = 0 & & ClientID < MAX_CLIENTS & & m_aClients [ ClientID ] . m_State = = CClient : : STATE_INGAME )
{
NETADDR Addr = m_NetServer . ClientAddr ( ClientID ) ;
2011-03-28 18:11:28 +00:00
Addr . port = 0 ;
net_addr_str ( & Addr , pAddrStr , Size ) ;
2010-05-29 07:25:38 +00:00
}
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
2011-02-12 10:40:36 +00:00
int * CServer : : LatestInput ( int ClientID , int * size )
2010-05-29 07:25:38 +00:00
{
2011-02-12 10:40:36 +00:00
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State < CServer : : CClient : : STATE_READY )
2010-05-29 07:25:38 +00:00
return 0 ;
2011-02-12 10:40:36 +00:00
return m_aClients [ ClientID ] . m_LatestInput . m_aData ;
2010-05-29 07:25:38 +00:00
}
2011-02-12 10:40:36 +00:00
const char * CServer : : ClientName ( int ClientID )
2010-05-29 07:25:38 +00:00
{
2011-02-12 10:40:36 +00:00
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State = = CServer : : CClient : : STATE_EMPTY )
2010-05-29 07:25:38 +00:00
return " (invalid client) " ;
2011-03-15 10:23:49 +00:00
if ( m_aClients [ ClientID ] . m_State = = CServer : : CClient : : STATE_INGAME )
return m_aClients [ ClientID ] . m_aName ;
else
2010-09-25 18:24:11 +00:00
return " (connecting client) " ;
2011-03-15 10:23:49 +00:00
}
const char * CServer : : ClientClan ( int ClientID )
{
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State = = CServer : : CClient : : STATE_EMPTY )
return " " ;
if ( m_aClients [ ClientID ] . m_State = = CServer : : CClient : : STATE_INGAME )
return m_aClients [ ClientID ] . m_aClan ;
else
return " " ;
}
int CServer : : ClientCountry ( int ClientID )
{
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State = = CServer : : CClient : : STATE_EMPTY )
return - 1 ;
if ( m_aClients [ ClientID ] . m_State = = CServer : : CClient : : STATE_INGAME )
return m_aClients [ ClientID ] . m_Country ;
else
return - 1 ;
}
2010-05-29 07:25:38 +00:00
bool CServer : : ClientIngame ( int ClientID )
{
return ClientID > = 0 & & ClientID < MAX_CLIENTS & & m_aClients [ ClientID ] . m_State = = CServer : : CClient : : STATE_INGAME ;
}
2011-02-12 10:40:36 +00:00
int CServer : : SendMsg ( CMsgPacker * pMsg , int Flags , int ClientID )
2010-05-29 07:25:38 +00:00
{
2011-02-12 10:40:36 +00:00
return SendMsgEx ( pMsg , Flags , ClientID , false ) ;
2010-05-29 07:25:38 +00:00
}
int CServer : : SendMsgEx ( CMsgPacker * pMsg , int Flags , int ClientID , bool System )
{
CNetChunk Packet ;
if ( ! pMsg )
return - 1 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
mem_zero ( & Packet , sizeof ( CNetChunk ) ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
Packet . m_ClientID = ClientID ;
Packet . m_pData = pMsg - > Data ( ) ;
Packet . m_DataSize = pMsg - > Size ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// HACK: modify the message id in the packet and store the system flag
* ( ( unsigned char * ) Packet . m_pData ) < < = 1 ;
if ( System )
* ( ( unsigned char * ) Packet . m_pData ) | = 1 ;
if ( Flags & MSGFLAG_VITAL )
Packet . m_Flags | = NETSENDFLAG_VITAL ;
if ( Flags & MSGFLAG_FLUSH )
Packet . m_Flags | = NETSENDFLAG_FLUSH ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// write message to demo recorder
if ( ! ( Flags & MSGFLAG_NORECORD ) )
m_DemoRecorder . RecordMessage ( pMsg - > Data ( ) , pMsg - > Size ( ) ) ;
if ( ! ( Flags & MSGFLAG_NOSEND ) )
{
if ( ClientID = = - 1 )
{
// broadcast
int i ;
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
if ( m_aClients [ i ] . m_State = = CClient : : STATE_INGAME )
{
Packet . m_ClientID = i ;
m_NetServer . Send ( & Packet ) ;
}
}
else
m_NetServer . Send ( & Packet ) ;
}
return 0 ;
}
void CServer : : DoSnapshot ( )
{
GameServer ( ) - > OnPreSnap ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// create snapshot for demo recording
if ( m_DemoRecorder . IsRecording ( ) )
{
char aData [ CSnapshot : : MAX_SIZE ] ;
int SnapshotSize ;
// build snap and possibly add some messages
m_SnapshotBuilder . Init ( ) ;
GameServer ( ) - > OnSnap ( - 1 ) ;
SnapshotSize = m_SnapshotBuilder . Finish ( aData ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// write snapshot
m_DemoRecorder . RecordSnapshot ( Tick ( ) , aData , SnapshotSize ) ;
}
// create snapshots for all clients
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
// client must be ingame to recive snapshots
if ( m_aClients [ i ] . m_State ! = CClient : : STATE_INGAME )
continue ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// this client is trying to recover, don't spam snapshots
if ( m_aClients [ i ] . m_SnapRate = = CClient : : SNAPRATE_RECOVER & & ( Tick ( ) % 50 ) ! = 0 )
continue ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// this client is trying to recover, don't spam snapshots
if ( m_aClients [ i ] . m_SnapRate = = CClient : : SNAPRATE_INIT & & ( Tick ( ) % 10 ) ! = 0 )
continue ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
{
char aData [ CSnapshot : : MAX_SIZE ] ;
2010-06-09 16:24:38 +00:00
CSnapshot * pData = ( CSnapshot * ) aData ; // Fix compiler warning for strict-aliasing
2010-05-29 07:25:38 +00:00
char aDeltaData [ CSnapshot : : MAX_SIZE ] ;
char aCompData [ CSnapshot : : MAX_SIZE ] ;
int SnapshotSize ;
int Crc ;
static CSnapshot EmptySnap ;
CSnapshot * pDeltashot = & EmptySnap ;
int DeltashotSize ;
int DeltaTick = - 1 ;
int DeltaSize ;
m_SnapshotBuilder . Init ( ) ;
GameServer ( ) - > OnSnap ( i ) ;
// finish snapshot
2010-06-09 16:24:38 +00:00
SnapshotSize = m_SnapshotBuilder . Finish ( pData ) ;
Crc = pData - > Crc ( ) ;
2010-05-29 07:25:38 +00:00
// remove old snapshos
// keep 3 seconds worth of snapshots
m_aClients [ i ] . m_Snapshots . PurgeUntil ( m_CurrentGameTick - SERVER_TICK_SPEED * 3 ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// save it the snapshot
2010-06-09 16:24:38 +00:00
m_aClients [ i ] . m_Snapshots . Add ( m_CurrentGameTick , time_get ( ) , SnapshotSize , pData , 0 ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// find snapshot that we can preform delta against
EmptySnap . Clear ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
{
DeltashotSize = m_aClients [ i ] . m_Snapshots . Get ( m_aClients [ i ] . m_LastAckedSnapshot , 0 , & pDeltashot , 0 ) ;
if ( DeltashotSize > = 0 )
DeltaTick = m_aClients [ i ] . m_LastAckedSnapshot ;
else
{
// no acked package found, force client to recover rate
if ( m_aClients [ i ] . m_SnapRate = = CClient : : SNAPRATE_FULL )
m_aClients [ i ] . m_SnapRate = CClient : : SNAPRATE_RECOVER ;
}
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// create delta
2010-06-09 16:24:38 +00:00
DeltaSize = m_SnapshotDelta . CreateDelta ( pDeltashot , pData , aDeltaData ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( DeltaSize )
{
// compress it
int SnapshotSize ;
const int MaxSize = MAX_SNAPSHOT_PACKSIZE ;
int NumPackets ;
SnapshotSize = CVariableInt : : Compress ( aDeltaData , DeltaSize , aCompData ) ;
NumPackets = ( SnapshotSize + MaxSize - 1 ) / MaxSize ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
for ( int n = 0 , Left = SnapshotSize ; Left ; n + + )
{
int Chunk = Left < MaxSize ? Left : MaxSize ;
Left - = Chunk ;
if ( NumPackets = = 1 )
{
CMsgPacker Msg ( NETMSG_SNAPSINGLE ) ;
Msg . AddInt ( m_CurrentGameTick ) ;
Msg . AddInt ( m_CurrentGameTick - DeltaTick ) ;
Msg . AddInt ( Crc ) ;
Msg . AddInt ( Chunk ) ;
Msg . AddRaw ( & aCompData [ n * MaxSize ] , Chunk ) ;
SendMsgEx ( & Msg , MSGFLAG_FLUSH , i , true ) ;
}
else
{
CMsgPacker Msg ( NETMSG_SNAP ) ;
Msg . AddInt ( m_CurrentGameTick ) ;
Msg . AddInt ( m_CurrentGameTick - DeltaTick ) ;
Msg . AddInt ( NumPackets ) ;
2010-10-10 13:36:58 +00:00
Msg . AddInt ( n ) ;
2010-05-29 07:25:38 +00:00
Msg . AddInt ( Crc ) ;
Msg . AddInt ( Chunk ) ;
Msg . AddRaw ( & aCompData [ n * MaxSize ] , Chunk ) ;
SendMsgEx ( & Msg , MSGFLAG_FLUSH , i , true ) ;
}
}
}
else
{
CMsgPacker Msg ( NETMSG_SNAPEMPTY ) ;
Msg . AddInt ( m_CurrentGameTick ) ;
Msg . AddInt ( m_CurrentGameTick - DeltaTick ) ;
SendMsgEx ( & Msg , MSGFLAG_FLUSH , i , true ) ;
}
}
}
GameServer ( ) - > OnPostSnap ( ) ;
}
2011-02-12 10:40:36 +00:00
int CServer : : NewClientCallback ( int ClientID , void * pUser )
2010-05-29 07:25:38 +00:00
{
CServer * pThis = ( CServer * ) pUser ;
2011-02-12 10:40:36 +00:00
pThis - > m_aClients [ ClientID ] . m_State = CClient : : STATE_AUTH ;
pThis - > m_aClients [ ClientID ] . m_aName [ 0 ] = 0 ;
pThis - > m_aClients [ ClientID ] . m_aClan [ 0 ] = 0 ;
2011-03-15 10:23:49 +00:00
pThis - > m_aClients [ ClientID ] . m_Country = - 1 ;
2011-02-12 10:40:36 +00:00
pThis - > m_aClients [ ClientID ] . m_Authed = 0 ;
pThis - > m_aClients [ ClientID ] . m_AuthTries = 0 ;
2011-02-13 05:35:13 +00:00
memset ( & pThis - > m_aClients [ ClientID ] . m_Addr , 0 , sizeof ( NETADDR ) ) ;
2011-02-12 10:40:36 +00:00
pThis - > m_aClients [ ClientID ] . Reset ( ) ;
2010-05-29 07:25:38 +00:00
return 0 ;
}
2011-02-12 10:40:36 +00:00
int CServer : : DelClientCallback ( int ClientID , const char * pReason , void * pUser )
2010-05-29 07:25:38 +00:00
{
CServer * pThis = ( CServer * ) pUser ;
2010-10-10 13:36:58 +00:00
2011-02-12 10:40:36 +00:00
NETADDR Addr = pThis - > m_NetServer . ClientAddr ( ClientID ) ;
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
2010-08-17 22:06:00 +00:00
char aBuf [ 256 ] ;
2011-03-28 18:11:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " client dropped. cid=%d addr=%s reason='%s' " , ClientID , aAddrStr , pReason ) ;
2010-08-17 22:06:00 +00:00
pThis - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " server " , aBuf ) ;
2010-05-29 07:25:38 +00:00
// notify the mod about the drop
2011-02-12 10:40:36 +00:00
if ( pThis - > m_aClients [ ClientID ] . m_State > = CClient : : STATE_READY )
2011-02-14 18:41:32 +00:00
pThis - > GameServer ( ) - > OnClientDrop ( ClientID , pReason ) ;
2010-05-29 07:25:38 +00:00
2011-02-12 10:40:36 +00:00
pThis - > m_aClients [ ClientID ] . m_State = CClient : : STATE_EMPTY ;
pThis - > m_aClients [ ClientID ] . m_aName [ 0 ] = 0 ;
pThis - > m_aClients [ ClientID ] . m_aClan [ 0 ] = 0 ;
2011-03-15 10:23:49 +00:00
pThis - > m_aClients [ ClientID ] . m_Country = - 1 ;
2011-02-12 10:40:36 +00:00
pThis - > m_aClients [ ClientID ] . m_Authed = 0 ;
pThis - > m_aClients [ ClientID ] . m_AuthTries = 0 ;
2011-02-13 05:35:13 +00:00
pThis - > m_aPrevStates [ ClientID ] = CClient : : STATE_EMPTY ;
memset ( & pThis - > m_aClients [ ClientID ] . m_Addr , 0 , sizeof ( NETADDR ) ) ;
2011-02-12 10:40:36 +00:00
pThis - > m_aClients [ ClientID ] . m_Snapshots . PurgeAll ( ) ;
2010-05-29 07:25:38 +00:00
return 0 ;
}
2011-02-12 10:40:36 +00:00
void CServer : : SendMap ( int ClientID )
2010-05-29 07:25:38 +00:00
{
CMsgPacker Msg ( NETMSG_MAP_CHANGE ) ;
2010-10-10 13:36:58 +00:00
Msg . AddString ( GetMapName ( ) , 0 ) ;
2010-05-29 07:25:38 +00:00
Msg . AddInt ( m_CurrentMapCrc ) ;
2011-02-16 11:07:54 +00:00
Msg . AddInt ( m_CurrentMapSize ) ;
2011-02-12 10:40:36 +00:00
SendMsgEx ( & Msg , MSGFLAG_VITAL | MSGFLAG_FLUSH , ClientID , true ) ;
2010-05-29 07:25:38 +00:00
}
2011-03-15 08:58:57 +00:00
void CServer : : SendConnectionReady ( int ClientID )
{
CMsgPacker Msg ( NETMSG_CON_READY ) ;
2011-02-12 10:40:36 +00:00
SendMsgEx ( & Msg , MSGFLAG_VITAL | MSGFLAG_FLUSH , ClientID , true ) ;
2010-05-29 07:25:38 +00:00
}
2011-02-12 10:40:36 +00:00
void CServer : : SendRconLine ( int ClientID , const char * pLine )
2010-05-29 07:25:38 +00:00
{
CMsgPacker Msg ( NETMSG_RCON_LINE ) ;
Msg . AddString ( pLine , 512 ) ;
2011-02-12 10:40:36 +00:00
SendMsgEx ( & Msg , MSGFLAG_VITAL , ClientID , true ) ;
2010-05-29 07:25:38 +00:00
}
void CServer : : SendRconLineAuthed ( const char * pLine , void * pUser )
{
CServer * pThis = ( CServer * ) pUser ;
static volatile int ReentryGuard = 0 ;
int i ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( ReentryGuard ) return ;
ReentryGuard + + ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( pThis - > m_aClients [ i ] . m_State ! = CClient : : STATE_EMPTY & & pThis - > m_aClients [ i ] . m_Authed )
pThis - > SendRconLine ( i , pLine ) ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
ReentryGuard - - ;
}
void CServer : : ProcessClientPacket ( CNetChunk * pPacket )
{
2011-02-12 10:40:36 +00:00
int ClientID = pPacket - > m_ClientID ;
2010-05-29 07:25:38 +00:00
NETADDR Addr ;
CUnpacker Unpacker ;
Unpacker . Reset ( pPacket - > m_pData , pPacket - > m_DataSize ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// unpack msgid and system flag
int Msg = Unpacker . GetInt ( ) ;
int Sys = Msg & 1 ;
Msg > > = 1 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( Unpacker . Error ( ) )
return ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
if ( Sys )
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
// system message
if ( Msg = = NETMSG_INFO )
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
if ( m_aClients [ ClientID ] . m_State = = CClient : : STATE_AUTH )
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
const char * pVersion = Unpacker . GetString ( CUnpacker : : SANITIZE_CC ) ;
if ( str_comp ( pVersion , GameServer ( ) - > NetVersion ( ) ) ! = 0 )
{
// wrong version
char aReason [ 256 ] ;
str_format ( aReason , sizeof ( aReason ) , " Wrong version. Server is running '%s' and client '%s' " , GameServer ( ) - > NetVersion ( ) , pVersion ) ;
m_NetServer . Drop ( ClientID , aReason ) ;
return ;
}
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
const char * pPassword = Unpacker . GetString ( CUnpacker : : SANITIZE_CC ) ;
if ( g_Config . m_Password [ 0 ] ! = 0 & & str_comp ( g_Config . m_Password , pPassword ) ! = 0 )
{
// wrong password
m_NetServer . Drop ( ClientID , " Wrong password " ) ;
return ;
}
2011-04-09 06:41:31 +00:00
// reserved slot
if ( ClientID > = ( g_Config . m_SvMaxClients - g_Config . m_SvReservedSlots ) & & g_Config . m_SvReservedSlotsPass [ 0 ] ! = 0 & & strcmp ( g_Config . m_SvReservedSlotsPass , pPassword ) ! = 0 )
{
m_NetServer . Drop ( ClientID , " This server is full " ) ;
return ;
}
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
m_aClients [ ClientID ] . m_State = CClient : : STATE_CONNECTING ;
SendMap ( ClientID ) ;
2010-10-11 01:50:43 +00:00
}
2010-05-29 07:25:38 +00:00
}
2011-03-15 08:58:57 +00:00
else if ( Msg = = NETMSG_REQUEST_MAP_DATA )
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
int Chunk = Unpacker . GetInt ( ) ;
int ChunkSize = 1024 - 128 ;
int Offset = Chunk * ChunkSize ;
int Last = 0 ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
// drop faulty map data requests
if ( Chunk < 0 | | Offset > m_CurrentMapSize )
return ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
if ( Offset + ChunkSize > = m_CurrentMapSize )
{
ChunkSize = m_CurrentMapSize - Offset ;
if ( ChunkSize < 0 )
ChunkSize = 0 ;
Last = 1 ;
}
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
CMsgPacker Msg ( NETMSG_MAP_DATA ) ;
Msg . AddInt ( Last ) ;
Msg . AddInt ( m_CurrentMapCrc ) ;
Msg . AddInt ( Chunk ) ;
Msg . AddInt ( ChunkSize ) ;
Msg . AddRaw ( & m_pCurrentMapData [ Offset ] , ChunkSize ) ;
SendMsgEx ( & Msg , MSGFLAG_VITAL | MSGFLAG_FLUSH , ClientID , true ) ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
if ( g_Config . m_Debug )
{
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " sending chunk %d with size %d " , Chunk , ChunkSize ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " server " , aBuf ) ;
2010-07-29 19:55:33 +00:00
}
2011-03-15 08:58:57 +00:00
}
else if ( Msg = = NETMSG_READY )
{
if ( m_aClients [ ClientID ] . m_State = = CClient : : STATE_CONNECTING )
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
Addr = m_NetServer . ClientAddr ( ClientID ) ;
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
char aBuf [ 256 ] ;
2011-03-28 18:11:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " player is ready. ClientID=%x addr=%s " , ClientID , aAddrStr ) ;
2011-03-15 08:58:57 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " server " , aBuf ) ;
m_aClients [ ClientID ] . m_State = CClient : : STATE_READY ;
GameServer ( ) - > OnClientConnected ( ClientID ) ;
2011-04-09 06:41:31 +00:00
GameServer ( ) - > OnSetAuthed ( ClientID , m_aClients [ ClientID ] . m_Authed ) ;
2011-03-15 08:58:57 +00:00
SendConnectionReady ( ClientID ) ;
2010-05-29 07:25:38 +00:00
}
2011-03-15 08:58:57 +00:00
}
else if ( Msg = = NETMSG_ENTERGAME )
{
if ( m_aClients [ ClientID ] . m_State = = CClient : : STATE_READY & & GameServer ( ) - > IsClientReady ( ClientID ) )
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
Addr = m_NetServer . ClientAddr ( ClientID ) ;
2011-04-09 06:41:31 +00:00
m_aClients [ ClientID ] . m_Addr = Addr ;
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
2010-05-29 07:25:38 +00:00
2011-03-15 08:58:57 +00:00
char aBuf [ 256 ] ;
2011-03-28 18:11:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " player has entered the game. ClientID=%x addr=%s " , ClientID , aAddrStr ) ;
2011-03-15 08:58:57 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
m_aClients [ ClientID ] . m_State = CClient : : STATE_INGAME ;
GameServer ( ) - > OnClientEnter ( ClientID ) ;
2010-09-06 02:59:02 +00:00
}
2011-03-15 08:58:57 +00:00
}
else if ( Msg = = NETMSG_INPUT )
{
CClient : : CInput * pInput ;
int64 TagTime ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
m_aClients [ ClientID ] . m_LastAckedSnapshot = Unpacker . GetInt ( ) ;
int IntendedTick = Unpacker . GetInt ( ) ;
int Size = Unpacker . GetInt ( ) ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
// check for errors
if ( Unpacker . Error ( ) | | Size / 4 > MAX_INPUT_SIZE )
return ;
2010-08-22 16:06:20 +00:00
2011-03-15 08:58:57 +00:00
if ( m_aClients [ ClientID ] . m_LastAckedSnapshot > 0 )
m_aClients [ ClientID ] . m_SnapRate = CClient : : SNAPRATE_FULL ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
if ( m_aClients [ ClientID ] . m_Snapshots . Get ( m_aClients [ ClientID ] . m_LastAckedSnapshot , & TagTime , 0 , 0 ) > = 0 )
m_aClients [ ClientID ] . m_Latency = ( int ) ( ( ( time_get ( ) - TagTime ) * 1000 ) / time_freq ( ) ) ;
2010-08-22 16:06:20 +00:00
2011-03-15 08:58:57 +00:00
// add message to report the input timing
// skip packets that are old
if ( IntendedTick > m_aClients [ ClientID ] . m_LastInputTick )
{
int TimeLeft = ( ( TickStartTime ( IntendedTick ) - time_get ( ) ) * 1000 ) / time_freq ( ) ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
CMsgPacker Msg ( NETMSG_INPUTTIMING ) ;
Msg . AddInt ( IntendedTick ) ;
Msg . AddInt ( TimeLeft ) ;
SendMsgEx ( & Msg , 0 , ClientID , true ) ;
}
2010-09-06 02:59:02 +00:00
2011-03-15 08:58:57 +00:00
m_aClients [ ClientID ] . m_LastInputTick = IntendedTick ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
pInput = & m_aClients [ ClientID ] . m_aInputs [ m_aClients [ ClientID ] . m_CurrentInput ] ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
if ( IntendedTick < = Tick ( ) )
IntendedTick = Tick ( ) + 1 ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
pInput - > m_GameTick = IntendedTick ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
for ( int i = 0 ; i < Size / 4 ; i + + )
pInput - > m_aData [ i ] = Unpacker . GetInt ( ) ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
mem_copy ( m_aClients [ ClientID ] . m_LatestInput . m_aData , pInput - > m_aData , MAX_INPUT_SIZE * sizeof ( int ) ) ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
m_aClients [ ClientID ] . m_CurrentInput + + ;
m_aClients [ ClientID ] . m_CurrentInput % = 200 ;
2010-10-10 13:36:58 +00:00
2011-03-15 08:58:57 +00:00
// call the mod with the fresh input data
if ( m_aClients [ ClientID ] . m_State = = CClient : : STATE_INGAME )
GameServer ( ) - > OnClientDirectInput ( ClientID , m_aClients [ ClientID ] . m_LatestInput . m_aData ) ;
}
else if ( Msg = = NETMSG_RCON_CMD )
{
const char * pCmd = Unpacker . GetString ( ) ;
2010-10-10 13:36:58 +00:00
2011-04-09 06:41:31 +00:00
/*if(Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed)
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " ClientID=%d rcon='%s' " , ClientID , pCmd ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " server " , aBuf ) ;
m_RconClientID = ClientID ;
Console ( ) - > ExecuteLine ( pCmd ) ;
m_RconClientID = - 1 ;
2011-04-09 06:41:31 +00:00
} */
if ( Unpacker . Error ( ) = = 0 )
{
char aBuf [ 256 ] ;
if ( m_aClients [ ClientID ] . m_Authed > = 0 )
2010-05-29 07:25:38 +00:00
{
2011-04-09 06:41:31 +00:00
Console ( ) - > RegisterAlternativePrintCallback ( 0 , 0 ) ;
2010-10-10 22:40:07 +00:00
2011-04-09 06:41:31 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " '%s' ClientID=%d Level=%d Rcon='%s' " , ClientName ( ClientID ) , ClientID , m_aClients [ ClientID ] . m_Authed , pCmd ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " server " , aBuf ) ;
Console ( ) - > ReleaseAlternativePrintCallback ( ) ;
m_RconClientID = ClientID ;
RconResponseInfo Info ;
Info . m_Server = this ;
Info . m_ClientID = ClientID ;
Console ( ) - > ExecuteLine ( pCmd , m_aClients [ ClientID ] . m_Authed , ClientID , SendRconLineAuthed , this , SendRconResponse , & Info ) ;
m_RconClientID = - 1 ;
2010-10-10 13:36:58 +00:00
}
}
2011-03-15 08:58:57 +00:00
}
else if ( Msg = = NETMSG_RCON_AUTH )
{
const char * pPw ;
Unpacker . GetString ( ) ; // login name, not used
pPw = Unpacker . GetString ( CUnpacker : : SANITIZE_CC ) ;
2010-10-12 07:31:47 +00:00
2011-03-15 08:58:57 +00:00
if ( Unpacker . Error ( ) = = 0 )
2011-04-09 06:41:31 +00:00
CheckPass ( ClientID , pPw ) ;
/*if(Unpacker.Error() == 0)
2011-03-15 08:58:57 +00:00
{
if ( g_Config . m_SvRconPassword [ 0 ] = = 0 )
2010-10-10 13:36:58 +00:00
{
2011-03-15 08:58:57 +00:00
SendRconLine ( ClientID , " No rcon password set on server. Set sv_rcon_password to enable the remote console. " ) ;
2010-05-29 07:25:38 +00:00
}
2011-03-15 08:58:57 +00:00
else if ( str_comp ( pPw , g_Config . m_SvRconPassword ) = = 0 )
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
CMsgPacker Msg ( NETMSG_RCON_AUTH_STATUS ) ;
Msg . AddInt ( 1 ) ;
SendMsgEx ( & Msg , MSGFLAG_VITAL , ClientID , true ) ;
2010-10-11 01:50:43 +00:00
2011-03-15 08:58:57 +00:00
m_aClients [ ClientID ] . m_Authed = 1 ;
SendRconLine ( ClientID , " Authentication successful. Remote console access granted. " ) ;
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " ClientID=%d authed " , ClientID ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
}
else if ( g_Config . m_SvRconMaxTries )
{
m_aClients [ ClientID ] . m_AuthTries + + ;
char aBuf [ 128 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " Wrong password %d/%d. " , m_aClients [ ClientID ] . m_AuthTries , g_Config . m_SvRconMaxTries ) ;
SendRconLine ( ClientID , aBuf ) ;
if ( m_aClients [ ClientID ] . m_AuthTries > = g_Config . m_SvRconMaxTries )
2010-10-11 01:50:43 +00:00
{
2011-03-15 08:58:57 +00:00
if ( ! g_Config . m_SvRconBantime )
m_NetServer . Drop ( ClientID , " Too many remote console authentication tries " ) ;
else
2010-10-11 01:50:43 +00:00
{
2011-03-15 08:58:57 +00:00
NETADDR Addr = m_NetServer . ClientAddr ( ClientID ) ;
BanAdd ( Addr , g_Config . m_SvRconBantime * 60 , " Too many remote console authentication tries " ) ;
2010-10-11 01:50:43 +00:00
}
}
2010-05-29 07:25:38 +00:00
}
2011-03-15 08:58:57 +00:00
else
2010-05-29 07:25:38 +00:00
{
2011-03-15 08:58:57 +00:00
SendRconLine ( ClientID , " Wrong password. " ) ;
2011-01-19 14:39:04 +00:00
}
2011-04-09 06:41:31 +00:00
} */
2010-05-29 07:25:38 +00:00
}
2011-03-15 08:58:57 +00:00
else if ( Msg = = NETMSG_PING )
{
CMsgPacker Msg ( NETMSG_PING_REPLY ) ;
SendMsgEx ( & Msg , 0 , ClientID , true ) ;
2010-05-29 07:25:38 +00:00
}
else
{
2011-03-15 08:58:57 +00:00
if ( g_Config . m_Debug )
{
char aHex [ ] = " 0123456789ABCDEF " ;
char aBuf [ 512 ] ;
for ( int b = 0 ; b < pPacket - > m_DataSize & & b < 32 ; b + + )
{
aBuf [ b * 3 ] = aHex [ ( ( const unsigned char * ) pPacket - > m_pData ) [ b ] > > 4 ] ;
aBuf [ b * 3 + 1 ] = aHex [ ( ( const unsigned char * ) pPacket - > m_pData ) [ b ] & 0xf ] ;
aBuf [ b * 3 + 2 ] = ' ' ;
aBuf [ b * 3 + 3 ] = 0 ;
}
char aBufMsg [ 256 ] ;
str_format ( aBufMsg , sizeof ( aBufMsg ) , " strange message ClientID=%d msg=%d data_size=%d " , ClientID , Msg , pPacket - > m_DataSize ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " server " , aBufMsg ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " server " , aBuf ) ;
}
2010-05-29 07:25:38 +00:00
}
2010-09-06 02:59:02 +00:00
}
2011-03-15 08:58:57 +00:00
else
{
// game message
if ( m_aClients [ ClientID ] . m_State > = CClient : : STATE_READY )
GameServer ( ) - > OnMessage ( Msg , & Unpacker , ClientID ) ;
}
2010-05-29 07:25:38 +00:00
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
void CServer : : SendServerInfo ( NETADDR * pAddr , int Token )
{
CNetChunk Packet ;
CPacker p ;
char aBuf [ 128 ] ;
// count the players
2011-03-20 14:33:49 +00:00
int PlayerCount = 0 , ClientCount = 0 ;
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( m_aClients [ i ] . m_State ! = CClient : : STATE_EMPTY )
2011-03-20 14:33:49 +00:00
{
if ( GameServer ( ) - > IsClientPlayer ( i ) )
PlayerCount + + ;
ClientCount + + ;
}
2010-05-29 07:25:38 +00:00
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
p . Reset ( ) ;
2011-03-04 17:14:08 +00:00
p . AddRaw ( SERVERBROWSE_INFO , sizeof ( SERVERBROWSE_INFO ) ) ;
str_format ( aBuf , sizeof ( aBuf ) , " %d " , Token ) ;
p . AddString ( aBuf , 6 ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
p . AddString ( GameServer ( ) - > Version ( ) , 32 ) ;
p . AddString ( g_Config . m_SvName , 64 ) ;
2010-10-10 13:36:58 +00:00
p . AddString ( GetMapName ( ) , 32 ) ;
2010-05-29 07:25:38 +00:00
// gametype
2011-02-16 11:31:47 +00:00
p . AddString ( GameServer ( ) - > GameType ( ) , 16 ) ;
2010-05-29 07:25:38 +00:00
// flags
int i = 0 ;
if ( g_Config . m_Password [ 0 ] ) // password set
i | = SERVER_FLAG_PASSWORD ;
str_format ( aBuf , sizeof ( aBuf ) , " %d " , i ) ;
p . AddString ( aBuf , 2 ) ;
str_format ( aBuf , sizeof ( aBuf ) , " %d " , PlayerCount ) ; p . AddString ( aBuf , 3 ) ; // num players
2011-04-09 06:41:31 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " %d " , m_NetServer . MaxClients ( ) - g_Config . m_SvSpectatorSlots - g_Config . m_SvReservedSlots ) ; p . AddString ( aBuf , 3 ) ; // max players
2011-03-20 14:33:49 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " %d " , ClientCount ) ; p . AddString ( aBuf , 3 ) ; // num clients
str_format ( aBuf , sizeof ( aBuf ) , " %d " , m_NetServer . MaxClients ( ) ) ; p . AddString ( aBuf , 3 ) ; // max clients
2010-05-29 07:25:38 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( m_aClients [ i ] . m_State ! = CClient : : STATE_EMPTY )
{
2011-03-20 14:33:49 +00:00
p . AddString ( ClientName ( i ) , MAX_NAME_LENGTH ) ; // client name
p . AddString ( ClientClan ( i ) , MAX_CLAN_LENGTH ) ; // client clan
str_format ( aBuf , sizeof ( aBuf ) , " %d " , m_aClients [ i ] . m_Country ) ; p . AddString ( aBuf , 6 ) ; // client country
str_format ( aBuf , sizeof ( aBuf ) , " %d " , m_aClients [ i ] . m_Score ) ; p . AddString ( aBuf , 6 ) ; // client score
str_format ( aBuf , sizeof ( aBuf ) , " %d " , GameServer ( ) - > IsClientPlayer ( i ) ? 1 : 0 ) ; p . AddString ( aBuf , 2 ) ; // is player?
2010-05-29 07:25:38 +00:00
}
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
Packet . m_ClientID = - 1 ;
Packet . m_Address = * pAddr ;
Packet . m_Flags = NETSENDFLAG_CONNLESS ;
Packet . m_DataSize = p . Size ( ) ;
Packet . m_pData = p . Data ( ) ;
m_NetServer . Send ( & Packet ) ;
}
void CServer : : UpdateServerInfo ( )
{
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
{
if ( m_aClients [ i ] . m_State ! = CClient : : STATE_EMPTY )
{
NETADDR Addr = m_NetServer . ClientAddr ( i ) ;
2011-03-04 17:14:08 +00:00
SendServerInfo ( & Addr , - 1 ) ;
2010-05-29 07:25:38 +00:00
}
}
}
2010-10-09 18:19:58 +00:00
int CServer : : BanAdd ( NETADDR Addr , int Seconds , const char * pReason )
2010-05-29 07:25:38 +00:00
{
2010-09-16 11:06:11 +00:00
Addr . port = 0 ;
char aAddrStr [ 128 ] ;
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
char aBuf [ 256 ] ;
if ( Seconds )
str_format ( aBuf , sizeof ( aBuf ) , " banned %s for %d minutes " , aAddrStr , Seconds / 60 ) ;
else
str_format ( aBuf , sizeof ( aBuf ) , " banned %s for life " , aAddrStr ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-10-09 18:19:58 +00:00
return m_NetServer . BanAdd ( Addr , Seconds , pReason ) ;
2010-05-29 07:25:38 +00:00
}
int CServer : : BanRemove ( NETADDR Addr )
{
return m_NetServer . BanRemove ( Addr ) ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
void CServer : : PumpNetwork ( )
{
CNetChunk Packet ;
m_NetServer . Update ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// process packets
while ( m_NetServer . Recv ( & Packet ) )
{
if ( Packet . m_ClientID = = - 1 )
{
// stateless
if ( ! m_Register . RegisterProcessPacket ( & Packet ) )
{
if ( Packet . m_DataSize = = sizeof ( SERVERBROWSE_GETINFO ) + 1 & &
mem_comp ( Packet . m_pData , SERVERBROWSE_GETINFO , sizeof ( SERVERBROWSE_GETINFO ) ) = = 0 )
{
SendServerInfo ( & Packet . m_Address , ( ( unsigned char * ) Packet . m_pData ) [ sizeof ( SERVERBROWSE_GETINFO ) ] ) ;
}
2011-04-09 06:41:31 +00:00
// Ban Master
2011-02-08 16:58:36 +00:00
if ( Packet . m_DataSize > = ( int ) sizeof ( BANMASTER_IPOK ) & &
2011-04-09 06:41:31 +00:00
mem_comp ( Packet . m_pData , BANMASTER_IPOK , sizeof ( BANMASTER_IPOK ) ) = = 0 & &
m_NetServer . BanmasterCheck ( & Packet . m_Address ) ! = - 1 )
2011-02-07 06:25:38 +00:00
{
2011-04-09 06:41:31 +00:00
2011-02-07 06:25:38 +00:00
}
2011-02-08 16:58:36 +00:00
if ( Packet . m_DataSize > = ( int ) sizeof ( BANMASTER_IPBAN ) & &
2011-04-09 06:41:31 +00:00
mem_comp ( Packet . m_pData , BANMASTER_IPBAN , sizeof ( BANMASTER_IPBAN ) ) = = 0 & &
g_Config . m_SvGlobalBantime & & m_NetServer . BanmasterCheck ( & Packet . m_Address ) ! = - 1 )
2011-02-07 06:25:38 +00:00
{
CUnpacker Up ;
char aIp [ 32 ] ;
char aReason [ 256 ] ;
NETADDR Addr ;
Up . Reset ( ( unsigned char * ) Packet . m_pData + sizeof ( BANMASTER_IPBAN ) , Packet . m_DataSize - sizeof ( BANMASTER_IPBAN ) ) ;
str_copy ( aIp , Up . GetString ( CUnpacker : : SANITIZE_CC | CUnpacker : : SKIP_START_WHITESPACES ) , sizeof ( aIp ) ) ;
str_copy ( aReason , Up . GetString ( CUnpacker : : SANITIZE_CC | CUnpacker : : SKIP_START_WHITESPACES ) , sizeof ( aReason ) ) ;
if ( net_addr_from_str ( & Addr , aIp ) )
{
dbg_msg ( " globalbans " , " dropped weird message from banmaster " ) ;
return ;
}
m_NetServer . BanAdd ( Addr , g_Config . m_SvGlobalBantime * 60 , aReason ) ;
dbg_msg ( " globalbans " , " added ban, ip=%d.%d.%d.%d, reason= \" %s \" " , Addr . ip [ 0 ] , Addr . ip [ 1 ] , Addr . ip [ 2 ] , Addr . ip [ 3 ] , aReason ) ;
}
2011-04-09 06:41:31 +00:00
2010-05-29 07:25:38 +00:00
}
}
else
ProcessClientPacket ( & Packet ) ;
}
}
2010-10-10 13:36:58 +00:00
char * CServer : : GetMapName ( )
{
// get the name of the map without his path
char * pMapShortName = & g_Config . m_SvMap [ 0 ] ;
for ( int i = 0 ; i < str_length ( g_Config . m_SvMap ) - 1 ; i + + )
{
if ( g_Config . m_SvMap [ i ] = = ' / ' | | g_Config . m_SvMap [ i ] = = ' \\ ' )
pMapShortName = & g_Config . m_SvMap [ i + 1 ] ;
}
return pMapShortName ;
}
2010-05-29 07:25:38 +00:00
int CServer : : LoadMap ( const char * pMapName )
{
//DATAFILE *df;
char aBuf [ 512 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " maps/%s.map " , pMapName ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
/*df = datafile_load(buf);
if ( ! df )
return 0 ; */
2011-03-31 13:13:49 +00:00
// check for valid standard map
if ( ! m_MapChecker . ReadAndValidateMap ( Storage ( ) , aBuf , IStorage : : TYPE_ALL ) )
{
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " mapchecker " , " invalid standard map " ) ;
return 0 ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( ! m_pMap - > Load ( aBuf ) )
return 0 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// stop recording when we change map
m_DemoRecorder . Stop ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// reinit snapshot ids
m_IDPool . TimeoutIDs ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// get the crc of the map
m_CurrentMapCrc = m_pMap - > Crc ( ) ;
2010-08-17 22:06:00 +00:00
char aBufMsg [ 256 ] ;
str_format ( aBufMsg , sizeof ( aBufMsg ) , " %s crc is %08x " , aBuf , m_CurrentMapCrc ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " server " , aBufMsg ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
str_copy ( m_aCurrentMap , pMapName , sizeof ( m_aCurrentMap ) ) ;
//map_set(df);
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// load compelate map into memory for download
{
2010-10-06 21:07:35 +00:00
IOHANDLE File = Storage ( ) - > OpenFile ( aBuf , IOFLAG_READ , IStorage : : TYPE_ALL ) ;
2010-05-29 07:25:38 +00:00
m_CurrentMapSize = ( int ) io_length ( File ) ;
if ( m_pCurrentMapData )
mem_free ( m_pCurrentMapData ) ;
m_pCurrentMapData = ( unsigned char * ) mem_alloc ( m_CurrentMapSize , 1 ) ;
io_read ( File , m_pCurrentMapData , m_CurrentMapSize ) ;
io_close ( File ) ;
}
2011-01-20 20:25:09 +00:00
2011-04-09 06:41:31 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2011-01-20 20:25:09 +00:00
m_aPrevStates [ i ] = m_aClients [ i ] . m_State ;
2010-05-29 07:25:38 +00:00
return 1 ;
}
2010-08-17 22:06:00 +00:00
void CServer : : InitRegister ( CNetServer * pNetServer , IEngineMasterServer * pMasterServer , IConsole * pConsole )
2010-05-29 07:25:38 +00:00
{
2010-08-17 22:06:00 +00:00
m_Register . Init ( pNetServer , pMasterServer , pConsole ) ;
2010-05-29 07:25:38 +00:00
}
int CServer : : Run ( )
{
m_pGameServer = Kernel ( ) - > RequestInterface < IGameServer > ( ) ;
m_pMap = Kernel ( ) - > RequestInterface < IEngineMap > ( ) ;
m_pStorage = Kernel ( ) - > RequestInterface < IStorage > ( ) ;
//
Console ( ) - > RegisterPrintCallback ( SendRconLineAuthed , this ) ;
2010-10-10 22:40:07 +00:00
Console ( ) - > RegisterPrintResponseCallback ( SendRconLineAuthed , this ) ;
2010-11-07 15:29:55 +00:00
Console ( ) - > RegisterClientOnlineCallback ( ClientOnline , this ) ;
Console ( ) - > RegisterCompareClientsCallback ( CompareClients , this ) ;
2010-05-29 07:25:38 +00:00
// load map
if ( ! LoadMap ( g_Config . m_SvMap ) )
{
dbg_msg ( " server " , " failed to load map. mapname='%s' " , g_Config . m_SvMap ) ;
return - 1 ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// start server
NETADDR BindAddr ;
2011-03-28 18:11:28 +00:00
if ( g_Config . m_SvBindaddr [ 0 ] & & net_host_lookup ( g_Config . m_SvBindaddr , & BindAddr , NETTYPE_ALL ) = = 0 )
2010-05-29 07:25:38 +00:00
{
// sweet!
BindAddr . port = g_Config . m_SvPort ;
}
else
{
mem_zero ( & BindAddr , sizeof ( BindAddr ) ) ;
2011-03-28 18:11:28 +00:00
BindAddr . type = NETTYPE_ALL ;
2010-05-29 07:25:38 +00:00
BindAddr . port = g_Config . m_SvPort ;
}
2010-10-10 13:36:58 +00:00
2010-06-03 12:48:32 +00:00
if ( ! m_NetServer . Open ( BindAddr , g_Config . m_SvMaxClients , g_Config . m_SvMaxClientsPerIP , 0 ) )
2010-05-29 07:25:38 +00:00
{
dbg_msg ( " server " , " couldn't open socket. port might already be in use " ) ;
return - 1 ;
}
2010-10-11 01:50:43 +00:00
m_NetServer . SetCallbacks ( NewClientCallback , DelClientCallback , this ) ;
2011-02-07 06:53:41 +00:00
Console ( ) - > ExecuteFile ( SERVER_BANMASTERFILE , 0 , 0 , 0 , 0 , 4 ) ;
2010-05-29 07:25:38 +00:00
2010-08-17 22:06:00 +00:00
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " server name is '%s' " , g_Config . m_SvName ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
GameServer ( ) - > OnInit ( ) ;
2010-08-17 22:06:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " version %s " , GameServer ( ) - > NetVersion ( ) ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-05-29 07:25:38 +00:00
2010-08-07 18:22:25 +00:00
// process pending commands
2011-04-09 06:41:31 +00:00
m_pConsole - > StoreCommands ( false , - 1 ) ;
2010-08-07 18:22:25 +00:00
2010-05-29 07:25:38 +00:00
// start game
{
int64 ReportTime = time_get ( ) ;
int ReportInterval = 3 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
m_Lastheartbeat = 0 ;
m_GameStartTime = time_get ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( g_Config . m_Debug )
2010-08-17 22:06:00 +00:00
{
str_format ( aBuf , sizeof ( aBuf ) , " baseline memory usage %dk " , mem_stats ( ) - > allocated / 1024 ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " server " , aBuf ) ;
}
2010-05-29 07:25:38 +00:00
while ( m_RunServer )
{
int64 t = time_get ( ) ;
int NewTicks = 0 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// load new map TODO: don't poll this
2010-05-30 12:01:11 +00:00
if ( str_comp ( g_Config . m_SvMap , m_aCurrentMap ) ! = 0 | | m_MapReload )
2010-05-29 07:25:38 +00:00
{
2010-05-30 12:01:11 +00:00
m_MapReload = 0 ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// load map
if ( LoadMap ( g_Config . m_SvMap ) )
{
// new map loaded
GameServer ( ) - > OnShutdown ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
for ( int c = 0 ; c < MAX_CLIENTS ; c + + )
{
2010-06-26 15:59:59 +00:00
if ( m_aClients [ c ] . m_State < = CClient : : STATE_AUTH )
2010-05-29 07:25:38 +00:00
continue ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
SendMap ( c ) ;
m_aClients [ c ] . Reset ( ) ;
m_aClients [ c ] . m_State = CClient : : STATE_CONNECTING ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
m_GameStartTime = time_get ( ) ;
m_CurrentGameTick = 0 ;
Kernel ( ) - > ReregisterInterface ( GameServer ( ) ) ;
GameServer ( ) - > OnInit ( ) ;
2010-06-07 11:34:47 +00:00
UpdateServerInfo ( ) ;
2010-05-29 07:25:38 +00:00
}
else
{
2010-08-17 22:06:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " failed to load map. mapname='%s' " , g_Config . m_SvMap ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-05-29 07:25:38 +00:00
str_copy ( g_Config . m_SvMap , m_aCurrentMap , sizeof ( g_Config . m_SvMap ) ) ;
}
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
while ( t > TickStartTime ( m_CurrentGameTick + 1 ) )
{
m_CurrentGameTick + + ;
NewTicks + + ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// apply new input
for ( int c = 0 ; c < MAX_CLIENTS ; c + + )
{
if ( m_aClients [ c ] . m_State = = CClient : : STATE_EMPTY )
continue ;
for ( int i = 0 ; i < 200 ; i + + )
{
if ( m_aClients [ c ] . m_aInputs [ i ] . m_GameTick = = Tick ( ) )
{
if ( m_aClients [ c ] . m_State = = CClient : : STATE_INGAME )
GameServer ( ) - > OnClientPredictedInput ( c , m_aClients [ c ] . m_aInputs [ i ] . m_aData ) ;
break ;
}
}
}
GameServer ( ) - > OnTick ( ) ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// snap game
if ( NewTicks )
{
if ( g_Config . m_SvHighBandwidth | | ( m_CurrentGameTick % 2 ) = = 0 )
DoSnapshot ( ) ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// master server stuff
2011-04-04 16:20:05 +00:00
m_Register . RegisterUpdate ( BindAddr . type ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
PumpNetwork ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( ReportTime < time_get ( ) )
{
if ( g_Config . m_Debug )
{
/*
static NETSTATS prev_stats ;
NETSTATS stats ;
netserver_stats ( net , & stats ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
perf_next ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( config . dbg_pref )
perf_dump ( & rootscope ) ;
dbg_msg ( " server " , " send=%8d recv=%8d " ,
( stats . send_bytes - prev_stats . send_bytes ) / reportinterval ,
( stats . recv_bytes - prev_stats . recv_bytes ) / reportinterval ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
prev_stats = stats ;
*/
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
ReportTime + = time_freq ( ) * ReportInterval ;
}
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// wait for incomming data
net_socket_read_wait ( m_NetServer . Socket ( ) , 5 ) ;
}
}
// disconnect all clients on shutdown
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
{
if ( m_aClients [ i ] . m_State ! = CClient : : STATE_EMPTY )
2010-10-09 18:19:58 +00:00
m_NetServer . Drop ( i , " Server shutdown " ) ;
2010-05-29 07:25:38 +00:00
}
GameServer ( ) - > OnShutdown ( ) ;
m_pMap - > Unload ( ) ;
if ( m_pCurrentMapData )
mem_free ( m_pCurrentMapData ) ;
return 0 ;
}
2011-02-13 05:35:13 +00:00
void CServer : : ConKick ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
2010-11-15 17:58:44 +00:00
int Victim = pResult - > GetVictim ( ) ;
if ( pResult - > NumArguments ( ) > = 1 )
2010-10-09 18:19:58 +00:00
{
char aBuf [ 128 ] ;
2011-04-09 06:41:31 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Kicked (%s) " , pResult - > GetString ( 0 ) ) ;
2010-11-15 17:58:44 +00:00
( ( CServer * ) pUser ) - > Kick ( Victim , aBuf ) ;
2010-10-09 18:19:58 +00:00
}
else
2010-11-15 17:58:44 +00:00
( ( CServer * ) pUser ) - > Kick ( Victim , " Kicked by console " ) ;
2010-05-29 07:25:38 +00:00
}
2011-02-13 05:35:13 +00:00
void CServer : : ConBan ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
NETADDR Addr ;
2010-09-12 10:07:10 +00:00
CServer * pServer = ( CServer * ) pUser ;
2010-05-29 07:25:38 +00:00
const char * pStr = pResult - > GetString ( 0 ) ;
2010-10-11 01:50:43 +00:00
int Minutes = 30 ;
2010-10-09 18:19:58 +00:00
const char * pReason = " No reason given " ;
2010-10-11 01:50:43 +00:00
2010-05-29 07:25:38 +00:00
if ( pResult - > NumArguments ( ) > 1 )
2010-10-11 01:50:43 +00:00
Minutes = pResult - > GetInteger ( 1 ) ;
2010-10-10 13:36:58 +00:00
2010-10-09 18:19:58 +00:00
if ( pResult - > NumArguments ( ) > 2 )
pReason = pResult - > GetString ( 2 ) ;
2010-05-29 07:25:38 +00:00
if ( net_addr_from_str ( & Addr , pStr ) = = 0 )
2010-09-12 11:52:25 +00:00
{
2011-02-12 10:40:36 +00:00
if ( pServer - > m_RconClientID > = 0 & & pServer - > m_RconClientID < MAX_CLIENTS & & pServer - > m_aClients [ pServer - > m_RconClientID ] . m_State ! = CClient : : STATE_EMPTY )
2010-09-12 11:52:25 +00:00
{
2011-02-12 10:40:36 +00:00
NETADDR AddrCheck = pServer - > m_NetServer . ClientAddr ( pServer - > m_RconClientID ) ;
2010-09-12 11:52:25 +00:00
Addr . port = AddrCheck . port = 0 ;
if ( net_addr_comp ( & Addr , & AddrCheck ) = = 0 )
{
2011-04-09 06:41:31 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " you can't ban yourself " ) ;
2010-09-12 11:52:25 +00:00
return ;
}
}
2010-10-09 18:19:58 +00:00
pServer - > BanAdd ( Addr , Minutes * 60 , pReason ) ;
2010-09-12 11:52:25 +00:00
}
2010-05-29 07:25:38 +00:00
else if ( StrAllnum ( pStr ) )
{
2011-04-09 06:41:31 +00:00
int Victim = str_toint ( pStr ) ;
2010-05-29 07:25:38 +00:00
2011-04-09 06:41:31 +00:00
if ( Victim < 0 | | Victim > = MAX_CLIENTS | | pServer - > m_aClients [ Victim ] . m_State = = CClient : : STATE_EMPTY )
2010-05-29 07:25:38 +00:00
{
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " invalid client id " ) ;
2010-05-29 07:25:38 +00:00
return ;
}
2011-04-09 06:41:31 +00:00
else if ( pServer - > m_RconClientID = = Victim )
2010-05-29 07:25:38 +00:00
{
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " you can't ban yourself " ) ;
2010-05-29 07:25:38 +00:00
return ;
}
2011-04-09 06:41:31 +00:00
if ( ClientID ! = - 1 & & ( ( CServer * ) pUser ) - > m_aClients [ ClientID ] . m_Authed < = ( ( CServer * ) pUser ) - > m_aClients [ Victim ] . m_Authed )
return ;
2010-05-29 07:25:38 +00:00
2011-04-09 06:41:31 +00:00
Addr = pServer - > m_NetServer . ClientAddr ( Victim ) ;
2010-10-09 18:19:58 +00:00
pServer - > BanAdd ( Addr , Minutes * 60 , pReason ) ;
2010-05-29 07:25:38 +00:00
}
2010-09-12 11:52:25 +00:00
else
{
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " invalid network address to ban " ) ;
2010-09-12 11:52:25 +00:00
return ;
2010-09-12 10:07:10 +00:00
}
2010-05-29 07:25:38 +00:00
}
2011-02-13 05:35:13 +00:00
void CServer : : ConUnban ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
NETADDR Addr ;
2010-06-07 12:12:06 +00:00
CServer * pServer = ( CServer * ) pUser ;
2010-05-29 07:25:38 +00:00
const char * pStr = pResult - > GetString ( 0 ) ;
2010-10-10 13:36:58 +00:00
2010-08-17 22:06:00 +00:00
if ( net_addr_from_str ( & Addr , pStr ) = = 0 & & ! pServer - > BanRemove ( Addr ) )
{
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
2010-08-17 22:06:00 +00:00
char aBuf [ 256 ] ;
2011-03-28 18:11:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " unbanned %s " , aAddrStr ) ;
2011-04-09 06:41:31 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-08-17 22:06:00 +00:00
}
2010-06-07 12:12:06 +00:00
else if ( StrAllnum ( pStr ) )
{
int BanIndex = str_toint ( pStr ) ;
CNetServer : : CBanInfo Info ;
if ( BanIndex < 0 | | ! pServer - > m_NetServer . BanGet ( BanIndex , & Info ) )
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " invalid ban index " ) ;
2010-08-17 22:06:00 +00:00
else if ( ! pServer - > BanRemove ( Info . m_Addr ) )
{
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
net_addr_str ( & Info . m_Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
2010-08-17 22:06:00 +00:00
char aBuf [ 256 ] ;
2011-03-28 18:11:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " unbanned %s " , aAddrStr ) ;
2011-04-09 06:41:31 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-08-17 22:06:00 +00:00
}
2010-06-07 12:12:06 +00:00
}
2010-05-29 07:25:38 +00:00
else
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " invalid network address " ) ;
2010-05-29 07:25:38 +00:00
}
2011-02-13 05:35:13 +00:00
void CServer : : ConBans ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
unsigned Now = time_timestamp ( ) ;
char aBuf [ 1024 ] ;
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
2010-05-29 07:25:38 +00:00
CServer * pServer = ( CServer * ) pUser ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
int Num = pServer - > m_NetServer . BanNum ( ) ;
for ( int i = 0 ; i < Num ; i + + )
{
CNetServer : : CBanInfo Info ;
pServer - > m_NetServer . BanGet ( i , & Info ) ;
NETADDR Addr = Info . m_Addr ;
2011-03-28 18:11:28 +00:00
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( Info . m_Expires = = - 1 )
{
2011-04-06 15:30:50 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " #%i %s for life " , i , aAddrStr ) ;
2010-05-29 07:25:38 +00:00
}
else
{
unsigned t = Info . m_Expires - Now ;
2011-04-06 15:30:50 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " #%i %s for %d minutes and %d seconds " , i , aAddrStr , t / 60 , t % 60 ) ;
2010-05-29 07:25:38 +00:00
}
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " Server " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
str_format ( aBuf , sizeof ( aBuf ) , " %d ban(s) " , Num ) ;
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " Server " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
2011-02-13 05:35:13 +00:00
void CServer : : ConStatus ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
int i ;
NETADDR Addr ;
char aBuf [ 1024 ] ;
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] ;
2010-05-29 07:25:38 +00:00
CServer * pServer = ( CServer * ) pUser ;
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
2010-06-03 12:48:32 +00:00
if ( pServer - > m_aClients [ i ] . m_State ! = CClient : : STATE_EMPTY )
2010-05-29 07:25:38 +00:00
{
Addr = pServer - > m_NetServer . ClientAddr ( i ) ;
2011-03-28 18:11:28 +00:00
net_addr_str ( & Addr , aAddrStr , sizeof ( aAddrStr ) ) ;
2010-06-03 12:48:32 +00:00
if ( pServer - > m_aClients [ i ] . m_State = = CClient : : STATE_INGAME )
2011-03-28 18:11:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " id=%d addr=%s name='%s' score=%d " , i , aAddrStr ,
2010-06-03 12:48:32 +00:00
pServer - > m_aClients [ i ] . m_aName , pServer - > m_aClients [ i ] . m_Score ) ;
else
2011-03-28 18:11:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " id=%d addr=%s connecting " , i , aAddrStr ) ;
2010-10-10 22:40:07 +00:00
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " Server " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
}
}
2011-02-13 05:35:13 +00:00
void CServer : : ConShutdown ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
( ( CServer * ) pUser ) - > m_RunServer = 0 ;
}
2011-02-13 05:35:13 +00:00
void CServer : : ConRecord ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
2010-12-07 23:42:32 +00:00
CServer * pServer = ( CServer * ) pUser ;
char aFilename [ 128 ] ;
if ( pResult - > NumArguments ( ) )
str_format ( aFilename , sizeof ( aFilename ) , " demos/%s.demo " , pResult - > GetString ( 0 ) ) ;
else
{
char aDate [ 20 ] ;
str_timestamp ( aDate , sizeof ( aDate ) ) ;
str_format ( aFilename , sizeof ( aFilename ) , " demos/demo_%s.demo " , aDate ) ;
}
pServer - > m_DemoRecorder . Start ( pServer - > Storage ( ) , pServer - > Console ( ) , aFilename , pServer - > GameServer ( ) - > NetVersion ( ) , pServer - > m_aCurrentMap , pServer - > m_CurrentMapCrc , " server " ) ;
2010-05-29 07:25:38 +00:00
}
2011-02-13 05:35:13 +00:00
void CServer : : ConStopRecord ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-29 07:25:38 +00:00
{
( ( CServer * ) pUser ) - > m_DemoRecorder . Stop ( ) ;
}
2011-02-13 05:35:13 +00:00
void CServer : : ConMapReload ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2010-05-30 12:01:11 +00:00
{
( ( CServer * ) pUser ) - > m_MapReload = 1 ;
}
2010-05-29 07:25:38 +00:00
void CServer : : ConchainSpecialInfoupdate ( IConsole : : IResult * pResult , void * pUserData , IConsole : : FCommandCallback pfnCallback , void * pCallbackUserData )
{
2010-07-29 05:21:18 +00:00
pfnCallback ( pResult , pCallbackUserData , - 1 ) ;
2010-05-29 07:25:38 +00:00
if ( pResult - > NumArguments ( ) )
( ( CServer * ) pUserData ) - > UpdateServerInfo ( ) ;
}
2010-06-03 12:48:32 +00:00
void CServer : : ConchainMaxclientsperipUpdate ( IConsole : : IResult * pResult , void * pUserData , IConsole : : FCommandCallback pfnCallback , void * pCallbackUserData )
{
2010-07-29 05:21:18 +00:00
pfnCallback ( pResult , pCallbackUserData , - 1 ) ;
2010-06-03 12:48:32 +00:00
if ( pResult - > NumArguments ( ) )
( ( CServer * ) pUserData ) - > m_NetServer . SetMaxClientsPerIP ( pResult - > GetInteger ( 0 ) ) ;
}
2010-05-29 07:25:38 +00:00
void CServer : : RegisterCommands ( )
{
m_pConsole = Kernel ( ) - > RequestInterface < IConsole > ( ) ;
2010-10-10 13:36:58 +00:00
2011-04-09 06:41:31 +00:00
Console ( ) - > Register ( " kick " , " v?r " , CFGFLAG_SERVER , ConKick , this , " " , IConsole : : CONSOLELEVEL_MODERATOR ) ;
2011-03-16 14:27:30 +00:00
Console ( ) - > Register ( " ban " , " s?ir " , CFGFLAG_SERVER | CFGFLAG_STORE , ConBan , this , " " , IConsole : : CONSOLELEVEL_MODERATOR ) ;
Console ( ) - > Register ( " unban " , " s " , CFGFLAG_SERVER | CFGFLAG_STORE , ConUnban , this , " " , IConsole : : CONSOLELEVEL_MODERATOR ) ;
Console ( ) - > Register ( " bans " , " " , CFGFLAG_SERVER | CFGFLAG_STORE , ConBans , this , " " , IConsole : : CONSOLELEVEL_MODERATOR ) ;
Console ( ) - > Register ( " status " , " " , CFGFLAG_SERVER , ConStatus , this , " " , IConsole : : CONSOLELEVEL_MODERATOR ) ;
Console ( ) - > Register ( " shutdown " , " " , CFGFLAG_SERVER , ConShutdown , this , " " , IConsole : : CONSOLELEVEL_ADMIN ) ;
2010-10-10 13:36:58 +00:00
2011-03-16 14:27:30 +00:00
Console ( ) - > Register ( " record " , " ?s " , CFGFLAG_SERVER | CFGFLAG_STORE , ConRecord , this , " " , IConsole : : CONSOLELEVEL_ADMIN ) ;
Console ( ) - > Register ( " stoprecord " , " " , CFGFLAG_SERVER , ConStopRecord , this , " " , IConsole : : CONSOLELEVEL_ADMIN ) ;
2010-10-10 13:36:58 +00:00
2011-03-16 14:27:30 +00:00
Console ( ) - > Register ( " reload " , " " , CFGFLAG_SERVER , ConMapReload , this , " " , IConsole : : CONSOLELEVEL_ADMIN ) ;
2010-05-29 07:25:38 +00:00
Console ( ) - > Chain ( " sv_name " , ConchainSpecialInfoupdate , this ) ;
Console ( ) - > Chain ( " password " , ConchainSpecialInfoupdate , this ) ;
2010-06-03 12:48:32 +00:00
Console ( ) - > Chain ( " sv_max_clients_per_ip " , ConchainMaxclientsperipUpdate , this ) ;
2010-10-11 00:39:08 +00:00
2011-04-09 06:41:31 +00:00
Console ( ) - > Register ( " add_banmaster " , " s " , CFGFLAG_SERVER , ConAddBanmaster , this , " " , IConsole : : CONSOLELEVEL_ADMIN ) ;
Console ( ) - > Register ( " banmasters " , " " , CFGFLAG_SERVER , ConBanmasters , this , " " , IConsole : : CONSOLELEVEL_ADMIN ) ;
Console ( ) - > Register ( " clear_banmasters " , " " , CFGFLAG_SERVER , ConClearBanmasters , this , " " , IConsole : : CONSOLELEVEL_ADMIN ) ;
2011-03-16 14:27:30 +00:00
Console ( ) - > Register ( " login " , " ?s " , CFGFLAG_SERVER , ConLogin , this , " Allows you access to rcon if no password is given, or changes your level if a password is given " , IConsole : : CONSOLELEVEL_USER ) ;
Console ( ) - > Register ( " auth " , " ?s " , CFGFLAG_SERVER , ConLogin , this , " Allows you access to rcon if no password is given, or changes your level if a password is given " , IConsole : : CONSOLELEVEL_USER ) ;
Console ( ) - > Register ( " cmdlist " , " ?i " , CFGFLAG_SERVER , ConCmdList , this , " Shows you the commands available for your remote console access. Specify the level if you want to see other level's commands " , IConsole : : CONSOLELEVEL_USER ) ;
2010-10-10 13:36:58 +00:00
}
2010-05-29 07:25:38 +00:00
int CServer : : SnapNewID ( )
{
return m_IDPool . NewID ( ) ;
}
void CServer : : SnapFreeID ( int ID )
{
m_IDPool . FreeID ( ID ) ;
}
2011-02-12 10:40:36 +00:00
void * CServer : : SnapNewItem ( int Type , int ID , int Size )
2010-05-29 07:25:38 +00:00
{
dbg_assert ( Type > = 0 & & Type < = 0xffff , " incorrect type " ) ;
2011-02-12 10:40:36 +00:00
dbg_assert ( ID > = 0 & & ID < = 0xffff , " incorrect id " ) ;
return ID < 0 ? 0 : m_SnapshotBuilder . NewItem ( Type , ID , Size ) ;
2010-05-29 07:25:38 +00:00
}
void CServer : : SnapSetStaticsize ( int ItemType , int Size )
{
m_SnapshotDelta . SetStaticsize ( ItemType , Size ) ;
}
static CServer * CreateServer ( ) { return new CServer ( ) ; }
int main ( int argc , const char * * argv ) // ignore_convention
{
# if defined(CONF_FAMILY_WINDOWS)
for ( int i = 1 ; i < argc ; i + + ) // ignore_convention
{
if ( str_comp ( " -s " , argv [ i ] ) = = 0 | | str_comp ( " --silent " , argv [ i ] ) = = 0 ) // ignore_convention
{
ShowWindow ( GetConsoleWindow ( ) , SW_HIDE ) ;
break ;
}
}
# endif
2010-11-17 23:32:54 +00:00
2010-05-29 07:25:38 +00:00
CServer * pServer = CreateServer ( ) ;
IKernel * pKernel = IKernel : : Create ( ) ;
// create the components
2011-02-27 14:03:57 +00:00
IEngine * pEngine = CreateEngine ( " Teeworlds " ) ;
2010-05-29 07:25:38 +00:00
IEngineMap * pEngineMap = CreateEngineMap ( ) ;
IGameServer * pGameServer = CreateGameServer ( ) ;
2010-06-18 18:32:52 +00:00
IConsole * pConsole = CreateConsole ( CFGFLAG_SERVER ) ;
2010-05-29 07:25:38 +00:00
IEngineMasterServer * pEngineMasterServer = CreateEngineMasterServer ( ) ;
2010-08-05 18:26:03 +00:00
IStorage * pStorage = CreateStorage ( " Teeworlds " , argc , argv ) ; // ignore_convention
2010-05-29 07:25:38 +00:00
IConfig * pConfig = CreateConfig ( ) ;
2010-10-10 13:36:58 +00:00
2010-08-17 22:06:00 +00:00
pServer - > InitRegister ( & pServer - > m_NetServer , pEngineMasterServer , pConsole ) ;
2010-05-29 07:25:38 +00:00
{
bool RegisterFail = false ;
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( pServer ) ; // register as both
2011-02-27 14:03:57 +00:00
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( pEngine ) ;
2010-05-29 07:25:38 +00:00
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( static_cast < IEngineMap * > ( pEngineMap ) ) ; // register as both
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( static_cast < IMap * > ( pEngineMap ) ) ;
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( pGameServer ) ;
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( pConsole ) ;
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( pStorage ) ;
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( pConfig ) ;
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( static_cast < IEngineMasterServer * > ( pEngineMasterServer ) ) ; // register as both
RegisterFail = RegisterFail | | ! pKernel - > RegisterInterface ( static_cast < IMasterServer * > ( pEngineMasterServer ) ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
if ( RegisterFail )
return - 1 ;
}
2010-10-10 13:36:58 +00:00
2011-03-05 10:46:24 +00:00
pEngine - > Init ( ) ;
2010-05-29 07:25:38 +00:00
pConfig - > Init ( ) ;
2011-02-27 14:03:57 +00:00
pEngineMasterServer - > Init ( ) ;
2010-05-29 07:25:38 +00:00
pEngineMasterServer - > Load ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// register all console commands
pServer - > RegisterCommands ( ) ;
pGameServer - > OnConsoleInit ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// execute autoexec file
2010-11-22 08:27:13 +00:00
pConsole - > ExecuteFile ( " autoexec.cfg " , 0 , 0 , 0 , 0 , 4 ) ;
2010-05-29 07:25:38 +00:00
// parse the command line arguments
if ( argc > 1 ) // ignore_convention
pConsole - > ParseArguments ( argc - 1 , & argv [ 1 ] ) ; // ignore_convention
2010-08-10 22:31:42 +00:00
// restore empty config strings to their defaults
pConfig - > RestoreStrings ( ) ;
2010-10-10 13:36:58 +00:00
2011-02-27 14:03:57 +00:00
pEngine - > InitLogfile ( ) ;
2010-08-22 16:06:20 +00:00
2010-05-29 07:25:38 +00:00
// run the server
2011-02-27 14:03:57 +00:00
dbg_msg ( " server " , " starting... " ) ;
2010-05-29 07:25:38 +00:00
pServer - > Run ( ) ;
2010-10-10 13:36:58 +00:00
2010-05-29 07:25:38 +00:00
// free
delete pServer ;
delete pKernel ;
delete pEngineMap ;
delete pGameServer ;
delete pConsole ;
delete pEngineMasterServer ;
delete pStorage ;
delete pConfig ;
return 0 ;
}
2011-04-09 06:41:31 +00:00
// DDRace
void CServer : : GetClientAddr ( int ClientID , NETADDR * pAddr )
{
if ( ClientID > = 0 & & ClientID < MAX_CLIENTS & & m_aClients [ ClientID ] . m_State = = CClient : : STATE_INGAME )
* pAddr = m_NetServer . ClientAddr ( ClientID ) ;
}
void DDRaceTunesReset ( CConsole * pConsole )
{
pConsole - > ExecuteLine ( " tune_reset " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " tune gun_speed 1400 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " tune shotgun_curvature 0 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " tune shotgun_speed 500 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " tune shotgun_speeddiff 0 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " tune gun_curvature 0 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " sv_hit 1 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " sv_npc 0 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " sv_phook 1 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " sv_endless_drag 0 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
pConsole - > ExecuteLine ( " sv_old_laser 0 " , IConsole : : CONSOLELEVEL_CONFIG , - 1 ) ;
}
2011-02-13 05:35:13 +00:00
void CServer : : SetRconLevel ( int ClientID , int Level )
2010-09-17 13:47:31 +00:00
{
2011-03-16 14:27:30 +00:00
Level = clamp ( Level , ( int ) IConsole : : CONSOLELEVEL_USER , ( int ) IConsole : : CONSOLELEVEL_ADMIN ) ;
if ( Level > IConsole : : CONSOLELEVEL_USER )
2010-09-17 14:23:07 +00:00
{
2011-02-13 05:35:13 +00:00
dbg_msg ( " server " , " %s set to level %d. ClientID=%x ip=%d.%d.%d.%d " , ClientName ( ClientID ) , Level , ClientID , m_aClients [ ClientID ] . m_Addr . ip [ 0 ] , m_aClients [ ClientID ] . m_Addr . ip [ 1 ] , m_aClients [ ClientID ] . m_Addr . ip [ 2 ] , m_aClients [ ClientID ] . m_Addr . ip [ 3 ] ) ;
2010-09-17 14:23:07 +00:00
CMsgPacker Msg ( NETMSG_RCON_AUTH_STATUS ) ;
Msg . AddInt ( 1 ) ;
2011-02-13 05:35:13 +00:00
SendMsgEx ( & Msg , MSGFLAG_VITAL , ClientID , true ) ;
m_aClients [ ClientID ] . m_Authed = Level ;
GameServer ( ) - > OnSetAuthed ( ClientID , m_aClients [ ClientID ] . m_Authed ) ;
2010-09-17 14:23:07 +00:00
}
2010-09-17 13:47:31 +00:00
}
2010-10-10 13:36:58 +00:00
2011-03-16 14:27:30 +00:00
void CServer : : CheckPass ( int ClientID , const char * pPassword )
2010-10-11 00:39:08 +00:00
{
2011-03-16 14:27:30 +00:00
if ( pPassword [ 0 ] ! = 0 )
2010-10-11 00:39:08 +00:00
{
2011-04-09 06:41:31 +00:00
if ( g_Config . m_SvRconPasswordModer [ 0 ] = = 0 & &
2010-10-11 00:39:08 +00:00
g_Config . m_SvRconPasswordAdmin [ 0 ] = = 0 )
{
2011-02-13 05:35:13 +00:00
SendRconLine ( ClientID , " No rcon password set on server. Set sv_admin_pass/sv_mod_pass/sv_helper_pass to enable the remote console. " ) ;
2010-10-11 00:39:08 +00:00
}
else
{
/*else if(str_comp(pPw, g_Config.m_SvRconPassword) == 0)
{
CMsgPacker Msg ( NETMSG_RCON_AUTH_STATUS ) ;
Msg . AddInt ( 1 ) ;
2011-02-13 05:35:13 +00:00
SendMsgEx ( & Msg , MSGFLAG_VITAL , ClientID , true ) ;
2010-10-11 00:39:08 +00:00
2011-02-13 05:35:13 +00:00
m_aClients [ ClientID ] . m_Authed = 1 ;
SendRconLine ( ClientID , " Authentication successful. Remote console access granted. " ) ;
dbg_msg ( " server " , " ClientID=%d authed " , ClientID ) ;
2010-10-11 00:39:08 +00:00
} */
2011-03-16 14:27:30 +00:00
int Level = IConsole : : CONSOLELEVEL_USER ;
if ( str_comp ( pPassword , g_Config . m_SvRconPasswordModer ) = = 0 )
2010-10-11 00:39:08 +00:00
{
2011-03-16 14:27:30 +00:00
Level = IConsole : : CONSOLELEVEL_MODERATOR ;
2010-10-11 00:39:08 +00:00
}
2011-03-16 14:27:30 +00:00
else if ( str_comp ( pPassword , g_Config . m_SvRconPasswordAdmin ) = = 0 )
2010-10-11 00:39:08 +00:00
{
2011-03-16 14:27:30 +00:00
Level = IConsole : : CONSOLELEVEL_ADMIN ;
2010-10-11 00:39:08 +00:00
}
2011-03-16 14:27:30 +00:00
if ( Level > IConsole : : CONSOLELEVEL_USER )
2010-10-11 00:39:08 +00:00
{
2011-02-13 05:35:13 +00:00
char buf [ 128 ] = " Authentication successful. Remote console access granted for ClientID=%d with level=%d " ;
2011-03-16 14:27:30 +00:00
SetRconLevel ( ClientID , Level ) ;
str_format ( buf , sizeof ( buf ) , buf , ClientID , Level ) ;
2011-02-13 05:35:13 +00:00
SendRconLine ( ClientID , buf ) ;
2011-03-16 14:27:30 +00:00
dbg_msg ( " server " , " '%s' ClientID=%d authed with Level=%d " , ClientName ( ClientID ) , ClientID , Level ) ;
2010-10-11 00:39:08 +00:00
}
else if ( g_Config . m_SvRconMaxTries )
{
2011-02-13 05:35:13 +00:00
m_aClients [ ClientID ] . m_AuthTries + + ;
2010-10-11 00:39:08 +00:00
char aBuf [ 128 ] ;
2011-02-13 05:35:13 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Wrong password %d/%d. " , m_aClients [ ClientID ] . m_AuthTries , g_Config . m_SvRconMaxTries ) ;
SendRconLine ( ClientID , aBuf ) ;
if ( m_aClients [ ClientID ] . m_AuthTries > = g_Config . m_SvRconMaxTries )
2010-10-11 00:39:08 +00:00
{
if ( ! g_Config . m_SvRconBantime )
2011-02-13 05:35:13 +00:00
m_NetServer . Drop ( ClientID , " Too many remote console authentication tries " ) ;
2010-10-11 00:39:08 +00:00
else
{
2011-02-13 05:35:13 +00:00
NETADDR Addr = m_NetServer . ClientAddr ( ClientID ) ;
2011-01-06 03:46:10 +00:00
BanAdd ( Addr , g_Config . m_SvRconBantime * 60 , " Too many remote console authentication tries " ) ;
2010-10-11 00:39:08 +00:00
}
}
}
}
}
/*else if(str_comp(pPw, g_Config.m_SvRconPassword) == 0)
{
CMsgPacker Msg ( NETMSG_RCON_AUTH_STATUS ) ;
Msg . AddInt ( 1 ) ;
2011-02-13 05:35:13 +00:00
SendMsgEx ( & Msg , MSGFLAG_VITAL , ClientID , true ) ;
2010-10-11 00:39:08 +00:00
2011-02-13 05:35:13 +00:00
m_aClients [ ClientID ] . m_Authed = 1 ;
SendRconLine ( ClientID , " Authentication successful. Remote console access granted. " ) ;
2010-10-11 00:39:08 +00:00
char aBuf [ 256 ] ;
2011-02-13 05:35:13 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " ClientID=%d authed " , ClientID ) ;
2010-10-11 00:39:08 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
} */
else
{
2011-03-16 14:27:30 +00:00
char aBuf [ 128 ] = " Authentication successful. Remote console access granted for ClientID=%d with level=%d " ;
2011-02-13 05:35:13 +00:00
SetRconLevel ( ClientID , 0 ) ;
2011-03-16 14:27:30 +00:00
str_format ( aBuf , sizeof ( aBuf ) , aBuf , ClientID , 0 ) ;
SendRconLine ( ClientID , aBuf ) ;
2011-02-13 05:35:13 +00:00
dbg_msg ( " server " , " '%s' ClientID=%d authed with Level=%d " , ClientName ( ClientID ) , ClientID , 0 ) ;
2010-10-11 00:39:08 +00:00
}
}
2010-11-22 10:59:25 +00:00
2011-03-16 14:27:30 +00:00
char * CServer : : GetAnnouncementLine ( char const * pFileName )
2010-11-22 10:59:25 +00:00
{
2011-03-16 14:27:30 +00:00
IOHANDLE File = m_pStorage - > OpenFile ( pFileName , IOFLAG_READ , IStorage : : TYPE_ALL ) ;
2010-11-22 10:59:25 +00:00
if ( File )
{
std : : vector < char * > v ;
char * pLine ;
CLineReader * lr = new CLineReader ( ) ;
lr - > Init ( File ) ;
2010-12-07 17:44:23 +00:00
while ( ( pLine = lr - > Get ( ) ) )
2010-11-22 10:59:25 +00:00
if ( str_length ( pLine ) )
2010-12-05 22:38:29 +00:00
if ( pLine [ 0 ] ! = ' # ' )
2010-11-29 04:21:04 +00:00
v . push_back ( pLine ) ;
2010-12-06 02:27:35 +00:00
if ( v . size ( ) = = 1 )
{
m_AnnouncementLastLine = 0 ;
}
else if ( ! g_Config . m_SvAnnouncementRandom )
{
if ( m_AnnouncementLastLine > = v . size ( ) )
m_AnnouncementLastLine % = v . size ( ) ;
}
else
{
2010-12-07 17:44:23 +00:00
unsigned Rand ;
2010-12-06 02:27:35 +00:00
do
Rand = rand ( ) % v . size ( ) ;
while ( Rand = = m_AnnouncementLastLine ) ;
2011-04-09 06:41:31 +00:00
2010-12-06 02:27:35 +00:00
m_AnnouncementLastLine = Rand ;
}
return v [ m_AnnouncementLastLine ] ;
2010-11-22 10:59:25 +00:00
}
return 0 ;
}
2010-12-19 05:25:01 +00:00
2011-02-13 05:35:13 +00:00
void CServer : : ConAddBanmaster ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2011-02-07 06:25:38 +00:00
{
CServer * pServer = ( CServer * ) pUser ;
2011-04-09 06:41:31 +00:00
2011-02-07 06:25:38 +00:00
int Result = pServer - > m_NetServer . BanmasterAdd ( pResult - > GetString ( 0 ) ) ;
2011-04-09 06:41:31 +00:00
2011-02-07 06:25:38 +00:00
if ( Result = = 0 )
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server/banmaster " , " succesfully added banmaster " ) ;
else if ( Result = = 1 )
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server/banmaster " , " invalid address for banmaster / net lookup failed " ) ;
else
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server/banmaster " , " too many banmasters " ) ;
}
2011-02-13 05:35:13 +00:00
void CServer : : ConBanmasters ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2011-02-07 06:25:38 +00:00
{
CServer * pServer = ( CServer * ) pUser ;
int NumBanmasters = pServer - > m_NetServer . BanmasterNum ( ) ;
2011-04-09 06:41:31 +00:00
2011-02-07 06:25:38 +00:00
char aBuf [ 128 ] ;
char aIpString [ 64 ] ;
2011-04-09 06:41:31 +00:00
2011-02-07 06:25:38 +00:00
for ( int i = 0 ; i < NumBanmasters ; i + + )
{
NETADDR * pBanmaster = pServer - > m_NetServer . BanmasterGet ( i ) ;
net_addr_str ( pBanmaster , aIpString , sizeof ( aIpString ) ) ;
str_format ( aBuf , sizeof ( aBuf ) , " %d: %s " , i , aIpString ) ;
pServer - > Console ( ) - > PrintResponse ( IConsole : : OUTPUT_LEVEL_STANDARD , " server/banmaster " , aBuf ) ;
}
}
2011-02-13 05:35:13 +00:00
void CServer : : ConClearBanmasters ( IConsole : : IResult * pResult , void * pUser , int ClientID )
2011-02-07 06:25:38 +00:00
{
CServer * pServer = ( CServer * ) pUser ;
2011-04-09 06:41:31 +00:00
2011-02-07 06:25:38 +00:00
pServer - > m_NetServer . BanmastersClear ( ) ;
}
2011-02-13 05:35:13 +00:00
void CServer : : SendRconResponse ( const char * pLine , void * pUser )
{
RconResponseInfo * pInfo = ( RconResponseInfo * ) pUser ;
CServer * pThis = pInfo - > m_Server ;
static volatile int ReentryGuard = 0 ;
if ( ReentryGuard )
return ;
ReentryGuard + + ;
if ( pThis - > m_aClients [ pInfo - > m_ClientID ] . m_State ! = CClient : : STATE_EMPTY )
pThis - > SendRconLine ( pInfo - > m_ClientID , pLine ) ;
ReentryGuard - - ;
}
void CServer : : ConCmdList ( IConsole : : IResult * pResult , void * pUserData , int ClientID )
{
CServer * pSelf = ( CServer * ) pUserData ;
if ( pResult - > NumArguments ( ) = = 0 )
pSelf - > Console ( ) - > List ( ( pSelf - > m_aClients [ ClientID ] . m_Authed ! = 0 ) ? pSelf - > m_aClients [ ClientID ] . m_Authed : - 1 , CFGFLAG_SERVER ) ;
else if ( pResult - > GetInteger ( 0 ) = = 0 )
pSelf - > Console ( ) - > List ( - 1 , CFGFLAG_SERVER ) ;
else
pSelf - > Console ( ) - > List ( pResult - > GetInteger ( 0 ) , CFGFLAG_SERVER ) ;
}
void CServer : : ConLogin ( IConsole : : IResult * pResult , void * pUser , int ClientID )
{
if ( pResult - > NumArguments ( ) )
( ( CServer * ) pUser ) - > CheckPass ( ClientID , pResult - > GetString ( 0 ) ) ;
else
( ( CServer * ) pUser ) - > SetRconLevel ( ClientID , 0 ) ;
}
bool CServer : : CompareClients ( int ClientLevel , int Victim , void * pUser )
{
CServer * pSelf = ( CServer * ) pUser ;
if ( ! ClientOnline ( Victim , pSelf ) )
return false ;
return clamp ( ClientLevel , 0 , 4 ) > clamp ( pSelf - > m_aClients [ Victim ] . m_Authed , 0 , 4 ) ;
}
bool CServer : : ClientOnline ( int ClientID , void * pUser )
{
CServer * pSelf = ( CServer * ) pUser ;
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS )
return false ;
2011-04-09 06:41:31 +00:00
2011-02-13 05:35:13 +00:00
return pSelf - > m_aClients [ ClientID ] . m_State ! = CClient : : STATE_EMPTY ;
}
void CServer : : SetClientAuthed ( int ClientID , int Level ) {
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | m_aClients [ ClientID ] . m_State = = CClient : : STATE_READY )
{
return ;
}
m_aClients [ ClientID ] . m_Authed = Level ;
}