diff options
Diffstat (limited to 'docs/ref')
| -rw-r--r-- | docs/ref/SUMMARY.md | 2 | ||||
| -rw-r--r-- | docs/ref/api/aio.md | 29 | ||||
| -rw-r--r-- | docs/ref/api/stream.md | 79 | ||||
| -rw-r--r-- | docs/ref/api/synch.md | 4 | ||||
| -rw-r--r-- | docs/ref/xref.md | 12 |
5 files changed, 124 insertions, 2 deletions
diff --git a/docs/ref/SUMMARY.md b/docs/ref/SUMMARY.md index a37ba31e..6db29e63 100644 --- a/docs/ref/SUMMARY.md +++ b/docs/ref/SUMMARY.md @@ -30,6 +30,8 @@ - [Errors](./api/errors.md) + - [Streams](./api/stream.md) + - [Miscellaneous](./api/misc.md) - [ID Map](./api/id_map.md) diff --git a/docs/ref/api/aio.md b/docs/ref/api/aio.md index 6e084e43..58c8e4f9 100644 --- a/docs/ref/api/aio.md +++ b/docs/ref/api/aio.md @@ -278,10 +278,39 @@ results. > It is an error to call this function while the _aio_ is currently > in use by an active asynchronous operation. +## Scatter Gather Vectors + +```c +typedef struct nng_iov { + void *iov_buf; + size_t iov_len; +} nng_iov; + +void nng_aio_set_iov(nng_aio *aio, unsigned nio, const nng_iov *iov); +``` + +{{hi:`nng_iov`}} +Some asynchronous operations, such as those dealing with [streams], use {{i:scatter}} or {{i:gather}} +vectors, where data to be transferred is either gathered from multiple separate regions of memory, or +scattered into separate regions of memory. For example a message may have a header located at one location +in memory, and a payload located in another. + +The {{i:`nng_aio_set_iov`}} function configures the _aio_ to use _nio_ separate segments, described by +the elements in _iov_. For each of these, the segment of size _iov_len_ located at _iov_buf_ will be used. + +The elements of _iov_ will be copied into _aio_, so the vector may be located +on the stack or another temporary location. The locations referenced by it, _must_ remain valid for +the duration of the operation, of course. + +Note that many of these operations are not guaranteed to perform a full transfer of data, so even a +successful operation should check the amount of data actually transferred using [`nng_aio_count`], +and if necessary resubmit the operation with a suitably updated vector of `nng_iov` using this function. + ## See Also [Synchronization][synchronization], [Threads][thread], +[Streams][streams], [Time][time] {{#include ../xref.md}} diff --git a/docs/ref/api/stream.md b/docs/ref/api/stream.md new file mode 100644 index 00000000..9609ef7b --- /dev/null +++ b/docs/ref/api/stream.md @@ -0,0 +1,79 @@ +# Streams + +NNG provides a common {{i:streams}} API for working with byte-oriented streams. In NNG, streams are bidirectional +connections for exchanging a stream of bytes. + +Some common examples of streams are TCP connections, UNIX domain sockets, Windows named pipes, and WebSockets. + +The API documented here is to facilitate applications that wish to work with these at a lower-level than +Scalability Protocols, in a way that is both portable and agnostic about the specific underlying transport mechanism. + +> [!TIP] +> When working with Scalability Protocols directly, it is unlikely that there will be any need for +> using these Streams APIs. + +## Stream Type + +```c +typedef struct nng_stream nng_stream` +``` + +The base {{i:`nng_stream`}} type represents a bidirectional, byte-oriented, reliable connection. + +> [!NOTE] +> The `nng_stream` object is used for raw byte stream connections, and +> should not be confused with a [pipe] object created on a [socket] using +> the [`nng_listen`], [`nng_dial`] or related functions. + +## Sending and Receiving Data + +```c +void nng_stream_send(nng_stream *s, nng_aio *aio); +void nng_stream_recv(nng_stream *s, nng_aio *aio); +``` + +The {{i:`nng_stream_send`}} function starts sending data asynchronously over the stream _s_. +The data is sent from the scatter/gather vector located in the [`nng_aio`] _aio_, +which must have been previously set using [`nng_aio_set_iov`]. + +The {{i:`nng_stream_recv`}} function starts receiving data [asynchronously over the stream _s_ +into the scatter/gather vector located in the [`nng_aio`] _aio_, +which must have been previously set using [`nng_aio_set_iov`]. + +These functions return immediately, with no return value. +Completion of the operation is signaled via the _aio_, and the final +result may be obtained via [`nng_aio_result`]. + +The I/O operation may complete as soon as at least one byte has been +transferred, or an error has occurred. +Therefore, the number of bytes transferred may be less than requested. +The actual number of bytes transferred can be determined with [`nng_aio_count`]. + +## Closing a Stream + +```c +void nng_stream_close(nng_stream *s); +void nng_stream_stop(nng_stream *s); +void nng_stream_free(nng_stream *s); +``` + +The {{i:`nng_stream_close`}} function closes a stream, but does not destroy it. +This function returns immediately. Operations that are pending against the stream, such +as [`nng_stream_send`] or [`nng_stream_recv`] operations will be canceled asynchronously, if possible. +Those operations will result in [`NNG_ECLOSED`]. + +The {{i:`nng_stream_stop`}} function not only closes the stream, but waits for any operations +pending against it to complete, and for any underlying asynchronous registered I/O to be fully deregistered. +As some systems use separate threads for asynchronous I/O, stopping the stream is necessary before those +resources can be freed. Until the stream is stopped, there could still be I/O operations in flight, +making it unsafe to deallocate memory. + +The {{i:`nng_stream_free`}} function stops the stream like `nng_stream_stop`, but also deallocates the +stream itself. + +> [!NOTE] +> Because `nng_stream_stop` and `nng_stream_free` both may block waiting for outstanding I/O to complete +> or be aborted, these functions are unsafe to call from functions that may not block, such as the +> completion function registered with an [`nng_aio`] when it is created. + +{{#include ../xref.md}} diff --git a/docs/ref/api/synch.md b/docs/ref/api/synch.md index 9ab9cc11..62e9b7c1 100644 --- a/docs/ref/api/synch.md +++ b/docs/ref/api/synch.md @@ -171,10 +171,10 @@ nng_cv_wake(cv); nng_mtx_unlock(m); ``` -{{#include ../xref.md}} - ## See Also [Threads][thread], [Time][time], [Asynchronous I/O][aio] + +{{#include ../xref.md}} diff --git a/docs/ref/xref.md b/docs/ref/xref.md index cb71794d..15db26f5 100644 --- a/docs/ref/xref.md +++ b/docs/ref/xref.md @@ -88,8 +88,12 @@ [`nng_aio_wait`]: /api/aio.md#wait-for-completion [`nng_aio_busy`]: /api/aio.md#test-for-completion [`nng_aio_result`]: /api/aio.md#result-of-operation +[`nng_aio_get_msg`]: /api/aio.md#messages +[`nng_aio_set_msg`]: /api/aio.md#messages [`nng_aio_count`]: /api/aio.md#result-of-operation [`nng_aio_set_timeout`]: /api/aio.md#set-timeout +[`nng_aio_set_iov`]: /api/aio.md#scatter-gather-vectors +[`nng_iov`]: /api/aio.md#scatter-gather-vectors [`nng_socket_id`]: /api/sock.md#socket-identity [`nng_socket_raw`]: /api/sock.md#socket-identity [`nng_socket_proto_id`]: /api/sock.md#socket-identity @@ -98,6 +102,12 @@ [`nng_socket_peer_name`]: /api/sock.md#socket-identity [`nng_socket_get_recv_poll_fd`]: /api/sock.md#polling-socket-events [`nng_socket_get_send_poll_fd`]: /api/sock.md#polling-socket-events +[`nng_stream`]: /api/stream.md#stream-type +[`nng_stream_send`]: /api/stream.md#sending-and-receiving-data +[`nng_stream_recv`]: /api/stream.md#sending-and-receiving-data +[`nng_stream_close`]: /api/stream.md#closing-a-stream +[`nng_stream_stop`]: /api/stream.md#closing-a-stream +[`nng_stream_free`]: /api/stream.md#closing-a-stream [`nng_init`]: /api/init.md#initialization [`nng_fini`]: /api/init.md#finalization [`nng_sub0_ctx_subscribe`]: /TODO.md @@ -159,6 +169,7 @@ [`NNG_EBADTYPE`]: /api/errors.md#NNG_EBADTYPE [`NNG_ECONNSHUT`]: /api/errors.md#NNG_ECONNSHUT [`NNG_EINTERNAL`]: /api/errors.md#NNG_EINTERNAL +[`NNG_ESTOPPED`]: /api/errors.md#NNG_ESTOPPED [`NNG_ESYSERR`]: /api/errors.md#NNG_ESYSERR [`NNG_ETRANERR`]: /api/errors.md#NNG_ETRANERR [`NNG_DURATION_INFINITE`]: /api/time.md#duration-type @@ -210,6 +221,7 @@ [dialer]: /TODO.md [listener]: /TODO.md [message]: /api/msg.md +[streams]: /api/stream.md [message-body]: /api/msg.md#message-body [message-header]: /api/msg.md#message-header [synchronization]: /api/synch.md |
