if (r < 0)
return r;
- r = varlink_server_serialize(m->varlink_server, f, fds);
+ r = varlink_server_serialize(m->varlink_server, /* name = */ NULL, f, fds);
+ if (r < 0)
+ return r;
+
+ r = varlink_server_serialize(m->metrics_varlink_server, "metrics", f, fds);
if (r < 0)
return r;
r = strv_extend(&m->subscribed_as_strv, val);
if (r < 0)
return r;
- } else if ((val = startswith(l, "varlink-server-socket-address="))) {
+ } else if ((val = startswith(l, "varlink-server-metrics-"))) {
+ if (m->objective == MANAGER_RELOAD)
+ /* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
+ continue;
+
+ r = manager_setup_varlink_metrics_server(m);
+ if (r < 0)
+ log_warning_errno(r, "Failed to setup metrics varlink server, ignoring: %m");
+ else
+ (void) varlink_server_deserialize_one(m->metrics_varlink_server, val, fds);
+
+ } else if ((val = startswith(l, "varlink-server-"))) {
if (m->objective == MANAGER_RELOAD)
/* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */
continue;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include "sd-event.h"
-
#include "alloc-util.h"
+#include "extract-word.h"
+#include "fd-util.h"
#include "fdset.h"
#include "log.h"
-#include "parse-util.h"
+#include "serialize.h"
#include "socket-util.h"
#include "string-util.h"
#include "varlink-internal.h"
#include "varlink-serialize.h"
-int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds) {
+int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds) {
assert(f);
assert(fds);
if (!s)
return 0;
- LIST_FOREACH(sockets, ss, s->sockets) {
- int copy;
+ const char *prefix = name ? strjoina("varlink-server-", name) : "varlink-server";
+ LIST_FOREACH(sockets, ss, s->sockets) {
assert(ss->address);
assert(ss->fd >= 0);
- fprintf(f, "varlink-server-socket-address=%s", ss->address);
-
/* If we fail to serialize the fd, it will be considered an error during deserialization */
- copy = fdset_put_dup(fds, ss->fd);
+ int copy = fdset_put_dup(fds, ss->fd);
if (copy < 0)
return copy;
- fprintf(f, " varlink-server-socket-fd=%i", copy);
-
- fputc('\n', f);
+ fprintf(f, "%s-socket-address=%s varlink-server-socket-fd=%d\n", prefix, ss->address, copy);
}
return 0;
}
int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds) {
- _cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
_cleanup_free_ char *address = NULL;
- const char *v = ASSERT_PTR(value);
- int r, fd = -EBADF;
- char *buf;
- size_t n;
+ _cleanup_close_ int fd = -EBADF;
+ const char *v;
+ int r;
+
+ /* This function expects a serialization line with "varlink-server(-name)-" prefix stripped! */
assert(s);
+ assert(value);
assert(fds);
- n = strcspn(v, " ");
- address = strndup(v, n);
- if (!address)
- return log_oom_debug();
-
- if (v[n] != ' ')
- return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL),
- "Failed to deserialize sd_varlink_server_socket: %s", value);
- v = startswith(v + n + 1, "varlink-server-socket-fd=");
+ v = startswith(value, "socket-address=");
if (!v)
- return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL),
- "Failed to deserialize VarlinkServerSocket fd: %s", value);
-
- n = strcspn(v, " ");
- buf = strndupa_safe(v, n);
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid varlink server serialization entry: %s", value);
+
+ r = extract_first_word(&v, &address, " ", /* flags = */ 0);
+ if (r <= 0)
+ return varlink_server_log_errno(s, r < 0 ? r : SYNTHETIC_ERRNO(ENODATA),
+ "Failed to extract socket address from varlink serialization: %s", value);
+ if (v)
+ v = startswith(v, "varlink-server-socket-fd=");
+ if (!v)
+ return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
+ "Got varlink serialization without socket fd, refusing.");
- fd = parse_fd(buf);
+ fd = deserialize_fd(fds, v);
if (fd < 0)
- return varlink_server_log_errno(s, fd, "Unable to parse VarlinkServerSocket varlink-server-socket-fd=%s: %m", buf);
- if (!fdset_contains(fds, fd))
- return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF),
- "VarlinkServerSocket varlink-server-socket-fd= has unknown fd: %d", fd);
+ return varlink_server_log_errno(s, fd, "Failed to deserialize varlink socket fd: %m");
+ /* NB: varlink_server_socket_free() does not close the fd! */
+ _cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
ss = new(VarlinkServerSocket, 1);
if (!ss)
return log_oom_debug();
*ss = (VarlinkServerSocket) {
.server = s,
.address = TAKE_PTR(address),
- .fd = fdset_remove(fds, fd),
+ .fd = fd,
};
r = varlink_server_add_socket_event_source(s, ss);
return varlink_server_log_errno(s, r, "Failed to add VarlinkServerSocket event source to the event loop: %m");
LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss));
+ TAKE_FD(fd); /* ownership is now transferred to varlink server */
+
return 0;
}