From 18f798073770643d266ad873801d84469470f162 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 25 Sep 2023 23:39:08 -0400
Subject: [PATCH] Wrote real API documentation and adjusted a few function
names.
---
SDL_net.c | 10 +-
SDL_net.h | 1261 ++++++++++++++++++++++++++++++++++--
examples/simple-http-get.c | 2 +-
examples/voipchat.c | 2 +-
4 files changed, 1229 insertions(+), 46 deletions(-)
diff --git a/SDL_net.c b/SDL_net.c
index f23af89..aa975f2 100644
--- a/SDL_net.c
+++ b/SDL_net.c
@@ -53,7 +53,7 @@ typedef enum SDLNet_SocketType
} SDLNet_SocketType;
-const SDL_version *SDLNet_Linked_Version(void)
+const SDL_version *SDLNet_LinkedVersion(void)
{
static const SDL_version linked_version = {
SDL_NET_MAJOR_VERSION, SDL_NET_MINOR_VERSION, SDL_NET_PATCHLEVEL
@@ -1156,7 +1156,7 @@ int SDLNet_WaitUntilStreamSocketDrained(SDLNet_StreamSocket *sock, int timeoutms
return SDLNet_GetStreamSocketPendingWrites(sock);
}
-int SDLNet_ReadStreamSocket(SDLNet_StreamSocket *sock, void *buf, int buflen)
+int SDLNet_ReadFromStreamSocket(SDLNet_StreamSocket *sock, void *buf, int buflen)
{
if (PumpStreamSocket(sock) < 0) { // try to flush any queued data to the socket now, before we go further.
return -1;
@@ -1323,7 +1323,7 @@ static int PumpDatagramSocket(SDLNet_DatagramSocket *sock)
}
/* else if (rc > 0) */
- SDLNet_FreeDatagram(dgram);
+ SDLNet_DestroyDatagram(dgram);
sock->pending_output_len--;
SDL_memmove(sock->pending_output, sock->pending_output + 1, sock->pending_output_len * sizeof (SDLNet_Datagram *));
sock->pending_output[sock->pending_output_len] = NULL;
@@ -1483,7 +1483,7 @@ int SDLNet_ReceiveDatagram(SDLNet_DatagramSocket *sock, SDLNet_Datagram **dgram)
return 0;
}
-void SDLNet_FreeDatagram(SDLNet_Datagram *dgram)
+void SDLNet_DestroyDatagram(SDLNet_Datagram *dgram)
{
if (dgram) {
SDLNet_UnrefAddress(dgram->addr);
@@ -1516,7 +1516,7 @@ void SDLNet_DestroyDatagramSocket(SDLNet_DatagramSocket *sock)
SDLNet_UnrefAddress(sock->latest_recv_addrs[i]);
}
for (int i = 0; i < sock->pending_output_len; i++) {
- SDLNet_FreeDatagram(sock->pending_output[i]);
+ SDLNet_DestroyDatagram(sock->pending_output[i]);
}
SDLNet_UnrefAddress(sock->addr);
SDL_free(sock->pending_output);
diff --git a/SDL_net.h b/SDL_net.h
index ed488ce..5e038cf 100644
--- a/SDL_net.h
+++ b/SDL_net.h
@@ -1,4 +1,43 @@
+/*
+ SDL_net: A simple networking library for use with SDL
+ Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_net.h
+ *
+ * Header file for SDL_net library
+ *
+ * A simple library to help with networking.
+ */
+
+#ifndef SDL_NET_H_
+#define SDL_NET_H_
+
#include <SDL3/SDL.h>
+#include <SDL3/SDL_version.h>
+#include <SDL3/SDL_begin_code.h>
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
/* Version checks... */
@@ -6,6 +45,16 @@
#define SDL_NET_MINOR_VERSION 0
#define SDL_NET_PATCHLEVEL 0
+/**
+ * Query the verion of the SDL_net library in use at compile time.
+ *
+ * This macro copies the version listen in the SDL_net headers into a
+ * struct of the app's choosing.
+ *
+ * \threadsafety It is safe to use this macro from any thread.
+ *
+ * \since This macro is available since SDL_Net 3.0.0.
+ */
#define SDL_NET_VERSION(X) \
{ \
(X)->major = SDL_NET_MAJOR_VERSION; \
@@ -13,74 +62,1208 @@
(X)->patch = SDL_NET_PATCHLEVEL; \
}
-extern DECLSPEC const SDL_version * SDLCALL SDLNet_Linked_Version(void);
+/**
+ * Query the verion of the SDL_net library in use at runtime.
+ *
+ * The returned value points to static, internal, read-only memory. Do not
+ * modify or free it. The pointer remains valid as long as the library is
+ * loaded by the system.
+ *
+ * This function can be safely called before SDLNet_Init().
+ *
+ * \returns An object with the runtime library version. Never returns NULL.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ */
+extern DECLSPEC const SDL_version * SDLCALL SDLNet_LinkedVersion(void);
-/* must call first/last... */
+/* init/quit functions... */
+/**
+ * Initialize the SDL_net library.
+ *
+ * This must be successfully called once before any (almost) any other SDL_net
+ * function can be used.
+ *
+ * It is save to call this multiple times; the library will only initialize
+ * once, and won't deinitialize until SDLNet_Quit() has been called a matching
+ * number of times. Extra attempts to init report success.
+ *
+ * \returns 0 on success, -1 on error; call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_net 3.0.0.
+ *
+ * \sa SDLNet_Quit
+ */
extern DECLSPEC int SDLCALL SDLNet_Init(void);
+
+/**
+ * Deinitialize the SDL_net library.
+ *
+ * This must be called when done with the library, probably at the end of
+ * your program.
+ *
+ * It is save to call this multiple times; the library will only deinitialize
+ * once, when this function is called the same number of times as SDLNet_Init
+ * was successfully called.
+ *
+ * Once you have successfully deinitialized the library, it is safe to call
+ * SDLNet_Init to reinitialize it for further use.
+ *
+ * \param devid the instance ID of the device to query.
+ * \returns 0 on success, -1 on error; call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_Quit
+ */
extern DECLSPEC void SDLCALL SDLNet_Quit(void);
+
/* hostname resolution API... */
-typedef struct SDLNet_Address SDLNet_Address;
+typedef struct SDLNet_Address SDLNet_Address; /**< Opaque struct that deals with computer-readable addresses. */
+
+/**
+ * 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
+ * SDLNet_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 SDLNet_Address. Until the address resolves, it can't be used.
+ *
+ * If you want to block until the resolution is finished, you can call
+ * SDLNet_WaitUntilResolved(). Otherwise, you can do a non-blocking check
+ * with SDLNet_GetAddressStatus().
+ *
+ * When you are done with the returned SDLNet_Address, call
+ * SDLNet_UnrefAddress() to dispose of it. You need to do this even if
+ * resolution later fails asynchronously.
+ *
+ * \param host The hostname to resolve.
+ * \returns A new SDLNet_Address on success, NULL on error; call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_WaitUntilResolved
+ * \sa SDLNet_GetAddressStatus
+ * \sa SDLNet_RefAddress
+ * \sa SDLNet_UnrefAddress
+ */
+extern DECLSPEC SDLNet_Address * SDLCALL SDLNet_ResolveHostname(const char *host);
+
+/**
+ * Block until an address is resolved.
+ *
+ * The SDLNet_Address objects returned by SDLNet_ResolveHostname take time
+ * to do their work, so it is 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 SDLNet_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
+ * SDLNet_GetAddressStatus from time to time until you get a non-zero result.
+ *
+ * \param address The SDLNet_Address object to wait on.
+ * \param timeout Number of milliseconds to wait for resolution to complete.
+ * -1 to wait indefinitely, 0 to check once without waiting.
+ * \returns 1 if successfully resolved, -1 if resolution failed, 0 if still
+ * resolving (this function timed out without resolution); if -1,
+ * call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread, and several
+ * threads can block on the same address simultaneously.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_GetAddressStatus
+ */
+extern DECLSPEC int SDLCALL SDLNet_WaitUntilResolved(SDLNet_Address *address, Sint32 timeout);
+
+/**
+ * Check if an address is resolved, without blocking.
+ *
+ * The SDLNet_Address objects returned by SDLNet_ResolveHostname take time
+ * to do their work, so it is 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.
+ *
+ * \param host The hostname to resolve.
+ * \returns 1 if successfully resolved, -1 if resolution failed, 0 if still
+ * resolving; if -1, call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_WaitUntilResolved
+ */
+extern DECLSPEC int SDLCALL SDLNet_GetAddressStatus(SDLNet_Address *address);
+
+/**
+ * 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
+ * SDLNet_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 SDLNet_GetAddressStatus() or SDLNet_WaitUntilResolved()
+ * to make sure resolution has successfully completed before calling this.
+ *
+ * \param address The SDLNet_Address to query.
+ * \returns a string, or NULL on error; call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_GetAddressStatus
+ * \sa SDLNet_WaitUntilResolved
+ */
+extern DECLSPEC const char * SDLCALL SDLNet_GetAddressString(SDLNet_Address *address);
+
+/**
+ * Add a reference to an SDLNet_Address.
+ *
+ * Since several pieces of the library might share a single SDLNet_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 SDLNet_Address, increasing its
+ * reference count by one.
+ *
+ * The documentation will tell you when the app has to explicitly unref an
+ * address. For example, SDLNet_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 = SDLNet_RefAddress(yourAddr);
+ * ```
+ *
+ * \param address The SDLNet_Address to add a reference to.
+ * \returns the same address that was passed as a parameter.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ */
+extern DECLSPEC SDLNet_Address *SDLCALL SDLNet_RefAddress(SDLNet_Address *address);
+
+/**
+ * Drop a reference to an SDLNet_Address.
+ *
+ * Since several pieces of the library might share a single SDLNet_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 SDLNet_Address, decreasing its
+ * reference count by one.
+ *
+ * The documentation will tell you when the app has to explicitly unref an
+ * address. For example, SDLNet_ResolveHostname() creates addresses that are
+ * already referenced, so the caller needs to unref it when done.
+ *
+ * \param address The SDLNet_Address to drop a reference to.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ */
+extern DECLSPEC void SDLCALL SDLNet_UnrefAddress(SDLNet_Address *address);
+
+/**
+ * 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.
+ *
+ * \param percent_loss A number between 0 and 100. Higher means more failures.
+ * Zero to disable.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ */
+extern DECLSPEC void SDLCALL SDLNet_SimulateAddressResolutionLoss(int percent_loss);
+
+/**
+ * Compare two SDLNet_Address objects.
+ *
+ * This compares two addresses, returning a value that is useful for qsort
+ * (or SDL_qsort).
+ *
+ * \param a first address to compare.
+ * \param b second address to compare.
+ * \returns -1 if `a` is "less than" `b`, 1 if "greater than", 0 if equal.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ */
+extern DECLSPEC int SDLCALL SDLNet_CompareAddresses(const SDLNet_Address *a, const SDLNet_Address *b);
+
+/**
+ * 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 SDLNet_CreateServer() or
+ * SDLNet_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 SDLNet_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 SDLNet_RefAddress() on them.
+ *
+ * \param num_addresses on exit, will be set to the number of addresses
+ * returned. Can be NULL.
+ * \returns A NULL-terminated array of SDLNet_Address pointers, one for
+ * each bindable address on the system, or NULL on error; call
+ * SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ */
+extern DECLSPEC SDLNet_Address **SDLCALL SDLNet_GetLocalAddresses(int *num_addresses);
+
+/**
+ * Free the results from SDLNet_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 SDLNet_RefAddress() on them first.
+ *
+ * It is safe to pass a NULL in here, it will be ignored.
+ *
+ * \param addresses A pointer returned by SDLNet_GetLocalAddresses().
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ */
+extern DECLSPEC void SDLCALL SDLNet_FreeLocalAddresses(SDLNet_Address **addresses);
-extern DECLSPEC SDLNet_Address * SDLCALL SDLNet_ResolveHostname(const char *host); /* does not block! */
-extern DECLSPEC int SDLCALL SDLNet_WaitUntilResolved(SDLNet_Address *address, Sint32 timeout); /* blocks until success or failure. Optional. timeout: 0: check once and don't block, -1: block until there's a definite answer, else: block for `timeout` milliseconds. */
-extern DECLSPEC int SDLCALL SDLNet_GetAddressStatus(SDLNet_Address *address); /* 0: still working, -1: failed (check SDL_GetError), 1: ready */
-extern DECLSPEC const char * SDLCALL SDLNet_GetAddressString(SDLNet_Address *address); /* human-readable string, like "127.0.0.1" or "::1" or whatever. NULL if GetAddressStatus != 1. String owned by address! */
-extern DECLSPEC SDLNet_Address *SDLCALL SDLNet_RefAddress(SDLNet_Address *address); /* +1 refcount; SDLNet_ResolveHost starts at 1. Returns `address` for convenience. */
-extern DECLSPEC void SDLCALL SDLNet_UnrefAddress(SDLNet_Address *address); /* when totally unref'd, gets freed. */
-extern DECLSPEC void SDLCALL SDLNet_SimulateAddressResolutionLoss(int percent_loss); /* make resolutions delay at random, fail some percent of them. */
-extern DECLSPEC int SDLCALL SDLNet_CompareAddresses(const SDLNet_Address *a, const SDLNet_Address *b); /* can be used with SDL_qsort. */
-extern DECLSPEC SDLNet_Address **SDLCALL SDLNet_GetLocalAddresses(int *num_addresses); /* returns NULL-terminated array of SDLNet_Address*, of all known interfaces. */
-extern DECLSPEC void SDLCALL SDLNet_FreeLocalAddresses(SDLNet_Address **addresses); /* unrefs each address, frees array. */
/* Streaming (TCP) API... */
-typedef struct SDLNet_StreamSocket SDLNet_StreamSocket; /* a TCP socket. Reliable transmission, with the usual pros/cons */
+typedef struct SDLNet_StreamSocket SDLNet_StreamSocket; /**< a TCP socket. Reliable transmission, with the usual pros/cons. */
+
+/**
+ * Begin connecting a socket as a client to a remote server.
+ *
+ * Each SDLNet_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
+ * SDLNet_WaitUntilConnected() or SDLNet_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 SDLNet_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.
+ *
+ * \param address the address of the remote server to connect to
+ * \param the port on the remote server to connect to
+ * \returns a new SDLNet_StreamSocket, pending connection, or NULL on error;
+ * call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_WaitUntilConnected
+ * \sa SDLNet_GetConnectionStatus
+ * \sa SDLNet_DestroyStreamSocket
+ */
+extern DECLSPEC SDLNet_StreamSocket * SDLCALL SDLNet_CreateClient(SDLNet_Address *address, Uint16 port);
+
+/**
+ * Block until a stream socket has connected to a server.
+ *
+ * The SDLNet_StreamSocket objects returned by SDLNet_CreateClient take time
+ * to do their work, so it is 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 SDLNet_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
+ * SDLNet_GetConnectionStatus() from time to time until you get a non-zero
+ * result.
+ *
+ * \param address The SDLNet_Address object to wait on.
+ * \param timeout Number of milliseconds to wait for resolution to complete.
+ * -1 to wait indefinitely, 0 to check once without waiting.
+ * \returns 1 if successfully connected, -1 if connection failed, 0 if still
+ * connecting (this function timed out without resolution); if -1,
+ * call SDL_GetError() for details.
+ *
+ * \threadsafety 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.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_GetConnectionStatus
+ */
+extern DECLSPEC int SDLCALL SDLNet_WaitUntilConnected(SDLNet_StreamSocket *sock, Sint32 timeout);
-/* Clients connect to servers, and then send/receive data on a stream socket. */
-extern DECLSPEC SDLNet_StreamSocket * SDLCALL SDLNet_CreateClient(SDLNet_Address *address, Uint16 port); /* Start connection to address:port. does not block! */
-extern DECLSPEC int SDLCALL SDLNet_WaitUntilConnected(SDLNet_StreamSocket *sock, Sint32 timeout); /* blocks until success or failure. Optional. timeout: 0: check once and don't block, -1: block until there's a definite answer, else: block for `timeout` milliseconds. */
+typedef struct SDLNet_Server SDLNet_Server; /**< a listen socket, internally. Binds to a port, accepts connections. */
-/* Servers listen for and accept connections from clients, and then send/receive data on a stream socket. */
-typedef struct SDLNet_Server SDLNet_Server; /* a listen socket internally. Binds to a port, accepts connections. */
-extern DECLSPEC SDLNet_Server * SDLCALL SDLNet_CreateServer(SDLNet_Address *addr, Uint16 port); /* Specify NULL for any/all interfaces, or something from GetLocalAddresses */
-extern DECLSPEC int SDLCALL SDLNet_AcceptClient(SDLNet_Server *server, SDLNet_StreamSocket **client_stream); /* Accept pending connection. Does not block, returns 0 and sets *client_stream=NULL if none available. -1 on errors, zero otherwise. */
+/**
+ * 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
+ * SDLNet_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 SDLNet_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.
+ *
+ * \param address the _local_ address to listen for connections on, or NULL.
+ * \param the port on the local address to listen for connections on
+ * \returns a new SDLNet_StreamSocket, pending connection, or NULL on error;
+ * call SDL_GetError() for details.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_Net 3.0.0.
+ *
+ * \sa SDLNet_GetLocalAddresses
+ * \sa SDLNet_AcceptClient
+ * \sa SDLNet_DestroyServer
+ */
+extern DECLSPEC SDLNet_Server * SDLCALL SDLNet_CreateServer(SDLNet_Address *addr, Uint16 port);
+
+/**
+ * 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 SDLNet_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 0 (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 SDLNet_WaitUntilInputAvailable().
+ *
+ * When done with the newly-accepted client, you can disconnect and dispose
+ * of the stream socket by calling SDL_DestroyStreamSocket().
+ *
+ * \param server the server object to check for pending connections
+ * \param client_stream Will be set to a new stream socket if a connection was
+ * pending, NULL otherwise.
+ * \returns 0
(Patch may be truncated, please check the link at the top of this post.)