xref: /freebsd/usr.sbin/bhyve/rfb.c (revision 64a0982bee3db2236df43357e70ce8dddbc21d48)
1 /*-
2  * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3  * Copyright (c) 2015 Leon Dang
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include <sys/param.h>
32 #ifndef WITHOUT_CAPSICUM
33 #include <sys/capsicum.h>
34 #endif
35 #include <sys/socket.h>
36 #include <sys/select.h>
37 #include <sys/time.h>
38 #include <arpa/inet.h>
39 #include <machine/cpufunc.h>
40 #include <machine/specialreg.h>
41 #include <netinet/in.h>
42 
43 #include <assert.h>
44 #include <err.h>
45 #include <errno.h>
46 #include <pthread.h>
47 #include <pthread_np.h>
48 #include <signal.h>
49 #include <stdbool.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <sysexits.h>
54 #include <unistd.h>
55 
56 #include <zlib.h>
57 
58 #include "bhyvegc.h"
59 #include "console.h"
60 #include "rfb.h"
61 #include "sockstream.h"
62 
63 static int rfb_debug = 0;
64 #define	DPRINTF(params) if (rfb_debug) printf params
65 #define	WPRINTF(params) printf params
66 
67 struct rfb_softc {
68 	int		sfd;
69 	pthread_t	tid;
70 
71 	int		cfd;
72 
73 	int		width, height;
74 
75 	bool		enc_raw_ok;
76 	bool		enc_zlib_ok;
77 	bool		enc_resize_ok;
78 
79 	z_stream	zstream;
80 	uint8_t		*zbuf;
81 	int		zbuflen;
82 
83 	int		conn_wait;
84 	int		sending;
85 	pthread_mutex_t mtx;
86 	pthread_cond_t  cond;
87 
88 	int		hw_crc;
89 	uint32_t	*crc;		/* WxH crc cells */
90 	uint32_t	*crc_tmp;	/* buffer to store single crc row */
91 	int		crc_width, crc_height;
92 };
93 
94 struct rfb_pixfmt {
95 	uint8_t		bpp;
96 	uint8_t		depth;
97 	uint8_t		bigendian;
98 	uint8_t		truecolor;
99 	uint16_t	red_max;
100 	uint16_t	green_max;
101 	uint16_t	blue_max;
102 	uint8_t		red_shift;
103 	uint8_t		green_shift;
104 	uint8_t		blue_shift;
105 	uint8_t		pad[3];
106 };
107 
108 struct rfb_srvr_info {
109 	uint16_t		width;
110 	uint16_t		height;
111 	struct rfb_pixfmt	pixfmt;
112 	uint32_t		namelen;
113 };
114 
115 struct rfb_pixfmt_msg {
116 	uint8_t			type;
117 	uint8_t			pad[3];
118 	struct rfb_pixfmt	pixfmt;
119 };
120 
121 #define	RFB_ENCODING_RAW		0
122 #define	RFB_ENCODING_ZLIB		6
123 #define	RFB_ENCODING_RESIZE		-223
124 
125 #define RFB_MAX_WIDTH			2000
126 #define RFB_MAX_HEIGHT			1200
127 #define	RFB_ZLIB_BUFSZ			RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
128 
129 /* percentage changes to screen before sending the entire screen */
130 #define RFB_SEND_ALL_THRESH             25
131 
132 struct rfb_enc_msg {
133 	uint8_t		type;
134 	uint8_t		pad;
135 	uint16_t	numencs;
136 };
137 
138 struct rfb_updt_msg {
139 	uint8_t		type;
140 	uint8_t		incremental;
141 	uint16_t	x;
142 	uint16_t	y;
143 	uint16_t	width;
144 	uint16_t	height;
145 };
146 
147 struct rfb_key_msg {
148 	uint8_t		type;
149 	uint8_t		down;
150 	uint16_t	pad;
151 	uint32_t	code;
152 };
153 
154 struct rfb_ptr_msg {
155 	uint8_t		type;
156 	uint8_t		button;
157 	uint16_t	x;
158 	uint16_t	y;
159 };
160 
161 struct rfb_srvr_updt_msg {
162 	uint8_t		type;
163 	uint8_t		pad;
164 	uint16_t	numrects;
165 };
166 
167 struct rfb_srvr_rect_hdr {
168 	uint16_t	x;
169 	uint16_t	y;
170 	uint16_t	width;
171 	uint16_t	height;
172 	uint32_t	encoding;
173 };
174 
175 struct rfb_cuttext_msg {
176 	uint8_t		type;
177 	uint8_t		padding[3];
178 	uint32_t	length;
179 };
180 
181 
182 static void
183 rfb_send_server_init_msg(int cfd)
184 {
185 	struct bhyvegc_image *gc_image;
186 	struct rfb_srvr_info sinfo;
187 
188 	gc_image = console_get_image();
189 
190 	sinfo.width = htons(gc_image->width);
191 	sinfo.height = htons(gc_image->height);
192 	sinfo.pixfmt.bpp = 32;
193 	sinfo.pixfmt.depth = 32;
194 	sinfo.pixfmt.bigendian = 0;
195 	sinfo.pixfmt.truecolor = 1;
196 	sinfo.pixfmt.red_max = htons(255);
197 	sinfo.pixfmt.green_max = htons(255);
198 	sinfo.pixfmt.blue_max = htons(255);
199 	sinfo.pixfmt.red_shift = 16;
200 	sinfo.pixfmt.green_shift = 8;
201 	sinfo.pixfmt.blue_shift = 0;
202 	sinfo.namelen = htonl(strlen("bhyve"));
203 	(void)stream_write(cfd, &sinfo, sizeof(sinfo));
204 	(void)stream_write(cfd, "bhyve", strlen("bhyve"));
205 }
206 
207 static void
208 rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd)
209 {
210 	struct rfb_srvr_updt_msg supdt_msg;
211         struct rfb_srvr_rect_hdr srect_hdr;
212 
213 	/* Number of rectangles: 1 */
214 	supdt_msg.type = 0;
215 	supdt_msg.pad = 0;
216 	supdt_msg.numrects = htons(1);
217 	stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
218 
219 	/* Rectangle header */
220 	srect_hdr.x = htons(0);
221 	srect_hdr.y = htons(0);
222 	srect_hdr.width = htons(rc->width);
223 	srect_hdr.height = htons(rc->height);
224 	srect_hdr.encoding = htonl(RFB_ENCODING_RESIZE);
225 	stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
226 }
227 
228 static void
229 rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
230 {
231 	struct rfb_pixfmt_msg pixfmt_msg;
232 
233 	(void)stream_read(cfd, ((void *)&pixfmt_msg)+1, sizeof(pixfmt_msg)-1);
234 }
235 
236 
237 static void
238 rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd)
239 {
240 	struct rfb_enc_msg enc_msg;
241 	int i;
242 	uint32_t encoding;
243 
244 	assert((sizeof(enc_msg) - 1) == 3);
245 	(void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1);
246 
247 	for (i = 0; i < htons(enc_msg.numencs); i++) {
248 		(void)stream_read(cfd, &encoding, sizeof(encoding));
249 		switch (htonl(encoding)) {
250 		case RFB_ENCODING_RAW:
251 			rc->enc_raw_ok = true;
252 			break;
253 		case RFB_ENCODING_ZLIB:
254 			rc->enc_zlib_ok = true;
255 			deflateInit(&rc->zstream, Z_BEST_SPEED);
256 			break;
257 		case RFB_ENCODING_RESIZE:
258 			rc->enc_resize_ok = true;
259 			break;
260 		}
261 	}
262 }
263 
264 /*
265  * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only
266  */
267 static __inline uint32_t
268 fast_crc32(void *buf, int len, uint32_t crcval)
269 {
270 	uint32_t q = len / sizeof(uint32_t);
271 	uint32_t *p = (uint32_t *)buf;
272 
273 	while (q--) {
274 		asm volatile (
275 			".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
276 			:"=S" (crcval)
277 			:"0" (crcval), "c" (*p)
278 		);
279 		p++;
280 	}
281 
282 	return (crcval);
283 }
284 
285 
286 static int
287 rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc,
288               int x, int y, int w, int h)
289 {
290 	struct rfb_srvr_updt_msg supdt_msg;
291         struct rfb_srvr_rect_hdr srect_hdr;
292 	unsigned long zlen;
293 	ssize_t nwrite, total;
294 	int err;
295 	uint32_t *p;
296 	uint8_t *zbufp;
297 
298 	/*
299 	 * Send a single rectangle of the given x, y, w h dimensions.
300 	 */
301 
302 	/* Number of rectangles: 1 */
303 	supdt_msg.type = 0;
304 	supdt_msg.pad = 0;
305 	supdt_msg.numrects = htons(1);
306 	nwrite = stream_write(cfd, &supdt_msg,
307 	                      sizeof(struct rfb_srvr_updt_msg));
308 	if (nwrite <= 0)
309 		return (nwrite);
310 
311 
312 	/* Rectangle header */
313 	srect_hdr.x = htons(x);
314 	srect_hdr.y = htons(y);
315 	srect_hdr.width = htons(w);
316 	srect_hdr.height = htons(h);
317 
318 	h = y + h;
319 	w *= sizeof(uint32_t);
320 	if (rc->enc_zlib_ok) {
321 		zbufp = rc->zbuf;
322 		rc->zstream.total_in = 0;
323 		rc->zstream.total_out = 0;
324 		for (p = &gc->data[y * gc->width + x]; y < h; y++) {
325 			rc->zstream.next_in = (Bytef *)p;
326 			rc->zstream.avail_in = w;
327 			rc->zstream.next_out = (Bytef *)zbufp;
328 			rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16 -
329 			                        rc->zstream.total_out;
330 			rc->zstream.data_type = Z_BINARY;
331 
332 			/* Compress with zlib */
333 			err = deflate(&rc->zstream, Z_SYNC_FLUSH);
334 			if (err != Z_OK) {
335 				WPRINTF(("zlib[rect] deflate err: %d\n", err));
336 				rc->enc_zlib_ok = false;
337 				deflateEnd(&rc->zstream);
338 				goto doraw;
339 			}
340 			zbufp = rc->zbuf + rc->zstream.total_out;
341 			p += gc->width;
342 		}
343 		srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB);
344 		nwrite = stream_write(cfd, &srect_hdr,
345 		                      sizeof(struct rfb_srvr_rect_hdr));
346 		if (nwrite <= 0)
347 			return (nwrite);
348 
349 		zlen = htonl(rc->zstream.total_out);
350 		nwrite = stream_write(cfd, &zlen, sizeof(uint32_t));
351 		if (nwrite <= 0)
352 			return (nwrite);
353 		return (stream_write(cfd, rc->zbuf, rc->zstream.total_out));
354 	}
355 
356 doraw:
357 
358 	total = 0;
359 	zbufp = rc->zbuf;
360 	for (p = &gc->data[y * gc->width + x]; y < h; y++) {
361 		memcpy(zbufp, p, w);
362 		zbufp += w;
363 		total += w;
364 		p += gc->width;
365 	}
366 
367 	srect_hdr.encoding = htonl(RFB_ENCODING_RAW);
368 	nwrite = stream_write(cfd, &srect_hdr,
369 	                      sizeof(struct rfb_srvr_rect_hdr));
370 	if (nwrite <= 0)
371 		return (nwrite);
372 
373 	total = stream_write(cfd, rc->zbuf, total);
374 
375 	return (total);
376 }
377 
378 static int
379 rfb_send_all(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc)
380 {
381 	struct rfb_srvr_updt_msg supdt_msg;
382         struct rfb_srvr_rect_hdr srect_hdr;
383 	ssize_t nwrite;
384 	unsigned long zlen;
385 	int err;
386 
387 	/*
388 	 * Send the whole thing
389 	 */
390 
391 	/* Number of rectangles: 1 */
392 	supdt_msg.type = 0;
393 	supdt_msg.pad = 0;
394 	supdt_msg.numrects = htons(1);
395 	nwrite = stream_write(cfd, &supdt_msg,
396 	                      sizeof(struct rfb_srvr_updt_msg));
397 	if (nwrite <= 0)
398 		return (nwrite);
399 
400 	/* Rectangle header */
401 	srect_hdr.x = 0;
402 	srect_hdr.y = 0;
403 	srect_hdr.width = htons(gc->width);
404 	srect_hdr.height = htons(gc->height);
405 	if (rc->enc_zlib_ok) {
406 		rc->zstream.next_in = (Bytef *)gc->data;
407 		rc->zstream.avail_in = gc->width * gc->height *
408 		                   sizeof(uint32_t);
409 		rc->zstream.next_out = (Bytef *)rc->zbuf;
410 		rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16;
411 		rc->zstream.data_type = Z_BINARY;
412 
413 		rc->zstream.total_in = 0;
414 		rc->zstream.total_out = 0;
415 
416 		/* Compress with zlib */
417 		err = deflate(&rc->zstream, Z_SYNC_FLUSH);
418 		if (err != Z_OK) {
419 			WPRINTF(("zlib deflate err: %d\n", err));
420 			rc->enc_zlib_ok = false;
421 			deflateEnd(&rc->zstream);
422 			goto doraw;
423 		}
424 
425 		srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB);
426 		nwrite = stream_write(cfd, &srect_hdr,
427 		                      sizeof(struct rfb_srvr_rect_hdr));
428 		if (nwrite <= 0)
429 			return (nwrite);
430 
431 		zlen = htonl(rc->zstream.total_out);
432 		nwrite = stream_write(cfd, &zlen, sizeof(uint32_t));
433 		if (nwrite <= 0)
434 			return (nwrite);
435 		return (stream_write(cfd, rc->zbuf, rc->zstream.total_out));
436 	}
437 
438 doraw:
439 	srect_hdr.encoding = htonl(RFB_ENCODING_RAW);
440 	nwrite = stream_write(cfd, &srect_hdr,
441 	                      sizeof(struct rfb_srvr_rect_hdr));
442 	if (nwrite <= 0)
443 		return (nwrite);
444 
445 	nwrite = stream_write(cfd, gc->data,
446 	               gc->width * gc->height * sizeof(uint32_t));
447 
448 	return (nwrite);
449 }
450 
451 #define PIX_PER_CELL	32
452 #define	PIXCELL_SHIFT	5
453 #define PIXCELL_MASK	0x1F
454 
455 static int
456 rfb_send_screen(struct rfb_softc *rc, int cfd, int all)
457 {
458 	struct bhyvegc_image *gc_image;
459 	ssize_t nwrite;
460 	int x, y;
461 	int celly, cellwidth;
462 	int xcells, ycells;
463 	int w, h;
464 	uint32_t *p;
465 	int rem_x, rem_y;   /* remainder for resolutions not x32 pixels ratio */
466 	int retval;
467 	uint32_t *crc_p, *orig_crc;
468 	int changes;
469 
470 	console_refresh();
471 	gc_image = console_get_image();
472 
473 	pthread_mutex_lock(&rc->mtx);
474 	if (rc->sending) {
475 		pthread_mutex_unlock(&rc->mtx);
476 		return (1);
477 	}
478 	rc->sending = 1;
479 	pthread_mutex_unlock(&rc->mtx);
480 
481 	retval = 0;
482 
483 	if (all) {
484 		retval = rfb_send_all(rc, cfd, gc_image);
485 		goto done;
486 	}
487 
488 	/*
489 	 * Calculate the checksum for each 32x32 cell. Send each that
490 	 * has changed since the last scan.
491 	 */
492 
493 	/* Resolution changed */
494 
495 	rc->crc_width = gc_image->width;
496 	rc->crc_height = gc_image->height;
497 
498 	w = rc->crc_width;
499 	h = rc->crc_height;
500 	xcells = howmany(rc->crc_width, PIX_PER_CELL);
501 	ycells = howmany(rc->crc_height, PIX_PER_CELL);
502 
503 	rem_x = w & PIXCELL_MASK;
504 
505 	rem_y = h & PIXCELL_MASK;
506 	if (!rem_y)
507 		rem_y = PIX_PER_CELL;
508 
509 	p = gc_image->data;
510 
511 	/*
512 	 * Go through all cells and calculate crc. If significant number
513 	 * of changes, then send entire screen.
514 	 * crc_tmp is dual purpose: to store the new crc and to flag as
515 	 * a cell that has changed.
516 	 */
517 	crc_p = rc->crc_tmp - xcells;
518 	orig_crc = rc->crc - xcells;
519 	changes = 0;
520 	memset(rc->crc_tmp, 0, sizeof(uint32_t) * xcells * ycells);
521 	for (y = 0; y < h; y++) {
522 		if ((y & PIXCELL_MASK) == 0) {
523 			crc_p += xcells;
524 			orig_crc += xcells;
525 		}
526 
527 		for (x = 0; x < xcells; x++) {
528 			if (rc->hw_crc)
529 				crc_p[x] = fast_crc32(p,
530 				             PIX_PER_CELL * sizeof(uint32_t),
531 				             crc_p[x]);
532 			else
533 				crc_p[x] = (uint32_t)crc32(crc_p[x],
534 				             (Bytef *)p,
535 				             PIX_PER_CELL * sizeof(uint32_t));
536 
537 			p += PIX_PER_CELL;
538 
539 			/* check for crc delta if last row in cell */
540 			if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) {
541 				if (orig_crc[x] != crc_p[x]) {
542 					orig_crc[x] = crc_p[x];
543 					crc_p[x] = 1;
544 					changes++;
545 				} else {
546 					crc_p[x] = 0;
547 				}
548 			}
549 		}
550 
551 		if (rem_x) {
552 			if (rc->hw_crc)
553 				crc_p[x] = fast_crc32(p,
554 				                    rem_x * sizeof(uint32_t),
555 				                    crc_p[x]);
556 			else
557 				crc_p[x] = (uint32_t)crc32(crc_p[x],
558 				                    (Bytef *)p,
559 				                    rem_x * sizeof(uint32_t));
560 			p += rem_x;
561 
562 			if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) {
563 				if (orig_crc[x] != crc_p[x]) {
564 					orig_crc[x] = crc_p[x];
565 					crc_p[x] = 1;
566 					changes++;
567 				} else {
568 					crc_p[x] = 0;
569 				}
570 			}
571 		}
572 	}
573 
574 	/* If number of changes is > THRESH percent, send the whole screen */
575 	if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) {
576 		retval = rfb_send_all(rc, cfd, gc_image);
577 		goto done;
578 	}
579 
580 	/* Go through all cells, and send only changed ones */
581 	crc_p = rc->crc_tmp;
582 	for (y = 0; y < h; y += PIX_PER_CELL) {
583 		/* previous cell's row */
584 		celly = (y >> PIXCELL_SHIFT);
585 
586 		/* Delta check crc to previous set */
587 		for (x = 0; x < xcells; x++) {
588 			if (*crc_p++ == 0)
589 				continue;
590 
591 			if (x == (xcells - 1) && rem_x > 0)
592 				cellwidth = rem_x;
593 			else
594 				cellwidth = PIX_PER_CELL;
595 			nwrite = rfb_send_rect(rc, cfd,
596 				gc_image,
597 				x * PIX_PER_CELL,
598 				celly * PIX_PER_CELL,
599 			        cellwidth,
600 				y + PIX_PER_CELL >= h ? rem_y : PIX_PER_CELL);
601 			if (nwrite <= 0) {
602 				retval = nwrite;
603 				goto done;
604 			}
605 		}
606 	}
607 	retval = 1;
608 
609 done:
610 	pthread_mutex_lock(&rc->mtx);
611 	rc->sending = 0;
612 	pthread_mutex_unlock(&rc->mtx);
613 
614 	return (retval);
615 }
616 
617 
618 static void
619 rfb_recv_update_msg(struct rfb_softc *rc, int cfd, int discardonly)
620 {
621 	struct rfb_updt_msg updt_msg;
622 	struct bhyvegc_image *gc_image;
623 
624 	(void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1);
625 
626 	console_refresh();
627 	gc_image = console_get_image();
628 
629 	updt_msg.x = htons(updt_msg.x);
630 	updt_msg.y = htons(updt_msg.y);
631 	updt_msg.width = htons(updt_msg.width);
632 	updt_msg.height = htons(updt_msg.height);
633 
634 	if (updt_msg.width != gc_image->width ||
635 	    updt_msg.height != gc_image->height) {
636 		rc->width = gc_image->width;
637 		rc->height = gc_image->height;
638 		if (rc->enc_resize_ok)
639 			rfb_send_resize_update_msg(rc, cfd);
640 	}
641 
642 	if (discardonly)
643 		return;
644 
645 	rfb_send_screen(rc, cfd, 1);
646 }
647 
648 static void
649 rfb_recv_key_msg(struct rfb_softc *rc, int cfd)
650 {
651 	struct rfb_key_msg key_msg;
652 
653 	(void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1);
654 
655 	console_key_event(key_msg.down, htonl(key_msg.code));
656 }
657 
658 static void
659 rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd)
660 {
661 	struct rfb_ptr_msg ptr_msg;
662 
663 	(void)stream_read(cfd, ((void *)&ptr_msg) + 1, sizeof(ptr_msg) - 1);
664 
665 	console_ptr_event(ptr_msg.button, htons(ptr_msg.x), htons(ptr_msg.y));
666 }
667 
668 static void
669 rfb_recv_cuttext_msg(struct rfb_softc *rc, int cfd)
670 {
671 	struct rfb_cuttext_msg ct_msg;
672 	unsigned char buf[32];
673 	int len;
674 
675 	len = stream_read(cfd, ((void *)&ct_msg) + 1, sizeof(ct_msg) - 1);
676 	ct_msg.length = htonl(ct_msg.length);
677 	while (ct_msg.length > 0) {
678 		len = stream_read(cfd, buf, ct_msg.length > sizeof(buf) ?
679 			sizeof(buf) : ct_msg.length);
680 		ct_msg.length -= len;
681 	}
682 }
683 
684 static int64_t
685 timeval_delta(struct timeval *prev, struct timeval *now)
686 {
687 	int64_t n1, n2;
688 	n1 = now->tv_sec * 1000000 + now->tv_usec;
689 	n2 = prev->tv_sec * 1000000 + prev->tv_usec;
690 	return (n1 - n2);
691 }
692 
693 static void *
694 rfb_wr_thr(void *arg)
695 {
696 	struct rfb_softc *rc;
697 	fd_set rfds;
698 	struct timeval tv;
699 	struct timeval prev_tv;
700 	int64_t tdiff;
701 	int cfd;
702 	int err;
703 
704 	rc = arg;
705 	cfd = rc->cfd;
706 
707 	prev_tv.tv_sec = 0;
708 	prev_tv.tv_usec = 0;
709 	while (rc->cfd >= 0) {
710 		FD_ZERO(&rfds);
711 		FD_SET(cfd, &rfds);
712 		tv.tv_sec = 0;
713 		tv.tv_usec = 10000;
714 
715 		err = select(cfd+1, &rfds, NULL, NULL, &tv);
716                 if (err < 0)
717 			return (NULL);
718 
719 		/* Determine if its time to push screen; ~24hz */
720 		gettimeofday(&tv, NULL);
721 		tdiff = timeval_delta(&prev_tv, &tv);
722 		if (tdiff > 40000) {
723 			prev_tv.tv_sec = tv.tv_sec;
724 			prev_tv.tv_usec = tv.tv_usec;
725 			if (rfb_send_screen(rc, cfd, 0) <= 0) {
726 				return (NULL);
727 			}
728 		} else {
729 			/* sleep */
730 			usleep(40000 - tdiff);
731 		}
732 	}
733 
734 	return (NULL);
735 }
736 
737 void
738 rfb_handle(struct rfb_softc *rc, int cfd)
739 {
740 	const char *vbuf = "RFB 003.008\n";
741 	unsigned char buf[80];
742 	pthread_t tid;
743         uint32_t sres;
744 	int len;
745 
746 	rc->cfd = cfd;
747 
748 	/* 1a. Send server version */
749 	stream_write(cfd, vbuf, strlen(vbuf));
750 
751 	/* 1b. Read client version */
752 	len = read(cfd, buf, sizeof(buf));
753 
754 	/* 2a. Send security type 'none' */
755 	buf[0] = 1;
756 	buf[1] = 1; /* none */
757 	stream_write(cfd, buf, 2);
758 
759 
760 	/* 2b. Read agreed security type */
761 	len = stream_read(cfd, buf, 1);
762 
763 	/* 2c. Write back a status of 0 */
764 	sres = 0;
765 	stream_write(cfd, &sres, 4);
766 
767 	/* 3a. Read client shared-flag byte */
768 	len = stream_read(cfd, buf, 1);
769 
770 	/* 4a. Write server-init info */
771 	rfb_send_server_init_msg(cfd);
772 
773 	if (!rc->zbuf) {
774 		rc->zbuf = malloc(RFB_ZLIB_BUFSZ + 16);
775 		assert(rc->zbuf != NULL);
776 	}
777 
778 	rfb_send_screen(rc, cfd, 1);
779 
780 	pthread_create(&tid, NULL, rfb_wr_thr, rc);
781 	pthread_set_name_np(tid, "rfbout");
782 
783         /* Now read in client requests. 1st byte identifies type */
784 	for (;;) {
785 		len = read(cfd, buf, 1);
786 		if (len <= 0) {
787 			DPRINTF(("rfb client exiting\r\n"));
788 			break;
789 		}
790 
791 		switch (buf[0]) {
792 		case 0:
793 			rfb_recv_set_pixfmt_msg(rc, cfd);
794 			break;
795 		case 2:
796 			rfb_recv_set_encodings_msg(rc, cfd);
797 			break;
798 		case 3:
799 			rfb_recv_update_msg(rc, cfd, 1);
800 			break;
801 		case 4:
802 			rfb_recv_key_msg(rc, cfd);
803 			break;
804 		case 5:
805 			rfb_recv_ptr_msg(rc, cfd);
806 			break;
807 		case 6:
808 			rfb_recv_cuttext_msg(rc, cfd);
809 			break;
810 		default:
811 			WPRINTF(("rfb unknown cli-code %d!\n", buf[0] & 0xff));
812 			goto done;
813 		}
814 	}
815 done:
816 	rc->cfd = -1;
817 	pthread_join(tid, NULL);
818 	if (rc->enc_zlib_ok)
819 		deflateEnd(&rc->zstream);
820 }
821 
822 static void *
823 rfb_thr(void *arg)
824 {
825 	struct rfb_softc *rc;
826 	sigset_t set;
827 
828 	int cfd;
829 
830 	rc = arg;
831 
832 	sigemptyset(&set);
833 	sigaddset(&set, SIGPIPE);
834 	if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
835 		perror("pthread_sigmask");
836 		return (NULL);
837 	}
838 
839 	for (;;) {
840 		rc->enc_raw_ok = false;
841 		rc->enc_zlib_ok = false;
842 		rc->enc_resize_ok = false;
843 
844 		cfd = accept(rc->sfd, NULL, NULL);
845 		if (rc->conn_wait) {
846 			pthread_mutex_lock(&rc->mtx);
847 			pthread_cond_signal(&rc->cond);
848 			pthread_mutex_unlock(&rc->mtx);
849 			rc->conn_wait = 0;
850 		}
851 		rfb_handle(rc, cfd);
852 		close(cfd);
853 	}
854 
855 	/* NOTREACHED */
856 	return (NULL);
857 }
858 
859 static int
860 sse42_supported(void)
861 {
862 	u_int cpu_registers[4], ecx;
863 
864 	do_cpuid(1, cpu_registers);
865 
866 	ecx = cpu_registers[2];
867 
868 	return ((ecx & CPUID2_SSE42) != 0);
869 }
870 
871 int
872 rfb_init(char *hostname, int port, int wait)
873 {
874 	struct rfb_softc *rc;
875 	struct sockaddr_in sin;
876 	int on = 1;
877 #ifndef WITHOUT_CAPSICUM
878 	cap_rights_t rights;
879 #endif
880 
881 	rc = calloc(1, sizeof(struct rfb_softc));
882 
883 	rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
884 	                 sizeof(uint32_t));
885 	rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
886 	                     sizeof(uint32_t));
887 	rc->crc_width = RFB_MAX_WIDTH;
888 	rc->crc_height = RFB_MAX_HEIGHT;
889 
890 	rc->sfd = socket(AF_INET, SOCK_STREAM, 0);
891 	if (rc->sfd < 0) {
892 		perror("socket");
893 		return (-1);
894 	}
895 
896 	setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
897 
898 	sin.sin_len = sizeof(sin);
899 	sin.sin_family = AF_INET;
900 	sin.sin_port = htons(port);
901 	if (hostname && strlen(hostname) > 0)
902 		inet_pton(AF_INET, hostname, &(sin.sin_addr));
903 	else
904 		sin.sin_addr.s_addr = htonl(INADDR_ANY);
905 
906 	if (bind(rc->sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
907 		perror("bind");
908 		return (-1);
909 	}
910 
911 	if (listen(rc->sfd, 1) < 0) {
912 		perror("listen");
913 		return (-1);
914 	}
915 
916 #ifndef WITHOUT_CAPSICUM
917 	cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE);
918 	if (cap_rights_limit(rc->sfd, &rights) == -1 && errno != ENOSYS)
919 		errx(EX_OSERR, "Unable to apply rights for sandbox");
920 #endif
921 
922 	rc->hw_crc = sse42_supported();
923 
924 	rc->conn_wait = wait;
925 	if (wait) {
926 		pthread_mutex_init(&rc->mtx, NULL);
927 		pthread_cond_init(&rc->cond, NULL);
928 	}
929 
930 	pthread_create(&rc->tid, NULL, rfb_thr, rc);
931 	pthread_set_name_np(rc->tid, "rfb");
932 
933 	if (wait) {
934 		DPRINTF(("Waiting for rfb client...\n"));
935 		pthread_mutex_lock(&rc->mtx);
936 		pthread_cond_wait(&rc->cond, &rc->mtx);
937 		pthread_mutex_unlock(&rc->mtx);
938 	}
939 
940 	return (0);
941 }
942