Beispiel #1
0
int bnbtmain( )
{
	gmtxOutput.Initialize( );

	srand( time( NULL ) );

	giStartTime = time( NULL );

	CFG_Open( CFG_FILE );
	CFG_SetDefaults( );
	CFG_Close( CFG_FILE );

	gstrErrorLogDir = CFG_GetString( "bnbt_error_log_dir", string( ) );

	if( !gstrErrorLogDir.empty( ) && gstrErrorLogDir[gstrErrorLogDir.size( ) - 1] != PATH_SEP )
		gstrErrorLogDir += PATH_SEP;

	gpErrorLog = NULL;
	gstrAccessLogDir = CFG_GetString( "bnbt_access_log_dir", string( ) );

	if( !gstrAccessLogDir.empty( ) && gstrAccessLogDir[gstrAccessLogDir.size( ) - 1] != PATH_SEP )
		gstrAccessLogDir += PATH_SEP;

	gpAccessLog = NULL;
	giErrorLogCount = 0;
	giAccessLogCount = 0;
	giFlushInterval = CFG_GetInt( "bnbt_flush_interval", 100 );
	gbDebug = CFG_GetInt( "bnbt_debug", 1 ) == 0 ? false : true;
	giMaxConns = CFG_GetInt( "bnbt_max_conns", 64 );
	gstrStyle = CFG_GetString( "bnbt_style_sheet", string( ) );
	gstrCharSet = CFG_GetString( "bnbt_charset", "iso-8859-1" );
	gstrRealm = CFG_GetString( "bnbt_realm", "BNBT" );
	// The Trinity Edition - Addition Begins
	// Sets the value for the Custom NT Service Name variable
	gstrNTServiceName = CFG_GetString( "trinity_nt_service_name", "BNBT Service" );
	// Sets the "bnbt_alt_signup_url" value
	gstrAltSignupURL = CFG_GetString( "bnbt_alt_signup_url", string( ) );
	// Sets the "bnbt_tracker_title" value
	gstrTrackerTitle = CFG_GetString( "bnbt_tracker_title", string( ) );
	// Sets the "bnbt_external_js" value
	gstrExternalJavascript = CFG_GetString( "bnbt_external_js", string( ) );
	// --------------------------------------- End of Addition

	// start winsock

#ifdef WIN32
	WSADATA wsadata;

	if( WSAStartup( MAKEWORD( 2, 0 ), &wsadata ) != 0 )
	{
		UTIL_LogPrint( "error - unable to start winsock (error %d)\n", GetLastError( ) );

		if( gpAccessLog )
			fclose( gpAccessLog );

		if( gpErrorLog )
			fclose( gpErrorLog );

		gmtxOutput.Destroy( );

		return 1;
	}
#endif

	gpServer = new CServer( );
	gpLink = NULL;
	gpLinkServer = NULL;

	if( CFG_GetInt( "bnbt_tlink_server", 0 ) != 0 )
		gpLinkServer = new CLinkServer( );
	else
	{
		if( !CFG_GetString( "bnbt_tlink_connect", string( ) ).empty( ) )
		{
#ifdef WIN32
			if( _beginthread( ( void (*)(void *) )StartLink, 0, NULL ) == -1 )
				UTIL_LogPrint( "error - unable to spawn link thread\n" );
#else
			pthread_t thread;

			// set detached state since we don't need to join with any threads

			pthread_attr_t attr;
			pthread_attr_init( &attr );
			pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );

			int c = pthread_create( &thread, &attr, ( void * (*)(void *) )StartLink, NULL );

			if( c != 0 )
				UTIL_LogPrint( "error - unable to spawn link thread (error %s)\n", strerror( c ) );
#endif
		}
	}

	while( 1 )
	{
		if( gpServer->Update( true ) )
		{
			delete gpServer;

			gpServer = NULL;

			if( gpLinkServer )
			{
				delete gpLinkServer;

				gpLinkServer = NULL;
			}

			break;
		}

		if( gpLinkServer )
			gpLinkServer->Update( );
	}

	// wait for the link or it might make a big mess

	if( gpLink )
		gpLink->Kill( );

	unsigned long iStart = GetTime( );

	while( gpLink )
	{
		UTIL_LogPrint( "server - waiting for link to disconnect\n" );

		MILLISLEEP( 1000 );

		if( GetTime( ) - iStart > 60 )
		{
			UTIL_LogPrint( "server - waited 60 seconds, exiting anyway\n" );

			break;
		}
	}

	if( gpAccessLog )
		fclose( gpAccessLog );

	if( gpErrorLog )
		fclose( gpErrorLog );

	gmtxOutput.Destroy( );

