Statistics
| Branch: | Revision:

root / vnc.c @ a885211e

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