[Libguestfs] [PATCH libnbd] python: Implement nbd.aio_connect for AF_UNIX

Eric Blake eblake at redhat.com
Wed Jun 30 21:38:33 UTC 2021


On Wed, Jun 30, 2021 at 08:22:19PM +0100, Richard W.M. Jones wrote:
> This call previously just called abort().  Implement it for Unix
> domain sockets (the easy case).  Implementing it for AF_INET and
> AF_INET6 is more complicated so that is left as a to-do.

Still, fixing it to return an error instead of abort()ing is nice.

> 
> Note also that implementing this fully for Python is a bit pointless.
> It would be easier for a Python program to call
> nbd.aio_connect_tcp(host, port) instead of calling
> nbd.aio_connect((host, port)).  Both cases would do hostname lookups
> but the former is already implemented.
> ---

> @@ -92,3 +94,64 @@ nbd_internal_py_free_string_list (char **argv)
>      free (argv[i]);
>    free (argv);
>  }
> +
> +/* Convert a Python object into a struct sockaddr, according to the
> + * general rules described here:
> + * https://docs.python.org/3/library/socket.html

Python's representation is complex!

> + *
> + * There is a function in cpython called getsockaddrarg which roughly
> + * does the same thing, but in cpython they know the socket family
> + * already (which we do not).  In any case that function cannot be
> + * called directly.
> + */
> +int
> +nbd_internal_py_get_sockaddr (PyObject *addr,
> +                              struct sockaddr_storage *ss, socklen_t *len)
> +{
> +  memset (ss, 0, sizeof *ss);
> +
> +  if (PyUnicode_Check (addr)) { /* AF_UNIX */
> +    struct sockaddr_un *sun = (struct sockaddr_un *)ss;
> +    const char *unixsocket;
> +    size_t namelen;
> +
> +    sun->sun_family = AF_UNIX;
> +    unixsocket = PyUnicode_AsUTF8 (addr);
> +    if (!unixsocket)
> +      goto err;

Given the PyUnicode_Check() call above, this is unlikely to fail; but
checking for failure anyway is good practice.

> +    namelen = strlen (unixsocket);
> +    if (namelen > sizeof sun->sun_path) {
> +      PyErr_SetString (PyExc_RuntimeError,
> +                       "get_sockaddr: Unix domain socket name too long");
> +      return -1;
> +    }
> +    memcpy (sun->sun_path, unixsocket, namelen);
> +    *len = sizeof *sun;
> +    return 0;
> +  }
> +
> +#if 0
> +  else if (PyTuple_Check (addr)) {
> +    Py_ssize_t n = PyTuple_Size (addr);
> +
> +    switch (n) {
> +    case 2:                     /* AF_INET */
> +      /* XXX TODO */
> +      break;
> +
> +    case 4:                     /* AF_INET6 */
> +      /* XXX TODO */
> +      break;

The python docs implied that the last two fields were optional for
AF_INET6, which makes this even more complicated.  But this is all #if
0 until someone needs and implements it anyway.

Patch looks good to me.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




More information about the Libguestfs mailing list