mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-15 13:16:58 +00:00
1
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
//====== Copyright Valve Corporation, All rights reserved. ====================
|
||||
//
|
||||
// Purpose: A low level API similar to Berkeley socket, to send messages
|
||||
// between hosts over the Steam network and addressed using Steam IDs.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef ISTEAMNETWORKINGSOCKETS
|
||||
#define ISTEAMNETWORKINGSOCKETS
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "steamnetworkingtypes.h"
|
||||
|
||||
// #KLUDGE! This is so we don't have to link with steam_api.lib
|
||||
#include <steam/steam_api.h>
|
||||
#include <steam/steam_gameserver.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// Lower level networking interface that more closely mirrors the standard
|
||||
/// Berkeley sockets model. Sockets are hard! You should probably only use
|
||||
/// this interface under the existing circumstances:
|
||||
///
|
||||
/// - You have an existing socket-based codebase you want to port, or coexist with.
|
||||
/// - You want to be able to connect based on IP address, rather than (just) Steam ID.
|
||||
/// - You need low-level control of bandwidth utilization, when to drop packets, etc.
|
||||
///
|
||||
/// Note that neither of the terms "connection" and "socket" will correspond
|
||||
/// one-to-one with an underlying UDP socket. An attempt has been made to
|
||||
/// keep the semantics as similar to the standard socket model when appropriate,
|
||||
/// but some deviations do exist.
|
||||
class ISteamSocketNetworking
|
||||
{
|
||||
public:
|
||||
|
||||
/// Creates a "server" socket that listens for clients to connect to, either by calling
|
||||
/// ConnectSocketBySteamID or ConnectSocketByIPv4Address.
|
||||
///
|
||||
/// nSteamConnectVirtualPort specifies how clients can connect to this socket using
|
||||
/// ConnectBySteamID. A negative value indicates that this functionality is
|
||||
/// disabled and clients must connect by IP address. It's very common for applications
|
||||
/// to only have one listening socket; in that case, use zero. If you need to open
|
||||
/// multiple listen sockets and have clients be able to connect to one or the other, then
|
||||
/// nSteamConnectVirtualPort should be a small integer constant unique to each listen socket
|
||||
/// you create.
|
||||
///
|
||||
/// If you want clients to connect to you by your IPv4 addresses using
|
||||
/// ConnectByIPv4Address, then you must set nPort to be nonzero. Steam will
|
||||
/// bind a UDP socket to the specified local port, and clients will send packets using
|
||||
/// ordinary IP routing. It's up to you to take care of NAT, protecting your server
|
||||
/// from DoS, etc. If you don't need clients to connect to you by IP, then set nPort=0.
|
||||
/// Use nIP if you wish to bind to a particular local interface. Typically you will use 0,
|
||||
/// which means to listen on all interfaces, and accept the default outbound IP address.
|
||||
/// If nPort is zero, then nIP must also be zero.
|
||||
///
|
||||
/// A SocketStatusCallback_t callback when another client attempts a connection.
|
||||
virtual HSteamListenSocket CreateListenSocket( int nSteamConnectVirtualPort, uint32 nIP, uint16 nPort ) = 0;
|
||||
|
||||
/// Creates a connection and begins talking to a remote destination. The remote host
|
||||
/// must be listening with the appropriate call to CreateListenSocket.
|
||||
///
|
||||
/// Use ConnectBySteamID to connect using the SteamID (client or game server) as the network address.
|
||||
/// Use ConnectByIPv4Address to connect by IP address.
|
||||
///
|
||||
/// On success, a SocketStatusCallback_t callback is triggered.
|
||||
/// On failure or timeout, a SocketStatusCallback_t callback with a failure code in m_eSNetSocketState
|
||||
virtual HSteamNetConnection ConnectBySteamID( CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec ) = 0;
|
||||
virtual HSteamNetConnection ConnectByIPv4Address( uint32 nIP, uint16 nPort, int nTimeoutSec ) = 0;
|
||||
|
||||
/// Accept an incoming connection that has been received on a listen socket.
|
||||
///
|
||||
/// When a connection attempt is received (perhaps after a few basic handshake
|
||||
/// packets have been exchanged to prevent trivial spoofing), a connection interface
|
||||
/// object is created in the k_ESteamNetworkingConnectionState_Connecting state
|
||||
/// and a SteamNetConnectionStatusChangedCallback_t is posted. At this point, your
|
||||
/// application MUST either accept or close the connection. (It may not ignore it.)
|
||||
/// Accepting the connection will transition it into the connected state.
|
||||
///
|
||||
/// You should take action within a few seconds, because accepting the connection is
|
||||
/// what actually sends the reply notifying the client that they are connected. If you
|
||||
/// delay taking action, from the client's perspective it is the same as the network
|
||||
/// being unresponsive, and the client may timeout the connection attempt. In other
|
||||
/// words, the client cannot distinguish between a delay caused by network problems
|
||||
/// and a delay caused by the application.
|
||||
///
|
||||
/// This means that if your application goes for more than a few seconds without
|
||||
/// processing callbacks, then there is a chance that a client may attempt to connect
|
||||
/// in that interval, and timeout.
|
||||
///
|
||||
/// If the application does not respond to the connection attempt in a timely manner,
|
||||
/// and we stop receiving communication from the client, the connection attempt will
|
||||
/// be timed out locally, transitioning the connection to the
|
||||
/// k_ESteamNetworkingConnectionState_ProblemDetectedLocally state. The client may also
|
||||
/// close the connection before it is accepted and a transition to the
|
||||
/// k_ESteamNetworkingConnectionState_ClosedByPeer is also possible.
|
||||
///
|
||||
/// Returns k_EResultInvalidParam if the handle is invalid.
|
||||
/// Returns k_EResultInvalidState if the connection is not in the appropriate state.
|
||||
/// (Remember that the connection state could change in between the time that the
|
||||
/// notification being posted to the queue and when it is received by the application.)
|
||||
virtual EResult AcceptConnection( HSteamNetConnection hConn ) = 0;
|
||||
|
||||
/// Disconnects from the remote host and invalidates the connection handle.
|
||||
/// Any unread data on the connection is discarded.
|
||||
///
|
||||
/// nReason is an application defined code that will be received on the other
|
||||
/// end and recorded (when possible) in backend analytics. The value should
|
||||
/// come from a restricted range. (See ESteamNetConnectionEnd.) If you don't need
|
||||
/// to communicate any information to the remote host, and do not want analytics to
|
||||
/// be able to distinguish "normal" connection terminations from "exceptional" ones,
|
||||
/// You may pass zero, in which case the generic value of
|
||||
/// k_ESteamNetConnectionEnd_App_Generic will be used.
|
||||
///
|
||||
/// pszDebug is an optional human-readable diagnostic string that will be received
|
||||
/// by the remote host and recorded (when possible) in backend analytics.
|
||||
///
|
||||
/// If you wish to put the socket into a "linger" state, where an attempt is made to
|
||||
/// flush any remaining sent data, use bEnableLinger=true. Otherwise reliable data
|
||||
/// is not flushed.
|
||||
///
|
||||
/// If the connection has already ended and you are just freeing up the
|
||||
/// connection interface, the reason code, debug string, and linger flag are
|
||||
/// ignored.
|
||||
virtual bool CloseConnection( HSteamNetConnection hPeer, int nReason, const char *pszDebug, bool bEnableLinger ) = 0;
|
||||
|
||||
/// Destroy a listen socket, and all the client sockets generated by accepting connections
|
||||
/// on the listen socket.
|
||||
///
|
||||
/// pszNotifyRemoteReason determines what cleanup actions are performed on the client
|
||||
/// sockets being destroyed. (See DestroySocket for more details.)
|
||||
///
|
||||
/// Note that if cleanup is requested and you have requested the listen socket bound to a
|
||||
/// particular local port to facilitate direct UDP/IPv4 connections, then the underlying UDP
|
||||
/// socket must remain open until all clients have been cleaned up.
|
||||
virtual bool CloseListenSocket( HSteamListenSocket hSocket, const char *pszNotifyRemoteReason ) = 0;
|
||||
|
||||
/// Set connection user data. Returns false if the handle is invalid.
|
||||
virtual bool SetConnectionUserData( HSteamNetConnection hPeer, int64 nUserData ) = 0;
|
||||
|
||||
/// Fetch connection user data. Returns -1 if handle is invalid
|
||||
/// or if you haven't set any userdata on the connection.
|
||||
virtual int64 GetConnectionUserData( HSteamNetConnection hPeer ) = 0;
|
||||
|
||||
/// Set a name for the connection, used mostly for debugging
|
||||
virtual void SetConnectionName( HSteamNetConnection hPeer, const char *pszName ) = 0;
|
||||
|
||||
/// Fetch connection user data. Returns -1 if handle is invalid
|
||||
/// or if you haven't set any userdata on the connection.
|
||||
virtual void GetConnectionName( HSteamNetConnection hPeer, char *ppszName, int nMaxLen ) = 0;
|
||||
|
||||
/// Send a message to the remote host on the connected socket.
|
||||
///
|
||||
/// eSendType determines the delivery guarantees that will be provided,
|
||||
/// when data should be buffered, etc.
|
||||
///
|
||||
/// Note that the semantics we use for messages are not precisely
|
||||
/// the same as the semantics of a standard "stream" socket.
|
||||
/// (SOCK_STREAM) For an ordinary stream socket, the boundaries
|
||||
/// between chunks are not considered relevant, and the sizes of
|
||||
/// the chunks of data written will not necessarily match up to
|
||||
/// the sizes of the chunks that are returned by the reads on
|
||||
/// the other end. The remote host might read a partial chunk,
|
||||
/// or chunks might be coalesced. For the message semantics
|
||||
/// used here, however, the sizes WILL match. Each send call
|
||||
/// will match a successful read call on the remote host
|
||||
/// one-for-one. If you are porting existing stream-oriented
|
||||
/// code to the semantics of reliable messages, your code should
|
||||
/// work the same, since reliable message semantics are more
|
||||
/// strict than stream semantics. The only caveat is related to
|
||||
/// performance: there is per-message overhead to retain the
|
||||
/// messages sizes, and so if your code sends many small chunks
|
||||
/// of data, performance will suffer. Any code based on stream
|
||||
/// sockets that does not write excessively small chunks will
|
||||
/// work without any changes.
|
||||
virtual EResult SendMessageToConnection( HSteamNetConnection hConn, const void *pData, uint32 cbData, ESteamNetworkingSendType eSendType ) = 0;
|
||||
|
||||
/// Fetch the next available message(s) from the socket, if any.
|
||||
/// Returns the number of messages returned into your array, up to nMaxMessages.
|
||||
/// If the connection handle is invalid, -1 is returned.
|
||||
///
|
||||
/// The order of the messages returned in the array is relevant.
|
||||
/// Reliable messages will be received in the order they were sent (and with the
|
||||
/// same sizes --- see SendMessageToConnection for on this subtle difference from a stream socket).
|
||||
///
|
||||
/// FIXME - We're still debating the exact set of guarantees for unreliable, so this might change.
|
||||
/// Unreliable messages may not be received. The order of delivery of unreliable messages
|
||||
/// is NOT specified. They may be received out of order with respect to each other or
|
||||
/// reliable messages. They may be received multiple times!
|
||||
///
|
||||
/// If any messages are returned, you MUST call Release() to each of them free up resources
|
||||
/// after you are done. It is safe to keep the object alive for a little while (put it
|
||||
/// into some queue, etc), and you may call Release() from any thread.
|
||||
virtual int ReceiveMessagesOnConnection( HSteamNetConnection hConn, ISteamNetworkingMessage **ppOutMessages, int nMaxMessages ) = 0;
|
||||
|
||||
/// Same as ReceiveMessagesOnConnection, but will return the next message available
|
||||
/// on any client socket that was accepted through the specified listen socket. Use
|
||||
/// ISteamNetworkingMessage::GetConnection to know which client connection.
|
||||
///
|
||||
/// Delivery order of messages among different clients is not defined. They may
|
||||
/// be returned in an order different from what they were actually received. (Delivery
|
||||
/// order of messages from the same client is well defined, and thus the order of the
|
||||
/// messages is relevant!)
|
||||
virtual int ReceiveMessagesOnListenSocket( HSteamListenSocket hSocket, ISteamNetworkingMessage **ppOutMessages, int nMaxMessages ) = 0;
|
||||
|
||||
/// Returns information about the specified connection.
|
||||
virtual bool GetConnectionInfo( HSteamNetConnection hConn, SteamNetConnectionInfo_t *pInfo ) = 0;
|
||||
|
||||
/// Returns brief set of connection status that you might want to display
|
||||
/// to the user in game.
|
||||
virtual bool GetQuickConnectionStatus( HSteamNetConnection hConn, SteamNetworkingQuickConnectionStatus *pStats ) = 0;
|
||||
|
||||
/// Returns detailed connection stats in text format. Useful
|
||||
/// for dumping to a log, etc.
|
||||
///
|
||||
/// Returns:
|
||||
/// -1 failure (bad connection handle)
|
||||
/// 0 OK, your buffer was filled in and '\0'-terminated
|
||||
/// >0 Your buffer was either nullptr, or it was too small and the text got truncated. Try again with a buffer of at least N bytes.
|
||||
virtual int GetDetailedConnectionStatus( HSteamNetConnection hConn, char *pszBuf, int cbBuf ) = 0;
|
||||
|
||||
/// Returns information about the listen socket.
|
||||
///
|
||||
/// *pnIP and *pnPort will be 0 if the socket is set to listen for connections based
|
||||
/// on SteamID only. If your listen socket accepts connections on IPv4, then both
|
||||
/// fields will return nonzero, even if you originally passed a zero IP. However,
|
||||
/// note that the address returned may be a private address (e.g. 10.0.0.x or 192.168.x.x),
|
||||
/// and may not be reachable by a general host on the Internet.
|
||||
virtual bool GetListenSocketInfo( HSteamListenSocket hSocket, uint32 *pnIP, uint16 *pnPort ) = 0;
|
||||
|
||||
//
|
||||
// Special SDR connections involved with servers hosted in Valve data centers
|
||||
//
|
||||
virtual bool SetHostedDedicatedServerCertificate( const void *pCert, int cbCert, void *pPrivateKey, int cbPrivateKey ) = 0;
|
||||
virtual HSteamListenSocket CreateHostedDedicatedServerListenSocket( uint16 nPort ) = 0;
|
||||
virtual HSteamNetConnection ConnectToHostedDedicatedServer( CSteamID steamIDTarget ) = 0;
|
||||
|
||||
//
|
||||
// Gets some debug text from the connection
|
||||
//
|
||||
virtual bool GetConnectionDebugText( HSteamNetConnection hConn, char *pOut, int nOutCCH ) = 0;
|
||||
|
||||
//
|
||||
// Set and get configuration values, see ESteamNetworkingConfigurationValue for individual descriptions.
|
||||
//
|
||||
// Returns the value or -1 is eConfigValue is invalid
|
||||
virtual int32 GetConfigurationValue( ESteamNetworkingConfigurationValue eConfigValue ) = 0;
|
||||
// Returns true if successfully set
|
||||
virtual bool SetConfigurationValue( ESteamNetworkingConfigurationValue eConfigValue, int32 nValue ) = 0;
|
||||
|
||||
// Return the name of an int configuration value, or NULL if config value isn't known
|
||||
virtual const char *GetConfigurationValueName( ESteamNetworkingConfigurationValue eConfigValue ) = 0;
|
||||
|
||||
//
|
||||
// Set and get configuration strings, see ESteamNetworkingConfigurationString for individual descriptions.
|
||||
//
|
||||
// Get the configuration string, returns length of string needed if pDest is nullpr or destSize is 0
|
||||
// returns -1 if the eConfigValue is invalid
|
||||
virtual int32 GetConfigurationString( ESteamNetworkingConfigurationString eConfigString, char *pDest, int32 destSize ) = 0;
|
||||
virtual bool SetConfigurationString( ESteamNetworkingConfigurationString eConfigString, const char *pString ) = 0;
|
||||
|
||||
// Return the name of a string configuration value, or NULL if config value isn't known
|
||||
virtual const char *GetConfigurationStringName( ESteamNetworkingConfigurationString eConfigString ) = 0;
|
||||
|
||||
};
|
||||
#define STEAMSOCKETNETWORKING_VERSION "SteamSocketNetworking001"
|
||||
|
||||
// Notification struct used to notify when a connection has changed state
|
||||
struct SteamNetConnectionStatusChangedCallback_t
|
||||
{
|
||||
HSteamNetConnection m_hConn; //< Connection handle
|
||||
SteamNetConnectionInfo_t m_info; //< Full connection info
|
||||
int m_eOldState; //< ESNetSocketState. (Current stats is in m_info)
|
||||
};
|
||||
|
||||
// Temporary global accessor. This will be moved to steam_api.h
|
||||
STEAMDATAGRAMLIB_INTERFACE ISteamSocketNetworking *SteamSocketNetworking();
|
||||
|
||||
typedef void * ( S_CALLTYPE *FSteamInternal_CreateInterface )( const char *);
|
||||
typedef void ( S_CALLTYPE *FSteamAPI_RegisterCallResult)( class CCallbackBase *pCallback, SteamAPICall_t hAPICall );
|
||||
typedef void ( S_CALLTYPE *FSteamAPI_UnregisterCallResult)( class CCallbackBase *pCallback, SteamAPICall_t hAPICall );
|
||||
|
||||
/// !KLUDGE! Glue code that will go away when we move everything into
|
||||
/// the ISteamNetwork interfaces
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamDatagramClient_Internal_SteamAPIKludge( FSteamAPI_RegisterCallResult fnRegisterCallResult, FSteamAPI_UnregisterCallResult fnUnregisterCallResult );
|
||||
STEAMDATAGRAMLIB_INTERFACE bool SteamDatagramClient_Init_Internal( const char *pszCacheDirectory, /* ESteamDatagramPartner */ int ePartner, int iPartnerMask, SteamDatagramErrMsg &errMsg, ISteamClient *pClient, HSteamUser hSteamUser, HSteamPipe hSteamPipe );
|
||||
inline bool SteamDatagramClient_Init( const char *pszCacheDirectory, /* ESteamDatagramPartner */ int ePartner, int iPartnerMask, SteamDatagramErrMsg &errMsg )
|
||||
{
|
||||
SteamDatagramClient_Internal_SteamAPIKludge( &::SteamAPI_RegisterCallResult, &::SteamAPI_UnregisterCallResult );
|
||||
return SteamDatagramClient_Init_Internal( pszCacheDirectory, ePartner, iPartnerMask, errMsg, ::SteamClient(), ::SteamAPI_GetHSteamUser(), ::SteamAPI_GetHSteamPipe() );
|
||||
}
|
||||
|
||||
|
||||
/// Shutdown all clients and close all sockets
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamDatagramClient_Kill();
|
||||
|
||||
/// Initialize the game server interface
|
||||
STEAMDATAGRAMLIB_INTERFACE bool SteamDatagramServer_Init_Internal( SteamDatagramErrMsg &errMsg, ISteamClient *pClient, HSteamUser hSteamUser, HSteamPipe hSteamPipe );
|
||||
// KLUDGE TF is using an old version of the SDK, which doesn't have this. TF doesn't need this, so just comment it out.
|
||||
// We'll need to upgrade the Steamworks SDK if we want to actually use SDR
|
||||
//inline bool SteamDatagramServer_Init( SteamDatagramErrMsg &errMsg )
|
||||
//{
|
||||
// SteamDatagramClient_Internal_SteamAPIKludge( &::SteamAPI_RegisterCallResult, &::SteamAPI_UnregisterCallResult );
|
||||
// return SteamDatagramServer_Init_Internal( errMsg, ::SteamGameServerClient(), ::SteamGameServer_GetHSteamUser(), ::SteamGameServer_GetHSteamPipe() );
|
||||
//}
|
||||
|
||||
/// Shutdown the game server interface
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamDatagramServer_Kill( );
|
||||
|
||||
// !KLUDGE! Check for connections that have changed status, and post callbacks.
|
||||
// This is temporary we can hook this up using the ordinary steam CCallback mechanism
|
||||
typedef void (*FSteamNetConnectionStatusChangedCallback)( SteamNetConnectionStatusChangedCallback_t *pInfo );
|
||||
STEAMDATAGRAMLIB_INTERFACE void Temp_DispatchsSteamNetConnectionStatusChangedCallbacks( FSteamNetConnectionStatusChangedCallback fnCallback );
|
||||
|
||||
enum ESteamDatagramDebugOutputType
|
||||
{
|
||||
k_ESteamDatagramDebugOutputType_None,
|
||||
k_ESteamDatagramDebugOutputType_Error,
|
||||
k_ESteamDatagramDebugOutputType_Important, // Nothing is wrong, but this is an important notification
|
||||
k_ESteamDatagramDebugOutputType_Warning,
|
||||
k_ESteamDatagramDebugOutputType_Msg, // Recommended amount
|
||||
k_ESteamDatagramDebugOutputType_Verbose, // Quite a bit
|
||||
k_ESteamDatagramDebugOutputType_Debug, // Practically everything
|
||||
};
|
||||
|
||||
/// Setup callback for debug output, and the desired verbosity you want.
|
||||
typedef void (*FSteamDatagramDebugOutput)( /* ESteamDatagramDebugOutputType */ int nType, const char *pszMsg );
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamDatagram_SetDebugOutputFunction( /* ESteamDatagramDebugOutputType */ int eDetailLevel, FSteamDatagramDebugOutput pfnFunc );
|
||||
|
||||
#endif // ISTEAMNETWORKINGSOCKETS
|
||||
@@ -0,0 +1,125 @@
|
||||
//====== Copyright Valve Corporation, All rights reserved. ====================
|
||||
//
|
||||
// Purpose: misc networking utilities
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef ISTEAMNETWORKINGUTILS
|
||||
#define ISTEAMNETWORKINGUTILS
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "steamnetworkingtypes.h"
|
||||
struct SteamDatagramRelayAuthTicket;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// Misc networking utilities for checking the local networking environment
|
||||
/// and estimating pings.
|
||||
class ISteamNetworkingUtils
|
||||
{
|
||||
public:
|
||||
|
||||
/// Fetch current timestamp. These values never go backwards, and
|
||||
/// the initial value is low enough that practically speaking it's
|
||||
/// not necessary to worry about the value wrapping around.
|
||||
virtual SteamNetworkingMicroseconds GetLocalTimestamp() = 0;
|
||||
|
||||
/// Check if the ping data of sufficient recency is available, and if
|
||||
/// it's too old, start refreshing it.
|
||||
///
|
||||
/// Games that use the ping location information will typically
|
||||
/// want to call this at boot time, to make sure all prerequisites
|
||||
/// are ready. Especially since the first measurement might take
|
||||
/// slightly longer than subsequent measurements.
|
||||
///
|
||||
/// Returns true if sufficiently recent data is already available.
|
||||
///
|
||||
/// Returns false if sufficiently recent data is not available. In this
|
||||
/// case, ping measurement is initiated, if it is not already active.
|
||||
/// (You cannot restart a measurement already in progress.)
|
||||
///
|
||||
/// A FIXME event will be posted when measurement is completed.
|
||||
virtual bool CheckPingDataUpToDate( float flMaxAgeSeconds ) = 0;
|
||||
|
||||
/// Return location info for the current host. Returns the approximate
|
||||
/// age of the data, in seconds, or -1 if no data is available.
|
||||
/// Note that this might return an age older than the age of your game's
|
||||
/// process, if the data was obtained before you game started.
|
||||
///
|
||||
/// This always return the most up-to-date information we have available
|
||||
/// right now, even if we are in the middle of re-calculating ping times.
|
||||
virtual float GetLocalPingLocation( SteamNetworkPingLocation_t &result ) = 0;
|
||||
|
||||
/// Return true if we are taking ping measurements to update our ping
|
||||
/// location or select optimal routing. Ping measurement typically takes
|
||||
/// a few seconds, perhaps up to 10 seconds.
|
||||
virtual bool IsPingMeasurementInProgress() = 0;
|
||||
|
||||
/// Estimate the round-trip latency between two arbitrary locations, in
|
||||
/// milliseconds. This is a conservative estimate, based on routing through
|
||||
/// the relay network. For most basic connections based on SteamID,
|
||||
/// this ping time will be pretty accurate, since it will be based on the
|
||||
/// route likely to be actually used.
|
||||
///
|
||||
/// If a direct IP route is used (perhaps via NAT traversal), then the route
|
||||
/// will be different, and the ping time might be better. Or it might actually
|
||||
/// be a bit worse! Standard IP routing is frequently suboptimal!
|
||||
///
|
||||
/// but even in this case, the estimate obtained using this method is a
|
||||
/// reasonable upper bound on the ping time. (Also it has the advantage
|
||||
/// of returning immediately and not sending any packets.)
|
||||
///
|
||||
/// In a few cases we might not able to estimate the route. In this case
|
||||
/// a negative value is returned. k_nSteamNetworkingPing_Failed means
|
||||
/// the reason was because of some networking difficulty. (Failure to
|
||||
/// ping, etc) k_nSteamNetworkingPing_Unknown is returned if we cannot
|
||||
/// currently answer the question for some other reason.
|
||||
virtual int EstimatePingTimeBetweenTwoLocations( const SteamNetworkPingLocation_t &location1, const SteamNetworkPingLocation_t &location2 ) = 0;
|
||||
|
||||
/// Same as EstimatePingTime, but assumes that one location is the local host.
|
||||
/// This is a bit faster, especially if you need to calculate a bunch of
|
||||
/// these in a loop to find the fastest one.
|
||||
///
|
||||
/// In rare cases this might return a slightly different estimate than combining
|
||||
/// GetLocalPingLocation with EstimatePingTimeBetweenTwoLocations. That's because
|
||||
/// this function uses a slightly more complete description
|
||||
virtual int EstimatePingTimeFromLocalHost( const SteamNetworkPingLocation_t &remoteLocation ) = 0;
|
||||
|
||||
// FIXME:
|
||||
//
|
||||
// Check current internet connection status
|
||||
|
||||
//
|
||||
// Low level ticket stuff. I need to get some advice and talk through how this should work
|
||||
// or how best to tuck it away and make it transparent.
|
||||
//
|
||||
|
||||
virtual bool ReceivedTicket( const void *pvTicket, int cbTicket, SteamDatagramRelayAuthTicket *pOutParsedTicket ) = 0;
|
||||
virtual bool HasTicketForServer( CSteamID steamID ) = 0;
|
||||
virtual uint32 GetIPForServerSteamIDFromTicket( CSteamID steamID ) = 0;
|
||||
|
||||
//
|
||||
// Low level network config stuff I haven't figure out how best to tuck away.
|
||||
// Dota and CSGO use it because we have gameservers in the datacenter, and
|
||||
// we need this information to do region selection. But most games won't
|
||||
// need it.
|
||||
//
|
||||
|
||||
/// Fetch directly measured ping time from local host to a particular network PoP.
|
||||
/// Most games will not need to call this.
|
||||
virtual int GetPingToDataCenter( SteamNetworkingPOPID popID, SteamNetworkingPOPID *pViaRelayPoP ) = 0;
|
||||
virtual int GetDirectPingToPOP( SteamNetworkingPOPID popID ) = 0;
|
||||
|
||||
/// Get number of network PoPs in the config
|
||||
virtual int GetPOPCount() = 0;
|
||||
|
||||
/// Get list of all POP IDs
|
||||
virtual int GetPOPList( SteamNetworkingPOPID *list, int nListSz ) = 0;
|
||||
};
|
||||
#define STEAMNETWORKINGUTILS_VERSION "SteamNetworkingUtils001"
|
||||
|
||||
/// Get ISteamNetworkingUtils object. This will eventually go in Steam_api.h with all the rest of its kin
|
||||
STEAMDATAGRAMLIB_INTERFACE ISteamNetworkingUtils *SteamNetworkingUtils();
|
||||
|
||||
#endif // ISTEAMNETWORKINGUTILS
|
||||
@@ -0,0 +1,298 @@
|
||||
//====== Copyright Valve Corporation, All rights reserved. ====================
|
||||
//
|
||||
// Some public types for communicating detailed connection stats
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef STEAMDATAGRAM_STATS_H
|
||||
#define STEAMDATAGRAM_STATS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "steamnetworkingtypes.h"
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(8)
|
||||
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamDatagramLinkInstantaneousStats_Clear( SteamDatagramLinkInstantaneousStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamDatagramLinkLifetimeStats_Clear( SteamDatagramLinkLifetimeStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE int SteamDatagramLinkLifetimeStats_PingHistogramTotalCount( const SteamDatagramLinkLifetimeStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE int SteamDatagramLinkLifetimeStats_QualityHistogramTotalCount( const SteamDatagramLinkLifetimeStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE int SteamDatagramLinkLifetimeStats_JitterHistogramTotalCount( const SteamDatagramLinkLifetimeStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE int SteamDatagramLinkLifetimeStats_TXSpeedHistogramTotalCount( const SteamDatagramLinkLifetimeStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE int SteamDatagramLinkLifetimeStats_RXSpeedHistogramTotalCount( const SteamDatagramLinkLifetimeStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamDatagramLinkStats_Clear( SteamDatagramLinkStats *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE void SteamNetworkingDetailedConnectionStatus_Clear( SteamNetworkingDetailedConnectionStatus *pThis );
|
||||
STEAMDATAGRAMLIB_INTERFACE int SteamNetworkingDetailedConnectionStatus_Print( const SteamNetworkingDetailedConnectionStatus *pThis, char *pszBuf, int cbBuf );
|
||||
|
||||
/// Instantaneous statistics for a link between two hosts.
|
||||
struct SteamDatagramLinkInstantaneousStats
|
||||
{
|
||||
|
||||
/// Data rates
|
||||
float m_flOutPacketsPerSec;
|
||||
float m_flOutBytesPerSec;
|
||||
float m_flInPacketsPerSec;
|
||||
float m_flInBytesPerSec;
|
||||
|
||||
/// Smoothed ping. This will be -1 if we don't have any idea!
|
||||
int m_nPingMS;
|
||||
|
||||
/// 0...1, estimated number of packets that were sent to us, but we failed to receive.
|
||||
/// <0 if we haven't received any sequenced packets and so we don't have any way to estimate this.
|
||||
float m_flPacketsDroppedPct;
|
||||
|
||||
/// Packets received with a sequence number abnormality, other than basic packet loss. (Duplicated, out of order, lurch.)
|
||||
/// <0 if we haven't received any sequenced packets and so we don't have any way to estimate this.
|
||||
float m_flPacketsWeirdSequenceNumberPct;
|
||||
|
||||
/// Peak jitter
|
||||
int m_usecMaxJitter;
|
||||
|
||||
/// Current sending rate, this can be low at connection start until the slow start
|
||||
/// ramps it up. It's adjusted as packets are lost and congestion is encountered during
|
||||
/// the connection
|
||||
int m_nSendRate;
|
||||
|
||||
/// How many pending bytes are waiting to be sent. This is data that is currently waiting
|
||||
/// to be sent and in outgoing buffers. If this is zero, then the connection is idle
|
||||
/// and all pending data has been sent. Note that in case of packet loss any pending
|
||||
/// reliable data might be re-sent. This does not include data that has been sent and is
|
||||
/// waiting for acknowledgment.
|
||||
int m_nPendingBytes;
|
||||
|
||||
inline void Clear() { SteamDatagramLinkInstantaneousStats_Clear( this ); }
|
||||
};
|
||||
|
||||
/// Stats for the lifetime of a connection.
|
||||
/// Should match CMsgSteamDatagramLinkLifetimeStats
|
||||
struct SteamDatagramLinkLifetimeStats
|
||||
{
|
||||
/// Reset all values to zero / unknown status
|
||||
inline void Clear() { return SteamDatagramLinkLifetimeStats_Clear( this ); }
|
||||
|
||||
//
|
||||
// Lifetime counters.
|
||||
// NOTE: Average packet loss, etc can be deduced from this.
|
||||
//
|
||||
int64 m_nPacketsSent;
|
||||
int64 m_nBytesSent;
|
||||
int64 m_nPacketsRecv; // total number of packets received, some of which might not have had a sequence number. Don't use this number to try to estimate lifetime packet loss, use m_nPacketsRecvSequenced
|
||||
int64 m_nBytesRecv;
|
||||
int64 m_nPktsRecvSequenced; // packets that we received that had a sequence number.
|
||||
int64 m_nPktsRecvDropped;
|
||||
int64 m_nPktsRecvOutOfOrder;
|
||||
int64 m_nPktsRecvDuplicate;
|
||||
int64 m_nPktsRecvSequenceNumberLurch;
|
||||
|
||||
// SNP message counters
|
||||
int64 m_nMessagesSentReliable;
|
||||
int64 m_nMessagesSentUnreliable;
|
||||
int64 m_nMessagesRecvReliable;
|
||||
int64 m_nMessagesRecvUnreliable;
|
||||
|
||||
//
|
||||
// Ping distribution
|
||||
//
|
||||
int m_nPingHistogram25; // 0..25
|
||||
int m_nPingHistogram50; // 26..50
|
||||
int m_nPingHistogram75; // 51..75
|
||||
int m_nPingHistogram100; // etc
|
||||
int m_nPingHistogram125;
|
||||
int m_nPingHistogram150;
|
||||
int m_nPingHistogram200;
|
||||
int m_nPingHistogram300;
|
||||
int m_nPingHistogramMax; // >300
|
||||
inline int PingHistogramTotalCount() const { return SteamDatagramLinkLifetimeStats_PingHistogramTotalCount( this ); }
|
||||
|
||||
// Distribution.
|
||||
// NOTE: Some of these might be -1 if we didn't have enough data to make a meaningful estimate!
|
||||
// It takes fewer samples to make an estimate of the median than the 98th percentile!
|
||||
short m_nPingNtile5th; // 5% of ping samples were <= Nms
|
||||
short m_nPingNtile50th; // 50% of ping samples were <= Nms
|
||||
short m_nPingNtile75th; // 70% of ping samples were <= Nms
|
||||
short m_nPingNtile95th; // 95% of ping samples were <= Nms
|
||||
short m_nPingNtile98th; // 98% of ping samples were <= Nms
|
||||
short m__pad1;
|
||||
|
||||
|
||||
//
|
||||
// Connection quality distribution
|
||||
//
|
||||
int m_nQualityHistogram100; // This means everything was perfect. If we delivered over 100 packets in the interval and were less than perfect, but greater than 99.5%, we will use 99% instead.
|
||||
int m_nQualityHistogram99; // 99%+
|
||||
int m_nQualityHistogram97;
|
||||
int m_nQualityHistogram95;
|
||||
int m_nQualityHistogram90;
|
||||
int m_nQualityHistogram75;
|
||||
int m_nQualityHistogram50;
|
||||
int m_nQualityHistogram1;
|
||||
int m_nQualityHistogramDead; // we received nothing during the interval; it looks like the connection dropped
|
||||
inline int QualityHistogramTotalCount() const { return SteamDatagramLinkLifetimeStats_QualityHistogramTotalCount( this ); }
|
||||
|
||||
// Distribution. Some might be -1, see above for why.
|
||||
short m_nQualityNtile2nd; // 2% of measurement intervals had quality <= N%
|
||||
short m_nQualityNtile5th; // 5% of measurement intervals had quality <= N%
|
||||
short m_nQualityNtile25th; // 25% of measurement intervals had quality <= N%
|
||||
short m_nQualityNtile50th; // 50% of measurement intervals had quality <= N%
|
||||
|
||||
// Jitter histogram
|
||||
int m_nJitterHistogramNegligible;
|
||||
int m_nJitterHistogram1;
|
||||
int m_nJitterHistogram2;
|
||||
int m_nJitterHistogram5;
|
||||
int m_nJitterHistogram10;
|
||||
int m_nJitterHistogram20;
|
||||
inline int JitterHistogramTotalCount() const { return SteamDatagramLinkLifetimeStats_JitterHistogramTotalCount( this ); }
|
||||
|
||||
//
|
||||
// Connection transmit speed histogram
|
||||
//
|
||||
int m_nTXSpeedMax; // Max speed we hit
|
||||
|
||||
int m_nTXSpeedHistogram16; // Speed at kb/s
|
||||
int m_nTXSpeedHistogram32;
|
||||
int m_nTXSpeedHistogram64;
|
||||
int m_nTXSpeedHistogram128;
|
||||
int m_nTXSpeedHistogram256;
|
||||
int m_nTXSpeedHistogram512;
|
||||
int m_nTXSpeedHistogram1024;
|
||||
int m_nTXSpeedHistogramMax;
|
||||
inline int TXSpeedHistogramTotalCount() const { return SteamDatagramLinkLifetimeStats_TXSpeedHistogramTotalCount( this ); }
|
||||
|
||||
// Distribution. Some might be -1, see above for why.
|
||||
int m_nTXSpeedNtile5th; // 5% of transmit samples were <= N kb/s
|
||||
int m_nTXSpeedNtile50th; // 50% of transmit samples were <= N kb/s
|
||||
int m_nTXSpeedNtile75th; // 75% of transmit samples were <= N kb/s
|
||||
int m_nTXSpeedNtile95th; // 95% of transmit samples were <= N kb/s
|
||||
int m_nTXSpeedNtile98th; // 98% of transmit samples were <= N kb/s
|
||||
|
||||
//
|
||||
// Connection receive speed histogram
|
||||
//
|
||||
int m_nRXSpeedMax; // Max speed we hit that formed the histogram
|
||||
|
||||
int m_nRXSpeedHistogram16; // Speed at kb/s
|
||||
int m_nRXSpeedHistogram32;
|
||||
int m_nRXSpeedHistogram64;
|
||||
int m_nRXSpeedHistogram128;
|
||||
int m_nRXSpeedHistogram256;
|
||||
int m_nRXSpeedHistogram512;
|
||||
int m_nRXSpeedHistogram1024;
|
||||
int m_nRXSpeedHistogramMax;
|
||||
inline int RXSpeedHistogramTotalCount() const { return SteamDatagramLinkLifetimeStats_RXSpeedHistogramTotalCount( this ); }
|
||||
|
||||
// Distribution. Some might be -1, see above for why.
|
||||
int m_nRXSpeedNtile5th; // 5% of transmit samples were <= N kb/s
|
||||
int m_nRXSpeedNtile50th; // 50% of transmit samples were <= N kb/s
|
||||
int m_nRXSpeedNtile75th; // 75% of transmit samples were <= N kb/s
|
||||
int m_nRXSpeedNtile95th; // 95% of transmit samples were <= N kb/s
|
||||
int m_nRXSpeedNtile98th; // 98% of transmit samples were <= N kb/s
|
||||
|
||||
};
|
||||
|
||||
/// Link stats. Pretty much everything you might possibly want to know about the connection
|
||||
struct SteamDatagramLinkStats
|
||||
{
|
||||
|
||||
/// Latest instantaneous stats, calculated locally
|
||||
SteamDatagramLinkInstantaneousStats m_latest;
|
||||
|
||||
/// Peak values for each instantaneous stat
|
||||
//SteamDatagramLinkInstantaneousStats m_peak;
|
||||
|
||||
/// Lifetime stats, calculated locally
|
||||
SteamDatagramLinkLifetimeStats m_lifetime;
|
||||
|
||||
/// Latest instantaneous stats received from remote host.
|
||||
/// (E.g. "sent" means they are reporting what they sent.)
|
||||
SteamDatagramLinkInstantaneousStats m_latestRemote;
|
||||
|
||||
/// How many seconds ago did we receive m_latestRemote?
|
||||
/// This will be <0 if the data is not valid!
|
||||
float m_flAgeLatestRemote;
|
||||
|
||||
/// Latest lifetime stats received from remote host.
|
||||
SteamDatagramLinkLifetimeStats m_lifetimeRemote;
|
||||
|
||||
/// How many seconds ago did we receive the lifetime stats?
|
||||
/// This will be <0 if the data is not valid!
|
||||
float m_flAgeLifetimeRemote;
|
||||
|
||||
/// Reset everything to unknown/initial state.
|
||||
inline void Clear() { SteamDatagramLinkStats_Clear( this ); }
|
||||
};
|
||||
|
||||
/// Status of a particular network resource
|
||||
enum ESteamDatagramAvailability
|
||||
{
|
||||
k_ESteamDatagramAvailability_CannotTry = -3, // A dependent resource is missing, so this service is unavailable. (E.g. we cannot talk to routers because Internet is down or we don't have the network config.)
|
||||
k_ESteamDatagramAvailability_Failed = -2, // We have tried for enough time that we would expect to have been successful by now. We have never been successful
|
||||
k_ESteamDatagramAvailability_Previously = -1, // We tried and were successful at one time, but now it looks like we have a problem
|
||||
k_ESteamDatagramAvailability_Unknown = 0, // Unknown, or not applicable in this context
|
||||
k_ESteamDatagramAvailability_NeverTried = 1, // We don't know because we haven't ever checked
|
||||
k_ESteamDatagramAvailability_Attempting = 2, // We're trying now, but are not yet successful. This is not an error, but it's not success, either.
|
||||
k_ESteamDatagramAvailability_Current = 3, // Resource is online.
|
||||
};
|
||||
|
||||
/// Describe detailed state of current connection
|
||||
struct SteamNetworkingDetailedConnectionStatus
|
||||
{
|
||||
/// Basic connection info
|
||||
SteamNetConnectionInfo_t m_info;
|
||||
|
||||
/// Do we have a valid network configuration? We cannot do anything without this.
|
||||
ESteamDatagramAvailability m_eAvailNetworkConfig;
|
||||
|
||||
// /// Does it look like we have a connection to the Internet at all?
|
||||
// EAvailability m_eAvailInternet;
|
||||
|
||||
/// Successful communication with a box on the routing network.
|
||||
/// This will be marked as failed if there is a general internet
|
||||
/// connection.
|
||||
ESteamDatagramAvailability m_eAvailAnyRouterCommunication;
|
||||
|
||||
/// End-to-end communication with the remote host.
|
||||
//ESteamDatagramAvailability m_eAvailEndToEnd;
|
||||
|
||||
/// Stats for end-to-end link to the gameserver
|
||||
SteamDatagramLinkStats m_statsEndToEnd;
|
||||
|
||||
/// Currently selected front router, if any.
|
||||
/// Note that PoP ID can be found in the SteamNetConnectionInfo_t
|
||||
char m_szPrimaryRouterName[64];
|
||||
uint32 m_unPrimaryRouterIP;
|
||||
uint16 m_unPrimaryRouterPort;
|
||||
|
||||
/// Stats for "front" link to current router
|
||||
SteamDatagramLinkStats m_statsPrimaryRouter;
|
||||
|
||||
/// Back ping time as reported by primary.
|
||||
/// (The front ping is in m_statsPrimaryRouter,
|
||||
/// and usually the front ping plus the back ping should
|
||||
/// approximately equal the end-to-end ping)
|
||||
int m_nPrimaryRouterBackPing;
|
||||
|
||||
/// Currently selected back router, if any
|
||||
SteamNetworkingPOPID m_idBackupRouterCluster;
|
||||
char m_szBackupRouterName[64];
|
||||
uint32 m_unBackupRouterIP;
|
||||
uint16 m_unBackupRouterPort;
|
||||
|
||||
/// Ping times to backup router, if any
|
||||
int m_nBackupRouterFrontPing, m_nBackupRouterBackPing;
|
||||
|
||||
/// Clear everything to an unknown state
|
||||
inline void Clear() { SteamNetworkingDetailedConnectionStatus_Clear( this ); }
|
||||
|
||||
/// Print into a buffer.
|
||||
/// 0 = OK
|
||||
/// >1 = buffer was null or too small (in which case truncation happened).
|
||||
/// Pass a buffer of at least N bytes.
|
||||
inline int Print( char *pszBuf, int cbBuf ) const { return SteamNetworkingDetailedConnectionStatus_Print( this, pszBuf, cbBuf ); }
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // STEAMDATAGRAM_STATS_H
|
||||
@@ -0,0 +1,60 @@
|
||||
//====== Copyright Valve Corporation, All rights reserved. ====================
|
||||
//
|
||||
// Backend functions to generate authorization tickets for steam datagram
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef STEAMDATAGRAM_TICKETGEN_H
|
||||
#define STEAMDATAGRAM_TICKETGEN_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// Import some common stuff that is useful by both the client
|
||||
// and the backend ticket-generating authority.
|
||||
#include "steamdatagram_tickets.h"
|
||||
|
||||
struct SteamDatagramSignedTicketBlob
|
||||
{
|
||||
int m_sz;
|
||||
uint8 m_blob[ k_cbSteamDatagramMaxSerializedTicket ];
|
||||
};
|
||||
|
||||
/// Initialize ticket generation with an Ed25519 private key.
|
||||
/// See: https://ed25519.cr.yp.to/
|
||||
///
|
||||
/// Input buffer will be securely wiped.
|
||||
///
|
||||
/// You can generate an Ed25519 key using OpenSSH:
|
||||
///
|
||||
/// ssh-keygen -t ed25519
|
||||
///
|
||||
/// The private key should be a PEM-like block of text
|
||||
/// ("-----BEGIN OPENSSH PRIVATE KEY-----").
|
||||
/// Private keys encrypted with a password are not supported.
|
||||
///
|
||||
/// In order for signatures using this key to be accepted by the relay network,
|
||||
/// you need to send your public key to Valve. This key should be on a single line
|
||||
/// of text that begins with "ssh-ed25519". (The format used in the .ssh/authorized_keys
|
||||
/// file.)
|
||||
STEAMDATAGRAM_TICKET_INTERFACE bool SteamDatagram_InitTicketGenerator_Ed25519( void *pvPrivateKey, size_t cbPrivateKey );
|
||||
|
||||
/// Serialize the specified auth ticket and attach a signature.
|
||||
/// Returns false if you did something stupid like forgot to load a key.
|
||||
/// Will also fail if your ticket is too big. (Probably because you
|
||||
/// added too many extra fields.)
|
||||
STEAMDATAGRAM_TICKET_INTERFACE bool SteamDatagram_SerializeAndSignTicket( const SteamDatagramRelayAuthTicket &ticket, SteamDatagramSignedTicketBlob &outBlob );
|
||||
|
||||
//
|
||||
// Legacy / deprecated
|
||||
//
|
||||
|
||||
/// Initialize ticket generation with an RSA private key. You can either
|
||||
/// pass a PEM block ("-----BEGIN PRIVATE KEY-----"), or binary PKCS#8 DER.
|
||||
/// Input buffer will be securely wiped.
|
||||
STEAMDATAGRAM_TICKET_INTERFACE bool SteamDatagram_InitTicketGenerator_RSA_deprecated( void *pvPrivateKey, size_t cbPrivateKey );
|
||||
|
||||
/// Generate a signature for legacy support
|
||||
STEAMDATAGRAM_TICKET_INTERFACE bool SteamDatagram_SerializeAndSignTicket_deprecated( const SteamDatagramRelayAuthTicket &ticket, SteamDatagramSignedTicketBlob &outBlob );
|
||||
|
||||
#endif // STEAMDATAGRAM_TICKETGEN_H
|
||||
@@ -0,0 +1,151 @@
|
||||
//====== Copyright Valve Corporation, All rights reserved. ====================
|
||||
//
|
||||
// Types and utilities for handling steam datagram tickets. These are
|
||||
// useful for both the client and the backend ticket generating authority.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef STEAMDATAGRAM_TICKETS_H
|
||||
#define STEAMDATAGRAM_TICKETS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef assert
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "steamnetworkingtypes.h"
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(8)
|
||||
|
||||
#if defined( STEAMDATAGRAM_TICKETGEN_FOREXPORT ) || defined( STEAMDATAGRAMLIB_FOREXPORT )
|
||||
#define STEAMDATAGRAM_TICKET_INTERFACE DLL_EXPORT
|
||||
#elif defined( STEAMDATAGRAMLIB_STATIC_LINK )
|
||||
#define STEAMDATAGRAM_TICKET_INTERFACE extern "C"
|
||||
#else
|
||||
#define STEAMDATAGRAM_TICKET_INTERFACE DLL_IMPORT
|
||||
#endif
|
||||
|
||||
/// Max length of serialized auth ticket. This is important so that we
|
||||
/// can ensure that we always fit into a single UDP datagram (along with
|
||||
/// other certs and signatures) and kep the implementation simple.
|
||||
const size_t k_cbSteamDatagramMaxSerializedTicket = 512;
|
||||
|
||||
/// Network-routable identifier for a service. In general, clients should
|
||||
/// treat this as an opaque structure. The only thing that is important
|
||||
/// is that this contains everything the system needs to route packets to a
|
||||
/// service.
|
||||
struct SteamDatagramServiceNetID
|
||||
{
|
||||
// Just use the private LAN address to identify the service
|
||||
uint32 m_unIP;
|
||||
uint16 m_unPort;
|
||||
uint16 m__nPad1;
|
||||
|
||||
void Clear() { *(uint64 *)this = 0; }
|
||||
|
||||
uint64 ConvertToUint64() const { return ( uint64(m_unIP) << 16U ) | uint64(m_unPort); }
|
||||
void SetFromUint64( uint64 x )
|
||||
{
|
||||
m_unIP = uint32(x >> 16U);
|
||||
m_unPort = uint16(x);
|
||||
m__nPad1 = 0;
|
||||
}
|
||||
|
||||
inline bool operator==( const SteamDatagramServiceNetID &x ) const { return m_unIP == x.m_unIP && m_unPort == x.m_unPort; }
|
||||
};
|
||||
|
||||
/// Ticket used to gain access to the relay network.
|
||||
struct SteamDatagramRelayAuthTicket
|
||||
{
|
||||
SteamDatagramRelayAuthTicket() { Clear(); }
|
||||
|
||||
/// Reset all fields
|
||||
void Clear() { memset( this, 0, sizeof(*this) ); }
|
||||
|
||||
/// Steam ID of the gameserver we want to talk to
|
||||
CSteamID m_steamIDGameserver;
|
||||
|
||||
/// Steam ID of the person who was authorized.
|
||||
CSteamID m_steamIDAuthorizedSender;
|
||||
|
||||
/// SteamID is authorized to send from a particular public IP. If this
|
||||
/// is 0, then the sender is not restricted to a particular IP.
|
||||
uint32 m_unPublicIP;
|
||||
|
||||
/// Time when the ticket expires.
|
||||
RTime32 m_rtimeTicketExpiry;
|
||||
|
||||
/// Routing information
|
||||
SteamDatagramServiceNetID m_routing;
|
||||
|
||||
/// App ID this is for
|
||||
uint32 m_nAppID;
|
||||
|
||||
struct ExtraField
|
||||
{
|
||||
enum EType
|
||||
{
|
||||
k_EType_String,
|
||||
k_EType_Int, // For most small integral values. Uses google protobuf sint64, so it's small on the wire. WARNING: In some places this value may be transmitted in JSON, in which case precision may be lost in backend analytics. Don't use this afor an "identifier", use it for a scalar quantity.
|
||||
k_EType_Fixed64, // 64 arbitrary bits. This value is treated as an "identifier". In places where JSON format is used, it will be serialized as a string. No aggregation / analytics can be performed on this value.
|
||||
};
|
||||
int /* EType */ m_eType;
|
||||
char m_szName[28];
|
||||
|
||||
union {
|
||||
char m_szStringValue[128];
|
||||
int64 m_nIntValue;
|
||||
uint64 m_nFixed64Value;
|
||||
};
|
||||
};
|
||||
enum { k_nMaxExtraFields = 16 };
|
||||
int m_nExtraFields;
|
||||
ExtraField m_vecExtraFields[ k_nMaxExtraFields ];
|
||||
|
||||
/// Helper to add an extra field in a single call
|
||||
void AddExtraField_Int( const char *pszName, int64 val )
|
||||
{
|
||||
ExtraField *p = AddExtraField( pszName, ExtraField::k_EType_Int );
|
||||
if ( p )
|
||||
p->m_nIntValue = val;
|
||||
}
|
||||
void AddExtraField_Fixed64( const char *pszName, uint64 val )
|
||||
{
|
||||
ExtraField *p = AddExtraField( pszName, ExtraField::k_EType_Fixed64 );
|
||||
if ( p )
|
||||
p->m_nFixed64Value = val;
|
||||
}
|
||||
void AddExtraField_String( const char *pszName, const char *val )
|
||||
{
|
||||
ExtraField *p = AddExtraField( pszName, ExtraField::k_EType_Fixed64 );
|
||||
if ( p )
|
||||
V_strcpy_safe( p->m_szStringValue, val );
|
||||
}
|
||||
|
||||
private:
|
||||
ExtraField *AddExtraField( const char *pszName, ExtraField::EType eType )
|
||||
{
|
||||
if ( m_nExtraFields >= k_nMaxExtraFields )
|
||||
{
|
||||
assert( false );
|
||||
return nullptr;
|
||||
}
|
||||
ExtraField *p = &m_vecExtraFields[ m_nExtraFields++ ];
|
||||
p->m_eType = eType;
|
||||
V_strcpy_safe( p->m_szName, pszName );
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
/// Unpack signed ticket. Does not check the signature!
|
||||
/// Note that it's assumed that you won't need to link with both the client
|
||||
/// lib and the ticket generating lib in any one project, since this symbol
|
||||
/// is exposed in both.
|
||||
STEAMDATAGRAM_TICKET_INTERFACE bool SteamDatagramRelayAuthTicket_Parse( const void *pvTicket, int cbTicket, SteamDatagramRelayAuthTicket *pOutTicket, SteamDatagramErrMsg &errMsg );
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // STEAMDATAGRAM_TICKETS_H
|
||||
@@ -0,0 +1,641 @@
|
||||
//====== Copyright Valve Corporation, All rights reserved. ====================
|
||||
//
|
||||
// Purpose: misc networking utilities
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef STEAMNETWORKINGTYPES
|
||||
#define STEAMNETWORKINGTYPES
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "steam/steamtypes.h"
|
||||
#include "steam/steamclientpublic.h"
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#if defined( STEAMDATAGRAMLIB_STATIC_LINK )
|
||||
#define STEAMDATAGRAMLIB_INTERFACE extern
|
||||
#elif defined( STEAMDATAGRAMLIB_FOREXPORT )
|
||||
#define STEAMDATAGRAMLIB_INTERFACE DLL_EXPORT
|
||||
#else
|
||||
#define STEAMDATAGRAMLIB_INTERFACE DLL_IMPORT
|
||||
#endif
|
||||
|
||||
#pragma pack( push, 8 )
|
||||
|
||||
struct SteamNetworkPingLocation_t;
|
||||
class ISteamNetworkingMessage;
|
||||
struct SteamDatagramLinkStats;
|
||||
struct SteamDatagramLinkLifetimeStats;
|
||||
struct SteamDatagramLinkInstantaneousStats;
|
||||
struct SteamNetworkingDetailedConnectionStatus;
|
||||
|
||||
/// Handle used to identify a connection to a remote host.
|
||||
typedef uint32 HSteamNetConnection;
|
||||
const HSteamNetConnection k_HSteamNetConnection_Invalid = 0;
|
||||
|
||||
/// Handle used to identify a "listen socket".
|
||||
typedef uint32 HSteamListenSocket;
|
||||
const HSteamListenSocket k_HSteamListenSocket_Invalid = 0;
|
||||
|
||||
/// Configuration values for Steam networking.
|
||||
///
|
||||
/// Most of these are for controlling extend logging or features
|
||||
/// of various subsystems
|
||||
enum ESteamNetworkingConfigurationValue
|
||||
{
|
||||
// Set to true (non-zero) to use Steam Network Protocol for message
|
||||
// delivery.
|
||||
// SNP is a protocol for sending a mix of reliable and unreliable message
|
||||
// payloads and handles retransmission of reliable messages and also
|
||||
// manages transfer rate congestion control. Defaults to 1 (on).
|
||||
k_ESteamNetworkingConfigurationValue_SNP = 0,
|
||||
|
||||
// 0-100 Randomly discard N pct of unreliable messages instead of sending
|
||||
// Defaults to 0 (no loss).
|
||||
k_ESteamNetworkingConfigurationValue_FakeMessageLoss_Send = 1,
|
||||
|
||||
// 0-100 Randomly discard N pct of unreliable messages upon receive
|
||||
// Defaults to 0 (no loss).
|
||||
k_ESteamNetworkingConfigurationValue_FakeMessageLoss_Recv = 2,
|
||||
|
||||
// 0-100 Randomly discard N pct of packets instead of sending
|
||||
k_ESteamNetworkingConfigurationValue_FakePacketLoss_Send = 3,
|
||||
|
||||
// 0-100 Randomly discard N pct of packets received
|
||||
k_ESteamNetworkingConfigurationValue_FakePacketLoss_Recv = 4,
|
||||
|
||||
// Set to true (non-zero) to open up a seperate debug window showing SNP
|
||||
// state for all current connections. Only works on Windows.
|
||||
// Defaults to 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_DebugWindow = 5,
|
||||
|
||||
// Upper limit of buffered pending bytes to be sent, if this is reached
|
||||
// SendMessage will return k_EResultPending
|
||||
// Default is 512k (524288 bytes)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_SendBufferSize = 6,
|
||||
|
||||
// Maximum send rate clamp, 0 is no limit
|
||||
// This value will control the maximum allowed sending rate that congestion
|
||||
// is allowed to reach. Default is 0 (no-limit)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_MaxRate = 7,
|
||||
|
||||
// Minimum send rate clamp, 0 is no limit
|
||||
// This value will control the minimum allowed sending rate that congestion
|
||||
// is allowed to reach. Default is 0 (no-limit)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_MinRate = 8,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP RTT
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_RTT = 9,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP Packet
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_Packet = 10,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP Segments
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_Segments = 11,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP Feedback
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_Feedback = 12,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP Relible
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_Reliable = 13,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP Messages
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_Message = 14,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP Loss
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_Loss = 15,
|
||||
|
||||
// Set to true (non-zero) to enable logging of SNP Throughput
|
||||
// Default is 0 (off)
|
||||
k_ESteamNetworkingConfigurationValue_SNP_Log_X = 16,
|
||||
|
||||
// If the first N pings to a port all fail, mark that port as unavailable for
|
||||
// a while, and try a different one. Some ISPs and routers may drop the first
|
||||
// packet, so setting this to 1 may greatly disrupt communications.
|
||||
k_ESteamNetworkingConfigurationValue_ClientConsecutitivePingTimeoutsFailInitial = 17,
|
||||
|
||||
// If N consecutive pings to a port fail, after having received successful
|
||||
// communication, mark that port as unavailable for a while, and try a
|
||||
// different one.
|
||||
k_ESteamNetworkingConfigurationValue_ClientConsecutitivePingTimeoutsFail = 18,
|
||||
|
||||
/// Minimum number of lifetime pings we need to send, before we think our estimate
|
||||
/// is solid. The first ping to each cluster is very often delayed because of NAT,
|
||||
/// routers not having the best route, etc. Until we've sent a sufficient number
|
||||
/// of pings, our estimate is often inaccurate. Keep pinging until we get this
|
||||
/// many pings.
|
||||
k_ESteamNetworkingConfigurationValue_ClientMinPingsBeforePingAccurate = 19,
|
||||
|
||||
// Set all steam datagram traffic to originate from the same local port.
|
||||
// By default, we open up a new UDP socket (on a different local port)
|
||||
// for each relay. This is not optimal, but it works around some
|
||||
// routers that don't implement NAT properly. If you have intermittent
|
||||
// problems talking to relays that might be NAT related, try toggling
|
||||
// this flag
|
||||
k_ESteamNetworkingConfigurationValue_ClientSingleSocket = 20,
|
||||
|
||||
// Globally delay all outbound packets by N ms before sending
|
||||
k_ESteamNetworkingConfigurationValue_FakePacketLag_Send = 21,
|
||||
|
||||
// Globally delay all received packets by N ms before processing
|
||||
k_ESteamNetworkingConfigurationValue_FakePacketLag_Recv = 22,
|
||||
|
||||
// Don't automatically fail IP connections that don't have strong auth.
|
||||
// On clients, this means we will attempt the connection even if we don't
|
||||
// know our SteamID or can't get a cert. On the server, it means that we won't
|
||||
// automatically reject a connection due to a failure to authenticate.
|
||||
// (You can examine the incoming connection and decide whether to accept it.)
|
||||
k_ESteamNetworkingConfigurationValue_IP_Allow_Without_Auth = 23,
|
||||
|
||||
// Number of k_ESteamNetworkingConfigurationValue defines
|
||||
k_ESteamNetworkingConfigurationValue_Count,
|
||||
};
|
||||
|
||||
/// Configuration strings for Steam networking.
|
||||
///
|
||||
/// Most of these are for controlling extend logging or features
|
||||
/// of various subsystems
|
||||
enum ESteamNetworkingConfigurationString
|
||||
{
|
||||
// Code of relay cluster to use. If not empty, we will only use relays in that cluster. E.g. 'iad'
|
||||
k_ESteamNetworkingConfigurationString_ClientForceRelayCluster = 0,
|
||||
|
||||
// For debugging, generate our own (unsigned) ticket, using the specified
|
||||
// gameserver address. Router must be configured to accept unsigned tickets.
|
||||
k_ESteamNetworkingConfigurationString_ClientDebugTicketAddress = 1,
|
||||
|
||||
// For debugging. Override list of relays from the config with this set
|
||||
// (maybe just one). Comma-separated list.
|
||||
k_ESteamNetworkingConfigurationString_ClientForceProxyAddr = 2,
|
||||
|
||||
// Number of k_ESteamNetworkingConfigurationString defines
|
||||
k_ESteamNetworkingConfigurationString_Count = k_ESteamNetworkingConfigurationString_ClientForceProxyAddr + 1,
|
||||
};
|
||||
|
||||
/// Basically a duplicate of EP2PSend.
|
||||
enum ESteamNetworkingSendType
|
||||
{
|
||||
// Send an unreliable message. Can be lost.
|
||||
// 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.
|
||||
k_ESteamNetworkingSendType_Unreliable = 0,
|
||||
|
||||
// Reliable message send. Can send up to 512kb of data 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.
|
||||
k_ESteamNetworkingSendType_Reliable = 1,
|
||||
};
|
||||
|
||||
/// High level connection status
|
||||
enum ESteamNetworkingConnectionState
|
||||
{
|
||||
|
||||
/// Dummy value used to indicate an error condition in the API.
|
||||
/// Specified connection doesn't exist or has already been closed.
|
||||
k_ESteamNetworkingConnectionState_None = 0,
|
||||
|
||||
/// - For connections on the "client" side (initiated locally):
|
||||
/// We're in the process of trying to establish a connection.
|
||||
/// Depending on the socket type, we might not even know who they are.
|
||||
/// Note that it is not possible to tell if we are waiting on the
|
||||
/// network to complete handshake packets, or for the application layer
|
||||
/// to accept the connection.
|
||||
///
|
||||
/// - For connections on the "server" side (accepted through listen socket):
|
||||
/// We have completed a series of basic handshake packets, and the connection
|
||||
/// is ready to be accepted using AcceptConnection.
|
||||
///
|
||||
/// In either case, any unreliable packets sent now are almost certain
|
||||
/// to be dropped. Attempts to receive packets are guaranteed to fail.
|
||||
/// You may send messages if the send mode allows for them to be queued.
|
||||
/// but if you close the connection before the connection is actually
|
||||
/// established, any queued messages will be discarded immediately.
|
||||
/// (We will not attempt to flush the queue and confirm delivery to the
|
||||
/// remote host, which ordinarily happens when a connection is closed.)
|
||||
k_ESteamNetworkingConnectionState_Connecting = 1,
|
||||
|
||||
/// We've received communications from our peer (and we know
|
||||
/// who they are) and are all good. If you close the connection now,
|
||||
/// we will make our best effort to flush out any reliable sent data that
|
||||
/// has not been acknowledged by the peer. (But note that this happens
|
||||
/// from within the application process, so unlike a TCP connection, you are
|
||||
/// not totally handing it off to the operating system to deal with it.)
|
||||
k_ESteamNetworkingConnectionState_Connected = 2,
|
||||
|
||||
/// Connection has been closed by our peer, but not closed locally.
|
||||
/// The connection still exists from an API perspective. You must close the
|
||||
/// handle to free up resources. If there are any messages in the inbound queue,
|
||||
/// you may retrieve them. Otherwise, nothing may be done with the connection
|
||||
/// except to close it.
|
||||
///
|
||||
/// This stats is similar to CLOSE_WAIT in the TCP state machine.
|
||||
k_ESteamNetworkingConnectionState_ClosedByPeer = 3,
|
||||
|
||||
/// A disruption in the connection has been detected locally. (E.g. timeout,
|
||||
/// local internet connection disrupted, etc.)
|
||||
///
|
||||
/// The connection still exists from an API perspective. You must close the
|
||||
/// handle to free up resources.
|
||||
///
|
||||
/// Attempts to send further messages will fail. Any remaining received messages
|
||||
/// in the queue are available.
|
||||
k_ESteamNetworkingConnectionState_ProblemDetectedLocally = 4,
|
||||
|
||||
//
|
||||
// The following values are used internally and will not be returned by any API.
|
||||
// We document them here to provide a little insight into the state machine that is used
|
||||
// under the hood.
|
||||
//
|
||||
|
||||
/// We've disconnected on our side, and from an API perspective the connection is closed.
|
||||
/// No more data may be sent or received. All reliable data has been flushed, or else
|
||||
/// we've given up and discarded it. We do not yet know for sure that the client knows
|
||||
/// the connection has been closed, however, so we're just hanging around so that if we do
|
||||
/// get a packet from them, we can send them the appropriate packets so that they can
|
||||
/// know why the connection was closed (and not have to rely on a timeout, which makes
|
||||
/// it appear as if something is wrong).
|
||||
///
|
||||
/// Note that, unlike TCP connections, Steam networking sessions have additional
|
||||
/// session identifiers that make the TIME_WAIT state unnecessary. (If another connection
|
||||
/// is established on the same port, and we get packets from an old session, we are able to
|
||||
/// identify this and either ignore those packets, or inform the remote host that the old
|
||||
/// session has been closed, if appropriate).
|
||||
k_ESteamNetworkingConnectionState_FinWait = -1,
|
||||
|
||||
/// We've disconnected on our side, and from an API perspective the connection is closed.
|
||||
/// No more data may be sent or received. From a network perspective, however, on the wire,
|
||||
/// we have not yet given any indication to the peer that the connection is closed.
|
||||
/// We are in the process of flushing out the last bit of reliable data. Once that is done,
|
||||
/// we will inform the peer that the connection has been closed, and transition to the
|
||||
/// FinWait state.
|
||||
///
|
||||
/// Note that no indication is given to the remote host that we have closed the connection,
|
||||
/// until the data has been flushed. If the remote host attempts to send us data, we will
|
||||
/// do whatever is necessary to keep the connection alive until it can be closed properly.
|
||||
/// But in fact the data will be discarded, since there is no way for the application to
|
||||
/// read it back. Typically this is not a problem, as application protocols that utilize
|
||||
/// the lingering functionality are designed for the remote host to wait for the response
|
||||
/// before sending any more data.
|
||||
k_ESteamNetworkingConnectionState_Linger = -2,
|
||||
|
||||
/// Connection is completely inactive and ready to be destroyed
|
||||
k_ESteamNetworkingConnectionState_Dead = -3,
|
||||
};
|
||||
|
||||
/// Identifier used for a network location point of presence.
|
||||
/// Typically you won't need to directly manipulate these.
|
||||
typedef uint32 SteamNetworkingPOPID;
|
||||
|
||||
/// Convert 3- or 4-character ID to 32-bit int.
|
||||
inline SteamNetworkingPOPID CalculateSteamNetworkingPOPIDFromString( const char *pszCode )
|
||||
{
|
||||
// OK we made a bad decision when we decided how to pack 3-character codes into a uint32. We'd like to support
|
||||
// 4-character codes, but we don't want to break compatibility. The migration path has some subtleties that make
|
||||
// this nontrivial, and there are already some IDs stored in SQL. Ug, so the 4 character code "abcd" will
|
||||
// be encoded with the digits like "0xddaabbcc"
|
||||
return
|
||||
( uint32(pszCode[3]) << 24U )
|
||||
| ( uint32(pszCode[0]) << 16U )
|
||||
| ( uint32(pszCode[1]) << 8U )
|
||||
| uint32(pszCode[2]);
|
||||
}
|
||||
|
||||
/// Unpack integer to string representation, including terminating '\0'
|
||||
template <int N>
|
||||
inline void GetSteamNetworkingLocationPOPStringFromID( SteamNetworkingPOPID id, char (&szCode)[N] )
|
||||
{
|
||||
COMPILE_TIME_ASSERT( N >= 5 );
|
||||
szCode[0] = ( id >> 16U );
|
||||
szCode[1] = ( id >> 8U );
|
||||
szCode[2] = ( id );
|
||||
szCode[3] = ( id >> 24U ); // See comment above about deep regret and sadness
|
||||
szCode[4] = 0;
|
||||
}
|
||||
|
||||
/// A local timestamp. You can subtract two timestamps to get the number of elapsed
|
||||
/// microseconds. This is guaranteed to increase over time during the lifetime
|
||||
/// of a process, but not globally across runs. You don't need to worry about
|
||||
/// the value wrapping around. Note that the underlying clock might not actually have
|
||||
/// microsecond *resolution*.
|
||||
typedef int64 SteamNetworkingMicroseconds;
|
||||
|
||||
/// A sequence number. Used to indentify packets and messages
|
||||
/// and other segments. Typically this is 64 bit internally and
|
||||
/// has the last 16 bits networked
|
||||
typedef int64 SteamNetworkingSequenceNumber;
|
||||
|
||||
// maximum amount of pending buffered messages allows
|
||||
const int k_cbMaxSteamDatagramMessageSize = 512 * 1024;
|
||||
|
||||
/// A message that has been received.
|
||||
class ISteamNetworkingMessage
|
||||
{
|
||||
public:
|
||||
|
||||
/// You MUST call this when you're done with the object,
|
||||
/// to free up memory, etc.
|
||||
virtual void Release() = 0;
|
||||
|
||||
/// Get size of the payload.
|
||||
inline uint32 GetSize() const { return m_cbSize; }
|
||||
|
||||
/// Get message payload
|
||||
inline const void *GetData() const { return m_pData; }
|
||||
|
||||
/// Return SteamID that sent this to us.
|
||||
inline CSteamID GetSenderSteamID() const { return m_steamIDSender; }
|
||||
|
||||
/// Return the channel number the message was received on.
|
||||
/// (Not used for messages received on "connections"
|
||||
inline int GetChannel() const { return m_nChannel; }
|
||||
|
||||
/// The socket this came from. (Not used when using the P2P calls)
|
||||
inline HSteamNetConnection GetConnection() const { return m_conn; }
|
||||
|
||||
/// Get 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.
|
||||
inline int64 GetConnectionUserData() const { return m_nConnUserData; }
|
||||
|
||||
/// Get the time that it was received
|
||||
inline SteamNetworkingMicroseconds GetTimeReceived() const { return m_usecTimeReceived; }
|
||||
|
||||
protected:
|
||||
CSteamID m_steamIDSender;
|
||||
void *m_pData;
|
||||
uint32 m_cbSize;
|
||||
int m_nChannel;
|
||||
HSteamNetConnection m_conn;
|
||||
int64 m_nConnUserData;
|
||||
SteamNetworkingMicroseconds m_usecTimeReceived;
|
||||
|
||||
inline ~ISteamNetworkingMessage() {}; // Destructor hidden - use Release()! But make it inline and empty, in case you want to derive your own type that satisfies this interface for use in your code.
|
||||
};
|
||||
|
||||
/// Object that describes a "location" on the Internet with sufficient
|
||||
/// detail that we can reasonably estimate an upper bound on the ping between
|
||||
/// the two hosts, even if a direct route between the hosts is not possible,
|
||||
/// and the connection must be routed through the Steam Datagram Relay network.
|
||||
/// This does not contain any information that identifies the host. Indeed,
|
||||
/// if two hosts are in the same building or otherwise have nearly identical
|
||||
/// networking characteristics, then it's valid to use the same location
|
||||
/// object for both of them.
|
||||
///
|
||||
/// NOTE: This object should only be used in memory. If you need to persist
|
||||
/// it or send it over the wire, convert it to a string representation using
|
||||
/// the methods in ISteamNetworkingUtils()
|
||||
struct SteamNetworkPingLocation_t
|
||||
{
|
||||
uint8 m_data[ 64 ];
|
||||
};
|
||||
|
||||
/// Special values that are returned by some functions that return a ping.
|
||||
const int k_nSteamNetworkingPing_Failed = -1;
|
||||
const int k_nSteamNetworkingPing_Unknown = -2;
|
||||
|
||||
/// Enumerate various causes of connection termination. These are designed
|
||||
/// to work sort of like HTTP error codes, in that the numeric range gives you
|
||||
/// a ballpark as to where the problem is.
|
||||
enum ESteamNetConnectionEnd
|
||||
{
|
||||
// Invalid/sentinel value
|
||||
k_ESteamNetConnectionEnd_Invalid = 0,
|
||||
|
||||
//
|
||||
// Application codes. You can use these codes if you want to
|
||||
// plumb through application-specific error codes. If you don't need this
|
||||
// facility, feel free to always use 0, which is a generic
|
||||
// application-initiated closure.
|
||||
//
|
||||
// The distinction between "normal" and "exceptional" termination is
|
||||
// one you may use if you find useful, but it's not necessary for you
|
||||
// to do so. The only place where we distinguish between normal and
|
||||
// exceptional is in connection analytics. If a significant
|
||||
// proportion of connections terminates in an exceptional manner,
|
||||
// this can trigger an alert.
|
||||
//
|
||||
|
||||
// 1xxx: Application ended the connection in a "usual" manner.
|
||||
// E.g.: user intentionally disconnected from the server,
|
||||
// gameplay ended normally, etc
|
||||
k_ESteamNetConnectionEnd_App_Min = 1000,
|
||||
k_ESteamNetConnectionEnd_App_Generic = k_ESteamNetConnectionEnd_App_Min,
|
||||
// Use codes in this range for "normal" disconnection
|
||||
k_ESteamNetConnectionEnd_App_Max = 1999,
|
||||
|
||||
// 2xxx: Application ended the connection in some sort of exceptional
|
||||
// or unusual manner that might indicate a bug or configuration
|
||||
// issue.
|
||||
//
|
||||
k_ESteamNetConnectionEnd_AppException_Min = 2000,
|
||||
k_ESteamNetConnectionEnd_AppException_Generic = k_ESteamNetConnectionEnd_AppException_Min,
|
||||
// Use codes in this range for "unusual" disconnection
|
||||
k_ESteamNetConnectionEnd_AppException_Max = 2999,
|
||||
|
||||
//
|
||||
// System codes:
|
||||
//
|
||||
|
||||
// 3xxx: Connection failed or ended because of problem with the
|
||||
// local host or their connection to the Internet.
|
||||
k_ESteamNetConnectionEnd_Local_Min = 3000,
|
||||
|
||||
// You cannot do what you want to do because you're running in offline mode.
|
||||
k_ESteamNetConnectionEnd_Local_OfflineMode = 3001,
|
||||
|
||||
// We're having trouble contacting many (perhaps all) relays.
|
||||
// Since it's unlikely that they all went offline at once, the best
|
||||
// explanation is that we have a problem on our end. Note that we don't
|
||||
// bother distinguishing between "many" and "all", because in practice,
|
||||
// it takes time to detect a connection problem, and by the time
|
||||
// the connection has timed out, we might not have been able to
|
||||
// actively probe all of the relay clusters, even if we were able to
|
||||
// contact them at one time. So this code just means that:
|
||||
//
|
||||
// * We don't have any recent successful communication with any relay.
|
||||
// * We have evidence of recent failures to communicate with multiple relays.
|
||||
k_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002,
|
||||
|
||||
// A hosted server is having trouble talking to the relay
|
||||
// that the client was using, so the problem is most likely
|
||||
// on our end
|
||||
k_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003,
|
||||
|
||||
// We're not able to get the network config. This is
|
||||
// *almost* always a local issue, since the network config
|
||||
// comes from the CDN, which is pretty darn reliable.
|
||||
k_ESteamNetConnectionEnd_Local_NetworkConfig = 3004,
|
||||
|
||||
k_ESteamNetConnectionEnd_Local_Max = 3999,
|
||||
|
||||
// 4xxx: Connection failed or ended, and it appears that the
|
||||
// cause does NOT have to do with the local host or their
|
||||
// connection to the Internet. It could be caused by the
|
||||
// remote host, or it could be somewhere in between.
|
||||
k_ESteamNetConnectionEnd_Remote_Min = 4000,
|
||||
|
||||
// The connection was lost, and as far as we can tell our connection
|
||||
// to relevant services (relays) has not been disrupted. This doesn't
|
||||
// mean that the problem is "their fault", it just means that it doesn't
|
||||
// appear that we are having network issues on our end.
|
||||
k_ESteamNetConnectionEnd_Remote_Timeout = 4001,
|
||||
|
||||
// Something was invalid with the cert or crypt handshake
|
||||
// info you gave me, I don't understand or like your key types,
|
||||
// etc.
|
||||
k_ESteamNetConnectionEnd_Remote_BadCrypt = 4002,
|
||||
|
||||
// You presented me with a cert that was technically
|
||||
// valid. But the CA key was missing (and I don't accept
|
||||
// unsigned certs), or the key isn't one that I trust.
|
||||
k_ESteamNetConnectionEnd_Remote_CertNotTrusted = 4003,
|
||||
|
||||
k_ESteamNetConnectionEnd_Remote_Max = 4999,
|
||||
|
||||
// 5xxx: Connection failed for some other reason.
|
||||
k_ESteamNetConnectionEnd_Misc_Min = 5000,
|
||||
|
||||
// A failure that isn't necessarily the result of a software bug,
|
||||
// but that should happen rarely enough that it isn't worth specifically
|
||||
// writing UI or making a localized message for.
|
||||
// The debug string should contain further details.
|
||||
k_ESteamNetConnectionEnd_Misc_Generic = 5001,
|
||||
|
||||
// Generic failure that is most likely a software bug.
|
||||
k_ESteamNetConnectionEnd_Misc_InternalError = 5002,
|
||||
|
||||
// The connection to the remote host timed out, but we
|
||||
// don't know if the problem is on our end, in the middle,
|
||||
// or on their end.
|
||||
k_ESteamNetConnectionEnd_Misc_Timeout = 5003,
|
||||
|
||||
// We're having trouble talking to the relevant relay.
|
||||
// We don't have enough information to say whether the
|
||||
// problem is on our end or not.
|
||||
k_ESteamNetConnectionEnd_Misc_RelayConnectivity = 5004,
|
||||
|
||||
// There's some trouble talking to Steam.
|
||||
k_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005,
|
||||
|
||||
// A server in a dedicated hosting situation has no relay sessions
|
||||
// active with which to talk back to a client. (It's the client's
|
||||
// job to open and maintain those sessions.)
|
||||
k_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006,
|
||||
|
||||
k_ESteamNetConnectionEnd_Misc_Max = 5999,
|
||||
};
|
||||
|
||||
/// Max length of diagnostic error message
|
||||
const int k_cchMaxSteamDatagramErrMsg = 1024;
|
||||
|
||||
/// Used to return English-language diagnostic error messages to caller.
|
||||
/// (For debugging or spewing to a console, etc. Not intended for UI.)
|
||||
typedef char SteamDatagramErrMsg[ k_cchMaxSteamDatagramErrMsg ];
|
||||
|
||||
/// Max length, in bytes (including null terminator) of the reason string
|
||||
/// when a connection is closed.
|
||||
const int k_cchSteamNetworkingMaxConnectionCloseReason = 128;
|
||||
|
||||
struct SteamNetConnectionInfo_t
|
||||
{
|
||||
|
||||
/// Handle to listen socket this was connected on, or k_HSteamListenSocket_Invalid if we initiated the connection
|
||||
HSteamListenSocket m_hListenSocket;
|
||||
|
||||
/// Who is on the other end. Depending on the connection type and phase of the connection, we might not know
|
||||
CSteamID m_steamIDRemote;
|
||||
|
||||
// FIXME - some sort of connection type enum?
|
||||
|
||||
/// Arbitrary user data set by the local application code
|
||||
int64 m_nUserData;
|
||||
|
||||
/// Remote address. Might be 0 if we don't know it
|
||||
uint32 m_unIPRemote;
|
||||
uint16 m_unPortRemote;
|
||||
uint16 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;
|
||||
|
||||
/// Local port that we're bound to for this connection. Might not be applicable
|
||||
/// for all connection types.
|
||||
//uint16 m_unPortLocal;
|
||||
|
||||
/// High level state of the connection
|
||||
int /* ESteamNetworkingConnectionState */ m_eState;
|
||||
|
||||
/// Basic cause of the connection termination or problem.
|
||||
/// One of ESteamNetConnectionEnd
|
||||
int /* ESteamNetConnectionEnd */ 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 ];
|
||||
};
|
||||
|
||||
/// Quick connection state, pared down to something you could call
|
||||
/// more frequently without it being too big of a perf hit.
|
||||
struct SteamNetworkingQuickConnectionStatus
|
||||
{
|
||||
|
||||
/// High level state of the connection
|
||||
int /* 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;
|
||||
|
||||
/// Actual current data rates
|
||||
float m_flOutPacketsPerSec;
|
||||
float m_flOutBytesPerSec;
|
||||
float m_flInPacketsPerSec;
|
||||
float m_flInBytesPerSec;
|
||||
|
||||
/// Estimate bandwidth of the connection (bytes per second)
|
||||
int m_nSendRate;
|
||||
|
||||
/// Number of bytes pending to be sent
|
||||
int m_nPendingBytes;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
enum ESteamDatagramPartner
|
||||
{
|
||||
k_ESteamDatagramPartner_None = -1,
|
||||
k_ESteamDatagramPartner_Steam = 0,
|
||||
k_ESteamDatagramPartner_China = 1,
|
||||
};
|
||||
|
||||
#endif // #ifndef STEAMNETWORKINGTYPES
|
||||
Reference in New Issue
Block a user