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