Statistics
| Branch: | Revision:

root / vnc.c @ 4f78c9ad

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