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