#ifdef WIN32
	WSACleanup( );
#endif

	return 0;
}
Beispiel #2
0
CServer :: CServer( )
{
	m_vecClients.reserve( guiMaxConns );

	m_bKill = false;

	m_uiSocketTimeOut = CFG_GetInt( "socket_timeout", 15 );
	m_strBind = CFG_GetString( "bind", string( ) );
	m_cCompression = (char)CFG_GetInt( "bnbt_compression_level", 6 );

	// clamp compression

	if( m_cCompression > 9 )
		m_cCompression = 9;

	struct sockaddr_in6 sin;

	memset( &sin, 0, sizeof( sin ) );

	sin.sin6_family = AF_INET6;

	if( !m_strBind.empty( ) )
	{
		// bind to m_strBind

		if( gbDebug && ( gucDebugLevel & DEBUG_SERVER ) )
			UTIL_LogPrint( "server - binding to %s\n", m_strBind.c_str( ) );

		if( inet_pton( AF_INET6, m_strBind.c_str( ), &sin.sin6_addr ) == NULL )
		{
			UTIL_LogPrint( ( gmapLANG_CFG["unable_to_bind"] + "\n" ).c_str( ), m_strBind.c_str( ) );

			exit( 1 );
		}
	}
	else
	{
		// bind to all available addresses

		if( gbDebug && ( gucDebugLevel & DEBUG_SERVER ) )
			UTIL_LogPrint( ( gmapLANG_CFG["binding_to_all"] + "\n" ).c_str( ) );

		sin.sin6_addr = in6addr_any;
	}

	// tphogan - legacy support, check for "port" config entry
	// by doing this here "port" will always be required
	// so in fact this isn't entirely legacy support since it'll continue to be used

	// sin.sin6_len = sizeof(sin);

	sin.sin6_port = htons( (u_short)CFG_GetInt( "port", 6969 ) ) ;

	if( sin.sin6_port == 0 )
		UTIL_LogPrint( ( gmapLANG_CFG["binding_to_all"] + "\n" ).c_str( ), CAtomInt( CFG_GetInt( "port", 6969 ) ).toString( ).c_str( ) );
	else if( !AddListener( sin ) )
		UTIL_LogPrint( ( gmapLANG_CFG["unable_to_listen"] + "\n" ).c_str( ), CAtomInt( CFG_GetInt( "port", 6969 ) ).toString( ).c_str( ) );
	else
		UTIL_LogPrint( ( gmapLANG_CFG["listen_on_port"] + "\n" ).c_str( ), CAtomInt( CFG_GetInt( "port", 6969 ) ).toString( ).c_str( ) );

	// tphogan - retrieve list of ports from config file for multiport listeners
	// do we want to support multiple bindings as well?
	// this code will bind every socket to the same address

	unsigned char ucPort = 1;

	string strName = "port" + CAtomInt( ucPort ).toString( );
	string strPort = CFG_GetString( strName, string( ) );

	while( !strPort.empty( ) )
	{
		sin.sin6_port = htons( (u_short)atoi( strPort.c_str( ) ) ) ;

		if( sin.sin6_port == 0 )
			UTIL_LogPrint( ( gmapLANG_CFG["invalid_ports"] + "\n" ).c_str( ), strPort.c_str( ), strName.c_str( ) );
		else if( !AddListener( sin ) )
			UTIL_LogPrint( ( gmapLANG_CFG["unable_to_listens"] + "\n" ).c_str( ), strPort.c_str( ), strName.c_str( ) );
		else
			UTIL_LogPrint( ( gmapLANG_CFG["listen_on_ports"] + "\n" ).c_str( ), strPort.c_str( ), strName.c_str( ) );

		strName = "port" + CAtomInt( ++ucPort ).toString( );
		strPort = CFG_GetString( strName, string( ) );
	}

	// tphogan - we didn't exit on invalid ports above
	// so make sure we're listening on at least one valid port
	// however, since "port" is always forced greater than zero in CFG_SetDefaults
	// this should only happen if a valid port is denied for "port"
	// for example, address in use or not enough privs for ports < 1024

	if( m_vecListeners.empty( ) )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["not_listening"] + "\n" ).c_str( ) );

		exit( 1 );
	}

	m_pTracker = new CTracker( );

	UTIL_LogPrint( ( gmapLANG_CFG["server_start"] + "\n" ).c_str( ) );
}
Beispiel #3
0
int bnbtmain( )
{
	gmtxOutput.Initialize( );

	srand( time( NULL ) );

	giStartTime = time( NULL );

	CFG_Open( CFG_FILE );
	CFG_SetDefaults( );
	CFG_Close( CFG_FILE );

	gstrErrorLogFilePattern = CFG_GetString( "bnbt_error_log_file_pattern", "%Y-%m-%de.log" );
	gstrErrorLogDir = CFG_GetString( "bnbt_error_log_dir", string( ) );

	if( !gstrErrorLogDir.empty( ) && gstrErrorLogDir[gstrErrorLogDir.size( ) - 1] != PATH_SEP )
		gstrErrorLogDir += PATH_SEP;

	gpErrorLog = NULL;
	gstrAccessLogFilePattern = CFG_GetString( "bnbt_access_log_file_pattern", "%Y-%m-%d.log" );
	gstrAccessLogDir = CFG_GetString( "bnbt_access_log_dir", string( ) );

	if( !gstrAccessLogDir.empty( ) && gstrAccessLogDir[gstrAccessLogDir.size( ) - 1] != PATH_SEP )
		gstrAccessLogDir += PATH_SEP;

	gpAccessLog = NULL;
	giErrorLogCount = 0;
	giAccessLogCount = 0;
	giFlushInterval = CFG_GetInt( "bnbt_flush_interval", 100 );
	gbDebug = CFG_GetInt( "bnbt_debug", 1 ) == 0 ? false : true;
	giMaxConns = CFG_GetInt( "bnbt_max_conns", 64 );
	giMaxRecvSize = CFG_GetInt( "bnbt_max_recv_size", 524288 );
	gstrStyle = CFG_GetString( "bnbt_style_sheet", string( ) );
	gstrCharSet = CFG_GetString( "bnbt_charset", "iso-8859-1" );
	gstrRealm = CFG_GetString( "bnbt_realm", "BNBT" );

	// start winsock
    	
	// TCP window size
	giSO_RECBUF = CFG_GetInt( "xbnbt_so_recbuf", 128 ) * 1024;
	giSO_SNDBUF = CFG_GetInt( "xbnbt_so_sndbuf", 128 ) * 1024;

#ifdef WIN32
	WSADATA wsaData;

	int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );

	if ( iResult != NO_ERROR )
	{
		UTIL_LogPrint( "error - unable to start winsock (error %d)\n", GetLastError( ) );

		if( gpAccessLog )
			fclose( gpAccessLog );

		if( gpErrorLog )
			fclose( gpErrorLog );

		gmtxOutput.Destroy( );

		return 1;
	}
