Statistics
| Branch: | Revision:

root / vnc.c @ 161c4f20

History | View | Annotate | Download (76.3 kB)

1 7d510b8c bellard
/*
2 7d510b8c bellard
 * QEMU VNC display driver
3 5fafdf24 ths
 *
4 7d510b8c bellard
 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 7d510b8c bellard
 * Copyright (C) 2006 Fabrice Bellard
6 19a490bf aliguori
 * Copyright (C) 2009 Red Hat, Inc
7 5fafdf24 ths
 *
8 7d510b8c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 7d510b8c bellard
 * of this software and associated documentation files (the "Software"), to deal
10 7d510b8c bellard
 * in the Software without restriction, including without limitation the rights
11 7d510b8c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 7d510b8c bellard
 * copies of the Software, and to permit persons to whom the Software is
13 7d510b8c bellard
 * furnished to do so, subject to the following conditions:
14 7d510b8c bellard
 *
15 7d510b8c bellard
 * The above copyright notice and this permission notice shall be included in
16 7d510b8c bellard
 * all copies or substantial portions of the Software.
17 7d510b8c bellard
 *
18 7d510b8c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 7d510b8c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 7d510b8c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 7d510b8c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 7d510b8c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 7d510b8c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 7d510b8c bellard
 * THE SOFTWARE.
25 7d510b8c bellard
 */
26 7d510b8c bellard
27 19a490bf aliguori
#include "vnc.h"
28 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 70a4568f Corentin Chary
void 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 24236869 bellard
}
667 24236869 bellard
668 24236869 bellard
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
669 24236869 bellard
{
670 fb437313 aliguori
    switch(vs->vnc_encoding) {
671 28a76be8 aliguori
        case VNC_ENCODING_ZLIB:
672 780a049e Corentin Chary
            vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
673 28a76be8 aliguori
            break;
674 28a76be8 aliguori
        case VNC_ENCODING_HEXTILE:
675 28a76be8 aliguori
            vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
676 70a4568f Corentin Chary
            vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
677 28a76be8 aliguori
            break;
678 28a76be8 aliguori
        default:
679 28a76be8 aliguori
            vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
680 70a4568f Corentin Chary
            vnc_raw_send_framebuffer_update(vs, x, y, w, h);
681 28a76be8 aliguori
            break;
682 fb437313 aliguori
    }
683 24236869 bellard
}
684 24236869 bellard
685 753b4053 aliguori
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
686 24236869 bellard
{
687 3e28c9ad Gerd Hoffmann
    /* send bitblit op to the vnc client */
688 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
689 24236869 bellard
    vnc_write_u8(vs, 0);
690 24236869 bellard
    vnc_write_u16(vs, 1); /* number of rects */
691 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
692 24236869 bellard
    vnc_write_u16(vs, src_x);
693 24236869 bellard
    vnc_write_u16(vs, src_y);
694 24236869 bellard
    vnc_flush(vs);
695 24236869 bellard
}
696 24236869 bellard
697 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)
698 753b4053 aliguori
{
699 753b4053 aliguori
    VncDisplay *vd = ds->opaque;
700 198a0039 Gerd Hoffmann
    VncState *vs, *vn;
701 1fc62412 Stefano Stabellini
    uint8_t *src_row;
702 1fc62412 Stefano Stabellini
    uint8_t *dst_row;
703 1fc62412 Stefano Stabellini
    int i,x,y,pitch,depth,inc,w_lim,s;
704 1fc62412 Stefano Stabellini
    int cmp_bytes;
705 198a0039 Gerd Hoffmann
706 1fc62412 Stefano Stabellini
    vnc_refresh_server_surface(vd);
707 41b4bef6 Amit Shah
    QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
708 198a0039 Gerd Hoffmann
        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
709 198a0039 Gerd Hoffmann
            vs->force_update = 1;
710 1fc62412 Stefano Stabellini
            vnc_update_client(vs, 1);
711 198a0039 Gerd Hoffmann
            /* vs might be free()ed here */
712 198a0039 Gerd Hoffmann
        }
713 198a0039 Gerd Hoffmann
    }
714 198a0039 Gerd Hoffmann
715 1fc62412 Stefano Stabellini
    /* do bitblit op on the local surface too */
716 1fc62412 Stefano Stabellini
    pitch = ds_get_linesize(vd->ds);
717 1fc62412 Stefano Stabellini
    depth = ds_get_bytes_per_pixel(vd->ds);
718 1fc62412 Stefano Stabellini
    src_row = vd->server->data + pitch * src_y + depth * src_x;
719 1fc62412 Stefano Stabellini
    dst_row = vd->server->data + pitch * dst_y + depth * dst_x;
720 1fc62412 Stefano Stabellini
    y = dst_y;
721 1fc62412 Stefano Stabellini
    inc = 1;
722 1fc62412 Stefano Stabellini
    if (dst_y > src_y) {
723 1fc62412 Stefano Stabellini
        /* copy backwards */
724 1fc62412 Stefano Stabellini
        src_row += pitch * (h-1);
725 1fc62412 Stefano Stabellini
        dst_row += pitch * (h-1);
726 1fc62412 Stefano Stabellini
        pitch = -pitch;
727 1fc62412 Stefano Stabellini
        y = dst_y + h - 1;
728 1fc62412 Stefano Stabellini
        inc = -1;
729 1fc62412 Stefano Stabellini
    }
730 1fc62412 Stefano Stabellini
    w_lim = w - (16 - (dst_x % 16));
731 1fc62412 Stefano Stabellini
    if (w_lim < 0)
732 1fc62412 Stefano Stabellini
        w_lim = w;
733 1fc62412 Stefano Stabellini
    else
734 1fc62412 Stefano Stabellini
        w_lim = w - (w_lim % 16);
735 1fc62412 Stefano Stabellini
    for (i = 0; i < h; i++) {
736 1fc62412 Stefano Stabellini
        for (x = 0; x <= w_lim;
737 1fc62412 Stefano Stabellini
                x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
738 1fc62412 Stefano Stabellini
            if (x == w_lim) {
739 1fc62412 Stefano Stabellini
                if ((s = w - w_lim) == 0)
740 1fc62412 Stefano Stabellini
                    break;
741 1fc62412 Stefano Stabellini
            } else if (!x) {
742 1fc62412 Stefano Stabellini
                s = (16 - (dst_x % 16));
743 1fc62412 Stefano Stabellini
                s = MIN(s, w_lim);
744 1fc62412 Stefano Stabellini
            } else {
745 1fc62412 Stefano Stabellini
                s = 16;
746 1fc62412 Stefano Stabellini
            }
747 1fc62412 Stefano Stabellini
            cmp_bytes = s * depth;
748 1fc62412 Stefano Stabellini
            if (memcmp(src_row, dst_row, cmp_bytes) == 0)
749 1fc62412 Stefano Stabellini
                continue;
750 1fc62412 Stefano Stabellini
            memmove(dst_row, src_row, cmp_bytes);
751 41b4bef6 Amit Shah
            QTAILQ_FOREACH(vs, &vd->clients, next) {
752 41b4bef6 Amit Shah
                if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
753 1fc62412 Stefano Stabellini
                    vnc_set_bit(vs->dirty[y], ((x + dst_x) / 16));
754 41b4bef6 Amit Shah
                }
755 1fc62412 Stefano Stabellini
            }
756 1fc62412 Stefano Stabellini
        }
757 1fc62412 Stefano Stabellini
        src_row += pitch - w * depth;
758 1fc62412 Stefano Stabellini
        dst_row += pitch - w * depth;
759 1fc62412 Stefano Stabellini
        y += inc;
760 1fc62412 Stefano Stabellini
    }
761 1fc62412 Stefano Stabellini
762 41b4bef6 Amit Shah
    QTAILQ_FOREACH(vs, &vd->clients, next) {
763 41b4bef6 Amit Shah
        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
764 753b4053 aliguori
            vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
765 41b4bef6 Amit Shah
        }
766 753b4053 aliguori
    }
767 753b4053 aliguori
}
768 753b4053 aliguori
769 d467b679 Gerd Hoffmann
static void vnc_mouse_set(int x, int y, int visible)
770 d467b679 Gerd Hoffmann
{
771 d467b679 Gerd Hoffmann
    /* can we ask the client(s) to move the pointer ??? */
772 d467b679 Gerd Hoffmann
}
773 d467b679 Gerd Hoffmann
774 d467b679 Gerd Hoffmann
static int vnc_cursor_define(VncState *vs)
775 d467b679 Gerd Hoffmann
{
776 d467b679 Gerd Hoffmann
    QEMUCursor *c = vs->vd->cursor;
777 d467b679 Gerd Hoffmann
    PixelFormat pf = qemu_default_pixelformat(32);
778 d467b679 Gerd Hoffmann
    int isize;
779 d467b679 Gerd Hoffmann
780 d467b679 Gerd Hoffmann
    if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
781 d467b679 Gerd Hoffmann
        vnc_write_u8(vs,  VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
782 d467b679 Gerd Hoffmann
        vnc_write_u8(vs,  0);  /*  padding     */
783 d467b679 Gerd Hoffmann
        vnc_write_u16(vs, 1);  /*  # of rects  */
784 d467b679 Gerd Hoffmann
        vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
785 d467b679 Gerd Hoffmann
                               VNC_ENCODING_RICH_CURSOR);
786 d467b679 Gerd Hoffmann
        isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel;
787 d467b679 Gerd Hoffmann
        vnc_write_pixels_generic(vs, &pf, c->data, isize);
788 d467b679 Gerd Hoffmann
        vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
789 d467b679 Gerd Hoffmann
        return 0;
790 d467b679 Gerd Hoffmann
    }
791 d467b679 Gerd Hoffmann
    return -1;
792 d467b679 Gerd Hoffmann
}
793 d467b679 Gerd Hoffmann
794 d467b679 Gerd Hoffmann
static void vnc_dpy_cursor_define(QEMUCursor *c)
795 d467b679 Gerd Hoffmann
{
796 d467b679 Gerd Hoffmann
    VncDisplay *vd = vnc_display;
797 d467b679 Gerd Hoffmann
    VncState *vs;
798 d467b679 Gerd Hoffmann
799 d467b679 Gerd Hoffmann
    cursor_put(vd->cursor);
800 d467b679 Gerd Hoffmann
    qemu_free(vd->cursor_mask);
801 d467b679 Gerd Hoffmann
802 d467b679 Gerd Hoffmann
    vd->cursor = c;
803 d467b679 Gerd Hoffmann
    cursor_get(vd->cursor);
804 d467b679 Gerd Hoffmann
    vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
805 d467b679 Gerd Hoffmann
    vd->cursor_mask = qemu_mallocz(vd->cursor_msize);
806 d467b679 Gerd Hoffmann
    cursor_get_mono_mask(c, 0, vd->cursor_mask);
807 d467b679 Gerd Hoffmann
808 d467b679 Gerd Hoffmann
    QTAILQ_FOREACH(vs, &vd->clients, next) {
809 d467b679 Gerd Hoffmann
        vnc_cursor_define(vs);
810 d467b679 Gerd Hoffmann
    }
811 d467b679 Gerd Hoffmann
}
812 d467b679 Gerd Hoffmann
813 1fc62412 Stefano Stabellini
static int find_and_clear_dirty_height(struct VncState *vs,
814 6baebed7 aliguori
                                       int y, int last_x, int x)
815 24236869 bellard
{
816 24236869 bellard
    int h;
817 1fc62412 Stefano Stabellini
    VncDisplay *vd = vs->vd;
818 24236869 bellard
819 1fc62412 Stefano Stabellini
    for (h = 1; h < (vd->server->height - y); h++) {
820 28a76be8 aliguori
        int tmp_x;
821 1fc62412 Stefano Stabellini
        if (!vnc_get_bit(vs->dirty[y + h], last_x))
822 28a76be8 aliguori
            break;
823 28a76be8 aliguori
        for (tmp_x = last_x; tmp_x < x; tmp_x++)
824 1fc62412 Stefano Stabellini
            vnc_clear_bit(vs->dirty[y + h], tmp_x);
825 24236869 bellard
    }
826 24236869 bellard
827 24236869 bellard
    return h;
828 24236869 bellard
}
829 24236869 bellard
830 2430ffe4 Stefano Stabellini
static int vnc_update_client(VncState *vs, int has_dirty)
831 24236869 bellard
{
832 24236869 bellard
    if (vs->need_update && vs->csock != -1) {
833 1fc62412 Stefano Stabellini
        VncDisplay *vd = vs->vd;
834 28a76be8 aliguori
        int y;
835 28a76be8 aliguori
        int n_rectangles;
836 28a76be8 aliguori
        int saved_offset;
837 24236869 bellard
838 703bc68f Stefano Stabellini
        if (vs->output.offset && !vs->audio_cap && !vs->force_update)
839 c522d0e2 aliguori
            /* kernel send buffers are full -> drop frames to throttle */
840 2430ffe4 Stefano Stabellini
            return 0;
841 a0ecfb73 balrog
842 703bc68f Stefano Stabellini
        if (!has_dirty && !vs->audio_cap && !vs->force_update)
843 2430ffe4 Stefano Stabellini
            return 0;
844 28a76be8 aliguori
845 6baebed7 aliguori
        /*
846 6baebed7 aliguori
         * Send screen updates to the vnc client using the server
847 6baebed7 aliguori
         * surface and server dirty map.  guest surface updates
848 6baebed7 aliguori
         * happening in parallel don't disturb us, the next pass will
849 6baebed7 aliguori
         * send them to the client.
850 6baebed7 aliguori
         */
851 28a76be8 aliguori
        n_rectangles = 0;
852 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
853 28a76be8 aliguori
        vnc_write_u8(vs, 0);
854 28a76be8 aliguori
        saved_offset = vs->output.offset;
855 28a76be8 aliguori
        vnc_write_u16(vs, 0);
856 28a76be8 aliguori
857 1fc62412 Stefano Stabellini
        for (y = 0; y < vd->server->height; y++) {
858 28a76be8 aliguori
            int x;
859 28a76be8 aliguori
            int last_x = -1;
860 1fc62412 Stefano Stabellini
            for (x = 0; x < vd->server->width / 16; x++) {
861 1fc62412 Stefano Stabellini
                if (vnc_get_bit(vs->dirty[y], x)) {
862 28a76be8 aliguori
                    if (last_x == -1) {
863 28a76be8 aliguori
                        last_x = x;
864 28a76be8 aliguori
                    }
865 1fc62412 Stefano Stabellini
                    vnc_clear_bit(vs->dirty[y], x);
866 28a76be8 aliguori
                } else {
867 28a76be8 aliguori
                    if (last_x != -1) {
868 1fc62412 Stefano Stabellini
                        int h = find_and_clear_dirty_height(vs, y, last_x, x);
869 28a76be8 aliguori
                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
870 28a76be8 aliguori
                        n_rectangles++;
871 28a76be8 aliguori
                    }
872 28a76be8 aliguori
                    last_x = -1;
873 28a76be8 aliguori
                }
874 28a76be8 aliguori
            }
875 28a76be8 aliguori
            if (last_x != -1) {
876 1fc62412 Stefano Stabellini
                int h = find_and_clear_dirty_height(vs, y, last_x, x);
877 28a76be8 aliguori
                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
878 28a76be8 aliguori
                n_rectangles++;
879 28a76be8 aliguori
            }
880 28a76be8 aliguori
        }
881 28a76be8 aliguori
        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
882 28a76be8 aliguori
        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
883 28a76be8 aliguori
        vnc_flush(vs);
884 c522d0e2 aliguori
        vs->force_update = 0;
885 2430ffe4 Stefano Stabellini
        return n_rectangles;
886 24236869 bellard
    }
887 24236869 bellard
888 703bc68f Stefano Stabellini
    if (vs->csock == -1)
889 198a0039 Gerd Hoffmann
        vnc_disconnect_finish(vs);
890 2430ffe4 Stefano Stabellini
891 2430ffe4 Stefano Stabellini
    return 0;
892 24236869 bellard
}
893 24236869 bellard
894 429a8ed3 malc
/* audio */
895 429a8ed3 malc
static void audio_capture_notify(void *opaque, audcnotification_e cmd)
896 429a8ed3 malc
{
897 429a8ed3 malc
    VncState *vs = opaque;
898 429a8ed3 malc
899 429a8ed3 malc
    switch (cmd) {
900 429a8ed3 malc
    case AUD_CNOTIFY_DISABLE:
901 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
902 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
903 46a183da Daniel P. Berrange
        vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_END);
904 429a8ed3 malc
        vnc_flush(vs);
905 429a8ed3 malc
        break;
906 429a8ed3 malc
907 429a8ed3 malc
    case AUD_CNOTIFY_ENABLE:
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_BEGIN);
911 429a8ed3 malc
        vnc_flush(vs);
