Skip to content
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,13 @@ if (WIN32)
else()
target_link_libraries(raknet OMP-SDK)
endif()

add_executable(raknet-udp-probe tools/udp_probe.cpp)
add_executable(raknet-omp-query-probe tools/omp_query_probe.cpp)
add_executable(raknet-omp-connect-probe tools/omp_connect_probe.cpp)

if (WIN32)
target_link_libraries(raknet-udp-probe Ws2_32)
target_link_libraries(raknet-omp-query-probe Ws2_32)
target_link_libraries(raknet-omp-connect-probe Ws2_32)
endif()
13 changes: 10 additions & 3 deletions Include/raknet/RakPeer.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ namespace RakNet
{
bool isActive; /// Is this structure in use?
PlayerID playerId; /// The remote system associated with this reliability layer
TransportAddress transportAddress; /// The transport address associated with this reliability layer
PlayerID myExternalPlayerId; /// Your own IP, as reported by the remote system
ReliabilityLayer reliabilityLayer; /// The reliability layer associated with this player
bool weInitiatedTheConnection; /// True if we started this connection via Connect. False if someone else connected to us.
Expand All @@ -518,6 +519,7 @@ namespace RakNet
};

unsigned short GetNumberOfUnverifiedInstances(const unsigned int binaryAddress);
unsigned short GetNumberOfUnverifiedInstances(const TransportAddress &transportAddress);
unsigned short GetNumberOfActivePeers();

protected:
Expand All @@ -526,11 +528,13 @@ namespace RakNet
// friend unsigned __stdcall RecvFromNetworkLoop(LPVOID arguments);
friend void __stdcall ProcessPortUnreachable( const unsigned int binaryAddress, const unsigned short port, RakPeer *rakPeer );
friend void __stdcall ProcessNetworkPacket( const unsigned int binaryAddress, const unsigned short port, const char *data, const int length, RakPeer *rakPeer );
friend void __stdcall ProcessNetworkPacket( const TransportAddress &transportAddress, const char *data, const int length, RakPeer *rakPeer );
friend unsigned __stdcall UpdateNetworkLoop( LPVOID arguments );
#else
// friend void* RecvFromNetworkLoop( void* arguments );
friend void ProcessPortUnreachable( const unsigned int binaryAddress, const unsigned short port, RakPeer *rakPeer );
friend void ProcessNetworkPacket( const unsigned int binaryAddress, const unsigned short port, const char *data, const int length, RakPeer *rakPeer );
friend void ProcessNetworkPacket( const TransportAddress &transportAddress, const char *data, const int length, RakPeer *rakPeer );
friend void* UpdateNetworkLoop( void* arguments );
#endif

Expand All @@ -547,12 +551,14 @@ namespace RakNet
/// \param[in] playerID The player identifier
/// \return 0 if none
RemoteSystemStruct *GetRemoteSystemFromPlayerID( const PlayerID playerID, bool calledFromNetworkThread, bool onlyActive) const;
RemoteSystemStruct *GetRemoteSystemFromTransportAddress( const TransportAddress &transportAddress, bool onlyActive ) const;
///Parse out a connection request packet
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);
void SecuredConnectionResponse( const PlayerID playerId, const TransportAddress &transportAddress );
///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
Expand Down Expand Up @@ -754,9 +760,10 @@ namespace RakNet
int threadSleepTimer;

SOCKET connectionSocket;
#if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
WSAEVENT recvEvent;
#endif
SOCKET connectionSocketV6;
#if defined (_WIN32) && defined(USE_WAIT_FOR_MULTIPLE_EVENTS)
WSAEVENT recvEvent;
#endif

// Used for RPC replies
RakNet::BitStream *replyFromTargetBS;
Expand Down
4 changes: 3 additions & 1 deletion Include/raknet/ReliabilityLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ namespace RakNet
/// \param[in] MTUSize maximum datagram size
/// \param[in] time current system time
/// \param[in] messageHandlerList A list of registered plugins
void Update( SOCKET s, PlayerID playerId, int MTUSize, RakNetTimeNS time, DataStructures::List<PluginInterface*> &messageHandlerList );
void Update( SOCKET s, PlayerID playerId, int MTUSize, RakNetTimeNS time, DataStructures::List<PluginInterface*> &messageHandlerList );
void Update( SOCKET s, PlayerID playerId, const TransportAddress &transportAddress, int MTUSize, RakNetTimeNS time, DataStructures::List<PluginInterface*> &messageHandlerList );

/// If Read returns -1 and this returns true then a modified packetwas detected
/// \return true when a modified packet is detected
Expand Down Expand Up @@ -177,6 +178,7 @@ namespace RakNet
/// \param[in] playerId The address and port to send to
/// \param[in] bitStream The data to send.
void SendBitStream( SOCKET s, PlayerID playerId, RakNet::BitStream *bitStream );
void SendBitStream( SOCKET s, const TransportAddress &transportAddress, RakNet::BitStream *bitStream );