#endif

	// start mysql

#ifdef BNBT_MYSQL
	if( !( gpMySQL = mysql_init( NULL ) ) )
	{
		UTIL_LogPrint( "mysql error - %s\n", mysql_error( gpMySQL ) );

		if( gpAccessLog )
			fclose( gpAccessLog );

		if( gpErrorLog )
			fclose( gpErrorLog );

		gmtxOutput.Destroy( );

		return 1;
	}

	gstrMySQLHost = CFG_GetString( "mysql_host", string( ) );
	gstrMySQLDatabase = CFG_GetString( "mysql_database", "bnbt" );
	gstrMySQLUser = CFG_GetString( "mysql_user", string( ) );
	gstrMySQLPassword = CFG_GetString( "mysql_password", string( ) );
	giMySQLPort = CFG_GetInt( "mysql_port", 0 );

	if( !( mysql_real_connect( gpMySQL, gstrMySQLHost.c_str( ), gstrMySQLUser.c_str( ), gstrMySQLPassword.c_str( ), gstrMySQLDatabase.c_str( ), giMySQLPort, NULL, 0 ) ) )
	{
		UTIL_LogPrint( "mysql error - %s\n", mysql_error( gpMySQL ) );

		if( gpAccessLog )
			fclose( gpAccessLog );

		if( gpErrorLog )
			fclose( gpErrorLog );

		gmtxOutput.Destroy( );

		return 1;
	}

	UTIL_LogPrint( "mysql - connected\n" );
