Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

306 lines
16 KiB

  1. //====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: interface to steam managing network connections between game clients & servers
  4. //
  5. //=============================================================================
  6. #ifndef ISTEAMNETWORKING
  7. #define ISTEAMNETWORKING
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "steamtypes.h"
  12. #include "steamclientpublic.h"
  13. // list of possible errors returned by SendP2PPacket() API
  14. // these will be posted in the P2PSessionConnectFail_t callback
  15. enum EP2PSessionError
  16. {
  17. k_EP2PSessionErrorNone = 0,
  18. k_EP2PSessionErrorNotRunningApp = 1, // target is not running the same game
  19. k_EP2PSessionErrorNoRightsToApp = 2, // local user doesn't own the app that is running
  20. k_EP2PSessionErrorDestinationNotLoggedIn = 3, // target user isn't connected to Steam
  21. k_EP2PSessionErrorTimeout = 4, // target isn't responding, perhaps not calling AcceptP2PSessionWithUser()
  22. // corporate firewalls can also block this (NAT traversal is not firewall traversal)
  23. // make sure that UDP ports 3478, 4379, and 4380 are open in an outbound direction
  24. k_EP2PSessionErrorMax = 5
  25. };
  26. // SendP2PPacket() send types
  27. // Typically k_EP2PSendUnreliable is what you want for UDP-like packets, k_EP2PSendReliable for TCP-like packets
  28. enum EP2PSend
  29. {
  30. // Basic UDP send. Packets can't be bigger than 1200 bytes (your typical MTU size). Can be lost, or arrive out of order (rare).
  31. // The sending API does have some knowledge of the underlying connection, so if there is no NAT-traversal accomplished or
  32. // there is a recognized adjustment happening on the connection, the packet will be batched until the connection is open again.
  33. k_EP2PSendUnreliable = 0,
  34. // As above, but if the underlying p2p connection isn't yet established the packet will just be thrown away. Using this on the first
  35. // packet sent to a remote host almost guarantees the packet will be dropped.
  36. // This is only really useful for kinds of data that should never buffer up, i.e. voice payload packets
  37. k_EP2PSendUnreliableNoDelay = 1,
  38. // Reliable message send. Can send up to 1MB of data in a single message.
  39. // Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for efficient sends of large chunks of data.
  40. k_EP2PSendReliable = 2,
  41. // As above, but applies the Nagle algorithm to the send - sends will accumulate
  42. // until the current MTU size (typically ~1200 bytes, but can change) or ~200ms has passed (Nagle algorithm).
  43. // Useful if you want to send a set of smaller messages but have the coalesced into a single packet
  44. // Since the reliable stream is all ordered, you can do several small message sends with k_EP2PSendReliableWithBuffering and then
  45. // do a normal k_EP2PSendReliable to force all the buffered data to be sent.
  46. k_EP2PSendReliableWithBuffering = 3,
  47. };
  48. // connection state to a specified user, returned by GetP2PSessionState()
  49. // this is under-the-hood info about what's going on with a SendP2PPacket(), shouldn't be needed except for debuggin
  50. #if defined( VALVE_CALLBACK_PACK_SMALL )
  51. #pragma pack( push, 4 )
  52. #elif defined( VALVE_CALLBACK_PACK_LARGE )
  53. #pragma pack( push, 8 )
  54. #else
  55. #error isteamclient.h must be included
  56. #endif
  57. struct P2PSessionState_t
  58. {
  59. uint8 m_bConnectionActive; // true if we've got an active open connection
  60. uint8 m_bConnecting; // true if we're currently trying to establish a connection
  61. uint8 m_eP2PSessionError; // last error recorded (see enum above)
  62. uint8 m_bUsingRelay; // true if it's going through a relay server (TURN)
  63. int32 m_nBytesQueuedForSend;
  64. int32 m_nPacketsQueuedForSend;
  65. uint32 m_nRemoteIP; // potential IP:Port of remote host. Could be TURN server.
  66. uint16 m_nRemotePort; // Only exists for compatibility with older authentication api's
  67. };
  68. #pragma pack( pop )
  69. // handle to a socket
  70. typedef uint32 SNetSocket_t; // CreateP2PConnectionSocket()
  71. typedef uint32 SNetListenSocket_t; // CreateListenSocket()
  72. // connection progress indicators, used by CreateP2PConnectionSocket()
  73. enum ESNetSocketState
  74. {
  75. k_ESNetSocketStateInvalid = 0,
  76. // communication is valid
  77. k_ESNetSocketStateConnected = 1,
  78. // states while establishing a connection
  79. k_ESNetSocketStateInitiated = 10, // the connection state machine has started
  80. // p2p connections
  81. k_ESNetSocketStateLocalCandidatesFound = 11, // we've found our local IP info
  82. k_ESNetSocketStateReceivedRemoteCandidates = 12,// we've received information from the remote machine, via the Steam back-end, about their IP info
  83. // direct connections
  84. k_ESNetSocketStateChallengeHandshake = 15, // we've received a challenge packet from the server
  85. // failure states
  86. k_ESNetSocketStateDisconnecting = 21, // the API shut it down, and we're in the process of telling the other end
  87. k_ESNetSocketStateLocalDisconnect = 22, // the API shut it down, and we've completed shutdown
  88. k_ESNetSocketStateTimeoutDuringConnect = 23, // we timed out while trying to creating the connection
  89. k_ESNetSocketStateRemoteEndDisconnected = 24, // the remote end has disconnected from us
  90. k_ESNetSocketStateConnectionBroken = 25, // connection has been broken; either the other end has disappeared or our local network connection has broke
  91. };
  92. // describes how the socket is currently connected
  93. enum ESNetSocketConnectionType
  94. {
  95. k_ESNetSocketConnectionTypeNotConnected = 0,
  96. k_ESNetSocketConnectionTypeUDP = 1,
  97. k_ESNetSocketConnectionTypeUDPRelay = 2,
  98. };
  99. //-----------------------------------------------------------------------------
  100. // Purpose: Functions for making connections and sending data between clients,
  101. // traversing NAT's where possible
  102. //-----------------------------------------------------------------------------
  103. class ISteamNetworking
  104. {
  105. public:
  106. ////////////////////////////////////////////////////////////////////////////////////////////
  107. // Session-less connection functions
  108. // automatically establishes NAT-traversing or Relay server connections
  109. // Sends a P2P packet to the specified user
  110. // UDP-like, unreliable and a max packet size of 1200 bytes
  111. // the first packet send may be delayed as the NAT-traversal code runs
  112. // if we can't get through to the user, an error will be posted via the callback P2PSessionConnectFail_t
  113. // see EP2PSend enum above for the descriptions of the different ways of sending packets
  114. //
  115. // nChannel is a routing number you can use to help route message to different systems - you'll have to call ReadP2PPacket()
  116. // with the same channel number in order to retrieve the data on the other end
  117. // using different channels to talk to the same user will still use the same underlying p2p connection, saving on resources
  118. virtual bool SendP2PPacket( CSteamID steamIDRemote, const void *pubData, uint32 cubData, EP2PSend eP2PSendType, int nChannel = 0 ) = 0;
  119. // returns true if any data is available for read, and the amount of data that will need to be read
  120. virtual bool IsP2PPacketAvailable( uint32 *pcubMsgSize, int nChannel = 0 ) = 0;
  121. // reads in a packet that has been sent from another user via SendP2PPacket()
  122. // returns the size of the message and the steamID of the user who sent it in the last two parameters
  123. // if the buffer passed in is too small, the message will be truncated
  124. // this call is not blocking, and will return false if no data is available
  125. virtual bool ReadP2PPacket( void *pubDest, uint32 cubDest, uint32 *pcubMsgSize, CSteamID *psteamIDRemote, int nChannel = 0 ) = 0;
  126. // AcceptP2PSessionWithUser() should only be called in response to a P2PSessionRequest_t callback
  127. // P2PSessionRequest_t will be posted if another user tries to send you a packet that you haven't talked to yet
  128. // if you don't want to talk to the user, just ignore the request
  129. // if the user continues to send you packets, another P2PSessionRequest_t will be posted periodically
  130. // this may be called multiple times for a single user
  131. // (if you've called SendP2PPacket() on the other user, this implicitly accepts the session request)
  132. virtual bool AcceptP2PSessionWithUser( CSteamID steamIDRemote ) = 0;
  133. // call CloseP2PSessionWithUser() when you're done talking to a user, will free up resources under-the-hood
  134. // if the remote user tries to send data to you again, another P2PSessionRequest_t callback will be posted
  135. virtual bool CloseP2PSessionWithUser( CSteamID steamIDRemote ) = 0;
  136. // call CloseP2PChannelWithUser() when you're done talking to a user on a specific channel. Once all channels
  137. // open channels to a user have been closed, the open session to the user will be closed and new data from this
  138. // user will trigger a P2PSessionRequest_t callback
  139. virtual bool CloseP2PChannelWithUser( CSteamID steamIDRemote, int nChannel ) = 0;
  140. // fills out P2PSessionState_t structure with details about the underlying connection to the user
  141. // should only needed for debugging purposes
  142. // returns false if no connection exists to the specified user
  143. virtual bool GetP2PSessionState( CSteamID steamIDRemote, P2PSessionState_t *pConnectionState ) = 0;
  144. // Allow P2P connections to fall back to being relayed through the Steam servers if a direct connection
  145. // or NAT-traversal cannot be established. Only applies to connections created after setting this value,
  146. // or to existing connections that need to automatically reconnect after this value is set.
  147. //
  148. // P2P packet relay is allowed by default
  149. virtual bool AllowP2PPacketRelay( bool bAllow ) = 0;
  150. ////////////////////////////////////////////////////////////////////////////////////////////
  151. // LISTEN / CONNECT style interface functions
  152. //
  153. // This is an older set of functions designed around the Berkeley TCP sockets model
  154. // it's preferential that you use the above P2P functions, they're more robust
  155. // and these older functions will be removed eventually
  156. //
  157. ////////////////////////////////////////////////////////////////////////////////////////////
  158. // creates a socket and listens others to connect
  159. // will trigger a SocketStatusCallback_t callback on another client connecting
  160. // nVirtualP2PPort is the unique ID that the client will connect to, in case you have multiple ports
  161. // this can usually just be 0 unless you want multiple sets of connections
  162. // unIP is the local IP address to bind to
  163. // pass in 0 if you just want the default local IP
  164. // unPort is the port to use
  165. // pass in 0 if you don't want users to be able to connect via IP/Port, but expect to be always peer-to-peer connections only
  166. virtual SNetListenSocket_t CreateListenSocket( int nVirtualP2PPort, uint32 nIP, uint16 nPort, bool bAllowUseOfPacketRelay ) = 0;
  167. // creates a socket and begin connection to a remote destination
  168. // can connect via a known steamID (client or game server), or directly to an IP
  169. // on success will trigger a SocketStatusCallback_t callback
  170. // on failure or timeout will trigger a SocketStatusCallback_t callback with a failure code in m_eSNetSocketState
  171. virtual SNetSocket_t CreateP2PConnectionSocket( CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay ) = 0;
  172. virtual SNetSocket_t CreateConnectionSocket( uint32 nIP, uint16 nPort, int nTimeoutSec ) = 0;
  173. // disconnects the connection to the socket, if any, and invalidates the handle
  174. // any unread data on the socket will be thrown away
  175. // if bNotifyRemoteEnd is set, socket will not be completely destroyed until the remote end acknowledges the disconnect
  176. virtual bool DestroySocket( SNetSocket_t hSocket, bool bNotifyRemoteEnd ) = 0;
  177. // destroying a listen socket will automatically kill all the regular sockets generated from it
  178. virtual bool DestroyListenSocket( SNetListenSocket_t hSocket, bool bNotifyRemoteEnd ) = 0;
  179. // sending data
  180. // must be a handle to a connected socket
  181. // data is all sent via UDP, and thus send sizes are limited to 1200 bytes; after this, many routers will start dropping packets
  182. // use the reliable flag with caution; although the resend rate is pretty aggressive,
  183. // it can still cause stalls in receiving data (like TCP)
  184. virtual bool SendDataOnSocket( SNetSocket_t hSocket, void *pubData, uint32 cubData, bool bReliable ) = 0;
  185. // receiving data
  186. // returns false if there is no data remaining
  187. // fills out *pcubMsgSize with the size of the next message, in bytes
  188. virtual bool IsDataAvailableOnSocket( SNetSocket_t hSocket, uint32 *pcubMsgSize ) = 0;
  189. // fills in pubDest with the contents of the message
  190. // messages are always complete, of the same size as was sent (i.e. packetized, not streaming)
  191. // if *pcubMsgSize < cubDest, only partial data is written
  192. // returns false if no data is available
  193. virtual bool RetrieveDataFromSocket( SNetSocket_t hSocket, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize ) = 0;
  194. // checks for data from any socket that has been connected off this listen socket
  195. // returns false if there is no data remaining
  196. // fills out *pcubMsgSize with the size of the next message, in bytes
  197. // fills out *phSocket with the socket that data is available on
  198. virtual bool IsDataAvailable( SNetListenSocket_t hListenSocket, uint32 *pcubMsgSize, SNetSocket_t *phSocket ) = 0;
  199. // retrieves data from any socket that has been connected off this listen socket
  200. // fills in pubDest with the contents of the message
  201. // messages are always complete, of the same size as was sent (i.e. packetized, not streaming)
  202. // if *pcubMsgSize < cubDest, only partial data is written
  203. // returns false if no data is available
  204. // fills out *phSocket with the socket that data is available on
  205. virtual bool RetrieveData( SNetListenSocket_t hListenSocket, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize, SNetSocket_t *phSocket ) = 0;
  206. // returns information about the specified socket, filling out the contents of the pointers
  207. virtual bool GetSocketInfo( SNetSocket_t hSocket, CSteamID *pSteamIDRemote, int *peSocketStatus, uint32 *punIPRemote, uint16 *punPortRemote ) = 0;
  208. // returns which local port the listen socket is bound to
  209. // *pnIP and *pnPort will be 0 if the socket is set to listen for P2P connections only
  210. virtual bool GetListenSocketInfo( SNetListenSocket_t hListenSocket, uint32 *pnIP, uint16 *pnPort ) = 0;
  211. // returns true to describe how the socket ended up connecting
  212. virtual ESNetSocketConnectionType GetSocketConnectionType( SNetSocket_t hSocket ) = 0;
  213. // max packet size, in bytes
  214. virtual int GetMaxPacketSize( SNetSocket_t hSocket ) = 0;
  215. };
  216. #define STEAMNETWORKING_INTERFACE_VERSION "SteamNetworking005"
  217. // callbacks
  218. #if defined( VALVE_CALLBACK_PACK_SMALL )
  219. #pragma pack( push, 4 )
  220. #elif defined( VALVE_CALLBACK_PACK_LARGE )
  221. #pragma pack( push, 8 )
  222. #else
  223. #error isteamclient.h must be included
  224. #endif
  225. // callback notification - a user wants to talk to us over the P2P channel via the SendP2PPacket() API
  226. // in response, a call to AcceptP2PPacketsFromUser() needs to be made, if you want to talk with them
  227. struct P2PSessionRequest_t
  228. {
  229. enum { k_iCallback = k_iSteamNetworkingCallbacks + 2 };
  230. CSteamID m_steamIDRemote; // user who wants to talk to us
  231. };
  232. // callback notification - packets can't get through to the specified user via the SendP2PPacket() API
  233. // all packets queued packets unsent at this point will be dropped
  234. // further attempts to send will retry making the connection (but will be dropped if we fail again)
  235. struct P2PSessionConnectFail_t
  236. {
  237. enum { k_iCallback = k_iSteamNetworkingCallbacks + 3 };
  238. CSteamID m_steamIDRemote; // user we were sending packets to
  239. uint8 m_eP2PSessionError; // EP2PSessionError indicating why we're having trouble
  240. };
  241. // callback notification - status of a socket has changed
  242. // used as part of the CreateListenSocket() / CreateP2PConnectionSocket()
  243. struct SocketStatusCallback_t
  244. {
  245. enum { k_iCallback = k_iSteamNetworkingCallbacks + 1 };
  246. SNetSocket_t m_hSocket; // the socket used to send/receive data to the remote host
  247. SNetListenSocket_t m_hListenSocket; // this is the server socket that we were listening on; NULL if this was an outgoing connection
  248. CSteamID m_steamIDRemote; // remote steamID we have connected to, if it has one
  249. int m_eSNetSocketState; // socket state, ESNetSocketState
  250. };
  251. #pragma pack( pop )
  252. #endif // ISTEAMNETWORKING