Statistics
| Branch: | Revision:

root / ui / vnc.c @ bd023f95

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