#endif

	gpServer = new CServer( );
	gpLink = NULL;
	gpLinkServer = NULL;

	if( CFG_GetInt( "bnbt_tlink_server", 0 ) != 0 )
		gpLinkServer = new CLinkServer( );
	else
	{
		if( !CFG_GetString( "bnbt_tlink_connect", string( ) ).empty( ) )
		{
#ifdef WIN32
			if( _beginthread( ( void (*)(void *) )StartLink, 0, NULL ) == -1 )
				UTIL_LogPrint( "error - unable to spawn link thread\n" );
#else
			pthread_t thread;

			// set detached state since we don't need to join with any threads

			pthread_attr_t attr;
			pthread_attr_init( &attr );
			pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );

			int c = pthread_create( &thread, &attr, ( void * (*)(void *) )StartLink, NULL );

			if( c != 0 )
				UTIL_LogPrint( "error - unable to spawn link thread (error %s)\n", strerror( c ) );
#endif
		}
	}

	while( 1 )
	{
		if( gpServer->Update( true ) )
		{
			delete gpServer;

			gpServer = NULL;

			if( gpLinkServer )
			{
				delete gpLinkServer;

				gpLinkServer = NULL;
			}

			break;
		}

		if( gpLinkServer )
			gpLinkServer->Update( );
	}

	// wait for the link or it might make a big mess

	if( gpLink )
		gpLink->Kill( );

	unsigned long iStart = GetTime( );

	while( gpLink )
	{
		UTIL_LogPrint( "server - waiting for link to disconnect\n" );

		MILLISLEEP( 1000 );

		if( GetTime( ) - iStart > 60 )
		{
			UTIL_LogPrint( "server - waited 60 seconds, exiting anyway\n" );

			break;
		}
	}

#ifdef BNBT_MYSQL
	mysql_close( gpMySQL );
#endif

	if( gpAccessLog )
		fclose( gpAccessLog );

	if( gpErrorLog )
		fclose( gpErrorLog );

	gmtxOutput.Destroy( );

#ifdef WIN32
	WSACleanup( );
#endif

	return 0;
}
Beispiel #4
0
CServer :: CServer( )
{
	m_bKill = false;

	m_iSocketTimeOut = CFG_GetInt( "socket_timeout", 15 );
	m_strBind = CFG_GetString( "bind", string( ) );
	m_iCompression = CFG_GetInt( "bnbt_compression_level", 6 );

	// clamp

	if( m_iCompression > 9 )
		m_iCompression = 9;

	struct sockaddr_in sin;

	memset( &sin, 0, sizeof( sin ) );

	sin.sin_family = AF_INET;

	if( !m_strBind.empty( ) )
	{
		// bind to m_strBind

		if( gbDebug )
			UTIL_LogPrint( "server - binding to %s\n", m_strBind.c_str( ) );

		if( ( sin.sin_addr.s_addr = inet_addr( m_strBind.c_str( ) ) ) == INADDR_NONE )
		{
			UTIL_LogPrint( "server error - unable to bind to %s\n", m_strBind.c_str( ) );

			Kill( );
		}
	}
	else
	{
		// bind to all available addresses

		if( gbDebug )
			UTIL_LogPrint( "server - binding to all available addresses\n" );

		sin.sin_addr.s_addr = INADDR_ANY;
	}

	if( ( sin.sin_port = htons( (u_short)CFG_GetInt( "port", 6969 ) ) ) == 0 )
	{
		UTIL_LogPrint( "server error - invalid port %d\n", CFG_GetInt( "port", 6969 ) );

		Kill( );
	}

	// map protocol name to protocol number

	struct protoent *pPE;

	if( ( pPE = getprotobyname( "tcp" ) ) == 0 )
	{
		UTIL_LogPrint( "server error - unable to get tcp protocol entry (error %d)\n", GetLastError( ) );

		Kill( );
	}

	// allocate socket

	if( ( m_sckServer = socket( PF_INET, SOCK_STREAM, pPE->p_proto ) ) == INVALID_SOCKET )
	{
		UTIL_LogPrint( "server error - unable to allocate socket (error %d)\n", GetLastError( ) );

		Kill( );
	}

	// bind socket

	int optval = 1;

#ifdef WIN32
	setsockopt( m_sckServer, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) );
#else
	setsockopt( m_sckServer, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) );
