Statistics
| Branch: | Revision:

root / ui / vnc.c @ bd5c51ee

History | View | Annotate | Download (95.1 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 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
30 1de7afc9 Paolo Bonzini
#include "qemu/sockets.h"
31 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
32 1de7afc9 Paolo Bonzini
#include "qemu/acl.h"
33 7b1b5d19 Paolo Bonzini
#include "qapi/qmp/types.h"
34 2b54aa87 Luiz Capitulino
#include "qmp-commands.h"
35 1de7afc9 Paolo Bonzini
#include "qemu/osdep.h"
36 24236869 bellard
37 0f7b2864 Gerd Hoffmann
#define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
38 2430ffe4 Stefano Stabellini
#define VNC_REFRESH_INTERVAL_INC  50
39 0f7b2864 Gerd Hoffmann
#define VNC_REFRESH_INTERVAL_MAX  GUI_REFRESH_INTERVAL_IDLE
40 999342a0 Corentin Chary
static const struct timeval VNC_REFRESH_STATS = { 0, 500000 };
41 999342a0 Corentin Chary
static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
42 24236869 bellard
43 24236869 bellard
#include "vnc_keysym.h"
44 70848515 ths
#include "d3des.h"
45 70848515 ths
46 753b4053 aliguori
static VncDisplay *vnc_display; /* needed for info vnc */
47 a9ce8590 bellard
48 d467b679 Gerd Hoffmann
static int vnc_cursor_define(VncState *vs);
49 7bc9318b Gerd Hoffmann
static void vnc_release_modifiers(VncState *vs);
50 d467b679 Gerd Hoffmann
51 8cf36489 Gerd Hoffmann
static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
52 8cf36489 Gerd Hoffmann
{
53 8cf36489 Gerd Hoffmann
#ifdef _VNC_DEBUG
54 8cf36489 Gerd Hoffmann
    static const char *mn[] = {
55 8cf36489 Gerd Hoffmann
        [0]                           = "undefined",
56 8cf36489 Gerd Hoffmann
        [VNC_SHARE_MODE_CONNECTING]   = "connecting",
57 8cf36489 Gerd Hoffmann
        [VNC_SHARE_MODE_SHARED]       = "shared",
58 8cf36489 Gerd Hoffmann
        [VNC_SHARE_MODE_EXCLUSIVE]    = "exclusive",
59 8cf36489 Gerd Hoffmann
        [VNC_SHARE_MODE_DISCONNECTED] = "disconnected",
60 8cf36489 Gerd Hoffmann
    };
61 8cf36489 Gerd Hoffmann
    fprintf(stderr, "%s/%d: %s -> %s\n", __func__,
62 8cf36489 Gerd Hoffmann
            vs->csock, mn[vs->share_mode], mn[mode]);
63 8cf36489 Gerd Hoffmann
#endif
64 8cf36489 Gerd Hoffmann
65 8cf36489 Gerd Hoffmann
    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
66 8cf36489 Gerd Hoffmann
        vs->vd->num_exclusive--;
67 8cf36489 Gerd Hoffmann
    }
68 8cf36489 Gerd Hoffmann
    vs->share_mode = mode;
69 8cf36489 Gerd Hoffmann
    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
70 8cf36489 Gerd Hoffmann
        vs->vd->num_exclusive++;
71 8cf36489 Gerd Hoffmann
    }
72 8cf36489 Gerd Hoffmann
}
73 8cf36489 Gerd Hoffmann
74 1ff7df1a aliguori
static char *addr_to_string(const char *format,
75 1ff7df1a aliguori
                            struct sockaddr_storage *sa,
76 1ff7df1a aliguori
                            socklen_t salen) {
77 1ff7df1a aliguori
    char *addr;
78 1ff7df1a aliguori
    char host[NI_MAXHOST];
79 1ff7df1a aliguori
    char serv[NI_MAXSERV];
80 1ff7df1a aliguori
    int err;
81 457772e6 aliguori
    size_t addrlen;
82 1ff7df1a aliguori
83 1ff7df1a aliguori
    if ((err = getnameinfo((struct sockaddr *)sa, salen,
84 1ff7df1a aliguori
                           host, sizeof(host),
85 1ff7df1a aliguori
                           serv, sizeof(serv),
86 1ff7df1a aliguori
                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
87 1ff7df1a aliguori
        VNC_DEBUG("Cannot resolve address %d: %s\n",
88 1ff7df1a aliguori
                  err, gai_strerror(err));
89 1ff7df1a aliguori
        return NULL;
90 1ff7df1a aliguori
    }
91 1ff7df1a aliguori
92 457772e6 aliguori
    /* Enough for the existing format + the 2 vars we're
93 f425c278 Stefan Weil
     * substituting in. */
94 457772e6 aliguori
    addrlen = strlen(format) + strlen(host) + strlen(serv);
95 7267c094 Anthony Liguori
    addr = g_malloc(addrlen + 1);
96 457772e6 aliguori
    snprintf(addr, addrlen, format, host, serv);
97 457772e6 aliguori
    addr[addrlen] = '\0';
98 1ff7df1a aliguori
99 1ff7df1a aliguori
    return addr;
100 1ff7df1a aliguori
}
101 1ff7df1a aliguori
102 2f9606b3 aliguori
103 2f9606b3 aliguori
char *vnc_socket_local_addr(const char *format, int fd) {
104 1ff7df1a aliguori
    struct sockaddr_storage sa;
105 1ff7df1a aliguori
    socklen_t salen;
106 1ff7df1a aliguori
107 1ff7df1a aliguori
    salen = sizeof(sa);
108 1ff7df1a aliguori
    if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0)
109 1ff7df1a aliguori
        return NULL;
110 1ff7df1a aliguori
111 1ff7df1a aliguori
    return addr_to_string(format, &sa, salen);
112 1ff7df1a aliguori
}
113 1ff7df1a aliguori
114 2f9606b3 aliguori
char *vnc_socket_remote_addr(const char *format, int fd) {
115 1ff7df1a aliguori
    struct sockaddr_storage sa;
116 1ff7df1a aliguori
    socklen_t salen;
117 1ff7df1a aliguori
118 1ff7df1a aliguori
    salen = sizeof(sa);
119 1ff7df1a aliguori
    if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0)
120 1ff7df1a aliguori
        return NULL;
121 1ff7df1a aliguori
122 1ff7df1a aliguori
    return addr_to_string(format, &sa, salen);
123 1ff7df1a aliguori
}
124 1ff7df1a aliguori
125 d96fd29c Luiz Capitulino
static int put_addr_qdict(QDict *qdict, struct sockaddr_storage *sa,
126 d96fd29c Luiz Capitulino
                          socklen_t salen)
127 d96fd29c Luiz Capitulino
{
128 d96fd29c Luiz Capitulino
    char host[NI_MAXHOST];
129 d96fd29c Luiz Capitulino
    char serv[NI_MAXSERV];
130 d96fd29c Luiz Capitulino
    int err;
131 d96fd29c Luiz Capitulino
132 d96fd29c Luiz Capitulino
    if ((err = getnameinfo((struct sockaddr *)sa, salen,
133 d96fd29c Luiz Capitulino
                           host, sizeof(host),
134 d96fd29c Luiz Capitulino
                           serv, sizeof(serv),
135 d96fd29c Luiz Capitulino
                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
136 d96fd29c Luiz Capitulino
        VNC_DEBUG("Cannot resolve address %d: %s\n",
137 d96fd29c Luiz Capitulino
                  err, gai_strerror(err));
138 d96fd29c Luiz Capitulino
        return -1;
139 d96fd29c Luiz Capitulino
    }
140 d96fd29c Luiz Capitulino
141 d96fd29c Luiz Capitulino
    qdict_put(qdict, "host", qstring_from_str(host));
142 d96fd29c Luiz Capitulino
    qdict_put(qdict, "service", qstring_from_str(serv));
143 dc0d4efc Luiz Capitulino
    qdict_put(qdict, "family",qstring_from_str(inet_strfamily(sa->ss_family)));
144 d96fd29c Luiz Capitulino
145 d96fd29c Luiz Capitulino
    return 0;
146 d96fd29c Luiz Capitulino
}
147 d96fd29c Luiz Capitulino
148 a7789382 Luiz Capitulino
static int vnc_server_addr_put(QDict *qdict, int fd)
149 d96fd29c Luiz Capitulino
{
150 d96fd29c Luiz Capitulino
    struct sockaddr_storage sa;
151 d96fd29c Luiz Capitulino
    socklen_t salen;
152 d96fd29c Luiz Capitulino
153 d96fd29c Luiz Capitulino
    salen = sizeof(sa);
154 d96fd29c Luiz Capitulino
    if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) {
155 d96fd29c Luiz Capitulino
        return -1;
156 d96fd29c Luiz Capitulino
    }
157 d96fd29c Luiz Capitulino
158 d96fd29c Luiz Capitulino
    return put_addr_qdict(qdict, &sa, salen);
159 d96fd29c Luiz Capitulino
}
160 d96fd29c Luiz Capitulino
161 d96fd29c Luiz Capitulino
static int vnc_qdict_remote_addr(QDict *qdict, int fd)
162 d96fd29c Luiz Capitulino
{
163 d96fd29c Luiz Capitulino
    struct sockaddr_storage sa;
164 d96fd29c Luiz Capitulino
    socklen_t salen;
165 d96fd29c Luiz Capitulino
166 d96fd29c Luiz Capitulino
    salen = sizeof(sa);
167 d96fd29c Luiz Capitulino
    if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) {
168 d96fd29c Luiz Capitulino
        return -1;
169 d96fd29c Luiz Capitulino
    }
170 d96fd29c Luiz Capitulino
171 d96fd29c Luiz Capitulino
    return put_addr_qdict(qdict, &sa, salen);
172 d96fd29c Luiz Capitulino
}
173 d96fd29c Luiz Capitulino
174 1ff7df1a aliguori
static const char *vnc_auth_name(VncDisplay *vd) {
175 1ff7df1a aliguori
    switch (vd->auth) {
176 1ff7df1a aliguori
    case VNC_AUTH_INVALID:
177 1ff7df1a aliguori
        return "invalid";
178 1ff7df1a aliguori
    case VNC_AUTH_NONE:
179 1ff7df1a aliguori
        return "none";
180 1ff7df1a aliguori
    case VNC_AUTH_VNC:
181 1ff7df1a aliguori
        return "vnc";
182 1ff7df1a aliguori
    case VNC_AUTH_RA2:
183 1ff7df1a aliguori
        return "ra2";
184 1ff7df1a aliguori
    case VNC_AUTH_RA2NE:
185 1ff7df1a aliguori
        return "ra2ne";
186 1ff7df1a aliguori
    case VNC_AUTH_TIGHT:
187 1ff7df1a aliguori
        return "tight";
188 1ff7df1a aliguori
    case VNC_AUTH_ULTRA:
189 1ff7df1a aliguori
        return "ultra";
190 1ff7df1a aliguori
    case VNC_AUTH_TLS:
191 1ff7df1a aliguori
        return "tls";
192 1ff7df1a aliguori
    case VNC_AUTH_VENCRYPT:
193 1ff7df1a aliguori
#ifdef CONFIG_VNC_TLS
194 1ff7df1a aliguori
        switch (vd->subauth) {
195 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_PLAIN:
196 1ff7df1a aliguori
            return "vencrypt+plain";
197 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_TLSNONE:
198 1ff7df1a aliguori
            return "vencrypt+tls+none";
199 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_TLSVNC:
200 1ff7df1a aliguori
            return "vencrypt+tls+vnc";
201 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_TLSPLAIN:
202 1ff7df1a aliguori
            return "vencrypt+tls+plain";
203 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_X509NONE:
204 1ff7df1a aliguori
            return "vencrypt+x509+none";
205 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_X509VNC:
206 1ff7df1a aliguori
            return "vencrypt+x509+vnc";
207 1ff7df1a aliguori
        case VNC_AUTH_VENCRYPT_X509PLAIN:
208 1ff7df1a aliguori
            return "vencrypt+x509+plain";
209 28a76be8 aliguori
        case VNC_AUTH_VENCRYPT_TLSSASL:
210 28a76be8 aliguori
            return "vencrypt+tls+sasl";
211 28a76be8 aliguori
        case VNC_AUTH_VENCRYPT_X509SASL:
212 28a76be8 aliguori
            return "vencrypt+x509+sasl";
213 1ff7df1a aliguori
        default:
214 1ff7df1a aliguori
            return "vencrypt";
215 1ff7df1a aliguori
        }
216 1ff7df1a aliguori
#else
217 1ff7df1a aliguori
        return "vencrypt";
218 1ff7df1a aliguori
#endif
219 2f9606b3 aliguori
    case VNC_AUTH_SASL:
220 28a76be8 aliguori
        return "sasl";
221 1ff7df1a aliguori
    }
222 1ff7df1a aliguori
    return "unknown";
223 1ff7df1a aliguori
}
224 1ff7df1a aliguori
225 a7789382 Luiz Capitulino
static int vnc_server_info_put(QDict *qdict)
226 a7789382 Luiz Capitulino
{
227 a7789382 Luiz Capitulino
    if (vnc_server_addr_put(qdict, vnc_display->lsock) < 0) {
228 a7789382 Luiz Capitulino
        return -1;
229 a7789382 Luiz Capitulino
    }
230 a7789382 Luiz Capitulino
231 a7789382 Luiz Capitulino
    qdict_put(qdict, "auth", qstring_from_str(vnc_auth_name(vnc_display)));
232 a7789382 Luiz Capitulino
    return 0;
233 a7789382 Luiz Capitulino
}
234 a7789382 Luiz Capitulino
235 4a80dba3 Luiz Capitulino
static void vnc_client_cache_auth(VncState *client)
236 1ff7df1a aliguori
{
237 2ded6ad7 Blue Swirl
#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
238 d96fd29c Luiz Capitulino
    QDict *qdict;
239 2ded6ad7 Blue Swirl
#endif
240 1ff7df1a aliguori
241 4a80dba3 Luiz Capitulino
    if (!client->info) {
242 4a80dba3 Luiz Capitulino
        return;
243 d96fd29c Luiz Capitulino
    }
244 1263b7d6 aliguori
245 2ded6ad7 Blue Swirl
#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
246 4a80dba3 Luiz Capitulino
    qdict = qobject_to_qdict(client->info);
247 2ded6ad7 Blue Swirl
#endif
248 4a80dba3 Luiz Capitulino
249 1263b7d6 aliguori
#ifdef CONFIG_VNC_TLS
250 1263b7d6 aliguori
    if (client->tls.session &&
251 d96fd29c Luiz Capitulino
        client->tls.dname) {
252 d96fd29c Luiz Capitulino
        qdict_put(qdict, "x509_dname", qstring_from_str(client->tls.dname));
253 d96fd29c Luiz Capitulino
    }
254 1263b7d6 aliguori
#endif
255 1263b7d6 aliguori
#ifdef CONFIG_VNC_SASL
256 1263b7d6 aliguori
    if (client->sasl.conn &&
257 d96fd29c Luiz Capitulino
        client->sasl.username) {
258 76825067 Luiz Capitulino
        qdict_put(qdict, "sasl_username",
259 76825067 Luiz Capitulino
                  qstring_from_str(client->sasl.username));
260 d96fd29c Luiz Capitulino
    }
261 1263b7d6 aliguori
#endif
262 4a80dba3 Luiz Capitulino
}
263 d96fd29c Luiz Capitulino
264 4a80dba3 Luiz Capitulino
static void vnc_client_cache_addr(VncState *client)
265 4a80dba3 Luiz Capitulino
{
266 4a80dba3 Luiz Capitulino
    QDict *qdict;
267 4a80dba3 Luiz Capitulino
268 4a80dba3 Luiz Capitulino
    qdict = qdict_new();
269 4a80dba3 Luiz Capitulino
    if (vnc_qdict_remote_addr(qdict, client->csock) < 0) {
270 4a80dba3 Luiz Capitulino
        QDECREF(qdict);
271 4a80dba3 Luiz Capitulino
        /* XXX: how to report the error? */
272 4a80dba3 Luiz Capitulino
        return;
273 4a80dba3 Luiz Capitulino
    }
274 4a80dba3 Luiz Capitulino
275 4a80dba3 Luiz Capitulino
    client->info = QOBJECT(qdict);
276 1ff7df1a aliguori
}
277 1ff7df1a aliguori
278 586153d9 Luiz Capitulino
static void vnc_qmp_event(VncState *vs, MonitorEvent event)
279 586153d9 Luiz Capitulino
{
280 586153d9 Luiz Capitulino
    QDict *server;
281 586153d9 Luiz Capitulino
    QObject *data;
282 586153d9 Luiz Capitulino
283 586153d9 Luiz Capitulino
    if (!vs->info) {
284 586153d9 Luiz Capitulino
        return;
285 586153d9 Luiz Capitulino
    }
286 586153d9 Luiz Capitulino
287 586153d9 Luiz Capitulino
    server = qdict_new();
288 586153d9 Luiz Capitulino
    if (vnc_server_info_put(server) < 0) {
289 586153d9 Luiz Capitulino
        QDECREF(server);
290 586153d9 Luiz Capitulino
        return;
291 586153d9 Luiz Capitulino
    }
292 586153d9 Luiz Capitulino
293 586153d9 Luiz Capitulino
    data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
294 586153d9 Luiz Capitulino
                              vs->info, QOBJECT(server));
295 586153d9 Luiz Capitulino
296 586153d9 Luiz Capitulino
    monitor_protocol_event(event, data);
297 586153d9 Luiz Capitulino
298 586153d9 Luiz Capitulino
    qobject_incref(vs->info);
299 586153d9 Luiz Capitulino
    qobject_decref(data);
300 586153d9 Luiz Capitulino
}
301 586153d9 Luiz Capitulino
302 2b54aa87 Luiz Capitulino
static VncClientInfo *qmp_query_vnc_client(const VncState *client)
303 a9ce8590 bellard
{
304 2b54aa87 Luiz Capitulino
    struct sockaddr_storage sa;
305 2b54aa87 Luiz Capitulino
    socklen_t salen = sizeof(sa);
306 2b54aa87 Luiz Capitulino
    char host[NI_MAXHOST];
307 2b54aa87 Luiz Capitulino
    char serv[NI_MAXSERV];
308 2b54aa87 Luiz Capitulino
    VncClientInfo *info;
309 2b54aa87 Luiz Capitulino
310 2b54aa87 Luiz Capitulino
    if (getpeername(client->csock, (struct sockaddr *)&sa, &salen) < 0) {
311 2b54aa87 Luiz Capitulino
        return NULL;
312 2b54aa87 Luiz Capitulino
    }
313 2b54aa87 Luiz Capitulino
314 2b54aa87 Luiz Capitulino
    if (getnameinfo((struct sockaddr *)&sa, salen,
315 2b54aa87 Luiz Capitulino
                    host, sizeof(host),
316 2b54aa87 Luiz Capitulino
                    serv, sizeof(serv),
317 2b54aa87 Luiz Capitulino
                    NI_NUMERICHOST | NI_NUMERICSERV) < 0) {
318 2b54aa87 Luiz Capitulino
        return NULL;
319 2b54aa87 Luiz Capitulino
    }
320 d96fd29c Luiz Capitulino
321 2b54aa87 Luiz Capitulino
    info = g_malloc0(sizeof(*info));
322 2b54aa87 Luiz Capitulino
    info->host = g_strdup(host);
323 2b54aa87 Luiz Capitulino
    info->service = g_strdup(serv);
324 2b54aa87 Luiz Capitulino
    info->family = g_strdup(inet_strfamily(sa.ss_family));
325 d96fd29c Luiz Capitulino
326 d96fd29c Luiz Capitulino
#ifdef CONFIG_VNC_TLS
327 2b54aa87 Luiz Capitulino
    if (client->tls.session && client->tls.dname) {
328 2b54aa87 Luiz Capitulino
        info->has_x509_dname = true;
329 2b54aa87 Luiz Capitulino
        info->x509_dname = g_strdup(client->tls.dname);
330 2b54aa87 Luiz Capitulino
    }
331 d96fd29c Luiz Capitulino
#endif
332 d96fd29c Luiz Capitulino
#ifdef CONFIG_VNC_SASL
333 2b54aa87 Luiz Capitulino
    if (client->sasl.conn && client->sasl.username) {
334 2b54aa87 Luiz Capitulino
        info->has_sasl_username = true;
335 2b54aa87 Luiz Capitulino
        info->sasl_username = g_strdup(client->sasl.username);
336 d96fd29c Luiz Capitulino
    }
337 2b54aa87 Luiz Capitulino
#endif
338 1ff7df1a aliguori
339 2b54aa87 Luiz Capitulino
    return info;
340 d96fd29c Luiz Capitulino
}
341 1ff7df1a aliguori
342 2b54aa87 Luiz Capitulino
VncInfo *qmp_query_vnc(Error **errp)
343 d96fd29c Luiz Capitulino
{
344 2b54aa87 Luiz Capitulino
    VncInfo *info = g_malloc0(sizeof(*info));
345 2b54aa87 Luiz Capitulino
346 d96fd29c Luiz Capitulino
    if (vnc_display == NULL || vnc_display->display == NULL) {
347 2b54aa87 Luiz Capitulino
        info->enabled = false;
348 d96fd29c Luiz Capitulino
    } else {
349 2b54aa87 Luiz Capitulino
        VncClientInfoList *cur_item = NULL;
350 2b54aa87 Luiz Capitulino
        struct sockaddr_storage sa;
351 2b54aa87 Luiz Capitulino
        socklen_t salen = sizeof(sa);
352 2b54aa87 Luiz Capitulino
        char host[NI_MAXHOST];
353 2b54aa87 Luiz Capitulino
        char serv[NI_MAXSERV];
354 41b4bef6 Amit Shah
        VncState *client;
355 1ff7df1a aliguori
356 2b54aa87 Luiz Capitulino
        info->enabled = true;
357 2b54aa87 Luiz Capitulino
358 2b54aa87 Luiz Capitulino
        /* for compatibility with the original command */
359 2b54aa87 Luiz Capitulino
        info->has_clients = true;
360 2b54aa87 Luiz Capitulino
361 41b4bef6 Amit Shah
        QTAILQ_FOREACH(client, &vnc_display->clients, next) {
362 2b54aa87 Luiz Capitulino
            VncClientInfoList *cinfo = g_malloc0(sizeof(*info));
363 2b54aa87 Luiz Capitulino
            cinfo->value = qmp_query_vnc_client(client);
364 2b54aa87 Luiz Capitulino
365 2b54aa87 Luiz Capitulino
            /* XXX: waiting for the qapi to support GSList */
366 2b54aa87 Luiz Capitulino
            if (!cur_item) {
367 2b54aa87 Luiz Capitulino
                info->clients = cur_item = cinfo;
368 2b54aa87 Luiz Capitulino
            } else {
369 2b54aa87 Luiz Capitulino
                cur_item->next = cinfo;
370 2b54aa87 Luiz Capitulino
                cur_item = cinfo;
371 1ff7df1a aliguori
            }
372 d96fd29c Luiz Capitulino
        }
373 d96fd29c Luiz Capitulino
374 417b0b88 Paolo Bonzini
        if (vnc_display->lsock == -1) {
375 417b0b88 Paolo Bonzini
            return info;
376 417b0b88 Paolo Bonzini
        }
377 417b0b88 Paolo Bonzini
378 2b54aa87 Luiz Capitulino
        if (getsockname(vnc_display->lsock, (struct sockaddr *)&sa,
379 2b54aa87 Luiz Capitulino
                        &salen) == -1) {
380 2b54aa87 Luiz Capitulino
            error_set(errp, QERR_UNDEFINED_ERROR);
381 2b54aa87 Luiz Capitulino
            goto out_error;
382 2b54aa87 Luiz Capitulino
        }
383 d96fd29c Luiz Capitulino
384 2b54aa87 Luiz Capitulino
        if (getnameinfo((struct sockaddr *)&sa, salen,
385 2b54aa87 Luiz Capitulino
                        host, sizeof(host),
386 2b54aa87 Luiz Capitulino
                        serv, sizeof(serv),
387 2b54aa87 Luiz Capitulino
                        NI_NUMERICHOST | NI_NUMERICSERV) < 0) {
388 2b54aa87 Luiz Capitulino
            error_set(errp, QERR_UNDEFINED_ERROR);
389 2b54aa87 Luiz Capitulino
            goto out_error;
390 1ff7df1a aliguori
        }
391 2b54aa87 Luiz Capitulino
392 2b54aa87 Luiz Capitulino
        info->has_host = true;
393 2b54aa87 Luiz Capitulino
        info->host = g_strdup(host);
394 2b54aa87 Luiz Capitulino
395 2b54aa87 Luiz Capitulino
        info->has_service = true;
396 2b54aa87 Luiz Capitulino
        info->service = g_strdup(serv);
397 2b54aa87 Luiz Capitulino
398 2b54aa87 Luiz Capitulino
        info->has_family = true;
399 2b54aa87 Luiz Capitulino
        info->family = g_strdup(inet_strfamily(sa.ss_family));
400 2b54aa87 Luiz Capitulino
401 2b54aa87 Luiz Capitulino
        info->has_auth = true;
402 2b54aa87 Luiz Capitulino
        info->auth = g_strdup(vnc_auth_name(vnc_display));
403 a9ce8590 bellard
    }
404 2b54aa87 Luiz Capitulino
405 2b54aa87 Luiz Capitulino
    return info;
406 2b54aa87 Luiz Capitulino
407 2b54aa87 Luiz Capitulino
out_error:
408 2b54aa87 Luiz Capitulino
    qapi_free_VncInfo(info);
409 2b54aa87 Luiz Capitulino
    return NULL;
410 a9ce8590 bellard
}
411 a9ce8590 bellard
412 24236869 bellard
/* TODO
413 24236869 bellard
   1) Get the queue working for IO.
414 24236869 bellard
   2) there is some weirdness when using the -S option (the screen is grey
415 24236869 bellard
      and not totally invalidated
416 24236869 bellard
   3) resolutions > 1024
417 24236869 bellard
*/
418 24236869 bellard
419 2430ffe4 Stefano Stabellini
static int vnc_update_client(VncState *vs, int has_dirty);
420 bd023f95 Corentin Chary
static int vnc_update_client_sync(VncState *vs, int has_dirty);
421 198a0039 Gerd Hoffmann
static void vnc_disconnect_start(VncState *vs);
422 24236869 bellard
423 753b4053 aliguori
static void vnc_colordepth(VncState *vs);
424 1fc62412 Stefano Stabellini
static void framebuffer_update_request(VncState *vs, int incremental,
425 1fc62412 Stefano Stabellini
                                       int x_position, int y_position,
426 1fc62412 Stefano Stabellini
                                       int w, int h);
