Statistics
| Branch: | Revision:

root / ui / vnc.c @ ce702e93

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