/// \file /// \brief Types used by RakNet, most of which involve user code. /// /// This file is part of RakNet Copyright 2003 Jenkins Software LLC /// /// Usage of RakNet is subject to the appropriate license agreement. #ifndef __NETWORK_TYPES_H #define __NETWORK_TYPES_H #include "RakNetDefines.h" #include "NativeTypes.h" #include "RakNetTime.h" #include "Export.h" #include "SocketIncludes.h" #include "WindowsIncludes.h" #include "XBox360Includes.h" 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, 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 94.198.81.195, 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; /// 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
/// 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
/// 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_in6 addr6; #endif struct 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 | // 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 | // 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) void SetPort(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 void 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); 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 ( 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