912 429a8ed3 malc
        break;
913 429a8ed3 malc
    }
914 429a8ed3 malc
}
915 429a8ed3 malc
916 429a8ed3 malc
static void audio_capture_destroy(void *opaque)
917 429a8ed3 malc
{
918 429a8ed3 malc
}
919 429a8ed3 malc
920 429a8ed3 malc
static void audio_capture(void *opaque, void *buf, int size)
921 429a8ed3 malc
{
922 429a8ed3 malc
    VncState *vs = opaque;
923 429a8ed3 malc
924 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
925 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
926 46a183da Daniel P. Berrange
    vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA);
927 429a8ed3 malc
    vnc_write_u32(vs, size);
928 429a8ed3 malc
    vnc_write(vs, buf, size);
929 429a8ed3 malc
    vnc_flush(vs);
930 429a8ed3 malc
}
931 429a8ed3 malc
932 429a8ed3 malc
static void audio_add(VncState *vs)
933 429a8ed3 malc
{
934 429a8ed3 malc
    struct audio_capture_ops ops;
935 429a8ed3 malc
936 429a8ed3 malc
    if (vs->audio_cap) {
937 8631b608 Markus Armbruster
        monitor_printf(default_mon, "audio already running\n");
938 429a8ed3 malc
        return;
939 429a8ed3 malc
    }
940 429a8ed3 malc
941 429a8ed3 malc
    ops.notify = audio_capture_notify;
942 429a8ed3 malc
    ops.destroy = audio_capture_destroy;
943 429a8ed3 malc
    ops.capture = audio_capture;
944 429a8ed3 malc
945 1a7dafce malc
    vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
946 429a8ed3 malc
    if (!vs->audio_cap) {
947 8631b608 Markus Armbruster
        monitor_printf(default_mon, "Failed to add audio capture\n");
948 429a8ed3 malc
    }
949 429a8ed3 malc
}
950 429a8ed3 malc
951 429a8ed3 malc
static void audio_del(VncState *vs)
952 429a8ed3 malc
{
953 429a8ed3 malc
    if (vs->audio_cap) {
954 429a8ed3 malc
        AUD_del_capture(vs->audio_cap, vs);
955 429a8ed3 malc
        vs->audio_cap = NULL;
956 429a8ed3 malc
    }
957 429a8ed3 malc
}
958 429a8ed3 malc
959 198a0039 Gerd Hoffmann
static void vnc_disconnect_start(VncState *vs)
960 198a0039 Gerd Hoffmann
{
961 198a0039 Gerd Hoffmann
    if (vs->csock == -1)
962 198a0039 Gerd Hoffmann
        return;
963 198a0039 Gerd Hoffmann
    qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
964 198a0039 Gerd Hoffmann
    closesocket(vs->csock);
965 198a0039 Gerd Hoffmann
    vs->csock = -1;
966 198a0039 Gerd Hoffmann
}
967 198a0039 Gerd Hoffmann
968 198a0039 Gerd Hoffmann
static void vnc_disconnect_finish(VncState *vs)
969 198a0039 Gerd Hoffmann
{
970 0d72f3d3 Luiz Capitulino
    vnc_qmp_event(vs, QEVENT_VNC_DISCONNECTED);
971 0d72f3d3 Luiz Capitulino
972 5d418e3b Corentin Chary
    buffer_free(&vs->input);
973 5d418e3b Corentin Chary
    buffer_free(&vs->output);
974 4a80dba3 Luiz Capitulino
975 4a80dba3 Luiz Capitulino
    qobject_decref(vs->info);
976 4a80dba3 Luiz Capitulino
977 161c4f20 Corentin Chary
    vnc_zlib_clear(vs);
978 161c4f20 Corentin Chary
979 198a0039 Gerd Hoffmann
#ifdef CONFIG_VNC_TLS
980 198a0039 Gerd Hoffmann
    vnc_tls_client_cleanup(vs);
981 198a0039 Gerd Hoffmann
#endif /* CONFIG_VNC_TLS */
982 198a0039 Gerd Hoffmann
#ifdef CONFIG_VNC_SASL
983 198a0039 Gerd Hoffmann
    vnc_sasl_client_cleanup(vs);
984 198a0039 Gerd Hoffmann
#endif /* CONFIG_VNC_SASL */
985 198a0039 Gerd Hoffmann
    audio_del(vs);
986 198a0039 Gerd Hoffmann
987 41b4bef6 Amit Shah
    QTAILQ_REMOVE(&vs->vd->clients, vs, next);
988 41b4bef6 Amit Shah
989 41b4bef6 Amit Shah
    if (QTAILQ_EMPTY(&vs->vd->clients)) {
990 198a0039 Gerd Hoffmann
        dcl->idle = 1;
991 41b4bef6 Amit Shah
    }
992 198a0039 Gerd Hoffmann
993 37c34d9d Anthony Liguori
    qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
994 703bc68f Stefano Stabellini
    vnc_remove_timer(vs->vd);
995 3a0558b5 Gerd Hoffmann
    if (vs->vd->lock_key_sync)
996 3a0558b5 Gerd Hoffmann
        qemu_remove_led_event_handler(vs->led);
997 5d95ac5b Glauber Costa
    qemu_free(vs);
998 198a0039 Gerd Hoffmann
}
999 2f9606b3 aliguori
1000 2f9606b3 aliguori
int vnc_client_io_error(VncState *vs, int ret, int last_errno)
1001 24236869 bellard
{
1002 24236869 bellard
    if (ret == 0 || ret == -1) {
1003 ea01e5fd balrog
        if (ret == -1) {
1004 ea01e5fd balrog
            switch (last_errno) {
1005 ea01e5fd balrog
                case EINTR:
1006 ea01e5fd balrog
                case EAGAIN:
1007 ea01e5fd balrog
#ifdef _WIN32
1008 ea01e5fd balrog
                case WSAEWOULDBLOCK:
1009 ea01e5fd balrog
#endif
1010 ea01e5fd balrog
                    return 0;
1011 ea01e5fd balrog
                default:
1012 ea01e5fd balrog
                    break;
1013 ea01e5fd balrog
            }
1014 ea01e5fd balrog
        }
1015 24236869 bellard
1016 198a0039 Gerd Hoffmann
        VNC_DEBUG("Closing down client sock: ret %d, errno %d\n",
1017 198a0039 Gerd Hoffmann
                  ret, ret < 0 ? last_errno : 0);
1018 198a0039 Gerd Hoffmann
        vnc_disconnect_start(vs);
1019 6baebed7 aliguori
1020 28a76be8 aliguori
        return 0;
1021 24236869 bellard
    }
1022 24236869 bellard
    return ret;
1023 24236869 bellard
}
1024 24236869 bellard
1025 5fb6c7a8 aliguori
1026 5fb6c7a8 aliguori
void vnc_client_error(VncState *vs)
1027 24236869 bellard
{
1028 198a0039 Gerd Hoffmann
    VNC_DEBUG("Closing down client sock: protocol error\n");
1029 198a0039 Gerd Hoffmann
    vnc_disconnect_start(vs);
1030 24236869 bellard
}
1031 24236869 bellard
1032 2f9606b3 aliguori
1033 2f9606b3 aliguori
/*
1034 2f9606b3 aliguori
 * Called to write a chunk of data to the client socket. The data may
1035 2f9606b3 aliguori
 * be the raw data, or may have already been encoded by SASL.
1036 2f9606b3 aliguori
 * The data will be written either straight onto the socket, or
1037 2f9606b3 aliguori
 * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1038 2f9606b3 aliguori
 *
1039 2f9606b3 aliguori
 * NB, it is theoretically possible to have 2 layers of encryption,
1040 2f9606b3 aliguori
 * both SASL, and this TLS layer. It is highly unlikely in practice
1041 2f9606b3 aliguori
 * though, since SASL encryption will typically be a no-op if TLS
1042 2f9606b3 aliguori
 * is active
1043 2f9606b3 aliguori
 *
1044 2f9606b3 aliguori
 * Returns the number of bytes written, which may be less than
1045 2f9606b3 aliguori
 * the requested 'datalen' if the socket would block. Returns
1046 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
1047 2f9606b3 aliguori
 */
1048 2f9606b3 aliguori
long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
1049 24236869 bellard
{
1050 ceb5caaf bellard
    long ret;
1051 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1052 5fb6c7a8 aliguori
    if (vs->tls.session) {
1053 28a76be8 aliguori
        ret = gnutls_write(vs->tls.session, data, datalen);
1054 28a76be8 aliguori
        if (ret < 0) {
1055 28a76be8 aliguori
            if (ret == GNUTLS_E_AGAIN)
1056 28a76be8 aliguori
                errno = EAGAIN;
1057 28a76be8 aliguori
            else
1058 28a76be8 aliguori
                errno = EIO;
1059 28a76be8 aliguori
            ret = -1;
1060 28a76be8 aliguori
        }
1061 8d5d2d4c ths
    } else
1062 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
1063 70503264 Stefan Weil
        ret = send(vs->csock, (const void *)data, datalen, 0);
1064 23decc87 aliguori
    VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
1065 2f9606b3 aliguori
    return vnc_client_io_error(vs, ret, socket_error());
1066 2f9606b3 aliguori
}
1067 2f9606b3 aliguori
1068 2f9606b3 aliguori
1069 2f9606b3 aliguori
/*
1070 2f9606b3 aliguori
 * Called to write buffered data to the client socket, when not
1071 2f9606b3 aliguori
 * using any SASL SSF encryption layers. Will write as much data
1072 2f9606b3 aliguori
 * as possible without blocking. If all buffered data is written,
1073 2f9606b3 aliguori
 * will switch the FD poll() handler back to read monitoring.
1074 2f9606b3 aliguori
 *
1075 2f9606b3 aliguori
 * Returns the number of bytes written, which may be less than
1076 2f9606b3 aliguori
 * the buffered output data if the socket would block. Returns
1077 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
1078 2f9606b3 aliguori
 */
1079 2f9606b3 aliguori
static long vnc_client_write_plain(VncState *vs)
1080 2f9606b3 aliguori
{
1081 2f9606b3 aliguori
    long ret;
1082 2f9606b3 aliguori
1083 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1084 23decc87 aliguori
    VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
1085 2f9606b3 aliguori
              vs->output.buffer, vs->output.capacity, vs->output.offset,
1086 2f9606b3 aliguori
              vs->sasl.waitWriteSSF);
1087 2f9606b3 aliguori
1088 2f9606b3 aliguori
    if (vs->sasl.conn &&
1089 2f9606b3 aliguori
        vs->sasl.runSSF &&
1090 2f9606b3 aliguori
        vs->sasl.waitWriteSSF) {
1091 2f9606b3 aliguori
        ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF);
1092 2f9606b3 aliguori
        if (ret)
1093 2f9606b3 aliguori
            vs->sasl.waitWriteSSF -= ret;
1094 2f9606b3 aliguori
    } else
1095 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1096 2f9606b3 aliguori
        ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset);
1097 24236869 bellard
    if (!ret)
1098 2f9606b3 aliguori
        return 0;
1099 24236869 bellard
1100 24236869 bellard
    memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
1101 24236869 bellard
    vs->output.offset -= ret;
1102 24236869 bellard
1103 24236869 bellard
    if (vs->output.offset == 0) {
1104 28a76be8 aliguori
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
1105 24236869 bellard
    }
1106 2f9606b3 aliguori
1107 2f9606b3 aliguori
    return ret;
1108 2f9606b3 aliguori
}
1109 2f9606b3 aliguori
1110 2f9606b3 aliguori
1111 2f9606b3 aliguori
/*
1112 2f9606b3 aliguori
 * First function called whenever there is data to be written to
1113 2f9606b3 aliguori
 * the client socket. Will delegate actual work according to whether
1114 2f9606b3 aliguori
 * SASL SSF layers are enabled (thus requiring encryption calls)
1115 2f9606b3 aliguori
 */
