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