Beispiel #1
0
bool CCCBot :: Update( )
{
	unsigned int NumFDs = 0;

	// take every socket we own and throw it in one giant select statement so we can block on all sockets

	int nfds = 0;
	fd_set fd;
	fd_set send_fd;
	FD_ZERO( &fd );
	FD_ZERO( &send_fd );

	// all battle.net sockets

	for( vector<CBNET *> :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); ++i )
		NumFDs += (*i)->SetFD( &fd, &send_fd, &nfds );

	struct timeval tv;
	tv.tv_sec = 0;
	tv.tv_usec = 50000;

#ifdef WIN32
	select( 1, &fd, &send_fd, NULL, &tv );
#else
	select( nfds + 1, &fd, &send_fd, NULL, &tv );
#endif

	if( NumFDs == 0 )
	{
		// we don't have any sockets (i.e. we aren't connected to battle.net maybe due to a lost connection)
		// select will return immediately and we'll chew up the CPU if we let it loop so just sleep for 200ms to kill some time

		MILLISLEEP( 200 );
	}

	// update battle.net connections

	for( vector<CBNET *> :: iterator i = m_BNETs.begin( ); i != m_BNETs.end( ); ++i )
	{
		if( (*i)->Update( &fd, &send_fd ) )
			m_Exiting = true;
	}

	return m_Exiting;
}
Beispiel #2
0
CServer :: ~CServer( )
{
	closesocket( m_sckServer );

	unsigned long iStart = GetTime( );

	while( 1 )
	{
		for( vector<CClient *> :: iterator i = m_vecClients.begin( ); i != m_vecClients.end( ); )
		{
			if( (*i)->m_iState == CS_WAITING1 || (*i)->m_iState == CS_WAITING2 || (*i)->m_iState == CS_DEAD )
			{
				delete *i;

				i = m_vecClients.erase( i );
			}
			else
				i++;
		}

		if( m_vecClients.size( ) > 0 )
		{
			UTIL_LogPrint( "server - waiting for %d clients to disconnect\n", m_vecClients.size( ) );

			MILLISLEEP( 1000 );
		}
		else
			break;

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

			break;
		}
	}

	if( m_pTracker )
		delete m_pTracker;

	m_pTracker = NULL;

	UTIL_LogPrint( "server - exit\n" );
}
Beispiel #3
0
void CGHostDBMySQL :: CreateThread( CBaseCallable *callable )
{
	try
	{
		boost :: thread Thread( boost :: ref( *callable ) );
	}
	catch( boost :: thread_resource_error tre )
	{
		CONSOLE_Print( "[MYSQL] error spawning thread on attempt #1 [" + string( tre.what( ) ) + "], pausing execution and trying again in 50ms" );
		MILLISLEEP( 50 );

		try
		{
			boost :: thread Thread( boost :: ref( *callable ) );
		}
		catch( boost :: thread_resource_error tre2 )
		{
			CONSOLE_Print( "[MYSQL] error spawning thread on attempt #2 [" + string( tre2.what( ) ) + "], giving up" );
			callable->SetReady( true );
		}
	}
}
Beispiel #4
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 #5
0
bool CServer :: Update( const bool &bBlock )
{
	if( m_vecClients.size( ) < guiMaxConns )
	{
		// tphogan - check every listener for new connections
		
		fd_set fdServer;
		FD_ZERO( &fdServer );
		
		struct timeval tv;
		struct sockaddr_in6 adrFrom;
		int iAddrLen = 0;
		SOCKET sckClient = 0;

		for( vector<SOCKET> :: iterator itListener = m_vecListeners.begin( ); itListener != m_vecListeners.end( ); itListener++ )
		{
			FD_CLR( *itListener, &fdServer );
			FD_SET( *itListener, &fdServer );

			// tphogan - only block on the first listener
			// this is actually a bit of a hack but it don't feel like doing it "right" :)

			if( bBlock && itListener == m_vecListeners.begin( ) )
			{
				// block for 100 ms to keep from eating up all cpu time

				tv.tv_sec = 0;
				tv.tv_usec = 100000;
			}
			else
			{
				tv.tv_sec = 0;
				tv.tv_usec = 0;
			}

#ifdef WIN32
			if( select( 1, &fdServer, 0, 0, &tv ) == SOCKET_ERROR )
#else
			if( select( *itListener + 1, &fdServer, 0, 0, &tv ) == SOCKET_ERROR )
#endif
			{
				UTIL_LogPrint( ( gmapLANG_CFG["select_error"] + "\n" ).c_str( ), GetLastErrorString( ) );

				FD_CLR( *itListener, &fdServer );
			}

			if( FD_ISSET( *itListener, &fdServer ) !=0 )
			{
				iAddrLen = sizeof( adrFrom );

#ifdef WIN32
				sckClient = accept( *itListener, (struct sockaddr *)&adrFrom, &iAddrLen );

				if( sckClient == INVALID_SOCKET )
#else
				sckClient = accept( *itListener, (struct sockaddr *)&adrFrom, (socklen_t *)&iAddrLen );

				if( sckClient == INVALID_SOCKET )
#endif
					UTIL_LogPrint( ( gmapLANG_CFG["accept_error"] + "\n" ).c_str( ), GetLastErrorString( ) );
				else
					m_vecClients.push_back( new CClient( sckClient, adrFrom, m_uiSocketTimeOut, m_cCompression ) );
			}
		}
	}
	else
	{
		// maximum connections reached

		// tphogan - reduced from 100 ms to 10 ms
		// it's very difficult to tell if the backlog is due to legitimate load or hung clients
		// hung clients don't eat CPU time so the server's CPU usage will skyrocket
		// but if it's due to load then sleeping for 100 ms is a terrible idea!
		// someone should take a look at this and rewrite it eventually

		UTIL_LogPrint( "Server Info - Max. connections reached\n" );

		MILLISLEEP( 10 );
	}

	// process the clients
	for( vector<CClient *> :: iterator itClient = m_vecClients.begin( ); itClient != m_vecClients.end( ); )
	{
		if( (*itClient)->Update( ) )
		{
			delete *itClient;

			itClient = m_vecClients.erase( itClient );
		}
		else
			itClient++;
	}

	if( m_pTracker )
		m_pTracker->Update( );

	return m_bKill;
}
Beispiel #6
0
bool CServer :: Update( bool bBlock )
{
	if( m_vecClients.size( ) < (unsigned int)giMaxConns )
	{
		fd_set fdServer;

		FD_ZERO( &fdServer );
		FD_SET( m_sckServer, &fdServer );

		struct timeval tv;

		if( bBlock )
		{
			// block for 100 ms to keep from eating up all cpu time

			tv.tv_sec = 0;
			tv.tv_usec = 100000;
		}
		else
		{
			tv.tv_sec = 0;
			tv.tv_usec = 0;
		}

#ifdef WIN32
		if( select( 1, &fdServer, NULL, NULL, &tv ) == SOCKET_ERROR )
#else
		if( select( m_sckServer + 1, &fdServer, NULL, NULL, &tv ) == SOCKET_ERROR )
#endif
		{
			UTIL_LogPrint( "server warning - select error (error %d)\n", GetLastError( ) );

			FD_ZERO( &fdServer );

			MILLISLEEP( 100 );
		}

		if( FD_ISSET( m_sckServer, &fdServer ) )
		{
			struct sockaddr_in adrFrom;

			int iAddrLen = sizeof( adrFrom );

			SOCKET sckClient;

#ifdef WIN32
			if( ( sckClient = accept( m_sckServer, (struct sockaddr *)&adrFrom, &iAddrLen ) ) == INVALID_SOCKET )
#else
			if( ( sckClient = accept( m_sckServer, (struct sockaddr *)&adrFrom, (socklen_t *)&iAddrLen ) ) == INVALID_SOCKET )
#endif
				UTIL_LogPrint( "server warning - accept error (error %d)\n", GetLastError( ) );
			else
			{
				// reuse the old timeval structure just because

				tv.tv_sec = m_iSocketTimeOut;
				tv.tv_usec = 0;

				CClient *pClient = new CClient( sckClient, adrFrom, tv, m_iCompression );

#ifdef WIN32
				if( _beginthread( ( void (*)(void *) )StartReceiving, 0, (void *)pClient ) == -1 )
				{
					UTIL_LogPrint( "server warning - unable to spawn receiver thread\n" );

					pClient->m_iState = CS_DEAD;
				}
#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 *) )StartReceiving, (void *)pClient );

				if( c != 0 )
				{
					UTIL_LogPrint( "server warning - unable to spawn receiver thread (error %s)\n", strerror( c ) );

					pClient->m_iState = CS_DEAD;
				}
#endif

				m_vecClients.push_back( pClient );
			}
		}
	}
	else
	{
		// maximum connections reached

		MILLISLEEP( 100 );
	}

	// process

	for( vector<CClient *> :: iterator i = m_vecClients.begin( ); i != m_vecClients.end( ); )
	{
		if( (*i)->m_iState == CS_WAITING1 )
		{
			(*i)->Process( );

			i++;
		}
		else if( (*i)->m_iState == CS_WAITING2 )
		{
			(*i)->m_iState = CS_SENDING;

#ifdef WIN32
			if( _beginthread( ( void (*)(void *) )StartSending, 0, (void *)(*i) ) == -1 )
			{
				UTIL_LogPrint( "server warning - unable to spawn sender thread\n" );

				(*i)->m_iState = CS_DEAD;
			}
#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 *) )StartSending, (void *)(*i) );

			if( c != 0 )
			{
				UTIL_LogPrint( "server warning - unable to spawn sender thread (error %s)\n", strerror( c ) );

				(*i)->m_iState = CS_DEAD;
			}
#endif

			i++;
		}
		else if( (*i)->m_iState == CS_DEAD )
		{
			delete *i;

			i = m_vecClients.erase( i );
		}
		else
			i++;
	}

	if( m_pTracker )
		m_pTracker->Update( );

	return m_bKill;
}
Beispiel #7
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;
}