Xen-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Rich Persaud <persaur@gmail.com>
To: "Marek Marczykowski-Górecki" <marmarek@invisiblethingslab.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>,
	Julien Grall <julien@xen.org>, Wei Liu <wl@xen.org>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	George Dunlap <George.Dunlap@eu.citrix.com>,
	Andrew Cooper <Andrew.Cooper3@citrix.com>,
	Ian Jackson <Ian.Jackson@eu.citrix.com>,
	Jan Beulich <JBeulich@suse.com>,
	xen-devel@lists.xenproject.org
Subject: Re: [Xen-devel] [PATCH v4 11/16] tools: add simple vchan-socket-proxy
Date: Fri, 17 Jan 2020 13:44:20 -0500
Message-ID: <887B9537-ABB7-459E-9E99-50AD4DDDBFE2@gmail.com> (raw)
In-Reply-To: <ce51dd78fd7aa0856d160b2d94c82f68dd4e7056.1579055705.git-series.marmarek@invisiblethingslab.com>

On Jan 14, 2020, at 21:42, Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> wrote:
> 
> diff --git a/tools/libvchan/Makefile b/tools/libvchan/Makefile
> index 7892750..1c845ca 100644
> --- a/tools/libvchan/Makefile
> +++ b/tools/libvchan/Makefile
> @@ -13,6 +13,7 @@ LIBVCHAN_PIC_OBJS = $(patsubst %.o,%.opic,$(LIBVCHAN_OBJS))
> LIBVCHAN_LIBS = $(LDLIBS_libxenstore) $(LDLIBS_libxengnttab) $(LDLIBS_libxenevtchn)
> $(LIBVCHAN_OBJS) $(LIBVCHAN_PIC_OBJS): CFLAGS += $(CFLAGS_libxenstore) $(CFLAGS_libxengnttab) $(CFLAGS_libxenevtchn)
> $(NODE_OBJS) $(NODE2_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxenevtchn)
> +vchan-socket-proxy.o: CFLAGS += $(CFLAGS_libxenstore) $(CFLAGS_libxenctrl) $(CFLAGS_libxengnttab) $(CFLAGS_libxenevtchn)
> 
> MAJOR = 4.14
> MINOR = 0
> @@ -39,7 +40,7 @@ $(PKG_CONFIG_LOCAL): PKG_CONFIG_LIBDIR = $(CURDIR)
> $(PKG_CONFIG_LOCAL): PKG_CONFIG_CFLAGS_LOCAL = $(CFLAGS_xeninclude)
> 
> .PHONY: all
> -all: libxenvchan.so vchan-node1 vchan-node2 libxenvchan.a $(PKG_CONFIG_INST) $(PKG_CONFIG_LOCAL)
> +all: libxenvchan.so vchan-node1 vchan-node2 vchan-socket-proxy libxenvchan.a $(PKG_CONFIG_INST) $(PKG_CONFIG_LOCAL)
> 
> libxenvchan.so: libxenvchan.so.$(MAJOR)
>    ln -sf $< $@
> @@ -59,6 +60,9 @@ vchan-node1: $(NODE_OBJS) libxenvchan.so
> vchan-node2: $(NODE2_OBJS) libxenvchan.so
>    $(CC) $(LDFLAGS) -o $@ $(NODE2_OBJS) $(LDLIBS_libxenvchan) $(APPEND_LDFLAGS)
> 
> +vchan-socket-proxy: vchan-socket-proxy.o libxenvchan.so
> +    $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenvchan) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
> +
> .PHONY: install
> install: all
>    $(INSTALL_DIR) $(DESTDIR)$(libdir)
> @@ -66,6 +70,7 @@ install: all
>    $(INSTALL_PROG) libxenvchan.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
>    ln -sf libxenvchan.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenvchan.so.$(MAJOR)
>    ln -sf libxenvchan.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenvchan.so
> +    $(INSTALL_PROG) vchan-socket-proxy $(DESTDIR)$(bindir)