///Parse an internalPacket and create a bitstream to represent this dataReturns number of bits used
int WriteToBitStreamFromInternalPacket( RakNet::BitStream *bitStream, const InternalPacket *const internalPacket );
Expand Down
41 changes: 39 additions & 2 deletions Include/raknet/SocketLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,38 @@ namespace RakNet
{
class RakPeer;

struct TransportAddress
{
unsigned short addressFamily;
unsigned short port;
unsigned int scopeId;
unsigned char address[16];

TransportAddress();
bool IsValid(void) const;
bool IsIPv4(void) const;
bool IsIPv6(void) const;
bool operator==(const TransportAddress &right) const;
bool operator!=(const TransportAddress &right) const;
unsigned int ToIPv4Binary(void) const;
bool ToSockaddr(sockaddr_storage *storage, socklen_t *len) const;
static TransportAddress FromSockaddr(const sockaddr *sa, socklen_t len);
};

struct SocketBindParameters
{
unsigned short port;
bool blockingSocket;
int addressFamily;
bool ipv6Only;
const char *forceHostAddress;

SocketBindParameters(unsigned short port_=0, bool blockingSocket_=true, int addressFamily_=AF_INET, bool ipv6Only_=false, const char *forceHostAddress_=0)
: port(port_), blockingSocket(blockingSocket_), addressFamily(addressFamily_), ipv6Only(ipv6Only_), forceHostAddress(forceHostAddress_)
{
}
};

// A platform independent implementation of Berkeley sockets, with settings used by RakNet
class SocketLayer
{
Expand Down Expand Up @@ -79,15 +111,18 @@ namespace RakNet
/// \param[in] port the remote port.
/// \return A new socket used for communication.
SOCKET Connect( SOCKET writeSocket, unsigned int binaryAddress, unsigned short port );
SOCKET Connect( SOCKET writeSocket, const TransportAddress &address );

// Creates a bound socket to listen for incoming connections on the specified port
/// \param[in] port the port number
/// \param[in] blockingSocket
/// \return A new socket used for accepting clients
SOCKET CreateBoundSocket( unsigned short port, bool blockingSocket, const char *forceHostAddress );
SOCKET CreateBoundSocket( unsigned short port, bool blockingSocket, const char *forceHostAddress=0 );
SOCKET CreateBoundSocket( const SocketBindParameters &parameters );

#if !defined(_COMPATIBILITY_1)
const char* DomainNameToIP( const char *domainName );
bool DomainNameToAddress( const char *domainName, unsigned short port, int addressFamily, TransportAddress *output );
#endif

#ifdef __USE_IO_COMPLETION_PORTS
Expand All @@ -111,11 +146,13 @@ namespace RakNet
/// \param[in] errorCode An error code if an error occured .
/// \return Returns true if you successfully read data, false on error.
int RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode );
int RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode, TransportAddress *sender );

#if !defined(_COMPATIBILITY_1)
/// Retrieve all local IP address in a string format.
/// \param[in] ipList An array of ip address in dotted notation.
void GetMyIP( char ipList[ 10 ][ 16 ] );
unsigned GetMyAddresses( TransportAddress *addresses, unsigned maxAddresses, int addressFamily );
#endif

/// Call sendto (UDP obviously)
Expand All @@ -135,6 +172,7 @@ namespace RakNet
/// \param[in] port The port number to send to.
/// \return 0 on success, nonzero on failure.
int SendTo( SOCKET s, const char *data, int length, unsigned int binaryAddress, unsigned short port );
int SendTo( SOCKET s, const char *data, int length, const TransportAddress &address );

/// Returns the local port, useful when passing 0 as the startup port.
/// \param[in] s The socket whose port we are referring to
Expand All @@ -151,4 +189,3 @@ namespace RakNet
}

#endif

53 changes: 44 additions & 9 deletions SAMPRakNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ SAMPRakNet::
}

