sdl3-net-sys 0.6.0-pre-0+SDL-net-3.1.0-prerelease

Low level Rust bindings for SDL3_net
Documentation
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
//! SDL_net is a simple library to help with networking.
//!
//! In current times, it's a relatively thin layer over system-level APIs like
//! BSD Sockets or WinSock. Its primary strength is in making those interfaces
//! less complicated to use, and handling several unexpected corner cases, so
//! the app doesn't have to.
//!
//! Some design philosophies of SDL_net:
//!
//! - Nothing is blocking (but you can explicitly wait on things if you want).
//! - Addressing is abstract so you don't have to worry about specific networks
//!   and their specific protocols.
//! - Simple is better than hard, and not necessarily less powerful either.
//!
//! There are several pieces to this library, and most apps won't use them all,
//! but rather choose the portion that's relevant to their needs.
//!
//! All apps will call [`NET_Init()`] on startup and [`NET_Quit()`] on shutdown.
//!
//! The cornerstone of the library is the [`NET_Address`] object. This is what
//! manages the details of how to reach another computer on the network, and
//! what network protocol to use to get there. You'll need a [`NET_Address`] to
//! talk over the network. If you need to convert a hostname (such as
//! "google.com" or "libsdl.org") into a [`NET_Address`], you can call
//! [`NET_ResolveHostname()`], which will do the appropriate DNS queries on a
//! background thread. Once these are ready, you can use the [`NET_Address`] to
//! connect to these hosts over the Internet.
//!
//! Something that initiates a connection to a remote system is called a
//! "client," connecting to a "server." To establish a connection, use the
//! [`NET_Address`] you resolved with [`NET_CreateClient()`]. Once the connection is
//! established (a non-blocking operation), you'll have a [`NET_StreamSocket`]
//! object that can send and receive data over the connection, using
//! [`NET_WriteToStreamSocket()`] and [`NET_ReadFromStreamSocket()`].
//!
//! To instead be a server, that clients connect to, call [`NET_CreateServer()`] to
//! get a [`NET_Server`] object. All a [`NET_Server`] does is allow you to accept
//! connections from clients, turning them into [`NET_StreamSockets`], where you
//! can read and write from the opposite side of the connection from a given
//! client.
//!
//! These things are, underneath this API, TCP connections, which means you can
//! use a client or server to talk to something that _isn't_ using SDL_net at
//! all.
//!
//! Clients and servers deal with "stream sockets," a reliable stream of bytes.
//! There are tradeoffs to using these, especially in poor network conditions.
//! Another option is to use "datagram sockets," which map to UDP packet
//! transmission. With datagrams, everyone involved can send small packets of
//! data that may arrive in any order, or not at all, but transmission can
//! carry on if a packet is lost, each packet is clearly separated from every
//! other, and communication can happen in a peer-to-peer model instead of
//! client-server: while datagrams can be more complex, these _are_ useful
//! properties not avaiable to stream sockets. [`NET_CreateDatagramSocket()`] is
//! used to prepare for datagram communication, then [`NET_SendDatagram()`] and
//! [`NET_ReceiveDatagram()`] transmit packets.
//!
//! As previously mentioned, SDL_net's API is "non-blocking" (asynchronous).
//! Any network operation might take time, but SDL_net's APIs will not wait
//! until they complete. Any operation will return immediately, with options to
//! check if the operation has completed later. Generally this is what a video
//! game needs, but there are times where it makes sense to pause until an
//! operation completes; in a background thread this might make sense, as it
//! could simplify the code dramatically.
//!
//! The functions that block until an operation completes:
//!
//! - [`NET_WaitUntilConnected`]
//! - [`NET_WaitUntilInputAvailable`]
//! - [`NET_WaitUntilResolved`]
//! - [`NET_WaitUntilStreamSocketDrained`]
//!
//! All of these functions offer a timeout, which allow for a maximum wait
//! time, an immediate non-blocking query, or an infinite wait.
//!
//! Finally, SDL_net offers a way to simulate network problems, to test the
//! always-less-than-ideal conditions in the real world. One can
//! programmatically make the app behave like it's on a flakey wifi connection
//! even if it's running wired directly to a gigabit fiber line. The functions:
//!
//! - [`NET_SimulateAddressResolutionLoss`]
//! - [`NET_SimulateStreamPacketLoss`]
//! - [`NET_SimulateDatagramPacketLoss`]

use sdl3_sys::everything::*;

/// The current major version of the SDL_net headers.
///
/// If this were SDL_net version 3.2.1, this value would be 3.
///
/// ## Availability
/// This macro is available since SDL_net 3.0.0.
pub const SDL_NET_MAJOR_VERSION: ::core::primitive::i32 = 3;

/// The current minor version of the SDL_net headers.
///
/// If this were SDL_net version 3.2.1, this value would be 2.
///
/// ## Availability
/// This macro is available since SDL_net 3.0.0.
pub const SDL_NET_MINOR_VERSION: ::core::primitive::i32 = 1;

/// The current micro (or patchlevel) version of the SDL_net headers.
///
/// If this were SDL_net version 3.2.1, this value would be 1.
///
/// ## Availability
/// This macro is available since SDL_net 3.0.0.
pub const SDL_NET_MICRO_VERSION: ::core::primitive::i32 = 0;

/// This is the version number macro for the current SDL_net version.
///
/// ## Availability
/// This macro is available since SDL_net 3.0.0.
///
/// ## See also
/// - [`NET_Version`]
pub const SDL_NET_VERSION: ::core::primitive::i32 = SDL_VERSIONNUM(
    SDL_NET_MAJOR_VERSION,
    SDL_NET_MINOR_VERSION,
    SDL_NET_MICRO_VERSION,
);

/// This macro will evaluate to true if compiled with SDL_net at least X.Y.Z.
///
/// ## Availability
/// This macro is available since SDL_net 3.0.0.
#[inline(always)]
pub const fn SDL_NET_VERSION_ATLEAST(
    X: ::core::primitive::i32,
    Y: ::core::primitive::i32,
    Z: ::core::primitive::i32,
) -> ::core::primitive::bool {
    (((SDL_NET_MAJOR_VERSION >= X)
        && ((SDL_NET_MAJOR_VERSION > X) || (SDL_NET_MINOR_VERSION >= Y)))
        && (((SDL_NET_MAJOR_VERSION > X) || (SDL_NET_MINOR_VERSION > Y))
            || (SDL_NET_MICRO_VERSION >= Z)))
}

unsafe extern "C" {
    /// This function gets the version of the dynamically linked SDL_net library.
    ///
    /// ## Return value
    /// Returns SDL_net version.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub safe fn NET_Version() -> ::core::ffi::c_int;
}

/// A tri-state for asynchronous operations.
///
/// Lots of tasks in SDL_net are asynchronous, as they can't complete until
/// data passes over a network at some murky future point in time.
///
/// This includes sending data over a stream socket, resolving a hostname,
/// connecting to a remote system, and other tasks.
///
/// The library never blocks on tasks that take time to complete, with the
/// exception of functions named "Wait", which are intended to do nothing but
/// block until a task completes. Functions that are attempting to do something
/// that might block, or are querying the status of a task in-progress, will
/// return a [`NET_Status`], so an app can see if a task completed, and its final
/// outcome.
///
/// ## Availability
/// This enum is available since SDL_net 3.0.0.
///
/// ## Known values (`sdl3-sys`)
/// | Associated constant | Global constant | Description |
/// | ------------------- | --------------- | ----------- |
/// | [`FAILURE`](NET_Status::FAILURE) | [`NET_FAILURE`] | Async operation complete, result was failure. |
/// | [`WAITING`](NET_Status::WAITING) | [`NET_WAITING`] | Async operation is still in progress, check again later. |
/// | [`SUCCESS`](NET_Status::SUCCESS) | [`NET_SUCCESS`] | Async operation complete, result was success. |
#[repr(transparent)]
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NET_Status(pub ::core::ffi::c_int);

impl ::core::cmp::PartialEq<::core::ffi::c_int> for NET_Status {
    #[inline(always)]
    fn eq(&self, other: &::core::ffi::c_int) -> bool {
        &self.0 == other
    }
}

