size_t input_buffer_size;
size_t input_buffer_unscanned;
+ void *input_control_buffer;
+ size_t input_control_buffer_size;
+
char *output_buffer; /* valid data starts at output_buffer_index, ends at output_buffer_index+output_buffer_size */
size_t output_buffer_index;
size_t output_buffer_size;
v->input_buffer = mfree(v->input_buffer);
v->output_buffer = v->output_buffer_sensitive ? erase_and_free(v->output_buffer) : mfree(v->output_buffer);
+ v->input_control_buffer = mfree(v->input_control_buffer);
+ v->input_control_buffer_size = 0;
+
varlink_clear_current(v);
close_many(v->output_fds, v->n_output_fds);
#define VARLINK_FDS_MAX (16U*1024U)
static int varlink_read(Varlink *v) {
- CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int) * VARLINK_FDS_MAX)) control;
struct iovec iov;
struct msghdr mh;
size_t rs;
rs = MALLOC_SIZEOF_SAFE(v->input_buffer) - (v->input_buffer_index + v->input_buffer_size);
if (v->allow_fd_passing_input) {
- iov = (struct iovec) {
- .iov_base = p,
- .iov_len = rs,
- };
+ iov = IOVEC_MAKE(p, rs);
+
+ /* Allocate the fd buffer on the heap, since we need a lot of space potentially */
+ if (!v->input_control_buffer) {
+ v->input_control_buffer_size = CMSG_SPACE(sizeof(int) * VARLINK_FDS_MAX);
+ v->input_control_buffer = malloc(v->input_control_buffer_size);
+ if (!v->input_control_buffer)
+ return -ENOMEM;
+ }
+
mh = (struct msghdr) {
.msg_iov = &iov,
.msg_iovlen = 1,
- .msg_control = &control,
- .msg_controllen = sizeof(control),
+ .msg_control = v->input_control_buffer,
+ .msg_controllen = v->input_control_buffer_size,
};
+
n = recvmsg_safe(v->fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
} else {
bool prefer_read = v->prefer_read_write;
return events;
r = fd_wait_for_event(fd, events, t);
- if (r < 0 && ERRNO_IS_TRANSIENT(r)) /* Treat EINTR as not a timeout, but also nothing happened, and
- * the caller gets a chance to call back into us */
+ if (ERRNO_IS_NEG_TRANSIENT(r)) /* Treat EINTR as not a timeout, but also nothing happened, and
+ * the caller gets a chance to call back into us */
return 1;
if (r <= 0)
return r;
}
r = fd_wait_for_event(v->fd, POLLOUT, USEC_INFINITY);
- if (r < 0) {
- if (ERRNO_IS_TRANSIENT(r))
- continue;
-
+ if (ERRNO_IS_NEG_TRANSIENT(r))
+ continue;
+ if (r < 0)
return varlink_log_errno(v, r, "Poll failed on fd: %m");
- }
-
- assert(r != 0);
+ assert(r > 0);
handle_revents(v, r);
}
return r;
}
- if (listen(fd, SOMAXCONN) < 0)
+ if (listen(fd, SOMAXCONN_DELUXE) < 0)
return -errno;
r = varlink_server_create_listen_fd_socket(s, fd, &ss);