X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg_steam_networking.h;fp=vg_steam_networking.h;h=6eb059909d261274abe9321572f935140b0fed68;hb=4c48fe01a5d1983be89b7dce6f08e6b708cfbb05;hp=0000000000000000000000000000000000000000;hpb=3dd767bb10e6fee9cbffeb185d1a9685810c17b5;p=vg.git diff --git a/vg_steam_networking.h b/vg_steam_networking.h new file mode 100644 index 0000000..6eb0599 --- /dev/null +++ b/vg_steam_networking.h @@ -0,0 +1,1010 @@ +#ifndef VG_STEAM_NETWORKING_H +#define VG_STEAM_NETWORKING_H + +#include "vg_steam.h" + +#ifdef VALVE_CALLBACK_PACK_SMALL +; + #pragma pack(push,4) +#else + #pragma pack(push,8) +#endif + +enum ESteamNetworkingConfigScope +{ + k_ESteamNetworkingConfig_Global = 1, + k_ESteamNetworkingConfig_SocketsInterface = 2, + k_ESteamNetworkingConfig_ListenSocket = 3, + k_ESteamNetworkingConfig_Connection = 4, + k_ESteamNetworkingConfigScope__Force32Bit = 0x7fffffff +}; +typedef enum ESteamNetworkingConfigScope ESteamNetworkingConfigScope; + +enum ESteamNetworkingConfigDataType +{ + k_ESteamNetworkingConfig_Int32 = 1, + k_ESteamNetworkingConfig_Int64 = 2, + k_ESteamNetworkingConfig_Float = 3, + k_ESteamNetworkingConfig_String = 4, + k_ESteamNetworkingConfig_Ptr = 5, + + k_ESteamNetworkingConfigDataType__Force32Bit = 0x7fffffff +}; +typedef enum ESteamNetworkingConfigDataType ESteamNetworkingConfigDataType; + +enum ESteamNetworkingConfigValue +{ + k_ESteamNetworkingConfig_Invalid = 0, + k_ESteamNetworkingConfig_TimeoutInitial = 24, + k_ESteamNetworkingConfig_TimeoutConnected = 25, + k_ESteamNetworkingConfig_SendBufferSize = 9, + k_ESteamNetworkingConfig_ConnectionUserData = 40, + k_ESteamNetworkingConfig_SendRateMin = 10, + k_ESteamNetworkingConfig_SendRateMax = 11, + k_ESteamNetworkingConfig_NagleTime = 12, + k_ESteamNetworkingConfig_IP_AllowWithoutAuth = 23, + k_ESteamNetworkingConfig_MTU_PacketSize = 32, + k_ESteamNetworkingConfig_MTU_DataSize = 33, + k_ESteamNetworkingConfig_Unencrypted = 34, + k_ESteamNetworkingConfig_SymmetricConnect = 37, + k_ESteamNetworkingConfig_LocalVirtualPort = 38, + k_ESteamNetworkingConfig_DualWifi_Enable = 39, + k_ESteamNetworkingConfig_EnableDiagnosticsUI = 46, + k_ESteamNetworkingConfig_FakePacketLoss_Send = 2, + k_ESteamNetworkingConfig_FakePacketLoss_Recv = 3, + k_ESteamNetworkingConfig_FakePacketLag_Send = 4, + k_ESteamNetworkingConfig_FakePacketLag_Recv = 5, + k_ESteamNetworkingConfig_FakePacketReorder_Send = 6, + k_ESteamNetworkingConfig_FakePacketReorder_Recv = 7, + k_ESteamNetworkingConfig_FakePacketReorder_Time = 8, + k_ESteamNetworkingConfig_FakePacketDup_Send = 26, + k_ESteamNetworkingConfig_FakePacketDup_Recv = 27, + k_ESteamNetworkingConfig_FakePacketDup_TimeMax = 28, + k_ESteamNetworkingConfig_PacketTraceMaxBytes = 41, + k_ESteamNetworkingConfig_FakeRateLimit_Send_Rate = 42, + k_ESteamNetworkingConfig_FakeRateLimit_Send_Burst = 43, + k_ESteamNetworkingConfig_FakeRateLimit_Recv_Rate = 44, + k_ESteamNetworkingConfig_FakeRateLimit_Recv_Burst = 45, + k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged = 201, + k_ESteamNetworkingConfig_Callback_AuthStatusChanged = 202, + k_ESteamNetworkingConfig_Callback_RelayNetworkStatusChanged = 203, + k_ESteamNetworkingConfig_Callback_MessagesSessionRequest = 204, + k_ESteamNetworkingConfig_Callback_MessagesSessionFailed = 205, + k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling = 206, + k_ESteamNetworkingConfig_Callback_FakeIPResult = 207, + k_ESteamNetworkingConfig_P2P_STUN_ServerList = 103, + k_ESteamNetworkingConfig_P2P_Transport_ICE_Enable = 104, + k_ESteamNetworkingConfig_P2P_Transport_ICE_Penalty = 105, + k_ESteamNetworkingConfig_P2P_Transport_SDR_Penalty = 106, + k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFailInitial = 19, + k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFail = 20, + k_ESteamNetworkingConfig_SDRClient_MinPingsBeforePingAccurate = 21, + k_ESteamNetworkingConfig_SDRClient_SingleSocket = 22, + k_ESteamNetworkingConfig_SDRClient_ForceRelayCluster = 29, + k_ESteamNetworkingConfig_SDRClient_DebugTicketAddress = 30, + k_ESteamNetworkingConfig_SDRClient_ForceProxyAddr = 31, + k_ESteamNetworkingConfig_SDRClient_FakeClusterPing = 36, + k_ESteamNetworkingConfig_LogLevel_AckRTT = 13, + k_ESteamNetworkingConfig_LogLevel_PacketDecode = 14, + k_ESteamNetworkingConfig_LogLevel_Message = 15, + k_ESteamNetworkingConfig_LogLevel_PacketGaps = 16, + k_ESteamNetworkingConfig_LogLevel_P2PRendezvous = 17, + k_ESteamNetworkingConfig_LogLevel_SDRRelayPings = 18, + k_ESteamNetworkingConfig_DELETED_EnumerateDevVars = 35, + k_ESteamNetworkingConfigValue__Force32Bit = 0x7fffffff +}; +typedef enum ESteamNetworkingConfigValue ESteamNetworkingConfigValue; + + +enum ESteamNetworkingConnectionState +{ + k_ESteamNetworkingConnectionState_None = 0, + k_ESteamNetworkingConnectionState_Connecting = 1, + k_ESteamNetworkingConnectionState_FindingRoute = 2, + k_ESteamNetworkingConnectionState_Connected = 3, + k_ESteamNetworkingConnectionState_ClosedByPeer = 4, + k_ESteamNetworkingConnectionState_ProblemDetectedLocally = 5, + k_ESteamNetworkingConnectionState_FinWait = -1, + k_ESteamNetworkingConnectionState_Linger = -2, + k_ESteamNetworkingConnectionState_Dead = -3, + k_ESteamNetworkingConnectionState__Force32Bit = 0x7fffffff +}; +typedef enum ESteamNetworkingConnectionState ESteamNetworkingConnectionState; + +enum ESteamNetConnectionEnd +{ + k_ESteamNetConnectionEnd_Invalid = 0, + k_ESteamNetConnectionEnd_App_Min = 1000, + k_ESteamNetConnectionEnd_App_Generic = k_ESteamNetConnectionEnd_App_Min, + k_ESteamNetConnectionEnd_App_Max = 1999, + k_ESteamNetConnectionEnd_AppException_Min = 2000, + k_ESteamNetConnectionEnd_AppException_Generic = + k_ESteamNetConnectionEnd_AppException_Min, + k_ESteamNetConnectionEnd_AppException_Max = 2999, + k_ESteamNetConnectionEnd_Local_Min = 3000, + k_ESteamNetConnectionEnd_Local_OfflineMode = 3001, + k_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002, + k_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003, + k_ESteamNetConnectionEnd_Local_NetworkConfig = 3004, + k_ESteamNetConnectionEnd_Local_Rights = 3005, + k_ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses = 3006, + + k_ESteamNetConnectionEnd_Local_Max = 3999, + k_ESteamNetConnectionEnd_Remote_Min = 4000, + k_ESteamNetConnectionEnd_Remote_Timeout = 4001, + k_ESteamNetConnectionEnd_Remote_BadCrypt = 4002, + k_ESteamNetConnectionEnd_Remote_BadCert = 4003, + k_ESteamNetConnectionEnd_Remote_BadProtocolVersion = 4006, + k_ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses = 4007, + + k_ESteamNetConnectionEnd_Remote_Max = 4999, + + k_ESteamNetConnectionEnd_Misc_Min = 5000, + k_ESteamNetConnectionEnd_Misc_Generic = 5001, + k_ESteamNetConnectionEnd_Misc_InternalError = 5002, + k_ESteamNetConnectionEnd_Misc_Timeout = 5003, + k_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005, + k_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006, + k_ESteamNetConnectionEnd_Misc_P2P_Rendezvous = 5008, + k_ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall = 5009, + k_ESteamNetConnectionEnd_Misc_PeerSentNoConnection = 5010, + + k_ESteamNetConnectionEnd_Misc_Max = 5999, + k_ESteamNetConnectionEnd__Force32Bit = 0x7fffffff +}; +typedef enum ESteamNetConnectionEnd ESteamNetConnectionEnd; + +enum ESteamNetworkingIdentityType +{ + k_ESteamNetworkingIdentityType_Invalid = 0, + k_ESteamNetworkingIdentityType_SteamID = 16, + k_ESteamNetworkingIdentityType_IPAddress = 1, + k_ESteamNetworkingIdentityType_GenericString = 2, + k_ESteamNetworkingIdentityType_GenericBytes = 3, + k_ESteamNetworkingIdentityType_UnknownType = 4, + k_ESteamNetworkingIdentityType__Force32bit = 0x7fffffff, +}; +typedef enum ESteamNetworkingIdentityType ESteamNetworkingIdentityType; + +enum ESteamNetworkingAvailability +{ + k_ESteamNetworkingAvailability_CannotTry = -102, + k_ESteamNetworkingAvailability_Failed = -101, + k_ESteamNetworkingAvailability_Previously = -100, + k_ESteamNetworkingAvailability_Retrying = -10, + k_ESteamNetworkingAvailability_NeverTried = 1, + k_ESteamNetworkingAvailability_Waiting = 2, + k_ESteamNetworkingAvailability_Attempting = 3, + k_ESteamNetworkingAvailability_Current = 100, + k_ESteamNetworkingAvailability_Unknown = 0, + k_ESteamNetworkingAvailability__Force32bit = 0x7fffffff, +}; +typedef enum ESteamNetworkingAvailability ESteamNetworkingAvailability; + +/* Handle used to identify a connection to a remote host. */ +typedef u32 HSteamNetConnection; +HSteamNetConnection const k_HSteamNetConnection_Invalid = 0; + +/* + * Handle used to identify a "listen socket". Unlike traditional + * Berkeley sockets, a listen socket and a connection are two + * different abstractions. + */ +typedef u32 HSteamListenSocket; +HSteamListenSocket const k_HSteamListenSocket_Invalid = 0; + +typedef u32 SteamNetworkingPOPID; +typedef i64 SteamNetworkingMicroseconds; + +#pragma pack(push,1) +/* Store an IP and port. IPv6 is always used; IPv4 is represented using + * "IPv4-mapped" addresses: IPv4 aa.bb.cc.dd => IPv6 ::ffff:aabb:ccdd + * (RFC 4291 section 2.5.5.2.) + */ +typedef struct SteamNetworkingIPAddr SteamNetworkingIPAddr; +struct SteamNetworkingIPAddr +{ + union + { + u8 m_ipv6[ 16 ]; + + /* RFC4038, section 4.2 */ + struct IPv4MappedAddress + { + u64 m_8zeros; + u16 m_0000; + u16 m_ffff; + u8 m_ip[ 4 ]; /* NOTE: As bytes, i.e. network byte order */ + } + m_ipv4; + }; + + u16 m_port; // Host byte order +}; + +typedef struct SteamNetworkingIdentity SteamNetworkingIdentity; +struct SteamNetworkingIdentity +{ + ESteamNetworkingIdentityType m_eType; + + int m_cbSize; + union + { + u64 m_steamID64; + char m_szGenericString[ 32 ]; + u8 m_genericBytes[ 32 ]; + char m_szUnknownRawString[ 128 ]; + SteamNetworkingIPAddr m_ip; + u32 m_reserved[ 32 ]; + }; +}; + +#pragma pack(pop) + +/* + * "Fake IPs" are assigned to hosts, to make it easier to interface with + * older code that assumed all hosts will have an IPv4 address + */ +enum ESteamNetworkingFakeIPType +{ + k_ESteamNetworkingFakeIPType_Invalid, + k_ESteamNetworkingFakeIPType_NotFake, + k_ESteamNetworkingFakeIPType_GlobalIPv4, + k_ESteamNetworkingFakeIPType_LocalIPv4, + k_ESteamNetworkingFakeIPType__Force32Bit = 0x7fffffff +}; +typedef enum ESteamNetworkingFakeIPType ESteamNetworkingFakeIPType; + +/* Set everything to zero. E.g. [::]:0 */ +void SteamAPI_SteamNetworkingIPAddr_Clear( SteamNetworkingIPAddr* self ); + +/* Returns true if the IP is ::0. (Doesn't check port.) */ +int SteamAPI_SteamNetworkingIPAddr_IsIPv6AllZeros( + SteamNetworkingIPAddr* self ); + +/* + * Set IPv6 address. IP is interpreted as bytes, so there are no endian issues. + * (Same as inaddr_in6.) The IP can be a mapped IPv4 address + */ +void SteamAPI_SteamNetworkingIPAddr_SetIPv6( SteamNetworkingIPAddr* self, + u8 *ipv6, u16 nPort ); + +/* Sets to IPv4 mapped address. IP and port are in host byte order. */ +void SteamAPI_SteamNetworkingIPAddr_SetIPv4( SteamNetworkingIPAddr* self, + u32 nIP, u16 nPort ); + +/* Return true if IP is mapped IPv4 */ +int SteamAPI_SteamNetworkingIPAddr_IsIPv4( SteamNetworkingIPAddr* self ); + +/* + * Returns IP in host byte order (e.g. aa.bb.cc.dd as 0xaabbccdd). + * Returns 0 if IP is not mapped IPv4. + */ +u32 SteamAPI_SteamNetworkingIPAddr_GetIPv4( SteamNetworkingIPAddr* self ); + +/* Set to the IPv6 localhost address ::1, and the specified port. */ +void SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( + SteamNetworkingIPAddr* self, u16 nPort ); + +/* + * Return true if this identity is localhost. + * (Either IPv6 ::1, or IPv4 127.0.0.1) + */ +int SteamAPI_SteamNetworkingIPAddr_IsLocalHost( SteamNetworkingIPAddr* self ); + +/* + * Print to a string, with or without the port. Mapped IPv4 addresses are + * printed as dotted decimal (12.34.56.78), otherwise this will print the + * canonical form according to RFC5952. If you include the port, IPv6 will be + * surrounded by brackets, e.g. [::1:2]:80. Your buffer should be at least + * k_cchMaxString bytes to avoid truncation + * + * See also SteamNetworkingIdentityRender + */ +void SteamAPI_SteamNetworkingIPAddr_ToString( SteamNetworkingIPAddr* self, + char *buf, u32 cbBuf, int bWithPort ); + +/* + * Parse an IP address and optional port. If a port is not present, it is set + * to 0. + * (This means that you cannot tell if a zero port was explicitly specified.) + */ +int SteamAPI_SteamNetworkingIPAddr_ParseString( SteamNetworkingIPAddr* self, + const char *pszStr ); + +/* See if two addresses are identical */ +int SteamAPI_SteamNetworkingIPAddr_IsEqualTo( SteamNetworkingIPAddr* self, + SteamNetworkingIPAddr *x ); + +/* + * Classify address as FakeIP. This function never returns + * k_ESteamNetworkingFakeIPType_Invalid. + */ +ESteamNetworkingFakeIPType SteamAPI_SteamNetworkingIPAddr_GetFakeIPType( + SteamNetworkingIPAddr* self ); + +/* Return true if we are a FakeIP */ +int SteamAPI_SteamNetworkingIPAddr_IsFakeIP( SteamNetworkingIPAddr* self ); + +/* + * In a few places we need to set configuration options on listen sockets and + * connections, and have them take effect *before* the listen socket or + * connection really starts doing anything. Creating the object and then setting + * the options "immediately" after creation doesn't work completely, because + * network packets could be received between the time the object is created and + * when the options are applied. To set options at creation time in a reliable + * way, they must be passed to the creation function. This structure is used to + * pass those options. + * + * For the meaning of these fields, see ISteamNetworkingUtils::SetConfigValue. + * Basically when the object is created, we just iterate over the list of + * options and call ISteamNetworkingUtils::SetConfigValueStruct, where the scope + * arguments are supplied by the object being created. + */ +typedef struct SteamNetworkingConfigValue_t SteamNetworkingConfigValue_t; +struct SteamNetworkingConfigValue_t +{ + /* Which option is being set */ + ESteamNetworkingConfigValue m_eValue; + + /// Which field below did you fill in? + ESteamNetworkingConfigDataType m_eDataType; + + /// Option value + union + { + i32 m_int32; + i64 m_int64; + float m_float; + const char *m_string; // Points to your '\0'-terminated buffer + void *m_ptr; + } m_val; +}; + +void SteamAPI_SteamNetworkingConfigValue_t_SetInt32( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, i32 data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetInt64( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, i64 data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetFloat( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, float data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetPtr( + SteamNetworkingConfigValue_t* self, + ESteamNetworkingConfigValue eVal, void *data ); + +void SteamAPI_SteamNetworkingConfigValue_t_SetString( + SteamNetworkingConfigValue_t* self, ESteamNetworkingConfigValue eVal, + const char * data ); + +typedef void ISteamNetworkingSockets; +typedef struct SteamNetworkingMessage_t SteamNetworkingMessage_t; +typedef struct SteamNetConnectionInfo_t SteamNetConnectionInfo_t; + + +/* + * Handle used to identify a poll group, used to query many + * connections at once efficiently. + */ +typedef u32 HSteamNetPollGroup; +HSteamNetPollGroup const k_HSteamNetPollGroup_Invalid = 0; + +ISteamNetworkingSockets +*SteamAPI_SteamGameServerNetworkingSockets_SteamAPI_v012(void); + +ISteamNetworkingSockets +*SteamAPI_SteamGameServerNetworkingSockets_SteamAPI(void) +{ + return SteamAPI_SteamGameServerNetworkingSockets_SteamAPI_v012(); +} + + +ISteamNetworkingSockets *SteamAPI_SteamNetworkingSockets_SteamAPI_v012(); +ISteamNetworkingSockets *SteamAPI_SteamNetworkingSockets_SteamAPI() +{ + return SteamAPI_SteamNetworkingSockets_SteamAPI_v012(); +} + + +/* + * Send the message unreliably. Can be lost. Messages *can* be larger than a + * single MTU (UDP packet), but there is no retransmission, so if any piece + * of the message is lost, the entire message will be dropped. + + * The sending API does have some knowledge of the underlying connection, so + * if there is no NAT-traversal accomplished or there is a recognized adjustment + * happening on the connection, the packet will be batched until the connection + * is open again. + + * Migration note: This is not exactly the same as k_EP2PSendUnreliable! You + * probably want k_ESteamNetworkingSendType_UnreliableNoNagle + */ +const int k_nSteamNetworkingSend_Unreliable = 0; + +/* + * Disable Nagle's algorithm. + * By default, Nagle's algorithm is applied to all outbound messages. This means + * that the message will NOT be sent immediately, in case further messages are + * sent soon after you send this, which can be grouped together. Any time there + * is enough buffered data to fill a packet, the packets will be pushed out + * immediately, but partially-full packets not be sent until the Nagle timer + * expires. See ISteamNetworkingSockets::FlushMessagesOnConnection, + * ISteamNetworkingMessages::FlushMessagesToUser + * + * NOTE: Don't just send every message without Nagle because you want packets to + * get there quicker. Make sure you understand the problem that Nagle is + * solving before disabling it. If you are sending small messages, often many at + * the same time, then it is very likely that it will be more efficient to leave + * Nagle enabled. A typical proper use of this flag is when you are sending + * what you know will be the last message sent for a while (e.g. the last in the + * server simulation tick to a particular client), and you use this flag to + * flush all messages. + */ +const int k_nSteamNetworkingSend_NoNagle = 1; + +/* + * Send a message unreliably, bypassing Nagle's algorithm for this message and + * any messages currently pending on the Nagle timer. This is equivalent to + * using k_ESteamNetworkingSend_Unreliable and then immediately flushing the + * messages using ISteamNetworkingSockets::FlushMessagesOnConnection or + * ISteamNetworkingMessages::FlushMessagesToUser. (But using this flag is more + * efficient since you only make one API call.) + */ +const int k_nSteamNetworkingSend_UnreliableNoNagle = + k_nSteamNetworkingSend_Unreliable | + k_nSteamNetworkingSend_NoNagle; +/* + * If the message cannot be sent very soon (because the connection is still + * doing some initial handshaking, route negotiations, etc), then just drop it. + * This is only applicable for unreliable messages. Using this flag on reliable + * messages is invalid. + */ +const int k_nSteamNetworkingSend_NoDelay = 4; + +/* + * Send an unreliable message, but if it cannot be sent relatively quickly, just + * drop it instead of queuing it. This is useful for messages that are not + * useful if they are excessively delayed, such as voice data. + * NOTE: The Nagle algorithm is not used, and if the message is not dropped, any + * messages waiting on the Nagle timer are immediately flushed. + * + * A message will be dropped under the following circumstances: + * - the connection is not fully connected. (E.g. the "Connecting" or + * "FindingRoute" states) + * - there is a sufficiently large number of messages queued up already such + * that the current message will not be placed on the wire in the next + * ~200ms or so. + * + * If a message is dropped for these reasons, k_EResultIgnored will be returned. + */ +const int k_nSteamNetworkingSend_UnreliableNoDelay = + k_nSteamNetworkingSend_Unreliable | + k_nSteamNetworkingSend_NoDelay | + k_nSteamNetworkingSend_NoNagle; + +/* + * Reliable message send. Can send up to + * k_cbMaxSteamNetworkingSocketsMessageSizeSend bytes in a single message. + * Does fragmentation/re-assembly of messages under the hood, as well as a + * sliding window for efficient sends of large chunks of data. + * The Nagle algorithm is used. See notes on + * k_ESteamNetworkingSendType_Unreliable for more details. + * See k_ESteamNetworkingSendType_ReliableNoNagle, + * ISteamNetworkingSockets::FlushMessagesOnConnection, + * ISteamNetworkingMessages::FlushMessagesToUser + * + * Migration note: This is NOT the same as k_EP2PSendReliable, it's more like + * k_EP2PSendReliableWithBuffering + */ +const int k_nSteamNetworkingSend_Reliable = 8; + +/* + * Send a message reliably, but bypass Nagle's algorithm. + * + * Migration note: This is equivalent to k_EP2PSendReliable + */ +const int k_nSteamNetworkingSend_ReliableNoNagle = + k_nSteamNetworkingSend_Reliable | + k_nSteamNetworkingSend_NoNagle; + + +HSteamListenSocket SteamAPI_ISteamNetworkingSockets_CreateListenSocketIP( + ISteamNetworkingSockets *self, + SteamNetworkingIPAddr *localAddress, int nOptions, + SteamNetworkingConfigValue_t *pOptions ); + +HSteamNetConnection SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress( + ISteamNetworkingSockets *self, + SteamNetworkingIPAddr *address, int nOptions, + SteamNetworkingConfigValue_t *pOptions ); + + +EResult SteamAPI_ISteamNetworkingSockets_AcceptConnection( + ISteamNetworkingSockets *self, + HSteamNetConnection hConn ); + +int SteamAPI_ISteamNetworkingSockets_CloseConnection( + ISteamNetworkingSockets *self, + HSteamNetConnection hPeer, int nReason, const char *pszDebug, + int bEnableLinger ); + +int SteamAPI_ISteamNetworkingSockets_GetListenSocketAddress( + ISteamNetworkingSockets *self, HSteamListenSocket hSocket, + SteamNetworkingIPAddr *address ); + +int SteamAPI_ISteamNetworkingSockets_CloseConnection( + ISteamNetworkingSockets *self, + HSteamNetConnection hPeer, int nReason, const char *pszDebug, + int bEnableLinger ); + +int SteamAPI_ISteamNetworkingSockets_CloseListenSocket( + ISteamNetworkingSockets *self, HSteamListenSocket hSocket ); + +EResult SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( + ISteamNetworkingSockets* self, + HSteamNetConnection hConn, const void *pData, u32 cbData, int nSendFlags, + i64 * pOutMessageNumber ); + +void SteamAPI_ISteamNetworkingSockets_SendMessages( + ISteamNetworkingSockets* self, + int nMessages, SteamNetworkingMessage_t *const *pMessages, + i64 *pOutMessageNumberOrResult ); + +EResult SteamAPI_ISteamNetworkingSockets_FlushMessagesOnConnection( + ISteamNetworkingSockets* self, + HSteamNetConnection hConn ); + +int SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection( + ISteamNetworkingSockets* self, + HSteamNetConnection hConn, + SteamNetworkingMessage_t **ppOutMessages, + int nMaxMessages ); + +/* + * Poll Groups + */ + +HSteamNetPollGroup SteamAPI_ISteamNetworkingSockets_CreatePollGroup( + ISteamNetworkingSockets *self ); + +int SteamAPI_ISteamNetworkingSockets_DestroyPollGroup( + ISteamNetworkingSockets *self, + HSteamNetPollGroup hPollGroup ); + +int SteamAPI_ISteamNetworkingSockets_SetConnectionPollGroup( + ISteamNetworkingSockets *self, + HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup ); + +int SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnPollGroup( + ISteamNetworkingSockets *self, + HSteamNetPollGroup hPollGroup, SteamNetworkingMessage_t **ppOutMessages, + int nMaxMessages ); +/* + * Returns basic information about the high-level state of the connection. + * Returns false if the connection handle is invalid. + */ +int SteamAPI_ISteamNetworkingSockets_GetConnectionInfo( + ISteamNetworkingSockets* self, + HSteamNetConnection hConn, SteamNetConnectionInfo_t * pInfo ); + +int SteamAPI_ISteamNetworkingSockets_GetDetailedConnectionStatus( + ISteamNetworkingSockets* self, + HSteamNetConnection hConn, char *pszBuf, int cbBuf ); + +int SteamAPI_ISteamNetworkingSockets_SetConnectionUserData( + ISteamNetworkingSockets* self, HSteamNetConnection hPeer, i64 nUserData ); + +i64 SteamAPI_ISteamNetworkingSockets_GetConnectionUserData( + ISteamNetworkingSockets* self, HSteamNetConnection hPeer ); + +int SteamAPI_ISteamNetworkingSockets_GetListenSocketAddress( + ISteamNetworkingSockets* self, + HSteamListenSocket hSocket, SteamNetworkingIPAddr *address ); + +enum{ k_cchSteamNetworkingMaxConnectionCloseReason = 128 }; +enum{ k_cchSteamNetworkingMaxConnectionDescription = 128 }; +enum{ k_cchSteamNetworkingMaxConnectionAppName = 32 }; +enum{ k_nSteamNetworkConnectionInfoFlags_Unauthenticated = 1 }; +enum{ k_nSteamNetworkConnectionInfoFlags_Unencrypted = 2 }; +enum{ k_nSteamNetworkConnectionInfoFlags_LoopbackBuffers = 4 }; +enum{ k_nSteamNetworkConnectionInfoFlags_Fast = 8 }; +enum{ k_nSteamNetworkConnectionInfoFlags_Relayed = 16 }; +enum{ k_nSteamNetworkConnectionInfoFlags_DualWifi = 32 }; + +/* Describe the state of a connection. */ +struct SteamNetConnectionInfo_t +{ + /* + * Who is on the other end? Depending on the connection type and phase of the + * connection, we might not know + */ + SteamNetworkingIdentity m_identityRemote; + + /* Arbitrary user data set by the local application code */ + i64 m_nUserData; + + /* + * Handle to listen socket this was connected on, or + * k_HSteamListenSocket_Invalid if we initiated the connection + */ + HSteamListenSocket m_hListenSocket; + + /* + * Remote address. Might be all 0's if we don't know it, or if this is N/A. + * (E.g. Basically everything except direct UDP connection.) + */ + SteamNetworkingIPAddr m_addrRemote; + u16 m__pad1; + + /* What data center is the remote host in? (0 if we don't know.) */ + SteamNetworkingPOPID m_idPOPRemote; + + /* + * What relay are we using to communicate with the remote host? + * (0 if not applicable.) + */ + SteamNetworkingPOPID m_idPOPRelay; + + /* High level state of the connection */ + ESteamNetworkingConnectionState m_eState; + + /* + * Basic cause of the connection termination or problem. + * See ESteamNetConnectionEnd for the values used + */ + int m_eEndReason; + + /* + * Human-readable, but non-localized explanation for connection + * termination or problem. This is intended for debugging / + * diagnostic purposes only, not to display to users. It might + * have some details specific to the issue. + */ + char m_szEndDebug[ k_cchSteamNetworkingMaxConnectionCloseReason ]; + + /* + * Debug description. This includes the internal connection ID, + * connection type (and peer information), and any name + * given to the connection by the app. This string is used in various + * internal logging messages. + * + * Note that the connection ID *usually* matches the HSteamNetConnection + * handle, but in certain cases with symmetric connections it might not. + */ + char m_szConnectionDescription + [ k_cchSteamNetworkingMaxConnectionDescription ]; + + /* Misc flags. Bitmask of k_nSteamNetworkConnectionInfoFlags_Xxxx */ + int m_nFlags; + + /* Internal stuff, room to change API easily */ + u32 reserved[63]; +}; + +/* + * Quick connection state, pared down to something you could call + * more frequently without it being too big of a perf hit. + */ +struct SteamNetConnectionRealTimeStatus_t +{ + /* High level state of the connection */ + ESteamNetworkingConnectionState m_eState; + + /* Current ping (ms) */ + int m_nPing; + + /* + * Connection quality measured locally, 0...1. + * (Percentage of packets delivered end-to-end in order). + */ + float m_flConnectionQualityLocal; + + /* Packet delivery success rate as observed from remote host */ + float m_flConnectionQualityRemote; + + /* Current data rates from recent history. */ + float m_flOutPacketsPerSec; + float m_flOutBytesPerSec; + float m_flInPacketsPerSec; + float m_flInBytesPerSec; + + /* + * Estimate rate that we believe that we can send data to our peer. + * Note that this could be significantly higher than m_flOutBytesPerSec, + * meaning the capacity of the channel is higher than you are sending data. + * (That's OK!) + */ + int m_nSendRateBytesPerSecond; + + /* + * Number of bytes pending to be sent. This is data that you have recently + * requested to be sent but has not yet actually been put on the wire. The + * reliable number ALSO includes data that was previously placed on the wire, + * but has now been scheduled for re-transmission. Thus, it's possible to + * observe m_cbPendingReliable increasing between two checks, even if no + * calls were made to send reliable data between the checks. Data that is + * awaiting the Nagle delay will appear in these numbers. + */ + int m_cbPendingUnreliable; + int m_cbPendingReliable; + + /* + * Number of bytes of reliable data that has been placed the wire, but + * for which we have not yet received an acknowledgment, and thus we may + * have to re-transmit. + */ + int m_cbSentUnackedReliable; + + /* + * If you queued a message right now, approximately how long would that + * message wait in the queue before we actually started putting its data on + * the wire in a packet? + * + * In general, data that is sent by the application is limited by the + * bandwidth of the channel. If you send data faster than this, it must be + * queued and put on the wire at a metered rate. Even sending a small amount + * of data (e.g. a few MTU, say ~3k) will require some of the data to be + * delayed a bit. + * + * Ignoring multiple lanes,the estimated delay will be approximately equal to + * + * ( m_cbPendingUnreliable+m_cbPendingReliable ) / + * m_nSendRateBytesPerSecond + * + * plus or minus one MTU. It depends on how much time has elapsed since the + * last packet was put on the wire. For example, the queue might have *just* + * been emptied, and the last packet placed on the wire, and we are exactly + * up against the send rate limit. In that case we might need to wait for + * one packet's worth of time to elapse before we can send again. On the + * other extreme, the queue might have data in it waiting for Nagle. (This + * will always be less than one packet, because as soon as we have a complete + * packet we would send it.) In that case, we might be ready to send data + * now, and this value will be 0. + * + * This value is only valid if multiple lanes are not used. If multiple lanes + * are in use, then the queue time will be different for each lane, and you + * must use the value in SteamNetConnectionRealTimeLaneStatus_t. + * + * Nagle delay is ignored for the purposes of this calculation. + */ + SteamNetworkingMicroseconds m_usecQueueTime; + + // Internal stuff, room to change API easily + u32 reserved[16]; +}; + +/* + * Callbacks + */ + +enum { k_iSteamNetConnectionStatusChangedCallBack = + k_iSteamNetworkingSocketsCallbacks + 1 }; + +typedef struct SteamNetConnectionStatusChangedCallback_t + SteamNetConnectionStatusChangedCallback_t; +struct SteamNetConnectionStatusChangedCallback_t +{ + /// Connection handle + HSteamNetConnection m_hConn; + + /// Full connection info + SteamNetConnectionInfo_t m_info; + + /// Previous state. (Current state is in m_info.m_eState) + ESteamNetworkingConnectionState m_eOldState; +}; + +enum { k_iSteamNetAuthenticationStatus = + k_iSteamNetworkingSocketsCallbacks + 2 }; + +typedef struct SteamNetAuthenticationStatus_t SteamNetAuthenticationStatus_t; +struct SteamNetAuthenticationStatus_t +{ + /// Status + ESteamNetworkingAvailability m_eAvail; + + /// Non-localized English language status. For diagnostic/debugging + /// purposes only. + char m_debugMsg[ 256 ]; +}; + +#pragma pack(pop) + +/* This does not have packing specified in the steamnetworkingtypes.h, it seems + * to use default */ +struct SteamNetworkingMessage_t +{ + /* + * Message payload + */ + void *m_pData; + + /* + * Size of the payload. + */ + int m_cbSize; + + HSteamNetConnection m_conn; + + /* + * For inbound messages: Who sent this to us? + * For outbound messages on connections: not used. + * For outbound messages on the ad-hoc ISteamNetworkingMessages interface: + * who should we send this to? + */ + SteamNetworkingIdentity m_identityPeer; + + /* + * For messages received on connections, this is the user data + * associated with the connection. + * + * This is *usually* the same as calling GetConnection() and then + * fetching the user data associated with that connection, but for + * the following subtle differences: + * + * - This user data will match the connection's user data at the time + * is captured at the time the message is returned by the API. + * If you subsequently change the userdata on the connection, + * this won't be updated. + * - This is an inline call, so it's *much* faster. + * - You might have closed the connection, so fetching the user data + * would not be possible. + * + * Not used when sending messages. + */ + i64 m_nConnUserData; + + /* + * Local timestamp when the message was received + * Not used for outbound messages. + */ + SteamNetworkingMicroseconds m_usecTimeReceived; + + /* + * Message number assigned by the sender. This is not used for outbound + * messages. Note that if multiple lanes are used, each lane has its own + * message numbers, which are assigned sequentially, so messages from + * different lanes will share the same numbers. + */ + i64 m_nMessageNumber; + + /* + * Function used to free up m_pData. This mechanism exists so that + * apps can create messages with buffers allocated from their own + * heap, and pass them into the library. This function will + * usually be something like: + * + * free( pMsg->m_pData ); + */ + void (*m_pfnFreeData)( SteamNetworkingMessage_t *pMsg ); + + /* + * Function to used to decrement the internal reference count and, if + * it's zero, release the message. You should not set this function pointer, + * or need to access this directly! Use the Release() function instead! + */ + void (*m_pfnRelease)( SteamNetworkingMessage_t *pMsg ); + + /* + * When using ISteamNetworkingMessages, the channel number the message was + * received on (Not used for messages sent or received on "connections") + */ + int m_nChannel; + + /* + * Bitmask of k_nSteamNetworkingSend_xxx flags. + * For received messages, only the k_nSteamNetworkingSend_Reliable bit is + * valid. + * For outbound messages, all bits are relevant + */ + int m_nFlags; + + /* + * Arbitrary user data that you can use when sending messages using + * ISteamNetworkingUtils::AllocateMessage and + * ISteamNetworkingSockets::SendMessage. + * (The callback you set in m_pfnFreeData might use this field.) + * + * Not used for received messages. + */ + i64 m_nUserData; + + /* + * For outbound messages, which lane to use? See + * ISteamNetworkingSockets::ConfigureConnectionLanes. + * For inbound messages, what lane was the message received on? + */ + u16 m_idxLane; + u16 _pad1__; +}; + +void SteamAPI_SteamNetworkingMessage_t_Release(SteamNetworkingMessage_t* self); + + + + +/* + * Utility + */ + +static const char *string_ESteamNetworkingConnectionState( + ESteamNetworkingConnectionState s ) +{ + switch(s) + { + case k_ESteamNetworkingConnectionState_None: return "None"; break; + case k_ESteamNetworkingConnectionState_Connecting: + return "Connecting"; + break; + case k_ESteamNetworkingConnectionState_FindingRoute: + return "Finding route"; + break; + case k_ESteamNetworkingConnectionState_Connected: + return "Connected"; + break; + case k_ESteamNetworkingConnectionState_ClosedByPeer: + return "Closed By Peer"; + break; + case k_ESteamNetworkingConnectionState_ProblemDetectedLocally: + return "Problem detected locally"; + break; + case k_ESteamNetworkingConnectionState_FinWait: + return "Finwait"; + break; + case k_ESteamNetworkingConnectionState_Linger: + return "Linger"; + break; + case k_ESteamNetworkingConnectionState_Dead: + return "Dead"; + break; + case k_ESteamNetworkingConnectionState__Force32Bit: + return "Force 32 Bit"; + break; + } + + return "Error"; +} + +static const char *string_ESteamNetworkingAvailability( + ESteamNetworkingAvailability s ) +{ + switch(s) + { + case k_ESteamNetworkingAvailability_CannotTry: + return "Cannot Try"; + break; + case k_ESteamNetworkingAvailability_Failed: + return "Failed"; + break; + case k_ESteamNetworkingAvailability_Previously: + return "Previously"; + break; + case k_ESteamNetworkingAvailability_Retrying: + return "Retrying"; + break; + case k_ESteamNetworkingAvailability_NeverTried: + return "Never tried"; + break; + case k_ESteamNetworkingAvailability_Waiting: + return "Waiting"; + break; + case k_ESteamNetworkingAvailability_Attempting: + return "Attempting"; + break; + case k_ESteamNetworkingAvailability_Current: + return "Current"; + break; + case k_ESteamNetworkingAvailability_Unknown: + return "Unknown"; + break; + default: + return "Error"; + break; + } +} + +#endif /* VG_STEAM_NETWORKING_H */