impl ::core::cmp::PartialEq<NET_Status> for ::core::ffi::c_int {
    #[inline(always)]
    fn eq(&self, other: &NET_Status) -> bool {
        self == &other.0
    }
}

impl From<NET_Status> for ::core::ffi::c_int {
    #[inline(always)]
    fn from(value: NET_Status) -> Self {
        value.0
    }
}

#[cfg(feature = "debug-impls")]
impl ::core::fmt::Debug for NET_Status {
    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
        #[allow(unreachable_patterns)]
        f.write_str(match *self {
            Self::FAILURE => "NET_FAILURE",
            Self::WAITING => "NET_WAITING",
            Self::SUCCESS => "NET_SUCCESS",

            _ => return write!(f, "NET_Status({})", self.0),
        })
    }
}

impl NET_Status {
    /// Async operation complete, result was failure.
    pub const FAILURE: Self = Self((-1_i32 as ::core::ffi::c_int));
    /// Async operation is still in progress, check again later.
    pub const WAITING: Self = Self((0 as ::core::ffi::c_int));
    /// Async operation complete, result was success.
    pub const SUCCESS: Self = Self((1 as ::core::ffi::c_int));
}

/// Async operation complete, result was failure.
pub const NET_FAILURE: NET_Status = NET_Status::FAILURE;
/// Async operation is still in progress, check again later.
pub const NET_WAITING: NET_Status = NET_Status::WAITING;
/// Async operation complete, result was success.
pub const NET_SUCCESS: NET_Status = NET_Status::SUCCESS;

impl NET_Status {
    /// Initialize a `NET_Status` from a raw value.
    #[inline(always)]
    pub const fn new(value: ::core::ffi::c_int) -> Self {
        Self(value)
    }
}

impl NET_Status {
    /// Get a copy of the inner raw value.
    #[inline(always)]
    pub const fn value(&self) -> ::core::ffi::c_int {
        self.0
    }
}

#[cfg(feature = "metadata")]
impl sdl3_sys::metadata::GroupMetadata for NET_Status {
    const GROUP_METADATA: &'static sdl3_sys::metadata::Group =
        &crate::metadata::net::METADATA_NET_Status;
}

unsafe extern "C" {
    /// Initialize the SDL_net library.
    ///
    /// This must be successfully called once before (almost) any other SDL_net
    /// function can be used.
    ///
    /// It is safe to call this multiple times; the library will only initialize
    /// once, and won't deinitialize until [`NET_Quit()`] has been called a matching
    /// number of times. Extra attempts to init report success.
    ///
    /// ## Return value
    /// Returns true on success, false on error; call [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_Quit`]
    pub fn NET_Init() -> ::core::primitive::bool;
}

unsafe extern "C" {
    /// Deinitialize the SDL_net library.
    ///
    /// This must be called when done with the library, probably at the end of your
    /// program.
    ///
    /// It is safe to call this multiple times; the library will only deinitialize
    /// once, when this function is called the same number of times as [`NET_Init`] was
    /// successfully called.
    ///
    /// Once you have successfully deinitialized the library, it is safe to call
    /// [`NET_Init`] to reinitialize it for further use.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_Init`]
    pub fn NET_Quit();
}

unsafe extern "C" {
    /// Resolve a human-readable hostname.
    ///
    /// SDL_net doesn't operate on human-readable hostnames (like `www.libsdl.org`
    /// but on computer-readable addresses. This function converts from one to the
    /// other. This process is known as "resolving" an address.
    ///
    /// You can also use this to turn IP address strings (like "159.203.69.7") into
    /// [`NET_Address`] objects.
    ///
    /// Note that resolving an address is an asynchronous operation, since the
    /// library will need to ask a server on the internet to get the information it
    /// needs, and this can take time (and possibly fail later). This function will
    /// not block. It either returns NULL (catastrophic failure) or an unresolved
    /// [`NET_Address`]. Until the address resolves, it can't be used.
    ///
    /// If you want to block until the resolution is finished, you can call
    /// [`NET_WaitUntilResolved()`]. Otherwise, you can do a non-blocking check with
    /// [`NET_GetAddressStatus()`].
    ///
    /// When you are done with the returned [`NET_Address`], call [`NET_UnrefAddress()`] to
    /// dispose of it. You need to do this even if resolution later fails
    /// asynchronously.
    ///
    /// ## Parameters
    /// - `host`: The hostname to resolve.
    ///
    /// ## Return value
    /// Returns A new [`NET_Address`] on success, NULL on error; call [`SDL_GetError()`]
    ///   for details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WaitUntilResolved`]
    /// - [`NET_GetAddressStatus`]
    /// - [`NET_RefAddress`]
    /// - [`NET_UnrefAddress`]
    pub fn NET_ResolveHostname(host: *const ::core::ffi::c_char) -> *mut NET_Address;
}

unsafe extern "C" {
    /// Block until an address is resolved.
    ///
    /// The [`NET_Address`] objects returned by [`NET_ResolveHostname`] take time to do
    /// their work, so it does so _asynchronously_ instead of making your program
    /// wait an indefinite amount of time.
    ///
    /// However, if you want your program to sleep until the address resolution is
    /// complete, you can call this function.
    ///
    /// This function takes a timeout value, represented in milliseconds, of how
    /// long to wait for resolution to complete. Specifying a timeout of -1
    /// instructs the library to wait indefinitely, and a timeout of 0 just checks
    /// the current status and returns immediately (and is functionally equivalent
    /// to calling [`NET_GetAddressStatus`]).
    ///
    /// Resolution can fail after some time (DNS server took awhile to reply that
    /// the hostname isn't recognized, etc), so be sure to check the result of this
    /// function instead of assuming it worked!
    ///
    /// Once an address is successfully resolved, it can be used to connect to the
    /// host represented by the address.
    ///
    /// If you don't want your program to block, you can call [`NET_GetAddressStatus`]
    /// from time to time until you get a non-zero result.
    ///
    /// ## Parameters
    /// - `address`: The [`NET_Address`] object to wait on.
    /// - `timeout`: Number of milliseconds to wait for resolution to complete.
    ///   -1 to wait indefinitely, 0 to check once without waiting.
    ///
    /// ## Return value
    /// Returns [`NET_SUCCESS`] if successfully resolved, [`NET_FAILURE`] if resolution
    ///   failed, [`NET_WAITING`] if still resolving (this function timed out
    ///   without resolution); if [`NET_FAILURE`], call [`SDL_GetError()`] for
    ///   details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread, and several
    ///   threads can block on the same address simultaneously.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_GetAddressStatus`]
    pub fn NET_WaitUntilResolved(address: *mut NET_Address, timeout: Sint32) -> NET_Status;
}

unsafe extern "C" {
    /// Check if an address is resolved, without blocking.
    ///
    /// The [`NET_Address`] objects returned by [`NET_ResolveHostname`] take time to do
    /// their work, so it does so _asynchronously_ instead of making your program
    /// wait an indefinite amount of time.
    ///
    /// This function allows you to check the progress of that work without
    /// blocking.
    ///
    /// Resolution can fail after some time (DNS server took awhile to reply that
    /// the hostname isn't recognized, etc), so be sure to check the result of this
    /// function instead of assuming it worked because it's non-zero!
    ///
    /// Once an address is successfully resolved, it can be used to connect to the
    /// host represented by the address.
    ///
    /// ## Parameters
    /// - `address`: The [`NET_Address`] to query.
    ///
    /// ## Return value
    /// Returns [`NET_SUCCESS`] if successfully resolved, [`NET_FAILURE`] if resolution
    ///   failed, [`NET_WAITING`] if still resolving (this function timed out
    ///   without resolution); if [`NET_FAILURE`], call [`SDL_GetError()`] for
    ///   details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WaitUntilResolved`]
    pub fn NET_GetAddressStatus(address: *mut NET_Address) -> NET_Status;
}

