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