rfb.c (7bb0eb348e1119aed76a61d633a9106b6b9912f1) rfb.c (1aa1f41fe10c6220a7fbef328fac1b72a8355a01)
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5 * Copyright (c) 2015 Leon Dang
6 * Copyright 2020 Joyent, Inc.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5 * Copyright (c) 2015 Leon Dang
6 * Copyright 2020 Joyent, Inc.
7 * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30/*
31 * This file and its contents are supplied under the terms of the
32 * Common Development and Distribution License ("CDDL"), version 1.0.
33 * You may only use this file in accordance with the terms of version
34 * 1.0 of the CDDL.
35 *
36 * A full copy of the text of the CDDL should have accompanied this
37 * source. A copy of the CDDL is also available via the Internet at
38 * http://www.illumos.org/license/CDDL.
39 *
40 * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
41 */
31
42
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
43/*
44 * References to the RFB protocol specification refer to:
45 * - [1] https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst
46 */
34
47
35#include <sys/param.h>
36#ifndef WITHOUT_CAPSICUM
37#include <sys/capsicum.h>
38#endif
39#include <sys/endian.h>
40#include <sys/socket.h>
41#include <sys/select.h>
42#include <sys/time.h>
43#include <arpa/inet.h>
44#include <stdatomic.h>
45#include <machine/cpufunc.h>
46#include <machine/specialreg.h>
47#include <netinet/in.h>
48#include <netdb.h>
49
50#include <assert.h>
51#ifndef WITHOUT_CAPSICUM
52#include <capsicum_helpers.h>
53#endif
54#include <err.h>
55#include <errno.h>
48#include <err.h>
49#include <errno.h>
50#include <libidspace.h>
51#include <netdb.h>
56#include <pthread.h>
57#include <pthread_np.h>
58#include <signal.h>
52#include <pthread.h>
53#include <pthread_np.h>
54#include <signal.h>
55#include <stdatomic.h>
59#include <stdbool.h>
56#include <stdbool.h>
60#include <stdlib.h>
61#include <stdio.h>
57#include <stdio.h>
58#include <stdlib.h>
62#include <string.h>
59#include <string.h>
63#include <sysexits.h>
64#include <unistd.h>
60#include <unistd.h>
65
66#include <zlib.h>
61#include <zlib.h>
67
68#ifndef __FreeBSD__
62#include <machine/cpufunc.h>
63#include <machine/specialreg.h>
64#include <netinet/in.h>
65#ifndef NO_OPENSSL
66#include <openssl/des.h>
67#endif
69#include <sys/debug.h>
68#include <sys/debug.h>
69#include <sys/endian.h>
70#include <sys/list.h>
71#include <sys/socket.h>
72#include <sys/types.h>
73#ifndef WITHOUT_CAPSICUM
74#include <sysexits.h>
75#include <sys/capsicum.h>
76#include <capsicum_helpers.h>
70#endif
71
72#include "bhyvegc.h"
77#endif
78
79#include "bhyvegc.h"
80#include "config.h"
73#include "debug.h"
74#include "console.h"
75#include "rfb.h"
81#include "debug.h"
82#include "console.h"
83#include "rfb.h"
84#include "rfb_impl.h"
76#include "sockstream.h"
77
85#include "sockstream.h"
86
78#ifndef NO_OPENSSL
79#include <openssl/des.h>
80#endif
87static uint_t rfb_debug = 0;
88static list_t rfb_list;
89static id_space_t *rfb_idspace;
81
90
82/* Delays in microseconds */
83#define CFD_SEL_DELAY 10000
84#define SCREEN_REFRESH_DELAY 33300 /* 30Hz */
85#define SCREEN_POLL_DELAY (SCREEN_REFRESH_DELAY / 2)
91static bool rfb_sse42;
92static pthread_once_t rfb_once = PTHREAD_ONCE_INIT;
86
93
87static int rfb_debug = 0;
88#define DPRINTF(params) if (rfb_debug) PRINTLN params
89#define WPRINTF(params) PRINTLN params
94extern int raw_stdio;
90
95
91#define VERSION_LENGTH 12
92#define AUTH_LENGTH 16
93#define PASSWD_LENGTH 8
96static void rfb_send_extended_keyevent_update_msg(rfb_client_t *);
94
97
95/* Protocol versions */
96#define CVERS_3_3 '3'
97#define CVERS_3_7 '7'
98#define CVERS_3_8 '8'
98static void
99rfb_printf(rfb_client_t *c, rfb_loglevel_t level, const char *fmt, ...)
100{
101 FILE *fp = stdout;
102 va_list ap;
99
103
100/* Client-to-server msg types */
101#define CS_SET_PIXEL_FORMAT 0
102#define CS_SET_ENCODINGS 2
103#define CS_UPDATE_MSG 3
104#define CS_KEY_EVENT 4
105#define CS_POINTER_EVENT 5
106#define CS_CUT_TEXT 6
107#define CS_MSG_CLIENT_QEMU 255
104 switch (level) {
105 case RFB_LOGDEBUG:
106 if (rfb_debug == 0)
107 return;
108 /* FALLTHROUGH */
109 case RFB_LOGERR:
110 fp = stderr;
111 /* FALLTHROUGH */
112 case RFB_LOGWARN:
113 if (c != NULL)
114 (void) fprintf(fp, "rfb%u: ", c->rc_instance);
115 else
116 (void) fprintf(fp, "rfb: ");
117 va_start(ap, fmt);
118 (void) vfprintf(fp, fmt, ap);
119 va_end(ap);
120 if (raw_stdio)
121 (void) fprintf(fp, "\r\n");
122 else
123 (void) fprintf(fp, "\n");
124 (void) fflush(fp);
125 }
126}
108
127
109#define SECURITY_TYPE_NONE 1
110#define SECURITY_TYPE_VNC_AUTH 2
128static void
129rfb_init_once(void)
130{
131 uint_t cpu_registers[4], ecx;
111
132
112#define AUTH_FAILED_UNAUTH 1
113#define AUTH_FAILED_ERROR 2
133 do_cpuid(1, cpu_registers);
134 ecx = cpu_registers[2];
135 rfb_sse42 = (ecx & CPUID2_SSE42) != 0;
114
136
115struct rfb_softc {
116 int sfd;
117 pthread_t tid;
137 if (rfb_sse42)
138 rfb_printf(NULL, RFB_LOGDEBUG, "enabled fast crc32");
139 else
140 rfb_printf(NULL, RFB_LOGWARN, "no support for fast crc32");
118
141
119 int cfd;
142 if (get_config_bool_default("rfb.debug", false))
143 rfb_debug = 1;
120
144
121 int width, height;
145 list_create(&rfb_list, sizeof (rfb_server_t),
146 offsetof(rfb_server_t, rs_node));
122
147
123 char *password;
148 rfb_idspace = id_space_create("rfb", 0, INT32_MAX);
149}
124
150
125 bool enc_raw_ok;
126 bool enc_zlib_ok;
127 bool enc_resize_ok;
128 bool enc_extkeyevent_ok;
151static void
152rfb_free_client(rfb_client_t *c)
153{
154 free(c->rc_crc);
155 free(c->rc_crc_tmp);
156 free(c->rc_zbuf);
157 free(c->rc_gci.data);
129
158
130 bool enc_extkeyevent_send;
159 if (c->rc_encodings & RFB_ENCODING_ZLIB)
160 (void) deflateEnd(&c->rc_zstream);
131
161
132 z_stream zstream;
133 uint8_t *zbuf;
134 int zbuflen;
162 if (c->rc_fd != -1)
163 (void) close(c->rc_fd);
135
164
136 int conn_wait;
137 int wrcount;
165 free(c);
166}
138
167
139 atomic_bool sending;
140 atomic_bool pending;
141 atomic_bool update_all;
142 atomic_bool input_detected;
168/*
169 * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only
170 */
171static inline uint32_t
172fast_crc32(void *buf, int len, uint32_t crcval)
173{
174 uint32_t q = len / sizeof (uint32_t);
175 uint32_t *p = (uint32_t *)buf;
143
176
144 pthread_mutex_t mtx;
145 pthread_cond_t cond;
177 while (q--) {
178 /* BEGIN CSTYLED */
179 asm volatile (
180 /* crc32l %ecx,%esi */
181 ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
182 :"=S" (crcval)
183 :"0" (crcval), "c" (*p)
184 );
185 /* END CSTYLED */
186 p++;
187 }
146
188
147 int hw_crc;
148 uint32_t *crc; /* WxH crc cells */
149 uint32_t *crc_tmp; /* buffer to store single crc row */
150 int crc_width, crc_height;
151#ifndef __FreeBSD__
152 const char *name;
153#endif
154};
189 return (crcval);
190}
155
191
156struct rfb_pixfmt {
157 uint8_t bpp;
158 uint8_t depth;
159 uint8_t bigendian;
160 uint8_t truecolor;
161 uint16_t red_max;
162 uint16_t green_max;
163 uint16_t blue_max;
164 uint8_t red_shift;
165 uint8_t green_shift;
166 uint8_t blue_shift;
167 uint8_t pad[3];
168};
192static void
193rfb_send_client_status(rfb_client_t *c, uint32_t status, const char *msg)
194{
195 status = htonl(status);
169
196
170struct rfb_srvr_info {
171 uint16_t width;
172 uint16_t height;
173 struct rfb_pixfmt pixfmt;
174 uint32_t namelen;
175};
197 (void) stream_write(c->rc_fd, &status, sizeof (status));
176
198
177struct rfb_pixfmt_msg {
178 uint8_t type;
179 uint8_t pad[3];
180 struct rfb_pixfmt pixfmt;
181};
199 if (msg != NULL && status != 0 && c->rc_cver == RFB_CVER_3_8) {
200 char buf[4];
182
201
183#define RFB_ENCODING_RAW 0
184#define RFB_ENCODING_ZLIB 6
185#define RFB_ENCODING_RESIZE -223
186#define RFB_ENCODING_EXT_KEYEVENT -258
202 rfb_printf(c, RFB_LOGWARN, msg);
187
203
188#define RFB_CLIENTMSG_EXT_KEYEVENT 0
204 be32enc(buf, strlen((char *)msg));
205 (void) stream_write(c->rc_fd, buf, 4);
206 (void) stream_write(c->rc_fd, msg, strlen((char *)msg));
207 }
208}
189
209
190#define RFB_MAX_WIDTH 2000
191#define RFB_MAX_HEIGHT 1200
192#define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
210static bool
211rfb_handshake_version(rfb_client_t *c)
212{
213 unsigned char buf[RFB_VERSION_LEN];
214 ssize_t l;
193
215
194/* percentage changes to screen before sending the entire screen */
195#define RFB_SEND_ALL_THRESH 25
216 rfb_printf(c, RFB_LOGDEBUG, "handshake version");
196
217
197struct rfb_enc_msg {
198 uint8_t type;
199 uint8_t pad;
200 uint16_t numencs;
201};
218 if (stream_write(c->rc_fd, RFB_VERSION, RFB_VERSION_LEN) !=
219 RFB_VERSION_LEN) {
220 rfb_printf(c, RFB_LOGWARN, "could not send server version.");
221 return (false);
222 }
202
223
203struct rfb_updt_msg {
204 uint8_t type;
205 uint8_t incremental;
206 uint16_t x;
207 uint16_t y;
208 uint16_t width;
209 uint16_t height;
210};
224 l = stream_read(c->rc_fd, buf, sizeof (buf));
225 if (l <= 0) {
226 rfb_printf(c, RFB_LOGWARN, "client version not read");
227 return (false);
228 } else if (l != RFB_VERSION_LEN) {
229 rfb_printf(c, RFB_LOGWARN, "client sent short version - '%.*s'",
230 l, buf);
231 return (false);
232 }
211
233
212struct rfb_key_msg {
213 uint8_t type;
214 uint8_t down;
215 uint16_t pad;
216 uint32_t sym;
217};
234 rfb_printf(c, RFB_LOGDEBUG, "version handshake, client ver '%.*s'",
235 l - 1, buf);
218
236
219struct rfb_client_msg {
220 uint8_t type;
221 uint8_t subtype;
222};
237 if (strncmp(RFB_VERSION, (char *)buf, RFB_VERSION_LEN - 2) != 0) {
238 rfb_printf(c, RFB_LOGERR, "bad client version '%.*s'", l, buf);
239 return (false);
240 }
223
241
224struct rfb_extended_key_msg {
225 uint8_t type;
226 uint8_t subtype;
227 uint16_t down;
228 uint32_t sym;
229 uint32_t code;
230};
242 switch (buf[RFB_VERSION_LEN - 2]) {
243 case '8':
244 c->rc_cver = RFB_CVER_3_8;
245 break;
246 case '7':
247 c->rc_cver = RFB_CVER_3_7;
248 break;
249 case '5':
250 /*
251 * From the RFB specification[1], section 7.1.1:
252 * "version 3.5 was wrongly reported by some clients, but this
253 * should be interpreted by all servers as 3.3."
254 */
255 case '3':
256 c->rc_cver = RFB_CVER_3_3;
257 break;
258 default:
259 rfb_printf(c, RFB_LOGERR, "unsupported client version '%.*s'",
260 l - 1, buf);
261 return (false);
262 }
231
263
232struct rfb_ptr_msg {
233 uint8_t type;
234 uint8_t button;
235 uint16_t x;
236 uint16_t y;
237};
264 return (true);
265}
238
266
239struct rfb_srvr_updt_msg {
240 uint8_t type;
241 uint8_t pad;
242 uint16_t numrects;
243};
267static bool
268rfb_handshake_auth(rfb_client_t *c)
269{
270 unsigned char buf[RFBP_SECURITY_VNC_AUTH_LEN];
271 int auth_type;
244
272
245struct rfb_srvr_rect_hdr {
246 uint16_t x;
247 uint16_t y;
248 uint16_t width;
249 uint16_t height;
250 uint32_t encoding;
251};
273 rfb_printf(c, RFB_LOGDEBUG, "handshake auth");
252
274
253struct rfb_cuttext_msg {
254 uint8_t type;
255 uint8_t padding[3];
256 uint32_t length;
257};
258
259static void
260#ifndef __FreeBSD__
261rfb_send_server_init_msg(int cfd, struct rfb_softc *rc)
262#else
263rfb_send_server_init_msg(int cfd)
275 auth_type = RFBP_SECURITY_NONE;
276#ifndef NO_OPENSSL
277 if (c->rc_s->rs_password != NULL)
278 auth_type = RFBP_SECURITY_VNC_AUTH;
264#endif
279#endif
265{
266 struct bhyvegc_image *gc_image;
267 struct rfb_srvr_info sinfo;
268
280
269 gc_image = console_get_image();
281 switch (c->rc_cver) {
282 case RFB_CVER_3_3:
283 /*
284 * RFB specification[1] section 7.1.2:
285 * The server decides the security type and sends a single word.
286 */
287 be32enc(buf, auth_type);
288 (void) stream_write(c->rc_fd, buf, 4);
270
289
271 sinfo.width = htons(gc_image->width);
272 sinfo.height = htons(gc_image->height);
273 sinfo.pixfmt.bpp = 32;
274 sinfo.pixfmt.depth = 32;
275 sinfo.pixfmt.bigendian = 0;
276 sinfo.pixfmt.truecolor = 1;
277 sinfo.pixfmt.red_max = htons(255);
278 sinfo.pixfmt.green_max = htons(255);
279 sinfo.pixfmt.blue_max = htons(255);
280 sinfo.pixfmt.red_shift = 16;
281 sinfo.pixfmt.green_shift = 8;
282 sinfo.pixfmt.blue_shift = 0;
283 sinfo.pixfmt.pad[0] = 0;
284 sinfo.pixfmt.pad[1] = 0;
285 sinfo.pixfmt.pad[2] = 0;
290 break;
286
291
287#ifndef __FreeBSD__
288 const char *name = rc->name != NULL ? rc->name : "bhyve";
292 case RFB_CVER_3_7:
293 case RFB_CVER_3_8:
294 /* Send list of supported types. */
295 buf[0] = 1; /* list length */
296 buf[1] = auth_type;
297 (void) stream_write(c->rc_fd, buf, 2);
289
298
290 sinfo.namelen = htonl(strlen(name));
291 (void)stream_write(cfd, &sinfo, sizeof(sinfo));
292 (void)stream_write(cfd, name, strlen(name));
299 /* Read agreed security type. */
300 if (stream_read(c->rc_fd, buf, 1) != 1) {
301 rfb_printf(c, RFB_LOGWARN,
302 "auth fail, no type from client");
303 return (false);
304 }
305
306 if (buf[0] != auth_type) {
307 rfb_send_client_status(c, 1,
308 "Auth failed: authentication type mismatch");
309 return (false);
310 }
311
312 break;
313 }
314
315 if (auth_type == RFBP_SECURITY_NONE) {
316 /*
317 * According to the RFB specification[1], section 7.2.1, for a
318 * security type of 'None', client versions 3.3 and 3.7 expect
319 * to move straight to the ClientInit phase, without the server
320 * sending a response. For version 3.8, a SecurityResult word
321 * needs to be sent indicating success.
322 */
323 switch (c->rc_cver) {
324 case RFB_CVER_3_3:
325 case RFB_CVER_3_7:
326 break;
327 case RFB_CVER_3_8:
328 rfb_send_client_status(c, 0, NULL);
329 break;
330 }
331 return (true);
332 }
333
334 /* Perform VNC authentication. */
335
336#ifdef NO_OPENSSL
337 rfb_printf(c, RFB_LOGERR,
338 "Auth not supported, no OpenSSL in your system");
339 rfb_send_client_status(c, 1, "Auth failed.");
340 return (false);
293#else
341#else
294 sinfo.namelen = htonl(strlen("bhyve"));
295 (void)stream_write(cfd, &sinfo, sizeof(sinfo));
296 (void)stream_write(cfd, "bhyve", strlen("bhyve"));
342 unsigned char challenge[RFBP_SECURITY_VNC_AUTH_LEN];
343 unsigned char keystr[RFBP_SECURITY_VNC_PASSWD_LEN];
344 unsigned char crypt_expected[RFBP_SECURITY_VNC_AUTH_LEN];
345 DES_key_schedule ks;
346
347 /*
348 * The client encrypts the challenge with DES, using a password
349 * supplied by the user as the key.
350 * To form the key, the password is truncated to eight characters, or
351 * padded with null bytes on the right.
352 * The client then sends the resulting 16-bytes response.
353 */
354 (void) strncpy((char *)keystr, c->rc_s->rs_password,
355 RFBP_SECURITY_VNC_PASSWD_LEN);
356
357 /*
358 * VNC clients encrypt the challenge with all the bit fields in each
359 * byte of the password mirrored.
360 * Here we flip each byte of the keystr.
361 */
362 for (uint_t i = 0; i < RFBP_SECURITY_VNC_PASSWD_LEN; i++) {
363 keystr[i] = (keystr[i] & 0xf0) >> 4 | (keystr[i] & 0x0f) << 4;
364 keystr[i] = (keystr[i] & 0xcc) >> 2 | (keystr[i] & 0x33) << 2;
365 keystr[i] = (keystr[i] & 0xaa) >> 1 | (keystr[i] & 0x55) << 1;
366 }
367
368 /* Initialize a 16-byte random challenge. */
369 arc4random_buf(challenge, sizeof (challenge));
370 (void) stream_write(c->rc_fd, challenge, RFBP_SECURITY_VNC_AUTH_LEN);
371
372 /* Receive the 16-byte challenge response. */
373 if (stream_read(c->rc_fd, buf, RFBP_SECURITY_VNC_AUTH_LEN)
374 != RFBP_SECURITY_VNC_AUTH_LEN) {
375 rfb_send_client_status(c, 1, "response read failed");
376 return (false);
377 }
378
379 memcpy(crypt_expected, challenge, RFBP_SECURITY_VNC_AUTH_LEN);
380
381 /* Encrypt the Challenge with DES. */
382 DES_set_key_unchecked((const_DES_cblock *)keystr, &ks);
383 DES_ecb_encrypt((const_DES_cblock *)challenge,
384 (const_DES_cblock *)crypt_expected, &ks, DES_ENCRYPT);
385 DES_ecb_encrypt(
386 (const_DES_cblock *)(challenge + RFBP_SECURITY_VNC_PASSWD_LEN),
387 (const_DES_cblock *)(crypt_expected + RFBP_SECURITY_VNC_PASSWD_LEN),
388 &ks, DES_ENCRYPT);
389
390 if (memcmp(crypt_expected, buf, RFBP_SECURITY_VNC_AUTH_LEN) != 0) {
391 rfb_send_client_status(c, 1, "Auth failed: Invalid password.");
392 return (false);
393 }
394
395 rfb_printf(c, RFB_LOGDEBUG, "authentication succeeded");
396 rfb_send_client_status(c, 0, NULL);
297#endif
397#endif
398
399 return (true);
298}
299
400}
401
300static void
301rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd)
402static bool
403rfb_handshake_init_message(rfb_client_t *c)
302{
404{
303 struct rfb_srvr_updt_msg supdt_msg;
304 struct rfb_srvr_rect_hdr srect_hdr;
405 struct bhyvegc_image *gci;
406 char buf[1];
407 char *name;
305
408
306 /* Number of rectangles: 1 */
307 supdt_msg.type = 0;
308 supdt_msg.pad = 0;
309 supdt_msg.numrects = htons(1);
310 stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
409 rfb_printf(c, RFB_LOGDEBUG, "handshake server init");
311
410
312 /* Rectangle header */
313 srect_hdr.x = htons(0);
314 srect_hdr.y = htons(0);
315 srect_hdr.width = htons(rc->width);
316 srect_hdr.height = htons(rc->height);
317 srect_hdr.encoding = htonl(RFB_ENCODING_RESIZE);
318 stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
411 /* Read the client init message. */
412 if (stream_read(c->rc_fd, buf, 1) != 1) {
413 rfb_printf(c, RFB_LOGWARN, "client did not send init");
414 return (false);
415 }
416
417 if (buf[0] == 0) {
418 rfb_client_t *oc;
419
420 rfb_printf(c, RFB_LOGDEBUG,
421 "client requested exclusive access");
422
423 pthread_mutex_lock(&c->rc_s->rs_clientlock);
424 c->rc_s->rs_exclusive = true;
425 /* Disconnect all other clients. */
426 for (oc = list_head(&c->rc_s->rs_clients); oc != NULL;
427 oc = list_next(&c->rc_s->rs_clients, oc)) {
428 if (oc != c)
429 oc->rc_closing = true;
430 }
431 pthread_mutex_unlock(&c->rc_s->rs_clientlock);
432 } else {
433 rfb_printf(c, RFB_LOGDEBUG, "client requested shared access");
434
435 pthread_mutex_lock(&c->rc_s->rs_clientlock);
436 if (c->rc_s->rs_exclusive) {
437 rfb_printf(c, RFB_LOGWARN,
438 "deny due to existing exclusive session");
439 pthread_mutex_unlock(&c->rc_s->rs_clientlock);
440 return (false);
441 }
442 pthread_mutex_unlock(&c->rc_s->rs_clientlock);
443 }
444
445 gci = console_get_image();
446
447 c->rc_sinfo.rsi_width = htons(gci->width);
448 c->rc_sinfo.rsi_height = htons(gci->height);
449 c->rc_width = gci->width;
450 c->rc_height = gci->height;
451
452 if (c->rc_s->rs_name != NULL)
453 name = (char *)c->rc_s->rs_name;
454 else
455 name = "bhyve";
456
457 c->rc_sinfo.rsi_namelen = htonl(strlen(name));
458 (void) stream_write(c->rc_fd, &c->rc_sinfo, sizeof (c->rc_sinfo));
459 (void) stream_write(c->rc_fd, name, strlen(name));
460
461 return (true);
319}
320
462}
463
321static void
322rfb_send_extended_keyevent_update_msg(struct rfb_softc *rc, int cfd)
464static bool
465rfb_handshake(rfb_client_t *c)
323{
466{
324 struct rfb_srvr_updt_msg supdt_msg;
325 struct rfb_srvr_rect_hdr srect_hdr;
467 if (!rfb_handshake_version(c))
468 return (false);
326
469
327 /* Number of rectangles: 1 */
328 supdt_msg.type = 0;
329 supdt_msg.pad = 0;
330 supdt_msg.numrects = htons(1);
331 stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
470 if (!rfb_handshake_auth(c))
471 return (false);
332
472
333 /* Rectangle header */
334 srect_hdr.x = htons(0);
335 srect_hdr.y = htons(0);
336 srect_hdr.width = htons(rc->width);
337 srect_hdr.height = htons(rc->height);
338 srect_hdr.encoding = htonl(RFB_ENCODING_EXT_KEYEVENT);
339 stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
473 if (!rfb_handshake_init_message(c))
474 return (false);
475
476 return (true);
340}
341
342static void
477}
478
479static void
343rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
480rfb_print_pixfmt(rfb_client_t *c, rfb_pixfmt_t *px, rfb_loglevel_t level)
344{
481{
345 struct rfb_pixfmt_msg pixfmt_msg;
346
347 (void)stream_read(cfd, ((void *)&pixfmt_msg)+1, sizeof(pixfmt_msg)-1);
482 rfb_printf(c, level, "%20s: %u", "bpp", px->rp_bpp);
483 rfb_printf(c, level, "%20s: %u", "depth", px->rp_depth);
484 rfb_printf(c, level, "%20s: %u", "bigendian", px->rp_bigendian);
485 rfb_printf(c, level, "%20s: %u", "truecolour", px->rp_truecolour);
486 rfb_printf(c, level, "%20s: %u", "r_max", ntohs(px->rp_r_max));
487 rfb_printf(c, level, "%20s: %u", "g_max", ntohs(px->rp_g_max));
488 rfb_printf(c, level, "%20s: %u", "b_max", ntohs(px->rp_b_max));
489 rfb_printf(c, level, "%20s: %u", "r_shift", px->rp_r_shift);
490 rfb_printf(c, level, "%20s: %u", "g_shift", px->rp_g_shift);
491 rfb_printf(c, level, "%20s: %u", "b_shift", px->rp_b_shift);
348}
349
492}
493
494static bool
495rfb_recv_set_pixel_format(rfb_client_t *c)
496{
497 rfb_cs_pixfmt_msg_t msg;
498 rfb_pixfmt_t *newpx = &msg.rp_pixfmt;
499 rfb_pixfmt_t *oldpx = &c->rc_sinfo.rsi_pixfmt;
500 rfb_pixfmt_t *spx = &c->rc_s->rs_pixfmt;
350
501
351static void
352rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd)
502 rfb_printf(c, RFB_LOGDEBUG, "received pixel format");
503
504 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
505 return (false);
506
507 /*
508 * The client has sent its desired pixel format. The protocol does not
509 * have a mechanism to reject this, we are supposed to just start using
510 * the requested format from the next update.
511 *
512 * At present, we can only support alternative rgb-shift values and
513 * will accept (and ignore) a new depth value.
514 */
515
516 if (oldpx->rp_bpp != newpx->rp_bpp ||
517 oldpx->rp_bigendian != newpx->rp_bigendian ||
518 oldpx->rp_truecolour != newpx->rp_truecolour ||
519 oldpx->rp_r_max != newpx->rp_r_max ||
520 oldpx->rp_g_max != newpx->rp_g_max ||
521 oldpx->rp_b_max != newpx->rp_b_max) {
522 rfb_printf(c, RFB_LOGWARN, "unsupported pixfmt from client");
523 rfb_print_pixfmt(c, newpx, RFB_LOGWARN);
524 return (false);
525 }
526
527 rfb_print_pixfmt(c, newpx, RFB_LOGDEBUG);
528
529 /* Check if the new shifts match the server's native values. */
530 if (newpx->rp_r_shift != spx->rp_r_shift ||
531 newpx->rp_g_shift != spx->rp_g_shift ||
532 newpx->rp_b_shift != spx->rp_b_shift) {
533 c->rc_custom_pixfmt = true;
534 rfb_printf(c, RFB_LOGDEBUG, "Using custom pixfmt");
535 } else {
536 c->rc_custom_pixfmt = false;
537 rfb_printf(c, RFB_LOGDEBUG, "Using native pixfmt");
538 }
539
540 c->rc_sinfo.rsi_pixfmt = msg.rp_pixfmt;
541 c->rc_crc_reset = true;
542
543 return (true);
544}
545
546static bool
547rfb_recv_set_encodings(rfb_client_t *c)
353{
548{
354 struct rfb_enc_msg enc_msg;
355 int i;
356 uint32_t encoding;
549 rfb_cs_encodings_msg_t msg;
357
550
358 (void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1);
551 rfb_printf(c, RFB_LOGDEBUG, "received encodings");
359
552
360 for (i = 0; i < htons(enc_msg.numencs); i++) {
361 (void)stream_read(cfd, &encoding, sizeof(encoding));
362 switch (htonl(encoding)) {
363 case RFB_ENCODING_RAW:
364 rc->enc_raw_ok = true;
553 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
554 return (false);
555
556 msg.re_numencs = htons(msg.re_numencs);
557
558 rfb_printf(c, RFB_LOGDEBUG, "%d values", msg.re_numencs);
559
560 for (uint_t i = 0; i < msg.re_numencs; i++) {
561 uint32_t enc;
562
563 if (stream_read(c->rc_fd, &enc, sizeof (enc)) != sizeof (enc))
564 return (false);
565
566 enc = htonl(enc);
567
568 switch (enc) {
569 case RFBP_ENCODING_RAW:
570 rfb_printf(c, RFB_LOGDEBUG,
571 "client supports raw encoding");
572 c->rc_encodings |= RFB_ENCODING_RAW;
365 break;
573 break;
366 case RFB_ENCODING_ZLIB:
367 if (!rc->enc_zlib_ok) {
368 deflateInit(&rc->zstream, Z_BEST_SPEED);
369 rc->enc_zlib_ok = true;
574 case RFBP_ENCODING_ZLIB:
575 rfb_printf(c, RFB_LOGDEBUG,
576 "client supports zlib encoding");
577 if (!(c->rc_encodings & RFB_ENCODING_ZLIB)) {
578 if (deflateInit(&c->rc_zstream, Z_BEST_SPEED)
579 != Z_OK) {
580 return (false);
581 }
582 c->rc_encodings |= RFB_ENCODING_ZLIB;
370 }
371 break;
583 }
584 break;
372 case RFB_ENCODING_RESIZE:
373 rc->enc_resize_ok = true;
585 case RFBP_ENCODING_RESIZE:
586 rfb_printf(c, RFB_LOGDEBUG, "client supports resize");
587 c->rc_encodings |= RFB_ENCODING_RESIZE;
374 break;
588 break;
375 case RFB_ENCODING_EXT_KEYEVENT:
376 rc->enc_extkeyevent_ok = true;
589 case RFBP_ENCODING_EXT_KEVENT:
590 rfb_printf(c, RFB_LOGDEBUG,
591 "client supports ext key event");
592 c->rc_encodings |= RFB_ENCODING_EXT_KEVENT;
377 break;
593 break;
594 case RFBP_ENCODING_DESKTOP_NAME:
595 rfb_printf(c, RFB_LOGDEBUG,
596 "client supports desktop name");
597 c->rc_encodings |= RFB_ENCODING_DESKTOP_NAME;
598 break;
599 default:
600 rfb_printf(c, RFB_LOGDEBUG,
601 "client supports encoding %d", (int32_t)enc);
378 }
379 }
602 }
603 }
604
605 return (true);
380}
381
606}
607
382/*
383 * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only
384 */
385static __inline uint32_t
386fast_crc32(void *buf, int len, uint32_t crcval)
608static bool
609rfb_recv_update(rfb_client_t *c)
387{
610{
388 uint32_t q = len / sizeof(uint32_t);
389 uint32_t *p = (uint32_t *)buf;
611 rfb_cs_update_msg_t msg;
390
612
391 while (q--) {
392 asm volatile (
393 ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
394 :"=S" (crcval)
395 :"0" (crcval), "c" (*p)
396 );
397 p++;
613 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
614 return (false);
615
616 if (!c->rc_keyevent_sent &&
617 (c->rc_encodings & RFB_ENCODING_EXT_KEVENT)) {
618 /*
619 * Take this opportunity to tell the client that we
620 * accept QEMU Extended Key Event Pseudo-encoding.
621 */
622 c->rc_keyevent_sent = true;
623 rfb_send_extended_keyevent_update_msg(c);
398 }
399
624 }
625
400 return (crcval);
626 c->rc_pending = true;
627 if (msg.rum_incremental == 0) {
628 rfb_printf(c, RFB_LOGDEBUG,
629 "client requested full screen update");
630 c->rc_send_fullscreen = true;
631 }
632
633 return (true);
401}
402
634}
635
403static int
404rfb_send_update_header(struct rfb_softc *rc, int cfd, int numrects)
636static bool
637rfb_recv_key_event(rfb_client_t *c)
405{
638{
406 struct rfb_srvr_updt_msg supdt_msg;
639 rfb_cs_key_event_msg_t msg;
407
640
408 supdt_msg.type = 0;
409 supdt_msg.pad = 0;
410 supdt_msg.numrects = htons(numrects);
641 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
642 return (false);
411
643
412 return stream_write(cfd, &supdt_msg,
413 sizeof(struct rfb_srvr_updt_msg));
644 msg.rke_sym = htonl(msg.rke_sym);
645
646 rfb_printf(c, RFB_LOGDEBUG, "received key %s %x",
647 msg.rke_down == 0 ? "up" : "down", msg.rke_sym);
648
649 console_key_event(msg.rke_down, msg.rke_sym, htonl(0));
650 c->rc_input_detected = true;
651
652 return (true);
414}
415
653}
654
416static int
417rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc,
418 int x, int y, int w, int h)
655static bool
656rfb_recv_pointer_event(rfb_client_t *c)
419{
657{
420 struct rfb_srvr_rect_hdr srect_hdr;
658 rfb_cs_pointer_event_msg_t msg;
659
660 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
661 return (false);
662
663 msg.rpe_x = htons(msg.rpe_x);
664 msg.rpe_y = htons(msg.rpe_y);
665
666 if (rfb_debug > 1) {
667 rfb_printf(c, RFB_LOGDEBUG, "received pointer event @ %dx%d",
668 msg.rpe_x, msg.rpe_y);
669 }
670
671 console_ptr_event(msg.rpe_button, msg.rpe_x, msg.rpe_y);
672 c->rc_input_detected = true;
673
674 return (true);
675}
676
677static bool
678rfb_recv_cut_text(rfb_client_t *c)
679{
680 rfb_cs_cut_text_msg_t msg;
681 unsigned char buf[32];
682
683 rfb_printf(c, RFB_LOGDEBUG, "received cut text event");
684
685 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
686 return (false);
687
688 msg.rct_length = htonl(msg.rct_length);
689 rfb_printf(c, RFB_LOGDEBUG, "%u bytes in buffer", msg.rct_length);
690 /* Consume the buffer */
691 while (msg.rct_length > 0) {
692 ssize_t l;
693
694 l = stream_read(c->rc_fd, buf,
695 MIN(sizeof (buf), msg.rct_length));
696 if (l <= 0)
697 return (false);
698 msg.rct_length -= l;
699 }
700
701 return (true);
702}
703
704static bool
705rfb_recv_qemu(rfb_client_t *c)
706{
707 rfb_cs_qemu_msg_t msg;
708
709 rfb_printf(c, RFB_LOGDEBUG, "received QEMU event");
710
711 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
712 return (false);
713
714 switch (msg.rq_subtype) {
715 case RFBP_CS_QEMU_KEVENT: {
716 rfb_cs_qemu_extended_key_msg_t keymsg;
717
718 if (stream_read(c->rc_fd, &keymsg, sizeof (keymsg)) !=
719 sizeof (keymsg)) {
720 return (false);
721 }
722
723 keymsg.rqek_sym = htonl(keymsg.rqek_sym);
724 keymsg.rqek_code = htonl(keymsg.rqek_code);
725
726 rfb_printf(c, RFB_LOGDEBUG, "QEMU key %s %x / %x",
727 keymsg.rqek_down == 0 ? "up" : "down",
728 keymsg.rqek_sym, keymsg.rqek_code);
729
730 console_key_event((int)keymsg.rqek_down, keymsg.rqek_sym,
731 keymsg.rqek_code);
732 c->rc_input_detected = true;
733 break;
734 }
735 default:
736 rfb_printf(c, RFB_LOGWARN, "Unknown QEMU event subtype: %d\n",
737 msg.rq_subtype);
738 return (false);
739 }
740
741 return (true);
742}
743
744static bool
745rfb_send_update_header(rfb_client_t *c, int numrects)
746{
747 rfb_server_update_msg_t msg;
748
749 msg.rss_type = RFBP_SC_UPDATE;
750 msg.rss_pad = 0;
751 msg.rss_numrects = htons(numrects);
752
753 return (stream_write(c->rc_fd, &msg, sizeof (msg)) == sizeof (msg));
754}
755
756static void
757rfb_send_resize_update_msg(rfb_client_t *c)
758{
759 rfb_rect_hdr_t rect;
760
761 rfb_printf(c, RFB_LOGDEBUG, "sending screen resize %dx%d",
762 c->rc_width, c->rc_height);
763
764 (void) rfb_send_update_header(c, 1);
765
766 rect.rr_x = htons(0);
767 rect.rr_y = htons(0);
768 rect.rr_width = htons(c->rc_width);
769 rect.rr_height = htons(c->rc_height);
770 rect.rr_encoding = htonl(RFBP_ENCODING_RESIZE);
771
772 (void) stream_write(c->rc_fd, &rect, sizeof (rect));
773}
774
775static void
776rfb_send_extended_keyevent_update_msg(rfb_client_t *c)
777{
778 rfb_rect_hdr_t rect;
779
780 rfb_printf(c, RFB_LOGDEBUG, "sending extended keyevent update message");
781
782 (void) rfb_send_update_header(c, 1);
783
784 rect.rr_x = htons(0);
785 rect.rr_y = htons(0);
786 rect.rr_width = htons(c->rc_width);
787 rect.rr_height = htons(c->rc_height);
788 rect.rr_encoding = htonl(RFBP_ENCODING_EXT_KEVENT);
789
790 (void) stream_write(c->rc_fd, &rect, sizeof (rect));
791}
792
793static void
794translate_pixels(rfb_client_t *c, struct bhyvegc_image *gci,
795 int x1, int y1, int x2, int y2)
796{
797 rfb_pixfmt_t *px = &c->rc_sinfo.rsi_pixfmt;
798 rfb_pixfmt_t *spx = &c->rc_s->rs_pixfmt;
799 int w, h;
800
801 w = gci->width;
802 h = gci->height;
803 VERIFY3S(gci->width, ==, c->rc_gci.width);
804 VERIFY3S(gci->height, ==, c->rc_gci.height);
805
806 for (uint_t y = y1; y < h && y < y2; y++) {
807 for (uint_t x = x1; x < w && x < x2; x++) {
808 uint32_t p;
809
810 p = gci->data[y * w + x];
811 c->rc_gci.data[y * w + x] =
812 0xff000000 |
813 ((p >> spx->rp_r_shift) & 0xff) << px->rp_r_shift |
814 ((p >> spx->rp_g_shift) & 0xff) << px->rp_g_shift |
815 ((p >> spx->rp_b_shift) & 0xff) << px->rp_b_shift;
816 }
817 }
818}
819
820static bool
821rfb_send_rect(rfb_client_t *c, struct bhyvegc_image *gci,
822 int x, int y, int w, int h)
823{
824 rfb_rect_hdr_t rect;
421 unsigned long zlen;
422 ssize_t nwrite, total;
423 int err;
424 uint32_t *p;
425 uint8_t *zbufp;
426
825 unsigned long zlen;
826 ssize_t nwrite, total;
827 int err;
828 uint32_t *p;
829 uint8_t *zbufp;
830
427 /*
428 * Send a single rectangle of the given x, y, w h dimensions.
429 */
831 if (rfb_debug > 1) {
832 rfb_printf(c, RFB_LOGDEBUG, "send rect %dx%d %dx%d",
833 x, y, w, h);
834 }
430
835
431 /* Rectangle header */
432 srect_hdr.x = htons(x);
433 srect_hdr.y = htons(y);
434 srect_hdr.width = htons(w);
435 srect_hdr.height = htons(h);
836 /* Rectangle header. */
837 rect.rr_x = htons(x);
838 rect.rr_y = htons(y);
839 rect.rr_width = htons(w);
840 rect.rr_height = htons(h);
436
841
842 uint32_t *data = gci->data;
843 if (c->rc_custom_pixfmt) {
844 translate_pixels(c, gci, x, y, x + w, y + h);
845 data = c->rc_gci.data;
846 }
847
437 h = y + h;
848 h = y + h;
438 w *= sizeof(uint32_t);
439 if (rc->enc_zlib_ok) {
440 zbufp = rc->zbuf;
441 rc->zstream.total_in = 0;
442 rc->zstream.total_out = 0;
443 for (p = &gc->data[y * gc->width + x]; y < h; y++) {
444 rc->zstream.next_in = (Bytef *)p;
445 rc->zstream.avail_in = w;
446 rc->zstream.next_out = (Bytef *)zbufp;
447 rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16 -
448 rc->zstream.total_out;
449 rc->zstream.data_type = Z_BINARY;
849 w *= sizeof (uint32_t);
450
850
451 /* Compress with zlib */
452 err = deflate(&rc->zstream, Z_SYNC_FLUSH);
851 if (c->rc_encodings & RFB_ENCODING_ZLIB) {
852 zbufp = c->rc_zbuf;
853 c->rc_zstream.total_in = 0;
854 c->rc_zstream.total_out = 0;
855 for (p = &data[y * gci->width + x]; y < h; y++) {
856 c->rc_zstream.next_in = (Bytef *)p;
857 c->rc_zstream.avail_in = w;
858 c->rc_zstream.next_out = (Bytef *)zbufp;
859 c->rc_zstream.avail_out = RFB_ZLIB_BUFSZ + 16 -
860 c->rc_zstream.total_out;
861 c->rc_zstream.data_type = Z_BINARY;
862
863 /* Compress with zlib. */
864 err = deflate(&c->rc_zstream, Z_SYNC_FLUSH);
453 if (err != Z_OK) {
865 if (err != Z_OK) {
454 WPRINTF(("zlib[rect] deflate err: %d", err));
455 rc->enc_zlib_ok = false;
456 deflateEnd(&rc->zstream);
866 rfb_printf(c, RFB_LOGWARN,
867 "zlib[rect] deflate err: %d", err);
457 goto doraw;
458 }
868 goto doraw;
869 }
459 zbufp = rc->zbuf + rc->zstream.total_out;
460 p += gc->width;
870 zbufp = c->rc_zbuf + c->rc_zstream.total_out;
871 p += gci->width;
461 }
872 }
462 srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB);
463 nwrite = stream_write(cfd, &srect_hdr,
464 sizeof(struct rfb_srvr_rect_hdr));
873 rect.rr_encoding = htonl(RFBP_ENCODING_ZLIB);
874 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
465 if (nwrite <= 0)
875 if (nwrite <= 0)
466 return (nwrite);
876 return (false);
467
877
468 zlen = htonl(rc->zstream.total_out);
469 nwrite = stream_write(cfd, &zlen, sizeof(uint32_t));
878 zlen = htonl(c->rc_zstream.total_out);
879 nwrite = stream_write(c->rc_fd, &zlen, sizeof (uint32_t));
470 if (nwrite <= 0)
880 if (nwrite <= 0)
471 return (nwrite);
472 return (stream_write(cfd, rc->zbuf, rc->zstream.total_out));
881 return (false);
882 return (stream_write(c->rc_fd, c->rc_zbuf,
883 c->rc_zstream.total_out) == c->rc_zstream.total_out);
473 }
474
475doraw:
476
477 total = 0;
884 }
885
886doraw:
887
888 total = 0;
478 zbufp = rc->zbuf;
479 for (p = &gc->data[y * gc->width + x]; y < h; y++) {
889 zbufp = c->rc_zbuf;
890 for (p = &data[y * gci->width + x]; y < h; y++) {
480 memcpy(zbufp, p, w);
481 zbufp += w;
482 total += w;
891 memcpy(zbufp, p, w);
892 zbufp += w;
893 total += w;
483 p += gc->width;
894 p += gci->width;
484 }
485
895 }
896
486 srect_hdr.encoding = htonl(RFB_ENCODING_RAW);
487 nwrite = stream_write(cfd, &srect_hdr,
488 sizeof(struct rfb_srvr_rect_hdr));
897 rect.rr_encoding = htonl(RFBP_ENCODING_RAW);
898 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
489 if (nwrite <= 0)
899 if (nwrite <= 0)
490 return (nwrite);
900 return (false);
491
901
492 total = stream_write(cfd, rc->zbuf, total);
493
494 return (total);
902 return (stream_write(c->rc_fd, c->rc_zbuf, total) == total);
495}
496
903}
904
497static int
498rfb_send_all(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc)
905
906static bool
907rfb_send_all(rfb_client_t *c, struct bhyvegc_image *gci)
499{
908{
500 struct rfb_srvr_updt_msg supdt_msg;
501 struct rfb_srvr_rect_hdr srect_hdr;
909 rfb_rect_hdr_t rect;
502 ssize_t nwrite;
503 unsigned long zlen;
504 int err;
505
910 ssize_t nwrite;
911 unsigned long zlen;
912 int err;
913
506 /*
507 * Send the whole thing
508 */
914 rfb_printf(c, RFB_LOGDEBUG, "send entire screen");
509
915
510 /* Number of rectangles: 1 */
511 supdt_msg.type = 0;
512 supdt_msg.pad = 0;
513 supdt_msg.numrects = htons(1);
514 nwrite = stream_write(cfd, &supdt_msg,
515 sizeof(struct rfb_srvr_updt_msg));
516 if (nwrite <= 0)
517 return (nwrite);
916 /* Just the one (big) rect. */
917 if (!rfb_send_update_header(c, 1))
918 return (false);
518
919
519 /* Rectangle header */
520 srect_hdr.x = 0;
521 srect_hdr.y = 0;
522 srect_hdr.width = htons(gc->width);
523 srect_hdr.height = htons(gc->height);
524 if (rc->enc_zlib_ok) {
525 rc->zstream.next_in = (Bytef *)gc->data;
526 rc->zstream.avail_in = gc->width * gc->height *
527 sizeof(uint32_t);
528 rc->zstream.next_out = (Bytef *)rc->zbuf;
529 rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16;
530 rc->zstream.data_type = Z_BINARY;
920 rect.rr_x = 0;
921 rect.rr_y = 0;
922 rect.rr_width = htons(gci->width);
923 rect.rr_height = htons(gci->height);
531
924
532 rc->zstream.total_in = 0;
533 rc->zstream.total_out = 0;
925 uint32_t *data = gci->data;
926 if (c->rc_custom_pixfmt) {
927 translate_pixels(c, gci, 0, 0, gci->width, gci->height);
928 data = c->rc_gci.data;
929 }
534
930
535 /* Compress with zlib */
536 err = deflate(&rc->zstream, Z_SYNC_FLUSH);
931 if (c->rc_encodings & RFB_ENCODING_ZLIB) {
932 c->rc_zstream.next_in = (Bytef *)data;
933 c->rc_zstream.avail_in = gci->width * gci->height *
934 sizeof (uint32_t);
935 c->rc_zstream.next_out = (Bytef *)c->rc_zbuf;
936 c->rc_zstream.avail_out = RFB_ZLIB_BUFSZ + 16;
937 c->rc_zstream.data_type = Z_BINARY;
938
939 c->rc_zstream.total_in = 0;
940 c->rc_zstream.total_out = 0;
941
942 /* Compress with zlib. */
943 err = deflate(&c->rc_zstream, Z_SYNC_FLUSH);
537 if (err != Z_OK) {
944 if (err != Z_OK) {
538 WPRINTF(("zlib deflate err: %d", err));
539 rc->enc_zlib_ok = false;
540 deflateEnd(&rc->zstream);
945 rfb_printf(c, RFB_LOGWARN, "zlib deflate err: %d", err);
541 goto doraw;
542 }
543
946 goto doraw;
947 }
948
544 srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB);
545 nwrite = stream_write(cfd, &srect_hdr,
546 sizeof(struct rfb_srvr_rect_hdr));
949 rect.rr_encoding = htonl(RFBP_ENCODING_ZLIB);
950 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
547 if (nwrite <= 0)
951 if (nwrite <= 0)
548 return (nwrite);
952 return (false);
549
953
550 zlen = htonl(rc->zstream.total_out);
551 nwrite = stream_write(cfd, &zlen, sizeof(uint32_t));
954 zlen = htonl(c->rc_zstream.total_out);
955 nwrite = stream_write(c->rc_fd, &zlen, sizeof (uint32_t));
552 if (nwrite <= 0)
956 if (nwrite <= 0)
553 return (nwrite);
554 return (stream_write(cfd, rc->zbuf, rc->zstream.total_out));
957 return (false);
958 return (stream_write(c->rc_fd, c->rc_zbuf,
959 c->rc_zstream.total_out) == c->rc_zstream.total_out);
555 }
556
557doraw:
960 }
961
962doraw:
558 srect_hdr.encoding = htonl(RFB_ENCODING_RAW);
559 nwrite = stream_write(cfd, &srect_hdr,
560 sizeof(struct rfb_srvr_rect_hdr));
963 rect.rr_encoding = htonl(RFBP_ENCODING_RAW);
964 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
561 if (nwrite <= 0)
965 if (nwrite <= 0)
562 return (nwrite);
966 return (false);
563
967
564 nwrite = stream_write(cfd, gc->data,
565 gc->width * gc->height * sizeof(uint32_t));
566
567 return (nwrite);
968 nwrite = gci->width * gci->height * sizeof (uint32_t);
969 return (stream_write(c->rc_fd, data, nwrite) == nwrite);
568}
569
970}
971
570#define PIX_PER_CELL 32
571#define PIXCELL_SHIFT 5
572#define PIXCELL_MASK 0x1F
573
574static int
575rfb_send_screen(struct rfb_softc *rc, int cfd)
972static bool
973rfb_send_screen(rfb_client_t *c)
576{
974{
577 struct bhyvegc_image *gc_image;
578 ssize_t nwrite;
579 int x, y;
580 int celly, cellwidth;
975 struct bhyvegc_image *gci;
976 bool retval = true;
977 bool sendall = false;
581 int xcells, ycells;
978 int xcells, ycells;
582 int w, h;
583 uint32_t *p;
584 int rem_x, rem_y; /* remainder for resolutions not x32 pixels ratio */
585 int retval;
586 uint32_t *crc_p, *orig_crc;
587 int changes;
588 bool expected;
979 int rem_x, rem_y;
980 uint32_t *p, *ncrc, *ocrc;
981 uint_t changes, perc, x, y;
589
982
590 /* Return if another thread sending */
591 expected = false;
592 if (atomic_compare_exchange_strong(&rc->sending, &expected, true) == false)
593 return (1);
983 /* Updates require a preceding client update request. */
984 if (atomic_exchange(&c->rc_pending, false) == false)
985 return (true);
594
986
595 retval = 1;
987 console_refresh();
988 gci = console_get_image();
596
989
597 /* Updates require a preceding update request */
598 if (atomic_exchange(&rc->pending, false) == false)
599 goto done;
990 /*
991 * It's helpful if the image size or data address does not change
992 * underneath us.
993 */
994 pthread_mutex_lock(&gci->mtx);
600
995
601 console_refresh();
602 gc_image = console_get_image();
996 /* Check for screen resolution changes. */
997 if (c->rc_width != gci->width ||
998 c->rc_height != gci->height) {
999 c->rc_width = gci->width;
1000 c->rc_height = gci->height;
1001 c->rc_crc_reset = true;
1002 c->rc_send_fullscreen = true;
603
1003
604 /* Clear old CRC values when the size changes */
605 if (rc->crc_width != gc_image->width ||
606 rc->crc_height != gc_image->height) {
607 memset(rc->crc, 0, sizeof(uint32_t) *
608 howmany(RFB_MAX_WIDTH, PIX_PER_CELL) *
609 howmany(RFB_MAX_HEIGHT, PIX_PER_CELL));
610 rc->crc_width = gc_image->width;
611 rc->crc_height = gc_image->height;
1004 /* If the client supports it, send a resize event. */
1005 if (c->rc_encodings & RFB_ENCODING_RESIZE) {
1006 rfb_send_resize_update_msg(c);
1007 /*
1008 * A resize message counts as an update in response to
1009 * the client's preceding request so rc->pending does
1010 * not need to be reset here.
1011 */
1012 goto done;
1013 }
612 }
613
1014 }
1015
614 /* A size update counts as an update in itself */
615 if (rc->width != gc_image->width ||
616 rc->height != gc_image->height) {
617 rc->width = gc_image->width;
618 rc->height = gc_image->height;
619 if (rc->enc_resize_ok) {
620 rfb_send_resize_update_msg(rc, cfd);
621 rc->update_all = true;
1016 /* Clear old CRC values. */
1017 if (atomic_exchange(&c->rc_crc_reset, false))
1018 memset(c->rc_crc, '\0', c->rc_cells * sizeof (uint32_t));
1019
1020 if (c->rc_custom_pixfmt && (c->rc_gci.data == NULL ||
1021 c->rc_gci.width != c->rc_width ||
1022 c->rc_gci.height != c->rc_height)) {
1023 c->rc_gci.data = reallocarray(c->rc_gci.data,
1024 c->rc_width * c->rc_height, sizeof (uint32_t));
1025 if (c->rc_gci.data == NULL) {
1026 retval = false;
622 goto done;
623 }
1027 goto done;
1028 }
1029 c->rc_gci.width = c->rc_width;
1030 c->rc_gci.height = c->rc_height;
1031 } else if (!c->rc_custom_pixfmt && c->rc_gci.data != NULL) {
1032 free(c->rc_gci.data);
1033 c->rc_gci.data = NULL;
624 }
625
1034 }
1035
626 if (atomic_exchange(&rc->update_all, false) == true) {
627 retval = rfb_send_all(rc, cfd, gc_image);
628 goto done;
629 }
1036 sendall = atomic_exchange(&c->rc_send_fullscreen, false);
630
631 /*
1037
1038 /*
632 * Calculate the checksum for each 32x32 cell. Send each that
633 * has changed since the last scan.
1039 * Calculate a checksum for each 32x32 cell. Send all that have
1040 * changed since the last scan.
634 */
635
1041 */
1042
636 w = rc->crc_width;
637 h = rc->crc_height;
638 xcells = howmany(rc->crc_width, PIX_PER_CELL);
639 ycells = howmany(rc->crc_height, PIX_PER_CELL);
1043 xcells = howmany(gci->width, RFB_PIX_PER_CELL);
1044 ycells = howmany(gci->height, RFB_PIX_PER_CELL);
1045 rem_x = gci->width & RFB_PIXCELL_MASK;
1046 rem_y = gci->height & RFB_PIXCELL_MASK;
1047 if (rem_y == 0)
1048 rem_y = RFB_PIX_PER_CELL;
640
1049
641 rem_x = w & PIXCELL_MASK;
1050 p = gci->data;
642
1051
643 rem_y = h & PIXCELL_MASK;
644 if (!rem_y)
645 rem_y = PIX_PER_CELL;
646
647 p = gc_image->data;
648
649 /*
650 * Go through all cells and calculate crc. If significant number
651 * of changes, then send entire screen.
652 * crc_tmp is dual purpose: to store the new crc and to flag as
653 * a cell that has changed.
654 */
655 crc_p = rc->crc_tmp - xcells;
656 orig_crc = rc->crc - xcells;
1052 ncrc = c->rc_crc_tmp - xcells;
1053 ocrc = c->rc_crc - xcells;
657 changes = 0;
1054 changes = 0;
658 memset(rc->crc_tmp, 0, sizeof(uint32_t) * xcells * ycells);
659 for (y = 0; y < h; y++) {
660 if ((y & PIXCELL_MASK) == 0) {
661 crc_p += xcells;
662 orig_crc += xcells;
1055 memset(c->rc_crc_tmp, '\0', sizeof (uint32_t) * xcells * ycells);
1056 for (y = 0; y < gci->height; y++) {
1057 if ((y & RFB_PIXCELL_MASK) == 0) {
1058 ncrc += xcells;
1059 ocrc += xcells;
663 }
664
665 for (x = 0; x < xcells; x++) {
1060 }
1061
1062 for (x = 0; x < xcells; x++) {
666 if (x == (xcells - 1) && rem_x > 0)
1063 uint_t cellwidth;
1064
1065 if (x == xcells - 1 && rem_x > 0)
667 cellwidth = rem_x;
668 else
1066 cellwidth = rem_x;
1067 else
669 cellwidth = PIX_PER_CELL;
1068 cellwidth = RFB_PIX_PER_CELL;
670
1069
671 if (rc->hw_crc)
672 crc_p[x] = fast_crc32(p,
673 cellwidth * sizeof(uint32_t),
674 crc_p[x]);
675 else
676 crc_p[x] = (uint32_t)crc32(crc_p[x],
677 (Bytef *)p,
678 cellwidth * sizeof(uint32_t));
1070 if (rfb_sse42) {
1071 ncrc[x] = fast_crc32(p,
1072 cellwidth * sizeof (uint32_t), ncrc[x]);
1073 } else {
1074 ncrc[x] = (uint32_t)crc32(ncrc[x],
1075 (Bytef *)p, cellwidth * sizeof (uint32_t));
1076 }
679
680 p += cellwidth;
681
1077
1078 p += cellwidth;
1079
682 /* check for crc delta if last row in cell */
683 if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) {
684 if (orig_crc[x] != crc_p[x]) {
685 orig_crc[x] = crc_p[x];
686 crc_p[x] = 1;
1080 /* check for crc delta if last row in cell. */
1081 if ((y & RFB_PIXCELL_MASK) == RFB_PIXCELL_MASK ||
1082 y == gci->height - 1) {
1083 if (ocrc[x] != ncrc[x]) {
1084 ocrc[x] = ncrc[x];
1085 ncrc[x] = 1;
687 changes++;
688 } else {
1086 changes++;
1087 } else {
689 crc_p[x] = 0;
1088 ncrc[x] = 0;
690 }
691 }
692 }
693 }
694
1089 }
1090 }
1091 }
1092 }
1093
695 /*
696 * We only send the update if there are changes.
697 * Restore the pending flag since it was unconditionally cleared
698 * above.
699 */
700 if (!changes) {
701 rc->pending = true;
1094 perc = (changes * 100) / (xcells * ycells);
1095 if (rfb_debug > 1 && changes > 0) {
1096 rfb_printf(c, RFB_LOGDEBUG,
1097 "scanned and found %u changed cell(s) - %u%%",
1098 changes, perc);
1099 }
1100
1101 /*
1102 * If there are no changes, don't send an update. Restore the pending
1103 * flag since we still owe the client an update.
1104 */
1105 if (!sendall && !changes) {
1106 c->rc_pending = true;
702 goto done;
703 }
704
1107 goto done;
1108 }
1109
705 /* If number of changes is > THRESH percent, send the whole screen */
706 if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) {
707 retval = rfb_send_all(rc, cfd, gc_image);
1110 /* If there are a lot of changes, send the whole screen. */
1111 if (perc >= RFB_SENDALL_THRESH)
1112 sendall = true;
1113
1114 if (sendall) {
1115 retval = rfb_send_all(c, gci);
708 goto done;
709 }
710
1116 goto done;
1117 }
1118
711 rfb_send_update_header(rc, cfd, changes);
1119 if (!rfb_send_update_header(c, changes)) {
1120 retval = false;
1121 goto done;
1122 }
712
1123
713 /* Go through all cells, and send only changed ones */
714 crc_p = rc->crc_tmp;
715 for (y = 0; y < h; y += PIX_PER_CELL) {
716 /* previous cell's row */
717 celly = (y >> PIXCELL_SHIFT);
1124 /* Send the changed cells as separate rects. */
1125 ncrc = c->rc_crc_tmp;
1126 for (y = 0; y < gci->height; y += RFB_PIX_PER_CELL) {
1127 /* Previous cell's row. */
1128 int celly = (y >> RFB_PIXCELL_SHIFT);
718
1129
719 /* Delta check crc to previous set */
1130 /* Delta check crc to previous set. */
720 for (x = 0; x < xcells; x++) {
1131 for (x = 0; x < xcells; x++) {
721 if (*crc_p++ == 0)
1132 uint_t cellwidth;
1133
1134 if (*ncrc++ == 0)
722 continue;
723
1135 continue;
1136
724 if (x == (xcells - 1) && rem_x > 0)
1137 if (x == xcells - 1 && rem_x > 0)
725 cellwidth = rem_x;
726 else
1138 cellwidth = rem_x;
1139 else
727 cellwidth = PIX_PER_CELL;
728 nwrite = rfb_send_rect(rc, cfd,
729 gc_image,
730 x * PIX_PER_CELL,
731 celly * PIX_PER_CELL,
732 cellwidth,
733 y + PIX_PER_CELL >= h ? rem_y : PIX_PER_CELL);
734 if (nwrite <= 0) {
735 retval = nwrite;
1140 cellwidth = RFB_PIX_PER_CELL;
1141
1142 if (!rfb_send_rect(c, gci,
1143 x * RFB_PIX_PER_CELL, celly * RFB_PIX_PER_CELL,
1144 cellwidth, y + RFB_PIX_PER_CELL >= gci->height ?
1145 rem_y : RFB_PIX_PER_CELL)) {
1146 retval = false;
736 goto done;
737 }
738 }
739 }
740
741done:
1147 goto done;
1148 }
1149 }
1150 }
1151
1152done:
742 rc->sending = false;
1153 pthread_mutex_unlock(&gci->mtx);
743
744 return (retval);
745}
746
1154
1155 return (retval);
1156}
1157
747
748static void
749rfb_recv_update_msg(struct rfb_softc *rc, int cfd)
1158static void *
1159rfb_client_rx_thread(void *arg)
750{
1160{
751 struct rfb_updt_msg updt_msg;
1161 rfb_client_t *c = arg;
1162 unsigned char cmd;
1163 bool ret = true;
752
1164
753 (void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1);
754
755 if (rc->enc_extkeyevent_ok && (!rc->enc_extkeyevent_send)) {
756 rfb_send_extended_keyevent_update_msg(rc, cfd);
757 rc->enc_extkeyevent_send = true;
1165 while (ret && !c->rc_closing && (read(c->rc_fd, &cmd, 1) == 1)) {
1166 switch (cmd) {
1167 case RFBP_CS_SET_PIXEL_FORMAT:
1168 ret = rfb_recv_set_pixel_format(c);
1169 break;
1170 case RFBP_CS_SET_ENCODINGS:
1171 ret = rfb_recv_set_encodings(c);
1172 break;
1173 case RFBP_CS_UPDATE_REQUEST:
1174 ret = rfb_recv_update(c);
1175 break;
1176 case RFBP_CS_KEY_EVENT:
1177 ret = rfb_recv_key_event(c);
1178 break;
1179 case RFBP_CS_POINTER_EVENT:
1180 ret = rfb_recv_pointer_event(c);
1181 break;
1182 case RFBP_CS_CUT_TEXT:
1183 ret = rfb_recv_cut_text(c);
1184 break;
1185 case RFBP_CS_QEMU:
1186 ret = rfb_recv_qemu(c);
1187 break;
1188 default:
1189 rfb_printf(c, RFB_LOGWARN, "unknown cs code %d",
1190 cmd & 0xff);
1191 ret = false;
1192 }
758 }
759
1193 }
1194
760 rc->pending = true;
761 if (!updt_msg.incremental)
762 rc->update_all = true;
1195 rfb_printf(c, RFB_LOGDEBUG, "client rx thread exiting");
1196 c->rc_closing = true;
1197
1198 return (NULL);
763}
764
1199}
1200
765static void
766rfb_recv_key_msg(struct rfb_softc *rc, int cfd)
1201static void *
1202rfb_client_tx_thread(void *arg)
767{
1203{
768 struct rfb_key_msg key_msg;
1204 rfb_client_t *c = arg;
1205 rfb_server_t *s = c->rc_s;
1206 char tname[MAXCOMLEN + 1];
1207 uint_t counter = 0;
1208 hrtime_t tprev;
1209 void *status;
1210 int err;
769
1211
770 (void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1);
1212 (void) snprintf(tname, sizeof (tname), "rfb%u tx", c->rc_instance);
1213 (void) pthread_set_name_np(c->rc_tx_tid, tname);
771
1214
772 console_key_event(key_msg.down, htonl(key_msg.sym), htonl(0));
773 rc->input_detected = true;
774}
1215 c->rc_sinfo.rsi_pixfmt = c->rc_s->rs_pixfmt;
1216 c->rc_encodings = RFB_ENCODING_RAW;
775
1217
776static void
777rfb_recv_client_msg(struct rfb_softc *rc, int cfd)
778{
779 struct rfb_client_msg client_msg;
780 struct rfb_extended_key_msg extkey_msg;
1218 if (!rfb_handshake(c))
1219 goto out;
781
1220
782 (void)stream_read(cfd, ((void *)&client_msg) + 1, sizeof(client_msg) - 1);
783
784 if (client_msg.subtype == RFB_CLIENTMSG_EXT_KEYEVENT ) {
785 (void)stream_read(cfd, ((void *)&extkey_msg) + 2, sizeof(extkey_msg) - 2);
786 console_key_event((int)extkey_msg.down, htonl(extkey_msg.sym), htonl(extkey_msg.code));
787 rc->input_detected = true;
1221 c->rc_cells = howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, RFB_PIX_PER_CELL);
1222 if ((c->rc_crc = calloc(c->rc_cells, sizeof (uint32_t))) == NULL ||
1223 (c->rc_crc_tmp = calloc(c->rc_cells, sizeof (uint32_t))) == NULL) {
1224 perror("calloc crc");
1225 goto out;
788 }
1226 }
789}
790
1227
791static void
792rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd)
793{
794 struct rfb_ptr_msg ptr_msg;
795
796 (void)stream_read(cfd, ((void *)&ptr_msg) + 1, sizeof(ptr_msg) - 1);
797
798 console_ptr_event(ptr_msg.button, htons(ptr_msg.x), htons(ptr_msg.y));
799 rc->input_detected = true;
800}
801
802static void
803rfb_recv_cuttext_msg(struct rfb_softc *rc, int cfd)
804{
805 struct rfb_cuttext_msg ct_msg;
806 unsigned char buf[32];
807 int len;
808
809 len = stream_read(cfd, ((void *)&ct_msg) + 1, sizeof(ct_msg) - 1);
810 ct_msg.length = htonl(ct_msg.length);
811 while (ct_msg.length > 0) {
812 len = stream_read(cfd, buf, ct_msg.length > sizeof(buf) ?
813 sizeof(buf) : ct_msg.length);
814 ct_msg.length -= len;
1228 err = pthread_create(&c->rc_rx_tid, NULL, rfb_client_rx_thread, c);
1229 if (err != 0) {
1230 perror("pthread_create client rx thread");
1231 goto out;
815 }
1232 }
816}
817
1233
818static int64_t
819timeval_delta(struct timeval *prev, struct timeval *now)
820{
821 int64_t n1, n2;
822 n1 = now->tv_sec * 1000000 + now->tv_usec;
823 n2 = prev->tv_sec * 1000000 + prev->tv_usec;
824 return (n1 - n2);
825}
1234 (void) snprintf(tname, sizeof (tname), "rfb%u rx", c->rc_instance);
1235 (void) pthread_set_name_np(c->rc_rx_tid, tname);
826
1236
827static void *
828rfb_wr_thr(void *arg)
829{
830 struct rfb_softc *rc;
831 fd_set rfds;
832 struct timeval tv;
833 struct timeval prev_tv;
834 int64_t tdiff;
835 int cfd;
836 int err;
1237 tprev = gethrtime();
837
1238
838 rc = arg;
839 cfd = rc->cfd;
1239 while (!c->rc_closing) {
1240 struct timeval tv;
1241 hrtime_t tnow;
1242 int64_t tdiff;
1243 fd_set rfds;
1244 int err;
840
1245
841 prev_tv.tv_sec = 0;
842 prev_tv.tv_usec = 0;
843 while (rc->cfd >= 0) {
844 FD_ZERO(&rfds);
1246 FD_ZERO(&rfds);
845 FD_SET(cfd, &rfds);
1247 FD_SET(c->rc_fd, &rfds);
846 tv.tv_sec = 0;
1248 tv.tv_sec = 0;
847 tv.tv_usec = CFD_SEL_DELAY;
1249 tv.tv_usec = RFB_SEL_DELAY_US;
848
1250
849 err = select(cfd+1, &rfds, NULL, NULL, &tv);
1251 err = select(c->rc_fd + 1, &rfds, NULL, NULL, &tv);
850 if (err < 0)
1252 if (err < 0)
851 return (NULL);
1253 break;
852
1254
853 /* Determine if its time to push screen; ~24hz */
854 gettimeofday(&tv, NULL);
855 tdiff = timeval_delta(&prev_tv, &tv);
856 if (tdiff >= SCREEN_POLL_DELAY) {
1255 /* Determine if its time to push the screen; ~24hz. */
1256 tnow = gethrtime();
1257 tdiff = NSEC2USEC(tnow - tprev);
1258 if (tdiff >= RFB_SCREEN_POLL_DELAY) {
857 bool input;
1259 bool input;
858 prev_tv.tv_sec = tv.tv_sec;
859 prev_tv.tv_usec = tv.tv_usec;
860 input = atomic_exchange(&rc->input_detected, false);
1260
1261 tprev = tnow;
1262
1263 input = atomic_exchange(&c->rc_input_detected, false);
861 /*
1264 /*
862 * Refresh the screen on every second trip through the loop,
863 * or if keyboard/mouse input has been detected.
1265 * Refresh the screen on every second trip through the
1266 * loop, or if keyboard/mouse input has been detected.
864 */
1267 */
865 if ((++rc->wrcount & 1) || input) {
866 if (rfb_send_screen(rc, cfd) <= 0) {
867 return (NULL);
868 }
1268 if ((++counter & 1) != 0 || input) {
1269 if (!rfb_send_screen(c))
1270 break;
869 }
870 } else {
1271 }
1272 } else {
871 /* sleep */
872 usleep(SCREEN_POLL_DELAY - tdiff);
1273 (void) usleep(RFB_SCREEN_POLL_DELAY - tdiff);
873 }
874 }
875
1274 }
1275 }
1276
1277 rfb_printf(c, RFB_LOGWARN, "disconnected");
1278
1279out:
1280
1281 (void) pthread_join(c->rc_rx_tid, &status);
1282 pthread_mutex_lock(&s->rs_clientlock);
1283 s->rs_clientcount--;
1284 list_remove(&s->rs_clients, c);
1285 if (s->rs_exclusive && s->rs_clientcount == 0)
1286 s->rs_exclusive = false;
1287 id_free(rfb_idspace, c->rc_instance);
1288 pthread_mutex_unlock(&s->rs_clientlock);
1289
1290 rfb_free_client(c);
876 return (NULL);
877}
878
1291 return (NULL);
1292}
1293
879void
880rfb_handle(struct rfb_softc *rc, int cfd)
1294static void
1295rfb_accept(int sfd, enum ev_type event, void *arg)
881{
1296{
882 const char *vbuf = "RFB 003.008\n";
883 unsigned char buf[80];
884 unsigned char *message = NULL;
1297 rfb_server_t *s = arg;
1298 rfb_client_t *c = NULL;
1299 struct sockaddr_storage cliaddr;
1300 socklen_t len;
1301 char host[NI_MAXHOST], port[NI_MAXSERV];
1302 int cfd, err;
1303 uint_t cc;
885
1304
886#ifndef NO_OPENSSL
887 unsigned char challenge[AUTH_LENGTH];
888 unsigned char keystr[PASSWD_LENGTH];
889 unsigned char crypt_expected[AUTH_LENGTH];
1305 rfb_printf(c, RFB_LOGDEBUG, "incoming connection");
890
1306
891 DES_key_schedule ks;
892 int i;
893#endif
894 uint8_t client_ver;
895 uint8_t auth_type;
896 pthread_t tid;
897 uint32_t sres = 0;
898 int len;
899 int perror = 1;
900
901 rc->cfd = cfd;
902
903 /* 1a. Send server version */
904 stream_write(cfd, vbuf, strlen(vbuf));
905
906 /* 1b. Read client version */
907 len = stream_read(cfd, buf, VERSION_LENGTH);
908#ifdef __FreeBSD__
909 if (len == VERSION_LENGTH && !strncmp(vbuf, buf, VERSION_LENGTH - 2)) {
910 client_ver = buf[VERSION_LENGTH - 2];
1307 len = sizeof (cliaddr);
1308 cfd = accept(sfd, (struct sockaddr *)&cliaddr, &len);
1309 if (cfd == -1) {
1310 perror("client accept");
1311 return;
911 }
1312 }
912#else
913 /* Work around gcc7 maybe-uninitialized warning */
914 client_ver = CVERS_3_3;
915 if (len == VERSION_LENGTH && !strncmp(vbuf, (char *)buf,
916 VERSION_LENGTH - 2)) {
917 client_ver = buf[VERSION_LENGTH - 2];
918 }
919#endif
920 if (client_ver != CVERS_3_8 && client_ver != CVERS_3_7) {
921 /* only recognize 3.3, 3.7 & 3.8. Others dflt to 3.3 */
922 client_ver = CVERS_3_3;
923 }
924
1313
925 /* 2a. Send security type */
926 buf[0] = 1;
927
928 /* In versions 3.7 & 3.8, it's 2-way handshake */
929 /* For version 3.3, server says what the authentication type must be */
930#ifndef NO_OPENSSL
931 if (rc->password) {
932 auth_type = SECURITY_TYPE_VNC_AUTH;
1314 *host = *port = '\0';
1315 if (cliaddr.ss_family == AF_UNIX) {
1316 rfb_printf(NULL, RFB_LOGDEBUG, "connection on UNIX socket");
1317 (void) strlcpy(host, "<UNIX>", sizeof (host));
933 } else {
1318 } else {
934 auth_type = SECURITY_TYPE_NONE;
1319 err = getnameinfo((struct sockaddr *)&cliaddr, len,
1320 host, sizeof (host), port, sizeof (port),
1321 NI_NUMERICHOST | NI_NUMERICSERV);
1322 if (err != 0) {
1323 rfb_printf(NULL, RFB_LOGERR, "getnameinfo: %s",
1324 gai_strerror(err));
1325 *host = *port = '\0';
1326 } else {
1327 rfb_printf(NULL, RFB_LOGDEBUG, "connection from %s:%s",
1328 host, port);
1329 }
935 }
1330 }
936#else
937 auth_type = SECURITY_TYPE_NONE;
938#endif
939
1331
940 switch (client_ver) {
941 case CVERS_3_7:
942 case CVERS_3_8:
943 buf[0] = 1;
944 buf[1] = auth_type;
945 stream_write(cfd, buf, 2);
1332 pthread_mutex_lock(&s->rs_clientlock);
1333 cc = s->rs_clientcount;
1334 pthread_mutex_unlock(&s->rs_clientlock);
1335 if (cc >= RFB_MAX_CLIENTS) {
1336 rfb_printf(NULL, RFB_LOGERR,
1337 "too many clients, closing connection.");
1338 goto fail;
1339 }
946
1340
947 /* 2b. Read agreed security type */
948 len = stream_read(cfd, buf, 1);
949 if (buf[0] != auth_type) {
950 /* deny */
951 sres = htonl(1);
952#ifdef __FreeBSD__
953 message = "Auth failed: authentication type mismatch";
954#else
955 message = (unsigned char *)
956 "Auth failed: authentication type mismatch";
957#endif
958 goto report_and_done;
959 }
960 break;
961 case CVERS_3_3:
962 default:
963 be32enc(buf, auth_type);
964 stream_write(cfd, buf, 4);
965 break;
1341 if ((c = calloc(1, sizeof (rfb_client_t))) == NULL) {
1342 perror("calloc client");
1343 goto fail;
966 }
967
1344 }
1345
968 /* 2c. Do VNC authentication */
969 switch (auth_type) {
970 case SECURITY_TYPE_NONE:
971 break;
972 case SECURITY_TYPE_VNC_AUTH:
973 /*
974 * The client encrypts the challenge with DES, using a password
975 * supplied by the user as the key.
976 * To form the key, the password is truncated to
977 * eight characters, or padded with null bytes on the right.
978 * The client then sends the resulting 16-bytes response.
979 */
980#ifndef NO_OPENSSL
981#ifdef __FreeBSD__
982 strncpy(keystr, rc->password, PASSWD_LENGTH);
983#else
984 strncpy((char *)keystr, rc->password, PASSWD_LENGTH);
985#endif
1346 c->rc_fd = cfd;
1347 c->rc_s = s;
1348 c->rc_zbuf = malloc(RFB_ZLIB_BUFSZ + 16);
1349 if (c->rc_zbuf == NULL)
1350 goto fail;
986
1351
987 /* VNC clients encrypts the challenge with all the bit fields
988 * in each byte of the password mirrored.
989 * Here we flip each byte of the keystr.
990 */
991 for (i = 0; i < PASSWD_LENGTH; i++) {
992 keystr[i] = (keystr[i] & 0xF0) >> 4
993 | (keystr[i] & 0x0F) << 4;
994 keystr[i] = (keystr[i] & 0xCC) >> 2
995 | (keystr[i] & 0x33) << 2;
996 keystr[i] = (keystr[i] & 0xAA) >> 1
997 | (keystr[i] & 0x55) << 1;
998 }
1352 pthread_mutex_lock(&s->rs_clientlock);
999
1353
1000 /* Initialize a 16-byte random challenge */
1001 arc4random_buf(challenge, sizeof(challenge));
1002 stream_write(cfd, challenge, AUTH_LENGTH);
1003
1004 /* Receive the 16-byte challenge response */
1005 stream_read(cfd, buf, AUTH_LENGTH);
1006
1007 memcpy(crypt_expected, challenge, AUTH_LENGTH);
1008
1009 /* Encrypt the Challenge with DES */
1010 DES_set_key((const_DES_cblock *)keystr, &ks);
1011 DES_ecb_encrypt((const_DES_cblock *)challenge,
1012 (const_DES_cblock *)crypt_expected,
1013 &ks, DES_ENCRYPT);
1014 DES_ecb_encrypt((const_DES_cblock *)(challenge + PASSWD_LENGTH),
1015 (const_DES_cblock *)(crypt_expected +
1016 PASSWD_LENGTH),
1017 &ks, DES_ENCRYPT);
1018
1019 if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) {
1020#ifdef __FreeBSD__
1021 message = "Auth Failed: Invalid Password.";
1022#else
1023 message =
1024 (unsigned char *)"Auth Failed: Invalid Password.";
1025#endif
1026 sres = htonl(1);
1027 } else {
1028 sres = 0;
1029 }
1030#else
1031 sres = htonl(1);
1032 WPRINTF(("Auth not supported, no OpenSSL in your system"));
1033#endif
1034
1035 break;
1354 err = pthread_create(&c->rc_tx_tid, NULL, rfb_client_tx_thread, c);
1355 if (err != 0) {
1356 perror("pthread_create client tx thread");
1357 pthread_mutex_unlock(&s->rs_clientlock);
1358 goto fail;
1036 }
1037
1359 }
1360
1038 switch (client_ver) {
1039 case CVERS_3_7:
1040 case CVERS_3_8:
1041report_and_done:
1042 /* 2d. Write back a status */
1043 stream_write(cfd, &sres, 4);
1361 s->rs_clientcount++;
1362 list_insert_tail(&s->rs_clients, c);
1363 c->rc_instance = id_allocff(rfb_idspace);
1364 pthread_mutex_unlock(&s->rs_clientlock);
1044
1365
1045 if (sres) {
1046 /* 3.7 does not want string explaining cause */
1047 if (client_ver == CVERS_3_8) {
1048#ifdef __FreeBSD__
1049 be32enc(buf, strlen(message));
1050 stream_write(cfd, buf, 4);
1051 stream_write(cfd, message, strlen(message));
1052#else
1053 be32enc(buf, strlen((char *)message));
1054 stream_write(cfd, buf, 4);
1055 stream_write(cfd, message,
1056 strlen((char *)message));
1057#endif
1058 }
1059 goto done;
1060 }
1061 break;
1062 case CVERS_3_3:
1063 default:
1064 /* for VNC auth case send status */
1065 if (auth_type == SECURITY_TYPE_VNC_AUTH) {
1066 /* 2d. Write back a status */
1067 stream_write(cfd, &sres, 4);
1068 }
1069 if (sres) {
1070 goto done;
1071 }
1072 break;
1073 }
1074 /* 3a. Read client shared-flag byte */
1075 len = stream_read(cfd, buf, 1);
1366 (void) pthread_detach(c->rc_tx_tid);
1076
1367
1077 /* 4a. Write server-init info */
1078#ifndef __FreeBSD__
1079 rfb_send_server_init_msg(cfd, rc);
1080#else
1081 rfb_send_server_init_msg(cfd);
1082#endif
1368 rfb_printf(c, RFB_LOGWARN, "connection from %s", host);
1083
1369
1084 if (!rc->zbuf) {
1085 rc->zbuf = malloc(RFB_ZLIB_BUFSZ + 16);
1086 assert(rc->zbuf != NULL);
1087 }
1370 return;
1088
1371
1089 perror = pthread_create(&tid, NULL, rfb_wr_thr, rc);
1090 if (perror == 0)
1091 pthread_set_name_np(tid, "rfbout");
1092
1093 /* Now read in client requests. 1st byte identifies type */
1094 for (;;) {
1095 len = read(cfd, buf, 1);
1096 if (len <= 0) {
1097 DPRINTF(("rfb client exiting"));
1098 break;
1099 }
1100
1101 switch (buf[0]) {
1102 case CS_SET_PIXEL_FORMAT:
1103 rfb_recv_set_pixfmt_msg(rc, cfd);
1104 break;
1105 case CS_SET_ENCODINGS:
1106 rfb_recv_set_encodings_msg(rc, cfd);
1107 break;
1108 case CS_UPDATE_MSG:
1109 rfb_recv_update_msg(rc, cfd);
1110 break;
1111 case CS_KEY_EVENT:
1112 rfb_recv_key_msg(rc, cfd);
1113 break;
1114 case CS_POINTER_EVENT:
1115 rfb_recv_ptr_msg(rc, cfd);
1116 break;
1117 case CS_CUT_TEXT:
1118 rfb_recv_cuttext_msg(rc, cfd);
1119 break;
1120 case CS_MSG_CLIENT_QEMU:
1121 rfb_recv_client_msg(rc, cfd);
1122 break;
1123 default:
1124 WPRINTF(("rfb unknown cli-code %d!", buf[0] & 0xff));
1125 goto done;
1126 }
1127 }
1128done:
1129 rc->cfd = -1;
1130 if (perror == 0)
1131 pthread_join(tid, NULL);
1132 if (rc->enc_zlib_ok)
1133 deflateEnd(&rc->zstream);
1372fail:
1373 (void) close(cfd);
1374 free(c);
1134}
1135
1375}
1376
1136static void *
1137rfb_thr(void *arg)
1377int
1378rfb_init(char *hostname, int port, int wait, const char *password,
1379 const char *name)
1138{
1380{
1139 struct rfb_softc *rc;
1140 sigset_t set;
1381 rfb_server_t *s;
1382#ifndef WITHOUT_CAPSICUM
1383 cap_rights_t rights;
1384#endif
1141
1385
1142 int cfd;
1386 (void) pthread_once(&rfb_once, rfb_init_once);
1143
1387
1144 rc = arg;
1388 if (rfb_idspace == NULL) {
1389 rfb_printf(NULL, RFB_LOGERR,
1390 "rfb_idspace could not be allocated");
1391 return (-1);
1392 }
1145
1393
1146 sigemptyset(&set);
1147 sigaddset(&set, SIGPIPE);
1148 if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
1149 perror("pthread_sigmask");
1150 return (NULL);
1394 if ((s = calloc(1, sizeof (rfb_server_t))) == NULL) {
1395 perror("calloc");
1396 return (-1);
1151 }
1397 }
1398 s->rs_fd = -1;
1399 s->rs_name = name;
1152
1400
1153 for (;;) {
1154 rc->enc_raw_ok = false;
1155 rc->enc_zlib_ok = false;
1156 rc->enc_resize_ok = false;
1157 rc->enc_extkeyevent_ok = false;
1401 if (password != NULL && strlen(password) > 0)
1402 s->rs_password = password;
1158
1403
1159 rc->enc_extkeyevent_send = false;
1160
1161 cfd = accept(rc->sfd, NULL, NULL);
1162 if (rc->conn_wait) {
1163 pthread_mutex_lock(&rc->mtx);
1164 pthread_cond_signal(&rc->cond);
1165 pthread_mutex_unlock(&rc->mtx);
1166 rc->conn_wait = 0;
1167 }
1168 rfb_handle(rc, cfd);
1169 close(cfd);
1404 if (pthread_mutex_init(&s->rs_clientlock, NULL) != 0) {
1405 perror("pthread_mutex_init");
1406 free(s);
1407 return (-1);
1170 }
1171
1408 }
1409
1172 /* NOTREACHED */
1173 return (NULL);
1174}
1410 list_create(&s->rs_clients, sizeof (rfb_client_t),
1411 offsetof(rfb_client_t, rc_node));
1175
1412
1176static int
1177sse42_supported(void)
1178{
1179 u_int cpu_registers[4], ecx;
1413 /* Server pixel format. */
1414 s->rs_pixfmt.rp_bpp = RFB_PIX_BPP;
1415 s->rs_pixfmt.rp_depth = RFB_PIX_DEPTH;
1416 s->rs_pixfmt.rp_bigendian = 0;
1417 s->rs_pixfmt.rp_truecolour = 1;
1418 s->rs_pixfmt.rp_r_max = htons(RFB_PIX_RMAX);
1419 s->rs_pixfmt.rp_g_max = htons(RFB_PIX_GMAX);
1420 s->rs_pixfmt.rp_b_max = htons(RFB_PIX_BMAX);
1421 s->rs_pixfmt.rp_r_shift = RFB_PIX_RSHIFT;
1422 s->rs_pixfmt.rp_g_shift = RFB_PIX_GSHIFT;
1423 s->rs_pixfmt.rp_b_shift = RFB_PIX_BSHIFT;
1180
1424
1181 do_cpuid(1, cpu_registers);
1425 /* UNIX socket. */
1426 if (port == -1 && hostname != NULL && *hostname == '/') {
1427 struct sockaddr_un sock;
1182
1428
1183 ecx = cpu_registers[2];
1429 s->rs_fd = socket(PF_UNIX, SOCK_STREAM, 0);
1430 if (s->rs_fd < 0) {
1431 perror("socket");
1432 goto fail;
1433 }
1184
1434
1185 return ((ecx & CPUID2_SSE42) != 0);
1186}
1435 sock.sun_family = AF_UNIX;
1436 if (strlcpy(sock.sun_path, hostname, sizeof (sock.sun_path)) >=
1437 sizeof (sock.sun_path)) {
1438 rfb_printf(NULL, RFB_LOGERR,
1439 "socket path '%s' too long\n", hostname);
1440 goto fail;
1441 }
1187
1442
1188int
1189#ifndef __FreeBSD__
1190rfb_init(char *hostname, int port, int wait, char *password, const char *name)
1191#else
1192rfb_init(char *hostname, int port, int wait, char *password)
1193#endif
1194{
1195 int e;
1196 char servname[6];
1197 struct rfb_softc *rc;
1198 struct addrinfo *ai = NULL;
1199 struct addrinfo hints;
1200 int on = 1;
1201 int cnt;
1202#ifndef WITHOUT_CAPSICUM
1203 cap_rights_t rights;
1204#endif
1443 (void) unlink(hostname);
1444 if (bind(s->rs_fd, (struct sockaddr *)&sock,
1445 sizeof (sock)) < 0) {
1446 perror("bind");
1447 goto fail;
1448 }
1449 } else {
1450 struct addrinfo hints, *ai = NULL;
1451 char servname[6];
1452 int e;
1205
1453
1206 rc = calloc(1, sizeof(struct rfb_softc));
1454 (void) snprintf(servname, sizeof (servname), "%d",
1455 port ? port : RFB_DEFAULT_PORT);
1207
1456
1208 cnt = howmany(RFB_MAX_WIDTH, PIX_PER_CELL) *
1209 howmany(RFB_MAX_HEIGHT, PIX_PER_CELL);
1210 rc->crc = calloc(cnt, sizeof(uint32_t));
1211 rc->crc_tmp = calloc(cnt, sizeof(uint32_t));
1212 rc->crc_width = RFB_MAX_WIDTH;
1213 rc->crc_height = RFB_MAX_HEIGHT;
1214 rc->sfd = -1;
1215
1216 rc->password = password;
1217
1218#ifndef __FreeBSD__
1219 rc->name = name;
1220#endif
1221
1222 snprintf(servname, sizeof(servname), "%d", port ? port : 5900);
1223
1224 if (!hostname || strlen(hostname) == 0)
1457 if (hostname == NULL || strlen(hostname) == 0) {
1225#if defined(INET)
1458#if defined(INET)
1226 hostname = "127.0.0.1";
1459 hostname = "127.0.0.1";
1227#elif defined(INET6)
1460#elif defined(INET6)
1228 hostname = "[::1]";
1461 hostname = "[::1]";
1229#endif
1462#endif
1463 }
1230
1464
1231 memset(&hints, 0, sizeof(hints));
1232 hints.ai_family = AF_UNSPEC;
1233 hints.ai_socktype = SOCK_STREAM;
1234 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE;
1465 memset(&hints, '\0', sizeof (hints));
1466 hints.ai_family = AF_UNSPEC;
1467 hints.ai_socktype = SOCK_STREAM;
1468 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE;
1235
1469
1236 if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) {
1237 EPRINTLN("getaddrinfo: %s", gai_strerror(e));
1238 goto error;
1239 }
1470 if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) {
1471 rfb_printf(NULL, RFB_LOGERR, "getaddrinfo: %s",
1472 gai_strerror(e));
1473 goto fail;
1474 }
1240
1475
1241 rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0);
1242 if (rc->sfd < 0) {
1243 perror("socket");
1244 goto error;
1245 }
1476 s->rs_fd = socket(ai->ai_family, ai->ai_socktype, 0);
1477 if (s->rs_fd < 0) {
1478 perror("socket");
1479 freeaddrinfo(ai);
1480 goto fail;
1481 }
1246
1482
1247 setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1483 e = 1;
1484 (void) setsockopt(s->rs_fd, SOL_SOCKET, SO_REUSEADDR,
1485 &e, sizeof (e));
1248
1486
1249 if (bind(rc->sfd, ai->ai_addr, ai->ai_addrlen) < 0) {
1250 perror("bind");
1251 goto error;
1487 if (bind(s->rs_fd, ai->ai_addr, ai->ai_addrlen) < 0) {
1488 perror("bind");
1489 freeaddrinfo(ai);
1490 goto fail;
1491 }
1492 freeaddrinfo(ai);
1252 }
1253
1493 }
1494
1254 if (listen(rc->sfd, 1) < 0) {
1495 if (listen(s->rs_fd, 5) < 0) {
1255 perror("listen");
1496 perror("listen");
1256 goto error;
1497 goto fail;
1257 }
1258
1259#ifndef WITHOUT_CAPSICUM
1260 cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE);
1498 }
1499
1500#ifndef WITHOUT_CAPSICUM
1501 cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE);
1261 if (caph_rights_limit(rc->sfd, &rights) == -1)
1502 if (caph_rights_limit(s->rs_fd, &rights) == -1)
1262 errx(EX_OSERR, "Unable to apply rights for sandbox");
1263#endif
1264
1503 errx(EX_OSERR, "Unable to apply rights for sandbox");
1504#endif
1505
1265 rc->hw_crc = sse42_supported();
1266
1267 rc->conn_wait = wait;
1268 if (wait) {
1269 pthread_mutex_init(&rc->mtx, NULL);
1270 pthread_cond_init(&rc->cond, NULL);
1271 }
1272
1273 pthread_create(&rc->tid, NULL, rfb_thr, rc);
1274 pthread_set_name_np(rc->tid, "rfb");
1275
1276 if (wait) {
1277 DPRINTF(("Waiting for rfb client..."));
1278 pthread_mutex_lock(&rc->mtx);
1279 pthread_cond_wait(&rc->cond, &rc->mtx);
1280 pthread_mutex_unlock(&rc->mtx);
1281 DPRINTF(("rfb client connected"));
1282 }
1283
1284 freeaddrinfo(ai);
1285 return (0);
1286
1287 error:
1288 if (ai != NULL)
1289 freeaddrinfo(ai);
1290 if (rc->sfd != -1)
1291 close(rc->sfd);
1292 free(rc->crc);
1293 free(rc->crc_tmp);
1294 free(rc);
1295 return (-1);
1296}
1297
1298#ifndef __FreeBSD__
1299int
1300rfb_init_unix(const char *path, int wait, char *password, const char *name)
1301{
1302 struct rfb_softc *rc;
1303 struct sockaddr_un sock;
1304
1305 if ((rc = calloc(1, sizeof (struct rfb_softc))) == NULL) {
1306 perror("calloc");
1307 return (-1);
1308 }
1309 rc->sfd = -1;
1310
1311 if ((rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
1312 sizeof (uint32_t))) == NULL) {
1313 perror("calloc");
1506 s->rs_connevent = mevent_add(s->rs_fd, EVF_READ, rfb_accept, s);
1507 if (s->rs_connevent == NULL) {
1508 rfb_printf(NULL, RFB_LOGERR,
1509 "Failed to set up rfb connection mevent");
1314 goto fail;
1315 }
1510 goto fail;
1511 }
1316 if ((rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
1317 sizeof (uint32_t))) == NULL) {
1318 perror("calloc");
1319 goto fail;
1320 }
1321 rc->crc_width = RFB_MAX_WIDTH;
1322 rc->crc_height = RFB_MAX_HEIGHT;
1323
1512
1324 rc->password = password;
1325 rc->name = name;
1513 list_insert_tail(&rfb_list, s);
1326
1514
1327 rc->sfd = socket(PF_UNIX, SOCK_STREAM, 0);
1328 if (rc->sfd < 0) {
1329 perror("socket");
1330 goto fail;
1331 }
1515 /*
1516 * Wait for first connection. Since the mevent thread is
1517 * not yet running, we can't rely on normal incoming connection
1518 * handling.
1519 */
1520 if (wait != 0) {
1521 fd_set rfds;
1522 int e;
1332
1523
1333 sock.sun_family = AF_UNIX;
1334 if (strlcpy(sock.sun_path, path, sizeof (sock.sun_path)) >=
1335 sizeof (sock.sun_path)) {
1336 (void) fprintf(stderr, "socket path '%s' too long\n", path);
1337 goto fail;
1338 }
1524 rfb_printf(NULL, RFB_LOGWARN,
1525 "holding boot until first client connection");
1339
1526
1340 (void) unlink(path);
1341 if (bind(rc->sfd, (struct sockaddr *)&sock, sizeof (sock)) < 0) {
1342 perror("bind");
1343 goto fail;
1344 }
1527 for (;;) {
1528 FD_ZERO(&rfds);
1529 FD_SET(s->rs_fd, &rfds);
1345
1530
1346 if (listen(rc->sfd, 1) < 0) {
1347 perror("listen");
1348 goto fail;
1531 e = select(s->rs_fd + 1, &rfds, NULL, NULL, NULL);
1532 if (e < 0 && errno == EINTR)
1533 continue;
1534 if (e < 0 || FD_ISSET(s->rs_fd, &rfds))
1535 break;
1536 }
1537 rfb_printf(NULL, RFB_LOGWARN, "continuing boot");
1349 }
1350
1538 }
1539
1351 rc->hw_crc = sse42_supported();
1352
1353 rc->conn_wait = wait;
1354 if (wait) {
1355 VERIFY3S(pthread_mutex_init(&rc->mtx, NULL), ==, 0);
1356 VERIFY3S(pthread_cond_init(&rc->cond, NULL), ==, 0);
1357 }
1358
1359 VERIFY3S(pthread_create(&rc->tid, NULL, rfb_thr, rc), ==, 0);
1360 pthread_set_name_np(rc->tid, "rfb");
1361
1362 if (wait) {
1363 DPRINTF(("Waiting for rfb client...\n"));
1364 pthread_mutex_lock(&rc->mtx);
1365 VERIFY3S(pthread_cond_wait(&rc->cond, &rc->mtx), ==, 0);
1366 pthread_mutex_unlock(&rc->mtx);
1367 }
1368
1369 return (0);
1370
1371fail:
1540 return (0);
1541
1542fail:
1372 if (rc->sfd != -1) {
1373 VERIFY3S(close(rc->sfd), ==, 0);
1374 }
1375 free(rc->crc);
1376 free(rc->crc_tmp);
1377 free(rc);
1543 if (s->rs_fd != -1)
1544 VERIFY3S(close(s->rs_fd), ==, 0);
1545 (void) pthread_mutex_destroy(&s->rs_clientlock);
1546 list_destroy(&s->rs_clients);
1547 free(s);
1378 return (-1);
1379}
1548 return (-1);
1549}
1380#endif