1 /// Transcription of isteamnetworkingsockets.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.sockets;
7 
8 import std..string;
9 
10 import steam_gns.misc;
11 import steam_gns.types;
12 import steam_gns.client_public;
13 
14 extern (C++):
15 
16 // I expected this to be the the default in this case, but apparently D aligns to 8 in some cases. Alignment depends
17 // on the companion C compiler so maybe my config is weird. This is more predictable, regardless.
18 align(4):
19 
20 // defines from steam_gns.types
21 version = STEAMNETWORKINGSOCKETS_STANDALONELIB;
22 
23 // Where are those defined‽
24 struct SteamDatagramRelayAuthTicket;
25 struct SteamDatagramHostedAddress;
26 struct SteamNetworkingFakeIPResult_t;
27 struct SteamDatagramGameCoordinatorServerLogin;
28 struct ISteamNetworkingConnectionSignaling;
29 struct ISteamNetworkingSignalingRecvContext;
30 struct ISteamNetworkingFakeUDPPort;
31 
32 /// Lower level networking API.
33 ///
34 /// - Connection-oriented API (like TCP, not UDP).  When sending and receiving
35 ///   messages, a connection handle is used.  (For a UDP-style interface, where
36 ///   the peer is identified by their address with each send/recv call, see
37 ///   ISteamNetworkingMessages.)  The typical pattern is for a "server" to "listen"
38 ///   on a "listen socket."  A "client" will "connect" to the server, and the
39 ///   server will "accept" the connection.  If you have a symmetric situation
40 ///   where either peer may initiate the connection and server/client roles are
41 ///   not clearly defined, check out k_ESteamNetworkingConfig_SymmetricConnect.
42 /// - But unlike TCP, it's message-oriented, not stream-oriented.
43 /// - Mix of reliable and unreliable messages
44 /// - Fragmentation and reassembly
45 /// - Supports connectivity over plain UDP
46 /// - Also supports SDR ("Steam Datagram Relay") connections, which are
47 ///   addressed by the identity of the peer.  There is a "P2P" use case and
48 ///   a "hosted dedicated server" use case.
49 ///
50 /// Note that neither of the terms "connection" nor "socket" necessarily correspond
51 /// one-to-one with an underlying UDP socket.  An attempt has been made to
52 /// keep the semantics as similar to the standard socket model when appropriate,
53 /// but some deviations do exist.
54 ///
55 /// See also: ISteamNetworkingMessages, the UDP-style interface.  This API might be
56 /// easier to use, especially when porting existing UDP code.
57 abstract class ISteamNetworkingSockets {
58 
59     /// Creates a "server" socket that listens for clients to connect to by
60     /// calling ConnectByIPAddress, over ordinary UDP (IPv4 or IPv6)
61     ///
62     /// You must select a specific local port to listen on and set it
63     /// the port field of the local address.
64     ///
65     /// Usually you will set the IP portion of the address to zero (SteamNetworkingIPAddr::Clear()).
66     /// This means that you will not bind to any particular local interface (i.e. the same
67     /// as INADDR_ANY in plain socket code).  Furthermore, if possible the socket will be bound
68     /// in "dual stack" mode, which means that it can accept both IPv4 and IPv6 client connections.
69     /// If you really do wish to bind a particular interface, then set the local address to the
70     /// appropriate IPv4 or IPv6 IP.
71     ///
72     /// If you need to set any initial config options, pass them here.  See
73     /// SteamNetworkingConfigValue_t for more about why this is preferable to
74     /// setting the options "immediately" after creation.
75     ///
76     /// When a client attempts to connect, a SteamNetConnectionStatusChangedCallback_t
77     /// will be posted.  The connection will be in the connecting state.
78     HSteamListenSocket CreateListenSocketIP(const ref SteamNetworkingIPAddr localAddress, int nOptions,
79     const SteamNetworkingConfigValue_t* pOptions);
80 
81     /// Creates a connection and begins talking to a "server" over UDP at the
82     /// given IPv4 or IPv6 address.  The remote host must be listening with a
83     /// matching call to CreateListenSocketIP on the specified port.
84     ///
85     /// A SteamNetConnectionStatusChangedCallback_t callback will be triggered when we start
86     /// connecting, and then another one on either timeout or successful connection.
87     ///
88     /// If the server does not have any identity configured, then their network address
89     /// will be the only identity in use.  Or, the network host may provide a platform-specific
90     /// identity with or without a valid certificate to authenticate that identity.  (These
91     /// details will be contained in the SteamNetConnectionStatusChangedCallback_t.)  It's
92     /// up to your application to decide whether to allow the connection.
93     ///
94     /// By default, all connections will get basic encryption sufficient to prevent
95     /// casual eavesdropping.  But note that without certificates (or a shared secret
96     /// distributed through some other out-of-band mechanism), you don't have any
97     /// way of knowing who is actually on the other end, and thus are vulnerable to
98     /// man-in-the-middle attacks.
99     ///
100     /// If you need to set any initial config options, pass them here.  See
101     /// SteamNetworkingConfigValue_t for more about why this is preferable to
102     /// setting the options "immediately" after creation.
103     HSteamNetConnection ConnectByIPAddress(const ref SteamNetworkingIPAddr address, int nOptions,
104     const SteamNetworkingConfigValue_t* pOptions);
105 
106     /// Like CreateListenSocketIP, but clients will connect using ConnectP2P.
107     ///
108     /// nLocalVirtualPort specifies how clients can connect to this socket using
109     /// ConnectP2P.  It's very common for applications to only have one listening socket;
110     /// in that case, use zero.  If you need to open multiple listen sockets and have clients
111     /// be able to connect to one or the other, then nLocalVirtualPort should be a small
112     /// integer (<1000) unique to each listen socket you create.
113     ///
114     /// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
115     /// when your app initializes.
116     ///
117     /// If you are listening on a dedicated servers in known data center,
118     /// then you can listen using this function instead of CreateHostedDedicatedServerListenSocket,
119     /// to allow clients to connect without a ticket.  Any user that owns
120     /// the app and is signed into Steam will be able to attempt to connect to
121     /// your server.  Also, a connection attempt may require the client to
122     /// be connected to Steam, which is one more moving part that may fail.  When
123     /// tickets are used, then once a ticket is obtained, a client can connect to
124     /// your server even if they got disconnected from Steam or Steam is offline.
125     ///
126     /// If you need to set any initial config options, pass them here.  See
127     /// SteamNetworkingConfigValue_t for more about why this is preferable to
128     /// setting the options "immediately" after creation.
129     HSteamListenSocket CreateListenSocketP2P(int nLocalVirtualPort, int nOptions,
130     const SteamNetworkingConfigValue_t* pOptions);
131 
132     /// Begin connecting to a peer that is identified using a platform-specific identifier.
133     /// This uses the default rendezvous service, which depends on the platform and library
134     /// configuration.  (E.g. on Steam, it goes through the steam backend.)
135     ///
136     /// If you need to set any initial config options, pass them here.  See
137     /// SteamNetworkingConfigValue_t for more about why this is preferable to
138     /// setting the options "immediately" after creation.
139     ///
140     /// To use your own signaling service, see:
141     /// - ConnectP2PCustomSignaling
142     /// - k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling
143     HSteamNetConnection ConnectP2P(const ref SteamNetworkingIdentity identityRemote, int nRemoteVirtualPort,
144     int nOptions, const SteamNetworkingConfigValue_t* pOptions);
145 
146     /// Accept an incoming connection that has been received on a listen socket.
147     ///
148     /// When a connection attempt is received (perhaps after a few basic handshake
149     /// packets have been exchanged to prevent trivial spoofing), a connection interface
150     /// object is created in the k_ESteamNetworkingConnectionState_Connecting state
151     /// and a SteamNetConnectionStatusChangedCallback_t is posted.  At this point, your
152     /// application MUST either accept or close the connection.  (It may not ignore it.)
153     /// Accepting the connection will transition it either into the connected state,
154     /// or the finding route state, depending on the connection type.
155     ///
156     /// You should take action within a second or two, because accepting the connection is
157     /// what actually sends the reply notifying the client that they are connected.  If you
158     /// delay taking action, from the client's perspective it is the same as the network
159     /// being unresponsive, and the client may timeout the connection attempt.  In other
160     /// words, the client cannot distinguish between a delay caused by network problems
161     /// and a delay caused by the application.
162     ///
163     /// This means that if your application goes for more than a few seconds without
164     /// processing callbacks (for example, while loading a map), then there is a chance
165     /// that a client may attempt to connect in that interval and fail due to timeout.
166     ///
167     /// If the application does not respond to the connection attempt in a timely manner,
168     /// and we stop receiving communication from the client, the connection attempt will
169     /// be timed out locally, transitioning the connection to the
170     /// k_ESteamNetworkingConnectionState_ProblemDetectedLocally state.  The client may also
171     /// close the connection before it is accepted, and a transition to the
172     /// k_ESteamNetworkingConnectionState_ClosedByPeer is also possible depending the exact
173     /// sequence of events.
174     ///
175     /// Returns k_EResultInvalidParam if the handle is invalid.
176     /// Returns k_EResultInvalidState if the connection is not in the appropriate state.
177     /// (Remember that the connection state could change in between the time that the
178     /// notification being posted to the queue and when it is received by the application.)
179     ///
180     /// A note about connection configuration options.  If you need to set any configuration
181     /// options that are common to all connections accepted through a particular listen
182     /// socket, consider setting the options on the listen socket, since such options are
183     /// inherited automatically.  If you really do need to set options that are connection
184     /// specific, it is safe to set them on the connection before accepting the connection.
185     EResult AcceptConnection(HSteamNetConnection hConn);
186 
187     /// Disconnects from the remote host and invalidates the connection handle.
188     /// Any unread data on the connection is discarded.
189     ///
190     /// nReason is an application defined code that will be received on the other
191     /// end and recorded (when possible) in backend analytics.  The value should
192     /// come from a restricted range.  (See ESteamNetConnectionEnd.)  If you don't need
193     /// to communicate any information to the remote host, and do not want analytics to
194     /// be able to distinguish "normal" connection terminations from "exceptional" ones,
195     /// You may pass zero, in which case the generic value of
196     /// k_ESteamNetConnectionEnd_App_Generic will be used.
197     ///
198     /// pszDebug is an optional human-readable diagnostic string that will be received
199     /// by the remote host and recorded (when possible) in backend analytics.
200     ///
201     /// If you wish to put the socket into a "linger" state, where an attempt is made to
202     /// flush any remaining sent data, use bEnableLinger=true.  Otherwise reliable data
203     /// is not flushed.
204     ///
205     /// If the connection has already ended and you are just freeing up the
206     /// connection interface, the reason code, debug string, and linger flag are
207     /// ignored.
208     bool CloseConnection(HSteamNetConnection hPeer, int nReason, const char* pszDebug, bool bEnableLinger);
209 
210     /// Destroy a listen socket.  All the connections that were accepting on the listen
211     /// socket are closed ungracefully.
212     bool CloseListenSocket(HSteamListenSocket hSocket);
213 
214     /// Set connection user data.  the data is returned in the following places
215     /// - You can query it using GetConnectionUserData.
216     /// - The SteamNetworkingmessage_t structure.
217     /// - The SteamNetConnectionInfo_t structure.
218     ///   (Which is a member of SteamNetConnectionStatusChangedCallback_t -- but see WARNINGS below!!!!)
219     ///
220     /// Do you need to set this atomically when the connection is created?
221     /// See k_ESteamNetworkingConfig_ConnectionUserData.
222     ///
223     /// WARNING: Be *very careful* when using the value provided in callbacks structs.
224     /// Callbacks are queued, and the value that you will receive in your
225     /// callback is the userdata that was effective at the time the callback
226     /// was queued.  There are subtle race conditions that can happen if you
227     /// don't understand this!
228     ///
229     /// If any incoming messages for this connection are queued, the userdata
230     /// field is updated, so that when when you receive messages (e.g. with
231     /// ReceiveMessagesOnConnection), they will always have the very latest
232     /// userdata.  So the tricky race conditions that can happen with callbacks
233     /// do not apply to retrieving messages.
234     ///
235     /// Returns false if the handle is invalid.
236     bool SetConnectionUserData(HSteamNetConnection hPeer, long nUserData);
237 
238     /// Fetch connection user data.  Returns -1 if handle is invalid
239     /// or if you haven't set any userdata on the connection.
240     long GetConnectionUserData(HSteamNetConnection hPeer);
241 
242     /// Set a name for the connection, used mostly for debugging
243     void SetConnectionName(HSteamNetConnection hPeer, const char *pszName);
244 
245     /// Fetch connection name.  Returns false if handle is invalid
246     bool GetConnectionName(HSteamNetConnection hPeer, char *pszName, int nMaxLen);
247 
248     /// Send a message to the remote host on the specified connection.
249     ///
250     /// nSendFlags determines the delivery guarantees that will be provided,
251     /// when data should be buffered, etc.  E.g. k_nSteamNetworkingSend_Unreliable
252     ///
253     /// Note that the semantics we use for messages are not precisely
254     /// the same as the semantics of a standard "stream" socket.
255     /// (SOCK_STREAM)  For an ordinary stream socket, the boundaries
256     /// between chunks are not considered relevant, and the sizes of
257     /// the chunks of data written will not necessarily match up to
258     /// the sizes of the chunks that are returned by the reads on
259     /// the other end.  The remote host might read a partial chunk,
260     /// or chunks might be coalesced.  For the message semantics
261     /// used here, however, the sizes WILL match.  Each send call
262     /// will match a successful read call on the remote host
263     /// one-for-one.  If you are porting existing stream-oriented
264     /// code to the semantics of reliable messages, your code should
265     /// work the same, since reliable message semantics are more
266     /// strict than stream semantics.  The only caveat is related to
267     /// performance: there is per-message overhead to retain the
268     /// message sizes, and so if your code sends many small chunks
269     /// of data, performance will suffer. Any code based on stream
270     /// sockets that does not write excessively small chunks will
271     /// work without any changes.
272     ///
273     /// The pOutMessageNumber is an optional pointer to receive the
274     /// message number assigned to the message, if sending was successful.
275     ///
276     /// Returns:
277     /// - k_EResultInvalidParam: invalid connection handle, or the individual message is too big.
278     ///   (See k_cbMaxSteamNetworkingSocketsMessageSizeSend)
279     /// - k_EResultInvalidState: connection is in an invalid state
280     /// - k_EResultNoConnection: connection has ended
281     /// - k_EResultIgnored: You used k_nSteamNetworkingSend_NoDelay, and the message was dropped because
282     ///   we were not ready to send it.
283     /// - k_EResultLimitExceeded: there was already too much data queued to be sent.
284     ///   (See k_ESteamNetworkingConfig_SendBufferSize)
285     EResult SendMessageToConnection(HSteamNetConnection hConn, const void* pData, uint cbData, int nSendFlags,
286     long* pOutMessageNumber);
287 
288     /// Send one or more messages without copying the message payload.
289     /// This is the most efficient way to send messages. To use this
290     /// function, you must first allocate a message object using
291     /// ISteamNetworkingUtils::AllocateMessage.  (Do not declare one
292     /// on the stack or allocate your own.)
293     ///
294     /// You should fill in the message payload.  You can either let
295     /// it allocate the buffer for you and then fill in the payload,
296     /// or if you already have a buffer allocated, you can just point
297     /// m_pData at your buffer and set the callback to the appropriate function
298     /// to free it.  Note that if you use your own buffer, it MUST remain valid
299     /// until the callback is executed.  And also note that your callback can be
300     /// invoked at any time from any thread (perhaps even before SendMessages
301     /// returns!), so it MUST be fast and threadsafe.
302     ///
303     /// You MUST also fill in:
304     /// - m_conn - the handle of the connection to send the message to
305     /// - m_nFlags - bitmask of k_nSteamNetworkingSend_xxx flags.
306     ///
307     /// All other fields are currently reserved and should not be modified.
308     ///
309     /// The library will take ownership of the message structures.  They may
310     /// be modified or become invalid at any time, so you must not read them
311     /// after passing them to this function.
312     ///
313     /// pOutMessageNumberOrResult is an optional array that will receive,
314     /// for each message, the message number that was assigned to the message
315     /// if sending was successful.  If sending failed, then a negative EResult
316     /// value is placed into the array.  For example, the array will hold
317     /// -k_EResultInvalidState if the connection was in an invalid state.
318     /// See ISteamNetworkingSockets::SendMessageToConnection for possible
319     /// failure codes.
320     void SendMessages(int nMessages, const(SteamNetworkingMessage_t*)* pMessages, long* pOutMessageNumberOrResult);
321 
322     /// Flush any messages waiting on the Nagle timer and send them
323     /// at the next transmission opportunity (often that means right now).
324     ///
325     /// If Nagle is enabled (it's on by default) then when calling
326     /// SendMessageToConnection the message will be buffered, up to the Nagle time
327     /// before being sent, to merge small messages into the same packet.
328     /// (See k_ESteamNetworkingConfig_NagleTime)
329     ///
330     /// Returns:
331     /// k_EResultInvalidParam: invalid connection handle
332     /// k_EResultInvalidState: connection is in an invalid state
333     /// k_EResultNoConnection: connection has ended
334     /// k_EResultIgnored: We weren't (yet) connected, so this operation has no effect.
335     EResult FlushMessagesOnConnection(HSteamNetConnection hConn);
336 
337     /// Fetch the next available message(s) from the connection, if any.
338     /// Returns the number of messages returned into your array, up to nMaxMessages.
339     /// If the connection handle is invalid, -1 is returned.
340     ///
341     /// The order of the messages returned in the array is relevant.
342     /// Reliable messages will be received in the order they were sent (and with the
343     /// same sizes --- see SendMessageToConnection for on this subtle difference from a stream socket).
344     ///
345     /// Unreliable messages may be dropped, or delivered out of order with respect to
346     /// each other or with respect to reliable messages.  The same unreliable message
347     /// may be received multiple times.
348     ///
349     /// If any messages are returned, you MUST call SteamNetworkingMessage_t::Release() on each
350     /// of them free up resources after you are done.  It is safe to keep the object alive for
351     /// a little while (put it into some queue, etc), and you may call Release() from any thread.
352     int ReceiveMessagesOnConnection(HSteamNetConnection hConn, SteamNetworkingMessage_t** ppOutMessages,
353     int nMaxMessages);
354 
355     /// Returns basic information about the high-level state of the connection.
356     bool GetConnectionInfo(HSteamNetConnection hConn, SteamNetConnectionInfo_t* pInfo);
357 
358     /// Returns a small set of information about the real-time state of the connection
359     /// Returns false if the connection handle is invalid, or the connection has ended.
360     bool GetQuickConnectionStatus(HSteamNetConnection hConn, SteamNetworkingQuickConnectionStatus* pStats);
361 
362     /// Returns detailed connection stats in text format.  Useful
363     /// for dumping to a log, etc.
364     ///
365     /// Returns:
366     /// -1 failure (bad connection handle)
367     /// 0 OK, your buffer was filled in and '\0'-terminated
368     /// >0 Your buffer was either nullptr, or it was too small and the text got truncated.
369     ///    Try again with a buffer of at least N bytes.
370     int GetDetailedConnectionStatus(HSteamNetConnection hConn, char* pszBuf, int cbBuf);
371 
372     /// Returns local IP and port that a listen socket created using CreateListenSocketIP is bound to.
373     ///
374     /// An IPv6 address of ::0 means "any IPv4 or IPv6"
375     /// An IPv6 address of ::ffff:0000:0000 means "any IPv4"
376     bool GetListenSocketAddress(HSteamListenSocket hSocket, SteamNetworkingIPAddr* address);
377 
378     /// Create a pair of connections that are talking to each other, e.g. a loopback connection.
379     /// This is very useful for testing, or so that your client/server code can work the same
380     /// even when you are running a local "server".
381     ///
382     /// The two connections will immediately be placed into the connected state, and no callbacks
383     /// will be posted immediately.  After this, if you close either connection, the other connection
384     /// will receive a callback, exactly as if they were communicating over the network.  You must
385     /// close *both* sides in order to fully clean up the resources!
386     ///
387     /// By default, internal buffers are used, completely bypassing the network, the chopping up of
388     /// messages into packets, encryption, copying the payload, etc.  This means that loopback
389     /// packets, by default, will not simulate lag or loss.  Passing true for bUseNetworkLoopback will
390     /// cause the socket pair to send packets through the local network loopback device (127.0.0.1)
391     /// on ephemeral ports.  Fake lag and loss are supported in this case, and CPU time is expended
392     /// to encrypt and decrypt.
393     ///
394     /// If you wish to assign a specific identity to either connection, you may pass a particular
395     /// identity.  Otherwise, if you pass nullptr, the respective connection will assume a generic
396     /// "localhost" identity.  If you use real network loopback, this might be translated to the
397     /// actual bound loopback port.  Otherwise, the port will be zero.
398     bool CreateSocketPair(HSteamNetConnection* pOutConnection1, HSteamNetConnection* pOutConnection2,
399     bool bUseNetworkLoopback, const SteamNetworkingIdentity* pIdentity1, const SteamNetworkingIdentity* pIdentity2);
400 
401     /// Configure multiple outbound messages streams ("lanes") on a connection, and
402     /// control head-of-line blocking between them.  Messages within a given lane
403     /// are always sent in the order they are queued, but messages from different
404     /// lanes may be sent out of order.  Each lane has its own message number
405     /// sequence.  The first message sent on each lane will be assigned the number 1.
406     ///
407     /// Each lane has a "priority".  Lower priority lanes will only be processed
408     /// when all higher-priority lanes are empty.  The magnitudes of the priority
409     /// values are not relevant, only their sort order.  Higher numeric values
410     /// take priority over lower numeric values.
411     ///
412     /// Each lane also is assigned a weight, which controls the approximate proportion
413     /// of the bandwidth that will be consumed by the lane, relative to other lanes
414     /// of the same priority.  (This is assuming the lane stays busy.  An idle lane
415     /// does not build up "credits" to be be spent once a message is queued.)
416     /// This value is only meaningful as a proportion, relative to other lanes with
417     /// the same priority.  For lanes with different priorities, the strict priority
418     /// order will prevail, and their weights relative to each other are not relevant.
419     /// Thus, if a lane has a unique priority value, the weight value for that lane is
420     /// not relevant.
421     ///
422     /// Example: 3 lanes, with priorities [ 0, 10, 10 ] and weights [ (NA), 20, 5 ].
423     /// Messages sent on the first will always be sent first, before messages in the
424     /// other two lanes.  Its weight value is irrelevant, since there are no other
425     /// lanes with priority=0.  The other two lanes will share bandwidth, with the second
426     /// and third lanes sharing bandwidth using a ratio of approximately 4:1.
427     /// (The weights [ NA, 4, 1 ] would be equivalent.)
428     ///
429     /// Notes:
430     /// - At the time of this writing, some code has performance cost that is linear
431     ///   in the number of lanes, so keep the number of lanes to an absolute minimum.
432     ///   3 or so is fine; >8 is a lot.  The max number of lanes on Steam is 255,
433     ///   which is a very large number and not recommended!  If you are compiling this
434     ///   library from source, see STEAMNETWORKINGSOCKETS_MAX_LANES.)
435     /// - Lane priority values may be any int.  Their absolute value is not relevant,
436     ///   only the order matters.
437     /// - Weights must be positive, and due to implementation details, they are restricted
438     ///   to 16-bit values.  The absolute magnitudes don't matter, just the proportions.
439     /// - Messages sent on a lane index other than 0 have a small overhead on the wire,
440     ///   so for maximum wire efficiency, lane 0 should be the "most common" lane, regardless
441     ///   of priorities or weights.
442     /// - A connection has a single lane by default.  Calling this function with
443     ///   nNumLanes=1 is legal, but pointless, since the priority and weight values are
444     ///   irrelevant in that case.
445     /// - You may reconfigure connection lanes at any time, however reducing the number of
446     ///   lanes is not allowed.
447     /// - Reconfiguring lanes might restart any bandwidth sharing balancing.  Usually you
448     ///   will call this function once, near the start of the connection, perhaps after
449     ///   exchanging a few messages.
450     /// - To assign all lanes the same priority, you may use pLanePriorities=NULL.
451     /// - If you wish all lanes with the same priority to share bandwidth equally (or
452     ///   if no two lanes have the same priority value, and thus priority values are
453     ///   irrelevant), you may use pLaneWeights=NULL
454     /// - Priorities and weights determine the order that messages are SENT on the wire.
455     ///   This DOES NOT guarantee the order that messages are RECEIVED!  Due to packet
456     ///   loss and out-of-order delivery, the messages might still be received out of
457     ///   order.  Essentially the only guarantee is that *reliable* messages on the *same
458     ///   lane* will be delivered in the order they are sent.
459     /// - Each host configures the lanes for the packets they send; the lanes for the flow
460     ///   in one direction are completely unrelated to the lanes in the opposite direction.
461     ///
462     /// Return value:
463     /// - k_EResultNoConnection - bad hConn
464     /// - k_EResultInvalidParam - Invalid number of channels, bad weights, or you tried to reduce the number of lanes
465     /// - k_EResultInvalidState - Connection is already dead, etc
466     ///
467     /// See also:
468     /// SteamNetworkingMessage_t::m_idxLane
469     // FIXME - WIP
470     //virtual EResult ConfigureConnectionLanes( HSteamNetConnection hConn, int nNumLanes, const int *pLanePriorities, const uint16 *pLaneWeights ) = 0;
471 
472     //
473     // Identity and authentication
474     //
475 
476     /// Get the identity assigned to this interface.
477     /// E.g. on Steam, this is the user's SteamID, or for the gameserver interface, the SteamID assigned
478     /// to the gameserver.  Returns false and sets the result to an invalid identity if we don't know
479     /// our identity yet.  (E.g. GameServer has not logged in.  On Steam, the user will know their SteamID
480     /// even if they are not signed into Steam.)
481     bool GetIdentity(SteamNetworkingIdentity* pIdentity);
482 
483     /// Indicate our desire to be ready participate in authenticated communications.
484     /// If we are currently not ready, then steps will be taken to obtain the necessary
485     /// certificates.   (This includes a certificate for us, as well as any CA certificates
486     /// needed to authenticate peers.)
487     ///
488     /// You can call this at program init time if you know that you are going to
489     /// be making authenticated connections, so that we will be ready immediately when
490     /// those connections are attempted.  (Note that essentially all connections require
491     /// authentication, with the exception of ordinary UDP connections with authentication
492     /// disabled using k_ESteamNetworkingConfig_IP_AllowWithoutAuth.)  If you don't call
493     /// this function, we will wait until a feature is utilized that that necessitates
494     /// these resources.
495     ///
496     /// You can also call this function to force a retry, if failure has occurred.
497     /// Once we make an attempt and fail, we will not automatically retry.
498     /// In this respect, the behavior of the system after trying and failing is the same
499     /// as before the first attempt: attempting authenticated communication or calling
500     /// this function will call the system to attempt to acquire the necessary resources.
501     ///
502     /// You can use GetAuthenticationStatus or listen for SteamNetAuthenticationStatus_t
503     /// to monitor the status.
504     ///
505     /// Returns the current value that would be returned from GetAuthenticationStatus.
506     ESteamNetworkingAvailability InitAuthentication();
507 
508     /// Query our readiness to participate in authenticated communications.  A
509     /// SteamNetAuthenticationStatus_t callback is posted any time this status changes,
510     /// but you can use this function to query it at any time.
511     ///
512     /// The value of SteamNetAuthenticationStatus_t::m_eAvail is returned.  If you only
513     /// want this high level status, you can pass NULL for pDetails.  If you want further
514     /// details, pass non-NULL to receive them.
515     ESteamNetworkingAvailability GetAuthenticationStatus(SteamNetAuthenticationStatus_t* pDetails);
516 
517     //
518     // Poll groups.  A poll group is a set of connections that can be polled efficiently.
519     // (In our API, to "poll" a connection means to retrieve all pending messages.  We
520     // actually don't have an API to "poll" the connection *state*, like BSD sockets.)
521     //
522 
523     /// Create a new poll group.
524     ///
525     /// You should destroy the poll group when you are done using DestroyPollGroup
526     HSteamNetPollGroup CreatePollGroup();
527 
528     /// Destroy a poll group created with CreatePollGroup().
529     ///
530     /// If there are any connections in the poll group, they are removed from the group,
531     /// and left in a state where they are not part of any poll group.
532     /// Returns false if passed an invalid poll group handle.
533     bool DestroyPollGroup(HSteamNetPollGroup hPollGroup);
534 
535     /// Assign a connection to a poll group.  Note that a connection may only belong to a
536     /// single poll group.  Adding a connection to a poll group implicitly removes it from
537     /// any other poll group it is in.
538     ///
539     /// You can pass k_HSteamNetPollGroup_Invalid to remove a connection from its current
540     /// poll group without adding it to a new poll group.
541     ///
542     /// If there are received messages currently pending on the connection, an attempt
543     /// is made to add them to the queue of messages for the poll group in approximately
544     /// the order that would have applied if the connection was already part of the poll
545     /// group at the time that the messages were received.
546     ///
547     /// Returns false if the connection handle is invalid, or if the poll group handle
548     /// is invalid (and not k_HSteamNetPollGroup_Invalid).
549     bool SetConnectionPollGroup(HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup);
550 
551     /// Same as ReceiveMessagesOnConnection, but will return the next messages available
552     /// on any connection in the poll group.  Examine SteamNetworkingMessage_t::m_conn
553     /// to know which connection.  (SteamNetworkingMessage_t::m_nConnUserData might also
554     /// be useful.)
555     ///
556     /// Delivery order of messages among different connections will usually match the
557     /// order that the last packet was received which completed the message.  But this
558     /// is not a strong guarantee, especially for packets received right as a connection
559     /// is being assigned to poll group.
560     ///
561     /// Delivery order of messages on the same connection is well defined and the
562     /// same guarantees are present as mentioned in ReceiveMessagesOnConnection.
563     /// (But the messages are not grouped by connection, so they will not necessarily
564     /// appear consecutively in the list; they may be interleaved with messages for
565     /// other connections.)
566     int ReceiveMessagesOnPollGroup(HSteamNetPollGroup hPollGroup, SteamNetworkingMessage_t** ppOutMessages,
567     int nMaxMessages);
568 
569     //
570     // Clients connecting to dedicated servers hosted in a data center,
571     // using tickets issued by your game coordinator.  If you are not
572     // issuing your own tickets to restrict who can attempt to connect
573     // to your server, then you won't use these functions.
574     //
575 
576     /// Call this when you receive a ticket from your backend / matchmaking system.  Puts the
577     /// ticket into a persistent cache, and optionally returns the parsed ticket.
578     ///
579     /// See stamdatagram_ticketgen.h for more details.
580     bool ReceivedRelayAuthTicket(const void* pvTicket, int cbTicket, SteamDatagramRelayAuthTicket* pOutParsedTicket);
581 
582     /// Search cache for a ticket to talk to the server on the specified virtual port.
583     /// If found, returns the number of seconds until the ticket expires, and optionally
584     /// the complete cracked ticket.  Returns 0 if we don't have a ticket.
585     ///
586     /// Typically this is useful just to confirm that you have a ticket, before you
587     /// call ConnectToHostedDedicatedServer to connect to the server.
588     int FindRelayAuthTicketForServer(const ref SteamNetworkingIdentity identityGameServer, int nRemoteVirtualPort,
589     SteamDatagramRelayAuthTicket* pOutParsedTicket);
590 
591     /// Client call to connect to a server hosted in a Valve data center, on the specified virtual
592     /// port.  You must have placed a ticket for this server into the cache, or else this connect
593     /// attempt will fail!  If you are not issuing your own tickets, then to connect to a dedicated
594     /// server via SDR in auto-ticket mode, use ConnectP2P.  (The server must be configured to allow
595     /// this type of connection by listening using CreateListenSocketP2P.)
596     ///
597     /// You may wonder why tickets are stored in a cache, instead of simply being passed as an argument
598     /// here.  The reason is to make reconnection to a gameserver robust, even if the client computer loses
599     /// connection to Steam or the central backend, or the app is restarted or crashes, etc.
600     ///
601     /// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
602     /// when your app initializes
603     ///
604     /// If you need to set any initial config options, pass them here.  See
605     /// SteamNetworkingConfigValue_t for more about why this is preferable to
606     /// setting the options "immediately" after creation.
607     HSteamNetConnection ConnectToHostedDedicatedServer(const ref SteamNetworkingIdentity identityTarget,
608     int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t* pOptions);
609 
610     //
611     // Servers hosted in data centers known to the Valve relay network
612     //
613 
614     /// Returns the value of the SDR_LISTEN_PORT environment variable.  This
615     /// is the UDP server your server will be listening on.  This will
616     /// configured automatically for you in production environments.
617     ///
618     /// In development, you'll need to set it yourself.  See
619     /// https://partner.steamgames.com/doc/api/ISteamNetworkingSockets
620     /// for more information on how to configure dev environments.
621     ushort GetHostedDedicatedServerPort();
622 
623     /// Returns 0 if SDR_LISTEN_PORT is not set.  Otherwise, returns the data center the server
624     /// is running in.  This will be k_SteamDatagramPOPID_dev in non-production environment.
625     SteamNetworkingPOPID GetHostedDedicatedServerPOPID();
626 
627     /// Return info about the hosted server.  This contains the PoPID of the server,
628     /// and opaque routing information that can be used by the relays to send traffic
629     /// to your server.
630     ///
631     /// You will need to send this information to your backend, and put it in tickets,
632     /// so that the relays will know how to forward traffic from
633     /// clients to your server.  See SteamDatagramRelayAuthTicket for more info.
634     ///
635     /// Also, note that the routing information is contained in SteamDatagramGameCoordinatorServerLogin,
636     /// so if possible, it's preferred to use GetGameCoordinatorServerLogin to send this info
637     /// to your game coordinator service, and also login securely at the same time.
638     ///
639     /// On a successful exit, k_EResultOK is returned
640     ///
641     /// Unsuccessful exit:
642     /// - Something other than k_EResultOK is returned.
643     /// - k_EResultInvalidState: We are not configured to listen for SDR (SDR_LISTEN_SOCKET
644     ///   is not set.)
645     /// - k_EResultPending: we do not (yet) have the authentication information needed.
646     ///   (See GetAuthenticationStatus.)  If you use environment variables to pre-fetch
647     ///   the network config, this data should always be available immediately.
648     /// - A non-localized diagnostic debug message will be placed in m_data that describes
649     ///   the cause of the failure.
650     ///
651     /// NOTE: The returned blob is not encrypted.  Send it to your backend, but don't
652     ///       directly share it with clients.
653     EResult GetHostedDedicatedServerAddress(SteamDatagramHostedAddress* pRouting);
654 
655     /// Create a listen socket on the specified virtual port.  The physical UDP port to use
656     /// will be determined by the SDR_LISTEN_PORT environment variable.  If a UDP port is not
657     /// configured, this call will fail.
658     ///
659     /// This call MUST be made through the SteamGameServerNetworkingSockets() interface.
660     ///
661     /// This function should be used when you are using the ticket generator library
662     /// to issue your own tickets.  Clients connecting to the server on this virtual
663     /// port will need a ticket, and they must connect using ConnectToHostedDedicatedServer.
664     ///
665     /// If you need to set any initial config options, pass them here.  See
666     /// SteamNetworkingConfigValue_t for more about why this is preferable to
667     /// setting the options "immediately" after creation.
668     HSteamListenSocket CreateHostedDedicatedServerListenSocket(int nLocalVirtualPort, int nOptions,
669     const SteamNetworkingConfigValue_t* pOptions);
670 
671     /// Generate an authentication blob that can be used to securely login with
672     /// your backend, using SteamDatagram_ParseHostedServerLogin.  (See
673     /// steamdatagram_gamecoordinator.h)
674     ///
675     /// Before calling the function:
676     /// - Populate the app data in pLoginInfo (m_cbAppData and m_appData).  You can leave
677     ///   all other fields uninitialized.
678     /// - *pcbSignedBlob contains the size of the buffer at pBlob.  (It should be
679     ///   at least k_cbMaxSteamDatagramGameCoordinatorServerLoginSerialized.)
680     ///
681     /// On a successful exit:
682     /// - k_EResultOK is returned
683     /// - All of the remaining fields of pLoginInfo will be filled out.
684     /// - *pcbSignedBlob contains the size of the serialized blob that has been
685     ///   placed into pBlob.
686     ///
687     /// Unsuccessful exit:
688     /// - Something other than k_EResultOK is returned.
689     /// - k_EResultNotLoggedOn: you are not logged in (yet)
690     /// - See GetHostedDedicatedServerAddress for more potential failure return values.
691     /// - A non-localized diagnostic debug message will be placed in pBlob that describes
692     ///   the cause of the failure.
693     ///
694     /// This works by signing the contents of the SteamDatagramGameCoordinatorServerLogin
695     /// with the cert that is issued to this server.  In dev environments, it's OK if you do
696     /// not have a cert.  (You will need to enable insecure dev login in SteamDatagram_ParseHostedServerLogin.)
697     /// Otherwise, you will need a signed cert.
698     ///
699     /// NOTE: The routing blob returned here is not encrypted.  Send it to your backend
700     ///       and don't share it directly with clients.
701     EResult GetGameCoordinatorServerLogin(SteamDatagramGameCoordinatorServerLogin* pLoginInfo, int* pcbSignedBlob,
702     void* pBlob);
703 
704 
705     //
706     // Relayed connections using custom signaling protocol
707     //
708     // This is used if you have your own method of sending out-of-band
709     // signaling / rendezvous messages through a mutually trusted channel.
710     //
711 
712     /// Create a P2P "client" connection that does signaling over a custom
713     /// rendezvous/signaling channel.
714     ///
715     /// pSignaling points to a new object that you create just for this connection.
716     /// It must stay valid until Release() is called.  Once you pass the
717     /// object to this function, it assumes ownership.  Release() will be called
718     /// from within the function call if the call fails.  Furthermore, until Release()
719     /// is called, you should be prepared for methods to be invoked on your
720     /// object from any thread!  You need to make sure your object is threadsafe!
721     /// Furthermore, you should make sure that dispatching the methods is done
722     /// as quickly as possible.
723     ///
724     /// This function will immediately construct a connection in the "connecting"
725     /// state.  Soon after (perhaps before this function returns, perhaps in another thread),
726     /// the connection will begin sending signaling messages by calling
727     /// ISteamNetworkingConnectionSignaling::SendSignal.
728     ///
729     /// When the remote peer accepts the connection (See
730     /// ISteamNetworkingSignalingRecvContext::OnConnectRequest),
731     /// it will begin sending signaling messages.  When these messages are received,
732     /// you can pass them to the connection using ReceivedP2PCustomSignal.
733     ///
734     /// If you know the identity of the peer that you expect to be on the other end,
735     /// you can pass their identity to improve debug output or just detect bugs.
736     /// If you don't know their identity yet, you can pass NULL, and their
737     /// identity will be established in the connection handshake.
738     ///
739     /// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
740     /// when your app initializes
741     ///
742     /// If you need to set any initial config options, pass them here.  See
743     /// SteamNetworkingConfigValue_t for more about why this is preferable to
744     /// setting the options "immediately" after creation.
745     HSteamNetConnection ConnectP2PCustomSignaling(ISteamNetworkingConnectionSignaling* pSignaling,
746     const SteamNetworkingIdentity* pPeerIdentity, int nRemoteVirtualPort, int nOptions,
747     const SteamNetworkingConfigValue_t* pOptions);
748 
749     /// Called when custom signaling has received a message.  When your
750     /// signaling channel receives a message, it should save off whatever
751     /// routing information was in the envelope into the context object,
752     /// and then pass the payload to this function.
753     ///
754     /// A few different things can happen next, depending on the message:
755     ///
756     /// - If the signal is associated with existing connection, it is dealt
757     ///   with immediately.  If any replies need to be sent, they will be
758     ///   dispatched using the ISteamNetworkingConnectionSignaling
759     ///   associated with the connection.
760     /// - If the message represents a connection request (and the request
761     ///   is not redundant for an existing connection), a new connection
762     ///   will be created, and ReceivedConnectRequest will be called on your
763     ///   context object to determine how to proceed.
764     /// - Otherwise, the message is for a connection that does not
765     ///   exist (anymore).  In this case, we *may* call SendRejectionReply
766     ///   on your context object.
767     ///
768     /// In any case, we will not save off pContext or access it after this
769     /// function returns.
770     ///
771     /// Returns true if the message was parsed and dispatched without anything
772     /// unusual or suspicious happening.  Returns false if there was some problem
773     /// with the message that prevented ordinary handling.  (Debug output will
774     /// usually have more information.)
775     ///
776     /// If you expect to be using relayed connections, then you probably want
777     /// to call ISteamNetworkingUtils::InitRelayNetworkAccess() when your app initializes
778     bool ReceivedP2PCustomSignal(const void* pMsg, int cbMsg, ISteamNetworkingSignalingRecvContext* pContext);
779 
780     //
781     // Certificate provision by the application.  On Steam, we normally handle all this automatically
782     // and you will not need to use these advanced functions.
783     //
784 
785     /// Get blob that describes a certificate request.  You can send this to your game coordinator.
786     /// Upon entry, *pcbBlob should contain the size of the buffer.  On successful exit, it will
787     /// return the number of bytes that were populated.  You can pass pBlob=NULL to query for the required
788     /// size.  (512 bytes is a conservative estimate.)
789     ///
790     /// Pass this blob to your game coordinator and call SteamDatagram_CreateCert.
791     bool GetCertificateRequest(int* pcbBlob, void* pBlob, ref SteamNetworkingErrMsg errMsg);
792 
793     /// Set the certificate.  The certificate blob should be the output of
794     /// SteamDatagram_CreateCert.
795     bool SetCertificate(const void* pCertificate, int cbCertificate, ref SteamNetworkingErrMsg errMsg);
796 
797     /// Reset the identity associated with this instance.
798     /// Any open connections are closed.  Any previous certificates, etc are discarded.
799     /// You can pass a specific identity that you want to use, or you can pass NULL,
800     /// in which case the identity will be invalid until you set it using SetCertificate
801     ///
802     /// NOTE: This function is not actually supported on Steam!  It is included
803     ///       for use on other platforms where the active user can sign out and
804     ///       a new user can sign in.
805     void ResetIdentity(const SteamNetworkingIdentity* pIdentity);
806 
807     //
808     // Misc
809     //
810 
811     /// Invoke all callback functions queued for this interface.
812     /// See k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, etc
813     ///
814     /// You don't need to call this if you are using Steam's callback dispatch
815     /// mechanism (SteamAPI_RunCallbacks and SteamGameserver_RunCallbacks).
816     void RunCallbacks();
817 
818     //
819     // "FakeIP" system.
820     //
821     // A FakeIP is essentially a temporary, arbitrary identifier that
822     // happens to be a valid IPv4 address.  The purpose of this system is to make it
823     // easy to integrate with existing code that identifies hosts using IPv4 addresses.
824     // The FakeIP address will never actually be used to send or receive any packets
825     // on the Internet, it is strictly an identifier.
826     //
827     // FakeIP addresses are designed to (hopefully) pass through existing code as
828     // transparently as possible, while conflicting with "real" addresses that might
829     // be in use on networks (both the Internet and LANs) in the same code as little
830     // as possible.  At the time this comment is being written, they come from the
831     // 169.254.0.0/16 range, and the port number will always be >1024.  HOWEVER,
832     // this is subject to change!  Do not make assumptions about these addresses,
833     // or your code might break in the future.  In particular, you should use
834     // functions such as  ISteamNetworkingUtils::IsFakeIP to determine if an IP
835     // address is a "fake" one used by this system.
836     //
837 
838     /// Begin asynchronous process of allocating a fake IPv4 address that other
839     /// peers can use to contact us via P2P.  IP addresses returned by this
840     /// function are globally unique for a given appid.
841     ///
842     /// nNumPorts is the numbers of ports you wish to reserve.  This is useful
843     /// for the same reason that listening on multiple UDP ports is useful for
844     /// different types of traffic.  Because these allocations come from a global
845     /// namespace, there is a relatively strict limit on the maximum number of
846     /// ports you may request.  (At the time of this writing, the limit is 4.)
847     /// The Port assignments are *not* guaranteed to have any particular order
848     /// or relationship!  Do *not* assume they are contiguous, even though that
849     /// may often occur in practice.
850     ///
851     /// Returns false if a request was already in progress, true if a new request
852     /// was started.  A SteamNetworkingFakeIP_t will be posted when the request
853     /// completes.
854     ///
855     /// You can call this before you are logged in.  For gameservers, doing so is
856     /// *required*, and all places where your public IP appears (such as the server
857     /// browser) will be replaced by the FakeIP, and the fake port at index 0.
858     /// A failure will not be posted (using SteamNetworkingFakeIP_t) unless we get
859     /// logged in, and then the request fails.  Furthermore, it is assumed that
860     /// FakeIP allocation is essential for your application to function, and so
861     /// failure will not be reported until *several* retries have been attempted,
862     /// possibly lasting several minutes.  It is highly recommended to treat failure
863     /// as fatal.
864     ///
865     /// To communicate using a connection-oriented (TCP-style) API:
866     /// - Server creates a listen socket using CreateListenSocketP2PFakeIP
867     /// - Client connects using ConnectByIPAddress, passing in the FakeIP address.
868     /// - The connection will behave mostly like a P2P connection.  The identities
869     ///   that appear in SteamNetConnectionInfo_t will be the FakeIP identity until
870     ///   we know the real identity.  Then it will be the real identity.  If the
871     ///   SteamNetConnectionInfo_t::m_addrRemote is valid, it will be a real IPv4
872     ///   address of a NAT-punched connection.  Otherwise, it will not be valid.
873     ///
874     /// To communicate using an ad-hoc sendto/recv from (UDP-style) API,
875     /// use CreateFakeUDPPort.
876     bool BeginAsyncRequestFakeIP(int nNumPorts);
877 
878     /// Return info about the FakeIP and port(s) that we have been assigned,
879     /// if any.  idxFirstPort is currently reserved and must be zero.
880     /// Make sure and check SteamNetworkingFakeIPResult_t::m_eResult
881     void GetFakeIP(int idxFirstPort, SteamNetworkingFakeIPResult_t* pInfo);
882 
883     /// Create a listen socket that will listen for P2P connections sent
884     /// to our FakeIP.  A peer can initiate connections to this listen
885     /// socket by calling ConnectByIPAddress.
886     ///
887     /// idxFakePort refers to the *index* of the fake port requested,
888     /// not the actual port number.  For example, pass 0 to refer to the
889     /// first port in the reservation.  You must call this only after calling
890     /// BeginAsyncRequestFakeIP.  However, you do not need to wait for the
891     /// request to complete before creating the listen socket.
892     HSteamListenSocket CreateListenSocketP2PFakeIP(int idxFakePort, int nOptions,
893     const SteamNetworkingConfigValue_t* pOptions);
894 
895     /// If the connection was initiated using the "FakeIP" system, then we
896     /// we can get an IP address for the remote host.  If the remote host had
897     /// a global FakeIP at the time the connection was established, this
898     /// function will return that global IP.  Otherwise, a FakeIP that is
899     /// unique locally will be allocated from the local FakeIP address space,
900     /// and that will be returned.
901     ///
902     /// The allocation of local FakeIPs attempts to assign addresses in
903     /// a consistent manner.  If multiple connections are made to the
904     /// same remote host, they *probably* will return the same FakeIP.
905     /// However, since the namespace is limited, this cannot be guaranteed.
906     ///
907     /// On failure, returns:
908     /// - k_EResultInvalidParam: invalid connection handle
909     /// - k_EResultIPNotFound: This connection wasn't made using FakeIP system
910     EResult GetRemoteFakeIPForConnection(HSteamNetConnection hConn, SteamNetworkingIPAddr* pOutAddr);
911 
912     /// Get an interface that can be used like a UDP port to send/receive
913     /// datagrams to a FakeIP address.  This is intended to make it easy
914     /// to port existing UDP-based code to take advantage of SDR.
915     ///
916     /// idxFakeServerPort refers to the *index* of the port allocated using
917     /// BeginAsyncRequestFakeIP and is used to create "server" ports.  You may
918     /// call this before the allocation has completed.  However, any attempts
919     /// to send packets will fail until the allocation has succeeded.  When
920     /// the peer receives packets sent from this interface, the from address
921     /// of the packet will be the globally-unique FakeIP.  If you call this
922     /// function multiple times and pass the same (nonnegative) fake port index,
923     /// the same object will be returned, and this object is not reference counted.
924     ///
925     /// To create a "client" port (e.g. the equivalent of an ephemeral UDP port)
926     /// pass -1.  In this case, a distinct object will be returned for each call.
927     /// When the peer receives packets sent from this interface, the peer will
928     /// assign a FakeIP from its own locally-controlled namespace.
929     ISteamNetworkingFakeUDPPort* CreateFakeUDPPort(int idxFakeServerPort);
930 
931 };
932 
933 enum STEAMNETWORKINGSOCKETS_INTERFACE_VERSION = "SteamNetworkingSockets011";
934 
935 // Global accessors
936 // Using standalone lib
937 version (STEAMNETWORKINGSOCKETS_STANDALONELIB) {
938 
939     // Standalone lib.
940     static assert(STEAMNETWORKINGSOCKETS_INTERFACE_VERSION[24] == '1', "Version mismatch");
941     extern (C) ISteamNetworkingSockets SteamNetworkingSockets_LibV11();
942     ISteamNetworkingSockets SteamNetworkingSockets_Lib() {
943         return SteamNetworkingSockets_LibV11();
944     }
945 
946     // If running in context of steam, we also define a gameserver instance.
947     version (STEAMNETWORKINGSOCKETS_STEAM) {
948         extern (C) ISteamNetworkingSockets SteamGameServerNetworkingSockets_LibV11();
949         ISteamNetworkingSockets SteamGameServerNetworkingSockets_Lib() {
950             return SteamGameServerNetworkingSockets_LibV11();
951         }
952     }
953 
954     version (STEAMNETWORKINGSOCKETS_STEAMAPI) { }
955     else {
956         ISteamNetworkingSockets SteamNetworkingSockets() {
957             return SteamNetworkingSockets_LibV11();
958         }
959         version (STEAMNETWORKINGSOCKETS_STEAM) {
960             ISteamNetworkingSockets SteamGameServerNetworkingSockets() {
961                 return SteamGameServerNetworkingSockets_LibV11();
962             }
963         }
964     }
965 }
966 
967 // Using Steamworks SDK
968 version (STEAMNETWORKINGSOCKETS_STEAMAPI) {
969 
970     // Steamworks SDK
971     //STEAM_DEFINE_USER_INTERFACE_ACCESSOR( ISteamNetworkingSockets *, SteamNetworkingSockets_SteamAPI, STEAMNETWORKINGSOCKETS_INTERFACE_VERSION );
972     //STEAM_DEFINE_GAMESERVER_INTERFACE_ACCESSOR( ISteamNetworkingSockets *, SteamGameServerNetworkingSockets_SteamAPI, STEAMNETWORKINGSOCKETS_INTERFACE_VERSION );
973 
974     version (STEAMNETWORKINGSOCKETS_STANDALONELIB) { }
975     else {
976         ISteamNetworkingSockets SteamNetworkingSockets() {
977             return SteamNetworkingSockets_SteamAPI();
978         }
979         ISteamNetworkingSockets SteamGameServerNetworkingSockets() {
980             return SteamGameServerNetworkingSockets_SteamAPI();
981         }
982     }
983 }
984 
985 /// This callback is posted whenever a connection is created, destroyed, or changes state.
986 /// The m_info field will contain a complete description of the connection at the time the
987 /// change occurred and the callback was posted.  In particular, m_eState will have the
988 /// new connection state.
989 ///
990 /// You will usually need to listen for this callback to know when:
991 /// - A new connection arrives on a listen socket.
992 ///   m_info.m_hListenSocket will be set, m_eOldState = k_ESteamNetworkingConnectionState_None,
993 ///   and m_info.m_eState = k_ESteamNetworkingConnectionState_Connecting.
994 ///   See ISteamNetworkigSockets::AcceptConnection.
995 /// - A connection you initiated has been accepted by the remote host.
996 ///   m_eOldState = k_ESteamNetworkingConnectionState_Connecting, and
997 ///   m_info.m_eState = k_ESteamNetworkingConnectionState_Connected.
998 ///   Some connections might transition to k_ESteamNetworkingConnectionState_FindingRoute first.
999 /// - A connection has been actively rejected or closed by the remote host.
1000 ///   m_eOldState = k_ESteamNetworkingConnectionState_Connecting or k_ESteamNetworkingConnectionState_Connected,
1001 ///   and m_info.m_eState = k_ESteamNetworkingConnectionState_ClosedByPeer.  m_info.m_eEndReason
1002 ///   and m_info.m_szEndDebug will have for more details.
1003 ///   NOTE: upon receiving this callback, you must still destroy the connection using
1004 ///   ISteamNetworkingSockets::CloseConnection to free up local resources.  (The details
1005 ///   passed to the function are not used in this case, since the connection is already closed.)
1006 /// - A problem was detected with the connection, and it has been closed by the local host.
1007 ///   The most common failure is timeout, but other configuration or authentication failures
1008 ///   can cause this.  m_eOldState = k_ESteamNetworkingConnectionState_Connecting or
1009 ///   k_ESteamNetworkingConnectionState_Connected, and m_info.m_eState = k_ESteamNetworkingConnectionState_ProblemDetectedLocally.
1010 ///   m_info.m_eEndReason and m_info.m_szEndDebug will have for more details.
1011 ///   NOTE: upon receiving this callback, you must still destroy the connection using
1012 ///   ISteamNetworkingSockets::CloseConnection to free up local resources.  (The details
1013 ///   passed to the function are not used in this case, since the connection is already closed.)
1014 ///
1015 /// Remember that callbacks are posted to a queue, and networking connections can
1016 /// change at any time.  It is possible that the connection has already changed
1017 /// state by the time you process this callback.
1018 ///
1019 /// Also note that callbacks will be posted when connections are created and destroyed by your own API calls.
1020 struct SteamNetConnectionStatusChangedCallback_t {
1021 
1022     enum { k_iCallback = k_iSteamNetworkingSocketsCallbacks + 1 };
1023 
1024     /// Connection handle
1025     HSteamNetConnection m_hConn;
1026 
1027     /// Full connection info
1028     SteamNetConnectionInfo_t m_info;
1029 
1030     /// Previous state.  (Current state is in m_info.m_eState)
1031     ESteamNetworkingConnectionState m_eOldState;
1032 
1033 }
1034 
1035 static assert(SteamNetConnectionStatusChangedCallback_t.sizeof == 704);
1036 
1037 /// A struct used to describe our readiness to participate in authenticated,
1038 /// encrypted communication.  In order to do this we need:
1039 ///
1040 /// - The list of trusted CA certificates that might be relevant for this
1041 ///   app.
1042 /// - A valid certificate issued by a CA.
1043 ///
1044 /// This callback is posted whenever the state of our readiness changes.
1045 struct SteamNetAuthenticationStatus_t {
1046 
1047     enum { k_iCallback = k_iSteamNetworkingSocketsCallbacks + 2 };
1048 
1049     /// Status
1050     ESteamNetworkingAvailability m_eAvail;
1051 
1052     /// Non-localized English language status.  For diagnostic/debugging
1053     /// purposes only.
1054     char[256] m_debugMsg;
1055 
1056 };