2014-03-15 16:59:03 +00:00
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright (C) 2000 by DooM Legacy Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// 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.
//
//-----------------------------------------------------------------------------
# ifdef __GNUC__
# include <unistd.h>
# include <sys/types.h>
# endif
# include <typeinfo>
# include <string.h>
# include <stdarg.h>
# include "ipcs.h"
# include "common.h"
# include "mysql.h"
# include "md5.h"
# include <time.h>
//#include <netdb.h>
//=============================================================================
# ifdef __GNUC__
# define ATTRPACK __attribute__ ((packed))
# else
# define ATTRPACK
# endif
# define PT_ASKINFOVIAMS 15
static CServerSocket server_socket ;
FILE * logfile ;
FILE * errorfile ;
FILE * mysqlfile ;
FILE * sockfile ;
FILE * pidfile ;
# if defined(_MSC_VER)
# pragma pack(1)
# endif
typedef struct
{
char ip [ 16 ] ; // Big enough to hold a full address.
UINT16 port ;
UINT8 padding1 [ 2 ] ;
UINT32 time ;
} ATTRPACK ms_holepunch_packet_t ;
typedef struct
{
char clientaddr [ 22 ] ;
UINT8 padding1 [ 2 ] ;
UINT32 time ;
} ATTRPACK msaskinfo_pak ;
//
// SRB2 network packet data.
//
typedef struct
{
UINT32 checksum ;
UINT8 ack ; // if not null the node asks for acknowledgement, the receiver must resend the ack
UINT8 ackreturn ; // the return of the ack number
UINT8 packettype ;
UINT8 reserved ; // padding
msaskinfo_pak msaskinfo ;
} ATTRPACK doomdata_t ;
# if defined(_MSC_VER)
# pragma pack()
# endif
//=============================================================================
2020-03-20 14:12:19 +00:00
# define HOSTNAME "localhost"
2014-03-15 16:59:03 +00:00
# define USER "srb2_ms"
# define PASSWORD "gLRDRb7WgLRDRb7W"
# define DATABASE "srb2_ms"
// MySQL Stuff :D
const char * server = HOSTNAME ;
const char * user = USER ;
const char * password = PASSWORD ;
const char * database = DATABASE ;
time_t lastupdate ;
MYSQL * conn ;
MYSQL_RES * res ;
MYSQL_ROW row ;
int mysqlconnected = 0 ;
/*
char * str_replace ( char * t1 , char * t2 , char * t6 )
{
char * t4 ;
char * t5 = new ( 0 ) ;
while ( strstr ( t6 , t1 ) ) {
t4 = strstr ( t6 , t1 ) ;
strncpy ( t5 + strlen ( t5 ) , t6 , t4 - t6 ) ;
strcat ( t5 , t2 ) ;
t4 + = strlen ( t1 ) ;
t6 = t4 ;
}
return strcat ( t5 , t4 ) ;
}
*/
/*
// Cue was here
char * str_quakeformat ( char * msg )
{
char * quakemsg , * quakemsg1 , * quakemsg2 ;
char * quakemsg3 , * quakemsg4 , * quakemsg5 ;
char * quakemsg6 , * quakemsg7 , * quakemsg8 ;
quakemsg1 = new ( sizeof ( char ) * ( strlen ( msg ) + 1 ) ) ;
strcpy ( quakemsg1 , msg ) ;
quakemsg2 = str_replace ( " ^1 " , " \x81 " , quakemsg1 ) ;
quakemsg3 = str_replace ( " ^2 " , " \x82 " , quakemsg2 ) ;
quakemsg4 = str_replace ( " ^3 " , " \x83 " , quakemsg3 ) ;
quakemsg5 = str_replace ( " ^4 " , " \x84 " , quakemsg4 ) ;
quakemsg6 = str_replace ( " ^5 " , " \x85 " , quakemsg5 ) ;
quakemsg7 = str_replace ( " ^6 " , " \x86 " , quakemsg6 ) ;
quakemsg8 = str_replace ( " ^7 " , " \x87 " , quakemsg7 ) ;
quakemsg = str_replace ( " ^0 " , " \x80 " , quakemsg8 ) ;
delete ( quakemsg1 ) ;
delete ( quakemsg2 ) ;
delete ( quakemsg3 ) ;
delete ( quakemsg4 ) ;
delete ( quakemsg5 ) ;
delete ( quakemsg6 ) ;
delete ( quakemsg7 ) ;
delete ( quakemsg8 ) ;
return quakemsg ;
}
*/
void MySQL_Conn ( bool force ) {
//if(mysql_ping(conn))
//mysqlconnected = 0;
logPrintf ( mysqlfile , " Trying to connect to MySQL... \n " ) ;
if ( mysqlconnected ! = 1 | | force ) {
if ( force )
mysql_close ( conn ) ;
const char * server = HOSTNAME ;
const char * user = USER ;
const char * password = PASSWORD ;
const char * database = DATABASE ;
conn = mysql_init ( NULL ) ;
/* Connect to database */
if ( ! mysql_real_connect ( conn , server ,
user , password , database , 8219 , NULL , 0 ) ) {
logPrintf ( errorfile , " %s \n " , mysql_error ( conn ) ) ;
}
conn = mysql_init ( NULL ) ;
/* Connect to database */
if ( ! mysql_real_connect ( conn , server , user , password , database , 0 , NULL , 0 ) ) {
logPrintf ( errorfile , " %s \n " , mysql_error ( conn ) ) ;
mysqlconnected = 0 ;
} else {
logPrintf ( mysqlfile , " Connection to MySQL Database successful! \n " ) ;
mysqlconnected = 1 ;
}
}
}
static int MySQL_CheckBan ( const char * ip , UINT32 id , bool sendinfo , bool type ) {
msg_t msg ;
int writecode ;
MySQL_Conn ( false ) ;
msg . id = id ;
char banqueryp1 [ 500 ] = " SELECT bid,INET_NTOA(ipstart),INET_NTOA(ipend),DATE_FORMAT(FROM_UNIXTIME(full_endtime),'%%a %%b %%e %%Y at %%k:%%i (CDT)'),reason,hostonly,permanent FROM ms_bans WHERE INET_ATON('%s') BETWEEN `ipstart` AND `ipend` AND (`full_endtime` > %ld OR `permanent` = '1') LIMIT 1 " ;
// char exqueryp1[500] = "SELECT * FROM ms_exceptions WHERE `ip` = '%s' AND `bid` = '%s' LIMIT 1";
// char exquery[500];
char banquery [ 500 ] ;
// char bid[5];
time_t current_time = time ( NULL ) ;
sprintf ( banquery , banqueryp1 , ip , current_time ) ;
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , banquery ) ;
if ( mysql_query ( conn , banquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
return false ;
} else {
res = mysql_store_result ( conn ) ;
if ( mysql_num_rows ( res ) > = 1 ) {
logPrintf ( logfile , " We got a ban coming on! \n " ) ;
row = mysql_fetch_row ( res ) ;
if ( ! type & & strcmp ( row [ 5 ] , " 1 " ) = = 0 )
return false ;
if ( sendinfo )
{
logPrintf ( logfile , " And we're meant to tell them some more! \n " ) ;
msg_ban_t * info = ( msg_ban_t * ) msg . buffer ;
info - > header [ 0 ] = ' \0 ' ;
logPrintf ( logfile , " Got Ban: %s - %s, ends %s, for %s \n " , row [ 1 ] , row [ 2 ] , row [ 3 ] , row [ 4 ] ) ;
logPrintf ( logfile , " COPY: ipstart \n " ) ;
strcpy ( info - > ipstart , row [ 1 ] ) ;
logPrintf ( logfile , " COPY: ipend \n " ) ;
strcpy ( info - > ipend , row [ 2 ] ) ;
logPrintf ( logfile , " COPY: endtime \n " ) ;
if ( strcmp ( row [ 6 ] , " 0 " ) = = 0 )
{
logPrintf ( logfile , " COPY: It's not permanent. \n " ) ;
strcpy ( info - > endstamp , row [ 3 ] ) ;
}
else
{
logPrintf ( logfile , " COPY: It's permanent. \n " ) ;
strcpy ( info - > endstamp , " Never " ) ;
}
logPrintf ( logfile , " COPY: reason \n " ) ;
strcpy ( info - > reason , row [ 4 ] ) ;
logPrintf ( logfile , " COPY: hostonly \n " ) ;
if ( strcmp ( row [ 5 ] , " 0 " ) = = 0 )
info - > hostonly = false ;
else
info - > hostonly = true ;
if ( info - > hostonly )
logPrintf ( logfile , " BAN HAMMER: %s - %s || Reason: %s || Endstamp: %s || HOSTONLY \n " , info - > ipstart , info - > ipend , info - > reason , info - > endstamp ) ;
else
logPrintf ( logfile , " BAN HAMMER: %s - %s || Reason: %s || Endstamp: %s || NOTHOSTONLY \n " , info - > ipstart , info - > ipend , info - > reason , info - > endstamp ) ;
mysql_free_result ( res ) ;
msg . type = GET_BANNED_MSG ;
msg . length = sizeof ( msg_ban_t ) ;
msg . room = 0 ;
logPrintf ( logfile , " Sending message? \n " ) ;
writecode = server_socket . write ( & msg ) ;
logPrintf ( logfile , " Message sent! :D \n " ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d "
" deleted \n " , writecode , id ) ;
return true ;
}
}
return true ;
} else {
mysql_free_result ( res ) ;
return false ;
}
}
}
int MySQL_CheckRoom ( UINT32 room )
{
MySQL_Conn ( false ) ;
char checkqueryp1 [ 500 ] = " SELECT private FROM `ms_rooms` WHERE `room_id` = '%d' AND `private` = '1' LIMIT 1 " ;
char checkquery [ 500 ] ;
sprintf ( checkquery , checkqueryp1 , room ) ;
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , checkquery ) ;
if ( mysql_query ( conn , checkquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
return false ;
} else {
res = mysql_store_result ( conn ) ;
if ( mysql_num_rows ( res ) < 1 )
return true ;
else
return false ;
}
}
void MySQL_AddServer ( const char * ip , const char * port , const char * name , const char * version , UINT32 room , bool firstadd , const char * key ) {
char escapedName [ 255 ] ;
char escapedPort [ 10 ] ;
char escapedVersion [ 10 ] ;
char escapedKey [ 32 ] ;
char insertquery [ 5000 ] ;
char checkquery [ 500 ] ;
char updatequery [ 5000 ] ;
char queryp1 [ 5000 ] = " INSERT INTO `ms_servers` (`name`,`ip`,`port`,`version`,`timestamp`,`room`,`key`) VALUES ('%s','%s','%s','%s','%ld','%d','%s') " ;
2020-05-04 06:38:38 +00:00
char checkqueryp1 [ 500 ] = " SELECT room_override FROM `ms_servers` WHERE `ip` = '%s' AND `port` = '%s' " ;
2014-03-15 16:59:03 +00:00
char updatequeryp1 [ 5000 ] ;
if ( firstadd )
{
logPrintf ( logfile , " First add. \n " ) ;
2020-05-04 06:38:38 +00:00
strcpy ( updatequeryp1 , " UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `delisted` = '0', `key` = '%s' WHERE `ip` = '%s' AND `port` = '%s' " ) ;
2014-03-15 16:59:03 +00:00
}
else
{
logPrintf ( logfile , " Update ping. \n " ) ;
2020-05-04 06:38:38 +00:00
strcpy ( updatequeryp1 , " UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `key` = '%s' WHERE `ip` = '%s' AND `port` = '%s' AND `delisted` = '0' " ) ;
2014-03-15 16:59:03 +00:00
}
MySQL_Conn ( false ) ;
mysql_real_escape_string ( conn , escapedName , name , ( unsigned long ) strlen ( name ) ) ;
mysql_real_escape_string ( conn , escapedPort , port , ( unsigned long ) strlen ( port ) ) ;
mysql_real_escape_string ( conn , escapedVersion , version , ( unsigned long ) strlen ( version ) ) ;
mysql_real_escape_string ( conn , escapedKey , key , ( unsigned long ) strlen ( key ) ) ;
if ( ! MySQL_CheckBan ( ip , 0 , false , 1 ) ) {
if ( ! MySQL_CheckRoom ( room ) )
{
logPrintf ( errorfile , " IP %s tried to use the private room %d! THIS SHOULD NOT HAPPEN \n " , ip , room ) ;
return ;
}
2020-05-04 06:38:38 +00:00
sprintf ( checkquery , checkqueryp1 , ip , port ) ;
2014-03-15 16:59:03 +00:00
time_t timestamp ;
timestamp = time ( NULL ) ;
2020-05-04 06:38:38 +00:00
logPrintf ( logfile , " Checking for existing servers in table with the same IP and port... \n " ) ;
2014-03-15 16:59:03 +00:00
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , checkquery ) ;
if ( mysql_query ( conn , checkquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
res = mysql_store_result ( conn ) ;
logPrintf ( logfile , " Found %d rows... \n " , mysql_num_rows ( res ) ) ;
if ( mysql_num_rows ( res ) < 1 ) {
mysql_free_result ( res ) ;
logPrintf ( logfile , " Adding the temporary server: %s:%s || Name: %s || Version: %s || Time: %ld || Room: %d || Key: %s \n " , ip , port , name , version , timestamp , room , key ) ;
sprintf ( insertquery , queryp1 , escapedName , ip , escapedPort , escapedVersion , timestamp , room , escapedKey ) ;
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , insertquery ) ;
if ( mysql_query ( conn , insertquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
logPrintf ( logfile , " Server added successfully! \n " ) ;
}
} else {
row = mysql_fetch_row ( res ) ;
if ( atoi ( row [ 0 ] ) ! = 0 )
room = atoi ( row [ 0 ] ) ;
mysql_free_result ( res ) ;
2020-05-04 06:44:49 +00:00
logPrintf ( logfile , " Server's IP and port already exists, so let's just update it instead... \n " ) ;
2014-03-15 16:59:03 +00:00
logPrintf ( logfile , " Updating Server Data for %s \n " , ip ) ;
2020-05-04 06:38:38 +00:00
sprintf ( updatequery , updatequeryp1 , escapedName , escapedPort , escapedVersion , timestamp , room , escapedKey , ip , port ) ;
2014-03-15 16:59:03 +00:00
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , updatequery ) ;
if ( mysql_query ( conn , updatequery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
logPrintf ( logfile , " Server status for Server: %s:%s || Name: %s || Version: %s || Time: %ld || Room: %d || Key: %s set successfully. \n " , ip , port , name , version , timestamp , room , key ) ;
}
}
}
} else {
logPrintf ( logfile , " IP %s is banned so do nothing. \n " , ip ) ;
}
}
void MySQL_ListServers ( UINT32 id , UINT32 type , const char * ip , UINT32 room ) {
msg_t msg ;
int writecode ;
MySQL_Conn ( false ) ;
msg . id = id ;
msg . type = type ;
char servquery [ 1000 ] ;
if ( room = = 0 )
sprintf ( servquery , " SELECT ip, port, name, version FROM ( SELECT * FROM `ms_servers` WHERE `upnow` = '1' ORDER BY `sid` ASC) as t2 ORDER BY `sticky` DESC " ) ;
else
{
char servqueryp1 [ 1000 ] = " SELECT ip, port, name, version FROM ( SELECT * FROM `ms_servers` WHERE `upnow` = '1' AND `room` = '%d' ORDER BY `sid` ASC) as t2 ORDER BY `sticky` DESC " ;
sprintf ( servquery , servqueryp1 , room ) ;
}
if ( ! MySQL_CheckBan ( ip , 0 , false , 0 ) ) {
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , servquery ) ;
if ( mysql_query ( conn , servquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
res = mysql_store_result ( conn ) ;
logPrintf ( logfile , " Found %d servers... \n " , mysql_num_rows ( res ) ) ;
while ( ( row = mysql_fetch_row ( res ) ) ! = NULL )
{
msg_server_t * info = ( msg_server_t * ) msg . buffer ;
info - > header [ 0 ] = ' \0 ' ; // nothing interresting in it (for now)
strcpy ( info - > ip , row [ 0 ] ) ;
strcpy ( info - > port , row [ 1 ] ) ;
strcpy ( info - > name , row [ 2 ] ) ;
strcpy ( info - > version , row [ 3 ] ) ;
msg . length = sizeof ( msg_server_t ) ;
msg . room = 0 ;
logPrintf ( logfile , " Sending message? \n " ) ;
writecode = server_socket . write ( & msg ) ;
logPrintf ( logfile , " Message sent! :D \n " ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d "
" deleted \n " , writecode , id ) ;
return ;
}
}
mysql_free_result ( res ) ;
}
} else {
logPrintf ( logfile , " IP %s is banned so do nothing. \n " , ip ) ;
}
}
void MySQL_ListRooms ( UINT32 id , UINT32 type , const char * ip , bool sendtype ) {
msg_t msg ;
int writecode ;
//(void)ip;
MySQL_Conn ( false ) ;
msg . id = id ;
msg . type = type ;
char roomquery [ 1000 ] ;
logPrintf ( logfile , " Check their ban status first... (ID %d) \n " , id ) ;
if ( MySQL_CheckBan ( ip , id , true , sendtype ) )
return ;
//Hmph! I suppose it'll be up to me to handle this. ~Inuyasha
if ( sendtype )
{
char overridequery [ 500 ] ;
sprintf ( overridequery , " SELECT room_override FROM `ms_servers` WHERE `ip` = '%s' AND `room_override` > 0 " , ip ) ;
logPrintf ( mysqlfile , " Checking for room overrides! Executing MySQL Query: %s \n " , overridequery ) ;
if ( mysql_query ( conn , overridequery ) )
{
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
return ;
}
res = mysql_store_result ( conn ) ;
if ( mysql_num_rows ( res ) > = 1 )
{
int overriddenRoom ;
row = mysql_fetch_row ( res ) ;
overriddenRoom = atoi ( row [ 0 ] ) ;
mysql_free_result ( res ) ;
sprintf ( roomquery , " SELECT room_id, title, motd FROM `ms_rooms` WHERE `room_id` = '%d' LIMIT 1 " , overriddenRoom ) ;
if ( mysql_query ( conn , roomquery ) )
{
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
return ;
}
res = mysql_store_result ( conn ) ;
if ( mysql_num_rows ( res ) > = 1 )
{
msg_rooms_t * info = ( msg_rooms_t * ) msg . buffer ;
char roommotd [ 300 ] ;
row = mysql_fetch_row ( res ) ;
info - > header [ 0 ] = ' \0 ' ; // nothing interesting in it (for now)
strcpy ( info - > name , row [ 1 ] ) ;
// Just in case, let's make sure we don't overflow.
sprintf ( roommotd , " \x85 Your server has had a room override applied to it, so this is the only room you may host in. \x80 \n \n %s " , row [ 2 ] ) ;
strncpy ( info - > motd , roommotd , 255 ) ;
info - > motd [ 255 ] = ' \0 ' ;
info - > id = atoi ( row [ 0 ] ) ;
logPrintf ( logfile , " Sending Room %s with ID %d and MOTD %s \n " , info - > name , info - > id , info - > motd ) ;
msg . length = sizeof ( msg_rooms_t ) ;
msg . room = 0 ;
logPrintf ( logfile , " Sending message? \n " ) ;
writecode = server_socket . write ( & msg ) ;
logPrintf ( logfile , " Message sent! :D \n " ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d "
" deleted \n " , writecode , id ) ;
}
mysql_free_result ( res ) ;
return ;
}
else
{
logPrintf ( errorfile , " Someone's room override isn't set correctly! Room %d doesn't exist! " , overriddenRoom ) ;
mysql_free_result ( res ) ;
}
}
}
if ( sendtype )
sprintf ( roomquery , " SELECT room_id, title, motd FROM `ms_rooms` WHERE `private` = '0' AND `visible` = '1' ORDER BY `order` ASC " ) ;
else
sprintf ( roomquery , " SELECT room_id, title, motd FROM `ms_rooms` WHERE `visible` = '1' ORDER BY `order` ASC " ) ;
if ( mysql_query ( conn , roomquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else
{
res = mysql_store_result ( conn ) ;
logPrintf ( logfile , " Found %d rooms... \n " , mysql_num_rows ( res ) ) ;
while ( ( row = mysql_fetch_row ( res ) ) ! = NULL )
{
msg_rooms_t * info = ( msg_rooms_t * ) msg . buffer ;
info - > header [ 0 ] = ' \0 ' ; // nothing interresting in it (for now)
strcpy ( info - > name , row [ 1 ] ) ;
strcpy ( info - > motd , row [ 2 ] ) ;
info - > id = atoi ( row [ 0 ] ) ;
logPrintf ( logfile , " Sending Room %s with ID %d and MOTD %s \n " , info - > name , info - > id , info - > motd ) ;
msg . length = sizeof ( msg_rooms_t ) ;
msg . room = 0 ;
logPrintf ( logfile , " Sending message? \n " ) ;
writecode = server_socket . write ( & msg ) ;
logPrintf ( logfile , " Message sent! :D \n " ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d "
" deleted \n " , writecode , id ) ;
return ;
}
}
mysql_free_result ( res ) ;
}
}
void MySQL_CheckVersion ( UINT32 id , UINT32 type , const char * ip , UINT32 modid , const char * modversion ) {
msg_t msg ;
int writecode ;
( void ) ip ;
MySQL_Conn ( false ) ;
msg . id = id ;
msg . type = type ;
char versionquery [ 1000 ] ;
sprintf ( versionquery , " SELECT * FROM `ms_versions` WHERE `mod_id` = '%d' AND `mod_version` > %s LIMIT 1 " , modid , modversion ) ;
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , versionquery ) ;
if ( mysql_query ( conn , versionquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else
{
res = mysql_store_result ( conn ) ;
if ( mysql_num_rows ( res ) < 1 )
{
logPrintf ( logfile , " Buffer to NULL \n " ) ;
strcpy ( msg . buffer , " NULL " ) ;
}
else
{
row = mysql_fetch_row ( res ) ;
logPrintf ( logfile , " Version found: %s || Codebase: %s || Version: %s || Version String: %s || Mod ID: %s \n " , row [ 4 ] , row [ 3 ] , row [ 1 ] , row [ 2 ] , row [ 0 ] ) ;
strcpy ( msg . buffer , row [ 2 ] ) ;
}
msg . length = sizeof msg . buffer ;
msg . room = 0 ;
logPrintf ( logfile , " Sending message? \n " ) ;
writecode = server_socket . write ( & msg ) ;
logPrintf ( logfile , " Message sent! :D \n " ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d "
" deleted \n " , writecode , id ) ;
return ;
}
mysql_free_result ( res ) ;
}
}
void MySQL_ListServServers ( UINT32 id , UINT32 type , const char * ip ) {
msg_t msg ;
int writecode ;
static char str [ 1024 ] ;
//char banqueryp1[500] = "SELECT reason,name,FROM_UNIXTIME(endtime) FROM ms_bans WHERE INET_ATON('%s') BETWEEN `ipstart` AND `ipend` AND `endtime` < %ld LIMIT 1";
//char banquery[500];
//time_t current_time = time (NULL);
char servquery [ 1000 ] = " SELECT ip, port, name, version, permanent FROM ( SELECT * FROM `ms_servers` WHERE `upnow` = '1' OR `permanent` = '1' ORDER BY `sid` ASC) as ms_servers ORDER BY `sticky` DESC " ;
MySQL_Conn ( false ) ;
if ( ! MySQL_CheckBan ( ip , 0 , false , 0 ) ) {
msg . id = id ;
msg . type = type ;
msg . room = 0 ;
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , servquery ) ;
if ( mysql_query ( conn , servquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
res = mysql_store_result ( conn ) ;
logPrintf ( logfile , " Found %d servers... \n " , mysql_num_rows ( res ) ) ;
while ( ( row = mysql_fetch_row ( res ) ) ! = NULL )
{
if ( strcmp ( row [ 4 ] , " 0 " ) = = 1 )
snprintf ( str , sizeof str , " IP \t \t : %s \n Port \t \t : %s \n Hostname \t : %s \n Version \t \t : %s \n Permanent \t : %s \n " , row [ 0 ] , row [ 1 ] , row [ 2 ] , row [ 3 ] , " Yes " ) ;
else
snprintf ( str , sizeof str , " IP \t \t : %s \n Port \t \t : %s \n Hostname \t : %s \n Version \t \t : %s \n Permanent \t : %s \n " , row [ 0 ] , row [ 1 ] , row [ 2 ] , row [ 3 ] , " No " ) ;
msg . length = ( INT32 ) ( strlen ( str ) + 1 ) ; // send also the '\0'
strcpy ( msg . buffer , str ) ;
dbgPrintf ( CYAN , " Writing: (%d) \n %s \n " , msg . length , msg . buffer ) ;
writecode = server_socket . write ( & msg ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d deleted \n " , writecode , id ) ;
return ;
}
}
mysql_free_result ( res ) ;
}
} else {
logPrintf ( logfile , " IP %s is banned so do nothing! Let them find out for themselves. \n " , ip ) ;
}
}
void MySQL_RemoveServer ( char * ip , char * port , char * name , char * version ) {
char escapedName [ 255 ] ;
char updatequery [ 5000 ] ;
2020-05-04 06:38:38 +00:00
char updatequeryp1 [ 5000 ] = " UPDATE `ms_servers` SET upnow = '0' WHERE `ip` = '%s' AND `port` = '%s' AND `permanent` = '0' " ;
2014-03-15 16:59:03 +00:00
MySQL_Conn ( false ) ;
mysql_real_escape_string ( conn , escapedName , name , ( unsigned long ) strlen ( name ) ) ;
2020-05-04 06:38:38 +00:00
sprintf ( updatequery , updatequeryp1 , ip , port ) ;
2014-03-15 16:59:03 +00:00
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , updatequery ) ;
if ( mysql_query ( conn , updatequery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
logPrintf ( logfile , " Server: %s:%s || Name: %s || Version: %s removed successfully. \n " , ip , port , name , version ) ;
}
}
/* LIVE FUNCTIONS */
void LIVE_AuthUser ( UINT32 id , char * buffer )
{
msg_live_auth_t * auth ;
char escapedName [ 255 ] ;
char saltedPassword [ 62 ] ;
char hashedPassword [ 34 ] ;
char namequery [ 1000 ] ;
char namequeryp1 [ 1000 ] = " SELECT username,userid,salt,password FROM `user` WHERE `username` = '%s' LIMIT 1 " ;
char userquery [ 1000 ] ;
char userqueryp1 [ 1000 ] = " SELECT userid,username,live_authkey,live_publickey FROM `user` WHERE `userid` = '%s' LIMIT 1 " ;
msg_t msg2 ;
char ip [ 32 ] ;
int writecode ;
msg2 . type = LIVE_INVALID_USER ;
auth = ( msg_live_auth_t * ) buffer ;
logPrintf ( logfile , " Got User %s Pass %s \n " , auth - > username , auth - > password ) ;
// retrieve the true ip of the server
strcpy ( ip , server_socket . getClientIP ( id ) ) ;
MySQL_Conn ( false ) ;
msg2 . id = id ;
logPrintf ( logfile , " Check their ban status first... (ID %d) \n " , id ) ;
if ( MySQL_CheckBan ( ip , 0 , false , 0 ) )
return ;
mysql_real_escape_string ( conn , escapedName , auth - > username , ( unsigned long ) strlen ( auth - > username ) ) ;
sprintf ( namequery , namequeryp1 , escapedName ) ;
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , namequery ) ;
if ( mysql_query ( conn , namequery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
res = mysql_store_result ( conn ) ;
if ( mysql_num_rows ( res ) < 1 )
{
logPrintf ( logfile , " Invalid user: %s \n " , auth - > username ) ;
msg2 . type = LIVE_INVALID_USER ;
}
else
{
row = mysql_fetch_row ( res ) ;
sprintf ( saltedPassword , " %s%s " , auth - > password , row [ 2 ] ) ;
logPrintf ( logfile , " Pre-hash: %s (Salt is %s) \n " , saltedPassword , row [ 2 ] ) ;
sprintf ( hashedPassword , md5 ( saltedPassword ) . c_str ( ) ) ;
logPrintf ( logfile , " Got Hashed Password: %s \n " , hashedPassword ) ;
if ( strcmp ( hashedPassword , row [ 3 ] ) ! = 0 )
{
msg2 . type = LIVE_INVALID_USER ;
logPrintf ( logfile , " INVALID USER! \n " ) ;
} else {
msg2 . type = LIVE_SEND_USER ;
sprintf ( userquery , userqueryp1 , row [ 1 ] ) ;
mysql_free_result ( res ) ;
logPrintf ( mysqlfile , " Executing MySQL Query: %s \n " , userquery ) ;
if ( mysql_query ( conn , userquery ) ) {
logPrintf ( errorfile , " MYSQL ERROR: %s \n " , mysql_error ( conn ) ) ;
MySQL_Conn ( true ) ;
} else {
res = mysql_store_result ( conn ) ;
if ( mysql_num_rows ( res ) < 1 )
{
logPrintf ( errorfile , " User Information Error, invalid USER ID! \n " ) ;
msg2 . type = LIVE_INVALID_USER ;
} else {
row = mysql_fetch_row ( res ) ;
msg_live_user_t * user = ( msg_live_user_t * ) msg2 . buffer ;
user - > header [ 0 ] = ' \0 ' ; // nothing interresting in it (for now)
user - > uid = atoi ( row [ 0 ] ) ;
strcpy ( user - > username , row [ 1 ] ) ;
logPrintf ( logfile , " Found user: %s, id %s \n " , row [ 1 ] , row [ 0 ] ) ;
logPrintf ( logfile , " Sending User %s with ID %d \n " , user - > username , user - > uid ) ;
msg2 . length = sizeof ( msg_live_user_t ) ;
}
}
}
}
}
msg2 . length = sizeof msg2 . buffer ;
msg2 . room = 0 ;
logPrintf ( logfile , " Sending message? \n " ) ;
writecode = server_socket . write ( & msg2 ) ;
logPrintf ( logfile , " Message sent! :D \n " ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d "
" deleted \n " , writecode , id ) ;
return ;
}
mysql_free_result ( res ) ;
}
/*
* * sendServersInformations ( )
*/
static void sendServersInformations ( UINT32 id , UINT32 room )
{
msg_t msg ;
int writecode ;
char ip [ 16 ] ;
strcpy ( ip , server_socket . getClientIP ( id ) ) ;
( void ) room ;
logPrintf ( logfile , " Sending servers informations \n " ) ;
msg . id = id ;
msg . type = SEND_SERVER_MSG ;
msg . room = 0 ;
MySQL_ListServServers ( id , SEND_SERVER_MSG , ip ) ; // Awesome new MySQL Code!
msg . length = 0 ;
//dbgPrintf(CYAN, "Writing: (%d) %s\n", msg.length, "");
writecode = server_socket . write ( & msg ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d deleted \n " ,
writecode , id ) ;
}
}
/*
* * sendShortServersInformations ( )
*/
static void sendShortServersInformations ( UINT32 id , UINT32 room )
{
msg_t msg ;
int writecode ;
char ip [ 16 ] ;
strcpy ( ip , server_socket . getClientIP ( id ) ) ;
logPrintf ( logfile , " Sending short servers informations \n " ) ;
msg . id = id ;
msg . type = SEND_SHORT_SERVER_MSG ;
MySQL_ListServers ( id , SEND_SHORT_SERVER_MSG , ip , room ) ; // New code that's full of win!
logPrintf ( logfile , " Packet Room: %d \n " , room ) ;
msg . length = 0 ;
writecode = server_socket . write ( & msg ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d deleted \n " ,
writecode , id ) ;
}
}
/*
* * sendRoomInformations ( )
*/
static void sendRoomInformations ( UINT32 id , UINT32 room , bool type )
{
msg_t msg ;
int writecode ;
char ip [ 16 ] ;
strcpy ( ip , server_socket . getClientIP ( id ) ) ;
( void ) room ;
logPrintf ( logfile , " Sending room information \n " ) ;
msg . id = id ;
msg . type = SEND_ROOMS_MSG ;
msg . room = 0 ;
MySQL_ListRooms ( id , SEND_ROOMS_MSG , ip , type ) ; // New code that's full of win!
msg . length = 0 ;
writecode = server_socket . write ( & msg ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d deleted \n " ,
writecode , id ) ;
}
}
/*
* * sendVersionInformations ( )
*/
static void sendVersionInformations ( UINT32 id , UINT32 modid , char * modversion )
{
msg_t msg ;
int writecode ;
char ip [ 16 ] ;
strcpy ( ip , server_socket . getClientIP ( id ) ) ;
logPrintf ( logfile , " Sending version information \n " ) ;
msg . id = id ;
msg . type = SEND_VERSION_MSG ;
msg . room = 0 ;
MySQL_CheckVersion ( id , SEND_VERSION_MSG , ip , modid , modversion ) ; // New code that's full of win!
msg . length = sizeof msg . buffer ;
writecode = server_socket . write ( & msg ) ;
if ( writecode < 0 )
{
dbgPrintf ( LIGHTRED , " Write error... %d client %d deleted \n " ,
writecode , id ) ;
}
}
/*
* * addServer ( )
*/
static void addServer ( int id , char * buffer , bool firstadd )
{
msg_server_t * info ;
char oldversion = 0 ;
//TODO: Be sure there is no flood from a given IP:
// If a host need more than 2 servers, then it should be registrated
// manually
info = ( msg_server_t * ) buffer ;
// I want to be sure the informations are correct, of course!
info - > port [ sizeof ( info - > port ) - 1 ] = ' \0 ' ;
info - > name [ sizeof ( info - > name ) - 1 ] = ' \0 ' ;
info - > version [ sizeof ( info - > version ) - 1 ] = ' \0 ' ;
2020-03-20 14:12:19 +00:00
logPrintf ( logfile , " addServer(): Version = \" %s \" \n " , info - > version ) ;
logPrintf ( logfile , " addServer(): Key = \" %s \" \n " , info - > key ) ;
2014-03-15 16:59:03 +00:00
// retrieve the true ip of the server
strcpy ( info - > ip , server_socket . getClientIP ( id ) ) ;
//strcpy(info->port, server_socket.getClientPort(id));
if ( info - > version [ 0 ] = = ' 1 ' & &
info - > version [ 1 ] = = ' . ' & &
info - > version [ 2 ] = = ' 0 ' & &
info - > version [ 3 ] = = ' 9 ' & &
info - > version [ 4 ] = = ' . ' )
{
if ( ( info - > version [ 5 ] = = ' 2 ' ) | | ( info - > version [ 5 ] = = ' 3 ' ) )
{
oldversion = 1 ;
}
}
if ( info - > version [ 0 ] = = ' 1 ' & &
info - > version [ 1 ] = = ' . ' & &
info - > version [ 2 ] = = ' 6 ' & &
info - > version [ 3 ] = = ' 9 ' & &
info - > version [ 4 ] = = ' . ' & &
info - > version [ 5 ] = = ' 6 ' )
{
oldversion = 1 ;
}
if ( ! oldversion )
{
MySQL_AddServer ( info - > ip , info - > port , info - > name , info - > version , info - > room , firstadd , info - > key ) ;
}
else
{
logPrintf ( logfile , " Not adding the temporary server: %s %s %s %s \n " , info - > ip , info - > port , info - > name , info - > version ) ;
}
}
/*
* * removeServer ( )
*/
static void removeServer ( int id , char * buffer )
{
msg_server_t * info ;
info = ( msg_server_t * ) buffer ;
// I want to be sure the informations are correct, of course!
info - > port [ sizeof ( info - > port ) - 1 ] = ' \0 ' ;
info - > name [ sizeof ( info - > name ) - 1 ] = ' \0 ' ;
info - > version [ sizeof ( info - > version ) - 1 ] = ' \0 ' ;
// retrieve the true ip of the server
strcpy ( info - > ip , server_socket . getClientIP ( id ) ) ;
logPrintf ( logfile , " Removing the temporary server: %s %s %s %s \n " , info - > ip , info - > port , info - > name , info - > version ) ;
MySQL_RemoveServer ( info - > ip , info - > port , info - > name , info - > version ) ; // New and win.
}
/*
* * analyseUDP ( )
*/
static int analyseUDP ( size_t size , const char * buffer )
{
// this would be the part of reading the PT_SERVERINFO packet,
// but i'm not about to backport that sloppy code
( void ) size ;
( void ) buffer ;
return INVALID_MSG ;
}
/*
* * UDPMessage ( )
*/
static int UDPMessage ( size_t size , const char * buffer )
{
if ( size = = 4 )
{
return 0 ;
}
else if ( size = = sizeof ( ms_holepunch_packet_t ) )
{
return 0 ;
}
else if ( size > 58 )
{
dbgPrintf ( LIGHTGREEN , " Got a UDP %d byte long message \n " , size ) ;
return analyseUDP ( size , buffer ) ;
}
else
return INVALID_MSG ;
}
/*
* * analyseMessage ( )
*/
static int analyseMessage ( msg_t * msg )
{
switch ( msg - > type )
{
case UDP_RECV_MSG :
return UDPMessage ( msg - > length , msg - > buffer ) ;
case ACCEPT_MSG :
break ;
case ADD_SERVER_MSG :
addServer ( msg - > id , msg - > buffer , true ) ;
break ;
case PING_SERVER_MSG :
addServer ( msg - > id , msg - > buffer , false ) ;
break ;
case REMOVE_SERVER_MSG :
removeServer ( msg - > id , msg - > buffer ) ;
break ;
case GET_SERVER_MSG :
sendServersInformations ( msg - > id , msg - > room ) ;
break ;
case GET_SHORT_SERVER_MSG :
sendShortServersInformations ( msg - > id , msg - > room ) ;
break ;
case GET_ROOMS_MSG :
sendRoomInformations ( msg - > id , msg - > room , 0 ) ;
break ;
case GET_ROOMS_HOST_MSG :
sendRoomInformations ( msg - > id , msg - > room , 1 ) ;
break ;
case GET_VERSION_MSG :
sendVersionInformations ( msg - > id , msg - > room , msg - > buffer ) ;
break ;
case LIVE_AUTH_USER :
LIVE_AuthUser ( msg - > id , msg - > buffer ) ;
break ;
default :
return INVALID_MSG ;
}
return 0 ;
}
/*
* * main ( )
*/
int main ( int argc , char * argv [ ] )
{
msg_t msg ;
# ifdef __unix__
pid_t pid ;
char pidstr [ 12 ] ;
# endif
if ( argc < = 1 )
{
fprintf ( stderr , " usage: %s port \n " , argv [ 0 ] ) ;
exit ( 1 ) ;
}
if ( server_socket . listen ( argv [ 1 ] ) < 0 )
{
2020-03-20 14:12:19 +00:00
fprintf ( stderr , " Error while initializing the server; port being used! Try killing the other Master Server. \n " ) ;
2014-03-15 16:59:03 +00:00
exit ( 2 ) ;
}
logfile = openFile ( " server.log " ) ;
errorfile = openFile ( " error.log " ) ;
mysqlfile = openFile ( " mysql.log " ) ;
sockfile = openFile ( " sockets.log " ) ;
MySQL_Conn ( false ) ;
# if !defined (DEBUG) && defined (__unix__)
pid = fork ( ) ;
switch ( pid )
{
case 0 : break ; // child
case - 1 : printf ( " Error while launching the server in background \n " ) ; return - 1 ;
default :
pidfile = fopen ( " msd.pid " , " w+ " ) ;
sprintf ( pidstr , " %d " , pid ) ;
fputs ( pidstr , pidfile ) ;
fclose ( pidfile ) ;
return 0 ; // parent: keep child in background
}
# endif
srand ( ( unsigned ) time ( NULL ) ) ; // Alam: GUIDs
for ( ; ; )
{
memset ( & msg , 0 , sizeof ( msg ) ) ; // remove previous message
if ( ! server_socket . read ( & msg ) )
{
// valid message: header message seems ok
analyseMessage ( & msg ) ;
//servers_list.show(); // for debug purpose
}
}
# ifndef _MSC_VER
/* NOTREACHED */
return 0 ;
# endif
}