From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=60735 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PIAAX-0006hZ-Vq for qemu-devel@nongnu.org; Mon, 15 Nov 2010 20:17:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PIAAU-0006yE-0N for qemu-devel@nongnu.org; Mon, 15 Nov 2010 20:17:09 -0500 Received: from e2.ny.us.ibm.com ([32.97.182.142]:35569) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PIAAT-0006y9-S1 for qemu-devel@nongnu.org; Mon, 15 Nov 2010 20:17:05 -0500 Received: from d01relay07.pok.ibm.com (d01relay07.pok.ibm.com [9.56.227.147]) by e2.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id oAG10wLC008542 for ; Mon, 15 Nov 2010 20:00:58 -0500 Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay07.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id oAG1H5e72027746 for ; Mon, 15 Nov 2010 20:17:05 -0500 Received: from d01av01.pok.ibm.com (loopback [127.0.0.1]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id oAG1H5FY028522 for ; Mon, 15 Nov 2010 20:17:05 -0500 From: Michael Roth Date: Mon, 15 Nov 2010 19:16:09 -0600 Message-Id: <1289870175-14880-16-git-send-email-mdroth@linux.vnet.ibm.com> In-Reply-To: <1289870175-14880-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1289870175-14880-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC][PATCH v3 15/21] virtproxy: add read handler for proxied connections List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: agl@linux.vnet.ibm.com, abeekhof@redhat.com, mdroth@linux.vnet.ibm.com, aliguori@linux.vnet.ibm.com, ryanh@us.ibm.com, amit.shah@redhat.com reads data from client/server connections as they become readable, then sends the data over the channel Signed-off-by: Michael Roth --- virtproxy.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ virtproxy.h | 1 + 2 files changed, 115 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 9e1745f..f1f6859 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -37,6 +37,40 @@ #define VP_CHAN_DATA_LEN 4096 /* max bytes channel can send at a time */ #define VP_MAGIC 0x1F374059 +QemuOptsList vp_opts = { + .name = "vpargs", + .head = QTAILQ_HEAD_INITIALIZER(vp_opts.head), + .desc = { + { + .name = "service_id", + .type = QEMU_OPT_STRING, + },{ + .name = "channel_method", + .type = QEMU_OPT_STRING, + },{ + .name = "index", + .type = QEMU_OPT_NUMBER, + },{ + .name = "path", + .type = QEMU_OPT_STRING, + },{ + .name = "host", + .type = QEMU_OPT_STRING, + },{ + .name = "port", + .type = QEMU_OPT_STRING, + },{ + .name = "ipv4", + .type = QEMU_OPT_BOOL, + },{ + .name = "ipv6", + .type = QEMU_OPT_BOOL, + }, + { /* end of list */ } + }, +}; + + /* listening fd, one for each service we're forwarding to remote end */ typedef struct VPOForward { VPDriver *drv; @@ -233,6 +267,86 @@ static VPIForward *get_iforward(const VPDriver *drv, const char *service_id) return NULL; } +/* read handler for proxied connections */ +static void vp_conn_read(void *opaque) +{ + VPConn *conn = opaque; + VPDriver *drv = conn->drv; + VPPacket pkt; + char buf[VP_CONN_DATA_LEN]; + int fd, count, ret; + bool client; + + TRACE("called with opaque: %p, drv: %p", opaque, drv); + + if (conn->state != VP_STATE_CONNECTED) { + LOG("invalid connection state"); + return; + } + + if (conn->type != VP_CONN_CLIENT && conn->type != VP_CONN_SERVER) { + LOG("invalid connection type"); + return; + } + + /* TODO: all fields should be explicitly set so we shouldn't + * need to memset. this might hurt if we beef up VPPacket size + */ + memset(&pkt, 0, sizeof(VPPacket)); + pkt.magic = VP_MAGIC; + + if (conn->type == VP_CONN_CLIENT) { + client = true; + fd = conn->client_fd; + } else { + client = false; + fd = conn->server_fd; + } + + count = read(fd, buf, VP_CONN_DATA_LEN); + if (count == -1) { + LOG("read() failed: %s", strerror(errno)); + return; + } else if (count == 0) { + /* connection closed, tell remote end to clean up */ + TRACE("connection closed"); + pkt.type = VP_PKT_CONTROL; + pkt.payload.msg.type = VP_CONTROL_CLOSE; + if (client) { + /* we're closing the client, have remote close the server conn */ + TRACE("closing connection for client fd %d", conn->client_fd); + pkt.payload.msg.args.close.client_fd = -1; + pkt.payload.msg.args.close.server_fd = conn->server_fd; + } else { + TRACE("closing connection for server fd %d", conn->server_fd); + pkt.payload.msg.args.close.server_fd = -1; + pkt.payload.msg.args.close.client_fd = conn->client_fd;; + } + /* clean up things on our end */ + closesocket(fd); + vp_set_fd_handler(fd, NULL, NULL, NULL); + QLIST_REMOVE(conn, next); + qemu_free(conn); + } else { + TRACE("data read"); + pkt.type = client ? VP_PKT_CLIENT : VP_PKT_SERVER; + pkt.payload.proxied.client_fd = conn->client_fd; + pkt.payload.proxied.server_fd = conn->server_fd; + memcpy(pkt.payload.proxied.data, buf, count); + pkt.payload.proxied.bytes = count; + } + + ret = vp_channel_send_all(drv, (uint8_t*)&pkt, sizeof(VPPacket)); + if (ret == -1) { + LOG("error sending data over channel: %s", strerror(errno)); + return; + } + if (ret != sizeof(VPPacket)) { + TRACE("buffer full?"); + return; + } +} + /* accept handler for communication channel * * accept()s connection to communication channel (for sockets), and sets diff --git a/virtproxy.h b/virtproxy.h index 83cc905..ef168b0 100644 --- a/virtproxy.h +++ b/virtproxy.h @@ -23,6 +23,7 @@ enum vp_context { VP_CTX_CHARDEV, /* in qemu/host, channel is a virtproxy chardev */ VP_CTX_FD, /* in guest, channel is an FD */ }; +extern QemuOptsList vp_opts; /* wrappers for s/vp/qemu/ functions we need */ int vp_send_all(int fd, const void *buf, int len1); -- 1.7.0.4