Pipes

typedef struct nng_pipe_s nng_pipe;

An nng_pipe is a handle to a pipe object, which can be thought of as a single connection. (In most cases this is actually the case – the pipe is an abstraction for a single TCP or IPC connection.) Pipes are associated with either the listener or dialer that created them, and therefore are also automatically associated with a single socket.

note

The nng_pipe 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.

tip

Most applications should never concern themselves with individual pipes. However it is possible to access a pipe when more information about the source of a message is needed, or when more control is required over message delivery.

Pipe objects are created by dialers and and listeners.

Initialization

A pipe may be initialized using the macro NNG_PIPE_INITIALIZER before it is opened, to prevent confusion with valid open pipes.

For example:

nng_pipe p = NNG_PIPE_INITIALIZER;

Pipe Identity

int nng_pipe_id(nng_pipe p);

The nng_pipe_id function returns a positive identifier for the pipe p, if it is valid. Otherwise it returns -1.

note

A pipe is considered valid if it was ever created by the socket. Pipes that are allocated on the stack or statically should be initialized with the macro NNG_PIPE_INITIALIZER to ensure that they cannot be confused with a valid pipe.

Closing a Pipe

nng_err nng_pipe_close(nng_pipe p);

The nng_pipe_close function closes the supplied pipe, p. Messages that have been submitted for sending may be flushed or delivered, depending upon the transport.

Further attempts to use the pipe after this call returns will result in NNG_ECLOSED.

tip

Pipes are automatically closed when their creator closes, or when the remote peer closes the underlying connection.

Pipe Creator

nng_dialer nng_pipe_dialer(nng_pipe p);
nng_listener nng_pipe_listener(nng_pipe p);
nng_socket nng_pipe_socket(nng_pipe p);

These functions return the socket, dialer, or listener that created or owns the pipe.

If the pipe was does not have an associated dialer or listener, then the associated will return [NNG_DIALER_INITIALIZER] or [NNG_LISTENER_INITIALIZER], as appropriate, and either [nng_dialer_id] or [nng_listener_id] for the returned object will return -1.

note

The socket, or the endpoint, returned by these functions may be in the process of closing, and might not be further usable as a result. (Other functions will result in NNG_ECLOSED.)

Pipe Options

nng_err nng_pipe_get_bool(nng_pipe p, const char *opt, bool *valp);
nng_err nng_pipe_get_int(nng_pipe p, const char *opt, int *valp);
nng_err nng_pipe_get_ms(nng_pipe p, const char *opt, nng_duration *valp);
nng_err nng_pipe_get_size(nng_pipe p, const char *opt, size_t *valp);
nng_err nng_pipe_get_addr(nng_pipe p, const char *opt, nng_sockaddr *valp);
nng_err nng_pipe_get_string(nng_pipe p, const char *opt, char **valp);

These functions are used to obtain value of an option named opt from the pipe p, and store it in the location referenced by valp.

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.

In the case of nng_pipe_get_string, the string is created as if by nng_strdup, and must be freed by the caller using nng_strfree when no longer needed.

Pipe Notifications

typedef enum {
        NNG_PIPE_EV_ADD_PRE,
        NNG_PIPE_EV_ADD_POST,
        NNG_PIPE_EV_REM_POST,
} nng_pipe_ev;

typedef void (*nng_pipe_cb)(nng_pipe, nng_pipe_ev, void *);

nng_err nng_pipe_notify(nng_socket s, nng_pipe_ev ev, nng_pipe_cb cb, void *arg);

The nng_pipe_notify function registers the callback function cb to be called whenever the pipe event specified by ev occurs on the socket s. The callback cb will be passed arg as its final argument.

A different callback may be supplied for each event. Each event may have at most one callback registered. Registering a callback implicitly unregisters any previously registered.

The following pipe events are supported:

EventDescription
NNG_PIPE_EV_ADD_PREThis event occurs after a connection and negotiation has completed, but before the pipe is added to the socket. If the pipe is closed (using nng_pipe_close) at this point, the socket will never see the pipe, and no further events will occur for the given pipe.
NNG_PIPE_EV_ADD_POSTThis event occurs after the pipe is fully added to the socket. Prior to this time, it is not possible to communicate over the pipe with the socket.
NNG_PIPE_EV_REM_POSTThis event occurs after the pipe has been removed from the socket. The underlying transport may be closed at this point, and it is not possible communicate using this pipe.

warning

The callback cb function must not attempt to perform any accesses to the socket, as it is called with a lock on the socket held! Doing so would thus result in a deadlock.

tip

The callback cb may close a pipe for any reason by simply closing it using nng_pipe_close. For example, this might be done to prevent an unauthorized peer from connecting to the socket, if an authorization check made during NNG_PIPE_EV_ADD_PRE fails.

note

This function ignores invalid values for ev.