Ejemplo n.º 1
0
CClient :: ~CClient( )
{
	if( closesocket( m_sckClient ) == SOCKET_ERROR )
		UTIL_LogPrint( "client error: Closing Socket (error %s)\n", GetLastErrorString( ) );
	else if( gbDebug )
		UTIL_LogPrint( "client: Socket Closed\n" );
}
Ejemplo n.º 2
0
CAtomDicti *DecodeDicti( const string &x, unsigned long iStart )
{
	unsigned long i = iStart + 1;

	CAtomDicti *pDicti = new CAtomDicti( );

	while( i < x.size( ) && x[i] != 'e' )
	{
		CAtom *pKey = Decode( x, i );

		if( pKey && dynamic_cast<CAtomString *>( pKey ) )
		{
			i += pKey->EncodedLength( );

			string strKey = pKey->toString( );

			delete pKey;

			if( i < x.size( ) )
			{
				CAtom *pValue = Decode( x, i );

				if( pValue )
				{
					i += pValue->EncodedLength( );

					pDicti->setItem( strKey, pValue );
				}
				else
				{
					UTIL_LogPrint( "error decoding dictionary - error decoding value, discarding dictionary\n" );

					delete pDicti;

					return NULL;
				}
			}
		}
		else
		{
			UTIL_LogPrint( "error decoding dictionary - error decoding key, discarding dictionary\n" );

			delete pDicti;

			return NULL;
		}
	}

	return pDicti;
}
Ejemplo n.º 3
0
CAtomList *DecodeList( const string &x, unsigned long iStart )
{
	unsigned long i = iStart + 1;

	CAtomList *pList = new CAtomList( );

	while( i < x.size( ) && x[i] != 'e' )
	{
		CAtom *pAtom = Decode( x, i );

		if( pAtom )
		{
			i += pAtom->EncodedLength( );

			pList->addItem( pAtom );
		}
		else
		{
			UTIL_LogPrint( "error decoding list - error decoding list item, discarding list\n" );

			delete pList;

			return NULL;
		}
	}

	return pList;
}
Ejemplo n.º 4
0
void CClient :: Reset( )
{
	if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
		UTIL_LogPrint( "client: reset\n" );

	m_ucState = CS_RECVHEADERS;
	m_strReceiveBuf.erase( );
	m_strReceiveBuf.reserve( 1024 );
	m_strSendBuf.erase( );
	m_strSendBuf.reserve( 1024 );
	rqst.strMethod.erase( );
	rqst.strURL.erase( );
	rqst.mapParams.clear( );
	rqst.mapHeaders.clear( );
	rqst.mapCookies.clear( );
	rqst.user.strLogin.erase( );
	rqst.user.strLowerLogin.erase( );
	rqst.user.strMD5.erase( );
	rqst.user.strMail.erase( );
	rqst.user.strLowerMail.erase( );
	rqst.user.strCreated.erase( );
	rqst.user.ucAccess = 0;
	rsp.strCode.erase( );
	rsp.mapHeaders.clear( );
	rsp.strContent.erase( );
	rsp.strContent.reserve( 1024 );
	rsp.bCompressOK = true;
	m_ulLast = GetTime( );
	m_bReset = true;
}
Ejemplo n.º 5
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" );
}
Ejemplo n.º 6
0
CAtomString *DecodeString( const string &x, unsigned long iStart )
{
	string :: size_type iSplit = x.find_first_not_of( "1234567890", iStart );

	if( iSplit == string :: npos )
	{
		UTIL_LogPrint( "error decoding string - couldn't find \":\", halting decode\n" );

		return NULL;
	}

	return new CAtomString( x.substr( iSplit + 1, atoi( x.substr( iStart, iSplit - iStart ).c_str( ) ) ) );
}
Ejemplo n.º 7
0
CAtom *Decode( const string &x, unsigned long iStart )
{
	if( iStart < x.size( ) )
	{
		if( x[iStart] == 'i' )
			return DecodeLong( x, iStart );
		else if( isdigit( x[iStart] ) )
			return DecodeString( x, iStart );
		else if( x[iStart] == 'l' )
			return DecodeList( x, iStart );
		else if( x[iStart] == 'd' )
			return DecodeDicti( x, iStart );

		string temp = x.substr( iStart );

		UTIL_LogPrint( "error decoding - found unexpected character %u, halting decode\n", (unsigned char)x[iStart] );
	}
	else
		UTIL_LogPrint( "error decoding - out of range\n" );

	return NULL;
}
Ejemplo n.º 8
0
CMySQLQuery :: CMySQLQuery( string strQuery )
{
	mysql_real_query( gpMySQL, strQuery.c_str( ), strQuery.size( ) );

	m_pRes = mysql_store_result( gpMySQL );

	if( mysql_errno( gpMySQL ) )
	{
		m_pRes = NULL;

		if( gbDebug )
			UTIL_LogPrint( "mysql error - %s\n", mysql_error( gpMySQL ) );
	}
}
Ejemplo n.º 9
0
CClient :: CClient( SOCKET &sckClient, struct sockaddr_in &sinAddress, const unsigned int &cuiTimeOut, const char &ccCompression )
{
	if( gbDebug )
		UTIL_LogPrint( "client: Socket Opening\n" );

	m_sckClient = sckClient;

	// make socket non blocking

#ifdef WIN32
	u_long ulMode = 1;

	if( ioctlsocket( m_sckClient, FIONBIO, &ulMode ) == SOCKET_ERROR )
#else
	if( fcntl( m_sckClient, F_SETFL, fcntl( m_sckClient, F_GETFL ) | O_NONBLOCK ) == SOCKET_ERROR )
#endif
		UTIL_LogPrint( "client warning: socket blocking (error %s)\n", GetLastErrorString( ) );

	m_uiTimeOut = cuiTimeOut;
	m_cCompression = ccCompression;
	rqst.sin = sinAddress;

	Reset( );
}
Ejemplo n.º 10
0
CServer :: ~CServer( )
{
	for( vector<SOCKET> :: iterator itListener = m_vecListeners.begin( ); itListener != m_vecListeners.end( ); itListener++ )
		closesocket( *itListener );

	for( vector<CClient *> :: iterator itClient = m_vecClients.begin( ); itClient != m_vecClients.end( ); itClient++ )
		delete *itClient;

	m_vecListeners.clear( );
	m_vecClients.clear( );

	if( m_pTracker )
		delete m_pTracker;

	m_pTracker = 0;

	UTIL_LogPrint( ( gmapLANG_CFG["server_exit"] + "\n" ).c_str( ) );
}
Ejemplo n.º 11
0
CAtom *DecodeFile( const char *szFile )
{
	FILE *pFile = FILE_ERROR;

	pFile = fopen( szFile, "rb" );

	if( pFile == FILE_ERROR )
	{
		UTIL_LogPrint( "warning - unable to open %s for reading\n", szFile );

		return 0;
	}

	// Find the end of the file
	fseek( pFile, 0, SEEK_END );

	// Remember the file size for later
	const unsigned long culFileSize( ftell( pFile ) );

	// Reset to the start of the file
	fseek( pFile, 0, SEEK_SET );

	// Allocate memory for the data buffer
	char *pData = (char *)malloc( sizeof( char ) * culFileSize );

	// Read the data
	fread( pData, sizeof( char ), culFileSize, pFile );

	// Close the file
	fclose( pFile );

	// Place the data in a string
	const string cstrFile( pData, culFileSize );

	// Free the data buffer memory
	free( pData );

	// Return the decoded data
	return Decode( cstrFile );
}
Ejemplo n.º 12
0
CAtomDicti :: CAtomDicti( const CAtomDicti &c )
{
	// copy constructor

	map<string, CAtom *> *pmapDicti = c.getValuePtr( );

	for( map<string, CAtom *> :: iterator i = pmapDicti->begin( ); i != pmapDicti->end( ); i++ )
	{
		if( dynamic_cast<CAtomInt *>( (*i).second ) && dynamic_cast<CAtomInt *>( (*i).second ) != NULL )
			setItem( (*i).first, new CAtomInt( *dynamic_cast<CAtomInt *>( (*i).second ) ) );
		else if( dynamic_cast<CAtomLong *>( (*i).second ) && dynamic_cast<CAtomLong *>( (*i).second ) != NULL )
			setItem( (*i).first, new CAtomLong( *dynamic_cast<CAtomLong *>( (*i).second ) ) );
		else if( dynamic_cast<CAtomString *>( (*i).second ) && dynamic_cast<CAtomString *>( (*i).second ) != NULL )
			setItem( (*i).first, new CAtomString( *dynamic_cast<CAtomString *>( (*i).second ) ) );
		else if( dynamic_cast<CAtomList *>( (*i).second ) && dynamic_cast<CAtomList *>( (*i).second ) != NULL )
			setItem( (*i).first, new CAtomList( *dynamic_cast<CAtomList *>( (*i).second ) ) );
		else if( dynamic_cast<CAtomDicti *>( (*i).second ) && dynamic_cast<CAtomDicti *>( (*i).second ) != NULL )
			setItem( (*i).first, new CAtomDicti( *dynamic_cast<CAtomDicti *>( (*i).second ) ) );
		else
			UTIL_LogPrint( "error copying dictionary - found invalid atom, ignoring\n" );
	}
}
Ejemplo n.º 13
0
CAtomDicti :: CAtomDicti( const CAtomDicti &c )
{
	// copy constructor

	map<string, CAtom *> *pmapDicti = c.getValuePtr( );

	for( map<string, CAtom *> :: iterator itAtom = pmapDicti->begin( ); itAtom != pmapDicti->end( ); itAtom++ )
	{
		if( dynamic_cast<CAtomInt *>( (*itAtom).second ) )
			setItem( (*itAtom).first, new CAtomInt( *dynamic_cast<CAtomInt *>( (*itAtom).second ) ) );
		else if( dynamic_cast<CAtomLong *>( (*itAtom).second ) )
			setItem( (*itAtom).first, new CAtomLong( *dynamic_cast<CAtomLong *>( (*itAtom).second ) ) );
		else if( dynamic_cast<CAtomString *>( (*itAtom).second ) )
			setItem( (*itAtom).first, new CAtomString( *dynamic_cast<CAtomString *>( (*itAtom).second ) ) );
		else if( dynamic_cast<CAtomList *>( (*itAtom).second ) )
			setItem( (*itAtom).first, new CAtomList( *dynamic_cast<CAtomList *>( (*itAtom).second ) ) );
		else if( dynamic_cast<CAtomDicti *>( (*itAtom).second ) )
			setItem( (*itAtom).first, new CAtomDicti( *dynamic_cast<CAtomDicti *>( (*itAtom).second ) ) );
		else
			UTIL_LogPrint( ( gmapLANG_CFG["atomdicti_copy_warning"] + "\n" ).c_str( ) );
	}
}
Ejemplo n.º 14
0
CAtomList :: CAtomList( const CAtomList &c )
{
	// copy constructor

	vector<CAtom *> *pvecList = c.getValuePtr( );

	for( vector<CAtom *> :: iterator i = pvecList->begin( ); i != pvecList->end( ); i++ )
	{
		if( dynamic_cast<CAtomInt *>( *i ) )
			addItem( new CAtomInt( *dynamic_cast<CAtomInt *>( *i ) ) );
		else if( dynamic_cast<CAtomLong *>( *i ) )
			addItem( new CAtomLong( *dynamic_cast<CAtomLong *>( *i ) ) );
		else if( dynamic_cast<CAtomString *>( *i ) )
			addItem( new CAtomString( *dynamic_cast<CAtomString *>( *i ) ) );
		else if( dynamic_cast<CAtomList *>( *i ) )
			addItem( new CAtomList( *dynamic_cast<CAtomList *>( *i ) ) );
		else if( dynamic_cast<CAtomDicti *>( *i ) )
			addItem( new CAtomDicti( *dynamic_cast<CAtomDicti *>( *i ) ) );
		else
			UTIL_LogPrint( "error copying list - found invalid atom, ignoring\n" );
	}
}
Ejemplo n.º 15
0
CAtomList :: CAtomList( const CAtomList &c )
{
	// copy constructor

	vector<CAtom *> *pvecList = c.getValuePtr( );

	for( vector<CAtom *> :: iterator itAtom = pvecList->begin( ); itAtom != pvecList->end( ); itAtom++ )
	{
		if( dynamic_cast<CAtomInt *>( *itAtom ) )
			addItem( new CAtomInt( *dynamic_cast<CAtomInt *>( *itAtom ) ) );
		else if( dynamic_cast<CAtomLong *>( *itAtom ) )
			addItem( new CAtomLong( *dynamic_cast<CAtomLong *>( *itAtom ) ) );
		else if( dynamic_cast<CAtomString *>( *itAtom ) )
			addItem( new CAtomString( *dynamic_cast<CAtomString *>( *itAtom ) ) );
		else if( dynamic_cast<CAtomList *>( *itAtom ) )
			addItem( new CAtomList( *dynamic_cast<CAtomList *>( *itAtom ) ) );
		else if( dynamic_cast<CAtomDicti *>( *itAtom ) )
			addItem( new CAtomDicti( *dynamic_cast<CAtomDicti *>( *itAtom ) ) );
		else
			UTIL_LogPrint( ( gmapLANG_CFG["atomlist_copy_warning"] + "\n" ).c_str( ) );
	}
}
Ejemplo n.º 16
0
CAtomLong *DecodeLong( const string &x, unsigned long iStart )
{
	string :: size_type iEnd = x.find( "e", iStart );

	if( iEnd == string :: npos )
	{
		UTIL_LogPrint( "error decoding long - couldn't find \"e\", halting decode\n" );

		return NULL;
	}

	int64 i;

#if defined( WIN32 )
	sscanf( x.substr( iStart + 1, iEnd - iStart - 1 ).c_str( ), "%I64d", &i );
#elif defined( FreeBSD )
	sscanf( x.substr( iStart + 1, iEnd - iStart - 1 ).c_str( ), "%qd", &i );
#else
	sscanf( x.substr( iStart + 1, iEnd - iStart - 1 ).c_str( ), "%lld", &i );
#endif

	return new CAtomLong( i );
}
Ejemplo n.º 17
0
CAtom *DecodeFile( const char *szFile )
{
	FILE *pFile = NULL;

	if( ( pFile = fopen( szFile, "rb" ) ) == NULL )
	{
		UTIL_LogPrint( "warning - unable to open %s for reading\n", szFile );

		return NULL;
	}

	fseek( pFile, 0, SEEK_END );
	unsigned long ulFileSize = ftell( pFile );
	fseek( pFile, 0, SEEK_SET );
	char *pData = (char *)malloc( sizeof( char ) * ulFileSize );
	memset( pData, 0, sizeof( char ) * ulFileSize );
	fread( (void *)pData, sizeof( char ), ulFileSize, pFile );
	fclose( pFile );
	string strFile( pData, ulFileSize );
	free( pData );

	return Decode( strFile );
}
Ejemplo n.º 18
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" );
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
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;
}
void CTracker :: serverResponseSignupLilyPOST( struct request_t *pRequest, struct response_t *pResponse, CAtomList *pPost )
{
    // Set the start time
    const struct bnbttv btv( UTIL_CurrentTime( ) );

    // Verify that the IP is permitted to access the tracker
    if( m_ucIPBanMode != 0 )
        if( IsIPBanned( pRequest, pResponse, btv, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), NOT_INDEX ) )
            return;

    string cstrLogin = string( );
    string cstrLilyID = string( );

    if( pPost )
    {
        // Initialise segment dictionary
        CAtomDicti *pSegment = 0;
        CAtom *pDisposition = 0;
        CAtom *pData = 0;
        CAtom *pName = 0;
        CAtom *pFile = 0;
        // Get the segments from the post
        vector<CAtom *> vecSegments = pPost->getValue( );

        // Loop through the segments
        for( unsigned long ulCount = 0; ulCount < vecSegments.size( ); ulCount++ )
        {
            // Is the segment a dictionary?
            if( vecSegments[ulCount]->isDicti( ) )
            {
                // Get the segment dictionary
                pSegment = (CAtomDicti *)vecSegments[ulCount];
                // Get the disposition and the data from the segment dictionary
                pDisposition = pSegment->getItem( "disposition" );
                pData = pSegment->getItem( "data" );

                // Did we get a disposition that is a dictionary and has data?
                if( pDisposition && pDisposition->isDicti( ) && pData )
                {
                    // Get the content name from the disposition
                    pName = ( (CAtomDicti *)pDisposition )->getItem( "name" );

                    // Did we get a content name?
                    if( pName )
                    {
                        // What is the content name to be tested?
                        string strName = pName->toString( );

                        if( strName == "us_login")
                            cstrLogin = pData->toString( );
                        else if( strName == "us_lilyid")
                            cstrLilyID = UTIL_ToLower( pData->toString( ) );
                    }
                    else
                    {
                        // Output common HTML head
                        HTML_Common_Begin(  pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_400 );

                        // failed
                        pResponse->strContent += "<p class=\"failed\">" + gmapLANG_CFG["failed"] + "</p>\n";
                        // Signal a bad request
                        pResponse->strContent += "<p class=\"body_upload\">400 " + gmapLANG_CFG["server_response_400"] + "</p>\n";

                        // Output common HTML tail
                        HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

                        if( gbDebug )
                            UTIL_LogPrint( "Login Warning - Bad request (no users name)\n" );

                        return;
                    }
                }
            }
        }
    }
    else
    {
        // Output common HTML head
        HTML_Common_Begin(  pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_400 );

        // failed
        pResponse->strContent += "<p class=\"failed\">" + gmapLANG_CFG["failed"] + "</p>\n";
        // Signal a bad request
        pResponse->strContent += "<p class=\"body_upload\">400 " + gmapLANG_CFG["server_response_400"] + "</p>\n";

        // Output common HTML tail
        HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

        if( gbDebug )
            UTIL_LogPrint( "Upload Warning - Bad request (no post received)\n" );

        return;
    }

    if( pRequest->user.ucAccess & ACCESS_SIGNUP )
    {
        HTML_Common_Begin(  pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_200 );

        if(  !cstrLogin.empty( ) && !cstrLilyID.empty( ) )
        {
// 			if( cstrLogin[0] == ' ' || cstrLogin[cstrLogin.size( ) - 1] == ' ' || cstrLogin.size( ) > m_uiNameLength )
            if( cstrLogin.find( ' ' ) != string :: npos || cstrLogin.find( '.' ) != string :: npos || cstrLogin.find( '%' ) != string :: npos || cstrLogin.find( '&' ) != string :: npos || cstrLilyID.find( ' ' ) != string :: npos || cstrLilyID.find( '.' ) != string :: npos || cstrLilyID.find( '%' ) != string :: npos || cstrLilyID.find( '&' ) != string :: npos || cstrLogin.size( ) > m_uiNameLength )
            {
                // Unable to signup. Your name must be less than " + CAtomInt( m_uiNameLength ).toString( ) + " characters long and it must not start or end with spaces.
                pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_name_error"].c_str( ), CAtomInt( m_uiNameLength ).toString( ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";

                // Output common HTML tail
                HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

                return;
            }
            time_t tNow = time( 0 );
            char pTime[256];
            memset( pTime, 0, sizeof( pTime ) / sizeof( char ) );
            strftime( pTime, sizeof( pTime ) / sizeof( char ), "%Y %m/%d %H:%M:%S", localtime( &tNow ) );

            const string cstrA1( cstrLogin + ":" + gstrRealm + ":" + pTime );

            unsigned char szMD5[16];
            memset( szMD5, 0, sizeof( szMD5 ) / sizeof( unsigned char ) );

            MD5_CTX md5;

            MD5Init( &md5 );
            MD5Update( &md5, (const unsigned char *)cstrA1.c_str( ), (unsigned int)cstrA1.size( ) );
            MD5Final( szMD5, &md5 );

            const string cstrPass = UTIL_HashToString( string( (char *)szMD5, sizeof( szMD5 ) / sizeof( unsigned char ) ) ).substr( 0, 8 );
            const string cstrMail = cstrLilyID + "@bbs.nju.edu.cn";

            if( !getUser( cstrLogin, m_ucGuestAccess ).strLogin.empty( ) )
            {
                // Unable to signup. The user \"" + UTIL_RemoveHTML( cstrLogin ) + "\" already exists.
                pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_exists_error"].c_str( ), UTIL_RemoveHTML( cstrLogin ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";
            }
            else
            {
                CMySQLQuery *pQuery = new CMySQLQuery( "SELECT blilyid FROM lily WHERE blilyid=\'" + UTIL_StringToMySQL( cstrLilyID ) + "\'" );

                if( pQuery->nextRow( ).size( ) == 1 )
                {
                    pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_exists_error_lily"].c_str( ), UTIL_RemoveHTML( cstrLogin ).c_str( ), UTIL_RemoveHTML( cstrLilyID ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";
                }
                else
                {
                    if( addUser( cstrLogin, cstrPass, m_ucMemberAccess, cstrMail ) )
                    {
                        CMySQLQuery mq01( "INSERT INTO lily (blilyid,busername,bpassword) VALUES(\'" + UTIL_StringToMySQL( cstrLilyID ) + "\',\'" + UTIL_StringToMySQL( cstrLogin ) + "\',\'" + UTIL_StringToMySQL( cstrPass ) + "\')" );

                        system( string( "echo \"ID: " + cstrLogin + " Password: "******"\" | mutt -s \"ZiJingBT\" " + cstrMail ).c_str( ) );

                        // Thanks! You've successfully signed up!
                        pResponse->strContent += "<p class=\"signup_ok\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_success_lily"].c_str( ), UTIL_RemoveHTML( cstrLilyID ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_LOGIN_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";
                    }
                    else
                        pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["users_max_create_fail"].c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_users"] + "\" href=\"" + RESPONSE_STR_USERS_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n";
                }
                delete pQuery;
            }

            HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );
        }
    }
    else
    {
        //Unable to signup. You must fill in all the fields.
        pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_fields_error"].c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";

        // Output common HTML tail
        HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

        return;
    }

}
Ejemplo n.º 23
0
// The signal catching routine
void sigCatcher( int sig )
{
	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "sigCatcher: reset the signals \n" );

	// reset the signal catcher
	signal( SIGABRT, sigCatcher );
	signal( SIGINT, sigCatcher );
	signal( SIGTERM, sigCatcher );