427 0f7b2864 Gerd Hoffmann
static void vnc_refresh(DisplayChangeListener *dcl);
428 1fc62412 Stefano Stabellini
static int vnc_refresh_server_surface(VncDisplay *vd);
429 7eac3a87 aliguori
430 7c20b4a3 Gerd Hoffmann
static void vnc_dpy_update(DisplayChangeListener *dcl,
431 7c20b4a3 Gerd Hoffmann
                           int x, int y, int w, int h)
432 24236869 bellard
{
433 24236869 bellard
    int i;
434 21ef45d7 Gerd Hoffmann
    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
435 1fc62412 Stefano Stabellini
    struct VncSurface *s = &vd->guest;
436 d39fa6d8 Gerd Hoffmann
    int width = surface_width(vd->ds);
437 d39fa6d8 Gerd Hoffmann
    int height = surface_height(vd->ds);
438 24236869 bellard
439 24236869 bellard
    h += y;
440 24236869 bellard
441 0486e8a7 balrog
    /* round x down to ensure the loop only spans one 16-pixel block per,
442 0486e8a7 balrog
       iteration.  otherwise, if (x % 16) != 0, the last iteration may span
443 0486e8a7 balrog
       two 16-pixel blocks but we only mark the first as dirty
444 0486e8a7 balrog
    */
445 0486e8a7 balrog
    w += (x % 16);
446 0486e8a7 balrog
    x -= (x % 16);
447 0486e8a7 balrog
448 9f64916d Gerd Hoffmann
    x = MIN(x, width);
449 9f64916d Gerd Hoffmann
    y = MIN(y, height);
450 9f64916d Gerd Hoffmann
    w = MIN(x + w, width) - x;
451 9f64916d Gerd Hoffmann
    h = MIN(h, height);
452 788abf8e balrog
453 24236869 bellard
    for (; y < h; y++)
454 28a76be8 aliguori
        for (i = 0; i < w; i += 16)
455 bc2429b9 Corentin Chary
            set_bit((x + i) / 16, s->dirty[y]);
456 24236869 bellard
}
457 24236869 bellard
458 70a4568f Corentin Chary
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
459 70a4568f Corentin Chary
                            int32_t encoding)
460 24236869 bellard
{
461 24236869 bellard
    vnc_write_u16(vs, x);
462 24236869 bellard
    vnc_write_u16(vs, y);
463 24236869 bellard
    vnc_write_u16(vs, w);
464 24236869 bellard
    vnc_write_u16(vs, h);
465 24236869 bellard
466 24236869 bellard
    vnc_write_s32(vs, encoding);
467 24236869 bellard
}
468 24236869 bellard
469 2f9606b3 aliguori
void buffer_reserve(Buffer *buffer, size_t len)
470 89064286 aliguori
{
471 89064286 aliguori
    if ((buffer->capacity - buffer->offset) < len) {
472 28a76be8 aliguori
        buffer->capacity += (len + 1024);
473 7267c094 Anthony Liguori
        buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
474 28a76be8 aliguori
        if (buffer->buffer == NULL) {
475 28a76be8 aliguori
            fprintf(stderr, "vnc: out of memory\n");
476 28a76be8 aliguori
            exit(1);
477 28a76be8 aliguori
        }
478 89064286 aliguori
    }
479 89064286 aliguori
}
480 89064286 aliguori
481 71a8cdec Blue Swirl
static int buffer_empty(Buffer *buffer)
482 89064286 aliguori
{
483 89064286 aliguori
    return buffer->offset == 0;
484 89064286 aliguori
}
485 89064286 aliguori
486 7536ee4b Tim Hardeck
uint8_t *buffer_end(Buffer *buffer)
487 89064286 aliguori
{
488 89064286 aliguori
    return buffer->buffer + buffer->offset;
489 89064286 aliguori
}
490 89064286 aliguori
491 2f9606b3 aliguori
void buffer_reset(Buffer *buffer)
492 89064286 aliguori
{
493 28a76be8 aliguori
        buffer->offset = 0;
494 89064286 aliguori
}
495 89064286 aliguori
496 5d418e3b Corentin Chary
void buffer_free(Buffer *buffer)
497 5d418e3b Corentin Chary
{
498 7267c094 Anthony Liguori
    g_free(buffer->buffer);
499 5d418e3b Corentin Chary
    buffer->offset = 0;
500 5d418e3b Corentin Chary
    buffer->capacity = 0;
501 5d418e3b Corentin Chary
    buffer->buffer = NULL;
502 5d418e3b Corentin Chary
}
503 5d418e3b Corentin Chary
504 2f9606b3 aliguori
void buffer_append(Buffer *buffer, const void *data, size_t len)
505 89064286 aliguori
{
506 89064286 aliguori
    memcpy(buffer->buffer + buffer->offset, data, len);
507 89064286 aliguori
    buffer->offset += len;
508 89064286 aliguori
}
509 89064286 aliguori
510 32ed2680 Tim Hardeck
void buffer_advance(Buffer *buf, size_t len)
511 32ed2680 Tim Hardeck
{
512 32ed2680 Tim Hardeck
    memmove(buf->buffer, buf->buffer + len,
513 32ed2680 Tim Hardeck
            (buf->offset - len));
514 32ed2680 Tim Hardeck
    buf->offset -= len;
515 32ed2680 Tim Hardeck
}
516 32ed2680 Tim Hardeck
517 621aaeb9 Gerd Hoffmann
static void vnc_desktop_resize(VncState *vs)
518 621aaeb9 Gerd Hoffmann
{
519 d39fa6d8 Gerd Hoffmann
    DisplaySurface *ds = vs->vd->ds;
520 621aaeb9 Gerd Hoffmann
521 621aaeb9 Gerd Hoffmann
    if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
522 621aaeb9 Gerd Hoffmann
        return;
523 621aaeb9 Gerd Hoffmann
    }
524 d39fa6d8 Gerd Hoffmann
    if (vs->client_width == surface_width(ds) &&
525 d39fa6d8 Gerd Hoffmann
        vs->client_height == surface_height(ds)) {
526 1d4b638a Gerd Hoffmann
        return;
527 1d4b638a Gerd Hoffmann
    }
528 d39fa6d8 Gerd Hoffmann
    vs->client_width = surface_width(ds);
529 d39fa6d8 Gerd Hoffmann
    vs->client_height = surface_height(ds);
530 bd023f95 Corentin Chary
    vnc_lock_output(vs);
531 621aaeb9 Gerd Hoffmann
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
532 621aaeb9 Gerd Hoffmann
    vnc_write_u8(vs, 0);
533 621aaeb9 Gerd Hoffmann
    vnc_write_u16(vs, 1); /* number of rects */
534 5862d195 Gerd Hoffmann
    vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height,
535 621aaeb9 Gerd Hoffmann
                           VNC_ENCODING_DESKTOPRESIZE);
536 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
537 621aaeb9 Gerd Hoffmann
    vnc_flush(vs);
538 621aaeb9 Gerd Hoffmann
}
539 621aaeb9 Gerd Hoffmann
540 bd023f95 Corentin Chary
static void vnc_abort_display_jobs(VncDisplay *vd)
541 bd023f95 Corentin Chary
{
542 bd023f95 Corentin Chary
    VncState *vs;
543 bd023f95 Corentin Chary
544 bd023f95 Corentin Chary
    QTAILQ_FOREACH(vs, &vd->clients, next) {
545 bd023f95 Corentin Chary
        vnc_lock_output(vs);
546 bd023f95 Corentin Chary
        vs->abort = true;
547 bd023f95 Corentin Chary
        vnc_unlock_output(vs);
548 bd023f95 Corentin Chary
    }
549 bd023f95 Corentin Chary
    QTAILQ_FOREACH(vs, &vd->clients, next) {
550 bd023f95 Corentin Chary
        vnc_jobs_join(vs);
551 bd023f95 Corentin Chary
    }
552 bd023f95 Corentin Chary
    QTAILQ_FOREACH(vs, &vd->clients, next) {
553 bd023f95 Corentin Chary
        vnc_lock_output(vs);
554 bd023f95 Corentin Chary
        vs->abort = false;
555 bd023f95 Corentin Chary
        vnc_unlock_output(vs);
556 bd023f95 Corentin Chary
    }
557 bd023f95 Corentin Chary
}
558 bd023f95 Corentin Chary
559 9f64916d Gerd Hoffmann
int vnc_server_fb_stride(VncDisplay *vd)
560 9f64916d Gerd Hoffmann
{
561 9f64916d Gerd Hoffmann
    return pixman_image_get_stride(vd->server);
562 9f64916d Gerd Hoffmann
}
563 9f64916d Gerd Hoffmann
564 9f64916d Gerd Hoffmann
void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
565 9f64916d Gerd Hoffmann
{
566 9f64916d Gerd Hoffmann
    uint8_t *ptr;
567 9f64916d Gerd Hoffmann
568 9f64916d Gerd Hoffmann
    ptr  = (uint8_t *)pixman_image_get_data(vd->server);
569 9f64916d Gerd Hoffmann
    ptr += y * vnc_server_fb_stride(vd);
570 9f64916d Gerd Hoffmann
    ptr += x * VNC_SERVER_FB_BYTES;
571 9f64916d Gerd Hoffmann
    return ptr;
572 9f64916d Gerd Hoffmann
}
573 9f64916d Gerd Hoffmann
574 c12aeb86 Gerd Hoffmann
static void vnc_dpy_switch(DisplayChangeListener *dcl,
575 c12aeb86 Gerd Hoffmann
                           DisplaySurface *surface)
576 24236869 bellard
{
577 21ef45d7 Gerd Hoffmann
    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
578 41b4bef6 Amit Shah
    VncState *vs;
579 1fc62412 Stefano Stabellini
580 bd023f95 Corentin Chary
    vnc_abort_display_jobs(vd);
581 bd023f95 Corentin Chary
582 1fc62412 Stefano Stabellini
    /* server surface */
583 9f64916d Gerd Hoffmann
    qemu_pixman_image_unref(vd->server);
584 d39fa6d8 Gerd Hoffmann
    vd->ds = surface;
585 9f64916d Gerd Hoffmann
    vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
586 d39fa6d8 Gerd Hoffmann
                                          surface_width(vd->ds),
587 d39fa6d8 Gerd Hoffmann
                                          surface_height(vd->ds),
588 9f64916d Gerd Hoffmann
                                          NULL, 0);
589 24236869 bellard
590 6baebed7 aliguori
    /* guest surface */
591 9f64916d Gerd Hoffmann
#if 0 /* FIXME */
592 1fc62412 Stefano Stabellini
    if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
593 a528b80c balrog
        console_color_init(ds);
594 9f64916d Gerd Hoffmann
#endif
595 9f64916d Gerd Hoffmann
    qemu_pixman_image_unref(vd->guest.fb);
596 d39fa6d8 Gerd Hoffmann
    vd->guest.fb = pixman_image_ref(surface->image);
597 d39fa6d8 Gerd Hoffmann
    vd->guest.format = surface->format;
598 1fc62412 Stefano Stabellini
    memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
599 24236869 bellard
600 41b4bef6 Amit Shah
    QTAILQ_FOREACH(vs, &vd->clients, next) {
601 1fc62412 Stefano Stabellini
        vnc_colordepth(vs);
602 1d4b638a Gerd Hoffmann
        vnc_desktop_resize(vs);
603 d467b679 Gerd Hoffmann
        if (vs->vd->cursor) {
604 d467b679 Gerd Hoffmann
            vnc_cursor_define(vs);
605 d467b679 Gerd Hoffmann
        }
606 1fc62412 Stefano Stabellini
        memset(vs->dirty, 0xFF, sizeof(vs->dirty));
607 753b4053 aliguori
    }
608 753b4053 aliguori
}
609 753b4053 aliguori
610 3512779a bellard
/* fastest code */
611 9f64916d Gerd Hoffmann
static void vnc_write_pixels_copy(VncState *vs,
612 d467b679 Gerd Hoffmann
                                  void *pixels, int size)
613 3512779a bellard
{
614 3512779a bellard
    vnc_write(vs, pixels, size);
615 3512779a bellard
}
616 3512779a bellard
617 3512779a bellard
/* slowest but generic code. */
618 70a4568f Corentin Chary
void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
619 3512779a bellard
{
620 7eac3a87 aliguori
    uint8_t r, g, b;
621 1fc62412 Stefano Stabellini
622 9f64916d Gerd Hoffmann
#if VNC_SERVER_FB_FORMAT == PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8)
623 9f64916d Gerd Hoffmann
    r = (((v & 0x00ff0000) >> 16) << vs->client_pf.rbits) >> 8;
624 9f64916d Gerd Hoffmann
    g = (((v & 0x0000ff00) >>  8) << vs->client_pf.gbits) >> 8;
625 9f64916d Gerd Hoffmann
    b = (((v & 0x000000ff) >>  0) << vs->client_pf.bbits) >> 8;
626 9f64916d Gerd Hoffmann
#else
627 9f64916d Gerd Hoffmann
# error need some bits here if you change VNC_SERVER_FB_FORMAT
628 9f64916d Gerd Hoffmann
#endif
629 9f64916d Gerd Hoffmann
    v = (r << vs->client_pf.rshift) |
630 9f64916d Gerd Hoffmann
        (g << vs->client_pf.gshift) |
631 9f64916d Gerd Hoffmann
        (b << vs->client_pf.bshift);
632 9f64916d Gerd Hoffmann
    switch (vs->client_pf.bytes_per_pixel) {
633 3512779a bellard
    case 1:
634 3512779a bellard
        buf[0] = v;
635 3512779a bellard
        break;
636 3512779a bellard
    case 2:
637 9f64916d Gerd Hoffmann
        if (vs->client_be) {
638 3512779a bellard
            buf[0] = v >> 8;
639 3512779a bellard
            buf[1] = v;
640 3512779a bellard
        } else {
641 3512779a bellard
            buf[1] = v >> 8;
642 3512779a bellard
            buf[0] = v;
643 3512779a bellard
        }
644 3512779a bellard
        break;
645 3512779a bellard
    default:
646 3512779a bellard
    case 4:
647 9f64916d Gerd Hoffmann
        if (vs->client_be) {
648 3512779a bellard
            buf[0] = v >> 24;
649 3512779a bellard
            buf[1] = v >> 16;
650 3512779a bellard
            buf[2] = v >> 8;
651 3512779a bellard
            buf[3] = v;
652 3512779a bellard
        } else {
653 3512779a bellard
            buf[3] = v >> 24;
654 3512779a bellard
            buf[2] = v >> 16;
655 3512779a bellard
            buf[1] = v >> 8;
656 3512779a bellard
            buf[0] = v;
657 3512779a bellard
        }
658 3512779a bellard
        break;
659 3512779a bellard
    }
660 3512779a bellard
}
661 3512779a bellard
662 9f64916d Gerd Hoffmann
static void vnc_write_pixels_generic(VncState *vs,
663 d467b679 Gerd Hoffmann
                                     void *pixels1, int size)
664 3512779a bellard
{
665 3512779a bellard
    uint8_t buf[4];
666 3512779a bellard
667 9f64916d Gerd Hoffmann
    if (VNC_SERVER_FB_BYTES == 4) {
668 7eac3a87 aliguori
        uint32_t *pixels = pixels1;
669 7eac3a87 aliguori
        int n, i;
670 7eac3a87 aliguori
        n = size >> 2;
671 9f64916d Gerd Hoffmann
        for (i = 0; i < n; i++) {
672 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
673 9f64916d Gerd Hoffmann
            vnc_write(vs, buf, vs->client_pf.bytes_per_pixel);
674 7eac3a87 aliguori
        }
675 3512779a bellard
    }
676 3512779a bellard
}
677 3512779a bellard
678 a885211e Corentin Chary
int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
679 24236869 bellard
{
680 24236869 bellard
    int i;
681 60fe76f3 ths
    uint8_t *row;
682 1fc62412 Stefano Stabellini
    VncDisplay *vd = vs->vd;
683 24236869 bellard
684 9f64916d Gerd Hoffmann
    row = vnc_server_fb_ptr(vd, x, y);
685 24236869 bellard
    for (i = 0; i < h; i++) {
686 9f64916d Gerd Hoffmann
        vs->write_pixels(vs, row, w * VNC_SERVER_FB_BYTES);
687 9f64916d Gerd Hoffmann
        row += vnc_server_fb_stride(vd);
688 24236869 bellard
    }
689 a885211e Corentin Chary
    return 1;
690 24236869 bellard
}
691 24236869 bellard
692 bd023f95 Corentin Chary
int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
693 24236869 bellard
{
694 a885211e Corentin Chary
    int n = 0;
695 a885211e Corentin Chary
696 fb437313 aliguori
    switch(vs->vnc_encoding) {
697 28a76be8 aliguori
        case VNC_ENCODING_ZLIB:
698 a885211e Corentin Chary
            n = vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
699 28a76be8 aliguori
            break;
700 28a76be8 aliguori
        case VNC_ENCODING_HEXTILE:
701 28a76be8 aliguori
            vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
702 a885211e Corentin Chary
            n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
703 28a76be8 aliguori
            break;
704 380282b0 Corentin Chary
        case VNC_ENCODING_TIGHT:
705 380282b0 Corentin Chary
            n = vnc_tight_send_framebuffer_update(vs, x, y, w, h);
706 380282b0 Corentin Chary
            break;
707 efe556ad Corentin Chary
        case VNC_ENCODING_TIGHT_PNG:
708 efe556ad Corentin Chary
            n = vnc_tight_png_send_framebuffer_update(vs, x, y, w, h);
709 efe556ad Corentin Chary
            break;
710 148954fa Corentin Chary
        case VNC_ENCODING_ZRLE:
711 148954fa Corentin Chary
            n = vnc_zrle_send_framebuffer_update(vs, x, y, w, h);
712 148954fa Corentin Chary
            break;
713 148954fa Corentin Chary
        case VNC_ENCODING_ZYWRLE:
714 148954fa Corentin Chary
            n = vnc_zywrle_send_framebuffer_update(vs, x, y, w, h);
715 148954fa Corentin Chary
            break;
716 28a76be8 aliguori
        default:
717 28a76be8 aliguori
            vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
718 a885211e Corentin Chary
            n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
719 28a76be8 aliguori
            break;
720 fb437313 aliguori
    }
721 a885211e Corentin Chary
    return n;
722 24236869 bellard
}
723 24236869 bellard
724 753b4053 aliguori
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
725 24236869 bellard
{
726 3e28c9ad Gerd Hoffmann
    /* send bitblit op to the vnc client */
727 bd023f95 Corentin Chary
    vnc_lock_output(vs);
728 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
729 24236869 bellard
    vnc_write_u8(vs, 0);
730 24236869 bellard
    vnc_write_u16(vs, 1); /* number of rects */
731 29fa4ed9 aliguori
    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
732 24236869 bellard
    vnc_write_u16(vs, src_x);
733 24236869 bellard
    vnc_write_u16(vs, src_y);
734 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
735 24236869 bellard
    vnc_flush(vs);
736 24236869 bellard
}
737 24236869 bellard
738 7c20b4a3 Gerd Hoffmann
static void vnc_dpy_copy(DisplayChangeListener *dcl,
739 7c20b4a3 Gerd Hoffmann
                         int src_x, int src_y,
740 7c20b4a3 Gerd Hoffmann
                         int dst_x, int dst_y, int w, int h)
741 753b4053 aliguori
{
742 21ef45d7 Gerd Hoffmann
    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
743 198a0039 Gerd Hoffmann
    VncState *vs, *vn;
744 1fc62412 Stefano Stabellini
    uint8_t *src_row;
745 1fc62412 Stefano Stabellini
    uint8_t *dst_row;
746 9f64916d Gerd Hoffmann
    int i, x, y, pitch, inc, w_lim, s;
747 1fc62412 Stefano Stabellini
    int cmp_bytes;
748 198a0039 Gerd Hoffmann
749 1fc62412 Stefano Stabellini
    vnc_refresh_server_surface(vd);
750 41b4bef6 Amit Shah
    QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
751 198a0039 Gerd Hoffmann
        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
752 198a0039 Gerd Hoffmann
            vs->force_update = 1;
753 bd023f95 Corentin Chary
            vnc_update_client_sync(vs, 1);
754 198a0039 Gerd Hoffmann
            /* vs might be free()ed here */
755 198a0039 Gerd Hoffmann
        }
756 198a0039 Gerd Hoffmann
    }
757 198a0039 Gerd Hoffmann
758 1fc62412 Stefano Stabellini
    /* do bitblit op on the local surface too */
759 9f64916d Gerd Hoffmann
    pitch = vnc_server_fb_stride(vd);
760 9f64916d Gerd Hoffmann
    src_row = vnc_server_fb_ptr(vd, src_x, src_y);
761 9f64916d Gerd Hoffmann
    dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
762 1fc62412 Stefano Stabellini
    y = dst_y;
763 1fc62412 Stefano Stabellini
    inc = 1;
764 1fc62412 Stefano Stabellini
    if (dst_y > src_y) {
765 1fc62412 Stefano Stabellini
        /* copy backwards */
766 1fc62412 Stefano Stabellini
        src_row += pitch * (h-1);
767 1fc62412 Stefano Stabellini
        dst_row += pitch * (h-1);
768 1fc62412 Stefano Stabellini
        pitch = -pitch;
769 1fc62412 Stefano Stabellini
        y = dst_y + h - 1;
770 1fc62412 Stefano Stabellini
        inc = -1;
771 1fc62412 Stefano Stabellini
    }
772 1fc62412 Stefano Stabellini
    w_lim = w - (16 - (dst_x % 16));
773 1fc62412 Stefano Stabellini
    if (w_lim < 0)
774 1fc62412 Stefano Stabellini
        w_lim = w;
775 1fc62412 Stefano Stabellini
    else
776 1fc62412 Stefano Stabellini
        w_lim = w - (w_lim % 16);
777 1fc62412 Stefano Stabellini
    for (i = 0; i < h; i++) {
778 1fc62412 Stefano Stabellini
        for (x = 0; x <= w_lim;
779 1fc62412 Stefano Stabellini
                x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
780 1fc62412 Stefano Stabellini
            if (x == w_lim) {
781 1fc62412 Stefano Stabellini
                if ((s = w - w_lim) == 0)
782 1fc62412 Stefano Stabellini
                    break;
783 1fc62412 Stefano Stabellini
            } else if (!x) {
784 1fc62412 Stefano Stabellini
                s = (16 - (dst_x % 16));
785 1fc62412 Stefano Stabellini
                s = MIN(s, w_lim);
786 1fc62412 Stefano Stabellini
            } else {
787 1fc62412 Stefano Stabellini
                s = 16;
788 1fc62412 Stefano Stabellini
            }
789 9f64916d Gerd Hoffmann
            cmp_bytes = s * VNC_SERVER_FB_BYTES;
790 1fc62412 Stefano Stabellini
            if (memcmp(src_row, dst_row, cmp_bytes) == 0)
791 1fc62412 Stefano Stabellini
                continue;
792 1fc62412 Stefano Stabellini
            memmove(dst_row, src_row, cmp_bytes);
793 41b4bef6 Amit Shah
            QTAILQ_FOREACH(vs, &vd->clients, next) {
794 41b4bef6 Amit Shah
                if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
795 bc2429b9 Corentin Chary
                    set_bit(((x + dst_x) / 16), vs->dirty[y]);
796 41b4bef6 Amit Shah
                }
797 1fc62412 Stefano Stabellini
            }
798 1fc62412 Stefano Stabellini
        }
799 9f64916d Gerd Hoffmann
        src_row += pitch - w * VNC_SERVER_FB_BYTES;
800 9f64916d Gerd Hoffmann
        dst_row += pitch - w * VNC_SERVER_FB_BYTES;
801 1fc62412 Stefano Stabellini
        y += inc;
802 1fc62412 Stefano Stabellini
    }
803 1fc62412 Stefano Stabellini
804 41b4bef6 Amit Shah
    QTAILQ_FOREACH(vs, &vd->clients, next) {
805 41b4bef6 Amit Shah
        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
806 753b4053 aliguori
            vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
807 41b4bef6 Amit Shah
        }
808 753b4053 aliguori
    }
809 753b4053 aliguori
}
810 753b4053 aliguori
811 7c20b4a3 Gerd Hoffmann
static void vnc_mouse_set(DisplayChangeListener *dcl,
812 7c20b4a3 Gerd Hoffmann
                          int x, int y, int visible)
813 d467b679 Gerd Hoffmann
{
814 d467b679 Gerd Hoffmann
    /* can we ask the client(s) to move the pointer ??? */
815 d467b679 Gerd Hoffmann
}
816 d467b679 Gerd Hoffmann
817 d467b679 Gerd Hoffmann
static int vnc_cursor_define(VncState *vs)
818 d467b679 Gerd Hoffmann
{
819 d467b679 Gerd Hoffmann
    QEMUCursor *c = vs->vd->cursor;
820 d467b679 Gerd Hoffmann
    int isize;
821 d467b679 Gerd Hoffmann
822 d467b679 Gerd Hoffmann
    if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
823 d01f9595 Corentin Chary
        vnc_lock_output(vs);
824 d467b679 Gerd Hoffmann
        vnc_write_u8(vs,  VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
825 d467b679 Gerd Hoffmann
        vnc_write_u8(vs,  0);  /*  padding     */
826 d467b679 Gerd Hoffmann
        vnc_write_u16(vs, 1);  /*  # of rects  */
827 d467b679 Gerd Hoffmann
        vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
828 d467b679 Gerd Hoffmann
                               VNC_ENCODING_RICH_CURSOR);
829 9f64916d Gerd Hoffmann
        isize = c->width * c->height * vs->client_pf.bytes_per_pixel;
830 9f64916d Gerd Hoffmann
        vnc_write_pixels_generic(vs, c->data, isize);
831 d467b679 Gerd Hoffmann
        vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
832 d01f9595 Corentin Chary
        vnc_unlock_output(vs);
833 d467b679 Gerd Hoffmann
        return 0;
834 d467b679 Gerd Hoffmann
    }
835 d467b679 Gerd Hoffmann
    return -1;
836 d467b679 Gerd Hoffmann
}
837 d467b679 Gerd Hoffmann
838 7c20b4a3 Gerd Hoffmann
static void vnc_dpy_cursor_define(DisplayChangeListener *dcl,
839 7c20b4a3 Gerd Hoffmann
                                  QEMUCursor *c)
