17536ee4bSTim Hardeck /* 27536ee4bSTim Hardeck * QEMU VNC display driver: Websockets support 37536ee4bSTim Hardeck * 47536ee4bSTim Hardeck * Copyright (C) 2010 Joel Martin 57536ee4bSTim Hardeck * Copyright (C) 2012 Tim Hardeck 67536ee4bSTim Hardeck * 77536ee4bSTim Hardeck * This is free software; you can redistribute it and/or modify 87536ee4bSTim Hardeck * it under the terms of the GNU General Public License as published by 97536ee4bSTim Hardeck * the Free Software Foundation; either version 2 of the License, or 107536ee4bSTim Hardeck * (at your option) any later version. 117536ee4bSTim Hardeck * 127536ee4bSTim Hardeck * This software is distributed in the hope that it will be useful, 137536ee4bSTim Hardeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 147536ee4bSTim Hardeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157536ee4bSTim Hardeck * GNU General Public License for more details. 167536ee4bSTim Hardeck * 177536ee4bSTim Hardeck * You should have received a copy of the GNU General Public License 187536ee4bSTim Hardeck * along with this software; if not, see <http://www.gnu.org/licenses/>. 197536ee4bSTim Hardeck */ 207536ee4bSTim Hardeck 217536ee4bSTim Hardeck #include "vnc.h" 22*d5f04223SDaniel P. Berrange #include "io/channel-websock.h" 232cc45228SDaniel P. Berrange 242cc45228SDaniel P. Berrange static void vncws_tls_handshake_done(Object *source, 252cc45228SDaniel P. Berrange Error *err, 262cc45228SDaniel P. Berrange gpointer user_data) 270057a0d5STim Hardeck { 282cc45228SDaniel P. Berrange VncState *vs = user_data; 290057a0d5STim Hardeck 302cc45228SDaniel P. Berrange if (err) { 313e305e4aSDaniel P. Berrange VNC_DEBUG("Handshake failed %s\n", error_get_pretty(err)); 323e305e4aSDaniel P. Berrange vnc_client_error(vs); 332cc45228SDaniel P. Berrange } else { 34*d5f04223SDaniel P. Berrange VNC_DEBUG("TLS handshake complete, starting websocket handshake\n"); 352cc45228SDaniel P. Berrange vs->ioc_tag = qio_channel_add_watch( 362cc45228SDaniel P. Berrange QIO_CHANNEL(vs->ioc), G_IO_IN, vncws_handshake_io, vs, NULL); 370057a0d5STim Hardeck } 382cc45228SDaniel P. Berrange } 392cc45228SDaniel P. Berrange 400057a0d5STim Hardeck 4104d2529dSDaniel P. Berrange gboolean vncws_tls_handshake_io(QIOChannel *ioc G_GNUC_UNUSED, 4204d2529dSDaniel P. Berrange GIOCondition condition G_GNUC_UNUSED, 4304d2529dSDaniel P. Berrange void *opaque) 440057a0d5STim Hardeck { 452cc45228SDaniel P. Berrange VncState *vs = opaque; 462cc45228SDaniel P. Berrange QIOChannelTLS *tls; 473e305e4aSDaniel P. Berrange Error *err = NULL; 480057a0d5STim Hardeck 492cc45228SDaniel P. Berrange VNC_DEBUG("TLS Websocket connection required\n"); 502cc45228SDaniel P. Berrange if (vs->ioc_tag) { 512cc45228SDaniel P. Berrange g_source_remove(vs->ioc_tag); 522cc45228SDaniel P. Berrange vs->ioc_tag = 0; 532cc45228SDaniel P. Berrange } 542cc45228SDaniel P. Berrange 552cc45228SDaniel P. Berrange tls = qio_channel_tls_new_server( 562cc45228SDaniel P. Berrange vs->ioc, 572cc45228SDaniel P. Berrange vs->vd->tlscreds, 583e305e4aSDaniel P. Berrange vs->vd->tlsaclname, 593e305e4aSDaniel P. Berrange &err); 602cc45228SDaniel P. Berrange if (!tls) { 612cc45228SDaniel P. Berrange VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err)); 623e305e4aSDaniel P. Berrange error_free(err); 633e305e4aSDaniel P. Berrange vnc_client_error(vs); 6404d2529dSDaniel P. Berrange return TRUE; 6551941e46SDaniel P. Berrange } 663e305e4aSDaniel P. Berrange 673e305e4aSDaniel P. Berrange VNC_DEBUG("Start TLS WS handshake process\n"); 682cc45228SDaniel P. Berrange object_unref(OBJECT(vs->ioc)); 692cc45228SDaniel P. Berrange vs->ioc = QIO_CHANNEL(tls); 702cc45228SDaniel P. Berrange vs->tls = qio_channel_tls_get_session(tls); 712cc45228SDaniel P. Berrange 722cc45228SDaniel P. Berrange qio_channel_tls_handshake(tls, 732cc45228SDaniel P. Berrange vncws_tls_handshake_done, 742cc45228SDaniel P. Berrange vs, 752cc45228SDaniel P. Berrange NULL); 762cc45228SDaniel P. Berrange 7704d2529dSDaniel P. Berrange return TRUE; 780057a0d5STim Hardeck } 790057a0d5STim Hardeck 80*d5f04223SDaniel P. Berrange 81*d5f04223SDaniel P. Berrange static void vncws_handshake_done(Object *source, 82*d5f04223SDaniel P. Berrange Error *err, 83*d5f04223SDaniel P. Berrange gpointer user_data) 847536ee4bSTim Hardeck { 85*d5f04223SDaniel P. Berrange VncState *vs = user_data; 867536ee4bSTim Hardeck 87*d5f04223SDaniel P. Berrange if (err) { 88*d5f04223SDaniel P. Berrange VNC_DEBUG("Websock handshake failed %s\n", error_get_pretty(err)); 89*d5f04223SDaniel P. Berrange vnc_client_error(vs); 90*d5f04223SDaniel P. Berrange } else { 91*d5f04223SDaniel P. Berrange VNC_DEBUG("Websock handshake complete, starting VNC protocol\n"); 92*d5f04223SDaniel P. Berrange vnc_init_state(vs); 9304d2529dSDaniel P. Berrange vs->ioc_tag = qio_channel_add_watch( 9404d2529dSDaniel P. Berrange vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); 957536ee4bSTim Hardeck } 967536ee4bSTim Hardeck } 977536ee4bSTim Hardeck 987536ee4bSTim Hardeck 9904d2529dSDaniel P. Berrange gboolean vncws_handshake_io(QIOChannel *ioc G_GNUC_UNUSED, 10004d2529dSDaniel P. Berrange GIOCondition condition G_GNUC_UNUSED, 10104d2529dSDaniel P. Berrange void *opaque) 10204d2529dSDaniel P. Berrange { 10304d2529dSDaniel P. Berrange VncState *vs = opaque; 104*d5f04223SDaniel P. Berrange QIOChannelWebsock *wioc; 10504d2529dSDaniel P. Berrange 106*d5f04223SDaniel P. Berrange VNC_DEBUG("Websocket negotiate starting\n"); 10704d2529dSDaniel P. Berrange if (vs->ioc_tag) { 10804d2529dSDaniel P. Berrange g_source_remove(vs->ioc_tag); 109*d5f04223SDaniel P. Berrange vs->ioc_tag = 0; 1107536ee4bSTim Hardeck } 1117536ee4bSTim Hardeck 112*d5f04223SDaniel P. Berrange wioc = qio_channel_websock_new_server(vs->ioc); 1137536ee4bSTim Hardeck 114*d5f04223SDaniel P. Berrange object_unref(OBJECT(vs->ioc)); 115*d5f04223SDaniel P. Berrange vs->ioc = QIO_CHANNEL(wioc); 1167536ee4bSTim Hardeck 117*d5f04223SDaniel P. Berrange qio_channel_websock_handshake(wioc, 118*d5f04223SDaniel P. Berrange vncws_handshake_done, 119*d5f04223SDaniel P. Berrange vs, 120*d5f04223SDaniel P. Berrange NULL); 1217536ee4bSTim Hardeck 122*d5f04223SDaniel P. Berrange return TRUE; 1237536ee4bSTim Hardeck } 124