You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
732 lines
37 KiB
C++
732 lines
37 KiB
C++
//====== Copyright Valve Corporation, All rights reserved. ====================
|
|
//
|
|
// Networking API similar to Berkeley sockets, but for games.
|
|
// - connection-oriented API (like TCP, not UDP)
|
|
// - but unlike TCP, it's message-oriented, not stream-oriented
|
|
// - mix of reliable and unreliable messages
|
|
// - fragmentation and reassembly
|
|
// - Supports connectivity over plain UDPv4
|
|
// - Also supports SDR ("Steam Datagram Relay") connections, which are
|
|
// addressed by SteamID. There is a "P2P" use case and also a "hosted
|
|
// dedicated server" use case.
|
|
//
|
|
//=============================================================================
|
|
|
|
#ifndef ISTEAMNETWORKINGSOCKETS001
|
|
#define ISTEAMNETWORKINGSOCKETS001
|
|
#ifdef STEAM_WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
const int k_nSteamNetworkingSendFlags_NoNagle = 1;
|
|
const int k_nSteamNetworkingSendFlags_NoDelay = 2;
|
|
const int k_nSteamNetworkingSendFlags_Reliable = 8;
|
|
|
|
/// Different methods that messages can be sent
|
|
enum ESteamNetworkingSendType
|
|
{
|
|
// Send an unreliable message. 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.
|
|
//
|
|
// NOTE: By default, Nagle's algorithm is applied to all outbound packets. 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 k_ESteamNetworkingSendType_UnreliableNoNagle, ISteamNetworkingSockets::FlushMessagesOnConnection,
|
|
// ISteamNetworkingP2P::FlushMessagesToUser
|
|
//
|
|
// This is not exactly the same as k_EP2PSendUnreliable! You probably want k_ESteamNetworkingSendType_UnreliableNoNagle
|
|
k_ESteamNetworkingSendType_Unreliable = 0,
|
|
|
|
// 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_ESteamNetworkingSendType_Unreliable,
|
|
// and then immediately flushing the messages using ISteamNetworkingSockets::FlushMessagesOnConnection or ISteamNetworkingP2P::FlushMessagesToUser.
|
|
// (But this is more efficient.)
|
|
k_ESteamNetworkingSendType_UnreliableNoNagle = k_nSteamNetworkingSendFlags_NoNagle,
|
|
|
|
// Send an unreliable message, but do not buffer it if it cannot be sent relatively quickly.
|
|
// This is useful for messages that are not useful if they are excessively delayed, such as voice data.
|
|
// 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.
|
|
k_ESteamNetworkingSendType_UnreliableNoDelay = k_nSteamNetworkingSendFlags_NoDelay|k_nSteamNetworkingSendFlags_NoNagle,
|
|
|
|
// 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.
|
|
//
|
|
// The Nagle algorithm is used. See notes on k_ESteamNetworkingSendType_Unreliable for more details.
|
|
// See k_ESteamNetworkingSendType_ReliableNoNagle, ISteamNetworkingSockets::FlushMessagesOnConnection,
|
|
// ISteamNetworkingP2P::FlushMessagesToUser
|
|
//
|
|
// This is NOT the same as k_EP2PSendReliable, it's more like k_EP2PSendReliableWithBuffering
|
|
k_ESteamNetworkingSendType_Reliable = k_nSteamNetworkingSendFlags_Reliable,
|
|
|
|
// Send a message reliably, but bypass Nagle's algorithm.
|
|
// See k_ESteamNetworkingSendType_UnreliableNoNagle for more info.
|
|
//
|
|
// This is equivalent to k_EP2PSendReliable
|
|
k_ESteamNetworkingSendType_ReliableNoNagle = k_nSteamNetworkingSendFlags_Reliable|k_nSteamNetworkingSendFlags_NoNagle,
|
|
};
|
|
|
|
/// Configuration values for Steam networking.
|
|
///
|
|
/// Most of these are for controlling extend logging or features
|
|
/// of various subsystems
|
|
enum ESteamNetworkingConfigurationValue
|
|
{
|
|
/// 0-100 Randomly discard N pct of unreliable messages instead of sending
|
|
/// Defaults to 0 (no loss).
|
|
k_ESteamNetworkingConfigurationValue_FakeMessageLoss_Send = 0,
|
|
|
|
/// 0-100 Randomly discard N pct of unreliable messages upon receive
|
|
/// Defaults to 0 (no loss).
|
|
k_ESteamNetworkingConfigurationValue_FakeMessageLoss_Recv = 1,
|
|
|
|
/// 0-100 Randomly discard N pct of packets instead of sending
|
|
k_ESteamNetworkingConfigurationValue_FakePacketLoss_Send = 2,
|
|
|
|
/// 0-100 Randomly discard N pct of packets received
|
|
k_ESteamNetworkingConfigurationValue_FakePacketLoss_Recv = 3,
|
|
|
|
/// Globally delay all outbound packets by N ms before sending
|
|
k_ESteamNetworkingConfigurationValue_FakePacketLag_Send = 4,
|
|
|
|
/// Globally delay all received packets by N ms before processing
|
|
k_ESteamNetworkingConfigurationValue_FakePacketLag_Recv = 5,
|
|
|
|
/// Globally reorder some percentage of packets we send
|
|
k_ESteamNetworkingConfigurationValue_FakePacketReorder_Send = 6,
|
|
|
|
/// Globally reorder some percentage of packets we receive
|
|
k_ESteamNetworkingConfigurationValue_FakePacketReorder_Recv = 7,
|
|
|
|
/// Amount of delay, in ms, to apply to reordered packets.
|
|
k_ESteamNetworkingConfigurationValue_FakePacketReorder_Time = 8,
|
|
|
|
/// Upper limit of buffered pending bytes to be sent, if this is reached
|
|
/// SendMessage will return k_EResultLimitExceeded
|
|
/// Default is 512k (524288 bytes)
|
|
k_ESteamNetworkingConfigurationValue_SendBufferSize = 9,
|
|
|
|
/// 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_MaxRate = 10,
|
|
|
|
/// 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_MinRate = 11,
|
|
|
|
/// Set the nagle timer. When SendMessage is called, if the outgoing message
|
|
/// is less than the size of the MTU, it will be queued for a delay equal to
|
|
/// the Nagle timer value. This is to ensure that if the application sends
|
|
/// several small messages rapidly, they are coalesced into a single packet.
|
|
/// See historical RFC 896. Value is in microseconds.
|
|
/// Default is 5000us (5ms).
|
|
k_ESteamNetworkingConfigurationValue_Nagle_Time = 12,
|
|
|
|
/// Set to true (non-zero) to enable logging of RTT's based on acks.
|
|
/// This doesn't track all sources of RTT, just the inline ones based
|
|
/// on acks, but those are the most common
|
|
k_ESteamNetworkingConfigurationValue_LogLevel_AckRTT = 13,
|
|
|
|
/// Log level of SNP packet decoding
|
|
k_ESteamNetworkingConfigurationValue_LogLevel_Packet = 14,
|
|
|
|
/// Log when messages are sent/received
|
|
k_ESteamNetworkingConfigurationValue_LogLevel_Message = 15,
|
|
|
|
/// Log level when individual packets drop
|
|
k_ESteamNetworkingConfigurationValue_LogLevel_PacketGaps = 16,
|
|
|
|
/// Log level for P2P rendezvous.
|
|
k_ESteamNetworkingConfigurationValue_LogLevel_P2PRendezvous = 17,
|
|
|
|
/// Log level for sending and receiving pings to relays
|
|
k_ESteamNetworkingConfigurationValue_LogLevel_RelayPings = 18,
|
|
|
|
/// 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 = 19,
|
|
|
|
/// 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 = 20,
|
|
|
|
/// 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 = 21,
|
|
|
|
/// 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 = 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,
|
|
|
|
/// Timeout value (in seconds) to use when first connecting
|
|
k_ESteamNetworkingConfigurationValue_Timeout_Seconds_Initial = 24,
|
|
|
|
/// Timeout value (in seconds) to use after connection is established
|
|
k_ESteamNetworkingConfigurationValue_Timeout_Seconds_Connected = 25,
|
|
|
|
/// 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,
|
|
};
|
|
|
|
/// Configuration values for Steam networking per connection
|
|
enum ESteamNetworkingConnectionConfigurationValue
|
|
{
|
|
// 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_ESteamNetworkingConnectionConfigurationValue_SNP_MaxRate = 0,
|
|
|
|
// 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_ESteamNetworkingConnectionConfigurationValue_SNP_MinRate = 1,
|
|
|
|
// Number of k_ESteamNetworkingConfigurationValue defines
|
|
k_ESteamNetworkingConnectionConfigurationValue_Count,
|
|
};
|
|
|
|
/// Message that has been received
|
|
typedef struct _SteamNetworkingMessage001_t
|
|
{
|
|
|
|
/// SteamID that sent this to us.
|
|
CSteamID m_steamIDSender;
|
|
|
|
/// 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.
|
|
int64 m_nConnUserData;
|
|
|
|
/// Local timestamps when it was received
|
|
SteamNetworkingMicroseconds m_usecTimeReceived;
|
|
|
|
/// Message number assigned by the sender
|
|
int64 m_nMessageNumber;
|
|
|
|
/// Function used to clean up this object. Normally you won't call
|
|
/// this directly, use Release() instead.
|
|
void (*m_pfnRelease)( struct _SteamNetworkingMessage001_t *msg );
|
|
|
|
/// Message payload
|
|
void *m_pData;
|
|
|
|
/// Size of the payload.
|
|
uint32 m_cbSize;
|
|
|
|
/// The connection this came from. (Not used when using the P2P calls)
|
|
HSteamNetConnection m_conn;
|
|
|
|
/// The channel number the message was received on.
|
|
/// (Not used for messages received on "connections")
|
|
int m_nChannel;
|
|
|
|
/// Pad to multiple of 8 bytes
|
|
int m___nPadDummy;
|
|
|
|
#ifdef __cplusplus
|
|
|
|
/// You MUST call this when you're done with the object,
|
|
/// to free up memory, etc.
|
|
inline void Release()
|
|
{
|
|
m_pfnRelease( this );
|
|
}
|
|
|
|
// For code compatibility, some accessors
|
|
inline uint32 GetSize() const { return m_cbSize; }
|
|
inline const void *GetData() const { return m_pData; }
|
|
inline CSteamID GetSenderSteamID() const { return m_steamIDSender; }
|
|
inline int GetChannel() const { return m_nChannel; }
|
|
inline HSteamNetConnection GetConnection() const { return m_conn; }
|
|
inline int64 GetConnectionUserData() const { return m_nConnUserData; }
|
|
inline SteamNetworkingMicroseconds GetTimeReceived() const { return m_usecTimeReceived; }
|
|
inline int64 GetMessageNumber() const { return m_nMessageNumber; }
|
|
#endif
|
|
} SteamNetworkingMessage001_t;
|
|
|
|
// For code compatibility
|
|
typedef SteamNetworkingMessage001_t ISteamNetworkingMessage001;
|
|
|
|
struct SteamNetConnectionInfo001_t
|
|
{
|
|
|
|
/// 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;
|
|
|
|
/// Handle to listen socket this was connected on, or k_HSteamListenSocket_Invalid if we initiated the connection
|
|
HSteamListenSocket m_hListenSocket;
|
|
|
|
/// 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 ];
|
|
};
|
|
|
|
/// TEMP callback dispatch mechanism.
|
|
/// You'll override this guy and hook any callbacks you are interested in,
|
|
/// and then use ISteamNetworkingSockets::RunCallbacks. Eventually this will go away,
|
|
/// and you will register for the callbacks you want using the normal SteamWorks callback
|
|
/// mechanisms, and they will get dispatched along with other Steamworks callbacks
|
|
/// when you call SteamAPI_RunCallbacks and SteamGameServer_RunCallbacks.
|
|
class ISteamNetworkingSocketsCallbacks
|
|
{
|
|
public:
|
|
inline ISteamNetworkingSocketsCallbacks() {}
|
|
virtual void OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t * ) {}
|
|
virtual void OnP2PSessionRequest( P2PSessionRequest_t * ) {}
|
|
virtual void OnP2PSessionConnectFail( P2PSessionConnectFail_t * ) {}
|
|
protected:
|
|
inline ~ISteamNetworkingSocketsCallbacks() {}
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// 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 ISteamNetworkingSockets001
|
|
{
|
|
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.
|
|
///
|
|
/// In the open-source version of this API, you must pass -1 for nSteamConnectVirtualPort
|
|
///
|
|
/// 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 a matching 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.
|
|
///
|
|
/// A SteamNetConnectionStatusChangedCallback_t callback will be triggered when we start connecting,
|
|
/// and then another one on timeout or successful connection
|
|
//#ifndef STEAMNETWORKINGSOCKETS_OPENSOURCE
|
|
virtual HSteamNetConnection ConnectBySteamID( CSteamID steamIDTarget, int nVirtualPort ) = 0;
|
|
//#endif
|
|
virtual HSteamNetConnection ConnectByIPv4Address( uint32 nIP, uint16 nPort ) = 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 either into the connected state,
|
|
/// of the finding route state, depending on the connection type.
|
|
///
|
|
/// You should take action within a second or two, 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 (for example, while loading a map), then there is a chance
|
|
/// that a client may attempt to connect in that interval and fail due to 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 depending the exact
|
|
/// sequence of events.
|
|
///
|
|
/// 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 name. Returns false if handle is invalid
|
|
virtual bool GetConnectionName( HSteamNetConnection hPeer, char *pszName, 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;
|
|
|
|
/// If Nagle is enabled (its on by default) then when calling
|
|
/// SendMessageToConnection the message will be queued up the Nagle time
|
|
/// before being sent to merge small messages into the same packet.
|
|
///
|
|
/// Call this function to flush any queued messages and send them immediately
|
|
/// on the next transmission time (often that means right now).
|
|
virtual EResult FlushMessagesOnConnection( HSteamNetConnection hConn ) = 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, SteamNetworkingMessage001_t **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. Examine
|
|
/// SteamNetworkingMessage_t::m_conn 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, SteamNetworkingMessage001_t **ppOutMessages, int nMaxMessages ) = 0;
|
|
|
|
/// Returns information about the specified connection.
|
|
virtual bool GetConnectionInfo( HSteamNetConnection hConn, SteamNetConnectionInfo001_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;
|
|
|
|
/// Create a pair of connections that are talking to each other, e.g. a loopback connection.
|
|
/// This is very useful for testing, or so that your client/server code can work the same
|
|
/// even when you are running a local "server".
|
|
///
|
|
/// The two connections will immediately be placed into the connected state, and no callbacks
|
|
/// will be posted immediately. After this, if you close either connection, the other connection
|
|
/// will receive a callback, exactly as if they were communicating over the network. You must
|
|
/// close *both* sides in order to fully clean up the resources!
|
|
///
|
|
/// By default, internal buffers are used, completely bypassing the network, the chopping up of
|
|
/// messages into packets, encryption, copying the payload, etc. This means that loopback
|
|
/// packets, by default, will not simulate lag or loss. Passing true for bUseNetworkLoopback will
|
|
/// cause the socket pair to send packets through the local network loopback device (127.0.0.1)
|
|
/// on ephemeral ports. Fake lag and loss are supported in this case, and CPU time is expended
|
|
/// to encrypt and decrypt.
|
|
///
|
|
/// The SteamID assigned to both ends of the connection will be the SteamID of this interface.
|
|
virtual bool CreateSocketPair( HSteamNetConnection *pOutConnection1, HSteamNetConnection *pOutConnection2, bool bUseNetworkLoopback ) = 0;
|
|
|
|
//#ifndef STEAMNETWORKINGSOCKETS_OPENSOURCE
|
|
|
|
//
|
|
// Clients connecting to dedicated servers hosted in a data center,
|
|
// using central-authority-granted tickets.
|
|
//
|
|
|
|
/// Called when we receive a ticket from our central matchmaking system. Puts the
|
|
/// ticket into a persistent cache, and optionally returns the parsed ticket.
|
|
///
|
|
/// See stamdatagram_ticketgen.h for more details.
|
|
virtual bool ReceivedRelayAuthTicket( const void *pvTicket, int cbTicket, SteamDatagramRelayAuthTicket *pOutParsedTicket ) = 0;
|
|
|
|
/// Search cache for a ticket to talk to the server on the specified virtual port.
|
|
/// If found, returns the number of second until the ticket expires, and optionally
|
|
/// the complete cracked ticket. Returns 0 if we don't have a ticket.
|
|
///
|
|
/// Typically this is useful just to confirm that you have a ticket, before you
|
|
/// call ConnectToHostedDedicatedServer to connect to the server.
|
|
virtual int FindRelayAuthTicketForServer( CSteamID steamID, int nVirtualPort, SteamDatagramRelayAuthTicket *pOutParsedTicket ) = 0;
|
|
|
|
/// Client call to connect to a server hosted in a Valve data center, on the specified virtual
|
|
/// port. You should have received a ticket for this server, or else this connect call will fail!
|
|
///
|
|
/// You may wonder why tickets are stored in a cache, instead of simply being passed as an argument
|
|
/// here. The reason is to make reconnection to a gameserver robust, even if the client computer loses
|
|
/// connection to Steam or the central backend, or the app is restarted or crashes, etc.
|
|
virtual HSteamNetConnection ConnectToHostedDedicatedServer( CSteamID steamIDTarget, int nVirtualPort ) = 0;
|
|
|
|
//
|
|
// Servers hosted in Valve data centers
|
|
//
|
|
|
|
/// Returns the value of the SDR_LISTEN_PORT environment variable.
|
|
virtual uint16 GetHostedDedicatedServerPort() = 0;
|
|
|
|
/// If you are running in a production data center, this will return the data
|
|
/// center code. Returns 0 otherwise.
|
|
virtual SteamNetworkingPOPID GetHostedDedicatedServerPOPID() = 0;
|
|
|
|
/// Return info about the hosted server. You will need to send this information to your
|
|
/// backend, and put it in tickets, so that the relays will know how to forward traffic from
|
|
/// clients to your server. See SteamDatagramRelayAuthTicket for more info.
|
|
///
|
|
/// NOTE ABOUT DEVELOPMENT ENVIRONMENTS:
|
|
/// In production in our data centers, these parameters are configured via environment variables.
|
|
/// In development, the only one you need to set is SDR_LISTEN_PORT, which is the local port you
|
|
/// want to listen on. Furthermore, if you are running your server behind a corporate firewall,
|
|
/// you probably will not be able to put the routing information returned by this function into
|
|
/// tickets. Instead, it should be a public internet address that the relays can use to send
|
|
/// data to your server. So you might just end up hardcoding a public address and setup port
|
|
/// forwarding on your corporate firewall. In that case, the port you put into the ticket
|
|
/// needs to be the public-facing port opened on your firewall, if it is different from the
|
|
/// actual server port.
|
|
///
|
|
/// This function will fail if SteamDatagramServer_Init has not been called.
|
|
///
|
|
/// Returns false if the SDR_LISTEN_PORT environment variable is not set.
|
|
virtual bool GetHostedDedicatedServerAddress( SteamDatagramHostedAddress *pRouting ) = 0;
|
|
|
|
/// Create a listen socket on the specified virtual port. The physical UDP port to use
|
|
/// will be determined by the SDR_LISTEN_PORT environment variable. If a UDP port is not
|
|
/// configured, this call will fail.
|
|
///
|
|
/// Note that this call MUST be made through the SteamNetworkingSocketsGameServer() interface
|
|
virtual HSteamListenSocket CreateHostedDedicatedServerListenSocket( int nVirtualPort ) = 0;
|
|
|
|
//#endif // #ifndef STEAMNETWORKINGSOCKETS_OPENSOURCE
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
// Set and get configuration values, see ESteamNetworkingConnectionConfigurationValue for individual descriptions.
|
|
//
|
|
// Returns the value or -1 is eConfigValue is invalid
|
|
virtual int32 GetConnectionConfigurationValue( HSteamNetConnection hConn, ESteamNetworkingConnectionConfigurationValue eConfigValue ) = 0;
|
|
// Returns true if successfully set
|
|
virtual bool SetConnectionConfigurationValue( HSteamNetConnection hConn, ESteamNetworkingConnectionConfigurationValue eConfigValue, int32 nValue ) = 0;
|
|
|
|
// TEMP KLUDGE Call to invoke all queued callbacks.
|
|
// Eventually this function will go away, and callwacks will be ordinary Steamworks callbacks.
|
|
// You should call this at the same time you call SteamAPI_RunCallbacks and SteamGameServer_RunCallbacks
|
|
// to minimize potential changes in timing when that change happens.
|
|
virtual void RunCallbacks( ISteamNetworkingSocketsCallbacks *pCallbacks ) = 0;
|
|
protected:
|
|
//~ISteamNetworkingSockets001(); // Silence some warnings
|
|
};
|
|
//#define STEAMNETWORKINGSOCKETS_VERSION "SteamNetworkingSockets001"
|
|
|
|
|
|
#endif // ISTEAMNETWORKINGSOCKETS001
|