unsafe extern "C" {
    /// Get a human-readable string from a resolved address.
    ///
    /// This returns a string that's "human-readable", in that it's probably a
    /// string of numbers and symbols, like "159.203.69.7" or
    /// "2604:a880:800:a1::71f:3001". It won't be the original hostname (like
    /// "icculus.org"), but it's suitable for writing to a log file, etc.
    ///
    /// Do not free or modify the returned string; it belongs to the [`NET_Address`]
    /// that was queried, and is valid as long as the object lives. Either make
    /// sure the address has a reference as long as you need this or make a copy of
    /// the string.
    ///
    /// This will return NULL if resolution is still in progress, or if resolution
    /// failed. You can use [`NET_GetAddressStatus()`] or [`NET_WaitUntilResolved()`] to
    /// make sure resolution has successfully completed before calling this.
    ///
    /// ## Parameters
    /// - `address`: The [`NET_Address`] to query.
    ///
    /// ## Return value
    /// Returns a string, or NULL on error; call [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_GetAddressStatus`]
    /// - [`NET_WaitUntilResolved`]
    pub fn NET_GetAddressString(address: *mut NET_Address) -> *const ::core::ffi::c_char;
}

unsafe extern "C" {
    /// Add a reference to an [`NET_Address`].
    ///
    /// Since several pieces of the library might share a single [`NET_Address`],
    /// including a background thread that's working on resolving, these objects
    /// are referenced counted. This allows everything that's using it to declare
    /// they still want it, and drop their reference to the address when they are
    /// done with it. The object's resources are freed when the last reference is
    /// dropped.
    ///
    /// This function adds a reference to an [`NET_Address`], increasing its reference
    /// count by one.
    ///
    /// The documentation will tell you when the app has to explicitly unref an
    /// address. For example, [`NET_ResolveHostname()`] creates addresses that are
    /// already referenced, so the caller needs to unref it when done.
    ///
    /// Generally you only have to explicit ref an address when you have different
    /// parts of your own app that will be sharing an address. In normal usage, you
    /// only have to unref things you've created once (like you might free()
    /// something), but you are free to add extra refs if it makes sense.
    ///
    /// This returns the same address passed as a parameter, which makes it easy to
    /// ref and assign in one step:
    ///
    /// ```c
    /// myAddr = NET_RefAddress(yourAddr);
    /// ```
    ///
    /// ## Parameters
    /// - `address`: The [`NET_Address`] to add a reference to.
    ///
    /// ## Return value
    /// Returns the same address that was passed as a parameter.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_RefAddress(address: *mut NET_Address) -> *mut NET_Address;
}

unsafe extern "C" {
    /// Drop a reference to an [`NET_Address`].
    ///
    /// Since several pieces of the library might share a single [`NET_Address`],
    /// including a background thread that's working on resolving, these objects
    /// are referenced counted. This allows everything that's using it to declare
    /// they still want it, and drop their reference to the address when they are
    /// done with it. The object's resources are freed when the last reference is
    /// dropped.
    ///
    /// This function drops a reference to an [`NET_Address`], decreasing its reference
    /// count by one.
    ///
    /// The documentation will tell you when the app has to explicitly unref an
    /// address. For example, [`NET_ResolveHostname()`] creates addresses that are
    /// already referenced, so the caller needs to unref it when done.
    ///
    /// ## Parameters
    /// - `address`: The [`NET_Address`] to drop a reference to.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_UnrefAddress(address: *mut NET_Address);
}

unsafe extern "C" {
    /// Enable simulated address resolution failures.
    ///
    /// Often times, testing a networked app on your development machine--which
    /// might have a wired connection to a fast, reliable network service--won't
    /// expose bugs that happen when networks intermittently fail in the real
    /// world, when the wifi is flakey and firewalls get in the way.
    ///
    /// This function allows you to tell the library to pretend that some
    /// percentage of address resolutions will fail.
    ///
    /// The higher the percentage, the more resolutions will fail and/or take
    /// longer for resolution to complete.
    ///
    /// Setting this to zero (the default) will disable the simulation. Setting to
    /// 100 means _everything_ fails unconditionally. At what percent the system
    /// merely borders on unusable is left as an exercise to the app developer.
    ///
    /// This is intended for debugging purposes, to simulate real-world conditions
    /// that are various degrees of terrible. You probably should _not_ call this
    /// in production code, where you'll likely see real failures anyhow.
    ///
    /// ## Parameters
    /// - `percent_loss`: A number between 0 and 100. Higher means more failures.
    ///   Zero to disable.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_SimulateAddressResolutionLoss(percent_loss: ::core::ffi::c_int);
}

unsafe extern "C" {
    /// Compare two [`NET_Address`] objects.
    ///
    /// This compares two addresses, returning a value that is useful for qsort (or
    /// [`SDL_qsort`]).
    ///
    /// ## Parameters
    /// - `a`: first address to compare.
    /// - `b`: second address to compare.
    ///
    /// ## Return value
    /// Returns a value less than zero if `a` is "less than" `b`, a value greater
    ///   than zero if "greater than", zero if equal.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_CompareAddresses(a: *const NET_Address, b: *const NET_Address)
    -> ::core::ffi::c_int;
}

unsafe extern "C" {
    /// Obtain a list of local addresses on the system.
    ///
    /// This returns addresses that you can theoretically bind a socket to, to
    /// accept connections from other machines at that address.
    ///
    /// You almost never need this function; first, it's hard to tell _what_ is a
    /// good address to bind to, without asking the user (who will likely find it
    /// equally hard to decide). Second, most machines will have lots of _private_
    /// addresses that are accessible on the same LAN, but not public ones that are
    /// accessible from the outside Internet.
    ///
    /// Usually it's better to use [`NET_CreateServer()`] or [`NET_CreateDatagramSocket()`]
    /// with a NULL address, to say "bind to all interfaces."
    ///
    /// The array of addresses returned from this is guaranteed to be
    /// NULL-terminated. You can also pass a pointer to an int, which will return
    /// the final count, not counting the NULL at the end of the array.
    ///
    /// Pass the returned array to [`NET_FreeLocalAddresses`] when you are done with
    /// it. It is safe to keep any addresses you want from this array even after
    /// calling that function, as long as you called [`NET_RefAddress()`] on them.
    ///
    /// ## Parameters
    /// - `num_addresses`: on exit, will be set to the number of addresses
    ///   returned. Can be NULL.
    ///
    /// ## Return value
    /// Returns A NULL-terminated array of [`NET_Address`] pointers, one for each
    ///   bindable address on the system, or NULL on error; call
    ///   [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_GetLocalAddresses(num_addresses: *mut ::core::ffi::c_int) -> *mut *mut NET_Address;
}

unsafe extern "C" {
    /// Free the results from [`NET_GetLocalAddresses`].
    ///
    /// This will unref all addresses in the array and free the array itself.
    ///
    /// Since addresses are reference counted, it is safe to keep any addresses you
    /// want from this array even after calling this function, as long as you
    /// called [`NET_RefAddress()`] on them first.
    ///
    /// It is safe to pass a NULL in here, it will be ignored.
    ///
    /// ## Parameters
    /// - `addresses`: A pointer returned by [`NET_GetLocalAddresses()`].
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_FreeLocalAddresses(addresses: *mut *mut NET_Address);
}

