]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/rfb.c
Merge libc++ r291274, and update the library Makefile.
[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 #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 }