840 d467b679 Gerd Hoffmann
{
841 d467b679 Gerd Hoffmann
    VncDisplay *vd = vnc_display;
842 d467b679 Gerd Hoffmann
    VncState *vs;
843 d467b679 Gerd Hoffmann
844 d467b679 Gerd Hoffmann
    cursor_put(vd->cursor);
845 7267c094 Anthony Liguori
    g_free(vd->cursor_mask);
846 d467b679 Gerd Hoffmann
847 d467b679 Gerd Hoffmann
    vd->cursor = c;
848 d467b679 Gerd Hoffmann
    cursor_get(vd->cursor);
849 d467b679 Gerd Hoffmann
    vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
850 7267c094 Anthony Liguori
    vd->cursor_mask = g_malloc0(vd->cursor_msize);
851 d467b679 Gerd Hoffmann
    cursor_get_mono_mask(c, 0, vd->cursor_mask);
852 d467b679 Gerd Hoffmann
853 d467b679 Gerd Hoffmann
    QTAILQ_FOREACH(vs, &vd->clients, next) {
854 d467b679 Gerd Hoffmann
        vnc_cursor_define(vs);
855 d467b679 Gerd Hoffmann
    }
856 d467b679 Gerd Hoffmann
}
857 d467b679 Gerd Hoffmann
858 1fc62412 Stefano Stabellini
static int find_and_clear_dirty_height(struct VncState *vs,
859 6c71a539 Corentin Chary
                                       int y, int last_x, int x, int height)
860 24236869 bellard
{
861 24236869 bellard
    int h;
862 24236869 bellard
863 6c71a539 Corentin Chary
    for (h = 1; h < (height - y); h++) {
864 28a76be8 aliguori
        int tmp_x;
865 bc2429b9 Corentin Chary
        if (!test_bit(last_x, vs->dirty[y + h])) {
866 28a76be8 aliguori
            break;
867 bc2429b9 Corentin Chary
        }
868 bc2429b9 Corentin Chary
        for (tmp_x = last_x; tmp_x < x; tmp_x++) {
869 bc2429b9 Corentin Chary
            clear_bit(tmp_x, vs->dirty[y + h]);
870 bc2429b9 Corentin Chary
        }
871 24236869 bellard
    }
872 24236869 bellard
873 24236869 bellard
    return h;
874 24236869 bellard
}
875 24236869 bellard
876 bd023f95 Corentin Chary
static int vnc_update_client_sync(VncState *vs, int has_dirty)
877 bd023f95 Corentin Chary
{
878 bd023f95 Corentin Chary
    int ret = vnc_update_client(vs, has_dirty);
879 bd023f95 Corentin Chary
    vnc_jobs_join(vs);
880 bd023f95 Corentin Chary
    return ret;
881 bd023f95 Corentin Chary
}
882 bd023f95 Corentin Chary
883 2430ffe4 Stefano Stabellini
static int vnc_update_client(VncState *vs, int has_dirty)
884 24236869 bellard
{
885 24236869 bellard
    if (vs->need_update && vs->csock != -1) {
886 1fc62412 Stefano Stabellini
        VncDisplay *vd = vs->vd;
887 bd023f95 Corentin Chary
        VncJob *job;
888 28a76be8 aliguori
        int y;
889 847ce6a1 Gerd Hoffmann
        int width, height;
890 bd023f95 Corentin Chary
        int n = 0;
891 bd023f95 Corentin Chary
892 24236869 bellard
893 703bc68f Stefano Stabellini
        if (vs->output.offset && !vs->audio_cap && !vs->force_update)
894 c522d0e2 aliguori
            /* kernel send buffers are full -> drop frames to throttle */
895 2430ffe4 Stefano Stabellini
            return 0;
896 a0ecfb73 balrog
897 703bc68f Stefano Stabellini
        if (!has_dirty && !vs->audio_cap && !vs->force_update)
898 2430ffe4 Stefano Stabellini
            return 0;
899 28a76be8 aliguori
900 6baebed7 aliguori
        /*
901 6baebed7 aliguori
         * Send screen updates to the vnc client using the server
902 6baebed7 aliguori
         * surface and server dirty map.  guest surface updates
903 6baebed7 aliguori
         * happening in parallel don't disturb us, the next pass will
904 6baebed7 aliguori
         * send them to the client.
905 6baebed7 aliguori
         */
906 bd023f95 Corentin Chary
        job = vnc_job_new(vs);
907 28a76be8 aliguori
908 9f64916d Gerd Hoffmann
        width = MIN(pixman_image_get_width(vd->server), vs->client_width);
909 9f64916d Gerd Hoffmann
        height = MIN(pixman_image_get_height(vd->server), vs->client_height);
910 847ce6a1 Gerd Hoffmann
911 847ce6a1 Gerd Hoffmann
        for (y = 0; y < height; y++) {
912 28a76be8 aliguori
            int x;
913 28a76be8 aliguori
            int last_x = -1;
914 847ce6a1 Gerd Hoffmann
            for (x = 0; x < width / 16; x++) {
915 bc2429b9 Corentin Chary
                if (test_and_clear_bit(x, vs->dirty[y])) {
916 28a76be8 aliguori
                    if (last_x == -1) {
917 28a76be8 aliguori
                        last_x = x;
918 28a76be8 aliguori
                    }
919 28a76be8 aliguori
                } else {
920 28a76be8 aliguori
                    if (last_x != -1) {
921 6c71a539 Corentin Chary
                        int h = find_and_clear_dirty_height(vs, y, last_x, x,
922 6c71a539 Corentin Chary
                                                            height);
923 bd023f95 Corentin Chary
924 bd023f95 Corentin Chary
                        n += vnc_job_add_rect(job, last_x * 16, y,
925 bd023f95 Corentin Chary
                                              (x - last_x) * 16, h);
926 28a76be8 aliguori
                    }
927 28a76be8 aliguori
                    last_x = -1;
928 28a76be8 aliguori
                }
929 28a76be8 aliguori
            }
930 28a76be8 aliguori
            if (last_x != -1) {
931 6c71a539 Corentin Chary
                int h = find_and_clear_dirty_height(vs, y, last_x, x, height);
932 bd023f95 Corentin Chary
                n += vnc_job_add_rect(job, last_x * 16, y,
933 bd023f95 Corentin Chary
                                      (x - last_x) * 16, h);
934 28a76be8 aliguori
            }
935 28a76be8 aliguori
        }
936 bd023f95 Corentin Chary
937 bd023f95 Corentin Chary
        vnc_job_push(job);
938 c522d0e2 aliguori
        vs->force_update = 0;
939 bd023f95 Corentin Chary
        return n;
940 24236869 bellard
    }
941 24236869 bellard
942 703bc68f Stefano Stabellini
    if (vs->csock == -1)
943 198a0039 Gerd Hoffmann
        vnc_disconnect_finish(vs);
944 2430ffe4 Stefano Stabellini
945 2430ffe4 Stefano Stabellini
    return 0;
946 24236869 bellard
}
947 24236869 bellard
948 429a8ed3 malc
/* audio */
949 429a8ed3 malc
static void audio_capture_notify(void *opaque, audcnotification_e cmd)
950 429a8ed3 malc
{
951 429a8ed3 malc
    VncState *vs = opaque;
952 429a8ed3 malc
953 429a8ed3 malc
    switch (cmd) {
954 429a8ed3 malc
    case AUD_CNOTIFY_DISABLE:
955 bd023f95 Corentin Chary
        vnc_lock_output(vs);
956 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
957 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
958 46a183da Daniel P. Berrange
        vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_END);
959 bd023f95 Corentin Chary
        vnc_unlock_output(vs);
960 429a8ed3 malc
        vnc_flush(vs);
961 429a8ed3 malc
        break;
962 429a8ed3 malc
963 429a8ed3 malc
    case AUD_CNOTIFY_ENABLE:
964 bd023f95 Corentin Chary
        vnc_lock_output(vs);
965 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
966 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
967 46a183da Daniel P. Berrange
        vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_BEGIN);
968 bd023f95 Corentin Chary
        vnc_unlock_output(vs);
969 429a8ed3 malc
        vnc_flush(vs);
970 429a8ed3 malc
        break;
971 429a8ed3 malc
    }
972 429a8ed3 malc
}
973 429a8ed3 malc
974 429a8ed3 malc
static void audio_capture_destroy(void *opaque)
975 429a8ed3 malc
{
976 429a8ed3 malc
}
977 429a8ed3 malc
978 429a8ed3 malc
static void audio_capture(void *opaque, void *buf, int size)
979 429a8ed3 malc
{
980 429a8ed3 malc
    VncState *vs = opaque;
981 429a8ed3 malc
982 bd023f95 Corentin Chary
    vnc_lock_output(vs);
983 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_QEMU);
984 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_QEMU_AUDIO);
985 46a183da Daniel P. Berrange
    vnc_write_u16(vs, VNC_MSG_SERVER_QEMU_AUDIO_DATA);
986 429a8ed3 malc
    vnc_write_u32(vs, size);
987 429a8ed3 malc
    vnc_write(vs, buf, size);
988 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
989 429a8ed3 malc
    vnc_flush(vs);
990 429a8ed3 malc
}
991 429a8ed3 malc
992 429a8ed3 malc
static void audio_add(VncState *vs)
993 429a8ed3 malc
{
994 429a8ed3 malc
    struct audio_capture_ops ops;
995 429a8ed3 malc
996 429a8ed3 malc
    if (vs->audio_cap) {
997 8631b608 Markus Armbruster
        monitor_printf(default_mon, "audio already running\n");
998 429a8ed3 malc
        return;
999 429a8ed3 malc
    }
1000 429a8ed3 malc
1001 429a8ed3 malc
    ops.notify = audio_capture_notify;
1002 429a8ed3 malc
    ops.destroy = audio_capture_destroy;
1003 429a8ed3 malc
    ops.capture = audio_capture;
1004 429a8ed3 malc
1005 1a7dafce malc
    vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
1006 429a8ed3 malc
    if (!vs->audio_cap) {
1007 8631b608 Markus Armbruster
        monitor_printf(default_mon, "Failed to add audio capture\n");
1008 429a8ed3 malc
    }
1009 429a8ed3 malc
}
1010 429a8ed3 malc
1011 429a8ed3 malc
static void audio_del(VncState *vs)
1012 429a8ed3 malc
{
1013 429a8ed3 malc
    if (vs->audio_cap) {
1014 429a8ed3 malc
        AUD_del_capture(vs->audio_cap, vs);
1015 429a8ed3 malc
        vs->audio_cap = NULL;
1016 429a8ed3 malc
    }
1017 429a8ed3 malc
}
1018 429a8ed3 malc
1019 198a0039 Gerd Hoffmann
static void vnc_disconnect_start(VncState *vs)
1020 198a0039 Gerd Hoffmann
{
1021 198a0039 Gerd Hoffmann
    if (vs->csock == -1)
1022 198a0039 Gerd Hoffmann
        return;
1023 8cf36489 Gerd Hoffmann
    vnc_set_share_mode(vs, VNC_SHARE_MODE_DISCONNECTED);
1024 198a0039 Gerd Hoffmann
    qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
1025 198a0039 Gerd Hoffmann
    closesocket(vs->csock);
1026 198a0039 Gerd Hoffmann
    vs->csock = -1;
1027 198a0039 Gerd Hoffmann
}
1028 198a0039 Gerd Hoffmann
1029 7536ee4b Tim Hardeck
void vnc_disconnect_finish(VncState *vs)
1030 198a0039 Gerd Hoffmann
{
1031 7d964c9d Corentin Chary
    int i;
1032 7d964c9d Corentin Chary
1033 bd023f95 Corentin Chary
    vnc_jobs_join(vs); /* Wait encoding jobs */
1034 bd023f95 Corentin Chary
1035 bd023f95 Corentin Chary
    vnc_lock_output(vs);
1036 0d72f3d3 Luiz Capitulino
    vnc_qmp_event(vs, QEVENT_VNC_DISCONNECTED);
1037 0d72f3d3 Luiz Capitulino
1038 5d418e3b Corentin Chary
    buffer_free(&vs->input);
1039 5d418e3b Corentin Chary
    buffer_free(&vs->output);
1040 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
1041 7536ee4b Tim Hardeck
    buffer_free(&vs->ws_input);
1042 7536ee4b Tim Hardeck
    buffer_free(&vs->ws_output);
1043 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
1044 4a80dba3 Luiz Capitulino
1045 4a80dba3 Luiz Capitulino
    qobject_decref(vs->info);
1046 4a80dba3 Luiz Capitulino
1047 161c4f20 Corentin Chary
    vnc_zlib_clear(vs);
1048 380282b0 Corentin Chary
    vnc_tight_clear(vs);
1049 148954fa Corentin Chary
    vnc_zrle_clear(vs);
1050 161c4f20 Corentin Chary
1051 198a0039 Gerd Hoffmann
#ifdef CONFIG_VNC_TLS
1052 198a0039 Gerd Hoffmann
    vnc_tls_client_cleanup(vs);
1053 198a0039 Gerd Hoffmann
#endif /* CONFIG_VNC_TLS */
1054 198a0039 Gerd Hoffmann
#ifdef CONFIG_VNC_SASL
1055 198a0039 Gerd Hoffmann
    vnc_sasl_client_cleanup(vs);
1056 198a0039 Gerd Hoffmann
#endif /* CONFIG_VNC_SASL */
1057 198a0039 Gerd Hoffmann
    audio_del(vs);
1058 7bc9318b Gerd Hoffmann
    vnc_release_modifiers(vs);
1059 198a0039 Gerd Hoffmann
1060 6fd8e79a Tim Hardeck
    if (vs->initialized) {
1061 6fd8e79a Tim Hardeck
        QTAILQ_REMOVE(&vs->vd->clients, vs, next);
1062 6fd8e79a Tim Hardeck
        qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
1063 6fd8e79a Tim Hardeck
    }
1064 41b4bef6 Amit Shah
1065 3a0558b5 Gerd Hoffmann
    if (vs->vd->lock_key_sync)
1066 3a0558b5 Gerd Hoffmann
        qemu_remove_led_event_handler(vs->led);
1067 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
1068 bd023f95 Corentin Chary
1069 bd023f95 Corentin Chary
    qemu_mutex_destroy(&vs->output_mutex);
1070 6fd8e79a Tim Hardeck
    if (vs->bh != NULL) {
1071 6fd8e79a Tim Hardeck
        qemu_bh_delete(vs->bh);
1072 6fd8e79a Tim Hardeck
    }
1073 175b2a6e Corentin Chary
    buffer_free(&vs->jobs_buffer);
1074 175b2a6e Corentin Chary
1075 7d964c9d Corentin Chary
    for (i = 0; i < VNC_STAT_ROWS; ++i) {
1076 7267c094 Anthony Liguori
        g_free(vs->lossy_rect[i]);
1077 7d964c9d Corentin Chary
    }
1078 7267c094 Anthony Liguori
    g_free(vs->lossy_rect);
1079 7267c094 Anthony Liguori
    g_free(vs);
1080 198a0039 Gerd Hoffmann
}
1081 2f9606b3 aliguori
1082 2f9606b3 aliguori
int vnc_client_io_error(VncState *vs, int ret, int last_errno)
1083 24236869 bellard
{
1084 24236869 bellard
    if (ret == 0 || ret == -1) {
1085 ea01e5fd balrog
        if (ret == -1) {
1086 ea01e5fd balrog
            switch (last_errno) {
1087 ea01e5fd balrog
                case EINTR:
1088 ea01e5fd balrog
                case EAGAIN:
1089 ea01e5fd balrog
#ifdef _WIN32
1090 ea01e5fd balrog
                case WSAEWOULDBLOCK:
1091 ea01e5fd balrog
#endif
1092 ea01e5fd balrog
                    return 0;
1093 ea01e5fd balrog
                default:
1094 ea01e5fd balrog
                    break;
1095 ea01e5fd balrog
            }
1096 ea01e5fd balrog
        }
1097 24236869 bellard
1098 198a0039 Gerd Hoffmann
        VNC_DEBUG("Closing down client sock: ret %d, errno %d\n",
1099 198a0039 Gerd Hoffmann
                  ret, ret < 0 ? last_errno : 0);
1100 198a0039 Gerd Hoffmann
        vnc_disconnect_start(vs);
1101 6baebed7 aliguori
1102 28a76be8 aliguori
        return 0;
1103 24236869 bellard
    }
1104 24236869 bellard
    return ret;
1105 24236869 bellard
}
1106 24236869 bellard
1107 5fb6c7a8 aliguori
1108 5fb6c7a8 aliguori
void vnc_client_error(VncState *vs)
1109 24236869 bellard
{
1110 198a0039 Gerd Hoffmann
    VNC_DEBUG("Closing down client sock: protocol error\n");
1111 198a0039 Gerd Hoffmann
    vnc_disconnect_start(vs);
1112 24236869 bellard
}
1113 24236869 bellard
1114 0057a0d5 Tim Hardeck
#ifdef CONFIG_VNC_TLS
1115 0057a0d5 Tim Hardeck
static long vnc_client_write_tls(gnutls_session_t *session,
1116 0057a0d5 Tim Hardeck
                                 const uint8_t *data,
1117 0057a0d5 Tim Hardeck
                                 size_t datalen)
1118 0057a0d5 Tim Hardeck
{
1119 0057a0d5 Tim Hardeck
    long ret = gnutls_write(*session, data, datalen);
1120 0057a0d5 Tim Hardeck
    if (ret < 0) {
1121 0057a0d5 Tim Hardeck
        if (ret == GNUTLS_E_AGAIN) {
1122 0057a0d5 Tim Hardeck
            errno = EAGAIN;
1123 0057a0d5 Tim Hardeck
        } else {
1124 0057a0d5 Tim Hardeck
            errno = EIO;
1125 0057a0d5 Tim Hardeck
        }
1126 0057a0d5 Tim Hardeck
        ret = -1;
1127 0057a0d5 Tim Hardeck
    }
1128 0057a0d5 Tim Hardeck
    return ret;
1129 0057a0d5 Tim Hardeck
}
1130 0057a0d5 Tim Hardeck
#endif /* CONFIG_VNC_TLS */
1131 2f9606b3 aliguori
1132 2f9606b3 aliguori
/*
1133 2f9606b3 aliguori
 * Called to write a chunk of data to the client socket. The data may
1134 2f9606b3 aliguori
 * be the raw data, or may have already been encoded by SASL.
1135 2f9606b3 aliguori
 * The data will be written either straight onto the socket, or
1136 2f9606b3 aliguori
 * written via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1137 2f9606b3 aliguori
 *
1138 2f9606b3 aliguori
 * NB, it is theoretically possible to have 2 layers of encryption,
1139 2f9606b3 aliguori
 * both SASL, and this TLS layer. It is highly unlikely in practice
1140 2f9606b3 aliguori
 * though, since SASL encryption will typically be a no-op if TLS
1141 2f9606b3 aliguori
 * is active
1142 2f9606b3 aliguori
 *
1143 2f9606b3 aliguori
 * Returns the number of bytes written, which may be less than
1144 2f9606b3 aliguori
 * the requested 'datalen' if the socket would block. Returns
1145 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
1146 2f9606b3 aliguori
 */
1147 2f9606b3 aliguori
long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
1148 24236869 bellard
{
1149 ceb5caaf bellard
    long ret;
1150 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1151 5fb6c7a8 aliguori
    if (vs->tls.session) {
1152 0057a0d5 Tim Hardeck
        ret = vnc_client_write_tls(&vs->tls.session, data, datalen);
1153 0057a0d5 Tim Hardeck
    } else {
1154 0057a0d5 Tim Hardeck
#ifdef CONFIG_VNC_WS
1155 0057a0d5 Tim Hardeck
        if (vs->ws_tls.session) {
1156 0057a0d5 Tim Hardeck
            ret = vnc_client_write_tls(&vs->ws_tls.session, data, datalen);
1157 0057a0d5 Tim Hardeck
        } else
1158 0057a0d5 Tim Hardeck
#endif /* CONFIG_VNC_WS */
1159 0057a0d5 Tim Hardeck
#endif /* CONFIG_VNC_TLS */
1160 0057a0d5 Tim Hardeck
        {
1161 0057a0d5 Tim Hardeck
            ret = send(vs->csock, (const void *)data, datalen, 0);
1162 28a76be8 aliguori
        }
1163 0057a0d5 Tim Hardeck
#ifdef CONFIG_VNC_TLS
1164 0057a0d5 Tim Hardeck
    }
1165 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
1166 23decc87 aliguori
    VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
1167 2f9606b3 aliguori
    return vnc_client_io_error(vs, ret, socket_error());
1168 2f9606b3 aliguori
}
1169 2f9606b3 aliguori
1170 2f9606b3 aliguori
1171 2f9606b3 aliguori
/*
1172 2f9606b3 aliguori
 * Called to write buffered data to the client socket, when not
1173 2f9606b3 aliguori
 * using any SASL SSF encryption layers. Will write as much data
1174 2f9606b3 aliguori
 * as possible without blocking. If all buffered data is written,
1175 2f9606b3 aliguori
 * will switch the FD poll() handler back to read monitoring.
1176 2f9606b3 aliguori
 *
1177 2f9606b3 aliguori
 * Returns the number of bytes written, which may be less than
1178 2f9606b3 aliguori
 * the buffered output data if the socket would block. Returns
1179 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
1180 2f9606b3 aliguori
 */
1181 2f9606b3 aliguori
static long vnc_client_write_plain(VncState *vs)
1182 2f9606b3 aliguori
{
1183 2f9606b3 aliguori
    long ret;
1184 2f9606b3 aliguori
1185 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1186 23decc87 aliguori
    VNC_DEBUG("Write Plain: Pending output %p size %zd offset %zd. Wait SSF %d\n",
1187 2f9606b3 aliguori
              vs->output.buffer, vs->output.capacity, vs->output.offset,
1188 2f9606b3 aliguori
              vs->sasl.waitWriteSSF);
1189 2f9606b3 aliguori
1190 2f9606b3 aliguori
    if (vs->sasl.conn &&
1191 2f9606b3 aliguori
        vs->sasl.runSSF &&
1192 2f9606b3 aliguori
        vs->sasl.waitWriteSSF) {
1193 2f9606b3 aliguori
        ret = vnc_client_write_buf(vs, vs->output.buffer, vs->sasl.waitWriteSSF);
1194 2f9606b3 aliguori
        if (ret)
1195 2f9606b3 aliguori
            vs->sasl.waitWriteSSF -= ret;
1196 2f9606b3 aliguori
    } else
1197 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1198 2f9606b3 aliguori
        ret = vnc_client_write_buf(vs, vs->output.buffer, vs->output.offset);
1199 24236869 bellard
    if (!ret)
1200 2f9606b3 aliguori
        return 0;
1201 24236869 bellard
1202 32ed2680 Tim Hardeck
    buffer_advance(&vs->output, ret);
1203 24236869 bellard
1204 24236869 bellard
    if (vs->output.offset == 0) {
1205 28a76be8 aliguori
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
1206 24236869 bellard
    }
1207 2f9606b3 aliguori
1208 2f9606b3 aliguori
    return ret;
1209 2f9606b3 aliguori
}
1210 2f9606b3 aliguori
1211 2f9606b3 aliguori
1212 2f9606b3 aliguori
/*
1213 2f9606b3 aliguori
 * First function called whenever there is data to be written to
1214 2f9606b3 aliguori
 * the client socket. Will delegate actual work according to whether
1215 2f9606b3 aliguori
 * SASL SSF layers are enabled (thus requiring encryption calls)
1216 2f9606b3 aliguori
 */
1217 bd023f95 Corentin Chary
static void vnc_client_write_locked(void *opaque)
1218 2f9606b3 aliguori
{
1219 2f9606b3 aliguori
    VncState *vs = opaque;
1220 2f9606b3 aliguori
1221 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1222 2f9606b3 aliguori
    if (vs->sasl.conn &&
1223 2f9606b3 aliguori
        vs->sasl.runSSF &&
1224 9678d950 Blue Swirl
        !vs->sasl.waitWriteSSF) {
1225 9678d950 Blue Swirl
        vnc_client_write_sasl(vs);
1226 9678d950 Blue Swirl
    } else
1227 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1228 7536ee4b Tim Hardeck
    {
1229 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
1230 7536ee4b Tim Hardeck
        if (vs->encode_ws) {
1231 7536ee4b Tim Hardeck
            vnc_client_write_ws(vs);
1232 7536ee4b Tim Hardeck
        } else
1233 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
1234 7536ee4b Tim Hardeck
        {
1235 7536ee4b Tim Hardeck
            vnc_client_write_plain(vs);
1236 7536ee4b Tim Hardeck
        }
1237 7536ee4b Tim Hardeck
    }
1238 24236869 bellard
}
1239 24236869 bellard
1240 bd023f95 Corentin Chary
void vnc_client_write(void *opaque)
1241 bd023f95 Corentin Chary
{
1242 bd023f95 Corentin Chary
    VncState *vs = opaque;
1243 bd023f95 Corentin Chary
1244 bd023f95 Corentin Chary
    vnc_lock_output(vs);
1245 7536ee4b Tim Hardeck
    if (vs->output.offset
1246 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
1247 7536ee4b Tim Hardeck
            || vs->ws_output.offset
1248 7536ee4b Tim Hardeck
#endif
1249 7536ee4b Tim Hardeck
            ) {
1250 bd023f95 Corentin Chary
        vnc_client_write_locked(opaque);
1251 ac71103d Yoshiaki Tamura
    } else if (vs->csock != -1) {
1252 bd023f95 Corentin Chary
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
1253 bd023f95 Corentin Chary
    }
1254 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
1255 bd023f95 Corentin Chary
}
1256 bd023f95 Corentin Chary
1257 5fb6c7a8 aliguori
void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
1258 24236869 bellard
{
1259 24236869 bellard
    vs->read_handler = func;
1260 24236869 bellard
    vs->read_handler_expect = expecting;
1261 24236869 bellard
}
1262 24236869 bellard
1263 0057a0d5 Tim Hardeck
#ifdef CONFIG_VNC_TLS
1264 0057a0d5 Tim Hardeck
static long vnc_client_read_tls(gnutls_session_t *session, uint8_t *data,
1265 0057a0d5 Tim Hardeck
                                size_t datalen)