#if defined SIGHUP
	signal( SIGHUP, sigCatcher );
#endif

	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "sigCatcher: reset the signals completed \n" );

	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
	{
		switch( sig )
		{
		case SIGABRT:
			UTIL_LogPrint( "sigCatcher: caught SIGABRT\n" );

			break;
		case SIGINT:
			UTIL_LogPrint( "sigCatcher: caught SIGINT\n" );

			break;
		case SIGTERM:
			UTIL_LogPrint( "sigCatcher: caught SIGTERM\n" );

			break;
#if defined SIGHUP
		case SIGHUP:
			UTIL_LogPrint( "sigCatcher: caught SIGHUP\n" );

			break;
#endif
		default:
			UTIL_LogPrint( "sigCatcher: caught unknown signal (signal %d)\n", sig );
		}
	}

	if( gpServer )
	{
		if( gpServer->isDying( ) )
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "sigCatcher: server is dying -> exit\n" );

			exit( 1 );
		}
		else
		{
			if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
				UTIL_LogPrint( "sigCatcher: server sending kill\n" );

			gpServer->Kill( );
		}
	}
	else
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
			UTIL_LogPrint( "sigCatcher: server closed -> exit\n" );
		
		exit( 1 );
	}
	
	if( gbDebug && ( gucDebugLevel & DEBUG_BNBT ) )
		UTIL_LogPrint( "sigCatcher: killing server\n" );
}
Ejemplo n.º 24
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( ) );
}
Ejemplo n.º 25
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;
}
Ejemplo n.º 26
0
bool CServer :: AddListener( struct sockaddr_in6 sin )
{
	SOCKET sckListener;

	// map protocol name to protocol number

	struct protoent *pPE;

	pPE = getprotobyname( "tcp" );

	if( pPE == 0 )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["no_tcp_protocol"] + "\n" ).c_str( ), GetLastErrorString( ) );

		return false;
	}

	// allocate socket

	sckListener = socket( PF_INET6, SOCK_STREAM, pPE->p_proto );

	if( sckListener == INVALID_SOCKET )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["not_allocated_socket"] + "\n" ).c_str( ), GetLastErrorString( ) );

		return false;
	}

