'\" t .TH "SD_VARLINK_REPLY_AND_UPGRADE" "3" "" "systemd 262" "sd_varlink_reply_and_upgrade" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" 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 .SH "SYNOPSIS" .sp .ft B .nf #include .fi .ft .sp .ft B .nf typedef int (*sd_varlink_upgrade_t)(sd_varlink *link, int input_fd, int output_fd, void *userdata); .fi .ft .HP \w'int\ sd_varlink_reply_and_upgrade('u .BI "int sd_varlink_reply_and_upgrade(sd_varlink\ *" "link" ", sd_json_variant\ *" "parameters" ", int\ *" "ret_input_fd" ", int\ *" "ret_output_fd" ");" .HP \w'int\ sd_varlink_respond_and_upgrade('u .BI "int sd_varlink_respond_and_upgrade(sd_varlink\ *" "link" ", sd_json_variant\ *" "parameters" ");" .HP \w'int\ sd_varlink_respond_and_upgradeb('u .BI "int sd_varlink_respond_and_upgradeb(sd_varlink\ *" "link" ", \&...);" .HP \w'int\ sd_varlink_respond_and_upgradebo('u .BI "int sd_varlink_respond_and_upgradebo(sd_varlink\ *" "link" ", \&...);" .HP \w'int\ sd_varlink_bind_upgrade('u .BI "int sd_varlink_bind_upgrade(sd_varlink\ *" "link" ", sd_varlink_upgrade_t\ " "callback" ");" .SH "DESCRIPTION" .PP These functions implement the server side of a Varlink \fIprotocol upgrade\fR\&. A Varlink client may request an upgrade when invoking a method (see \fBsd_varlink_call\fR(3) and the \fBSD_VARLINK_METHOD_UPGRADE\fR 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\&. .PP \fBsd_varlink_reply_and_upgrade()\fR sends a final reply to the currently processed method call and then takes over the connection\*(Aqs file descriptors \fIsynchronously\fR\&. It takes the Varlink connection object, a JSON object with the reply parameters (which may be \fBNULL\fR), and two output pointers for the file descriptors\&. The \fIparameters\fR object is validated against the method\*(Aqs 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 \fBclose\fR(2)\&. .PP The returned file descriptors are switched to blocking mode\&. For bidirectional sockets a single underlying file descriptor carries both directions; in this case \fIret_input_fd\fR and \fIret_output_fd\fR 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 \fIret_input_fd\fR or \fIret_output_fd\fR (but not both) may be \fBNULL\fR; in that case the unwanted direction is shut down (if they refer to the same socket, see \fBshutdown\fR(2)) or closed (if separate file descriptors) rather than returned\&. .PP Note that \fBsd_varlink_reply_and_upgrade()\fR 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 \fBsd_varlink_respond_and_upgrade()\fR in that case instead\&. .PP \fBsd_varlink_respond_and_upgrade()\fR is the \fIasynchronous\fR counterpart of \fBsd_varlink_reply_and_upgrade()\fR\&. 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 \fBsd_varlink_process\fR(3) invocations\&. Once the reply has been fully flushed, the connection\*(Aqs file descriptors are handed to the upgrade callback previously registered with \fBsd_varlink_bind_upgrade()\fR, 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\&. .PP \fBsd_varlink_respond_and_upgradeb()\fR is similar to \fBsd_varlink_respond_and_upgrade()\fR, but instead of expecting a fully constructed \fBsd_json_variant\fR object carrying the reply parameters, this object is constructed on\-the\-fly from the variadic argument list, in a style identical to \fBsd_json_build\fR(3)\&. \fBsd_varlink_respond_and_upgradebo()\fR is identical to \fBsd_varlink_respond_and_upgradeb()\fR, 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 \fBsd_json_buildo\fR(3)\&. .PP \fBsd_varlink_bind_upgrade()\fR registers the upgrade \fIcallback\fR that is invoked once a reply enqueued via \fBsd_varlink_respond_and_upgrade()\fR (or one of its variants) has been flushed to the connection\&. The callback is of type \fBsd_varlink_upgrade_t\fR 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 \fBsd_varlink_set_userdata\fR(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 \fBsd_varlink_reply_and_upgrade()\fR above\&. Passing \fBNULL\fR as \fIcallback\fR removes a previously registered callback\&. .SH "RETURN VALUE" .PP On success, \fBsd_varlink_reply_and_upgrade()\fR, \fBsd_varlink_respond_and_upgrade()\fR, \fBsd_varlink_respond_and_upgradeb()\fR and \fBsd_varlink_respond_and_upgradebo()\fR return a positive integer\&. \fBsd_varlink_bind_upgrade()\fR returns a non\-negative integer on success\&. On failure, they all return a negative errno\-style error code\&. .SS "Errors" .PP Returned errors may indicate the following problems: .PP \fB\-EINVAL\fR .RS 4 An argument is invalid\&. .RE .PP \fB\-ENOTCONN\fR .RS 4 The Varlink connection object is not connected\&. .RE .PP \fB\-EBUSY\fR .RS 4 The connection is not currently processing a method call, so there is no reply to send\&. When returned by \fBsd_varlink_bind_upgrade()\fR, a different upgrade callback was already registered on the connection\&. .RE .PP \fB\-EPROTO\fR .RS 4 The currently processed method call did not request a protocol upgrade, hence the connection may not be taken over\&. .RE .PP \fB\-EBADMSG\fR .RS 4 The client sent unexpected data before the upgrade completed, i\&.e\&. it pipelined raw protocol data before receiving the upgrade reply\&. .RE .PP \fB\-ENOMEM\fR .RS 4 Memory allocation failed\&. .RE .SH "NOTES" .PP Functions described here are available as a shared library, which can be compiled against and linked to with the \fBlibsystemd\fR\ \&\fBpkg-config\fR(1) file\&. .PP The code described here uses \fBgetenv\fR(3), which is declared to be not multi\-thread\-safe\&. This means that the code calling the functions described here must not call \fBsetenv\fR(3) from a parallel thread\&. It is recommended to only do calls to \fBsetenv()\fR from an early phase of the program when no other threads have been started\&. .SH "HISTORY" .PP \fBsd_varlink_reply_and_upgrade()\fR was added in version 261\&. .PP \fBsd_varlink_respond_and_upgrade()\fR, \fBsd_varlink_respond_and_upgradeb()\fR, \fBsd_varlink_respond_and_upgradebo()\fR and \fBsd_varlink_bind_upgrade()\fR were added in version 262\&. .SH "SEE ALSO" .PP \fBsystemd\fR(1), \fBsd-varlink\fR(3), \fBsd_varlink_reply\fR(3), \fBsd_varlink_call\fR(3), \fBsd_varlink_call_and_upgrade\fR(3), \fBsd_varlink_process\fR(3), \fBsd_varlink_set_userdata\fR(3), \fBsd_json_build\fR(3)