1266 0057a0d5 Tim Hardeck
{
1267 0057a0d5 Tim Hardeck
    long ret = gnutls_read(*session, data, datalen);
1268 0057a0d5 Tim Hardeck
    if (ret < 0) {
1269 0057a0d5 Tim Hardeck
        if (ret == GNUTLS_E_AGAIN) {
1270 0057a0d5 Tim Hardeck
            errno = EAGAIN;
1271 0057a0d5 Tim Hardeck
        } else {
1272 0057a0d5 Tim Hardeck
            errno = EIO;
1273 0057a0d5 Tim Hardeck
        }
1274 0057a0d5 Tim Hardeck
        ret = -1;
1275 0057a0d5 Tim Hardeck
    }
1276 0057a0d5 Tim Hardeck
    return ret;
1277 0057a0d5 Tim Hardeck
}
1278 0057a0d5 Tim Hardeck
#endif /* CONFIG_VNC_TLS */
1279 2f9606b3 aliguori
1280 2f9606b3 aliguori
/*
1281 2f9606b3 aliguori
 * Called to read a chunk of data from the client socket. The data may
1282 2f9606b3 aliguori
 * be the raw data, or may need to be further decoded by SASL.
1283 2f9606b3 aliguori
 * The data will be read either straight from to the socket, or
1284 2f9606b3 aliguori
 * read via the GNUTLS wrappers, if TLS/SSL encryption is enabled
1285 2f9606b3 aliguori
 *
1286 2f9606b3 aliguori
 * NB, it is theoretically possible to have 2 layers of encryption,
1287 2f9606b3 aliguori
 * both SASL, and this TLS layer. It is highly unlikely in practice
1288 2f9606b3 aliguori
 * though, since SASL encryption will typically be a no-op if TLS
1289 2f9606b3 aliguori
 * is active
1290 2f9606b3 aliguori
 *
1291 2f9606b3 aliguori
 * Returns the number of bytes read, which may be less than
1292 2f9606b3 aliguori
 * the requested 'datalen' if the socket would block. Returns
1293 2f9606b3 aliguori
 * -1 on error, and disconnects the client socket.
1294 2f9606b3 aliguori
 */
1295 2f9606b3 aliguori
long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
1296 24236869 bellard
{
1297 ceb5caaf bellard
    long ret;
1298 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1299 5fb6c7a8 aliguori
    if (vs->tls.session) {
1300 0057a0d5 Tim Hardeck
        ret = vnc_client_read_tls(&vs->tls.session, data, datalen);
1301 0057a0d5 Tim Hardeck
    } else {
1302 0057a0d5 Tim Hardeck
#ifdef CONFIG_VNC_WS
1303 0057a0d5 Tim Hardeck
        if (vs->ws_tls.session) {
1304 0057a0d5 Tim Hardeck
            ret = vnc_client_read_tls(&vs->ws_tls.session, data, datalen);
1305 0057a0d5 Tim Hardeck
        } else
1306 0057a0d5 Tim Hardeck
#endif /* CONFIG_VNC_WS */
1307 0057a0d5 Tim Hardeck
#endif /* CONFIG_VNC_TLS */
1308 0057a0d5 Tim Hardeck
        {
1309 0057a0d5 Tim Hardeck
            ret = qemu_recv(vs->csock, data, datalen, 0);
1310 28a76be8 aliguori
        }
1311 0057a0d5 Tim Hardeck
#ifdef CONFIG_VNC_TLS
1312 0057a0d5 Tim Hardeck
    }
1313 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
1314 23decc87 aliguori
    VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
1315 2f9606b3 aliguori
    return vnc_client_io_error(vs, ret, socket_error());
1316 2f9606b3 aliguori
}
1317 24236869 bellard
1318 2f9606b3 aliguori
1319 2f9606b3 aliguori
/*
1320 2f9606b3 aliguori
 * Called to read data from the client socket to the input buffer,
1321 2f9606b3 aliguori
 * when not using any SASL SSF encryption layers. Will read as much
1322 2f9606b3 aliguori
 * data as possible without blocking.
1323 2f9606b3 aliguori
 *
1324 2f9606b3 aliguori
 * Returns the number of bytes read. Returns -1 on error, and
1325 2f9606b3 aliguori
 * disconnects the client socket.
1326 2f9606b3 aliguori
 */
1327 2f9606b3 aliguori
static long vnc_client_read_plain(VncState *vs)
1328 2f9606b3 aliguori
{
1329 2f9606b3 aliguori
    int ret;
1330 23decc87 aliguori
    VNC_DEBUG("Read plain %p size %zd offset %zd\n",
1331 2f9606b3 aliguori
              vs->input.buffer, vs->input.capacity, vs->input.offset);
1332 2f9606b3 aliguori
    buffer_reserve(&vs->input, 4096);
1333 2f9606b3 aliguori
    ret = vnc_client_read_buf(vs, buffer_end(&vs->input), 4096);
1334 2f9606b3 aliguori
    if (!ret)
1335 2f9606b3 aliguori
        return 0;
1336 24236869 bellard
    vs->input.offset += ret;
1337 2f9606b3 aliguori
    return ret;
1338 2f9606b3 aliguori
}
1339 2f9606b3 aliguori
1340 175b2a6e Corentin Chary
static void vnc_jobs_bh(void *opaque)
1341 175b2a6e Corentin Chary
{
1342 175b2a6e Corentin Chary
    VncState *vs = opaque;
1343 175b2a6e Corentin Chary
1344 175b2a6e Corentin Chary
    vnc_jobs_consume_buffer(vs);
1345 175b2a6e Corentin Chary
}
1346 2f9606b3 aliguori
1347 2f9606b3 aliguori
/*
1348 2f9606b3 aliguori
 * First function called whenever there is more data to be read from
1349 2f9606b3 aliguori
 * the client socket. Will delegate actual work according to whether
1350 2f9606b3 aliguori
 * SASL SSF layers are enabled (thus requiring decryption calls)
1351 2f9606b3 aliguori
 */
1352 2f9606b3 aliguori
void vnc_client_read(void *opaque)
1353 2f9606b3 aliguori
{
1354 2f9606b3 aliguori
    VncState *vs = opaque;
1355 2f9606b3 aliguori
    long ret;
1356 2f9606b3 aliguori
1357 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
1358 2f9606b3 aliguori
    if (vs->sasl.conn && vs->sasl.runSSF)
1359 2f9606b3 aliguori
        ret = vnc_client_read_sasl(vs);
1360 2f9606b3 aliguori
    else
1361 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
1362 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
1363 7536ee4b Tim Hardeck
        if (vs->encode_ws) {
1364 7536ee4b Tim Hardeck
            ret = vnc_client_read_ws(vs);
1365 7536ee4b Tim Hardeck
            if (ret == -1) {
1366 7536ee4b Tim Hardeck
                vnc_disconnect_start(vs);
1367 7536ee4b Tim Hardeck
                return;
1368 7536ee4b Tim Hardeck
            } else if (ret == -2) {
1369 7536ee4b Tim Hardeck
                vnc_client_error(vs);
1370 7536ee4b Tim Hardeck
                return;
1371 7536ee4b Tim Hardeck
            }
1372 7536ee4b Tim Hardeck
        } else
1373 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
1374 7536ee4b Tim Hardeck
        {
1375 2f9606b3 aliguori
        ret = vnc_client_read_plain(vs);
1376 7536ee4b Tim Hardeck
        }
1377 198a0039 Gerd Hoffmann
    if (!ret) {
1378 198a0039 Gerd Hoffmann
        if (vs->csock == -1)
1379 198a0039 Gerd Hoffmann
            vnc_disconnect_finish(vs);
1380 28a76be8 aliguori
        return;
1381 198a0039 Gerd Hoffmann
    }
1382 24236869 bellard
1383 24236869 bellard
    while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
1384 28a76be8 aliguori
        size_t len = vs->read_handler_expect;
1385 28a76be8 aliguori
        int ret;
1386 28a76be8 aliguori
1387 28a76be8 aliguori
        ret = vs->read_handler(vs, vs->input.buffer, len);
1388 198a0039 Gerd Hoffmann
        if (vs->csock == -1) {
1389 198a0039 Gerd Hoffmann
            vnc_disconnect_finish(vs);
1390 28a76be8 aliguori
            return;
1391 198a0039 Gerd Hoffmann
        }
1392 28a76be8 aliguori
1393 28a76be8 aliguori
        if (!ret) {
1394 32ed2680 Tim Hardeck
            buffer_advance(&vs->input, len);
1395 28a76be8 aliguori
        } else {
1396 28a76be8 aliguori
            vs->read_handler_expect = ret;
1397 28a76be8 aliguori
        }
1398 24236869 bellard
    }
1399 24236869 bellard
}
1400 24236869 bellard
1401 5fb6c7a8 aliguori
void vnc_write(VncState *vs, const void *data, size_t len)
1402 24236869 bellard
{
1403 24236869 bellard
    buffer_reserve(&vs->output, len);
1404 24236869 bellard
1405 198a0039 Gerd Hoffmann
    if (vs->csock != -1 && buffer_empty(&vs->output)) {
1406 28a76be8 aliguori
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1407 24236869 bellard
    }
1408 24236869 bellard
1409 24236869 bellard
    buffer_append(&vs->output, data, len);
1410 24236869 bellard
}
1411 24236869 bellard
1412 5fb6c7a8 aliguori
void vnc_write_s32(VncState *vs, int32_t value)
1413 24236869 bellard
{
1414 24236869 bellard
    vnc_write_u32(vs, *(uint32_t *)&value);
1415 24236869 bellard
}
1416 24236869 bellard
1417 5fb6c7a8 aliguori
void vnc_write_u32(VncState *vs, uint32_t value)
1418 24236869 bellard
{
1419 24236869 bellard
    uint8_t buf[4];
1420 24236869 bellard
1421 24236869 bellard
    buf[0] = (value >> 24) & 0xFF;
1422 24236869 bellard
    buf[1] = (value >> 16) & 0xFF;
1423 24236869 bellard
    buf[2] = (value >>  8) & 0xFF;
1424 24236869 bellard
    buf[3] = value & 0xFF;
1425 24236869 bellard
1426 24236869 bellard
    vnc_write(vs, buf, 4);
1427 24236869 bellard
}
1428 24236869 bellard
1429 5fb6c7a8 aliguori
void vnc_write_u16(VncState *vs, uint16_t value)
1430 24236869 bellard
{
1431 64f5a135 bellard
    uint8_t buf[2];
1432 24236869 bellard
1433 24236869 bellard
    buf[0] = (value >> 8) & 0xFF;
1434 24236869 bellard
    buf[1] = value & 0xFF;
1435 24236869 bellard
1436 24236869 bellard
    vnc_write(vs, buf, 2);
1437 24236869 bellard
}
1438 24236869 bellard
1439 5fb6c7a8 aliguori
void vnc_write_u8(VncState *vs, uint8_t value)
1440 24236869 bellard
{
1441 24236869 bellard
    vnc_write(vs, (char *)&value, 1);
1442 24236869 bellard
}
1443 24236869 bellard
1444 5fb6c7a8 aliguori
void vnc_flush(VncState *vs)
1445 24236869 bellard
{
1446 bd023f95 Corentin Chary
    vnc_lock_output(vs);
1447 7536ee4b Tim Hardeck
    if (vs->csock != -1 && (vs->output.offset
1448 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
1449 7536ee4b Tim Hardeck
                || vs->ws_output.offset
1450 7536ee4b Tim Hardeck
#endif
1451 7536ee4b Tim Hardeck
                )) {
1452 bd023f95 Corentin Chary
        vnc_client_write_locked(vs);
1453 bd023f95 Corentin Chary
    }
1454 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
1455 24236869 bellard
}
1456 24236869 bellard
1457 71a8cdec Blue Swirl
static uint8_t read_u8(uint8_t *data, size_t offset)
1458 24236869 bellard
{
1459 24236869 bellard
    return data[offset];
1460 24236869 bellard
}
1461 24236869 bellard
1462 71a8cdec Blue Swirl
static uint16_t read_u16(uint8_t *data, size_t offset)
1463 24236869 bellard
{
1464 24236869 bellard
    return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
1465 24236869 bellard
}
1466 24236869 bellard
1467 71a8cdec Blue Swirl
static int32_t read_s32(uint8_t *data, size_t offset)
1468 24236869 bellard
{
1469 24236869 bellard
    return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
1470 28a76be8 aliguori
                     (data[offset + 2] << 8) | data[offset + 3]);
1471 24236869 bellard
}
1472 24236869 bellard
1473 5fb6c7a8 aliguori
uint32_t read_u32(uint8_t *data, size_t offset)
1474 24236869 bellard
{
1475 24236869 bellard
    return ((data[offset] << 24) | (data[offset + 1] << 16) |
1476 28a76be8 aliguori
            (data[offset + 2] << 8) | data[offset + 3]);
1477 24236869 bellard
}
1478 24236869 bellard
1479 60fe76f3 ths
static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
1480 24236869 bellard
{
1481 24236869 bellard
}
1482 24236869 bellard
1483 9e8dd451 Jan Kiszka
static void check_pointer_type_change(Notifier *notifier, void *data)
1484 564c337e bellard
{
1485 37c34d9d Anthony Liguori
    VncState *vs = container_of(notifier, VncState, mouse_mode_notifier);
1486 37c34d9d Anthony Liguori
    int absolute = kbd_mouse_is_absolute();
1487 37c34d9d Anthony Liguori
1488 29fa4ed9 aliguori
    if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
1489 bd023f95 Corentin Chary
        vnc_lock_output(vs);
1490 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1491 28a76be8 aliguori
        vnc_write_u8(vs, 0);
1492 28a76be8 aliguori
        vnc_write_u16(vs, 1);
1493 28a76be8 aliguori
        vnc_framebuffer_update(vs, absolute, 0,
1494 d39fa6d8 Gerd Hoffmann
                               surface_width(vs->vd->ds),
1495 d39fa6d8 Gerd Hoffmann
                               surface_height(vs->vd->ds),
1496 29fa4ed9 aliguori
                               VNC_ENCODING_POINTER_TYPE_CHANGE);
1497 bd023f95 Corentin Chary
        vnc_unlock_output(vs);
1498 28a76be8 aliguori
        vnc_flush(vs);
1499 564c337e bellard
    }
1500 564c337e bellard
    vs->absolute = absolute;
1501 564c337e bellard
}
1502 564c337e bellard
1503 24236869 bellard
static void pointer_event(VncState *vs, int button_mask, int x, int y)
1504 24236869 bellard
{
1505 24236869 bellard
    int buttons = 0;
1506 24236869 bellard
    int dz = 0;
1507 d39fa6d8 Gerd Hoffmann
    int width = surface_width(vs->vd->ds);
1508 d39fa6d8 Gerd Hoffmann
    int height = surface_height(vs->vd->ds);
1509 24236869 bellard
1510 24236869 bellard
    if (button_mask & 0x01)
1511 28a76be8 aliguori
        buttons |= MOUSE_EVENT_LBUTTON;
1512 24236869 bellard
    if (button_mask & 0x02)
1513 28a76be8 aliguori
        buttons |= MOUSE_EVENT_MBUTTON;
1514 24236869 bellard
    if (button_mask & 0x04)
1515 28a76be8 aliguori
        buttons |= MOUSE_EVENT_RBUTTON;
1516 24236869 bellard
    if (button_mask & 0x08)
1517 28a76be8 aliguori
        dz = -1;
1518 24236869 bellard
    if (button_mask & 0x10)
1519 28a76be8 aliguori
        dz = 1;
1520 564c337e bellard
1521 564c337e bellard
    if (vs->absolute) {
1522 d39fa6d8 Gerd Hoffmann
        kbd_mouse_event(width  > 1 ? x * 0x7FFF / (width  - 1) : 0x4000,
1523 d39fa6d8 Gerd Hoffmann
                        height > 1 ? y * 0x7FFF / (height - 1) : 0x4000,
1524 28a76be8 aliguori
                        dz, buttons);
1525 29fa4ed9 aliguori
    } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
1526 28a76be8 aliguori
        x -= 0x7FFF;
1527 28a76be8 aliguori
        y -= 0x7FFF;
1528 24236869 bellard
1529 28a76be8 aliguori
        kbd_mouse_event(x, y, dz, buttons);
1530 564c337e bellard
    } else {
1531 28a76be8 aliguori
        if (vs->last_x != -1)
1532 28a76be8 aliguori
            kbd_mouse_event(x - vs->last_x,
1533 28a76be8 aliguori
                            y - vs->last_y,
1534 28a76be8 aliguori
                            dz, buttons);
1535 28a76be8 aliguori
        vs->last_x = x;
1536 28a76be8 aliguori
        vs->last_y = y;
1537 24236869 bellard
    }
1538 24236869 bellard
}
1539 24236869 bellard
1540 64f5a135 bellard
static void reset_keys(VncState *vs)
1541 64f5a135 bellard
{
1542 64f5a135 bellard
    int i;
1543 64f5a135 bellard
    for(i = 0; i < 256; i++) {
1544 64f5a135 bellard
        if (vs->modifiers_state[i]) {
1545 44bb61c8 Samuel Thibault
            if (i & SCANCODE_GREY)
1546 44bb61c8 Samuel Thibault
                kbd_put_keycode(SCANCODE_EMUL0);
1547 44bb61c8 Samuel Thibault
            kbd_put_keycode(i | SCANCODE_UP);
1548 64f5a135 bellard
            vs->modifiers_state[i] = 0;
1549 64f5a135 bellard
        }
1550 64f5a135 bellard
    }
1551 64f5a135 bellard
}
1552 64f5a135 bellard
1553 a528b80c balrog
static void press_key(VncState *vs, int keysym)
1554 a528b80c balrog
{
1555 44bb61c8 Samuel Thibault
    int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
1556 44bb61c8 Samuel Thibault
    if (keycode & SCANCODE_GREY)
1557 44bb61c8 Samuel Thibault
        kbd_put_keycode(SCANCODE_EMUL0);
1558 44bb61c8 Samuel Thibault
    kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
1559 44bb61c8 Samuel Thibault
    if (keycode & SCANCODE_GREY)
1560 44bb61c8 Samuel Thibault
        kbd_put_keycode(SCANCODE_EMUL0);
1561 44bb61c8 Samuel Thibault
    kbd_put_keycode(keycode | SCANCODE_UP);
1562 a528b80c balrog
}
1563 a528b80c balrog
1564 ab99e5c1 Lei Li
static int current_led_state(VncState *vs)
1565 ab99e5c1 Lei Li
{
1566 ab99e5c1 Lei Li
    int ledstate = 0;
1567 ab99e5c1 Lei Li
1568 ab99e5c1 Lei Li
    if (vs->modifiers_state[0x46]) {
1569 ab99e5c1 Lei Li
        ledstate |= QEMU_SCROLL_LOCK_LED;
1570 ab99e5c1 Lei Li
    }
1571 ab99e5c1 Lei Li
    if (vs->modifiers_state[0x45]) {
1572 ab99e5c1 Lei Li
        ledstate |= QEMU_NUM_LOCK_LED;
1573 ab99e5c1 Lei Li
    }
1574 ab99e5c1 Lei Li
    if (vs->modifiers_state[0x3a]) {
1575 ab99e5c1 Lei Li
        ledstate |= QEMU_CAPS_LOCK_LED;
1576 ab99e5c1 Lei Li
    }
1577 ab99e5c1 Lei Li
1578 ab99e5c1 Lei Li
    return ledstate;
1579 ab99e5c1 Lei Li
}
1580 ab99e5c1 Lei Li
1581 ab99e5c1 Lei Li
static void vnc_led_state_change(VncState *vs)
1582 ab99e5c1 Lei Li
{
1583 ab99e5c1 Lei Li
    int ledstate = 0;
1584 ab99e5c1 Lei Li
1585 ab99e5c1 Lei Li
    if (!vnc_has_feature(vs, VNC_FEATURE_LED_STATE)) {
1586 ab99e5c1 Lei Li
        return;
1587 ab99e5c1 Lei Li
    }
1588 ab99e5c1 Lei Li
1589 ab99e5c1 Lei Li
    ledstate = current_led_state(vs);
1590 ab99e5c1 Lei Li
    vnc_lock_output(vs);
1591 ab99e5c1 Lei Li
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1592 ab99e5c1 Lei Li
    vnc_write_u8(vs, 0);
1593 ab99e5c1 Lei Li
    vnc_write_u16(vs, 1);
1594 ab99e5c1 Lei Li
    vnc_framebuffer_update(vs, 0, 0, 1, 1, VNC_ENCODING_LED_STATE);
1595 ab99e5c1 Lei Li
    vnc_write_u8(vs, ledstate);
1596 ab99e5c1 Lei Li
    vnc_unlock_output(vs);
1597 ab99e5c1 Lei Li
    vnc_flush(vs);
1598 ab99e5c1 Lei Li
}
1599 ab99e5c1 Lei Li
1600 7ffb82ca Gerd Hoffmann
static void kbd_leds(void *opaque, int ledstate)
1601 7ffb82ca Gerd Hoffmann
{
1602 7ffb82ca Gerd Hoffmann
    VncState *vs = opaque;
1603 96f3d174 Lei Li
    int caps, num, scr;
1604 1483adcf Lei Li
    bool has_changed = (ledstate != current_led_state(vs));
1605 7ffb82ca Gerd Hoffmann
1606 7ffb82ca Gerd Hoffmann
    caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0;
1607 7ffb82ca Gerd Hoffmann
    num  = ledstate & QEMU_NUM_LOCK_LED  ? 1 : 0;
1608 96f3d174 Lei Li
    scr  = ledstate & QEMU_SCROLL_LOCK_LED ? 1 : 0;
1609 7ffb82ca Gerd Hoffmann
1610 7ffb82ca Gerd Hoffmann
    if (vs->modifiers_state[0x3a] != caps) {
1611 7ffb82ca Gerd Hoffmann
        vs->modifiers_state[0x3a] = caps;
1612 7ffb82ca Gerd Hoffmann
    }
1613 7ffb82ca Gerd Hoffmann
    if (vs->modifiers_state[0x45] != num) {
1614 7ffb82ca Gerd Hoffmann
        vs->modifiers_state[0x45] = num;
1615 7ffb82ca Gerd Hoffmann
    }
1616 96f3d174 Lei Li
    if (vs->modifiers_state[0x46] != scr) {
1617 96f3d174 Lei Li
        vs->modifiers_state[0x46] = scr;
1618 96f3d174 Lei Li
    }
1619 ab99e5c1 Lei Li
1620 ab99e5c1 Lei Li
    /* Sending the current led state message to the client */
1621 1483adcf Lei Li
    if (has_changed) {
1622 ab99e5c1 Lei Li
        vnc_led_state_change(vs);
1623 ab99e5c1 Lei Li
    }
1624 7ffb82ca Gerd Hoffmann
}
1625 7ffb82ca Gerd Hoffmann
1626 9ca313aa aliguori
static void do_key_event(VncState *vs, int down, int keycode, int sym)
1627 24236869 bellard
{
1628 64f5a135 bellard
    /* QEMU console switch */
1629 64f5a135 bellard
    switch(keycode) {
1630 64f5a135 bellard
    case 0x2a:                          /* Left Shift */
1631 64f5a135 bellard
    case 0x36:                          /* Right Shift */
1632 64f5a135 bellard
    case 0x1d:                          /* Left CTRL */
1633 64f5a135 bellard
    case 0x9d:                          /* Right CTRL */
1634 64f5a135 bellard
    case 0x38:                          /* Left ALT */
1635 64f5a135 bellard
    case 0xb8:                          /* Right ALT */
1636 64f5a135 bellard
        if (down)
1637 64f5a135 bellard
            vs->modifiers_state[keycode] = 1;
1638 64f5a135 bellard
        else
1639 64f5a135 bellard
            vs->modifiers_state[keycode] = 0;
1640 64f5a135 bellard
        break;
1641 5fafdf24 ths
    case 0x02 ... 0x0a: /* '1' to '9' keys */
1642 64f5a135 bellard
        if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1643 64f5a135 bellard
            /* Reset the modifiers sent to the current console */
1644 64f5a135 bellard
            reset_keys(vs);
1645 64f5a135 bellard
            console_select(keycode - 0x02);
1646 64f5a135 bellard
            return;
1647 64f5a135 bellard
        }
1648 64f5a135 bellard
        break;
1649 28a76be8 aliguori
    case 0x3a:                        /* CapsLock */
1650 28a76be8 aliguori
    case 0x45:                        /* NumLock */
1651 7ffb82ca Gerd Hoffmann
        if (down)
1652 a528b80c balrog
            vs->modifiers_state[keycode] ^= 1;
1653 a528b80c balrog
        break;
1654 a528b80c balrog
    }
1655 a528b80c balrog
1656 e7b2aacc Lei Li
    /* Turn off the lock state sync logic if the client support the led
1657 e7b2aacc Lei Li
       state extension.
1658 e7b2aacc Lei Li
    */
1659 9892088b Gerd Hoffmann
    if (down && vs->vd->lock_key_sync &&
1660 e7b2aacc Lei Li
        !vnc_has_feature(vs, VNC_FEATURE_LED_STATE) &&
1661 3a0558b5 Gerd Hoffmann
        keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
1662 a528b80c balrog
        /* If the numlock state needs to change then simulate an additional
1663 a528b80c balrog
           keypress before sending this one.  This will happen if the user
1664 a528b80c balrog
           toggles numlock away from the VNC window.
1665 a528b80c balrog
        */
1666 753b4053 aliguori
        if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
1667 a528b80c balrog
            if (!vs->modifiers_state[0x45]) {
1668 a528b80c balrog
                vs->modifiers_state[0x45] = 1;
1669 a528b80c balrog
                press_key(vs, 0xff7f);
1670 a528b80c balrog
            }
1671 a528b80c balrog
        } else {
1672 a528b80c balrog
            if (vs->modifiers_state[0x45]) {
1673 a528b80c balrog
                vs->modifiers_state[0x45] = 0;
1674 a528b80c balrog
                press_key(vs, 0xff7f);
1675 a528b80c balrog
            }
1676 a528b80c balrog
        }
1677 64f5a135 bellard
    }
1678 24236869 bellard
1679 9892088b Gerd Hoffmann
    if (down && vs->vd->lock_key_sync &&
1680 e7b2aacc Lei Li
        !vnc_has_feature(vs, VNC_FEATURE_LED_STATE) &&
1681 3a0558b5 Gerd Hoffmann
        ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
1682 6b132502 Gerd Hoffmann
        /* If the capslock state needs to change then simulate an additional
1683 6b132502 Gerd Hoffmann
           keypress before sending this one.  This will happen if the user
1684 6b132502 Gerd Hoffmann
           toggles capslock away from the VNC window.
1685 6b132502 Gerd Hoffmann
        */
1686 6b132502 Gerd Hoffmann
        int uppercase = !!(sym >= 'A' && sym <= 'Z');
1687 6b132502 Gerd Hoffmann
        int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
1688 6b132502 Gerd Hoffmann
        int capslock = !!(vs->modifiers_state[0x3a]);
1689 6b132502 Gerd Hoffmann
        if (capslock) {
1690 6b132502 Gerd Hoffmann
            if (uppercase == shift) {
1691 6b132502 Gerd Hoffmann
                vs->modifiers_state[0x3a] = 0;
1692 6b132502 Gerd Hoffmann
                press_key(vs, 0xffe5);
1693 6b132502 Gerd Hoffmann
            }
1694 6b132502 Gerd Hoffmann
        } else {
1695 6b132502 Gerd Hoffmann
            if (uppercase != shift) {
1696 6b132502 Gerd Hoffmann
                vs->modifiers_state[0x3a] = 1;
1697 6b132502 Gerd Hoffmann
                press_key(vs, 0xffe5);
1698 6b132502 Gerd Hoffmann
            }
1699 6b132502 Gerd Hoffmann
        }
1700 6b132502 Gerd Hoffmann
    }