#endif

	if( bind( m_sckServer, (struct sockaddr *)&sin, sizeof( sin ) ) == SOCKET_ERROR )
	{
		UTIL_LogPrint( "server error - unable to bind socket (error %d)\n", GetLastError( ) );

		Kill( );
	}

	// listen, queue length 8

	if( listen( m_sckServer, 8 ) == SOCKET_ERROR )
	{
		UTIL_LogPrint( "server error - unable to listen (error %d)\n", GetLastError( ) );

		Kill( );
	}

	m_pTracker = new CTracker( );

	UTIL_LogPrint( "server - start\n" );
}
Beispiel #5
0
int bnbtmain( )
{
	gmtxOutput.Initialize( );
	gmtxMySQL.Initialize( );

	UTIL_LogPrint( "Tracker Start\n" );

	srand( (unsigned int)time( 0 ) );

	gtStartTime = time( 0 );

	CFG_Open( CFG_FILE );
	CFG_SetDefaults( );
	CFG_Close( CFG_FILE );

	// XBNBT Language Configuration
	LANG_CFG_Init( LANG_CFG_FILE );

	UTIL_LogPrint( "Setting debug level, access and error log files\n" );

	guiFlushInterval = CFG_GetInt( "bnbt_flush_interval", 100 );
	
	// Log
	gstrLogDir = CFG_GetString( "bnbt_log_dir", string( ) );
	gstrLogFilePattern = CFG_GetString( "bnbt_log_file_pattern", "%Y-%m-%d.log" );
	
	if( !gstrLogDir.empty( ) && gstrLogDir[gstrLogDir.size( ) - 1] != PATH_SEP )
		gstrLogDir += PATH_SEP;

	gpLog = 0;
	gulLogCount = 0;
	
	// Error log
	gstrErrorLogDir = CFG_GetString( "bnbt_error_log_dir", string( ) );
	gstrErrorLogFilePattern = CFG_GetString( "bnbt_error_log_file_pattern", "%Y-%m-%de.log" );
	
	if( !gstrErrorLogDir.empty( ) && gstrErrorLogDir[gstrErrorLogDir.size( ) - 1] != PATH_SEP )
		gstrErrorLogDir += PATH_SEP;

	gpErrorLog = 0;
	gulErrorLogCount = 0;

	// Access log
	gstrAccessLogDir = CFG_GetString( "bnbt_access_log_dir", string( ) );
	gstrAccessLogFilePattern = CFG_GetString( "bnbt_access_log_file_pattern", "%Y-%m-%da.log" );

	if( !gstrAccessLogDir.empty( ) && gstrAccessLogDir[gstrAccessLogDir.size( ) - 1] != PATH_SEP )
		gstrAccessLogDir += PATH_SEP;

	gpAccessLog = 0;
	gulAccessLogCount = 0;

	// Set the debug level
	gbDebug = CFG_GetInt( "bnbt_debug", 1 ) == 0 ? false : true;
	gucDebugLevel = (unsigned char)CFG_GetInt( "bnbt_debug_level", 0 );

	UTIL_LogPrint( "***********************************************\n" );

	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
	{
		UTIL_LogPrint( "Debug is on at level (%u)\n", gucDebugLevel );
		
		if( gstrLogDir.empty( ) )
			UTIL_LogPrint( "Log directory is not set\n" );
		else
			UTIL_LogPrint( "Log dir (%s)\n", gstrLogDir.c_str( ) );

		if( gstrErrorLogDir.empty( ) )
			UTIL_LogPrint( "Error log directory is not set\n" );
		else
			UTIL_LogPrint( "Error log dir (%s)\n", gstrErrorLogDir.c_str( ) );

		if( gstrErrorLogDir.empty( ) )
			UTIL_LogPrint( "Access log directory is not set\n" );
		else
			UTIL_LogPrint( "Access log dir (%s)\n", gstrAccessLogDir.c_str( ) );
	}

	// Other globals
	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "Setting global variables\n" );

	// PID
	gstrPID = CFG_GetString( "bnbt_pid_file", string( ) );

	if( gstrPID.empty( ) )
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "PID file is not set\n" );
	}
	else
	{
		// Write the process ID to file
		const long clPID( (long)getpid( ) );

		UTIL_LogPrint( "Recording PID (%ld) to file (%s)\n", clPID, gstrPID.c_str( ) );

		FILE *pFile = FILE_ERROR;

		pFile = fopen( gstrPID.c_str( ), "wt" );

		if( pFile == FILE_ERROR )
			UTIL_LogPrint( "Unable to write PID file (%s)\n", gstrPID.c_str( ) );
		else
		{
			fprintf( pFile, "%ld", clPID );
			fclose( pFile );
		}

		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "Recording PID completed\n" );
	}
	
	guiRestartServerInterval = CFG_GetInt( "bnbt_restart_interval", 24 );
	gulRestartServerNext = GetTime( ) + guiRestartServerInterval * 3600;

	guiMaxConns = CFG_GetInt( "bnbt_max_conns", 64 );
	guiMaxRecvSize = CFG_GetInt( "bnbt_max_recv_size", 524288 );
	gstrStyle = CFG_GetString( "bnbt_style_sheet", string( ) );
	gstrCharSet = CFG_GetString( "bnbt_charset", "utf-8" );
	gstrRealm = CFG_GetString( "bnbt_realm", "BNBT" );
	gstrPasswordKey = CFG_GetString( "bnbt_password_key", "ZiJingBT" );

	// The Trinity Edition - Addition Begins
	// Sets the value for the Custom NT Service Name variable
	gstrNTServiceName = CFG_GetString( "cbtt_service_name", "BNBT Service" );

	// TCP window size
	guiSO_RECBUF = CFG_GetInt( "xbnbt_so_recbuf", 128 ) * 1024;
	guiSO_SNDBUF = CFG_GetInt( "xbnbt_so_sndbuf", 128 ) * 1024;

	// Naggles algorithm
	gbTCP_NODELAY = CFG_GetInt( "xbnbt_tcp_nodelay", 0 ) == 0 ? false : true;

