Statistics
| Branch: | Revision:

root / vnc.c @ 4556bd8b

History | View | Annotate | Download (74.6 kB)

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