[Spice-devel] [PATCH spice 5/9] reds-stream: add send_msgfd()

Frediano Ziglio fziglio at redhat.com
Fri Dec 11 03:48:43 PST 2015


> 
> 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?

> +    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).

> +    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?

> +    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?

> +    }
> +
> +    do {
> +        r = sendmsg(stream->socket, &msgh, 0);

MSG_NOSIGNAL as flag?

> +    } 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,

Frediano


More information about the Spice-devel mailing list