1701 6b132502 Gerd Hoffmann
1702 81c0d5a6 Gerd Hoffmann
    if (qemu_console_is_graphic(NULL)) {
1703 44bb61c8 Samuel Thibault
        if (keycode & SCANCODE_GREY)
1704 44bb61c8 Samuel Thibault
            kbd_put_keycode(SCANCODE_EMUL0);
1705 64f5a135 bellard
        if (down)
1706 44bb61c8 Samuel Thibault
            kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
1707 64f5a135 bellard
        else
1708 44bb61c8 Samuel Thibault
            kbd_put_keycode(keycode | SCANCODE_UP);
1709 64f5a135 bellard
    } else {
1710 e26437c2 Gerd Hoffmann
        bool numlock = vs->modifiers_state[0x45];
1711 e26437c2 Gerd Hoffmann
        bool control = (vs->modifiers_state[0x1d] ||
1712 e26437c2 Gerd Hoffmann
                        vs->modifiers_state[0x9d]);
1713 64f5a135 bellard
        /* QEMU console emulation */
1714 64f5a135 bellard
        if (down) {
1715 64f5a135 bellard
            switch (keycode) {
1716 64f5a135 bellard
            case 0x2a:                          /* Left Shift */
1717 64f5a135 bellard
            case 0x36:                          /* Right Shift */
1718 64f5a135 bellard
            case 0x1d:                          /* Left CTRL */
1719 64f5a135 bellard
            case 0x9d:                          /* Right CTRL */
1720 64f5a135 bellard
            case 0x38:                          /* Left ALT */
1721 64f5a135 bellard
            case 0xb8:                          /* Right ALT */
1722 64f5a135 bellard
                break;
1723 64f5a135 bellard
            case 0xc8:
1724 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_UP);
1725 64f5a135 bellard
                break;
1726 64f5a135 bellard
            case 0xd0:
1727 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DOWN);
1728 64f5a135 bellard
                break;
1729 64f5a135 bellard
            case 0xcb:
1730 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_LEFT);
1731 64f5a135 bellard
                break;
1732 64f5a135 bellard
            case 0xcd:
1733 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_RIGHT);
1734 64f5a135 bellard
                break;
1735 64f5a135 bellard
            case 0xd3:
1736 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DELETE);
1737 64f5a135 bellard
                break;
1738 64f5a135 bellard
            case 0xc7:
1739 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_HOME);
1740 64f5a135 bellard
                break;
1741 64f5a135 bellard
            case 0xcf:
1742 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_END);
1743 64f5a135 bellard
                break;
1744 64f5a135 bellard
            case 0xc9:
1745 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEUP);
1746 64f5a135 bellard
                break;
1747 64f5a135 bellard
            case 0xd1:
1748 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1749 64f5a135 bellard
                break;
1750 bb0a18e1 Gerd Hoffmann
1751 bb0a18e1 Gerd Hoffmann
            case 0x47:
1752 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
1753 bb0a18e1 Gerd Hoffmann
                break;
1754 bb0a18e1 Gerd Hoffmann
            case 0x48:
1755 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
1756 bb0a18e1 Gerd Hoffmann
                break;
1757 bb0a18e1 Gerd Hoffmann
            case 0x49:
1758 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
1759 bb0a18e1 Gerd Hoffmann
                break;
1760 bb0a18e1 Gerd Hoffmann
            case 0x4b:
1761 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
1762 bb0a18e1 Gerd Hoffmann
                break;
1763 bb0a18e1 Gerd Hoffmann
            case 0x4c:
1764 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('5');
1765 bb0a18e1 Gerd Hoffmann
                break;
1766 bb0a18e1 Gerd Hoffmann
            case 0x4d:
1767 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
1768 bb0a18e1 Gerd Hoffmann
                break;
1769 bb0a18e1 Gerd Hoffmann
            case 0x4f:
1770 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
1771 bb0a18e1 Gerd Hoffmann
                break;
1772 bb0a18e1 Gerd Hoffmann
            case 0x50:
1773 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
1774 bb0a18e1 Gerd Hoffmann
                break;
1775 bb0a18e1 Gerd Hoffmann
            case 0x51:
1776 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
1777 bb0a18e1 Gerd Hoffmann
                break;
1778 bb0a18e1 Gerd Hoffmann
            case 0x52:
1779 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('0');
1780 bb0a18e1 Gerd Hoffmann
                break;
1781 bb0a18e1 Gerd Hoffmann
            case 0x53:
1782 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
1783 bb0a18e1 Gerd Hoffmann
                break;
1784 bb0a18e1 Gerd Hoffmann
1785 bb0a18e1 Gerd Hoffmann
            case 0xb5:
1786 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('/');
1787 bb0a18e1 Gerd Hoffmann
                break;
1788 bb0a18e1 Gerd Hoffmann
            case 0x37:
1789 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('*');
1790 bb0a18e1 Gerd Hoffmann
                break;
1791 bb0a18e1 Gerd Hoffmann
            case 0x4a:
1792 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('-');
1793 bb0a18e1 Gerd Hoffmann
                break;
1794 bb0a18e1 Gerd Hoffmann
            case 0x4e:
1795 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('+');
1796 bb0a18e1 Gerd Hoffmann
                break;
1797 bb0a18e1 Gerd Hoffmann
            case 0x9c:
1798 bb0a18e1 Gerd Hoffmann
                kbd_put_keysym('\n');
1799 bb0a18e1 Gerd Hoffmann
                break;
1800 bb0a18e1 Gerd Hoffmann
1801 64f5a135 bellard
            default:
1802 e26437c2 Gerd Hoffmann
                if (control) {
1803 e26437c2 Gerd Hoffmann
                    kbd_put_keysym(sym & 0x1f);
1804 e26437c2 Gerd Hoffmann
                } else {
1805 e26437c2 Gerd Hoffmann
                    kbd_put_keysym(sym);
1806 e26437c2 Gerd Hoffmann
                }
1807 64f5a135 bellard
                break;
1808 64f5a135 bellard
            }
1809 64f5a135 bellard
        }
1810 64f5a135 bellard
    }
1811 24236869 bellard
}
1812 24236869 bellard
1813 7bc9318b Gerd Hoffmann
static void vnc_release_modifiers(VncState *vs)
1814 7bc9318b Gerd Hoffmann
{
1815 7bc9318b Gerd Hoffmann
    static const int keycodes[] = {
1816 7bc9318b Gerd Hoffmann
        /* shift, control, alt keys, both left & right */
1817 7bc9318b Gerd Hoffmann
        0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
1818 7bc9318b Gerd Hoffmann
    };
1819 7bc9318b Gerd Hoffmann
    int i, keycode;
1820 7bc9318b Gerd Hoffmann
1821 81c0d5a6 Gerd Hoffmann
    if (!qemu_console_is_graphic(NULL)) {
1822 7bc9318b Gerd Hoffmann
        return;
1823 7bc9318b Gerd Hoffmann
    }
1824 7bc9318b Gerd Hoffmann
    for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
1825 7bc9318b Gerd Hoffmann
        keycode = keycodes[i];
1826 7bc9318b Gerd Hoffmann
        if (!vs->modifiers_state[keycode]) {
1827 7bc9318b Gerd Hoffmann
            continue;
1828 7bc9318b Gerd Hoffmann
        }
1829 7bc9318b Gerd Hoffmann
        if (keycode & SCANCODE_GREY) {
1830 7bc9318b Gerd Hoffmann
            kbd_put_keycode(SCANCODE_EMUL0);
1831 7bc9318b Gerd Hoffmann
        }
1832 7bc9318b Gerd Hoffmann
        kbd_put_keycode(keycode | SCANCODE_UP);
1833 7bc9318b Gerd Hoffmann
    }
1834 7bc9318b Gerd Hoffmann
}
1835 7bc9318b Gerd Hoffmann
1836 bdbd7676 bellard
static void key_event(VncState *vs, int down, uint32_t sym)
1837 bdbd7676 bellard
{
1838 9ca313aa aliguori
    int keycode;
1839 4a93fe17 Gerd Hoffmann
    int lsym = sym;
1840 9ca313aa aliguori
1841 81c0d5a6 Gerd Hoffmann
    if (lsym >= 'A' && lsym <= 'Z' && qemu_console_is_graphic(NULL)) {
1842 4a93fe17 Gerd Hoffmann
        lsym = lsym - 'A' + 'a';
1843 4a93fe17 Gerd Hoffmann
    }
1844 9ca313aa aliguori
1845 44bb61c8 Samuel Thibault
    keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
1846 9ca313aa aliguori
    do_key_event(vs, down, keycode, sym);
1847 9ca313aa aliguori
}
1848 9ca313aa aliguori
1849 9ca313aa aliguori
static void ext_key_event(VncState *vs, int down,
1850 9ca313aa aliguori
                          uint32_t sym, uint16_t keycode)
1851 9ca313aa aliguori
{
1852 9ca313aa aliguori
    /* if the user specifies a keyboard layout, always use it */
1853 9ca313aa aliguori
    if (keyboard_layout)
1854 9ca313aa aliguori
        key_event(vs, down, sym);
1855 9ca313aa aliguori
    else
1856 9ca313aa aliguori
        do_key_event(vs, down, keycode, sym);
1857 bdbd7676 bellard
}
1858 bdbd7676 bellard
1859 24236869 bellard
static void framebuffer_update_request(VncState *vs, int incremental,
1860 28a76be8 aliguori
                                       int x_position, int y_position,
1861 28a76be8 aliguori
                                       int w, int h)
1862 24236869 bellard
{
1863 6ed391bf Wen Congyang
    int i;
1864 d39fa6d8 Gerd Hoffmann
    const size_t width = surface_width(vs->vd->ds) / 16;
1865 d39fa6d8 Gerd Hoffmann
    const size_t height = surface_height(vs->vd->ds);
1866 6ed391bf Wen Congyang
1867 d39fa6d8 Gerd Hoffmann
    if (y_position > height) {
1868 d39fa6d8 Gerd Hoffmann
        y_position = height;
1869 d39fa6d8 Gerd Hoffmann
    }
1870 d39fa6d8 Gerd Hoffmann
    if (y_position + h >= height) {
1871 d39fa6d8 Gerd Hoffmann
        h = height - y_position;
1872 d39fa6d8 Gerd Hoffmann
    }
1873 cf2d385c ths
1874 24236869 bellard
    vs->need_update = 1;
1875 24236869 bellard
    if (!incremental) {
1876 24cf0a6e Gerd Hoffmann
        vs->force_update = 1;
1877 28a76be8 aliguori
        for (i = 0; i < h; i++) {
1878 6ed391bf Wen Congyang
            bitmap_set(vs->dirty[y_position + i], 0, width);
1879 6ed391bf Wen Congyang
            bitmap_clear(vs->dirty[y_position + i], width,
1880 a0843a68 Anthony Liguori
                         VNC_DIRTY_BITS - width);
1881 28a76be8 aliguori
        }
1882 24236869 bellard
    }
1883 24236869 bellard
}
1884 24236869 bellard
1885 9ca313aa aliguori
static void send_ext_key_event_ack(VncState *vs)
1886 9ca313aa aliguori
{
1887 bd023f95 Corentin Chary
    vnc_lock_output(vs);
1888 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1889 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1890 9ca313aa aliguori
    vnc_write_u16(vs, 1);
1891 d39fa6d8 Gerd Hoffmann
    vnc_framebuffer_update(vs, 0, 0,
1892 d39fa6d8 Gerd Hoffmann
                           surface_width(vs->vd->ds),
1893 d39fa6d8 Gerd Hoffmann
                           surface_height(vs->vd->ds),
1894 29fa4ed9 aliguori
                           VNC_ENCODING_EXT_KEY_EVENT);
1895 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
1896 9ca313aa aliguori
    vnc_flush(vs);
1897 9ca313aa aliguori
}
1898 9ca313aa aliguori
1899 429a8ed3 malc
static void send_ext_audio_ack(VncState *vs)
1900 429a8ed3 malc
{
1901 bd023f95 Corentin Chary
    vnc_lock_output(vs);
1902 46a183da Daniel P. Berrange
    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
1903 429a8ed3 malc
    vnc_write_u8(vs, 0);
1904 429a8ed3 malc
    vnc_write_u16(vs, 1);
1905 d39fa6d8 Gerd Hoffmann
    vnc_framebuffer_update(vs, 0, 0,
1906 d39fa6d8 Gerd Hoffmann
                           surface_width(vs->vd->ds),
1907 d39fa6d8 Gerd Hoffmann
                           surface_height(vs->vd->ds),
1908 29fa4ed9 aliguori
                           VNC_ENCODING_AUDIO);
1909 bd023f95 Corentin Chary
    vnc_unlock_output(vs);
1910 429a8ed3 malc
    vnc_flush(vs);
1911 429a8ed3 malc
}
1912 429a8ed3 malc
1913 24236869 bellard
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1914 24236869 bellard
{
1915 24236869 bellard
    int i;
1916 29fa4ed9 aliguori
    unsigned int enc = 0;
1917 24236869 bellard
1918 29fa4ed9 aliguori
    vs->features = 0;
1919 a9f20d31 Corentin Chary
    vs->vnc_encoding = 0;
1920 d1af0e05 Corentin Chary
    vs->tight.compression = 9;
1921 d1af0e05 Corentin Chary
    vs->tight.quality = -1; /* Lossless by default */
1922 564c337e bellard
    vs->absolute = -1;
1923 24236869 bellard
1924 8a0f0d0c Corentin Chary
    /*
1925 8a0f0d0c Corentin Chary
     * Start from the end because the encodings are sent in order of preference.
1926 e5bed759 Dong Xu Wang
     * This way the preferred encoding (first encoding defined in the array)
1927 8a0f0d0c Corentin Chary
     * will be set at the end of the loop.
1928 8a0f0d0c Corentin Chary
     */
1929 24236869 bellard
    for (i = n_encodings - 1; i >= 0; i--) {
1930 29fa4ed9 aliguori
        enc = encodings[i];
1931 29fa4ed9 aliguori
        switch (enc) {
1932 29fa4ed9 aliguori
        case VNC_ENCODING_RAW:
1933 a9f20d31 Corentin Chary
            vs->vnc_encoding = enc;
1934 29fa4ed9 aliguori
            break;
1935 29fa4ed9 aliguori
        case VNC_ENCODING_COPYRECT:
1936 753b4053 aliguori
            vs->features |= VNC_FEATURE_COPYRECT_MASK;
1937 29fa4ed9 aliguori
            break;
1938 29fa4ed9 aliguori
        case VNC_ENCODING_HEXTILE:
1939 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_HEXTILE_MASK;
1940 a9f20d31 Corentin Chary
            vs->vnc_encoding = enc;
1941 29fa4ed9 aliguori
            break;
1942 380282b0 Corentin Chary
        case VNC_ENCODING_TIGHT:
1943 380282b0 Corentin Chary
            vs->features |= VNC_FEATURE_TIGHT_MASK;
1944 380282b0 Corentin Chary
            vs->vnc_encoding = enc;
1945 380282b0 Corentin Chary
            break;
1946 fe3e7f2d Joel Martin
#ifdef CONFIG_VNC_PNG
1947 efe556ad Corentin Chary
        case VNC_ENCODING_TIGHT_PNG:
1948 efe556ad Corentin Chary
            vs->features |= VNC_FEATURE_TIGHT_PNG_MASK;
1949 efe556ad Corentin Chary
            vs->vnc_encoding = enc;
1950 efe556ad Corentin Chary
            break;
1951 fe3e7f2d Joel Martin
#endif
1952 059cef40 aliguori
        case VNC_ENCODING_ZLIB:
1953 059cef40 aliguori
            vs->features |= VNC_FEATURE_ZLIB_MASK;
1954 a9f20d31 Corentin Chary
            vs->vnc_encoding = enc;
1955 059cef40 aliguori
            break;
1956 148954fa Corentin Chary
        case VNC_ENCODING_ZRLE:
1957 148954fa Corentin Chary
            vs->features |= VNC_FEATURE_ZRLE_MASK;
1958 148954fa Corentin Chary
            vs->vnc_encoding = enc;
1959 148954fa Corentin Chary
            break;
1960 148954fa Corentin Chary
        case VNC_ENCODING_ZYWRLE:
1961 148954fa Corentin Chary
            vs->features |= VNC_FEATURE_ZYWRLE_MASK;
1962 148954fa Corentin Chary
            vs->vnc_encoding = enc;
1963 148954fa Corentin Chary
            break;
1964 29fa4ed9 aliguori
        case VNC_ENCODING_DESKTOPRESIZE:
1965 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_RESIZE_MASK;
1966 29fa4ed9 aliguori
            break;
1967 29fa4ed9 aliguori
        case VNC_ENCODING_POINTER_TYPE_CHANGE:
1968 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
1969 29fa4ed9 aliguori
            break;
1970 d467b679 Gerd Hoffmann
        case VNC_ENCODING_RICH_CURSOR:
1971 d467b679 Gerd Hoffmann
            vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
1972 d467b679 Gerd Hoffmann
            break;
1973 29fa4ed9 aliguori
        case VNC_ENCODING_EXT_KEY_EVENT:
1974 9ca313aa aliguori
            send_ext_key_event_ack(vs);
1975 9ca313aa aliguori
            break;
1976 29fa4ed9 aliguori
        case VNC_ENCODING_AUDIO:
1977 429a8ed3 malc
            send_ext_audio_ack(vs);
1978 429a8ed3 malc
            break;
1979 29fa4ed9 aliguori
        case VNC_ENCODING_WMVi:
1980 29fa4ed9 aliguori
            vs->features |= VNC_FEATURE_WMVI_MASK;
1981 ca4cca4d aliguori
            break;
1982 ab99e5c1 Lei Li
        case VNC_ENCODING_LED_STATE:
1983 ab99e5c1 Lei Li
            vs->features |= VNC_FEATURE_LED_STATE_MASK;
1984 ab99e5c1 Lei Li
            break;
1985 fb437313 aliguori
        case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
1986 d1af0e05 Corentin Chary
            vs->tight.compression = (enc & 0x0F);
1987 fb437313 aliguori
            break;
1988 fb437313 aliguori
        case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
1989 b31f519e Corentin Chary
            if (vs->vd->lossy) {
1990 b31f519e Corentin Chary
                vs->tight.quality = (enc & 0x0F);
1991 b31f519e Corentin Chary
            }
1992 fb437313 aliguori
            break;
1993 29fa4ed9 aliguori
        default:
1994 29fa4ed9 aliguori
            VNC_DEBUG("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
1995 29fa4ed9 aliguori
            break;
1996 29fa4ed9 aliguori
        }
1997 24236869 bellard
    }
1998 6356e472 Gerd Hoffmann
    vnc_desktop_resize(vs);
1999 9e8dd451 Jan Kiszka
    check_pointer_type_change(&vs->mouse_mode_notifier, NULL);
2000 ab99e5c1 Lei Li
    vnc_led_state_change(vs);
2001 24236869 bellard
}
2002 24236869 bellard
2003 6cec5487 aliguori
static void set_pixel_conversion(VncState *vs)
2004 6cec5487 aliguori
{
2005 9f64916d Gerd Hoffmann
    pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf);
2006 9f64916d Gerd Hoffmann
2007 9f64916d Gerd Hoffmann
    if (fmt == VNC_SERVER_FB_FORMAT) {
2008 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_copy;
2009 70a4568f Corentin Chary
        vnc_hextile_set_pixel_conversion(vs, 0);
2010 6cec5487 aliguori
    } else {
2011 6cec5487 aliguori
        vs->write_pixels = vnc_write_pixels_generic;
2012 70a4568f Corentin Chary
        vnc_hextile_set_pixel_conversion(vs, 1);
2013 6cec5487 aliguori
    }
2014 6cec5487 aliguori
}
2015 6cec5487 aliguori
2016 24236869 bellard
static void set_pixel_format(VncState *vs,
2017 28a76be8 aliguori
                             int bits_per_pixel, int depth,
2018 28a76be8 aliguori
                             int big_endian_flag, int true_color_flag,
2019 28a76be8 aliguori
                             int red_max, int green_max, int blue_max,
2020 28a76be8 aliguori
                             int red_shift, int green_shift, int blue_shift)
2021 24236869 bellard
{
2022 3512779a bellard
    if (!true_color_flag) {
2023 28a76be8 aliguori
        vnc_client_error(vs);
2024 3512779a bellard
        return;
2025 3512779a bellard
    }
2026 24236869 bellard
2027 9f64916d Gerd Hoffmann
    vs->client_pf.rmax = red_max;
2028 9f64916d Gerd Hoffmann
    vs->client_pf.rbits = hweight_long(red_max);
2029 9f64916d Gerd Hoffmann
    vs->client_pf.rshift = red_shift;
2030 9f64916d Gerd Hoffmann
    vs->client_pf.rmask = red_max << red_shift;
2031 9f64916d Gerd Hoffmann
    vs->client_pf.gmax = green_max;
2032 9f64916d Gerd Hoffmann
    vs->client_pf.gbits = hweight_long(green_max);
2033 9f64916d Gerd Hoffmann
    vs->client_pf.gshift = green_shift;
2034 9f64916d Gerd Hoffmann
    vs->client_pf.gmask = green_max << green_shift;
2035 9f64916d Gerd Hoffmann
    vs->client_pf.bmax = blue_max;
2036 9f64916d Gerd Hoffmann
    vs->client_pf.bbits = hweight_long(blue_max);
2037 9f64916d Gerd Hoffmann
    vs->client_pf.bshift = blue_shift;
2038 9f64916d Gerd Hoffmann
    vs->client_pf.bmask = blue_max << blue_shift;
2039 9f64916d Gerd Hoffmann
    vs->client_pf.bits_per_pixel = bits_per_pixel;
2040 9f64916d Gerd Hoffmann
    vs->client_pf.bytes_per_pixel = bits_per_pixel / 8;
2041 9f64916d Gerd Hoffmann
    vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
2042 9f64916d Gerd Hoffmann
    vs->client_be = big_endian_flag;
2043 6cec5487 aliguori
2044 6cec5487 aliguori
    set_pixel_conversion(vs);
2045 24236869 bellard
2046 1dbfa005 Gerd Hoffmann
    graphic_hw_invalidate(NULL);
2047 1dbfa005 Gerd Hoffmann
    graphic_hw_update(NULL);
2048 24236869 bellard
}
2049 24236869 bellard
2050 ca4cca4d aliguori
static void pixel_format_message (VncState *vs) {
2051 ca4cca4d aliguori
    char pad[3] = { 0, 0, 0 };
2052 ca4cca4d aliguori
2053 9f64916d Gerd Hoffmann
    vs->client_pf = qemu_default_pixelformat(32);
2054 9f64916d Gerd Hoffmann
2055 9f64916d Gerd Hoffmann
    vnc_write_u8(vs, vs->client_pf.bits_per_pixel); /* bits-per-pixel */
2056 9f64916d Gerd Hoffmann
    vnc_write_u8(vs, vs->client_pf.depth); /* depth */
2057 ca4cca4d aliguori
2058 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
2059 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* big-endian-flag */
2060 ca4cca4d aliguori
#else
2061 ca4cca4d aliguori
    vnc_write_u8(vs, 0);             /* big-endian-flag */
2062 ca4cca4d aliguori
#endif
2063 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* true-color-flag */
2064 9f64916d Gerd Hoffmann
    vnc_write_u16(vs, vs->client_pf.rmax);     /* red-max */
2065 9f64916d Gerd Hoffmann
    vnc_write_u16(vs, vs->client_pf.gmax);     /* green-max */
2066 9f64916d Gerd Hoffmann
    vnc_write_u16(vs, vs->client_pf.bmax);     /* blue-max */
2067 9f64916d Gerd Hoffmann
    vnc_write_u8(vs, vs->client_pf.rshift);    /* red-shift */
2068 9f64916d Gerd Hoffmann
    vnc_write_u8(vs, vs->client_pf.gshift);    /* green-shift */
2069 9f64916d Gerd Hoffmann
    vnc_write_u8(vs, vs->client_pf.bshift);    /* blue-shift */
2070 9f64916d Gerd Hoffmann
    vnc_write(vs, pad, 3);           /* padding */
2071 70a4568f Corentin Chary
2072 70a4568f Corentin Chary
    vnc_hextile_set_pixel_conversion(vs, 0);
2073 ca4cca4d aliguori
    vs->write_pixels = vnc_write_pixels_copy;
2074 ca4cca4d aliguori
}
2075 ca4cca4d aliguori
2076 753b4053 aliguori
static void vnc_colordepth(VncState *vs)
2077 7eac3a87 aliguori
{
2078 753b4053 aliguori
    if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
2079 ca4cca4d aliguori
        /* Sending a WMVi message to notify the client*/
2080 bd023f95 Corentin Chary
        vnc_lock_output(vs);
2081 46a183da Daniel P. Berrange
        vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
2082 ca4cca4d aliguori
        vnc_write_u8(vs, 0);
2083 ca4cca4d aliguori
        vnc_write_u16(vs, 1); /* number of rects */
2084 d39fa6d8 Gerd Hoffmann
        vnc_framebuffer_update(vs, 0, 0,
2085 d39fa6d8 Gerd Hoffmann
                               surface_width(vs->vd->ds),
2086 d39fa6d8 Gerd Hoffmann
                               surface_height(vs->vd->ds),
2087 d39fa6d8 Gerd Hoffmann
                               VNC_ENCODING_WMVi);
2088 ca4cca4d aliguori
        pixel_format_message(vs);
2089 bd023f95 Corentin Chary
        vnc_unlock_output(vs);
2090 ca4cca4d aliguori
        vnc_flush(vs);
2091 7eac3a87 aliguori
    } else {
2092 6cec5487 aliguori
        set_pixel_conversion(vs);
2093 7eac3a87 aliguori
    }
