]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/rfb.c
Merge branch 'releng/11.1' into releng-CDN/11.1
[FreeBSD/FreeBSD.git] / usr.sbin / bhyve / rfb.c
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 = port ? htons(port) : htons(5900);
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_LOOPBACK);
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 }