1 //====== Copyright Valve Corporation, All rights reserved. ====================
2 //
3 // Purpose: misc networking utilities
4 //
5 //=============================================================================
6 
7 #ifndef STEAMNETWORKINGTYPES
8 #define STEAMNETWORKINGTYPES
9 #pragma once
10 
11 #include <string.h>
12 #include <stdint.h>
13 #include "steamtypes.h"
14 #include "steamclientpublic.h"
15 
16 //----------------------------------------
17 // SteamNetworkingSockets library config
18 // Opensource version
19 //
20 #ifndef STEAMNETWORKINGSOCKETS_OPENSOURCE
21 #define STEAMNETWORKINGSOCKETS_OPENSOURCE
22 #endif
23 #define STEAMNETWORKINGSOCKETS_STANDALONELIB
24 //#define STEAMNETWORKINGSOCKETS_STEAMAPI // Comment this in to support linking with steam_api.h as well
25 // End SteamNetworkingSockets config.
26 //-----------------------------------------------------------------------------
27 
28 #if !defined( STEAMNETWORKINGSOCKETS_OPENSOURCE ) && !defined( STEAMNETWORKINGSOCKETS_STREAMINGCLIENT )
29 	#define STEAMNETWORKINGSOCKETS_STEAM
30 #endif
31 #ifdef NN_NINTENDO_SDK // We always static link on Nintendo
32 	#define STEAMNETWORKINGSOCKETS_STATIC_LINK
33 #endif
34 #if defined( STEAMNETWORKINGSOCKETS_STATIC_LINK )
35 	#define STEAMNETWORKINGSOCKETS_INTERFACE extern "C"
36 #elif defined( STEAMNETWORKINGSOCKETS_FOREXPORT )
37 	#ifdef _WIN32
38 		#define STEAMNETWORKINGSOCKETS_INTERFACE extern "C" __declspec( dllexport )
39 	#else
40 		#define STEAMNETWORKINGSOCKETS_INTERFACE extern "C" __attribute__((visibility("default")))
41 	#endif
42 #else
43 	#ifdef _WIN32
44 		#define STEAMNETWORKINGSOCKETS_INTERFACE extern "C" __declspec( dllimport )
45 	#else
46 		#define STEAMNETWORKINGSOCKETS_INTERFACE extern "C"
47 	#endif
48 #endif
49 
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 "Must define VALVE_CALLBACK_PACK_SMALL or VALVE_CALLBACK_PACK_LARGE"
56 #endif
57 
58 struct SteamDatagramRelayAuthTicket;
59 struct SteamDatagramHostedAddress;
60 struct SteamDatagramGameCoordinatorServerLogin;
61 struct SteamNetConnectionStatusChangedCallback_t;
62 struct SteamNetAuthenticationStatus_t;
63 struct SteamRelayNetworkStatus_t;
64 struct SteamNetworkingMessagesSessionRequest_t;
65 struct SteamNetworkingMessagesSessionFailed_t;
66 
67 typedef void (*FnSteamNetConnectionStatusChanged)( SteamNetConnectionStatusChangedCallback_t * );
68 typedef void (*FnSteamNetAuthenticationStatusChanged)( SteamNetAuthenticationStatus_t * );
69 typedef void (*FnSteamRelayNetworkStatusChanged)(SteamRelayNetworkStatus_t *);
70 typedef void (*FnSteamNetworkingMessagesSessionRequest)(SteamNetworkingMessagesSessionRequest_t *);
71 typedef void (*FnSteamNetworkingMessagesSessionFailed)(SteamNetworkingMessagesSessionFailed_t *);
72 
73 /// Handle used to identify a connection to a remote host.
74 typedef uint32 HSteamNetConnection;
75 const HSteamNetConnection k_HSteamNetConnection_Invalid = 0;
76 
77 /// Handle used to identify a "listen socket".  Unlike traditional
78 /// Berkeley sockets, a listen socket and a connection are two
79 /// different abstractions.
80 typedef uint32 HSteamListenSocket;
81 const HSteamListenSocket k_HSteamListenSocket_Invalid = 0;
82 
83 /// Handle used to identify a poll group, used to query many
84 /// connections at once efficiently.
85 typedef uint32 HSteamNetPollGroup;
86 const HSteamNetPollGroup k_HSteamNetPollGroup_Invalid = 0;
87 
88 /// Max length of diagnostic error message
89 const int k_cchMaxSteamNetworkingErrMsg = 1024;
90 
91 /// Used to return English-language diagnostic error messages to caller.
92 /// (For debugging or spewing to a console, etc.  Not intended for UI.)
93 typedef char SteamNetworkingErrMsg[ k_cchMaxSteamNetworkingErrMsg ];
94 
95 /// Identifier used for a network location point of presence.  (E.g. a Valve data center.)
96 /// Typically you won't need to directly manipulate these.
97 typedef uint32 SteamNetworkingPOPID;
98 
99 /// A local timestamp.  You can subtract two timestamps to get the number of elapsed
100 /// microseconds.  This is guaranteed to increase over time during the lifetime
101 /// of a process, but not globally across runs.  You don't need to worry about
102 /// the value wrapping around.  Note that the underlying clock might not actually have
103 /// microsecond resolution.
104 typedef int64 SteamNetworkingMicroseconds;
105 
106 /// Describe the status of a particular network resource
107 enum ESteamNetworkingAvailability
108 {
109 	// Negative values indicate a problem.
110 	//
111 	// In general, we will not automatically retry unless you take some action that
112 	// depends on of requests this resource, such as querying the status, attempting
113 	// to initiate a connection, receive a connection, etc.  If you do not take any
114 	// action at all, we do not automatically retry in the background.
115 	k_ESteamNetworkingAvailability_CannotTry = -102,		// 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.)
116 	k_ESteamNetworkingAvailability_Failed = -101,			// We have tried for enough time that we would expect to have been successful by now.  We have never been successful
117 	k_ESteamNetworkingAvailability_Previously = -100,		// We tried and were successful at one time, but now it looks like we have a problem
118 
119 	k_ESteamNetworkingAvailability_Retrying = -10,		// We previously failed and are currently retrying
120 
121 	// Not a problem, but not ready either
122 	k_ESteamNetworkingAvailability_NeverTried = 1,		// We don't know because we haven't ever checked/tried
123 	k_ESteamNetworkingAvailability_Waiting = 2,			// We're waiting on a dependent resource to be acquired.  (E.g. we cannot obtain a cert until we are logged into Steam.  We cannot measure latency to relays until we have the network config.)
124 	k_ESteamNetworkingAvailability_Attempting = 3,		// We're actively trying now, but are not yet successful.
125 
126 	k_ESteamNetworkingAvailability_Current = 100,			// Resource is online/available
127 
128 
129 	k_ESteamNetworkingAvailability_Unknown = 0,			// Internal dummy/sentinel, or value is not applicable in this context
130 	k_ESteamNetworkingAvailability__Force32bit = 0x7fffffff,
131 };
132 
133 //
134 // Describing network hosts
135 //
136 
137 /// Different methods of describing the identity of a network host
138 enum ESteamNetworkingIdentityType
139 {
140 	// Dummy/empty/invalid.
141 	// Plese note that if we parse a string that we don't recognize
142 	// but that appears reasonable, we will NOT use this type.  Instead
143 	// we'll use k_ESteamNetworkingIdentityType_UnknownType.
144 	k_ESteamNetworkingIdentityType_Invalid = 0,
145 
146 	//
147 	// Basic platform-specific identifiers.
148 	//
149 	k_ESteamNetworkingIdentityType_SteamID = 16, // 64-bit CSteamID
150 
151 	//
152 	// Special identifiers.
153 	//
154 
155 	// Use their IP address (and port) as their "identity".
156 	// These types of identities are always unauthenticated.
157 	// They are useful for porting plain sockets code, and other
158 	// situations where you don't care about authentication.  In this
159 	// case, the local identity will be "localhost",
160 	// and the remote address will be their network address.
161 	//
162 	// We use the same type for either IPv4 or IPv6, and
163 	// the address is always store as IPv6.  We use IPv4
164 	// mapped addresses to handle IPv4.
165 	k_ESteamNetworkingIdentityType_IPAddress = 1,
166 
167 	// Generic string/binary blobs.  It's up to your app to interpret this.
168 	// This library can tell you if the remote host presented a certificate
169 	// signed by somebody you have chosen to trust, with this identity on it.
170 	// It's up to you to ultimately decide what this identity means.
171 	k_ESteamNetworkingIdentityType_GenericString = 2,
172 	k_ESteamNetworkingIdentityType_GenericBytes = 3,
173 
174 	// This identity type is used when we parse a string that looks like is a
175 	// valid identity, just of a kind that we don't recognize.  In this case, we
176 	// can often still communicate with the peer!  Allowing such identities
177 	// for types we do not recognize useful is very useful for forward
178 	// compatibility.
179 	k_ESteamNetworkingIdentityType_UnknownType = 4,
180 
181 	// Make sure this enum is stored in an int.
182 	k_ESteamNetworkingIdentityType__Force32bit = 0x7fffffff,
183 };
184 
185 #pragma pack(push,1)
186 
187 /// Store an IP and port.  IPv6 is always used; IPv4 is represented using
188 /// "IPv4-mapped" addresses: IPv4 aa.bb.cc.dd => IPv6 ::ffff:aabb:ccdd
189 /// (RFC 4291 section 2.5.5.2.)
190 struct SteamNetworkingIPAddr
191 {
192 	void Clear(); // Set everything to zero.  E.g. [::]:0
193 	bool IsIPv6AllZeros() const;  // Return true if the IP is ::0.  (Doesn't check port.)
194 	void SetIPv6( const uint8 *ipv6, uint16 nPort ); // Set IPv6 address.  IP is interpreted as bytes, so there are no endian issues.  (Same as inaddr_in6.)  The IP can be a mapped IPv4 address
195 	void SetIPv4( uint32 nIP, uint16 nPort ); // Sets to IPv4 mapped address.  IP and port are in host byte order.
196 	bool IsIPv4() const; // Return true if IP is mapped IPv4
197 	uint32 GetIPv4() const; // Returns IP in host byte order (e.g. aa.bb.cc.dd as 0xaabbccdd).  Returns 0 if IP is not mapped IPv4.
198 	void SetIPv6LocalHost( uint16 nPort = 0); // Set to the IPv6 localhost address ::1, and the specified port.
199 	bool IsLocalHost() const; // Return true if this identity is localhost.  (Either IPv6 ::1, or IPv4 127.0.0.1)
200 
201 	// Max length of the buffer needed to hold IP formatted using ToString, including '\0'
202 	// ([0123:4567:89ab:cdef:0123:4567:89ab:cdef]:12345)
203 	enum { k_cchMaxString = 48 };
204 
205 	/// Print to a string, with or without the port.  Mapped IPv4 addresses are printed
206 	/// as dotted decimal (12.34.56.78), otherwise this will print the canonical
207 	/// form according to RFC5952.  If you include the port, IPv6 will be surrounded by
208 	/// brackets, e.g. [::1:2]:80.  Your buffer should be at least k_cchMaxString bytes
209 	/// to avoid truncation
210 	///
211 	/// See also SteamNetworkingIdentityRender
212 	inline void ToString( char *buf, size_t cbBuf, bool bWithPort ) const;
213 
214 	/// Parse an IP address and optional port.  If a port is not present, it is set to 0.
215 	/// (This means that you cannot tell if a zero port was explicitly specified.)
216 	inline bool ParseString( const char *pszStr );
217 
218 	/// RFC4038, section 4.2
219 	struct IPv4MappedAddress {
220 		uint64 m_8zeros;
221 		uint16 m_0000;
222 		uint16 m_ffff;
223 		uint8 m_ip[ 4 ]; // NOTE: As bytes, i.e. network byte order
224 	};
225 
226 	union
227 	{
228 		uint8 m_ipv6[ 16 ];
229 		IPv4MappedAddress m_ipv4;
230 	};
231 	uint16 m_port; // Host byte order
232 
233 	/// See if two addresses are identical
234 	bool operator==(const SteamNetworkingIPAddr &x ) const;
235 };
236 
237 /// An abstract way to represent the identity of a network host.  All identities can
238 /// be represented as simple string.  Furthermore, this string representation is actually
239 /// used on the wire in several places, even though it is less efficient, in order to
240 /// facilitate forward compatibility.  (Old client code can handle an identity type that
241 /// it doesn't understand.)
242 struct SteamNetworkingIdentity
243 {
244 	/// Type of identity.
245 	ESteamNetworkingIdentityType m_eType;
246 
247 	//
248 	// Get/Set in various formats.
249 	//
250 
251 	void Clear();
252 	bool IsInvalid() const; // Return true if we are the invalid type.  Does not make any other validity checks (e.g. is SteamID actually valid)
253 
254 	void SetSteamID( CSteamID steamID );
255 	CSteamID GetSteamID() const; // Return black CSteamID (!IsValid()) if identity is not a SteamID
256 	void SetSteamID64( uint64 steamID ); // Takes SteamID as raw 64-bit number
257 	uint64 GetSteamID64() const; // Returns 0 if identity is not SteamID
258 
259 	void SetIPAddr( const SteamNetworkingIPAddr &addr ); // Set to specified IP:port
260 	const SteamNetworkingIPAddr *GetIPAddr() const; // returns null if we are not an IP address.
261 	void SetIPv4Addr( uint32 nIPv4, uint16 nPort ); // Set to specified IPv4:port
262 	uint32 GetIPv4() const; // returns 0 if we are not an IPv4 address.
263 
264 	// "localhost" is equivalent for many purposes to "anonymous."  Our remote
265 	// will identify us by the network address we use.
266 	void SetLocalHost(); // Set to localhost.  (We always use IPv6 ::1 for this, not 127.0.0.1)
267 	bool IsLocalHost() const; // Return true if this identity is localhost.
268 
269 	bool SetGenericString( const char *pszString ); // Returns false if invalid length
270 	const char *GetGenericString() const; // Returns nullptr if not generic string type
271 
272 	bool SetGenericBytes( const void *data, size_t cbLen ); // Returns false if invalid size.
273 	const uint8 *GetGenericBytes( int &cbLen ) const; // Returns null if not generic bytes type
274 
275 	/// See if two identities are identical
276 	bool operator==(const SteamNetworkingIdentity &x ) const;
277 
278 	/// Print to a human-readable string.  This is suitable for debug messages
279 	/// or any other time you need to encode the identity as a string.  It has a
280 	/// URL-like format (type:<type-data>).  Your buffer should be at least
281 	/// k_cchMaxString bytes big to avoid truncation.
282 	///
283 	/// See also SteamNetworkingIPAddrRender
284 	void ToString( char *buf, size_t cbBuf ) const;
285 
286 	/// Parse back a string that was generated using ToString.  If we don't understand the
287 	/// string, but it looks "reasonable" (it matches the pattern type:<type-data> and doesn't
288 	/// have any funky characters, etc), then we will return true, and the type is set to
289 	/// k_ESteamNetworkingIdentityType_UnknownType.  false will only be returned if the string
290 	/// looks invalid.
291 	bool ParseString( const char *pszStr );
292 
293 	// Max sizes
294 	enum {
295 		k_cchMaxString = 128, // Max length of the buffer needed to hold any identity, formatted in string format by ToString
296 		k_cchMaxGenericString = 32, // Max length of the string for generic string identities.  Including terminating '\0'
297 		k_cbMaxGenericBytes = 32,
298 	};
299 
300 	//
301 	// Internal representation.  Don't access this directly, use the accessors!
302 	//
303 	// Number of bytes that are relevant below.  This MUST ALWAYS be
304 	// set.  (Use the accessors!)  This is important to enable old code to work
305 	// with new identity types.
306 	int m_cbSize;
307 	union {
308 		uint64 m_steamID64;
309 		char m_szGenericString[ k_cchMaxGenericString ];
310 		uint8 m_genericBytes[ k_cbMaxGenericBytes ];
311 		char m_szUnknownRawString[ k_cchMaxString ];
312 		SteamNetworkingIPAddr m_ip;
313 		uint32 m_reserved[ 32 ]; // Pad structure to leave easy room for future expansion
314 	};
315 };
316 #pragma pack(pop)
317 
318 //
319 // Connection status
320 //
321 
322 /// High level connection status
323 enum ESteamNetworkingConnectionState
324 {
325 
326 	/// Dummy value used to indicate an error condition in the API.
327 	/// Specified connection doesn't exist or has already been closed.
328 	k_ESteamNetworkingConnectionState_None = 0,
329 
330 	/// We are trying to establish whether peers can talk to each other,
331 	/// whether they WANT to talk to each other, perform basic auth,
332 	/// and exchange crypt keys.
333 	///
334 	/// - For connections on the "client" side (initiated locally):
335 	///   We're in the process of trying to establish a connection.
336 	///   Depending on the connection type, we might not know who they are.
337 	///   Note that it is not possible to tell if we are waiting on the
338 	///   network to complete handshake packets, or for the application layer
339 	///   to accept the connection.
340 	///
341 	/// - For connections on the "server" side (accepted through listen socket):
342 	///   We have completed some basic handshake and the client has presented
343 	///   some proof of identity.  The connection is ready to be accepted
344 	///   using AcceptConnection().
345 	///
346 	/// In either case, any unreliable packets sent now are almost certain
347 	/// to be dropped.  Attempts to receive packets are guaranteed to fail.
348 	/// You may send messages if the send mode allows for them to be queued.
349 	/// but if you close the connection before the connection is actually
350 	/// established, any queued messages will be discarded immediately.
351 	/// (We will not attempt to flush the queue and confirm delivery to the
352 	/// remote host, which ordinarily happens when a connection is closed.)
353 	k_ESteamNetworkingConnectionState_Connecting = 1,
354 
355 	/// Some connection types use a back channel or trusted 3rd party
356 	/// for earliest communication.  If the server accepts the connection,
357 	/// then these connections switch into the rendezvous state.  During this
358 	/// state, we still have not yet established an end-to-end route (through
359 	/// the relay network), and so if you send any messages unreliable, they
360 	/// are going to be discarded.
361 	k_ESteamNetworkingConnectionState_FindingRoute = 2,
362 
363 	/// We've received communications from our peer (and we know
364 	/// who they are) and are all good.  If you close the connection now,
365 	/// we will make our best effort to flush out any reliable sent data that
366 	/// has not been acknowledged by the peer.  (But note that this happens
367 	/// from within the application process, so unlike a TCP connection, you are
368 	/// not totally handing it off to the operating system to deal with it.)
369 	k_ESteamNetworkingConnectionState_Connected = 3,
370 
371 	/// Connection has been closed by our peer, but not closed locally.
372 	/// The connection still exists from an API perspective.  You must close the
373 	/// handle to free up resources.  If there are any messages in the inbound queue,
374 	/// you may retrieve them.  Otherwise, nothing may be done with the connection
375 	/// except to close it.
376 	///
377 	/// This stats is similar to CLOSE_WAIT in the TCP state machine.
378 	k_ESteamNetworkingConnectionState_ClosedByPeer = 4,
379 
380 	/// A disruption in the connection has been detected locally.  (E.g. timeout,
381 	/// local internet connection disrupted, etc.)
382 	///
383 	/// The connection still exists from an API perspective.  You must close the
384 	/// handle to free up resources.
385 	///
386 	/// Attempts to send further messages will fail.  Any remaining received messages
387 	/// in the queue are available.
388 	k_ESteamNetworkingConnectionState_ProblemDetectedLocally = 5,
389 
390 //
391 // The following values are used internally and will not be returned by any API.
392 // We document them here to provide a little insight into the state machine that is used
393 // under the hood.
394 //
395 
396 	/// We've disconnected on our side, and from an API perspective the connection is closed.
397 	/// No more data may be sent or received.  All reliable data has been flushed, or else
398 	/// we've given up and discarded it.  We do not yet know for sure that the peer knows
399 	/// the connection has been closed, however, so we're just hanging around so that if we do
400 	/// get a packet from them, we can send them the appropriate packets so that they can
401 	/// know why the connection was closed (and not have to rely on a timeout, which makes
402 	/// it appear as if something is wrong).
403 	k_ESteamNetworkingConnectionState_FinWait = -1,
404 
405 	/// We've disconnected on our side, and from an API perspective the connection is closed.
406 	/// No more data may be sent or received.  From a network perspective, however, on the wire,
407 	/// we have not yet given any indication to the peer that the connection is closed.
408 	/// We are in the process of flushing out the last bit of reliable data.  Once that is done,
409 	/// we will inform the peer that the connection has been closed, and transition to the
410 	/// FinWait state.
411 	///
412 	/// Note that no indication is given to the remote host that we have closed the connection,
413 	/// until the data has been flushed.  If the remote host attempts to send us data, we will
414 	/// do whatever is necessary to keep the connection alive until it can be closed properly.
415 	/// But in fact the data will be discarded, since there is no way for the application to
416 	/// read it back.  Typically this is not a problem, as application protocols that utilize
417 	/// the lingering functionality are designed for the remote host to wait for the response
418 	/// before sending any more data.
419 	k_ESteamNetworkingConnectionState_Linger = -2,
420 
421 	/// Connection is completely inactive and ready to be destroyed
422 	k_ESteamNetworkingConnectionState_Dead = -3,
423 
424 	k_ESteamNetworkingConnectionState__Force32Bit = 0x7fffffff
425 };
426 
427 /// Enumerate various causes of connection termination.  These are designed to work similar
428 /// to HTTP error codes: the numeric range gives you a rough classification as to the source
429 /// of the problem.
430 enum ESteamNetConnectionEnd
431 {
432 	// Invalid/sentinel value
433 	k_ESteamNetConnectionEnd_Invalid = 0,
434 
435 	//
436 	// Application codes.  These are the values you will pass to
437 	// ISteamNetworkingSockets::CloseConnection.  You can use these codes if
438 	// you want to plumb through application-specific reason codes.  If you don't
439 	// need this facility, feel free to always pass
440 	// k_ESteamNetConnectionEnd_App_Generic.
441 	//
442 	// The distinction between "normal" and "exceptional" termination is
443 	// one you may use if you find useful, but it's not necessary for you
444 	// to do so.  The only place where we distinguish between normal and
445 	// exceptional is in connection analytics.  If a significant
446 	// proportion of connections terminates in an exceptional manner,
447 	// this can trigger an alert.
448 	//
449 
450 	// 1xxx: Application ended the connection in a "usual" manner.
451 	//       E.g.: user intentionally disconnected from the server,
452 	//             gameplay ended normally, etc
453 	k_ESteamNetConnectionEnd_App_Min = 1000,
454 		k_ESteamNetConnectionEnd_App_Generic = k_ESteamNetConnectionEnd_App_Min,
455 		// Use codes in this range for "normal" disconnection
456 	k_ESteamNetConnectionEnd_App_Max = 1999,
457 
458 	// 2xxx: Application ended the connection in some sort of exceptional
459 	//       or unusual manner that might indicate a bug or configuration
460 	//       issue.
461 	//
462 	k_ESteamNetConnectionEnd_AppException_Min = 2000,
463 		k_ESteamNetConnectionEnd_AppException_Generic = k_ESteamNetConnectionEnd_AppException_Min,
464 		// Use codes in this range for "unusual" disconnection
465 	k_ESteamNetConnectionEnd_AppException_Max = 2999,
466 
467 	//
468 	// System codes.  These will be returned by the system when
469 	// the connection state is k_ESteamNetworkingConnectionState_ClosedByPeer
470 	// or k_ESteamNetworkingConnectionState_ProblemDetectedLocally.  It is
471 	// illegal to pass a code in this range to ISteamNetworkingSockets::CloseConnection
472 	//
473 
474 	// 3xxx: Connection failed or ended because of problem with the
475 	//       local host or their connection to the Internet.
476 	k_ESteamNetConnectionEnd_Local_Min = 3000,
477 
478 		// You cannot do what you want to do because you're running in offline mode.
479 		k_ESteamNetConnectionEnd_Local_OfflineMode = 3001,
480 
481 		// We're having trouble contacting many (perhaps all) relays.
482 		// Since it's unlikely that they all went offline at once, the best
483 		// explanation is that we have a problem on our end.  Note that we don't
484 		// bother distinguishing between "many" and "all", because in practice,
485 		// it takes time to detect a connection problem, and by the time
486 		// the connection has timed out, we might not have been able to
487 		// actively probe all of the relay clusters, even if we were able to
488 		// contact them at one time.  So this code just means that:
489 		//
490 		// * We don't have any recent successful communication with any relay.
491 		// * We have evidence of recent failures to communicate with multiple relays.
492 		k_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002,
493 
494 		// A hosted server is having trouble talking to the relay
495 		// that the client was using, so the problem is most likely
496 		// on our end
497 		k_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003,
498 
499 		// We're not able to get the SDR network config.  This is
500 		// *almost* always a local issue, since the network config
501 		// comes from the CDN, which is pretty darn reliable.
502 		k_ESteamNetConnectionEnd_Local_NetworkConfig = 3004,
503 
504 		// Steam rejected our request because we don't have rights
505 		// to do this.
506 		k_ESteamNetConnectionEnd_Local_Rights = 3005,
507 
508 		// ICE P2P rendezvous failed because we were not able to
509 		// determine our "public" address (e.g. reflexive address via STUN)
510 		//
511 		// If relay fallback is available (it always is on Steam), then
512 		// this is only used internally and will not be returned as a high
513 		// level failure.
514 		k_ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses = 3006,
515 
516 	k_ESteamNetConnectionEnd_Local_Max = 3999,
517 
518 	// 4xxx: Connection failed or ended, and it appears that the
519 	//       cause does NOT have to do with the local host or their
520 	//       connection to the Internet.  It could be caused by the
521 	//       remote host, or it could be somewhere in between.
522 	k_ESteamNetConnectionEnd_Remote_Min = 4000,
523 
524 		// The connection was lost, and as far as we can tell our connection
525 		// to relevant services (relays) has not been disrupted.  This doesn't
526 		// mean that the problem is "their fault", it just means that it doesn't
527 		// appear that we are having network issues on our end.
528 		k_ESteamNetConnectionEnd_Remote_Timeout = 4001,
529 
530 		// Something was invalid with the cert or crypt handshake
531 		// info you gave me, I don't understand or like your key types,
532 		// etc.
533 		k_ESteamNetConnectionEnd_Remote_BadCrypt = 4002,
534 
535 		// You presented me with a cert that was I was able to parse
536 		// and *technically* we could use encrypted communication.
537 		// But there was a problem that prevents me from checking your identity
538 		// or ensuring that somebody int he middle can't observe our communication.
539 		// E.g.: - the CA key was missing (and I don't accept unsigned certs)
540 		// - The CA key isn't one that I trust,
541 		// - The cert doesn't was appropriately restricted by app, user, time, data center, etc.
542 		// - The cert wasn't issued to you.
543 		// - etc
544 		k_ESteamNetConnectionEnd_Remote_BadCert = 4003,
545 
546 		// These will never be returned
547 		//k_ESteamNetConnectionEnd_Remote_NotLoggedIn_DEPRECATED = 4004,
548 		//k_ESteamNetConnectionEnd_Remote_NotRunningApp_DEPRECATED = 4005,
549 
550 		// Something wrong with the protocol version you are using.
551 		// (Probably the code you are running is too old.)
552 		k_ESteamNetConnectionEnd_Remote_BadProtocolVersion = 4006,
553 
554 		// NAT punch failed failed because we never received any public
555 		// addresses from the remote host.  (But we did receive some
556 		// signals form them.)
557 		//
558 		// If relay fallback is available (it always is on Steam), then
559 		// this is only used internally and will not be returned as a high
560 		// level failure.
561 		k_ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses = 4007,
562 
563 	k_ESteamNetConnectionEnd_Remote_Max = 4999,
564 
565 	// 5xxx: Connection failed for some other reason.
566 	k_ESteamNetConnectionEnd_Misc_Min = 5000,
567 
568 		// A failure that isn't necessarily the result of a software bug,
569 		// but that should happen rarely enough that it isn't worth specifically
570 		// writing UI or making a localized message for.
571 		// The debug string should contain further details.
572 		k_ESteamNetConnectionEnd_Misc_Generic = 5001,
573 
574 		// Generic failure that is most likely a software bug.
575 		k_ESteamNetConnectionEnd_Misc_InternalError = 5002,
576 
577 		// The connection to the remote host timed out, but we
578 		// don't know if the problem is on our end, in the middle,
579 		// or on their end.
580 		k_ESteamNetConnectionEnd_Misc_Timeout = 5003,
581 
582 		//k_ESteamNetConnectionEnd_Misc_RelayConnectivity_DEPRECATED = 5004,
583 
584 		// There's some trouble talking to Steam.
585 		k_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005,
586 
587 		// A server in a dedicated hosting situation has no relay sessions
588 		// active with which to talk back to a client.  (It's the client's
589 		// job to open and maintain those sessions.)
590 		k_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006,
591 
592 		// While trying to initiate a connection, we never received
593 		// *any* communication from the peer.
594 		//k_ESteamNetConnectionEnd_Misc_ServerNeverReplied = 5007,
595 
596 		// P2P rendezvous failed in a way that we don't have more specific
597 		// information
598 		k_ESteamNetConnectionEnd_Misc_P2P_Rendezvous = 5008,
599 
600 		// NAT punch failed, probably due to NAT/firewall configuration.
601 		//
602 		// If relay fallback is available (it always is on Steam), then
603 		// this is only used internally and will not be returned as a high
604 		// level failure.
605 		k_ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall = 5009,
606 
607 		// Our peer replied that it has no record of the connection.
608 		// This should not happen ordinarily, but can happen in a few
609 		// exception cases:
610 		//
611 		// - This is an old connection, and the peer has already cleaned
612 		//   up and forgotten about it.  (Perhaps it timed out and they
613 		//   closed it and were not able to communicate this to us.)
614 		// - A bug or internal protocol error has caused us to try to
615 		//   talk to the peer about the connection before we received
616 		//   confirmation that the peer has accepted the connection.
617 		// - The peer thinks that we have closed the connection for some
618 		//   reason (perhaps a bug), and believes that is it is
619 		//   acknowledging our closure.
620 		k_ESteamNetConnectionEnd_Misc_PeerSentNoConnection = 5010,
621 
622 	k_ESteamNetConnectionEnd_Misc_Max = 5999,
623 
624 	k_ESteamNetConnectionEnd__Force32Bit = 0x7fffffff
625 };
626 
627 /// Max length, in bytes (including null terminator) of the reason string
628 /// when a connection is closed.
629 const int k_cchSteamNetworkingMaxConnectionCloseReason = 128;
630 
631 /// Max length, in bytes (include null terminator) of debug description
632 /// of a connection.
633 const int k_cchSteamNetworkingMaxConnectionDescription = 128;
634 
635 const int k_nSteamNetworkConnectionInfoFlags_Unauthenticated = 1; // We don't have a certificate for the remote host.
636 const int k_nSteamNetworkConnectionInfoFlags_Unencrypted = 2; // Information is being sent out over a wire unencrypted (by this library)
637 const int k_nSteamNetworkConnectionInfoFlags_LoopbackBuffers = 4; // Internal loopback buffers.  Won't be true for localhost.  (You can check the address to determine that.)  This implies k_nSteamNetworkConnectionInfoFlags_FastLAN
638 const int k_nSteamNetworkConnectionInfoFlags_Fast = 8; // The connection is "fast" and "reliable".  Either internal/localhost (check the address to find out), or the peer is on the same LAN.  (Probably.  It's based on the address and the ping time, this is actually hard to determine unambiguously).
639 const int k_nSteamNetworkConnectionInfoFlags_Relayed = 16; // The connection is relayed somehow (SDR or TURN).
640 const int k_nSteamNetworkConnectionInfoFlags_DualWifi = 32; // We're taking advantage of dual-wifi multi-path
641 
642 /// Describe the state of a connection.
643 struct SteamNetConnectionInfo_t
644 {
645 
646 	/// Who is on the other end?  Depending on the connection type and phase of the connection, we might not know
647 	SteamNetworkingIdentity m_identityRemote;
648 
649 	/// Arbitrary user data set by the local application code
650 	int64 m_nUserData;
651 
652 	/// Handle to listen socket this was connected on, or k_HSteamListenSocket_Invalid if we initiated the connection
653 	HSteamListenSocket m_hListenSocket;
654 
655 	/// Remote address.  Might be all 0's if we don't know it, or if this is N/A.
656 	/// (E.g. Basically everything except direct UDP connection.)
657 	SteamNetworkingIPAddr m_addrRemote;
658 	uint16 m__pad1;
659 
660 	/// What data center is the remote host in?  (0 if we don't know.)
661 	SteamNetworkingPOPID m_idPOPRemote;
662 
663 	/// What relay are we using to communicate with the remote host?
664 	/// (0 if not applicable.)
665 	SteamNetworkingPOPID m_idPOPRelay;
666 
667 	/// High level state of the connection
668 	ESteamNetworkingConnectionState m_eState;
669 
670 	/// Basic cause of the connection termination or problem.
671 	/// See ESteamNetConnectionEnd for the values used
672 	int m_eEndReason;
673 
674 	/// Human-readable, but non-localized explanation for connection
675 	/// termination or problem.  This is intended for debugging /
676 	/// diagnostic purposes only, not to display to users.  It might
677 	/// have some details specific to the issue.
678 	char m_szEndDebug[ k_cchSteamNetworkingMaxConnectionCloseReason ];
679 
680 	/// Debug description.  This includes the internal connection ID,
681 	/// connection type (and peer information), and any name
682 	/// given to the connection by the app.  This string is used in various
683 	/// internal logging messages.
684 	char m_szConnectionDescription[ k_cchSteamNetworkingMaxConnectionDescription ];
685 
686 	/// Misc flags.  Bitmask of k_nSteamNetworkConnectionInfoFlags_Xxxx
687 	int m_nFlags;
688 
689 	/// Internal stuff, room to change API easily
690 	uint32 reserved[63];
691 };
692 
693 /// Quick connection state, pared down to something you could call
694 /// more frequently without it being too big of a perf hit.
695 struct SteamNetworkingQuickConnectionStatus
696 {
697 
698 	/// High level state of the connection
699 	ESteamNetworkingConnectionState m_eState;
700 
701 	/// Current ping (ms)
702 	int m_nPing;
703 
704 	/// Connection quality measured locally, 0...1.  (Percentage of packets delivered
705 	/// end-to-end in order).
706 	float m_flConnectionQualityLocal;
707 
708 	/// Packet delivery success rate as observed from remote host
709 	float m_flConnectionQualityRemote;
710 
711 	/// Current data rates from recent history.
712 	float m_flOutPacketsPerSec;
713 	float m_flOutBytesPerSec;
714 	float m_flInPacketsPerSec;
715 	float m_flInBytesPerSec;
716 
717 	/// Estimate rate that we believe that we can send data to our peer.
718 	/// Note that this could be significantly higher than m_flOutBytesPerSec,
719 	/// meaning the capacity of the channel is higher than you are sending data.
720 	/// (That's OK!)
721 	int m_nSendRateBytesPerSecond;
722 
723 	/// Number of bytes pending to be sent.  This is data that you have recently
724 	/// requested to be sent but has not yet actually been put on the wire.  The
725 	/// reliable number ALSO includes data that was previously placed on the wire,
726 	/// but has now been scheduled for re-transmission.  Thus, it's possible to
727 	/// observe m_cbPendingReliable increasing between two checks, even if no
728 	/// calls were made to send reliable data between the checks.  Data that is
729 	/// awaiting the Nagle delay will appear in these numbers.
730 	int m_cbPendingUnreliable;
731 	int m_cbPendingReliable;
732 
733 	/// Number of bytes of reliable data that has been placed the wire, but
734 	/// for which we have not yet received an acknowledgment, and thus we may
735 	/// have to re-transmit.
736 	int m_cbSentUnackedReliable;
737 
738 	/// If you asked us to send a message right now, how long would that message
739 	/// sit in the queue before we actually started putting packets on the wire?
740 	/// (And assuming Nagle does not cause any packets to be delayed.)
741 	///
742 	/// In general, data that is sent by the application is limited by the
743 	/// bandwidth of the channel.  If you send data faster than this, it must
744 	/// be queued and put on the wire at a metered rate.  Even sending a small amount
745 	/// of data (e.g. a few MTU, say ~3k) will require some of the data to be delayed
746 	/// a bit.
747 	///
748 	/// In general, the estimated delay will be approximately equal to
749 	///
750 	///		( m_cbPendingUnreliable+m_cbPendingReliable ) / m_nSendRateBytesPerSecond
751 	///
752 	/// plus or minus one MTU.  It depends on how much time has elapsed since the last
753 	/// packet was put on the wire.  For example, the queue might have *just* been emptied,
754 	/// and the last packet placed on the wire, and we are exactly up against the send
755 	/// rate limit.  In that case we might need to wait for one packet's worth of time to
756 	/// elapse before we can send again.  On the other extreme, the queue might have data
757 	/// in it waiting for Nagle.  (This will always be less than one packet, because as soon
758 	/// as we have a complete packet we would send it.)  In that case, we might be ready
759 	/// to send data now, and this value will be 0.
760 	SteamNetworkingMicroseconds m_usecQueueTime;
761 
762 	/// Internal stuff, room to change API easily
763 	uint32 reserved[16];
764 };
765 
766 #pragma pack( pop )
767 
768 //
769 // Network messages
770 //
771 
772 /// Max size of a single message that we can SEND.
773 /// Note: We might be wiling to receive larger messages,
774 /// and our peer might, too.
775 const int k_cbMaxSteamNetworkingSocketsMessageSizeSend = 512 * 1024;
776 
777 /// A message that has been received.
778 struct SteamNetworkingMessage_t
779 {
780 
781 	/// Message payload
782 	void *m_pData;
783 
784 	/// Size of the payload.
785 	int m_cbSize;
786 
787 	/// For messages received on connections: what connection did this come from?
788 	/// For outgoing messages: what connection to send it to?
789 	/// Not used when using the ISteamNetworkingMessages interface
790 	HSteamNetConnection m_conn;
791 
792 	/// For inbound messages: Who sent this to us?
793 	/// For outbound messages on connections: not used.
794 	/// For outbound messages on the ad-hoc ISteamNetworkingMessages interface: who should we send this to?
795 	SteamNetworkingIdentity m_identityPeer;
796 
797 	/// For messages received on connections, this is the user data
798 	/// associated with the connection.
799 	///
800 	/// This is *usually* the same as calling GetConnection() and then
801 	/// fetching the user data associated with that connection, but for
802 	/// the following subtle differences:
803 	///
804 	/// - This user data will match the connection's user data at the time
805 	///   is captured at the time the message is returned by the API.
806 	///   If you subsequently change the userdata on the connection,
807 	///   this won't be updated.
808 	/// - This is an inline call, so it's *much* faster.
809 	/// - You might have closed the connection, so fetching the user data
810 	///   would not be possible.
811 	///
812 	/// Not used when sending messages,
813 	int64 m_nConnUserData;
814 
815 	/// Local timestamp when the message was received
816 	/// Not used for outbound messages.
817 	SteamNetworkingMicroseconds m_usecTimeReceived;
818 
819 	/// Message number assigned by the sender.
820 	/// This is not used for outbound messages
821 	int64 m_nMessageNumber;
822 
823 	/// Function used to free up m_pData.  This mechanism exists so that
824 	/// apps can create messages with buffers allocated from their own
825 	/// heap, and pass them into the library.  This function will
826 	/// usually be something like:
827 	///
828 	/// free( pMsg->m_pData );
829 	void (*m_pfnFreeData)( SteamNetworkingMessage_t *pMsg );
830 
831 	/// Function to used to decrement the internal reference count and, if
832 	/// it's zero, release the message.  You should not set this function pointer,
833 	/// or need to access this directly!  Use the Release() function instead!
834 	void (*m_pfnRelease)( SteamNetworkingMessage_t *pMsg );
835 
836 	/// When using ISteamNetworkingMessages, the channel number the message was received on
837 	/// (Not used for messages sent or received on "connections")
838 	int m_nChannel;
839 
840 	/// Bitmask of k_nSteamNetworkingSend_xxx flags.
841 	/// For received messages, only the k_nSteamNetworkingSend_Reliable bit is valid.
842 	/// For outbound messages, all bits are relevant
843 	int m_nFlags;
844 
845 	/// Arbitrary user data that you can use when sending messages using
846 	/// ISteamNetworkingUtils::AllocateMessage and ISteamNetworkingSockets::SendMessage.
847 	/// (The callback you set in m_pfnFreeData might use this field.)
848 	///
849 	/// Not used for received messages.
850 	int64 m_nUserData;
851 
852 	/// You MUST call this when you're done with the object,
853 	/// to free up memory, etc.
854 	inline void Release();
855 
856 	// For code compatibility, some accessors
857 #ifndef API_GEN
GetSizeSteamNetworkingMessage_t858 	inline uint32 GetSize() const { return m_cbSize; }
GetDataSteamNetworkingMessage_t859 	inline const void *GetData() const { return m_pData; }
GetChannelSteamNetworkingMessage_t860 	inline int GetChannel() const { return m_nChannel; }
GetConnectionSteamNetworkingMessage_t861 	inline HSteamNetConnection GetConnection() const { return m_conn; }
GetConnectionUserDataSteamNetworkingMessage_t862 	inline int64 GetConnectionUserData() const { return m_nConnUserData; }
GetTimeReceivedSteamNetworkingMessage_t863 	inline SteamNetworkingMicroseconds GetTimeReceived() const { return m_usecTimeReceived; }
GetMessageNumberSteamNetworkingMessage_t864 	inline int64 GetMessageNumber() const { return m_nMessageNumber; }
865 #endif
866 protected:
867 	// Declare destructor protected.  You should never need to declare a message
868 	// object on the stack or create one yourself.
869 	// - You will receive a pointer to a message object when you receive messages (e.g. ISteamNetworkingSockets::ReceiveMessagesOnConnection)
870 	// - You can allocate a message object for efficient sending using ISteamNetworkingUtils::AllocateMessage
871 	// - Call Release() to free the object
~SteamNetworkingMessage_tSteamNetworkingMessage_t872 	inline ~SteamNetworkingMessage_t() {}
873 };
874 
875 //
876 // Flags used to set options for message sending
877 //
878 
879 // Send the message unreliably. Can be lost.  Messages *can* be larger than a
880 // single MTU (UDP packet), but there is no retransmission, so if any piece
881 // of the message is lost, the entire message will be dropped.
882 //
883 // The sending API does have some knowledge of the underlying connection, so
884 // if there is no NAT-traversal accomplished or there is a recognized adjustment
885 // happening on the connection, the packet will be batched until the connection
886 // is open again.
887 //
888 // Migration note: This is not exactly the same as k_EP2PSendUnreliable!  You
889 // probably want k_ESteamNetworkingSendType_UnreliableNoNagle
890 const int k_nSteamNetworkingSend_Unreliable = 0;
891 
892 // Disable Nagle's algorithm.
893 // By default, Nagle's algorithm is applied to all outbound messages.  This means
894 // that the message will NOT be sent immediately, in case further messages are
895 // sent soon after you send this, which can be grouped together.  Any time there
896 // is enough buffered data to fill a packet, the packets will be pushed out immediately,
897 // but partially-full packets not be sent until the Nagle timer expires.  See
898 // ISteamNetworkingSockets::FlushMessagesOnConnection, ISteamNetworkingMessages::FlushMessagesToUser
899 //
900 // NOTE: Don't just send every message without Nagle because you want packets to get there
901 // quicker.  Make sure you understand the problem that Nagle is solving before disabling it.
902 // If you are sending small messages, often many at the same time, then it is very likely that
903 // it will be more efficient to leave Nagle enabled.  A typical proper use of this flag is
904 // when you are sending what you know will be the last message sent for a while (e.g. the last
905 // in the server simulation tick to a particular client), and you use this flag to flush all
906 // messages.
907 const int k_nSteamNetworkingSend_NoNagle = 1;
908 
909 // Send a message unreliably, bypassing Nagle's algorithm for this message and any messages
910 // currently pending on the Nagle timer.  This is equivalent to using k_ESteamNetworkingSend_Unreliable
911 // and then immediately flushing the messages using ISteamNetworkingSockets::FlushMessagesOnConnection
912 // or ISteamNetworkingMessages::FlushMessagesToUser.  (But using this flag is more efficient since you
913 // only make one API call.)
914 const int k_nSteamNetworkingSend_UnreliableNoNagle = k_nSteamNetworkingSend_Unreliable|k_nSteamNetworkingSend_NoNagle;
915 
916 // If the message cannot be sent very soon (because the connection is still doing some initial
917 // handshaking, route negotiations, etc), then just drop it.  This is only applicable for unreliable
918 // messages.  Using this flag on reliable messages is invalid.
919 const int k_nSteamNetworkingSend_NoDelay = 4;
920 
921 // Send an unreliable message, but if it cannot be sent relatively quickly, just drop it instead of queuing it.
922 // This is useful for messages that are not useful if they are excessively delayed, such as voice data.
923 // NOTE: The Nagle algorithm is not used, and if the message is not dropped, any messages waiting on the
924 // Nagle timer are immediately flushed.
925 //
926 // A message will be dropped under the following circumstances:
927 // - the connection is not fully connected.  (E.g. the "Connecting" or "FindingRoute" states)
928 // - there is a sufficiently large number of messages queued up already such that the current message
929 //   will not be placed on the wire in the next ~200ms or so.
930 //
931 // If a message is dropped for these reasons, k_EResultIgnored will be returned.
932 const int k_nSteamNetworkingSend_UnreliableNoDelay = k_nSteamNetworkingSend_Unreliable|k_nSteamNetworkingSend_NoDelay|k_nSteamNetworkingSend_NoNagle;
933 
934 // Reliable message send. Can send up to k_cbMaxSteamNetworkingSocketsMessageSizeSend bytes in a single message.
935 // Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for
936 // efficient sends of large chunks of data.
937 //
938 // The Nagle algorithm is used.  See notes on k_ESteamNetworkingSendType_Unreliable for more details.
939 // See k_ESteamNetworkingSendType_ReliableNoNagle, ISteamNetworkingSockets::FlushMessagesOnConnection,
940 // ISteamNetworkingMessages::FlushMessagesToUser
941 //
942 // Migration note: This is NOT the same as k_EP2PSendReliable, it's more like k_EP2PSendReliableWithBuffering
943 const int k_nSteamNetworkingSend_Reliable = 8;
944 
945 // Send a message reliably, but bypass Nagle's algorithm.
946 //
947 // Migration note: This is equivalent to k_EP2PSendReliable
948 const int k_nSteamNetworkingSend_ReliableNoNagle = k_nSteamNetworkingSend_Reliable|k_nSteamNetworkingSend_NoNagle;
949 
950 // By default, message sending is queued, and the work of encryption and talking to
951 // the operating system sockets, etc is done on a service thread.  This is usually a
952 // a performance win when messages are sent from the "main thread".  However, if this
953 // flag is set, and data is ready to be sent immediately (either from this message
954 // or earlier queued data), then that work will be done in the current thread, before
955 // the current call returns.  If data is not ready to be sent (due to rate limiting
956 // or Nagle), then this flag has no effect.
957 //
958 // This is an advanced flag used to control performance at a very low level.  For
959 // most applications running on modern hardware with more than one CPU core, doing
960 // the work of sending on a service thread will yield the best performance.  Only
961 // use this flag if you have a really good reason and understand what you are doing.
962 // Otherwise you will probably just make performance worse.
963 const int k_nSteamNetworkingSend_UseCurrentThread = 16;
964 
965 // When sending a message using ISteamNetworkingMessages, automatically re-establish
966 // a broken session, without returning k_EResultNoConnection.  Without this flag,
967 // if you attempt to send a message, and the session was proactively closed by the
968 // peer, or an error occurred that disrupted communications, then you must close the
969 // session using ISteamNetworkingMessages::CloseSessionWithUser before attempting to
970 // send another message.  (Or you can simply add this flag and retry.)  In this way,
971 // the disruption cannot go unnoticed, and a more clear order of events can be
972 // ascertained. This is especially important when reliable messages are used, since
973 // if the connection is disrupted, some of those messages will not have been delivered,
974 // and it is in general not possible to know which.  Although a
975 // SteamNetworkingMessagesSessionFailed_t callback will be posted when an error occurs
976 // to notify you that a failure has happened, callbacks are asynchronous, so it is not
977 // possible to tell exactly when it happened.  And because the primary purpose of
978 // ISteamNetworkingMessages is to be like UDP, there is no notification when a peer closes
979 // the session.
980 //
981 // If you are not using any reliable messages (e.g. you are using ISteamNetworkingMessages
982 // exactly as a transport replacement for UDP-style datagrams only), you may not need to
983 // know when an underlying connection fails, and so you may not need this notification.
984 const int k_nSteamNetworkingSend_AutoRestartBrokenSession = 32;
985 
986 //
987 // Ping location / measurement
988 //
989 
990 /// Object that describes a "location" on the Internet with sufficient
991 /// detail that we can reasonably estimate an upper bound on the ping between
992 /// the two hosts, even if a direct route between the hosts is not possible,
993 /// and the connection must be routed through the Steam Datagram Relay network.
994 /// This does not contain any information that identifies the host.  Indeed,
995 /// if two hosts are in the same building or otherwise have nearly identical
996 /// networking characteristics, then it's valid to use the same location
997 /// object for both of them.
998 ///
999 /// NOTE: This object should only be used in the same process!  Do not serialize it,
1000 /// send it over the wire, or persist it in a file or database!  If you need
1001 /// to do that, convert it to a string representation using the methods in
1002 /// ISteamNetworkingUtils().
1003 struct SteamNetworkPingLocation_t
1004 {
1005 	uint8 m_data[ 512 ];
1006 };
1007 
1008 /// Max possible length of a ping location, in string format.  This is
1009 /// an extremely conservative worst case value which leaves room for future
1010 /// syntax enhancements.  Most strings in practice are a lot shorter.
1011 /// If you are storing many of these, you will very likely benefit from
1012 /// using dynamic memory.
1013 const int k_cchMaxSteamNetworkingPingLocationString = 1024;
1014 
1015 /// Special values that are returned by some functions that return a ping.
1016 const int k_nSteamNetworkingPing_Failed = -1;
1017 const int k_nSteamNetworkingPing_Unknown = -2;
1018 
1019 //
1020 // Configuration values
1021 //
1022 
1023 /// Configuration values can be applied to different types of objects.
1024 enum ESteamNetworkingConfigScope
1025 {
1026 
1027 	/// Get/set global option, or defaults.  Even options that apply to more specific scopes
1028 	/// have global scope, and you may be able to just change the global defaults.  If you
1029 	/// need different settings per connection (for example), then you will need to set those
1030 	/// options at the more specific scope.
1031 	k_ESteamNetworkingConfig_Global = 1,
1032 
1033 	/// Some options are specific to a particular interface.  Note that all connection
1034 	/// and listen socket settings can also be set at the interface level, and they will
1035 	/// apply to objects created through those interfaces.
1036 	k_ESteamNetworkingConfig_SocketsInterface = 2,
1037 
1038 	/// Options for a listen socket.  Listen socket options can be set at the interface layer,
1039 	/// if  you have multiple listen sockets and they all use the same options.
1040 	/// You can also set connection options on a listen socket, and they set the defaults
1041 	/// for all connections accepted through this listen socket.  (They will be used if you don't
1042 	/// set a connection option.)
1043 	k_ESteamNetworkingConfig_ListenSocket = 3,
1044 
1045 	/// Options for a specific connection.
1046 	k_ESteamNetworkingConfig_Connection = 4,
1047 
1048 	k_ESteamNetworkingConfigScope__Force32Bit = 0x7fffffff
1049 };
1050 
1051 // Different configuration values have different data types
1052 enum ESteamNetworkingConfigDataType
1053 {
1054 	k_ESteamNetworkingConfig_Int32 = 1,
1055 	k_ESteamNetworkingConfig_Int64 = 2,
1056 	k_ESteamNetworkingConfig_Float = 3,
1057 	k_ESteamNetworkingConfig_String = 4,
1058 	k_ESteamNetworkingConfig_Ptr = 5,
1059 
1060 	k_ESteamNetworkingConfigDataType__Force32Bit = 0x7fffffff
1061 };
1062 
1063 /// Configuration options
1064 enum ESteamNetworkingConfigValue
1065 {
1066 	k_ESteamNetworkingConfig_Invalid = 0,
1067 
1068 //
1069 // Connection options
1070 //
1071 
1072 	/// [connection int32] Timeout value (in ms) to use when first connecting
1073 	k_ESteamNetworkingConfig_TimeoutInitial = 24,
1074 
1075 	/// [connection int32] Timeout value (in ms) to use after connection is established
1076 	k_ESteamNetworkingConfig_TimeoutConnected = 25,
1077 
1078 	/// [connection int32] Upper limit of buffered pending bytes to be sent,
1079 	/// if this is reached SendMessage will return k_EResultLimitExceeded
1080 	/// Default is 512k (524288 bytes)
1081 	k_ESteamNetworkingConfig_SendBufferSize = 9,
1082 
1083 	/// [connection int64] Get/set userdata as a configuration option.
1084 	/// The default value is -1.   You may want to set the user data as
1085 	/// a config value, instead of using ISteamNetworkingSockets::SetConnectionUserData
1086 	/// in two specific instances:
1087 	///
1088 	/// - You wish to set the userdata atomically when creating
1089 	///   an outbound connection, so that the userdata is filled in properly
1090 	///   for any callbacks that happen.  However, note that this trick
1091 	///   only works for connections initiated locally!  For incoming
1092 	///   connections, multiple state transitions may happen and
1093 	///   callbacks be queued, before you are able to service the first
1094 	///   callback!  Be careful!
1095 	///
1096 	/// - You can set the default userdata for all newly created connections
1097 	///   by setting this value at a higher level (e.g. on the listen
1098 	///   socket or at the global level.)  Then this default
1099 	///   value will be inherited when the connection is created.
1100 	///   This is useful in case -1 is a valid userdata value, and you
1101 	///   wish to use something else as the default value so you can
1102 	///   tell if it has been set or not.
1103 	///
1104 	///   HOWEVER: once a connection is created, the effective value is
1105 	///   then bound to the connection.  Unlike other connection options,
1106 	///   if you change it again at a higher level, the new value will not
1107 	///   be inherited by connections.
1108 	///
1109 	/// Using the userdata field in callback structs is not advised because
1110 	/// of tricky race conditions.  Instead, you might try one of these methods:
1111 	///
1112 	/// - Use a separate map with the HSteamNetConnection as the key.
1113 	/// - Fetch the userdata from the connection in your callback
1114 	///   using ISteamNetworkingSockets::GetConnectionUserData, to
1115 	//    ensure you have the current value.
1116 	k_ESteamNetworkingConfig_ConnectionUserData = 40,
1117 
1118 	/// [connection int32] Minimum/maximum send rate clamp, 0 is no limit.
1119 	/// This value will control the min/max allowed sending rate that
1120 	/// bandwidth estimation is allowed to reach.  Default is 0 (no-limit)
1121 	k_ESteamNetworkingConfig_SendRateMin = 10,
1122 	k_ESteamNetworkingConfig_SendRateMax = 11,
1123 
1124 	/// [connection int32] Nagle time, in microseconds.  When SendMessage is called, if
1125 	/// the outgoing message is less than the size of the MTU, it will be
1126 	/// queued for a delay equal to the Nagle timer value.  This is to ensure
1127 	/// that if the application sends several small messages rapidly, they are
1128 	/// coalesced into a single packet.
1129 	/// See historical RFC 896.  Value is in microseconds.
1130 	/// Default is 5000us (5ms).
1131 	k_ESteamNetworkingConfig_NagleTime = 12,
1132 
1133 	/// [connection int32] Don't automatically fail IP connections that don't have
1134 	/// strong auth.  On clients, this means we will attempt the connection even if
1135 	/// we don't know our identity or can't get a cert.  On the server, it means that
1136 	/// we won't automatically reject a connection due to a failure to authenticate.
1137 	/// (You can examine the incoming connection and decide whether to accept it.)
1138 	///
1139 	/// This is a dev configuration value, and you should not let users modify it in
1140 	/// production.
1141 	k_ESteamNetworkingConfig_IP_AllowWithoutAuth = 23,
1142 
1143 	/// [connection int32] Do not send UDP packets with a payload of
1144 	/// larger than N bytes.  If you set this, k_ESteamNetworkingConfig_MTU_DataSize
1145 	/// is automatically adjusted
1146 	k_ESteamNetworkingConfig_MTU_PacketSize = 32,
1147 
1148 	/// [connection int32] (read only) Maximum message size you can send that
1149 	/// will not fragment, based on k_ESteamNetworkingConfig_MTU_PacketSize
1150 	k_ESteamNetworkingConfig_MTU_DataSize = 33,
1151 
1152 	/// [connection int32] Allow unencrypted (and unauthenticated) communication.
1153 	/// 0: Not allowed (the default)
1154 	/// 1: Allowed, but prefer encrypted
1155 	/// 2: Allowed, and preferred
1156 	/// 3: Required.  (Fail the connection if the peer requires encryption.)
1157 	///
1158 	/// This is a dev configuration value, since its purpose is to disable encryption.
1159 	/// You should not let users modify it in production.  (But note that it requires
1160 	/// the peer to also modify their value in order for encryption to be disabled.)
1161 	k_ESteamNetworkingConfig_Unencrypted = 34,
1162 
1163 	/// [connection int32] Set this to 1 on outbound connections and listen sockets,
1164 	/// to enable "symmetric connect mode", which is useful in the following
1165 	/// common peer-to-peer use case:
1166 	///
1167 	/// - The two peers are "equal" to each other.  (Neither is clearly the "client"
1168 	///   or "server".)
1169 	/// - Either peer may initiate the connection, and indeed they may do this
1170 	///   at the same time
1171 	/// - The peers only desire a single connection to each other, and if both
1172 	///   peers initiate connections simultaneously, a protocol is needed for them
1173 	///   to resolve the conflict, so that we end up with a single connection.
1174 	///
1175 	/// This use case is both common, and involves subtle race conditions and tricky
1176 	/// pitfalls, which is why the API has support for dealing with it.
1177 	///
1178 	/// If an incoming connection arrives on a listen socket or via custom signaling,
1179 	/// and the application has not attempted to make a matching outbound connection
1180 	/// in symmetric mode, then the incoming connection can be accepted as usual.
1181 	/// A "matching" connection means that the relevant endpoint information matches.
1182 	/// (At the time this comment is being written, this is only supported for P2P
1183 	/// connections, which means that the peer identities must match, and the virtual
1184 	/// port must match.  At a later time, symmetric mode may be supported for other
1185 	/// connection types.)
1186 	///
1187 	/// If connections are initiated by both peers simultaneously, race conditions
1188 	/// can arise, but fortunately, most of them are handled internally and do not
1189 	/// require any special awareness from the application.  However, there
1190 	/// is one important case that application code must be aware of:
1191 	/// If application code attempts an outbound connection using a ConnectXxx
1192 	/// function in symmetric mode, and a matching incoming connection is already
1193 	/// waiting on a listen socket, then instead of forming a new connection,
1194 	/// the ConnectXxx call will accept the existing incoming connection, and return
1195 	/// a connection handle to this accepted connection.
1196 	/// IMPORTANT: in this case, a SteamNetConnectionStatusChangedCallback_t
1197 	/// has probably *already* been posted to the queue for the incoming connection!
1198 	/// (Once callbacks are posted to the queue, they are not modified.)  It doesn't
1199 	/// matter if the callback has not been consumed by the app.  Thus, application
1200 	/// code that makes use of symmetric connections must be aware that, when processing a
1201 	/// SteamNetConnectionStatusChangedCallback_t for an incoming connection, the
1202 	/// m_hConn may refer to a new connection that the app has has not
1203 	/// seen before (the usual case), but it may also refer to a connection that
1204 	/// has already been accepted implicitly through a call to Connect()!  In this
1205 	/// case, AcceptConnection() will return k_EResultDuplicateRequest.
1206 	///
1207 	/// Only one symmetric connection to a given peer (on a given virtual port)
1208 	/// may exist at any given time.  If client code attempts to create a connection,
1209 	/// and a (live) connection already exists on the local host, then either the
1210 	/// existing connection will be accepted as described above, or the attempt
1211 	/// to create a new connection will fail.  Furthermore, linger mode functionality
1212 	/// is not supported on symmetric connections.
1213 	///
1214 	/// A more complicated race condition can arise if both peers initiate a connection
1215 	/// at roughly the same time.  In this situation, each peer will receive an incoming
1216 	/// connection from the other peer, when the application code has already initiated
1217 	/// an outgoing connection to that peer.  The peers must resolve this conflict and
1218 	/// decide who is going to act as the "server" and who will act as the "client".
1219 	/// Typically the application does not need to be aware of this case as it is handled
1220 	/// internally.  On both sides, the will observe their outbound connection being
1221 	/// "accepted", although one of them one have been converted internally to act
1222 	/// as the "server".
1223 	///
1224 	/// In general, symmetric mode should be all-or-nothing: do not mix symmetric
1225 	/// connections with a non-symmetric connection that it might possible "match"
1226 	/// with.  If you use symmetric mode on any connections, then both peers should
1227 	/// use it on all connections, and the corresponding listen socket, if any.  The
1228 	/// behaviour when symmetric and ordinary connections are mixed is not defined by
1229 	/// this API, and you should not rely on it.  (This advice only applies when connections
1230 	/// might possibly "match".  For example, it's OK to use all symmetric mode
1231 	/// connections on one virtual port, and all ordinary, non-symmetric connections
1232 	/// on a different virtual port, as there is no potential for ambiguity.)
1233 	///
1234 	/// When using the feature, you should set it in the following situations on
1235 	/// applicable objects:
1236 	///
1237 	/// - When creating an outbound connection using ConnectXxx function
1238 	/// - When creating a listen socket.  (Note that this will automatically cause
1239 	///   any accepted connections to inherit the flag.)
1240 	/// - When using custom signaling, before accepting an incoming connection.
1241 	///
1242 	/// Setting the flag on listen socket and accepted connections will enable the
1243 	/// API to automatically deal with duplicate incoming connections, even if the
1244 	/// local host has not made any outbound requests.  (In general, such duplicate
1245 	/// requests from a peer are ignored internally and will not be visible to the
1246 	/// application code.  The previous connection must be closed or resolved first.)
1247 	k_ESteamNetworkingConfig_SymmetricConnect = 37,
1248 
1249 	/// [connection int32] For connection types that use "virtual ports", this can be used
1250 	/// to assign a local virtual port.  For incoming connections, this will always be the
1251 	/// virtual port of the listen socket (or the port requested by the remote host if custom
1252 	/// signaling is used and the connection is accepted), and cannot be changed.  For
1253 	/// connections initiated locally, the local virtual port will default to the same as the
1254 	/// requested remote virtual port, if you do not specify a different option when creating
1255 	/// the connection.  The local port is only relevant for symmetric connections, when
1256 	/// determining if two connections "match."  In this case, if you need the local and remote
1257 	/// port to differ, you can set this value.
1258 	///
1259 	/// You can also read back this value on listen sockets.
1260 	///
1261 	/// This value should not be read or written in any other context.
1262 	k_ESteamNetworkingConfig_LocalVirtualPort = 38,
1263 
1264 //
1265 // Simulating network conditions
1266 //
1267 // These are global (not per-connection) because they apply at
1268 // a relatively low UDP layer.
1269 //
1270 
1271 	/// [global float, 0--100] Randomly discard N pct of packets instead of sending/recv
1272 	/// This is a global option only, since it is applied at a low level
1273 	/// where we don't have much context
1274 	k_ESteamNetworkingConfig_FakePacketLoss_Send = 2,
1275 	k_ESteamNetworkingConfig_FakePacketLoss_Recv = 3,
1276 
1277 	/// [global int32].  Delay all outbound/inbound packets by N ms
1278 	k_ESteamNetworkingConfig_FakePacketLag_Send = 4,
1279 	k_ESteamNetworkingConfig_FakePacketLag_Recv = 5,
1280 
1281 	/// [global float] 0-100 Percentage of packets we will add additional delay
1282 	/// to (causing them to be reordered)
1283 	k_ESteamNetworkingConfig_FakePacketReorder_Send = 6,
1284 	k_ESteamNetworkingConfig_FakePacketReorder_Recv = 7,
1285 
1286 	/// [global int32] Extra delay, in ms, to apply to reordered packets.
1287 	k_ESteamNetworkingConfig_FakePacketReorder_Time = 8,
1288 
1289 	/// [global float 0--100] Globally duplicate some percentage of packets we send
1290 	k_ESteamNetworkingConfig_FakePacketDup_Send = 26,
1291 	k_ESteamNetworkingConfig_FakePacketDup_Recv = 27,
1292 
1293 	/// [global int32] Amount of delay, in ms, to delay duplicated packets.
1294 	/// (We chose a random delay between 0 and this value)
1295 	k_ESteamNetworkingConfig_FakePacketDup_TimeMax = 28,
1296 
1297 	/// [global int32] Trace every UDP packet, similar to Wireshark or tcpdump.
1298 	/// Value is max number of bytes to dump.  -1 disables tracing.
1299 	// 0 only traces the info but no actual data bytes
1300 	k_ESteamNetworkingConfig_PacketTraceMaxBytes = 41,
1301 
1302 
1303 	// [global int32] Global UDP token bucket rate limits.
1304 	// "Rate" refers to the steady state rate. (Bytes/sec, the
1305 	// rate that tokens are put into the bucket.)  "Burst"
1306 	// refers to the max amount that could be sent in a single
1307 	// burst.  (In bytes, the max capacity of the bucket.)
1308 	// Rate=0 disables the limiter entirely, which is the default.
1309 	// Burst=0 disables burst.  (This is not realistic.  A
1310 	// burst of at least 4K is recommended; the default is higher.)
1311 	k_ESteamNetworkingConfig_FakeRateLimit_Send_Rate = 42,
1312 	k_ESteamNetworkingConfig_FakeRateLimit_Send_Burst = 43,
1313 	k_ESteamNetworkingConfig_FakeRateLimit_Recv_Rate = 44,
1314 	k_ESteamNetworkingConfig_FakeRateLimit_Recv_Burst = 45,
1315 
1316 //
1317 // Callbacks
1318 //
1319 
1320 	// On Steam, you may use the default Steam callback dispatch mechanism.  If you prefer
1321 	// to not use this dispatch mechanism (or you are not running with Steam), or you want
1322 	// to associate specific functions with specific listen sockets or connections, you can
1323 	// register them as configuration values.
1324 	//
1325 	// Note also that ISteamNetworkingUtils has some helpers to set these globally.
1326 
1327 	/// [connection FnSteamNetConnectionStatusChanged] Callback that will be invoked
1328 	/// when the state of a connection changes.
1329 	///
1330 	/// IMPORTANT: callbacks are dispatched to the handler that is in effect at the time
1331 	/// the event occurs, which might be in another thread.  For example, immediately after
1332 	/// creating a listen socket, you may receive an incoming connection.  And then immediately
1333 	/// after this, the remote host may close the connection.  All of this could happen
1334 	/// before the function to create the listen socket has returned.  For this reason,
1335 	/// callbacks usually must be in effect at the time of object creation.  This means
1336 	/// you should set them when you are creating the listen socket or connection, or have
1337 	/// them in effect so they will be inherited at the time of object creation.
1338 	///
1339 	/// For example:
1340 	///
1341 	/// exterm void MyStatusChangedFunc( SteamNetConnectionStatusChangedCallback_t *info );
1342 	/// SteamNetworkingConfigValue_t opt; opt.SetPtr( k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, MyStatusChangedFunc );
1343 	/// SteamNetworkingIPAddr localAddress; localAddress.Clear();
1344 	/// HSteamListenSocket hListenSock = SteamNetworkingSockets()->CreateListenSocketIP( localAddress, 1, &opt );
1345 	///
1346 	/// When accepting an incoming connection, there is no atomic way to switch the
1347 	/// callback.  However, if the connection is DOA, AcceptConnection() will fail, and
1348 	/// you can fetch the state of the connection at that time.
1349 	///
1350 	/// If all connections and listen sockets can use the same callback, the simplest
1351 	/// method is to set it globally before you create any listen sockets or connections.
1352 	k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged = 201,
1353 
1354 	/// [global FnSteamNetAuthenticationStatusChanged] Callback that will be invoked
1355 	/// when our auth state changes.  If you use this, install the callback before creating
1356 	/// any connections or listen sockets, and don't change it.
1357 	/// See: ISteamNetworkingUtils::SetGlobalCallback_SteamNetAuthenticationStatusChanged
1358 	k_ESteamNetworkingConfig_Callback_AuthStatusChanged = 202,
1359 
1360 	/// [global FnSteamRelayNetworkStatusChanged] Callback that will be invoked
1361 	/// when our auth state changes.  If you use this, install the callback before creating
1362 	/// any connections or listen sockets, and don't change it.
1363 	/// See: ISteamNetworkingUtils::SetGlobalCallback_SteamRelayNetworkStatusChanged
1364 	k_ESteamNetworkingConfig_Callback_RelayNetworkStatusChanged = 203,
1365 
1366 	/// [global FnSteamNetworkingMessagesSessionRequest] Callback that will be invoked
1367 	/// when a peer wants to initiate a SteamNetworkingMessagesSessionRequest.
1368 	/// See: ISteamNetworkingUtils::SetGlobalCallback_MessagesSessionRequest
1369 	k_ESteamNetworkingConfig_Callback_MessagesSessionRequest = 204,
1370 
1371 	/// [global FnSteamNetworkingMessagesSessionFailed] Callback that will be invoked
1372 	/// when a session you have initiated, or accepted either fails to connect, or loses
1373 	/// connection in some unexpected way.
1374 	/// See: ISteamNetworkingUtils::SetGlobalCallback_MessagesSessionFailed
1375 	k_ESteamNetworkingConfig_Callback_MessagesSessionFailed = 205,
1376 
1377 	/// [global FnSteamNetworkingSocketsCreateConnectionSignaling] Callback that will
1378 	/// be invoked when we need to create a signaling object for a connection
1379 	/// initiated locally.  See: ISteamNetworkingSockets::ConnectP2P,
1380 	/// ISteamNetworkingMessages.
1381 	k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling = 206,
1382 
1383 //
1384 // P2P connection settings
1385 //
1386 
1387 //	/// [listen socket int32] When you create a P2P listen socket, we will automatically
1388 //	/// open up a UDP port to listen for LAN connections.  LAN connections can be made
1389 //	/// without any signaling: both sides can be disconnected from the Internet.
1390 //	///
1391 //	/// This value can be set to zero to disable the feature.
1392 //	k_ESteamNetworkingConfig_P2P_Discovery_Server_LocalPort = 101,
1393 //
1394 //	/// [connection int32] P2P connections can perform broadcasts looking for the peer
1395 //	/// on the LAN.
1396 //	k_ESteamNetworkingConfig_P2P_Discovery_Client_RemotePort = 102,
1397 
1398 	/// [connection string] Comma-separated list of STUN servers that can be used
1399 	/// for NAT piercing.  If you set this to an empty string, NAT piercing will
1400 	/// not be attempted.  Also if "public" candidates are not allowed for
1401 	/// P2P_Transport_ICE_Enable, then this is ignored.
1402 	k_ESteamNetworkingConfig_P2P_STUN_ServerList = 103,
1403 
1404 	/// [connection int32] What types of ICE candidates to share with the peer.
1405 	/// See k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_xxx values
1406 	k_ESteamNetworkingConfig_P2P_Transport_ICE_Enable = 104,
1407 
1408 	/// [connection int32] When selecting P2P transport, add various
1409 	/// penalties to the scores for selected transports.  (Route selection
1410 	/// scores are on a scale of milliseconds.  The score begins with the
1411 	/// route ping time and is then adjusted.)
1412 	k_ESteamNetworkingConfig_P2P_Transport_ICE_Penalty = 105,
1413 	k_ESteamNetworkingConfig_P2P_Transport_SDR_Penalty = 106,
1414 	//k_ESteamNetworkingConfig_P2P_Transport_LANBeacon_Penalty = 107,
1415 
1416 //
1417 // Settings for SDR relayed connections
1418 //
1419 
1420 	/// [int32 global] If the first N pings to a port all fail, mark that port as unavailable for
1421 	/// a while, and try a different one.  Some ISPs and routers may drop the first
1422 	/// packet, so setting this to 1 may greatly disrupt communications.
1423 	k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFailInitial = 19,
1424 
1425 	/// [int32 global] If N consecutive pings to a port fail, after having received successful
1426 	/// communication, mark that port as unavailable for a while, and try a
1427 	/// different one.
1428 	k_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFail = 20,
1429 
1430 	/// [int32 global] Minimum number of lifetime pings we need to send, before we think our estimate
1431 	/// is solid.  The first ping to each cluster is very often delayed because of NAT,
1432 	/// routers not having the best route, etc.  Until we've sent a sufficient number
1433 	/// of pings, our estimate is often inaccurate.  Keep pinging until we get this
1434 	/// many pings.
1435 	k_ESteamNetworkingConfig_SDRClient_MinPingsBeforePingAccurate = 21,
1436 
1437 	/// [int32 global] Set all steam datagram traffic to originate from the same
1438 	/// local port. By default, we open up a new UDP socket (on a different local
1439 	/// port) for each relay.  This is slightly less optimal, but it works around
1440 	/// some routers that don't implement NAT properly.  If you have intermittent
1441 	/// problems talking to relays that might be NAT related, try toggling
1442 	/// this flag
1443 	k_ESteamNetworkingConfig_SDRClient_SingleSocket = 22,
1444 
1445 	/// [global string] Code of relay cluster to force use.  If not empty, we will
1446 	/// only use relays in that cluster.  E.g. 'iad'
1447 	k_ESteamNetworkingConfig_SDRClient_ForceRelayCluster = 29,
1448 
1449 	/// [connection string] For debugging, generate our own (unsigned) ticket, using
1450 	/// the specified  gameserver address.  Router must be configured to accept unsigned
1451 	/// tickets.
1452 	k_ESteamNetworkingConfig_SDRClient_DebugTicketAddress = 30,
1453 
1454 	/// [global string] For debugging.  Override list of relays from the config with
1455 	/// this set (maybe just one).  Comma-separated list.
1456 	k_ESteamNetworkingConfig_SDRClient_ForceProxyAddr = 31,
1457 
1458 	/// [global string] For debugging.  Force ping times to clusters to be the specified
1459 	/// values.  A comma separated list of <cluster>=<ms> values.  E.g. "sto=32,iad=100"
1460 	///
1461 	/// This is a dev configuration value, you probably should not let users modify it
1462 	/// in production.
1463 	k_ESteamNetworkingConfig_SDRClient_FakeClusterPing = 36,
1464 
1465 //
1466 // Misc / debugging
1467 //
1468 
1469 	/// [global int32] 0 or 1.  Some variables are "dev" variables.  They are useful
1470 	/// for debugging, but should not be adjusted in production.  When this flag is false (the default),
1471 	/// such variables will not be enumerated by the ISteamnetworkingUtils::GetFirstConfigValue
1472 	/// ISteamNetworkingUtils::GetConfigValueInfo functions.  The idea here is that you
1473 	/// can use those functions to provide a generic mechanism to set any configuration
1474 	/// value from a console or configuration file, looking up the variable by name.  Depending
1475 	/// on your game, modifying other configuration values may also have negative effects, and
1476 	/// you may wish to further lock down which variables are allowed to be modified by the user.
1477 	/// (Maybe no variables!)  Or maybe you use a whitelist or blacklist approach.
1478 	///
1479 	/// (This flag is itself a dev variable.)
1480 	k_ESteamNetworkingConfig_EnumerateDevVars = 35,
1481 
1482 //
1483 // Log levels for debugging information of various subsystems.
1484 // Higher numeric values will cause more stuff to be printed.
1485 // See ISteamNetworkingUtils::SetDebugOutputFunction for more
1486 // information
1487 //
1488 // The default for all values is k_ESteamNetworkingSocketsDebugOutputType_Warning.
1489 //
1490 	k_ESteamNetworkingConfig_LogLevel_AckRTT = 13, // [connection int32] RTT calculations for inline pings and replies
1491 	k_ESteamNetworkingConfig_LogLevel_PacketDecode = 14, // [connection int32] log SNP packets send/recv
1492 	k_ESteamNetworkingConfig_LogLevel_Message = 15, // [connection int32] log each message send/recv
1493 	k_ESteamNetworkingConfig_LogLevel_PacketGaps = 16, // [connection int32] dropped packets
1494 	k_ESteamNetworkingConfig_LogLevel_P2PRendezvous = 17, // [connection int32] P2P rendezvous messages
1495 	k_ESteamNetworkingConfig_LogLevel_SDRRelayPings = 18, // [global int32] Ping relays
1496 
1497 	k_ESteamNetworkingConfigValue__Force32Bit = 0x7fffffff
1498 };
1499 
1500 // Bitmask of types to share
1501 const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Default = -1; // Special value - use user defaults
1502 const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Disable = 0; // Do not do any ICE work at all or share any IP addresses with peer
1503 const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Relay = 1; // Relayed connection via TURN server.
1504 const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Private = 2; // host addresses that appear to be link-local or RFC1918 addresses
1505 const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Public = 4; // STUN reflexive addresses, or host address that isn't a "private" address
1506 const int k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_All = 0x7fffffff;
1507 
1508 /// In a few places we need to set configuration options on listen sockets and connections, and
1509 /// have them take effect *before* the listen socket or connection really starts doing anything.
1510 /// Creating the object and then setting the options "immediately" after creation doesn't work
1511 /// completely, because network packets could be received between the time the object is created and
1512 /// when the options are applied.  To set options at creation time in a reliable way, they must be
1513 /// passed to the creation function.  This structure is used to pass those options.
1514 ///
1515 /// For the meaning of these fields, see ISteamNetworkingUtils::SetConfigValue.  Basically
1516 /// when the object is created, we just iterate over the list of options and call
1517 /// ISteamNetworkingUtils::SetConfigValueStruct, where the scope arguments are supplied by the
1518 /// object being created.
1519 struct SteamNetworkingConfigValue_t
1520 {
1521 	/// Which option is being set
1522 	ESteamNetworkingConfigValue m_eValue;
1523 
1524 	/// Which field below did you fill in?
1525 	ESteamNetworkingConfigDataType m_eDataType;
1526 
1527 	/// Option value
1528 	union
1529 	{
1530 		int32_t m_int32;
1531 		int64_t m_int64;
1532 		float m_float;
1533 		const char *m_string; // Points to your '\0'-terminated buffer
1534 		void *m_ptr;
1535 	} m_val;
1536 
1537 	//
1538 	// Shortcut helpers to set the type and value in a single call
1539 	//
SetInt32SteamNetworkingConfigValue_t1540 	inline void SetInt32( ESteamNetworkingConfigValue eVal, int32_t data )
1541 	{
1542 		m_eValue = eVal;
1543 		m_eDataType = k_ESteamNetworkingConfig_Int32;
1544 		m_val.m_int32 = data;
1545 	}
SetInt64SteamNetworkingConfigValue_t1546 	inline void SetInt64( ESteamNetworkingConfigValue eVal, int64_t data )
1547 	{
1548 		m_eValue = eVal;
1549 		m_eDataType = k_ESteamNetworkingConfig_Int64;
1550 		m_val.m_int64 = data;
1551 	}
SetFloatSteamNetworkingConfigValue_t1552 	inline void SetFloat( ESteamNetworkingConfigValue eVal, float data )
1553 	{
1554 		m_eValue = eVal;
1555 		m_eDataType = k_ESteamNetworkingConfig_Float;
1556 		m_val.m_float = data;
1557 	}
SetPtrSteamNetworkingConfigValue_t1558 	inline void SetPtr( ESteamNetworkingConfigValue eVal, void *data )
1559 	{
1560 		m_eValue = eVal;
1561 		m_eDataType = k_ESteamNetworkingConfig_Ptr;
1562 		m_val.m_ptr = data;
1563 	}
SetStringSteamNetworkingConfigValue_t1564 	inline void SetString( ESteamNetworkingConfigValue eVal, const char *data ) // WARNING - Just saves your pointer.  Does NOT make a copy of the string
1565 	{
1566 		m_eValue = eVal;
1567 		m_eDataType = k_ESteamNetworkingConfig_Ptr;
1568 		m_val.m_string = data;
1569 	}
1570 };
1571 
1572 /// Return value of ISteamNetworkintgUtils::GetConfigValue
1573 enum ESteamNetworkingGetConfigValueResult
1574 {
1575 	k_ESteamNetworkingGetConfigValue_BadValue = -1,	// No such configuration value
1576 	k_ESteamNetworkingGetConfigValue_BadScopeObj = -2,	// Bad connection handle, etc
1577 	k_ESteamNetworkingGetConfigValue_BufferTooSmall = -3, // Couldn't fit the result in your buffer
1578 	k_ESteamNetworkingGetConfigValue_OK = 1,
1579 	k_ESteamNetworkingGetConfigValue_OKInherited = 2, // A value was not set at this level, but the effective (inherited) value was returned.
1580 
1581 	k_ESteamNetworkingGetConfigValueResult__Force32Bit = 0x7fffffff
1582 };
1583 
1584 //
1585 // Debug output
1586 //
1587 
1588 /// Detail level for diagnostic output callback.
1589 /// See ISteamNetworkingUtils::SetDebugOutputFunction
1590 enum ESteamNetworkingSocketsDebugOutputType
1591 {
1592 	k_ESteamNetworkingSocketsDebugOutputType_None = 0,
1593 	k_ESteamNetworkingSocketsDebugOutputType_Bug = 1, // You used the API incorrectly, or an internal error happened
1594 	k_ESteamNetworkingSocketsDebugOutputType_Error = 2, // Run-time error condition that isn't the result of a bug.  (E.g. we are offline, cannot bind a port, etc)
1595 	k_ESteamNetworkingSocketsDebugOutputType_Important = 3, // Nothing is wrong, but this is an important notification
1596 	k_ESteamNetworkingSocketsDebugOutputType_Warning = 4,
1597 	k_ESteamNetworkingSocketsDebugOutputType_Msg = 5, // Recommended amount
1598 	k_ESteamNetworkingSocketsDebugOutputType_Verbose = 6, // Quite a bit
1599 	k_ESteamNetworkingSocketsDebugOutputType_Debug = 7, // Practically everything
1600 	k_ESteamNetworkingSocketsDebugOutputType_Everything = 8, // Wall of text, detailed packet contents breakdown, etc
1601 
1602 	k_ESteamNetworkingSocketsDebugOutputType__Force32Bit = 0x7fffffff
1603 };
1604 
1605 /// Setup callback for debug output, and the desired verbosity you want.
1606 typedef void (*FSteamNetworkingSocketsDebugOutput)( ESteamNetworkingSocketsDebugOutputType nType, const char *pszMsg );
1607 
1608 //
1609 // Valve data centers
1610 //
1611 
1612 /// Convert 3- or 4-character ID to 32-bit int.
CalculateSteamNetworkingPOPIDFromString(const char * pszCode)1613 inline SteamNetworkingPOPID CalculateSteamNetworkingPOPIDFromString( const char *pszCode )
1614 {
1615 	// OK we made a bad decision when we decided how to pack 3-character codes into a uint32.  We'd like to support
1616 	// 4-character codes, but we don't want to break compatibility.  The migration path has some subtleties that make
1617 	// this nontrivial, and there are already some IDs stored in SQL.  Ug, so the 4 character code "abcd" will
1618 	// be encoded with the digits like "0xddaabbcc".
1619 	//
1620 	// Also: we don't currently use 1- or 2-character codes, but if ever do in the future, let's make sure don't read
1621 	// past the end of the string and access uninitialized memory.  (And if the string is empty, we always want
1622 	// to return 0 and not read bytes past the '\0'.)
1623 	//
1624 	// There is also extra paranoia to make sure the bytes are not treated as signed.
1625 	SteamNetworkingPOPID result = (uint32)(uint8)pszCode[0] << 16U;
1626 	if ( pszCode[1] )
1627 	{
1628 		result |= ( (uint32)(uint8)pszCode[1] << 8U );
1629 		if ( pszCode[2] )
1630 		{
1631 			result |= (uint32)(uint8)pszCode[2] | ( (uint32)(uint8)pszCode[3] << 24U );
1632 		}
1633 	}
1634 	return result;
1635 }
1636 
1637 /// Unpack integer to string representation, including terminating '\0'
1638 ///
1639 /// See also SteamNetworkingPOPIDRender
1640 template <int N>
GetSteamNetworkingLocationPOPStringFromID(SteamNetworkingPOPID id,char (& szCode)[N])1641 inline void GetSteamNetworkingLocationPOPStringFromID( SteamNetworkingPOPID id, char (&szCode)[N] )
1642 {
1643 	static_assert( N >= 5, "Fixed-size buffer not big enough to hold SDR POP ID" );
1644 	szCode[0] = char( id >> 16U );
1645 	szCode[1] = char( id >> 8U );
1646 	szCode[2] = char( id );
1647 	szCode[3] = char( id >> 24U ); // See comment above about deep regret and sadness
1648 	szCode[4] = 0;
1649 }
1650 
1651 /// The POPID "dev" is used in non-production environments for testing.
1652 const SteamNetworkingPOPID k_SteamDatagramPOPID_dev = ( (uint32)'d' << 16U ) | ( (uint32)'e' << 8U ) | (uint32)'v';
1653 
1654 /// Utility class for printing a SteamNetworkingPOPID.
1655 struct SteamNetworkingPOPIDRender
1656 {
SteamNetworkingPOPIDRenderSteamNetworkingPOPIDRender1657 	SteamNetworkingPOPIDRender( SteamNetworkingPOPID x ) { GetSteamNetworkingLocationPOPStringFromID( x, buf ); }
c_strSteamNetworkingPOPIDRender1658 	inline const char *c_str() const { return buf; }
1659 private:
1660 	char buf[ 8 ];
1661 };
1662 
1663 
1664 ///////////////////////////////////////////////////////////////////////////////
1665 //
1666 // Internal stuff
1667 #ifndef API_GEN
1668 
1669 // For code compatibility
1670 typedef SteamNetworkingMessage_t ISteamNetworkingMessage;
1671 typedef SteamNetworkingErrMsg SteamDatagramErrMsg;
1672 
Clear()1673 inline void SteamNetworkingIPAddr::Clear() { memset( this, 0, sizeof(*this) ); }
IsIPv6AllZeros()1674 inline bool SteamNetworkingIPAddr::IsIPv6AllZeros() const { const uint64 *q = (const uint64 *)m_ipv6; return q[0] == 0 && q[1] == 0; }
SetIPv6(const uint8 * ipv6,uint16 nPort)1675 inline void SteamNetworkingIPAddr::SetIPv6( const uint8 *ipv6, uint16 nPort ) { memcpy( m_ipv6, ipv6, 16 ); m_port = nPort; }
SetIPv4(uint32 nIP,uint16 nPort)1676 inline void SteamNetworkingIPAddr::SetIPv4( uint32 nIP, uint16 nPort ) { m_ipv4.m_8zeros = 0; m_ipv4.m_0000 = 0; m_ipv4.m_ffff = 0xffff; m_ipv4.m_ip[0] = uint8(nIP>>24); m_ipv4.m_ip[1] = uint8(nIP>>16); m_ipv4.m_ip[2] = uint8(nIP>>8); m_ipv4.m_ip[3] = uint8(nIP); m_port = nPort; }
IsIPv4()1677 inline bool SteamNetworkingIPAddr::IsIPv4() const { return m_ipv4.m_8zeros == 0 && m_ipv4.m_0000 == 0 && m_ipv4.m_ffff == 0xffff; }
GetIPv4()1678 inline uint32 SteamNetworkingIPAddr::GetIPv4() const { return IsIPv4() ? ( (uint32(m_ipv4.m_ip[0])<<24) | (uint32(m_ipv4.m_ip[1])<<16) | (uint32(m_ipv4.m_ip[2])<<8) | uint32(m_ipv4.m_ip[3]) ) : 0; }
SetIPv6LocalHost(uint16 nPort)1679 inline void SteamNetworkingIPAddr::SetIPv6LocalHost( uint16 nPort ) { m_ipv4.m_8zeros = 0; m_ipv4.m_0000 = 0; m_ipv4.m_ffff = 0; m_ipv6[12] = 0; m_ipv6[13] = 0; m_ipv6[14] = 0; m_ipv6[15] = 1; m_port = nPort; }
IsLocalHost()1680 inline bool SteamNetworkingIPAddr::IsLocalHost() const { return ( m_ipv4.m_8zeros == 0 && m_ipv4.m_0000 == 0 && m_ipv4.m_ffff == 0 && m_ipv6[12] == 0 && m_ipv6[13] == 0 && m_ipv6[14] == 0 && m_ipv6[15] == 1 ) || ( GetIPv4() == 0x7f000001 ); }
1681 inline bool SteamNetworkingIPAddr::operator==(const SteamNetworkingIPAddr &x ) const { return memcmp( this, &x, sizeof(SteamNetworkingIPAddr) ) == 0; }
1682 
Clear()1683 inline void SteamNetworkingIdentity::Clear() { memset( this, 0, sizeof(*this) ); }
IsInvalid()1684 inline bool SteamNetworkingIdentity::IsInvalid() const { return m_eType == k_ESteamNetworkingIdentityType_Invalid; }
SetSteamID(CSteamID steamID)1685 inline void SteamNetworkingIdentity::SetSteamID( CSteamID steamID ) { SetSteamID64( steamID.ConvertToUint64() ); }
GetSteamID()1686 inline CSteamID SteamNetworkingIdentity::GetSteamID() const { return CSteamID( GetSteamID64() ); }
SetSteamID64(uint64 steamID)1687 inline void SteamNetworkingIdentity::SetSteamID64( uint64 steamID ) { m_eType = k_ESteamNetworkingIdentityType_SteamID; m_cbSize = sizeof( m_steamID64 ); m_steamID64 = steamID; }
GetSteamID64()1688 inline uint64 SteamNetworkingIdentity::GetSteamID64() const { return m_eType == k_ESteamNetworkingIdentityType_SteamID ? m_steamID64 : 0; }
SetIPAddr(const SteamNetworkingIPAddr & addr)1689 inline void SteamNetworkingIdentity::SetIPAddr( const SteamNetworkingIPAddr &addr ) { m_eType = k_ESteamNetworkingIdentityType_IPAddress; m_cbSize = (int)sizeof(m_ip); m_ip = addr; }
GetIPAddr()1690 inline const SteamNetworkingIPAddr *SteamNetworkingIdentity::GetIPAddr() const { return m_eType == k_ESteamNetworkingIdentityType_IPAddress ? &m_ip : NULL; }
SetIPv4Addr(uint32 nIPv4,uint16 nPort)1691 inline void SteamNetworkingIdentity::SetIPv4Addr( uint32 nIPv4, uint16 nPort ) { m_eType = k_ESteamNetworkingIdentityType_IPAddress; m_cbSize = (int)sizeof(m_ip); m_ip.SetIPv4( nIPv4, nPort ); }
GetIPv4()1692 inline uint32 SteamNetworkingIdentity::GetIPv4() const { return m_eType == k_ESteamNetworkingIdentityType_IPAddress ? m_ip.GetIPv4() : 0; }
SetLocalHost()1693 inline void SteamNetworkingIdentity::SetLocalHost() { m_eType = k_ESteamNetworkingIdentityType_IPAddress; m_cbSize = (int)sizeof(m_ip); m_ip.SetIPv6LocalHost(); }
IsLocalHost()1694 inline bool SteamNetworkingIdentity::IsLocalHost() const { return m_eType == k_ESteamNetworkingIdentityType_IPAddress && m_ip.IsLocalHost(); }
SetGenericString(const char * pszString)1695 inline bool SteamNetworkingIdentity::SetGenericString( const char *pszString ) { size_t l = strlen( pszString ); if ( l >= sizeof(m_szGenericString) ) return false;
1696 	m_eType = k_ESteamNetworkingIdentityType_GenericString; m_cbSize = int(l+1); memcpy( m_szGenericString, pszString, m_cbSize ); return true; }
GetGenericString()1697 inline const char *SteamNetworkingIdentity::GetGenericString() const { return m_eType == k_ESteamNetworkingIdentityType_GenericString ? m_szGenericString : NULL; }
SetGenericBytes(const void * data,size_t cbLen)1698 inline bool SteamNetworkingIdentity::SetGenericBytes( const void *data, size_t cbLen ) { if ( cbLen > sizeof(m_genericBytes) ) return false;
1699 	m_eType = k_ESteamNetworkingIdentityType_GenericBytes; m_cbSize = int(cbLen); memcpy( m_genericBytes, data, m_cbSize ); return true; }
GetGenericBytes(int & cbLen)1700 inline const uint8 *SteamNetworkingIdentity::GetGenericBytes( int &cbLen ) const { if ( m_eType != k_ESteamNetworkingIdentityType_GenericBytes ) return NULL;
1701 	cbLen = m_cbSize; return m_genericBytes; }
1702 inline bool SteamNetworkingIdentity::operator==(const SteamNetworkingIdentity &x ) const { return m_eType == x.m_eType && m_cbSize == x.m_cbSize && memcmp( m_genericBytes, x.m_genericBytes, m_cbSize ) == 0; }
Release()1703 inline void SteamNetworkingMessage_t::Release() { (*m_pfnRelease)( this ); }
1704 
1705 #endif // #ifndef API_GEN
1706 
1707 #endif // #ifndef STEAMNETWORKINGTYPES
1708