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 };