2094 7eac3a87 aliguori
}
2095 7eac3a87 aliguori
2096 60fe76f3 ths
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
2097 24236869 bellard
{
2098 24236869 bellard
    int i;
2099 24236869 bellard
    uint16_t limit;
2100 2430ffe4 Stefano Stabellini
    VncDisplay *vd = vs->vd;
2101 2430ffe4 Stefano Stabellini
2102 2430ffe4 Stefano Stabellini
    if (data[0] > 3) {
2103 0f7b2864 Gerd Hoffmann
        update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
2104 2430ffe4 Stefano Stabellini
    }
2105 24236869 bellard
2106 24236869 bellard
    switch (data[0]) {
2107 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_SET_PIXEL_FORMAT:
2108 28a76be8 aliguori
        if (len == 1)
2109 28a76be8 aliguori
            return 20;
2110 28a76be8 aliguori
2111 28a76be8 aliguori
        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
2112 28a76be8 aliguori
                         read_u8(data, 6), read_u8(data, 7),
2113 28a76be8 aliguori
                         read_u16(data, 8), read_u16(data, 10),
2114 28a76be8 aliguori
                         read_u16(data, 12), read_u8(data, 14),
2115 28a76be8 aliguori
                         read_u8(data, 15), read_u8(data, 16));
2116 28a76be8 aliguori
        break;
2117 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_SET_ENCODINGS:
2118 28a76be8 aliguori
        if (len == 1)
2119 28a76be8 aliguori
            return 4;
2120 24236869 bellard
2121 28a76be8 aliguori
        if (len == 4) {
2122 69dd5c9f aliguori
            limit = read_u16(data, 2);
2123 69dd5c9f aliguori
            if (limit > 0)
2124 69dd5c9f aliguori
                return 4 + (limit * 4);
2125 69dd5c9f aliguori
        } else
2126 69dd5c9f aliguori
            limit = read_u16(data, 2);
2127 24236869 bellard
2128 28a76be8 aliguori
        for (i = 0; i < limit; i++) {
2129 28a76be8 aliguori
            int32_t val = read_s32(data, 4 + (i * 4));
2130 28a76be8 aliguori
            memcpy(data + 4 + (i * 4), &val, sizeof(val));
2131 28a76be8 aliguori
        }
2132 24236869 bellard
2133 28a76be8 aliguori
        set_encodings(vs, (int32_t *)(data + 4), limit);
2134 28a76be8 aliguori
        break;
2135 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_FRAMEBUFFER_UPDATE_REQUEST:
2136 28a76be8 aliguori
        if (len == 1)
2137 28a76be8 aliguori
            return 10;
2138 24236869 bellard
2139 28a76be8 aliguori
        framebuffer_update_request(vs,
2140 28a76be8 aliguori
                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
2141 28a76be8 aliguori
                                   read_u16(data, 6), read_u16(data, 8));
2142 28a76be8 aliguori
        break;
2143 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_KEY_EVENT:
2144 28a76be8 aliguori
        if (len == 1)
2145 28a76be8 aliguori
            return 8;
2146 24236869 bellard
2147 28a76be8 aliguori
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
2148 28a76be8 aliguori
        break;
2149 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_POINTER_EVENT:
2150 28a76be8 aliguori
        if (len == 1)
2151 28a76be8 aliguori
            return 6;
2152 24236869 bellard
2153 28a76be8 aliguori
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
2154 28a76be8 aliguori
        break;
2155 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_CUT_TEXT:
2156 28a76be8 aliguori
        if (len == 1)
2157 28a76be8 aliguori
            return 8;
2158 24236869 bellard
2159 28a76be8 aliguori
        if (len == 8) {
2160 baa7666c ths
            uint32_t dlen = read_u32(data, 4);
2161 baa7666c ths
            if (dlen > 0)
2162 baa7666c ths
                return 8 + dlen;
2163 baa7666c ths
        }
2164 24236869 bellard
2165 28a76be8 aliguori
        client_cut_text(vs, read_u32(data, 4), data + 8);
2166 28a76be8 aliguori
        break;
2167 46a183da Daniel P. Berrange
    case VNC_MSG_CLIENT_QEMU:
2168 9ca313aa aliguori
        if (len == 1)
2169 9ca313aa aliguori
            return 2;
2170 9ca313aa aliguori
2171 9ca313aa aliguori
        switch (read_u8(data, 1)) {
2172 46a183da Daniel P. Berrange
        case VNC_MSG_CLIENT_QEMU_EXT_KEY_EVENT:
2173 9ca313aa aliguori
            if (len == 2)
2174 9ca313aa aliguori
                return 12;
2175 9ca313aa aliguori
2176 9ca313aa aliguori
            ext_key_event(vs, read_u16(data, 2),
2177 9ca313aa aliguori
                          read_u32(data, 4), read_u32(data, 8));
2178 9ca313aa aliguori
            break;
2179 46a183da Daniel P. Berrange
        case VNC_MSG_CLIENT_QEMU_AUDIO:
2180 429a8ed3 malc
            if (len == 2)
2181 429a8ed3 malc
                return 4;
2182 429a8ed3 malc
2183 429a8ed3 malc
            switch (read_u16 (data, 2)) {
2184 46a183da Daniel P. Berrange
            case VNC_MSG_CLIENT_QEMU_AUDIO_ENABLE:
2185 429a8ed3 malc
                audio_add(vs);
2186 429a8ed3 malc
                break;
2187 46a183da Daniel P. Berrange
            case VNC_MSG_CLIENT_QEMU_AUDIO_DISABLE:
2188 429a8ed3 malc
                audio_del(vs);
2189 429a8ed3 malc
                break;
2190 46a183da Daniel P. Berrange
            case VNC_MSG_CLIENT_QEMU_AUDIO_SET_FORMAT:
2191 429a8ed3 malc
                if (len == 4)
2192 429a8ed3 malc
                    return 10;
2193 429a8ed3 malc
                switch (read_u8(data, 4)) {
2194 429a8ed3 malc
                case 0: vs->as.fmt = AUD_FMT_U8; break;
2195 429a8ed3 malc
                case 1: vs->as.fmt = AUD_FMT_S8; break;
2196 429a8ed3 malc
                case 2: vs->as.fmt = AUD_FMT_U16; break;
2197 429a8ed3 malc
                case 3: vs->as.fmt = AUD_FMT_S16; break;
2198 429a8ed3 malc
                case 4: vs->as.fmt = AUD_FMT_U32; break;
2199 429a8ed3 malc
                case 5: vs->as.fmt = AUD_FMT_S32; break;
2200 429a8ed3 malc
                default:
2201 429a8ed3 malc
                    printf("Invalid audio format %d\n", read_u8(data, 4));
2202 429a8ed3 malc
                    vnc_client_error(vs);
2203 429a8ed3 malc
                    break;
2204 429a8ed3 malc
                }
2205 429a8ed3 malc
                vs->as.nchannels = read_u8(data, 5);
2206 429a8ed3 malc
                if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
2207 429a8ed3 malc
                    printf("Invalid audio channel coount %d\n",
2208 429a8ed3 malc
                           read_u8(data, 5));
2209 429a8ed3 malc
                    vnc_client_error(vs);
2210 429a8ed3 malc
                    break;
2211 429a8ed3 malc
                }
2212 429a8ed3 malc
                vs->as.freq = read_u32(data, 6);
2213 429a8ed3 malc
                break;
2214 429a8ed3 malc
            default:
2215 429a8ed3 malc
                printf ("Invalid audio message %d\n", read_u8(data, 4));
2216 429a8ed3 malc
                vnc_client_error(vs);
2217 429a8ed3 malc
                break;
2218 429a8ed3 malc
            }
2219 429a8ed3 malc
            break;
2220 429a8ed3 malc
2221 9ca313aa aliguori
        default:
2222 9ca313aa aliguori
            printf("Msg: %d\n", read_u16(data, 0));
2223 9ca313aa aliguori
            vnc_client_error(vs);
2224 9ca313aa aliguori
            break;
2225 9ca313aa aliguori
        }
2226 9ca313aa aliguori
        break;
2227 24236869 bellard
    default:
2228 28a76be8 aliguori
        printf("Msg: %d\n", data[0]);
2229 28a76be8 aliguori
        vnc_client_error(vs);
2230 28a76be8 aliguori
        break;
2231 24236869 bellard
    }
2232 5fafdf24 ths
2233 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
2234 24236869 bellard
    return 0;
2235 24236869 bellard
}
2236 24236869 bellard
2237 60fe76f3 ths
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
2238 24236869 bellard
{
2239 c35734b2 ths
    char buf[1024];
2240 8cf36489 Gerd Hoffmann
    VncShareMode mode;
2241 c35734b2 ths
    int size;
2242 24236869 bellard
2243 8cf36489 Gerd Hoffmann
    mode = data[0] ? VNC_SHARE_MODE_SHARED : VNC_SHARE_MODE_EXCLUSIVE;
2244 8cf36489 Gerd Hoffmann
    switch (vs->vd->share_policy) {
2245 8cf36489 Gerd Hoffmann
    case VNC_SHARE_POLICY_IGNORE:
2246 8cf36489 Gerd Hoffmann
        /*
2247 8cf36489 Gerd Hoffmann
         * Ignore the shared flag.  Nothing to do here.
2248 8cf36489 Gerd Hoffmann
         *
2249 8cf36489 Gerd Hoffmann
         * Doesn't conform to the rfb spec but is traditional qemu
2250 8cf36489 Gerd Hoffmann
         * behavior, thus left here as option for compatibility
2251 8cf36489 Gerd Hoffmann
         * reasons.
2252 8cf36489 Gerd Hoffmann
         */
2253 8cf36489 Gerd Hoffmann
        break;
2254 8cf36489 Gerd Hoffmann
    case VNC_SHARE_POLICY_ALLOW_EXCLUSIVE:
2255 8cf36489 Gerd Hoffmann
        /*
2256 8cf36489 Gerd Hoffmann
         * Policy: Allow clients ask for exclusive access.
2257 8cf36489 Gerd Hoffmann
         *
2258 8cf36489 Gerd Hoffmann
         * Implementation: When a client asks for exclusive access,
2259 8cf36489 Gerd Hoffmann
         * disconnect all others. Shared connects are allowed as long
2260 8cf36489 Gerd Hoffmann
         * as no exclusive connection exists.
2261 8cf36489 Gerd Hoffmann
         *
2262 8cf36489 Gerd Hoffmann
         * This is how the rfb spec suggests to handle the shared flag.
2263 8cf36489 Gerd Hoffmann
         */
2264 8cf36489 Gerd Hoffmann
        if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
2265 8cf36489 Gerd Hoffmann
            VncState *client;
2266 8cf36489 Gerd Hoffmann
            QTAILQ_FOREACH(client, &vs->vd->clients, next) {
2267 8cf36489 Gerd Hoffmann
                if (vs == client) {
2268 8cf36489 Gerd Hoffmann
                    continue;
2269 8cf36489 Gerd Hoffmann
                }
2270 8cf36489 Gerd Hoffmann
                if (client->share_mode != VNC_SHARE_MODE_EXCLUSIVE &&
2271 8cf36489 Gerd Hoffmann
                    client->share_mode != VNC_SHARE_MODE_SHARED) {
2272 8cf36489 Gerd Hoffmann
                    continue;
2273 8cf36489 Gerd Hoffmann
                }
2274 8cf36489 Gerd Hoffmann
                vnc_disconnect_start(client);
2275 8cf36489 Gerd Hoffmann
            }
2276 8cf36489 Gerd Hoffmann
        }
2277 8cf36489 Gerd Hoffmann
        if (mode == VNC_SHARE_MODE_SHARED) {
2278 8cf36489 Gerd Hoffmann
            if (vs->vd->num_exclusive > 0) {
2279 8cf36489 Gerd Hoffmann
                vnc_disconnect_start(vs);
2280 8cf36489 Gerd Hoffmann
                return 0;
2281 8cf36489 Gerd Hoffmann
            }
2282 8cf36489 Gerd Hoffmann
        }
2283 8cf36489 Gerd Hoffmann
        break;
2284 8cf36489 Gerd Hoffmann
    case VNC_SHARE_POLICY_FORCE_SHARED:
2285 8cf36489 Gerd Hoffmann
        /*
2286 8cf36489 Gerd Hoffmann
         * Policy: Shared connects only.
2287 8cf36489 Gerd Hoffmann
         * Implementation: Disallow clients asking for exclusive access.
2288 8cf36489 Gerd Hoffmann
         *
2289 8cf36489 Gerd Hoffmann
         * Useful for shared desktop sessions where you don't want
2290 8cf36489 Gerd Hoffmann
         * someone forgetting to say -shared when running the vnc
2291 8cf36489 Gerd Hoffmann
         * client disconnect everybody else.
2292 8cf36489 Gerd Hoffmann
         */
2293 8cf36489 Gerd Hoffmann
        if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
2294 8cf36489 Gerd Hoffmann
            vnc_disconnect_start(vs);
2295 8cf36489 Gerd Hoffmann
            return 0;
2296 8cf36489 Gerd Hoffmann
        }
2297 8cf36489 Gerd Hoffmann
        break;
2298 8cf36489 Gerd Hoffmann
    }
2299 8cf36489 Gerd Hoffmann
    vnc_set_share_mode(vs, mode);
2300 8cf36489 Gerd Hoffmann
2301 d39fa6d8 Gerd Hoffmann
    vs->client_width = surface_width(vs->vd->ds);
2302 d39fa6d8 Gerd Hoffmann
    vs->client_height = surface_height(vs->vd->ds);
2303 5862d195 Gerd Hoffmann
    vnc_write_u16(vs, vs->client_width);
2304 5862d195 Gerd Hoffmann
    vnc_write_u16(vs, vs->client_height);
2305 24236869 bellard
2306 ca4cca4d aliguori
    pixel_format_message(vs);
2307 24236869 bellard
2308 c35734b2 ths
    if (qemu_name)
2309 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
2310 c35734b2 ths
    else
2311 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU");
2312 c35734b2 ths
2313 c35734b2 ths
    vnc_write_u32(vs, size);
2314 c35734b2 ths
    vnc_write(vs, buf, size);
2315 24236869 bellard
    vnc_flush(vs);
2316 24236869 bellard
2317 4a80dba3 Luiz Capitulino
    vnc_client_cache_auth(vs);
2318 0d2ed46a Luiz Capitulino
    vnc_qmp_event(vs, QEVENT_VNC_INITIALIZED);
2319 4a80dba3 Luiz Capitulino
2320 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
2321 24236869 bellard
2322 24236869 bellard
    return 0;
2323 24236869 bellard
}
2324 24236869 bellard
2325 5fb6c7a8 aliguori
void start_client_init(VncState *vs)
2326 5fb6c7a8 aliguori
{
2327 5fb6c7a8 aliguori
    vnc_read_when(vs, protocol_client_init, 1);
2328 5fb6c7a8 aliguori
}
2329 5fb6c7a8 aliguori
2330 70848515 ths
static void make_challenge(VncState *vs)
2331 70848515 ths
{
2332 70848515 ths
    int i;
2333 70848515 ths
2334 70848515 ths
    srand(time(NULL)+getpid()+getpid()*987654+rand());
2335 70848515 ths
2336 70848515 ths
    for (i = 0 ; i < sizeof(vs->challenge) ; i++)
2337 70848515 ths
        vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
2338 70848515 ths
}
2339 70848515 ths
2340 60fe76f3 ths
static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
2341 70848515 ths
{
2342 60fe76f3 ths
    unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
2343 70848515 ths
    int i, j, pwlen;
2344 60fe76f3 ths
    unsigned char key[8];
2345 3c9405a0 Gerd Hoffmann
    time_t now = time(NULL);
2346 70848515 ths
2347 1cd20f8b Anthony Liguori
    if (!vs->vd->password) {
2348 28a76be8 aliguori
        VNC_DEBUG("No password configured on server");
2349 6bffdf0f Gerd Hoffmann
        goto reject;
2350 70848515 ths
    }
2351 3c9405a0 Gerd Hoffmann
    if (vs->vd->expires < now) {
2352 3c9405a0 Gerd Hoffmann
        VNC_DEBUG("Password is expired");
2353 3c9405a0 Gerd Hoffmann
        goto reject;
2354 3c9405a0 Gerd Hoffmann
    }
2355 70848515 ths
2356 70848515 ths
    memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
2357 70848515 ths
2358 70848515 ths
    /* Calculate the expected challenge response */
2359 753b4053 aliguori
    pwlen = strlen(vs->vd->password);
2360 70848515 ths
    for (i=0; i<sizeof(key); i++)
2361 753b4053 aliguori
        key[i] = i<pwlen ? vs->vd->password[i] : 0;
2362 70848515 ths
    deskey(key, EN0);
2363 70848515 ths
    for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
2364 70848515 ths
        des(response+j, response+j);
2365 70848515 ths
2366 70848515 ths
    /* Compare expected vs actual challenge response */
2367 70848515 ths
    if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
2368 e5bed759 Dong Xu Wang
        VNC_DEBUG("Client challenge response did not match\n");
2369 6bffdf0f Gerd Hoffmann
        goto reject;
2370 70848515 ths
    } else {
2371 28a76be8 aliguori
        VNC_DEBUG("Accepting VNC challenge response\n");
2372 28a76be8 aliguori
        vnc_write_u32(vs, 0); /* Accept auth */
2373 28a76be8 aliguori
        vnc_flush(vs);
2374 70848515 ths
2375 5fb6c7a8 aliguori
        start_client_init(vs);
2376 70848515 ths
    }
2377 70848515 ths
    return 0;
2378 6bffdf0f Gerd Hoffmann
2379 6bffdf0f Gerd Hoffmann
reject:
2380 6bffdf0f Gerd Hoffmann
    vnc_write_u32(vs, 1); /* Reject auth */
2381 6bffdf0f Gerd Hoffmann
    if (vs->minor >= 8) {
2382 6bffdf0f Gerd Hoffmann
        static const char err[] = "Authentication failed";
2383 6bffdf0f Gerd Hoffmann
        vnc_write_u32(vs, sizeof(err));
2384 6bffdf0f Gerd Hoffmann
        vnc_write(vs, err, sizeof(err));
2385 6bffdf0f Gerd Hoffmann
    }
2386 6bffdf0f Gerd Hoffmann
    vnc_flush(vs);
2387 6bffdf0f Gerd Hoffmann
    vnc_client_error(vs);
2388 6bffdf0f Gerd Hoffmann
    return 0;
2389 70848515 ths
}
2390 70848515 ths
2391 5fb6c7a8 aliguori
void start_auth_vnc(VncState *vs)
2392 70848515 ths
{
2393 70848515 ths
    make_challenge(vs);
2394 70848515 ths
    /* Send client a 'random' challenge */
2395 70848515 ths
    vnc_write(vs, vs->challenge, sizeof(vs->challenge));
2396 70848515 ths
    vnc_flush(vs);
2397 70848515 ths
2398 70848515 ths
    vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
2399 469b15c6 ths
}
2400 469b15c6 ths
2401 469b15c6 ths
2402 60fe76f3 ths
static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2403 70848515 ths
{
2404 70848515 ths
    /* We only advertise 1 auth scheme at a time, so client
2405 70848515 ths
     * must pick the one we sent. Verify this */
2406 7e7e2ebc Daniel P. Berrange
    if (data[0] != vs->auth) { /* Reject auth */
2407 1263b7d6 aliguori
       VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
2408 70848515 ths
       vnc_write_u32(vs, 1);
2409 70848515 ths
       if (vs->minor >= 8) {
2410 70848515 ths
           static const char err[] = "Authentication failed";
2411 70848515 ths
           vnc_write_u32(vs, sizeof(err));
2412 70848515 ths
           vnc_write(vs, err, sizeof(err));
2413 70848515 ths
       }
2414 70848515 ths
       vnc_client_error(vs);
2415 70848515 ths
    } else { /* Accept requested auth */
2416 70848515 ths
       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2417 7e7e2ebc Daniel P. Berrange
       switch (vs->auth) {
2418 70848515 ths
       case VNC_AUTH_NONE:
2419 70848515 ths
           VNC_DEBUG("Accept auth none\n");
2420 a26c97ad balrog
           if (vs->minor >= 8) {
2421 a26c97ad balrog
               vnc_write_u32(vs, 0); /* Accept auth completion */
2422 a26c97ad balrog
               vnc_flush(vs);
2423 a26c97ad balrog
           }
2424 5fb6c7a8 aliguori
           start_client_init(vs);
2425 70848515 ths
           break;
2426 70848515 ths
2427 70848515 ths
       case VNC_AUTH_VNC:
2428 70848515 ths
           VNC_DEBUG("Start VNC auth\n");
2429 5fb6c7a8 aliguori
           start_auth_vnc(vs);
2430 5fb6c7a8 aliguori
           break;
2431 70848515 ths
2432 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2433 8d5d2d4c ths
       case VNC_AUTH_VENCRYPT:
2434 3a93113a Dong Xu Wang
           VNC_DEBUG("Accept VeNCrypt auth\n");
2435 5fb6c7a8 aliguori
           start_auth_vencrypt(vs);
2436 5fb6c7a8 aliguori
           break;
2437 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2438 8d5d2d4c ths
2439 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
2440 2f9606b3 aliguori
       case VNC_AUTH_SASL:
2441 2f9606b3 aliguori
           VNC_DEBUG("Accept SASL auth\n");
2442 2f9606b3 aliguori
           start_auth_sasl(vs);
2443 2f9606b3 aliguori
           break;
2444 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
2445 2f9606b3 aliguori
2446 70848515 ths
       default: /* Should not be possible, but just in case */
2447 7e7e2ebc Daniel P. Berrange
           VNC_DEBUG("Reject auth %d server code bug\n", vs->auth);
2448 70848515 ths
           vnc_write_u8(vs, 1);
2449 70848515 ths
           if (vs->minor >= 8) {
2450 70848515 ths
               static const char err[] = "Authentication failed";
2451 70848515 ths
               vnc_write_u32(vs, sizeof(err));
2452 70848515 ths
               vnc_write(vs, err, sizeof(err));
2453 70848515 ths
           }
2454 70848515 ths
           vnc_client_error(vs);
2455 70848515 ths
       }
2456 70848515 ths
    }
2457 70848515 ths
    return 0;
2458 70848515 ths
}
2459 70848515 ths
2460 60fe76f3 ths
static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2461 24236869 bellard
{
2462 24236869 bellard
    char local[13];
2463 24236869 bellard
2464 24236869 bellard
    memcpy(local, version, 12);
2465 24236869 bellard
    local[12] = 0;
2466 24236869 bellard
2467 70848515 ths
    if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2468 28a76be8 aliguori
        VNC_DEBUG("Malformed protocol version %s\n", local);
2469 28a76be8 aliguori
        vnc_client_error(vs);
2470 28a76be8 aliguori
        return 0;
2471 24236869 bellard
    }
2472 70848515 ths
    VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2473 70848515 ths
    if (vs->major != 3 ||
2474 28a76be8 aliguori
        (vs->minor != 3 &&
2475 28a76be8 aliguori
         vs->minor != 4 &&
2476 28a76be8 aliguori
         vs->minor != 5 &&
2477 28a76be8 aliguori
         vs->minor != 7 &&
2478 28a76be8 aliguori
         vs->minor != 8)) {
2479 28a76be8 aliguori
        VNC_DEBUG("Unsupported client version\n");
2480 28a76be8 aliguori
        vnc_write_u32(vs, VNC_AUTH_INVALID);
2481 28a76be8 aliguori
        vnc_flush(vs);
2482 28a76be8 aliguori
        vnc_client_error(vs);
2483 28a76be8 aliguori
        return 0;
2484 70848515 ths
    }
2485 b0566f4f ths
    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2486 70848515 ths
     * as equivalent to v3.3 by servers
2487 70848515 ths
     */
2488 b0566f4f ths
    if (vs->minor == 4 || vs->minor == 5)
2489 28a76be8 aliguori
        vs->minor = 3;
2490 70848515 ths
2491 70848515 ths
    if (vs->minor == 3) {
2492 7e7e2ebc Daniel P. Berrange
        if (vs->auth == VNC_AUTH_NONE) {
2493 70848515 ths
            VNC_DEBUG("Tell client auth none\n");
2494 7e7e2ebc Daniel P. Berrange
            vnc_write_u32(vs, vs->auth);
2495 70848515 ths
            vnc_flush(vs);
2496 28a76be8 aliguori
            start_client_init(vs);
2497 7e7e2ebc Daniel P. Berrange
       } else if (vs->auth == VNC_AUTH_VNC) {
2498 70848515 ths
            VNC_DEBUG("Tell client VNC auth\n");
2499 7e7e2ebc Daniel P. Berrange
            vnc_write_u32(vs, vs->auth);
2500 70848515 ths
            vnc_flush(vs);
2501 70848515 ths
            start_auth_vnc(vs);
2502 70848515 ths
       } else {
2503 7e7e2ebc Daniel P. Berrange
            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
2504 70848515 ths
            vnc_write_u32(vs, VNC_AUTH_INVALID);
2505 70848515 ths
            vnc_flush(vs);
2506 70848515 ths
            vnc_client_error(vs);
2507 70848515 ths
       }
2508 70848515 ths
    } else {
2509 7e7e2ebc Daniel P. Berrange
        VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
2510 28a76be8 aliguori
        vnc_write_u8(vs, 1); /* num auth */
2511 7e7e2ebc Daniel P. Berrange
        vnc_write_u8(vs, vs->auth);
2512 28a76be8 aliguori
        vnc_read_when(vs, protocol_client_auth, 1);
2513 28a76be8 aliguori
        vnc_flush(vs);
2514 70848515 ths
    }
2515 24236869 bellard
2516 24236869 bellard
    return 0;