Does this need directory creation, to avoid vchan binary being named "bin"?
+       $(INSTALL_DIR) $(DESTDIR)$(bindir)


> 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
> @@ -0,0 +1,469 @@
> +/**
> + * @file
> + * @section AUTHORS
> + *
> + * Copyright (C) 2010  Rafal Wojtczuk  <rafal@invisiblethingslab.com>
> + *
> + *  Authors:
> + *       Rafal Wojtczuk  <rafal@invisiblethingslab.com>
> + *       Daniel De Graaf <dgdegra@tycho.nsa.gov>
> + *       Marek Marczykowski-Górecki  <marmarek@invisiblethingslab.com>
> + *
> + * @section LICENSE
> + *
> + *  This program is free software; you can redistribute it and/or
> + *  modify it under the terms of the GNU Lesser General Public
> + *  License as published by the Free Software Foundation; either
> + *  version 2.1 of the License, or (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + *  Lesser General Public License for more details.
> + *
> + *  You should have received a copy of the GNU Lesser General Public
> + *  License along with this program; If not, see <http://www.gnu.org/licenses/>.
> + *
> + * @section DESCRIPTION
> + *
> + * This is a vchan to unix socket proxy. Vchan server is set, and on client
> + * connection, local socket connection is established. Communication is bidirectional.
> + * One client is served at a time, clients needs to coordinate this themselves.
> + */
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <getopt.h>
> +
> +#include <xenstore.h>
> +#include <xenctrl.h>
> +#include <libxenvchan.h>
> +
> +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"
> +        "\t-m, --state-path=path - xenstore path where write \"running\" to at startup\n"
> +        "\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"
> +        "\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",
> +        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);
> +    if (ret > 0) {
> +        insiz -= ret;
> +        memmove(inbuf, inbuf + ret, insiz);
> +    }
> +}
> +
> +static void socket_wr(int output_fd) {
> +    int ret;
> +
> +    if (!outsiz)
> +        return;
> +    ret = write(output_fd, outbuf, outsiz);
> +    if (ret < 0 && errno != EAGAIN)
> +        exit(1);
> +    if (ret > 0) {
> +        outsiz -= ret;
> +        memmove(outbuf, outbuf + ret, outsiz);
> +    }
> +}
> +
> +static int set_nonblocking(int fd, int nonblocking) {
> +    int flags = fcntl(fd, F_GETFL);
> +    if (flags == -1)
> +        return -1;
> +
> +    if (nonblocking)
> +        flags |= O_NONBLOCK;
> +    else
> +        flags &= ~O_NONBLOCK;
> +
> +    if (fcntl(fd, F_SETFL, flags) == -1)
> +        return -1;
> +
> +    return 0;
> +}
> +
> +static int connect_socket(const char *path_or_fd) {
> +    int fd;
> +    char *endptr;
> +    struct sockaddr_un addr;
> +
> +    fd = strtoll(path_or_fd, &endptr, 0);
> +    if (*endptr == '\0') {
> +        set_nonblocking(fd, 1);
> +        return fd;
> +    }
> +
> +    fd = socket(AF_UNIX, SOCK_STREAM, 0);
> +    if (fd == -1)
> +        return -1;
> +
> +    addr.sun_family = AF_UNIX;
> +    strncpy(addr.sun_path, path_or_fd, sizeof(addr.sun_path));
> +    if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) == -1) {
> +        close(fd);
> +        return -1;
> +    }
> +
> +    set_nonblocking(fd, 1);
> +
> +    return fd;
> +}
> +
> +static int listen_socket(const char *path_or_fd) {
> +    int fd;
> +    char *endptr;
> +    struct sockaddr_un addr;
> +
> +    fd = strtoll(path_or_fd, &endptr, 0);
> +    if (*endptr == '\0') {
> +        return fd;
> +    }
> +
> +    /* if not a number, assume a socket path */
> +    fd = socket(AF_UNIX, SOCK_STREAM, 0);
> +    if (fd == -1)
> +        return -1;
> +
> +    addr.sun_family = AF_UNIX;
> +    strncpy(addr.sun_path, path_or_fd, sizeof(addr.sun_path));
> +    if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) == -1) {
> +        close(fd);
> +        return -1;
> +    }
> +    if (listen(fd, 5) != 0) {
> +        close(fd);
> +        return -1;
> +    }
> +
> +    return fd;
> +}
> +
> +static struct libxenvchan *connect_vchan(int domid, const char *path) {
> +    struct libxenvchan *ctrl = NULL;
> +    struct xs_handle *xs = NULL;
> +    xc_interface *xc = NULL;
> +    xc_dominfo_t dominfo;
> +    char **watch_ret;
> +    unsigned int watch_num;
> +    int ret;
> +
> +    xs = xs_open(XS_OPEN_READONLY);
> +    if (!xs) {
> +        perror("xs_open");
> +        goto out;
> +    }
> +    xc = xc_interface_open(NULL, NULL, XC_OPENFLAG_NON_REENTRANT);
> +    if (!xc) {
> +        perror("xc_interface_open");
> +        goto out;
> +    }
> +    /* wait for vchan server to create *path* */
> +    xs_watch(xs, path, "path");
> +    xs_watch(xs, "@releaseDomain", "release");
> +    while ((watch_ret = xs_read_watch(xs, &watch_num))) {
> +        /* don't care about exact which fired the watch */
> +        free(watch_ret);
> +        ctrl = libxenvchan_client_init(NULL, domid, path);
> +        if (ctrl)
> +            break;
> +
> +        ret = xc_domain_getinfo(xc, domid, 1, &dominfo);
> +        /* break the loop if domain is definitely not there anymore, but
> +         * continue if it is or the call failed (like EPERM) */
> +        if (ret == -1 && errno == ESRCH)
> +            break;
> +        if (ret == 1 && (dominfo.domid != (uint32_t)domid || dominfo.dying))
> +            break;
> +    }
> +
> +out:
> +    if (xc)
> +        xc_interface_close(xc);
> +    if (xs)
> +        xs_close(xs);
> +    return ctrl;
> +}
> +
> +
> +static void discard_buffers(struct libxenvchan *ctrl) {
> +    /* discard local buffers */
> +    insiz = 0;
> +    outsiz = 0;
> +
> +    /* discard remaining incoming data */
> +    while (libxenvchan_data_ready(ctrl)) {
> +        if (libxenvchan_read(ctrl, inbuf, BUFSIZE) == -1) {
> +            perror("vchan read");
> +            exit(1);
> +        }
> +    }
> +}
> +
> +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 */
> +
> +        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 */
> +                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;
> +}
> +
> +/**
> +    Simple libxenvchan application, both client and server.
> +    Both sides may write and read, both from the libxenvchan and from
> +    stdin/stdout (just like netcat).
> +*/
> +
> +static struct option options[] = {
> +    { "mode",       required_argument, NULL, 'm' },
> +    { "verbose",          no_argument, NULL, 'v' },
> +    { "state-path", required_argument, NULL, 's' },
> +    { }
> +};
> +
> +int main(int argc, char **argv)
> +{
> +    int is_server = 0;
> +    int socket_fd;

When compiled for OpenEmbedded / OpenXT, gcc complained about socket_fd being uninitialized before possible use.

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

  parent reply index

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-15  2:39 [Xen-devel] [PATCH v4 00/16] Add support for qemu-xen runnning in a Linux-based stubdomain Marek Marczykowski-Górecki
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 01/16] Document ioemu MiniOS stubdomain protocol Marek Marczykowski-Górecki
2020-01-20 18:30   ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 02/16] Document ioemu Linux " Marek Marczykowski-Górecki
2020-01-20 18:54   ` Jason Andryuk
2020-01-21 21:08     ` Marek Marczykowski-Górecki
2020-01-22 14:04       ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 03/16] libxl: fix qemu-trad cmdline for no sdl/vnc case Marek Marczykowski-Górecki
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 04/16] libxl: Allow running qemu-xen in stubdomain Marek Marczykowski-Górecki
2020-01-20 18:56   ` Jason Andryuk
2020-01-21 21:12     ` Marek Marczykowski-Górecki
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 05/16] libxl: Handle Linux stubdomain specific QEMU options Marek Marczykowski-Górecki
2020-01-20 19:24   ` Jason Andryuk
2020-01-21 21:18     ` Marek Marczykowski-Górecki
2020-01-22 14:25       ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 06/16] libxl: write qemu arguments into separate xenstore keys Marek Marczykowski-Górecki
2020-01-20 19:36   ` Jason Andryuk
2020-01-21 21:19     ` Marek Marczykowski-Górecki
2020-01-22 14:39       ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 07/16] xl: add stubdomain related options to xl config parser Marek Marczykowski-Górecki
2020-01-20 19:41   ` Jason Andryuk
2020-01-21 21:22     ` Marek Marczykowski-Górecki
2020-01-22 14:39       ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 08/16] tools/libvchan: notify server when client is connected Marek Marczykowski-Górecki
2020-01-20 19:44   ` Jason Andryuk
2020-01-21 21:28     ` Marek Marczykowski-Górecki
2020-01-22 14:43       ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 09/16] libxl: add save/restore support for qemu-xen in stubdomain Marek Marczykowski-Górecki
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 10/16] tools: add missing libxenvchan cflags Marek Marczykowski-Górecki
2020-01-20 19:58   ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 11/16] tools: add simple vchan-socket-proxy Marek Marczykowski-Górecki
2020-01-15 11:02   ` Jan Beulich
2020-01-16 17:11     ` Marek Marczykowski-Górecki
2020-01-17  8:13       ` Jan Beulich
2020-01-17 18:44   ` Rich Persaud [this message]
2020-01-17 18:56     ` Marek Marczykowski-Górecki
2020-01-21 19:43   ` Jason Andryuk
2020-01-21 23:09     ` Marek Marczykowski-Górecki
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 12/16] libxl: use vchan for QMP access with Linux stubdomain Marek Marczykowski-Górecki
2020-01-21 20:17   ` Jason Andryuk
2020-01-21 23:46     ` Marek Marczykowski-Górecki
2020-01-24 14:05       ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 13/16] Regenerate autotools files Marek Marczykowski-Górecki
2020-01-15 21:57   ` Rich Persaud
2020-01-21 20:56     ` Marek Marczykowski-Górecki
2020-01-21 21:28       ` Rich Persaud
2020-01-22  8:57         ` Lars Kurth
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 14/16] libxl: require qemu in dom0 even if stubdomain is in use Marek Marczykowski-Górecki
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 15/16] libxl: ignore emulated IDE disks beyond the first 4 Marek Marczykowski-Górecki
2020-01-21 20:24   ` Jason Andryuk
2020-01-15  2:39 ` [Xen-devel] [PATCH v4 16/16] libxl: consider also qemu in stubdomain in libxl__dm_active check Marek Marczykowski-Górecki
2020-01-21 20:25   ` Jason Andryuk
2020-01-22 16:50 ` [Xen-devel] [PATCH v4 00/16] Add support for qemu-xen runnning in a Linux-based stubdomain Jason Andryuk

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=887B9537-ABB7-459E-9E99-50AD4DDDBFE2@gmail.com \
    --to=persaur@gmail.com \
    --cc=Andrew.Cooper3@citrix.com \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=JBeulich@suse.com \
    --cc=julien@xen.org \
    --cc=konrad.wilk@oracle.com \
    --cc=marmarek@invisiblethingslab.com \
    --cc=sstabellini@kernel.org \
    --cc=wl@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Xen-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/xen-devel/0 xen-devel/git/0.git
	git clone --mirror https://lore.kernel.org/xen-devel/1 xen-devel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 xen-devel xen-devel/ https://lore.kernel.org/xen-devel \
		xen-devel@lists.xenproject.org xen-devel@lists.xen.org
	public-inbox-index xen-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.xenproject.lists.xen-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git