2008-07-01 11:48:17 +02:00
/**
* vim : set ts = 4 :
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* SourceMod
* Copyright ( C ) 2004 - 2008 AlliedModders LLC . All rights reserved .
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* This program is free software ; you can redistribute it and / or modify it under
* the terms of the GNU General Public License , version 3.0 , as published by the
* Free Software Foundation .
*
* This program 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
* this program . If not , see < http : //www.gnu.org/licenses/>.
*
* As a special exception , AlliedModders LLC gives you permission to link the
* code of this program ( as well as its derivative works ) to " Half-Life 2, " the
* " Source Engine, " the " SourcePawn JIT, " and any Game MODs that run on software
* by the Valve Corporation . You must obey the GNU General Public License in
* all respects for all other code used . Additionally , AlliedModders LLC grants
* this exception to all derivative works . AlliedModders LLC defines further
* exceptions , found in LICENSE . txt ( as of this writing , version JULY - 31 - 2007 ) ,
* or < http : //www.sourcemod.net/license.php>.
*
* Version : $ Id $
*/
# include "GameDataFetcher.h"
# include "bitbuf.h"
# ifdef PLATFORM_WINDOWS
# include <winsock2.h>
# else
# include <unistd.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
# include <arpa/inet.h>
# define INVALID_SOCKET -1
# define closesocket close
# endif
# include "sh_vector.h"
# include "sh_string.h"
# include "sm_version.h"
# ifdef ORANGEBOX_BUILD
# include "convar_sm_ob.h"
# else
# include "convar_sm.h"
# endif
# include "sourcemm_api.h"
# include "time.h"
# include "TimerSys.h"
2008-07-03 08:26:28 +02:00
# include "compat_wrappers.h"
2008-09-02 08:29:50 +02:00
# include "sm_stringutil.h"
2008-07-01 11:48:17 +02:00
# define QUERY_MAX_LENGTH 1024
BuildMD5ableBuffer g_MD5Builder ;
FetcherThread g_FetchThread ;
FILE * logfile = NULL ;
bool g_disableGameDataUpdate = false ;
bool g_restartAfterUpdate = false ;
2008-09-02 08:29:50 +02:00
int g_serverPort = 6500 ;
char g_serverAddress [ 100 ] = " hayate.alliedmods.net " ;
2008-07-01 11:48:17 +02:00
void FetcherThread : : RunThread ( IThreadHandle * pHandle )
{
char lock_path [ PLATFORM_MAX_PATH ] ;
g_SourceMod . BuildPath ( Path_SM , lock_path , sizeof ( lock_path ) , " data/temp " ) ;
g_LibSys . CreateFolder ( lock_path ) ;
g_SourceMod . BuildPath ( Path_SM , lock_path , sizeof ( lock_path ) , " data/temp/gamedata.lock " ) ;
2008-10-19 06:27:54 +02:00
g_Logger . LogMessage ( " Starting Gamedata update fetcher... please report problems to bugs.alliedmods.net " ) ;
2008-07-01 11:48:17 +02:00
char log_path [ PLATFORM_MAX_PATH ] ;
g_SourceMod . BuildPath ( Path_SM , log_path , sizeof ( log_path ) , " logs/gamedata " ) ;
g_LibSys . CreateFolder ( log_path ) ;
time_t t ;
GetAdjustedTime ( & t ) ;
tm * curtime = localtime ( & t ) ;
g_SourceMod . BuildPath ( Path_SM , log_path , sizeof ( log_path ) , " logs/gamedata/L%02d%02d.log " , curtime - > tm_mon + 1 , curtime - > tm_mday ) ;
logfile = fopen ( log_path , " a " ) ;
if ( ! logfile )
{
g_Logger . LogError ( " Failed to create GameData log file " ) ;
return ;
}
//Create a blank lock file
FILE * fp = fopen ( lock_path , " w " ) ;
if ( fp )
{
fclose ( fp ) ;
}
char query [ QUERY_MAX_LENGTH ] ;
/* Check for updated gamedata files */
int len = BuildGameDataQuery ( query , QUERY_MAX_LENGTH ) ;
if ( len = = 0 )
{
g_Logger . LogToOpenFile ( logfile , " Query Writing failed " ) ;
2008-07-02 04:57:08 +02:00
fclose ( logfile ) ;
unlink ( lock_path ) ;
2008-07-01 11:48:17 +02:00
return ;
}
if ( g_disableGameDataUpdate )
{
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogMessage ( " Skipping GameData Query due to DisableAutoUpdate being set to true " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-02 04:57:08 +02:00
fclose ( logfile ) ;
unlink ( lock_path ) ;
2008-07-01 11:48:17 +02:00
return ;
}
2008-10-19 06:27:54 +02:00
/* Create a new socket for this connection */
int socketDescriptor = ConnectSocket ( ) ;
if ( socketDescriptor = = INVALID_SOCKET )
{
fclose ( logfile ) ;
unlink ( lock_path ) ;
return ;
}
int sent = SendData ( socketDescriptor , query , len ) ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Sent Query! " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
if ( sent = = 0 )
{
2008-10-19 06:27:54 +02:00
g_Logger . LogToOpenFile ( logfile , " Failed to send gamedata query data to remote host " ) ;
2008-07-02 04:57:08 +02:00
2008-07-01 11:48:17 +02:00
closesocket ( socketDescriptor ) ;
2008-07-02 04:57:08 +02:00
fclose ( logfile ) ;
unlink ( lock_path ) ;
2008-07-01 11:48:17 +02:00
return ;
}
ProcessGameDataQuery ( socketDescriptor ) ;
/* And we're done! */
closesocket ( socketDescriptor ) ;
fclose ( logfile ) ;
unlink ( lock_path ) ;
}
void FetcherThread : : OnTerminate ( IThreadHandle * pHandle , bool cancel )
{
2008-07-10 03:26:02 +02:00
g_blockGameDataLoad = false ;
2008-07-01 11:48:17 +02:00
}
int FetcherThread : : BuildGameDataQuery ( char * buffer , int maxlen )
{
char gamedata_path [ PLATFORM_MAX_PATH ] ;
g_SourceMod . BuildPath ( Path_SM , gamedata_path , sizeof ( gamedata_path ) , " gamedata " ) ;
IDirectory * dir = g_LibSys . OpenDirectory ( gamedata_path ) ;
if ( dir = = NULL )
{
return 0 ;
}
bf_write Writer = bf_write ( " GameDataQuery " , buffer , maxlen ) ;
Writer . WriteByte ( ' A ' ) ; //Generic Header char
Writer . WriteByte ( ' G ' ) ; //G for gamedata query, or green, like my hat.
short build [ 4 ] = { SVN_FILE_VERSION } ;
Writer . WriteBytes ( & build [ 0 ] , 8 ) ;
Writer . WriteByte ( 0 ) ; // Initialize the file counter - Index 10
while ( dir - > MoreFiles ( ) )
{
if ( dir - > IsEntryFile ( ) )
{
const char * name = dir - > GetEntryName ( ) ;
size_t len = strlen ( name ) ;
if ( len > = 4
& & strcmp ( & name [ len - 4 ] , " .txt " ) = = 0 )
{
char file [ PLATFORM_MAX_PATH ] ;
g_LibSys . PathFormat ( file , sizeof ( file ) , " %s/%s " , gamedata_path , name ) ;
SMCStates states ;
if ( g_TextParser . ParseFile_SMC ( file , & g_MD5Builder , & states ) = = SMCError_Okay )
{
unsigned char * md5 = g_MD5Builder . GetMD5 ( ) ;
if ( md5 ! = NULL )
{
( uint8_t ) buffer [ 10 ] + + ; //Increment the file counter
Writer . WriteBytes ( md5 , 16 ) ;
g_Logger . LogToOpenFile ( logfile , " %s - \" %s \" " , file , g_MD5Builder . GetMD5String ( ) ) ;
FileData * data = new FileData ( ) ;
data - > filename = new SourceHook : : String ( file ) ;
memcpy ( data - > checksum , g_MD5Builder . GetMD5String ( ) , 33 ) ;
filenames . push_back ( data ) ;
}
else
{
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " %s no md5? " , file ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
}
}
else
{
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " %s failed! " , file ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
}
}
}
dir - > NextEntry ( ) ;
}
return Writer . GetNumBytesWritten ( ) ;
}
int FetcherThread : : ConnectSocket ( )
{
struct protoent * ptrp ;
ptrp = getprotobyname ( " tcp " ) ;
# ifdef WIN32
WSADATA wsaData ;
WSAStartup ( 0x0101 , & wsaData ) ;
# endif
if ( ptrp = = NULL )
{
g_Logger . LogToOpenFile ( logfile , " Failed to find TCP " ) ;
return INVALID_SOCKET ;
}
int socketDescriptor = socket ( AF_INET , SOCK_STREAM , ptrp - > p_proto ) ;
if ( socketDescriptor = = INVALID_SOCKET )
{
//bugger aye?
2008-10-19 06:27:54 +02:00
# ifdef WIN32
g_Logger . LogToOpenFile ( logfile , " Failed to create a new socket - Error %i " , WSAGetLastError ( ) ) ;
# else
g_Logger . LogToOpenFile ( logfile , " Failed to create a new socket - Error %i " , errno ) ;
# endif
2008-07-01 11:48:17 +02:00
closesocket ( socketDescriptor ) ;
return INVALID_SOCKET ;
}
struct hostent * he ;
struct sockaddr_in local_addr ;
local_addr . sin_family = AF_INET ;
2008-09-02 08:29:50 +02:00
local_addr . sin_port = htons ( ( u_short ) g_serverPort ) ;
2008-07-01 11:48:17 +02:00
2008-09-02 08:29:50 +02:00
he = gethostbyname ( g_serverAddress ) ;
2008-07-01 11:48:17 +02:00
if ( ! he )
{
2008-09-02 08:29:50 +02:00
if ( ( local_addr . sin_addr . s_addr = inet_addr ( g_serverAddress ) ) = = INADDR_NONE )
2008-07-01 11:48:17 +02:00
{
2008-10-19 06:27:54 +02:00
g_Logger . LogToOpenFile ( logfile , " Couldn't locate address " ) ;
2008-07-01 11:48:17 +02:00
closesocket ( socketDescriptor ) ;
return INVALID_SOCKET ;
}
}
else
{
memcpy ( & local_addr . sin_addr , ( struct in_addr * ) he - > h_addr , he - > h_length ) ;
}
if ( connect ( socketDescriptor , ( struct sockaddr * ) & local_addr , sizeof ( local_addr ) ) < 0 )
{
2008-10-19 06:27:54 +02:00
# ifdef WIN32
g_Logger . LogToOpenFile ( logfile , " Couldn't connect - Error %i " , WSAGetLastError ( ) ) ;
# else
g_Logger . LogToOpenFile ( logfile , " Couldn't connect - Error %i " , errno ) ;
# endif
2008-07-01 11:48:17 +02:00
closesocket ( socketDescriptor ) ;
return INVALID_SOCKET ;
}
return socketDescriptor ;
}
void FetcherThread : : ProcessGameDataQuery ( int socketDescriptor )
{
char buffer [ 50 ] ;
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Waiting for reply! " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
//Read in the header bytes
2008-10-19 06:27:54 +02:00
int returnLen = RecvData ( socketDescriptor , buffer , 12 ) ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Recv Completed " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
if ( returnLen = = 0 )
{
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " ,but it failed. " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
/* Timeout or fail? */
return ;
}
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Received Header! " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
bf_read Reader = bf_read ( " GameDataQuery " , buffer , 12 ) ;
if ( Reader . ReadByte ( ) ! = ' A ' | | Reader . ReadByte ( ) ! = ' G ' )
{
2008-10-19 06:27:54 +02:00
g_Logger . LogToOpenFile ( logfile , " Unknown Query Response " ) ;
2008-07-01 11:48:17 +02:00
return ;
}
UpdateStatus updateStatus = ( UpdateStatus ) Reader . ReadByte ( ) ;
short build [ 4 ] = { 0 , 0 , 0 , 0 } ;
build [ 0 ] = Reader . ReadShort ( ) ;
build [ 1 ] = Reader . ReadShort ( ) ;
build [ 2 ] = Reader . ReadShort ( ) ;
build [ 3 ] = Reader . ReadShort ( ) ;
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Update Status: %i - Latest %i.%i.%i.%i " , updateStatus , build [ 0 ] , build [ 1 ] , build [ 2 ] , build [ 3 ] ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
HandleUpdateStatus ( updateStatus , build ) ;
int changedFiles = Reader . ReadByte ( ) ;
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Files to download: %i " , changedFiles ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
for ( int i = 0 ; i < changedFiles ; i + + )
{
//Read in the file index and byte count
2008-10-19 06:27:54 +02:00
returnLen = RecvData ( socketDescriptor , buffer , 5 ) ;
2008-07-01 11:48:17 +02:00
if ( returnLen = = 0 )
{
/* Timeout or fail? */
return ;
}
Reader . StartReading ( buffer , 5 ) ;
int index = Reader . ReadByte ( ) ;
int tempLen = Reader . ReadUBitLong ( 32 ) ;
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " File index %i and length %i " , index , tempLen ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
void * memPtr ;
memtable - > CreateMem ( tempLen + 1 , & memPtr ) ;
//Read the contents of our file into the memtable
2008-10-19 06:27:54 +02:00
returnLen = RecvData ( socketDescriptor , ( char * ) memPtr , tempLen ) ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Recieved %i bytes " , returnLen ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
if ( returnLen = = 0 )
{
/* Timeout or fail? */
return ;
}
( ( unsigned char * ) memPtr ) [ tempLen ] = ' \0 ' ;
FileData * data = filenames . at ( index ) ;
const char * filename ;
if ( data ! = NULL )
{
filename = data - > filename - > c_str ( ) ;
FILE * fp = fopen ( filename , " w " ) ;
if ( fp )
{
fprintf ( fp , ( const char * ) memPtr ) ;
fclose ( fp ) ;
}
2008-10-19 06:27:54 +02:00
else
{
g_Logger . LogToOpenFile ( logfile , " Failed to open file \" %s \" " , filename ) ;
}
2008-07-01 11:48:17 +02:00
}
else
{
filename = " " ;
}
memtable - > Reset ( ) ;
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Updated File %s " , filename ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
}
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " File Downloads Completed! " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
bool needsRestart = false ;
if ( changedFiles > 0 )
{
needsRestart = true ;
g_Logger . LogMessage ( " New GameData Files have been downloaded to your gamedata directory. Please restart your server for these to take effect " ) ;
}
//Read changed file count
2008-10-19 06:27:54 +02:00
returnLen = RecvData ( socketDescriptor , buffer , 1 ) ;
2008-07-01 11:48:17 +02:00
if ( returnLen = = 0 )
{
/* Timeout or fail? */
g_Logger . LogToOpenFile ( logfile , " Failed to receive unknown count " ) ;
return ;
}
Reader . StartReading ( buffer , 1 ) ;
changedFiles = Reader . ReadByte ( ) ;
if ( changedFiles = = 0 )
{
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " No unknown files. We're all done " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
return ;
}
char * changedFileIndexes = new char [ changedFiles ] ;
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " %i Files were unknown " , changedFiles ) ;
2008-10-19 06:27:54 +02:00
# endif
returnLen = RecvData ( socketDescriptor , changedFileIndexes , changedFiles ) ;
2008-07-01 11:48:17 +02:00
if ( returnLen = = 0 )
{
/* Timeout or fail? */
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Failed to receive unknown list " ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
return ;
}
Reader . StartReading ( changedFileIndexes , changedFiles ) ;
for ( int i = 0 ; i < changedFiles ; i + + )
{
int index = Reader . ReadByte ( ) ;
char fileName [ 30 ] ;
FileData * data = filenames . at ( index ) ;
const char * pathname ;
if ( data ! = NULL )
{
pathname = data - > filename - > c_str ( ) ;
}
else
{
pathname = " " ;
}
g_LibSys . GetFileFromPath ( fileName , sizeof ( fileName ) , pathname ) ;
2008-10-19 06:27:54 +02:00
# ifdef DEBUG
2008-07-01 11:48:17 +02:00
g_Logger . LogToOpenFile ( logfile , " Unknown File %i : %s " , index , fileName ) ;
2008-10-19 06:27:54 +02:00
# endif
2008-07-01 11:48:17 +02:00
}
delete [ ] changedFileIndexes ;
if ( needsRestart & & g_restartAfterUpdate )
{
g_Logger . LogMessage ( " Automatically restarting server after a successful gamedata update! " ) ;
engine - > ServerCommand ( " quit \n " ) ;
}
}
2008-10-19 06:27:54 +02:00
int FetcherThread : : RecvData ( int socketDescriptor , char * buffer , int len )
2008-07-01 11:48:17 +02:00
{
fd_set fds ;
struct timeval tv ;
/* Create a 10 Second Timeout */
tv . tv_sec = 10 ;
tv . tv_usec = 0 ;
2008-10-19 06:27:54 +02:00
int bytesReceivedTotal = 0 ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
while ( bytesReceivedTotal < len )
{
/* Add our socket to a socket set */
FD_ZERO ( & fds ) ;
FD_SET ( socketDescriptor , & fds ) ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
/* Wait max of 10 seconds for recv to become available */
select ( socketDescriptor + 1 , & fds , NULL , NULL , & tv ) ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
int bytesReceived = 0 ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
/* Is there a limit on how much we can receive? Some site said 1024 bytes, which will be well short of a file */
if ( FD_ISSET ( socketDescriptor , & fds ) )
{
2008-10-20 07:42:22 +02:00
bytesReceived = recv ( socketDescriptor , buffer + bytesReceivedTotal , len - bytesReceivedTotal , 0 ) ;
2008-10-19 06:27:54 +02:00
}
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
if ( bytesReceived = = 0 | | bytesReceived = = - 1 )
{
return 0 ;
}
bytesReceivedTotal + = bytesReceived ;
2008-07-01 11:48:17 +02:00
}
2008-10-19 06:27:54 +02:00
return bytesReceivedTotal ;
2008-07-01 11:48:17 +02:00
}
2008-10-19 06:27:54 +02:00
int FetcherThread : : SendData ( int socketDescriptor , char * buffer , int len )
2008-07-01 11:48:17 +02:00
{
fd_set fds ;
struct timeval tv ;
tv . tv_sec = 10 ;
tv . tv_usec = 0 ;
2008-10-19 06:27:54 +02:00
int sentBytesTotal = 0 ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
while ( sentBytesTotal < len )
{
FD_ZERO ( & fds ) ;
FD_SET ( socketDescriptor , & fds ) ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
select ( socketDescriptor + 1 , NULL , & fds , NULL , & tv ) ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
int sentBytes = 0 ;
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
if ( FD_ISSET ( socketDescriptor , & fds ) )
{
2008-10-20 07:42:22 +02:00
sentBytes = send ( socketDescriptor , buffer + sentBytesTotal , len - sentBytesTotal , 0 ) ;
2008-10-19 06:27:54 +02:00
}
2008-07-01 11:48:17 +02:00
2008-10-19 06:27:54 +02:00
if ( sentBytes = = 0 | | sentBytes = = - 1 )
{
return 0 ;
}
sentBytesTotal + = sentBytes ;
2008-07-01 11:48:17 +02:00
}
2008-10-19 06:27:54 +02:00
return sentBytesTotal ;
2008-07-01 11:48:17 +02:00
}
void FetcherThread : : HandleUpdateStatus ( UpdateStatus status , short version [ 4 ] )
{
switch ( status )
{
case Update_Unknown :
case Update_Current :
{
break ;
}
case Update_NewBuild :
{
2008-10-19 06:27:54 +02:00
g_Logger . LogMessage ( " SourceMod Update: A new Mercurial build is available from sourcemod.net " ) ;
2008-07-01 11:48:17 +02:00
g_Logger . LogMessage ( " Current Version: %i.%i.%i.%i Available: %i.%i.%i.%i " , version [ 0 ] , version [ 1 ] , version [ 2 ] , version [ 3 ] , version [ 0 ] , version [ 1 ] , version [ 2 ] , version [ 3 ] ) ;
break ;
}
case Update_MinorAvailable :
{
g_Logger . LogMessage ( " SourceMod Update: An incremental minor release of SourceMod is now available from sourcemod.net " ) ;
g_Logger . LogMessage ( " Current Version: %i.%i.%i Available: %i.%i.%i " , version [ 0 ] , version [ 1 ] , version [ 2 ] , version [ 0 ] , version [ 1 ] , version [ 2 ] ) ;
break ;
}
case Update_MajorAvailable :
{
g_Logger . LogMessage ( " SourceMod Update: An major release of SourceMod is now available from sourcemod.net " ) ;
g_Logger . LogMessage ( " Current Version: %i.%i.%i Available: %i.%i.%i " , version [ 0 ] , version [ 1 ] , version [ 2 ] , version [ 0 ] , version [ 1 ] , version [ 2 ] ) ;
break ;
}
case Update_CriticalAvailable :
{
g_Logger . LogError ( " SourceMod Update: A new critical release of SourceMod is now available from sourcemod.net. It is strongly recommended that you update " ) ;
g_Logger . LogMessage ( " Current Version: %i.%i.%i.%i Available: %i.%i.%i.%i " , version [ 0 ] , version [ 1 ] , version [ 2 ] , version [ 3 ] , version [ 0 ] , version [ 1 ] , version [ 2 ] , version [ 3 ] ) ;
break ;
}
}
}
bool g_blockGameDataLoad = false ;
class InitFetch : public SMGlobalClass
{
public :
void OnSourceModAllInitialized_Post ( )
{
char lock_path [ PLATFORM_MAX_PATH ] ;
g_SourceMod . BuildPath ( Path_SM , lock_path , sizeof ( lock_path ) , " data/temp/gamedata.lock " ) ;
if ( g_LibSys . IsPathFile ( lock_path ) & & g_LibSys . PathExists ( lock_path ) )
{
g_Logger . LogError ( " sourcemod/data/temp/gamedata.lock file detected. This is most likely due to a crash during GameData updating - Blocking GameData loading " ) ;
g_Logger . LogError ( " If this error persists delete the file manually " ) ;
g_blockGameDataLoad = true ;
}
ThreadParams fetchThreadParams = ThreadParams ( ) ;
fetchThreadParams . prio = ThreadPrio_Low ;
g_pThreader - > MakeThread ( & g_FetchThread , & fetchThreadParams ) ;
}
ConfigResult OnSourceModConfigChanged ( const char * key ,
const char * value ,
ConfigSource source ,
char * error ,
size_t maxlength )
{
if ( strcmp ( key , " DisableAutoUpdate " ) = = 0 )
{
if ( strcmp ( value , " yes " ) = = 0 )
{
g_disableGameDataUpdate = true ;
return ConfigResult_Accept ;
}
else if ( strcmp ( value , " no " ) = = 0 )
{
g_disableGameDataUpdate = false ;
return ConfigResult_Accept ;
}
return ConfigResult_Reject ;
}
if ( strcmp ( key , " ForceRestartAfterUpdate " ) = = 0 )
{
if ( strcmp ( value , " yes " ) = = 0 )
{
g_restartAfterUpdate = true ;
return ConfigResult_Accept ;
}
else if ( strcmp ( value , " no " ) = = 0 )
{
g_restartAfterUpdate = false ;
return ConfigResult_Accept ;
}
return ConfigResult_Reject ;
}
2008-09-02 08:29:50 +02:00
if ( strcmp ( key , " AutoUpdateServer " ) = = 0 )
{
UTIL_Format ( g_serverAddress , sizeof ( g_serverAddress ) , " %s " , value ) ;
return ConfigResult_Accept ;
}
if ( strcmp ( key , " AutoUpdatePort " ) = = 0 )
{
int port = atoi ( value ) ;
if ( ! port )
{
return ConfigResult_Reject ;
}
g_serverPort = port ;
return ConfigResult_Accept ;
}
2008-07-01 11:48:17 +02:00
return ConfigResult_Ignore ;
}
} g_InitFetch ;
CON_COMMAND ( sm_gamedata_md5 , " Checks the MD5 sum for a given gamedata file " )
{
# if !defined ORANGEBOX_BUILD
CCommand args ;
# endif
if ( args . ArgC ( ) < 2 )
{
g_SMAPI - > ConPrint ( " Usage: sm_gamedata_md5 <file> \n " ) ;
return ;
}
const char * file = args . Arg ( 1 ) ;
if ( ! file | | file [ 0 ] = = ' \0 ' )
{
g_SMAPI - > ConPrint ( " Usage: sm_gamedata_md5 <file> \n " ) ;
return ;
}
SourceHook : : CVector < FileData * > : : iterator iter = g_FetchThread . filenames . begin ( ) ;
FileData * curData ;
while ( iter ! = g_FetchThread . filenames . end ( ) )
{
curData = ( * iter ) ;
char fileName [ 30 ] ;
g_LibSys . GetFileFromPath ( fileName , sizeof ( fileName ) , curData - > filename - > c_str ( ) ) ;
if ( strcmpi ( fileName , file ) = = 0 )
{
g_SMAPI - > ConPrintf ( " MD5 Sum: %s \n " , curData - > checksum ) ;
return ;
}
iter + + ;
}
g_SMAPI - > ConPrint ( " File not found! \n " ) ;
}