-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmodule.jai
2132 lines (1913 loc) · 121 KB
/
module.jai
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//
// Game Networking Sockets is a cleaned-up version of steam's networking library.
// This is a simplified and un-steamify binding so intended to be easy to use.
//
#import "Basic"; // print
// GameNetworkingSockets
GameNetworkingSockets :: struct
{
Initialize :: (pIdentity : *Identity = null) -> success : bool
{
hasFailed : bool = false;
err : *s8;
// Initialize the library. Optionally, you can set an initial identity
// for the default interface that is returned by SteamNetworkingSockets().
// On failure, false is returned, and a non-localized diagnostic message is returned.
GameNetworkingSockets_Init :: (pIdentity: *Identity, errMsg: *NetworkingErrMsg) -> bool #foreign lib "GameNetworkingSockets_Init";
hasFailed |= (GameNetworkingSockets_Init(pIdentity, *err) == false);
if hasFailed
{
errMsg : string;
errMsg.data = xx err;
errMsg.count = c_style_strlen(xx err);
print("GameNetworkingSocket_Init() failed! ErrMsg: %\n", errMsg);
}
g_sockets_interface = GetISockets();
hasFailed |= (g_sockets_interface == null);
if hasFailed then print("GetISockets() failed!\n");
g_utils_interface = GetIUtils();
hasFailed |= (g_utils_interface == null);
if hasFailed then print("GetIUtils() failed!\n");
return !hasFailed;
}
Finalize :: ()
{
// Close all connections and listen sockets and free all resources
GameNetworkingSockets_Kill :: () #c_call #foreign lib "GameNetworkingSockets_Kill";
GameNetworkingSockets_Kill();
}
GetISockets :: () -> *ISockets #foreign lib "SteamAPI_SteamNetworkingSockets_v009";
GetIUtils :: () -> *IUtils #foreign lib "SteamAPI_SteamNetworkingUtils_v003";
// Custom memory allocation methods. If you call this, you MUST call it exactly once,
// before calling any other API function. *Most* allocations will pass through these,
// especially all allocations that are per-connection. A few allocations
// might still go to the default CRT malloc and operator new.
// To use this, you must compile the library with STEAMNETWORKINGSOCKETS_ENABLE_MEM_OVERRIDE
//
// The included binaries in gns-jai DO NOT compile with STEAMNETWORKINGSOCKETS_ENABLE_MEM_OVERRIDE
// so you MUST make your own binaries to use this feature.
//
SetCustomMemoryAllocator :: (
pfn_malloc: Malloc,
pfn_free: Free,
pfn_realloc: Realloc) #foreign lib "SteamNetworkingSockets_SetCustomMemoryAllocator";
Malloc :: #type (s: u64) -> *void;
Free :: #type (p: *void);
Realloc :: #type (p: *void, s: u64) -> *void;
}
//-----------------------------------------------------------------------------
// Lower level networking API.
//
// - Connection-oriented API (like TCP, not UDP). When sending and receiving
// messages, a connection handle is used. In this TCP-style interface, the
// "server" will "listen" on a "listen socket." A "client" will "connect"
// to the server, and the server will "accept" the connection.
// - But unlike TCP, it's message-oriented, not stream-oriented.
// - Mix of reliable and unreliable messages
// - Fragmentation and reassembly
// - Supports connectivity over plain UDP
//
// These bindings do not support:
// - gns-jai is simplified and does NOT provide the bindings for supports SDR ("Steam Datagram Relay"). The
// "P2P" (peer to peer) custom signaling for "ICE" (Interactive Connectivity Establishment) using a STUN
// and TURN servers are also NOT included since the GNS 1.2.0 doesn't provide a C-friendly interface.
//
// Note that neither of the terms "connection" nor "socket" necessarily correspond
// one-to-one with an underlying UDP socket. An attempt has been made to
// keep the semantics as similar to the standard socket model when appropriate,
// but some deviations do exist.
//
Sockets :: WrapISockets(#bake_arguments GlobalInterfaceWrapper(pp = *g_sockets_interface));
//-----------------------------------------------------------------------------
// Misc networking utilities for checking the local networking environment
// and estimating pings.
Utils :: WrapIUtils(#bake_arguments GlobalInterfaceWrapper(pp = *g_utils_interface));
// Wrapper around ISockets to enable Sockets.functionName to pass the interface pointer
WrapISockets :: struct(s : () -> *ISockets)
{
// Creates a "server" socket that listens for clients to connect to by
// calling ConnectByIPAddress, over ordinary UDP (IPv4 or IPv6)
//
// You must select a specific local port to listen on and set it
// the port field of the local address.
//
// Usually you will set the IP portion of the address to zero (IPAddr.Clear()).
// This means that you will not bind to any particular local interface (i.e. the same
// as INADDR_ANY in plain socket code). Furthermore, if possible the socket will be bound
// in "dual stack" mode, which means that it can accept both IPv4 and IPv6 client connections.
// If you really do wish to bind a particular interface, then set the local address to the
// appropriate IPv4 or IPv6 IP.
//
// If you need to set any initial config options, pass them here. See ConfigValue for more
// about why this is preferable to setting the options "immediately" after creation.
//
// When a client attempts to connect, a ConnectionStatusChanged
// will be posted. The connection will be in the connecting state.
CreateListenSocketIP :: (localAddress: *IPAddr, nOptions: s32, pOptions: *ConfigValue) -> ListenSocket { return s().CreateListenSocketIP(s(), localAddress, nOptions, pOptions); }
// Creates a connection and begins talking to a "server" over UDP at the
// given IPv4 or IPv6 address. The remote host must be listening with a
// matching call to CreateListenSocketIP on the specified port.
//
// A ConnectionStatusChanged callback will be triggered when we start
// connecting, and then another one on either timeout or successful connection.
//
// If the server does not have any identity configured, then their network address
// will be the only identity in use. Or, the network host may provide a platform-specific
// identity with or without a valid certificate to authenticate that identity. (These
// details will be contained in the ConnectionStatusChanged.) It's up to your application
// to decide whether to allow the connection.
//
// By default, all connections will get basic encryption sufficient to prevent
// casual eavesdropping. But note that without certificates (or a shared secret
// distributed through some other out-of-band mechanism), you don't have any
// way of knowing who is actually on the other end, and thus are vulnerable to
// man-in-the-middle attacks.
//
// If you need to set any initial config options, pass them here. See
// ConfigValue for more about why this is preferable to
// setting the options "immediately" after creation.
ConnectByIPAddress :: (address: *IPAddr, nOptions: s32, pOptions: *ConfigValue) -> NetConnection { return s().ConnectByIPAddress(s(), address, nOptions, pOptions); }
// Accept an incoming connection that has been received on a listen socket.
//
// When a connection attempt is received (perhaps after a few basic handshake
// packets have been exchanged to prevent trivial spoofing), a connection interface
// object is created in the ConnectionState.Connecting state
// and a ConnectionStatusChanged is posted. At this point, your
// application MUST either accept or close the connection. (It may not ignore it.)
// Accepting the connection will transition it either into the connected state,
// or the finding route state, depending on the connection type.
//
// You should take action within a second or two, because accepting the connection is
// what actually sends the reply notifying the client that they are connected. If you
// delay taking action, from the client's perspective it is the same as the network
// being unresponsive, and the client may timeout the connection attempt. In other
// words, the client cannot distinguish between a delay caused by network problems
// and a delay caused by the application.
//
// This means that if your application goes for more than a few seconds without
// processing callbacks (for example, while loading a map), then there is a chance
// that a client may attempt to connect in that interval and fail due to timeout.
//
// If the application does not respond to the connection attempt in a timely manner,
// and we stop receiving communication from the client, the connection attempt will
// be timed out locally, transitioning the connection to the
// ConnectionState.ProblemDetectedLocally state. The client may also
// close the connection before it is accepted, and a transition to the
// ConnectionState.ClosedByPeer is also possible on the exact
// sequence of events.
//
// Returns Result.InvalidParam if the handle is invalid.
// Returns Result.InvalidState if the connection is not in the appropriate state.
// (Remember that the connection state could change in between the time that the
// notification being posted to the queue and when it is received by the application.)
//
// A note about connection configuration options. If you need to set any configuration
// options that are common to all connections accepted through a particular listen
// socket, consider setting the options on the listen socket, since such options are
// inherited automatically. If you really do need to set options that are connection
// specific, it is safe to set them on the connection before accepting the connection.
AcceptConnection :: (conn: NetConnection) -> Result { return s().AcceptConnection(s(), conn); }
// Disconnects from the remote host and invalidates the connection handle.
// Any unread data on the connection is discarded.
//
// reason: ConnectionEnd is an application-defined code that will be received on the other
// end and recorded (when possible) in backend analytics. The value should come from
// a restricted range. (See ConnectionEnd) If you don't need to communicate any
// information to the remote host, and do not want analytics to be able to distinguish
// "normal" connection terminations from "exceptional" ones, You may pass zero, in
// which case the generic value of ConnectionEnd.App_Generic will be used.
//
// debugMessage: *s8 is an optional human-readable diagnostic string that will be received
// by the remote host and recorded (when possible) in backend analytics.
//
// If you wish to put the socket into a "linger" state, where an attempt is made to
// flush any remaining sent data, use bEnableLinger=true. Otherwise reliable data
// is not flushed.
//
// If the connection has already ended and you are just freeing up the connection
// interface, the reason code, debug string, and linger flag are ignored.
CloseConnection :: (peer: NetConnection, reason: ConnectionEnd, debugMessage: *s8, bEnableLinger: bool) -> bool { return s().CloseConnection(s(), peer, reason, debugMessage, bEnableLinger); }
// Destroy a listen socket. All the connections that were accepting on the listen
// socket are closed ungracefully.
CloseListenSocket :: (socket: ListenSocket) -> bool { return s().CloseListenSocket(s(), socket); }
// Set connection user data. the data is returned in the following places
// - You can query it using GetConnectionUserData.
// - The NetworkingMessage structure.
// - The ConnectionInfo structure. (Which is a member of ConnectionStatusChanged.)
// (Which is a member of ConnectionStatusChangedFunctionType -- but see WARNINGS below!!!!)
//
// Do you need to set this atomically when the connection is created?
// See ConfigValueLabel.ConnectionUserData.
//
// WARNING: Be *very careful* when using the value provided in callbacks structs.
// Callbacks are queued, and the value that you will receive in your
// callback is the userdata that was effective at the time the callback
// was queued. There are subtle race conditions that can hapen if you
// don't understand this!
//
// If any incoming messages for this connection are queued, the userdata
// field is updated, so that when when you receive messages (e.g. with
// ReceiveMessagesOnConnection), they will always have the very latest
// userdata. So the tricky race conditions that can happen with callbacks
// do not apply to retrieving messages.
//
// Returns false if the handle is invalid.
SetConnectionUserData :: (peer: NetConnection, nUserData: s64) -> bool { return s().SetConnectionUserData(s(), peer, nUserData); }
// Fetch connection user data. Returns -1 if handle is invalid
// or if you haven't set any userdata on the connection.
GetConnectionUserData :: (peer: NetConnection) -> s64 { return s().GetConnectionUserData(s(), peer); };
// Set a name for the connection, used mostly for debugging
SetConnectionName :: (peer: NetConnection, name: *s8) { s().SetConnectionName(s(), peer, name); }
// Fetch connection name. Returns false if handle is invalid
GetConnectionName :: (peer: NetConnection, name: *s8, maxLen: s32) -> bool { return s().GetConnectionName(s(), peer, name, maxLen); }
// Send a message to the remote host on the specified connection.
//
// sendFlags: NetworkingSend determines the delivery guarantees that will be
// provided, when data should be buffered, etc. (E.g. NetworkingSend.Unreliable)
//
// Note that the semantics we use for messages are not precisely
// the same as the semantics of a standard "stream" socket.
// (SOCK_STREAM) For an ordinary stream socket, the boundaries
// between chunks are not considered relevant, and the sizes of
// the chunks of data written will not necessarily match up to
// the sizes of the chunks that are returned by the reads on
// the other end. The remote host might read a partial chunk,
// or chunks might be coalesced. For the message semantics
// used here, however, the sizes WILL match. Each send call
// will match a successful read call on the remote host
// one-for-one. If you are porting existing stream-oriented
// code to the semantics of reliable messages, your code should
// work the same, since reliable message semantics are more
// strict than stream semantics. The only caveat is related to
// performance: there is per-message overhead to retain the
// message sizes, and so if your code sends many small chunks
// of data, performance will suffer. Any code based on stream
// sockets that does not write excessively small chunks will
// work without any changes.
//
// The pOutMessageNumber is an optional pointer to receive the
// message number assigned to the message, if sending was successful.
//
// Returns:
// - ResultInvalidParam: invalid connection handle, or the individual message is too big.
// (See MaxNetworkingMessageSendSize)
// - Result.InvalidState: connection is in an invalid state
// - Result.NoConnection: connection has ended
// - Result.Ignored: You used NetworkingSend.NoDelay, and the message was dropped because
// we were not ready to send it.
// - Result.LimitExceeded: there was already too much data queued to be sent.
// (See ConfigValueLabel.SendBufferSize)
SendMessageToConnection :: (conn: NetConnection, data: *void, cbData: u32, sendFlags: NetworkingSend, pOutMessageNumber: *s64) -> Result { return s().SendMessageToConnection(s(), conn, data, cbData, sendFlags, pOutMessageNumber); }
SendStringToConnection :: (conn: NetConnection, str: string, sendFlags: NetworkingSend, pOutMessageNumber: *s64) -> Result { return s().SendMessageToConnection(s(), conn, str.data, xx str.count, sendFlags, pOutMessageNumber); }
// Send one or more messages without copying the message payload.
// This is the most efficient way to send messages. To use this
// function, you must first allocate a message object using
// IUtils.AllocateMessage. (Do not declare one
// on the stack or allocate your own.)
//
// You should fill in the message payload. You can either let
// it allocate the buffer for you and then fill in the payload,
// or if you already have a buffer allocated, you can just point
// m_pData at your buffer and set the callback to the appropriate function
// to free it. Note that if you use your own buffer, it MUST remain valid
// until the callback is executed. And also note that your callback can be
// invoked at any time from any thread (perhaps even before SendMessages
// returns!), so it MUST be fast and threadsafe.
//
// You MUST also fill in:
// - m_conn - the handle of the connection to send the message to
// - m_nFlags - bitmask of NetworkingSend.xxx flags.
//
// All other fields are currently reserved and should not be modified.
//
// The library will take ownership of the message structures. They may
// be modified or become invalid at any time, so you must not read them
// after passing them to this function.
//
// pOutMessageNumberOrResult is an optional array that will receive,
// for each message, the message number that was assigned to the message
// if sending was successful. If sending failed, then a negative EResult
// value is placed into the array. For example, the array will hold
// -Result.InvalidState if the connection was in an invalid state.
// See ISockets.SendMessageToConnection for possible
// failure codes.
SendMessages :: (nMessages: s32, pMessages: **NetworkingMessage, pOutMessageNumberOrResult: *s64) { s().SendMessages(s(), nMessages, pMessages, pOutMessageNumberOrResult); }
// Flush any messages waiting on the Nagle timer and send them
// at the next transmission opportunity (often that means right now).
//
// If Nagle is enabled (it's on by default) then when calling
// SendMessageToConnection the message will be buffered, up to the Nagle time
// before being sent, to merge small messages into the same packet.
// (See ConfigValueLabel.NagleTime)
//
// Returns:
// Result.InvalidParam: invalid connection handle
// Result.InvalidState: connection is in an invalid state
// Result.NoConnection: connection has ended
// Result.Ignored: We weren't (yet) connected, so this operation has no effect.
FlushMessagesOnConnection :: (conn: NetConnection) -> Result { return s().FlushMessagesOnConnection(s(), conn); }
// Fetch the next available message(s) from the connection, if any.
// Returns the number of messages returned into your array, up to nMaxMessages.
// If the connection handle is invalid, -1 is returned.
//
// The order of the messages returned in the array is relevant.
// Reliable messages will be received in the order they were sent (and with the
// same sizes --- see SendMessageToConnection for on this subtle difference from a stream socket).
//
// Unreliable messages may be dropped, or delivered out of order with respect to
// each other or with respect to reliable messages. The same unreliable message
// may be received multiple times.
//
// If any messages are returned, you MUST call NetworkingMessage.Release() on each
// of them free up resources after you are done. It is safe to keep the object alive for
// a little while (put it into some queue, etc), and you may call Release() from any thread.
ReceiveMessagesOnConnection :: (conn: NetConnection, ppOutMessages: **NetworkingMessage, nMaxMessages: s32) -> s32 { return s().ReceiveMessagesOnConnection(s(), conn, ppOutMessages, nMaxMessages); }
// Returns basic information about the high-level state of the connection.
GetConnectionInfo :: (conn: NetConnection, info: *ConnectionInfo) -> bool { return s().GetConnectionInfo(s(), conn, info); }
// Returns a small set of information about the real-time state of the connection
// Returns false if the connection handle is invalid, or the connection has ended.
GetQuickConnectionStatus :: (conn: NetConnection, stats: *QuickConnectionStatus) -> bool { return s().GetQuickConnectionStatus(s(), conn, stats); }
// Returns detailed connection stats in text format. Useful for dumping to a log, etc.
//
// Returns:
// -1 failure (bad connection handle)
// 0 OK, your buffer was filled in and '\0'-terminated
// >0 Your buffer was either nullptr, or it was too small and the text got truncated.
// Try again with a buffer of at least N bytes.
GetDetailedConnectionStatus :: (conn: NetConnection, buf: *s8, cbBuf: s32) -> s32 { return s().GetDetailedConnectionStatus(s(), conn, buf, cbBuf); }
// Returns local IP and port that a listen socket created using CreateListenSocketIP is bound to.
//
// An IPv6 address of ::0 means "any IPv4 or IPv6"
// An IPv6 address of ::ffff:0000:0000 means "any IPv4"
GetListenSocketAddress :: (socket: ListenSocket, address: *IPAddr) -> bool { return s().GetListenSocketAddress(s(), socket, address); }
// Create a pair of connections that are talking to each other, e.g. a loopback connection.
// This is very useful for testing, or so that your client/server code can work the same
// even when you are running a local "server".
//
// The two connections will immediately be placed into the connected state, and no callbacks
// will be posted immediately. After this, if you close either connection, the other connection
// will receive a callback, exactly as if they were communicating over the network. You must
// close *both* sides in order to fully clean up the resources!
//
// By default, internal buffers are used, completely bypassing the network, the chopping up of
// messages into packets, encryption, copying the payload, etc. This means that loopback
// packets, by default, will not simulate lag or loss. Passing true for bUseNetworkLoopback will
// cause the socket pair to send packets through the local network loopback device (127.0.0.1)
// on ephemeral ports. Fake lag and loss are supported in this case, and CPU time is expended
// to encrypt and decrypt.
//
// If you wish to assign a specific identity to either connection, you may pass a particular
// identity. Otherwise, if you pass nullptr, the respective connection will assume a generic
// "localhost" identity. If you use real network loopback, this might be translated to the
// actual bound loopback port. Otherwise, the port will be zero.
CreateSocketPair :: (pOutConnection1: *NetConnection, pOutConnection2: *NetConnection, bUseNetworkLoopback: bool, pIdentity1: *Identity, pIdentity2: *Identity) -> bool { return s().CreateSocketPair(s(), pOutConnection1, pOutConnection2, bUseNetworkLoopback, pIdentity1, pIdentity2); }
// Get the identity assigned to this interface.
// E.g. on Steam, this is the user's SteamID, or for the gameserver interface, the SteamID assigned
// to the gameserver. Returns false and sets the result to an invalid identity if we don't know
// our identity yet. (E.g. GameServer has not logged in. On Steam, the user will know their SteamID
// even if they are not signed into Steam.)
GetIdentity :: (pIdentity: *Identity) -> bool { return s().GetIdentity(s(), pIdentity); }
// Indicate our desire to be ready participate in authenticated communications.
// If we are currently not ready, then steps will be taken to obtain the necessary
// certificates. (This includes a certificate for us, as well as any CA certificates
// needed to authenticate peers.)
//
// You can call this at program init time if you know that you are going to
// be making authenticated connections, so that we will be ready immediately when
// those connections are attempted. (Note that essentially all connections require
// authentication, with the exception of ordinary UDP connections with authentication
// disabled using ConfigValueLabel.IP_AllowWithoutAuth.) If you don't call
// this function, we will wait until a feature is utilized that that necessitates
// these resources.
//
// You can also call this function to force a retry, if failure has occurred.
// Once we make an attempt and fail, we will not automatically retry.
// In this respect, the behavior of the system after trying and failing is the same
// as before the first attempt: attempting authenticated communication or calling
// this function will call the system to attempt to acquire the necessary resources.
//
// You can use GetAuthenticationStatus or listen for AuthenticationStatus
// to monitor the status.
//
// Returns the current value that would be returned from GetAuthenticationStatus.
InitAuthentication :: () -> NetworkAvailability { return s().InitAuthentication(s()); }
// Query our readiness to participate in authenticated communications. A
// AuthenticationStatus callback is posted any time this status changes,
// but you can use this function to query it at any time.
//
// The value of AuthenticationStatus.m_eAvail is returned. If you only
// want this high level status, you can pass NULL for pDetails. If you want further
// details, pass non-NULL to receive them.
GetAuthenticationStatus :: (details: *AuthenticationStatus) -> NetworkAvailability { return s().GetAuthenticationStatus(s(), details); }
//
// Poll groups. A poll group is a set of connections that can be polled efficiently.
// (In our API, to "poll" a connection means to retrieve all pending messages. We
// actually don't have an API to "poll" the connection *state*, like BSD sockets.)
//
// Create a new poll group.
//
// You should destroy the poll group when you are done using DestroyPollGroup
CreatePollGroup :: () -> PollGroup { return s().CreatePollGroup(s()); }
// Destroy a poll group created with CreatePollGroup().
//
// If there are any connections in the poll group, they are removed from the group,
// and left in a state where they are not part of any poll group.
// Returns false if passed an invalid poll group handle.
DestroyPollGroup :: (pollGroup: PollGroup) -> bool{ return s().DestroyPollGroup(s(), pollGroup); }
// Assign a connection to a poll group. Note that a connection may only belong to a
// single poll group. Adding a connection to a poll group implicitly removes it from
// any other poll group it is in.
//
// You can pass PollGroup.Invalid to remove a connection from its current
// poll group without adding it to a new poll group.
//
// If there are received messages currently pending on the connection, an attempt
// is made to add them to the queue of messages for the poll group in approximately
// the order that would have applied if the connection was already part of the poll
// group at the time that the messages were received.
//
// Returns false if the connection handle is invalid, or if the poll group handle
// is invalid (and not PollGroup.Invalid).
SetConnectionPollGroup :: (conn: NetConnection, pollGroup: PollGroup) -> bool { return s().SetConnectionPollGroup(s(), conn, pollGroup); }
// Same as ReceiveMessagesOnConnection, but will return the next messages available
// on any connection in the poll group. Examine NetworkingMessage.m_conn
// to know which connection. (NetworkingMessage.m_nConnUserData might also
// be useful.)
//
// Delivery order of messages among different connections will usually match the
// order that the last packet was received which completed the message. But this
// is not a strong guarantee, especially for packets received right as a connection
// is being assigned to poll group.
//
// Delivery order of messages on the same connection is well defined and the
// same guarantees are present as mentioned in ReceiveMessagesOnConnection.
// (But the messages are not grouped by connection, so they will not necessarily
// appear consecutively in the list; they may be interleaved with messages for
// other connections.)
ReceiveMessagesOnPollGroup :: (pollGroup: PollGroup, ppOutMessages: **NetworkingMessage, nMaxMessages: s32) -> s32{ return s().ReceiveMessagesOnPollGroup(s(), pollGroup, ppOutMessages, nMaxMessages); }
//
// Certificate provision by the application. On Steam, we normally handle all this automatically
// and you will not need to use these advanced functions.
//
// Get blob that describes a certificate request. You can send this to your game coordinator.
// Upon entry, *pcbBlob should contain the size of the buffer. On successful exit, it will
// return the number of bytes that were populated. You can pass pBlob=NULL to query for the required
// size. (256 bytes is a very conservative estimate.)
//
// Pass this blob to your game coordinator and call SteamDatagram_CreateCert.
GetCertificateRequest :: (pcbBlob: *s32, pBlob: *void, errMsg: *NetworkingErrMsg) -> bool { return s().GetCertificateRequest(s(), pcbBlob, pBlob, errMsg); }
// Set the certificate. The certificate blob should be the output of SteamDatagram_CreateCert.
SetCertificate :: (pCertificate: *void, cbCertificate: s32, errMsg: *NetworkingErrMsg) -> bool { return s().SetCertificate(s(), pCertificate, cbCertificate, errMsg); }
// Invoke all callback functions queued for this interface.
// See ConfigValueLabel.Callback_ConnectionStatusChanged, etc
RunCallbacks :: () { s().RunCallbacks(s()); }
}
// Wrapper around IUtils to enable Utils.functionName to pass the interface pointer
WrapIUtils :: struct(s : () -> *IUtils)
{
// Allocate and initialize a message object. Usually the reason
// you call this is to pass it to ISockets.SendMessages.
// The returned object will have all of the relevant fields cleared to zero.
//
// Optionally you can also request that this system allocate space to
// hold the payload itself. If size is nonzero, the system
// will allocate memory to hold a payload of at least size bytes.
// m_pData will point to the allocated buffer, m_cbSize will be set to the
// size, and m_pfnFreeData will be set to the proper function to free up
// the buffer.
//
// If size=0, then no buffer is allocated. m_pData will be NULL,
// m_cbSize will be zero, and m_pfnFreeData will be NULL. You will need to
// set each of these.
AllocateMessage :: (size: s32) -> *NetworkingMessage { return s().AllocateMessage (s(), size);}
// Fetch current timestamp. This timer has the following properties:
//
// - Monotonicity is guaranteed.
// - The initial value will be at least 24*3600*30*1e6, i.e. about
// 30 days worth of microseconds. In this way, the timestamp value of
// 0 will always be at least "30 days ago". Also, negative numbers
// will never be returned.
// - Wraparound / overflow is not a practical concern.
//
// If you are running under the debugger and stop the process, the clock
// might not advance the full wall clock time that has elapsed between
// calls. If the process is not blocked from normal operation, the
// timestamp values will track wall clock time, even if you don't call
// the function frequently.
//
// The value is only meaningful for this run of the process. Don't compare
// it to values obtained on another computer, or other runs of the same process.
GetLocalTimestamp :: () -> Microseconds { return s().GetLocalTimestamp(s()); }
// Set a function to receive network-related information that is useful for debugging.
// This can be very useful during development, but it can also be useful for troubleshooting
// problems with tech savvy end users. If you have a console or other log that customers
// can examine, these log messages can often be helpful to troubleshoot network issues.
// (Especially any warning/error messages.)
//
// The detail level indicates what message to invoke your callback on. Lower numeric
// value means more important, and the value you pass is the lowest priority (highest
// numeric value) you wish to receive callbacks for.
//
// The value here controls the detail level for most messages. You can control the
// detail level for various subsystems (perhaps only for certain connections) by
// adjusting the configuration values ConfigValueLabel.LogLevel_Xxxxx.
//
// Except when debugging, you should only use DebugOutputLevel.Msg or DebugOutputLevel.Warning.
// For best performance, do NOT request a high detail level and then filter out messages in
// your callback. This incurs all of the expense of formatting the messages, which are then
// discarded. Setting a high priority value (low numeric value) here allows the library to
// avoid doing this work.
//
// IMPORTANT: This may be called from a service thread, while we own a mutex, etc.
// Your output function must be threadsafe and fast! Do not make any other
// Steamworks calls from within the handler.
SetDebugOutputFunction :: (detailLevel: DebugOutputLevel, pfnFunc: DebugOutputFunctionType) { s().SetDebugOutputFunction(s(), detailLevel, pfnFunc); }
//
// Set and get configuration values, see ESteamNetworkingConfigValue for individual descriptions.
//
// Shortcuts for common cases. (Implemented as inline functions below)
SetGlobalConfigValueInt32 :: (valueLabel: ConfigValueLabel, val: s32) -> bool { return s().SetGlobalConfigValueInt32 (s(), valueLabel, val); }
SetGlobalConfigValueFloat :: (valueLabel: ConfigValueLabel, val: float32) -> bool { return s().SetGlobalConfigValueFloat (s(), valueLabel, val); }
SetGlobalConfigValueString :: (valueLabel: ConfigValueLabel, val: *s8) -> bool { return s().SetGlobalConfigValueString(s(), valueLabel, val); }
SetGlobalConfigValuePtr :: (valueLabel: ConfigValueLabel, val: *void) -> bool { return s().SetGlobalConfigValuePtr (s(), valueLabel, val); };
SetConnectionConfigValueInt32 :: (conn: NetConnection, valueLabel: ConfigValueLabel, val: s32) -> bool { return s().SetConnectionConfigValueInt32 (s(), conn, valueLabel, val); }
SetConnectionConfigValueFloat :: (conn: NetConnection, valueLabel: ConfigValueLabel, val: float32) -> bool { return s().SetConnectionConfigValueFloat (s(), conn, valueLabel, val); }
SetConnectionConfigValueString :: (conn: NetConnection, valueLabel: ConfigValueLabel, val: *s8) -> bool { return s().SetConnectionConfigValueString(s(), conn, valueLabel, val); }
//
// Set global callbacks. ISockets.RunCallbacks() will invoke these methods.
//
SetGlobalCallbackConnectionStatusChanged :: (fnCallback: ConnectionStatusChangedFunctionType) -> bool { return s().SetGlobalCallbackConnectionStatusChanged(s(), fnCallback); }
SetGlobalCallbackAuthenticationStatusChanged :: (fnCallback: AuthenticationStatusChangedFunctionType) -> bool { return s().SetGlobalCallbackAuthenticationStatusChanged(s(), fnCallback); }
// Set a configuration value.
// - valueLabel: which value is being set
// - scope: Onto what type of object are you applying the setting?
// - scopeObj: Which object you want to change? (Ignored for global scope). E.g. connection handle, listen socket handle, interface pointer, etc.
// - eDataType: What type of data is in the buffer at pValue? This must match the type of the variable exactly!
// - pArg: Value to set it to. You can pass NULL to remove a non-global setting at this scope,
// causing the value for that object to use global defaults. Or at global scope, passing NULL
// will reset any custom value and restore it to the system default.
// NOTE: When setting pointers (e.g. callback functions), do not pass the function pointer directly.
// Your argument should be a pointer to a function pointer.
SetConfigValue :: (valueLabel: ConfigValueLabel, scope: ConfigScope, scopeObj: intptr, eDataType: ConfigDataType, pArg: *void) -> bool { return s().SetConfigValue(s(), valueLabel, scope, scopeObj, eDataType, pArg); }
// Set a configuration value, using a struct to pass the value.
// (This is just a convenience shortcut; see below for the implementation and
// a little insight into how ConfigValue is used when
// setting config options during listen socket and connection creation.)
SetConfigValueStruct :: (opt: *ConfigValue, scope: ConfigScope, scopeObj: intptr) -> bool { return s().SetConfigValueStruct(s(), opt, scope, scopeObj); }
// Get a configuration value.
// - valueLabel: which value to fetch
// - scope: query setting on what type of object
// - scopeObj: the object to query the setting for
// - pOutDataType: If non-NULL, the data type of the value is returned.
// - pResult: Where to put the result. Pass NULL to query the required buffer size. (GetConfigValueResult.BufferTooSmall will be returned.)
// - cbResult: IN: the size of your buffer. OUT: the number of bytes filled in or required.
GetConfigValue :: (valueLabel: ConfigValueLabel, scope: ConfigScope, scopeObj: intptr, pOutDataType: *ConfigDataType, pResult: *void, cbResult: *u64) -> IUtils.GetConfigValueResult { return s().GetConfigValue(s(), valueLabel, scope, scopeObj, pOutDataType, pResult, cbResult); }
// Returns info about a configuration value. Returns false if the value does not exist.
// pOutNextValue can be used to iterate through all of the known configuration values.
// (Use GetFirstConfigValue() to begin the iteration, will be ConfigValueLabel.Invalid on the last value)
// Any of the output parameters can be NULL if you do not need that information.
//
// See ConfigValueLabel.EnumerateDevVars for some more info about "dev" variables,
// which are usually excluded from the set of variables enumerated using this function.
GetConfigValueInfo :: (valueLabel: ConfigValueLabel, pOutName: **s8, pOutDataType: *ConfigDataType, pOutScope: *ConfigScope, pOutNextValue: *ConfigValueLabel) -> bool { return s().GetConfigValueInfo (s(), valueLabel, pOutName, pOutDataType, pOutScope, pOutNextValue); }
// Return the lowest numbered configuration value available in the current environment.
GetFirstConfigValue :: () -> ConfigValueLabel { return s().GetFirstConfigValue (s()); }
}
//
// Network message
//
NetworkingMessage :: struct
{
// You MUST call this when you're done with the object, to free up memory, etc.
Release :: (self: *NetworkingMessage) -> void #foreign lib "SteamAPI_SteamNetworkingMessage_t_Release";
// Message payload
m_pData: *void;
// Size of the payload.
m_cbSize: s32;
// Max size of a single message that we can SEND.
// Note: We might be wiling to receive larger messages, and our peer might, too.
MaxNetworkingMessageSendSize :s32: 524288; // in bytes
// For messages received on connections: what connection did this come from?
// For outgoing messages: what connection to send it to?
m_conn: NetConnection;
// For inbound messages: Who sent this to us?
// For outbound messages on connections: not used.
m_identityPeer: Identity;
// For messages received on connections, this is the user data
// associated with the connection.
//
// This is *usually* the same as calling GetConnection() and then
// fetching the user data associated with that connection, but for
// the following subtle differences:
//
// - This user data will match the connection's user data at the time
// is captured at the time the message is returned by the API.
// If you subsequently change the userdata on the connection,
// this won't be updated.
// - This is an inline call, so it's *much* faster.
// - You might have closed the connection, so fetching the user data
// would not be possible.
//
// Not used when sending messages,
m_nConnUserData: s64;
// Local timestamp when the message was received
// Not used for outbound messages.
m_usecTimeReceived: Microseconds;
// Message number assigned by the sender.
// This is not used for outbound messages
m_nMessageNumber: s64;
// Function used to free up m_pData. This mechanism exists so that
// apps can create messages with buffers allocated from their own
// heap, and pass them into the library. This function will
// usually be something like:
//
// free( pMsg->m_pData );
m_pfnFreeData: #type (a0: *NetworkingMessage) -> void #c_call;
// Function to used to decrement the internal reference count and, if
// it's zero, release the message. You should not set this function pointer,
// or need to access this directly! Use the Release() function instead!
m_pfnRelease: #type (a0: *NetworkingMessage) -> void #c_call;
// When using ISteamNetworkingMessages, the channel number the message was received on
// (Not used for messages sent or received on "connections")
m_nChannel: s32;
// Bitmask of NetworkingSend.xxx flags.
// For received messages, only the NetworkingSend.Reliable bit is valid.
// For outbound messages, all bits are relevant
m_nFlags: s32;
// Arbitrary user data that you can use when sending messages using
// IUtils.AllocateMessage and ISockets.SendMessage.
// (The callback you set in m_pfnFreeData might use this field.)
//
// Not used for received messages.
m_nUserData: s64;
}
//
// Flags used to set options for message sending
//
NetworkingSend :: enum s32
{
// Send the message unreliably. Can be lost. Messages *can* be larger than a
// single MTU (UDP packet), but there is no retransmission, so if any piece
// of the message is lost, the entire message will be dropped.
//
// The sending API does have some knowledge of the underlying connection, so
// if there is no NAT-traversal accomplished or there is a recognized adjustment
// happening on the connection, the packet will be batched until the connection
// is open again.
//
// Migration note: This is not exactly the same as k_EP2PSendUnreliable! You
// probably want UnreliableNoNagle
Unreliable :: 0;
// Disable Nagle's algorithm.
// By default, Nagle's algorithm is applied to all outbound messages. This means
// that the message will NOT be sent immediately, in case further messages are
// sent soon after you send this, which can be grouped together. Any time there
// is enough buffered data to fill a packet, the packets will be pushed out immediately,
// but partially-full packets not be sent until the Nagle timer expires. See
// ISockets.FlushMessagesOnConnection
//
// NOTE: Don't just send every message without Nagle because you want packets to get there
// quicker. Make sure you understand the problem that Nagle is solving before disabling it.
// If you are sending small messages, often many at the same time, then it is very likely that
// it will be more efficient to leave Nagle enabled. A typical proper use of this flag is
// when you are sending what you know will be the last message sent for a while (e.g. the last
// in the server simulation tick to a particular client), and you use this flag to flush all
// messages.
NoNagle :: 1;
// Send a message unreliably, bypassing Nagle's algorithm for this message and any messages
// currently pending on the Nagle timer. This is equivalent to using Unreliable
// and then immediately flushing the messages using ISockets.FlushMessagesOnConnection.
// (But using this flag is more efficient since you only make one API call.)
UnreliableNoNagle :: Unreliable | NoNagle;
// If the message cannot be sent very soon (because the connection is still doing some initial
// handshaking, route negotiations, etc), then just drop it. This is only applicable for unreliable
// messages. Using this flag on reliable messages is invalid.
NoDelay :: 4;
// Send an unreliable message, but if it cannot be sent relatively quickly, just drop it instead of queuing it.
// This is useful for messages that are not useful if they are excessively delayed, such as voice data.
// NOTE: The Nagle algorithm is not used, and if the message is not dropped, any messages waiting on the
// Nagle timer are immediately flushed.
//
// A message will be dropped under the following circumstances:
// - the connection is not fully connected. (E.g. the "Connecting" or "FindingRoute" states)
// - there is a sufficiently large number of messages queued up already such that the current message
// will not be placed on the wire in the next ~200ms or so.
//
// If a message is dropped for these reasons, Result.Ignored will be returned.
UnreliableNoDelay :: Unreliable | NoDelay | NoNagle;
// Reliable message send. Can send up to NetworkingMessage.MaxNetworkingMessageSendSize bytes in a single message.
// Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for
// efficient sends of large chunks of data.
//
// The Nagle algorithm is used. See notes on NetworkingSend.Unreliable for more details.
// See ReliableNoNagle, ISockets.FlushMessagesOnConnection
//
// Migration note: This is NOT the same as k_EP2PSendReliable, it's more like k_EP2PSendReliableWithBuffering
Reliable :: 8;
// Send a message reliably, but bypass Nagle's algorithm.
//
// Migration note: This is equivalent to k_EP2PSendReliabl
ReliableNoNagle :: Reliable | NoNagle;
// By default, message sending is queued, and the work of encryption and talking to
// the operating system sockets, etc is done on a service thread. This is usually a
// a performance win when messages are sent from the "main thread". However, if this
// flag is set, and data is ready to be sent immediately (either from this message
// or earlier queued data), then that work will be done in the current thread, before
// the current call returns. If data is not ready to be sent (due to rate limiting
// or Nagle), then this flag has no effect.
//
// This is an advanced flag used to control performance at a very low level. For
// most applications running on modern hardware with more than one CPU core, doing
// the work of sending on a service thread will yield the best performance. Only
// use this flag if you have a really good reason and understand what you are doing.
// Otherwise you will probably just make performance worse.
UseCurrentThread :: 16;
}
//
// General result codes
//
Result :: enum s32
{
OK :: 1; // success
Fail :: 2; // generic failure
NoConnection :: 3; // no/failed network connection
//NoConnectionRetry :: 4; // OBSOLETE - removed
InvalidPassword :: 5; // password/ticket is invalid
LoggedInElsewhere :: 6; // same user logged in elsewhere
InvalidProtocolVer :: 7; // protocol version is incorrect
InvalidParam :: 8; // a parameter is incorrect
FileNotFound :: 9; // file was not found
Busy :: 10; // called method busy - action not taken
InvalidState :: 11; // called object was in an invalid state
InvalidName :: 12; // name is invalid
InvalidEmail :: 13; // email is invalid
DuplicateName :: 14; // name is not unique
AccessDenied :: 15; // access is denied
Timeout :: 16; // operation timed out
Banned :: 17; // VAC2 banned
AccountNotFound :: 18; // account not found
InvalidSteamID :: 19; // steamID is invalid
ServiceUnavailable :: 20; // The requested service is currently unavailable
NotLoggedOn :: 21; // The user is not logged on
Pending :: 22; // Request is pending (may be in process, or waiting on third party)
EncryptionFailure :: 23; // Encryption or Decryption failed
InsufficientPrivilege :: 24; // Insufficient privilege
LimitExceeded :: 25; // Too much of a good thing
Revoked :: 26; // Access has been revoked (used for revoked guest passes)
Expired :: 27; // License/Guest pass the user is trying to access is expired
AlreadyRedeemed :: 28; // Guest pass has already been redeemed by account, cannot be acked again
DuplicateRequest :: 29; // The request is a duplicate and the action has already occurred in the past, ignored this time
AlreadyOwned :: 30; // All the games in this guest pass redemption request are already owned by the user
IPNotFound :: 31; // IP address not found
PersistFailed :: 32; // failed to write change to the data store
LockingFailed :: 33; // failed to acquire access lock for this operation
LogonSessionReplaced :: 34;
ConnectFailed :: 35;
HandshakeFailed :: 36;
IOFailure :: 37;
RemoteDisconnect :: 38;
ShoppingCartNotFound :: 39; // failed to find the shopping cart requested
Blocked :: 40; // a user didn't allow it
Ignored :: 41; // target is ignoring sender
NoMatch :: 42; // nothing matching the request found
AccountDisabled :: 43;
ServiceReadOnly :: 44; // this service is not accepting content changes right now
AccountNotFeatured :: 45; // account doesn't have value, so this feature isn't available
AdministratorOK :: 46; // allowed to take this action, but only because requester is admin
ContentVersion :: 47; // A Version mismatch in content transmitted within the Steam protocol.
TryAnotherCM :: 48; // The current CM can't service the user making a request, user should try another.
PasswordRequiredToKickSession :: 49;// You are already logged in elsewhere this cached credential login has failed.
AlreadyLoggedInElsewhere :: 50; // You are already logged in elsewhere, you must wait
Suspended :: 51; // Long running operation (content download) suspended/paused
Cancelled :: 52; // Operation canceled (typically by user: content download)
DataCorruption :: 53; // Operation canceled because data is ill formed or unrecoverable
DiskFull :: 54; // Operation canceled - not enough disk space.
RemoteCallFailed :: 55; // an remote call or IPC call failed
PasswordUnset :: 56; // Password could not be verified as it's unset server side
ExternalAccountUnlinked :: 57; // External account (PSN, Facebook...) is not linked to a Steam account
PSNTicketInvalid :: 58; // PSN ticket was invalid
ExternalAccountAlreadyLinked :: 59; // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first
RemoteFileConflict :: 60; // The sync cannot resume due to a conflict between the local and remote files
IllegalPassword :: 61; // The requested new password is not legal
SameAsPreviousValue :: 62; // new value is the same as the old one ( secret question and answer )
AccountLogonDenied :: 63; // account login denied due to 2nd factor authentication failure
CannotUseOldPassword :: 64; // The requested new password is not legal
InvalidLoginAuthCode :: 65; // account login denied due to auth code invalid
AccountLogonDeniedNoMail :: 66; // account login denied due to 2nd factor auth failure - and no mail has been sent
HardwareNotCapableOfIPT :: 67; //
IPTInitError :: 68; //
ParentalControlRestricted :: 69; // operation failed due to parental control restrictions for current user
FacebookQueryError :: 70; // Facebook query returned an error
ExpiredLoginAuthCode :: 71; // account login denied due to auth code expired
IPLoginRestrictionFailed :: 72;
AccountLockedDown :: 73;
AccountLogonDeniedVerifiedEmailRequired :: 74;
NoMatchingURL :: 75;
BadResponse :: 76; // parse failure, missing field, etc.
RequirePasswordReEntry :: 77; // The user cannot complete the action until they re-enter their password
ValueOutOfRange :: 78; // the value entered is outside the acceptable range
UnexpectedError :: 79; // something happened that we didn't expect to ever happen
Disabled :: 80; // The requested service has been configured to be unavailable
InvalidCEGSubmission :: 81; // The set of files submitted to the CEG server are not valid !
RestrictedDevice :: 82; // The device being used is not allowed to perform this action
RegionLocked :: 83; // The action could not be complete because it is region restricted
RateLimitExceeded :: 84; // Temporary rate limit exceeded, try again later, different from Result.LimitExceeded which may be permanent
AccountLoginDeniedNeedTwoFactor :: 85; // Need two-factor code to login
ItemDeleted :: 86; // The thing we're trying to access has been deleted
AccountLoginDeniedThrottle :: 87; // login attempt failed, try to throttle response to possible attacker
TwoFactorCodeMismatch :: 88; // two factor code mismatch
TwoFactorActivationCodeMismatch :: 89; // activation code for two-factor didn't match
AccountAssociatedToMultiplePartners :: 90; // account has been associated with multiple partners
NotModified :: 91; // data not modified
NoMobileDevice :: 92; // the account does not have a mobile device associated with it
TimeNotSynced :: 93; // the time presented is out of range or tolerance
SmsCodeFailed :: 94; // SMS code failure (no match, none pending, etc.)
AccountLimitExceeded :: 95; // Too many accounts access this resource
AccountActivityLimitExceeded :: 96; // Too many changes to this account
PhoneActivityLimitExceeded :: 97; // Too many changes to this phone
RefundToWallet :: 98; // Cannot refund to payment method, must use wallet
EmailSendFailure :: 99; // Cannot send an email
NotSettled :: 100; // Can't perform operation till payment has settled
NeedCaptcha :: 101; // Needs to provide a valid captcha
GSLTDenied :: 102; // a game server login token owned by this token's owner has been banned
GSOwnerDenied :: 103; // game server owner is denied for other reason (account lock, community ban, vac ban, missing phone)
InvalidItemType :: 104; // the type of thing we were requested to act on is invalid
IPBanned :: 105; // the ip address has been banned from taking this action
GSLTExpired :: 106; // this token has expired from disuse, can be reset for use
InsufficientFunds :: 107; // user doesn't have enough wallet funds to complete the action
TooManyPending :: 108; // There are too many of this thing pending already
NoSiteLicensesFound :: 109; // No site licenses found
WGNetworkSendExceeded :: 110; // the WG couldn't send a response because we exceeded max network send size
}
// Handle used to identify a connection to a remote host.
NetConnection :: enum u32
{
Invalid :: 0; // value of an invalid NetConnection
};
// Handle used to identify a "listen socket". Unlike traditional
// Berkeley sockets, a listen socket and a connection are two
// different abstractions.
ListenSocket :: enum u32
{
Invalid :: 0; // value of an invalid ListenSocket
}
// Handle used to identify a poll group, used to query many
// connections at once efficiently.
PollGroup :: enum u32
{
Invalid :: 0; // value of an invalid PollGroup
}
// Used to return English-language diagnostic error messages to caller.
// (For debugging or spewing to a console, etc. Not intended for UI.)
NetworkingErrMsg :: *s8;
// Max length of diagnostic error message
MaxNetworkingErrMsgSize :: 1024;
// Identifier used for a network location point of presence. (E.g. a Valve data center.)
// Typically you won't need to directly manipulate these.
SteamNetworkingPOPID :: u32;
// A local timestamp. You can subtract two timestamps to get the number of elapsed
// microseconds. This is guaranteed to increase over time during the lifetime
// of a process, but not globally across runs. You don't need to worry about
// the value wrapping around. Note that the underlying clock might not actually have
// microsecond resolution.
Microseconds :: s64;
// Describe the status of a particular network resource
NetworkAvailability :: enum s32
{
// Negative values indicate a problem.
//
// In general, we will not automatically retry unless you take some action that
// depends on of requests this resource, such as querying the status, attempting
// to initiate a connection, receive a connection, etc. If you do not take any
// action at all, we do not automatically retry in the background.
CannotTry :: -102; // A dependent resource is missing, so this service is unavailable. (E.g. we cannot talk to routers because the Internet is down or we don't have the network config.)
Failed :: -101; // We have tried for enough time that we would expect to have been successful by now. We have never been successful
Previously :: -100; // We tried and were successful at one time, but now it looks like we have a problem
Retrying :: -10; // We previously failed and are currently retrying
// Not a problem, but not ready either
NeverTried :: 1; // We don't know because we haven't ever checked/tried
Waiting :: 2; // We're waiting on a dependent resource to be acquired. (E.g. we cannot obtain a cert until we are logged into Steam. We cannot measure latency to relays until we have the network config.)
Attempting :: 3; // We're actively trying now, but are not yet successful.
Current :: 100; // Resource is online/available
Unknown :: 0; // Internal dummy/sentinel, or value is not applicable in this context
}
//
// Store an IP and port. IPv6 is always used; IPv4 is represented using
// "IPv4-mapped" addresses: IPv4 aa.bb.cc.dd => IPv6 ::ffff:aabb:ccdd
// (RFC 4291 section 2.5.5.2.)
//
IPAddr :: struct
{
// Constants
// Max length of the buffer needed to hold IP formatted using ToString, including '\0'
// ([0123:4567:89ab:cdef:0123:4567:89ab:cdef]:12345)
MaxStringIPAddrSize :: 48;
// Types
IPv6 :: [16] u8;
IPv4 :: [16] u8;
//
// @TODO @COMPILER BUG, Jai compiler version 0.66
// Using IPv4 gives the struct the incorrect size.