Statistics
| Branch: | Revision:

root / vnc.c @ 8950a950

History | View | Annotate | Download (77 kB)

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