xref: /openbmc/qemu/ui/vnc.c (revision 3e230dd23b750f19a2fb95cf08250c74432ed164)
1*3e230dd2SCorentin Chary /*
2*3e230dd2SCorentin Chary  * QEMU VNC display driver
3*3e230dd2SCorentin Chary  *
4*3e230dd2SCorentin Chary  * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5*3e230dd2SCorentin Chary  * Copyright (C) 2006 Fabrice Bellard
6*3e230dd2SCorentin Chary  * Copyright (C) 2009 Red Hat, Inc
7*3e230dd2SCorentin Chary  *
8*3e230dd2SCorentin Chary  * Permission is hereby granted, free of charge, to any person obtaining a copy
9*3e230dd2SCorentin Chary  * of this software and associated documentation files (the "Software"), to deal
10*3e230dd2SCorentin Chary  * in the Software without restriction, including without limitation the rights
11*3e230dd2SCorentin Chary  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12*3e230dd2SCorentin Chary  * copies of the Software, and to permit persons to whom the Software is
13*3e230dd2SCorentin Chary  * furnished to do so, subject to the following conditions:
14*3e230dd2SCorentin Chary  *
15*3e230dd2SCorentin Chary  * The above copyright notice and this permission notice shall be included in
16*3e230dd2SCorentin Chary  * all copies or substantial portions of the Software.
17*3e230dd2SCorentin Chary  *
18*3e230dd2SCorentin Chary  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*3e230dd2SCorentin Chary  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*3e230dd2SCorentin Chary  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21*3e230dd2SCorentin Chary  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*3e230dd2SCorentin Chary  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*3e230dd2SCorentin Chary  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24*3e230dd2SCorentin Chary  * THE SOFTWARE.
25*3e230dd2SCorentin Chary  */
26*3e230dd2SCorentin Chary 
27*3e230dd2SCorentin Chary #include "vnc.h"
28*3e230dd2SCorentin Chary #include "sysemu.h"
29*3e230dd2SCorentin Chary #include "qemu_socket.h"
30*3e230dd2SCorentin Chary #include "qemu-timer.h"
31*3e230dd2SCorentin Chary #include "acl.h"
32*3e230dd2SCorentin Chary #include "qemu-objects.h"
33*3e230dd2SCorentin Chary 
34*3e230dd2SCorentin Chary #define VNC_REFRESH_INTERVAL_BASE 30
35*3e230dd2SCorentin Chary #define VNC_REFRESH_INTERVAL_INC  50
36*3e230dd2SCorentin Chary #define VNC_REFRESH_INTERVAL_MAX  2000
37*3e230dd2SCorentin Chary 
38*3e230dd2SCorentin Chary #include "vnc_keysym.h"
39*3e230dd2SCorentin Chary #include "d3des.h"
40*3e230dd2SCorentin Chary 
41*3e230dd2SCorentin Chary #define count_bits(c, v) { \
42*3e230dd2SCorentin Chary     for (c = 0; v; v >>= 1) \
43*3e230dd2SCorentin Chary     { \
44*3e230dd2SCorentin Chary         c += v & 1; \
45*3e230dd2SCorentin Chary     } \
46*3e230dd2SCorentin Chary }
47*3e230dd2SCorentin Chary 
48*3e230dd2SCorentin Chary 
49*3e230dd2SCorentin Chary static VncDisplay *vnc_display; /* needed for info vnc */
50*3e230dd2SCorentin Chary static DisplayChangeListener *dcl;
51*3e230dd2SCorentin Chary 
52*3e230dd2SCorentin Chary static int vnc_cursor_define(VncState *vs);
53*3e230dd2SCorentin Chary 
54*3e230dd2SCorentin Chary static char *addr_to_string(const char *format,
55*3e230dd2SCorentin Chary                             struct sockaddr_storage *sa,
56*3e230dd2SCorentin Chary                             socklen_t salen) {
57*3e230dd2SCorentin Chary     char *addr;
58*3e230dd2SCorentin Chary     char host[NI_MAXHOST];
59*3e230dd2SCorentin Chary     char serv[NI_MAXSERV];
60*3e230dd2SCorentin Chary     int err;
61*3e230dd2SCorentin Chary     size_t addrlen;
62*3e230dd2SCorentin Chary 
63*3e230dd2SCorentin Chary     if ((err = getnameinfo((struct sockaddr *)sa, salen,
64*3e230dd2SCorentin Chary                            host, sizeof(host),
65*3e230dd2SCorentin Chary                            serv, sizeof(serv),
66*3e230dd2SCorentin Chary                            NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
67*3e230dd2SCorentin Chary         VNC_DEBUG("Cannot resolve address %d: %s\n",
68*3e230dd2SCorentin Chary                   err, gai_strerror(err));
69*3e230dd2SCorentin Chary         return NULL;
70*3e230dd2SCorentin Chary     }
71*3e230dd2SCorentin Chary 
72*3e230dd2SCorentin Chary     /* Enough for the existing format + the 2 vars we're
73*3e230dd2SCorentin Chary      * substituting in. */
74*3e230dd2SCorentin Chary     addrlen = strlen(format) + strlen(host) + strlen(serv);
75*3e230dd2SCorentin Chary     addr = qemu_malloc(addrlen + 1);
76*3e230dd2SCorentin Chary     snprintf(addr, addrlen, format, host, serv);
77*3e230dd2SCorentin Chary     addr[addrlen] = '\0';
78*3e230dd2SCorentin Chary 
79*3e230dd2SCorentin Chary     return addr;
80*3e230dd2SCorentin Chary }
81*3e230dd2SCorentin Chary 
82*3e230dd2SCorentin Chary 
83*3e230dd2SCorentin Chary char *vnc_socket_local_addr(const char *format, int fd) {
84*3e230dd2SCorentin Chary     struct sockaddr_storage sa;
85*3e230dd2SCorentin Chary     socklen_t salen;
86*3e230dd2SCorentin Chary 
87*3e230dd2SCorentin Chary     salen = sizeof(sa);
88*3e230dd2SCorentin Chary     if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0)
89*3e230dd2SCorentin Chary         return NULL;
90*3e230dd2SCorentin Chary 
91*3e230dd2SCorentin Chary     return addr_to_string(format, &sa, salen);
92*3e230dd2SCorentin Chary }
93*3e230dd2SCorentin Chary 
94*3e230dd2SCorentin Chary char *vnc_socket_remote_addr(const char *format, int fd) {
95*3e230dd2SCorentin Chary     struct sockaddr_storage sa;
96*3e230dd2SCorentin Chary     socklen_t salen;
97*3e230dd2SCorentin Chary 
98*3e230dd2SCorentin Chary     salen = sizeof(sa);
99*3e230dd2SCorentin Chary     if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0)
100*3e230dd2SCorentin Chary         return NULL;
101*3e230dd2SCorentin Chary 
102*3e230dd2SCorentin Chary     return addr_to_string(format, &sa, salen);
103*3e230dd2SCorentin Chary }
104*3e230dd2SCorentin Chary 
105*3e230dd2SCorentin Chary static int put_addr_qdict(QDict *qdict, struct sockaddr_storage *sa,
106*3e230dd2SCorentin Chary                           socklen_t salen)
107*3e230dd2SCorentin Chary {
108*3e230dd2SCorentin Chary     char host[NI_MAXHOST];
109*3e230dd2SCorentin Chary     char serv[NI_MAXSERV];
110*3e230dd2SCorentin Chary     int err;
111*3e230dd2SCorentin Chary 
112*3e230dd2SCorentin Chary     if ((err = getnameinfo((struct sockaddr *)sa, salen,
113*3e230dd2SCorentin Chary                            host, sizeof(host),
114*3e230dd2SCorentin Chary                            serv, sizeof(serv),
115*3e230dd2SCorentin Chary                            NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
116*3e230dd2SCorentin Chary         VNC_DEBUG("Cannot resolve address %d: %s\n",
117*3e230dd2SCorentin Chary                   err, gai_strerror(err));
118*3e230dd2SCorentin Chary         return -1;
119*3e230dd2SCorentin Chary     }
120*3e230dd2SCorentin Chary 
121*3e230dd2SCorentin Chary     qdict_put(qdict, "host", qstring_from_str(host));
122*3e230dd2SCorentin Chary     qdict_put(qdict, "service", qstring_from_str(serv));
123*3e230dd2SCorentin Chary     qdict_put(qdict, "family",qstring_from_str(inet_strfamily(sa->ss_family)));
124*3e230dd2SCorentin Chary 
125*3e230dd2SCorentin Chary     return 0;
126*3e230dd2SCorentin Chary }
127*3e230dd2SCorentin Chary 
128*3e230dd2SCorentin Chary static int vnc_server_addr_put(QDict *qdict, int fd)
129*3e230dd2SCorentin Chary {
130*3e230dd2SCorentin Chary     struct sockaddr_storage sa;
131*3e230dd2SCorentin Chary     socklen_t salen;
132*3e230dd2SCorentin Chary 
133*3e230dd2SCorentin Chary     salen = sizeof(sa);
134*3e230dd2SCorentin Chary     if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) {
135*3e230dd2SCorentin Chary         return -1;
136*3e230dd2SCorentin Chary     }
137*3e230dd2SCorentin Chary 
138*3e230dd2SCorentin Chary     return put_addr_qdict(qdict, &sa, salen);
139*3e230dd2SCorentin Chary }
140*3e230dd2SCorentin Chary 
141*3e230dd2SCorentin Chary static int vnc_qdict_remote_addr(QDict *qdict, int fd)
142*3e230dd2SCorentin Chary {
143*3e230dd2SCorentin Chary     struct sockaddr_storage sa;
144*3e230dd2SCorentin Chary     socklen_t salen;
145*3e230dd2SCorentin Chary 
146*3e230dd2SCorentin Chary     salen = sizeof(sa);
147*3e230dd2SCorentin Chary     if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) {
148*3e230dd2SCorentin Chary         return -1;
149*3e230dd2SCorentin Chary     }
150*3e230dd2SCorentin Chary 
151*3e230dd2SCorentin Chary     return put_addr_qdict(qdict, &sa, salen);
152*3e230dd2SCorentin Chary }
153*3e230dd2SCorentin Chary 
154*3e230dd2SCorentin Chary static const char *vnc_auth_name(VncDisplay *vd) {
155*3e230dd2SCorentin Chary     switch (vd->auth) {
156*3e230dd2SCorentin Chary     case VNC_AUTH_INVALID:
157*3e230dd2SCorentin Chary         return "invalid";
158*3e230dd2SCorentin Chary     case VNC_AUTH_NONE:
159*3e230dd2SCorentin Chary         return "none";
160*3e230dd2SCorentin Chary     case VNC_AUTH_VNC:
161*3e230dd2SCorentin Chary         return "vnc";
162*3e230dd2SCorentin Chary     case VNC_AUTH_RA2:
163*3e230dd2SCorentin Chary         return "ra2";
164*3e230dd2SCorentin Chary     case VNC_AUTH_RA2NE:
165*3e230dd2SCorentin Chary         return "ra2ne";
166*3e230dd2SCorentin Chary     case VNC_AUTH_TIGHT:
167*3e230dd2SCorentin Chary         return "tight";
168*3e230dd2SCorentin Chary     case VNC_AUTH_ULTRA:
169*3e230dd2SCorentin Chary         return "ultra";
170*3e230dd2SCorentin Chary     case VNC_AUTH_TLS:
171*3e230dd2SCorentin Chary         return "tls";
172*3e230dd2SCorentin Chary     case VNC_AUTH_VENCRYPT:
173*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
174*3e230dd2SCorentin Chary         switch (vd->subauth) {
175*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_PLAIN:
176*3e230dd2SCorentin Chary             return "vencrypt+plain";
177*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_TLSNONE:
178*3e230dd2SCorentin Chary             return "vencrypt+tls+none";
179*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_TLSVNC:
180*3e230dd2SCorentin Chary             return "vencrypt+tls+vnc";
181*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_TLSPLAIN:
182*3e230dd2SCorentin Chary             return "vencrypt+tls+plain";
183*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_X509NONE:
184*3e230dd2SCorentin Chary             return "vencrypt+x509+none";
185*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_X509VNC:
186*3e230dd2SCorentin Chary             return "vencrypt+x509+vnc";
187*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_X509PLAIN:
188*3e230dd2SCorentin Chary             return "vencrypt+x509+plain";
189*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_TLSSASL:
190*3e230dd2SCorentin Chary             return "vencrypt+tls+sasl";
191*3e230dd2SCorentin Chary         case VNC_AUTH_VENCRYPT_X509SASL:
192*3e230dd2SCorentin Chary             return "vencrypt+x509+sasl";
193*3e230dd2SCorentin Chary         default:
194*3e230dd2SCorentin Chary             return "vencrypt";
195*3e230dd2SCorentin Chary         }
196*3e230dd2SCorentin Chary #else
197*3e230dd2SCorentin Chary         return "vencrypt";
198*3e230dd2SCorentin Chary #endif
199*3e230dd2SCorentin Chary     case VNC_AUTH_SASL:
200*3e230dd2SCorentin Chary         return "sasl";
201*3e230dd2SCorentin Chary     }
202*3e230dd2SCorentin Chary     return "unknown";
203*3e230dd2SCorentin Chary }
204*3e230dd2SCorentin Chary 
205*3e230dd2SCorentin Chary static int vnc_server_info_put(QDict *qdict)
206*3e230dd2SCorentin Chary {
207*3e230dd2SCorentin Chary     if (vnc_server_addr_put(qdict, vnc_display->lsock) < 0) {
208*3e230dd2SCorentin Chary         return -1;
209*3e230dd2SCorentin Chary     }
210*3e230dd2SCorentin Chary 
211*3e230dd2SCorentin Chary     qdict_put(qdict, "auth", qstring_from_str(vnc_auth_name(vnc_display)));
212*3e230dd2SCorentin Chary     return 0;
213*3e230dd2SCorentin Chary }
214*3e230dd2SCorentin Chary 
215*3e230dd2SCorentin Chary static void vnc_client_cache_auth(VncState *client)
216*3e230dd2SCorentin Chary {
217*3e230dd2SCorentin Chary     QDict *qdict;
218*3e230dd2SCorentin Chary 
219*3e230dd2SCorentin Chary     if (!client->info) {
220*3e230dd2SCorentin Chary         return;
221*3e230dd2SCorentin Chary     }
222*3e230dd2SCorentin Chary 
223*3e230dd2SCorentin Chary     qdict = qobject_to_qdict(client->info);
224*3e230dd2SCorentin Chary 
225*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
226*3e230dd2SCorentin Chary     if (client->tls.session &&
227*3e230dd2SCorentin Chary         client->tls.dname) {
228*3e230dd2SCorentin Chary         qdict_put(qdict, "x509_dname", qstring_from_str(client->tls.dname));
229*3e230dd2SCorentin Chary     }
230*3e230dd2SCorentin Chary #endif
231*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
232*3e230dd2SCorentin Chary     if (client->sasl.conn &&
233*3e230dd2SCorentin Chary         client->sasl.username) {
234*3e230dd2SCorentin Chary         qdict_put(qdict, "sasl_username",
235*3e230dd2SCorentin Chary                   qstring_from_str(client->sasl.username));
236*3e230dd2SCorentin Chary     }
237*3e230dd2SCorentin Chary #endif
238*3e230dd2SCorentin Chary }
239*3e230dd2SCorentin Chary 
240*3e230dd2SCorentin Chary static void vnc_client_cache_addr(VncState *client)
241*3e230dd2SCorentin Chary {
242*3e230dd2SCorentin Chary     QDict *qdict;
243*3e230dd2SCorentin Chary 
244*3e230dd2SCorentin Chary     qdict = qdict_new();
245*3e230dd2SCorentin Chary     if (vnc_qdict_remote_addr(qdict, client->csock) < 0) {
246*3e230dd2SCorentin Chary         QDECREF(qdict);
247*3e230dd2SCorentin Chary         /* XXX: how to report the error? */
248*3e230dd2SCorentin Chary         return;
249*3e230dd2SCorentin Chary     }
250*3e230dd2SCorentin Chary 
251*3e230dd2SCorentin Chary     client->info = QOBJECT(qdict);
252*3e230dd2SCorentin Chary }
253*3e230dd2SCorentin Chary 
254*3e230dd2SCorentin Chary static void vnc_qmp_event(VncState *vs, MonitorEvent event)
255*3e230dd2SCorentin Chary {
256*3e230dd2SCorentin Chary     QDict *server;
257*3e230dd2SCorentin Chary     QObject *data;
258*3e230dd2SCorentin Chary 
259*3e230dd2SCorentin Chary     if (!vs->info) {
260*3e230dd2SCorentin Chary         return;
261*3e230dd2SCorentin Chary     }
262*3e230dd2SCorentin Chary 
263*3e230dd2SCorentin Chary     server = qdict_new();
264*3e230dd2SCorentin Chary     if (vnc_server_info_put(server) < 0) {
265*3e230dd2SCorentin Chary         QDECREF(server);
266*3e230dd2SCorentin Chary         return;
267*3e230dd2SCorentin Chary     }
268*3e230dd2SCorentin Chary 
269*3e230dd2SCorentin Chary     data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
270*3e230dd2SCorentin Chary                               vs->info, QOBJECT(server));
271*3e230dd2SCorentin Chary 
272*3e230dd2SCorentin Chary     monitor_protocol_event(event, data);
273*3e230dd2SCorentin Chary 
274*3e230dd2SCorentin Chary     qobject_incref(vs->info);
275*3e230dd2SCorentin Chary     qobject_decref(data);
276*3e230dd2SCorentin Chary }
277*3e230dd2SCorentin Chary 
278*3e230dd2SCorentin Chary static void info_vnc_iter(QObject *obj, void *opaque)
279*3e230dd2SCorentin Chary {
280*3e230dd2SCorentin Chary     QDict *client;
281*3e230dd2SCorentin Chary     Monitor *mon = opaque;
282*3e230dd2SCorentin Chary 
283*3e230dd2SCorentin Chary     client = qobject_to_qdict(obj);
284*3e230dd2SCorentin Chary     monitor_printf(mon, "Client:\n");
285*3e230dd2SCorentin Chary     monitor_printf(mon, "     address: %s:%s\n",
286*3e230dd2SCorentin Chary                    qdict_get_str(client, "host"),
287*3e230dd2SCorentin Chary                    qdict_get_str(client, "service"));
288*3e230dd2SCorentin Chary 
289*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
290*3e230dd2SCorentin Chary     monitor_printf(mon, "  x509_dname: %s\n",
291*3e230dd2SCorentin Chary         qdict_haskey(client, "x509_dname") ?
292*3e230dd2SCorentin Chary         qdict_get_str(client, "x509_dname") : "none");
293*3e230dd2SCorentin Chary #endif
294*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
295*3e230dd2SCorentin Chary     monitor_printf(mon, "    username: %s\n",
296*3e230dd2SCorentin Chary         qdict_haskey(client, "sasl_username") ?
297*3e230dd2SCorentin Chary         qdict_get_str(client, "sasl_username") : "none");
298*3e230dd2SCorentin Chary #endif
299*3e230dd2SCorentin Chary }
300*3e230dd2SCorentin Chary 
301*3e230dd2SCorentin Chary void do_info_vnc_print(Monitor *mon, const QObject *data)
302*3e230dd2SCorentin Chary {
303*3e230dd2SCorentin Chary     QDict *server;
304*3e230dd2SCorentin Chary     QList *clients;
305*3e230dd2SCorentin Chary 
306*3e230dd2SCorentin Chary     server = qobject_to_qdict(data);
307*3e230dd2SCorentin Chary     if (qdict_get_bool(server, "enabled") == 0) {
308*3e230dd2SCorentin Chary         monitor_printf(mon, "Server: disabled\n");
309*3e230dd2SCorentin Chary         return;
310*3e230dd2SCorentin Chary     }
311*3e230dd2SCorentin Chary 
312*3e230dd2SCorentin Chary     monitor_printf(mon, "Server:\n");
313*3e230dd2SCorentin Chary     monitor_printf(mon, "     address: %s:%s\n",
314*3e230dd2SCorentin Chary                    qdict_get_str(server, "host"),
315*3e230dd2SCorentin Chary                    qdict_get_str(server, "service"));
316*3e230dd2SCorentin Chary     monitor_printf(mon, "        auth: %s\n", qdict_get_str(server, "auth"));
317*3e230dd2SCorentin Chary 
318*3e230dd2SCorentin Chary     clients = qdict_get_qlist(server, "clients");
319*3e230dd2SCorentin Chary     if (qlist_empty(clients)) {
320*3e230dd2SCorentin Chary         monitor_printf(mon, "Client: none\n");
321*3e230dd2SCorentin Chary     } else {
322*3e230dd2SCorentin Chary         qlist_iter(clients, info_vnc_iter, mon);
323*3e230dd2SCorentin Chary     }
324*3e230dd2SCorentin Chary }
325*3e230dd2SCorentin Chary 
326*3e230dd2SCorentin Chary void do_info_vnc(Monitor *mon, QObject **ret_data)
327*3e230dd2SCorentin Chary {
328*3e230dd2SCorentin Chary     if (vnc_display == NULL || vnc_display->display == NULL) {
329*3e230dd2SCorentin Chary         *ret_data = qobject_from_jsonf("{ 'enabled': false }");
330*3e230dd2SCorentin Chary     } else {
331*3e230dd2SCorentin Chary         QList *clist;
332*3e230dd2SCorentin Chary         VncState *client;
333*3e230dd2SCorentin Chary 
334*3e230dd2SCorentin Chary         clist = qlist_new();
335*3e230dd2SCorentin Chary         QTAILQ_FOREACH(client, &vnc_display->clients, next) {
336*3e230dd2SCorentin Chary             if (client->info) {
337*3e230dd2SCorentin Chary                 /* incref so that it's not freed by upper layers */
338*3e230dd2SCorentin Chary                 qobject_incref(client->info);
339*3e230dd2SCorentin Chary                 qlist_append_obj(clist, client->info);
340*3e230dd2SCorentin Chary             }
341*3e230dd2SCorentin Chary         }
342*3e230dd2SCorentin Chary 
343*3e230dd2SCorentin Chary         *ret_data = qobject_from_jsonf("{ 'enabled': true, 'clients': %p }",
344*3e230dd2SCorentin Chary                                        QOBJECT(clist));
345*3e230dd2SCorentin Chary         assert(*ret_data != NULL);
346*3e230dd2SCorentin Chary 
347*3e230dd2SCorentin Chary         if (vnc_server_info_put(qobject_to_qdict(*ret_data)) < 0) {
348*3e230dd2SCorentin Chary             qobject_decref(*ret_data);
349*3e230dd2SCorentin Chary             *ret_data = NULL;
350*3e230dd2SCorentin Chary         }
351*3e230dd2SCorentin Chary     }
352*3e230dd2SCorentin Chary }
353*3e230dd2SCorentin Chary 
354*3e230dd2SCorentin Chary static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
355*3e230dd2SCorentin Chary     return (vs->features & (1 << feature));
356*3e230dd2SCorentin Chary }
357*3e230dd2SCorentin Chary 
358*3e230dd2SCorentin Chary /* TODO
359*3e230dd2SCorentin Chary    1) Get the queue working for IO.
360*3e230dd2SCorentin Chary    2) there is some weirdness when using the -S option (the screen is grey
361*3e230dd2SCorentin Chary       and not totally invalidated
362*3e230dd2SCorentin Chary    3) resolutions > 1024
363*3e230dd2SCorentin Chary */
364*3e230dd2SCorentin Chary 
365*3e230dd2SCorentin Chary static int vnc_update_client(VncState *vs, int has_dirty);
366*3e230dd2SCorentin Chary static void vnc_disconnect_start(VncState *vs);
367*3e230dd2SCorentin Chary static void vnc_disconnect_finish(VncState *vs);
368*3e230dd2SCorentin Chary static void vnc_init_timer(VncDisplay *vd);
369*3e230dd2SCorentin Chary static void vnc_remove_timer(VncDisplay *vd);
370*3e230dd2SCorentin Chary 
371*3e230dd2SCorentin Chary static void vnc_colordepth(VncState *vs);
372*3e230dd2SCorentin Chary static void framebuffer_update_request(VncState *vs, int incremental,
373*3e230dd2SCorentin Chary                                        int x_position, int y_position,
374*3e230dd2SCorentin Chary                                        int w, int h);
375*3e230dd2SCorentin Chary static void vnc_refresh(void *opaque);
376*3e230dd2SCorentin Chary static int vnc_refresh_server_surface(VncDisplay *vd);
377*3e230dd2SCorentin Chary 
378*3e230dd2SCorentin Chary static inline void vnc_set_bit(uint32_t *d, int k)
379*3e230dd2SCorentin Chary {
380*3e230dd2SCorentin Chary     d[k >> 5] |= 1 << (k & 0x1f);
381*3e230dd2SCorentin Chary }
382*3e230dd2SCorentin Chary 
383*3e230dd2SCorentin Chary static inline void vnc_clear_bit(uint32_t *d, int k)
384*3e230dd2SCorentin Chary {
385*3e230dd2SCorentin Chary     d[k >> 5] &= ~(1 << (k & 0x1f));
386*3e230dd2SCorentin Chary }
387*3e230dd2SCorentin Chary 
388*3e230dd2SCorentin Chary static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
389*3e230dd2SCorentin Chary {
390*3e230dd2SCorentin Chary     int j;
391*3e230dd2SCorentin Chary 
392*3e230dd2SCorentin Chary     j = 0;
393*3e230dd2SCorentin Chary     while (n >= 32) {
394*3e230dd2SCorentin Chary         d[j++] = -1;
395*3e230dd2SCorentin Chary         n -= 32;
396*3e230dd2SCorentin Chary     }
397*3e230dd2SCorentin Chary     if (n > 0)
398*3e230dd2SCorentin Chary         d[j++] = (1 << n) - 1;
399*3e230dd2SCorentin Chary     while (j < nb_words)
400*3e230dd2SCorentin Chary         d[j++] = 0;
401*3e230dd2SCorentin Chary }
402*3e230dd2SCorentin Chary 
403*3e230dd2SCorentin Chary static inline int vnc_get_bit(const uint32_t *d, int k)
404*3e230dd2SCorentin Chary {
405*3e230dd2SCorentin Chary     return (d[k >> 5] >> (k & 0x1f)) & 1;
406*3e230dd2SCorentin Chary }
407*3e230dd2SCorentin Chary 
408*3e230dd2SCorentin Chary static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
409*3e230dd2SCorentin Chary                                int nb_words)
410*3e230dd2SCorentin Chary {
411*3e230dd2SCorentin Chary     int i;
412*3e230dd2SCorentin Chary     for(i = 0; i < nb_words; i++) {
413*3e230dd2SCorentin Chary         if ((d1[i] & d2[i]) != 0)
414*3e230dd2SCorentin Chary             return 1;
415*3e230dd2SCorentin Chary     }
416*3e230dd2SCorentin Chary     return 0;
417*3e230dd2SCorentin Chary }
418*3e230dd2SCorentin Chary 
419*3e230dd2SCorentin Chary static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
420*3e230dd2SCorentin Chary {
421*3e230dd2SCorentin Chary     int i;
422*3e230dd2SCorentin Chary     VncDisplay *vd = ds->opaque;
423*3e230dd2SCorentin Chary     struct VncSurface *s = &vd->guest;
424*3e230dd2SCorentin Chary 
425*3e230dd2SCorentin Chary     h += y;
426*3e230dd2SCorentin Chary 
427*3e230dd2SCorentin Chary     /* round x down to ensure the loop only spans one 16-pixel block per,
428*3e230dd2SCorentin Chary        iteration.  otherwise, if (x % 16) != 0, the last iteration may span
429*3e230dd2SCorentin Chary        two 16-pixel blocks but we only mark the first as dirty
430*3e230dd2SCorentin Chary     */
431*3e230dd2SCorentin Chary     w += (x % 16);
432*3e230dd2SCorentin Chary     x -= (x % 16);
433*3e230dd2SCorentin Chary 
434*3e230dd2SCorentin Chary     x = MIN(x, s->ds->width);
435*3e230dd2SCorentin Chary     y = MIN(y, s->ds->height);
436*3e230dd2SCorentin Chary     w = MIN(x + w, s->ds->width) - x;
437*3e230dd2SCorentin Chary     h = MIN(h, s->ds->height);
438*3e230dd2SCorentin Chary 
439*3e230dd2SCorentin Chary     for (; y < h; y++)
440*3e230dd2SCorentin Chary         for (i = 0; i < w; i += 16)
441*3e230dd2SCorentin Chary             vnc_set_bit(s->dirty[y], (x + i) / 16);
442*3e230dd2SCorentin Chary }
443*3e230dd2SCorentin Chary 
444*3e230dd2SCorentin Chary void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
445*3e230dd2SCorentin Chary                             int32_t encoding)
446*3e230dd2SCorentin Chary {
447*3e230dd2SCorentin Chary     vnc_write_u16(vs, x);
448*3e230dd2SCorentin Chary     vnc_write_u16(vs, y);
449*3e230dd2SCorentin Chary     vnc_write_u16(vs, w);
450*3e230dd2SCorentin Chary     vnc_write_u16(vs, h);
451*3e230dd2SCorentin Chary 
452*3e230dd2SCorentin Chary     vnc_write_s32(vs, encoding);
453*3e230dd2SCorentin Chary }
454*3e230dd2SCorentin Chary 
455*3e230dd2SCorentin Chary void buffer_reserve(Buffer *buffer, size_t len)
456*3e230dd2SCorentin Chary {
457*3e230dd2SCorentin Chary     if ((buffer->capacity - buffer->offset) < len) {
458*3e230dd2SCorentin Chary         buffer->capacity += (len + 1024);
459*3e230dd2SCorentin Chary         buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
460*3e230dd2SCorentin Chary         if (buffer->buffer == NULL) {
461*3e230dd2SCorentin Chary             fprintf(stderr, "vnc: out of memory\n");
462*3e230dd2SCorentin Chary             exit(1);
463*3e230dd2SCorentin Chary         }
464*3e230dd2SCorentin Chary     }
465*3e230dd2SCorentin Chary }
466*3e230dd2SCorentin Chary 
467*3e230dd2SCorentin Chary int buffer_empty(Buffer *buffer)
468*3e230dd2SCorentin Chary {
469*3e230dd2SCorentin Chary     return buffer->offset == 0;
470*3e230dd2SCorentin Chary }
471*3e230dd2SCorentin Chary 
472*3e230dd2SCorentin Chary uint8_t *buffer_end(Buffer *buffer)
473*3e230dd2SCorentin Chary {
474*3e230dd2SCorentin Chary     return buffer->buffer + buffer->offset;
475*3e230dd2SCorentin Chary }
476*3e230dd2SCorentin Chary 
477*3e230dd2SCorentin Chary void buffer_reset(Buffer *buffer)
478*3e230dd2SCorentin Chary {
479*3e230dd2SCorentin Chary         buffer->offset = 0;
480*3e230dd2SCorentin Chary }
481*3e230dd2SCorentin Chary 
482*3e230dd2SCorentin Chary void buffer_free(Buffer *buffer)
483*3e230dd2SCorentin Chary {
484*3e230dd2SCorentin Chary     qemu_free(buffer->buffer);
485*3e230dd2SCorentin Chary     buffer->offset = 0;
486*3e230dd2SCorentin Chary     buffer->capacity = 0;
487*3e230dd2SCorentin Chary     buffer->buffer = NULL;
488*3e230dd2SCorentin Chary }
489*3e230dd2SCorentin Chary 
490*3e230dd2SCorentin Chary void buffer_append(Buffer *buffer, const void *data, size_t len)
491*3e230dd2SCorentin Chary {
492*3e230dd2SCorentin Chary     memcpy(buffer->buffer + buffer->offset, data, len);
493*3e230dd2SCorentin Chary     buffer->offset += len;
494*3e230dd2SCorentin Chary }
495*3e230dd2SCorentin Chary 
496*3e230dd2SCorentin Chary static void vnc_desktop_resize(VncState *vs)
497*3e230dd2SCorentin Chary {
498*3e230dd2SCorentin Chary     DisplayState *ds = vs->ds;
499*3e230dd2SCorentin Chary 
500*3e230dd2SCorentin Chary     if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
501*3e230dd2SCorentin Chary         return;
502*3e230dd2SCorentin Chary     }
503*3e230dd2SCorentin Chary     if (vs->client_width == ds_get_width(ds) &&
504*3e230dd2SCorentin Chary         vs->client_height == ds_get_height(ds)) {
505*3e230dd2SCorentin Chary         return;
506*3e230dd2SCorentin Chary     }
507*3e230dd2SCorentin Chary     vs->client_width = ds_get_width(ds);
508*3e230dd2SCorentin Chary     vs->client_height = ds_get_height(ds);
509*3e230dd2SCorentin Chary     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
510*3e230dd2SCorentin Chary     vnc_write_u8(vs, 0);
511*3e230dd2SCorentin Chary     vnc_write_u16(vs, 1); /* number of rects */
512*3e230dd2SCorentin Chary     vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height,
513*3e230dd2SCorentin Chary                            VNC_ENCODING_DESKTOPRESIZE);
514*3e230dd2SCorentin Chary     vnc_flush(vs);
515*3e230dd2SCorentin Chary }
516*3e230dd2SCorentin Chary 
517*3e230dd2SCorentin Chary static void vnc_dpy_resize(DisplayState *ds)
518*3e230dd2SCorentin Chary {
519*3e230dd2SCorentin Chary     VncDisplay *vd = ds->opaque;
520*3e230dd2SCorentin Chary     VncState *vs;
521*3e230dd2SCorentin Chary 
522*3e230dd2SCorentin Chary     /* server surface */
523*3e230dd2SCorentin Chary     if (!vd->server)
524*3e230dd2SCorentin Chary         vd->server = qemu_mallocz(sizeof(*vd->server));
525*3e230dd2SCorentin Chary     if (vd->server->data)
526*3e230dd2SCorentin Chary         qemu_free(vd->server->data);
527*3e230dd2SCorentin Chary     *(vd->server) = *(ds->surface);
528*3e230dd2SCorentin Chary     vd->server->data = qemu_mallocz(vd->server->linesize *
529*3e230dd2SCorentin Chary                                     vd->server->height);
530*3e230dd2SCorentin Chary 
531*3e230dd2SCorentin Chary     /* guest surface */
532*3e230dd2SCorentin Chary     if (!vd->guest.ds)
533*3e230dd2SCorentin Chary         vd->guest.ds = qemu_mallocz(sizeof(*vd->guest.ds));
534*3e230dd2SCorentin Chary     if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
535*3e230dd2SCorentin Chary         console_color_init(ds);
536*3e230dd2SCorentin Chary     *(vd->guest.ds) = *(ds->surface);
537*3e230dd2SCorentin Chary     memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
538*3e230dd2SCorentin Chary 
539*3e230dd2SCorentin Chary     QTAILQ_FOREACH(vs, &vd->clients, next) {
540*3e230dd2SCorentin Chary         vnc_colordepth(vs);
541*3e230dd2SCorentin Chary         vnc_desktop_resize(vs);
542*3e230dd2SCorentin Chary         if (vs->vd->cursor) {
543*3e230dd2SCorentin Chary             vnc_cursor_define(vs);
544*3e230dd2SCorentin Chary         }
545*3e230dd2SCorentin Chary         memset(vs->dirty, 0xFF, sizeof(vs->dirty));
546*3e230dd2SCorentin Chary     }
547*3e230dd2SCorentin Chary }
548*3e230dd2SCorentin Chary 
549*3e230dd2SCorentin Chary /* fastest code */
550*3e230dd2SCorentin Chary static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf,
551*3e230dd2SCorentin Chary                                   void *pixels, int size)
552*3e230dd2SCorentin Chary {
553*3e230dd2SCorentin Chary     vnc_write(vs, pixels, size);
554*3e230dd2SCorentin Chary }
555*3e230dd2SCorentin Chary 
556*3e230dd2SCorentin Chary /* slowest but generic code. */
557*3e230dd2SCorentin Chary void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
558*3e230dd2SCorentin Chary {
559*3e230dd2SCorentin Chary     uint8_t r, g, b;
560*3e230dd2SCorentin Chary     VncDisplay *vd = vs->vd;
561*3e230dd2SCorentin Chary 
562*3e230dd2SCorentin Chary     r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >>
563*3e230dd2SCorentin Chary         vd->server->pf.rbits);
564*3e230dd2SCorentin Chary     g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >>
565*3e230dd2SCorentin Chary         vd->server->pf.gbits);
566*3e230dd2SCorentin Chary     b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >>
567*3e230dd2SCorentin Chary         vd->server->pf.bbits);
568*3e230dd2SCorentin Chary     v = (r << vs->clientds.pf.rshift) |
569*3e230dd2SCorentin Chary         (g << vs->clientds.pf.gshift) |
570*3e230dd2SCorentin Chary         (b << vs->clientds.pf.bshift);
571*3e230dd2SCorentin Chary     switch(vs->clientds.pf.bytes_per_pixel) {
572*3e230dd2SCorentin Chary     case 1:
573*3e230dd2SCorentin Chary         buf[0] = v;
574*3e230dd2SCorentin Chary         break;
575*3e230dd2SCorentin Chary     case 2:
576*3e230dd2SCorentin Chary         if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
577*3e230dd2SCorentin Chary             buf[0] = v >> 8;
578*3e230dd2SCorentin Chary             buf[1] = v;
579*3e230dd2SCorentin Chary         } else {
580*3e230dd2SCorentin Chary             buf[1] = v >> 8;
581*3e230dd2SCorentin Chary             buf[0] = v;
582*3e230dd2SCorentin Chary         }
583*3e230dd2SCorentin Chary         break;
584*3e230dd2SCorentin Chary     default:
585*3e230dd2SCorentin Chary     case 4:
586*3e230dd2SCorentin Chary         if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
587*3e230dd2SCorentin Chary             buf[0] = v >> 24;
588*3e230dd2SCorentin Chary             buf[1] = v >> 16;
589*3e230dd2SCorentin Chary             buf[2] = v >> 8;
590*3e230dd2SCorentin Chary             buf[3] = v;
591*3e230dd2SCorentin Chary         } else {
592*3e230dd2SCorentin Chary             buf[3] = v >> 24;
593*3e230dd2SCorentin Chary             buf[2] = v >> 16;
594*3e230dd2SCorentin Chary             buf[1] = v >> 8;
595*3e230dd2SCorentin Chary             buf[0] = v;
596*3e230dd2SCorentin Chary         }
597*3e230dd2SCorentin Chary         break;
598*3e230dd2SCorentin Chary     }
599*3e230dd2SCorentin Chary }
600*3e230dd2SCorentin Chary 
601*3e230dd2SCorentin Chary static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf,
602*3e230dd2SCorentin Chary                                      void *pixels1, int size)
603*3e230dd2SCorentin Chary {
604*3e230dd2SCorentin Chary     uint8_t buf[4];
605*3e230dd2SCorentin Chary 
606*3e230dd2SCorentin Chary     if (pf->bytes_per_pixel == 4) {
607*3e230dd2SCorentin Chary         uint32_t *pixels = pixels1;
608*3e230dd2SCorentin Chary         int n, i;
609*3e230dd2SCorentin Chary         n = size >> 2;
610*3e230dd2SCorentin Chary         for(i = 0; i < n; i++) {
611*3e230dd2SCorentin Chary             vnc_convert_pixel(vs, buf, pixels[i]);
612*3e230dd2SCorentin Chary             vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
613*3e230dd2SCorentin Chary         }
614*3e230dd2SCorentin Chary     } else if (pf->bytes_per_pixel == 2) {
615*3e230dd2SCorentin Chary         uint16_t *pixels = pixels1;
616*3e230dd2SCorentin Chary         int n, i;
617*3e230dd2SCorentin Chary         n = size >> 1;
618*3e230dd2SCorentin Chary         for(i = 0; i < n; i++) {
619*3e230dd2SCorentin Chary             vnc_convert_pixel(vs, buf, pixels[i]);
620*3e230dd2SCorentin Chary             vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
621*3e230dd2SCorentin Chary         }
622*3e230dd2SCorentin Chary     } else if (pf->bytes_per_pixel == 1) {
623*3e230dd2SCorentin Chary         uint8_t *pixels = pixels1;
624*3e230dd2SCorentin Chary         int n, i;
625*3e230dd2SCorentin Chary         n = size;
626*3e230dd2SCorentin Chary         for(i = 0; i < n; i++) {
627*3e230dd2SCorentin Chary             vnc_convert_pixel(vs, buf, pixels[i]);
628*3e230dd2SCorentin Chary             vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
629*3e230dd2SCorentin Chary         }
630*3e230dd2SCorentin Chary     } else {
631*3e230dd2SCorentin Chary         fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
632*3e230dd2SCorentin Chary     }
633*3e230dd2SCorentin Chary }
634*3e230dd2SCorentin Chary 
635*3e230dd2SCorentin Chary int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
636*3e230dd2SCorentin Chary {
637*3e230dd2SCorentin Chary     int i;
638*3e230dd2SCorentin Chary     uint8_t *row;
639*3e230dd2SCorentin Chary     VncDisplay *vd = vs->vd;
640*3e230dd2SCorentin Chary 
641*3e230dd2SCorentin Chary     row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
642*3e230dd2SCorentin Chary     for (i = 0; i < h; i++) {
643*3e230dd2SCorentin Chary         vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds));
644*3e230dd2SCorentin Chary         row += ds_get_linesize(vs->ds);
645*3e230dd2SCorentin Chary     }
646*3e230dd2SCorentin Chary     return 1;
647*3e230dd2SCorentin Chary }
648*3e230dd2SCorentin Chary 
649*3e230dd2SCorentin Chary static int send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
650*3e230dd2SCorentin Chary {
651*3e230dd2SCorentin Chary     int n = 0;
652*3e230dd2SCorentin Chary 
653*3e230dd2SCorentin Chary     switch(vs->vnc_encoding) {
654*3e230dd2SCorentin Chary         case VNC_ENCODING_ZLIB:
655*3e230dd2SCorentin Chary             n = vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
656*3e230dd2SCorentin Chary             break;
657*3e230dd2SCorentin Chary         case VNC_ENCODING_HEXTILE:
658*3e230dd2SCorentin Chary             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
659*3e230dd2SCorentin Chary             n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
660*3e230dd2SCorentin Chary             break;
661*3e230dd2SCorentin Chary         case VNC_ENCODING_TIGHT:
662*3e230dd2SCorentin Chary             n = vnc_tight_send_framebuffer_update(vs, x, y, w, h);
663*3e230dd2SCorentin Chary             break;
664*3e230dd2SCorentin Chary         default:
665*3e230dd2SCorentin Chary             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
666*3e230dd2SCorentin Chary             n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
667*3e230dd2SCorentin Chary             break;
668*3e230dd2SCorentin Chary     }
669*3e230dd2SCorentin Chary     return n;
670*3e230dd2SCorentin Chary }
671*3e230dd2SCorentin Chary 
672*3e230dd2SCorentin Chary static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
673*3e230dd2SCorentin Chary {
674*3e230dd2SCorentin Chary     /* send bitblit op to the vnc client */
675*3e230dd2SCorentin Chary     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
676*3e230dd2SCorentin Chary     vnc_write_u8(vs, 0);
677*3e230dd2SCorentin Chary     vnc_write_u16(vs, 1); /* number of rects */
678*3e230dd2SCorentin Chary     vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
679*3e230dd2SCorentin Chary     vnc_write_u16(vs, src_x);
680*3e230dd2SCorentin Chary     vnc_write_u16(vs, src_y);
681*3e230dd2SCorentin Chary     vnc_flush(vs);
682*3e230dd2SCorentin Chary }
683*3e230dd2SCorentin Chary 
684*3e230dd2SCorentin Chary static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
685*3e230dd2SCorentin Chary {
686*3e230dd2SCorentin Chary     VncDisplay *vd = ds->opaque;
687*3e230dd2SCorentin Chary     VncState *vs, *vn;
688*3e230dd2SCorentin Chary     uint8_t *src_row;
689*3e230dd2SCorentin Chary     uint8_t *dst_row;
690*3e230dd2SCorentin Chary     int i,x,y,pitch,depth,inc,w_lim,s;
691*3e230dd2SCorentin Chary     int cmp_bytes;
692*3e230dd2SCorentin Chary 
693*3e230dd2SCorentin Chary     vnc_refresh_server_surface(vd);
694*3e230dd2SCorentin Chary     QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
695*3e230dd2SCorentin Chary         if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
696*3e230dd2SCorentin Chary             vs->force_update = 1;
697*3e230dd2SCorentin Chary             vnc_update_client(vs, 1);
698*3e230dd2SCorentin Chary             /* vs might be free()ed here */
699*3e230dd2SCorentin Chary         }
700*3e230dd2SCorentin Chary     }
701*3e230dd2SCorentin Chary 
702*3e230dd2SCorentin Chary     /* do bitblit op on the local surface too */
703*3e230dd2SCorentin Chary     pitch = ds_get_linesize(vd->ds);
704*3e230dd2SCorentin Chary     depth = ds_get_bytes_per_pixel(vd->ds);
705*3e230dd2SCorentin Chary     src_row = vd->server->data + pitch * src_y + depth * src_x;
706*3e230dd2SCorentin Chary     dst_row = vd->server->data + pitch * dst_y + depth * dst_x;
707*3e230dd2SCorentin Chary     y = dst_y;
708*3e230dd2SCorentin Chary     inc = 1;
709*3e230dd2SCorentin Chary     if (dst_y > src_y) {
710*3e230dd2SCorentin Chary         /* copy backwards */
711*3e230dd2SCorentin Chary         src_row += pitch * (h-1);
712*3e230dd2SCorentin Chary         dst_row += pitch * (h-1);
713*3e230dd2SCorentin Chary         pitch = -pitch;
714*3e230dd2SCorentin Chary         y = dst_y + h - 1;
715*3e230dd2SCorentin Chary         inc = -1;
716*3e230dd2SCorentin Chary     }
717*3e230dd2SCorentin Chary     w_lim = w - (16 - (dst_x % 16));
718*3e230dd2SCorentin Chary     if (w_lim < 0)
719*3e230dd2SCorentin Chary         w_lim = w;
720*3e230dd2SCorentin Chary     else
721*3e230dd2SCorentin Chary         w_lim = w - (w_lim % 16);
722*3e230dd2SCorentin Chary     for (i = 0; i < h; i++) {
723*3e230dd2SCorentin Chary         for (x = 0; x <= w_lim;
724*3e230dd2SCorentin Chary                 x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
725*3e230dd2SCorentin Chary             if (x == w_lim) {
726*3e230dd2SCorentin Chary                 if ((s = w - w_lim) == 0)
727*3e230dd2SCorentin Chary                     break;
728*3e230dd2SCorentin Chary             } else if (!x) {
729*3e230dd2SCorentin Chary                 s = (16 - (dst_x % 16));
730*3e230dd2SCorentin Chary                 s = MIN(s, w_lim);
731*3e230dd2SCorentin Chary             } else {
732*3e230dd2SCorentin Chary                 s = 16;
733*3e230dd2SCorentin Chary             }
734*3e230dd2SCorentin Chary             cmp_bytes = s * depth;
735*3e230dd2SCorentin Chary             if (memcmp(src_row, dst_row, cmp_bytes) == 0)
736*3e230dd2SCorentin Chary                 continue;
737*3e230dd2SCorentin Chary             memmove(dst_row, src_row, cmp_bytes);
738*3e230dd2SCorentin Chary             QTAILQ_FOREACH(vs, &vd->clients, next) {
739*3e230dd2SCorentin Chary                 if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
740*3e230dd2SCorentin Chary                     vnc_set_bit(vs->dirty[y], ((x + dst_x) / 16));
741*3e230dd2SCorentin Chary                 }
742*3e230dd2SCorentin Chary             }
743*3e230dd2SCorentin Chary         }
744*3e230dd2SCorentin Chary         src_row += pitch - w * depth;
745*3e230dd2SCorentin Chary         dst_row += pitch - w * depth;
746*3e230dd2SCorentin Chary         y += inc;
747*3e230dd2SCorentin Chary     }
748*3e230dd2SCorentin Chary 
749*3e230dd2SCorentin Chary     QTAILQ_FOREACH(vs, &vd->clients, next) {
750*3e230dd2SCorentin Chary         if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
751*3e230dd2SCorentin Chary             vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
752*3e230dd2SCorentin Chary         }
753*3e230dd2SCorentin Chary     }
754*3e230dd2SCorentin Chary }
755*3e230dd2SCorentin Chary 
756*3e230dd2SCorentin Chary static void vnc_mouse_set(int x, int y, int visible)
757*3e230dd2SCorentin Chary {
758*3e230dd2SCorentin Chary     /* can we ask the client(s) to move the pointer ??? */
759*3e230dd2SCorentin Chary }
760*3e230dd2SCorentin Chary 
761*3e230dd2SCorentin Chary static int vnc_cursor_define(VncState *vs)
762*3e230dd2SCorentin Chary {
763*3e230dd2SCorentin Chary     QEMUCursor *c = vs->vd->cursor;
764*3e230dd2SCorentin Chary     PixelFormat pf = qemu_default_pixelformat(32);
765*3e230dd2SCorentin Chary     int isize;
766*3e230dd2SCorentin Chary 
767*3e230dd2SCorentin Chary     if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
768*3e230dd2SCorentin Chary         vnc_write_u8(vs,  VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
769*3e230dd2SCorentin Chary         vnc_write_u8(vs,  0);  /*  padding     */
770*3e230dd2SCorentin Chary         vnc_write_u16(vs, 1);  /*  # of rects  */
771*3e230dd2SCorentin Chary         vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
772*3e230dd2SCorentin Chary                                VNC_ENCODING_RICH_CURSOR);
773*3e230dd2SCorentin Chary         isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel;
774*3e230dd2SCorentin Chary         vnc_write_pixels_generic(vs, &pf, c->data, isize);
775*3e230dd2SCorentin Chary         vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
776*3e230dd2SCorentin Chary         return 0;
777*3e230dd2SCorentin Chary     }
778*3e230dd2SCorentin Chary     return -1;
779*3e230dd2SCorentin Chary }
780*3e230dd2SCorentin Chary 
781*3e230dd2SCorentin Chary static void vnc_dpy_cursor_define(QEMUCursor *c)
782*3e230dd2SCorentin Chary {
783*3e230dd2SCorentin Chary     VncDisplay *vd = vnc_display;
784*3e230dd2SCorentin Chary     VncState *vs;
785*3e230dd2SCorentin Chary 
786*3e230dd2SCorentin Chary     cursor_put(vd->cursor);
787*3e230dd2SCorentin Chary     qemu_free(vd->cursor_mask);
788*3e230dd2SCorentin Chary 
789*3e230dd2SCorentin Chary     vd->cursor = c;
790*3e230dd2SCorentin Chary     cursor_get(vd->cursor);
791*3e230dd2SCorentin Chary     vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
792*3e230dd2SCorentin Chary     vd->cursor_mask = qemu_mallocz(vd->cursor_msize);
793*3e230dd2SCorentin Chary     cursor_get_mono_mask(c, 0, vd->cursor_mask);
794*3e230dd2SCorentin Chary 
795*3e230dd2SCorentin Chary     QTAILQ_FOREACH(vs, &vd->clients, next) {
796*3e230dd2SCorentin Chary         vnc_cursor_define(vs);
797*3e230dd2SCorentin Chary     }
798*3e230dd2SCorentin Chary }
799*3e230dd2SCorentin Chary 
800*3e230dd2SCorentin Chary static int find_and_clear_dirty_height(struct VncState *vs,
801*3e230dd2SCorentin Chary                                        int y, int last_x, int x)
802*3e230dd2SCorentin Chary {
803*3e230dd2SCorentin Chary     int h;
804*3e230dd2SCorentin Chary     VncDisplay *vd = vs->vd;
805*3e230dd2SCorentin Chary 
806*3e230dd2SCorentin Chary     for (h = 1; h < (vd->server->height - y); h++) {
807*3e230dd2SCorentin Chary         int tmp_x;
808*3e230dd2SCorentin Chary         if (!vnc_get_bit(vs->dirty[y + h], last_x))
809*3e230dd2SCorentin Chary             break;
810*3e230dd2SCorentin Chary         for (tmp_x = last_x; tmp_x < x; tmp_x++)
811*3e230dd2SCorentin Chary             vnc_clear_bit(vs->dirty[y + h], tmp_x);
812*3e230dd2SCorentin Chary     }
813*3e230dd2SCorentin Chary 
814*3e230dd2SCorentin Chary     return h;
815*3e230dd2SCorentin Chary }
816*3e230dd2SCorentin Chary 
817*3e230dd2SCorentin Chary static int vnc_update_client(VncState *vs, int has_dirty)
818*3e230dd2SCorentin Chary {
819*3e230dd2SCorentin Chary     if (vs->need_update && vs->csock != -1) {
820*3e230dd2SCorentin Chary         VncDisplay *vd = vs->vd;
821*3e230dd2SCorentin Chary         int y;
822*3e230dd2SCorentin Chary         int n_rectangles;
823*3e230dd2SCorentin Chary         int saved_offset;
824*3e230dd2SCorentin Chary         int width, height;
825*3e230dd2SCorentin Chary         int n;
826*3e230dd2SCorentin Chary 
827*3e230dd2SCorentin Chary         if (vs->output.offset && !vs->audio_cap && !vs->force_update)
828*3e230dd2SCorentin Chary             /* kernel send buffers are full -> drop frames to throttle */
829*3e230dd2SCorentin Chary             return 0;
830*3e230dd2SCorentin Chary 
831*3e230dd2SCorentin Chary         if (!has_dirty && !vs->audio_cap && !vs->force_update)
832*3e230dd2SCorentin Chary             return 0;
833*3e230dd2SCorentin Chary 
834*3e230dd2SCorentin Chary         /*
835*3e230dd2SCorentin Chary          * Send screen updates to the vnc client using the server
836*3e230dd2SCorentin Chary          * surface and server dirty map.  guest surface updates
837*3e230dd2SCorentin Chary          * happening in parallel don't disturb us, the next pass will
838*3e230dd2SCorentin Chary          * send them to the client.
839*3e230dd2SCorentin Chary          */
840*3e230dd2SCorentin Chary         n_rectangles = 0;
841*3e230dd2SCorentin Chary         vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
842*3e230dd2SCorentin Chary         vnc_write_u8(vs, 0);
843*3e230dd2SCorentin Chary         saved_offset = vs->output.offset;
844*3e230dd2SCorentin Chary         vnc_write_u16(vs, 0);
845*3e230dd2SCorentin Chary 
846*3e230dd2SCorentin Chary         width = MIN(vd->server->width, vs->client_width);
847*3e230dd2SCorentin Chary         height = MIN(vd->server->height, vs->client_height);
848*3e230dd2SCorentin Chary 
849*3e230dd2SCorentin Chary         for (y = 0; y < height; y++) {
850*3e230dd2SCorentin Chary             int x;
851*3e230dd2SCorentin Chary             int last_x = -1;
852*3e230dd2SCorentin Chary             for (x = 0; x < width / 16; x++) {
853*3e230dd2SCorentin Chary                 if (vnc_get_bit(vs->dirty[y], x)) {
854*3e230dd2SCorentin Chary                     if (last_x == -1) {
855*3e230dd2SCorentin Chary                         last_x = x;
856*3e230dd2SCorentin Chary                     }
857*3e230dd2SCorentin Chary                     vnc_clear_bit(vs->dirty[y], x);
858*3e230dd2SCorentin Chary                 } else {
859*3e230dd2SCorentin Chary                     if (last_x != -1) {
860*3e230dd2SCorentin Chary                         int h = find_and_clear_dirty_height(vs, y, last_x, x);
861*3e230dd2SCorentin Chary                         n = send_framebuffer_update(vs, last_x * 16, y,
862*3e230dd2SCorentin Chary                                                     (x - last_x) * 16, h);
863*3e230dd2SCorentin Chary                         n_rectangles += n;
864*3e230dd2SCorentin Chary                     }
865*3e230dd2SCorentin Chary                     last_x = -1;
866*3e230dd2SCorentin Chary                 }
867*3e230dd2SCorentin Chary             }
868*3e230dd2SCorentin Chary             if (last_x != -1) {
869*3e230dd2SCorentin Chary                 int h = find_and_clear_dirty_height(vs, y, last_x, x);
870*3e230dd2SCorentin Chary                 n = send_framebuffer_update(vs, last_x * 16, y,
871*3e230dd2SCorentin Chary                                             (x - last_x) * 16, h);
872*3e230dd2SCorentin Chary                 n_rectangles += n;
873*3e230dd2SCorentin Chary             }
874*3e230dd2SCorentin Chary         }
875*3e230dd2SCorentin Chary         vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
876*3e230dd2SCorentin Chary         vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
877*3e230dd2SCorentin Chary         vnc_flush(vs);
878*3e230dd2SCorentin Chary         vs->force_update = 0;
879*3e230dd2SCorentin Chary         return n_rectangles;
880*3e230dd2SCorentin Chary     }
881*3e230dd2SCorentin Chary 
882*3e230dd2SCorentin Chary     if (vs->csock == -1)
883*3e230dd2SCorentin Chary         vnc_disconnect_finish(vs);
884*3e230dd2SCorentin Chary 
885*3e230dd2SCorentin Chary     return 0;
886*3e230dd2SCorentin Chary }
887*3e230dd2SCorentin Chary 
888*3e230dd2SCorentin Chary /* audio */
889*3e230dd2SCorentin Chary static void audio_capture_notify(void *opaque, audcnotification_e cmd)
890*3e230dd2SCorentin Chary {
891*3e230dd2SCorentin Chary     VncState *vs = opaque;
892*3e230dd2SCorentin Chary 
893*3e230dd2SCorentin Chary     switch (cmd) {
894*3e230dd2SCorentin Chary     case AUD_CNOTIFY_DISABLE:
895*3e230dd2SCorentin Chary         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
896*3e230dd2SCorentin Chary         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
897*3e230dd2SCorentin Chary         vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_END);
898*3e230dd2SCorentin Chary         vnc_flush(vs);
899*3e230dd2SCorentin Chary         break;
900*3e230dd2SCorentin Chary 
901*3e230dd2SCorentin Chary     case AUD_CNOTIFY_ENABLE:
902*3e230dd2SCorentin Chary         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
903*3e230dd2SCorentin Chary         vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
904*3e230dd2SCorentin Chary         vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_BEGIN);
905*3e230dd2SCorentin Chary         vnc_flush(vs);
906*3e230dd2SCorentin Chary         break;
907*3e230dd2SCorentin Chary     }
908*3e230dd2SCorentin Chary }
909*3e230dd2SCorentin Chary 
910*3e230dd2SCorentin Chary static void audio_capture_destroy(void *opaque)
911*3e230dd2SCorentin Chary {
912*3e230dd2SCorentin Chary }
913*3e230dd2SCorentin Chary 
914*3e230dd2SCorentin Chary static void audio_capture(void *opaque, void *buf, int size)
915*3e230dd2SCorentin Chary {
916*3e230dd2SCorentin Chary     VncState *vs = opaque;
917*3e230dd2SCorentin Chary 
918*3e230dd2SCorentin Chary     vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
919*3e230dd2SCorentin Chary     vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
920*3e230dd2SCorentin Chary     vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA);
921*3e230dd2SCorentin Chary     vnc_write_u32(vs, size);
922*3e230dd2SCorentin Chary     vnc_write(vs, buf, size);
923*3e230dd2SCorentin Chary     vnc_flush(vs);
924*3e230dd2SCorentin Chary }
925*3e230dd2SCorentin Chary 
926*3e230dd2SCorentin Chary static void audio_add(VncState *vs)
927*3e230dd2SCorentin Chary {
928*3e230dd2SCorentin Chary     struct audio_capture_ops ops;
929*3e230dd2SCorentin Chary 
930*3e230dd2SCorentin Chary     if (vs->audio_cap) {
931*3e230dd2SCorentin Chary         monitor_printf(default_mon, "audio already running\n");
932*3e230dd2SCorentin Chary         return;
933*3e230dd2SCorentin Chary     }
934*3e230dd2SCorentin Chary 
935*3e230dd2SCorentin Chary     ops.notify = audio_capture_notify;
936*3e230dd2SCorentin Chary     ops.destroy = audio_capture_destroy;
937*3e230dd2SCorentin Chary     ops.capture = audio_capture;
938*3e230dd2SCorentin Chary 
939*3e230dd2SCorentin Chary     vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
940*3e230dd2SCorentin Chary     if (!vs->audio_cap) {
941*3e230dd2SCorentin Chary         monitor_printf(default_mon, "Failed to add audio capture\n");
942*3e230dd2SCorentin Chary     }
943*3e230dd2SCorentin Chary }
944*3e230dd2SCorentin Chary 
945*3e230dd2SCorentin Chary static void audio_del(VncState *vs)
946*3e230dd2SCorentin Chary {
947*3e230dd2SCorentin Chary     if (vs->audio_cap) {
948*3e230dd2SCorentin Chary         AUD_del_capture(vs->audio_cap, vs);
949*3e230dd2SCorentin Chary         vs->audio_cap = NULL;
950*3e230dd2SCorentin Chary     }
951*3e230dd2SCorentin Chary }
952*3e230dd2SCorentin Chary 
953*3e230dd2SCorentin Chary static void vnc_disconnect_start(VncState *vs)
954*3e230dd2SCorentin Chary {
955*3e230dd2SCorentin Chary     if (vs->csock == -1)
956*3e230dd2SCorentin Chary         return;
957*3e230dd2SCorentin Chary     qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
958*3e230dd2SCorentin Chary     closesocket(vs->csock);
959*3e230dd2SCorentin Chary     vs->csock = -1;
960*3e230dd2SCorentin Chary }
961*3e230dd2SCorentin Chary 
962*3e230dd2SCorentin Chary static void vnc_disconnect_finish(VncState *vs)
963*3e230dd2SCorentin Chary {
964*3e230dd2SCorentin Chary     vnc_qmp_event(vs, QEVENT_VNC_DISCONNECTED);
965*3e230dd2SCorentin Chary 
966*3e230dd2SCorentin Chary     buffer_free(&vs->input);
967*3e230dd2SCorentin Chary     buffer_free(&vs->output);
968*3e230dd2SCorentin Chary 
969*3e230dd2SCorentin Chary     qobject_decref(vs->info);
970*3e230dd2SCorentin Chary 
971*3e230dd2SCorentin Chary     vnc_zlib_clear(vs);
972*3e230dd2SCorentin Chary     vnc_tight_clear(vs);
973*3e230dd2SCorentin Chary 
974*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
975*3e230dd2SCorentin Chary     vnc_tls_client_cleanup(vs);
976*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
977*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
978*3e230dd2SCorentin Chary     vnc_sasl_client_cleanup(vs);
979*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */
980*3e230dd2SCorentin Chary     audio_del(vs);
981*3e230dd2SCorentin Chary 
982*3e230dd2SCorentin Chary     QTAILQ_REMOVE(&vs->vd->clients, vs, next);
983*3e230dd2SCorentin Chary 
984*3e230dd2SCorentin Chary     if (QTAILQ_EMPTY(&vs->vd->clients)) {
985*3e230dd2SCorentin Chary         dcl->idle = 1;
986*3e230dd2SCorentin Chary     }
987*3e230dd2SCorentin Chary 
988*3e230dd2SCorentin Chary     qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
989*3e230dd2SCorentin Chary     vnc_remove_timer(vs->vd);
990*3e230dd2SCorentin Chary     if (vs->vd->lock_key_sync)
991*3e230dd2SCorentin Chary         qemu_remove_led_event_handler(vs->led);
992*3e230dd2SCorentin Chary     qemu_free(vs);
993*3e230dd2SCorentin Chary }
994*3e230dd2SCorentin Chary 
995*3e230dd2SCorentin Chary int vnc_client_io_error(VncState *vs, int ret, int last_errno)
996*3e230dd2SCorentin Chary {
997*3e230dd2SCorentin Chary     if (ret == 0 || ret == -1) {
998*3e230dd2SCorentin Chary         if (ret == -1) {
999*3e230dd2SCorentin Chary             switch (last_errno) {
1000*3e230dd2SCorentin Chary                 case EINTR:
1001*3e230dd2SCorentin Chary                 case EAGAIN:
1002*3e230dd2SCorentin Chary #ifdef _WIN32
1003*3e230dd2SCorentin Chary                 case WSAEWOULDBLOCK:
1004*3e230dd2SCorentin Chary #endif
1005*3e230dd2SCorentin Chary                     return 0;
1006*3e230dd2SCorentin Chary                 default:
1007*3e230dd2SCorentin Chary                     break;
1008*3e230dd2SCorentin Chary             }
1009*3e230dd2SCorentin Chary         }
1010*3e230dd2SCorentin Chary 
1011*3e230dd2SCorentin Chary         VNC_DEBUG("Closing down client sock: ret %d, errno %d\n",
1012*3e230dd2SCorentin Chary                   ret, ret < 0 ? last_errno : 0);
1013*3e230dd2SCorentin Chary         vnc_disconnect_start(vs);
1014*3e230dd2SCorentin Chary 
1015*3e230dd2SCorentin Chary         return 0;
1016*3e230dd2SCorentin Chary     }
1017*3e230dd2SCorentin Chary     return ret;
1018*3e230dd2SCorentin Chary }
1019*3e230dd2SCorentin Chary 
1020*3e230dd2SCorentin Chary 
1021*3e230dd2SCorentin Chary void vnc_client_error(VncState *vs)
1022*3e230dd2SCorentin Chary {
1023*3e230dd2SCorentin Chary     VNC_DEBUG("Closing down client sock: protocol error\n");
1024*3e230dd2SCorentin Chary     vnc_disconnect_start(vs);
1025*3e230dd2SCorentin Chary }
1026*3e230dd2SCorentin Chary 
1027*3e230dd2SCorentin Chary 
1028*3e230dd2SCorentin Chary /*
1029*3e230dd2SCorentin Chary  * Called to write a chunk of data to the client socket. The data may
1030*3e230dd2SCorentin Chary  * be the raw data, or may have already been encoded by SASL.
1031*3e230dd2SCorentin Chary  * The data will be written either straight onto the socket, or
1032*3e230dd2SCorentin Chary  * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1033*3e230dd2SCorentin Chary  *
1034*3e230dd2SCorentin Chary  * NB, it is theoretically possible to have 2 layers of encryption,
1035*3e230dd2SCorentin Chary  * both SASL, and this TLS layer. It is highly unlikely in practice
1036*3e230dd2SCorentin Chary  * though, since SASL encryption will typically be a no-op if TLS
1037*3e230dd2SCorentin Chary  * is active
1038*3e230dd2SCorentin Chary  *
1039*3e230dd2SCorentin Chary  * Returns the number of bytes written, which may be less than
1040*3e230dd2SCorentin Chary  * the requested 'datalen' if the socket would block. Returns
1041*3e230dd2SCorentin Chary  * -1 on error, and disconnects the client socket.
1042*3e230dd2SCorentin Chary  */
1043*3e230dd2SCorentin Chary long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
1044*3e230dd2SCorentin Chary {
1045*3e230dd2SCorentin Chary     long ret;
1046*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
1047*3e230dd2SCorentin Chary     if (vs->tls.session) {
1048*3e230dd2SCorentin Chary         ret = gnutls_write(vs->tls.session, data, datalen);
1049*3e230dd2SCorentin Chary         if (ret < 0) {
1050*3e230dd2SCorentin Chary             if (ret == GNUTLS_E_AGAIN)
1051*3e230dd2SCorentin Chary                 errno = EAGAIN;
1052*3e230dd2SCorentin Chary             else
1053*3e230dd2SCorentin Chary                 errno = EIO;
1054*3e230dd2SCorentin Chary             ret = -1;
1055*3e230dd2SCorentin Chary         }
1056*3e230dd2SCorentin Chary     } else
1057*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
1058*3e230dd2SCorentin Chary         ret = send(vs->csock, (const void *)data, datalen, 0);
1059*3e230dd2SCorentin Chary     VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
1060*3e230dd2SCorentin Chary     return vnc_client_io_error(vs, ret, socket_error());
1061*3e230dd2SCorentin Chary }
1062*3e230dd2SCorentin Chary 
1063*3e230dd2SCorentin Chary 
1064*3e230dd2SCorentin Chary /*
1065*3e230dd2SCorentin Chary  * Called to write buffered data to the client socket, when not
1066*3e230dd2SCorentin Chary  * using any SASL SSF encryption layers. Will write as much data
1067*3e230dd2SCorentin Chary  * as possible without blocking. If all buffered data is written,
1068*3e230dd2SCorentin Chary  * will switch the FD poll() handler back to read monitoring.
1069*3e230dd2SCorentin Chary  *
1070*3e230dd2SCorentin Chary  * Returns the number of bytes written, which may be less than
1071*3e230dd2SCorentin Chary  * the buffered output data if the socket would block. Returns
1072*3e230dd2SCorentin Chary  * -1 on error, and disconnects the client socket.
1073*3e230dd2SCorentin Chary  */
1074*3e230dd2SCorentin Chary static long vnc_client_write_plain(VncState *vs)
1075*3e230dd2SCorentin Chary {
1076*3e230dd2SCorentin Chary     long ret;
1077*3e230dd2SCorentin Chary 
1078*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
1079*3e230dd2SCorentin Chary     VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
1080*3e230dd2SCorentin Chary               vs->output.buffer, vs->output.capacity, vs->output.offset,
1081*3e230dd2SCorentin Chary               vs->sasl.waitWriteSSF);
1082*3e230dd2SCorentin Chary 
1083*3e230dd2SCorentin Chary     if (vs->sasl.conn &&
1084*3e230dd2SCorentin Chary         vs->sasl.runSSF &&
1085*3e230dd2SCorentin Chary         vs->sasl.waitWriteSSF) {
1086*3e230dd2SCorentin Chary         ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF);
1087*3e230dd2SCorentin Chary         if (ret)
1088*3e230dd2SCorentin Chary             vs->sasl.waitWriteSSF -= ret;
1089*3e230dd2SCorentin Chary     } else
1090*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */
1091*3e230dd2SCorentin Chary         ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset);
1092*3e230dd2SCorentin Chary     if (!ret)
1093*3e230dd2SCorentin Chary         return 0;
1094*3e230dd2SCorentin Chary 
1095*3e230dd2SCorentin Chary     memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
1096*3e230dd2SCorentin Chary     vs->output.offset -= ret;
1097*3e230dd2SCorentin Chary 
1098*3e230dd2SCorentin Chary     if (vs->output.offset == 0) {
1099*3e230dd2SCorentin Chary         qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
1100*3e230dd2SCorentin Chary     }
1101*3e230dd2SCorentin Chary 
1102*3e230dd2SCorentin Chary     return ret;
1103*3e230dd2SCorentin Chary }
1104*3e230dd2SCorentin Chary 
1105*3e230dd2SCorentin Chary 
1106*3e230dd2SCorentin Chary /*
1107*3e230dd2SCorentin Chary  * First function called whenever there is data to be written to
1108*3e230dd2SCorentin Chary  * the client socket. Will delegate actual work according to whether
1109*3e230dd2SCorentin Chary  * SASL SSF layers are enabled (thus requiring encryption calls)
1110*3e230dd2SCorentin Chary  */
1111*3e230dd2SCorentin Chary void vnc_client_write(void *opaque)
1112*3e230dd2SCorentin Chary {
1113*3e230dd2SCorentin Chary     VncState *vs = opaque;
1114*3e230dd2SCorentin Chary 
1115*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
1116*3e230dd2SCorentin Chary     if (vs->sasl.conn &&
1117*3e230dd2SCorentin Chary         vs->sasl.runSSF &&
1118*3e230dd2SCorentin Chary         !vs->sasl.waitWriteSSF) {
1119*3e230dd2SCorentin Chary         vnc_client_write_sasl(vs);
1120*3e230dd2SCorentin Chary     } else
1121*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */
1122*3e230dd2SCorentin Chary         vnc_client_write_plain(vs);
1123*3e230dd2SCorentin Chary }
1124*3e230dd2SCorentin Chary 
1125*3e230dd2SCorentin Chary void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
1126*3e230dd2SCorentin Chary {
1127*3e230dd2SCorentin Chary     vs->read_handler = func;
1128*3e230dd2SCorentin Chary     vs->read_handler_expect = expecting;
1129*3e230dd2SCorentin Chary }
1130*3e230dd2SCorentin Chary 
1131*3e230dd2SCorentin Chary 
1132*3e230dd2SCorentin Chary /*
1133*3e230dd2SCorentin Chary  * Called to read a chunk of data from the client socket. The data may
1134*3e230dd2SCorentin Chary  * be the raw data, or may need to be further decoded by SASL.
1135*3e230dd2SCorentin Chary  * The data will be read either straight from to the socket, or
1136*3e230dd2SCorentin Chary  * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1137*3e230dd2SCorentin Chary  *
1138*3e230dd2SCorentin Chary  * NB, it is theoretically possible to have 2 layers of encryption,
1139*3e230dd2SCorentin Chary  * both SASL, and this TLS layer. It is highly unlikely in practice
1140*3e230dd2SCorentin Chary  * though, since SASL encryption will typically be a no-op if TLS
1141*3e230dd2SCorentin Chary  * is active
1142*3e230dd2SCorentin Chary  *
1143*3e230dd2SCorentin Chary  * Returns the number of bytes read, which may be less than
1144*3e230dd2SCorentin Chary  * the requested 'datalen' if the socket would block. Returns
1145*3e230dd2SCorentin Chary  * -1 on error, and disconnects the client socket.
1146*3e230dd2SCorentin Chary  */
1147*3e230dd2SCorentin Chary long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
1148*3e230dd2SCorentin Chary {
1149*3e230dd2SCorentin Chary     long ret;
1150*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
1151*3e230dd2SCorentin Chary     if (vs->tls.session) {
1152*3e230dd2SCorentin Chary         ret = gnutls_read(vs->tls.session, data, datalen);
1153*3e230dd2SCorentin Chary         if (ret < 0) {
1154*3e230dd2SCorentin Chary             if (ret == GNUTLS_E_AGAIN)
1155*3e230dd2SCorentin Chary                 errno = EAGAIN;
1156*3e230dd2SCorentin Chary             else
1157*3e230dd2SCorentin Chary                 errno = EIO;
1158*3e230dd2SCorentin Chary             ret = -1;
1159*3e230dd2SCorentin Chary         }
1160*3e230dd2SCorentin Chary     } else
1161*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
1162*3e230dd2SCorentin Chary         ret = recv(vs->csock, (void *)data, datalen, 0);
1163*3e230dd2SCorentin Chary     VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
1164*3e230dd2SCorentin Chary     return vnc_client_io_error(vs, ret, socket_error());
1165*3e230dd2SCorentin Chary }
1166*3e230dd2SCorentin Chary 
1167*3e230dd2SCorentin Chary 
1168*3e230dd2SCorentin Chary /*
1169*3e230dd2SCorentin Chary  * Called to read data from the client socket to the input buffer,
1170*3e230dd2SCorentin Chary  * when not using any SASL SSF encryption layers. Will read as much
1171*3e230dd2SCorentin Chary  * data as possible without blocking.
1172*3e230dd2SCorentin Chary  *
1173*3e230dd2SCorentin Chary  * Returns the number of bytes read. Returns -1 on error, and
1174*3e230dd2SCorentin Chary  * disconnects the client socket.
1175*3e230dd2SCorentin Chary  */
1176*3e230dd2SCorentin Chary static long vnc_client_read_plain(VncState *vs)
1177*3e230dd2SCorentin Chary {
1178*3e230dd2SCorentin Chary     int ret;
1179*3e230dd2SCorentin Chary     VNC_DEBUG("Read plain %p size %zd offset %zd\n",
1180*3e230dd2SCorentin Chary               vs->input.buffer, vs->input.capacity, vs->input.offset);
1181*3e230dd2SCorentin Chary     buffer_reserve(&vs->input, 4096);
1182*3e230dd2SCorentin Chary     ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096);
1183*3e230dd2SCorentin Chary     if (!ret)
1184*3e230dd2SCorentin Chary         return 0;
1185*3e230dd2SCorentin Chary     vs->input.offset += ret;
1186*3e230dd2SCorentin Chary     return ret;
1187*3e230dd2SCorentin Chary }
1188*3e230dd2SCorentin Chary 
1189*3e230dd2SCorentin Chary 
1190*3e230dd2SCorentin Chary /*
1191*3e230dd2SCorentin Chary  * First function called whenever there is more data to be read from
1192*3e230dd2SCorentin Chary  * the client socket. Will delegate actual work according to whether
1193*3e230dd2SCorentin Chary  * SASL SSF layers are enabled (thus requiring decryption calls)
1194*3e230dd2SCorentin Chary  */
1195*3e230dd2SCorentin Chary void vnc_client_read(void *opaque)
1196*3e230dd2SCorentin Chary {
1197*3e230dd2SCorentin Chary     VncState *vs = opaque;
1198*3e230dd2SCorentin Chary     long ret;
1199*3e230dd2SCorentin Chary 
1200*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
1201*3e230dd2SCorentin Chary     if (vs->sasl.conn && vs->sasl.runSSF)
1202*3e230dd2SCorentin Chary         ret = vnc_client_read_sasl(vs);
1203*3e230dd2SCorentin Chary     else
1204*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */
1205*3e230dd2SCorentin Chary         ret = vnc_client_read_plain(vs);
1206*3e230dd2SCorentin Chary     if (!ret) {
1207*3e230dd2SCorentin Chary         if (vs->csock == -1)
1208*3e230dd2SCorentin Chary             vnc_disconnect_finish(vs);
1209*3e230dd2SCorentin Chary         return;
1210*3e230dd2SCorentin Chary     }
1211*3e230dd2SCorentin Chary 
1212*3e230dd2SCorentin Chary     while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
1213*3e230dd2SCorentin Chary         size_t len = vs->read_handler_expect;
1214*3e230dd2SCorentin Chary         int ret;
1215*3e230dd2SCorentin Chary 
1216*3e230dd2SCorentin Chary         ret = vs->read_handler(vs, vs->input.buffer, len);
1217*3e230dd2SCorentin Chary         if (vs->csock == -1) {
1218*3e230dd2SCorentin Chary             vnc_disconnect_finish(vs);
1219*3e230dd2SCorentin Chary             return;
1220*3e230dd2SCorentin Chary         }
1221*3e230dd2SCorentin Chary 
1222*3e230dd2SCorentin Chary         if (!ret) {
1223*3e230dd2SCorentin Chary             memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
1224*3e230dd2SCorentin Chary             vs->input.offset -= len;
1225*3e230dd2SCorentin Chary         } else {
1226*3e230dd2SCorentin Chary             vs->read_handler_expect = ret;
1227*3e230dd2SCorentin Chary         }
1228*3e230dd2SCorentin Chary     }
1229*3e230dd2SCorentin Chary }
1230*3e230dd2SCorentin Chary 
1231*3e230dd2SCorentin Chary void vnc_write(VncState *vs, const void *data, size_t len)
1232*3e230dd2SCorentin Chary {
1233*3e230dd2SCorentin Chary     buffer_reserve(&vs->output, len);
1234*3e230dd2SCorentin Chary 
1235*3e230dd2SCorentin Chary     if (vs->csock != -1 && buffer_empty(&vs->output)) {
1236*3e230dd2SCorentin Chary         qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1237*3e230dd2SCorentin Chary     }
1238*3e230dd2SCorentin Chary 
1239*3e230dd2SCorentin Chary     buffer_append(&vs->output, data, len);
1240*3e230dd2SCorentin Chary }
1241*3e230dd2SCorentin Chary 
1242*3e230dd2SCorentin Chary void vnc_write_s32(VncState *vs, int32_t value)
1243*3e230dd2SCorentin Chary {
1244*3e230dd2SCorentin Chary     vnc_write_u32(vs, *(uint32_t *)&value);
1245*3e230dd2SCorentin Chary }
1246*3e230dd2SCorentin Chary 
1247*3e230dd2SCorentin Chary void vnc_write_u32(VncState *vs, uint32_t value)
1248*3e230dd2SCorentin Chary {
1249*3e230dd2SCorentin Chary     uint8_t buf[4];
1250*3e230dd2SCorentin Chary 
1251*3e230dd2SCorentin Chary     buf[0] = (value >> 24) & 0xFF;
1252*3e230dd2SCorentin Chary     buf[1] = (value >> 16) & 0xFF;
1253*3e230dd2SCorentin Chary     buf[2] = (value >>  8) & 0xFF;
1254*3e230dd2SCorentin Chary     buf[3] = value & 0xFF;
1255*3e230dd2SCorentin Chary 
1256*3e230dd2SCorentin Chary     vnc_write(vs, buf, 4);
1257*3e230dd2SCorentin Chary }
1258*3e230dd2SCorentin Chary 
1259*3e230dd2SCorentin Chary void vnc_write_u16(VncState *vs, uint16_t value)
1260*3e230dd2SCorentin Chary {
1261*3e230dd2SCorentin Chary     uint8_t buf[2];
1262*3e230dd2SCorentin Chary 
1263*3e230dd2SCorentin Chary     buf[0] = (value >> 8) & 0xFF;
1264*3e230dd2SCorentin Chary     buf[1] = value & 0xFF;
1265*3e230dd2SCorentin Chary 
1266*3e230dd2SCorentin Chary     vnc_write(vs, buf, 2);
1267*3e230dd2SCorentin Chary }
1268*3e230dd2SCorentin Chary 
1269*3e230dd2SCorentin Chary void vnc_write_u8(VncState *vs, uint8_t value)
1270*3e230dd2SCorentin Chary {
1271*3e230dd2SCorentin Chary     vnc_write(vs, (char *)&value, 1);
1272*3e230dd2SCorentin Chary }
1273*3e230dd2SCorentin Chary 
1274*3e230dd2SCorentin Chary void vnc_flush(VncState *vs)
1275*3e230dd2SCorentin Chary {
1276*3e230dd2SCorentin Chary     if (vs->csock != -1 && vs->output.offset)
1277*3e230dd2SCorentin Chary         vnc_client_write(vs);
1278*3e230dd2SCorentin Chary }
1279*3e230dd2SCorentin Chary 
1280*3e230dd2SCorentin Chary uint8_t read_u8(uint8_t *data, size_t offset)
1281*3e230dd2SCorentin Chary {
1282*3e230dd2SCorentin Chary     return data[offset];
1283*3e230dd2SCorentin Chary }
1284*3e230dd2SCorentin Chary 
1285*3e230dd2SCorentin Chary uint16_t read_u16(uint8_t *data, size_t offset)
1286*3e230dd2SCorentin Chary {
1287*3e230dd2SCorentin Chary     return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
1288*3e230dd2SCorentin Chary }
1289*3e230dd2SCorentin Chary 
1290*3e230dd2SCorentin Chary int32_t read_s32(uint8_t *data, size_t offset)
1291*3e230dd2SCorentin Chary {
1292*3e230dd2SCorentin Chary     return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
1293*3e230dd2SCorentin Chary                      (data[offset + 2] << 8) | data[offset + 3]);
1294*3e230dd2SCorentin Chary }
1295*3e230dd2SCorentin Chary 
1296*3e230dd2SCorentin Chary uint32_t read_u32(uint8_t *data, size_t offset)
1297*3e230dd2SCorentin Chary {
1298*3e230dd2SCorentin Chary     return ((data[offset] << 24) | (data[offset + 1] << 16) |
1299*3e230dd2SCorentin Chary             (data[offset + 2] << 8) | data[offset + 3]);
1300*3e230dd2SCorentin Chary }
1301*3e230dd2SCorentin Chary 
1302*3e230dd2SCorentin Chary static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
1303*3e230dd2SCorentin Chary {
1304*3e230dd2SCorentin Chary }
1305*3e230dd2SCorentin Chary 
1306*3e230dd2SCorentin Chary static void check_pointer_type_change(Notifier *notifier)
1307*3e230dd2SCorentin Chary {
1308*3e230dd2SCorentin Chary     VncState *vs = container_of(notifier, VncState, mouse_mode_notifier);
1309*3e230dd2SCorentin Chary     int absolute = kbd_mouse_is_absolute();
1310*3e230dd2SCorentin Chary 
1311*3e230dd2SCorentin Chary     if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
1312*3e230dd2SCorentin Chary         vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1313*3e230dd2SCorentin Chary         vnc_write_u8(vs, 0);
1314*3e230dd2SCorentin Chary         vnc_write_u16(vs, 1);
1315*3e230dd2SCorentin Chary         vnc_framebuffer_update(vs, absolute, 0,
1316*3e230dd2SCorentin Chary                                ds_get_width(vs->ds), ds_get_height(vs->ds),
1317*3e230dd2SCorentin Chary                                VNC_ENCODING_POINTER_TYPE_CHANGE);
1318*3e230dd2SCorentin Chary         vnc_flush(vs);
1319*3e230dd2SCorentin Chary     }
1320*3e230dd2SCorentin Chary     vs->absolute = absolute;
1321*3e230dd2SCorentin Chary }
1322*3e230dd2SCorentin Chary 
1323*3e230dd2SCorentin Chary static void pointer_event(VncState *vs, int button_mask, int x, int y)
1324*3e230dd2SCorentin Chary {
1325*3e230dd2SCorentin Chary     int buttons = 0;
1326*3e230dd2SCorentin Chary     int dz = 0;
1327*3e230dd2SCorentin Chary 
1328*3e230dd2SCorentin Chary     if (button_mask & 0x01)
1329*3e230dd2SCorentin Chary         buttons |= MOUSE_EVENT_LBUTTON;
1330*3e230dd2SCorentin Chary     if (button_mask & 0x02)
1331*3e230dd2SCorentin Chary         buttons |= MOUSE_EVENT_MBUTTON;
1332*3e230dd2SCorentin Chary     if (button_mask & 0x04)
1333*3e230dd2SCorentin Chary         buttons |= MOUSE_EVENT_RBUTTON;
1334*3e230dd2SCorentin Chary     if (button_mask & 0x08)
1335*3e230dd2SCorentin Chary         dz = -1;
1336*3e230dd2SCorentin Chary     if (button_mask & 0x10)
1337*3e230dd2SCorentin Chary         dz = 1;
1338*3e230dd2SCorentin Chary 
1339*3e230dd2SCorentin Chary     if (vs->absolute) {
1340*3e230dd2SCorentin Chary         kbd_mouse_event(ds_get_width(vs->ds) > 1 ?
1341*3e230dd2SCorentin Chary                           x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000,
1342*3e230dd2SCorentin Chary                         ds_get_height(vs->ds) > 1 ?
1343*3e230dd2SCorentin Chary                           y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000,
1344*3e230dd2SCorentin Chary                         dz, buttons);
1345*3e230dd2SCorentin Chary     } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
1346*3e230dd2SCorentin Chary         x -= 0x7FFF;
1347*3e230dd2SCorentin Chary         y -= 0x7FFF;
1348*3e230dd2SCorentin Chary 
1349*3e230dd2SCorentin Chary         kbd_mouse_event(x, y, dz, buttons);
1350*3e230dd2SCorentin Chary     } else {
1351*3e230dd2SCorentin Chary         if (vs->last_x != -1)
1352*3e230dd2SCorentin Chary             kbd_mouse_event(x - vs->last_x,
1353*3e230dd2SCorentin Chary                             y - vs->last_y,
1354*3e230dd2SCorentin Chary                             dz, buttons);
1355*3e230dd2SCorentin Chary         vs->last_x = x;
1356*3e230dd2SCorentin Chary         vs->last_y = y;
1357*3e230dd2SCorentin Chary     }
1358*3e230dd2SCorentin Chary }
1359*3e230dd2SCorentin Chary 
1360*3e230dd2SCorentin Chary static void reset_keys(VncState *vs)
1361*3e230dd2SCorentin Chary {
1362*3e230dd2SCorentin Chary     int i;
1363*3e230dd2SCorentin Chary     for(i = 0; i < 256; i++) {
1364*3e230dd2SCorentin Chary         if (vs->modifiers_state[i]) {
1365*3e230dd2SCorentin Chary             if (i & SCANCODE_GREY)
1366*3e230dd2SCorentin Chary                 kbd_put_keycode(SCANCODE_EMUL0);
1367*3e230dd2SCorentin Chary             kbd_put_keycode(i | SCANCODE_UP);
1368*3e230dd2SCorentin Chary             vs->modifiers_state[i] = 0;
1369*3e230dd2SCorentin Chary         }
1370*3e230dd2SCorentin Chary     }
1371*3e230dd2SCorentin Chary }
1372*3e230dd2SCorentin Chary 
1373*3e230dd2SCorentin Chary static void press_key(VncState *vs, int keysym)
1374*3e230dd2SCorentin Chary {
1375*3e230dd2SCorentin Chary     int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
1376*3e230dd2SCorentin Chary     if (keycode & SCANCODE_GREY)
1377*3e230dd2SCorentin Chary         kbd_put_keycode(SCANCODE_EMUL0);
1378*3e230dd2SCorentin Chary     kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
1379*3e230dd2SCorentin Chary     if (keycode & SCANCODE_GREY)
1380*3e230dd2SCorentin Chary         kbd_put_keycode(SCANCODE_EMUL0);
1381*3e230dd2SCorentin Chary     kbd_put_keycode(keycode | SCANCODE_UP);
1382*3e230dd2SCorentin Chary }
1383*3e230dd2SCorentin Chary 
1384*3e230dd2SCorentin Chary static void kbd_leds(void *opaque, int ledstate)
1385*3e230dd2SCorentin Chary {
1386*3e230dd2SCorentin Chary     VncState *vs = opaque;
1387*3e230dd2SCorentin Chary     int caps, num;
1388*3e230dd2SCorentin Chary 
1389*3e230dd2SCorentin Chary     caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0;
1390*3e230dd2SCorentin Chary     num  = ledstate & QEMU_NUM_LOCK_LED  ? 1 : 0;
1391*3e230dd2SCorentin Chary 
1392*3e230dd2SCorentin Chary     if (vs->modifiers_state[0x3a] != caps) {
1393*3e230dd2SCorentin Chary         vs->modifiers_state[0x3a] = caps;
1394*3e230dd2SCorentin Chary     }
1395*3e230dd2SCorentin Chary     if (vs->modifiers_state[0x45] != num) {
1396*3e230dd2SCorentin Chary         vs->modifiers_state[0x45] = num;
1397*3e230dd2SCorentin Chary     }
1398*3e230dd2SCorentin Chary }
1399*3e230dd2SCorentin Chary 
1400*3e230dd2SCorentin Chary static void do_key_event(VncState *vs, int down, int keycode, int sym)
1401*3e230dd2SCorentin Chary {
1402*3e230dd2SCorentin Chary     /* QEMU console switch */
1403*3e230dd2SCorentin Chary     switch(keycode) {
1404*3e230dd2SCorentin Chary     case 0x2a:                          /* Left Shift */
1405*3e230dd2SCorentin Chary     case 0x36:                          /* Right Shift */
1406*3e230dd2SCorentin Chary     case 0x1d:                          /* Left CTRL */
1407*3e230dd2SCorentin Chary     case 0x9d:                          /* Right CTRL */
1408*3e230dd2SCorentin Chary     case 0x38:                          /* Left ALT */
1409*3e230dd2SCorentin Chary     case 0xb8:                          /* Right ALT */
1410*3e230dd2SCorentin Chary         if (down)
1411*3e230dd2SCorentin Chary             vs->modifiers_state[keycode] = 1;
1412*3e230dd2SCorentin Chary         else
1413*3e230dd2SCorentin Chary             vs->modifiers_state[keycode] = 0;
1414*3e230dd2SCorentin Chary         break;
1415*3e230dd2SCorentin Chary     case 0x02 ... 0x0a: /* '1' to '9' keys */
1416*3e230dd2SCorentin Chary         if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1417*3e230dd2SCorentin Chary             /* Reset the modifiers sent to the current console */
1418*3e230dd2SCorentin Chary             reset_keys(vs);
1419*3e230dd2SCorentin Chary             console_select(keycode - 0x02);
1420*3e230dd2SCorentin Chary             return;
1421*3e230dd2SCorentin Chary         }
1422*3e230dd2SCorentin Chary         break;
1423*3e230dd2SCorentin Chary     case 0x3a:                        /* CapsLock */
1424*3e230dd2SCorentin Chary     case 0x45:                        /* NumLock */
1425*3e230dd2SCorentin Chary         if (down)
1426*3e230dd2SCorentin Chary             vs->modifiers_state[keycode] ^= 1;
1427*3e230dd2SCorentin Chary         break;
1428*3e230dd2SCorentin Chary     }
1429*3e230dd2SCorentin Chary 
1430*3e230dd2SCorentin Chary     if (vs->vd->lock_key_sync &&
1431*3e230dd2SCorentin Chary         keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
1432*3e230dd2SCorentin Chary         /* If the numlock state needs to change then simulate an additional
1433*3e230dd2SCorentin Chary            keypress before sending this one.  This will happen if the user
1434*3e230dd2SCorentin Chary            toggles numlock away from the VNC window.
1435*3e230dd2SCorentin Chary         */
1436*3e230dd2SCorentin Chary         if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
1437*3e230dd2SCorentin Chary             if (!vs->modifiers_state[0x45]) {
1438*3e230dd2SCorentin Chary                 vs->modifiers_state[0x45] = 1;
1439*3e230dd2SCorentin Chary                 press_key(vs, 0xff7f);
1440*3e230dd2SCorentin Chary             }
1441*3e230dd2SCorentin Chary         } else {
1442*3e230dd2SCorentin Chary             if (vs->modifiers_state[0x45]) {
1443*3e230dd2SCorentin Chary                 vs->modifiers_state[0x45] = 0;
1444*3e230dd2SCorentin Chary                 press_key(vs, 0xff7f);
1445*3e230dd2SCorentin Chary             }
1446*3e230dd2SCorentin Chary         }
1447*3e230dd2SCorentin Chary     }
1448*3e230dd2SCorentin Chary 
1449*3e230dd2SCorentin Chary     if (vs->vd->lock_key_sync &&
1450*3e230dd2SCorentin Chary         ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
1451*3e230dd2SCorentin Chary         /* If the capslock state needs to change then simulate an additional
1452*3e230dd2SCorentin Chary            keypress before sending this one.  This will happen if the user
1453*3e230dd2SCorentin Chary            toggles capslock away from the VNC window.
1454*3e230dd2SCorentin Chary         */
1455*3e230dd2SCorentin Chary         int uppercase = !!(sym >= 'A' && sym <= 'Z');
1456*3e230dd2SCorentin Chary         int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
1457*3e230dd2SCorentin Chary         int capslock = !!(vs->modifiers_state[0x3a]);
1458*3e230dd2SCorentin Chary         if (capslock) {
1459*3e230dd2SCorentin Chary             if (uppercase == shift) {
1460*3e230dd2SCorentin Chary                 vs->modifiers_state[0x3a] = 0;
1461*3e230dd2SCorentin Chary                 press_key(vs, 0xffe5);
1462*3e230dd2SCorentin Chary             }
1463*3e230dd2SCorentin Chary         } else {
1464*3e230dd2SCorentin Chary             if (uppercase != shift) {
1465*3e230dd2SCorentin Chary                 vs->modifiers_state[0x3a] = 1;
1466*3e230dd2SCorentin Chary                 press_key(vs, 0xffe5);
1467*3e230dd2SCorentin Chary             }
1468*3e230dd2SCorentin Chary         }
1469*3e230dd2SCorentin Chary     }
1470*3e230dd2SCorentin Chary 
1471*3e230dd2SCorentin Chary     if (is_graphic_console()) {
1472*3e230dd2SCorentin Chary         if (keycode & SCANCODE_GREY)
1473*3e230dd2SCorentin Chary             kbd_put_keycode(SCANCODE_EMUL0);
1474*3e230dd2SCorentin Chary         if (down)
1475*3e230dd2SCorentin Chary             kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
1476*3e230dd2SCorentin Chary         else
1477*3e230dd2SCorentin Chary             kbd_put_keycode(keycode | SCANCODE_UP);
1478*3e230dd2SCorentin Chary     } else {
1479*3e230dd2SCorentin Chary         /* QEMU console emulation */
1480*3e230dd2SCorentin Chary         if (down) {
1481*3e230dd2SCorentin Chary             int numlock = vs->modifiers_state[0x45];
1482*3e230dd2SCorentin Chary             switch (keycode) {
1483*3e230dd2SCorentin Chary             case 0x2a:                          /* Left Shift */
1484*3e230dd2SCorentin Chary             case 0x36:                          /* Right Shift */
1485*3e230dd2SCorentin Chary             case 0x1d:                          /* Left CTRL */
1486*3e230dd2SCorentin Chary             case 0x9d:                          /* Right CTRL */
1487*3e230dd2SCorentin Chary             case 0x38:                          /* Left ALT */
1488*3e230dd2SCorentin Chary             case 0xb8:                          /* Right ALT */
1489*3e230dd2SCorentin Chary                 break;
1490*3e230dd2SCorentin Chary             case 0xc8:
1491*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_UP);
1492*3e230dd2SCorentin Chary                 break;
1493*3e230dd2SCorentin Chary             case 0xd0:
1494*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_DOWN);
1495*3e230dd2SCorentin Chary                 break;
1496*3e230dd2SCorentin Chary             case 0xcb:
1497*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_LEFT);
1498*3e230dd2SCorentin Chary                 break;
1499*3e230dd2SCorentin Chary             case 0xcd:
1500*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_RIGHT);
1501*3e230dd2SCorentin Chary                 break;
1502*3e230dd2SCorentin Chary             case 0xd3:
1503*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_DELETE);
1504*3e230dd2SCorentin Chary                 break;
1505*3e230dd2SCorentin Chary             case 0xc7:
1506*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_HOME);
1507*3e230dd2SCorentin Chary                 break;
1508*3e230dd2SCorentin Chary             case 0xcf:
1509*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_END);
1510*3e230dd2SCorentin Chary                 break;
1511*3e230dd2SCorentin Chary             case 0xc9:
1512*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_PAGEUP);
1513*3e230dd2SCorentin Chary                 break;
1514*3e230dd2SCorentin Chary             case 0xd1:
1515*3e230dd2SCorentin Chary                 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1516*3e230dd2SCorentin Chary                 break;
1517*3e230dd2SCorentin Chary 
1518*3e230dd2SCorentin Chary             case 0x47:
1519*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
1520*3e230dd2SCorentin Chary                 break;
1521*3e230dd2SCorentin Chary             case 0x48:
1522*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
1523*3e230dd2SCorentin Chary                 break;
1524*3e230dd2SCorentin Chary             case 0x49:
1525*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
1526*3e230dd2SCorentin Chary                 break;
1527*3e230dd2SCorentin Chary             case 0x4b:
1528*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
1529*3e230dd2SCorentin Chary                 break;
1530*3e230dd2SCorentin Chary             case 0x4c:
1531*3e230dd2SCorentin Chary                 kbd_put_keysym('5');
1532*3e230dd2SCorentin Chary                 break;
1533*3e230dd2SCorentin Chary             case 0x4d:
1534*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
1535*3e230dd2SCorentin Chary                 break;
1536*3e230dd2SCorentin Chary             case 0x4f:
1537*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
1538*3e230dd2SCorentin Chary                 break;
1539*3e230dd2SCorentin Chary             case 0x50:
1540*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
1541*3e230dd2SCorentin Chary                 break;
1542*3e230dd2SCorentin Chary             case 0x51:
1543*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
1544*3e230dd2SCorentin Chary                 break;
1545*3e230dd2SCorentin Chary             case 0x52:
1546*3e230dd2SCorentin Chary                 kbd_put_keysym('0');
1547*3e230dd2SCorentin Chary                 break;
1548*3e230dd2SCorentin Chary             case 0x53:
1549*3e230dd2SCorentin Chary                 kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
1550*3e230dd2SCorentin Chary                 break;
1551*3e230dd2SCorentin Chary 
1552*3e230dd2SCorentin Chary             case 0xb5:
1553*3e230dd2SCorentin Chary                 kbd_put_keysym('/');
1554*3e230dd2SCorentin Chary                 break;
1555*3e230dd2SCorentin Chary             case 0x37:
1556*3e230dd2SCorentin Chary                 kbd_put_keysym('*');
1557*3e230dd2SCorentin Chary                 break;
1558*3e230dd2SCorentin Chary             case 0x4a:
1559*3e230dd2SCorentin Chary                 kbd_put_keysym('-');
1560*3e230dd2SCorentin Chary                 break;
1561*3e230dd2SCorentin Chary             case 0x4e:
1562*3e230dd2SCorentin Chary                 kbd_put_keysym('+');
1563*3e230dd2SCorentin Chary                 break;
1564*3e230dd2SCorentin Chary             case 0x9c:
1565*3e230dd2SCorentin Chary                 kbd_put_keysym('\n');
1566*3e230dd2SCorentin Chary                 break;
1567*3e230dd2SCorentin Chary 
1568*3e230dd2SCorentin Chary             default:
1569*3e230dd2SCorentin Chary                 kbd_put_keysym(sym);
1570*3e230dd2SCorentin Chary                 break;
1571*3e230dd2SCorentin Chary             }
1572*3e230dd2SCorentin Chary         }
1573*3e230dd2SCorentin Chary     }
1574*3e230dd2SCorentin Chary }
1575*3e230dd2SCorentin Chary 
1576*3e230dd2SCorentin Chary static void key_event(VncState *vs, int down, uint32_t sym)
1577*3e230dd2SCorentin Chary {
1578*3e230dd2SCorentin Chary     int keycode;
1579*3e230dd2SCorentin Chary     int lsym = sym;
1580*3e230dd2SCorentin Chary 
1581*3e230dd2SCorentin Chary     if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) {
1582*3e230dd2SCorentin Chary         lsym = lsym - 'A' + 'a';
1583*3e230dd2SCorentin Chary     }
1584*3e230dd2SCorentin Chary 
1585*3e230dd2SCorentin Chary     keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
1586*3e230dd2SCorentin Chary     do_key_event(vs, down, keycode, sym);
1587*3e230dd2SCorentin Chary }
1588*3e230dd2SCorentin Chary 
1589*3e230dd2SCorentin Chary static void ext_key_event(VncState *vs, int down,
1590*3e230dd2SCorentin Chary                           uint32_t sym, uint16_t keycode)
1591*3e230dd2SCorentin Chary {
1592*3e230dd2SCorentin Chary     /* if the user specifies a keyboard layout, always use it */
1593*3e230dd2SCorentin Chary     if (keyboard_layout)
1594*3e230dd2SCorentin Chary         key_event(vs, down, sym);
1595*3e230dd2SCorentin Chary     else
1596*3e230dd2SCorentin Chary         do_key_event(vs, down, keycode, sym);
1597*3e230dd2SCorentin Chary }
1598*3e230dd2SCorentin Chary 
1599*3e230dd2SCorentin Chary static void framebuffer_update_request(VncState *vs, int incremental,
1600*3e230dd2SCorentin Chary                                        int x_position, int y_position,
1601*3e230dd2SCorentin Chary                                        int w, int h)
1602*3e230dd2SCorentin Chary {
1603*3e230dd2SCorentin Chary     if (y_position > ds_get_height(vs->ds))
1604*3e230dd2SCorentin Chary         y_position = ds_get_height(vs->ds);
1605*3e230dd2SCorentin Chary     if (y_position + h >= ds_get_height(vs->ds))
1606*3e230dd2SCorentin Chary         h = ds_get_height(vs->ds) - y_position;
1607*3e230dd2SCorentin Chary 
1608*3e230dd2SCorentin Chary     int i;
1609*3e230dd2SCorentin Chary     vs->need_update = 1;
1610*3e230dd2SCorentin Chary     if (!incremental) {
1611*3e230dd2SCorentin Chary         vs->force_update = 1;
1612*3e230dd2SCorentin Chary         for (i = 0; i < h; i++) {
1613*3e230dd2SCorentin Chary             vnc_set_bits(vs->dirty[y_position + i],
1614*3e230dd2SCorentin Chary                          (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1615*3e230dd2SCorentin Chary         }
1616*3e230dd2SCorentin Chary     }
1617*3e230dd2SCorentin Chary }
1618*3e230dd2SCorentin Chary 
1619*3e230dd2SCorentin Chary static void send_ext_key_event_ack(VncState *vs)
1620*3e230dd2SCorentin Chary {
1621*3e230dd2SCorentin Chary     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1622*3e230dd2SCorentin Chary     vnc_write_u8(vs, 0);
1623*3e230dd2SCorentin Chary     vnc_write_u16(vs, 1);
1624*3e230dd2SCorentin Chary     vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1625*3e230dd2SCorentin Chary                            VNC_ENCODING_EXT_KEY_EVENT);
1626*3e230dd2SCorentin Chary     vnc_flush(vs);
1627*3e230dd2SCorentin Chary }
1628*3e230dd2SCorentin Chary 
1629*3e230dd2SCorentin Chary static void send_ext_audio_ack(VncState *vs)
1630*3e230dd2SCorentin Chary {
1631*3e230dd2SCorentin Chary     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1632*3e230dd2SCorentin Chary     vnc_write_u8(vs, 0);
1633*3e230dd2SCorentin Chary     vnc_write_u16(vs, 1);
1634*3e230dd2SCorentin Chary     vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1635*3e230dd2SCorentin Chary                            VNC_ENCODING_AUDIO);
1636*3e230dd2SCorentin Chary     vnc_flush(vs);
1637*3e230dd2SCorentin Chary }
1638*3e230dd2SCorentin Chary 
1639*3e230dd2SCorentin Chary static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1640*3e230dd2SCorentin Chary {
1641*3e230dd2SCorentin Chary     int i;
1642*3e230dd2SCorentin Chary     unsigned int enc = 0;
1643*3e230dd2SCorentin Chary 
1644*3e230dd2SCorentin Chary     vs->features = 0;
1645*3e230dd2SCorentin Chary     vs->vnc_encoding = 0;
1646*3e230dd2SCorentin Chary     vs->tight_compression = 9;
1647*3e230dd2SCorentin Chary     vs->tight_quality = -1; /* Lossless by default */
1648*3e230dd2SCorentin Chary     vs->absolute = -1;
1649*3e230dd2SCorentin Chary 
1650*3e230dd2SCorentin Chary     /*
1651*3e230dd2SCorentin Chary      * Start from the end because the encodings are sent in order of preference.
1652*3e230dd2SCorentin Chary      * This way the prefered encoding (first encoding defined in the array)
1653*3e230dd2SCorentin Chary      * will be set at the end of the loop.
1654*3e230dd2SCorentin Chary      */
1655*3e230dd2SCorentin Chary     for (i = n_encodings - 1; i >= 0; i--) {
1656*3e230dd2SCorentin Chary         enc = encodings[i];
1657*3e230dd2SCorentin Chary         switch (enc) {
1658*3e230dd2SCorentin Chary         case VNC_ENCODING_RAW:
1659*3e230dd2SCorentin Chary             vs->vnc_encoding = enc;
1660*3e230dd2SCorentin Chary             break;
1661*3e230dd2SCorentin Chary         case VNC_ENCODING_COPYRECT:
1662*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_COPYRECT_MASK;
1663*3e230dd2SCorentin Chary             break;
1664*3e230dd2SCorentin Chary         case VNC_ENCODING_HEXTILE:
1665*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_HEXTILE_MASK;
1666*3e230dd2SCorentin Chary             vs->vnc_encoding = enc;
1667*3e230dd2SCorentin Chary             break;
1668*3e230dd2SCorentin Chary         case VNC_ENCODING_TIGHT:
1669*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_TIGHT_MASK;
1670*3e230dd2SCorentin Chary             vs->vnc_encoding = enc;
1671*3e230dd2SCorentin Chary             break;
1672*3e230dd2SCorentin Chary         case VNC_ENCODING_ZLIB:
1673*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_ZLIB_MASK;
1674*3e230dd2SCorentin Chary             vs->vnc_encoding = enc;
1675*3e230dd2SCorentin Chary             break;
1676*3e230dd2SCorentin Chary         case VNC_ENCODING_DESKTOPRESIZE:
1677*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_RESIZE_MASK;
1678*3e230dd2SCorentin Chary             break;
1679*3e230dd2SCorentin Chary         case VNC_ENCODING_POINTER_TYPE_CHANGE:
1680*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
1681*3e230dd2SCorentin Chary             break;
1682*3e230dd2SCorentin Chary         case VNC_ENCODING_RICH_CURSOR:
1683*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
1684*3e230dd2SCorentin Chary             break;
1685*3e230dd2SCorentin Chary         case VNC_ENCODING_EXT_KEY_EVENT:
1686*3e230dd2SCorentin Chary             send_ext_key_event_ack(vs);
1687*3e230dd2SCorentin Chary             break;
1688*3e230dd2SCorentin Chary         case VNC_ENCODING_AUDIO:
1689*3e230dd2SCorentin Chary             send_ext_audio_ack(vs);
1690*3e230dd2SCorentin Chary             break;
1691*3e230dd2SCorentin Chary         case VNC_ENCODING_WMVi:
1692*3e230dd2SCorentin Chary             vs->features |= VNC_FEATURE_WMVI_MASK;
1693*3e230dd2SCorentin Chary             break;
1694*3e230dd2SCorentin Chary         case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
1695*3e230dd2SCorentin Chary             vs->tight_compression = (enc & 0x0F);
1696*3e230dd2SCorentin Chary             break;
1697*3e230dd2SCorentin Chary         case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
1698*3e230dd2SCorentin Chary             vs->tight_quality = (enc & 0x0F);
1699*3e230dd2SCorentin Chary             break;
1700*3e230dd2SCorentin Chary         default:
1701*3e230dd2SCorentin Chary             VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
1702*3e230dd2SCorentin Chary             break;
1703*3e230dd2SCorentin Chary         }
1704*3e230dd2SCorentin Chary     }
1705*3e230dd2SCorentin Chary     vnc_desktop_resize(vs);
1706*3e230dd2SCorentin Chary     check_pointer_type_change(&vs->mouse_mode_notifier);
1707*3e230dd2SCorentin Chary }
1708*3e230dd2SCorentin Chary 
1709*3e230dd2SCorentin Chary static void set_pixel_conversion(VncState *vs)
1710*3e230dd2SCorentin Chary {
1711*3e230dd2SCorentin Chary     if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
1712*3e230dd2SCorentin Chary         (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
1713*3e230dd2SCorentin Chary         !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
1714*3e230dd2SCorentin Chary         vs->write_pixels = vnc_write_pixels_copy;
1715*3e230dd2SCorentin Chary         vnc_hextile_set_pixel_conversion(vs, 0);
1716*3e230dd2SCorentin Chary     } else {
1717*3e230dd2SCorentin Chary         vs->write_pixels = vnc_write_pixels_generic;
1718*3e230dd2SCorentin Chary         vnc_hextile_set_pixel_conversion(vs, 1);
1719*3e230dd2SCorentin Chary     }
1720*3e230dd2SCorentin Chary }
1721*3e230dd2SCorentin Chary 
1722*3e230dd2SCorentin Chary static void set_pixel_format(VncState *vs,
1723*3e230dd2SCorentin Chary                              int bits_per_pixel, int depth,
1724*3e230dd2SCorentin Chary                              int big_endian_flag, int true_color_flag,
1725*3e230dd2SCorentin Chary                              int red_max, int green_max, int blue_max,
1726*3e230dd2SCorentin Chary                              int red_shift, int green_shift, int blue_shift)
1727*3e230dd2SCorentin Chary {
1728*3e230dd2SCorentin Chary     if (!true_color_flag) {
1729*3e230dd2SCorentin Chary         vnc_client_error(vs);
1730*3e230dd2SCorentin Chary         return;
1731*3e230dd2SCorentin Chary     }
1732*3e230dd2SCorentin Chary 
1733*3e230dd2SCorentin Chary     vs->clientds = *(vs->vd->guest.ds);
1734*3e230dd2SCorentin Chary     vs->clientds.pf.rmax = red_max;
1735*3e230dd2SCorentin Chary     count_bits(vs->clientds.pf.rbits, red_max);
1736*3e230dd2SCorentin Chary     vs->clientds.pf.rshift = red_shift;
1737*3e230dd2SCorentin Chary     vs->clientds.pf.rmask = red_max << red_shift;
1738*3e230dd2SCorentin Chary     vs->clientds.pf.gmax = green_max;
1739*3e230dd2SCorentin Chary     count_bits(vs->clientds.pf.gbits, green_max);
1740*3e230dd2SCorentin Chary     vs->clientds.pf.gshift = green_shift;
1741*3e230dd2SCorentin Chary     vs->clientds.pf.gmask = green_max << green_shift;
1742*3e230dd2SCorentin Chary     vs->clientds.pf.bmax = blue_max;
1743*3e230dd2SCorentin Chary     count_bits(vs->clientds.pf.bbits, blue_max);
1744*3e230dd2SCorentin Chary     vs->clientds.pf.bshift = blue_shift;
1745*3e230dd2SCorentin Chary     vs->clientds.pf.bmask = blue_max << blue_shift;
1746*3e230dd2SCorentin Chary     vs->clientds.pf.bits_per_pixel = bits_per_pixel;
1747*3e230dd2SCorentin Chary     vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8;
1748*3e230dd2SCorentin Chary     vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
1749*3e230dd2SCorentin Chary     vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00;
1750*3e230dd2SCorentin Chary 
1751*3e230dd2SCorentin Chary     set_pixel_conversion(vs);
1752*3e230dd2SCorentin Chary 
1753*3e230dd2SCorentin Chary     vga_hw_invalidate();
1754*3e230dd2SCorentin Chary     vga_hw_update();
1755*3e230dd2SCorentin Chary }
1756*3e230dd2SCorentin Chary 
1757*3e230dd2SCorentin Chary static void pixel_format_message (VncState *vs) {
1758*3e230dd2SCorentin Chary     char pad[3] = { 0, 0, 0 };
1759*3e230dd2SCorentin Chary 
1760*3e230dd2SCorentin Chary     vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */
1761*3e230dd2SCorentin Chary     vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */
1762*3e230dd2SCorentin Chary 
1763*3e230dd2SCorentin Chary #ifdef HOST_WORDS_BIGENDIAN
1764*3e230dd2SCorentin Chary     vnc_write_u8(vs, 1);             /* big-endian-flag */
1765*3e230dd2SCorentin Chary #else
1766*3e230dd2SCorentin Chary     vnc_write_u8(vs, 0);             /* big-endian-flag */
1767*3e230dd2SCorentin Chary #endif
1768*3e230dd2SCorentin Chary     vnc_write_u8(vs, 1);             /* true-color-flag */
1769*3e230dd2SCorentin Chary     vnc_write_u16(vs, vs->ds->surface->pf.rmax);     /* red-max */
1770*3e230dd2SCorentin Chary     vnc_write_u16(vs, vs->ds->surface->pf.gmax);     /* green-max */
1771*3e230dd2SCorentin Chary     vnc_write_u16(vs, vs->ds->surface->pf.bmax);     /* blue-max */
1772*3e230dd2SCorentin Chary     vnc_write_u8(vs, vs->ds->surface->pf.rshift);    /* red-shift */
1773*3e230dd2SCorentin Chary     vnc_write_u8(vs, vs->ds->surface->pf.gshift);    /* green-shift */
1774*3e230dd2SCorentin Chary     vnc_write_u8(vs, vs->ds->surface->pf.bshift);    /* blue-shift */
1775*3e230dd2SCorentin Chary 
1776*3e230dd2SCorentin Chary     vnc_hextile_set_pixel_conversion(vs, 0);
1777*3e230dd2SCorentin Chary 
1778*3e230dd2SCorentin Chary     vs->clientds = *(vs->ds->surface);
1779*3e230dd2SCorentin Chary     vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
1780*3e230dd2SCorentin Chary     vs->write_pixels = vnc_write_pixels_copy;
1781*3e230dd2SCorentin Chary 
1782*3e230dd2SCorentin Chary     vnc_write(vs, pad, 3);           /* padding */
1783*3e230dd2SCorentin Chary }
1784*3e230dd2SCorentin Chary 
1785*3e230dd2SCorentin Chary static void vnc_dpy_setdata(DisplayState *ds)
1786*3e230dd2SCorentin Chary {
1787*3e230dd2SCorentin Chary     /* We don't have to do anything */
1788*3e230dd2SCorentin Chary }
1789*3e230dd2SCorentin Chary 
1790*3e230dd2SCorentin Chary static void vnc_colordepth(VncState *vs)
1791*3e230dd2SCorentin Chary {
1792*3e230dd2SCorentin Chary     if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
1793*3e230dd2SCorentin Chary         /* Sending a WMVi message to notify the client*/
1794*3e230dd2SCorentin Chary         vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1795*3e230dd2SCorentin Chary         vnc_write_u8(vs, 0);
1796*3e230dd2SCorentin Chary         vnc_write_u16(vs, 1); /* number of rects */
1797*3e230dd2SCorentin Chary         vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
1798*3e230dd2SCorentin Chary                                ds_get_height(vs->ds), VNC_ENCODING_WMVi);
1799*3e230dd2SCorentin Chary         pixel_format_message(vs);
1800*3e230dd2SCorentin Chary         vnc_flush(vs);
1801*3e230dd2SCorentin Chary     } else {
1802*3e230dd2SCorentin Chary         set_pixel_conversion(vs);
1803*3e230dd2SCorentin Chary     }
1804*3e230dd2SCorentin Chary }
1805*3e230dd2SCorentin Chary 
1806*3e230dd2SCorentin Chary static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1807*3e230dd2SCorentin Chary {
1808*3e230dd2SCorentin Chary     int i;
1809*3e230dd2SCorentin Chary     uint16_t limit;
1810*3e230dd2SCorentin Chary     VncDisplay *vd = vs->vd;
1811*3e230dd2SCorentin Chary 
1812*3e230dd2SCorentin Chary     if (data[0] > 3) {
1813*3e230dd2SCorentin Chary         vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1814*3e230dd2SCorentin Chary         if (!qemu_timer_expired(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval))
1815*3e230dd2SCorentin Chary             qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
1816*3e230dd2SCorentin Chary     }
1817*3e230dd2SCorentin Chary 
1818*3e230dd2SCorentin Chary     switch (data[0]) {
1819*3e230dd2SCorentin Chary     case VNC_MSG_CLIENT_SET_PIXEL_FORMAT:
1820*3e230dd2SCorentin Chary         if (len == 1)
1821*3e230dd2SCorentin Chary             return 20;
1822*3e230dd2SCorentin Chary 
1823*3e230dd2SCorentin Chary         set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1824*3e230dd2SCorentin Chary                          read_u8(data, 6), read_u8(data, 7),
1825*3e230dd2SCorentin Chary                          read_u16(data, 8), read_u16(data, 10),
1826*3e230dd2SCorentin Chary                          read_u16(data, 12), read_u8(data, 14),
1827*3e230dd2SCorentin Chary                          read_u8(data, 15), read_u8(data, 16));
1828*3e230dd2SCorentin Chary         break;
1829*3e230dd2SCorentin Chary     case VNC_MSG_CLIENT_SET_ENCODINGS:
1830*3e230dd2SCorentin Chary         if (len == 1)
1831*3e230dd2SCorentin Chary             return 4;
1832*3e230dd2SCorentin Chary 
1833*3e230dd2SCorentin Chary         if (len == 4) {
1834*3e230dd2SCorentin Chary             limit = read_u16(data, 2);
1835*3e230dd2SCorentin Chary             if (limit > 0)
1836*3e230dd2SCorentin Chary                 return 4 + (limit * 4);
1837*3e230dd2SCorentin Chary         } else
1838*3e230dd2SCorentin Chary             limit = read_u16(data, 2);
1839*3e230dd2SCorentin Chary 
1840*3e230dd2SCorentin Chary         for (i = 0; i < limit; i++) {
1841*3e230dd2SCorentin Chary             int32_t val = read_s32(data, 4 + (i * 4));
1842*3e230dd2SCorentin Chary             memcpy(data + 4 + (i * 4), &val, sizeof(val));
1843*3e230dd2SCorentin Chary         }
1844*3e230dd2SCorentin Chary 
1845*3e230dd2SCorentin Chary         set_encodings(vs, (int32_t *)(data + 4), limit);
1846*3e230dd2SCorentin Chary         break;
1847*3e230dd2SCorentin Chary     case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST:
1848*3e230dd2SCorentin Chary         if (len == 1)
1849*3e230dd2SCorentin Chary             return 10;
1850*3e230dd2SCorentin Chary 
1851*3e230dd2SCorentin Chary         framebuffer_update_request(vs,
1852*3e230dd2SCorentin Chary                                    read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1853*3e230dd2SCorentin Chary                                    read_u16(data, 6), read_u16(data, 8));
1854*3e230dd2SCorentin Chary         break;
1855*3e230dd2SCorentin Chary     case VNC_MSG_CLIENT_KEY_EVENT:
1856*3e230dd2SCorentin Chary         if (len == 1)
1857*3e230dd2SCorentin Chary             return 8;
1858*3e230dd2SCorentin Chary 
1859*3e230dd2SCorentin Chary         key_event(vs, read_u8(data, 1), read_u32(data, 4));
1860*3e230dd2SCorentin Chary         break;
1861*3e230dd2SCorentin Chary     case VNC_MSG_CLIENT_POINTER_EVENT:
1862*3e230dd2SCorentin Chary         if (len == 1)
1863*3e230dd2SCorentin Chary             return 6;
1864*3e230dd2SCorentin Chary 
1865*3e230dd2SCorentin Chary         pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1866*3e230dd2SCorentin Chary         break;
1867*3e230dd2SCorentin Chary     case VNC_MSG_CLIENT_CUT_TEXT:
1868*3e230dd2SCorentin Chary         if (len == 1)
1869*3e230dd2SCorentin Chary             return 8;
1870*3e230dd2SCorentin Chary 
1871*3e230dd2SCorentin Chary         if (len == 8) {
1872*3e230dd2SCorentin Chary             uint32_t dlen = read_u32(data, 4);
1873*3e230dd2SCorentin Chary             if (dlen > 0)
1874*3e230dd2SCorentin Chary                 return 8 + dlen;
1875*3e230dd2SCorentin Chary         }
1876*3e230dd2SCorentin Chary 
1877*3e230dd2SCorentin Chary         client_cut_text(vs, read_u32(data, 4), data + 8);
1878*3e230dd2SCorentin Chary         break;
1879*3e230dd2SCorentin Chary     case VNC_MSG_CLIENT_QEMU:
1880*3e230dd2SCorentin Chary         if (len == 1)
1881*3e230dd2SCorentin Chary             return 2;
1882*3e230dd2SCorentin Chary 
1883*3e230dd2SCorentin Chary         switch (read_u8(data, 1)) {
1884*3e230dd2SCorentin Chary         case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT:
1885*3e230dd2SCorentin Chary             if (len == 2)
1886*3e230dd2SCorentin Chary                 return 12;
1887*3e230dd2SCorentin Chary 
1888*3e230dd2SCorentin Chary             ext_key_event(vs, read_u16(data, 2),
1889*3e230dd2SCorentin Chary                           read_u32(data, 4), read_u32(data, 8));
1890*3e230dd2SCorentin Chary             break;
1891*3e230dd2SCorentin Chary         case VNC_MSG_CLIENT_QEMU_AUDIO:
1892*3e230dd2SCorentin Chary             if (len == 2)
1893*3e230dd2SCorentin Chary                 return 4;
1894*3e230dd2SCorentin Chary 
1895*3e230dd2SCorentin Chary             switch (read_u16 (data, 2)) {
1896*3e230dd2SCorentin Chary             case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:
1897*3e230dd2SCorentin Chary                 audio_add(vs);
1898*3e230dd2SCorentin Chary                 break;
1899*3e230dd2SCorentin Chary             case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:
1900*3e230dd2SCorentin Chary                 audio_del(vs);
1901*3e230dd2SCorentin Chary                 break;
1902*3e230dd2SCorentin Chary             case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:
1903*3e230dd2SCorentin Chary                 if (len == 4)
1904*3e230dd2SCorentin Chary                     return 10;
1905*3e230dd2SCorentin Chary                 switch (read_u8(data, 4)) {
1906*3e230dd2SCorentin Chary                 case 0: vs->as.fmt = AUD_FMT_U8; break;
1907*3e230dd2SCorentin Chary                 case 1: vs->as.fmt = AUD_FMT_S8; break;
1908*3e230dd2SCorentin Chary                 case 2: vs->as.fmt = AUD_FMT_U16; break;
1909*3e230dd2SCorentin Chary                 case 3: vs->as.fmt = AUD_FMT_S16; break;
1910*3e230dd2SCorentin Chary                 case 4: vs->as.fmt = AUD_FMT_U32; break;
1911*3e230dd2SCorentin Chary                 case 5: vs->as.fmt = AUD_FMT_S32; break;
1912*3e230dd2SCorentin Chary                 default:
1913*3e230dd2SCorentin Chary                     printf("Invalid audio format %d\n", read_u8(data, 4));
1914*3e230dd2SCorentin Chary                     vnc_client_error(vs);
1915*3e230dd2SCorentin Chary                     break;
1916*3e230dd2SCorentin Chary                 }
1917*3e230dd2SCorentin Chary                 vs->as.nchannels = read_u8(data, 5);
1918*3e230dd2SCorentin Chary                 if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
1919*3e230dd2SCorentin Chary                     printf("Invalid audio channel coount %d\n",
1920*3e230dd2SCorentin Chary                            read_u8(data, 5));
1921*3e230dd2SCorentin Chary                     vnc_client_error(vs);
1922*3e230dd2SCorentin Chary                     break;
1923*3e230dd2SCorentin Chary                 }
1924*3e230dd2SCorentin Chary                 vs->as.freq = read_u32(data, 6);
1925*3e230dd2SCorentin Chary                 break;
1926*3e230dd2SCorentin Chary             default:
1927*3e230dd2SCorentin Chary                 printf ("Invalid audio message %d\n", read_u8(data, 4));
1928*3e230dd2SCorentin Chary                 vnc_client_error(vs);
1929*3e230dd2SCorentin Chary                 break;
1930*3e230dd2SCorentin Chary             }
1931*3e230dd2SCorentin Chary             break;
1932*3e230dd2SCorentin Chary 
1933*3e230dd2SCorentin Chary         default:
1934*3e230dd2SCorentin Chary             printf("Msg: %d\n", read_u16(data, 0));
1935*3e230dd2SCorentin Chary             vnc_client_error(vs);
1936*3e230dd2SCorentin Chary             break;
1937*3e230dd2SCorentin Chary         }
1938*3e230dd2SCorentin Chary         break;
1939*3e230dd2SCorentin Chary     default:
1940*3e230dd2SCorentin Chary         printf("Msg: %d\n", data[0]);
1941*3e230dd2SCorentin Chary         vnc_client_error(vs);
1942*3e230dd2SCorentin Chary         break;
1943*3e230dd2SCorentin Chary     }
1944*3e230dd2SCorentin Chary 
1945*3e230dd2SCorentin Chary     vnc_read_when(vs, protocol_client_msg, 1);
1946*3e230dd2SCorentin Chary     return 0;
1947*3e230dd2SCorentin Chary }
1948*3e230dd2SCorentin Chary 
1949*3e230dd2SCorentin Chary static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1950*3e230dd2SCorentin Chary {
1951*3e230dd2SCorentin Chary     char buf[1024];
1952*3e230dd2SCorentin Chary     int size;
1953*3e230dd2SCorentin Chary 
1954*3e230dd2SCorentin Chary     vs->client_width = ds_get_width(vs->ds);
1955*3e230dd2SCorentin Chary     vs->client_height = ds_get_height(vs->ds);
1956*3e230dd2SCorentin Chary     vnc_write_u16(vs, vs->client_width);
1957*3e230dd2SCorentin Chary     vnc_write_u16(vs, vs->client_height);
1958*3e230dd2SCorentin Chary 
1959*3e230dd2SCorentin Chary     pixel_format_message(vs);
1960*3e230dd2SCorentin Chary 
1961*3e230dd2SCorentin Chary     if (qemu_name)
1962*3e230dd2SCorentin Chary         size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
1963*3e230dd2SCorentin Chary     else
1964*3e230dd2SCorentin Chary         size = snprintf(buf, sizeof(buf), "QEMU");
1965*3e230dd2SCorentin Chary 
1966*3e230dd2SCorentin Chary     vnc_write_u32(vs, size);
1967*3e230dd2SCorentin Chary     vnc_write(vs, buf, size);
1968*3e230dd2SCorentin Chary     vnc_flush(vs);
1969*3e230dd2SCorentin Chary 
1970*3e230dd2SCorentin Chary     vnc_client_cache_auth(vs);
1971*3e230dd2SCorentin Chary     vnc_qmp_event(vs, QEVENT_VNC_INITIALIZED);
1972*3e230dd2SCorentin Chary 
1973*3e230dd2SCorentin Chary     vnc_read_when(vs, protocol_client_msg, 1);
1974*3e230dd2SCorentin Chary 
1975*3e230dd2SCorentin Chary     return 0;
1976*3e230dd2SCorentin Chary }
1977*3e230dd2SCorentin Chary 
1978*3e230dd2SCorentin Chary void start_client_init(VncState *vs)
1979*3e230dd2SCorentin Chary {
1980*3e230dd2SCorentin Chary     vnc_read_when(vs, protocol_client_init, 1);
1981*3e230dd2SCorentin Chary }
1982*3e230dd2SCorentin Chary 
1983*3e230dd2SCorentin Chary static void make_challenge(VncState *vs)
1984*3e230dd2SCorentin Chary {
1985*3e230dd2SCorentin Chary     int i;
1986*3e230dd2SCorentin Chary 
1987*3e230dd2SCorentin Chary     srand(time(NULL)+getpid()+getpid()*987654+rand());
1988*3e230dd2SCorentin Chary 
1989*3e230dd2SCorentin Chary     for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1990*3e230dd2SCorentin Chary         vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1991*3e230dd2SCorentin Chary }
1992*3e230dd2SCorentin Chary 
1993*3e230dd2SCorentin Chary static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1994*3e230dd2SCorentin Chary {
1995*3e230dd2SCorentin Chary     unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
1996*3e230dd2SCorentin Chary     int i, j, pwlen;
1997*3e230dd2SCorentin Chary     unsigned char key[8];
1998*3e230dd2SCorentin Chary 
1999*3e230dd2SCorentin Chary     if (!vs->vd->password || !vs->vd->password[0]) {
2000*3e230dd2SCorentin Chary         VNC_DEBUG("No password configured on server");
2001*3e230dd2SCorentin Chary         vnc_write_u32(vs, 1); /* Reject auth */
2002*3e230dd2SCorentin Chary         if (vs->minor >= 8) {
2003*3e230dd2SCorentin Chary             static const char err[] = "Authentication failed";
2004*3e230dd2SCorentin Chary             vnc_write_u32(vs, sizeof(err));
2005*3e230dd2SCorentin Chary             vnc_write(vs, err, sizeof(err));
2006*3e230dd2SCorentin Chary         }
2007*3e230dd2SCorentin Chary         vnc_flush(vs);
2008*3e230dd2SCorentin Chary         vnc_client_error(vs);
2009*3e230dd2SCorentin Chary         return 0;
2010*3e230dd2SCorentin Chary     }
2011*3e230dd2SCorentin Chary 
2012*3e230dd2SCorentin Chary     memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
2013*3e230dd2SCorentin Chary 
2014*3e230dd2SCorentin Chary     /* Calculate the expected challenge response */
2015*3e230dd2SCorentin Chary     pwlen = strlen(vs->vd->password);
2016*3e230dd2SCorentin Chary     for (i=0; i<sizeof(key); i++)
2017*3e230dd2SCorentin Chary         key[i] = i<pwlen ? vs->vd->password[i] : 0;
2018*3e230dd2SCorentin Chary     deskey(key, EN0);
2019*3e230dd2SCorentin Chary     for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
2020*3e230dd2SCorentin Chary         des(response+j, response+j);
2021*3e230dd2SCorentin Chary 
2022*3e230dd2SCorentin Chary     /* Compare expected vs actual challenge response */
2023*3e230dd2SCorentin Chary     if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
2024*3e230dd2SCorentin Chary         VNC_DEBUG("Client challenge reponse did not match\n");
2025*3e230dd2SCorentin Chary         vnc_write_u32(vs, 1); /* Reject auth */
2026*3e230dd2SCorentin Chary         if (vs->minor >= 8) {
2027*3e230dd2SCorentin Chary             static const char err[] = "Authentication failed";
2028*3e230dd2SCorentin Chary             vnc_write_u32(vs, sizeof(err));
2029*3e230dd2SCorentin Chary             vnc_write(vs, err, sizeof(err));
2030*3e230dd2SCorentin Chary         }
2031*3e230dd2SCorentin Chary         vnc_flush(vs);
2032*3e230dd2SCorentin Chary         vnc_client_error(vs);
2033*3e230dd2SCorentin Chary     } else {
2034*3e230dd2SCorentin Chary         VNC_DEBUG("Accepting VNC challenge response\n");
2035*3e230dd2SCorentin Chary         vnc_write_u32(vs, 0); /* Accept auth */
2036*3e230dd2SCorentin Chary         vnc_flush(vs);
2037*3e230dd2SCorentin Chary 
2038*3e230dd2SCorentin Chary         start_client_init(vs);
2039*3e230dd2SCorentin Chary     }
2040*3e230dd2SCorentin Chary     return 0;
2041*3e230dd2SCorentin Chary }
2042*3e230dd2SCorentin Chary 
2043*3e230dd2SCorentin Chary void start_auth_vnc(VncState *vs)
2044*3e230dd2SCorentin Chary {
2045*3e230dd2SCorentin Chary     make_challenge(vs);
2046*3e230dd2SCorentin Chary     /* Send client a 'random' challenge */
2047*3e230dd2SCorentin Chary     vnc_write(vs, vs->challenge, sizeof(vs->challenge));
2048*3e230dd2SCorentin Chary     vnc_flush(vs);
2049*3e230dd2SCorentin Chary 
2050*3e230dd2SCorentin Chary     vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
2051*3e230dd2SCorentin Chary }
2052*3e230dd2SCorentin Chary 
2053*3e230dd2SCorentin Chary 
2054*3e230dd2SCorentin Chary static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2055*3e230dd2SCorentin Chary {
2056*3e230dd2SCorentin Chary     /* We only advertise 1 auth scheme at a time, so client
2057*3e230dd2SCorentin Chary      * must pick the one we sent. Verify this */
2058*3e230dd2SCorentin Chary     if (data[0] != vs->vd->auth) { /* Reject auth */
2059*3e230dd2SCorentin Chary        VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
2060*3e230dd2SCorentin Chary        vnc_write_u32(vs, 1);
2061*3e230dd2SCorentin Chary        if (vs->minor >= 8) {
2062*3e230dd2SCorentin Chary            static const char err[] = "Authentication failed";
2063*3e230dd2SCorentin Chary            vnc_write_u32(vs, sizeof(err));
2064*3e230dd2SCorentin Chary            vnc_write(vs, err, sizeof(err));
2065*3e230dd2SCorentin Chary        }
2066*3e230dd2SCorentin Chary        vnc_client_error(vs);
2067*3e230dd2SCorentin Chary     } else { /* Accept requested auth */
2068*3e230dd2SCorentin Chary        VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2069*3e230dd2SCorentin Chary        switch (vs->vd->auth) {
2070*3e230dd2SCorentin Chary        case VNC_AUTH_NONE:
2071*3e230dd2SCorentin Chary            VNC_DEBUG("Accept auth none\n");
2072*3e230dd2SCorentin Chary            if (vs->minor >= 8) {
2073*3e230dd2SCorentin Chary                vnc_write_u32(vs, 0); /* Accept auth completion */
2074*3e230dd2SCorentin Chary                vnc_flush(vs);
2075*3e230dd2SCorentin Chary            }
2076*3e230dd2SCorentin Chary            start_client_init(vs);
2077*3e230dd2SCorentin Chary            break;
2078*3e230dd2SCorentin Chary 
2079*3e230dd2SCorentin Chary        case VNC_AUTH_VNC:
2080*3e230dd2SCorentin Chary            VNC_DEBUG("Start VNC auth\n");
2081*3e230dd2SCorentin Chary            start_auth_vnc(vs);
2082*3e230dd2SCorentin Chary            break;
2083*3e230dd2SCorentin Chary 
2084*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2085*3e230dd2SCorentin Chary        case VNC_AUTH_VENCRYPT:
2086*3e230dd2SCorentin Chary            VNC_DEBUG("Accept VeNCrypt auth\n");;
2087*3e230dd2SCorentin Chary            start_auth_vencrypt(vs);
2088*3e230dd2SCorentin Chary            break;
2089*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
2090*3e230dd2SCorentin Chary 
2091*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
2092*3e230dd2SCorentin Chary        case VNC_AUTH_SASL:
2093*3e230dd2SCorentin Chary            VNC_DEBUG("Accept SASL auth\n");
2094*3e230dd2SCorentin Chary            start_auth_sasl(vs);
2095*3e230dd2SCorentin Chary            break;
2096*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */
2097*3e230dd2SCorentin Chary 
2098*3e230dd2SCorentin Chary        default: /* Should not be possible, but just in case */
2099*3e230dd2SCorentin Chary            VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth);
2100*3e230dd2SCorentin Chary            vnc_write_u8(vs, 1);
2101*3e230dd2SCorentin Chary            if (vs->minor >= 8) {
2102*3e230dd2SCorentin Chary                static const char err[] = "Authentication failed";
2103*3e230dd2SCorentin Chary                vnc_write_u32(vs, sizeof(err));
2104*3e230dd2SCorentin Chary                vnc_write(vs, err, sizeof(err));
2105*3e230dd2SCorentin Chary            }
2106*3e230dd2SCorentin Chary            vnc_client_error(vs);
2107*3e230dd2SCorentin Chary        }
2108*3e230dd2SCorentin Chary     }
2109*3e230dd2SCorentin Chary     return 0;
2110*3e230dd2SCorentin Chary }
2111*3e230dd2SCorentin Chary 
2112*3e230dd2SCorentin Chary static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2113*3e230dd2SCorentin Chary {
2114*3e230dd2SCorentin Chary     char local[13];
2115*3e230dd2SCorentin Chary 
2116*3e230dd2SCorentin Chary     memcpy(local, version, 12);
2117*3e230dd2SCorentin Chary     local[12] = 0;
2118*3e230dd2SCorentin Chary 
2119*3e230dd2SCorentin Chary     if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2120*3e230dd2SCorentin Chary         VNC_DEBUG("Malformed protocol version %s\n", local);
2121*3e230dd2SCorentin Chary         vnc_client_error(vs);
2122*3e230dd2SCorentin Chary         return 0;
2123*3e230dd2SCorentin Chary     }
2124*3e230dd2SCorentin Chary     VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2125*3e230dd2SCorentin Chary     if (vs->major != 3 ||
2126*3e230dd2SCorentin Chary         (vs->minor != 3 &&
2127*3e230dd2SCorentin Chary          vs->minor != 4 &&
2128*3e230dd2SCorentin Chary          vs->minor != 5 &&
2129*3e230dd2SCorentin Chary          vs->minor != 7 &&
2130*3e230dd2SCorentin Chary          vs->minor != 8)) {
2131*3e230dd2SCorentin Chary         VNC_DEBUG("Unsupported client version\n");
2132*3e230dd2SCorentin Chary         vnc_write_u32(vs, VNC_AUTH_INVALID);
2133*3e230dd2SCorentin Chary         vnc_flush(vs);
2134*3e230dd2SCorentin Chary         vnc_client_error(vs);
2135*3e230dd2SCorentin Chary         return 0;
2136*3e230dd2SCorentin Chary     }
2137*3e230dd2SCorentin Chary     /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2138*3e230dd2SCorentin Chary      * as equivalent to v3.3 by servers
2139*3e230dd2SCorentin Chary      */
2140*3e230dd2SCorentin Chary     if (vs->minor == 4 || vs->minor == 5)
2141*3e230dd2SCorentin Chary         vs->minor = 3;
2142*3e230dd2SCorentin Chary 
2143*3e230dd2SCorentin Chary     if (vs->minor == 3) {
2144*3e230dd2SCorentin Chary         if (vs->vd->auth == VNC_AUTH_NONE) {
2145*3e230dd2SCorentin Chary             VNC_DEBUG("Tell client auth none\n");
2146*3e230dd2SCorentin Chary             vnc_write_u32(vs, vs->vd->auth);
2147*3e230dd2SCorentin Chary             vnc_flush(vs);
2148*3e230dd2SCorentin Chary             start_client_init(vs);
2149*3e230dd2SCorentin Chary        } else if (vs->vd->auth == VNC_AUTH_VNC) {
2150*3e230dd2SCorentin Chary             VNC_DEBUG("Tell client VNC auth\n");
2151*3e230dd2SCorentin Chary             vnc_write_u32(vs, vs->vd->auth);
2152*3e230dd2SCorentin Chary             vnc_flush(vs);
2153*3e230dd2SCorentin Chary             start_auth_vnc(vs);
2154*3e230dd2SCorentin Chary        } else {
2155*3e230dd2SCorentin Chary             VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth);
2156*3e230dd2SCorentin Chary             vnc_write_u32(vs, VNC_AUTH_INVALID);
2157*3e230dd2SCorentin Chary             vnc_flush(vs);
2158*3e230dd2SCorentin Chary             vnc_client_error(vs);
2159*3e230dd2SCorentin Chary        }
2160*3e230dd2SCorentin Chary     } else {
2161*3e230dd2SCorentin Chary         VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth);
2162*3e230dd2SCorentin Chary         vnc_write_u8(vs, 1); /* num auth */
2163*3e230dd2SCorentin Chary         vnc_write_u8(vs, vs->vd->auth);
2164*3e230dd2SCorentin Chary         vnc_read_when(vs, protocol_client_auth, 1);
2165*3e230dd2SCorentin Chary         vnc_flush(vs);
2166*3e230dd2SCorentin Chary     }
2167*3e230dd2SCorentin Chary 
2168*3e230dd2SCorentin Chary     return 0;
2169*3e230dd2SCorentin Chary }
2170*3e230dd2SCorentin Chary 
2171*3e230dd2SCorentin Chary static int vnc_refresh_server_surface(VncDisplay *vd)
2172*3e230dd2SCorentin Chary {
2173*3e230dd2SCorentin Chary     int y;
2174*3e230dd2SCorentin Chary     uint8_t *guest_row;
2175*3e230dd2SCorentin Chary     uint8_t *server_row;
2176*3e230dd2SCorentin Chary     int cmp_bytes;
2177*3e230dd2SCorentin Chary     uint32_t width_mask[VNC_DIRTY_WORDS];
2178*3e230dd2SCorentin Chary     VncState *vs;
2179*3e230dd2SCorentin Chary     int has_dirty = 0;
2180*3e230dd2SCorentin Chary 
2181*3e230dd2SCorentin Chary     /*
2182*3e230dd2SCorentin Chary      * Walk through the guest dirty map.
2183*3e230dd2SCorentin Chary      * Check and copy modified bits from guest to server surface.
2184*3e230dd2SCorentin Chary      * Update server dirty map.
2185*3e230dd2SCorentin Chary      */
2186*3e230dd2SCorentin Chary     vnc_set_bits(width_mask, (ds_get_width(vd->ds) / 16), VNC_DIRTY_WORDS);
2187*3e230dd2SCorentin Chary     cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
2188*3e230dd2SCorentin Chary     guest_row  = vd->guest.ds->data;
2189*3e230dd2SCorentin Chary     server_row = vd->server->data;
2190*3e230dd2SCorentin Chary     for (y = 0; y < vd->guest.ds->height; y++) {
2191*3e230dd2SCorentin Chary         if (vnc_and_bits(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
2192*3e230dd2SCorentin Chary             int x;
2193*3e230dd2SCorentin Chary             uint8_t *guest_ptr;
2194*3e230dd2SCorentin Chary             uint8_t *server_ptr;
2195*3e230dd2SCorentin Chary 
2196*3e230dd2SCorentin Chary             guest_ptr  = guest_row;
2197*3e230dd2SCorentin Chary             server_ptr = server_row;
2198*3e230dd2SCorentin Chary 
2199*3e230dd2SCorentin Chary             for (x = 0; x < vd->guest.ds->width;
2200*3e230dd2SCorentin Chary                     x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
2201*3e230dd2SCorentin Chary                 if (!vnc_get_bit(vd->guest.dirty[y], (x / 16)))
2202*3e230dd2SCorentin Chary                     continue;
2203*3e230dd2SCorentin Chary                 vnc_clear_bit(vd->guest.dirty[y], (x / 16));
2204*3e230dd2SCorentin Chary                 if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
2205*3e230dd2SCorentin Chary                     continue;
2206*3e230dd2SCorentin Chary                 memcpy(server_ptr, guest_ptr, cmp_bytes);
2207*3e230dd2SCorentin Chary                 QTAILQ_FOREACH(vs, &vd->clients, next) {
2208*3e230dd2SCorentin Chary                     vnc_set_bit(vs->dirty[y], (x / 16));
2209*3e230dd2SCorentin Chary                 }
2210*3e230dd2SCorentin Chary                 has_dirty++;
2211*3e230dd2SCorentin Chary             }
2212*3e230dd2SCorentin Chary         }
2213*3e230dd2SCorentin Chary         guest_row  += ds_get_linesize(vd->ds);
2214*3e230dd2SCorentin Chary         server_row += ds_get_linesize(vd->ds);
2215*3e230dd2SCorentin Chary     }
2216*3e230dd2SCorentin Chary     return has_dirty;
2217*3e230dd2SCorentin Chary }
2218*3e230dd2SCorentin Chary 
2219*3e230dd2SCorentin Chary static void vnc_refresh(void *opaque)
2220*3e230dd2SCorentin Chary {
2221*3e230dd2SCorentin Chary     VncDisplay *vd = opaque;
2222*3e230dd2SCorentin Chary     VncState *vs, *vn;
2223*3e230dd2SCorentin Chary     int has_dirty, rects = 0;
2224*3e230dd2SCorentin Chary 
2225*3e230dd2SCorentin Chary     vga_hw_update();
2226*3e230dd2SCorentin Chary 
2227*3e230dd2SCorentin Chary     has_dirty = vnc_refresh_server_surface(vd);
2228*3e230dd2SCorentin Chary 
2229*3e230dd2SCorentin Chary     QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
2230*3e230dd2SCorentin Chary         rects += vnc_update_client(vs, has_dirty);
2231*3e230dd2SCorentin Chary         /* vs might be free()ed here */
2232*3e230dd2SCorentin Chary     }
2233*3e230dd2SCorentin Chary     /* vd->timer could be NULL now if the last client disconnected,
2234*3e230dd2SCorentin Chary      * in this case don't update the timer */
2235*3e230dd2SCorentin Chary     if (vd->timer == NULL)
2236*3e230dd2SCorentin Chary         return;
2237*3e230dd2SCorentin Chary 
2238*3e230dd2SCorentin Chary     if (has_dirty && rects) {
2239*3e230dd2SCorentin Chary         vd->timer_interval /= 2;
2240*3e230dd2SCorentin Chary         if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE)
2241*3e230dd2SCorentin Chary             vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
2242*3e230dd2SCorentin Chary     } else {
2243*3e230dd2SCorentin Chary         vd->timer_interval += VNC_REFRESH_INTERVAL_INC;
2244*3e230dd2SCorentin Chary         if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX)
2245*3e230dd2SCorentin Chary             vd->timer_interval = VNC_REFRESH_INTERVAL_MAX;
2246*3e230dd2SCorentin Chary     }
2247*3e230dd2SCorentin Chary     qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
2248*3e230dd2SCorentin Chary }
2249*3e230dd2SCorentin Chary 
2250*3e230dd2SCorentin Chary static void vnc_init_timer(VncDisplay *vd)
2251*3e230dd2SCorentin Chary {
2252*3e230dd2SCorentin Chary     vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
2253*3e230dd2SCorentin Chary     if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
2254*3e230dd2SCorentin Chary         vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
2255*3e230dd2SCorentin Chary         vnc_refresh(vd);
2256*3e230dd2SCorentin Chary     }
2257*3e230dd2SCorentin Chary }
2258*3e230dd2SCorentin Chary 
2259*3e230dd2SCorentin Chary static void vnc_remove_timer(VncDisplay *vd)
2260*3e230dd2SCorentin Chary {
2261*3e230dd2SCorentin Chary     if (vd->timer != NULL && QTAILQ_EMPTY(&vd->clients)) {
2262*3e230dd2SCorentin Chary         qemu_del_timer(vd->timer);
2263*3e230dd2SCorentin Chary         qemu_free_timer(vd->timer);
2264*3e230dd2SCorentin Chary         vd->timer = NULL;
2265*3e230dd2SCorentin Chary     }
2266*3e230dd2SCorentin Chary }
2267*3e230dd2SCorentin Chary 
2268*3e230dd2SCorentin Chary static void vnc_connect(VncDisplay *vd, int csock)
2269*3e230dd2SCorentin Chary {
2270*3e230dd2SCorentin Chary     VncState *vs = qemu_mallocz(sizeof(VncState));
2271*3e230dd2SCorentin Chary     vs->csock = csock;
2272*3e230dd2SCorentin Chary 
2273*3e230dd2SCorentin Chary     VNC_DEBUG("New client on socket %d\n", csock);
2274*3e230dd2SCorentin Chary     dcl->idle = 0;
2275*3e230dd2SCorentin Chary     socket_set_nonblock(vs->csock);
2276*3e230dd2SCorentin Chary     qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2277*3e230dd2SCorentin Chary 
2278*3e230dd2SCorentin Chary     vnc_client_cache_addr(vs);
2279*3e230dd2SCorentin Chary     vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
2280*3e230dd2SCorentin Chary 
2281*3e230dd2SCorentin Chary     vs->vd = vd;
2282*3e230dd2SCorentin Chary     vs->ds = vd->ds;
2283*3e230dd2SCorentin Chary     vs->last_x = -1;
2284*3e230dd2SCorentin Chary     vs->last_y = -1;
2285*3e230dd2SCorentin Chary 
2286*3e230dd2SCorentin Chary     vs->as.freq = 44100;
2287*3e230dd2SCorentin Chary     vs->as.nchannels = 2;
2288*3e230dd2SCorentin Chary     vs->as.fmt = AUD_FMT_S16;
2289*3e230dd2SCorentin Chary     vs->as.endianness = 0;
2290*3e230dd2SCorentin Chary 
2291*3e230dd2SCorentin Chary     QTAILQ_INSERT_HEAD(&vd->clients, vs, next);
2292*3e230dd2SCorentin Chary 
2293*3e230dd2SCorentin Chary     vga_hw_update();
2294*3e230dd2SCorentin Chary 
2295*3e230dd2SCorentin Chary     vnc_write(vs, "RFB 003.008\n", 12);
2296*3e230dd2SCorentin Chary     vnc_flush(vs);
2297*3e230dd2SCorentin Chary     vnc_read_when(vs, protocol_version, 12);
2298*3e230dd2SCorentin Chary     reset_keys(vs);
2299*3e230dd2SCorentin Chary     if (vs->vd->lock_key_sync)
2300*3e230dd2SCorentin Chary         vs->led = qemu_add_led_event_handler(kbd_leds, vs);
2301*3e230dd2SCorentin Chary 
2302*3e230dd2SCorentin Chary     vs->mouse_mode_notifier.notify = check_pointer_type_change;
2303*3e230dd2SCorentin Chary     qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
2304*3e230dd2SCorentin Chary 
2305*3e230dd2SCorentin Chary     vnc_init_timer(vd);
2306*3e230dd2SCorentin Chary 
2307*3e230dd2SCorentin Chary     /* vs might be free()ed here */
2308*3e230dd2SCorentin Chary }
2309*3e230dd2SCorentin Chary 
2310*3e230dd2SCorentin Chary static void vnc_listen_read(void *opaque)
2311*3e230dd2SCorentin Chary {
2312*3e230dd2SCorentin Chary     VncDisplay *vs = opaque;
2313*3e230dd2SCorentin Chary     struct sockaddr_in addr;
2314*3e230dd2SCorentin Chary     socklen_t addrlen = sizeof(addr);
2315*3e230dd2SCorentin Chary 
2316*3e230dd2SCorentin Chary     /* Catch-up */
2317*3e230dd2SCorentin Chary     vga_hw_update();
2318*3e230dd2SCorentin Chary 
2319*3e230dd2SCorentin Chary     int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2320*3e230dd2SCorentin Chary     if (csock != -1) {
2321*3e230dd2SCorentin Chary         vnc_connect(vs, csock);
2322*3e230dd2SCorentin Chary     }
2323*3e230dd2SCorentin Chary }
2324*3e230dd2SCorentin Chary 
2325*3e230dd2SCorentin Chary void vnc_display_init(DisplayState *ds)
2326*3e230dd2SCorentin Chary {
2327*3e230dd2SCorentin Chary     VncDisplay *vs = qemu_mallocz(sizeof(*vs));
2328*3e230dd2SCorentin Chary 
2329*3e230dd2SCorentin Chary     dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2330*3e230dd2SCorentin Chary 
2331*3e230dd2SCorentin Chary     ds->opaque = vs;
2332*3e230dd2SCorentin Chary     dcl->idle = 1;
2333*3e230dd2SCorentin Chary     vnc_display = vs;
2334*3e230dd2SCorentin Chary 
2335*3e230dd2SCorentin Chary     vs->lsock = -1;
2336*3e230dd2SCorentin Chary 
2337*3e230dd2SCorentin Chary     vs->ds = ds;
2338*3e230dd2SCorentin Chary     QTAILQ_INIT(&vs->clients);
2339*3e230dd2SCorentin Chary 
2340*3e230dd2SCorentin Chary     if (keyboard_layout)
2341*3e230dd2SCorentin Chary         vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
2342*3e230dd2SCorentin Chary     else
2343*3e230dd2SCorentin Chary         vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
2344*3e230dd2SCorentin Chary 
2345*3e230dd2SCorentin Chary     if (!vs->kbd_layout)
2346*3e230dd2SCorentin Chary         exit(1);
2347*3e230dd2SCorentin Chary 
2348*3e230dd2SCorentin Chary     dcl->dpy_copy = vnc_dpy_copy;
2349*3e230dd2SCorentin Chary     dcl->dpy_update = vnc_dpy_update;
2350*3e230dd2SCorentin Chary     dcl->dpy_resize = vnc_dpy_resize;
2351*3e230dd2SCorentin Chary     dcl->dpy_setdata = vnc_dpy_setdata;
2352*3e230dd2SCorentin Chary     register_displaychangelistener(ds, dcl);
2353*3e230dd2SCorentin Chary     ds->mouse_set = vnc_mouse_set;
2354*3e230dd2SCorentin Chary     ds->cursor_define = vnc_dpy_cursor_define;
2355*3e230dd2SCorentin Chary }
2356*3e230dd2SCorentin Chary 
2357*3e230dd2SCorentin Chary 
2358*3e230dd2SCorentin Chary void vnc_display_close(DisplayState *ds)
2359*3e230dd2SCorentin Chary {
2360*3e230dd2SCorentin Chary     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2361*3e230dd2SCorentin Chary 
2362*3e230dd2SCorentin Chary     if (!vs)
2363*3e230dd2SCorentin Chary         return;
2364*3e230dd2SCorentin Chary     if (vs->display) {
2365*3e230dd2SCorentin Chary         qemu_free(vs->display);
2366*3e230dd2SCorentin Chary         vs->display = NULL;
2367*3e230dd2SCorentin Chary     }
2368*3e230dd2SCorentin Chary     if (vs->lsock != -1) {
2369*3e230dd2SCorentin Chary         qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2370*3e230dd2SCorentin Chary         close(vs->lsock);
2371*3e230dd2SCorentin Chary         vs->lsock = -1;
2372*3e230dd2SCorentin Chary     }
2373*3e230dd2SCorentin Chary     vs->auth = VNC_AUTH_INVALID;
2374*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2375*3e230dd2SCorentin Chary     vs->subauth = VNC_AUTH_INVALID;
2376*3e230dd2SCorentin Chary     vs->tls.x509verify = 0;
2377*3e230dd2SCorentin Chary #endif
2378*3e230dd2SCorentin Chary }
2379*3e230dd2SCorentin Chary 
2380*3e230dd2SCorentin Chary int vnc_display_password(DisplayState *ds, const char *password)
2381*3e230dd2SCorentin Chary {
2382*3e230dd2SCorentin Chary     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2383*3e230dd2SCorentin Chary 
2384*3e230dd2SCorentin Chary     if (!vs) {
2385*3e230dd2SCorentin Chary         return -1;
2386*3e230dd2SCorentin Chary     }
2387*3e230dd2SCorentin Chary 
2388*3e230dd2SCorentin Chary     if (vs->password) {
2389*3e230dd2SCorentin Chary         qemu_free(vs->password);
2390*3e230dd2SCorentin Chary         vs->password = NULL;
2391*3e230dd2SCorentin Chary     }
2392*3e230dd2SCorentin Chary     if (password && password[0]) {
2393*3e230dd2SCorentin Chary         if (!(vs->password = qemu_strdup(password)))
2394*3e230dd2SCorentin Chary             return -1;
2395*3e230dd2SCorentin Chary         if (vs->auth == VNC_AUTH_NONE) {
2396*3e230dd2SCorentin Chary             vs->auth = VNC_AUTH_VNC;
2397*3e230dd2SCorentin Chary         }
2398*3e230dd2SCorentin Chary     } else {
2399*3e230dd2SCorentin Chary         vs->auth = VNC_AUTH_NONE;
2400*3e230dd2SCorentin Chary     }
2401*3e230dd2SCorentin Chary 
2402*3e230dd2SCorentin Chary     return 0;
2403*3e230dd2SCorentin Chary }
2404*3e230dd2SCorentin Chary 
2405*3e230dd2SCorentin Chary char *vnc_display_local_addr(DisplayState *ds)
2406*3e230dd2SCorentin Chary {
2407*3e230dd2SCorentin Chary     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2408*3e230dd2SCorentin Chary 
2409*3e230dd2SCorentin Chary     return vnc_socket_local_addr("%s:%s", vs->lsock);
2410*3e230dd2SCorentin Chary }
2411*3e230dd2SCorentin Chary 
2412*3e230dd2SCorentin Chary int vnc_display_open(DisplayState *ds, const char *display)
2413*3e230dd2SCorentin Chary {
2414*3e230dd2SCorentin Chary     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2415*3e230dd2SCorentin Chary     const char *options;
2416*3e230dd2SCorentin Chary     int password = 0;
2417*3e230dd2SCorentin Chary     int reverse = 0;
2418*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2419*3e230dd2SCorentin Chary     int tls = 0, x509 = 0;
2420*3e230dd2SCorentin Chary #endif
2421*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
2422*3e230dd2SCorentin Chary     int sasl = 0;
2423*3e230dd2SCorentin Chary     int saslErr;
2424*3e230dd2SCorentin Chary #endif
2425*3e230dd2SCorentin Chary     int acl = 0;
2426*3e230dd2SCorentin Chary     int lock_key_sync = 1;
2427*3e230dd2SCorentin Chary 
2428*3e230dd2SCorentin Chary     if (!vnc_display)
2429*3e230dd2SCorentin Chary         return -1;
2430*3e230dd2SCorentin Chary     vnc_display_close(ds);
2431*3e230dd2SCorentin Chary     if (strcmp(display, "none") == 0)
2432*3e230dd2SCorentin Chary         return 0;
2433*3e230dd2SCorentin Chary 
2434*3e230dd2SCorentin Chary     if (!(vs->display = strdup(display)))
2435*3e230dd2SCorentin Chary         return -1;
2436*3e230dd2SCorentin Chary 
2437*3e230dd2SCorentin Chary     options = display;
2438*3e230dd2SCorentin Chary     while ((options = strchr(options, ','))) {
2439*3e230dd2SCorentin Chary         options++;
2440*3e230dd2SCorentin Chary         if (strncmp(options, "password", 8) == 0) {
2441*3e230dd2SCorentin Chary             password = 1; /* Require password auth */
2442*3e230dd2SCorentin Chary         } else if (strncmp(options, "reverse", 7) == 0) {
2443*3e230dd2SCorentin Chary             reverse = 1;
2444*3e230dd2SCorentin Chary         } else if (strncmp(options, "no-lock-key-sync", 9) == 0) {
2445*3e230dd2SCorentin Chary             lock_key_sync = 0;
2446*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
2447*3e230dd2SCorentin Chary         } else if (strncmp(options, "sasl", 4) == 0) {
2448*3e230dd2SCorentin Chary             sasl = 1; /* Require SASL auth */
2449*3e230dd2SCorentin Chary #endif
2450*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2451*3e230dd2SCorentin Chary         } else if (strncmp(options, "tls", 3) == 0) {
2452*3e230dd2SCorentin Chary             tls = 1; /* Require TLS */
2453*3e230dd2SCorentin Chary         } else if (strncmp(options, "x509", 4) == 0) {
2454*3e230dd2SCorentin Chary             char *start, *end;
2455*3e230dd2SCorentin Chary             x509 = 1; /* Require x509 certificates */
2456*3e230dd2SCorentin Chary             if (strncmp(options, "x509verify", 10) == 0)
2457*3e230dd2SCorentin Chary                 vs->tls.x509verify = 1; /* ...and verify client certs */
2458*3e230dd2SCorentin Chary 
2459*3e230dd2SCorentin Chary             /* Now check for 'x509=/some/path' postfix
2460*3e230dd2SCorentin Chary              * and use that to setup x509 certificate/key paths */
2461*3e230dd2SCorentin Chary             start = strchr(options, '=');
2462*3e230dd2SCorentin Chary             end = strchr(options, ',');
2463*3e230dd2SCorentin Chary             if (start && (!end || (start < end))) {
2464*3e230dd2SCorentin Chary                 int len = end ? end-(start+1) : strlen(start+1);
2465*3e230dd2SCorentin Chary                 char *path = qemu_strndup(start + 1, len);
2466*3e230dd2SCorentin Chary 
2467*3e230dd2SCorentin Chary                 VNC_DEBUG("Trying certificate path '%s'\n", path);
2468*3e230dd2SCorentin Chary                 if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
2469*3e230dd2SCorentin Chary                     fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2470*3e230dd2SCorentin Chary                     qemu_free(path);
2471*3e230dd2SCorentin Chary                     qemu_free(vs->display);
2472*3e230dd2SCorentin Chary                     vs->display = NULL;
2473*3e230dd2SCorentin Chary                     return -1;
2474*3e230dd2SCorentin Chary                 }
2475*3e230dd2SCorentin Chary                 qemu_free(path);
2476*3e230dd2SCorentin Chary             } else {
2477*3e230dd2SCorentin Chary                 fprintf(stderr, "No certificate path provided\n");
2478*3e230dd2SCorentin Chary                 qemu_free(vs->display);
2479*3e230dd2SCorentin Chary                 vs->display = NULL;
2480*3e230dd2SCorentin Chary                 return -1;
2481*3e230dd2SCorentin Chary             }
2482*3e230dd2SCorentin Chary #endif
2483*3e230dd2SCorentin Chary         } else if (strncmp(options, "acl", 3) == 0) {
2484*3e230dd2SCorentin Chary             acl = 1;
2485*3e230dd2SCorentin Chary         } else if (strncmp(options, "lossy", 5) == 0) {
2486*3e230dd2SCorentin Chary             vs->lossy = true;
2487*3e230dd2SCorentin Chary         }
2488*3e230dd2SCorentin Chary     }
2489*3e230dd2SCorentin Chary 
2490*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2491*3e230dd2SCorentin Chary     if (acl && x509 && vs->tls.x509verify) {
2492*3e230dd2SCorentin Chary         if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {
2493*3e230dd2SCorentin Chary             fprintf(stderr, "Failed to create x509 dname ACL\n");
2494*3e230dd2SCorentin Chary             exit(1);
2495*3e230dd2SCorentin Chary         }
2496*3e230dd2SCorentin Chary     }
2497*3e230dd2SCorentin Chary #endif
2498*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
2499*3e230dd2SCorentin Chary     if (acl && sasl) {
2500*3e230dd2SCorentin Chary         if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) {
2501*3e230dd2SCorentin Chary             fprintf(stderr, "Failed to create username ACL\n");
2502*3e230dd2SCorentin Chary             exit(1);
2503*3e230dd2SCorentin Chary         }
2504*3e230dd2SCorentin Chary     }
2505*3e230dd2SCorentin Chary #endif
2506*3e230dd2SCorentin Chary 
2507*3e230dd2SCorentin Chary     /*
2508*3e230dd2SCorentin Chary      * Combinations we support here:
2509*3e230dd2SCorentin Chary      *
2510*3e230dd2SCorentin Chary      *  - no-auth                (clear text, no auth)
2511*3e230dd2SCorentin Chary      *  - password               (clear text, weak auth)
2512*3e230dd2SCorentin Chary      *  - sasl                   (encrypt, good auth *IF* using Kerberos via GSSAPI)
2513*3e230dd2SCorentin Chary      *  - tls                    (encrypt, weak anonymous creds, no auth)
2514*3e230dd2SCorentin Chary      *  - tls + password         (encrypt, weak anonymous creds, weak auth)
2515*3e230dd2SCorentin Chary      *  - tls + sasl             (encrypt, weak anonymous creds, good auth)
2516*3e230dd2SCorentin Chary      *  - tls + x509             (encrypt, good x509 creds, no auth)
2517*3e230dd2SCorentin Chary      *  - tls + x509 + password  (encrypt, good x509 creds, weak auth)
2518*3e230dd2SCorentin Chary      *  - tls + x509 + sasl      (encrypt, good x509 creds, good auth)
2519*3e230dd2SCorentin Chary      *
2520*3e230dd2SCorentin Chary      * NB1. TLS is a stackable auth scheme.
2521*3e230dd2SCorentin Chary      * NB2. the x509 schemes have option to validate a client cert dname
2522*3e230dd2SCorentin Chary      */
2523*3e230dd2SCorentin Chary     if (password) {
2524*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2525*3e230dd2SCorentin Chary         if (tls) {
2526*3e230dd2SCorentin Chary             vs->auth = VNC_AUTH_VENCRYPT;
2527*3e230dd2SCorentin Chary             if (x509) {
2528*3e230dd2SCorentin Chary                 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2529*3e230dd2SCorentin Chary                 vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2530*3e230dd2SCorentin Chary             } else {
2531*3e230dd2SCorentin Chary                 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2532*3e230dd2SCorentin Chary                 vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2533*3e230dd2SCorentin Chary             }
2534*3e230dd2SCorentin Chary         } else {
2535*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
2536*3e230dd2SCorentin Chary             VNC_DEBUG("Initializing VNC server with password auth\n");
2537*3e230dd2SCorentin Chary             vs->auth = VNC_AUTH_VNC;
2538*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2539*3e230dd2SCorentin Chary             vs->subauth = VNC_AUTH_INVALID;
2540*3e230dd2SCorentin Chary         }
2541*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
2542*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
2543*3e230dd2SCorentin Chary     } else if (sasl) {
2544*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2545*3e230dd2SCorentin Chary         if (tls) {
2546*3e230dd2SCorentin Chary             vs->auth = VNC_AUTH_VENCRYPT;
2547*3e230dd2SCorentin Chary             if (x509) {
2548*3e230dd2SCorentin Chary                 VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
2549*3e230dd2SCorentin Chary                 vs->subauth = VNC_AUTH_VENCRYPT_X509SASL;
2550*3e230dd2SCorentin Chary             } else {
2551*3e230dd2SCorentin Chary                 VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
2552*3e230dd2SCorentin Chary                 vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL;
2553*3e230dd2SCorentin Chary             }
2554*3e230dd2SCorentin Chary         } else {
2555*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
2556*3e230dd2SCorentin Chary             VNC_DEBUG("Initializing VNC server with SASL auth\n");
2557*3e230dd2SCorentin Chary             vs->auth = VNC_AUTH_SASL;
2558*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2559*3e230dd2SCorentin Chary             vs->subauth = VNC_AUTH_INVALID;
2560*3e230dd2SCorentin Chary         }
2561*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_TLS */
2562*3e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */
2563*3e230dd2SCorentin Chary     } else {
2564*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2565*3e230dd2SCorentin Chary         if (tls) {
2566*3e230dd2SCorentin Chary             vs->auth = VNC_AUTH_VENCRYPT;
2567*3e230dd2SCorentin Chary             if (x509) {
2568*3e230dd2SCorentin Chary                 VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2569*3e230dd2SCorentin Chary                 vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2570*3e230dd2SCorentin Chary             } else {
2571*3e230dd2SCorentin Chary                 VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2572*3e230dd2SCorentin Chary                 vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2573*3e230dd2SCorentin Chary             }
2574*3e230dd2SCorentin Chary         } else {
2575*3e230dd2SCorentin Chary #endif
2576*3e230dd2SCorentin Chary             VNC_DEBUG("Initializing VNC server with no auth\n");
2577*3e230dd2SCorentin Chary             vs->auth = VNC_AUTH_NONE;
2578*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_TLS
2579*3e230dd2SCorentin Chary             vs->subauth = VNC_AUTH_INVALID;
2580*3e230dd2SCorentin Chary         }
2581*3e230dd2SCorentin Chary #endif
2582*3e230dd2SCorentin Chary     }
2583*3e230dd2SCorentin Chary 
2584*3e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL
2585*3e230dd2SCorentin Chary     if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
2586*3e230dd2SCorentin Chary         fprintf(stderr, "Failed to initialize SASL auth %s",
2587*3e230dd2SCorentin Chary                 sasl_errstring(saslErr, NULL, NULL));
2588*3e230dd2SCorentin Chary         free(vs->display);
2589*3e230dd2SCorentin Chary         vs->display = NULL;
2590*3e230dd2SCorentin Chary         return -1;
2591*3e230dd2SCorentin Chary     }
2592*3e230dd2SCorentin Chary #endif
2593*3e230dd2SCorentin Chary     vs->lock_key_sync = lock_key_sync;
2594*3e230dd2SCorentin Chary 
2595*3e230dd2SCorentin Chary     if (reverse) {
2596*3e230dd2SCorentin Chary         /* connect to viewer */
2597*3e230dd2SCorentin Chary         if (strncmp(display, "unix:", 5) == 0)
2598*3e230dd2SCorentin Chary             vs->lsock = unix_connect(display+5);
2599*3e230dd2SCorentin Chary         else
2600*3e230dd2SCorentin Chary             vs->lsock = inet_connect(display, SOCK_STREAM);
2601*3e230dd2SCorentin Chary         if (-1 == vs->lsock) {
2602*3e230dd2SCorentin Chary             free(vs->display);
2603*3e230dd2SCorentin Chary             vs->display = NULL;
2604*3e230dd2SCorentin Chary             return -1;
2605*3e230dd2SCorentin Chary         } else {
2606*3e230dd2SCorentin Chary             int csock = vs->lsock;
2607*3e230dd2SCorentin Chary             vs->lsock = -1;
2608*3e230dd2SCorentin Chary             vnc_connect(vs, csock);
2609*3e230dd2SCorentin Chary         }
2610*3e230dd2SCorentin Chary         return 0;
2611*3e230dd2SCorentin Chary 
2612*3e230dd2SCorentin Chary     } else {
2613*3e230dd2SCorentin Chary         /* listen for connects */
2614*3e230dd2SCorentin Chary         char *dpy;
2615*3e230dd2SCorentin Chary         dpy = qemu_malloc(256);
2616*3e230dd2SCorentin Chary         if (strncmp(display, "unix:", 5) == 0) {
2617*3e230dd2SCorentin Chary             pstrcpy(dpy, 256, "unix:");
2618*3e230dd2SCorentin Chary             vs->lsock = unix_listen(display+5, dpy+5, 256-5);
2619*3e230dd2SCorentin Chary         } else {
2620*3e230dd2SCorentin Chary             vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
2621*3e230dd2SCorentin Chary         }
2622*3e230dd2SCorentin Chary         if (-1 == vs->lsock) {
2623*3e230dd2SCorentin Chary             free(dpy);
2624*3e230dd2SCorentin Chary             return -1;
2625*3e230dd2SCorentin Chary         } else {
2626*3e230dd2SCorentin Chary             free(vs->display);
2627*3e230dd2SCorentin Chary             vs->display = dpy;
2628*3e230dd2SCorentin Chary         }
2629*3e230dd2SCorentin Chary     }
2630*3e230dd2SCorentin Chary     return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
2631*3e230dd2SCorentin Chary }
2632