[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v4 11/16] tools: add simple vchan-socket-proxy



On Tue, Jan 14, 2020 at 9:42 PM Marek Marczykowski-Górecki
<marmarek@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> Add a simple proxy for tunneling socket connection over vchan. This is
> based on existing vchan-node* applications, but extended with socket
> support. vchan-socket-proxy serves both as a client and as a server,
> depending on parameters. It can be used to transparently communicate
> with an application in another domian that normally expose UNIX socket
> interface. Specifically, it's written to communicate with qemu running
> within stubdom.
>
> Server mode listens for vchan connections and when one is opened,
> connects to a pointed UNIX socket.  Client mode listens on UNIX
> socket and when someone connects, opens a vchan connection.  Only
> a single connection at a time is supported.
>
> Additionally, socket can be provided as a number - in which case it's
> interpreted as already open FD (in case of UNIX listening socket -
> listen() needs to be already called). Or "-" meaning stdin/stdout - in
> which case it is reduced to vchan-node2 functionality.
>
> Example usage:
>
> 1. (in dom0) vchan-socket-proxy --mode=client <DOMID>
>     /local/domain/<DOMID>/data/vchan/1234 /run/qemu.(DOMID)
>
> 2. (in DOMID) vchan-socket-proxy --mode=server 0
>    /local/domain/<DOMID>/data/vchan/1234 /run/qemu.(DOMID)
>
> This will listen on /run/qemu.(DOMID) in dom0 and whenever connection is
> made, it will connect to DOMID, where server process will connect to
> /run/qemu.(DOMID) there. When client disconnects, vchan connection is
> terminated and server vchan-socket-proxy process also disconnects from
> qemu.
>
> Signed-off-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
> ---

Looks good.  A few typos and string updates below.

Reviewed-by: Jason Andryuk <jandryuk@xxxxxxxxx>

<snip>

> diff --git a/tools/libvchan/vchan-socket-proxy.c 
> b/tools/libvchan/vchan-socket-proxy.c
> new file mode 100644
> index 0000000..6b4ae09
> --- /dev/null
> +++ b/tools/libvchan/vchan-socket-proxy.c

<snip>

> +static void usage(char** argv)
> +{
> +    fprintf(stderr, "usage:\n"
> +        "\t%s [options] domainid nodepath [socket-path|file-no|-]\n"
> +        "\n"
> +        "options:\n"
> +        "\t-m, --mode=client|server - vchan connection mode\n"

Add "(client by default)"?

> +        "\t-m, --state-path=path - xenstore path where write \"running\" to 
> at startup\n"

-s is the short option here.

> +        "\t-v, --verbose - verbose logging\n"
> +        "\n"
> +        "client: client of a vchan connection, fourth parameter can be:\n"
> +        "\tsocket-path: listen on a UNIX socket at this path and connect to 
> vchan\n"
> +        "\t  whenever new connection is accepted;\n"
> +        "\t  handle multiple _subsequent_ connections, until terminated\n"
> +        "\tfile-no: except open FD of a socket in listen mode; otherwise 
> similar to socket-path\n"

Many of these lines are long and hard to read on 80 column terminals.

> +        "\t-: open vchan connection immediately and pass the data from 
> stdin/stdout;\n"
> +        "\t  terminate when vchan connection is closed\n"
> +        "server: server of a vchan connection, fourth parameter can be:\n"
> +        "\tsocket-path: connect to this UNIX socket when new vchan 
> connection is accepted\n"
> +        "\t  handle multiple _subsequent_ connections, until terminated\n"
> +        "\tfile-no: pass data to/from this FD; terminate when vchan 
> connection is closed\n"
> +        "\t-: pass data to/from stdin/stdout; terminatate when vchan 
> connection is closed\n",

s/terminatate/terminate/

> +        argv[0]);
> +    exit(1);
> +}
> +
> +#define BUFSIZE 8192
> +char inbuf[BUFSIZE];
> +char outbuf[BUFSIZE];
> +int insiz = 0;
> +int outsiz = 0;
> +int verbose = 0;
> +
> +static void vchan_wr(struct libxenvchan *ctrl) {
> +    int ret;
> +
> +    if (!insiz)
> +        return;
> +    ret = libxenvchan_write(ctrl, inbuf, insiz);
> +    if (ret < 0) {
> +        fprintf(stderr, "vchan write failed\n");
> +        exit(1);
> +    }
> +    if (verbose)
> +        fprintf(stderr, "written %d bytes to vchan\n", ret);

s/written/wrote/

> +    if (ret > 0) {
> +        insiz -= ret;
> +        memmove(inbuf, inbuf + ret, insiz);
> +    }
> +}
> +

