diff --git a/src/brei-shared.c b/src/brei-shared.c index 67b8671..027af13 100644 --- a/src/brei-shared.c +++ b/src/brei-shared.c @@ -31,6 +31,21 @@ #include "proto/ei.pb-c.h" #include "brei-shared.h" +struct brei_message_private { + struct brei_message base; + int *fd; +}; + +int +brei_message_take_fd(struct brei_message *m) +{ + struct brei_message_private *msg = (struct brei_message_private*)m; + + int fd = *msg->fd; + *msg->fd = -1; + return fd; +} + static void frame_cleanup(Frame **f) { if (*f) frame__free_unpacked(*f, NULL); @@ -80,7 +95,7 @@ brei_dispatch(int fd, void *user_data) { _cleanup_iobuf_ struct iobuf *buf = iobuf_new(64); - int rc = iobuf_append_from_fd(buf, fd); + int rc = iobuf_recv_from_fd(buf, fd); if (rc == -EAGAIN) { return 0; } else if (rc == 0) { @@ -90,6 +105,7 @@ brei_dispatch(int fd, goto error; } + _cleanup_close_ int recvfd = -1; size_t idx = 0; while (true) { const char *data = iobuf_data(buf) + idx; @@ -105,13 +121,23 @@ brei_dispatch(int fd, assert(len >= msglen); - struct brei_message msg = { - .data = msgdata, - .len = msglen, + /* This is a bit messy because it's just blu tacked on. + * Our protocol passes maximum of one fd per message. We + * take whatever next fd is and pass it along. Where the + * parser takes it (brei_message_take_fd()) it gets set to + * -1 and we take the next fd for the next message. + */ + if (recvfd == -1) + recvfd = iobuf_take_fd(buf); + + struct brei_message_private msg = { + .base.data = msgdata, + .base.len = msglen, + .fd = &recvfd, }; /* Actual message parsing is done by the caller */ - consumed = callback(&msg, user_data); + consumed = callback(&msg.base, user_data); assert(consumed != 0); if (consumed < 0) { rc = consumed; diff --git a/src/brei-shared.h b/src/brei-shared.h index 8f07109..80c3899 100644 --- a/src/brei-shared.h +++ b/src/brei-shared.h @@ -30,6 +30,17 @@ struct brei_message { size_t len; }; +/** + * Return the first file descriptor passed along with this message, or -1. + * You must only call this when a message is supposed to have an fd. + * + * Brei can not determine which message an fd belongs to, hence calling this + * function for a non-fd-carrying message will take that fd away from the + * message that fd actually belongs to. + */ +int +brei_message_take_fd(struct brei_message *b); + /** * Dispatch messages for the data on fd. * The callback is called for each protocol message, parsing must be done by