summaryrefslogtreecommitdiff
path: root/docs/reference/src/api
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2024-03-24 12:53:58 -0700
committerGarrett D'Amore <garrett@damore.org>2024-03-24 12:53:58 -0700
commitb24ef189f1dc9f9bf4889cb420e4645721728036 (patch)
tree1dd4be3ce52c9c07018fb2a1d35c425e6dd33352 /docs/reference/src/api
parent85fbe7f9e4642b554d0d97f2e3ff2aa12978691a (diff)
downloadnng-b24ef189f1dc9f9bf4889cb420e4645721728036.tar.gz
nng-b24ef189f1dc9f9bf4889cb420e4645721728036.tar.bz2
nng-b24ef189f1dc9f9bf4889cb420e4645721728036.zip
Initial swag at mdbook content.
This has the nng_a* to nng_c* content converted. Various editorial changes have been made as well.
Diffstat (limited to 'docs/reference/src/api')
-rw-r--r--docs/reference/src/api/aio_provider.md10
-rw-r--r--docs/reference/src/api/compat.md120
-rw-r--r--docs/reference/src/api/context.md1
-rw-r--r--docs/reference/src/api/general.md1
-rw-r--r--docs/reference/src/api/index.md8
-rw-r--r--docs/reference/src/api/nng_aio.md59
-rw-r--r--docs/reference/src/api/nng_aio_abort.md36
-rw-r--r--docs/reference/src/api/nng_aio_alloc.md76
-rw-r--r--docs/reference/src/api/nng_aio_begin.md47
-rw-r--r--docs/reference/src/api/nng_aio_busy.md42
-rw-r--r--docs/reference/src/api/nng_aio_cancel.md38
-rw-r--r--docs/reference/src/api/nng_aio_count.md46
-rw-r--r--docs/reference/src/api/nng_aio_defer.md59
-rw-r--r--docs/reference/src/api/nng_aio_finish.md41
-rw-r--r--docs/reference/src/api/nng_aio_free.md35
-rw-r--r--docs/reference/src/api/nng_aio_get_input.md35
-rw-r--r--docs/reference/src/api/nng_aio_get_msg.md31
-rw-r--r--docs/reference/src/api/nng_aio_get_output.md41
-rw-r--r--docs/reference/src/api/nng_aio_result.md46
-rw-r--r--docs/reference/src/api/nng_aio_set_input.md43
-rw-r--r--docs/reference/src/api/nng_aio_set_iov.md45
-rw-r--r--docs/reference/src/api/nng_aio_set_msg.md29
-rw-r--r--docs/reference/src/api/nng_aio_set_output.md37
-rw-r--r--docs/reference/src/api/nng_aio_set_timeout.md54
-rw-r--r--docs/reference/src/api/nng_aio_stop.md40
-rw-r--r--docs/reference/src/api/nng_aio_wait.md34
-rw-r--r--docs/reference/src/api/nng_alloc.md44
-rw-r--r--docs/reference/src/api/nng_bus_open.md40
-rw-r--r--docs/reference/src/api/nng_clock.md43
-rw-r--r--docs/reference/src/api/nng_close.md45
-rw-r--r--docs/reference/src/api/nng_ctx.md160
-rw-r--r--docs/reference/src/api/nng_ctx_close.md42
-rw-r--r--docs/reference/src/api/nng_ctx_get.md113
-rw-r--r--docs/reference/src/api/nng_ctx_getopt.md117
-rw-r--r--docs/reference/src/api/nng_ctx_id.md35
-rw-r--r--docs/reference/src/api/nng_ctx_open.md57
-rw-r--r--docs/reference/src/api/nng_ctx_recv.md61
-rw-r--r--docs/reference/src/api/nng_ctx_recvmsg.md51
-rw-r--r--docs/reference/src/api/nng_ctx_send.md69
-rw-r--r--docs/reference/src/api/nng_ctx_sendmsg.md70
-rw-r--r--docs/reference/src/api/nng_ctx_set.md95
-rw-r--r--docs/reference/src/api/nng_ctx_setopt.md99
-rw-r--r--docs/reference/src/api/nng_cv_alloc.md46
-rw-r--r--docs/reference/src/api/nng_cv_free.md22
-rw-r--r--docs/reference/src/api/nng_cv_until.md75
-rw-r--r--docs/reference/src/api/nng_cv_wait.md68
-rw-r--r--docs/reference/src/api/nng_cv_wake.md42
-rw-r--r--docs/reference/src/api/nng_cv_wake1.md43
-rw-r--r--docs/reference/src/api/protocol.md1
49 files changed, 2492 insertions, 0 deletions
diff --git a/docs/reference/src/api/aio_provider.md b/docs/reference/src/api/aio_provider.md
new file mode 100644
index 00000000..cf5acce7
--- /dev/null
+++ b/docs/reference/src/api/aio_provider.md
@@ -0,0 +1,10 @@
+# Asynchronous I/O for Providers
+
+This section documents functions used when implementing I/O providers.
+
+I/O providers actually perform the operations that are linked to
+an [`nng_aio`](nng_aio.md) object.
+
+Most applications will not use the functions listed here.
+Applications the implement their own HTTP handler functions, or
+custom transport providers, might make use of these functions.
diff --git a/docs/reference/src/api/compat.md b/docs/reference/src/api/compat.md
new file mode 100644
index 00000000..4ff75b3e
--- /dev/null
+++ b/docs/reference/src/api/compat.md
@@ -0,0 +1,120 @@
+# Legacy Compatibility Functions
+
+{{hi:compatibility layer}}
+_NNG_ provides source-level compatibility for most _libnanomsg_ 1.0 applications.
+
+This is intended to facilitate converting {{i:legacy applications}} to use _NNG_.
+New applications should use the newer _NNG_ APIs instead.
+
+Applications making use of this must take care
+to link with _libnng_ instead of _libnn_.
+
+> [!TIP]
+> While not recommended for long term use, the value returned by
+> [`nng_socket_id()`](nng_socket_id.md) can be used with these functions
+> just like a value returned by [`nn_socket()`](nn_socket.md).
+> This can be way to facilitate incremental transition to the new API.
+
+Some capabilities, protocols, and transports, will not be accessible
+using this API, as the compatible API has no provision for expression
+of certain concepts introduced in the new API.
+
+While reasonable efforts have been made to provide for compatibility,
+some things may behave differently, and some less common parts of the
+_libnanomsg_ 1.0 API are not supported at this time, including certain
+options and the statistics API.
+See the [Caveats](#caveats) section below.
+
+### Availability
+
+The availability of this legacy API depends on whether the library was
+configured to include it.
+
+> [!NOTE]
+> Future versions of _NNG_ may not include this compatibility layer
+> by default, or even at all. Modernizing applications to use the new
+> API is strongly recommended.
+
+### Compiling
+
+When compiling legacy _nanomsg_ applications, it will generally be
+necessary to change the include search path to add the `compat` subdirectory
+of the directory where headers were installed.
+For example, if _NNG_ is installed in `$prefix`, then header files will
+normally be located in `$prefix/include/nng`.
+In this case, to build legacy _nanomsg_ apps against _NNG_ you would
+add `$prefix/include/nng/compat` to your compiler's search path.
+
+Alternatively, you can change your source code so that `#include` statements
+referring to `<nanomsg>` instead refer to `<nng/compat/nanomsg>`.
+For example, instead of:
+
+```c
+#include <nanomsg/nn.h>
+#include <nanomsg/reqrep.h>
+```
+
+you would have this:
+
+```c
+#include <nng/compat/nanomsg/nn.h>
+#include <nng/compat/nanomsg/reqrep.h>
+```
+
+Legacy applications built using these methods should be linked against _libnng_
+instead of _libnn_, just like any other _NNG_ application.
+
+### Caveats
+
+The following caveats apply when using the legacy API with _NNG_.
+
+- Socket numbers can be quite large.
+ The legacy _libnanomsg_ attempted to reuse socket numbers, like
+ file descriptors in UNIX systems.
+ _NNG_ avoids this to prevent accidental reuse or
+ collision after a descriptor is closed.
+ Consequently, socket numbers can become quite large, and should
+ probably not be used for array indices.
+
+- The following options (`nn_getsockopt`) are unsupported:
+ `NN_SNDPRIO`, `NN_RCVPRIO`, `NN_IPV4ONLY`.
+
+- Access to statistics using this legacy API
+ [`nn_get_statistic()`](nn_get_statistic.md) is unsupported.
+
+- Some transports can support longer URLs than legacy _libnanomsg_ can.
+ It is a good idea to use short pathnames in URLs if interoperability
+ is a concern.
+
+- Only absolute paths are supported in `ipc://` URLs.
+ For example, `ipc:///tmp/mysocket` is acceptable, but `ipc://mysocket` is not.
+
+- The WebSocket transport in this implementation (`ws://` URLs)
+ only supports `BINARY` frames.
+
+- Some newer transports are unusable from this mode.
+ In particular, this legacy API offers no way to configure
+ TLS or ZeroTier parameters that may be required for use.
+
+- ABI versioning of the compatibility layer is not supported,
+ and the `NN_VERSION_` macros are not present.
+
+- Runtime symbol information is not implemented.
+ Specifically, there is no `nn_symbol()` function.
+
+- The TCP transport (`tcp://` URLs) does not support specifying the local
+ address or interface when binding. (This could be fixed in the future,
+ but most likely this will be available only using the new API.)
+
+- The values of `NN_RCVMAXSIZE` are constrained.
+ Specifically, values set larger than 2GB using the new API will be reported
+ as unlimited (`-1`) in the new API, and the value `0` will disable any
+ enforcement, just like `-1`.
+ (There is no practical reason to ever want to limit the receive size to
+ zero.)
+
+- This implementation counts buffers in terms of messages rather than bytes.
+ As a result, the buffer sizes accessed with `NN_SNDBUF` and `NN_RCVBUF` are
+ rounded up to a whole number of kilobytes, then divided by 1024, in order
+ to approximate buffering assuming 1 KB messages.
+ Few applications should need to adjust the default values.
diff --git a/docs/reference/src/api/context.md b/docs/reference/src/api/context.md
new file mode 100644
index 00000000..6131b985
--- /dev/null
+++ b/docs/reference/src/api/context.md
@@ -0,0 +1 @@
+# Context Functions
diff --git a/docs/reference/src/api/general.md b/docs/reference/src/api/general.md
new file mode 100644
index 00000000..a830d6bd
--- /dev/null
+++ b/docs/reference/src/api/general.md
@@ -0,0 +1 @@
+# General Purpose Functions
diff --git a/docs/reference/src/api/index.md b/docs/reference/src/api/index.md
new file mode 100644
index 00000000..0d1089e3
--- /dev/null
+++ b/docs/reference/src/api/index.md
@@ -0,0 +1,8 @@
+# API Reference
+
+This section documents the functions and data structures that make up
+the _NNG_ programming interface.
+
+> [!NOTE]
+> Interfaces not documented here are not considered public or stable,
+> and they may be removed or altered in incompatible ways at any time.
diff --git a/docs/reference/src/api/nng_aio.md b/docs/reference/src/api/nng_aio.md
new file mode 100644
index 00000000..667e785c
--- /dev/null
+++ b/docs/reference/src/api/nng_aio.md
@@ -0,0 +1,59 @@
+# nng_aio
+
+## NAME
+
+nng_aio --- asynchronous I/O handle
+
+```c
+#include <nng/nng.h>
+
+typedef struct nng_aio nng_aio;
+```
+
+## DESCRIPTION
+
+An `nng_aio`{{hi:aio}} is an opaque structure used in conjunction with
+{{i:asynchronous I/O}} operations.
+Every asynchronous operation uses one of these structures, each of which
+can only be used with a single operation at a time.
+
+Asynchronous operations are performed without blocking calling application
+threads.
+Instead the application registers a callback function to be executed
+when the operation is complete (whether successfully or not).
+This callback will be executed exactly once.
+
+The asynchronous I/O framework also supports cancellation of
+operations that are already in progress
+(see [`nng_aio_cancel()`](nng_aio_cancel.md)), as well setting a maximum
+timeout for them to complete within
+(see [`nng_aio_set_timeout()`](nng_aio_set_timeout.md)).
+
+It is also possible to initiate an asynchronous operation, and wait for it to
+complete [`nng_aio_wait()`](nng_aio_wait.md).
+
+These structures are created using the [`nng_aio_alloc()`](nng_aio_alloc.md),
+and destroyed using [`nng_aio_free()`](nng_aio_free.md).
+
+> [!IMPORTANT]
+> A given `nng_aio` can only have a single operation in progress
+> at any given time. Attempts to reuse an `nng_aio` while another
+> operation is in progress will generally cause a crash.
+
+## SEE ALSO
+
+[nng_aio_abort()](nng_aio_abort.md),
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_count()](nng_aio_count.md),
+[nng_aio_free()](nng_aio_free.md),
+[nng_aio_get_input()](nng_aio_get_input.md),
+[nng_aio_get_msg()](nng_aio_get_msg.md),
+[nng_aio_get_output()](nng_aio_get_output.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio_set_input()](nng_aio_set_input.md),
+[nng_aio_set_iov()](nng_aio_set_iov.md),
+[nng_aio_set_msg()](nng_aio_set_msg.md),
+[nng_aio_set_timeout()](nng_aio_set_timeout.md),
+[nng_aio_stop()](nng_aio_stop.md),
+[nng_aio_wait()](nng_aio_wait.md),
diff --git a/docs/reference/src/api/nng_aio_abort.md b/docs/reference/src/api/nng_aio_abort.md
new file mode 100644
index 00000000..4f4b8773
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_abort.md
@@ -0,0 +1,36 @@
+# nng_aio_abort()
+
+## NAME
+
+nng_aio_abort --- abort asynchronous I/O operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_abort(nng_aio *aio, int err);
+```
+
+## DESCRIPTION
+
+The `nng_aio_abort()` function aborts an operation previously started
+with the handle _aio_.
+If the operation is aborted, then the callback
+for the handle will be called, and the function
+[`nng_aio_result()`](nng_aio_result.md)
+will return the error _err_.
+
+This function does not wait for the operation to be fully aborted, but
+returns immediately.
+
+If no operation is currently in progress (either because it has already
+finished, or no operation has been started yet), then this function
+has no effect.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_alloc.md b/docs/reference/src/api/nng_aio_alloc.md
new file mode 100644
index 00000000..4acb45aa
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_alloc.md
@@ -0,0 +1,76 @@
+# nng_aio_alloc()
+
+## NAME
+
+nng_aio_alloc --- allocate asynchronous I/O handle
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_aio_alloc(nng_aio **aiop, void (*callb)(void *), void *arg);
+```
+
+## DESCRIPTION
+
+The `nng_aio_alloc()` function allocates a handle for {{i:asynchronous I/O}}
+operations, and stores a pointer to it in the location referenced by _aiop_.
+The handle is initialized with a completion {{i:callback}} of _callb_,
+which will be executed when an associated asynchronous operation finishes.
+It will be called with the argument _arg_.
+
+> [!IMPORTANT]
+> The callback _callb_ must not perform any blocking operations, and
+> must complete its execution quickly. If _callb_ does block, this can
+> lead ultimately to an apparent "hang" or deadlock in the application.
+> This also means you should avoid operations such as allocating new objects,
+> which also means opening or closing sockets, dialers, and so forth.
+
+> [!TIP]
+> If more complex or blocking work needs to be performed by _callb_, a separate
+> thread can be used, along with a [condition variable](nng_cv_alloc.md)
+> which can be signaled by the callback.
+
+Asynchronous I/O operations all take an [`nng_aio`](nng_aio.md)
+handle such as allocated by this function.
+Such operations are usually started by a function that returns immediately.
+The operation is then run asynchronously, and completes sometime later.
+When that operation is complete, the callback supplied here is called,
+and that callback is able to determine the result of the operation using
+[`nng_aio_result()`](nng_aio_result.md), [`nng_aio_count()`](nng_aio_count.md),
+and [`nng_aio_get_output()`](nng_aio_get_output.md).
+
+It is possible to wait synchronously for an otherwise asynchronous operation
+by using the function [`nng_aio_wait()`](nng_aio_wait.md).
+In that case, it is permissible for _callb_ and _arg_ to both be `NULL`.
+Note that if these are `NULL`, then it will not be possible to determine when the
+operation is complete except by calling the aforementioned
+[`nng_aio_wait()`](nng_aio_wait.md).
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ENOMEM`: Insufficient free memory to perform the operation.
+
+## SEE ALSO
+
+[nng_aio_abort()](nng_aio_abort.md),
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_count()](nng_aio_count.md),
+[nng_aio_free()](nng_aio_free.md),
+[nng_aio_get_input()](nng_aio_get_input.md),
+[nng_aio_get_msg()](nng_aio_get_msg.md),
+[nng_aio_get_output()](nng_aio_get_output.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio_set_input()](nng_aio_set_input.md),
+[nng_aio_set_iov()](nng_aio_set_iov.md),
+[nng_aio_set_msg()](nng_aio_set_msg.md),
+[nng_aio_set_timeout()](nng_aio_set_timeout.md),
+[nng_aio_stop()](nng_aio_stop.md),
+[nng_aio_wait()](nng_aio_wait.md),
+[nng_strerror()](nng_strerror.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_begin.md b/docs/reference/src/api/nng_aio_begin.md
new file mode 100644
index 00000000..da817091
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_begin.md
@@ -0,0 +1,47 @@
+# nng_aio_begin()
+
+## NAME
+
+nng_aio_begin --- begin asynchronous I/O operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+bool nng_aio_begin(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_begin()` function is called by the I/O provider to indicate that
+it is going to process the operation.
+
+The function may return `false`, indicating that the _aio_ has been closed.
+In this case the provider should abandon the operation and do nothing else.
+
+This operation should be called at the start of any I/O operation, and must
+be called not more than once for a given I/O operation on a given _aio_.
+
+Once this function is called, if `true` is returned, then the provider MUST
+guarantee that [`nng_aio_finish()`](nng_aio_finish.md) is called for the _aio_
+exactly once, when the operation is complete or canceled.
+
+> [!TIP]
+> This function is only for I/O providers (those actually performing
+> the operation such as HTTP handler functions or transport providers); ordinary
+> users of the _aio_ should not call this function.
+
+## RETURN VALUES
+
+- `true`: The operation has been started.
+- `false`: The operation cannot be started.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_defer()](nng_aio_defer.md),
+[nng_aio_finish()](nng_aio_finish.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_busy.md b/docs/reference/src/api/nng_aio_busy.md
new file mode 100644
index 00000000..f5a1003b
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_busy.md
@@ -0,0 +1,42 @@
+# nng_aio_busy()
+
+## NAME
+
+nng_aio_busy --- test if asynchronous I/O is busy
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+bool nng_aio_busy(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_busy()` function returns true if the
+_aio_ is currently busy performing an asynchronous I/O
+operation or is executing a completion callback.
+
+If no operation has been started, or the operation has
+been completed or canceled, and any callback has been
+executed, then it returns false.
+
+This is the same test used internally by
+[`nng_aio_wait()`](nng_aio_wait.md).
+
+> [!IMPORTANT]
+> Care should be taken to ensure that the _aio_ object is not
+> freed when using this function. The caller is responsible for
+> coordinating any use of this with any reuse of the _aio_.
+
+## RETURN VALUES
+
+True if the _aio_ is busy, false otherwise.
+
+## SEE ALSO
+
+[nng_aio_abort()](nng_aio_abort.md),
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_wait(3)](nng_aio_wait.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_cancel.md b/docs/reference/src/api/nng_aio_cancel.md
new file mode 100644
index 00000000..1bb8869e
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_cancel.md
@@ -0,0 +1,38 @@
+# nng_aio_cancel()
+
+## NAME
+
+nng_aio_cancel --- cancel asynchronous I/O operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_cancel(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_cancel()` function aborts an operation previously started
+with the handle _aio_.
+If the operation is aborted, then the callback
+for the handle will be called, and the function
+[`nng_aio_result()`](nng_aio_result.md) will return the error `NNG_ECANCELED`.
+
+This function does not wait for the operation to be fully aborted, but
+returns immediately.
+
+If no operation is currently in progress (either because it has already
+finished, or no operation has been started yet), then this function
+has no effect.
+
+This function is the same as calling
+[`nng_aio_abort()`](nng_aio_abort.md) with the error `NNG_ECANCELED`.
+
+## SEE ALSO
+
+[nng_aio_abort()](nng_aio_abort.md),
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_count.md b/docs/reference/src/api/nng_aio_count.md
new file mode 100644
index 00000000..2ce22786
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_count.md
@@ -0,0 +1,46 @@
+# nng_aio_count()
+
+## NAME
+
+nng_aio_count --- return number of bytes transferred
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+size_t nng_aio_count(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_count()` returns the number of bytes transferred by the
+asynchronous operation associated with the handle _aio_.
+
+Some asynchronous operations do not provide meaningful data for this
+function; for example operations that establish connections do not
+transfer user data (they may transfer protocol data though) -- in this case
+this function will generally return zero.
+
+This function is most useful when used with operations that make use of
+of a scatter/gather vector (set by [`nng_aio_set_iov()`](nng_aio_set_iov.md)).
+
+> [!NOTE]
+> The return value from this function is undefined if the operation
+> has not completed yet.
+> Either call this from the handle's completion callback,
+> or after waiting for the operation to complete with
+> [`nng_aio_wait()`](nng_aio_wait.md).
+
+## RETURN VALUES
+
+The number of bytes transferred by the operation.
+
+## SEE ALSO
+
+[.text-left]
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio_set_iov()](nng_aio_set_iov.md),
+[nng_aio_wait()](nng_aio_wait.md),
+[nng_aio](nng_aio)
diff --git a/docs/reference/src/api/nng_aio_defer.md b/docs/reference/src/api/nng_aio_defer.md
new file mode 100644
index 00000000..6b634f42
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_defer.md
@@ -0,0 +1,59 @@
+# nng_aio_defer()
+
+## NAME
+
+nng_aio_defer --- defer asynchronous I/O operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+typedef void (*nng_aio_cancelfn)(nng_aio *aio, void *arg, int err);
+
+void nng_aio_defer(nng_aio *aio, nng_aio_cancelfn fn, void *arg);
+```
+
+## DESCRIPTION
+
+The `nng_aio_defer()` function marks operation associated with _aio_ as
+being deferred for asynchronous completion, registering a cancellation
+function _fn_ and associated argument _arg_.
+This permits the operation to be canceled.
+
+If the _aio_ is canceled, the cancellation routine _fn_ will be called
+with the _aio_, the _arg_ specified by `nng_aio_defer()`, and an error
+value in _err_, which is the reason that the operation is being canceled.
+
+At any given time, the operation may not be cancelable.
+For example it may have already been
+completed, or be in a state where it is no longer possible to unschedule it.
+In this case, the _cancelfn_ should just return without making any changes.
+
+If the cancellation routine successfully canceled the operation, it should
+ensure that [`nng_aio_finish()`](nng_aio_finish.md) is called, with the
+error code specified by _err_.
+
+> [!IMPORTANT]
+> It is mandatory that I/O providers call [`nng_aio_finish()`](nng_aio_finish.md) _*exactly once*_ when they are finished with the operation.
+
+> [!IMPORTANT]
+> Care must be taken to ensure that cancellation and completion of
+> the routine are multi-thread safe. This will usually involve the use
+> of locks or other synchronization primitives.
+
+> [!TIP]
+> For operations that complete synchronously, without any need to be
+> deferred, the provider need not call `nng_aio_defer()`.
+
+> [!TIP]
+> This function is only for I/O providers (those actually performing
+> the operation such as HTTP handler functions or transport providers); ordinary
+> users of the _aio_ should not call this function.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_finish()](nng_aio_finish.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_finish.md b/docs/reference/src/api/nng_aio_finish.md
new file mode 100644
index 00000000..48a52151
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_finish.md
@@ -0,0 +1,41 @@
+# nng_aio_finish()
+
+## NAME
+
+nng_aio_finish --- finish asynchronous I/O operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_finish(nng_aio *aio, int err);
+```
+
+## DESCRIPTION
+
+The `nng_aio_finish()` function marks operation associated with _aio_ as
+complete, with the status _err_.
+This will be the result returned by [`nng_aio_result()`](nng_aio_result.md).
+
+This function causes the callback associated with the _aio_ to called.
+
+> [!IMPORTANT]
+> It is mandatory that operation providers call this function
+> _exactly once_ when they are finished with the operation.
+> After calling this function, the provider _must not_ perform any
+> further accesses to the _aio_.
+
+> [!TIP]
+> This function is only for I/O providers (those actually performing
+> the operation such as HTTP handler functions or transport providers); ordinary
+> users of the _aio_ should not have any need for this function.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_begin()](nng_aio_begin.md),
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_defer()](nng_aio_defer.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_free.md b/docs/reference/src/api/nng_aio_free.md
new file mode 100644
index 00000000..49019439
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_free.md
@@ -0,0 +1,35 @@
+# nng_aio_free(3)
+
+## NAME
+
+nng_aio_free --- free asynchronous I/O handle
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_free(nng_aio *aio);
+void nng_aio_reap(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_free()` function frees an allocated asynchronous I/O handle.
+If any operation is in progress, the operation is canceled, and the
+caller is blocked until the operation is completely canceled, to ensure
+that it is safe to deallocate the handle and any associated resources.
+(This is done by implicitly calling [`nng_aio_stop()`](nng_aio_stop.md).)
+
+The `nng_aio_reap()` function is the same as `nng_aio_free()`, but does
+its work in a background thread.
+This can be useful to discard the _aio_ object from within the callback for the _aio_.
+
+> [!IMPORTANT]
+> Once either of these functions are called, the _aio_ object is invalid and must not be used again.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_stop()](nng_aio_stop.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_get_input.md b/docs/reference/src/api/nng_aio_get_input.md
new file mode 100644
index 00000000..192c82d3
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_get_input.md
@@ -0,0 +1,35 @@
+# nng_aio_get_input(3)
+
+## NAME
+
+nng_aio_get_input --- return input parameter
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void *nng_aio_get_input(nng_aio *aio, unsigned int index);
+```
+
+## DESCRIPTION
+
+The `nng_aio_get_input()` function returns the value of the input parameter
+previously set at _index_ on _aio_ with the
+[`nng_aio_set_input()`](nng_aio_set_input.md) function.
+
+The valid values of _index_ range from zero (0) to three (3), as no operation
+currently defined can accept more than four parameters.
+If the index supplied is outside of this range,
+or if the input parameter was not previously set, then `NULL` is returned.
+
+## RETURN VALUES
+
+Value previously set, or `NULL`.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_get_output()](nng_aio_get_output.md),
+[nng_aio_set_input()](nng_aio_set_input.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_get_msg.md b/docs/reference/src/api/nng_aio_get_msg.md
new file mode 100644
index 00000000..70e18be9
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_get_msg.md
@@ -0,0 +1,31 @@
+# nng_aio_get_msg()
+
+## NAME
+
+nng_aio_get_msg --- get message from asynchronous receive
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+nng_msg *nng_aio_get_msg(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_get_msg()` function gets any message stored in _aio_ as
+either a result of a successful receive
+(see [`nng_recv_aio()`](nng_recv_aio.md))
+or that was previously stored with
+[`nng_aio_set_msg()`](nng_aio_set_msg.md).
+
+> [!IMPORTANT]
+> The _aio_ must not have an operation in progress.
+
+## SEE ALSO
+
+[nng_aio_set_msg()](nng_aio_set_msg.md),
+[nng_recv_aio()](nng_recv_aio.md),
+[nng_aio](nng_aio.md),
+[nng_msg](nng_msg.md)
diff --git a/docs/reference/src/api/nng_aio_get_output.md b/docs/reference/src/api/nng_aio_get_output.md
new file mode 100644
index 00000000..8f0a10a4
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_get_output.md
@@ -0,0 +1,41 @@
+# nng_aio_get_output()
+
+## NAME
+
+nng_aio_get_output --- return output result
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void *nng_aio_get_output(nng_aio *aio, unsigned int index);
+```
+
+## DESCRIPTION
+
+The `nng_aio_get_output()` function returns the output result at _index_
+resulting from the asynchronous operation associated with _aio_.
+
+The type and semantics of output parameters are determined by specific
+operations.
+
+> [!NOTE]
+> If the _index_ does not correspond to a defined output for the operation,
+> or the operation did not succeed, then the return value will be `NULL`.
+
+> [!IMPORTANT]
+> It is an error to call this function while the _aio_ is currently
+> in use by an active asynchronous operation, or if no operation has been
+> performed using the _aio_ yet.
+
+## RETURN VALUES
+
+The _index_&zwj;th output from the operation, or `NULL`.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_set_output()](nng_aio_set_output.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio](nng_aio.md),
diff --git a/docs/reference/src/api/nng_aio_result.md b/docs/reference/src/api/nng_aio_result.md
new file mode 100644
index 00000000..fe6688fd
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_result.md
@@ -0,0 +1,46 @@
+# nng_aio_result()
+
+## NAME
+
+nng_aio_result --- return result of asynchronous operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_aio_result(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_result()` returns the result of the operation associated
+with the handle _aio_.
+If the operation was successful, then 0 is returned.
+Otherwise a non-zero error code is returned.
+
+NOTE: The return value from this function is undefined if the operation
+has not completed yet.
+Either call this from the handle's completion
+callback, or after waiting for the operation to complete with
+[`nng_aio_wait()`](nng_aio_wait.md).
+
+## RETURN VALUES
+
+The result of the operation, either zero on success, or an error
+number on failure.
+
+## ERRORS
+
+- `NNG_ETIMEDOUT`: The operation timed out.
+- `NNG_ECANCELED`: The operation was canceled.
+
+Various other return values are possible depending on the operation.
+
+## SEE ALSO
+
+[nng_aio_abort()](nng_aio_abort.md),
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_wait()](nng_aio_wait.md),
+[nng_strerror()](nng_strerror.md),
+[nng_aio](nng_aio.md),
diff --git a/docs/reference/src/api/nng_aio_set_input.md b/docs/reference/src/api/nng_aio_set_input.md
new file mode 100644
index 00000000..739489ad
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_set_input.md
@@ -0,0 +1,43 @@
+# nng_aio_set_input()
+
+## NAME
+
+nng_aio_set_input --- set input parameter
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_set_input(nng_aio *aio, unsigned int index, void *param);
+```
+
+## DESCRIPTION
+
+The `nng_aio_set_input()` function sets the input parameter at _index_
+to _param_ for the asynchronous operation associated with _aio_.
+
+The type and semantics of input parameters are determined by specific
+operations; the caller must supply appropriate inputs for the operation
+to be performed.
+
+The valid values of _index_ range from zero (0) to three (3), as no operation
+currently defined can accept more than four parameters.
+(This limit could increase in the future.)
+
+> [!NOTE]
+> If the _index_ does not correspond to a defined input for the operation,
+> then this function will have no effect.
+
+> [!IMPORTANT]
+> It is an error to call this function while the _aio_ is currently
+> in use by an active asynchronous operation.
+
+An input parameter set with this function may be retrieved later with
+the [`nng_aio_get_input()`](nng_aio_get_input.md) function.
+
+## SEE ALSO
+
+[nng_aio_alloc()](nng_aio_alloc.md),
+[nng_aio_get_input()](nng_aio_get_input.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_set_iov.md b/docs/reference/src/api/nng_aio_set_iov.md
new file mode 100644
index 00000000..8b33b9f1
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_set_iov.md
@@ -0,0 +1,45 @@
+# nng_aio_set_iov
+
+## NAME
+
+nng_aio_set_iov --- set scatter/gather vector
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_aio_set_iov(nng_aio *aio, unsigned int niov, nng_iov *iov);
+```
+
+## DESCRIPTION
+
+The `nng_aio_set_iov()` function sets a {{i:scatter/gather}} vector _iov_ on the handle _aio_.
+
+The _iov_ is a pointer to an array of _niov_ [`nng_iov`](nng_iov.md)
+structures, which have the following definition:
+
+```c
+typedef struct nng_iov {
+ void * iov_buf;
+ size_t iov_len;
+};
+```
+
+The _iov_ is copied into storage in the _aio_ itself, so that callers may use stack allocated `nng_iov` structures.
+The values pointed to by the `iov_buf` members are _not_ copied by this function though.
+
+A maximum of four (4) `nng_iov` members may be supplied.
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_EINVAL`: Value of specified _niov_ is too large.
+
+## SEE ALSO
+
+[nng_aio](nng_aio),
+[nng_iov](nng_iov)
diff --git a/docs/reference/src/api/nng_aio_set_msg.md b/docs/reference/src/api/nng_aio_set_msg.md
new file mode 100644
index 00000000..eb0bd4ed
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_set_msg.md
@@ -0,0 +1,29 @@
+# nng_aio_set_msg()
+
+## NAME
+
+nng_aio_set_msg --- set message for asynchronous send
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_set_msg(nng_aio *aio, nng_msg *msg);
+```
+
+## DESCRIPTION
+
+The `nng_aio_set_msg()` function sets the message that will be used
+for an asynchronous send operation (see
+[`nng_send_aio()`](nng_send_aio.md)).
+
+> [!IMPORTANT]
+> The _aio_ must not have an operation in progress.
+
+## SEE ALSO
+
+[nng_aio_get_msg()](nng_aio_get_msg.md),
+[nng_send_aio()](nng_send_aio.md),
+[nng_aio](nng_aio.md),
+[nng_msg](nng_msg.md)
diff --git a/docs/reference/src/api/nng_aio_set_output.md b/docs/reference/src/api/nng_aio_set_output.md
new file mode 100644
index 00000000..c3c86440
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_set_output.md
@@ -0,0 +1,37 @@
+# nng_aio_set_output()
+
+## NAME
+
+nng_aio_set_output --- set output result
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_set_output(nng_aio *aio, unsigned int index, void *result);
+```
+
+## DESCRIPTION
+
+The `nng_aio_set_output()` function sets the output result at _index_
+to _result_ for the asynchronous operation associated with _aio_.
+
+The type and semantics of output results are determined by specific
+operations; the operation must supply appropriate output results when
+the operation completes successfully.
+
+The valid values of _index_ range from zero (0) to three (3), as no operation
+currently defined can return more than four results.
+
+> [!NOTE]
+> Note that attempts to set results with an _index_ greater than
+> three (3) will be ignored.
+
+An output result set with this function may be retrieved later with
+the [`nng_aio_get_output()`](nng_aio_get_output.md) function.
+
+## SEE ALSO
+
+[nng_aio_get_output(3)](nng_aio_get_output.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_aio_set_timeout.md b/docs/reference/src/api/nng_aio_set_timeout.md
new file mode 100644
index 00000000..e8643570
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_set_timeout.md
@@ -0,0 +1,54 @@
+# nng_aio_set_timeout()
+
+## NAME
+
+nng_aio_set_timeout --- set asynchronous I/O timeout
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+typedef int nng_duration;
+void nng_aio_set_timeout(nng_aio *aio, nng_duration timeout);
+
+typedef uint64_t nng_time;
+void nng_aio_set_expire(nng_aio *aio, nng_time expiration);
+```
+
+## DESCRIPTION
+
+The `nng_aio_set_timeout()` function sets a {{ii:timeout}}
+for the asynchronous operation associated with _aio_.
+This causes a timer to be started when the operation is actually started.
+If the timer expires before the operation is completed, then it is
+aborted with an error of `NNG_ETIMEDOUT`.
+The _timeout_ is specified as a relative number of milliseconds.
+
+If the timeout is `NNG_DURATION_INFINITE`, then no timeout is used.
+If the timeout is `NNG_DURATION_DEFAULT`, then a "default" or socket-specific
+timeout is used.
+(This is frequently the same as `NNG_DURATION_INFINITE`.)
+
+The `nng_aio_set_expire()` function is similar to `nng_aio_set_timeout()`, but sets
+an absolute expiration time based on the system clock. The _expiration_
+is expressed as a number of milliseconds since some point in the past.
+The [`nng_clock()`](nng_clock.md) function can be used to determine
+the current value of the clock.
+
+> [!TIP]
+> As most operations involve some context switching, it is usually a good
+> idea to allow at least a few tens of milliseconds before timing them out --
+> a too small timeout might not allow the operation to properly begin before
+> giving up!
+
+The value of _timeout_ set for the _aio_ is persistent, so that if the
+handle is reused for future operations, it will have the same relative
+or absolute timeout.
+
+## SEE ALSO
+
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_result()](nng_aio_result.md),
+[nng_aio](nng_aio),
+[nng_duration](nng_duration)
diff --git a/docs/reference/src/api/nng_aio_stop.md b/docs/reference/src/api/nng_aio_stop.md
new file mode 100644
index 00000000..4cfe41b6
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_stop.md
@@ -0,0 +1,40 @@
+# nng_aio_stop()
+
+## NAME
+
+nng_aio_stop - stop asynchronous I/O operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_stop(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_stop()` function stops the asynchronous I/O operation
+associated with _aio_ by aborting with `NNG_ECANCELED`, and then waits
+for it to complete or to be completely aborted, and for the
+callback associated with the _aio_ to have completed executing.
+
+Further calls to
+[`nng_aio_begin()`](nng_aio_begin.md) using this _aio_ will return `false`.
+
+It is safe to call this for an _aio_, even when no operation is currently
+pending for it.
+
+> [!TIP]
+> When multiple asynchronous I/O handles are in use and need to be
+> shut down, it is safest to stop all of them, before deallocating any of
+> them with [`nng_aio_free()`](nng_aio_free.md), particularly if the callbacks
+> might attempt to reschedule additional operations.
+
+## SEE ALSO
+
+[nng_aio_cancel()](nng_aio_cancel.md),
+[nng_aio_free()](nng_aio_free.md),
+[nng_aio_begin()](nng_aio_begin.md),
+[nng_aio_wait()](nng_aio-wait.md),
+[nng_aio](nng_aio.md),
diff --git a/docs/reference/src/api/nng_aio_wait.md b/docs/reference/src/api/nng_aio_wait.md
new file mode 100644
index 00000000..2cddcb29
--- /dev/null
+++ b/docs/reference/src/api/nng_aio_wait.md
@@ -0,0 +1,34 @@
+# nng_aio_wait()
+
+## NAME
+
+nng_aio_wait --- wait for asynchronous I/O operation
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_aio_wait(nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_aio_wait()` function waits for an asynchronous I/O operation
+to complete.
+If the operation has not been started, or has already
+completed, then it returns immediately.
+
+If a callback was set with _aio_ when it was allocated, then this
+function will not be called until the callback has completed.
+
+> [!IMPORTANT]
+> This function should never be called from a function that itself
+> is a callback of an [`nng_aio`](nng_aio.md), either this one or any other.
+> Doing so may result in a deadlock.
+
+## SEE ALSO
+
+[nng_aio_abort()](nng_aio_abort.md),
+[nng_aio_busy()](nng_aio_busy.md),
+[nng_aio](nng_aio.md)
diff --git a/docs/reference/src/api/nng_alloc.md b/docs/reference/src/api/nng_alloc.md
new file mode 100644
index 00000000..6cc4b21f
--- /dev/null
+++ b/docs/reference/src/api/nng_alloc.md
@@ -0,0 +1,44 @@
+# nng_alloc()
+
+## NAME
+
+nng_alloc --- allocate memory
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void *nng_alloc(size_t size);
+```
+
+## DESCRIPTION
+
+The `nng_alloc()` function allocates a contiguous memory region of
+at least _size_ bytes.
+The memory will be 64-bit aligned.
+
+The returned memory can be used to hold message buffers, in which
+case it can be directly passed to [`nng_send()`](nng_send.md) using
+the flag `NNG_FLAG_ALLOC`. Alternatively, it can be freed when no
+longer needed using [`nng_free()`](nng_free.md).
+
+> [!IMPORTANT]
+> Do not use the system `free()` function (or the C++ `delete` operator) to release this memory.
+> On some configurations this may work, but on others it will lead to a crash or
+> other unpredictable behavior.
+
+## RETURN VALUES
+
+This function returns a pointer to the allocated memory on success,
+and `NULL` otherwise.
+
+## ERRORS
+
+No errors are returned, but if memory cannot be allocated then `NULL`
+is returned.
+
+## SEE ALSO
+
+[nng_free()](nng_free.md),
+[nng_send()](nng_send.md)
diff --git a/docs/reference/src/api/nng_bus_open.md b/docs/reference/src/api/nng_bus_open.md
new file mode 100644
index 00000000..a579acfb
--- /dev/null
+++ b/docs/reference/src/api/nng_bus_open.md
@@ -0,0 +1,40 @@
+# nng_bus_open()
+
+## NAME
+
+nng_bus_open --- create bus socket
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/protocol/bus0/bus.h>
+
+int nng_bus0_open(nng_socket *s);
+
+int nng_bus0_open_raw(nng_socket *s);
+```
+
+## DESCRIPTION
+
+The `nng_bus0_open()` function creates a [_BUS_](../protocols/bus.md) version 0
+[socket](nng_socket.md) and returns it at the location pointed to by _s_.
+
+The `nng_bus0_open_raw()` function creates a [_BUS_](../protocols/bus.md) version 0
+[socket](nng_socket.md) in
+[raw](../overview/raw.md) mode, and returns it at the location pointed to by _s_.
+
+## RETURN VALUES
+
+These functions return 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ENOMEM`: Insufficient memory is available.
+- `NNG_ENOTSUP`: The protocol is not supported.
+
+## SEE ALSO
+
+[nng_socket()](nng_socket.md),
+[BUS protocol](../protocols/bus.md),
+[RAW mode](../overview/raw.md)
diff --git a/docs/reference/src/api/nng_clock.md b/docs/reference/src/api/nng_clock.md
new file mode 100644
index 00000000..37be0d0c
--- /dev/null
+++ b/docs/reference/src/api/nng_clock.md
@@ -0,0 +1,43 @@
+# nng_clock()
+
+## NAME
+
+nng_clock - get time
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+typedef uint64_t nng_time;
+
+nng_time nng_clock(void);
+```
+
+## DESCRIPTION
+
+The `nng_clock()` function returns the number of elapsed milliseconds since some
+arbitrary time in the past.
+The resolution of the clock depends on the underlying timing facilities
+of the system.
+This function may be used for timing, but applications should not expect
+very fine-grained values.
+
+> [!NOTE]
+> The reference time will be the same for a given program,
+> but different programs may have different references.
+
+This function is intended to help with setting appropriate
+timeouts using [`nng_cv_until()`](nng_cv_until.md).
+
+## RETURN VALUES
+
+Milliseconds since reference time.
+
+## SEE ALSO
+
+[nng_sleep_aio()](nng_sleep_aio.md),
+[nng_cv_until()](nng_cv_until.md),
+[nng_msleep()](nng_msleep.md),
+[nng_duration](nng_duration.md)
diff --git a/docs/reference/src/api/nng_close.md b/docs/reference/src/api/nng_close.md
new file mode 100644
index 00000000..486cfe2c
--- /dev/null
+++ b/docs/reference/src/api/nng_close.md
@@ -0,0 +1,45 @@
+# nng_close(3)
+
+## NAME
+
+nng_close --- close socket
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_close(nng_socket s);
+```
+
+## DESCRIPTION
+
+The `nng_close()` function closes the supplied socket, _s_.
+Messages that have been submitted for sending may be flushed or delivered,
+depending upon the transport.
+
+Further attempts to use the socket after this call returns will result
+in `NNG_ECLOSED`.
+Threads waiting for operations on the socket when this
+call is executed may also return with an `NNG_ECLOSED` result.
+
+> [!NOTE]
+> Closing the socket while data is in transmission will likely lead to loss
+> of that data.
+> There is no automatic linger or flush to ensure that the socket send buffers
+> have completely transmitted.
+> It is recommended to wait a brief period after calling
+> [`nng_send()`](nng_send.md) or similar functions, before calling this
+> function.
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ECLOSED`: The socket _s_ is already closed or was never opened.
+
+## SEE ALSO
+
+[nng_socket](nng_socket.md)
diff --git a/docs/reference/src/api/nng_ctx.md b/docs/reference/src/api/nng_ctx.md
new file mode 100644
index 00000000..9f963e9a
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx.md
@@ -0,0 +1,160 @@
+# nng_ctx
+
+## NAME
+
+nng_ctx --- protocol context
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+typedef struct nng_ctx_s nng_ctx
+```
+
+## DESCRIPTION
+
+An `nng_ctx`{{hi:context}} is a handle to an underlying context object,
+which keeps the protocol state for some stateful protocols.
+The purpose of a separate context object is to permit applications to
+share a single [socket](nng_socket.md), with its various underlying
+[dialers](nng_dialer.md),
+[listeners](nng_listener.md),
+[pipes](nng_pipe.md),
+while still benefiting from separate state tracking.
+
+For example, a [_REQ_](../protocols/req.md) context will contain the request ID
+of any sent request, a timer to retry the request on failure, and so forth.
+A separate context on the same socket can have similar data, but corresponding
+to a completely different request.
+
+> [!NOTE]
+> The `nng_ctx` structure is always passed by value (both
+> for input parameters and return values), and should be treated opaquely.
+> Passing structures this way gives the compiler a chance to perform
+> accurate type checks in functions passing values of this type.
+
+All contexts share the same socket, and so some options, as well as the
+underlying transport details, will be common to all contexts on that socket.
+
+Protocols that make use of contexts will also have a default context
+that is used when the socket global operations are used.
+Operations using the global context will generally not interfere with
+any other contexts, except that certain socket options may affect socket
+global behavior.
+
+{{hi:concurrent}}{{hi:raw mode}}
+Historically, applications wanting to use a stateful protocol concurrently
+would have to resort to [raw mode](../overview/raw.md) sockets, which bypasses
+much of the various protocol handling, leaving it to up to the application
+to do so.
+Contexts make it possible to still benefit from advanced protocol handling,
+including timeouts, retries, and matching requests to responses, while doing so
+concurrently.
+
+> [!TIP]
+> Contexts are an excellent mechanism to use when building concurrent
+> applications, and should be used in lieu of
+> [raw mode](../overview/raw.md) sockets when possible.
+
+## Caveats
+
+Not every protocol supports separate contexts.
+See the protocol-specific documentation for further details about whether
+contexts are supported, and details about what options are supported for
+contexts.
+
+Use of file descriptor polling (with descriptors obtained using the
+[`NNG_OPT_RECVFD`](nng_options.md#NNG_OPT_RECVFD) or
+[`NNG_OPT_SENDFD`](nng_options.md#NNG_OPT_SENDFD) options) while contexts
+are in use on the same socket is not supported, and may lead to unpredictable
+behavior. These asynchronous methods should not be mixed on the same socket.
+
+[Raw mode](../overview/raw.md) sockets do not support contexts, since
+there is generally no state tracked for them, and thus contexts make no sense.
+
+## Initialization
+
+A context may be initialized using the macro `NNG_CTX_INITIALIZER`
+before it is opened, to prevent confusion with valid open contexts.
+
+## Example
+
+The following program fragment demonstrates the use of contexts to implement
+a concurrent [_REP_](../protocols/rep.md) service that simply echos messages back
+to the sender.
+
+```c
+struct echo_context {
+ nng_ctx ctx;
+ nng_aio *aio;
+ enum { INIT, RECV, SEND } state;
+};
+
+void
+echo(void *arg)
+{
+ struct echo_context *ec = arg;
+
+ switch (ec->state) {
+ case INIT:
+ ec->state = RECV;
+ nng_ctx_recv(ec->ctx, ec->aio);
+ return;
+ case RECV:
+ if (nng_aio_result(ec->aio) != 0) {
+ // ... handle error
+ }
+ // We reuse the message on the ec->aio
+ ec->state = SEND;
+ nng_ctx_send(ec->ctx, ec->aio);
+ return;
+ case SEND:
+ if (nng_aio_result(ec->aio) != 0) {
+ // ... handle error
+ }
+ ec->state = RECV;
+ nng_ctx_recv(ec->ctx, ec->aio);
+ return;
+ }
+}
+```
+
+Given the above fragment, the following example shows setting up the
+service. It assumes that the [socket](nng_socket.md) has already been
+created and any transports set up as well with functions such as
+[`nng_dial()`](nng_dial.md) or [`nng_listen()`](nng_listen.md).
+
+```c
+#define CONCURRENCY 1024
+
+echo_context ecs[CONCURRENCY];
+
+void
+start_echo_service(nng_socket rep_socket)
+{
+ for (int i = 0; i < CONCURRENCY; i++) {
+ // error checks elided for clarity
+ nng_ctx_open(ec[i].ctx, rep_socket)
+ nng_aio_alloc(ec[i].aio, echo, &e[i]);
+ ec[i].state = INIT;
+ echo(&ec[i]); // start it running
+ }
+}
+```
+
+## SEE ALSO
+
+[nng_ctx_close()](nng_ctx_close.md),
+[nng_ctx_open()](nng_ctx_open.md),
+[nng_ctx_get()](nng_ctx_get.md),
+[nng_ctx_id()](nng_ctx_id.md)
+[nng_ctx_recv()](nng_ctx_recv.md),
+[nng_ctx_recvmsg()](nng_ctx_recvmsg.md),
+[nng_ctx_send()](nng_ctx_send.md),
+[nng_ctx_sendmsg()](nng_ctx_sendmsg.md),
+[nng_ctx_set()](nng_ctx_set.md),
+[nng_dialer](nng_dialer.md),
+[nng_listener](nng_listener.md),
+[nng_socket](nng_socket.md),
+[nng_options](nng_options.md)
diff --git a/docs/reference/src/api/nng_ctx_close.md b/docs/reference/src/api/nng_ctx_close.md
new file mode 100644
index 00000000..443df76e
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_close.md
@@ -0,0 +1,42 @@
+# nng_ctx_close()
+
+## NAME
+
+nng_ctx_close --- close context
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_close(nng_ctx ctx);
+```
+
+## DESCRIPTION
+
+The `nng_ctx_close()` function closes the context _ctx_.
+Messages that have been submitted for sending may be flushed or delivered,
+depending upon the transport.
+
+Further attempts to use the context after this call returns will result
+in `NNG_ECLOSED`.
+Threads waiting for operations on the context when this
+call is executed may also return with an `NNG_ECLOSED` result.
+
+> [!NOTE]
+> Closing the socket associated with _ctx_
+> (using [`nng_close()`](nng_close.md)) also closes this context.
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ECLOSED`: The context _ctx_ is already closed or was never opened.
+
+## SEE ALSO
+
+[nng_close()](nng_close.md),
+[nng_ctx_open()](nng_ctx_open.md),
+[nng_ctx](nng_ctx.md),
diff --git a/docs/reference/src/api/nng_ctx_get.md b/docs/reference/src/api/nng_ctx_get.md
new file mode 100644
index 00000000..0c2d131c
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_get.md
@@ -0,0 +1,113 @@
+# nng_ctx_get()
+
+## NAME
+
+nng_ctx_get --- get context option
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_get(nng_ctx ctx, const char *opt, void *val, size_t *valszp);
+
+int nng_ctx_get_bool(nng_ctx ctx, const char *opt, bool *bvalp);
+
+int nng_ctx_get_int(nng_ctx ctx, const char *opt, int *ivalp);
+
+int nng_ctx_get_ms(nng_ctx ctx, const char *opt, nng_duration *durp);
+
+int nng_ctx_get_size(nng_ctx ctx, const char *opt, size_t *zp);
+
+int nng_ctx_get_string(nng_ctx ctx, const char *opt, char **strp);
+
+int nng_ctx_get_uint64(nng_ctx ctx, const char *opt, uint64_t *u64p);
+```
+
+## DESCRIPTION
+
+{{hi:options, context}}
+The `nng_ctx_get()` functions are used to retrieve option values for
+the [context](nng_ctx.md) _ctx_.
+The actual options that may be retrieved in this way vary.
+A number of them are documented in [nng_options](nng_options.md).
+
+> [!NOTE]
+> Context options are protocol specific.
+> The details will be documented with the protocol.
+
+### Forms
+
+In all of these forms, the option _opt_ is retrieved from the context _ctx_.
+The forms vary based on the type of the option they take.
+
+The details of the type, size, and semantics of the option will depend
+on the actual option, and will be documented with the option itself.
+
+- `nng_ctx_get()`:\
+ This function is untyped and can be used to retrieve the value of any option.
+ The caller must store a pointer to a buffer to receive the value in _val_,
+ and the size of the buffer shall be stored at the location referenced by
+ _valszp_.\
+ \
+ When the function returns, the actual size of the data copied (or that
+ would have been copied if sufficient space were present) is stored at
+ the location referenced by _valszp_.
+ If the caller's buffer is not large enough to hold the entire object,
+ then the copy is truncated.
+ Therefore the caller should check for truncation by verifying that the
+ returned size in _valszp_ does not exceed the original buffer size.\
+ \
+ It is acceptable to pass `NULL` for _val_ if the value in _valszp_ is zero.
+ This can be used to determine the size of the buffer needed to receive
+ the object.
+
+- `nng_ctx_get_bool()`:\
+ This function is for options which take a Boolean (`bool`).
+ The value will be stored at _ivalp_.
+
+- `nng_ctx_get_int()`:\
+ This function is for options which take an integer (`int`).
+ The value will be stored at _ivalp_.
+
+- `nng_ctx_get_ms()`:\
+ This function is used to retrieve time [durations](nng_duration.md)
+ (such as timeouts), stored in _durp_ as a number of milliseconds.
+ (The special value {{i:`NNG_DURATION_INFINITE`}} means an infinite amount of time, and
+ the special value {{i:`NNG_DURATION_DEFAULT`}} means a context-specific default.)
+- `nng_ctx_get_size()`:\
+ This function is used to retrieve a size into the pointer _zp_,
+ typically for buffer sizes, message maximum sizes, and similar options.
+- `nng_ctx_get_string()`:\
+ This function is used to retrieve a string into _strp_.
+ This string is created from the source using [`nng_strdup()`](nng_strdup.md)
+ and consequently must be freed by the caller using
+ [`nng_strfree()`](nng_strfree.md) when it is no longer needed.
+
+- `nng_ctx_get_uint64()`:\
+ This function is used to retrieve a 64-bit unsigned value into the value
+ referenced by _u64p_.
+ This is typically used for options related to identifiers, network
+ numbers, and similar.
+
+## RETURN VALUES
+
+These functions return 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_EBADTYPE`: Incorrect type for option.
+- `NNG_ECLOSED`: Parameter _s_ does not refer to an open socket.
+- `NNG_EINVAL`: Size of destination _val_ too small for object.
+- `NNG_ENOMEM`: Insufficient memory exists.
+- `NNG_ENOTSUP`: The option _opt_ is not supported.
+- `NNG_EWRITEONLY`: The option _opt_ is write-only.
+
+## SEE ALSO
+
+[nng_ctx_set()](nng_ctx_set.md),
+[nng_strdup()](nng_strdup.md),
+[nng_strfree()](nng_strfree.md),
+[nng_duration](nng_duration.md),
+[nng_ctx](nng_ctx.md),
+[nng_options](nng_options.md)
diff --git a/docs/reference/src/api/nng_ctx_getopt.md b/docs/reference/src/api/nng_ctx_getopt.md
new file mode 100644
index 00000000..ddd6f791
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_getopt.md
@@ -0,0 +1,117 @@
+# nng_ctx_getopt()
+
+## NAME
+
+nng_ctx_getopt --- get context option (deprecated)
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_getopt(nng_ctx ctx, const char *opt, void *val, size_t *valszp);
+
+int nng_ctx_getopt_bool(nng_ctx ctx, const char *opt, bool *bvalp);
+
+int nng_ctx_getopt_int(nng_ctx ctx, const char *opt, int *ivalp);
+
+int nng_ctx_getopt_ms(nng_ctx ctx, const char *opt, nng_duration *durp);
+
+int nng_ctx_getopt_size(nng_ctx ctx, const char *opt, size_t *zp);
+
+int nng_ctx_getopt_string(nng_ctx ctx, const char *opt, char **strp);
+
+int nng_ctx_getopt_uint64(nng_ctx ctx, const char *opt, uint64_t *u64p);
+```
+
+## DESCRIPTION
+
+> [!IMPORTANT]
+> These functions are deprecated. Please see [nng_ctx_get](nng_ctx_get.md).
+> They may not be present if the library was built with `NNG_ELIDE_DEPRECATED`.
+> They may also be removed entirely in a future version of _NNG_.
+
+The `nng_ctx_getopt()` functions are used to retrieve option values for
+the [context](nng_ctx.md) _ctx_.
+The actual options that may be retrieved in this way vary.
+
+> [!NOTE]
+> Context options are protocol specific.
+> The details will be documented with the protocol.
+
+### Forms
+
+In all of these forms, the option _opt_ is retrieved from the context _ctx_.
+The forms vary based on the type of the option they take.
+
+The details of the type, size, and semantics of the option will depend
+on the actual option, and will be documented with the option itself.
+
+- `nng_ctx_getopt()`:\
+ This function is untyped and can be used to retrieve the value of any option.
+ The caller must store a pointer to a buffer to receive the value in _val_,
+ and the size of the buffer shall be stored at the location referenced by
+ _valszp_.\
+ \
+ When the function returns, the actual size of the data copied (or that
+ would have been copied if sufficient space were present) is stored at
+ the location referenced by _valszp_.
+ If the caller's buffer is not large enough to hold the entire object,
+ then the copy is truncated.
+ Therefore the caller should check for truncation by verifying that the
+ returned size in _valszp_ does not exceed the original buffer size.\
+ \
+ It is acceptable to pass `NULL` for _val_ if the value in _valszp_ is zero.
+ This can be used to determine the size of the buffer needed to receive
+ the object.
+
+- `nng_ctx_getopt_bool()`:\
+ This function is for options which take a Boolean (`bool`).
+ The value will be stored at _ivalp_.
+
+- `nng_ctx_getopt_int()`:\
+ This function is for options which take an integer (`int`).
+ The value will be stored at _ivalp_.
+
+- `nng_ctx_getopt_ms()`:\
+ This function is used to retrieve time [durations](nng_duration.md)
+ (such as timeouts), stored in _durp_ as a number of milliseconds.
+ (The special value `NNG_DURATION_INFINITE` means an infinite amount of time, and
+ the special value `NNG_DURATION_DEFAULT` means a context-specific default.)
+
+- `nng_ctx_getopt_size()`:\
+ This function is used to retrieve a size into the pointer _zp_,
+ typically for buffer sizes, message maximum sizes, and similar options.
+
+- `nng_ctx_getopt_string()`:\
+ This function is used to retrieve a string into _strp_.
+ This string is created from the source using `nng_strdup()`](nng_strdup.md)
+ and consequently must be freed by the caller using
+ [`nng_strfree()`](nng_strfree.md) when it is no longer needed.
+
+- `nng_ctx_getopt_uint64()`:\
+ This function is used to retrieve a 64-bit unsigned value into the value
+ referenced by _u64p_.
+ This is typically used for options related to identifiers, network
+ numbers, and similar.
+
+## RETURN VALUES
+
+These functions return 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_EBADTYPE`: Incorrect type for option.
+- `NNG_ECLOSED`: Parameter _s_ does not refer to an open socket.
+- `NNG_EINVAL`: Size of destination _val_ too small for object.
+- `NNG_ENOMEM`: Insufficient memory exists.
+- `NNG_ENOTSUP`: The option _opt_ is not supported.
+- `NNG_EWRITEONLY`: The option _opt_ is write-only.
+
+## SEE ALSO
+
+[nng_strdup()](nng_strdup.md),
+[nng_strfree()](nng_strfree.md),
+[nng_duration](nng_duration.md),
+[nng_ctx](nng_ctx.md),
+[nng_options](nng_options.md)
diff --git a/docs/reference/src/api/nng_ctx_id.md b/docs/reference/src/api/nng_ctx_id.md
new file mode 100644
index 00000000..07af4c4b
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_id.md
@@ -0,0 +1,35 @@
+# nng_ctx_id()
+
+## NAME
+
+nng_ctx_id --- return numeric context identifier
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_id(nng_ctx c);
+```
+
+## DESCRIPTION
+
+The `nng_ctx_id()` function returns a positive identifier for the context _c_,
+if it is valid.
+Otherwise it returns `-1`.
+
+> [!NOTE]
+> A context is considered valid if it was ever opened with
+> [`nng_ctx_open()`](nng_ctx_open.md) function.
+> Contexts that are allocated on the stack or statically should be
+> initialized with the macro `NNG_CTX_INITIALIZER` to ensure that
+> they cannot be confused with a valid context before they are opened.
+
+## RETURN VALUES
+
+This function returns the positive value for the context identifier, or
+`-1` if the context is invalid.
+
+## SEE ALSO
+
+[nng_ctx](nng_ctx)
diff --git a/docs/reference/src/api/nng_ctx_open.md b/docs/reference/src/api/nng_ctx_open.md
new file mode 100644
index 00000000..521da916
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_open.md
@@ -0,0 +1,57 @@
+# nng_ctx_open()
+
+## NAME
+
+nng_ctx_open --- create context
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_open(nng_ctx *ctxp, nng_socket s);
+```
+
+## DESCRIPTION
+
+The `nng_ctx_open()` function creates a separate {{i:context}} to be used with
+the socket _s_,
+and returns it at the location pointed by _ctxp_.
+
+> [!NOTE]
+> Not every protocol supports creation of separate contexts.
+
+Contexts allow the independent and concurrent use of stateful operations
+using the same socket.
+For example, two different contexts created on a
+[_REP_](../protocols/rep.md)
+socket can each receive requests, and send replies to them, without any
+regard to or interference with each other.
+
+> [!TIP]
+> Using contexts is an excellent way to write simpler concurrent
+> applications, while retaining the benefits of the protocol-specific
+> advanced processing, avoiding the need to bypass that with
+> {{hi:raw mode}}[raw mode](../overview/raw.md) sockets.
+
+> [!NOTE]
+> Use of contexts with [raw mode](../overview/raw.md) sockets is
+> nonsensical, and not supported.
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ENOMEM`: Insufficient memory is available.
+- `NNG_ENOTSUP`: The protocol does not support separate contexts, or the socket was opened in raw mode.
+
+## SEE ALSO
+
+[nng_ctx_close()](nng_ctx_close.md),
+[nng_ctx_get()](nng_ctx_get.md),
+[nng_ctx_recv()](nng_ctx_recv.md),
+[nng_ctx_send()](nng_ctx_send.md),
+[nng_ctx_set()](nng_ctx_set.md),
+[nng_ctx](nng_ctx.md)
diff --git a/docs/reference/src/api/nng_ctx_recv.md b/docs/reference/src/api/nng_ctx_recv.md
new file mode 100644
index 00000000..d9aaae0f
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_recv.md
@@ -0,0 +1,61 @@
+# nng_ctx_recv()
+
+## NAME
+
+nng_ctx_recv --- receive message using context asynchronously
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_ctx_recv(nng_ctx ctx, nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_ctx_recv()` receives a [message](nng_msg.md) using the
+[context](nng_ctx.md) _s_ asynchronously.
+
+When a message is successfully received by the context, it is
+stored in the _aio_ by an internal call equivalent to
+[`nng_aio_set_msg()`](nng_aio_set_msg.md), then the completion
+callback on the _aio_ is executed.
+In this case, [`nng_aio_result()`](nng_aio_result.md) will
+return zero.
+The callback function is responsible for retrieving the message
+and disposing of it appropriately.
+
+> [!IMPORTANT]
+> Failing to accept and dispose of messages in this
+> case can lead to memory leaks.
+
+If for some reason the asynchronous receive cannot be completed
+successfully (including by being canceled or timing out), then
+the callback will still be executed,
+but [`nng_aio_result()`](nng_aio_result.md) will be non-zero.
+
+> [!TIP]
+> The semantics of what receiving a message means varies from protocol to
+> protocol, so examination of the protocol documentation is encouraged.
+
+## ERRORS
+
+The following errors may be set on the _aio_, if the operation fails.
+
+- `NNG_ECANCELED`: The operation was aborted.
+- `NNG_ECLOSED`: The context _ctx_ is not open.
+- `NNG_ENOMEM`: Insufficient memory is available.
+- `NNG_ENOTSUP`: The protocol for context _ctx_ does not support receiving.
+- `NNG_ESTATE`: The context _ctx_ cannot receive data in this state.
+- `NNG_ETIMEDOUT`: The receive timeout expired.
+
+## SEE ALSO
+
+[nng_aio_get_msg()](nng_aio_get_msg.md),
+[nng_aio_set_msg()](nng_aio_set_msg.md),
+[nng_msg_alloc()](nng_msg_alloc.md),
+[nng_msg_free()](nng_msg_free.md),
+[nng_aio](nng_aio.md),
+[nng_ctx](nng_ctx.md),
+[nng_msg](nng_msg.md)
diff --git a/docs/reference/src/api/nng_ctx_recvmsg.md b/docs/reference/src/api/nng_ctx_recvmsg.md
new file mode 100644
index 00000000..84368f76
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_recvmsg.md
@@ -0,0 +1,51 @@
+# nng_ctx_recvmsg()
+
+## NAME
+
+nng_ctx_recvmsg --- receive message using socket
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_recvmsg(nng_ctx ctx, nng_msg **msgp, int flags);
+```
+
+## DESCRIPTION
+
+The `nng_ctx_recvmsg()` receives a message on context _ctx_, storing the
+received message at the location pointed to by _msgp_.
+
+The _flags_ may contain the following value:
+
+- `NNG_FLAG_NONBLOCK`:\
+ The function returns immediately, even if no message is available.
+ Without this flag, the function will wait until a message is receivable
+ on the context _ctx_, or any configured timer expires.
+
+> [!TIP]
+> The semantics of what receiving a message means vary from protocol to
+> protocol, so examination of the protocol documentation is encouraged.
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_EAGAIN`: The operation would block, but `NNG_FLAG_NONBLOCK` was specified.
+- `NNG_ECLOSED`: The context or socket is not open.
+- `NNG_EINVAL`: An invalid set of _flags_ was specified.
+- `NNG_ENOMEM`: Insufficient memory is available.
+- `NNG_ENOTSUP`: The protocol does not support receiving.
+- `NNG_ESTATE`: The context cannot receive data in this state.
+- `NNG_ETIMEDOUT`: The operation timed out.
+
+## SEE ALSO
+
+[nng_msg_free()](nng_msg_free.md),
+[nng_ctx_open()](nng_ctx_open.md),
+[nng_ctx_recv()](nng_ctx_recv.md),
+[nng_ctx_sendmsg()](nng_ctx_sendmsg.md),
+[nng_ctx](nng_ctx)
diff --git a/docs/reference/src/api/nng_ctx_send.md b/docs/reference/src/api/nng_ctx_send.md
new file mode 100644
index 00000000..dcf839c0
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_send.md
@@ -0,0 +1,69 @@
+# nng_ctx_send()
+
+## NAME
+
+nng_ctx_send --- send message using context asynchronously
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+void nng_ctx_send(nng_ctx ctx, nng_aio *aio);
+```
+
+## DESCRIPTION
+
+The `nng_ctx_send()` sends a [message](nng_msg.md) using the
+[context](nng_ctx.md) _ctx_ asynchronously.
+
+The message to send must have previously been set on the _aio_
+using the [`nng_aio_set_msg()`](nng_aio_set_msg.md) function.
+The function assumes ownership of the message.
+
+If the message was successfully queued for delivery to the socket,
+then the _aio_ will be completed, and [`nng_aio_result()`](nng_aio_result.md)
+will return zero.
+In this case the socket will dispose of the message when it is finished with it.
+
+> [!NOTE]
+> The operation will be completed, and the callback associated
+> with the _aio_ executed, as soon as the socket accepts the message
+> for sending.
+> This does _not_ indicate that the message was actually delivered, as it
+> may still be buffered in the sending socket, buffered in the receiving
+> socket, or in flight over physical media.
+
+If the operation fails for any reason (including cancellation or timeout),
+then the _aio_ callback will be executed and
+[`nng_aio_result()`](nng_aio_result.md) will return a non-zero error status.
+In this case, the callback has a responsibility to retrieve the message from
+the _aio_ with [`nng_aio_get_msg()`](nng_aio_get_msg.md) and dispose of
+it appropriately.
+(This may include retrying the send operation on the same or a different
+socket, or deallocating the message with [`nng_msg_free()`](nng_msg_free.md).
+
+> [!TIP]
+> The semantics of what sending a message means varies from protocol to
+> protocol, so examination of the protocol documentation is encouraged.
+
+## ERRORS
+
+- `NNG_ECANCELED`: The operation was aborted.
+- `NNG_ECLOSED`: The context _ctx_ is not open.
+- `NNG_EMSGSIZE`: The message is too large.
+- `NNG_ENOMEM`: Insufficient memory is available.
+- `NNG_ENOTSUP`: The protocol for context _ctx_ does not support sending.
+- `NNG_ESTATE`: The context _ctx_ cannot send data in this state.
+- `NNG_ETIMEDOUT`: The send timeout expired.
+
+## SEE ALSO
+
+[nng_aio_get_msg()](nng_aio_get_msg.md),
+[nng_aio_set_msg()](nng_aio_set_msg.md),
+[nng_ctx_sendmsg()](nng_ctx_sendmsg.md),
+[nng_msg_alloc()](nng_msg_alloc.md),
+[nng_msg_alloc()](nng_msg_free.md),
+[nng_aio](nng_aio.md),
+[nng_ctx](nng_ctx),
+[nng_msg](nng_msg)
diff --git a/docs/reference/src/api/nng_ctx_sendmsg.md b/docs/reference/src/api/nng_ctx_sendmsg.md
new file mode 100644
index 00000000..5c36837c
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_sendmsg.md
@@ -0,0 +1,70 @@
+# nng_ctx_sendmsg()
+
+## NAME
+
+nng_ctx_sendmsg --- send message using context
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_sendmsg(nng_ctx c, nng_msg *msg, int flags);
+```
+
+## DESCRIPTION
+
+The `nng_ctx_sendmsg()` sends message _msg_ using the context _ctx_.
+
+If the function returns zero, indicating it has accepted the message for
+delivery, then the _msg_ is owned by the socket _s_, and the caller
+must not make any further use of it.
+The socket will free the message when it is finished.
+
+If the function returns non-zero, then it is the caller's responsibility
+to dispose of the _msg_, which may include freeing it, sending it to
+another socket, or simply trying again later.
+
+> [!TIP]
+> The semantics of what sending a message means vary from protocol to
+> protocol, so examination of the protocol documentation is encouraged.
+
+The _flags_ may contain the following value:
+
+- `NNG_FLAG_NONBLOCK`:\
+ The function returns immediately, regardless of whether
+ the context is able to accept the data or not.
+ If the context is unable to accept the data (such as if backpressure exists
+ because the peers are consuming messages too slowly, or no peer is present),
+ then the function will return with `NNG_EAGAIN`.
+ If this flag is not specified, then the function will block if such a
+ condition exists.
+
+> [!NOTE]
+> Regardless of the presence or absence of `NNG_FLAG_NONBLOCK`, there may
+> be queues between the sender and the receiver.
+> Furthermore, there is no guarantee that the message has actually been delivered.
+> Finally, with some protocols, the semantic is implicitly `NNG_FLAG_NONBLOCK`.
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_EAGAIN`: The operation would block, but `NNG_FLAG_NONBLOCK` was specified.
+- `NNG_ECLOSED`: The context or socket is not open.
+- `NNG_EINVAL`: An invalid set of _flags_ was specified.
+- `NNG_EMSGSIZE`: The value of _size_ is too large.
+- `NNG_ENOMEM`: Insufficient memory is available.
+- `NNG_ENOTSUP`: The protocol does not support sending.
+- `NNG_ESTATE`: The context cannot send data in this state.
+- `NNG_ETIMEDOUT`: The operation timed out.
+
+## SEE ALSO
+
+[nng_ctx_send()](nng_ctx_send.md),
+[nng_msg_alloc()](nng_msg_alloc.md),
+[nng_msg_alloc()](nng_msg_free.md),
+[nng_ctx](nng_ctx),
+[nng_msg](nng_msg)
diff --git a/docs/reference/src/api/nng_ctx_set.md b/docs/reference/src/api/nng_ctx_set.md
new file mode 100644
index 00000000..13692c14
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_set.md
@@ -0,0 +1,95 @@
+# nng_ctx_set()
+
+## NAME
+
+nng_ctx_set --- set context option
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_set(nng_ctx ctx, const char *opt, const void *val, size_t valsz);
+
+int nng_ctx_set_bool(nng_ctx ctx, const char *opt, int bval);
+
+int nng_ctx_set_int(nng_ctx ctx, const char *opt, int ival);
+
+int nng_ctx_set_ms(nng_ctx ctx, const char *opt, nng_duration dur);
+
+int nng_ctx_set_size(nng_ctx ctx, const char *opt, size_t z);
+
+int nng_ctx_set_string(nng_ctx ctx, const char *opt, const char *str);
+
+int nng_ctx_set_uint64(nng_ctx ctx, const char *opt, uint64_t u64);
+```
+
+## DESCRIPTION
+
+{{hi:options, context}}
+The `nng_ctx_set()` functions are used to configure options for
+the context _ctx_.
+The actual options that may be configured in this way vary, and are
+specified by _opt_.
+
+> [!NOTE]
+> Context options are protocol specific.
+> The details will be documented with the protocol.
+
+### Forms
+
+The details of the type, size, and semantics of the option will depend
+on the actual option, and will be documented with the option itself.
+
+- `nng_ctx_set()`:\
+ This function is untyped, and can be used to configure any arbitrary data.
+ The _val_ pointer addresses the data to copy, and _valsz_ is the
+ size of the objected located at _val_.
+
+- `nng_ctx_set_bool()`:\
+ This function is for options which take a Boolean (`bool`).
+ The _bval_ is passed to the option.
+
+- `nng_ctx_set_int()`:\
+ This function is for options which take an integer (`int`).
+ The _ival_ is passed to the option.
+
+- `nng_ctx_set_ms()`:\
+ This function is used to configure time durations (such as timeouts) using
+ type [`nng_duration`](nng_duration.md).
+ The duration _dur_ is an integer number of milliseconds.
+
+- `nng_ctx_set_size()`:\
+ This function is used to configure a size, _z_, typically for buffer sizes,
+ message maximum sizes, and similar options.
+
+- `nng_ctx_set_string()`:\
+ This function is used to pass configure a string, _str_.
+ Strings passed this way must be legal UTF-8 or ASCII strings, terminated
+ with a `NUL` (`\0`) byte.
+ (Other constraints may apply as well, see the documentation for each option
+ for details.)
+
+- `nng_ctx_set_uint64()`:\
+ This function is used to configure a 64-bit unsigned value, _u64_.
+ This is typically used for options related to identifiers, network numbers,
+ and similar.
+
+## RETURN VALUES
+
+These functions return 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ECLOSED`: Parameter _s_ does not refer to an open socket.
+- `NNG_EINVAL`: The value being passed is invalid.
+- `NNG_ENOTSUP`: The option _opt_ is not supported.
+- `NNG_EREADONLY`: The option _opt_ is read-only.
+- `NNG_ESTATE`: The socket is in an inappropriate state for setting this option.
+
+## SEE ALSO
+
+[nng_ctx_get()](nng_ctx_get),
+[nng_socket_set()](nng_socket_get),
+[nng_ctx](nng_ctx),
+[nng_options](nng_options)
diff --git a/docs/reference/src/api/nng_ctx_setopt.md b/docs/reference/src/api/nng_ctx_setopt.md
new file mode 100644
index 00000000..6bf7261a
--- /dev/null
+++ b/docs/reference/src/api/nng_ctx_setopt.md
@@ -0,0 +1,99 @@
+# nng_ctx_setopt()
+
+## NAME
+
+nng_ctx_setopt --- set context option (deprecated)
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+
+int nng_ctx_setopt(nng_ctx ctx, const char *opt, const void *val, size_t valsz);
+
+int nng_ctx_setopt_bool(nng_ctx ctx, const char *opt, int bval);
+
+int nng_ctx_setopt_int(nng_ctx ctx, const char *opt, int ival);
+
+int nng_ctx_setopt_ms(nng_ctx ctx, const char *opt, nng_duration dur);
+
+int nng_ctx_setopt_size(nng_ctx ctx, const char *opt, size_t z);
+
+int nng_ctx_setopt_string(nng_ctx ctx, const char *opt, const char *str);
+
+int nng_ctx_setopt_uint64(nng_ctx ctx, const char *opt, uint64_t u64);
+```
+
+## DESCRIPTION
+
+> [!IMPORTANT]
+> These functions are deprecated.
+> Please see [nng_ctx_set()](nng_ctx_set.md).
+> They may not be present if the library was built with `NNG_ELIDE_DEPRECATED`.
+> They may also be removed entirely in a future version of _NNG_.
+
+The `nng_ctx_setopt()` functions are used to configure options for
+the context _ctx_.
+The actual options that may be configured in this way vary, and are
+specified by _opt_.
+
+> [!NOTE]
+> Context options are protocol specific.
+> The details will be documented with the protocol.
+
+### Forms
+
+The details of the type, size, and semantics of the option will depend
+on the actual option, and will be documented with the option itself.
+
+- `nng_ctx_setopt()`:\
+ This function is untyped, and can be used to configure any arbitrary data.
+ The _val_ pointer addresses the data to copy, and _valsz_ is the
+ size of the objected located at _val_.
+
+- `nng_ctx_setopt_bool()`:\
+ This function is for options which take a Boolean (`bool`).
+ The _bval_ is passed to the option.
+
+- `nng_ctx_setopt_int()`:\
+ This function is for options which take an integer (`int`).
+ The _ival_ is passed to the option.
+
+- `nng_ctx_setopt_ms()`:\
+ This function is used to configure time durations (such as timeouts) using
+ type [`nng_duration`](nng_duration.md).
+ The duration _dur_ is an integer number of milliseconds.
+
+- `nng_ctx_setopt_size()`:\
+ This function is used to configure a size, _z_, typically for buffer sizes,
+ message maximum sizes, and similar options.
+
+- `nng_ctx_setopt_string()`:\
+ This function is used to pass configure a string, _str_.
+ Strings passed this way must be legal UTF-8 or ASCII strings, terminated
+ with a `NUL` (`\0`) byte.
+ (Other constraints may apply as well, see the documentation for each option
+ for details.)
+
+- `nng_ctx_setopt_uint64()`:\
+ This function is used to configure a 64-bit unsigned value, _u64_.
+ This is typically used for options related to identifiers, network numbers,
+ and similar.
+
+## RETURN VALUES
+
+These functions return 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ECLOSED`: Parameter _s_ does not refer to an open socket.
+- `NNG_EINVAL`: The value being passed is invalid.
+- `NNG_ENOTSUP`: The option _opt_ is not supported.
+- `NNG_EREADONLY`: The option _opt_ is read-only.
+- `NNG_ESTATE`: The socket is in an inappropriate state for setting this option.
+
+## SEE ALSO
+
+[nng_ctx_set()](nng_ctx_set.md),
+[nng_ctx](nng_ctx.md),
+[nng_options](nng_options.md)
diff --git a/docs/reference/src/api/nng_cv_alloc.md b/docs/reference/src/api/nng_cv_alloc.md
new file mode 100644
index 00000000..abb5eca6
--- /dev/null
+++ b/docs/reference/src/api/nng_cv_alloc.md
@@ -0,0 +1,46 @@
+# nng_cv_alloc()
+
+## NAME
+
+nng_cv_alloc --- allocate condition variable
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+typedef struct nng_cv nng_cv;
+
+int nng_cv_alloc(nng_cv **cvp, nng_mtx *mtx);
+```
+
+## DESCRIPTION
+
+The `nng_cv_alloc()` function allocates a condition variable, using
+the mutex _mtx_, and returns it in _cvp_.
+
+Every condition variable is associated with a mutex, which must be
+owned when a thread waits for the condition using
+[`nng_cv_wait()`](nng_cv_wait.md) or
+[`nng_cv_until()`](nng_cv_until.md).
+The mutex must also be owned when signaling the condition using the
+[`nng_cv_wake()`](nng_cv_wake.md) or
+[`nng_cv_wake1()`](nng_cv_wake1.md) functions.
+
+## RETURN VALUES
+
+This function returns 0 on success, and non-zero otherwise.
+
+## ERRORS
+
+- `NNG_ENOMEM`: Insufficient free memory exists.
+
+## SEE ALSO
+
+[nng_cv_free(3supp)](nng_cv_free.md),
+[nng_cv_until(3supp)](nng_cv_until.md),
+[nng_cv_wait(3supp)](nng_cv_wait.md),
+[nng_cv_wake(3supp)](nng_cv_wake.md),
+[nng_cv_wake1(3supp)](nng_cv_wake1.md),
+[nng_mtx_alloc()](nng_mtx_alloc.md)
diff --git a/docs/reference/src/api/nng_cv_free.md b/docs/reference/src/api/nng_cv_free.md
new file mode 100644
index 00000000..87412ce9
--- /dev/null
+++ b/docs/reference/src/api/nng_cv_free.md
@@ -0,0 +1,22 @@
+# nng_cv_free()
+
+## NAME
+
+nng_cv_free --- free condition variable
+
+### SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_free(nng_cv *cv);
+```
+
+## DESCRIPTION
+
+The `nng_cv_free()` function frees the condition variable _cv_.
+
+## SEE ALSO
+
+[nng_cv_alloc()](nng_cv_alloc.md)
diff --git a/docs/reference/src/api/nng_cv_until.md b/docs/reference/src/api/nng_cv_until.md
new file mode 100644
index 00000000..34669953
--- /dev/null
+++ b/docs/reference/src/api/nng_cv_until.md
@@ -0,0 +1,75 @@
+# nng_cv_until()
+
+## NAME
+
+nng_cv_until --- wait for condition or timeout
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+int nng_cv_until(nng_cv *cv, nng_time when);
+```
+
+## DESCRIPTION
+
+The `nng_cv_until()` waits until either the condition variable _cv_ is signaled
+by another thread calling either
+[`nng_cv_wake()`](nng_cv_wake.md) or
+[`nng_cv_wake1()`](nng_cv_wake1.md), or the system clock (as tracked
+by [`nng_clock()`](nng_clock.md)) reaches _when_.
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+This function will drop the ownership of that mutex, and reacquire it
+atomically just before returning to the caller.
+(The waiting is done without holding the mutex.)
+
+Spurious wakeups can occur.
+
+> [!TIP]
+> Any condition may be used or checked, but the condition must be
+> checked, as it is possible for this function to wake up spuriously.
+> The best way to do this is inside a loop that repeats until the condition
+> tests for true.
+
+## EXAMPLE
+
+The following example demonstrates use of this function:
+
+### Example 1: Waiting for the condition
+
+```c
+ expire = nng_clock() + 1000; // 1 second in the future
+ nng_mtx_lock(m); // assume cv was allocated using m
+ while (!condition_true) {
+ if (nng_cv_until(cv, expire) == NNG_ETIMEDOUT) {
+ printf("Time out reached!\n");
+ break;
+ }
+ }
+ // condition_true is true
+ nng_mtx_unlock(m);
+```
+
+### Example 2: Signaling the condition
+
+```c
+ nng_mtx_lock(m);
+ condition_true = true;
+ nng_cv_wake(cv);
+ nng_mtx_unlock(m);
+```
+
+## SEE ALSO
+
+[nng_clock()](nng_clock.md),
+[nng_cv_alloc()](nng_cv_alloc.md),
+[nng_cv_wait()](nng_cv_wait.md),
+[nng_cv_wake()](nng_cv_wake.md),
+[nng_cv_wake1()](nng_cv_wake1.md),
+[nng_mtx_alloc()](nng_mtx_alloc.md),
+[nng_mtx_lock()](nng_mtx_lock.md),
+[nng_mtx_unlock()](nng_mtx_unlock.md)
diff --git a/docs/reference/src/api/nng_cv_wait.md b/docs/reference/src/api/nng_cv_wait.md
new file mode 100644
index 00000000..1f4ddf42
--- /dev/null
+++ b/docs/reference/src/api/nng_cv_wait.md
@@ -0,0 +1,68 @@
+# nng_cv_wait()
+
+## NAME
+
+nng_cv_wait --- wait for condition
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_wait(nng_cv *cv);
+```
+
+## DESCRIPTION
+
+The `nng_cv_wait()` waits for the condition variable _cv_ to be signaled
+by another thread calling either [`nng_cv_wake()`](nng_cv_wake.md) or
+[`nng_cv_wake1()`](nng_cv_wake1.md).
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+This function will drop the ownership of that mutex, and reacquire it
+atomically just before returning to the caller.
+(The waiting is done without holding the mutex.)
+
+Spurious wakeups are possible.
+
+> [!TIP]
+> Any condition may be used or checked, but the condition must be
+> checked, as it is possible for this function to wake up spuriously.
+> The best way to do this is inside a loop that repeats until the condition
+> tests for true.
+
+## EXAMPLE
+
+The following example demonstrates use of this function:
+
+### Example 1: Waiting for the condition
+
+```c
+ nng_mtx_lock(m); // assume cv was allocated using m
+ while (!condition_true) {
+ nng_cv_wait(cv);
+ }
+ // condition_true is true
+ nng_mtx_unlock(m);
+```
+
+### Example 2: Signaling the condition
+
+```c
+ nng_mtx_lock(m);
+ condition_true = true;
+ nng_cv_wake(cv);
+ nng_mtx_unlock(m);
+```
+
+## SEE ALSO
+
+[nng_cv_alloc()](nng_cv_alloc.md),
+[nng_cv_until()](nng_cv_until.md),
+[nng_cv_wake()](nng_cv_wake.md),
+[nng_cv_wake1()](nng_cv_wake1.md),
+[nng_mtx_alloc()](nng_mtx_alloc.md),
+[nng_mtx_lock()](nng_mtx_lock.md),
+[nng_mtx_unlock()](nng_mtx_unlock.md)
diff --git a/docs/reference/src/api/nng_cv_wake.md b/docs/reference/src/api/nng_cv_wake.md
new file mode 100644
index 00000000..e83fa96d
--- /dev/null
+++ b/docs/reference/src/api/nng_cv_wake.md
@@ -0,0 +1,42 @@
+# nng_cv_wake()
+
+## NAME
+
+nng_cv_wake --- wake all waiters
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_wake(nng_cv *cv);
+```
+
+## DESCRIPTION
+
+The `nng_cv_wake()` wakes any threads waiting for the condition variable _cv_
+to be signaled in the [`nng_cv_wait()`](nng_cv_wait.md) or
+[`nng_cv_until()`](nng_cv_until.md) functions.
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+
+The caller should already have set the condition that the waiters
+will check, while holding the mutex.
+
+> [!TIP]
+> This function wakes all threads, which is generally safer but can
+> lead to a performance problem when there are many waiters, as they are all
+> woken simultaneously and may contend for resources.
+> See [`nng_cv_wake1()`](nng_cv_wake1.md) for a solution to this problem.
+
+## SEE ALSO
+
+[nng_cv_alloc()](nng_cv_alloc.md),
+[nng_cv_until()](nng_cv_until.md),
+[nng_cv_wait()](nng_cv_wait.md),
+[nng_cv_wake1()](nng_cv_wake1.md),
+[nng_mtx_alloc()](nng_mtx_alloc.md),
+[nng_mtx_lock()](nng_mtx_lock.md),
+[nng_mtx_unlock()](nng_mtx_unlock.md)
diff --git a/docs/reference/src/api/nng_cv_wake1.md b/docs/reference/src/api/nng_cv_wake1.md
new file mode 100644
index 00000000..1c70388d
--- /dev/null
+++ b/docs/reference/src/api/nng_cv_wake1.md
@@ -0,0 +1,43 @@
+# nng_cv_wake1()
+
+## NAME
+
+nng_cv_wake1 --- wake one waiter
+
+## SYNOPSIS
+
+```c
+#include <nng/nng.h>
+#include <nng/supplemental/util/platform.h>
+
+void nng_cv_wake1(nng_cv *cv);
+```
+
+## DESCRIPTION
+
+The `nng_cv_wake1()` wakes at most one thread waiting for the condition
+variable _cv_
+to be signaled in the [`nng_cv_wait()`](nng_cv_wait.md) or
+[`nng_cv_until()`](nng_cv_until.md) functions.
+
+The caller must have have ownership of the mutex that was used when
+_cv_ was allocated.
+
+The caller should already have set the condition that the waiters
+will check, while holding the mutex.
+
+> [!NOTE]
+> The caller cannot predict which waiter will be woken, and so the design must
+> ensure that it is sufficient that _any_ waiter be woken.
+> When in doubt, it is safer to use [`nng_cv_wake()`](nng_cv_wake.md).
+
+## SEE ALSO
+
+[.text-left]
+[nng_cv_alloc()](nng_cv_alloc.md),
+[nng_cv_until()](nng_cv_until.md),
+[nng_cv_wait()](nng_cv_wait.md),
+[nng_cv_wake()](nng_cv_wake.md),
+[nng_mtx_alloc()](nng_mtx_alloc.md),
+[nng_mtx_lock()](nng_mtx_lock.md),
+[nng_mtx_unlock()](nng_mtx_unlock.md)
diff --git a/docs/reference/src/api/protocol.md b/docs/reference/src/api/protocol.md
new file mode 100644
index 00000000..990b7cbb
--- /dev/null
+++ b/docs/reference/src/api/protocol.md
@@ -0,0 +1 @@
+# Protocol Sockets