Statistics
| Branch: | Revision:

root / vnc.c @ ff952ba2

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