2517 24236869 bellard
}
2518 24236869 bellard
2519 999342a0 Corentin Chary
static VncRectStat *vnc_stat_rect(VncDisplay *vd, int x, int y)
2520 999342a0 Corentin Chary
{
2521 999342a0 Corentin Chary
    struct VncSurface *vs = &vd->guest;
2522 999342a0 Corentin Chary
2523 999342a0 Corentin Chary
    return &vs->stats[y / VNC_STAT_RECT][x / VNC_STAT_RECT];
2524 999342a0 Corentin Chary
}
2525 999342a0 Corentin Chary
2526 7d964c9d Corentin Chary
void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h)
2527 7d964c9d Corentin Chary
{
2528 7d964c9d Corentin Chary
    int i, j;
2529 7d964c9d Corentin Chary
2530 7d964c9d Corentin Chary
    w = (x + w) / VNC_STAT_RECT;
2531 7d964c9d Corentin Chary
    h = (y + h) / VNC_STAT_RECT;
2532 7d964c9d Corentin Chary
    x /= VNC_STAT_RECT;
2533 7d964c9d Corentin Chary
    y /= VNC_STAT_RECT;
2534 7d964c9d Corentin Chary
2535 207f328a Corentin Chary
    for (j = y; j <= h; j++) {
2536 207f328a Corentin Chary
        for (i = x; i <= w; i++) {
2537 7d964c9d Corentin Chary
            vs->lossy_rect[j][i] = 1;
2538 7d964c9d Corentin Chary
        }
2539 7d964c9d Corentin Chary
    }
2540 7d964c9d Corentin Chary
}
2541 7d964c9d Corentin Chary
2542 7d964c9d Corentin Chary
static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
2543 7d964c9d Corentin Chary
{
2544 7d964c9d Corentin Chary
    VncState *vs;
2545 7d964c9d Corentin Chary
    int sty = y / VNC_STAT_RECT;
2546 7d964c9d Corentin Chary
    int stx = x / VNC_STAT_RECT;
2547 7d964c9d Corentin Chary
    int has_dirty = 0;
2548 7d964c9d Corentin Chary
2549 7d964c9d Corentin Chary
    y = y / VNC_STAT_RECT * VNC_STAT_RECT;
2550 7d964c9d Corentin Chary
    x = x / VNC_STAT_RECT * VNC_STAT_RECT;
2551 7d964c9d Corentin Chary
2552 7d964c9d Corentin Chary
    QTAILQ_FOREACH(vs, &vd->clients, next) {
2553 bc2429b9 Corentin Chary
        int j;
2554 7d964c9d Corentin Chary
2555 7d964c9d Corentin Chary
        /* kernel send buffers are full -> refresh later */
2556 7d964c9d Corentin Chary
        if (vs->output.offset) {
2557 7d964c9d Corentin Chary
            continue;
2558 7d964c9d Corentin Chary
        }
2559 7d964c9d Corentin Chary
2560 7d964c9d Corentin Chary
        if (!vs->lossy_rect[sty][stx]) {
2561 7d964c9d Corentin Chary
            continue;
2562 7d964c9d Corentin Chary
        }
2563 207f328a Corentin Chary
2564 7d964c9d Corentin Chary
        vs->lossy_rect[sty][stx] = 0;
2565 7d964c9d Corentin Chary
        for (j = 0; j < VNC_STAT_RECT; ++j) {
2566 bc2429b9 Corentin Chary
            bitmap_set(vs->dirty[y + j], x / 16, VNC_STAT_RECT / 16);
2567 7d964c9d Corentin Chary
        }
2568 7d964c9d Corentin Chary
        has_dirty++;
2569 7d964c9d Corentin Chary
    }
2570 207f328a Corentin Chary
2571 7d964c9d Corentin Chary
    return has_dirty;
2572 7d964c9d Corentin Chary
}
2573 7d964c9d Corentin Chary
2574 7d964c9d Corentin Chary
static int vnc_update_stats(VncDisplay *vd,  struct timeval * tv)
2575 999342a0 Corentin Chary
{
2576 9f64916d Gerd Hoffmann
    int width = pixman_image_get_width(vd->guest.fb);
2577 9f64916d Gerd Hoffmann
    int height = pixman_image_get_height(vd->guest.fb);
2578 999342a0 Corentin Chary
    int x, y;
2579 999342a0 Corentin Chary
    struct timeval res;
2580 7d964c9d Corentin Chary
    int has_dirty = 0;
2581 999342a0 Corentin Chary
2582 9f64916d Gerd Hoffmann
    for (y = 0; y < height; y += VNC_STAT_RECT) {
2583 9f64916d Gerd Hoffmann
        for (x = 0; x < width; x += VNC_STAT_RECT) {
2584 999342a0 Corentin Chary
            VncRectStat *rect = vnc_stat_rect(vd, x, y);
2585 999342a0 Corentin Chary
2586 999342a0 Corentin Chary
            rect->updated = false;
2587 999342a0 Corentin Chary
        }
2588 999342a0 Corentin Chary
    }
2589 999342a0 Corentin Chary
2590 ad620c29 Blue Swirl
    qemu_timersub(tv, &VNC_REFRESH_STATS, &res);
2591 999342a0 Corentin Chary
2592 999342a0 Corentin Chary
    if (timercmp(&vd->guest.last_freq_check, &res, >)) {
2593 7d964c9d Corentin Chary
        return has_dirty;
2594 999342a0 Corentin Chary
    }
2595 999342a0 Corentin Chary
    vd->guest.last_freq_check = *tv;
2596 999342a0 Corentin Chary
2597 9f64916d Gerd Hoffmann
    for (y = 0; y < height; y += VNC_STAT_RECT) {
2598 9f64916d Gerd Hoffmann
        for (x = 0; x < width; x += VNC_STAT_RECT) {
2599 999342a0 Corentin Chary
            VncRectStat *rect= vnc_stat_rect(vd, x, y);
2600 999342a0 Corentin Chary
            int count = ARRAY_SIZE(rect->times);
2601 999342a0 Corentin Chary
            struct timeval min, max;
2602 999342a0 Corentin Chary
2603 999342a0 Corentin Chary
            if (!timerisset(&rect->times[count - 1])) {
2604 999342a0 Corentin Chary
                continue ;
2605 999342a0 Corentin Chary
            }
2606 999342a0 Corentin Chary
2607 999342a0 Corentin Chary
            max = rect->times[(rect->idx + count - 1) % count];
2608 ad620c29 Blue Swirl
            qemu_timersub(tv, &max, &res);
2609 999342a0 Corentin Chary
2610 999342a0 Corentin Chary
            if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {
2611 999342a0 Corentin Chary
                rect->freq = 0;
2612 7d964c9d Corentin Chary
                has_dirty += vnc_refresh_lossy_rect(vd, x, y);
2613 999342a0 Corentin Chary
                memset(rect->times, 0, sizeof (rect->times));
2614 999342a0 Corentin Chary
                continue ;
2615 999342a0 Corentin Chary
            }
2616 999342a0 Corentin Chary
2617 999342a0 Corentin Chary
            min = rect->times[rect->idx];
2618 999342a0 Corentin Chary
            max = rect->times[(rect->idx + count - 1) % count];
2619 ad620c29 Blue Swirl
            qemu_timersub(&max, &min, &res);
2620 999342a0 Corentin Chary
2621 999342a0 Corentin Chary
            rect->freq = res.tv_sec + res.tv_usec / 1000000.;
2622 999342a0 Corentin Chary
            rect->freq /= count;
2623 999342a0 Corentin Chary
            rect->freq = 1. / rect->freq;
2624 999342a0 Corentin Chary
        }
2625 999342a0 Corentin Chary
    }
2626 7d964c9d Corentin Chary
    return has_dirty;
2627 999342a0 Corentin Chary
}
2628 999342a0 Corentin Chary
2629 999342a0 Corentin Chary
double vnc_update_freq(VncState *vs, int x, int y, int w, int h)
2630 999342a0 Corentin Chary
{
2631 999342a0 Corentin Chary
    int i, j;
2632 999342a0 Corentin Chary
    double total = 0;
2633 999342a0 Corentin Chary
    int num = 0;
2634 999342a0 Corentin Chary
2635 999342a0 Corentin Chary
    x =  (x / VNC_STAT_RECT) * VNC_STAT_RECT;
2636 999342a0 Corentin Chary
    y =  (y / VNC_STAT_RECT) * VNC_STAT_RECT;
2637 999342a0 Corentin Chary
2638 999342a0 Corentin Chary
    for (j = y; j <= y + h; j += VNC_STAT_RECT) {
2639 999342a0 Corentin Chary
        for (i = x; i <= x + w; i += VNC_STAT_RECT) {
2640 999342a0 Corentin Chary
            total += vnc_stat_rect(vs->vd, i, j)->freq;
2641 999342a0 Corentin Chary
            num++;
2642 999342a0 Corentin Chary
        }
2643 999342a0 Corentin Chary
    }
2644 999342a0 Corentin Chary
2645 999342a0 Corentin Chary
    if (num) {
2646 999342a0 Corentin Chary
        return total / num;
2647 999342a0 Corentin Chary
    } else {
2648 999342a0 Corentin Chary
        return 0;
2649 999342a0 Corentin Chary
    }
2650 999342a0 Corentin Chary
}
2651 999342a0 Corentin Chary
2652 999342a0 Corentin Chary
static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv)
2653 999342a0 Corentin Chary
{
2654 999342a0 Corentin Chary
    VncRectStat *rect;
2655 999342a0 Corentin Chary
2656 999342a0 Corentin Chary
    rect = vnc_stat_rect(vd, x, y);
2657 999342a0 Corentin Chary
    if (rect->updated) {
2658 999342a0 Corentin Chary
        return ;
2659 999342a0 Corentin Chary
    }
2660 999342a0 Corentin Chary
    rect->times[rect->idx] = *tv;
2661 999342a0 Corentin Chary
    rect->idx = (rect->idx + 1) % ARRAY_SIZE(rect->times);
2662 999342a0 Corentin Chary
    rect->updated = true;
2663 999342a0 Corentin Chary
}
2664 999342a0 Corentin Chary
2665 1fc62412 Stefano Stabellini
static int vnc_refresh_server_surface(VncDisplay *vd)
2666 1fc62412 Stefano Stabellini
{
2667 9f64916d Gerd Hoffmann
    int width = pixman_image_get_width(vd->guest.fb);
2668 9f64916d Gerd Hoffmann
    int height = pixman_image_get_height(vd->guest.fb);
2669 1fc62412 Stefano Stabellini
    int y;
2670 1fc62412 Stefano Stabellini
    uint8_t *guest_row;
2671 1fc62412 Stefano Stabellini
    uint8_t *server_row;
2672 1fc62412 Stefano Stabellini
    int cmp_bytes;
2673 41b4bef6 Amit Shah
    VncState *vs;
2674 1fc62412 Stefano Stabellini
    int has_dirty = 0;
2675 9f64916d Gerd Hoffmann
    pixman_image_t *tmpbuf = NULL;
2676 1fc62412 Stefano Stabellini
2677 80e0c8c3 Corentin Chary
    struct timeval tv = { 0, 0 };
2678 999342a0 Corentin Chary
2679 80e0c8c3 Corentin Chary
    if (!vd->non_adaptive) {
2680 80e0c8c3 Corentin Chary
        gettimeofday(&tv, NULL);
2681 80e0c8c3 Corentin Chary
        has_dirty = vnc_update_stats(vd, &tv);
2682 80e0c8c3 Corentin Chary
    }
2683 999342a0 Corentin Chary
2684 1fc62412 Stefano Stabellini
    /*
2685 1fc62412 Stefano Stabellini
     * Walk through the guest dirty map.
2686 1fc62412 Stefano Stabellini
     * Check and copy modified bits from guest to server surface.
2687 1fc62412 Stefano Stabellini
     * Update server dirty map.
2688 1fc62412 Stefano Stabellini
     */
2689 9f64916d Gerd Hoffmann
    cmp_bytes = 64;
2690 9f64916d Gerd Hoffmann
    if (cmp_bytes > vnc_server_fb_stride(vd)) {
2691 9f64916d Gerd Hoffmann
        cmp_bytes = vnc_server_fb_stride(vd);
2692 9f64916d Gerd Hoffmann
    }
2693 9f64916d Gerd Hoffmann
    if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
2694 9f64916d Gerd Hoffmann
        int width = pixman_image_get_width(vd->server);
2695 9f64916d Gerd Hoffmann
        tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
2696 9e4dd565 Stefan Weil
    }
2697 9f64916d Gerd Hoffmann
    guest_row = (uint8_t *)pixman_image_get_data(vd->guest.fb);
2698 9f64916d Gerd Hoffmann
    server_row = (uint8_t *)pixman_image_get_data(vd->server);
2699 9f64916d Gerd Hoffmann
    for (y = 0; y < height; y++) {
2700 23bfe28f Stefan Weil
        if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) {
2701 1fc62412 Stefano Stabellini
            int x;
2702 1fc62412 Stefano Stabellini
            uint8_t *guest_ptr;
2703 1fc62412 Stefano Stabellini
            uint8_t *server_ptr;
2704 1fc62412 Stefano Stabellini
2705 9f64916d Gerd Hoffmann
            if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
2706 bc210eb1 Gerd Hoffmann
                qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, 0, y);
2707 9f64916d Gerd Hoffmann
                guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf);
2708 9f64916d Gerd Hoffmann
            } else {
2709 9f64916d Gerd Hoffmann
                guest_ptr = guest_row;
2710 9f64916d Gerd Hoffmann
            }
2711 1fc62412 Stefano Stabellini
            server_ptr = server_row;
2712 1fc62412 Stefano Stabellini
2713 9f64916d Gerd Hoffmann
            for (x = 0; x + 15 < width;
2714 1fc62412 Stefano Stabellini
                    x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
2715 bc2429b9 Corentin Chary
                if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
2716 1fc62412 Stefano Stabellini
                    continue;
2717 1fc62412 Stefano Stabellini
                if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
2718 1fc62412 Stefano Stabellini
                    continue;
2719 1fc62412 Stefano Stabellini
                memcpy(server_ptr, guest_ptr, cmp_bytes);
2720 80e0c8c3 Corentin Chary
                if (!vd->non_adaptive)
2721 80e0c8c3 Corentin Chary
                    vnc_rect_updated(vd, x, y, &tv);
2722 41b4bef6 Amit Shah
                QTAILQ_FOREACH(vs, &vd->clients, next) {
2723 bc2429b9 Corentin Chary
                    set_bit((x / 16), vs->dirty[y]);
2724 1fc62412 Stefano Stabellini
                }
2725 1fc62412 Stefano Stabellini
                has_dirty++;
2726 1fc62412 Stefano Stabellini
            }
2727 1fc62412 Stefano Stabellini
        }
2728 9f64916d Gerd Hoffmann
        guest_row  += pixman_image_get_stride(vd->guest.fb);
2729 9f64916d Gerd Hoffmann
        server_row += pixman_image_get_stride(vd->server);
2730 1fc62412 Stefano Stabellini
    }
2731 9f64916d Gerd Hoffmann
    qemu_pixman_image_unref(tmpbuf);
2732 1fc62412 Stefano Stabellini
    return has_dirty;
2733 1fc62412 Stefano Stabellini
}
2734 1fc62412 Stefano Stabellini
2735 0f7b2864 Gerd Hoffmann
static void vnc_refresh(DisplayChangeListener *dcl)
2736 703bc68f Stefano Stabellini
{
2737 0f7b2864 Gerd Hoffmann
    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
2738 41b4bef6 Amit Shah
    VncState *vs, *vn;
2739 41b4bef6 Amit Shah
    int has_dirty, rects = 0;
2740 703bc68f Stefano Stabellini
2741 1dbfa005 Gerd Hoffmann
    graphic_hw_update(NULL);
2742 703bc68f Stefano Stabellini
2743 bd023f95 Corentin Chary
    if (vnc_trylock_display(vd)) {
2744 0f7b2864 Gerd Hoffmann
        update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
2745 bd023f95 Corentin Chary
        return;
2746 bd023f95 Corentin Chary
    }
2747 bd023f95 Corentin Chary
2748 1fc62412 Stefano Stabellini
    has_dirty = vnc_refresh_server_surface(vd);
2749 bd023f95 Corentin Chary
    vnc_unlock_display(vd);
2750 1fc62412 Stefano Stabellini
2751 41b4bef6 Amit Shah
    QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
2752 2430ffe4 Stefano Stabellini
        rects += vnc_update_client(vs, has_dirty);
2753 6185c578 Stefano Stabellini
        /* vs might be free()ed here */
2754 703bc68f Stefano Stabellini
    }
2755 bd023f95 Corentin Chary
2756 0f7b2864 Gerd Hoffmann
    if (QTAILQ_EMPTY(&vd->clients)) {
2757 0f7b2864 Gerd Hoffmann
        update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_MAX);
2758 83755c17 Stefano Stabellini
        return;
2759 0f7b2864 Gerd Hoffmann
    }
2760 703bc68f Stefano Stabellini
2761 2430ffe4 Stefano Stabellini
    if (has_dirty && rects) {
2762 0f7b2864 Gerd Hoffmann
        vd->dcl.update_interval /= 2;
2763 0f7b2864 Gerd Hoffmann
        if (vd->dcl.update_interval < VNC_REFRESH_INTERVAL_BASE) {
2764 0f7b2864 Gerd Hoffmann
            vd->dcl.update_interval = VNC_REFRESH_INTERVAL_BASE;
2765 0f7b2864 Gerd Hoffmann
        }
2766 2430ffe4 Stefano Stabellini
    } else {
2767 0f7b2864 Gerd Hoffmann
        vd->dcl.update_interval += VNC_REFRESH_INTERVAL_INC;
2768 0f7b2864 Gerd Hoffmann
        if (vd->dcl.update_interval > VNC_REFRESH_INTERVAL_MAX) {
2769 0f7b2864 Gerd Hoffmann
            vd->dcl.update_interval = VNC_REFRESH_INTERVAL_MAX;
2770 0f7b2864 Gerd Hoffmann
        }
2771 703bc68f Stefano Stabellini
    }
2772 703bc68f Stefano Stabellini
}
2773 703bc68f Stefano Stabellini
2774 7536ee4b Tim Hardeck
static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
2775 3aa3eea3 balrog
{
2776 7267c094 Anthony Liguori
    VncState *vs = g_malloc0(sizeof(VncState));
2777 7d964c9d Corentin Chary
    int i;
2778 7d964c9d Corentin Chary
2779 753b4053 aliguori
    vs->csock = csock;
2780 7e7e2ebc Daniel P. Berrange
2781 7e7e2ebc Daniel P. Berrange
    if (skipauth) {
2782 7e7e2ebc Daniel P. Berrange
        vs->auth = VNC_AUTH_NONE;
2783 7e7e2ebc Daniel P. Berrange
#ifdef CONFIG_VNC_TLS
2784 7e7e2ebc Daniel P. Berrange
        vs->subauth = VNC_AUTH_INVALID;
2785 7e7e2ebc Daniel P. Berrange
#endif
2786 7e7e2ebc Daniel P. Berrange
    } else {
2787 7e7e2ebc Daniel P. Berrange
        vs->auth = vd->auth;
2788 7e7e2ebc Daniel P. Berrange
#ifdef CONFIG_VNC_TLS
2789 7e7e2ebc Daniel P. Berrange
        vs->subauth = vd->subauth;
2790 7e7e2ebc Daniel P. Berrange
#endif
2791 7e7e2ebc Daniel P. Berrange
    }
2792 7e7e2ebc Daniel P. Berrange
2793 7267c094 Anthony Liguori
    vs->lossy_rect = g_malloc0(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
2794 7d964c9d Corentin Chary
    for (i = 0; i < VNC_STAT_ROWS; ++i) {
2795 7267c094 Anthony Liguori
        vs->lossy_rect[i] = g_malloc0(VNC_STAT_COLS * sizeof (uint8_t));
2796 7d964c9d Corentin Chary
    }
2797 753b4053 aliguori
2798 753b4053 aliguori
    VNC_DEBUG("New client on socket %d\n", csock);
2799 0f7b2864 Gerd Hoffmann
    update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
2800 f9e8cacc Stefan Hajnoczi
    qemu_set_nonblock(vs->csock);
2801 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
2802 7536ee4b Tim Hardeck
    if (websocket) {
2803 7536ee4b Tim Hardeck
        vs->websocket = 1;
2804 0057a0d5 Tim Hardeck
#ifdef CONFIG_VNC_TLS
2805 0057a0d5 Tim Hardeck
        if (vd->tls.x509cert) {
2806 0057a0d5 Tim Hardeck
            qemu_set_fd_handler2(vs->csock, NULL, vncws_tls_handshake_peek,
2807 0057a0d5 Tim Hardeck
                                 NULL, vs);
2808 0057a0d5 Tim Hardeck
        } else
2809 0057a0d5 Tim Hardeck
#endif /* CONFIG_VNC_TLS */
2810 0057a0d5 Tim Hardeck
        {
2811 0057a0d5 Tim Hardeck
            qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read,
2812 0057a0d5 Tim Hardeck
                                 NULL, vs);
2813 0057a0d5 Tim Hardeck
        }
2814 7536ee4b Tim Hardeck
    } else
2815 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
2816 7536ee4b Tim Hardeck
    {
2817 7536ee4b Tim Hardeck
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2818 7536ee4b Tim Hardeck
    }
2819 753b4053 aliguori
2820 4a80dba3 Luiz Capitulino
    vnc_client_cache_addr(vs);
2821 586153d9 Luiz Capitulino
    vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
2822 8cf36489 Gerd Hoffmann
    vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING);
2823 4a80dba3 Luiz Capitulino
2824 753b4053 aliguori
    vs->vd = vd;
2825 7536ee4b Tim Hardeck
2826 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
2827 7536ee4b Tim Hardeck
    if (!vs->websocket)
2828 7536ee4b Tim Hardeck
#endif
2829 7536ee4b Tim Hardeck
    {
2830 7536ee4b Tim Hardeck
        vnc_init_state(vs);
2831 7536ee4b Tim Hardeck
    }
