diff options
Diffstat (limited to 'ref/api/stream.html')
| -rw-r--r-- | ref/api/stream.html | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/ref/api/stream.html b/ref/api/stream.html index 631d1871..e68e3be2 100644 --- a/ref/api/stream.html +++ b/ref/api/stream.html @@ -311,6 +311,246 @@ referenced by <em>valp</em>.</p> are available, and which type they may be accessed using.</p> <p>In the case of <code>nng_stream_get_string</code>, the string is created as if by <a href="/api/memory.html#duplicate-string"><code>nng_strdup</code></a>, and must be freed by the caller using <a href="/api/memory.html#free-string"><code>nng_strfree</code></a> when no longer needed.</p> +<h2 id="stream-factories"><a class="header" href="#stream-factories">Stream Factories</a></h2> +<pre><code class="language-c">typedef struct nng_stream_dialer nng_stream_dialer; +typedef struct nng_stream_listener nng_stream_listener; +</code></pre> +<p><a name="a015"></a> +The <a name="a016"></a><code>nng_stream_listener</code> object and <a name="a017"></a><code>nng_stream_listener</code> objects can be thought of as factories that +create <a href="/api/stream.html#stream-type"><code>nng_stream</code></a> streams.</p> +<p>The <code>nng_stream_listener</code> object a handle to a listener, which creates streams by accepting incoming connection requests. +In a BSD socket implementation, this is the entity responsible for doing <a name="a018"></a><code>bind</code>, <a name="a019"></a><code>listen</code> and <a name="a020"></a><code>accept</code>. +Normally a listener may be used to accept multiple, possibly many, concurrent connections.</p> +<p>The <code>nng_stream_dialer</code> object is a handle to a dialer, which creates streams by making outgoing +connection requests. While there isn’t a specific BSD socket analogue, this can be thought of as a factory for TCP sockets +created by opening them with <a name="a021"></a><code>socket</code> and then calling <a name="a022"></a><code>connect</code> on them.</p> +<h2 id="creating-a-stream-factory"><a class="header" href="#creating-a-stream-factory">Creating a Stream Factory</a></h2> +<pre><code class="language-c">int nng_stream_dialer_alloc(nng_stream_dialer **dialerp, const char *url); +int nng_stream_dialer_alloc_url(nng_stream_dialer **dialerp, const nng_url *url); +int nng_stream_listener_alloc(nng_stream_listener **lstenerp, const char *url); +int nng_stream_listener_alloc_url(nng_stream_listener **listenerp, const nng_url *url); +</code></pre> +<p>The <a name="a023"></a><code>nng_stream_dialer_alloc</code> and <a name="a024"></a><code>nng_stream_dialer_alloc_url</code> functions create a stream dialer, associated the +<a name="a025"></a>URL specified by <em>url</em> represented as a string, or as an <a href="/api/url.html#url-structure"><code>nng_url</code></a> object, respectively. The dialer is returned in the location +<em>dialerp</em> references.</p> +<p>The <a name="a026"></a><code>nng_stream_listener_alloc</code> and <a name="a027"></a><code>nng_stream_listener_alloc_url</code> functions create a stream listener, associated the +URL specified by <em>url</em> represented as a string, or as an <a href="/api/url.html#url-structure"><code>nng_url</code></a> object, respectively. The listener is returned in the location +<em>listenerp</em> references.</p> +<h3 id="example-1-creating-a-tcp-listener"><a class="header" href="#example-1-creating-a-tcp-listener">Example 1: Creating a TCP Listener</a></h3> +<p>This shows creating a TCP listener that listens on <code>INADDR_ANY</code>, port 444.</p> +<pre><code class="language-c">nng_listener listener; +int rv = nng_stream_listener_alloc(&listener, "tcp://:444"); +</code></pre> +<h2 id="closing-a-stream-factory"><a class="header" href="#closing-a-stream-factory">Closing a Stream Factory</a></h2> +<pre><code class="language-c">void nng_stream_dialer_close(nng_stream_listener *dialer); +void nng_stream_dialer_stop(nng_stream_listener *dialer); +void nng_stream_dialer_free(nng_stream_listener *dialer); +void nng_stream_listener_close(nng_stream_listener *listener); +void nng_stream_listener_stop(nng_stream_listener *listener); +void nng_stream_listener_free(nng_stream_listener *listener); +</code></pre> +<p>The <a name="a028"></a><code>nng_stream_dialer_close</code> and <a name="a029"></a><code>nng_stream_listener_close</code> functions close the stream <em>dialer</em> or <em>listener</em>, +preventing it from creating new connections. +This will generally include closing any underlying file used for creating such connections. +However, some requests may still be pending when this function returns, as it does not wait for the shutdown to complete.</p> +<p>The <a name="a030"></a><code>nng_stream_dialer_stop</code> and <a name="a031"></a><code>nng_stream_listener_stop</code> functions performs the same action, +but also wait until all outstanding requests are serviced, and the <em>dialer</em> or <em>listener</em> is completely stopped. +Because they blocks, these functions must not be called in contexts where blocking is not allowed.</p> +<p>The <a name="a032"></a><code>nng_stream_dialer_free</code> and <a name="a033"></a><code>nng_stream_listener_free</code> function performs the same action as +<code>nng_stream_dialer_stop</code> or <code>nng_stream_listener_stop</code>, but also deallocates the <em>dialer</em> or <em>listener</em>, and any associated resources.</p> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>A best practice for shutting down an application safely is to stop everything <em>before</em> deallocating. This ensures that no +callbacks are running that could reference an object after it is deallocated.</p> +</div> +<h2 id="making-outgoing-connections"><a class="header" href="#making-outgoing-connections">Making Outgoing Connections</a></h2> +<pre><code class="language-c">void nng_stream_dialer_dial(nng_stream_dialer *dialer, nng_aio *aio); +</code></pre> +<p>The <a name="a034"></a><code>nng_stream_dialer_dial</code> initiates an outgoing connection asynchronously, using the <a href="/api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a> <em>aio</em>. +If it successfully establishes a connection, it creates an <a href="/api/stream.html#stream-type"><code>nng_stream</code></a>, which can be obtained as the first +output result on <em>aio</em> using the <a href="/api/aio.html#inputs-and-outputs"><code>nng_aio_get_output</code></a> function with index zero.</p> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>An <a href="/api/stream.html#stream-factories"><code>nng_stream_dialer</code></a> can be used multiple times to make multiple concurrent connection requests, but +they all must reference the same URL.</p> +</div> +<h3 id="example-3-connecting-to-google"><a class="header" href="#example-3-connecting-to-google">Example 3: Connecting to Google</a></h3> +<p>This demonstrates making an outbound connection to “google.com” on TCP port 80. +Error handling is elided for clarity.</p> +<pre><code class="language-c">nng_aio *aio; +nng_stream_dialer *dialer; +nng_stream *stream; + +nng_stream_dialer_alloc(&dialer, "tcp://google.com:80"); + +nng_aio_alloc(&aio, NULL, NULL); + +// make a single outbound connection +nng_stream_dialer_dial(dialer, aio); +nng_aio_wait(aio); // wait for the asynch operation to complete +if (nng_aio_result(aio) != 0) { + // ... handle the error +} +stream = nng_aio_get_output(aio, 0); +</code></pre> +<h2 id="accepting-incoming-connections"><a class="header" href="#accepting-incoming-connections">Accepting Incoming Connections</a></h2> +<pre><code class="language-c">int nng_stream_listener_listen(nng_stream_listener *listener); +void nng_stream_listener_accept(nng_stream_listener *listener, nng_aio *aio); +</code></pre> +<p>Accepting incoming connections is performed in two steps. The first step, <a name="a035"></a><code>nng_stream_listener_listen</code> is to setup for +listening. For a TCP implementation of this, for example, this would perform the <code>bind</code> and the <code>listen</code> steps. This will bind +to the address represented by the URL that was specific when the listener was created with <a href="/api/stream.html#creating-a-stream-factory"><code>nng_stream_listener_alloc</code></a>.</p> +<p>In the second step, <a name="a036"></a><code>nng_stream_listener_accept</code> accepts an incoming connection on <em>listener</em> asynchronously, using the <a href="/api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a> <em>aio</em>. +If an incoming connection is accepted, it will be represented as an <a href="/api/stream.html#stream-type"><code>nng_stream</code></a>, which can be obtained from the <em>aio</em> as the first +output result using the <a href="/api/aio.html#inputs-and-outputs"><code>nng_aio_get_output</code></a> function with index zero.</p> +<h3 id="example-3-accepting-an-inbound-stream"><a class="header" href="#example-3-accepting-an-inbound-stream">Example 3: Accepting an Inbound Stream</a></h3> +<p>For clarity this example uses a synchronous approach using <a href="/api/aio.html#wait-for-completion"><code>nng_aio_wait</code></a>, but a typical server application +would most likely use a callback to accept the incoming stream, and start another instance of <code>nng_stream_listener_accept</code>.</p> +<pre><code class="language-c">nng_aio *aio; +nng_listener *listener; +nng_stream *stream; + +nng_stream_listener_alloc(&listener, "tcp://:8181"); +nng_aio_alloc(&aio, NULL, NULL); // normally would use a callback + +// listen (binding to the URL in the process) +if (nng_stream_listener_listen(listener)) { + // ... handle the error +} + +// now accept a single incoming connection as a stream object +nng_stream_listener_accept(l, aio); +nng_aio_wait(aio); // wait for the asynch operation to complete +if (nng_aio_result(aio) != 0) { + // ... handle the error +} +stream = nng_aio_get_output(aio, 0); +</code></pre> +<h2 id="stream-factory-options"><a class="header" href="#stream-factory-options">Stream Factory Options</a></h2> +<pre><code class="language-c">int nng_stream_dialer_get_bool(nng_stream_dialer *dialer, const char *opt, bool *valp); +int nng_stream_dialer_get_int(nng_stream_dialer *dialer, const char *opt, int *valp); +int nng_stream_dialer_get_ms(nng_stream_dialer *dialer, const char *opt, nng_duration *valp); +int nng_stream_dialer_get_size(nng_stream_dialer *dialer, const char *opt, size_t *valp); +int nng_stream_dialer_get_addr(nng_stream_dialer *dialer, const char *opt, nng_sockaddr *valp); +int nng_stream_dialer_get_string(nng_stream_dialer *dialer, const char *opt, char **valp); +int nng_stream_dialer_get_uint64(nng_stream_dialer *dialer, const char *opt, uint64_t *valp); + +int nng_stream_listener_get_bool(nng_stream_listener *listener, const char *opt, bool *valp); +int nng_stream_listener_get_int(nng_stream_listener *listener, const char *opt, int *valp); +int nng_stream_listener_get_ms(nng_stream_listener *listener, const char *opt, nng_duration *valp); +int nng_stream_listener_get_size(nng_stream_listener *listener, const char *opt, size_t *valp); +int nng_stream_listener_get_addr(nng_stream_listener *listener, const char *opt, nng_sockaddr *valp); +int nng_stream_listener_get_string(nng_stream_listener *listener, const char *opt, char **valp); +int nng_stream_listener_get_uint64(nng_stream_listener *listener, const char *opt, uint64_t *valp); + +int nng_stream_dialer_set_bool(nng_stream_dialer *dialer, const char *opt, bool val); +int nng_stream_dialer_set_int(nng_stream_dialer *dialer, const char *opt, int val); +int nng_stream_dialer_set_ms(nng_stream_dialer *dialer, const char *opt, nng_duration val); +int nng_stream_dialer_set_size(nng_stream_dialer *dialer, const char *opt, size_t val); +int nng_stream_dialer_set_string(nng_stream_dialer *dialer, const char *opt, const char *val); +int nng_stream_dialer_set_uint64(nng_stream_dialer *dialer, const char *opt, uint64_t val); +int nng_stream_dialer_set_addr(nng_stream_dialer *dialer, const char *opt, const nng_sockaddr *val); + +int nng_stream_listener_set_bool(nng_stream_listener *listener, const char *opt, bool val); +int nng_stream_listener_set_int(nng_stream_listener *listener, const char *opt, int val); +int nng_stream_listener_set_ms(nng_stream_listener *listener, const char *opt, nng_duration val); +int nng_stream_listener_set_size(nng_stream_listener *listener, const char *opt, size_t val); +int nng_stream_listener_set_string(nng_stream_listener *listener, const char *opt, const char *val); +int nng_stream_listener_set_uint64(nng_stream_listener *listener, const char *opt, uint64_t val); +int nng_stream_listener_set_addr(nng_stream_listener *listener, const char *opt, const nng_sockaddr *val); +</code></pre> +<p><a name="a037"></a> +<a name="a038"></a> +<a name="a039"></a> +<a name="a040"></a> +<a name="a041"></a> +<a name="a042"></a> +<a name="a043"></a> +<a name="a044"></a> +<a name="a045"></a> +<a name="a046"></a> +<a name="a047"></a> +<a name="a048"></a> +<a name="a049"></a> +<a name="a050"></a> +<a name="a051"></a> +<a name="a052"></a> +<a name="a053"></a> +<a name="a054"></a> +<a name="a055"></a> +<a name="a056"></a> +<a name="a057"></a> +<a name="a058"></a> +<a name="a059"></a> +<a name="a060"></a> +<a name="a061"></a> +<a name="a062"></a> +<a name="a063"></a> +<a name="a064"></a> +These functions are used to retrieve or change the value of an option named <em>opt</em> from the stream <em>dialer</em> or <em>listener</em>. +The <code>nng_stream_dialer_get_</code> and <code>nng_stream_listener_get_</code> function families retrieve the value, and store it in the location <em>valp</em> references. +The <code>nng_stream_dialer_set_</code> and <code>nng_stream_listener_set_</code> function families change the value for the <em>dialer</em> or <em>listener</em>, taking it from <em>val</em>.</p> +<p>These functions access an option as a specific type. The transport layer will have details about which options +are available, and which type they may be accessed using.</p> +<p>In the case of <code>nng_stream_dialer_get_string</code> and <code>nng_stream_listener_get_string</code>, the string is created as if by <a href="/api/memory.html#duplicate-string"><code>nng_strdup</code></a>, and must be freed by +the caller using <a href="/api/memory.html#free-string"><code>nng_strfree</code></a> when no longer needed.</p> +<p>In the case of <code>nng_stream_dialer_set_string</code> and <code>nng_stream_listener_set_string</code>, the string contents are copied if necessary, so that the caller +need not retain the value referenced once the function returns.</p> +<p>In the case of <code>nng_stream_dialer_set_addr</code> and <code>nng_stream_listener_set_addr</code>, the contents of <em>addr</em> are copied if necessary, so that the caller +need not retain the value referenced once the function returns.</p> +<h3 id="example-4-socket-activation"><a class="header" href="#example-4-socket-activation">Example 4: Socket Activation<a name="socket-activation"></a></a></h3> +<p>Some <a href="/api/stream.html#stream-factories"><code>nng_stream_listener</code></a> objects, depending on the underlying transport and platform, can support a technique known as “<a name="a065"></a>socket activation”, +where the file descriptor used for listening and accepting is supplied externally, such as by a system service manager. +In this case, the application supplies the file descriptor or <code>SOCKET</code> object using the <a name="a066"></a><code>NNG_OPT_LISTEN_FD</code> option, +instead of calling <a href="/api/stream.html#accepting-incoming-connections"><code>nng_stream_listener_listen</code></a>.</p> +<div class="mdbook-alerts mdbook-alerts-tip"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + tip +</p> +<p>Scalability Protocols transports based upon stream implementations that support socket activation can also benefit from this approach.</p> +</div> +<pre><code class="language-c">nng_stream_listener *listener; +int fd; + +// This is a systemd API, not part of NNG. +// See systemd documentation for an explanation. +// fd at this point has already had bind() and listen() called. +fd = SD_LISTEN_FDS_START + 0; + +nng_stream_listener_alloc(&listener, "tcp://"); +nng_stream_listener_set_int(listener, NNG_OPT_LISTEN_FD, fd); + +// can now start doing nng_stream_listener_accept... +</code></pre> +<h2 id="tls-configuration"><a class="header" href="#tls-configuration">TLS Configuration</a></h2> +<pre><code class="language-c">int nng_stream_dialer_get_tls(nng_stream_listener *dialer, nng_tls_config **tlsp); +int nng_stream_dialer_set_tls(nng_stream_listener *dialer, nng_tls_config *tls); +int nng_stream_listener_get_tls(nng_stream_listener *listener, nng_tls_config **tlsp); +int nng_stream_listener_set_tls(nng_stream_listener *listener, nng_tls_config *tls); +</code></pre> +<p>Both <a href="/api/stream.html#stream-factories"><code>nng_stream_dialer</code></a> and <a href="/api/stream.html#stream-factories"><code>nng_stream_listener</code></a> objects may support configuration of <a name="a067"></a>TLS parameters. +The <a name="a068"></a><code>nng_stream_dialer_set_tls</code> and <a name="a069"></a><code>nng_stream_listener_set_tls</code> functions support setting the +configuration of a <a href="/TODO.html"><code>nng_tls_config</code></a> object supplied by <em>tls</em> on <em>dialer</em> or <em>listener</em>. +This must be performed before the <em>listener</em> starts listening with <a href="/api/stream.html#accepting-incoming-connections"><code>nng_stream_listener_listen</code></a>, or the dialer starts an outgoing connection +as a result of <a href="/api/stream.html#making-outgoing-connections"><code>nng_stream_dialer_dial</code></a>.</p> +<p>The configuration object that was previously established (which may be a default if one was not explicitly +configured) can be obtained with the <a name="a070"></a><code>nng_stream_dialer_get_tls</code> and <a name="a071"></a><code>nng_stream_listener_get_tls</code>. +They will return a pointer to the <a href="/TODO.html"><code>nng_tls_config</code></a> object in question at the location referenced by <em>tlsp</em>.</p> +<div class="mdbook-alerts mdbook-alerts-note"> +<p class="mdbook-alerts-title"> + <span class="mdbook-alerts-icon"></span> + note +</p> +<p>TLS configuration cannot be changed once it has started being used by a listener or dialer. This applies to +both configuring a different TLS configuration object, as well as mutating the existing <a href="/TODO.html"><code>nng_tls_config</code></a> object.</p> +</div> <!-- Symbol cross reference --> <!-- Macros --> <!-- Protocols --> |