1116 2f9606b3 aliguori
void vnc_client_write(void *opaque)
1117 2f9606b3 aliguori
{
1118 2f9606b3 aliguori
    VncState *vs = opaque;
1119 2f9606b3 aliguori
1120 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1121 2f9606b3 aliguori
    if (vs->sasl.conn &&
1122 2f9606b3 aliguori
        vs->sasl.runSSF &&
1123 9678d950 Blue Swirl
        !vs->sasl.waitWriteSSF) {
1124 9678d950 Blue Swirl
        vnc_client_write_sasl(vs);
1125 9678d950 Blue Swirl
    } else
1126 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1127 9678d950 Blue Swirl
        vnc_client_write_plain(vs);
1128 24236869 bellard
}
1129 24236869 bellard
1130 5fb6c7a8 aliguori
void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
1131 24236869 bellard
{
1132 24236869 bellard
    vs->read_handler = func;
1133 24236869 bellard
    vs->read_handler_expect = expecting;
1134 24236869 bellard
}
1135 24236869 bellard
1136 2f9606b3 aliguori
1137 2f9606b3 aliguori
/*
1138 2f9606b3 aliguori
 * Called to read a chunk of data from the client socket. The data may
1139 2f9606b3 aliguori
 * be the raw data, or may need to be further decoded by SASL.
1140 2f9606b3 aliguori
 * The data will be read either straight from to the socket, or
1141 2f9606b3 aliguori
 * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1142 2f9606b3 aliguori
 *
1143 2f9606b3 aliguori
 * NB, it is theoretically possible to have 2 layers of encryption,
1144 2f9606b3 aliguori
 * both SASL, and this TLS layer. It is highly unlikely in practice
1145 2f9606b3 aliguori
 * though, since SASL encryption will typically be a no-op if TLS
1146 2f9606b3 aliguori
 * is active
1147 2f9606b3 aliguori
 *
1148 2f9606b3 aliguori
 * Returns the number of bytes read, which may be less than
1149 2f9606b3 aliguori
 * the requested 'datalen' if the socket would block. Returns
1150 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
1151 2f9606b3 aliguori
 */
1152 2f9606b3 aliguori
long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
1153 24236869 bellard
{
1154 ceb5caaf bellard
    long ret;
1155 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1156 5fb6c7a8 aliguori
    if (vs->tls.session) {
1157 28a76be8 aliguori
        ret = gnutls_read(vs->tls.session, data, datalen);
1158 28a76be8 aliguori
        if (ret < 0) {
1159 28a76be8 aliguori
            if (ret == GNUTLS_E_AGAIN)
1160 28a76be8 aliguori
                errno = EAGAIN;
1161 28a76be8 aliguori
            else
1162 28a76be8 aliguori
                errno = EIO;
1163 28a76be8 aliguori
            ret = -1;
1164 28a76be8 aliguori
        }
1165 8d5d2d4c ths
    } else
1166 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
1167 c5b76b38 Blue Swirl
        ret = recv(vs->csock, (void *)data, datalen, 0);
1168 23decc87 aliguori
    VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
1169 2f9606b3 aliguori
    return vnc_client_io_error(vs, ret, socket_error());
1170 2f9606b3 aliguori
}
1171 24236869 bellard
1172 2f9606b3 aliguori
1173 2f9606b3 aliguori
/*
1174 2f9606b3 aliguori
 * Called to read data from the client socket to the input buffer,
1175 2f9606b3 aliguori
 * when not using any SASL SSF encryption layers. Will read as much
1176 2f9606b3 aliguori
 * data as possible without blocking.
1177 2f9606b3 aliguori
 *
1178 2f9606b3 aliguori
 * Returns the number of bytes read. Returns -1 on error, and
1179 2f9606b3 aliguori
 * disconnects the client socket.
1180 2f9606b3 aliguori
 */
1181 2f9606b3 aliguori
static long vnc_client_read_plain(VncState *vs)
1182 2f9606b3 aliguori
{
1183 2f9606b3 aliguori
    int ret;
1184 23decc87 aliguori
    VNC_DEBUG("Read plain %p size %zd offset %zd\n",
1185 2f9606b3 aliguori
              vs->input.buffer, vs->input.capacity, vs->input.offset);
1186 2f9606b3 aliguori
    buffer_reserve(&vs->input, 4096);
1187 2f9606b3 aliguori
    ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096);
1188 2f9606b3 aliguori
    if (!ret)
1189 2f9606b3 aliguori
        return 0;
1190 24236869 bellard
    vs->input.offset += ret;
1191 2f9606b3 aliguori
    return ret;
1192 2f9606b3 aliguori
}
1193 2f9606b3 aliguori
1194 2f9606b3 aliguori
1195 2f9606b3 aliguori
/*
1196 2f9606b3 aliguori
 * First function called whenever there is more data to be read from
1197 2f9606b3 aliguori
 * the client socket. Will delegate actual work according to whether
1198 2f9606b3 aliguori
 * SASL SSF layers are enabled (thus requiring decryption calls)
1199 2f9606b3 aliguori
 */
1200 2f9606b3 aliguori
void vnc_client_read(void *opaque)
1201 2f9606b3 aliguori
{
1202 2f9606b3 aliguori
    VncState *vs = opaque;
1203 2f9606b3 aliguori
    long ret;
1204 2f9606b3 aliguori
1205 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1206 2f9606b3 aliguori
    if (vs->sasl.conn && vs->sasl.runSSF)
1207 2f9606b3 aliguori
        ret = vnc_client_read_sasl(vs);
1208 2f9606b3 aliguori
    else
1209 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1210 2f9606b3 aliguori
        ret = vnc_client_read_plain(vs);
1211 198a0039 Gerd Hoffmann
    if (!ret) {
1212 198a0039 Gerd Hoffmann
        if (vs->csock == -1)
1213 198a0039 Gerd Hoffmann
            vnc_disconnect_finish(vs);
1214 28a76be8 aliguori
        return;
1215 198a0039 Gerd Hoffmann
    }
1216 24236869 bellard
1217 24236869 bellard
    while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
1218 28a76be8 aliguori
        size_t len = vs->read_handler_expect;
1219 28a76be8 aliguori
        int ret;
1220 28a76be8 aliguori
1221 28a76be8 aliguori
        ret = vs->read_handler(vs, vs->input.buffer, len);
1222 198a0039 Gerd Hoffmann
        if (vs->csock == -1) {
1223 198a0039 Gerd Hoffmann
            vnc_disconnect_finish(vs);
1224 28a76be8 aliguori
            return;
1225 198a0039 Gerd Hoffmann
        }
1226 28a76be8 aliguori
1227 28a76be8 aliguori
        if (!ret) {
1228 28a76be8 aliguori
            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
1229 28a76be8 aliguori
            vs->input.offset -= len;
1230 28a76be8 aliguori
        } else {
1231 28a76be8 aliguori
            vs->read_handler_expect = ret;
1232 28a76be8 aliguori
        }
1233 24236869 bellard
    }
1234 24236869 bellard
}
1235 24236869 bellard
1236 5fb6c7a8 aliguori
void vnc_write(VncState *vs, const void *data, size_t len)
1237 24236869 bellard
{
1238 24236869 bellard
    buffer_reserve(&vs->output, len);
1239 24236869 bellard
1240 198a0039 Gerd Hoffmann
    if (vs->csock != -1 && buffer_empty(&vs->output)) {
1241 28a76be8 aliguori
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1242 24236869 bellard
    }
1243 24236869 bellard
1244 24236869 bellard
    buffer_append(&vs->output, data, len);
1245 24236869 bellard
}
1246 24236869 bellard
1247 5fb6c7a8 aliguori
void vnc_write_s32(VncState *vs, int32_t value)
1248 24236869 bellard
{
1249 24236869 bellard
    vnc_write_u32(vs, *(uint32_t *)&value);
1250 24236869 bellard
}
1251 24236869 bellard
1252 5fb6c7a8 aliguori
void vnc_write_u32(VncState *vs, uint32_t value)
1253 24236869 bellard
{
1254 24236869 bellard
    uint8_t buf[4];
1255 24236869 bellard
1256 24236869 bellard
    buf[0] = (value >> 24) & 0xFF;
1257 24236869 bellard
    buf[1] = (value >> 16) & 0xFF;
1258 24236869 bellard
    buf[2] = (value >>  8) & 0xFF;
1259 24236869 bellard
    buf[3] = value & 0xFF;
1260 24236869 bellard
1261 24236869 bellard
    vnc_write(vs, buf, 4);
1262 24236869 bellard
}
1263 24236869 bellard
1264 5fb6c7a8 aliguori
void vnc_write_u16(VncState *vs, uint16_t value)
1265 24236869 bellard
{
1266 64f5a135 bellard
    uint8_t buf[2];
1267 24236869 bellard
1268 24236869 bellard
    buf[0] = (value >> 8) & 0xFF;
1269 24236869 bellard
    buf[1] = value & 0xFF;
1270 24236869 bellard
1271 24236869 bellard
    vnc_write(vs, buf, 2);
1272 24236869 bellard
}
1273 24236869 bellard
1274 5fb6c7a8 aliguori
void vnc_write_u8(VncState *vs, uint8_t value)
1275 24236869 bellard
{
1276 24236869 bellard
    vnc_write(vs, (char *)&value, 1);
1277 24236869 bellard
}
1278 24236869 bellard
1279 5fb6c7a8 aliguori
void vnc_flush(VncState *vs)
1280 24236869 bellard
{
1281 198a0039 Gerd Hoffmann
    if (vs->csock != -1 && vs->output.offset)
1282 28a76be8 aliguori
        vnc_client_write(vs);
1283 24236869 bellard
}
1284 24236869 bellard
1285 5fb6c7a8 aliguori
uint8_t read_u8(uint8_t *data, size_t offset)
1286 24236869 bellard
{
1287 24236869 bellard
    return data[offset];
1288 24236869 bellard
}
1289 24236869 bellard
1290 5fb6c7a8 aliguori
uint16_t read_u16(uint8_t *data, size_t offset)
1291 24236869 bellard
{
1292 24236869 bellard
    return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
1293 24236869 bellard
}
1294 24236869 bellard
1295 5fb6c7a8 aliguori
int32_t read_s32(uint8_t *data, size_t offset)
1296 24236869 bellard
{
1297 24236869 bellard
    return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
1298 28a76be8 aliguori
                     (data[offset + 2] << 8) | data[offset + 3]);
1299 24236869 bellard
}
1300 24236869 bellard
1301 5fb6c7a8 aliguori
uint32_t read_u32(uint8_t *data, size_t offset)
1302 24236869 bellard
{
1303 24236869 bellard
    return ((data[offset] << 24) | (data[offset + 1] << 16) |
1304 28a76be8 aliguori
            (data[offset + 2] << 8) | data[offset + 3]);
1305 24236869 bellard
}
1306 24236869 bellard
1307 60fe76f3 ths
static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
1308 24236869 bellard
{
1309 24236869 bellard
}
1310 24236869 bellard
1311 37c34d9d Anthony Liguori
static void check_pointer_type_change(Notifier *notifier)
1312 564c337e bellard
{
1313 37c34d9d Anthony Liguori
    VncState *vs = container_of(notifier, VncState, mouse_mode_notifier);
1314 37c34d9d Anthony Liguori
    int absolute = kbd_mouse_is_absolute();
1315 37c34d9d Anthony Liguori
1316 29fa4ed9 aliguori
    if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
1317 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1318 28a76be8 aliguori
        vnc_write_u8(vs, 0);
1319 28a76be8 aliguori
        vnc_write_u16(vs, 1);
1320 28a76be8 aliguori
        vnc_framebuffer_update(vs, absolute, 0,
1321 28a76be8 aliguori
                               ds_get_width(vs->ds), ds_get_height(vs->ds),
1322 29fa4ed9 aliguori
                               VNC_ENCODING_POINTER_TYPE_CHANGE);
1323 28a76be8 aliguori
        vnc_flush(vs);
1324 564c337e bellard
    }
1325 564c337e bellard
    vs->absolute = absolute;
1326 564c337e bellard
}
1327 564c337e bellard
1328 24236869 bellard
static void pointer_event(VncState *vs, int button_mask, int x, int y)
1329 24236869 bellard
{
1330 24236869 bellard
    int buttons = 0;
1331 24236869 bellard
    int dz = 0;
1332 24236869 bellard
1333 24236869 bellard
    if (button_mask & 0x01)
1334 28a76be8 aliguori
        buttons |= MOUSE_EVENT_LBUTTON;
1335 24236869 bellard
    if (button_mask & 0x02)
1336 28a76be8 aliguori
        buttons |= MOUSE_EVENT_MBUTTON;
1337 24236869 bellard
    if (button_mask & 0x04)
1338 28a76be8 aliguori
        buttons |= MOUSE_EVENT_RBUTTON;
1339 24236869 bellard
    if (button_mask & 0x08)
1340 28a76be8 aliguori
        dz = -1;
1341 24236869 bellard
    if (button_mask & 0x10)
1342 28a76be8 aliguori
        dz = 1;
1343 564c337e bellard
1344 564c337e bellard
    if (vs->absolute) {
1345 cc39a92c Chris Webb
        kbd_mouse_event(ds_get_width(vs->ds) > 1 ?
1346 cc39a92c Chris Webb
                          x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000,
1347 cc39a92c Chris Webb
                        ds_get_height(vs->ds) > 1 ?
1348 cc39a92c Chris Webb
                          y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000,
1349 28a76be8 aliguori
                        dz, buttons);
1350 29fa4ed9 aliguori
    } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
1351 28a76be8 aliguori
        x -= 0x7FFF;
1352 28a76be8 aliguori
        y -= 0x7FFF;
1353 24236869 bellard
1354 28a76be8 aliguori
        kbd_mouse_event(x, y, dz, buttons);
1355 564c337e bellard
    } else {
1356 28a76be8 aliguori
        if (vs->last_x != -1)
1357 28a76be8 aliguori
            kbd_mouse_event(x - vs->last_x,
1358 28a76be8 aliguori
                            y - vs->last_y,
1359 28a76be8 aliguori
                            dz, buttons);
1360 28a76be8 aliguori
        vs->last_x = x;
1361 28a76be8 aliguori
        vs->last_y = y;
1362 24236869 bellard
    }