2832 7536ee4b Tim Hardeck
}
2833 7536ee4b Tim Hardeck
2834 7536ee4b Tim Hardeck
void vnc_init_state(VncState *vs)
2835 7536ee4b Tim Hardeck
{
2836 6fd8e79a Tim Hardeck
    vs->initialized = true;
2837 7536ee4b Tim Hardeck
    VncDisplay *vd = vs->vd;
2838 7536ee4b Tim Hardeck
2839 753b4053 aliguori
    vs->last_x = -1;
2840 753b4053 aliguori
    vs->last_y = -1;
2841 753b4053 aliguori
2842 753b4053 aliguori
    vs->as.freq = 44100;
2843 753b4053 aliguori
    vs->as.nchannels = 2;
2844 753b4053 aliguori
    vs->as.fmt = AUD_FMT_S16;
2845 753b4053 aliguori
    vs->as.endianness = 0;
2846 753b4053 aliguori
2847 bd023f95 Corentin Chary
    qemu_mutex_init(&vs->output_mutex);
2848 175b2a6e Corentin Chary
    vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
2849 bd023f95 Corentin Chary
2850 41b4bef6 Amit Shah
    QTAILQ_INSERT_HEAD(&vd->clients, vs, next);
2851 1fc62412 Stefano Stabellini
2852 1dbfa005 Gerd Hoffmann
    graphic_hw_update(NULL);
2853 1fc62412 Stefano Stabellini
2854 3aa3eea3 balrog
    vnc_write(vs, "RFB 003.008\n", 12);
2855 3aa3eea3 balrog
    vnc_flush(vs);
2856 3aa3eea3 balrog
    vnc_read_when(vs, protocol_version, 12);
2857 53762ddb malc
    reset_keys(vs);
2858 3a0558b5 Gerd Hoffmann
    if (vs->vd->lock_key_sync)
2859 3a0558b5 Gerd Hoffmann
        vs->led = qemu_add_led_event_handler(kbd_leds, vs);
2860 753b4053 aliguori
2861 37c34d9d Anthony Liguori
    vs->mouse_mode_notifier.notify = check_pointer_type_change;
2862 37c34d9d Anthony Liguori
    qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
2863 37c34d9d Anthony Liguori
2864 198a0039 Gerd Hoffmann
    /* vs might be free()ed here */
2865 3aa3eea3 balrog
}
2866 3aa3eea3 balrog
2867 7536ee4b Tim Hardeck
static void vnc_listen_read(void *opaque, bool websocket)
2868 24236869 bellard
{
2869 753b4053 aliguori
    VncDisplay *vs = opaque;
2870 24236869 bellard
    struct sockaddr_in addr;
2871 24236869 bellard
    socklen_t addrlen = sizeof(addr);
2872 7536ee4b Tim Hardeck
    int csock;
2873 24236869 bellard
2874 9f60ad50 balrog
    /* Catch-up */
2875 1dbfa005 Gerd Hoffmann
    graphic_hw_update(NULL);
2876 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
2877 7536ee4b Tim Hardeck
    if (websocket) {
2878 7536ee4b Tim Hardeck
        csock = qemu_accept(vs->lwebsock, (struct sockaddr *)&addr, &addrlen);
2879 7536ee4b Tim Hardeck
    } else
2880 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
2881 7536ee4b Tim Hardeck
    {
2882 7536ee4b Tim Hardeck
        csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2883 7536ee4b Tim Hardeck
    }
2884 9f60ad50 balrog
2885 753b4053 aliguori
    if (csock != -1) {
2886 7536ee4b Tim Hardeck
        vnc_connect(vs, csock, 0, websocket);
2887 24236869 bellard
    }
2888 24236869 bellard
}
2889 24236869 bellard
2890 7536ee4b Tim Hardeck
static void vnc_listen_regular_read(void *opaque)
2891 7536ee4b Tim Hardeck
{
2892 7536ee4b Tim Hardeck
    vnc_listen_read(opaque, 0);
2893 7536ee4b Tim Hardeck
}
2894 7536ee4b Tim Hardeck
2895 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
2896 7536ee4b Tim Hardeck
static void vnc_listen_websocket_read(void *opaque)
2897 7536ee4b Tim Hardeck
{
2898 7536ee4b Tim Hardeck
    vnc_listen_read(opaque, 1);
2899 7536ee4b Tim Hardeck
}
2900 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
2901 7536ee4b Tim Hardeck
2902 7c20b4a3 Gerd Hoffmann
static const DisplayChangeListenerOps dcl_ops = {
2903 7c20b4a3 Gerd Hoffmann
    .dpy_name          = "vnc",
2904 0f7b2864 Gerd Hoffmann
    .dpy_refresh       = vnc_refresh,
2905 7c20b4a3 Gerd Hoffmann
    .dpy_gfx_copy      = vnc_dpy_copy,
2906 7c20b4a3 Gerd Hoffmann
    .dpy_gfx_update    = vnc_dpy_update,
2907 c12aeb86 Gerd Hoffmann
    .dpy_gfx_switch    = vnc_dpy_switch,
2908 7c20b4a3 Gerd Hoffmann
    .dpy_mouse_set     = vnc_mouse_set,
2909 7c20b4a3 Gerd Hoffmann
    .dpy_cursor_define = vnc_dpy_cursor_define,
2910 7c20b4a3 Gerd Hoffmann
};
2911 7c20b4a3 Gerd Hoffmann
2912 71cab5ca ths
void vnc_display_init(DisplayState *ds)
2913 24236869 bellard
{
2914 7267c094 Anthony Liguori
    VncDisplay *vs = g_malloc0(sizeof(*vs));
2915 24236869 bellard
2916 753b4053 aliguori
    vnc_display = vs;
2917 24236869 bellard
2918 24236869 bellard
    vs->lsock = -1;
2919 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
2920 7536ee4b Tim Hardeck
    vs->lwebsock = -1;
2921 7536ee4b Tim Hardeck
#endif
2922 24236869 bellard
2923 41b4bef6 Amit Shah
    QTAILQ_INIT(&vs->clients);
2924 3c9405a0 Gerd Hoffmann
    vs->expires = TIME_MAX;
2925 24236869 bellard
2926 9ca313aa aliguori
    if (keyboard_layout)
2927 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
2928 9ca313aa aliguori
    else
2929 0483755a aliguori
        vs->kbd_layout = init_keyboard_layout(name2keysym, "en-us");
2930 24236869 bellard
2931 24236869 bellard
    if (!vs->kbd_layout)
2932 28a76be8 aliguori
        exit(1);
2933 24236869 bellard
2934 bd023f95 Corentin Chary
    qemu_mutex_init(&vs->mutex);
2935 bd023f95 Corentin Chary
    vnc_start_worker_thread();
2936 bd023f95 Corentin Chary
2937 21ef45d7 Gerd Hoffmann
    vs->dcl.ops = &dcl_ops;
2938 5209089f Gerd Hoffmann
    register_displaychangelistener(&vs->dcl);
2939 71cab5ca ths
}
2940 71cab5ca ths
2941 6f43024c ths
2942 71a8cdec Blue Swirl
static void vnc_display_close(DisplayState *ds)
2943 71cab5ca ths
{
2944 21ef45d7 Gerd Hoffmann
    VncDisplay *vs = vnc_display;
2945 71cab5ca ths
2946 452b4d88 aliguori
    if (!vs)
2947 452b4d88 aliguori
        return;
2948 71cab5ca ths
    if (vs->display) {
2949 7267c094 Anthony Liguori
        g_free(vs->display);
2950 28a76be8 aliguori
        vs->display = NULL;
2951 71cab5ca ths
    }
2952 71cab5ca ths
    if (vs->lsock != -1) {
2953 28a76be8 aliguori
        qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2954 28a76be8 aliguori
        close(vs->lsock);
2955 28a76be8 aliguori
        vs->lsock = -1;
2956 71cab5ca ths
    }
2957 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
2958 7536ee4b Tim Hardeck
    g_free(vs->ws_display);
2959 7536ee4b Tim Hardeck
    vs->ws_display = NULL;
2960 7536ee4b Tim Hardeck
    if (vs->lwebsock != -1) {
2961 7536ee4b Tim Hardeck
        qemu_set_fd_handler2(vs->lwebsock, NULL, NULL, NULL, NULL);
2962 7536ee4b Tim Hardeck
        close(vs->lwebsock);
2963 7536ee4b Tim Hardeck
        vs->lwebsock = -1;
2964 7536ee4b Tim Hardeck
    }
2965 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
2966 70848515 ths
    vs->auth = VNC_AUTH_INVALID;
2967 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2968 8d5d2d4c ths
    vs->subauth = VNC_AUTH_INVALID;
2969 5fb6c7a8 aliguori
    vs->tls.x509verify = 0;
2970 8d5d2d4c ths
#endif
2971 70848515 ths
}
2972 70848515 ths
2973 71a8cdec Blue Swirl
static int vnc_display_disable_login(DisplayState *ds)
2974 1cd20f8b Anthony Liguori
{
2975 21ef45d7 Gerd Hoffmann
    VncDisplay *vs = vnc_display;
2976 1cd20f8b Anthony Liguori
2977 1cd20f8b Anthony Liguori
    if (!vs) {
2978 1cd20f8b Anthony Liguori
        return -1;
2979 1cd20f8b Anthony Liguori
    }
2980 1cd20f8b Anthony Liguori
2981 1cd20f8b Anthony Liguori
    if (vs->password) {
2982 7267c094 Anthony Liguori
        g_free(vs->password);
2983 1cd20f8b Anthony Liguori
    }
2984 1cd20f8b Anthony Liguori
2985 1cd20f8b Anthony Liguori
    vs->password = NULL;
2986 7dfbfc79 Daniel P. Berrange
    if (vs->auth == VNC_AUTH_NONE) {
2987 7dfbfc79 Daniel P. Berrange
        vs->auth = VNC_AUTH_VNC;
2988 7dfbfc79 Daniel P. Berrange
    }
2989 1cd20f8b Anthony Liguori
2990 1cd20f8b Anthony Liguori
    return 0;
2991 1cd20f8b Anthony Liguori
}
2992 1cd20f8b Anthony Liguori
2993 70848515 ths
int vnc_display_password(DisplayState *ds, const char *password)
2994 70848515 ths
{
2995 21ef45d7 Gerd Hoffmann
    VncDisplay *vs = vnc_display;
2996 70848515 ths
2997 7ef92331 Zachary Amsden
    if (!vs) {
2998 a6aa9d3e Luiz Capitulino
        return -EINVAL;
2999 7ef92331 Zachary Amsden
    }
3000 7ef92331 Zachary Amsden
3001 1cd20f8b Anthony Liguori
    if (!password) {
3002 1cd20f8b Anthony Liguori
        /* This is not the intention of this interface but err on the side
3003 1cd20f8b Anthony Liguori
           of being safe */
3004 a6aa9d3e Luiz Capitulino
        return vnc_display_disable_login(ds);
3005 1cd20f8b Anthony Liguori
    }
3006 1cd20f8b Anthony Liguori
3007 70848515 ths
    if (vs->password) {
3008 7267c094 Anthony Liguori
        g_free(vs->password);
3009 28a76be8 aliguori
        vs->password = NULL;
3010 70848515 ths
    }
3011 7267c094 Anthony Liguori
    vs->password = g_strdup(password);
3012 7dfbfc79 Daniel P. Berrange
    if (vs->auth == VNC_AUTH_NONE) {
3013 7dfbfc79 Daniel P. Berrange
        vs->auth = VNC_AUTH_VNC;
3014 7dfbfc79 Daniel P. Berrange
    }
3015 a6aa9d3e Luiz Capitulino
3016 a6aa9d3e Luiz Capitulino
    return 0;
3017 71cab5ca ths
}
3018 71cab5ca ths
3019 3c9405a0 Gerd Hoffmann
int vnc_display_pw_expire(DisplayState *ds, time_t expires)
3020 3c9405a0 Gerd Hoffmann
{
3021 21ef45d7 Gerd Hoffmann
    VncDisplay *vs = vnc_display;
3022 3c9405a0 Gerd Hoffmann
3023 1643f2b2 Gerd Hoffmann
    if (!vs) {
3024 1643f2b2 Gerd Hoffmann
        return -EINVAL;
3025 1643f2b2 Gerd Hoffmann
    }
3026 1643f2b2 Gerd Hoffmann
3027 3c9405a0 Gerd Hoffmann
    vs->expires = expires;
3028 3c9405a0 Gerd Hoffmann
    return 0;
3029 3c9405a0 Gerd Hoffmann
}
3030 3c9405a0 Gerd Hoffmann
3031 f92f8afe Anthony Liguori
char *vnc_display_local_addr(DisplayState *ds)
3032 f92f8afe Anthony Liguori
{
3033 21ef45d7 Gerd Hoffmann
    VncDisplay *vs = vnc_display;
3034 f92f8afe Anthony Liguori
    
3035 f92f8afe Anthony Liguori
    return vnc_socket_local_addr("%s:%s", vs->lsock);
3036 f92f8afe Anthony Liguori
}
3037 f92f8afe Anthony Liguori
3038 2d55f0e8 Paolo Bonzini
void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
3039 71cab5ca ths
{
3040 21ef45d7 Gerd Hoffmann
    VncDisplay *vs = vnc_display;
3041 70848515 ths
    const char *options;
3042 70848515 ths
    int password = 0;
3043 3aa3eea3 balrog
    int reverse = 0;
3044 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
3045 3a702699 ths
    int tls = 0, x509 = 0;
3046 8d5d2d4c ths
#endif
3047 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
3048 2f9606b3 aliguori
    int sasl = 0;
3049 2f9606b3 aliguori
    int saslErr;
3050 2f9606b3 aliguori
#endif
3051 2ded6ad7 Blue Swirl
#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
3052 76655d6d aliguori
    int acl = 0;
3053 2ded6ad7 Blue Swirl
#endif
3054 3a0558b5 Gerd Hoffmann
    int lock_key_sync = 1;
3055 71cab5ca ths
3056 2d55f0e8 Paolo Bonzini
    if (!vnc_display) {
3057 2d55f0e8 Paolo Bonzini
        error_setg(errp, "VNC display not active");
3058 2d55f0e8 Paolo Bonzini
        return;
3059 2d55f0e8 Paolo Bonzini
    }
3060 71cab5ca ths
    vnc_display_close(ds);
3061 70848515 ths
    if (strcmp(display, "none") == 0)
3062 2d55f0e8 Paolo Bonzini
        return;
3063 24236869 bellard
3064 1ce52c78 Paolo Bonzini
    vs->display = g_strdup(display);
3065 8cf36489 Gerd Hoffmann
    vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
3066 70848515 ths
3067 70848515 ths
    options = display;
3068 70848515 ths
    while ((options = strchr(options, ','))) {
3069 28a76be8 aliguori
        options++;
3070 28a76be8 aliguori
        if (strncmp(options, "password", 8) == 0) {
3071 0f66998f Paul Moore
            if (fips_get_state()) {
3072 2d55f0e8 Paolo Bonzini
                error_setg(errp,
3073 2d55f0e8 Paolo Bonzini
                           "VNC password auth disabled due to FIPS mode, "
3074 2d55f0e8 Paolo Bonzini
                           "consider using the VeNCrypt or SASL authentication "
3075 2d55f0e8 Paolo Bonzini
                           "methods as an alternative");
3076 1ce52c78 Paolo Bonzini
                goto fail;
3077 0f66998f Paul Moore
            }
3078 28a76be8 aliguori
            password = 1; /* Require password auth */
3079 28a76be8 aliguori
        } else if (strncmp(options, "reverse", 7) == 0) {
3080 28a76be8 aliguori
            reverse = 1;
3081 cee8e6ad Stefan Hajnoczi
        } else if (strncmp(options, "no-lock-key-sync", 16) == 0) {
3082 3a0558b5 Gerd Hoffmann
            lock_key_sync = 0;
3083 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
3084 28a76be8 aliguori
        } else if (strncmp(options, "sasl", 4) == 0) {
3085 28a76be8 aliguori
            sasl = 1; /* Require SASL auth */
3086 2f9606b3 aliguori
#endif
3087 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
3088 7536ee4b Tim Hardeck
        } else if (strncmp(options, "websocket", 9) == 0) {
3089 7536ee4b Tim Hardeck
            char *start, *end;
3090 7536ee4b Tim Hardeck
            vs->websocket = 1;
3091 7536ee4b Tim Hardeck
3092 7536ee4b Tim Hardeck
            /* Check for 'websocket=<port>' */
3093 7536ee4b Tim Hardeck
            start = strchr(options, '=');
3094 7536ee4b Tim Hardeck
            end = strchr(options, ',');
3095 7536ee4b Tim Hardeck
            if (start && (!end || (start < end))) {
3096 7536ee4b Tim Hardeck
                int len = end ? end-(start+1) : strlen(start+1);
3097 7536ee4b Tim Hardeck
                if (len < 6) {
3098 7536ee4b Tim Hardeck
                    /* extract the host specification from display */
3099 7536ee4b Tim Hardeck
                    char  *host = NULL, *port = NULL, *host_end = NULL;
3100 7536ee4b Tim Hardeck
                    port = g_strndup(start + 1, len);
3101 7536ee4b Tim Hardeck
3102 7536ee4b Tim Hardeck
                    /* ipv6 hosts have colons */
3103 7536ee4b Tim Hardeck
                    end = strchr(display, ',');
3104 7536ee4b Tim Hardeck
                    host_end = g_strrstr_len(display, end - display, ":");
3105 7536ee4b Tim Hardeck
3106 7536ee4b Tim Hardeck
                    if (host_end) {
3107 7536ee4b Tim Hardeck
                        host = g_strndup(display, host_end - display + 1);
3108 7536ee4b Tim Hardeck
                    } else {
3109 7536ee4b Tim Hardeck
                        host = g_strndup(":", 1);
3110 7536ee4b Tim Hardeck
                    }
3111 7536ee4b Tim Hardeck
                    vs->ws_display = g_strconcat(host, port, NULL);
3112 7536ee4b Tim Hardeck
                    g_free(host);
3113 7536ee4b Tim Hardeck
                    g_free(port);
3114 7536ee4b Tim Hardeck
                }
3115 7536ee4b Tim Hardeck
            }
3116 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
3117 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
3118 28a76be8 aliguori
        } else if (strncmp(options, "tls", 3) == 0) {
3119 28a76be8 aliguori
            tls = 1; /* Require TLS */
3120 28a76be8 aliguori
        } else if (strncmp(options, "x509", 4) == 0) {
3121 28a76be8 aliguori
            char *start, *end;
3122 28a76be8 aliguori
            x509 = 1; /* Require x509 certificates */
3123 28a76be8 aliguori
            if (strncmp(options, "x509verify", 10) == 0)
3124 28a76be8 aliguori
                vs->tls.x509verify = 1; /* ...and verify client certs */
3125 28a76be8 aliguori
3126 28a76be8 aliguori
            /* Now check for 'x509=/some/path' postfix
3127 28a76be8 aliguori
             * and use that to setup x509 certificate/key paths */
3128 28a76be8 aliguori
            start = strchr(options, '=');
3129 28a76be8 aliguori
            end = strchr(options, ',');
3130 28a76be8 aliguori
            if (start && (!end || (start < end))) {
3131 28a76be8 aliguori
                int len = end ? end-(start+1) : strlen(start+1);
3132 7267c094 Anthony Liguori
                char *path = g_strndup(start + 1, len);
3133 28a76be8 aliguori
3134 28a76be8 aliguori
                VNC_DEBUG("Trying certificate path '%s'\n", path);
3135 28a76be8 aliguori
                if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
3136 2d55f0e8 Paolo Bonzini
                    error_setg(errp, "Failed to find x509 certificates/keys in %s", path);
3137 7267c094 Anthony Liguori
                    g_free(path);
3138 1ce52c78 Paolo Bonzini
                    goto fail;
3139 28a76be8 aliguori
                }
3140 7267c094 Anthony Liguori
                g_free(path);
3141 28a76be8 aliguori
            } else {
3142 2d55f0e8 Paolo Bonzini
                error_setg(errp, "No certificate path provided");
3143 1ce52c78 Paolo Bonzini
                goto fail;
3144 28a76be8 aliguori
            }
3145 8d5d2d4c ths
#endif
3146 2ded6ad7 Blue Swirl
#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
3147 28a76be8 aliguori
        } else if (strncmp(options, "acl", 3) == 0) {
3148 28a76be8 aliguori
            acl = 1;
3149 2ded6ad7 Blue Swirl
#endif
3150 6f9c78c1 Corentin Chary
        } else if (strncmp(options, "lossy", 5) == 0) {
3151 6f9c78c1 Corentin Chary
            vs->lossy = true;
3152 7eff5742 Catalin Patulea
        } else if (strncmp(options, "non-adaptive", 12) == 0) {
3153 80e0c8c3 Corentin Chary
            vs->non_adaptive = true;
3154 8cf36489 Gerd Hoffmann
        } else if (strncmp(options, "share=", 6) == 0) {
3155 8cf36489 Gerd Hoffmann
            if (strncmp(options+6, "ignore", 6) == 0) {
3156 8cf36489 Gerd Hoffmann
                vs->share_policy = VNC_SHARE_POLICY_IGNORE;
3157 8cf36489 Gerd Hoffmann
            } else if (strncmp(options+6, "allow-exclusive", 15) == 0) {
3158 8cf36489 Gerd Hoffmann
                vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
3159 8cf36489 Gerd Hoffmann
            } else if (strncmp(options+6, "force-shared", 12) == 0) {
3160 8cf36489 Gerd Hoffmann
                vs->share_policy = VNC_SHARE_POLICY_FORCE_SHARED;
3161 8cf36489 Gerd Hoffmann
            } else {
3162 2d55f0e8 Paolo Bonzini
                error_setg(errp, "unknown vnc share= option");
3163 1ce52c78 Paolo Bonzini
                goto fail;
3164 8cf36489 Gerd Hoffmann
            }
3165 28a76be8 aliguori
        }
3166 70848515 ths
    }
3167 70848515 ths
3168 76655d6d aliguori
#ifdef CONFIG_VNC_TLS
3169 76655d6d aliguori
    if (acl && x509 && vs->tls.x509verify) {
3170 28a76be8 aliguori
        if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {
3171 28a76be8 aliguori
            fprintf(stderr, "Failed to create x509 dname ACL\n");
3172 28a76be8 aliguori
            exit(1);
3173 28a76be8 aliguori
        }
3174 76655d6d aliguori
    }
3175 76655d6d aliguori
#endif
3176 76655d6d aliguori
#ifdef CONFIG_VNC_SASL
3177 76655d6d aliguori
    if (acl && sasl) {
3178 28a76be8 aliguori
        if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) {
3179 28a76be8 aliguori
            fprintf(stderr, "Failed to create username ACL\n");
3180 28a76be8 aliguori
            exit(1);
3181 28a76be8 aliguori
        }
3182 76655d6d aliguori
    }
3183 76655d6d aliguori
#endif
3184 76655d6d aliguori
3185 2f9606b3 aliguori
    /*
3186 2f9606b3 aliguori
     * Combinations we support here:
3187 2f9606b3 aliguori
     *
3188 2f9606b3 aliguori
     *  - no-auth                (clear text, no auth)
3189 2f9606b3 aliguori
     *  - password               (clear text, weak auth)
3190 2f9606b3 aliguori
     *  - sasl                   (encrypt, good auth *IF* using Kerberos via GSSAPI)
3191 2f9606b3 aliguori
     *  - tls                    (encrypt, weak anonymous creds, no auth)
3192 2f9606b3 aliguori
     *  - tls + password         (encrypt, weak anonymous creds, weak auth)
3193 2f9606b3 aliguori
     *  - tls + sasl             (encrypt, weak anonymous creds, good auth)
3194 2f9606b3 aliguori
     *  - tls + x509             (encrypt, good x509 creds, no auth)
3195 2f9606b3 aliguori
     *  - tls + x509 + password  (encrypt, good x509 creds, weak auth)
3196 2f9606b3 aliguori
     *  - tls + x509 + sasl      (encrypt, good x509 creds, good auth)
3197 2f9606b3 aliguori
     *
3198 2f9606b3 aliguori
     * NB1. TLS is a stackable auth scheme.
3199 2f9606b3 aliguori
     * NB2. the x509 schemes have option to validate a client cert dname
3200 2f9606b3 aliguori
     */
3201 70848515 ths
    if (password) {
3202 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
3203 28a76be8 aliguori
        if (tls) {
3204 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
3205 28a76be8 aliguori
            if (x509) {
3206 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 password auth\n");
3207 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
3208 28a76be8 aliguori
            } else {
3209 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS password auth\n");
3210 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
3211 28a76be8 aliguori
            }
3212 28a76be8 aliguori
        } else {
3213 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
3214 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with password auth\n");
3215 28a76be8 aliguori
            vs->auth = VNC_AUTH_VNC;
3216 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
3217 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
3218 28a76be8 aliguori
        }
3219 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
3220 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
3221 2f9606b3 aliguori
    } else if (sasl) {
3222 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
3223 2f9606b3 aliguori
        if (tls) {
3224 2f9606b3 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
3225 2f9606b3 aliguori
            if (x509) {
3226 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 SASL auth\n");
3227 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509SASL;
3228 2f9606b3 aliguori
            } else {
3229 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS SASL auth\n");
3230 2f9606b3 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSSASL;
3231 2f9606b3 aliguori
            }
3232 2f9606b3 aliguori
        } else {
3233 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
3234 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with SASL auth\n");
3235 2f9606b3 aliguori
            vs->auth = VNC_AUTH_SASL;
3236 2f9606b3 aliguori
#ifdef CONFIG_VNC_TLS
3237 2f9606b3 aliguori
            vs->subauth = VNC_AUTH_INVALID;
3238 2f9606b3 aliguori
        }
3239 2f9606b3 aliguori
#endif /* CONFIG_VNC_TLS */
3240 2f9606b3 aliguori
#endif /* CONFIG_VNC_SASL */
3241 70848515 ths
    } else {
3242 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
3243 28a76be8 aliguori
        if (tls) {
3244 28a76be8 aliguori
            vs->auth = VNC_AUTH_VENCRYPT;
3245 28a76be8 aliguori
            if (x509) {
3246 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with x509 no auth\n");
3247 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
3248 28a76be8 aliguori
            } else {
3249 28a76be8 aliguori
                VNC_DEBUG("Initializing VNC server with TLS no auth\n");
3250 28a76be8 aliguori
                vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
3251 28a76be8 aliguori
            }
3252 28a76be8 aliguori
        } else {
3253 8d5d2d4c ths
#endif
3254 28a76be8 aliguori
            VNC_DEBUG("Initializing VNC server with no auth\n");
3255 28a76be8 aliguori
            vs->auth = VNC_AUTH_NONE;
3256 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
3257 28a76be8 aliguori
            vs->subauth = VNC_AUTH_INVALID;
3258 28a76be8 aliguori
        }
3259 8d5d2d4c ths
#endif
3260 70848515 ths
    }
3261 24236869 bellard
3262 2f9606b3 aliguori
#ifdef CONFIG_VNC_SASL
3263 2f9606b3 aliguori
    if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) {
3264 2d55f0e8 Paolo Bonzini
        error_setg(errp, "Failed to initialize SASL auth: %s",
3265 2d55f0e8 Paolo Bonzini
                   sasl_errstring(saslErr, NULL, NULL));
3266 1ce52c78 Paolo Bonzini
        goto fail;
3267 2f9606b3 aliguori
    }
3268 2f9606b3 aliguori
#endif
3269 3a0558b5 Gerd Hoffmann
    vs->lock_key_sync = lock_key_sync;
3270 2f9606b3 aliguori
3271 3aa3eea3 balrog
    if (reverse) {
3272 9712ecaf aliguori
        /* connect to viewer */
3273 007fcd3e Paolo Bonzini
        int csock;
3274 007fcd3e Paolo Bonzini
        vs->lsock = -1;
3275 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
3276 7536ee4b Tim Hardeck
        vs->lwebsock = -1;
3277 7536ee4b Tim Hardeck
#endif
3278 007fcd3e Paolo Bonzini
        if (strncmp(display, "unix:", 5) == 0) {
3279 2d55f0e8 Paolo Bonzini
            csock = unix_connect(display+5, errp);
3280 3aa3eea3 balrog
        } else {
3281 2d55f0e8 Paolo Bonzini
            csock = inet_connect(display, errp);
3282 3aa3eea3 balrog
        }
3283 007fcd3e Paolo Bonzini
        if (csock < 0) {
3284 007fcd3e Paolo Bonzini
            goto fail;
3285 007fcd3e Paolo Bonzini
        }
3286 7536ee4b Tim Hardeck
        vnc_connect(vs, csock, 0, 0);
3287 9712ecaf aliguori
    } else {
3288 9712ecaf aliguori
        /* listen for connects */
3289 9712ecaf aliguori
        char *dpy;
3290 7267c094 Anthony Liguori
        dpy = g_malloc(256);
3291 9712ecaf aliguori
        if (strncmp(display, "unix:", 5) == 0) {
3292 bc575e95 blueswir1
            pstrcpy(dpy, 256, "unix:");
3293 2d55f0e8 Paolo Bonzini
            vs->lsock = unix_listen(display+5, dpy+5, 256-5, errp);
3294 9712ecaf aliguori
        } else {
3295 029409e5 Amos Kong
            vs->lsock = inet_listen(display, dpy, 256,
3296 2d55f0e8 Paolo Bonzini
                                    SOCK_STREAM, 5900, errp);
3297 7536ee4b Tim Hardeck
            if (vs->lsock < 0) {
3298 7536ee4b Tim Hardeck
                g_free(dpy);
3299 7536ee4b Tim Hardeck
                goto fail;
3300 7536ee4b Tim Hardeck
            }
3301 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
3302 7536ee4b Tim Hardeck
            if (vs->websocket) {
3303 7536ee4b Tim Hardeck
                if (vs->ws_display) {
3304 7536ee4b Tim Hardeck
                    vs->lwebsock = inet_listen(vs->ws_display, NULL, 256,
3305 7536ee4b Tim Hardeck
                        SOCK_STREAM, 0, errp);
3306 7536ee4b Tim Hardeck
                } else {
3307 7536ee4b Tim Hardeck
                    vs->lwebsock = inet_listen(vs->display, NULL, 256,
3308 7536ee4b Tim Hardeck
                        SOCK_STREAM, 5700, errp);
3309 7536ee4b Tim Hardeck
                }
3310 7536ee4b Tim Hardeck
3311 7536ee4b Tim Hardeck
                if (vs->lwebsock < 0) {
3312 7536ee4b Tim Hardeck
                    if (vs->lsock) {
3313 7536ee4b Tim Hardeck
                        close(vs->lsock);
3314 7536ee4b Tim Hardeck
                        vs->lsock = -1;
3315 7536ee4b Tim Hardeck
                    }
3316 7536ee4b Tim Hardeck
                    g_free(dpy);
3317 7536ee4b Tim Hardeck
                    goto fail;
3318 7536ee4b Tim Hardeck
                }
3319 7536ee4b Tim Hardeck
            }
3320 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
3321 9712ecaf aliguori
        }
3322 1ce52c78 Paolo Bonzini
        g_free(vs->display);
3323 1ce52c78 Paolo Bonzini
        vs->display = dpy;
3324 7536ee4b Tim Hardeck
        qemu_set_fd_handler2(vs->lsock, NULL,
3325 7536ee4b Tim Hardeck
                vnc_listen_regular_read, NULL, vs);
3326 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
3327 7536ee4b Tim Hardeck
        if (vs->websocket) {
3328 7536ee4b Tim Hardeck
            qemu_set_fd_handler2(vs->lwebsock, NULL,
3329 7536ee4b Tim Hardeck
                    vnc_listen_websocket_read, NULL, vs);
3330 7536ee4b Tim Hardeck
        }
3331 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
3332 24236869 bellard
    }
3333 2d55f0e8 Paolo Bonzini
    return;
3334 1ce52c78 Paolo Bonzini
3335 1ce52c78 Paolo Bonzini
fail:
3336 1ce52c78 Paolo Bonzini
    g_free(vs->display);
3337 1ce52c78 Paolo Bonzini
    vs->display = NULL;
3338 7536ee4b Tim Hardeck
#ifdef CONFIG_VNC_WS
3339 7536ee4b Tim Hardeck
    g_free(vs->ws_display);
3340 7536ee4b Tim Hardeck
    vs->ws_display = NULL;
3341 7536ee4b Tim Hardeck
#endif /* CONFIG_VNC_WS */
3342 24236869 bellard
}
3343 13661089 Daniel P. Berrange
3344 13661089 Daniel P. Berrange
void vnc_display_add_client(DisplayState *ds, int csock, int skipauth)
3345 13661089 Daniel P. Berrange
{
3346 21ef45d7 Gerd Hoffmann
    VncDisplay *vs = vnc_display;
3347 13661089 Daniel P. Berrange
3348 7536ee4b Tim Hardeck
    vnc_connect(vs, csock, skipauth, 0);
3349 13661089 Daniel P. Berrange
}