#ifdef WIN32
	const unsigned int cuiOptVal( 1 );

	// TCP window size 
	// Send
	if( setsockopt( sckListener, SOL_SOCKET, SO_SNDBUF, (const char *)&guiSO_SNDBUF, sizeof(guiSO_SNDBUF) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_sndbuf"] + "\n" ).c_str( ), GetLastErrorString( ) );

	// Receive
	if( setsockopt( sckListener, SOL_SOCKET, SO_RCVBUF, (const char *)&guiSO_RECBUF, sizeof(guiSO_RECBUF) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_rcvbuf"] + "\n" ).c_str( ), GetLastErrorString( ) );

	// 	Allows the socket to be bound to an address that is already in use.
	if( setsockopt( sckListener, SOL_SOCKET, SO_REUSEADDR, (const char *)&cuiOptVal, sizeof( cuiOptVal ) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_reuseaddr"] + "\n" ).c_str( ), GetLastErrorString( ) );

	// Naggle's Algorithm
	if( setsockopt( sckListener, SOL_SOCKET, TCP_NODELAY, (const char *)&gbTCP_NODELAY, sizeof( int ) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_nodelay"] + "\n" ).c_str( ), GetLastErrorString( ) );

	// bind socket
	if( bind( sckListener, (SOCKADDR*)&sin, sizeof( sin ) ) == SOCKET_ERROR )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["unable_to_bind_socket"] + "\n" ).c_str( ), GetLastErrorString( ) );

		return false;
	}
#else
	const unsigned int cuiOptVal( 1 );

#ifdef SO_NOSIGPIPE
	// Ignore SIGPIPE - FreeBSD
	if( setsockopt( sckListener, SOL_SOCKET, SO_NOSIGPIPE, (const void *)&cuiOptVal, (socklen_t)sizeof( cuiOptVal ) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_nosigpipe"] + "\n" ).c_str( ), GetLastErrorString( ) );
#endif

#ifdef SO_SNDBUF
	// TCP window size Send
	if( setsockopt( sckListener, SOL_SOCKET, SO_SNDBUF, (const char *)&guiSO_SNDBUF, (socklen_t)sizeof( guiSO_SNDBUF ) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_sndbuf"] + "\n" ).c_str( ), GetLastErrorString( ) );
#endif

#ifdef SO_RCVBUF
	// TCP window size Receive
	if( setsockopt( sckListener, SOL_SOCKET, SO_RCVBUF, (const char *)&guiSO_RECBUF, (socklen_t)sizeof( guiSO_RECBUF ) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_rcvbuf"] + "\n" ).c_str( ), GetLastErrorString( ) );
#endif

#ifdef SO_REUSEADDR
	// Allows the socket to be bound to an address that is already in use.
	if( setsockopt( sckListener, SOL_SOCKET, SO_REUSEADDR, (const void *)&cuiOptVal, (socklen_t)sizeof( cuiOptVal ) ) == SOCKET_ERROR );
		UTIL_LogPrint( ( gmapLANG_CFG["no_reuseaddr"] + "\n" ).c_str( ), GetLastErrorString( ) );
#endif

#ifdef TCP_NODELAY
	// Nagle's Algorithm
	if( setsockopt( sckListener, SOL_SOCKET, TCP_NODELAY, (const char *)&gbTCP_NODELAY, (socklen_t)sizeof( int ) ) == SOCKET_ERROR )
		UTIL_LogPrint( ( gmapLANG_CFG["no_nodelay"] + "\n" ).c_str( ), GetLastErrorString( ) );
#endif

	// bind
	if( bind( sckListener, (struct sockaddr *)&sin, sizeof( sin ) ) == SOCKET_ERROR )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["unable_to_bind_socket"] + "\n" ).c_str( ), GetLastErrorString( ) );

		return false;
	}
#endif

	// listen on the socket
	if( listen( sckListener, 1 ) == SOCKET_ERROR )
	{
		UTIL_LogPrint( ( gmapLANG_CFG["unable_to_listen"] + "\n" ).c_str( ), GetLastErrorString( ) );

		return false;
	}

	// Add the socket to the vector of sockets
	m_vecListeners.push_back( sckListener );

	return true;
}
Ejemplo n.º 27
0
bool CClient :: Update( )
{
	if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
		UTIL_LogPrint( "client: update start\n" );

	if( GetTime( ) > m_ulLast + m_uiTimeOut )
	{
		if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
			UTIL_LogPrint( "client warning: socket timed out (%d s, state(%d), reset(%d))\n", m_uiTimeOut, m_ucState, m_bReset );

		return true;
	}

	bool bGrabParams = true;
	bool bGrabHeaders = true;
	bool bGrabCookies = true;

	fd_set fdClient;
	//FD_ZERO( &fdClient );

	struct timeval tv;

	char cCompress = COMPRESS_NONE;
	char *szAuth = 0; 
	unsigned char *pBuf = 0;
	unsigned char *pNextIn = 0;

	unsigned char szMD5[16];

	string :: size_type iNewLine = 0;
	string :: size_type iDoubleNewLine = 0;
	string :: size_type iMethodEnd = 0;
	string :: size_type iParamsStart = 0;
	string :: size_type iURLEnd = 0;
	string :: size_type iWhite = 0;
	string :: size_type iSplit = 0;
	string :: size_type iEnd = 0;

	string strAuthorization = string( );
	string strContentLength = string( );
	string strCookies = string( );
	string strLogin = string( );
	string strMD5 = string( );
	string strRequest = string( );
	string strTemp = string( );
	string strType = string( );
	string strBase64 = string( );
	string strAuth = string( );
	string strPass = string( );
	string strA1 = string( );
	string strAcceptEncoding = string( );
	string strKey = string( );
	string strValue = string( );

	int iRecv = 0;
	int iSend = 0;
	int windowBits = 0;
	int iResult = 0;
	unsigned int uiSize = 0;

	switch( m_ucState )
	{
	case CS_RECVHEADERS :
		if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
			UTIL_LogPrint( "client: receive headers\n" );

		FD_ZERO( &fdClient );
		//FD_CLR( m_sckClient, &fdClient );
		FD_SET( m_sckClient, &fdClient );

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

#ifdef WIN32
		if( select( 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR )
#else
		if( select( m_sckClient + 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR )
#endif
		{
			UTIL_LogPrint( "client error: select error headers (error %s)\n", GetLastErrorString( ) );

			return true;
		}

		if( FD_ISSET( m_sckClient, &fdClient ) )
		{
			m_ulLast = GetTime( );

			memset( gpBuf, 0, sizeof(gpBuf) / sizeof(char) );

			iRecv = recv( m_sckClient, gpBuf, sizeof(gpBuf), 0 );

			if( iRecv == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
			{
				if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
					UTIL_LogPrint( "client error: receive headers error (error %s)\n", GetLastErrorString( ) );
				else if( GetLastError( ) != EPIPE && GetLastError( ) != ECONNRESET )
					UTIL_LogPrint( "client error: receive headers error (error %s)\n", GetLastErrorString( ) );

				return true;
			}
			else if( iRecv == 0 )
			{
				if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
					UTIL_LogPrint( "client error: receive headers returned 0\n" );

				return true;
			}
			else if( iRecv > 0 )
			{
				m_strReceiveBuf += string( gpBuf, iRecv );

				if( m_strReceiveBuf.size( ) > guiMaxRecvSize )
				{
					UTIL_LogPrint( "client error: exceeded max receive header size\n" );

					return true;
				}

				gtXStats.tcp.iRecv += iRecv;
			}
			else
			{
				UTIL_LogPrint( "client error: receive header returned garbage\n" );

				return true;
			}
		}

		if( m_strReceiveBuf.find( C_STR_DOUBLE_NEWLINE ) != string :: npos )
			m_ucState = CS_PROCESSHEADERS;
		else
			break;

	case CS_PROCESSHEADERS:
		if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
			UTIL_LogPrint( "client: process headers\n" );

		// grab method

		iMethodEnd = m_strReceiveBuf.find( C_STR_WSPACE );

		if( iMethodEnd == string :: npos )
		{
			UTIL_LogPrint( "client error: malformed HTTP request (can't find method)\n" );

			return true;
		}

		rqst.strMethod = m_strReceiveBuf.substr( 0, iMethodEnd );

		// grab url

		strTemp = m_strReceiveBuf.substr( iMethodEnd + 1 );

		iURLEnd = strTemp.find( C_STR_WSPACE );

		if( iURLEnd == string :: npos )
		{
			UTIL_LogPrint( "client error: malformed HTTP request (can't find URL)\n" );

			return true;
		}

		strTemp = strTemp.substr( 0, iURLEnd );

		iParamsStart = strTemp.find( C_STR_ITEMQU );

		if( iParamsStart == string :: npos )
		{
			rqst.strURL = strTemp;
			rqst.hasQuery = false;
		}
		else
		{
			rqst.strURL = strTemp.substr( 0, iParamsStart );
			rqst.hasQuery = true;
		}

		// grab params

		if( iParamsStart != string :: npos )
		{
			strTemp = strTemp.substr( iParamsStart + 1 );
			rqst.hasQuery = true;

			iSplit = 0;
			iEnd = 0;

			strKey = string( );
			strValue = string( );

			bGrabParams = true;

			while( bGrabParams )
			{
				iSplit = strTemp.find( C_STR_ITEMEQ );
				iEnd = strTemp.find( C_STR_ITEMAND );

				if( iSplit == string :: npos )
				{
					UTIL_LogPrint( "client warning: malformed HTTP request (found param key without value)\n" );

					bGrabParams = false;
				}

				strKey = UTIL_EscapedToString( strTemp.substr( 0, iSplit ) );
				strValue = UTIL_EscapedToString( strTemp.substr( iSplit + 1, iEnd - iSplit - 1 ) );

				// multimap for scrape, regular map for everything else
				if ( rqst.strURL == RESPONSE_STR_SCRAPE )
					rqst.multiParams.insert( pair<string,string>( strKey, strValue ) );
				else
					rqst.mapParams.insert( pair<string, string>( strKey, strValue ) );

				strTemp = strTemp.substr( iEnd + 1, strTemp.size( ) - iEnd - 1 );

				if( iEnd == string :: npos )
					bGrabParams = false;
			}
		}

		// grab headers

		iNewLine = m_strReceiveBuf.find( C_STR_NEWLINE );
		iDoubleNewLine = m_strReceiveBuf.find( C_STR_DOUBLE_NEWLINE );

		if( iNewLine != iDoubleNewLine )
		{
			strTemp = m_strReceiveBuf.substr( iNewLine + ( sizeof(C_STR_NEWLINE) - 1 ), iDoubleNewLine - iNewLine - ( sizeof(C_STR_NEWLINE) - 1 ) );

			iSplit = 0;
			iEnd = 0;

			strKey = string( );
			strValue = string( );

			bGrabHeaders = true;

			while( bGrabHeaders )
			{
				iSplit = strTemp.find( C_STR_COLON );
				iEnd = strTemp.find( C_STR_NEWLINE );

				// http://www.addict3d.org/index.php?page=viewarticle&type=security&ID=4861
				if( iSplit == string :: npos || iSplit == 0 )
				{
					UTIL_LogPrint( "client warning: malformed HTTP request (bad header)\n" );

					bGrabHeaders = false;
				}

				strKey = strTemp.substr( 0, iSplit );
				strValue = strTemp.substr( iSplit + ( sizeof(": ") - 1 ), iEnd - iSplit - ( sizeof(C_STR_NEWLINE) - 1 ) );

				rqst.mapHeaders.insert( pair<string, string>( strKey, strValue ) );

				strTemp = strTemp.substr( iEnd + ( sizeof(C_STR_NEWLINE) - 1 ) );

				if( iEnd == string :: npos )
					bGrabHeaders = false;
			}
		}

		// grab cookies

		strCookies = rqst.mapHeaders["Cookie"];

		if( !strCookies.empty( ) )
		{
			iWhite = 0;

			iSplit = 0;
			iEnd = 0;		

			strKey = string( );
			strValue = string( );

			bGrabCookies = true;

			while( bGrabCookies )
			{
				iWhite = strCookies.find_first_not_of( C_STR_WSPACE );

				if( iWhite != string :: npos )
					strCookies = strCookies.substr( iWhite );

				iSplit = strCookies.find( C_STR_ITEMEQ );
				iEnd = strCookies.find( C_STR_SEMICOLON );

				if( iSplit == string :: npos )
				{
					UTIL_LogPrint( "client warning: malformed HTTP request (found cookie key without value)\n" );

					bGrabCookies = false;
				}

				strKey = UTIL_EscapedToString( strCookies.substr( 0, iSplit ) );
				strValue = UTIL_EscapedToString( strCookies.substr( iSplit + 1, iEnd - iSplit - 1 ) );

				// strip quotes

				if( strValue.size( ) > 1 && strValue[0] == CHAR_QUOTE )
					strValue = strValue.substr( 1, strValue.size( ) - 2 );

				rqst.mapCookies.insert( pair<string, string>( strKey, strValue ) );

				strCookies = strCookies.substr( iEnd + 1, strCookies.size( ) - iEnd - 1 );

				if( iEnd == string :: npos )
					bGrabCookies = false;
			}
		}

		// grab authentication
		strLogin = rqst.mapCookies["login"];
		strMD5 = rqst.mapCookies["md5"];

		strAuthorization = rqst.mapHeaders["Authorization"];
		
// 		if( ( !strAuthorization.empty( ) && strLogout != "1" ) || ( !strLogin.empty( ) ) )
		if( !strAuthorization.empty( ) )
		{
			iWhite = strAuthorization.find( C_STR_WSPACE );

			if( iWhite != string :: npos )
			{
				strType = strAuthorization.substr( 0, iWhite );
				strBase64 = strAuthorization.substr( iWhite + 1 );

				if( strType == "Basic" )
				{
					szAuth = b64decode( strBase64.c_str( ) );

					if( szAuth )
					{
						strAuth = szAuth;

						free( szAuth );

						iSplit = strAuth.find( C_STR_COLON );

						if( iSplit != string :: npos )
						{
							strLogin = strAuth.substr( 0, iSplit );
							strPass = strAuth.substr( iSplit + 1 );

#if defined ( XBNBT_MYSQL )
							// XBNBT MySQL Users Integration
							if( gbMySQLUsersOverrideUsers )
							{
								CMD5 md5( ( const char* )strPass.c_str( ) );
								strMD5 = md5.getMD5Digest( );
							}
							else
							{
#endif
								// Original code
								// calculate md5 hash of A1

								strA1 = strLogin + C_STR_COLON + gstrRealm + C_STR_COLON + strPass;

								memset( szMD5, 0, sizeof(szMD5) / sizeof(unsigned char) );

								MD5_CTX md5;

								MD5Init( &md5 );
								MD5Update( &md5, (const unsigned char *)strA1.c_str( ), (unsigned int)strA1.size( ) );
								MD5Final( szMD5, &md5 );

								strMD5 = string( (char *)szMD5, sizeof(szMD5) / sizeof(unsigned char) );

#if defined ( XBNBT_MYSQL )
							}
#endif
						}
					}
				}
			}
		}

// 		if ( strOldLogin.empty( ) )
// 		{
// 			if ( !strLogin.empty( ) )
// 				UTIL_LogPrint( "NewLogin: (%s)\n", strLogin.c_str( ) );
// 				rqst.user = gpServer->getTracker( )->checkUser( strOldLogin, strOldMD5 );
// 			if ( strLogout != "1" )
// 				if ( !strLogin.empty( ) )
		rqst.user = gpServer->getTracker( )->checkUser( strLogin, strMD5 );
				
				
// 			else
// 				rqst.user = gpServer->getTracker( )->checkUser( strOldLogin, strOldMD5 );
// 		}
		
// 		}
// 		else
// 		{
// 			rqst.user.strLogin.erase( );
// 			rqst.user.strLowerLogin.erase( );
// 			rqst.user.strMD5.erase( );
// 			rqst.user.strMail.erase( );
// 			rqst.user.strLowerMail.erase( );
// 			rqst.user.strCreated.erase( );
// 			rqst.user.ucAccess = 0;
// 		}

		if( rqst.strMethod == "POST" )
			m_ucState = CS_RECVBODY;
		else
		{
			m_ucState = CS_MAKERESPONSE;

			break;
		}

	case CS_RECVBODY:
		if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
			UTIL_LogPrint( "client: receive body\n" );

		strContentLength = rqst.mapHeaders["Content-Length"];

		if( strContentLength.empty( ) )
		{
			UTIL_LogPrint( "client error: malformed HTTP request (no Content-Length with POST)\n" );

			return true;
		}

		FD_ZERO( &fdClient );
		//FD_CLR( m_sckClient, &fdClient );
		FD_SET( m_sckClient, &fdClient );

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

#ifdef WIN32
		if( select( 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR )
#else
		if( select( m_sckClient + 1, &fdClient, 0, 0, &tv ) == SOCKET_ERROR )
#endif
		{
			UTIL_LogPrint( "client error: select error body (error %s)\n", GetLastErrorString( ) );

			return true;
		}

		if( FD_ISSET( m_sckClient, &fdClient ) )
		{
			m_ulLast = GetTime( );

			memset( gpBuf, 0, sizeof(gpBuf) / sizeof(char) );

			iRecv = recv( m_sckClient, gpBuf, sizeof(gpBuf), 0 );

			if( iRecv == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
			{
				if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
					UTIL_LogPrint( "client error: receive body error (error %s)\n", GetLastErrorString( ) );
				else if( GetLastError( ) != EPIPE && GetLastError( ) != ECONNRESET )
					UTIL_LogPrint( "client error: receive body error (error %s)\n", GetLastErrorString( ) );

				return true;
			}
			else if( iRecv == 0 )
			{
				UTIL_LogPrint( "client error: receive body returned 0\n" );

				return true;
			}
			else if( iRecv > 0 )
			{
				m_strReceiveBuf += string( gpBuf, iRecv );

				if( m_strReceiveBuf.size( ) > guiMaxRecvSize )
				{
					UTIL_LogPrint( "client error: exceeded max receive body size\n" );

					return true;
				}

				gtXStats.tcp.iRecv += iRecv;
			}
			else
			{
				UTIL_LogPrint( "client error: receive body returned garbage\n" );

				return true;
			}
		}

		if( m_strReceiveBuf.size( ) >= m_strReceiveBuf.find( C_STR_DOUBLE_NEWLINE ) + ( sizeof(C_STR_DOUBLE_NEWLINE) - 1 ) + atol( strContentLength.c_str( ) ) )
			m_ucState = CS_MAKERESPONSE;
		else
			break;

	case CS_MAKERESPONSE:
		if( gbDebug )
			UTIL_LogPrint( "client - make response\n" );

		if( rqst.strMethod == "GET" )
			gpServer->getTracker( )->serverResponseGET( &rqst, &rsp );
		else if( rqst.strMethod == "POST" )
		{
			CAtomList *pPost = UTIL_DecodeHTTPPost( m_strReceiveBuf );

			gpServer->getTracker( )->serverResponsePOST( &rqst, &rsp, pPost );

			if( pPost )
				delete pPost;
		}
		else
			rsp.strCode = "400 Bad Request";

		// compress

		cCompress = COMPRESS_NONE;

		if( rsp.bCompressOK && m_cCompression > 0 )
		{
			strAcceptEncoding = UTIL_ToLower( rqst.mapHeaders["Accept-Encoding"] );

			if( strAcceptEncoding.find( "gzip" ) != string :: npos )
				cCompress = COMPRESS_GZIP;
			else if( strAcceptEncoding.find( "deflate" ) != string :: npos )
				cCompress = COMPRESS_DEFLATE;
		}

		if( !rsp.strContent.empty( ) && cCompress != COMPRESS_NONE )
		{
			// allocate avail_in * 1.001 + 18 bytes (12 + 6 for gzip)

			uiSize = (unsigned int)( rsp.strContent.size( ) * 1.001 + 18 );

			pBuf = new unsigned char[uiSize];
			memset( pBuf, 0, sizeof(pBuf) / sizeof(unsigned char) );

			z_stream_s zCompress;

			//unsigned char
			pNextIn = new unsigned char[uiSize];
			memset( pNextIn, 0, sizeof(pNextIn) / sizeof(unsigned char) );
			snprintf( (char *)pNextIn, uiSize / sizeof(unsigned char), "%s", rsp.strContent.c_str( ) );

			zCompress.next_in = pNextIn;
			zCompress.avail_in = (unsigned int)rsp.strContent.size( );
			zCompress.next_out = pBuf;
			zCompress.avail_out = uiSize;
			zCompress.zalloc = (alloc_func)0;
			zCompress.zfree = (free_func)0;
			zCompress.opaque = (voidpf)0;
			zCompress.total_in = 0;
			zCompress.total_out = 0;

			windowBits = 15;

			if( cCompress == COMPRESS_GZIP )
				windowBits = 31;

			iResult = deflateInit2( &zCompress, m_cCompression, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY );

			if( iResult == Z_OK )
			{
				iResult = deflate( &zCompress, Z_FINISH );

				if( iResult == Z_STREAM_END )
				{
					if( zCompress.total_in > zCompress.total_out )
					{
						if( gbDebug )
							UTIL_LogPrint( "client: (zlib) compressed %lu bytes to %lu bytes\n", zCompress.total_in, zCompress.total_out );

						if( cCompress == COMPRESS_GZIP )
							rsp.mapHeaders.insert( pair<string, string>( "Content-Encoding", "gzip" ) );
						else
							rsp.mapHeaders.insert( pair<string, string>( "Content-Encoding", "deflate" ) );

						rsp.strContent = string( (char *)pBuf, zCompress.total_out );
					}

					deflateEnd( &zCompress );

					delete [] pBuf;
				}
				else
				{
					if( iResult != Z_OK )
						UTIL_LogPrint( "client warning: (zlib) deflate error (%d) on \"%s\", in = %u, sending raw\n", iResult, rqst.strURL.c_str( ), rsp.strContent.size( ) );

					deflateEnd( &zCompress );

					delete [] pBuf;
				}
			}
			else
			{
				UTIL_LogPrint( "client warning: (zlib) deflateInit2 error (%d), sending raw\n", iResult );

				delete [] pBuf;
			}

			delete [] pNextIn;
		}

		// keep alive

		if( UTIL_ToLower( rqst.mapHeaders["Connection"] ) == "keep-alive" )
		{
			m_bKeepAlive = true;

			rsp.mapHeaders.insert( pair<string, string>( "Connection", "Keep-Alive" ) );
			rsp.mapHeaders.insert( pair<string, string>( "Keep-Alive", CAtomInt( m_uiTimeOut - 1 ).toString( ) ) );
		}
		else
		{
			m_bKeepAlive = false;

			rsp.mapHeaders.insert( pair<string, string>( "Connection", "Close" ) );
		}

		rsp.mapHeaders.insert( pair<string, string>( "Content-Length", CAtomLong( rsp.strContent.size( ) ).toString( ) ) );

		// access log

		strRequest = string( );

		iNewLine = m_strReceiveBuf.find( C_STR_NEWLINE );

		if( iNewLine != string :: npos )
			strRequest = m_strReceiveBuf.substr( 0, iNewLine );

		UTIL_AccessLogPrint( inet_ntoa( rqst.sin.sin_addr ), rqst.user.strLogin, strRequest, atoi( rsp.strCode.substr( 0, 3 ).c_str( ) ), (int)rsp.strContent.size( ) );

		// compose send buffer

		// fix for \r\n issues with non-tolerant HTTP client implementations - DWK
		m_strSendBuf += "HTTP/1.1 " + rsp.strCode + "\r\n";

		for( multimap<string, string> :: iterator it = rsp.mapHeaders.begin( ); it != rsp.mapHeaders.end( ); it++ )
			m_strSendBuf += (*it).first + ": " + (*it).second + "\r\n";

		m_strSendBuf += "\r\n";
		m_strSendBuf += rsp.strContent;

		m_ucState = CS_SEND;

	case CS_SEND:
		if( gbDebug )
			UTIL_LogPrint( "client - send\n" );

		FD_ZERO( &fdClient );
		//FD_CLR( m_sckClient, &fdClient );
		FD_SET( m_sckClient, &fdClient );

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

#ifdef WIN32
		if( select( 1, 0, &fdClient, 0, &tv ) == SOCKET_ERROR )
#else
		if( select( m_sckClient + 1, 0, &fdClient, 0, &tv ) == SOCKET_ERROR )
#endif
		{
			UTIL_LogPrint( "client error: select error send (error %s)\n", GetLastErrorString( ) );

			return true;
		}

		if( FD_ISSET( m_sckClient, &fdClient ) )
		{
			m_ulLast = GetTime( );

			iSend = send( m_sckClient, m_strSendBuf.c_str( ), (int)m_strSendBuf.size( ), MSG_NOSIGNAL );

			if( iSend == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
			{
				if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
					UTIL_LogPrint( "client error: send error (error %s)\n", GetLastErrorString( ) );
				else if( GetLastError( ) != EPIPE && GetLastError( ) != ECONNRESET )
					UTIL_LogPrint( "client error: send error (error %s)\n", GetLastErrorString( ) );

				return true;
			}
			else if( iSend == 0 )
			{
				UTIL_LogPrint( "client error: send returned 0\n" );

				return true;
			}
			else if( iSend > 0 )
			{
				m_strSendBuf = m_strSendBuf.substr( iSend );

				gtXStats.tcp.iSend += iSend;

				if( m_strSendBuf.empty( ) )
				{
					if( m_bKeepAlive )
					{
						if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
							UTIL_LogPrint( "client: keep alive\n" );

						Reset( );

						return false;
					}
					else
						return true;
				}
			}
			else
			{
				UTIL_LogPrint( "client error: send returned garbage\n" );

				return true;
			}
		}

		break;

	default:
		UTIL_LogPrint( "client error: unknown state\n" );
	}

	if( gbDebug && ( gucDebugLevel & DEBUG_CLIENT ) )
		UTIL_LogPrint( "client: update end\n" );

	m_bReset = false;
	return false;
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
0
inline CAtomList *UTIL_DecodeHTTPPost( const string &cstrPost )
{
	// find the boundary

	string :: size_type iBoundary = cstrPost.find( C_STR_BOUNDARY );

	if( iBoundary == string :: npos )
		return 0;

	iBoundary += ( sizeof(C_STR_BOUNDARY) - 1 );

	string strBoundary = cstrPost.substr( iBoundary );

	const string :: size_type ciBoundEnd( strBoundary.find( C_STR_NEWLINE ) );

	if( ciBoundEnd == string :: npos )
		return 0;

	strBoundary = strBoundary.substr( 0, ciBoundEnd );

	// strBoundary now contains the boundary

	string :: size_type iContent = cstrPost.find( C_STR_DOUBLE_NEWLINE );

	if( iContent == string :: npos )
		return 0;

	iContent += ( sizeof(C_STR_DOUBLE_NEWLINE) - 1 );

	const string cstrContent( cstrPost.substr( iContent ) );

	// decode

	CAtomList *pList = new CAtomList( );

	CAtomDicti *pSegment = 0;

	string :: size_type iSegStart = 0;
	string :: size_type iSegEnd = 0;

	string :: size_type iDispPrev = 0;
	string :: size_type iDispPos = 0;

	CAtomDicti *pDisp = 0;

	string strSeg = string( );
	string strDisp = string( );

	string :: size_type iDispStart = 0;
	string :: size_type iDispEnd = 0;

	string strCurr = string( );

	string :: size_type iSplit = 0;
	string :: size_type iKeyStart = 0;

	string strKey = string( );
	string strValue = string( );

	string :: size_type iDataStart = 0;

	bool bDoSegmentLoop = true;

	while( bDoSegmentLoop )
	{
		// segment start

		iSegStart = cstrContent.find( strBoundary, iSegStart );

		if( iSegStart == string :: npos )
			return pList;

		iSegStart += strBoundary.size( );

		if( cstrContent.substr( iSegStart, 2 ) == C_STR_SEGSTART )
			return pList;

		iSegStart += ( sizeof(C_STR_SEGSTART) - 1 );

		// segment end

		iSegEnd = cstrContent.find( strBoundary, iSegStart );

		if( iSegEnd == string :: npos )
		{
			UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_end"] + "\n" ).c_str( ) );

			delete pList;

			pList = 0;

			return 0;
		}

		iSegEnd -= ( sizeof(C_STR_SEGEND) - 1 );

		// found segment

		pSegment = new CAtomDicti( );

		pList->addItem( pSegment );

		// this could do with some serious optimizing...

		strSeg = cstrContent.substr( iSegStart, iSegEnd - iSegStart );

		iDispStart = strSeg.find( C_STR_DISPSTART );

		if( iDispStart == string :: npos )
		{
			UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_notfound"] + "\n" ).c_str( ) );

			delete pList;

			pList = 0;

			return 0;
		}

		iDispStart += ( sizeof(C_STR_DISPSTART) - 1 );

		iDispEnd = strSeg.find( C_STR_NEWLINE, iDispStart );

		if( iDispEnd == string :: npos )
		{
			UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_disposition"] + "\n" ).c_str( ) );

			delete pList;

			pList = 0;

			return 0;
		}

		strDisp = strSeg.substr( iDispStart, iDispEnd - iDispStart );

		iDispPrev = 0;
		iDispPos = 0;

		pDisp = new CAtomDicti( );

		pSegment->setItem( "disposition", pDisp );

		bool bDoItemLoop = true;

		while( bDoItemLoop )
		{
			// assume a semicolon indicates the end of the item and will never appear inside the item (probably a bad assumption)

			iDispPrev = iDispPos;
			iDispPos = strDisp.find( C_STR_ITEMEND, iDispPos );

			if( iDispPos == string :: npos )
			{
				// decode last item

				iDispPos = strDisp.size( );
			}

			strCurr = strDisp.substr( iDispPrev, iDispPos - iDispPrev );

			iSplit = strCurr.find( C_STR_ITEMEQ );

			if( iSplit == string :: npos )
			{
				// found a key without value, i.e. "form-data", useless so ignore it

				if( iDispPos == strDisp.size( ) )
					break;

				// + strlen( ";" )

				iDispPos++;

				continue;
			}

			// strip whitespace

			iKeyStart = strCurr.find_first_not_of( C_STR_WSPACE );

			if( iKeyStart == string :: npos || iKeyStart > iSplit )
			{
				UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_disposition"] + "\n" ).c_str( ) );

				delete pList;

				pList = 0;

				return 0;
			}

			strKey = strCurr.substr( iKeyStart, iSplit - iKeyStart );
			strValue = strCurr.substr( iSplit + 1 );

			// strip quotes

			if( strValue.size( ) > 1 && strValue[0] == CHAR_QUOTE )
				strValue = strValue.substr( 1, strValue.size( ) - 2 );

			pDisp->setItem( strKey, new CAtomString( strValue ) );

			if( iDispPos == strDisp.size( ) )
				bDoItemLoop = false;

			// + strlen( ";" )

			iDispPos++;
		}

		// data

		iDataStart = strSeg.find( C_STR_DOUBLE_NEWLINE );

		if( iDataStart == string :: npos )
		{
			UTIL_LogPrint( string( gmapLANG_CFG["decode_http_post_segment"] + "\n" ).c_str( ) );

			delete pList;

			pList = 0;

			return 0;
		}

		iDataStart += ( sizeof(C_STR_DOUBLE_NEWLINE) - 1 );

		pSegment->setItem( "data", new CAtomString( strSeg.substr( iDataStart ) ) );
	}

	// this should never happen, so who cares

	delete pList;

	pList = 0;

	return 0;
}