1363 24236869 bellard
}
1364 24236869 bellard
1365 64f5a135 bellard
static void reset_keys(VncState *vs)
1366 64f5a135 bellard
{
1367 64f5a135 bellard
    int i;
1368 64f5a135 bellard
    for(i = 0; i < 256; i++) {
1369 64f5a135 bellard
        if (vs->modifiers_state[i]) {
1370 44bb61c8 Samuel Thibault
            if (i & SCANCODE_GREY)
1371 44bb61c8 Samuel Thibault
                kbd_put_keycode(SCANCODE_EMUL0);
1372 44bb61c8 Samuel Thibault
            kbd_put_keycode(i | SCANCODE_UP);
1373 64f5a135 bellard
            vs->modifiers_state[i] = 0;
1374 64f5a135 bellard
        }
1375 64f5a135 bellard
    }
1376 64f5a135 bellard
}
1377 64f5a135 bellard
1378 a528b80c balrog
static void press_key(VncState *vs, int keysym)
1379 a528b80c balrog
{
1380 44bb61c8 Samuel Thibault
    int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
1381 44bb61c8 Samuel Thibault
    if (keycode & SCANCODE_GREY)
1382 44bb61c8 Samuel Thibault
        kbd_put_keycode(SCANCODE_EMUL0);
1383 44bb61c8 Samuel Thibault
    kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
1384 44bb61c8 Samuel Thibault
    if (keycode & SCANCODE_GREY)
1385 44bb61c8 Samuel Thibault
        kbd_put_keycode(SCANCODE_EMUL0);
1386 44bb61c8 Samuel Thibault
    kbd_put_keycode(keycode | SCANCODE_UP);
1387 a528b80c balrog
}
1388 a528b80c balrog
1389 7ffb82ca Gerd Hoffmann
static void kbd_leds(void *opaque, int ledstate)
1390 7ffb82ca Gerd Hoffmann
{
1391 7ffb82ca Gerd Hoffmann
    VncState *vs = opaque;
1392 7ffb82ca Gerd Hoffmann
    int caps, num;
1393 7ffb82ca Gerd Hoffmann
1394 7ffb82ca Gerd Hoffmann
    caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0;
1395 7ffb82ca Gerd Hoffmann
    num  = ledstate & QEMU_NUM_LOCK_LED  ? 1 : 0;
1396 7ffb82ca Gerd Hoffmann
1397 7ffb82ca Gerd Hoffmann
    if (vs->modifiers_state[0x3a] != caps) {
1398 7ffb82ca Gerd Hoffmann
        vs->modifiers_state[0x3a] = caps;
1399 7ffb82ca Gerd Hoffmann
    }
1400 7ffb82ca Gerd Hoffmann
    if (vs->modifiers_state[0x45] != num) {
1401 7ffb82ca Gerd Hoffmann
        vs->modifiers_state[0x45] = num;
1402 7ffb82ca Gerd Hoffmann
    }
1403 7ffb82ca Gerd Hoffmann
}
1404 7ffb82ca Gerd Hoffmann
1405 9ca313aa aliguori
static void do_key_event(VncState *vs, int down, int keycode, int sym)
1406 24236869 bellard
{
1407 64f5a135 bellard
    /* QEMU console switch */
1408 64f5a135 bellard
    switch(keycode) {
1409 64f5a135 bellard
    case 0x2a:                          /* Left Shift */
1410 64f5a135 bellard
    case 0x36:                          /* Right Shift */
1411 64f5a135 bellard
    case 0x1d:                          /* Left CTRL */
1412 64f5a135 bellard
    case 0x9d:                          /* Right CTRL */
1413 64f5a135 bellard
    case 0x38:                          /* Left ALT */
1414 64f5a135 bellard
    case 0xb8:                          /* Right ALT */
1415 64f5a135 bellard
        if (down)
1416 64f5a135 bellard
            vs->modifiers_state[keycode] = 1;
1417 64f5a135 bellard
        else
1418 64f5a135 bellard
            vs->modifiers_state[keycode] = 0;
1419 64f5a135 bellard
        break;
1420 5fafdf24 ths
    case 0x02 ... 0x0a: /* '1' to '9' keys */
1421 64f5a135 bellard
        if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1422 64f5a135 bellard
            /* Reset the modifiers sent to the current console */
1423 64f5a135 bellard
            reset_keys(vs);
1424 64f5a135 bellard
            console_select(keycode - 0x02);
1425 64f5a135 bellard
            return;
1426 64f5a135 bellard
        }
1427 64f5a135 bellard
        break;
1428 28a76be8 aliguori
    case 0x3a:                        /* CapsLock */
1429 28a76be8 aliguori
    case 0x45:                        /* NumLock */
1430 7ffb82ca Gerd Hoffmann
        if (down)
1431 a528b80c balrog
            vs->modifiers_state[keycode] ^= 1;
1432 a528b80c balrog
        break;
1433 a528b80c balrog
    }
1434 a528b80c balrog
1435 3a0558b5 Gerd Hoffmann
    if (vs->vd->lock_key_sync &&
1436 3a0558b5 Gerd Hoffmann
        keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
1437 a528b80c balrog
        /* If the numlock state needs to change then simulate an additional
1438 a528b80c balrog
           keypress before sending this one.  This will happen if the user
1439 a528b80c balrog
           toggles numlock away from the VNC window.
1440 a528b80c balrog
        */
1441 753b4053 aliguori
        if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
1442 a528b80c balrog
            if (!vs->modifiers_state[0x45]) {
1443 a528b80c balrog
                vs->modifiers_state[0x45] = 1;
1444 a528b80c balrog
                press_key(vs, 0xff7f);
1445 a528b80c balrog
            }
1446 a528b80c balrog
        } else {
1447 a528b80c balrog
            if (vs->modifiers_state[0x45]) {
1448 a528b80c balrog
                vs->modifiers_state[0x45] = 0;
1449 a528b80c balrog
                press_key(vs, 0xff7f);
1450 a528b80c balrog
            }
1451 a528b80c balrog
        }
1452 64f5a135 bellard
    }
1453 24236869 bellard
1454 3a0558b5 Gerd Hoffmann
    if (vs->vd->lock_key_sync &&
1455 3a0558b5 Gerd Hoffmann
        ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
1456 6b132502 Gerd Hoffmann
        /* If the capslock state needs to change then simulate an additional
1457 6b132502 Gerd Hoffmann
           keypress before sending this one.  This will happen if the user
1458 6b132502 Gerd Hoffmann
           toggles capslock away from the VNC window.
1459 6b132502 Gerd Hoffmann
        */
1460 6b132502 Gerd Hoffmann
        int uppercase = !!(sym >= 'A' && sym <= 'Z');
1461 6b132502 Gerd Hoffmann
        int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
1462 6b132502 Gerd Hoffmann
        int capslock = !!(vs->modifiers_state[0x3a]);
1463 6b132502 Gerd Hoffmann
        if (capslock) {
1464 6b132502 Gerd Hoffmann
            if (uppercase == shift) {
1465 6b132502 Gerd Hoffmann
                vs->modifiers_state[0x3a] = 0;
1466 6b132502 Gerd Hoffmann
                press_key(vs, 0xffe5);
1467 6b132502 Gerd Hoffmann
            }
1468 6b132502 Gerd Hoffmann
        } else {
1469 6b132502 Gerd Hoffmann
            if (uppercase != shift) {
1470 6b132502 Gerd Hoffmann
                vs->modifiers_state[0x3a] = 1;
1471 6b132502 Gerd Hoffmann
                press_key(vs, 0xffe5);
1472 6b132502 Gerd Hoffmann
            }
1473 6b132502 Gerd Hoffmann
        }
1474 6b132502 Gerd Hoffmann
    }
1475 6b132502 Gerd Hoffmann
1476 64f5a135 bellard
    if (is_graphic_console()) {
1477 44bb61c8 Samuel Thibault
        if (keycode & SCANCODE_GREY)
1478 44bb61c8 Samuel Thibault
            kbd_put_keycode(SCANCODE_EMUL0);
1479 64f5a135 bellard
        if (down)
1480 44bb61c8 Samuel Thibault
            kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
1481 64f5a135 bellard
        else
1482 44bb61c8 Samuel Thibault
            kbd_put_keycode(keycode | SCANCODE_UP);
1483 64f5a135 bellard
    } else {
1484 64f5a135 bellard
        /* QEMU console emulation */
1485 64f5a135 bellard
        if (down) {
1486 bb0a18e1 Gerd Hoffmann
            int numlock = vs->modifiers_state[0x45];
1487 64f5a135 bellard
            switch (keycode) {
1488 64f5a135 bellard
            case 0x2a:                          /* Left Shift */
1489 64f5a135 bellard
            case 0x36:                          /* Right Shift */
1490 64f5a135 bellard
            case 0x1d:                          /* Left CTRL */
1491 64f5a135 bellard
            case 0x9d:                          /* Right CTRL */
1492 64f5a135 bellard
            case 0x38:                          /* Left ALT */
1493 64f5a135 bellard
            case 0xb8:                          /* Right ALT */
1494 64f5a135 bellard
                break;
1495 64f5a135 bellard
            case 0xc8:
1496 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_UP);
1497 64f5a135 bellard
                break;
1498 64f5a135 bellard
            case 0xd0:
1499 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DOWN);
1500 64f5a135 bellard
                break;
1501 64f5a135 bellard
            case 0xcb:
1502 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_LEFT);
1503 64f5a135 bellard
                break;
1504 64f5a135 bellard
            case 0xcd:
1505 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_RIGHT);
1506 64f5a135 bellard
                break;
1507 64f5a135 bellard
            case 0xd3:
1508 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DELETE);
1509 64f5a135 bellard
                break;
1510 64f5a135 bellard
            case 0xc7:
1511 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_HOME);
1512 64f5a135 bellard
                break;
1513 64f5a135 bellard
            case 0xcf:
1514 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_END);
1515 64f5a135 bellard
                break;
1516 64f5a135 bellard
            case 0xc9:
1517 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEUP);
1518 64f5a135 bellard
                break;
1519 64f5a135 bellard
            case 0xd1:
1520 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1521 64f5a135 bellard
                break;
1522 bb0a18e1 Gerd Hoffmann
1523 bb0a18e1 Gerd Hoffmann
            case 0x47:
1524 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
1525 bb0a18e1 Gerd Hoffmann
                break;
1526 bb0a18e1 Gerd Hoffmann
            case 0x48:
1527 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
1528 bb0a18e1 Gerd Hoffmann
                break;
1529 bb0a18e1 Gerd Hoffmann
            case 0x49:
1530 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
1531 bb0a18e1 Gerd Hoffmann
                break;
1532 bb0a18e1 Gerd Hoffmann
            case 0x4b:
1533 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
1534 bb0a18e1 Gerd Hoffmann
                break;
1535 bb0a18e1 Gerd Hoffmann
            case 0x4c:
1536 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('5');
1537 bb0a18e1 Gerd Hoffmann
                break;
1538 bb0a18e1 Gerd Hoffmann
            case 0x4d:
1539 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
1540 bb0a18e1 Gerd Hoffmann
                break;
1541 bb0a18e1 Gerd Hoffmann
            case 0x4f:
1542 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
1543 bb0a18e1 Gerd Hoffmann
                break;
1544 bb0a18e1 Gerd Hoffmann
            case 0x50:
1545 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
1546 bb0a18e1 Gerd Hoffmann
                break;
1547 bb0a18e1 Gerd Hoffmann
            case 0x51:
1548 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
1549 bb0a18e1 Gerd Hoffmann
                break;
1550 bb0a18e1 Gerd Hoffmann
            case 0x52:
1551 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('0');
1552 bb0a18e1 Gerd Hoffmann
                break;
1553 bb0a18e1 Gerd Hoffmann
            case 0x53:
1554 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
1555 bb0a18e1 Gerd Hoffmann
                break;
1556 bb0a18e1 Gerd Hoffmann
1557 bb0a18e1 Gerd Hoffmann
            case 0xb5:
1558 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('/');
1559 bb0a18e1 Gerd Hoffmann
                break;
1560 bb0a18e1 Gerd Hoffmann
            case 0x37:
1561 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('*');
1562 bb0a18e1 Gerd Hoffmann
                break;
1563 bb0a18e1 Gerd Hoffmann
            case 0x4a:
1564 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('-');
1565 bb0a18e1 Gerd Hoffmann
                break;
1566 bb0a18e1 Gerd Hoffmann
            case 0x4e:
1567 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('+');
1568 bb0a18e1 Gerd Hoffmann
                break;
1569 bb0a18e1 Gerd Hoffmann
            case 0x9c:
1570 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('\n');
1571 bb0a18e1 Gerd Hoffmann
                break;
1572 bb0a18e1 Gerd Hoffmann
1573 64f5a135 bellard
            default:
1574 64f5a135 bellard
                kbd_put_keysym(sym);
1575 64f5a135 bellard
                break;
1576 64f5a135 bellard
            }
1577 64f5a135 bellard
        }
1578 64f5a135 bellard
    }
1579 24236869 bellard
}
1580 24236869 bellard
1581 bdbd7676 bellard
static void key_event(VncState *vs, int down, uint32_t sym)
1582 bdbd7676 bellard
{
1583 9ca313aa aliguori
    int keycode;
1584 4a93fe17 Gerd Hoffmann
    int lsym = sym;
1585 9ca313aa aliguori
1586 4a93fe17 Gerd Hoffmann
    if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) {
1587 4a93fe17 Gerd Hoffmann
        lsym = lsym - 'A' + 'a';
1588 4a93fe17 Gerd Hoffmann
    }
1589 9ca313aa aliguori
1590 44bb61c8 Samuel Thibault
    keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
1591 9ca313aa aliguori
    do_key_event(vs, down, keycode, sym);
1592 9ca313aa aliguori
}
1593 9ca313aa aliguori
1594 9ca313aa aliguori
static void ext_key_event(VncState *vs, int down,
1595 9ca313aa aliguori
                          uint32_t sym, uint16_t keycode)
1596 9ca313aa aliguori
{
1597 9ca313aa aliguori
    /* if the user specifies a keyboard layout, always use it */
1598 9ca313aa aliguori
    if (keyboard_layout)
1599 9ca313aa aliguori
        key_event(vs, down, sym);
1600 9ca313aa aliguori
    else
1601 9ca313aa aliguori
        do_key_event(vs, down, keycode, sym);
1602 bdbd7676 bellard
}
1603 bdbd7676 bellard
1604 24236869 bellard
static void framebuffer_update_request(VncState *vs, int incremental,
1605 28a76be8 aliguori
                                       int x_position, int y_position,
1606 28a76be8 aliguori
                                       int w, int h)
