Statistics
| Branch: | Revision:

root / ui / vnc.c @ 2c80e423

History | View | Annotate | Download (78.7 kB)

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