/// \file /// /// This file is part of RakNet Copyright 2003 Kevin Jenkins. /// /// Usage of RakNet is subject to the appropriate license agreement. /// Creative Commons Licensees are subject to the /// license found at /// http://creativecommons.org/licenses/by-nc/2.5/ /// Single application licensees are subject to the license found at /// http://www.rakkarsoft.com/SingleApplicationLicense.html /// Custom license users are subject to the terms therein. /// GPL license users are subject to the GNU General Public /// License as published by the Free /// Software Foundation; either version 2 of the License, or (at your /// option) any later version. #include "RakServer.h" #include "PacketEnumerations.h" #include "GetTime.h" #include "Rand.h" #ifdef _MSC_VER #pragma warning( push ) #endif RakServer::RakServer() { nextSeedUpdate = 0; synchronizedRandomInteger = false; relayStaticClientData = false; broadcastPingsTime = 0; } RakServer::~RakServer() {} void RakServer::InitializeSecurity( const char *pubKeyE, const char *pubKeyN ) { RakPeer::InitializeSecurity( 0, 0, pubKeyE, pubKeyN ); } void RakServer::DisableSecurity( void ) { RakPeer::DisableSecurity(); } #ifdef _MSC_VER #pragma warning( disable : 4100 ) // warning C4100: 'depreciated' : unreferenced formal parameter #endif bool RakServer::Start( unsigned short AllowedPlayers, unsigned int depreciated, int threadSleepTimer, unsigned short port, const char *forceHostAddress ) { bool init; RakPeer::Disconnect( 30 ); init = RakPeer::Initialize( AllowedPlayers, port, threadSleepTimer, forceHostAddress ); RakPeer::SetMaximumIncomingConnections( AllowedPlayers ); // Random number seed RakNetTime time = RakNet::GetTime(); seedMT( (unsigned int) time ); seed = randomMT(); if ( seed % 2 == 0 ) // Even seed--; // make odd nextSeed = randomMT(); if ( nextSeed % 2 == 0 ) // Even nextSeed--; // make odd return init; } void RakServer::SetPassword( const char *_password ) { if ( _password ) { RakPeer::SetIncomingPassword( _password, ( int ) strlen( _password ) + 1 ); } else { RakPeer::SetIncomingPassword( 0, 0 ); } } bool RakServer::HasPassword( void ) { int passwordLength; GetIncomingPassword(0, &passwordLength); return passwordLength > 0; } void RakServer::Disconnect( unsigned int blockDuration, unsigned char orderingChannel ) { RakPeer::Disconnect( blockDuration, orderingChannel ); } bool RakServer::Send( const char *data, const int length, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast ) { return RakPeer::Send( data, length, priority, reliability, orderingChannel, playerId, broadcast ); } bool RakServer::Send( RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast ) { return RakPeer::Send( bitStream, priority, reliability, orderingChannel, playerId, broadcast ); } Packet* RakServer::Receive( void ) { Packet * packet = RakPeer::Receive(); // This is just a regular time based update. Nowhere else good to put it if ( RakPeer::IsActive() && occasionalPing ) { RakNetTime time = RakNet::GetTime(); if ( time > broadcastPingsTime || ( packet && packet->data[ 0 ] == ID_RECEIVED_STATIC_DATA ) ) { if ( time > broadcastPingsTime ) broadcastPingsTime = time + 30000; // Broadcast pings every 30 seconds unsigned i, count; RemoteSystemStruct *remoteSystem; RakNet::BitStream bitStream( ( PlayerID_Size + sizeof( short ) ) * 32 + sizeof(unsigned char) ); unsigned char typeId = ID_BROADCAST_PINGS; bitStream.Write( typeId ); //for ( i = 0, count = 0; count < 32 && i < remoteSystemListSize; i++ ) for ( i = 0, count = 0; count < 32 && i < maximumNumberOfPeers; i++ ) { remoteSystem = remoteSystemList + i; if ( remoteSystem->playerId != UNASSIGNED_PLAYER_ID && remoteSystem->isActive) { bitStream.Write( remoteSystem->playerId.binaryAddress ); bitStream.Write( remoteSystem->playerId.port ); bitStream.Write( remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime ); count++; } } if ( count > 0 ) // If we wrote anything { if ( packet && packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) // If this was a new connection Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, false ); // Send to the new connection else Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, UNASSIGNED_PLAYER_ID, true ); // Send to everyone } } } // This is just a regular time based update. Nowhere else good to put it if ( RakPeer::IsActive() && synchronizedRandomInteger ) { RakNetTime time = RakNet::GetTime(); if ( time > nextSeedUpdate || ( packet && packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) ) { if ( time > nextSeedUpdate ) nextSeedUpdate = time + 9000; // Seeds are updated every 9 seconds seed = nextSeed; nextSeed = randomMT(); if ( nextSeed % 2 == 0 ) // Even nextSeed--; // make odd /* SetRandomNumberSeedStruct s; s.ts = ID_TIMESTAMP; s.timeStamp = RakNet::GetTime(); s.typeId = ID_SET_RANDOM_NUMBER_SEED; s.seed = seed; s.nextSeed = nextSeed; RakNet::BitStream s_BitS( SetRandomNumberSeedStruct_Size ); s.Serialize( s_BitS ); */ RakNet::BitStream outBitStream(sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned int)); outBitStream.Write((unsigned char) ID_TIMESTAMP); outBitStream.Write((unsigned int) RakNet::GetTime()); outBitStream.Write((unsigned char) ID_SET_RANDOM_NUMBER_SEED); outBitStream.Write(seed); outBitStream.Write(nextSeed); if ( packet && packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) Send( &outBitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, false ); else Send( &outBitStream, SYSTEM_PRIORITY, RELIABLE, 0, UNASSIGNED_PLAYER_ID, true ); } } if ( packet ) { // Intercept specific client / server feature packets. This will do an extra send and still pass on the data to the user if ( packet->data[ 0 ] == ID_RECEIVED_STATIC_DATA ) { if ( relayStaticClientData ) { // Relay static data to the other systems but the sender RakNet::BitStream bitStream( packet->length + PlayerID_Size ); unsigned char typeId = ID_REMOTE_STATIC_DATA; bitStream.Write( typeId ); bitStream.Write( packet->playerId.binaryAddress ); bitStream.Write( packet->playerId.port ); bitStream.Write( packet->playerIndex ); bitStream.Write( ( char* ) packet->data + sizeof(unsigned char), packet->length - sizeof(unsigned char) ); Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, true ); } } else if ( packet->data[ 0 ] == ID_DISCONNECTION_NOTIFICATION || packet->data[ 0 ] == ID_CONNECTION_LOST || packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) { // Relay the disconnection RakNet::BitStream bitStream( packet->length + PlayerID_Size ); unsigned char typeId; if ( packet->data[ 0 ] == ID_DISCONNECTION_NOTIFICATION ) typeId = ID_REMOTE_DISCONNECTION_NOTIFICATION; else if ( packet->data[ 0 ] == ID_CONNECTION_LOST ) typeId = ID_REMOTE_CONNECTION_LOST; else typeId = ID_REMOTE_NEW_INCOMING_CONNECTION; bitStream.Write( typeId ); bitStream.Write( packet->playerId.binaryAddress ); bitStream.Write( packet->playerId.port ); bitStream.Write( ( unsigned short& ) packet->playerIndex ); Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, true ); if ( packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) { unsigned i; //for ( i = 0; i < remoteSystemListSize; i++ ) for ( i = 0; i < maximumNumberOfPeers; i++ ) { if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].playerId != UNASSIGNED_PLAYER_ID && packet->playerId != remoteSystemList[ i ].playerId ) { bitStream.Reset(); typeId = ID_REMOTE_EXISTING_CONNECTION; bitStream.Write( typeId ); bitStream.Write( remoteSystemList[ i ].playerId.binaryAddress ); bitStream.Write( remoteSystemList[ i ].playerId.port ); bitStream.Write( ( unsigned short ) i ); // One send to tell them of the connection Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, false ); if ( relayStaticClientData ) { bitStream.Reset(); typeId = ID_REMOTE_STATIC_DATA; bitStream.Write( typeId ); bitStream.Write( remoteSystemList[ i ].playerId.binaryAddress ); bitStream.Write( remoteSystemList[ i ].playerId.port ); bitStream.Write( (unsigned short) i ); bitStream.Write( ( char* ) remoteSystemList[ i ].staticData.GetData(), remoteSystemList[ i ].staticData.GetNumberOfBytesUsed() ); // Another send to tell them of the static data Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, false ); } } } } } } return packet; } void RakServer::Kick( const PlayerID playerId ) { RakPeer::CloseConnection(playerId, true, 0); } void RakServer::DeallocatePacket( Packet *packet ) { RakPeer::DeallocatePacket( packet ); } void RakServer::SetAllowedPlayers( unsigned short AllowedPlayers ) { RakPeer::SetMaximumIncomingConnections( AllowedPlayers ); } unsigned short RakServer::GetAllowedPlayers( void ) const { return RakPeer::GetMaximumIncomingConnections(); } unsigned short RakServer::GetConnectedPlayers( void ) { unsigned short numberOfSystems; RakPeer::GetConnectionList( 0, &numberOfSystems ); return numberOfSystems; } void RakServer::GetPlayerIPFromID( const PlayerID playerId, char returnValue[ 22 ], unsigned short *port ) { *port = playerId.port; strcpy( returnValue, RakPeer::PlayerIDToDottedIP( playerId ) ); } void RakServer::PingPlayer( const PlayerID playerId ) { RakPeer::Ping( playerId ); } int RakServer::GetAveragePing( const PlayerID playerId ) { return RakPeer::GetAveragePing( playerId ); } int RakServer::GetLastPing( const PlayerID playerId ) { return RakPeer::GetLastPing( playerId ); } int RakServer::GetLowestPing( const PlayerID playerId ) { return RakPeer::GetLowestPing( playerId ); } void RakServer::StartOccasionalPing( void ) { RakPeer::SetOccasionalPing( true ); } void RakServer::StopOccasionalPing( void ) { RakPeer::SetOccasionalPing( false ); } bool RakServer::IsActive( void ) const { return RakPeer::IsActive(); } unsigned int RakServer::GetSynchronizedRandomInteger( void ) const { return seed; } void RakServer::StartSynchronizedRandomInteger( void ) { synchronizedRandomInteger = true; } void RakServer::StopSynchronizedRandomInteger( void ) { synchronizedRandomInteger = false; } bool RakServer::GenerateCompressionLayer( unsigned int inputFrequencyTable[ 256 ], bool inputLayer ) { return RakPeer::GenerateCompressionLayer( inputFrequencyTable, inputLayer ); } bool RakServer::DeleteCompressionLayer( bool inputLayer ) { return RakPeer::DeleteCompressionLayer( inputLayer ); } void RakServer::RegisterAsRemoteProcedureCall( char* uniqueID, void ( *functionPointer ) ( RPCParameters *rpcParms ) ) { RakPeer::RegisterAsRemoteProcedureCall( uniqueID, functionPointer ); } void RakServer::RegisterClassMemberRPC( char* uniqueID, void *functionPointer ) { RakPeer::RegisterClassMemberRPC( uniqueID, functionPointer ); } void RakServer::UnregisterAsRemoteProcedureCall( char* uniqueID ) { RakPeer::UnregisterAsRemoteProcedureCall( uniqueID ); } bool RakServer::RPC( char* uniqueID, const char *data, unsigned int bitLength, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool shiftTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget ) { return RakPeer::RPC( uniqueID, data, bitLength, priority, reliability, orderingChannel, playerId, broadcast, shiftTimestamp, networkID, replyFromTarget ); } bool RakServer::RPC( char* uniqueID, RakNet::BitStream *parameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool shiftTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget ) { return RakPeer::RPC( uniqueID, parameters, priority, reliability, orderingChannel, playerId, broadcast, shiftTimestamp, networkID, replyFromTarget ); } void RakServer::SetTrackFrequencyTable( bool b ) { RakPeer::SetCompileFrequencyTable( b ); } bool RakServer::GetSendFrequencyTable( unsigned int outputFrequencyTable[ 256 ] ) { return RakPeer::GetOutgoingFrequencyTable( outputFrequencyTable ); } float RakServer::GetCompressionRatio( void ) const { return RakPeer::GetCompressionRatio(); } float RakServer::GetDecompressionRatio( void ) const { return RakPeer::GetDecompressionRatio(); } void RakServer::AttachPlugin( PluginInterface *messageHandler ) { RakPeer::AttachPlugin(messageHandler); } void RakServer::DetachPlugin( PluginInterface *messageHandler ) { RakPeer::DetachPlugin(messageHandler); } RakNet::BitStream * RakServer::GetStaticServerData( void ) { return RakPeer::GetRemoteStaticData( myPlayerId ); } void RakServer::SetStaticServerData( const char *data, const int length ) { RakPeer::SetRemoteStaticData( myPlayerId, data, length ); } void RakServer::SetRelayStaticClientData( bool b ) { relayStaticClientData = b; } void RakServer::SendStaticServerDataToClient( const PlayerID playerId ) { RakPeer::SendStaticData( playerId ); } void RakServer::SetOfflinePingResponse( const char *data, const unsigned int length ) { RakPeer::SetOfflinePingResponse( data, length ); } RakNet::BitStream * RakServer::GetStaticClientData( const PlayerID playerId ) { return RakPeer::GetRemoteStaticData( playerId ); } void RakServer::SetStaticClientData( const PlayerID playerId, const char *data, const int length ) { RakPeer::SetRemoteStaticData( playerId, data, length ); } // This will read the data from playerChangedId and send it to playerToSendToId void RakServer::ChangeStaticClientData( const PlayerID playerChangedId, PlayerID playerToSendToId ) { RemoteSystemStruct * remoteSystem = GetRemoteSystemFromPlayerID( playerChangedId, false, true ); if ( remoteSystem == 0 ) return ; // No such playerChangedId // Relay static data to the other systems but the sender RakNet::BitStream bitStream; unsigned char typeId = ID_REMOTE_STATIC_DATA; bitStream.Write( typeId ); bitStream.Write( playerChangedId.binaryAddress ); bitStream.Write( playerChangedId.port ); bitStream.Write( ( char* ) remoteSystem->staticData.GetData(), remoteSystem->staticData.GetNumberOfBytesUsed() ); Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, playerToSendToId, true ); } unsigned int RakServer::GetNumberOfAddresses( void ) { return RakPeer::GetNumberOfAddresses(); } PlayerID RakServer::GetInternalID( void ) const { return RakPeer::GetInternalID(); } void RakServer::PushBackPacket( Packet *packet, bool pushAtHead ) { RakPeer::PushBackPacket(packet, pushAtHead); } void RakServer::SetRouterInterface( RouterInterface *routerInterface ) { RakPeer::SetRouterInterface(routerInterface); } void RakServer::RemoveRouterInterface( RouterInterface *routerInterface ) { RakPeer::RemoveRouterInterface(routerInterface); } const char* RakServer::GetLocalIP( unsigned int index ) { return RakPeer::GetLocalIP( index ); } int RakServer::GetIndexFromPlayerID( const PlayerID playerId ) { return RakPeer::GetIndexFromPlayerID( playerId ); } PlayerID RakServer::GetPlayerIDFromIndex( int index ) { return RakPeer::GetPlayerIDFromIndex( index ); } void RakServer::AddToBanList( const char *IP ) { RakPeer::AddToBanList( IP ); } void RakServer::RemoveFromBanList( const char *IP ) { RakPeer::RemoveFromBanList( IP ); } void RakServer::ClearBanList( void ) { RakPeer::ClearBanList(); } bool RakServer::IsBanned( const char *IP ) { return RakPeer::IsBanned( IP ); } bool RakServer::IsActivePlayerID( const PlayerID playerId ) { return RakPeer::GetRemoteSystemFromPlayerID( playerId, false, true ) != 0; } void RakServer::SetTimeoutTime( RakNetTime timeMS, const PlayerID target ) { RakPeer::SetTimeoutTime(timeMS, target); } bool RakServer::SetMTUSize( int size ) { return RakPeer::SetMTUSize( size ); } int RakServer::GetMTUSize( void ) const { return RakPeer::GetMTUSize(); } void RakServer::AdvertiseSystem( const char *host, unsigned short remotePort, const char *data, int dataLength ) { RakPeer::AdvertiseSystem( host, remotePort, data, dataLength ); } RakNetStatisticsStruct * const RakServer::GetStatistics( const PlayerID playerId ) { return RakPeer::GetStatistics( playerId ); } void RakServer::ApplyNetworkSimulator( double maxSendBPS, unsigned short minExtraPing, unsigned short extraPingVariance) { RakPeer::ApplyNetworkSimulator( maxSendBPS, minExtraPing, extraPingVariance ); } bool RakServer::IsNetworkSimulatorActive( void ) { return RakPeer::IsNetworkSimulatorActive(); } #ifdef _MSC_VER #pragma warning( pop ) #endif