1607 24236869 bellard
{
1608 0e1f5a0c aliguori
    if (y_position > ds_get_height(vs->ds))
1609 0e1f5a0c aliguori
        y_position = ds_get_height(vs->ds);
1610 0e1f5a0c aliguori
    if (y_position + h >= ds_get_height(vs->ds))
1611 0e1f5a0c aliguori
        h = ds_get_height(vs->ds) - y_position;
1612 cf2d385c ths
1613 24236869 bellard
    int i;
1614 24236869 bellard
    vs->need_update = 1;
1615 24236869 bellard
    if (!incremental) {
1616 24cf0a6e Gerd Hoffmann
        vs->force_update = 1;
1617 28a76be8 aliguori
        for (i = 0; i < h; i++) {
1618 1fc62412 Stefano Stabellini
            vnc_set_bits(vs->dirty[y_position + i],
1619 0e1f5a0c aliguori
                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1620 28a76be8 aliguori
        }
1621 24236869 bellard
    }
1622 24236869 bellard
}
1623 24236869 bellard
1624 9ca313aa aliguori
static void send_ext_key_event_ack(VncState *vs)
1625 9ca313aa aliguori
{
1626 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1627 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1628 9ca313aa aliguori
    vnc_write_u16(vs, 1);
1629 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1630 29fa4ed9 aliguori
                           VNC_ENCODING_EXT_KEY_EVENT);
1631 9ca313aa aliguori
    vnc_flush(vs);
1632 9ca313aa aliguori
}
1633 9ca313aa aliguori
1634 429a8ed3 malc
static void send_ext_audio_ack(VncState *vs)
1635 429a8ed3 malc
{
1636 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1637 429a8ed3 malc
    vnc_write_u8(vs, 0);
1638 429a8ed3 malc
    vnc_write_u16(vs, 1);
1639 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
1640 29fa4ed9 aliguori
                           VNC_ENCODING_AUDIO);
1641 429a8ed3 malc
    vnc_flush(vs);
1642 429a8ed3 malc
}
1643 429a8ed3 malc
1644 24236869 bellard
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1645 24236869 bellard
{
1646 24236869 bellard
    int i;
1647 29fa4ed9 aliguori
    unsigned int enc = 0;
1648 24236869 bellard
1649 29fa4ed9 aliguori
    vs->features = 0;
1650 a9f20d31 Corentin Chary
    vs->vnc_encoding = 0;
1651 fb437313 aliguori
    vs->tight_compression = 9;
1652 fb437313 aliguori
    vs->tight_quality = 9;
1653 564c337e bellard
    vs->absolute = -1;
1654 24236869 bellard
1655 8a0f0d0c Corentin Chary
    /*
1656 8a0f0d0c Corentin Chary
     * Start from the end because the encodings are sent in order of preference.
1657 8a0f0d0c Corentin Chary
     * This way the prefered encoding (first encoding defined in the array)
1658 8a0f0d0c Corentin Chary
     * will be set at the end of the loop.
1659 8a0f0d0c Corentin Chary
     */
1660 24236869 bellard
    for (i = n_encodings - 1; i >= 0; i--) {
1661 29fa4ed9 aliguori
        enc = encodings[i];
1662 29fa4ed9 aliguori
        switch (enc) {
1663 29fa4ed9 aliguori
        case VNC_ENCODING_RAW:
1664 a9f20d31 Corentin Chary
            vs->vnc_encoding = enc;
1665 29fa4ed9 aliguori
            break;
1666 29fa4ed9 aliguori
        case VNC_ENCODING_COPYRECT:
1667 753b4053 aliguori
            vs->features |= VNC_FEATURE_COPYRECT_MASK;
1668 29fa4ed9 aliguori
            break;
1669 29fa4ed9 aliguori
        case VNC_ENCODING_HEXTILE:
1670 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_HEXTILE_MASK;
1671 a9f20d31 Corentin Chary
            vs->vnc_encoding = enc;
1672 29fa4ed9 aliguori
            break;
1673 059cef40 aliguori
        case VNC_ENCODING_ZLIB:
1674 059cef40 aliguori
            vs->features |= VNC_FEATURE_ZLIB_MASK;
1675 a9f20d31 Corentin Chary
            vs->vnc_encoding = enc;
1676 059cef40 aliguori
            break;
1677 29fa4ed9 aliguori
        case VNC_ENCODING_DESKTOPRESIZE:
1678 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_RESIZE_MASK;
1679 29fa4ed9 aliguori
            break;
1680 29fa4ed9 aliguori
        case VNC_ENCODING_POINTER_TYPE_CHANGE:
1681 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
1682 29fa4ed9 aliguori
            break;
1683 d467b679 Gerd Hoffmann
        case VNC_ENCODING_RICH_CURSOR:
1684 d467b679 Gerd Hoffmann
            vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
1685 d467b679 Gerd Hoffmann
            break;
1686 29fa4ed9 aliguori
        case VNC_ENCODING_EXT_KEY_EVENT:
1687 9ca313aa aliguori
            send_ext_key_event_ack(vs);
1688 9ca313aa aliguori
            break;
1689 29fa4ed9 aliguori
        case VNC_ENCODING_AUDIO:
1690 429a8ed3 malc
            send_ext_audio_ack(vs);
1691 429a8ed3 malc
            break;
1692 29fa4ed9 aliguori
        case VNC_ENCODING_WMVi:
1693 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_WMVI_MASK;
1694 ca4cca4d aliguori
            break;
1695 fb437313 aliguori
        case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
1696 fb437313 aliguori
            vs->tight_compression = (enc & 0x0F);
1697 fb437313 aliguori
            break;
1698 fb437313 aliguori
        case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
1699 fb437313 aliguori
            vs->tight_quality = (enc & 0x0F);
1700 fb437313 aliguori
            break;
1701 29fa4ed9 aliguori
        default:
1702 29fa4ed9 aliguori
            VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
1703 29fa4ed9 aliguori
            break;
1704 29fa4ed9 aliguori
        }
1705 24236869 bellard
    }
1706 0684bf1b Anthony Liguori
    check_pointer_type_change(&vs->mouse_mode_notifier);
1707 24236869 bellard
}
1708 24236869 bellard
1709 6cec5487 aliguori
static void set_pixel_conversion(VncState *vs)
1710 6cec5487 aliguori
{
1711 6cec5487 aliguori
    if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
1712 6cec5487 aliguori
        (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && 
1713 6cec5487 aliguori
        !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
1714 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_copy;
1715 70a4568f Corentin Chary
        vnc_hextile_set_pixel_conversion(vs, 0);
1716 6cec5487 aliguori
    } else {
1717 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_generic;
1718 70a4568f Corentin Chary
        vnc_hextile_set_pixel_conversion(vs, 1);
1719 6cec5487 aliguori
    }
1720 6cec5487 aliguori
}
1721 6cec5487 aliguori
1722 24236869 bellard
static void set_pixel_format(VncState *vs,
1723 28a76be8 aliguori
                             int bits_per_pixel, int depth,
1724 28a76be8 aliguori
                             int big_endian_flag, int true_color_flag,
1725 28a76be8 aliguori
                             int red_max, int green_max, int blue_max,
1726 28a76be8 aliguori
                             int red_shift, int green_shift, int blue_shift)
1727 24236869 bellard
{
1728 3512779a bellard
    if (!true_color_flag) {
1729 28a76be8 aliguori
        vnc_client_error(vs);
1730 3512779a bellard
        return;
1731 3512779a bellard
    }
1732 24236869 bellard
1733 1fc62412 Stefano Stabellini
    vs->clientds = *(vs->vd->guest.ds);
1734 6cec5487 aliguori
    vs->clientds.pf.rmax = red_max;
1735 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.rbits, red_max);
1736 6cec5487 aliguori
    vs->clientds.pf.rshift = red_shift;
1737 6cec5487 aliguori
    vs->clientds.pf.rmask = red_max << red_shift;
1738 6cec5487 aliguori
    vs->clientds.pf.gmax = green_max;
1739 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.gbits, green_max);
1740 6cec5487 aliguori
    vs->clientds.pf.gshift = green_shift;
1741 6cec5487 aliguori
    vs->clientds.pf.gmask = green_max << green_shift;
1742 6cec5487 aliguori
    vs->clientds.pf.bmax = blue_max;
1743 90a1e3c0 aliguori
    count_bits(vs->clientds.pf.bbits, blue_max);
1744 6cec5487 aliguori
    vs->clientds.pf.bshift = blue_shift;
1745 6cec5487 aliguori
    vs->clientds.pf.bmask = blue_max << blue_shift;
1746 6cec5487 aliguori
    vs->clientds.pf.bits_per_pixel = bits_per_pixel;
1747 6cec5487 aliguori
    vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8;
1748 6cec5487 aliguori
    vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
1749 6cec5487 aliguori
    vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00;
1750 6cec5487 aliguori
1751 6cec5487 aliguori
    set_pixel_conversion(vs);
1752 24236869 bellard
1753 24236869 bellard
    vga_hw_invalidate();
1754 24236869 bellard
    vga_hw_update();
1755 24236869 bellard
}
1756 24236869 bellard
1757 ca4cca4d aliguori
static void pixel_format_message (VncState *vs) {
1758 ca4cca4d aliguori
    char pad[3] = { 0, 0, 0 };
1759 ca4cca4d aliguori
1760 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */
1761 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */
1762 ca4cca4d aliguori
1763 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
1764 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* big-endian-flag */
1765 ca4cca4d aliguori
#else
1766 ca4cca4d aliguori
    vnc_write_u8(vs, 0);             /* big-endian-flag */
1767 ca4cca4d aliguori
#endif
1768 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* true-color-flag */
1769 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.rmax);     /* red-max */
1770 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.gmax);     /* green-max */
1771 6cec5487 aliguori
    vnc_write_u16(vs, vs->ds->surface->pf.bmax);     /* blue-max */
1772 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.rshift);    /* red-shift */
1773 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.gshift);    /* green-shift */
1774 6cec5487 aliguori
    vnc_write_u8(vs, vs->ds->surface->pf.bshift);    /* blue-shift */
1775 70a4568f Corentin Chary
1776 70a4568f Corentin Chary
    vnc_hextile_set_pixel_conversion(vs, 0);
1777 70a4568f Corentin Chary
1778 6cec5487 aliguori
    vs->clientds = *(vs->ds->surface);
1779 3cded540 aurel32
    vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
1780 ca4cca4d aliguori
    vs->write_pixels = vnc_write_pixels_copy;
1781 ca4cca4d aliguori
1782 ca4cca4d aliguori
    vnc_write(vs, pad, 3);           /* padding */
1783 ca4cca4d aliguori
}
1784 ca4cca4d aliguori
1785 7d957bd8 aliguori
static void vnc_dpy_setdata(DisplayState *ds)
1786 7d957bd8 aliguori
{
1787 7d957bd8 aliguori
    /* We don't have to do anything */
1788 7d957bd8 aliguori
}
1789 7d957bd8 aliguori
1790 753b4053 aliguori
static void vnc_colordepth(VncState *vs)
1791 7eac3a87 aliguori
{
1792 753b4053 aliguori
    if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
1793 ca4cca4d aliguori
        /* Sending a WMVi message to notify the client*/
1794 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1795 ca4cca4d aliguori
        vnc_write_u8(vs, 0);
1796 ca4cca4d aliguori
        vnc_write_u16(vs, 1); /* number of rects */
1797 753b4053 aliguori
        vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), 
1798 753b4053 aliguori
                               ds_get_height(vs->ds), VNC_ENCODING_WMVi);
1799 ca4cca4d aliguori
        pixel_format_message(vs);
1800 ca4cca4d aliguori
        vnc_flush(vs);
1801 7eac3a87 aliguori
    } else {
1802 6cec5487 aliguori
        set_pixel_conversion(vs);
1803 7eac3a87 aliguori
    }