unsafe extern "C" {
    /// Begin connecting a socket as a client to a remote server.
    ///
    /// Each [`NET_StreamSocket`] represents a single connection between systems.
    /// Usually, a client app will have one connection to a server app on a
    /// different computer, and the server app might have many connections from
    /// different clients. Each of these connections communicate over a separate
    /// stream socket.
    ///
    /// Connecting is an asynchronous operation; this function does not block, and
    /// will return before the connection is complete. One has to then use
    /// [`NET_WaitUntilConnected()`] or [`NET_GetConnectionStatus()`] to see when the
    /// operation has completed, and if it was successful.
    ///
    /// Once connected, you can read and write data to the returned socket. Stream
    /// sockets are a mode of _reliable_ transmission, which means data will be
    /// received as a stream of bytes in the order you sent it. If there are
    /// problems in transmission, the system will deal with protocol negotiation
    /// and retransmission as necessary, transparent to your app, but this means
    /// until data is available in the order sent, the remote side will not get any
    /// new data. This is the tradeoff vs datagram sockets, where data can arrive
    /// in any order, or not arrive at all, without waiting, but the sender will
    /// not know.
    ///
    /// Stream sockets don't employ any protocol (above the TCP level), so they can
    /// connect to servers that aren't using SDL_net, but if you want to speak any
    /// protocol beyond an abritrary stream of bytes, such as HTTP, you'll have to
    /// implement that yourself on top of the stream socket.
    ///
    /// This function will fail if `address` is not finished resolving.
    ///
    /// When you are done with this connection (whether it failed to connect or
    /// not), you must dispose of it with [`NET_DestroyStreamSocket()`].
    ///
    /// Unlike BSD sockets or WinSock, you specify the port as a normal integer;
    /// you do not have to byteswap it into "network order," as the library will
    /// handle that for you.
    ///
    /// There are currently no extra properties for creating a client, so `props`
    /// should be zero. A future revision of SDL_net may add additional (optional)
    /// properties.
    ///
    /// ## Parameters
    /// - `address`: the address of the remote server to connect to.
    /// - `port`: the port on the remote server to connect to.
    /// - `props`: properties of the new client. Specify zero for defaults.
    ///
    /// ## Return value
    /// Returns a new [`NET_StreamSocket`], pending connection, or NULL on error; call
    ///   [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WaitUntilConnected`]
    /// - [`NET_GetConnectionStatus`]
    /// - [`NET_DestroyStreamSocket`]
    pub fn NET_CreateClient(
        address: *mut NET_Address,
        port: Uint16,
        props: SDL_PropertiesID,
    ) -> *mut NET_StreamSocket;
}

unsafe extern "C" {
    /// Block until a stream socket has connected to a server.
    ///
    /// The [`NET_StreamSocket`] objects returned by [`NET_CreateClient`] take time to do
    /// their work, so it does so _asynchronously_ instead of making your program
    /// wait an indefinite amount of time.
    ///
    /// However, if you want your program to sleep until the connection is
    /// complete, you can call this function.
    ///
    /// This function takes a timeout value, represented in milliseconds, of how
    /// long to wait for resolution to complete. Specifying a timeout of -1
    /// instructs the library to wait indefinitely, and a timeout of 0 just checks
    /// the current status and returns immediately (and is functionally equivalent
    /// to calling [`NET_GetConnectionStatus`]).
    ///
    /// Connections can fail after some time (server took awhile to respond at all,
    /// and then refused the connection outright), so be sure to check the result
    /// of this function instead of assuming it worked!
    ///
    /// Once a connection is successfully made, the socket may read data from, or
    /// write data to, the connected server.
    ///
    /// If you don't want your program to block, you can call
    /// [`NET_GetConnectionStatus()`] from time to time until you get a non-zero
    /// result.
    ///
    /// ## Parameters
    /// - `sock`: The [`NET_StreamSocket`] object to wait on.
    /// - `timeout`: Number of milliseconds to wait for resolution to complete.
    ///   -1 to wait indefinitely, 0 to check once without waiting.
    ///
    /// ## Return value
    /// Returns [`NET_SUCCESS`] if successfully connected, [`NET_FAILURE`] if connection
    ///   failed, [`NET_WAITING`] if still connecting (this function timed out
    ///   without resolution); if [`NET_FAILURE`], call [`SDL_GetError()`] for
    ///   details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   socket at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_GetConnectionStatus`]
    pub fn NET_WaitUntilConnected(sock: *mut NET_StreamSocket, timeout: Sint32) -> NET_Status;
}

unsafe extern "C" {
    /// Create a server, which listens for connections to accept.
    ///
    /// An app that initiates connection to a remote computer is called a "client,"
    /// and the thing the client connects to is called a "server."
    ///
    /// Servers listen for and accept connections from clients, which spawns a new
    /// stream socket on the server's end, which it can then send/receive data on.
    ///
    /// Use this function to create a server that will accept connections from
    /// other systems.
    ///
    /// This function does not block, and is not asynchronous, as the system can
    /// decide immediately if it can create a server or not. If this returns
    /// success, you can immediately start accepting connections.
    ///
    /// You can specify an address to listen for connections on; this address must
    /// be local to the system, and probably one returned by
    /// [`NET_GetLocalAddresses()`], but almost always you just want to specify NULL
    /// here, to listen on any address available to the app.
    ///
    /// After creating a server, you get stream sockets to talk to incoming client
    /// connections by calling [`NET_AcceptClient()`].
    ///
    /// Stream sockets don't employ any protocol (above the TCP level), so they can
    /// accept connections from clients that aren't using SDL_net, but if you want
    /// to speak any protocol beyond an abritrary stream of bytes, such as HTTP,
    /// you'll have to implement that yourself on top of the stream socket.
    ///
    /// Unlike BSD sockets or WinSock, you specify the port as a normal integer;
    /// you do not have to byteswap it into "network order," as the library will
    /// handle that for you.
    ///
    /// The caller may supply properties to customize behavior. This is optional,
    /// and a value of zero for `props` will request defaults for all properties.
    ///
    /// These are the supported properties:
    ///
    /// - [`NET_PROP_SERVER_REUSEADDR_BOOLEAN`]\: true if the server should be created
    ///   even if a previous server has recently used this address. For various
    ///   reasons, networks prefer that there be some delay between apps reusing
    ///   the same address, but this can be problematic when iterating quickly, for
    ///   software development purposes or just restarting a crashed service. This
    ///   property defaults to true (although it should be noted that, at the
    ///   operating system level, this defaults to false!). If this property is
    ///   false and the OS feels that not enough time has elapsed, server creation
    ///   will fail and this function will report an error.
    ///
    /// ## Parameters
    /// - `addr`: the _local_ address to listen for connections on, or NULL.
    /// - `port`: the port on the local address to listen for connections on.
    /// - `props`: properties of the new server. Specify zero for defaults.
    ///
    /// ## Return value
    /// Returns a new [`NET_Server`], or NULL on error; call [`SDL_GetError()`] for
    ///   details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_GetLocalAddresses`]
    /// - [`NET_AcceptClient`]
    /// - [`NET_DestroyServer`]
    pub fn NET_CreateServer(
        addr: *mut NET_Address,
        port: Uint16,
        props: SDL_PropertiesID,
    ) -> *mut NET_Server;
}

pub const NET_PROP_SERVER_REUSEADDR_BOOLEAN: *const ::core::ffi::c_char =
    c"NET.server.reuseaddr".as_ptr();

unsafe extern "C" {
    /// Create a stream socket for the next pending client connection.
    ///
    /// When a client connects to a server, their connection will be pending until
    /// the server _accepts_ the connection. Once accepted, the server will be
    /// given a stream socket to communicate with the client, and they can send
    /// data to, and receive data from, each other.
    ///
    /// Unlike [`NET_CreateClient`], stream sockets returned from this function are
    /// already connected and do not have to wait for the connection to complete,
    /// as server acceptance is the final step of connecting.
    ///
    /// This function does not block. If there are no new connections pending, this
    /// function will return true (for success, but `*client_stream` will be set to
    /// NULL. This is not an error and a common condition the app should expect. In
    /// fact, this function should be called in a loop until this condition occurs,
    /// so all pending connections are accepted in a single batch.
    ///
    /// If you want the server to sleep until there's a new connection, you can use
    /// [`NET_WaitUntilInputAvailable()`].
    ///
    /// When done with the newly-accepted client, you can disconnect and dispose of
    /// the stream socket by calling [`NET_DestroyStreamSocket()`].
    ///
    /// ## Parameters
    /// - `server`: the server object to check for pending connections.
    /// - `client_stream`: Will be set to a new stream socket if a connection was
    ///   pending, NULL otherwise.
    ///
    /// ## Return value
    /// Returns true on success (even if no new connections were pending), false
    ///   on error; call [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same server from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   servers at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WaitUntilInputAvailable`]
    /// - [`NET_DestroyStreamSocket`]
    pub fn NET_AcceptClient(
        server: *mut NET_Server,
        client_stream: *mut *mut NET_StreamSocket,
    ) -> ::core::primitive::bool;
}

