sd_varlink_reply_and_upgrade, sd_varlink_respond_and_upgrade, sd_varlink_respond_and_upgradeb, sd_varlink_respond_and_upgradebo, sd_varlink_bind_upgrade, sd_varlink_upgrade_t — Reply to a Varlink method call and take over the connection for a raw protocol
#include <systemd/sd-varlink.h>
typedef int (*sd_varlink_upgrade_t)(sd_varlink *link, intinput_fd, intoutput_fd, void *userdata);
int sd_varlink_reply_and_upgrade( | sd_varlink *link, |
| sd_json_variant *parameters, | |
| int *ret_input_fd, | |
int *ret_output_fd); |
int sd_varlink_respond_and_upgrade( | sd_varlink *link, |
sd_json_variant *parameters); |
int sd_varlink_respond_and_upgradeb( | sd_varlink *link, |
…); |
int sd_varlink_respond_and_upgradebo( | sd_varlink *link, |
…); |
int sd_varlink_bind_upgrade( | sd_varlink *link, |
sd_varlink_upgrade_t callback); |
These functions implement the server side of a Varlink protocol upgrade. A
Varlink client may request an upgrade when invoking a method (see
sd_varlink_call(3) and
the SD_VARLINK_METHOD_UPGRADE flag passed to method callbacks). If a method is
invoked this way, the server may send one final reply and then abandon the Varlink protocol on the
connection entirely, handing the underlying socket or pipe file descriptors back to the caller so that an
arbitrary, non-Varlink ("raw") protocol may be spoken over them instead. This is useful for methods that
negotiate a switch to a streaming or binary protocol, in a manner similar to the
"Upgrade:" mechanism of HTTP.
sd_varlink_reply_and_upgrade() sends a final reply to the currently processed
method call and then takes over the connection's file descriptors synchronously. It
takes the Varlink connection object, a JSON object with the reply parameters (which may be
NULL), and two output pointers for the file descriptors. The parameters
object is validated against the method's declared reply signature, if known. The reply is flushed to the
connection before the file descriptors are returned, so that the client has received the full reply before
the caller starts speaking the upgraded protocol. On success the connection is detached from its event
loop (if any) and disconnected, and ownership of the file descriptors is transferred to the caller, which
is responsible for eventually closing them with
close(2).
The returned file descriptors are switched to blocking mode. For bidirectional sockets a single
underlying file descriptor carries both directions; in this case ret_input_fd and
ret_output_fd are returned as two independent (duplicated) descriptors referring
to the same socket, so they may be closed separately. For transports backed by a pair of pipes the two
descriptors differ and refer to the distinct read and write ends. Either
ret_input_fd or ret_output_fd (but not both) may be
NULL; in that case the unwanted direction is shut down (if they refer to the same
socket, see shutdown(2)) or
closed (if separate file descriptors) rather than returned.
Note that sd_varlink_reply_and_upgrade() blocks synchronously until the reply
has been flushed to the socket. A misbehaving or adversarial client that stops reading could stall the
caller. It should hence not be used in servers that multiplex many Varlink connections in a single event
loop, as one stalled connection would block progress on all others. Use
sd_varlink_respond_and_upgrade() in that case instead.
sd_varlink_respond_and_upgrade() is the asynchronous
counterpart of sd_varlink_reply_and_upgrade(). It enqueues the final reply and
returns immediately, without blocking and without returning the file descriptors directly. The reply is
subsequently flushed by the event loop during regular
sd_varlink_process(3)
invocations. Once the reply has been fully flushed, the connection's file descriptors are handed to the
upgrade callback previously registered with sd_varlink_bind_upgrade(), and the
Varlink connection is disconnected. This variant is the right choice for servers that handle many
connections concurrently, as it never blocks on a single client.
sd_varlink_respond_and_upgradeb() is similar to
sd_varlink_respond_and_upgrade(), but instead of expecting a fully constructed
sd_json_variant object carrying the reply parameters, this object is constructed on-the-fly
from the variadic argument list, in a style identical to
sd_json_build(3).
sd_varlink_respond_and_upgradebo() is identical to
sd_varlink_respond_and_upgradeb(), but an enclosing JSON object is added implicitly,
so that the argument list is expected to consist of object field pairs only, in a style identical to
sd_json_buildo(3).
sd_varlink_bind_upgrade() registers the upgrade
callback that is invoked once a reply enqueued via
sd_varlink_respond_and_upgrade() (or one of its variants) has been flushed to the
connection. The callback is of type sd_varlink_upgrade_t and receives the Varlink connection
object, the input and output file descriptors of the (now upgraded) connection, and the userdata pointer
associated with the connection (see
sd_varlink_set_userdata(3)).
Ownership of the two file descriptors is transferred to the callback (regardless if the callback later
fails or not). The descriptor semantics (blocking mode, duplication for bidirectional sockets, distinct
ends for pipe pairs) match those described for sd_varlink_reply_and_upgrade()
above. Passing NULL as callback removes a previously
registered callback.
On success, sd_varlink_reply_and_upgrade(),
sd_varlink_respond_and_upgrade(),
sd_varlink_respond_and_upgradeb() and
sd_varlink_respond_and_upgradebo() return a positive integer.
sd_varlink_bind_upgrade() returns a non-negative integer on success. On failure, they
all return a negative errno-style error code.
Returned errors may indicate the following problems:
-EINVAL¶An argument is invalid.
-ENOTCONN¶The Varlink connection object is not connected.
-EBUSY¶The connection is not currently processing a method call, so there is no reply to
send. When returned by sd_varlink_bind_upgrade(), a different upgrade callback
was already registered on the connection.
-EPROTO¶The currently processed method call did not request a protocol upgrade, hence the connection may not be taken over.
-EBADMSG¶The client sent unexpected data before the upgrade completed, i.e. it pipelined raw protocol data before receiving the upgrade reply.
-ENOMEM¶Memory allocation failed.
Functions described here are available as a shared
library, which can be compiled against and linked to with the
libsystemd pkg-config(1)
file.
The code described here uses
getenv(3),
which is declared to be not multi-thread-safe. This means that the code calling the functions described
here must not call
setenv(3)
from a parallel thread. It is recommended to only do calls to setenv()
from an early phase of the program when no other threads have been started.
sd_varlink_reply_and_upgrade() was added in version 261.
sd_varlink_respond_and_upgrade(),
sd_varlink_respond_and_upgradeb(),
sd_varlink_respond_and_upgradebo() and
sd_varlink_bind_upgrade() were added in version 262.