mirror of
https://github.com/qemu/qemu.git
synced 2024-11-30 15:23:34 +08:00
60e705c51c
Currently the QIOTaskFunc signature takes an Object * for the source, and an Error * for any error. We also need to be able to provide a result pointer. Rather than continue to add parameters to QIOTaskFunc, remove the existing ones and simply pass the QIOTask object instead. This has methods to access all the other data items required in the callback impl. Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
132 lines
3.8 KiB
C
132 lines
3.8 KiB
C
/*
|
|
* QEMU VNC display driver: Websockets support
|
|
*
|
|
* Copyright (C) 2010 Joel Martin
|
|
* Copyright (C) 2012 Tim Hardeck
|
|
*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This software 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this software; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "vnc.h"
|
|
#include "io/channel-websock.h"
|
|
#include "qemu/bswap.h"
|
|
|
|
static void vncws_tls_handshake_done(QIOTask *task,
|
|
gpointer user_data)
|
|
{
|
|
VncState *vs = user_data;
|
|
Error *err = NULL;
|
|
|
|
if (qio_task_propagate_error(task, &err)) {
|
|
VNC_DEBUG("Handshake failed %s\n", error_get_pretty(err));
|
|
vnc_client_error(vs);
|
|
error_free(err);
|
|
} else {
|
|
VNC_DEBUG("TLS handshake complete, starting websocket handshake\n");
|
|
vs->ioc_tag = qio_channel_add_watch(
|
|
QIO_CHANNEL(vs->ioc), G_IO_IN, vncws_handshake_io, vs, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
gboolean vncws_tls_handshake_io(QIOChannel *ioc G_GNUC_UNUSED,
|
|
GIOCondition condition G_GNUC_UNUSED,
|
|
void *opaque)
|
|
{
|
|
VncState *vs = opaque;
|
|
QIOChannelTLS *tls;
|
|
Error *err = NULL;
|
|
|
|
VNC_DEBUG("TLS Websocket connection required\n");
|
|
if (vs->ioc_tag) {
|
|
g_source_remove(vs->ioc_tag);
|
|
vs->ioc_tag = 0;
|
|
}
|
|
|
|
tls = qio_channel_tls_new_server(
|
|
vs->ioc,
|
|
vs->vd->tlscreds,
|
|
vs->vd->tlsaclname,
|
|
&err);
|
|
if (!tls) {
|
|
VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
|
|
error_free(err);
|
|
vnc_client_error(vs);
|
|
return TRUE;
|
|
}
|
|
|
|
qio_channel_set_name(QIO_CHANNEL(tls), "vnc-ws-server-tls");
|
|
|
|
VNC_DEBUG("Start TLS WS handshake process\n");
|
|
object_unref(OBJECT(vs->ioc));
|
|
vs->ioc = QIO_CHANNEL(tls);
|
|
vs->tls = qio_channel_tls_get_session(tls);
|
|
|
|
qio_channel_tls_handshake(tls,
|
|
vncws_tls_handshake_done,
|
|
vs,
|
|
NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static void vncws_handshake_done(QIOTask *task,
|
|
gpointer user_data)
|
|
{
|
|
VncState *vs = user_data;
|
|
Error *err = NULL;
|
|
|
|
if (qio_task_propagate_error(task, &err)) {
|
|
VNC_DEBUG("Websock handshake failed %s\n", error_get_pretty(err));
|
|
vnc_client_error(vs);
|
|
error_free(err);
|
|
} else {
|
|
VNC_DEBUG("Websock handshake complete, starting VNC protocol\n");
|
|
vnc_start_protocol(vs);
|
|
vs->ioc_tag = qio_channel_add_watch(
|
|
vs->ioc, G_IO_IN, vnc_client_io, vs, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
gboolean vncws_handshake_io(QIOChannel *ioc G_GNUC_UNUSED,
|
|
GIOCondition condition G_GNUC_UNUSED,
|
|
void *opaque)
|
|
{
|
|
VncState *vs = opaque;
|
|
QIOChannelWebsock *wioc;
|
|
|
|
VNC_DEBUG("Websocket negotiate starting\n");
|
|
if (vs->ioc_tag) {
|
|
g_source_remove(vs->ioc_tag);
|
|
vs->ioc_tag = 0;
|
|
}
|
|
|
|
wioc = qio_channel_websock_new_server(vs->ioc);
|
|
qio_channel_set_name(QIO_CHANNEL(wioc), "vnc-ws-server-websock");
|
|
|
|
object_unref(OBJECT(vs->ioc));
|
|
vs->ioc = QIO_CHANNEL(wioc);
|
|
|
|
qio_channel_websock_handshake(wioc,
|
|
vncws_handshake_done,
|
|
vs,
|
|
NULL);
|
|
|
|
return TRUE;
|
|
}
|