unsafe extern "C" {
    /// Dispose of a previously-created server.
    ///
    /// This will immediately disconnect any pending client connections that had
    /// not yet been accepted, but will not disconnect any existing accepted
    /// connections (which can still be used and must be destroyed separately).
    /// Further attempts to make new connections to this server will fail on the
    /// client side.
    ///
    /// ## Parameters
    /// - `server`: server to destroy.
    ///
    /// ## Thread safety
    /// You should not operate on the same server from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   servers at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_CreateServer`]
    pub fn NET_DestroyServer(server: *mut NET_Server);
}

unsafe extern "C" {
    /// Get the remote address of a stream socket.
    ///
    /// This reports the address of the remote side of a stream socket, which might
    /// still be pending connnection.
    ///
    /// This adds a reference to the address; the caller _must_ call
    /// [`NET_UnrefAddress()`] when done with it.
    ///
    /// ## Parameters
    /// - `sock`: the stream socket to query.
    ///
    /// ## Return value
    /// Returns the socket's remote address, or NULL on error; call [`SDL_GetError()`]
    ///   for details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_GetStreamSocketAddress(sock: *mut NET_StreamSocket) -> *mut NET_Address;
}

unsafe extern "C" {
    /// Check if a stream socket is connected, without blocking.
    ///
    /// The [`NET_StreamSocket`] objects returned by [`NET_CreateClient`] take time to do
    /// negotiate a connection to a server, so it does so _asynchronously_ instead
    /// of making your program wait an indefinite amount of time.
    ///
    /// This function allows you to check the progress of that work without
    /// blocking.
    ///
    /// Connection can fail after some time (server took a while to respond, and
    /// then rejected the connection), so be sure to check the result of this
    /// function instead of assuming it worked because it's non-zero!
    ///
    /// Once a connection is successfully made, the stream socket can be used to
    /// send and receive data with the server.
    ///
    /// Note that if the connection succeeds, but later the connection is dropped,
    /// this will still report the connection as successful, as it only deals with
    /// the initial asynchronous work of getting connected; you'll know the
    /// connection dropped later when your reads and writes report failures.
    ///
    /// ## Parameters
    /// - `sock`: the stream socket to query.
    ///
    /// ## Return value
    /// Returns [`NET_SUCCESS`] if successfully connected, [`NET_FAILURE`] if connection
    ///   failed, [`NET_WAITING`] if still connecting; if [`NET_FAILURE`], call
    ///   [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WaitUntilConnected`]
    pub fn NET_GetConnectionStatus(sock: *mut NET_StreamSocket) -> NET_Status;
}

unsafe extern "C" {
    /// Send bytes over a stream socket to a remote system.
    ///
    /// Stream sockets are _reliable_, which means data sent over them will arrive
    /// in the order it was transmitted, and the system will retransmit data as
    /// necessary to ensure its delivery. Which is to say, short of catastrophic
    /// failure, data will arrive, possibly with severe delays. Also, "catastrophic
    /// failure" isn't an uncommon event.
    ///
    /// (This is opposed to Datagram sockets, which send chunks of data that might
    /// arrive in any order, or not arrive at all, but you never wait for missing
    /// chunks to show up.)
    ///
    /// Stream sockets are _bidirectional_; you can read and write from the same
    /// stream, and the other end of the connection can, too.
    ///
    /// This call never blocks; if it can't send the data immediately, the library
    /// will queue it for later transmission. You can use
    /// [`NET_GetStreamSocketPendingWrites()`] to see how much is still queued for
    /// later transmission, or [`NET_WaitUntilStreamSocketDrained()`] to block until
    /// all pending data has been sent.
    ///
    /// If the connection has failed (remote side dropped us, or one of a million
    /// other networking failures occurred), this function will report failure by
    /// returning false. Stream sockets only report failure for unrecoverable
    /// conditions; once a stream socket fails, you should assume it is no longer
    /// usable and should destroy it with [`NET_DestroyStreamSocket()`].
    ///
    /// ## Parameters
    /// - `sock`: the stream socket to send data through.
    /// - `buf`: a pointer to the data to send.
    /// - `buflen`: the size of the data to send, in bytes.
    ///
    /// ## Return value
    /// Returns true if data sent or queued for transmission, false on failure;
    ///   call [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_GetStreamSocketPendingWrites`]
    /// - [`NET_WaitUntilStreamSocketDrained`]
    /// - [`NET_ReadFromStreamSocket`]
    pub fn NET_WriteToStreamSocket(
        sock: *mut NET_StreamSocket,
        buf: *const ::core::ffi::c_void,
        buflen: ::core::ffi::c_int,
    ) -> ::core::primitive::bool;
}

unsafe extern "C" {
    /// Query bytes still pending transmission on a stream socket.
    ///
    /// If [`NET_WriteToStreamSocket()`] couldn't send all its data immediately, it
    /// will queue it to be sent later. This function lets the app see how much of
    /// that queue is still pending to be sent.
    ///
    /// The library will try to send more queued data before reporting what's left,
    /// but it will not block to do so.
    ///
    /// If the connection has failed (remote side dropped us, or one of a million
    /// other networking failures occurred), this function will report failure by
    /// returning -1. Stream sockets only report failure for unrecoverable
    /// conditions; once a stream socket fails, you should assume it is no longer
    /// usable and should destroy it with [`NET_DestroyStreamSocket()`].
    ///
    /// ## Parameters
    /// - `sock`: the stream socket to query.
    ///
    /// ## Return value
    /// Returns number of bytes still pending transmission, -1 on failure; call
    ///   [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WriteToStreamSocket`]
    /// - [`NET_WaitUntilStreamSocketDrained`]
    pub fn NET_GetStreamSocketPendingWrites(sock: *mut NET_StreamSocket) -> ::core::ffi::c_int;
}

unsafe extern "C" {
    /// Block until all of a stream socket's pending data is sent.
    ///
    /// If [`NET_WriteToStreamSocket()`] couldn't send all its data immediately, it
    /// will queue it to be sent later. This function lets the app sleep until all
    /// the data is transmitted.
    ///
    /// This function takes a timeout value, represented in milliseconds, of how
    /// long to wait for transmission to complete. Specifying a timeout of -1
    /// instructs the library to wait indefinitely, and a timeout of 0 just checks
    /// the current status and returns immediately (and is functionally equivalent
    /// to calling [`NET_GetStreamSocketPendingWrites`]).
    ///
    /// If you don't want your program to block, you can call
    /// [`NET_GetStreamSocketPendingWrites`] from time to time until you get a result
    /// <= 0.
    ///
    /// If the connection has failed (remote side dropped us, or one of a million
    /// other networking failures occurred), this function will report failure by
    /// returning -1. Stream sockets only report failure for unrecoverable
    /// conditions; once a stream socket fails, you should assume it is no longer
    /// usable and should destroy it with [`NET_DestroyStreamSocket()`].
    ///
    /// ## Parameters
    /// - `sock`: the stream socket to wait on.
    /// - `timeout`: Number of milliseconds to wait for draining to complete. -1
    ///   to wait indefinitely, 0 to check once without waiting.
    ///
    /// ## Return value
    /// Returns number of bytes still pending transmission, -1 on failure; call
    ///   [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WriteToStreamSocket`]
    /// - [`NET_GetStreamSocketPendingWrites`]
    pub fn NET_WaitUntilStreamSocketDrained(
        sock: *mut NET_StreamSocket,
        timeout: Sint32,
    ) -> ::core::ffi::c_int;
}

