summaryrefslogtreecommitdiff
path: root/vnc.c
diff options
context:
space:
mode:
authorbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2008-02-03 02:54:04 +0000
committerbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2008-02-03 02:54:04 +0000
commit3aa3eea310318553c853c07f78690a540f7ed94c (patch)
treee53e1049460e4d15a880963853fbe253a59931ac /vnc.c
parent3d575329a53ad3b72b07cea0d8f97ccc000df6ff (diff)
Add VNC reverse connections, by Eddie Kohler.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3951 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'vnc.c')
-rw-r--r--vnc.c54
1 files changed, 40 insertions, 14 deletions
diff --git a/vnc.c b/vnc.c
index 64889de5a6..e7f3255c88 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1898,6 +1898,22 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
return 0;
}
+static void vnc_connect(VncState *vs)
+{
+ VNC_DEBUG("New client on socket %d\n", vs->csock);
+ socket_set_nonblock(vs->csock);
+ qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+ vnc_write(vs, "RFB 003.008\n", 12);
+ vnc_flush(vs);
+ vnc_read_when(vs, protocol_version, 12);
+ memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
+ memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
+ vs->has_resize = 0;
+ vs->has_hextile = 0;
+ vs->ds->dpy_copy = NULL;
+ vnc_update_client(vs);
+}
+
static void vnc_listen_read(void *opaque)
{
VncState *vs = opaque;
@@ -1909,18 +1925,7 @@ static void vnc_listen_read(void *opaque)
vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
if (vs->csock != -1) {
- VNC_DEBUG("New client on socket %d\n", vs->csock);
- socket_set_nonblock(vs->csock);
- qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
- vnc_write(vs, "RFB 003.008\n", 12);
- vnc_flush(vs);
- vnc_read_when(vs, protocol_version, 12);
- memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
- memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
- vs->has_resize = 0;
- vs->has_hextile = 0;
- vs->ds->dpy_copy = NULL;
- vnc_update_client(vs);
+ vnc_connect(vs);
}
}
@@ -2087,6 +2092,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
const char *options;
int password = 0;
+ int reverse = 0;
#if CONFIG_VNC_TLS
int tls = 0, x509 = 0;
#endif
@@ -2103,6 +2109,8 @@ int vnc_display_open(DisplayState *ds, const char *display)
options++;
if (strncmp(options, "password", 8) == 0) {
password = 1; /* Require password auth */
+ } else if (strncmp(options, "reverse", 7) == 0) {
+ reverse = 1;
#if CONFIG_VNC_TLS
} else if (strncmp(options, "tls", 3) == 0) {
tls = 1; /* Require TLS */
@@ -2196,7 +2204,9 @@ int vnc_display_open(DisplayState *ds, const char *display)
memset(uaddr.sun_path, 0, 108);
snprintf(uaddr.sun_path, 108, "%s", p);
- unlink(uaddr.sun_path);
+ if (!reverse) {
+ unlink(uaddr.sun_path);
+ }
} else
#endif
{
@@ -2210,7 +2220,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
return -1;
}
- iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
+ iaddr.sin_port = htons(ntohs(iaddr.sin_port) + (reverse ? 0 : 5900));
vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
if (vs->lsock == -1) {
@@ -2233,6 +2243,22 @@ int vnc_display_open(DisplayState *ds, const char *display)
}
}
+ if (reverse) {
+ if (connect(vs->lsock, addr, addrlen) == -1) {
+ fprintf(stderr, "Connection to VNC client failed\n");
+ close(vs->lsock);
+ vs->lsock = -1;
+ free(vs->display);
+ vs->display = NULL;
+ return -1;
+ } else {
+ vs->csock = vs->lsock;
+ vs->lsock = -1;
+ vnc_connect(vs);
+ return 0;
+ }
+ }
+
if (bind(vs->lsock, addr, addrlen) == -1) {
fprintf(stderr, "bind() failed\n");
close(vs->lsock);