diff --git a/CMakeLists.txt b/CMakeLists.txt index 94c66ef..189c2b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,5 @@ +option(RAKNET_BUILD_FOR_CLIENT "Build RakNet without server-side functionality" NO) + if(WIN32) add_definitions( -D_CRT_SECURE_NO_WARNINGS @@ -50,7 +52,11 @@ target_include_directories(raknet ) if (WIN32) - target_link_libraries(raknet Ws2_32 OMP-SDK) + target_link_libraries(raknet Ws2_32) +endif() + +if (RAKNET_BUILD_FOR_CLIENT) + target_compile_definitions(raknet PUBLIC -DRAKNET_BUILD_FOR_CLIENT) else() target_link_libraries(raknet OMP-SDK) endif() diff --git a/Include/raknet/RakPeer.h b/Include/raknet/RakPeer.h index 565106d..0a50141 100644 --- a/Include/raknet/RakPeer.h +++ b/Include/raknet/RakPeer.h @@ -476,10 +476,12 @@ namespace RakNet /// \sa RakNetStatistics.h RakNetStatisticsStruct * GetStatistics( const PlayerID playerId ) override; +#ifndef RAKNET_BUILD_FOR_CLIENT /// Reserves a number of connection slots for internal use (e.g., NPCs). /// Reserved slots are subtracted from the maximum peer limit when accepting new connections. /// \param[in] count: The number of slots to reserve. void ReserveSlots(unsigned short count) override; +#endif // --------------------------------------------------------------------------------------------EVERYTHING AFTER THIS COMMENT IS FOR INTERNAL USE ONLY-------------------------------------------------------------------------------------------- /// \internal @@ -513,7 +515,9 @@ namespace RakNet bool setAESKey; /// true if security is enabled. RPCMap rpcMap; /// Mapping of RPC calls to single byte integers to save transmission bandwidth. enum ConnectMode {NO_ACTION, DISCONNECT_ASAP, DISCONNECT_ASAP_SILENTLY, DISCONNECT_ON_NO_ACK, REQUESTED_CONNECTION, HANDLING_CONNECTION_REQUEST, UNVERIFIED_SENDER, SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET, CONNECTED} connectMode; +#ifndef RAKNET_BUILD_FOR_CLIENT SAMPRakNet::RemoteSystemData sampData; +#endif bool isLogon; }; @@ -534,7 +538,9 @@ namespace RakNet friend void* UpdateNetworkLoop( void* arguments ); #endif +#ifndef RAKNET_BUILD_FOR_CLIENT friend bool __stdcall ProcessBan(RakPeer* rakPeer, PlayerID playerId, const char* data, const int length); +#endif // This is done to provide custom RPC handling when in a blocking RPC Packet* ReceiveIgnoreRPC( void ); @@ -548,11 +554,13 @@ namespace RakNet /// \return 0 if none RemoteSystemStruct *GetRemoteSystemFromPlayerID( const PlayerID playerID, bool calledFromNetworkThread, bool onlyActive) const; ///Parse out a connection request packet +#ifndef RAKNET_BUILD_FOR_CLIENT void ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, PlayerID playerId, const char *data, int byteSize); bool ParseConnectionAuthPacket(RakPeer::RemoteSystemStruct* remoteSystem, PlayerID playerId, unsigned char* data, int byteSize); ///When we get a connection request from an ip / port, accept it unless full void OnConnectionRequest( RakPeer::RemoteSystemStruct *remoteSystem, unsigned char *AESKey, bool setAESKey ); void AcceptConnectionRequest(RakPeer::RemoteSystemStruct* remoteSystem); +#endif ///Send a reliable disconnect packet to this player and disconnect them when it is delivered void NotifyAndFlagForDisconnect( const PlayerID playerId, bool performImmediate, unsigned char orderingChannel ); ///Returns how many remote systems initiated a connection to us @@ -593,8 +601,10 @@ namespace RakNet ///Store number of active peers. unsigned short activePeersCount; +#ifndef RAKNET_BUILD_FOR_CLIENT ///Store reserved slots, for the times slots are taken outside of RakNet unsigned short reservedSlots; +#endif //05/02/06 Just using maximumNumberOfPeers instead ///Store the maximum number of peers able to connect, including reserved connection slots for pings, etc. diff --git a/Include/raknet/RakPeerInterface.h b/Include/raknet/RakPeerInterface.h index 3a3e415..020bc6e 100644 --- a/Include/raknet/RakPeerInterface.h +++ b/Include/raknet/RakPeerInterface.h @@ -448,10 +448,12 @@ namespace RakNet /// \sa RakNetStatistics.h virtual RakNetStatisticsStruct * GetStatistics( const PlayerID playerId )=0; +#ifndef RAKNET_BUILD_FOR_CLIENT /// Reserves a number of connection slots for internal use (e.g., NPCs). /// Reserved slots are subtracted from the maximum peer limit when accepting new connections. /// \param[in] count: The number of slots to reserve. virtual void ReserveSlots(unsigned short count) = 0; +#endif // --------------------------------------------------------------------------------------------EVERYTHING AFTER THIS COMMENT IS FOR INTERNAL USE ONLY-------------------------------------------------------------------------------------------- /// \internal diff --git a/Include/raknet/RakServer.h b/Include/raknet/RakServer.h index bd19804..91cf7da 100644 --- a/Include/raknet/RakServer.h +++ b/Include/raknet/RakServer.h @@ -435,16 +435,20 @@ namespace RakNet /// \sa RakNetStatistics.h RakNetStatisticsStruct * GetStatistics( const PlayerID playerId ) override; +#ifndef RAKNET_BUILD_FOR_CLIENT /// Return the SAMPRakNet RemoteSystemData for a player ID virtual SAMPRakNet::RemoteSystemData GetSAMPDataFromPlayerID(const PlayerID playerId) override; +#endif /// Get Remote System data for a player from their ID virtual RakPeer::RemoteSystemStruct* GetRemoteSystemFromPlayerID(const PlayerID playerId) override; +#ifndef RAKNET_BUILD_FOR_CLIENT /// Reserves a number of connection slots for internal use (e.g., NPCs). /// Reserved slots are subtracted from the maximum peer limit when accepting new connections. /// \param[in] count: The number of slots to reserve. void ReserveSlots(unsigned short count) override; +#endif private: unsigned int seed, nextSeed; diff --git a/Include/raknet/RakServerInterface.h b/Include/raknet/RakServerInterface.h index 223d8fe..a29750b 100644 --- a/Include/raknet/RakServerInterface.h +++ b/Include/raknet/RakServerInterface.h @@ -429,16 +429,20 @@ namespace RakNet /// \sa RakNetStatistics.h virtual RakNetStatisticsStruct * GetStatistics( const PlayerID playerId )=0; +#ifndef RAKNET_BUILD_FOR_CLIENT /// Get SAMP data for a player from their ID virtual SAMPRakNet::RemoteSystemData GetSAMPDataFromPlayerID(const PlayerID playerId) = 0; +#endif /// Get Remote System data for a player from their ID virtual RakPeer::RemoteSystemStruct* GetRemoteSystemFromPlayerID(const PlayerID playerId) = 0; +#ifndef RAKNET_BUILD_FOR_CLIENT /// Reserves a number of connection slots for internal use (e.g., NPCs). /// Reserved slots are subtracted from the maximum peer limit when accepting new connections. /// \param[in] count: The number of slots to reserve. virtual void ReserveSlots(unsigned short count) = 0; +#endif }; } diff --git a/SAMPRakNet.cpp b/SAMPRakNet.cpp index 99dcdca..2abd74c 100644 --- a/SAMPRakNet.cpp +++ b/SAMPRakNet.cpp @@ -11,22 +11,33 @@ uint8_t SAMPRakNet::decryptBuffer_[MAXIMUM_MTU_SIZE]; uint8_t SAMPRakNet::encryptBuffer_[MAXIMUM_MTU_SIZE]; +#ifdef RAKNET_BUILD_FOR_CLIENT +char SAMPRakNet::authkeyBuffer_[AUTHKEY_RESPONSE_LEN]; +bool SAMPRakNet::connectAsNpc_ = false; +#endif +#ifndef RAKNET_BUILD_FOR_CLIENT uint32_t SAMPRakNet::token_; +#endif uint16_t SAMPRakNet::portNumber = 7777; +#ifndef RAKNET_BUILD_FOR_CLIENT Query* SAMPRakNet::query_ = nullptr; +#endif unsigned int SAMPRakNet::timeout_ = 10000; +#ifndef RAKNET_BUILD_FOR_CLIENT unsigned int SAMPRakNet::minConnectionTime_ = 0; unsigned int SAMPRakNet::messagesLimit_ = 500; unsigned int SAMPRakNet::messageHoleLimit_ = 3000; unsigned int SAMPRakNet::acksLimit_ = 3000; unsigned int SAMPRakNet::networkLimitsBanTime_ = 60000; +#endif float SAMPRakNet::minimumSendBitsPerSecond_ = 96000.0f; +#ifndef RAKNET_BUILD_FOR_CLIENT bool SAMPRakNet::logCookies_ = false; ICore* SAMPRakNet::core_ = nullptr; FlatHashSet SAMPRakNet::incomingConnections_; RakNet::RakNetTime SAMPRakNet::gracePeriod_ = 0; FlatHashMap SAMPRakNet::ompPlayers_; - +#endif uint16_t SAMPRakNet:: GetPort() @@ -322,7 +333,7 @@ SAMPRakNet:: } return decryptBuffer_; } - +#ifndef RAKNET_BUILD_FOR_CLIENT uint8_t* SAMPRakNet:: Encrypt(const OmpPlayerEncryptionData* encryptionData, uint8_t const* src, int len) @@ -346,7 +357,385 @@ SAMPRakNet:: encryptBuffer_[0] = checksum; return encryptBuffer_; } +#else +uint8_t* +SAMPRakNet:: + Encrypt(uint8_t const* src, int len) +{ + static const uint8_t + key[256] + = { + 0x27, + 0x69, + 0xFD, + 0x87, + 0x60, + 0x7D, + 0x83, + 0x02, + 0xF2, + 0x3F, + 0x71, + 0x99, + 0xA3, + 0x7C, + 0x1B, + 0x9D, + 0x76, + 0x30, + 0x23, + 0x25, + 0xC5, + 0x82, + 0x9B, + 0xEB, + 0x1E, + 0xFA, + 0x46, + 0x4F, + 0x98, + 0xC9, + 0x37, + 0x88, + 0x18, + 0xA2, + 0x68, + 0xD6, + 0xD7, + 0x22, + 0xD1, + 0x74, + 0x7A, + 0x79, + 0x2E, + 0xD2, + 0x6D, + 0x48, + 0x0F, + 0xB1, + 0x62, + 0x97, + 0xBC, + 0x8B, + 0x59, + 0x7F, + 0x29, + 0xB6, + 0xB9, + 0x61, + 0xBE, + 0xC8, + 0xC1, + 0xC6, + 0x40, + 0xEF, + 0x11, + 0x6A, + 0xA5, + 0xC7, + 0x3A, + 0xF4, + 0x4C, + 0x13, + 0x6C, + 0x2B, + 0x1C, + 0x54, + 0x56, + 0x55, + 0x53, + 0xA8, + 0xDC, + 0x9C, + 0x9A, + 0x16, + 0xDD, + 0xB0, + 0xF5, + 0x2D, + 0xFF, + 0xDE, + 0x8A, + 0x90, + 0xFC, + 0x95, + 0xEC, + 0x31, + 0x85, + 0xC2, + 0x01, + 0x06, + 0xDB, + 0x28, + 0xD8, + 0xEA, + 0xA0, + 0xDA, + 0x10, + 0x0E, + 0xF0, + 0x2A, + 0x6B, + 0x21, + 0xF1, + 0x86, + 0xFB, + 0x65, + 0xE1, + 0x6F, + 0xF6, + 0x26, + 0x33, + 0x39, + 0xAE, + 0xBF, + 0xD4, + 0xE4, + 0xE9, + 0x44, + 0x75, + 0x3D, + 0x63, + 0xBD, + 0xC0, + 0x7B, + 0x9E, + 0xA6, + 0x5C, + 0x1F, + 0xB2, + 0xA4, + 0xC4, + 0x8D, + 0xB3, + 0xFE, + 0x8F, + 0x19, + 0x8C, + 0x4D, + 0x5E, + 0x34, + 0xCC, + 0xF9, + 0xB5, + 0xF3, + 0xF8, + 0xA1, + 0x50, + 0x04, + 0x93, + 0x73, + 0xE0, + 0xBA, + 0xCB, + 0x45, + 0x35, + 0x1A, + 0x49, + 0x47, + 0x6E, + 0x2F, + 0x51, + 0x12, + 0xE2, + 0x4A, + 0x72, + 0x05, + 0x66, + 0x70, + 0xB8, + 0xCD, + 0x00, + 0xE5, + 0xBB, + 0x24, + 0x58, + 0xEE, + 0xB4, + 0x80, + 0x81, + 0x36, + 0xA9, + 0x67, + 0x5A, + 0x4B, + 0xE8, + 0xCA, + 0xCF, + 0x9F, + 0xE3, + 0xAC, + 0xAA, + 0x14, + 0x5B, + 0x5F, + 0x0A, + 0x3B, + 0x77, + 0x92, + 0x09, + 0x15, + 0x4E, + 0x94, + 0xAD, + 0x17, + 0x64, + 0x52, + 0xD3, + 0x38, + 0x43, + 0x0D, + 0x0C, + 0x07, + 0x3C, + 0x1D, + 0xAF, + 0xED, + 0xE7, + 0x08, + 0xB7, + 0x03, + 0xE6, + 0x8E, + 0xAB, + 0x91, + 0x89, + 0x3E, + 0x2C, + 0x96, + 0x42, + 0xD9, + 0x78, + 0xDF, + 0xD0, + 0x57, + 0x5D, + 0x84, + 0x41, + 0x7E, + 0xCE, + 0xF7, + 0x32, + 0xC3, + 0xD5, + 0x20, + 0x0B, + 0xA7, + }; + uint8_t + cur, + checksum = 0, + port = GetPort() ^ 0xCC; + for (int i = 0; i != len; ++i) { + // Alternate the mask every byte. + cur = (uint8_t)src[i]; + checksum ^= cur & 0xAA; + cur = key[cur]; + if (i & 1) + cur ^= port; + encryptBuffer_[i + 1] = cur; + } + encryptBuffer_[0] = checksum; + return encryptBuffer_; +} +#endif + +#ifdef RAKNET_BUILD_FOR_CLIENT +inline uint8_t transformAuthSha1(const uint8_t value, const uint8_t xorValue) +{ + static const uint8_t authHashTransformTable[] = { + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, + 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x08, 0x06, 0x00, 0x00, 0x00, 0xE4, 0xB5, 0xB7, 0x0A, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x13, 0x00, 0x00, 0x0B, + 0x13, 0x01, 0x00, 0x9A, 0x9C, 0x18, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, + 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8E, 0x7C, 0xFB, 0x51, 0x93, 0x00, 0x00, + 0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x25, 0x00, 0x00, + 0x80, 0x83, 0x00, 0x00, 0xF9, 0xFF, 0x00, 0x00, 0x80, 0xE9, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00 + }; + + uint8_t result = value; + + for (const uint8_t &entry : authHashTransformTable) { + result = result ^ entry ^ xorValue; + } + + return result; +} + +inline const char * uint8ToHex(const uint8_t num) { + static uint8_t buffer[2]; + + buffer[0] = (num >> 4) & 0xF; + buffer[1] = num & 0xF; + + for (uint8_t &entry : buffer) { + uint8_t result = entry + '0'; + + if (result > '9') + result = entry + '7'; + + entry = result; + } + return (char*)buffer; +} + +char* +SAMPRakNet:: + PrepareAuthkeyResponse(const char* initialKey) +{ + static const uint8_t code_from_CAnimManager_AddAnimation[] = + { + 0xFF, 0x25, 0x34, 0x39, // gta_sa.exe + 0x4D3AA0 + 0x4D, 0x00, 0x90, 0x90, // gta_sa.exe + 0x4D3AA4 + 0x90, 0x90, 0x56, 0x57, // gta_sa.exe + 0x4D3AAC + 0x50, 0x8B, 0x44, 0x24, // gta_sa.exe + 0x4D3AA8 + 0x14, 0x8D, 0x0C, 0x80 // gta_sa.exe + 0x4D3AB0 + }; + + RakNet::CSHA1 sha1; + sha1.Update( (unsigned char*) initialKey, strlen(initialKey) ); + sha1.Final(); + + auto sha1_finalized = (uint32_t*)sha1.GetHash(); + + uint32_t sha1_digits[5]; + for (int i = 0; i < 5; i++) { + uint32_t digit = sha1_finalized[i]; + // Flipping bytes order + digit = ((digit & 0xFF) << 24) | ((digit & 0xFF00) << 8) | + ((digit >> 8) & 0xFF00) | ((digit >> 24) & 0xFF); + sha1_digits[i] = digit; + } + + auto sha1_digits_u8 = (uint8_t*)&sha1_digits; + + static const uint8_t xorValues[] = { + 0x2F, 0x45, 0x6F, 0xDB + }; + + for (int i = 0; i < 20; i++) { + uint8_t xorVal = xorValues[i / 5]; + sha1_digits_u8[i] = transformAuthSha1(sha1_digits_u8[i], xorVal); + sha1_digits_u8[i] ^= code_from_CAnimManager_AddAnimation[i]; + } + + for (int i = 0; i < 40;) { + uint8_t hash = sha1_digits_u8[i / 2]; + const char* hashHex = uint8ToHex(hash); + authkeyBuffer_[i] = hashHex[0]; + i++; + authkeyBuffer_[i] = hashHex[1]; + i++; + } + + return authkeyBuffer_; +} +#endif + +#ifndef RAKNET_BUILD_FOR_CLIENT void SAMPRakNet:: HandleQuery(SOCKET instance, int outsize, const sockaddr_in& client, char const* buf, int insize) { @@ -747,3 +1136,4 @@ bool SAMPRakNet::OnConnectionRequest( return true; } +#endif diff --git a/SAMPRakNet.hpp b/SAMPRakNet.hpp index 5ac80ff..e561d3f 100644 --- a/SAMPRakNet.hpp +++ b/SAMPRakNet.hpp @@ -24,7 +24,13 @@ typedef int SOCKET; #define MAX_AUTH_RESPONSE_LEN (64) +#ifdef RAKNET_BUILD_FOR_CLIENT +#define AUTHKEY_RESPONSE_LEN (40) +#endif + +#ifndef RAKNET_BUILD_FOR_CLIENT #include "../../Server/Components/LegacyNetwork/Query/query.hpp" +#endif #include "Include/raknet/NetworkTypes.h" #include "Include/raknet/GetTime.h" @@ -33,8 +39,6 @@ typedef int SOCKET; #define LOCALHOST (0x0100007fu) -#include - enum class OmpVersion { None = 0, @@ -52,7 +56,7 @@ class SAMPRakNet static constexpr int OMP_PETARDED = 0x6D70; // it's basically 'mp' in 16bit static constexpr int SAMP_PETARDED = 0x6969; // it's from default SAMP... Petarded [S04E06] static constexpr OmpVersion CURRENT_OMP_CLIENT_MOD_VERSION = OmpVersion::v0_1_4; - +#ifndef RAKNET_BUILD_FOR_CLIENT enum AuthType { AuthType_Invalid, @@ -73,7 +77,7 @@ class SAMPRakNet { } }; - +#endif struct OmpPlayerEncryptionData { uint32_t key; @@ -91,7 +95,7 @@ class SAMPRakNet { } }; - +#ifndef RAKNET_BUILD_FOR_CLIENT static void Init(ICore* core) { core_ = core; @@ -102,13 +106,22 @@ class SAMPRakNet { return (static_cast(player.binaryAddress) << 16) | player.port; } +#endif static uint8_t* Decrypt(uint8_t const* src, int len); +#ifndef RAKNET_BUILD_FOR_CLIENT static uint8_t* Encrypt(const OmpPlayerEncryptionData* encryptionData, uint8_t const* src, int len); - +#else + static uint8_t* Encrypt(uint8_t const* src, int len); +#endif static uint16_t GetPort(); static void SetPort(uint16_t value); +#ifdef RAKNET_BUILD_FOR_CLIENT + static char * PrepareAuthkeyResponse(const char* initialKey); +#endif + +#ifndef RAKNET_BUILD_FOR_CLIENT static uint32_t GetToken() { return token_; } static void SeedToken() { token_ = rand(); } @@ -119,10 +132,17 @@ class SAMPRakNet static void SeedCookie(); static uint16_t GetCookie(unsigned int address); +#endif static void SetTimeout(unsigned int timeout) { timeout_ = timeout; } static unsigned int GetTimeout() { return timeout_; } +#ifdef RAKNET_BUILD_FOR_CLIENT + static void SetConnectionAsNpc(bool enabled) { connectAsNpc_ = enabled; } + static bool ShouldConnectAsNpc() { return connectAsNpc_; } +#endif + +#ifndef RAKNET_BUILD_FOR_CLIENT static void SetQuery(Query* query) { query_ = query; } static void SetLogCookies(bool log) { logCookies_ = log; } @@ -145,10 +165,12 @@ class SAMPRakNet static void SetGracePeriod(unsigned int time) { gracePeriod_ = RakNet::GetTime() + time; } static RakNet::RakNetTime GetGracePeriod() { return gracePeriod_; } +#endif static void SetMinimumSendBitsPerSecond(float bps) { minimumSendBitsPerSecond_ = bps; } static inline float GetMinimumSendBitsPerSecond() { return minimumSendBitsPerSecond_; } +#ifndef RAKNET_BUILD_FOR_CLIENT static ICore* GetCore() { return core_; } static void ReplyToOmpClientAccessRequest(SOCKET connectionSocket, const RakNet::PlayerID& playerId, uint32_t encryptionKey); @@ -232,23 +254,35 @@ class SAMPRakNet const char* data, RakNet::RakNetTime& minConnectionTick, RakNet::RakNetTime& minConnectionLogTick); - +#endif private: static uint8_t decryptBuffer_[MAXIMUM_MTU_SIZE]; static uint8_t encryptBuffer_[MAXIMUM_MTU_SIZE]; +#ifdef RAKNET_BUILD_FOR_CLIENT + static char authkeyBuffer_[AUTHKEY_RESPONSE_LEN]; + static bool connectAsNpc_; +#endif +#ifndef RAKNET_BUILD_FOR_CLIENT static uint32_t token_; +#endif static uint16_t portNumber; +#ifndef RAKNET_BUILD_FOR_CLIENT static Query* query_; +#endif static unsigned int timeout_; +#ifndef RAKNET_BUILD_FOR_CLIENT static bool logCookies_; static unsigned int minConnectionTime_; static unsigned int messagesLimit_; static unsigned int messageHoleLimit_; static unsigned int acksLimit_; static unsigned int networkLimitsBanTime_; +#endif static float minimumSendBitsPerSecond_; +#ifndef RAKNET_BUILD_FOR_CLIENT static ICore* core_; static FlatHashSet incomingConnections_; static RakNet::RakNetTime gracePeriod_; static FlatHashMap ompPlayers_; +#endif }; diff --git a/Source/RakPeer.cpp b/Source/RakPeer.cpp index 4a731dc..99ff160 100644 --- a/Source/RakPeer.cpp +++ b/Source/RakPeer.cpp @@ -177,7 +177,9 @@ RakPeer::RakPeer() maximumIncomingConnections = 0; maximumNumberOfPeers = 0; activePeersCount = 0; +#ifndef RAKNET_BUILD_FOR_CLIENT reservedSlots = 0; +#endif //remoteSystemListSize=0; remoteSystemList = 0; bytesSentPerSecond = bytesReceivedPerSecond = 0; @@ -293,7 +295,9 @@ bool RakPeer::Initialize( unsigned short maxConnections, unsigned short localPor // Clear the lookup table. Safe to call from the user thread since the network thread is now stopped remoteSystemLookup.Clear(); activePeersCount = 0; - reservedSlots = 0; +#ifndef RAKNET_BUILD_FOR_CLIENT + reservedSlots = 0; +#endif } // For histogram statistics @@ -700,7 +704,9 @@ void RakPeer::Disconnect( unsigned int blockDuration, unsigned char orderingChan maximumNumberOfPeers = 0; //remoteSystemListSize = 0; activePeersCount = 0; +#ifndef RAKNET_BUILD_FOR_CLIENT reservedSlots = 0; +#endif // Free any packets the user didn't deallocate Packet **packet; @@ -2523,10 +2529,12 @@ RakNetStatisticsStruct * RakPeer::GetStatistics( const PlayerID playerId ) return 0; } +#ifndef RAKNET_BUILD_FOR_CLIENT void RakPeer::ReserveSlots(unsigned short count) { reservedSlots = count; } +#endif // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- /* @@ -2666,6 +2674,7 @@ RakPeer::RemoteSystemStruct *RakPeer::GetRemoteSystemFromPlayerID( const PlayerI return 0; } +#ifndef RAKNET_BUILD_FOR_CLIENT // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- void RakPeer::ParseConnectionRequestPacket( RakPeer::RemoteSystemStruct *remoteSystem, PlayerID playerId, const char *data, int byteSize ) { @@ -2787,6 +2796,7 @@ void RakPeer::OnConnectionRequest( RakPeer::RemoteSystemStruct *remoteSystem, un } } } +#endif // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- void RakPeer::NotifyAndFlagForDisconnect(const PlayerID playerId, bool performImmediate, unsigned char orderingChannel) @@ -2834,7 +2844,11 @@ RakPeer::RemoteSystemStruct * RakPeer::AssignPlayerIDToRemoteSystemList( const P RakAssert(playerId!=UNASSIGNED_PLAYER_ID); // Check if maximum number of peers is reached .. without looping them. +#ifndef RAKNET_BUILD_FOR_CLIENT if (activePeersCount >= maximumNumberOfPeers - reservedSlots) +#else + if (activePeersCount >= maximumNumberOfPeers) +#endif { return 0; } @@ -3487,9 +3501,9 @@ void RakPeer::CloseConnectionInternal( const PlayerID target, bool sendDisconnec if ( remoteSystemList == 0 || endThreads == true ) return; - +#ifndef RAKNET_BUILD_FOR_CLIENT SAMPRakNet::ResetOmpPlayerConfiguration(target); - +#endif if (sendDisconnectionNotification) { NotifyAndFlagForDisconnect(target, performImmediate, orderingChannel); @@ -3509,7 +3523,9 @@ void RakPeer::CloseConnectionInternal( const PlayerID target, bool sendDisconnec remoteSystemList[ i ].isActive=false; -- activePeersCount; +#ifndef RAKNET_BUILD_FOR_CLIENT SAMPRakNet::SetRequestingConnection(target.binaryAddress, false); +#endif // Reserve this reliability layer for ourselves //remoteSystemList[ i ].playerId = UNASSIGNED_PLAYER_ID; @@ -3878,6 +3894,7 @@ namespace RakNet } +#ifndef RAKNET_BUILD_FOR_CLIENT bool __stdcall ProcessBan(RakPeer* rakPeer, PlayerID playerId, const char* data, const int length) { if (rakPeer->IsBanned(rakPeer->PlayerIDToDottedIP(playerId))) @@ -3898,6 +3915,7 @@ namespace RakNet return false; } +#endif // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #ifdef _WIN32 @@ -3906,8 +3924,10 @@ namespace RakNet void ProcessNetworkPacket( const unsigned int binaryAddress, const unsigned short port, const char *data, const int length, RakPeer *rakPeer ) #endif { +#ifndef RAKNET_BUILD_FOR_CLIENT static RakNetTime minConnectionTick; static RakNetTime minConnectionLogTick; +#endif Packet *packet; PlayerID playerId; @@ -3916,6 +3936,7 @@ namespace RakNet playerId.binaryAddress = binaryAddress; playerId.port = port; +#ifndef RAKNET_BUILD_FOR_CLIENT const bool needsBanCheck = (data[0] == ID_OPEN_CONNECTION_REQUEST || data[0] == ID_OPEN_CONNECTION_REPLY || data[0] == ID_CONNECTION_ATTEMPT_FAILED); #if !defined(_COMPATIBILITY_1) @@ -3924,6 +3945,7 @@ namespace RakNet return; } #endif +#endif // We didn't check this datagram to see if it came from a connected system or not yet. // Therefore, this datagram must be under 17 bits - otherwise it may be normal network traffic as the min size for a raknet send is 17 bits @@ -4074,20 +4096,25 @@ namespace RakNet // Therefore, this datagram must be under 17 bits - otherwise it may be normal network traffic as the min size for a raknet send is 17 bits else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST && length == sizeof(unsigned char)*3) { +#ifndef RAKNET_BUILD_FOR_CLIENT if (!SAMPRakNet::OnConnectionRequest(rakPeer->connectionSocket, playerId, data, minConnectionTick, minConnectionLogTick)) { return; } +#endif for (i=0; i < rakPeer->messageHandlerList.Size(); i++) rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, playerId); // If this guy is already connected and they initiated the connection, ignore the connection request RakPeer::RemoteSystemStruct *rss = rakPeer->GetRemoteSystemFromPlayerID( playerId, true, true ); +#ifndef RAKNET_BUILD_FOR_CLIENT static unsigned int s_uiLastProcessedBinaryAddr = 0; static unsigned int s_uiLastProcessedConnTick = 0; +#endif if (rss==0 || rss->weInitiatedTheConnection==true) { +#ifndef RAKNET_BUILD_FOR_CLIENT if (rakPeer->GetNumberOfUnverifiedInstances(binaryAddress) > 30) { SAMPRakNet::GetCore()->printLn("Blocking %s due to a 'server full' attack (1)", playerId.ToString()); @@ -4103,6 +4130,7 @@ namespace RakNet rakPeer->AddToBanList(rakPeer->PlayerIDToDottedIP(playerId), 120000); return; } +#endif @@ -4113,8 +4141,10 @@ namespace RakNet unsigned char c[2]; if (rss) // If this guy is already connected remote system will be 0 { +#ifndef RAKNET_BUILD_FOR_CLIENT s_uiLastProcessedBinaryAddr = playerId.binaryAddress; s_uiLastProcessedConnTick = RakNet::GetTime(); +#endif c[0] = ID_OPEN_CONNECTION_REPLY; } else @@ -4126,10 +4156,12 @@ namespace RakNet rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*)&c, 16, playerId); SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, (char*)&c, 2, playerId.binaryAddress, playerId.port ); +#ifndef RAKNET_BUILD_FOR_CLIENT if (rss) { SAMPRakNet::SetRequestingConnection(binaryAddress, true); } +#endif return; } @@ -4152,6 +4184,74 @@ namespace RakNet } } +#ifdef RAKNET_BUILD_FOR_CLIENT + // SAMP clientside connection cookie verification + else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_COOKIE && length == sizeof(unsigned char)*3) + { + for (i=0; i < rakPeer->messageHandlerList.Size(); i++) + rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, playerId); + + unsigned char c[3]; + + c[0] = ID_OPEN_CONNECTION_REQUEST; + *(uint16_t*)&c[1] = (*(uint16_t*)&data[1]) ^ SAMPRakNet::SAMP_PETARDED; + + unsigned i; + for (i=0; i < rakPeer->messageHandlerList.Size(); i++) + rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*)&c, 24, playerId); + + SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, (char*)&c, 3, playerId.binaryAddress, playerId.port ); + return; + } + else if ( + ((unsigned char)(data)[0] == ID_CONNECTION_BANNED || (unsigned char)(data)[0] == ID_NO_FREE_INCOMING_CONNECTIONS) + && length <= sizeof(unsigned char)*2 + ) + { + // Remove the connection attempt from the buffered commands + RakPeer::RequestedConnectionStruct *rcsFirst, *rcs; + rcsFirst = rakPeer->requestedConnectionList.ReadLock(); + rcs=rcsFirst; + bool connectionAttemptCancelled=false; + while (rcs) + { + if (rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT && rcs->playerId==playerId) + { + connectionAttemptCancelled=true; + if (rcs==rcsFirst) + { + rakPeer->requestedConnectionList.ReadUnlock(); + rcsFirst=rakPeer->requestedConnectionList.ReadLock(); + rcs=rcsFirst; + } + else + { + // Hole in the middle + rcs->playerId=UNASSIGNED_PLAYER_ID; + rcs=rakPeer->requestedConnectionList.ReadLock(); + } + + continue; + } + + rcs=rakPeer->requestedConnectionList.ReadLock(); + } + + if (rcsFirst) + rakPeer->requestedConnectionList.CancelReadLock(rcsFirst); + + if (connectionAttemptCancelled) + { + // Tell user of connection attempt failed + packet=AllocPacket(sizeof( char )); + packet->data[ 0 ] = (unsigned char)(data)[0]; // Attempted a connection and couldn't + packet->bitSize = ( sizeof( char ) * 8); + packet->playerId = playerId; + packet->playerIndex = 65535; + rakPeer->AddPacketToProducer(packet); + } + } +#endif // See if this datagram came from a connected system remoteSystem = rakPeer->GetRemoteSystemFromPlayerID( playerId, true, true ); @@ -4191,6 +4291,7 @@ namespace RakNet } } +#ifndef RAKNET_BUILD_FOR_CLIENT if (shouldBanPeer && playerId.binaryAddress != LOCALHOST && GetTime() > SAMPRakNet::GetGracePeriod()) { const char* playerIp = rakPeer->PlayerIDToDottedIP(playerId); @@ -4206,13 +4307,16 @@ namespace RakNet rakPeer->CloseConnectionInternal(playerId, false, true, 0); } +#endif } else { +#ifndef RAKNET_BUILD_FOR_CLIENT if (ProcessBan(rakPeer, playerId, data, length)) { return; } +#endif for (i=0; i < rakPeer->messageHandlerList.Size(); i++) rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, playerId); @@ -4322,7 +4426,11 @@ namespace RakNet if ( errorCode != 0 && endThreads == false ) { #ifdef _DO_PRINTF +#ifndef RAKNET_BUILD_FOR_CLIENT SAMPRakNet::GetCore()->printLn( "Server RecvFrom critical failure!" ); +#else + printf( "Server RecvFrom critical failure!\n" ); +#endif #endif // Some kind of critical error // peer->isRecvfromThreadActive=false; @@ -4544,10 +4652,12 @@ namespace RakNet } // else connection shutting down, don't bother telling the user +#ifndef RAKNET_BUILD_FOR_CLIENT #ifdef _DO_PRINTF const char* ipPort = playerId.ToString(true); SAMPRakNet::GetCore()->printLn("Connection dropped for player %s", ipPort); #endif +#endif CloseConnectionInternal( playerId, false, true, 0 ); continue; } @@ -4582,6 +4692,7 @@ namespace RakNet // Ping this guy if it is time to do so if ( remoteSystem->connectMode==RemoteSystemStruct::CONNECTED ) { +#ifndef RAKNET_BUILD_FOR_CLIENT // Taken from SA-MP 0.3.7 changes if (!remoteSystem->isLogon) { @@ -4594,6 +4705,7 @@ namespace RakNet continue; } } +#endif if (timeMS > remoteSystem->nextPingTime && (occasionalPing || remoteSystem->lowestPing == (unsigned short)-1)) { @@ -4658,9 +4770,12 @@ namespace RakNet { if ( (unsigned char)(data)[0] == ID_CONNECTION_REQUEST ) { +#ifndef RAKNET_BUILD_FOR_CLIENT ParseConnectionRequestPacket(remoteSystem, playerId, (const char*)data, byteSize); +#endif delete [] data; } +#ifndef RAKNET_BUILD_FOR_CLIENT else if ((unsigned char)(data)[0] != ID_AUTH_KEY || !ParseConnectionAuthPacket(remoteSystem, playerId, data, byteSize)) { if ((unsigned char)(data)[0] == ID_RPC && remoteSystem->sampData.unverifiedRPCs++ < MAX_UNVERIFIED_RPCS) @@ -4692,6 +4807,18 @@ namespace RakNet delete[] data; } } +#else // !RAKNET_BUILD_FOR_CLIENT + else + { + CloseConnectionInternal(playerId, false, true, 0); + +#if !defined(_COMPATIBILITY_1) + AddToBanList(PlayerIDToDottedIP(playerId), remoteSystem->reliabilityLayer.GetTimeoutTime()); +#endif + if (data) + delete[] data; + } +#endif } else { @@ -4701,8 +4828,10 @@ namespace RakNet { // 04/27/06 This is wrong. With cross connections, we can both have initiated the connection are in state REQUESTED_CONNECTION // 04/28/06 Downgrading connections from connected will close the connection due to security at ((remoteSystem->connectMode!=RemoteSystemStruct::CONNECTED && time > remoteSystem->connectionTime && time - remoteSystem->connectionTime > 10000)) +#ifndef RAKNET_BUILD_FOR_CLIENT if (remoteSystem->connectMode!=RemoteSystemStruct::CONNECTED) ParseConnectionRequestPacket(remoteSystem, playerId, (const char*)data, byteSize); +#endif delete [] data; } else if ( (unsigned char) data[ 0 ] == ID_NEW_INCOMING_CONNECTION && byteSize == sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned short) ) @@ -4717,7 +4846,9 @@ namespace RakNet playerId==myPlayerId) // local system connect { +#ifndef RAKNET_BUILD_FOR_CLIENT SAMPRakNet::SetRequestingConnection(playerId.binaryAddress, false); +#endif remoteSystem->connectMode=RemoteSystemStruct::CONNECTED; PingInternal( playerId, true ); @@ -4913,7 +5044,9 @@ namespace RakNet AESKey[ i ] = data[ 1 + i ] ^ ( ( unsigned char* ) ( message ) ) [ i ]; // Connect this player assuming we have open slots +#ifndef RAKNET_BUILD_FOR_CLIENT OnConnectionRequest( remoteSystem, AESKey, true ); +#endif } delete [] data; } @@ -5018,12 +5151,54 @@ namespace RakNet // Tell the remote system the connection failed NotifyAndFlagForDisconnect(playerId, true, 0); #ifdef _DO_PRINTF +#ifndef RAKNET_BUILD_FOR_CLIENT SAMPRakNet::GetCore()->printLn( "Error: Got a connection accept when we didn't request the connection." ); +#else + printf( "Error: Got a connection accept when we didn't request the connection.\n" ); +#endif #endif if (data) delete [] data; } } +#ifdef RAKNET_BUILD_FOR_CLIENT + else if ( (unsigned char)(data)[0] == ID_AUTH_KEY && byteSize >= sizeof(unsigned char)*4 ) + { + RakNet::BitStream inBitStream( (unsigned char *) data, byteSize, false ); + inBitStream.IgnoreBits(8); + + unsigned char initialAuthKeyLen; + inBitStream.Read(initialAuthKeyLen); + + // Prebuilt server initial authkeys usually have length between 14-16 characters + // But, to support wider range and keep backward compatibility with original SAMP, + // We should make it possible to keep up to 256 chars + char initialAuthKey[256]; + if (initialAuthKeyLen > 1 && inBitStream.Read((char*)initialAuthKey, initialAuthKeyLen)) + { + // Server could send NULL terminator in the middle of string (why?) + // But send larger initialAuthKeyLen than the actual string length + // Original SAMP backward compatibility, so will use strlen() in PrepareAuthkeyResponse instead of initialAuthKeyLen + initialAuthKey[initialAuthKeyLen] = NULL; + + RakNet::BitStream outBitStream(sizeof(unsigned char)+sizeof(unsigned char)+AUTHKEY_RESPONSE_LEN); + outBitStream.Write((unsigned char)ID_AUTH_KEY); + if (!SAMPRakNet::ShouldConnectAsNpc()) + { + const char* response = SAMPRakNet::PrepareAuthkeyResponse(initialAuthKey); + outBitStream.Write((unsigned char)AUTHKEY_RESPONSE_LEN); + outBitStream.Write(response, AUTHKEY_RESPONSE_LEN); + } + else + { + // Server requires length & string including NULL terminator in case of NPC + outBitStream.Write((unsigned char)4); + outBitStream.Write("NPC", 4); + } + SendImmediate( (char*)outBitStream.GetData(), outBitStream.GetNumberOfBitsUsed(), SYSTEM_PRIORITY, RELIABLE, 0, playerId, false, false, RakNet::GetTime() ); + } + } +#endif else if (data[0] == (unsigned char)ID_CONNECTION_LOST) { // Do nothing - packet is received through network. diff --git a/Source/ReliabilityLayer.cpp b/Source/ReliabilityLayer.cpp index e33620a..96a23ca 100644 --- a/Source/ReliabilityLayer.cpp +++ b/Source/ReliabilityLayer.cpp @@ -342,9 +342,11 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe shouldBanPeer = false; //int numberOfAcksInFrame = 0; +#ifndef RAKNET_BUILD_FOR_CLIENT unsigned int acksLimit = 0; unsigned int messageHoleLimit = 0; unsigned int messagesLimit = 0; +#endif RakNetTimeNS time; bool indexFound; int count, size; @@ -375,9 +377,11 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe RakNet::BitStream socketData( (unsigned char*) buffer, length, false ); // Convert the incoming data to a bitstream for easy parsing time = RakNet::GetTimeNS(); +#ifndef RAKNET_BUILD_FOR_CLIENT acksLimit = SAMPRakNet::GetAcksLimit(); messageHoleLimit = SAMPRakNet::GetMessageHoleLimit(); messagesLimit = SAMPRakNet::GetMessagesLimit(); +#endif DataStructures::RangeList incomingAcks; socketData.Read(hasAcks); @@ -396,6 +400,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe statistics.acknowlegementsReceived += incomingAcks.ranges[i].maxIndex - incomingAcks.ranges[i].minIndex; +#ifndef RAKNET_BUILD_FOR_CLIENT if (incomingAcks.ranges[i].maxIndex - incomingAcks.ranges[i].minIndex > messageHoleLimit) { unsigned int receivedAcks = incomingAcks.ranges[i].maxIndex - incomingAcks.ranges[i].minIndex; @@ -405,6 +410,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe shouldBanPeer = true; return 1; } +#endif for (messageNumber=incomingAcks.ranges[i].minIndex; messageNumber >= incomingAcks.ranges[i].minIndex && messageNumber <= incomingAcks.ranges[i].maxIndex; messageNumber++) { @@ -447,6 +453,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe statistics.perFrameAcksLimitCounter = 0; } +#ifndef RAKNET_BUILD_FOR_CLIENT if (statistics.perSecondAcksLimitCounter > acksLimit) { const char * ipPort = playerId.ToString(true); @@ -455,6 +462,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe shouldBanPeer = true; return 1; } +#endif } } @@ -589,6 +597,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe statistics.perSecondMessagesLimitCounter = statistics.perFrameMessagesLimitCounter; statistics.perFrameMessagesLimitCounter = 0; } +#ifndef RAKNET_BUILD_FOR_CLIENT if (statistics.perSecondMessagesLimitCounter > messagesLimit) { const char* ipPort = playerId.ToString(true); @@ -597,6 +606,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe shouldBanPeer = true; return 1; } +#endif statistics.messagesReceived++; if (time - statistics.lastRecvMsgProcess > 1000000) @@ -799,6 +809,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe // RakAssert(waitingForOrderedPacketReadIndex[ internalPacket->orderingChannel ] < internalPacket->orderingIndex); statistics.orderedMessagesOutOfOrder++; +#ifndef RAKNET_BUILD_FOR_CLIENT if (statistics.orderedMessagesOutOfOrder > messageHoleLimit) { const char* ipPort = playerId.ToString(true); @@ -807,6 +818,7 @@ bool ReliabilityLayer::HandleSocketReceiveFromConnectedPlayer( const char *buffe shouldBanPeer = true; return 1; } +#endif // This is a newer ordered packet than we are waiting for. Store it for future use AddToOrderingList( internalPacket ); @@ -1945,12 +1957,14 @@ InternalPacket* ReliabilityLayer::CreateInternalPacketFromBitStream( RakNet::Bit return 0; } +#ifndef RAKNET_BUILD_FOR_CLIENT #ifdef _DEBUG SAMPRakNet::GetCore()->logLn(LogLevel::Warning, "dropping a split packet from client"); #endif internalPacketPool.ReleasePointer(internalPacket); return 0; +#endif } else { diff --git a/Source/SocketLayer.cpp b/Source/SocketLayer.cpp index dc2308f..90cea05 100644 --- a/Source/SocketLayer.cpp +++ b/Source/SocketLayer.cpp @@ -370,14 +370,17 @@ int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode ) if ( len != SOCKET_ERROR ) { +#ifndef RAKNET_BUILD_FOR_CLIENT if (len > 10 && data[0] == 'S' && data[1] == 'A' && data[2] == 'M' && data[3] == 'P') { SAMPRakNet::HandleQuery(s, len2, sa, data, len); return 1; } +#endif unsigned short portnum; portnum = ntohs( sa.sin_port ); +#ifndef RAKNET_BUILD_FOR_CLIENT uint8_t* decrypted = SAMPRakNet::Decrypt((uint8_t*)data, len); if (decrypted) { ProcessNetworkPacket(sa.sin_addr.s_addr, portnum, (char*)decrypted, len - 1, rakPeer); @@ -387,6 +390,9 @@ int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode ) uint8_t* const addr = reinterpret_cast(&sa.sin_addr.s_addr); SAMPRakNet::GetCore()->printLn("Dropping bad packet from %u.%u.%u.%u:%u!", addr[0], addr[1], addr[2], addr[3], sa.sin_port); } +#endif +#else // RAKNET_BUILD_FOR_CLIENT + ProcessNetworkPacket(sa.sin_addr.s_addr, portnum, data, len, rakPeer); #endif return 1; } @@ -456,6 +462,7 @@ int SocketLayer::SendTo( SOCKET s, const char *data, int length, unsigned int bi do { // TODO - use WSASendTo which is faster. +#ifndef RAKNET_BUILD_FOR_CLIENT auto encrypted = (uint8_t*)data; if (SAMPRakNet::IsOmpEncryptionEnabled()) { @@ -474,6 +481,10 @@ int SocketLayer::SendTo( SOCKET s, const char *data, int length, unsigned int bi { len = sendto(s, (char*)encrypted, length, 0, (const sockaddr*)&sa, sizeof(struct sockaddr_in)); } +#else + auto encrypted = SAMPRakNet::Encrypt((uint8_t*)data, length); + len = sendto(s, (char*)encrypted, length + 1, 0, (const sockaddr*)&sa, sizeof(struct sockaddr_in)); +#endif } while ( len == 0 ); diff --git a/Source/rakserver.cpp b/Source/rakserver.cpp index 7007d20..98f74d5 100644 --- a/Source/rakserver.cpp +++ b/Source/rakserver.cpp @@ -459,6 +459,7 @@ RakPeer::RemoteSystemStruct* RakServer::GetRemoteSystemFromPlayerID(const Player return RakPeer::GetRemoteSystemFromPlayerID(playerId, false, false); } +#ifndef RAKNET_BUILD_FOR_CLIENT void RakServer::ReserveSlots(unsigned short count) { RakPeer::ReserveSlots(count); @@ -473,6 +474,7 @@ SAMPRakNet::RemoteSystemData RakServer::GetSAMPDataFromPlayerID(const PlayerID p return remoteSystem->sampData; } +#endif #ifdef _MSC_VER #pragma warning( pop )