unsafe extern "C" {
    /// Receive bytes that a remote system sent to a stream socket.
    ///
    /// Stream sockets are _reliable_, which means data sent over them will arrive
    /// in the order it was transmitted, and the system will retransmit data as
    /// necessary to ensure its delivery. Which is to say, short of catastrophic
    /// failure, data will arrive, possibly with severe delays. Also, "catastrophic
    /// failure" isn't an uncommon event.
    ///
    /// (This is opposed to Datagram sockets, which send chunks of data that might
    /// arrive in any order, or not arrive at all, but you never wait for missing
    /// chunks to show up.)
    ///
    /// Stream sockets are _bidirectional_; you can read and write from the same
    /// stream, and the other end of the connection can, too.
    ///
    /// This function returns data that has arrived for the stream socket that
    /// hasn't been read yet. Data is provided in the order it was sent on the
    /// remote side. This function may return less data than requested, depending
    /// on what is available at the time, and also the app isn't required to read
    /// all available data at once.
    ///
    /// This call never blocks; if no new data isn't available at the time of the
    /// call, it returns 0 immediately. The caller can try again later.
    ///
    /// If the connection has failed (remote side dropped us, or one of a million
    /// other networking failures occurred), this function will report failure by
    /// returning -1. Stream sockets only report failure for unrecoverable
    /// conditions; once a stream socket fails, you should assume it is no longer
    /// usable and should destroy it with [`NET_DestroyStreamSocket()`].
    ///
    /// ## Parameters
    /// - `sock`: the stream socket to receive data from.
    /// - `buf`: a pointer to a buffer where received data will be collected.
    /// - `buflen`: the size of the buffer pointed to by `buf`, in bytes. This is
    ///   the maximum that will be read from the stream socket.
    ///
    /// ## Return value
    /// Returns number of bytes read from the stream socket (which can be less
    ///   than `buflen` or zero if none available), -1 on failure; call
    ///   [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_WriteToStreamSocket`]
    pub fn NET_ReadFromStreamSocket(
        sock: *mut NET_StreamSocket,
        buf: *mut ::core::ffi::c_void,
        buflen: ::core::ffi::c_int,
    ) -> ::core::ffi::c_int;
}

unsafe extern "C" {
    /// Enable simulated stream socket failures.
    ///
    /// Often times, testing a networked app on your development machine--which
    /// might have a wired connection to a fast, reliable network service--won't
    /// expose bugs that happen when networks intermittently fail in the real
    /// world, when the wifi is flakey and firewalls get in the way.
    ///
    /// This function allows you to tell the library to pretend that some
    /// percentage of stream socket data transmission will fail.
    ///
    /// Since stream sockets are reliable, failure in this case pretends that
    /// packets are getting lost on the network, making the stream retransmit to
    /// deal with it. To simulate this, the library will introduce some amount of
    /// delay before it sends or receives data on the socket. The higher the
    /// percentage, the more delay is introduced for bytes to make their way to
    /// their final destination. The library may also decide to drop connections at
    /// random, to simulate disasterous network conditions.
    ///
    /// Setting this to zero (the default) will disable the simulation. Setting to
    /// 100 means _everything_ fails unconditionally and no further data will get
    /// through (and perhaps your sockets eventually fail). At what percent the
    /// system merely borders on unusable is left as an exercise to the app
    /// developer.
    ///
    /// This is intended for debugging purposes, to simulate real-world conditions
    /// that are various degrees of terrible. You probably should _not_ call this
    /// in production code, where you'll likely see real failures anyhow.
    ///
    /// ## Parameters
    /// - `sock`: The socket to set a failure rate on.
    /// - `percent_loss`: A number between 0 and 100. Higher means more failures.
    ///   Zero to disable.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_SimulateStreamPacketLoss(
        sock: *mut NET_StreamSocket,
        percent_loss: ::core::ffi::c_int,
    );
}

unsafe extern "C" {
    /// Dispose of a previously-created stream socket.
    ///
    /// This will immediately disconnect the other side of the connection, if
    /// necessary. Further attempts to read or write the socket on the remote end
    /// will fail.
    ///
    /// This will _abandon_ any data queued for sending that hasn't made it to the
    /// socket. If you need this data to arrive, you should wait for it to transmit
    /// before destroying the socket with [`NET_GetStreamSocketPendingWrites()`] or
    /// [`NET_WaitUntilStreamSocketDrained()`]. Any data that has arrived from the
    /// remote end of the connection that hasn't been read yet is lost.
    ///
    /// ## Parameters
    /// - `sock`: stream socket to destroy.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_CreateClient`]
    /// - [`NET_AcceptClient`]
    /// - [`NET_GetStreamSocketPendingWrites`]
    /// - [`NET_WaitUntilStreamSocketDrained`]
    pub fn NET_DestroyStreamSocket(sock: *mut NET_StreamSocket);
}

/// The data provided for new incoming packets from [`NET_ReceiveDatagram()`].
///
/// ## Availability
/// This datatype is available since SDL_net 3.0.0.
///
/// ## See also
/// - [`NET_ReceiveDatagram`]
/// - [`NET_DestroyDatagram`]
#[repr(C)]
#[cfg_attr(feature = "debug-impls", derive(Debug))]
pub struct NET_Datagram {
    /// Sender's address. This is unref'd by [`NET_DestroyDatagram`]. You only need to ref it if you want to keep it.
    pub addr: *mut NET_Address,
    /// Sender's port. These do not have to come from the same port the receiver is bound to. These are in host byte order, don't byteswap them!
    pub port: Uint16,
    /// the payload of this datagram.
    pub buf: *mut Uint8,
    /// the number of bytes available at `buf`.
    pub buflen: ::core::ffi::c_int,
}

impl ::core::default::Default for NET_Datagram {
    /// Initialize all fields to zero
    #[inline(always)]
    fn default() -> Self {
        unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() }
    }
}

unsafe extern "C" {
    /// Create and bind a new datagram socket.
    ///
    /// Datagram sockets follow different rules than stream sockets. They are not a
    /// reliable stream of bytes but rather packets, they are not limited to
    /// talking to a single other remote system, they do not maintain a single
    /// "connection" that can be dropped, and they are more nimble about network
    /// failures at the expense of being more complex to use. What makes sense for
    /// your app depends entirely on what your app is trying to accomplish.
    ///
    /// Generally the idea of a datagram socket is that you send data one chunk
    /// ("packet") at a time to any address you want, and it arrives whenever it
    /// gets there, even if later packets get there first, and maybe it doesn't get
    /// there at all, and you don't know when anything of this happens by default.
    ///
    /// This function creates a new datagram socket.
    ///
    /// This function does not block, and is not asynchronous, as the system can
    /// decide immediately if it can create a socket or not. If this returns
    /// success, you can immediately start talking to the network.
    ///
    /// You can specify an address to listen for connections on; this address must
    /// be local to the system, and probably one returned by
    /// [`NET_GetLocalAddresses()`], but almost always you just want to specify NULL
    /// here, to listen on any address available to the app.
    ///
    /// If you need to bind to a specific port (like a server), you should specify
    /// it in the `port` argument; datagram servers should do this, so they can be
    /// reached at a well-known port. If you only plan to initiate communications
    /// (like a client), you should specify 0 and let the system pick an unused
    /// port. Only one process can bind to a specific port at a time, so if you
    /// aren't acting as a server, you should choose 0. Datagram sockets can send
    /// individual packets to any port, so this just declares where data will
    /// arrive for your socket.
    ///
    /// Datagram sockets don't employ any protocol (above the UDP level), so they
    /// can talk to apps that aren't using SDL_net, but if you want to speak any
    /// protocol beyond arbitrary packets of bytes, such as WebRTC, you'll have to
    /// implement that yourself on top of the stream socket.
    ///
    /// Unlike BSD sockets or WinSock, you specify the port as a normal integer;
    /// you do not have to byteswap it into "network order," as the library will
    /// handle that for you.
    ///
    /// The caller may supply properties to customize behavior. This is optional,
    /// and a value of zero for `props` will request defaults for all properties.
    ///
    /// These are the supported properties:
    ///
    /// - [`NET_PROP_DATAGRAM_SOCKET_REUSEADDR_BOOLEAN`]\: true if the socket should
    ///   be created even if a previous socket has recently used this address. For
    ///   various reasons, networks prefer that there be some delay between apps
    ///   reusing the same address, but this can be problematic when iterating
    ///   quickly, for software development purposes or just restarting a crashed
    ///   service. This property defaults to true (although it should be noted
    ///   that, at the operating system level, this defaults to false!). If this
    ///   property is false and the OS feels that not enough time has elapsed,
    ///   socket creation will fail and this function will report an error.
    /// - [`NET_PROP_DATAGRAM_SOCKET_ALLOW_BROADCAST_BOOLEAN`]\: true if the socket
    ///   should allow broadcasting. At the lower level, this will set
    ///   `SO_BROADCAST` for IPv4 sockets, to allow sending to the subnet's
    ///   broadcast address at the OS level. For IPv6, it'll join the all-nodes
    ///   link-local multicast group, ff02::1, allowing sending and receiving
    ///   there, more or less simulating the usual IPv4 broadcast semantics. Other
    ///   protocols take similar approaches. If you do not intend to send or
    ///   receive broadcast packets on this socket, set this property to false, or
    ///   omit it, as it defaults to false. Note: IPv4 will still be able to
    ///   receive broadcast packets without this option, but IPv6 will not. Also
    ///   see notes about sending to a broadcast address in [`NET_SendDatagram()`].
    ///
    /// ## Parameters
    /// - `addr`: the local address to listen for connections on, or NULL to
    ///   listen on all available local addresses.
    /// - `port`: the port on the local address to listen for connections on, or
    ///   zero for the system to decide.
    /// - `props`: properties of the new socket. Specify zero for defaults.
    ///
    /// ## Return value
    /// Returns a new [`NET_DatagramSocket`], or NULL on error; call [`SDL_GetError()`]
    ///   for details.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_GetLocalAddresses`]
    /// - [`NET_DestroyDatagramSocket`]
    pub fn NET_CreateDatagramSocket(
        addr: *mut NET_Address,
        port: Uint16,
        props: SDL_PropertiesID,
    ) -> *mut NET_DatagramSocket;
}