#ifdef WIN32
	// start winsock
	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "Starting the windows sockets\n" );

	WSADATA wsaData;

	const int ciResult( WSAStartup( MAKEWORD(2,2), &wsaData ) );

	if ( ciResult != NO_ERROR )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["unable_to_start_winsock"] + "\n" ).c_str( ), GetLastErrorString( ) );

		// Delete the PID file
		if( !gstrPID.empty( ) )
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "Deleting the PID file\n" );

			UTIL_DeleteFile( gstrPID.c_str( ) );
		}
		
		// Close the log
		if( gpLog )
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "Closing the log\n" );

			fclose( gpLog );
		}

		// Close the access log
		if( gpAccessLog )
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "Closing the access log\n" );

			fclose( gpAccessLog );
		}

		// Close the error log
		if( gpErrorLog )
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "Closing the error log\n" );

			fclose( gpErrorLog );
		}

		UTIL_LogPrint( "Tracker Stop\n" );

		gmtxMySQL.Destroy( );
		gmtxOutput.Destroy( );

		return 1;
	}
#endif

	// start mysql
	if( gbDebug )
		if( gucDebugLevel & DEBUG_BNBT )
			UTIL_LogPrint( "Setting MySQL dstate global variables\n" );

	if( !( gpMySQL = mysql_init( 0 ) ) )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_error"] + "\n" ).c_str( ), mysql_error( gpMySQL ) );

		// Delete the PID file
		if( !gstrPID.empty( ) )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Deleting the PID file\n" );

			UTIL_DeleteFile( gstrPID.c_str( ) );
		}
		
		// Close the log
		if( gpLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the log\n" );

			fclose( gpLog );
		}

		// Close the access log
		if( gpAccessLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the access log\n" );

			fclose( gpAccessLog );
		}

		// Close the error log
		if( gpErrorLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the error log\n" );

			fclose( gpErrorLog );
		}

		UTIL_LogPrint( "Tracker Stop\n" );

		gmtxMySQL.Destroy( );
		gmtxOutput.Destroy( );

		return 1;
	}

	gmapMySQL.clear( );
	gmapMySQL[pthread_self( )] = gpMySQL;
	gstrMySQLHost = CFG_GetString( "mysql_host", string( ) );
	gstrMySQLDatabase = CFG_GetString( "mysql_database", "bnbt" );
	gstrMySQLUser = CFG_GetString( "mysql_user", string( ) );
	gstrMySQLPassword = CFG_GetString( "mysql_password", string( ) );
	guiMySQLPort = CFG_GetInt( "mysql_port", 0 );
	
	if( !( mysql_real_connect( gpMySQL, gstrMySQLHost.c_str( ), gstrMySQLUser.c_str( ), gstrMySQLPassword.c_str( ), 0, guiMySQLPort, 0, 0 ) ) )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_error"] + "\n" ).c_str( ), mysql_error( gpMySQL ) );

		// Delete the PID file
		if( !gstrPID.empty( ) )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Deleting the PID file\n" );

			UTIL_DeleteFile( gstrPID.c_str( ) );
		}
		
		// Close the log
		if( gpLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the log\n" );

			fclose( gpLog );
		}

		// Close the access log
		if( gpAccessLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the access log\n" );

			fclose( gpAccessLog );
		}

		// Close the error log
		if( gpErrorLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the error log\n" );

			fclose( gpErrorLog );
		}

		UTIL_LogPrint( "Tracker Stop\n" );

		gmtxMySQL.Destroy( );
		gmtxOutput.Destroy( );

		return 1;
	}
	
	UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_connected"] + "\n" ).c_str( ) );

	UTIL_MySQLCreateDatabase( );

	if( mysql_select_db( gpMySQL, gstrMySQLDatabase.c_str( ) ) )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["bnbt_mysql_error"] + "\n" ).c_str( ), mysql_error( gpMySQL ) );

		// Delete the PID file
		if( !gstrPID.empty( ) )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Deleting the PID file\n" );

			UTIL_DeleteFile( gstrPID.c_str( ) );
		}
		
		// Close the log
		if( gpLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the log\n" );

			fclose( gpLog );
		}

		// Close the access log
		if( gpAccessLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the access log\n" );

			fclose( gpAccessLog );
		}

		// Close the error log
		if( gpErrorLog )
		{
			if( gbDebug )
				if( gucDebugLevel & DEBUG_BNBT )
					UTIL_LogPrint( "Closing the error log\n" );

			fclose( gpErrorLog );
		}

		UTIL_LogPrint( "Tracker Stop\n" );

		gmtxMySQL.Destroy( );
		gmtxOutput.Destroy( );

		return 1;
	}

	UTIL_MySQLCreateTables( );

	// Create the server
	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "Creating server\n" );

	gpServer = new CServer( );

	//
	// Link
	//