1804 7eac3a87 aliguori
}
1805 7eac3a87 aliguori
1806 60fe76f3 ths
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1807 24236869 bellard
{
1808 24236869 bellard
    int i;
1809 24236869 bellard
    uint16_t limit;
1810 2430ffe4 Stefano Stabellini
    VncDisplay *vd = vs->vd;
1811 2430ffe4 Stefano Stabellini
1812 2430ffe4 Stefano Stabellini
    if (data[0] > 3) {
1813 2430ffe4 Stefano Stabellini
        vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
1814 2430ffe4 Stefano Stabellini
        if (!qemu_timer_expired(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval))
1815 2430ffe4 Stefano Stabellini
            qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
1816 2430ffe4 Stefano Stabellini
    }
1817 24236869 bellard
1818 24236869 bellard
    switch (data[0]) {
1819 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_SET_PIXEL_FORMAT:
1820 28a76be8 aliguori
        if (len == 1)
1821 28a76be8 aliguori
            return 20;
1822 28a76be8 aliguori
1823 28a76be8 aliguori
        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1824 28a76be8 aliguori
                         read_u8(data, 6), read_u8(data, 7),
1825 28a76be8 aliguori
                         read_u16(data, 8), read_u16(data, 10),
1826 28a76be8 aliguori
                         read_u16(data, 12), read_u8(data, 14),
1827 28a76be8 aliguori
                         read_u8(data, 15), read_u8(data, 16));
1828 28a76be8 aliguori
        break;
1829 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_SET_ENCODINGS:
1830 28a76be8 aliguori
        if (len == 1)
1831 28a76be8 aliguori
            return 4;
1832 24236869 bellard
1833 28a76be8 aliguori
        if (len == 4) {
1834 69dd5c9f aliguori
            limit = read_u16(data, 2);
1835 69dd5c9f aliguori
            if (limit > 0)
1836 69dd5c9f aliguori
                return 4 + (limit * 4);
1837 69dd5c9f aliguori
        } else
1838 69dd5c9f aliguori
            limit = read_u16(data, 2);
1839 24236869 bellard
1840 28a76be8 aliguori
        for (i = 0; i < limit; i++) {
1841 28a76be8 aliguori
            int32_t val = read_s32(data, 4 + (i * 4));
1842 28a76be8 aliguori
            memcpy(data + 4 + (i * 4), &val, sizeof(val));
1843 28a76be8 aliguori
        }
1844 24236869 bellard
1845 28a76be8 aliguori
        set_encodings(vs, (int32_t *)(data + 4), limit);
1846 28a76be8 aliguori
        break;
1847 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST:
1848 28a76be8 aliguori
        if (len == 1)
1849 28a76be8 aliguori
            return 10;
1850 24236869 bellard
1851 28a76be8 aliguori
        framebuffer_update_request(vs,
1852 28a76be8 aliguori
                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1853 28a76be8 aliguori
                                   read_u16(data, 6), read_u16(data, 8));
1854 28a76be8 aliguori
        break;
1855 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_KEY_EVENT:
1856 28a76be8 aliguori
        if (len == 1)
1857 28a76be8 aliguori
            return 8;
1858 24236869 bellard
1859 28a76be8 aliguori
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
1860 28a76be8 aliguori
        break;
1861 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_POINTER_EVENT:
1862 28a76be8 aliguori
        if (len == 1)
1863 28a76be8 aliguori
            return 6;
1864 24236869 bellard
1865 28a76be8 aliguori
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1866 28a76be8 aliguori
        break;
1867 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_CUT_TEXT:
1868 28a76be8 aliguori
        if (len == 1)
1869 28a76be8 aliguori
            return 8;
1870 24236869 bellard
1871 28a76be8 aliguori
        if (len == 8) {
1872 baa7666c ths
            uint32_t dlen = read_u32(data, 4);
1873 baa7666c ths
            if (dlen > 0)
1874 baa7666c ths
                return 8 + dlen;
1875 baa7666c ths
        }
1876 24236869 bellard
1877 28a76be8 aliguori
        client_cut_text(vs, read_u32(data, 4), data + 8);
1878 28a76be8 aliguori
        break;
1879 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_QEMU:
1880 9ca313aa aliguori
        if (len == 1)
1881 9ca313aa aliguori
            return 2;
1882 9ca313aa aliguori
1883 9ca313aa aliguori
        switch (read_u8(data, 1)) {
1884 46a183da Daniel P. Berrange
        case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT:
1885 9ca313aa aliguori
            if (len == 2)
1886 9ca313aa aliguori
                return 12;
1887 9ca313aa aliguori
1888 9ca313aa aliguori
            ext_key_event(vs, read_u16(data, 2),
1889 9ca313aa aliguori
                          read_u32(data, 4), read_u32(data, 8));
1890 9ca313aa aliguori
            break;
1891 46a183da Daniel P. Berrange
        case VNC_MSG_CLIENT_QEMU_AUDIO:
1892 429a8ed3 malc
            if (len == 2)
1893 429a8ed3 malc
                return 4;
1894 429a8ed3 malc
1895 429a8ed3 malc
            switch (read_u16 (data, 2)) {
1896 46a183da Daniel P. Berrange
            case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:
1897 429a8ed3 malc
                audio_add(vs);
1898 429a8ed3 malc
                break;
1899 46a183da Daniel P. Berrange
            case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:
1900 429a8ed3 malc
                audio_del(vs);
1901 429a8ed3 malc
                break;
1902 46a183da Daniel P. Berrange
            case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:
1903 429a8ed3 malc
                if (len == 4)
1904 429a8ed3 malc
                    return 10;
1905 429a8ed3 malc
                switch (read_u8(data, 4)) {
1906 429a8ed3 malc
                case 0: vs->as.fmt = AUD_FMT_U8; break;
1907 429a8ed3 malc
                case 1: vs->as.fmt = AUD_FMT_S8; break;
1908 429a8ed3 malc
                case 2: vs->as.fmt = AUD_FMT_U16; break;
1909 429a8ed3 malc
                case 3: vs->as.fmt = AUD_FMT_S16; break;
1910 429a8ed3 malc
                case 4: vs->as.fmt = AUD_FMT_U32; break;
1911 429a8ed3 malc
                case 5: vs->as.fmt = AUD_FMT_S32; break;
1912 429a8ed3 malc
                default:
1913 429a8ed3 malc
                    printf("Invalid audio format %d\n", read_u8(data, 4));
1914 429a8ed3 malc
                    vnc_client_error(vs);
1915 429a8ed3 malc
                    break;
1916 429a8ed3 malc
                }
1917 429a8ed3 malc
                vs->as.nchannels = read_u8(data, 5);
1918 429a8ed3 malc
                if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
1919 429a8ed3 malc
                    printf("Invalid audio channel coount %d\n",
1920 429a8ed3 malc
                           read_u8(data, 5));
1921 429a8ed3 malc
                    vnc_client_error(vs);
1922 429a8ed3 malc
                    break;
1923 429a8ed3 malc
                }
1924 429a8ed3 malc
                vs->as.freq = read_u32(data, 6);
1925 429a8ed3 malc
                break;
1926 429a8ed3 malc
            default:
1927 429a8ed3 malc
                printf ("Invalid audio message %d\n", read_u8(data, 4));
1928 429a8ed3 malc
                vnc_client_error(vs);
1929 429a8ed3 malc
                break;
1930 429a8ed3 malc
            }
1931 429a8ed3 malc
            break;
1932 429a8ed3 malc
1933 9ca313aa aliguori
        default:
1934 9ca313aa aliguori
            printf("Msg: %d\n", read_u16(data, 0));
1935 9ca313aa aliguori
            vnc_client_error(vs);
1936 9ca313aa aliguori
            break;
1937 9ca313aa aliguori
        }
1938 9ca313aa aliguori
        break;
1939 24236869 bellard
    default:
1940 28a76be8 aliguori
        printf("Msg: %d\n", data[0]);
1941 28a76be8 aliguori
        vnc_client_error(vs);
1942 28a76be8 aliguori
        break;
1943 24236869 bellard
    }
1944 5fafdf24 ths
1945 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1946 24236869 bellard
    return 0;
1947 24236869 bellard
}
1948 24236869 bellard
1949 60fe76f3 ths
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1950 24236869 bellard
{
1951 c35734b2 ths
    char buf[1024];
1952 c35734b2 ths
    int size;
1953 24236869 bellard
1954 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_width(vs->ds));
1955 0e1f5a0c aliguori
    vnc_write_u16(vs, ds_get_height(vs->ds));
1956 24236869 bellard
1957 ca4cca4d aliguori
    pixel_format_message(vs);
1958 24236869 bellard
1959 c35734b2 ths
    if (qemu_name)
1960 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
1961 c35734b2 ths
    else
1962 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU");
1963 c35734b2 ths
1964 c35734b2 ths
    vnc_write_u32(vs, size);
1965 c35734b2 ths
    vnc_write(vs, buf, size);
1966 24236869 bellard
    vnc_flush(vs);
1967 24236869 bellard
1968 4a80dba3 Luiz Capitulino
    vnc_client_cache_auth(vs);
1969 0d2ed46a Luiz Capitulino
    vnc_qmp_event(vs, QEVENT_VNC_INITIALIZED);
1970 4a80dba3 Luiz Capitulino
1971 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1972 24236869 bellard
1973 24236869 bellard
    return 0;
1974 24236869 bellard
}
1975 24236869 bellard
1976 5fb6c7a8 aliguori
void start_client_init(VncState *vs)
1977 5fb6c7a8 aliguori
{
1978 5fb6c7a8 aliguori
    vnc_read_when(vs, protocol_client_init, 1);
1979 5fb6c7a8 aliguori
}
1980 5fb6c7a8 aliguori
1981 70848515 ths
static void make_challenge(VncState *vs)
1982 70848515 ths
{
1983 70848515 ths
    int i;
1984 70848515 ths
1985 70848515 ths
    srand(time(NULL)+getpid()+getpid()*987654+rand());
1986 70848515 ths
1987 70848515 ths
    for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1988 70848515 ths
        vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1989 70848515 ths
}
1990 70848515 ths
1991 60fe76f3 ths
static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1992 70848515 ths
{
1993 60fe76f3 ths
    unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
1994 70848515 ths
    int i, j, pwlen;
1995 60fe76f3 ths
    unsigned char key[8];
1996 70848515 ths
1997 753b4053 aliguori
    if (!vs->vd->password || !vs->vd->password[0]) {
1998 28a76be8 aliguori
        VNC_DEBUG("No password configured on server");
1999 28a76be8 aliguori
        vnc_write_u32(vs, 1); /* Reject auth */
2000 28a76be8 aliguori
        if (vs->minor >= 8) {
2001 28a76be8 aliguori
            static const char err[] = "Authentication failed";
2002 28a76be8 aliguori
            vnc_write_u32(vs, sizeof(err));
2003 28a76be8 aliguori
            vnc_write(vs, err, sizeof(err));
2004 28a76be8 aliguori
        }
2005 28a76be8 aliguori
        vnc_flush(vs);
2006 28a76be8 aliguori
        vnc_client_error(vs);
2007 28a76be8 aliguori
        return 0;
2008 70848515 ths
    }
2009 70848515 ths
2010 70848515 ths
    memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
2011 70848515 ths
2012 70848515 ths
    /* Calculate the expected challenge response */
2013 753b4053 aliguori
    pwlen = strlen(vs->vd->password);
2014 70848515 ths
    for (i=0; i<sizeof(key); i++)
2015 753b4053 aliguori
        key[i] = i<pwlen ? vs->vd->password[i] : 0;
2016 70848515 ths
    deskey(key, EN0);
2017 70848515 ths
    for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
2018 70848515 ths
        des(response+j, response+j);
2019 70848515 ths
2020 70848515 ths
    /* Compare expected vs actual challenge response */
2021 70848515 ths
    if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
2022 28a76be8 aliguori
        VNC_DEBUG("Client challenge reponse did not match\n");
2023 28a76be8 aliguori
        vnc_write_u32(vs, 1); /* Reject auth */
2024 28a76be8 aliguori
        if (vs->minor >= 8) {
2025 28a76be8 aliguori
            static const char err[] = "Authentication failed";
2026 28a76be8 aliguori
            vnc_write_u32(vs, sizeof(err));
2027 28a76be8 aliguori
            vnc_write(vs, err, sizeof(err));
2028 28a76be8 aliguori
        }
2029 28a76be8 aliguori
        vnc_flush(vs);
2030 28a76be8 aliguori
        vnc_client_error(vs);
2031 70848515 ths
    } else {
2032 28a76be8 aliguori
        VNC_DEBUG("Accepting VNC challenge response\n");
2033 28a76be8 aliguori
        vnc_write_u32(vs, 0); /* Accept auth */
2034 28a76be8 aliguori
        vnc_flush(vs);
2035 70848515 ths
2036 5fb6c7a8 aliguori
        start_client_init(vs);
2037 70848515 ths
    }
2038 70848515 ths
    return 0;
2039 70848515 ths
}
2040 70848515 ths
2041 5fb6c7a8 aliguori
void start_auth_vnc(VncState *vs)
2042 70848515 ths
{
2043 70848515 ths
    make_challenge(vs);
2044 70848515 ths
    /* Send client a 'random' challenge */
2045 70848515 ths
    vnc_write(vs, vs->challenge, sizeof(vs->challenge));
2046 70848515 ths
    vnc_flush(vs);
2047 70848515 ths
2048 70848515 ths
    vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
2049 469b15c6 ths
}
2050 469b15c6 ths
2051 469b15c6 ths
2052 60fe76f3 ths
static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2053 70848515 ths
{
2054 70848515 ths
    /* We only advertise 1 auth scheme at a time, so client
2055 70848515 ths
     * must pick the one we sent. Verify this */
2056 753b4053 aliguori
    if (data[0] != vs->vd->auth) { /* Reject auth */
2057 1263b7d6 aliguori
       VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
2058 70848515 ths
       vnc_write_u32(vs, 1);
2059 70848515 ths
       if (vs->minor >= 8) {
2060 70848515 ths
           static const char err[] = "Authentication failed";
2061 70848515 ths
           vnc_write_u32(vs, sizeof(err));
2062 70848515 ths
           vnc_write(vs, err, sizeof(err));
2063 70848515 ths
       }
2064 70848515 ths
       vnc_client_error(vs);
2065 70848515 ths
    } else { /* Accept requested auth */
2066 70848515 ths
       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2067 753b4053 aliguori
       switch (vs->vd->auth) {
2068 70848515 ths
       case VNC_AUTH_NONE:
2069 70848515 ths
           VNC_DEBUG("Accept auth none\n");
2070 a26c97ad balrog
           if (vs->minor >= 8) {
2071 a26c97ad balrog
               vnc_write_u32(vs, 0); /* Accept auth completion */
2072 a26c97ad balrog
               vnc_flush(vs);
2073 a26c97ad balrog
           }
2074 5fb6c7a8 aliguori
           start_client_init(vs);
2075 70848515 ths
           break;
2076 70848515 ths
2077 70848515 ths
       case VNC_AUTH_VNC:
2078 70848515 ths
           VNC_DEBUG("Start VNC auth\n");
2079 5fb6c7a8 aliguori
           start_auth_vnc(vs);
2080 5fb6c7a8 aliguori
           break;
2081 70848515 ths
2082 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2083 8d5d2d4c ths
       case VNC_AUTH_VENCRYPT:
2084 8d5d2d4c ths
           VNC_DEBUG("Accept VeNCrypt auth\n");;
2085 5fb6c7a8 aliguori
           start_auth_vencrypt(vs);
2086 5fb6c7a8 aliguori
           break;
2087 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2088 8d5d2d4c ths
2089 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2090 2f9606b3 aliguori
       case VNC_AUTH_SASL:
2091 2f9606b3 aliguori
           VNC_DEBUG("Accept SASL auth\n");
2092 2f9606b3 aliguori
           start_auth_sasl(vs);
2093 2f9606b3 aliguori
           break;
2094 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
2095 2f9606b3 aliguori
2096 70848515 ths
       default: /* Should not be possible, but just in case */
2097 1263b7d6 aliguori
           VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth);
2098 70848515 ths
           vnc_write_u8(vs, 1);
2099 70848515 ths
           if (vs->minor >= 8) {
2100 70848515 ths
               static const char err[] = "Authentication failed";
2101 70848515 ths
               vnc_write_u32(vs, sizeof(err));
2102 70848515 ths
               vnc_write(vs, err, sizeof(err));
2103 70848515 ths
           }
2104 70848515 ths
           vnc_client_error(vs);
2105 70848515 ths
       }
2106 70848515 ths
    }
2107 70848515 ths
    return 0;
2108 70848515 ths
}
2109 70848515 ths
2110 60fe76f3 ths
static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2111 24236869 bellard
{
2112 24236869 bellard
    char local[13];
2113 24236869 bellard
2114 24236869 bellard
    memcpy(local, version, 12);
2115 24236869 bellard
    local[12] = 0;
2116 24236869 bellard
2117 70848515 ths
    if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2118 28a76be8 aliguori
        VNC_DEBUG("Malformed protocol version %s\n", local);
2119 28a76be8 aliguori
        vnc_client_error(vs);
2120 28a76be8 aliguori
        return 0;
2121 24236869 bellard
    }
2122 70848515 ths
    VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2123 70848515 ths
    if (vs->major != 3 ||
2124 28a76be8 aliguori
        (vs->minor != 3 &&
2125 28a76be8 aliguori
         vs->minor != 4 &&
2126 28a76be8 aliguori
         vs->minor != 5 &&
2127 28a76be8 aliguori
         vs->minor != 7 &&
2128 28a76be8 aliguori
         vs->minor != 8)) {
2129 28a76be8 aliguori
        VNC_DEBUG("Unsupported client version\n");
2130 28a76be8 aliguori
        vnc_write_u32(vs, VNC_AUTH_INVALID);
2131 28a76be8 aliguori
        vnc_flush(vs);
2132 28a76be8 aliguori
        vnc_client_error(vs);
2133 28a76be8 aliguori
        return 0;
2134 70848515 ths
    }
