libnative-utilities/include/raknet/RakNetTypes.hpp
2024-08-15 18:40:30 +08:00

508 lines
18 KiB
C++

/*
* Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
/// \file
/// \brief Types used by RakNet, most of which involve user code.
///
#ifndef __NETWORK_TYPES_H
#define __NETWORK_TYPES_H
#include "RakNetDefines.hpp"
#include "NativeTypes.hpp"
#include "RakNetTime.hpp"
#include "Export.hpp"
#include "WindowsIncludes.hpp"
#include "XBox360Includes.hpp"
#include "SocketIncludes.hpp"
namespace RakNet {
/// Forward declarations
class RakPeerInterface;
class BitStream;
struct Packet;
enum StartupResult
{
RAKNET_STARTED,
RAKNET_ALREADY_STARTED,
INVALID_SOCKET_DESCRIPTORS,
INVALID_MAX_CONNECTIONS,
SOCKET_FAMILY_NOT_SUPPORTED,
SOCKET_PORT_ALREADY_IN_USE,
SOCKET_FAILED_TO_BIND,
SOCKET_FAILED_TEST_SEND,
PORT_CANNOT_BE_ZERO,
FAILED_TO_CREATE_NETWORK_THREAD,
COULD_NOT_GENERATE_GUID,
STARTUP_OTHER_FAILURE
};
enum ConnectionAttemptResult
{
CONNECTION_ATTEMPT_STARTED,
INVALID_PARAMETER,
CANNOT_RESOLVE_DOMAIN_NAME,
ALREADY_CONNECTED_TO_ENDPOINT,
CONNECTION_ATTEMPT_ALREADY_IN_PROGRESS,
SECURITY_INITIALIZATION_FAILED
};
/// Returned from RakPeerInterface::GetConnectionState()
enum ConnectionState
{
/// Connect() was called, but the process hasn't started yet
IS_PENDING,
/// Processing the connection attempt
IS_CONNECTING,
/// Is connected and able to communicate
IS_CONNECTED,
/// Was connected, but will disconnect as soon as the remaining messages are delivered
IS_DISCONNECTING,
/// A connection attempt failed and will be aborted
IS_SILENTLY_DISCONNECTING,
/// No longer connected
IS_DISCONNECTED,
/// Was never connected, or else was disconnected long enough ago that the entry has been discarded
IS_NOT_CONNECTED
};
/// Given a number of bits, return how many bytes are needed to represent that.
#define BITS_TO_BYTES(x) (((x)+7)>>3)
#define BYTES_TO_BITS(x) ((x)<<3)
/// \sa NetworkIDObject.h
typedef unsigned char UniqueIDType;
typedef unsigned short SystemIndex;
typedef unsigned char RPCIndex;
const int MAX_RPC_MAP_SIZE=((RPCIndex)-1)-1;
const int UNDEFINED_RPC_INDEX=((RPCIndex)-1);
/// First byte of a network message
typedef unsigned char MessageID;
typedef uint32_t BitSize_t;
#if defined(_MSC_VER) && _MSC_VER > 0
#define PRINTF_64_BIT_MODIFIER "I64"
#else
#define PRINTF_64_BIT_MODIFIER "ll"
#endif
/// Used with the PublicKey structure
enum PublicKeyMode
{
/// The connection is insecure. You can also just pass 0 for the pointer to PublicKey in RakPeerInterface::Connect()
PKM_INSECURE_CONNECTION,
/// Accept whatever public key the server gives us. This is vulnerable to man in the middle, but does not require
/// distribution of the public key in advance of connecting.
PKM_ACCEPT_ANY_PUBLIC_KEY,
/// Use a known remote server public key. PublicKey::remoteServerPublicKey must be non-zero.
/// This is the recommended mode for secure connections.
PKM_USE_KNOWN_PUBLIC_KEY,
/// Use a known remote server public key AND provide a public key for the connecting client.
/// PublicKey::remoteServerPublicKey, myPublicKey and myPrivateKey must be all be non-zero.
/// The server must cooperate for this mode to work.
/// I recommend not using this mode except for server-to-server communication as it significantly increases the CPU requirements during connections for both sides.
/// Furthermore, when it is used, a connection password should be used as well to avoid DoS attacks.
PKM_USE_TWO_WAY_AUTHENTICATION
};
/// Passed to RakPeerInterface::Connect()
struct RAK_DLL_EXPORT PublicKey
{
/// How to interpret the public key, see above
PublicKeyMode publicKeyMode;
/// Pointer to a public key of length cat::EasyHandshake::PUBLIC_KEY_BYTES. See the Encryption sample.
char *remoteServerPublicKey;
/// (Optional) Pointer to a public key of length cat::EasyHandshake::PUBLIC_KEY_BYTES
char *myPublicKey;
/// (Optional) Pointer to a private key of length cat::EasyHandshake::PRIVATE_KEY_BYTES
char *myPrivateKey;
};
/// Describes the local socket to use for RakPeer::Startup
struct RAK_DLL_EXPORT SocketDescriptor
{
SocketDescriptor();
SocketDescriptor(unsigned short _port, const char *_hostAddress);
/// The local port to bind to. Pass 0 to have the OS autoassign a port.
unsigned short port;
/// The local network card address to bind to, such as "127.0.0.1". Pass an empty string to use INADDR_ANY.
char hostAddress[32];
/// IP version: For IPV4, use AF_INET (default). For IPV6, use AF_INET6. To autoselect, use AF_UNSPEC.
/// IPV6 is the newer internet protocol. Instead of addresses such as natpunch.jenkinssoftware.com, you may have an address such as fe80::7c:31f7:fec4:27de%14.
/// Encoding takes 16 bytes instead of 4, so IPV6 is less efficient for bandwidth.
/// On the positive side, NAT Punchthrough is not needed and should not be used with IPV6 because there are enough addresses that routers do not need to create address mappings.
/// RakPeer::Startup() will fail if this IP version is not supported.
/// \pre RAKNET_SUPPORT_IPV6 must be set to 1 in RakNetDefines.h for AF_INET6
short socketFamily;
unsigned short remotePortRakNetWasStartedOn_PS3_PSP2;
// Required for Google chrome
_PP_Instance_ chromeInstance;
// Set to true to use a blocking socket (default, do not change unless you have a reason to)
bool blockingSocket;
/// XBOX only: set IPPROTO_VDP if you want to use VDP. If enabled, this socket does not support broadcast to 255.255.255.255
unsigned int extraSocketOptions;
};
extern bool NonNumericHostString( const char *host );
/// \brief Network address for a system
/// \details Corresponds to a network address<BR>
/// This is not necessarily a unique identifier. For example, if a system has both LAN and internet connections, the system may be identified by either one, depending on who is communicating<BR>
/// Therefore, you should not transmit the SystemAddress over the network and expect it to identify a system, or use it to connect to that system, except in the case where that system is not behind a NAT (such as with a dedciated server)
/// Use RakNetGUID for a unique per-instance of RakPeer to identify systems
struct RAK_DLL_EXPORT SystemAddress
{
/// Constructors
SystemAddress();
SystemAddress(const char *str);
SystemAddress(const char *str, unsigned short port);
/// SystemAddress, with RAKNET_SUPPORT_IPV6 defined, holds both an sockaddr_in6 and a sockaddr_in
union// In6OrIn4
{
#if RAKNET_SUPPORT_IPV6==1
struct sockaddr_storage sa_stor;
sockaddr_in6 addr6;
#endif
sockaddr_in addr4;
} address;
/// This is not used internally, but holds a copy of the port held in the address union, so for debugging it's easier to check what port is being held
unsigned short debugPort;
/// \internal Return the size to write to a bitStream
static int size(void);
/// Hash the system address
static unsigned long ToInteger( const SystemAddress &sa );
/// Return the IP version, either IPV4 or IPV6
/// \return Either 4 or 6
unsigned char GetIPVersion(void) const;
/// \internal Returns either IPPROTO_IP or IPPROTO_IPV6
/// \sa GetIPVersion
unsigned int GetIPPROTO(void) const;
/// Call SetToLoopback(), with whatever IP version is currently held. Defaults to IPV4
void SetToLoopback(void);
/// Call SetToLoopback() with a specific IP version
/// \param[in] ipVersion Either 4 for IPV4 or 6 for IPV6
void SetToLoopback(unsigned char ipVersion);
/// \return If was set to 127.0.0.1 or ::1
bool IsLoopback(void) const;
// Return the systemAddress as a string in the format <IP>|<Port>
// Returns a static string
// NOT THREADSAFE
// portDelineator should not be '.', ':', '%', '-', '/', a number, or a-f
const char *ToString(bool writePort=true, char portDelineator='|') const;
// Return the systemAddress as a string in the format <IP>|<Port>
// dest must be large enough to hold the output
// portDelineator should not be '.', ':', '%', '-', '/', a number, or a-f
// THREADSAFE
void ToString(bool writePort, char *dest, char portDelineator='|') const;
/// Set the system address from a printable IP string, for example "192.0.2.1" or "2001:db8:63b3:1::3490"
/// You can write the port as well, using the portDelineator, for example "192.0.2.1|1234"
/// \param[in] str A printable IP string, for example "192.0.2.1" or "2001:db8:63b3:1::3490". Pass 0 for \a str to set to UNASSIGNED_SYSTEM_ADDRESS
/// \param[in] portDelineator if \a str contains a port, delineate the port with this character. portDelineator should not be '.', ':', '%', '-', '/', a number, or a-f
/// \param[in] ipVersion Only used if str is a pre-defined address in the wrong format, such as 127.0.0.1 but you want ip version 6, so you can pass 6 here to do the conversion
/// \note The current port is unchanged if a port is not specified in \a str
/// \return True on success, false on ipVersion does not match type of passed string
bool FromString(const char *str, char portDelineator='|', int ipVersion=0);
/// Same as FromString(), but you explicitly set a port at the same time
bool FromStringExplicitPort(const char *str, unsigned short port, int ipVersion=0);
/// Copy the port from another SystemAddress structure
void CopyPort( const SystemAddress& right );
/// Returns if two system addresses have the same IP (port is not checked)
bool EqualsExcludingPort( const SystemAddress& right ) const;
/// Returns the port in host order (this is what you normally use)
unsigned short GetPort(void) const;
/// \internal Returns the port in network order
unsigned short GetPortNetworkOrder(void) const;
/// Sets the port. The port value should be in host order (this is what you normally use)
/// Renamed from SetPort because of winspool.h http://edn.embarcadero.com/article/21494
void SetPortHostOrder(unsigned short s);
/// \internal Sets the port. The port value should already be in network order.
void SetPortNetworkOrder(unsigned short s);
/// Old version, for crap platforms that don't support newer socket functions
bool SetBinaryAddress(const char *str, char portDelineator=':');
/// Old version, for crap platforms that don't support newer socket functions
void ToString_Old(bool writePort, char *dest, char portDelineator=':') const;
/// \internal sockaddr_in6 requires extra data beyond just the IP and port. Copy that extra data from an existing SystemAddress that already has it
void FixForIPVersion(const SystemAddress &boundAddressToSocket);
bool IsLANAddress(void);
SystemAddress& operator = ( const SystemAddress& input );
bool operator==( const SystemAddress& right ) const;
bool operator!=( const SystemAddress& right ) const;
bool operator > ( const SystemAddress& right ) const;
bool operator < ( const SystemAddress& right ) const;
/// \internal Used internally for fast lookup. Optional (use -1 to do regular lookup). Don't transmit this.
SystemIndex systemIndex;
private:
#if RAKNET_SUPPORT_IPV6==1
void ToString_New(bool writePort, char *dest, char portDelineator) const;
#endif
};
/// Uniquely identifies an instance of RakPeer. Use RakPeer::GetGuidFromSystemAddress() and RakPeer::GetSystemAddressFromGuid() to go between SystemAddress and RakNetGUID
/// Use RakPeer::GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS) to get your own GUID
struct RAK_DLL_EXPORT RakNetGUID
{
RakNetGUID();
explicit RakNetGUID(uint64_t _g) {g=_g; systemIndex=(SystemIndex)-1;}
// uint32_t g[6];
uint64_t g;
// Return the GUID as a string
// Returns a static string
// NOT THREADSAFE
const char *ToString(void) const;
// Return the GUID as a string
// dest must be large enough to hold the output
// THREADSAFE
void ToString(char *dest) const;
bool FromString(const char *source);
static unsigned long ToUint32( const RakNetGUID &g );
RakNetGUID& operator = ( const RakNetGUID& input )
{
g=input.g;
systemIndex=input.systemIndex;
return *this;
}
// Used internally for fast lookup. Optional (use -1 to do regular lookup). Don't transmit this.
SystemIndex systemIndex;
static int size() {return (int) sizeof(uint64_t);}
bool operator==( const RakNetGUID& right ) const;
bool operator!=( const RakNetGUID& right ) const;
bool operator > ( const RakNetGUID& right ) const;
bool operator < ( const RakNetGUID& right ) const;
};
/// Index of an invalid SystemAddress
//const SystemAddress UNASSIGNED_SYSTEM_ADDRESS =
//{
// 0xFFFFFFFF, 0xFFFF
//};
#ifndef SWIG
const SystemAddress UNASSIGNED_SYSTEM_ADDRESS;
const RakNetGUID UNASSIGNED_RAKNET_GUID((uint64_t)-1);
#endif
//{
// {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}
// 0xFFFFFFFFFFFFFFFF
//};
struct RAK_DLL_EXPORT AddressOrGUID
{
RakNetGUID rakNetGuid;
SystemAddress systemAddress;
SystemIndex GetSystemIndex(void) const {if (rakNetGuid!=UNASSIGNED_RAKNET_GUID) return rakNetGuid.systemIndex; else return systemAddress.systemIndex;}
bool IsUndefined(void) const {return rakNetGuid==UNASSIGNED_RAKNET_GUID && systemAddress==UNASSIGNED_SYSTEM_ADDRESS;}
void SetUndefined(void) {rakNetGuid=UNASSIGNED_RAKNET_GUID; systemAddress=UNASSIGNED_SYSTEM_ADDRESS;}
static unsigned long ToInteger( const AddressOrGUID &aog );
const char *ToString(bool writePort=true) const;
void ToString(bool writePort, char *dest) const;
AddressOrGUID() {}
AddressOrGUID( const AddressOrGUID& input )
{
rakNetGuid=input.rakNetGuid;
systemAddress=input.systemAddress;
}
AddressOrGUID( const SystemAddress& input )
{
rakNetGuid=UNASSIGNED_RAKNET_GUID;
systemAddress=input;
}
AddressOrGUID( Packet *packet );
AddressOrGUID( const RakNetGUID& input )
{
rakNetGuid=input;
systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
}
AddressOrGUID& operator = ( const AddressOrGUID& input )
{
rakNetGuid=input.rakNetGuid;
systemAddress=input.systemAddress;
return *this;
}
AddressOrGUID& operator = ( const SystemAddress& input )
{
rakNetGuid=UNASSIGNED_RAKNET_GUID;
systemAddress=input;
return *this;
}
AddressOrGUID& operator = ( const RakNetGUID& input )
{
rakNetGuid=input;
systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
return *this;
}
inline bool operator==( const AddressOrGUID& right ) const {return (rakNetGuid!=UNASSIGNED_RAKNET_GUID && rakNetGuid==right.rakNetGuid) || (systemAddress!=UNASSIGNED_SYSTEM_ADDRESS && systemAddress==right.systemAddress);}
};
typedef uint64_t NetworkID;
/// This represents a user message from another system.
struct Packet
{
/// The system that send this packet.
SystemAddress systemAddress;
/// A unique identifier for the system that sent this packet, regardless of IP address (internal / external / remote system)
/// Only valid once a connection has been established (ID_CONNECTION_REQUEST_ACCEPTED, or ID_NEW_INCOMING_CONNECTION)
/// Until that time, will be UNASSIGNED_RAKNET_GUID
RakNetGUID guid;
/// The length of the data in bytes
unsigned int length;
/// The length of the data in bits
BitSize_t bitSize;
/// The data from the sender
unsigned char* data;
/// @internal
/// Indicates whether to delete the data, or to simply delete the packet.
bool deleteData;
/// @internal
/// If true, this message is meant for the user, not for the plugins, so do not process it through plugins
bool wasGeneratedLocally;
};
/// Index of an unassigned player
const SystemIndex UNASSIGNED_PLAYER_INDEX = 65535;
/// Unassigned object ID
const NetworkID UNASSIGNED_NETWORK_ID = (uint64_t) -1;
const int PING_TIMES_ARRAY_SIZE = 5;
struct RAK_DLL_EXPORT uint24_t
{
uint32_t val;
uint24_t() {}
inline operator uint32_t() { return val; }
inline operator uint32_t() const { return val; }
inline uint24_t(const uint24_t& a) {val=a.val;}
inline uint24_t operator++() {++val; val&=0x00FFFFFF; return *this;}
inline uint24_t operator--() {--val; val&=0x00FFFFFF; return *this;}
inline uint24_t operator++(int) {uint24_t temp(val); ++val; val&=0x00FFFFFF; return temp;}
inline uint24_t operator--(int) {uint24_t temp(val); --val; val&=0x00FFFFFF; return temp;}
inline uint24_t operator&(const uint24_t& a) {return uint24_t(val&a.val);}
inline uint24_t& operator=(const uint24_t& a) { val=a.val; return *this; }
inline uint24_t& operator+=(const uint24_t& a) { val+=a.val; val&=0x00FFFFFF; return *this; }
inline uint24_t& operator-=(const uint24_t& a) { val-=a.val; val&=0x00FFFFFF; return *this; }
inline bool operator==( const uint24_t& right ) const {return val==right.val;}
inline bool operator!=( const uint24_t& right ) const {return val!=right.val;}
inline bool operator > ( const uint24_t& right ) const {return val>right.val;}
inline bool operator < ( const uint24_t& right ) const {return val<right.val;}
inline const uint24_t operator+( const uint24_t &other ) const { return uint24_t(val+other.val); }
inline const uint24_t operator-( const uint24_t &other ) const { return uint24_t(val-other.val); }
inline const uint24_t operator/( const uint24_t &other ) const { return uint24_t(val/other.val); }
inline const uint24_t operator*( const uint24_t &other ) const { return uint24_t(val*other.val); }
inline uint24_t(const uint32_t& a) {val=a; val&=0x00FFFFFF;}
inline uint24_t operator&(const uint32_t& a) {return uint24_t(val&a);}
inline uint24_t& operator=(const uint32_t& a) { val=a; val&=0x00FFFFFF; return *this; }
inline uint24_t& operator+=(const uint32_t& a) { val+=a; val&=0x00FFFFFF; return *this; }
inline uint24_t& operator-=(const uint32_t& a) { val-=a; val&=0x00FFFFFF; return *this; }
inline bool operator==( const uint32_t& right ) const {return val==(right&0x00FFFFFF);}
inline bool operator!=( const uint32_t& right ) const {return val!=(right&0x00FFFFFF);}
inline bool operator > ( const uint32_t& right ) const {return val>(right&0x00FFFFFF);}
inline bool operator < ( const uint32_t& right ) const {return val<(right&0x00FFFFFF);}
inline const uint24_t operator+( const uint32_t &other ) const { return uint24_t(val+other); }
inline const uint24_t operator-( const uint32_t &other ) const { return uint24_t(val-other); }
inline const uint24_t operator/( const uint32_t &other ) const { return uint24_t(val/other); }
inline const uint24_t operator*( const uint32_t &other ) const { return uint24_t(val*other); }
};
} // namespace RakNet
#endif