//	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
//		UTIL_LogPrint( "Creating link client/server\n" );

//	gpLink = 0;
//	gpLinkServer = 0;

//	if( CFG_GetInt( "bnbt_tlink_server", 0 ) != 0 )
//		gpLinkServer = new CLinkServer( );
//	else
//	{
//		if( !CFG_GetString( "bnbt_tlink_connect", string( ) ).empty( ) )
//		{
//#ifdef WIN32
//            int iLinkThreadResult = (int)_beginthread( ( void (*)(void *) )StartLink, 0, 0 );
//            
//			if( iLinkThreadResult == -1 )
//				UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_link_thread_win32"] + "\n" ).c_str( ) );
//#else
//			pthread_t thread;

//			// set detached state since we don't need to join with any threads

//			pthread_attr_t attr;
//			pthread_attr_init( &attr );
//			pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );

//			int iLinkThreadResult = pthread_create( &thread, &attr, ( void * (*)(void *) )StartLink, 0 );

//			if( iLinkThreadResult != 0 )
//				UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_link_thread"] + "\n" ).c_str( ), strerror( iLinkThreadResult ) );
//#endif
//		}
//	}

	//
	// HUBLink
	//

//	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
//		UTIL_LogPrint( "Creating hublink client/server\n" );

//	gpHUBLink = 0;
//	gpHUBLinkServer = 0;

//	if( CFG_GetInt( "xbnbt_thlink_server", 0 ) != 0 )
//		gpHUBLinkServer = new CHUBLinkServer( );
//	else
//	{
//		if( !CFG_GetString( "xbnbt_thlink_connect", string( ) ).empty( ) )
//		{
//#ifdef WIN32
//            int iHubLinkThreadResult = (int)_beginthread( ( void (*)(void *) )StartHUBLink, 0, 0 );
//            
//			if( iHubLinkThreadResult == -1 )
//				UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_hublink_thread_win32"] + "\n" ).c_str( ) );
//#else
//			pthread_t thread;

//			// set detached state since we don't need to join with any threads

//			pthread_attr_t attr;
//			pthread_attr_init( &attr );
//			pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );

//			int iHubLinkThreadResult = pthread_create( &thread, &attr, ( void * (*)(void *) )StartHUBLink, 0 );