2135 b0566f4f ths
    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2136 70848515 ths
     * as equivalent to v3.3 by servers
2137 70848515 ths
     */
2138 b0566f4f ths
    if (vs->minor == 4 || vs->minor == 5)
2139 28a76be8 aliguori
        vs->minor = 3;
2140 70848515 ths
2141 70848515 ths
    if (vs->minor == 3) {
2142 28a76be8 aliguori
        if (vs->vd->auth == VNC_AUTH_NONE) {
2143 70848515 ths
            VNC_DEBUG("Tell client auth none\n");
2144 753b4053 aliguori
            vnc_write_u32(vs, vs->vd->auth);
2145 70848515 ths
            vnc_flush(vs);
2146 28a76be8 aliguori
            start_client_init(vs);
2147 753b4053 aliguori
       } else if (vs->vd->auth == VNC_AUTH_VNC) {
2148 70848515 ths
            VNC_DEBUG("Tell client VNC auth\n");
2149 753b4053 aliguori
            vnc_write_u32(vs, vs->vd->auth);
2150 70848515 ths
            vnc_flush(vs);
2151 70848515 ths
            start_auth_vnc(vs);
2152 70848515 ths
       } else {
2153 753b4053 aliguori
            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth);
2154 70848515 ths
            vnc_write_u32(vs, VNC_AUTH_INVALID);
2155 70848515 ths
            vnc_flush(vs);
2156 70848515 ths
            vnc_client_error(vs);
2157 70848515 ths
       }
2158 70848515 ths
    } else {
2159 28a76be8 aliguori
        VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth);
2160 28a76be8 aliguori
        vnc_write_u8(vs, 1); /* num auth */
2161 28a76be8 aliguori
        vnc_write_u8(vs, vs->vd->auth);
2162 28a76be8 aliguori
        vnc_read_when(vs, protocol_client_auth, 1);
2163 28a76be8 aliguori
        vnc_flush(vs);
2164 70848515 ths
    }
2165 24236869 bellard
2166 24236869 bellard
    return 0;
2167 24236869 bellard
}
2168 24236869 bellard
2169 1fc62412 Stefano Stabellini
static int vnc_refresh_server_surface(VncDisplay *vd)
2170 1fc62412 Stefano Stabellini
{
2171 1fc62412 Stefano Stabellini
    int y;
2172 1fc62412 Stefano Stabellini
    uint8_t *guest_row;
2173 1fc62412 Stefano Stabellini
    uint8_t *server_row;
2174 1fc62412 Stefano Stabellini
    int cmp_bytes;
2175 1fc62412 Stefano Stabellini
    uint32_t width_mask[VNC_DIRTY_WORDS];
2176 41b4bef6 Amit Shah
    VncState *vs;
2177 1fc62412 Stefano Stabellini
    int has_dirty = 0;
2178 1fc62412 Stefano Stabellini
2179 1fc62412 Stefano Stabellini
    /*
2180 1fc62412 Stefano Stabellini
     * Walk through the guest dirty map.
2181 1fc62412 Stefano Stabellini
     * Check and copy modified bits from guest to server surface.
2182 1fc62412 Stefano Stabellini
     * Update server dirty map.
2183 1fc62412 Stefano Stabellini
     */
2184 1fc62412 Stefano Stabellini
    vnc_set_bits(width_mask, (ds_get_width(vd->ds) / 16), VNC_DIRTY_WORDS);
2185 1fc62412 Stefano Stabellini
    cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
2186 1fc62412 Stefano Stabellini
    guest_row  = vd->guest.ds->data;
2187 1fc62412 Stefano Stabellini
    server_row = vd->server->data;
2188 1fc62412 Stefano Stabellini
    for (y = 0; y < vd->guest.ds->height; y++) {
2189 1fc62412 Stefano Stabellini
        if (vnc_and_bits(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
2190 1fc62412 Stefano Stabellini
            int x;
2191 1fc62412 Stefano Stabellini
            uint8_t *guest_ptr;
2192 1fc62412 Stefano Stabellini
            uint8_t *server_ptr;
2193 1fc62412 Stefano Stabellini
2194 1fc62412 Stefano Stabellini
            guest_ptr  = guest_row;
2195 1fc62412 Stefano Stabellini
            server_ptr = server_row;
2196 1fc62412 Stefano Stabellini
2197 1fc62412 Stefano Stabellini
            for (x = 0; x < vd->guest.ds->width;
2198 1fc62412 Stefano Stabellini
                    x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
2199 1fc62412 Stefano Stabellini
                if (!vnc_get_bit(vd->guest.dirty[y], (x / 16)))
2200 1fc62412 Stefano Stabellini
                    continue;
2201 1fc62412 Stefano Stabellini
                vnc_clear_bit(vd->guest.dirty[y], (x / 16));
2202 1fc62412 Stefano Stabellini
                if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
2203 1fc62412 Stefano Stabellini
                    continue;
2204 1fc62412 Stefano Stabellini
                memcpy(server_ptr, guest_ptr, cmp_bytes);
2205 41b4bef6 Amit Shah
                QTAILQ_FOREACH(vs, &vd->clients, next) {
2206 1fc62412 Stefano Stabellini
                    vnc_set_bit(vs->dirty[y], (x / 16));
2207 1fc62412 Stefano Stabellini
                }
2208 1fc62412 Stefano Stabellini
                has_dirty++;
2209 1fc62412 Stefano Stabellini
            }
2210 1fc62412 Stefano Stabellini
        }
2211 1fc62412 Stefano Stabellini
        guest_row  += ds_get_linesize(vd->ds);
2212 1fc62412 Stefano Stabellini
        server_row += ds_get_linesize(vd->ds);
2213 1fc62412 Stefano Stabellini
    }
2214 1fc62412 Stefano Stabellini
    return has_dirty;
2215 1fc62412 Stefano Stabellini
}
2216 1fc62412 Stefano Stabellini
2217 703bc68f Stefano Stabellini
static void vnc_refresh(void *opaque)
2218 703bc68f Stefano Stabellini
{
2219 703bc68f Stefano Stabellini
    VncDisplay *vd = opaque;
2220 41b4bef6 Amit Shah
    VncState *vs, *vn;
2221 41b4bef6 Amit Shah
    int has_dirty, rects = 0;
2222 703bc68f Stefano Stabellini
2223 703bc68f Stefano Stabellini
    vga_hw_update();
2224 703bc68f Stefano Stabellini
2225 1fc62412 Stefano Stabellini
    has_dirty = vnc_refresh_server_surface(vd);
2226 1fc62412 Stefano Stabellini
2227 41b4bef6 Amit Shah
    QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
2228 2430ffe4 Stefano Stabellini
        rects += vnc_update_client(vs, has_dirty);
2229 6185c578 Stefano Stabellini
        /* vs might be free()ed here */
2230 703bc68f Stefano Stabellini
    }
2231 83755c17 Stefano Stabellini
    /* vd->timer could be NULL now if the last client disconnected,
2232 83755c17 Stefano Stabellini
     * in this case don't update the timer */
2233 83755c17 Stefano Stabellini
    if (vd->timer == NULL)
2234 83755c17 Stefano Stabellini
        return;
2235 703bc68f Stefano Stabellini
2236 2430ffe4 Stefano Stabellini
    if (has_dirty && rects) {
2237 2430ffe4 Stefano Stabellini
        vd->timer_interval /= 2;
2238 2430ffe4 Stefano Stabellini
        if (vd->timer_interval < VNC_REFRESH_INTERVAL_BASE)
2239 2430ffe4 Stefano Stabellini
            vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
2240 2430ffe4 Stefano Stabellini
    } else {
2241 2430ffe4 Stefano Stabellini
        vd->timer_interval += VNC_REFRESH_INTERVAL_INC;
2242 2430ffe4 Stefano Stabellini
        if (vd->timer_interval > VNC_REFRESH_INTERVAL_MAX)
2243 2430ffe4 Stefano Stabellini
            vd->timer_interval = VNC_REFRESH_INTERVAL_MAX;
2244 2430ffe4 Stefano Stabellini
    }
2245 2430ffe4 Stefano Stabellini
    qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + vd->timer_interval);
2246 703bc68f Stefano Stabellini
}
2247 703bc68f Stefano Stabellini
2248 703bc68f Stefano Stabellini
static void vnc_init_timer(VncDisplay *vd)
2249 703bc68f Stefano Stabellini
{
2250 2430ffe4 Stefano Stabellini
    vd->timer_interval = VNC_REFRESH_INTERVAL_BASE;
2251 41b4bef6 Amit Shah
    if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) {
2252 703bc68f Stefano Stabellini
        vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
2253 1fc62412 Stefano Stabellini
        vnc_refresh(vd);
2254 703bc68f Stefano Stabellini
    }