pub const NET_PROP_DATAGRAM_SOCKET_REUSEADDR_BOOLEAN: *const ::core::ffi::c_char =
    c"NET.datagram_socket.reuseaddr".as_ptr();

pub const NET_PROP_DATAGRAM_SOCKET_ALLOW_BROADCAST_BOOLEAN: *const ::core::ffi::c_char =
    c"NET.datagram_socket.allow_broadcast".as_ptr();

unsafe extern "C" {
    /// Send a new packet over a datagram socket to a remote system.
    ///
    /// Datagram sockets send packets of data. They either arrive as complete
    /// packets or they don't arrive at all, as opposed to stream sockets, where
    /// individual bytes might trickle in as they attempt to reliably deliver a
    /// stream of data.
    ///
    /// Datagram packets might arrive in a different order than you sent them, or
    /// they may just be lost while travelling across the network. You have to plan
    /// for this. As an added confusion, since SDL_net might send the same packet
    /// on multiple interfaces, you might get duplicate packets, possibly from
    /// different network addresses. You have to plan for this, too.
    ///
    /// You can send to any address and port on the network, but there has to be a
    /// datagram socket waiting for the data on the other side for the packet not
    /// to be lost.
    ///
    /// General wisdom is that you shouldn't send a packet larger than 1500 bytes
    /// over the Internet, as bad routers might fragment or lose larger ones, but
    /// this limit is not hardcoded into SDL_net and in good conditions you might
    /// be able to send significantly more.
    ///
    /// This call never blocks; if it can't send the data immediately, the library
    /// will queue it for later transmission. There is no query to see what is
    /// still queued, as datagram transmission is unreliable, so you should never
    /// assume anything about queued data.
    ///
    /// If there's a fatal error, this function will return false. Datagram sockets
    /// generally won't report failures, because there is no state like a
    /// "connection" to fail at this level, but may report failure for
    /// unrecoverable system-level conditions; once a datagram socket fails, you
    /// should assume it is no longer usable and should destroy it with
    /// [`SDL_DestroyDatagramSocket()`].
    ///
    /// Sending to a NULL address is treated as a request to broadcast a packet.
    /// Note that this will report failure immediately if the socket was not
    /// created with broadcast permission. Broadcast packets are (more or less)
    /// sent to every machine on the LAN, unconditionally.
    ///
    /// **WARNING**: It is possible to build a game where everyone is playing on
    /// the same LAN, and every player is simply broadcasting packets. This is
    /// absolutely the wrong thing to do, however. Broadcast packets go to every
    /// device on the LAN, whether they want them or not. The game DOOM, in its
    /// heyday, was capable of
    /// [bringing entire networks to their knees](https://doomwiki.org/wiki/Doom_in_workplaces)
    /// , as many players on the same network would all be broadcasting
    /// relentlessly.
    ///
    /// In practice, broadcasting sparingly can be useful for certain
    /// functionality: a LAN-only client broadcasting a few packets to ask for
    /// available servers, and running servers replying directly to that client
    /// without broadcasting at all, is reasonable and safe. Once clients and
    /// servers have found each other, they can communicate directly without any
    /// broadcasting at all. For peer-to-peer games, once connection is
    /// established, it's better to either send unique packets to each known
    /// player, or use a multicasting (which works like broadcast, but only routes
    /// packets to devices that are explicitly listening for it).
    ///
    /// With IPv6, which doesn't support broadcasts, broadcasting is faked with
    /// multicast to the all-nodes link-local multicast group, ff02::1, either on a
    /// specific interface or letting the OS choose the default. Other protocols
    /// might fake broadcast operations in similar ways in the future.
    ///
    /// ## Parameters
    /// - `sock`: the datagram socket to send data through.
    /// - `address`: the [`NET_Address`] object address. May be NULL to broadcast.
    /// - `port`: the address port.
    /// - `buf`: a pointer to the data to send as a single packet.
    /// - `buflen`: the size of the data to send, in bytes.
    ///
    /// ## Return value
    /// Returns true if data sent or queued for transmission, false on failure;
    ///   call [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_ReceiveDatagram`]
    pub fn NET_SendDatagram(
        sock: *mut NET_DatagramSocket,
        address: *mut NET_Address,
        port: Uint16,
        buf: *const ::core::ffi::c_void,
        buflen: ::core::ffi::c_int,
    ) -> ::core::primitive::bool;
}

unsafe extern "C" {
    /// Receive a new packet that a remote system sent to a datagram socket.
    ///
    /// Datagram sockets send packets of data. They either arrive as complete
    /// packets or they don't arrive at all, so you'll never receive half a packet.
    ///
    /// This call never blocks; if no new data is available at the time of the
    /// call, it returns true immediately. The caller can try again later.
    ///
    /// On a successful call to this function, it returns true, even if no new
    /// packets are available, so you should check for a successful return and a
    /// non-NULL value in `*dgram` to decide if a new packet is available.
    ///
    /// You must pass received packets to [`NET_DestroyDatagram`] when you are done
    /// with them. If you want to save the sender's address past this time, it is
    /// safe to call [`NET_RefAddress()`] on the address and hold onto the pointer, so
    /// long as you call [`NET_UnrefAddress()`] on it when you are done with it.
    ///
    /// Since datagrams can arrive from any address or port on the network without
    /// prior warning, this information is available in the [`NET_Datagram`] object
    /// that is provided by this function, and this is the only way to know who to
    /// reply to. Even if you aren't acting as a "server," packets can still arrive
    /// at your socket if someone sends one.
    ///
    /// If there's a fatal error, this function will return false. Datagram sockets
    /// generally won't report failures, because there is no state like a
    /// "connection" to fail at this level, but may report failure for
    /// unrecoverable system-level conditions; once a datagram socket fails, you
    /// should assume it is no longer usable and should destroy it with
    /// [`SDL_DestroyDatagramSocket()`].
    ///
    /// ## Parameters
    /// - `sock`: the datagram socket to send data through.
    /// - `dgram`: a pointer to the datagram packet pointer.
    ///
    /// ## Return value
    /// Returns true if data sent or queued for transmission, false on failure;
    ///   call [`SDL_GetError()`] for details.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_SendDatagram`]
    /// - [`NET_DestroyDatagram`]
    pub fn NET_ReceiveDatagram(
        sock: *mut NET_DatagramSocket,
        dgram: *mut *mut NET_Datagram,
    ) -> ::core::primitive::bool;
}

unsafe extern "C" {
    /// Dispose of a datagram packet previously received.
    ///
    /// You must pass packets received through [`NET_ReceiveDatagram`] to this function
    /// when you are done with them. This will free resources used by this packet
    /// and unref its [`NET_Address`].
    ///
    /// If you want to save the sender's address from the packet past this time, it
    /// is safe to call [`NET_RefAddress()`] on the address and hold onto its pointer,
    /// so long as you call [`NET_UnrefAddress()`] on it when you are done with it.
    ///
    /// Once you call this function, the datagram pointer becomes invalid and
    /// should not be used again by the app.
    ///
    /// ## Parameters
    /// - `dgram`: the datagram packet to destroy.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_DestroyDatagram(dgram: *mut NET_Datagram);
}

