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