Statistics
| Branch: | Revision:

root / ui / vnc.c @ 7bd427d8

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