void SAMPRakNet::
HandleQuery(SOCKET instance, int outsize, const sockaddr_in& client, char const* buf, int insize)
HandleQuery(SOCKET instance, int outsize, const sockaddr_storage& client, char const* buf, int insize)
{
if (query_ == nullptr) {
return;
Expand Down Expand Up @@ -653,7 +653,25 @@ uint16_t SAMPRakNet::GetCookie(unsigned int address)
return (cookies[0][addressSplit[0]] | cookies[1][addressSplit[3]] << 8) ^ ((addressSplit[1] << 8) | addressSplit[2]);
}

uint16_t SAMPRakNet::GetCookie(const RakNet::TransportAddress& address)
{
if (address.IsIPv4())
return GetCookie(address.ToIPv4Binary());

const auto hash = HashTransportAddress(address);
return static_cast<uint16_t>((hash ^ (hash >> 16) ^ (hash >> 32) ^ (hash >> 48)) & 0xFFFFu);
}

void SAMPRakNet::ReplyToOmpClientAccessRequest(SOCKET connectionSocket, const RakNet::PlayerID& playerId, uint32_t encryptionKey)
{
RakNet::TransportAddress address;
address.addressFamily = AF_INET;
address.port = playerId.port;
memcpy(address.address, &playerId.binaryAddress, sizeof(playerId.binaryAddress));
ReplyToOmpClientAccessRequest(connectionSocket, address, playerId, encryptionKey);
}

void SAMPRakNet::ReplyToOmpClientAccessRequest(SOCKET connectionSocket, const RakNet::TransportAddress& address, const RakNet::PlayerID& playerId, uint32_t encryptionKey)
{
if (IsOmpEncryptionEnabled())
{
Expand All @@ -664,7 +682,7 @@ void SAMPRakNet::ReplyToOmpClientAccessRequest(SOCKET connectionSocket, const Ra
*(uint32_t*)&c[5] = encryptionKey;
*(uint32_t*)&c[9] = uint32_t(CURRENT_OMP_CLIENT_MOD_VERSION);

RakNet::SocketLayer::Instance()->SendTo(connectionSocket, (const char*)&c, len, playerId.binaryAddress, playerId.port);
RakNet::SocketLayer::Instance()->SendTo(connectionSocket, (const char*)&c, len, address);
}

ConfigurePlayerUsingOmp(playerId, encryptionKey);
Expand All @@ -677,10 +695,27 @@ bool SAMPRakNet::OnConnectionRequest(
RakNet::RakNetTime& minConnectionTick,
RakNet::RakNetTime& minConnectionLogTick
)
{
RakNet::TransportAddress address;
address.addressFamily = AF_INET;
address.port = playerId.port;
memcpy(address.address, &playerId.binaryAddress, sizeof(playerId.binaryAddress));
return OnConnectionRequest(connectionSocket, address, playerId, data, minConnectionTick, minConnectionLogTick);
}

bool SAMPRakNet::OnConnectionRequest(
SOCKET connectionSocket,
const RakNet::TransportAddress& address,
RakNet::PlayerID& playerId,
const char* data,
RakNet::RakNetTime& minConnectionTick,
RakNet::RakNetTime& minConnectionLogTick
)
{
ResetOmpPlayerConfiguration(playerId);

if (playerId.binaryAddress == LOCALHOST)
if ((address.IsIPv4() && playerId.binaryAddress == LOCALHOST) ||
(address.IsIPv6() && IN6_IS_ADDR_LOOPBACK(reinterpret_cast<const in6_addr*>(address.address))))
{
// Allow unlimited connections from localhost (testing and bots).
}
Expand All @@ -691,7 +726,7 @@ bool SAMPRakNet::OnConnectionRequest(
{
// Allow unlimited connections during the grace period
}
else if (SAMPRakNet::IsAlreadyRequestingConnection(playerId.binaryAddress))
else if (SAMPRakNet::IsAlreadyRequestingConnection(address))
{
return false;
}
Expand All @@ -717,9 +752,9 @@ bool SAMPRakNet::OnConnectionRequest(
}

uint16_t xordCookie = *(uint16_t*)(data + 1);
if ((xordCookie ^ SAMP_PETARDED) != (uint16_t)(SAMPRakNet::GetCookie(playerId.binaryAddress)))
if ((xordCookie ^ SAMP_PETARDED) != (uint16_t)(SAMPRakNet::GetCookie(address)))
{
if ((xordCookie ^ OMP_PETARDED) != (uint16_t)(SAMPRakNet::GetCookie(playerId.binaryAddress))) // it's omp
if ((xordCookie ^ OMP_PETARDED) != (uint16_t)(SAMPRakNet::GetCookie(address))) // it's omp
{
#ifdef _DO_PRINTF
if (SAMPRakNet::ShouldLogCookies())
Expand All @@ -729,8 +764,8 @@ bool SAMPRakNet::OnConnectionRequest(
#endif
char c[3];
c[0] = RakNet::ID_OPEN_CONNECTION_COOKIE;
*(uint16_t*)&c[1] = (uint16_t)(SAMPRakNet::GetCookie(playerId.binaryAddress));
RakNet::SocketLayer::Instance()->SendTo(connectionSocket, (const char*)&c, 3, playerId.binaryAddress, playerId.port);
*(uint16_t*)&c[1] = (uint16_t)(SAMPRakNet::GetCookie(address));
RakNet::SocketLayer::Instance()->SendTo(connectionSocket, (const char*)&c, 3, address);
ResetOmpPlayerConfiguration(playerId);
return false;
}
Expand All @@ -741,7 +776,7 @@ bool SAMPRakNet::OnConnectionRequest(
std::uniform_int_distribution<uint32_t> dist(0, UINT32_MAX);

uint32_t randomInt = dist(gen);
ReplyToOmpClientAccessRequest(connectionSocket, playerId, randomInt);
ReplyToOmpClientAccessRequest(connectionSocket, address, playerId, randomInt);
}
}

Expand Down
Loading