<snip>

> +
> +int data_loop(struct libxenvchan *ctrl, int input_fd, int output_fd)
> +{
> +    int ret;
> +    int libxenvchan_fd;
> +    int max_fd;
> +
> +    libxenvchan_fd = libxenvchan_fd_for_select(ctrl);
> +    for (;;) {
> +        fd_set rfds;
> +        fd_set wfds;
> +        FD_ZERO(&rfds);
> +        FD_ZERO(&wfds);
> +
> +        max_fd = -1;
> +        if (input_fd != -1 && insiz != BUFSIZE) {
> +            FD_SET(input_fd, &rfds);
> +            if (input_fd > max_fd)
> +                max_fd = input_fd;
> +        }
> +        if (output_fd != -1 && outsiz) {
> +            FD_SET(output_fd, &wfds);
> +            if (output_fd > max_fd)
> +                max_fd = output_fd;
> +        }
> +        FD_SET(libxenvchan_fd, &rfds);
> +        if (libxenvchan_fd > max_fd)
> +            max_fd = libxenvchan_fd;
> +        ret = select(max_fd + 1, &rfds, &wfds, NULL, NULL);
> +        if (ret < 0) {
> +            perror("select");
> +            exit(1);
> +        }
> +        if (FD_ISSET(libxenvchan_fd, &rfds)) {
> +            libxenvchan_wait(ctrl);
> +            if (!libxenvchan_is_open(ctrl)) {
> +                if (verbose)
> +                    fprintf(stderr, "vchan client disconnected\n");
> +                while (outsiz)
> +                    socket_wr(output_fd);
> +                close(output_fd);
> +                close(input_fd);
> +                discard_buffers(ctrl);
> +                break;
> +            }
> +            vchan_wr(ctrl);
> +        }
> +
> +        /* socket_fd guaranteed to be != -1 */

Old comment?

> +        if (FD_ISSET(input_fd, &rfds)) {
> +            ret = read(input_fd, inbuf + insiz, BUFSIZE - insiz);
> +            if (ret < 0 && errno != EAGAIN)
> +                exit(1);
> +            if (verbose)
> +                fprintf(stderr, "from-unix: %.*s\n", ret, inbuf + insiz);
> +            if (ret == 0) {
> +                /* EOF on socket, write everything in the buffer and close 
> the
> +                 * socket */

Change to socket to input_fd?

> +                while (insiz) {
> +                    vchan_wr(ctrl);
> +                    libxenvchan_wait(ctrl);
> +                }
> +                close(input_fd);
> +                input_fd = -1;
> +                /* TODO: maybe signal the vchan client somehow? */
> +                break;
> +            }
> +            if (ret)
> +                insiz += ret;
> +            vchan_wr(ctrl);
> +        }
> +        if (FD_ISSET(output_fd, &wfds))
> +            socket_wr(output_fd);
> +        while (libxenvchan_data_ready(ctrl) && outsiz < BUFSIZE) {
> +            ret = libxenvchan_read(ctrl, outbuf + outsiz, BUFSIZE - outsiz);
> +            if (ret < 0)
> +                exit(1);
> +            if (verbose)
> +                fprintf(stderr, "from-vchan: %.*s\n", ret, outbuf + outsiz);
> +            outsiz += ret;
> +            socket_wr(output_fd);
> +        }
> +    }
> +    return 0;
> +}
> +

<snip>

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.