2255 703bc68f Stefano Stabellini
}
2256 703bc68f Stefano Stabellini
2257 703bc68f Stefano Stabellini
static void vnc_remove_timer(VncDisplay *vd)
2258 703bc68f Stefano Stabellini
{
2259 41b4bef6 Amit Shah
    if (vd->timer != NULL && QTAILQ_EMPTY(&vd->clients)) {
2260 703bc68f Stefano Stabellini
        qemu_del_timer(vd->timer);
2261 703bc68f Stefano Stabellini
        qemu_free_timer(vd->timer);
2262 703bc68f Stefano Stabellini
        vd->timer = NULL;
2263 703bc68f Stefano Stabellini
    }
2264 703bc68f Stefano Stabellini
}
2265 703bc68f Stefano Stabellini
2266 753b4053 aliguori
static void vnc_connect(VncDisplay *vd, int csock)
2267 3aa3eea3 balrog
{
2268 753b4053 aliguori
    VncState *vs = qemu_mallocz(sizeof(VncState));
2269 753b4053 aliguori
    vs->csock = csock;
2270 753b4053 aliguori
2271 753b4053 aliguori
    VNC_DEBUG("New client on socket %d\n", csock);
2272 7d957bd8 aliguori
    dcl->idle = 0;
2273 3aa3eea3 balrog
    socket_set_nonblock(vs->csock);
2274 3aa3eea3 balrog
    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2275 753b4053 aliguori
2276 4a80dba3 Luiz Capitulino
    vnc_client_cache_addr(vs);
2277 586153d9 Luiz Capitulino
    vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
2278 4a80dba3 Luiz Capitulino
2279 753b4053 aliguori
    vs->vd = vd;
2280 753b4053 aliguori
    vs->ds = vd->ds;
2281 753b4053 aliguori
    vs->last_x = -1;
2282 753b4053 aliguori
    vs->last_y = -1;
2283 753b4053 aliguori
2284 753b4053 aliguori
    vs->as.freq = 44100;
2285 753b4053 aliguori
    vs->as.nchannels = 2;
2286 753b4053 aliguori
    vs->as.fmt = AUD_FMT_S16;
2287 753b4053 aliguori
    vs->as.endianness = 0;
2288 753b4053 aliguori
2289 41b4bef6 Amit Shah
    QTAILQ_INSERT_HEAD(&vd->clients, vs, next);
2290 1fc62412 Stefano Stabellini
2291 1fc62412 Stefano Stabellini
    vga_hw_update();
2292 1fc62412 Stefano Stabellini
2293 3aa3eea3 balrog
    vnc_write(vs, "RFB 003.008\n", 12);
2294 3aa3eea3 balrog
    vnc_flush(vs);
2295 3aa3eea3 balrog
    vnc_read_when(vs, protocol_version, 12);
2296 53762ddb malc
    reset_keys(vs);
2297 3a0558b5 Gerd Hoffmann
    if (vs->vd->lock_key_sync)
2298 3a0558b5 Gerd Hoffmann
        vs->led = qemu_add_led_event_handler(kbd_leds, vs);
2299 753b4053 aliguori
2300 37c34d9d Anthony Liguori
    vs->mouse_mode_notifier.notify = check_pointer_type_change;
2301 37c34d9d Anthony Liguori
    qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
2302 37c34d9d Anthony Liguori
2303 703bc68f Stefano Stabellini
    vnc_init_timer(vd);
2304 1fc62412 Stefano Stabellini
2305 198a0039 Gerd Hoffmann
    /* vs might be free()ed here */
2306 3aa3eea3 balrog
}
2307 3aa3eea3 balrog
2308 24236869 bellard
static void vnc_listen_read(void *opaque)
2309 24236869 bellard
{
2310 753b4053 aliguori
    VncDisplay *vs = opaque;
2311 24236869 bellard
    struct sockaddr_in addr;
2312 24236869 bellard
    socklen_t addrlen = sizeof(addr);
2313 24236869 bellard
2314 9f60ad50 balrog
    /* Catch-up */
2315 9f60ad50 balrog
    vga_hw_update();
2316 9f60ad50 balrog
2317 40ff6d7e Kevin Wolf
    int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2318 753b4053 aliguori
    if (csock != -1) {
2319 753b4053 aliguori
        vnc_connect(vs, csock);
2320 24236869 bellard
    }
2321 24236869 bellard
}
2322 24236869 bellard
2323 71cab5ca ths
void vnc_display_init(DisplayState *ds)
2324 24236869 bellard
{
2325 afd32160 Stefan Weil
    VncDisplay *vs = qemu_mallocz(sizeof(*vs));
2326 24236869 bellard
2327 7d957bd8 aliguori
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2328 24236869 bellard
2329 24236869 bellard
    ds->opaque = vs;
2330 7d957bd8 aliguori
    dcl->idle = 1;
2331 753b4053 aliguori
    vnc_display = vs;
2332 24236869 bellard
2333 24236869 bellard
    vs->lsock = -1;
2334 24236869 bellard
2335 24236869 bellard
    vs->ds = ds;
2336 41b4bef6 Amit Shah
    QTAILQ_INIT(&vs->clients);
2337 24236869 bellard
2338 9ca313aa aliguori
    if (keyboard_layout)
2339 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
2340 9ca313aa aliguori
    else
2341 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
2342 24236869 bellard
2343 24236869 bellard
    if (!vs->kbd_layout)
2344 28a76be8 aliguori
        exit(1);
2345 24236869 bellard
2346 753b4053 aliguori
    dcl->dpy_copy = vnc_dpy_copy;
2347 7d957bd8 aliguori
    dcl->dpy_update = vnc_dpy_update;
2348 7d957bd8 aliguori
    dcl->dpy_resize = vnc_dpy_resize;
2349 7d957bd8 aliguori
    dcl->dpy_setdata = vnc_dpy_setdata;
2350 7d957bd8 aliguori
    register_displaychangelistener(ds, dcl);
2351 d467b679 Gerd Hoffmann
    ds->mouse_set = vnc_mouse_set;
2352 d467b679 Gerd Hoffmann
    ds->cursor_define = vnc_dpy_cursor_define;
2353 71cab5ca ths
}
2354 71cab5ca ths
2355 6f43024c ths
2356 71cab5ca ths
void vnc_display_close(DisplayState *ds)
2357 71cab5ca ths
{
2358 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2359 71cab5ca ths
2360 452b4d88 aliguori
    if (!vs)
2361 452b4d88 aliguori
        return;
2362 71cab5ca ths
    if (vs->display) {
2363 28a76be8 aliguori
        qemu_free(vs->display);
2364 28a76be8 aliguori
        vs->display = NULL;
2365 71cab5ca ths
    }
2366 71cab5ca ths
    if (vs->lsock != -1) {
2367 28a76be8 aliguori
        qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2368 28a76be8 aliguori
        close(vs->lsock);
2369 28a76be8 aliguori
        vs->lsock = -1;
2370 71cab5ca ths
    }
2371 70848515 ths
    vs->auth = VNC_AUTH_INVALID;
2372 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2373 8d5d2d4c ths
    vs->subauth = VNC_AUTH_INVALID;
2374 5fb6c7a8 aliguori
    vs->tls.x509verify = 0;
2375 8d5d2d4c ths
#endif
2376 70848515 ths
}
2377 70848515 ths
2378 70848515 ths
int vnc_display_password(DisplayState *ds, const char *password)
2379 70848515 ths
{
2380 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2381 70848515 ths
2382 7ef92331 Zachary Amsden
    if (!vs) {
2383 7ef92331 Zachary Amsden
        return -1;
2384 7ef92331 Zachary Amsden
    }
2385 7ef92331 Zachary Amsden
2386 70848515 ths
    if (vs->password) {
2387 28a76be8 aliguori
        qemu_free(vs->password);
2388 28a76be8 aliguori
        vs->password = NULL;
2389 70848515 ths
    }
2390 70848515 ths
    if (password && password[0]) {
2391 28a76be8 aliguori
        if (!(vs->password = qemu_strdup(password)))
2392 28a76be8 aliguori
            return -1;
2393 52c18be9 Zachary Amsden
        if (vs->auth == VNC_AUTH_NONE) {
2394 52c18be9 Zachary Amsden
            vs->auth = VNC_AUTH_VNC;
2395 52c18be9 Zachary Amsden
        }
2396 52c18be9 Zachary Amsden
    } else {
2397 52c18be9 Zachary Amsden
        vs->auth = VNC_AUTH_NONE;
2398 70848515 ths
    }
2399 70848515 ths
2400 70848515 ths
    return 0;
2401 71cab5ca ths
}
2402 71cab5ca ths
2403 f92f8afe Anthony Liguori
char *vnc_display_local_addr(DisplayState *ds)
2404 f92f8afe Anthony Liguori
{
2405 f92f8afe Anthony Liguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2406 f92f8afe Anthony Liguori
    
2407 f92f8afe Anthony Liguori
    return vnc_socket_local_addr("%s:%s", vs->lsock);
2408 f92f8afe Anthony Liguori
}
2409 f92f8afe Anthony Liguori
2410 70848515 ths
int vnc_display_open(DisplayState *ds, const char *display)
2411 71cab5ca ths
{
2412 753b4053 aliguori
    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
2413 70848515 ths
    const char *options;
2414 70848515 ths
    int password = 0;
2415 3aa3eea3 balrog
    int reverse = 0;
2416 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2417 3a702699 ths
    int tls = 0, x509 = 0;
2418 8d5d2d4c ths
#endif
2419 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2420 2f9606b3 aliguori
    int sasl = 0;
2421 2f9606b3 aliguori
    int saslErr;
2422 2f9606b3 aliguori
#endif
2423 76655d6d aliguori
    int acl = 0;
2424 3a0558b5 Gerd Hoffmann
    int lock_key_sync = 1;
2425 71cab5ca ths
2426 753b4053 aliguori
    if (!vnc_display)
2427 452b4d88 aliguori
        return -1;
2428 71cab5ca ths
    vnc_display_close(ds);
2429 70848515 ths
    if (strcmp(display, "none") == 0)
2430 28a76be8 aliguori
        return 0;
2431 24236869 bellard
2432 70848515 ths
    if (!(vs->display = strdup(display)))
2433 28a76be8 aliguori
        return -1;
2434 70848515 ths
2435 70848515 ths
    options = display;
2436 70848515 ths
    while ((options = strchr(options, ','))) {
2437 28a76be8 aliguori
        options++;
2438 28a76be8 aliguori
        if (strncmp(options, "password", 8) == 0) {
2439 28a76be8 aliguori
            password = 1; /* Require password auth */
2440 28a76be8 aliguori
        } else if (strncmp(options, "reverse", 7) == 0) {
2441 28a76be8 aliguori
            reverse = 1;
2442 3a0558b5 Gerd Hoffmann
        } else if (strncmp(options, "no-lock-key-sync", 9) == 0) {
2443 3a0558b5 Gerd Hoffmann
            lock_key_sync = 0;
2444 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2445 28a76be8 aliguori
        } else if (strncmp(options, "sasl", 4) == 0) {
2446 28a76be8 aliguori
            sasl = 1; /* Require SASL auth */
2447 2f9606b3 aliguori
#endif
2448 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2449 28a76be8 aliguori
        } else if (strncmp(options, "tls", 3) == 0) {
2450 28a76be8 aliguori
            tls = 1; /* Require TLS */
2451 28a76be8 aliguori
        } else if (strncmp(options, "x509", 4) == 0) {
2452 28a76be8 aliguori
            char *start, *end;
2453 28a76be8 aliguori
            x509 = 1; /* Require x509 certificates */
2454 28a76be8 aliguori
            if (strncmp(options, "x509verify", 10) == 0)
2455 28a76be8 aliguori
                vs->tls.x509verify = 1; /* ...and verify client certs */
2456 28a76be8 aliguori
2457 28a76be8 aliguori
            /* Now check for 'x509=/some/path' postfix
2458 28a76be8 aliguori
             * and use that to setup x509 certificate/key paths */
2459 28a76be8 aliguori
            start = strchr(options, '=');
2460 28a76be8 aliguori
            end = strchr(options, ',');
2461 28a76be8 aliguori
            if (start && (!end || (start < end))) {
2462 28a76be8 aliguori
                int len = end ? end-(start+1) : strlen(start+1);
2463 28a76be8 aliguori
                char *path = qemu_strndup(start + 1, len);
2464 28a76be8 aliguori
2465 28a76be8 aliguori
                VNC_DEBUG("Trying certificate path '%s'\n", path);
2466 28a76be8 aliguori
                if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
2467 28a76be8 aliguori
                    fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2468 28a76be8 aliguori
                    qemu_free(path);
2469 28a76be8 aliguori
                    qemu_free(vs->display);
2470 28a76be8 aliguori
                    vs->display = NULL;
2471 28a76be8 aliguori
                    return -1;
2472 28a76be8 aliguori
                }
2473 28a76be8 aliguori
                qemu_free(path);
2474 28a76be8 aliguori
            } else {
2475 28a76be8 aliguori
                fprintf(stderr, "No certificate path provided\n");
2476 28a76be8 aliguori
                qemu_free(vs->display);
2477 28a76be8 aliguori
                vs->display = NULL;
2478 28a76be8 aliguori
                return -1;
2479 28a76be8 aliguori
            }
2480 8d5d2d4c ths
#endif
2481 28a76be8 aliguori
        } else if (strncmp(options, "acl", 3) == 0) {
2482 28a76be8 aliguori
            acl = 1;
2483 28a76be8 aliguori
        }
2484 70848515 ths
    }
2485 70848515 ths
2486 76655d6d aliguori
#ifdef CONFIG_VNC_TLS
2487 76655d6d aliguori
    if (acl && x509 && vs->tls.x509verify) {
2488 28a76be8 aliguori
        if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {
2489 28a76be8 aliguori
            fprintf(stderr, "Failed to create x509 dname ACL\n");
2490 28a76be8 aliguori
            exit(1);
2491 28a76be8 aliguori
        }
2492 76655d6d aliguori
    }
2493 76655d6d aliguori
#endif
2494 76655d6d aliguori
#ifdef CONFIG_VNC_SASL
2495 76655d6d aliguori
    if (acl && sasl) {
2496 28a76be8 aliguori
        if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) {
2497 28a76be8 aliguori
            fprintf(stderr, "Failed to create username ACL\n");
2498 28a76be8 aliguori
            exit(1);
2499 28a76be8 aliguori
        }
2500 76655d6d aliguori
    }
2501 76655d6d aliguori
#endif
2502 76655d6d aliguori
2503 2f9606b3 aliguori
    /*
2504 2f9606b3 aliguori
     * Combinations we support here:
2505 2f9606b3 aliguori
     *
2506 2f9606b3 aliguori
     *  - no-auth                (clear text, no auth)
2507 2f9606b3 aliguori
     *  - password               (clear text, weak auth)
2508 2f9606b3 aliguori
     *  - sasl                   (encrypt, good auth *IF* using Kerberos via GSSAPI)
2509 2f9606b3 aliguori
     *  - tls                    (encrypt, weak anonymous creds, no auth)
2510 2f9606b3 aliguori
     *  - tls + password         (encrypt, weak anonymous creds, weak auth)
2511 2f9606b3 aliguori
     *  - tls + sasl             (encrypt, weak anonymous creds, good auth)
2512 2f9606b3 aliguori
     *  - tls + x509             (encrypt, good x509 creds, no auth)
2513 2f9606b3 aliguori
     *  - tls + x509 + password  (encrypt, good x509 creds, weak auth)
2514 2f9606b3 aliguori
     *  - tls + x509 + sasl      (encrypt, good x509 creds, good auth)
2515 2f9606b3 aliguori
     *
2516 2f9606b3 aliguori
     * NB1. TLS is a stackable auth scheme.
2517 2f9606b3 aliguori
     * NB2. the x509 schemes have option to validate a client cert dname
2518 2f9606b3 aliguori
     */
2519 70848515 ths
    if (password) {
2520 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2521 28a76be8 aliguori
        if (tls) {
2522 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2523 28a76be8 aliguori
            if (x509) {
2524 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2525 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2526 28a76be8 aliguori
            } else {
2527 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2528 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2529 28a76be8 aliguori
            }
2530 28a76be8 aliguori
        } else {
2531 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2532 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with password auth\n");
2533 28a76be8 aliguori
            vs->auth = VNC_AUTH_VNC;
2534 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2535 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2536 28a76be8 aliguori
        }
2537 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2538 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2539 2f9606b3 aliguori
    } else if (sasl) {
2540 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
2541 2f9606b3 aliguori
        if (tls) {
2542 2f9606b3 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2543 2f9606b3 aliguori
            if (x509) {
2544 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
2545 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509SASL;
2546 2f9606b3 aliguori
            } else {
2547 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
2548 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL;
2549 2f9606b3 aliguori
            }
2550 2f9606b3 aliguori
        } else {
2551 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2552 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with SASL auth\n");
2553 2f9606b3 aliguori
            vs->auth = VNC_AUTH_SASL;
2554 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
2555 2f9606b3 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2556 2f9606b3 aliguori
        }
2557 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
2558 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
2559 70848515 ths
    } else {
2560 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2561 28a76be8 aliguori
        if (tls) {
2562 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
2563 28a76be8 aliguori
            if (x509) {
2564 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2565 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2566 28a76be8 aliguori
            } else {
2567 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2568 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2569 28a76be8 aliguori
            }
2570 28a76be8 aliguori
        } else {
2571 8d5d2d4c ths
#endif
2572 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with no auth\n");
2573 28a76be8 aliguori
            vs->auth = VNC_AUTH_NONE;
2574 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2575 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
2576 28a76be8 aliguori
        }
2577 8d5d2d4c ths
#endif
2578 70848515 ths
    }
2579 24236869 bellard
2580 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2581 2f9606b3 aliguori
    if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
2582 2f9606b3 aliguori
        fprintf(stderr, "Failed to initialize SASL auth %s",
2583 2f9606b3 aliguori
                sasl_errstring(saslErr, NULL, NULL));
2584 2f9606b3 aliguori
        free(vs->display);
2585 2f9606b3 aliguori
        vs->display = NULL;
2586 2f9606b3 aliguori
        return -1;
2587 2f9606b3 aliguori
    }
2588 2f9606b3 aliguori
#endif
2589 3a0558b5 Gerd Hoffmann
    vs->lock_key_sync = lock_key_sync;
2590 2f9606b3 aliguori
2591 3aa3eea3 balrog
    if (reverse) {
2592 9712ecaf aliguori
        /* connect to viewer */
2593 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0)
2594 9712ecaf aliguori
            vs->lsock = unix_connect(display+5);
2595 9712ecaf aliguori
        else
2596 9712ecaf aliguori
            vs->lsock = inet_connect(display, SOCK_STREAM);
2597 9712ecaf aliguori
        if (-1 == vs->lsock) {
2598 3aa3eea3 balrog
            free(vs->display);
2599 3aa3eea3 balrog
            vs->display = NULL;
2600 3aa3eea3 balrog
            return -1;
2601 3aa3eea3 balrog
        } else {
2602 753b4053 aliguori
            int csock = vs->lsock;
2603 3aa3eea3 balrog
            vs->lsock = -1;
2604 753b4053 aliguori
            vnc_connect(vs, csock);
2605 3aa3eea3 balrog
        }
2606 9712ecaf aliguori
        return 0;
2607 24236869 bellard
2608 9712ecaf aliguori
    } else {
2609 9712ecaf aliguori
        /* listen for connects */
2610 9712ecaf aliguori
        char *dpy;
2611 9712ecaf aliguori
        dpy = qemu_malloc(256);
2612 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0) {
2613 bc575e95 blueswir1
            pstrcpy(dpy, 256, "unix:");
2614 4a55bfdf aliguori
            vs->lsock = unix_listen(display+5, dpy+5, 256-5);
2615 9712ecaf aliguori
        } else {
2616 9712ecaf aliguori
            vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
2617 9712ecaf aliguori
        }
2618 9712ecaf aliguori
        if (-1 == vs->lsock) {
2619 9712ecaf aliguori
            free(dpy);
2620 d0513623 balrog
            return -1;
2621 9712ecaf aliguori
        } else {
2622 9712ecaf aliguori
            free(vs->display);
2623 9712ecaf aliguori
            vs->display = dpy;
2624 9712ecaf aliguori
        }
2625 24236869 bellard
    }
2626 753b4053 aliguori
    return qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
2627 24236869 bellard
}