[Spice-devel] [PATCH spice 5/9] reds-stream: add send_msgfd()
Marc-André Lureau
mlureau at redhat.com
Fri Dec 11 04:06:00 PST 2015
Hi
----- Original Message -----
> >
> > From: Marc-André Lureau <mlureau at redhat.com>
> >
> > A new function to send fd with unix socket anciliary data.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau at gmail.com>
> > ---
> > server/reds-stream.c | 42 ++++++++++++++++++++++++++++++++++++++++++
> > server/reds-stream.h | 1 +
> > 2 files changed, 43 insertions(+)
> >
> > diff --git a/server/reds-stream.c b/server/reds-stream.c
> > index d87cb23..4829b43 100644
> > --- a/server/reds-stream.c
> > +++ b/server/reds-stream.c
> > @@ -28,6 +28,7 @@
> > #include <netdb.h>
> > #include <unistd.h>
> > #include <sys/socket.h>
> > +#include <fcntl.h>
> >
> > #include <glib.h>
> >
> > @@ -254,6 +255,47 @@ int reds_stream_is_plain_unix(const RedsStream *s)
> >
> > }
> >
> > +int reds_stream_send_msgfd(RedsStream *stream, int fd)
> > +{
> > + struct msghdr msgh;
> > + struct iovec iov;
> > + int r;
> > +
> > + size_t fd_size = 1 * sizeof(int);
>
> const here?
Yeah, I am not that strict about internal variables. Sure why not?
>
> > + char control[CMSG_SPACE(fd_size)];
>
> This would be better to be an union of data and struct cmsghdr, something
> like
>
> union {
> struct cmsghdr hdr;
> char data[CMSG_SPACE(fd_size)];
> } control;
>
> (of course this needs some other changes in the code).
Ok
>
> > + struct cmsghdr *cmsg;
> > +
> > + spice_return_val_if_fail(reds_stream_is_plain_unix(stream), -1);
> > +
> > + memset(&msgh, 0, sizeof(msgh));
> > + memset(control, 0, sizeof(control));
> > + /* set the payload */
> > + iov.iov_base = (char*)"@";
>
> is the cast required?
yes, "assignment discards 'const' qualifier from pointer target type"
>
> > + iov.iov_len = 1;
> > +
> > + if (fd != -1) {
> > + msgh.msg_iovlen = 1;
> > + msgh.msg_iov = &iov;
> > + msgh.msg_control = control;
> > + msgh.msg_controllen = sizeof(control);
> > +
> > + cmsg = CMSG_FIRSTHDR(&msgh);
> > +
> > + cmsg->cmsg_len = CMSG_LEN(fd_size);
> > + cmsg->cmsg_level = SOL_SOCKET;
> > + cmsg->cmsg_type = SCM_RIGHTS;
> > + memcpy(CMSG_DATA(cmsg), &fd, fd_size);
> > + } else {
> > + msgh.msg_iovlen = 0;
>
> So you don't send nothing if no file descriptor is passes?
> How do you handle the read on the other end?
The read of one byte takes place, but no fd get through. The client should not always expect a fd with the msg, depending on the msg. For SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX, it's possible to send no fd to "unset" the current scanout.
> > + }
> > +
> > + do {
> > + r = sendmsg(stream->socket, &msgh, 0);
>
> MSG_NOSIGNAL as flag?
Why not? does that really change something here?
>
> > + } while (r < 0 && (errno == EINTR || errno == EAGAIN));
> > +
> > + return r;
> > +}
> > +
> > ssize_t reds_stream_writev(RedsStream *s, const struct iovec *iov, int
> > iovcnt)
> > {
> > int i;
> > diff --git a/server/reds-stream.h b/server/reds-stream.h
> > index 9e53b22..72e5dd1 100644
> > --- a/server/reds-stream.h
> > +++ b/server/reds-stream.h
> > @@ -74,6 +74,7 @@ int reds_stream_enable_ssl(RedsStream *stream, SSL_CTX
> > *ctx);
> > void reds_stream_set_info_flag(RedsStream *stream, unsigned int flag);
> > int reds_stream_get_family(const RedsStream *stream);
> > int reds_stream_is_plain_unix(const RedsStream *stream);
> > +int reds_stream_send_msgfd(RedsStream *stream, int fd);
> >
> > typedef enum {
> > REDS_SASL_ERROR_OK,
thanks for the review
More information about the Spice-devel
mailing list