//			if( iHubLinkThreadResult != 0 )
//				UTIL_LogPrint( ( gmapLANG_CFG["unable_to_spawn_hublink_thread"] + "\n" ).c_str( ), strerror( iHubLinkThreadResult ) );
//#endif
//		}
//	}

	//
	// update loop
	//

	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "Entering update loop\n" );

	bool bDoUpdate = true;

	while( bDoUpdate )
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_LOOPS ) && gpServer )
			UTIL_LogPrint( "Updating server\n" );

		if( gpServer && gpServer->Update( true ) )
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "Deleting server\n" );

			delete gpServer;

			gpServer = 0;	 

//			if( gpLinkServer )
//			{
//				if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
//					UTIL_LogPrint( "Deleting link server\n" );

//				delete gpLinkServer;

//				gpLinkServer = 0;
//			}

//			if( gpHUBLinkServer )
//			{
//				if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
//					UTIL_LogPrint( "Deleting hublink server\n" );

//				delete gpHUBLinkServer;

//				gpHUBLinkServer = 0;
//			}

			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "Exit the update loop\n" );

			bDoUpdate = false;
		}
		else
		if( gpServer && guiRestartServerInterval > 0 && GetTime( ) > gulRestartServerNext )
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "Restarting server\n" );

			delete gpServer;

			gpServer = new CServer( );
			
			gulRestartServerNext = GetTime( ) + guiRestartServerInterval * 3600;
		}

//		if( gpLinkServer && gucDebugLevel != 0 )
//		{
//			if( gbDebug && ( gucDebugLevel & DEBUG_LOOPS ) )
//				UTIL_LogPrint( "Updating link server\n" );

//			gpLinkServer->Update( );
//		}

//		if( gpHUBLinkServer && gucDebugLevel != 0 )
//		{
//			if( gbDebug && ( gucDebugLevel & DEBUG_LOOPS ) )
//				UTIL_LogPrint( "Updating hublink server\n" );

//			gpHUBLinkServer->Update( );
//		}
	}

	//
	// wait for the link or it might make a big mess
	//

//	if( gpLink )
//	{
//		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
//			UTIL_LogPrint( "Killing link client\n" );
//		
//		gpLink->Kill( );
//	}

//	const unsigned long culStart( GetTime( ) );

//	while( gpLink )
//	{
//		UTIL_LogPrint( ( gmapLANG_CFG["wait_link_disconnect"] + "\n" ).c_str( ) );

//		MILLISLEEP( 1000 );

//		if( GetTime( ) - culStart > 60 )
//		{
//			UTIL_LogPrint( ( gmapLANG_CFG["waited_link_disconnect"] + "\n" ).c_str( ) );

//			break;
//		}
//	}

	//
	// wait for the hub link or it might make a big mess
	//

//	if( gpHUBLink )
//	{
//		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
//			UTIL_LogPrint( "Killing hublink client\n" );

//		gpHUBLink->Kill( );
//	}

//	const unsigned long culStartHUB( GetTime( ) );

//	while( gpHUBLink )
//	{
//		UTIL_LogPrint( ( gmapLANG_CFG["wait_hublink_disconnect"] + "\n" ).c_str( ) );

//		MILLISLEEP( 1000 );

//		if( GetTime( ) - culStartHUB > 60 )
//		{
//			UTIL_LogPrint( ( gmapLANG_CFG["waited_hublink_disconnect"] + "\n" ).c_str( ) );

//			break;
//		}
//	}

	// Close the BNBT MySQL database
	if( gpMySQL )
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "Closing MySQL dstate integration build\n" );

		mysql_close( gpMySQL );
	}

#ifdef WIN32
	// Exit windows sockets
	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "Closing the windows sockets\n" );

	WSACleanup( );
#endif

	// Delete the PID file
	if( !gstrPID.empty( ) )
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "Deleting the PID file\n" );

		UTIL_DeleteFile( gstrPID.c_str( ) );
	}
	
	// Close the log
	if( gpLog )
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "Closing the log\n" );

		fclose( gpLog );
	}

	// Close the access log
	if( gpAccessLog )
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "Closing the access log\n" );

		fclose( gpAccessLog );
	}

	// Close the error log
	if( gpErrorLog )
	{
	 	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "Closing the error log\n" );

		fclose( gpErrorLog );
	}

	UTIL_LogPrint( "Tracker Stop\n" );

	gmtxMySQL.Destroy( );
	gmtxOutput.Destroy( );

	return 0;
}