unsafe extern "C" {
    /// Enable simulated datagram socket failures.
    ///
    /// Often times, testing a networked app on your development machine--which
    /// might have a wired connection to a fast, reliable network service--won't
    /// expose bugs that happen when networks intermittently fail in the real
    /// world, when the wifi is flakey and firewalls get in the way.
    ///
    /// This function allows you to tell the library to pretend that some
    /// percentage of datagram socket data transmission will fail.
    ///
    /// The library will randomly lose packets (both incoming and outgoing) at an
    /// average matching `percent_loss`. Setting this to zero (the default) will
    /// disable the simulation. Setting to 100 means _everything_ fails
    /// unconditionally and no further data will get through. At what percent the
    /// system merely borders on unusable is left as an exercise to the app
    /// developer.
    ///
    /// This is intended for debugging purposes, to simulate real-world conditions
    /// that are various degrees of terrible. You probably should _not_ call this
    /// in production code, where you'll likely see real failures anyhow.
    ///
    /// ## Parameters
    /// - `sock`: The socket to set a failure rate on.
    /// - `percent_loss`: A number between 0 and 100. Higher means more failures.
    ///   Zero to disable.
    ///
    /// ## Thread safety
    /// It is safe to call this function from any thread.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    pub fn NET_SimulateDatagramPacketLoss(
        sock: *mut NET_DatagramSocket,
        percent_loss: ::core::ffi::c_int,
    );
}

unsafe extern "C" {
    /// Dispose of a previously-created datagram socket.
    ///
    /// This will _abandon_ any data queued for sending that hasn't made it to the
    /// socket. If you need this data to arrive, you should wait for confirmation
    /// from the remote computer in some form that you devise yourself. Queued data
    /// is not guaranteed to arrive even if the library made efforts to transmit it
    /// here.
    ///
    /// Any data that has arrived from the remote end of the connection that hasn't
    /// been read yet is lost.
    ///
    /// ## Parameters
    /// - `sock`: datagram socket to destroy.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_CreateDatagramSocket`]
    /// - [`NET_SendDatagram`]
    /// - [`NET_ReceiveDatagram`]
    pub fn NET_DestroyDatagramSocket(sock: *mut NET_DatagramSocket);
}

unsafe extern "C" {
    /// Block on multiple sockets until at least one has data available.
    ///
    /// This is a complex function that most apps won't need, but it could be used
    /// to implement a more efficient server or i/o thread in some cases.
    ///
    /// This allows you to give it a list of objects and wait for new input to
    /// become available on any of them. The calling thread is put to sleep until
    /// such a time.
    ///
    /// The following things can be specified in the `vsockets` array, cast to
    /// `void *`:
    ///
    /// - [`NET_Server`] (reports new input when a connection is ready to be accepted
    ///   with [`NET_AcceptClient()`])
    /// - [`NET_StreamSocket`] (reports new input when the remote end has sent more
    ///   bytes of data to be read with [`NET_ReadFromStreamSocket`], or if the socket
    ///   finished making its initial connection).
    /// - [`NET_DatagramSocket`] (reports new input when a new packet arrives that can
    ///   be read with [`NET_ReceiveDatagram`]).
    ///
    /// This function takes a timeout value, represented in milliseconds, of how
    /// long to wait for resolution to complete. Specifying a timeout of -1
    /// instructs the library to wait indefinitely, and a timeout of 0 just checks
    /// the current status and returns immediately.
    ///
    /// This returns the number of items that have new input, but it does not tell
    /// you which ones; since access to them is non-blocking, you can just try to
    /// read from each of them and see which are ready. If nothing is ready and the
    /// timeout is reached, this returns zero. On error, this returns -1.
    ///
    /// ## Parameters
    /// - `vsockets`: an array of pointers to various objects that can be waited
    ///   on, each cast to a void pointer.
    /// - `numsockets`: the number of pointers in the `vsockets` array.
    /// - `timeout`: Number of milliseconds to wait for new input to become
    ///   available. -1 to wait indefinitely, 0 to check once without
    ///   waiting.
    ///
    /// ## Return value
    /// Returns the number of items that have new input, or -1 on error.
    ///
    /// ## Thread safety
    /// You should not operate on the same socket from multiple
    ///   threads at the same time without supplying a serialization
    ///   mechanism. However, different threads may access different
    ///   sockets at the same time without problems.
    ///
    /// ## Availability
    /// This function is available since SDL_net 3.0.0.
    ///
    /// ## See also
    /// - [`NET_CreateDatagramSocket`]
    /// - [`NET_SendDatagram`]
    /// - [`NET_ReceiveDatagram`]
    pub fn NET_WaitUntilInputAvailable(
        vsockets: *mut *mut ::core::ffi::c_void,
        numsockets: ::core::ffi::c_int,
        timeout: Sint32,
    ) -> ::core::ffi::c_int;
}

/// Opaque representation of a computer-readable network address.
///
/// This is an opaque datatype, to be treated by the app as a handle.
///
/// SDL_net uses these to identify other servers; you use them to connect to a
/// remote machine, and you use them to find out who connected to you. They are
/// also used to decide what network interface to use when creating a server.
///
/// These are intended to be protocol-independent; a given address might be for
/// IPv4, IPv6, or something more esoteric. SDL_net attempts to hide the
/// differences.
///
/// ## Availability
/// This datatype is available since SDL_net 3.0.0.
///
/// ## See also
/// - [`NET_ResolveHostname`]
/// - [`NET_GetLocalAddresses`]
/// - [`NET_CompareAddresses`]
#[repr(C)]
pub struct NET_Address {
    _opaque: [::core::primitive::u8; 0],
}

/// An object that represents a datagram connection to another system.
///
/// This is meant to be an unreliable, packet-oriented connection, such as UDP.
///
/// Datagram sockets follow different rules than stream sockets. They are not a
/// reliable stream of bytes but rather packets, they are not limited to
/// talking to a single other remote system, they do not maintain a single
/// "connection" that can be dropped, and they are more nimble about network
/// failures at the expense of being more complex to use. What makes sense for
/// your app depends entirely on what your app is trying to accomplish.
///
/// Generally the idea of a datagram socket is that you send data one chunk
/// ("packet") at a time to any address you want, and it arrives whenever it
/// gets there, even if later packets get there first, and maybe it doesn't get
/// there at all, and you don't know when anything of this happens by default.
///
/// ## Availability
/// This datatype is available since SDL_net 3.0.0.
///
/// ## See also
/// - [`NET_CreateDatagramSocket`]
/// - [`NET_SendDatagram`]
/// - [`NET_ReceiveDatagram`]
#[repr(C)]
pub struct NET_DatagramSocket {
    _opaque: [::core::primitive::u8; 0],
}

/// The receiving end of a stream connection.
///
/// This is an opaque datatype, to be treated by the app as a handle.
///
/// Internally, this is what BSD sockets refers to as a "listen socket".
/// Clients attempt to connect to a server, and if the server accepts the
/// connection, will provide the app with a stream socket to send and receive
/// data over that connection.
///
/// ## Availability
/// This datatype is available since SDL_net 3.0.0.
///
/// ## See also
/// - [`NET_CreateServer`]
#[repr(C)]
pub struct NET_Server {
    _opaque: [::core::primitive::u8; 0],
}

/// An object that represents a streaming connection to another system.
///
/// This is meant to be a reliable, stream-oriented connection, such as TCP.
///
/// Each [`NET_StreamSocket`] represents a single connection between systems.
/// Usually, a client app will have one connection to a server app on a
/// different computer, and the server app might have many connections from
/// different clients. Each of these connections communicate over a separate
/// stream socket.
///
/// ## Availability
/// This datatype is available since SDL_net 3.0.0.
///
/// ## See also
/// - [`NET_CreateClient`]
/// - [`NET_WriteToStreamSocket`]
/// - [`NET_ReadFromStreamSocket`]
#[repr(C)]
pub struct NET_StreamSocket {
    _opaque: [::core::primitive::u8; 0],
}

#[cfg(doc)]
use crate::everything::*;