1bf21cd93STycho Nightingale /*- 24c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34c87aefeSPatrick Mooney * 4bf21cd93STycho Nightingale * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 54c87aefeSPatrick Mooney * Copyright (c) 2015 Leon Dang 64c87aefeSPatrick Mooney * Copyright 2018 Joyent, Inc. 7bf21cd93STycho Nightingale * All rights reserved. 8bf21cd93STycho Nightingale * 9bf21cd93STycho Nightingale * Redistribution and use in source and binary forms, with or without 10bf21cd93STycho Nightingale * modification, are permitted provided that the following conditions 11bf21cd93STycho Nightingale * are met: 12bf21cd93STycho Nightingale * 1. Redistributions of source code must retain the above copyright 13bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer. 14bf21cd93STycho Nightingale * 2. Redistributions in binary form must reproduce the above copyright 15bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer in the 16bf21cd93STycho Nightingale * documentation and/or other materials provided with the distribution. 17bf21cd93STycho Nightingale * 18bf21cd93STycho Nightingale * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 19bf21cd93STycho Nightingale * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20bf21cd93STycho Nightingale * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21bf21cd93STycho Nightingale * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22bf21cd93STycho Nightingale * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23bf21cd93STycho Nightingale * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24bf21cd93STycho Nightingale * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25bf21cd93STycho Nightingale * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26bf21cd93STycho Nightingale * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27bf21cd93STycho Nightingale * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28bf21cd93STycho Nightingale * SUCH DAMAGE. 29bf21cd93STycho Nightingale */ 30bf21cd93STycho Nightingale 31bf21cd93STycho Nightingale #include <sys/cdefs.h> 32bf21cd93STycho Nightingale __FBSDID("$FreeBSD$"); 33bf21cd93STycho Nightingale 344c87aefeSPatrick Mooney #include <sys/param.h> 354c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 364c87aefeSPatrick Mooney #include <sys/capsicum.h> 374c87aefeSPatrick Mooney #endif 384c87aefeSPatrick Mooney #include <sys/endian.h> 39bf21cd93STycho Nightingale #include <sys/socket.h> 404c87aefeSPatrick Mooney #include <sys/select.h> 414c87aefeSPatrick Mooney #include <sys/time.h> 424c87aefeSPatrick Mooney #include <arpa/inet.h> 434c87aefeSPatrick Mooney #include <machine/cpufunc.h> 444c87aefeSPatrick Mooney #include <machine/specialreg.h> 45bf21cd93STycho Nightingale #include <netinet/in.h> 464c87aefeSPatrick Mooney #include <netdb.h> 47bf21cd93STycho Nightingale 48bf21cd93STycho Nightingale #include <assert.h> 494c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 504c87aefeSPatrick Mooney #include <capsicum_helpers.h> 514c87aefeSPatrick Mooney #endif 524c87aefeSPatrick Mooney #include <err.h> 534c87aefeSPatrick Mooney #include <errno.h> 54bf21cd93STycho Nightingale #include <pthread.h> 554c87aefeSPatrick Mooney #include <pthread_np.h> 56bf21cd93STycho Nightingale #include <signal.h> 57bf21cd93STycho Nightingale #include <stdbool.h> 58bf21cd93STycho Nightingale #include <stdlib.h> 59bf21cd93STycho Nightingale #include <stdio.h> 60bf21cd93STycho Nightingale #include <string.h> 614c87aefeSPatrick Mooney #include <sysexits.h> 62bf21cd93STycho Nightingale #include <unistd.h> 63bf21cd93STycho Nightingale 644c87aefeSPatrick Mooney #include <zlib.h> 654c87aefeSPatrick Mooney 664c87aefeSPatrick Mooney #ifndef __FreeBSD__ 674c87aefeSPatrick Mooney #include <sys/debug.h> 684c87aefeSPatrick Mooney #endif 694c87aefeSPatrick Mooney 70bf21cd93STycho Nightingale #include "bhyvegc.h" 71bf21cd93STycho Nightingale #include "console.h" 72bf21cd93STycho Nightingale #include "rfb.h" 734c87aefeSPatrick Mooney #include "sockstream.h" 744c87aefeSPatrick Mooney 754c87aefeSPatrick Mooney #ifndef NO_OPENSSL 764c87aefeSPatrick Mooney #include <openssl/des.h> 774c87aefeSPatrick Mooney #endif 784c87aefeSPatrick Mooney 794c87aefeSPatrick Mooney static int rfb_debug = 0; 804c87aefeSPatrick Mooney #define DPRINTF(params) if (rfb_debug) printf params 814c87aefeSPatrick Mooney #define WPRINTF(params) printf params 824c87aefeSPatrick Mooney 834c87aefeSPatrick Mooney #define AUTH_LENGTH 16 844c87aefeSPatrick Mooney #define PASSWD_LENGTH 8 854c87aefeSPatrick Mooney 864c87aefeSPatrick Mooney #define SECURITY_TYPE_NONE 1 874c87aefeSPatrick Mooney #define SECURITY_TYPE_VNC_AUTH 2 884c87aefeSPatrick Mooney 894c87aefeSPatrick Mooney #define AUTH_FAILED_UNAUTH 1 904c87aefeSPatrick Mooney #define AUTH_FAILED_ERROR 2 91bf21cd93STycho Nightingale 92bf21cd93STycho Nightingale struct rfb_softc { 93bf21cd93STycho Nightingale int sfd; 94bf21cd93STycho Nightingale pthread_t tid; 95bf21cd93STycho Nightingale 964c87aefeSPatrick Mooney int cfd; 974c87aefeSPatrick Mooney 98bf21cd93STycho Nightingale int width, height; 99bf21cd93STycho Nightingale 1004c87aefeSPatrick Mooney char *password; 1014c87aefeSPatrick Mooney 1024c87aefeSPatrick Mooney bool enc_raw_ok; 1034c87aefeSPatrick Mooney bool enc_zlib_ok; 1044c87aefeSPatrick Mooney bool enc_resize_ok; 1054c87aefeSPatrick Mooney 1064c87aefeSPatrick Mooney z_stream zstream; 1074c87aefeSPatrick Mooney uint8_t *zbuf; 1084c87aefeSPatrick Mooney int zbuflen; 1094c87aefeSPatrick Mooney 1104c87aefeSPatrick Mooney int conn_wait; 1114c87aefeSPatrick Mooney int sending; 1124c87aefeSPatrick Mooney pthread_mutex_t mtx; 1134c87aefeSPatrick Mooney pthread_cond_t cond; 1144c87aefeSPatrick Mooney 1154c87aefeSPatrick Mooney int hw_crc; 1164c87aefeSPatrick Mooney uint32_t *crc; /* WxH crc cells */ 1174c87aefeSPatrick Mooney uint32_t *crc_tmp; /* buffer to store single crc row */ 1184c87aefeSPatrick Mooney int crc_width, crc_height; 119bf21cd93STycho Nightingale }; 120bf21cd93STycho Nightingale 121bf21cd93STycho Nightingale struct rfb_pixfmt { 122bf21cd93STycho Nightingale uint8_t bpp; 123bf21cd93STycho Nightingale uint8_t depth; 124bf21cd93STycho Nightingale uint8_t bigendian; 125bf21cd93STycho Nightingale uint8_t truecolor; 126bf21cd93STycho Nightingale uint16_t red_max; 127bf21cd93STycho Nightingale uint16_t green_max; 128bf21cd93STycho Nightingale uint16_t blue_max; 129bf21cd93STycho Nightingale uint8_t red_shift; 130bf21cd93STycho Nightingale uint8_t green_shift; 131bf21cd93STycho Nightingale uint8_t blue_shift; 132bf21cd93STycho Nightingale uint8_t pad[3]; 133bf21cd93STycho Nightingale }; 134bf21cd93STycho Nightingale 135bf21cd93STycho Nightingale struct rfb_srvr_info { 136bf21cd93STycho Nightingale uint16_t width; 137bf21cd93STycho Nightingale uint16_t height; 138bf21cd93STycho Nightingale struct rfb_pixfmt pixfmt; 139bf21cd93STycho Nightingale uint32_t namelen; 140bf21cd93STycho Nightingale }; 141bf21cd93STycho Nightingale 142bf21cd93STycho Nightingale struct rfb_pixfmt_msg { 143bf21cd93STycho Nightingale uint8_t type; 144bf21cd93STycho Nightingale uint8_t pad[3]; 145bf21cd93STycho Nightingale struct rfb_pixfmt pixfmt; 146bf21cd93STycho Nightingale }; 147bf21cd93STycho Nightingale 148bf21cd93STycho Nightingale #define RFB_ENCODING_RAW 0 1494c87aefeSPatrick Mooney #define RFB_ENCODING_ZLIB 6 150bf21cd93STycho Nightingale #define RFB_ENCODING_RESIZE -223 151bf21cd93STycho Nightingale 1524c87aefeSPatrick Mooney #define RFB_MAX_WIDTH 2000 1534c87aefeSPatrick Mooney #define RFB_MAX_HEIGHT 1200 1544c87aefeSPatrick Mooney #define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4 1554c87aefeSPatrick Mooney 1564c87aefeSPatrick Mooney /* percentage changes to screen before sending the entire screen */ 1574c87aefeSPatrick Mooney #define RFB_SEND_ALL_THRESH 25 1584c87aefeSPatrick Mooney 159bf21cd93STycho Nightingale struct rfb_enc_msg { 160bf21cd93STycho Nightingale uint8_t type; 161bf21cd93STycho Nightingale uint8_t pad; 162bf21cd93STycho Nightingale uint16_t numencs; 163bf21cd93STycho Nightingale }; 164bf21cd93STycho Nightingale 165bf21cd93STycho Nightingale struct rfb_updt_msg { 166bf21cd93STycho Nightingale uint8_t type; 167bf21cd93STycho Nightingale uint8_t incremental; 168bf21cd93STycho Nightingale uint16_t x; 169bf21cd93STycho Nightingale uint16_t y; 170bf21cd93STycho Nightingale uint16_t width; 171bf21cd93STycho Nightingale uint16_t height; 172bf21cd93STycho Nightingale }; 173bf21cd93STycho Nightingale 174bf21cd93STycho Nightingale struct rfb_key_msg { 175bf21cd93STycho Nightingale uint8_t type; 176bf21cd93STycho Nightingale uint8_t down; 177bf21cd93STycho Nightingale uint16_t pad; 178bf21cd93STycho Nightingale uint32_t code; 179bf21cd93STycho Nightingale }; 180bf21cd93STycho Nightingale 181bf21cd93STycho Nightingale struct rfb_ptr_msg { 182bf21cd93STycho Nightingale uint8_t type; 183bf21cd93STycho Nightingale uint8_t button; 184bf21cd93STycho Nightingale uint16_t x; 185bf21cd93STycho Nightingale uint16_t y; 186bf21cd93STycho Nightingale }; 187bf21cd93STycho Nightingale 188bf21cd93STycho Nightingale struct rfb_srvr_updt_msg { 189bf21cd93STycho Nightingale uint8_t type; 190bf21cd93STycho Nightingale uint8_t pad; 191bf21cd93STycho Nightingale uint16_t numrects; 192bf21cd93STycho Nightingale }; 193bf21cd93STycho Nightingale 194bf21cd93STycho Nightingale struct rfb_srvr_rect_hdr { 195bf21cd93STycho Nightingale uint16_t x; 196bf21cd93STycho Nightingale uint16_t y; 197bf21cd93STycho Nightingale uint16_t width; 198bf21cd93STycho Nightingale uint16_t height; 199bf21cd93STycho Nightingale uint32_t encoding; 200bf21cd93STycho Nightingale }; 201bf21cd93STycho Nightingale 2024c87aefeSPatrick Mooney struct rfb_cuttext_msg { 2034c87aefeSPatrick Mooney uint8_t type; 2044c87aefeSPatrick Mooney uint8_t padding[3]; 2054c87aefeSPatrick Mooney uint32_t length; 2064c87aefeSPatrick Mooney }; 2074c87aefeSPatrick Mooney 2084c87aefeSPatrick Mooney 209bf21cd93STycho Nightingale static void 210bf21cd93STycho Nightingale rfb_send_server_init_msg(int cfd) 211bf21cd93STycho Nightingale { 212bf21cd93STycho Nightingale struct bhyvegc_image *gc_image; 213bf21cd93STycho Nightingale struct rfb_srvr_info sinfo; 214bf21cd93STycho Nightingale 215bf21cd93STycho Nightingale gc_image = console_get_image(); 216bf21cd93STycho Nightingale 2174c87aefeSPatrick Mooney sinfo.width = htons(gc_image->width); 2184c87aefeSPatrick Mooney sinfo.height = htons(gc_image->height); 219bf21cd93STycho Nightingale sinfo.pixfmt.bpp = 32; 220bf21cd93STycho Nightingale sinfo.pixfmt.depth = 32; 221bf21cd93STycho Nightingale sinfo.pixfmt.bigendian = 0; 222bf21cd93STycho Nightingale sinfo.pixfmt.truecolor = 1; 2234c87aefeSPatrick Mooney sinfo.pixfmt.red_max = htons(255); 2244c87aefeSPatrick Mooney sinfo.pixfmt.green_max = htons(255); 2254c87aefeSPatrick Mooney sinfo.pixfmt.blue_max = htons(255); 226bf21cd93STycho Nightingale sinfo.pixfmt.red_shift = 16; 227bf21cd93STycho Nightingale sinfo.pixfmt.green_shift = 8; 228bf21cd93STycho Nightingale sinfo.pixfmt.blue_shift = 0; 2294c87aefeSPatrick Mooney sinfo.namelen = htonl(strlen("bhyve")); 2304c87aefeSPatrick Mooney (void)stream_write(cfd, &sinfo, sizeof(sinfo)); 2314c87aefeSPatrick Mooney (void)stream_write(cfd, "bhyve", strlen("bhyve")); 232bf21cd93STycho Nightingale } 233bf21cd93STycho Nightingale 234bf21cd93STycho Nightingale static void 235bf21cd93STycho Nightingale rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd) 236bf21cd93STycho Nightingale { 237bf21cd93STycho Nightingale struct rfb_srvr_updt_msg supdt_msg; 2384c87aefeSPatrick Mooney struct rfb_srvr_rect_hdr srect_hdr; 239bf21cd93STycho Nightingale 240bf21cd93STycho Nightingale /* Number of rectangles: 1 */ 241bf21cd93STycho Nightingale supdt_msg.type = 0; 242bf21cd93STycho Nightingale supdt_msg.pad = 0; 2434c87aefeSPatrick Mooney supdt_msg.numrects = htons(1); 2444c87aefeSPatrick Mooney stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg)); 245bf21cd93STycho Nightingale 246bf21cd93STycho Nightingale /* Rectangle header */ 2474c87aefeSPatrick Mooney srect_hdr.x = htons(0); 2484c87aefeSPatrick Mooney srect_hdr.y = htons(0); 2494c87aefeSPatrick Mooney srect_hdr.width = htons(rc->width); 2504c87aefeSPatrick Mooney srect_hdr.height = htons(rc->height); 2514c87aefeSPatrick Mooney srect_hdr.encoding = htonl(RFB_ENCODING_RESIZE); 2524c87aefeSPatrick Mooney stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr)); 253bf21cd93STycho Nightingale } 254bf21cd93STycho Nightingale 255bf21cd93STycho Nightingale static void 256bf21cd93STycho Nightingale rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd) 257bf21cd93STycho Nightingale { 258bf21cd93STycho Nightingale struct rfb_pixfmt_msg pixfmt_msg; 259bf21cd93STycho Nightingale 2604c87aefeSPatrick Mooney (void)stream_read(cfd, ((void *)&pixfmt_msg)+1, sizeof(pixfmt_msg)-1); 261bf21cd93STycho Nightingale } 262bf21cd93STycho Nightingale 263bf21cd93STycho Nightingale 264bf21cd93STycho Nightingale static void 265bf21cd93STycho Nightingale rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd) 266bf21cd93STycho Nightingale { 267bf21cd93STycho Nightingale struct rfb_enc_msg enc_msg; 2684c87aefeSPatrick Mooney int i; 269bf21cd93STycho Nightingale uint32_t encoding; 270bf21cd93STycho Nightingale 271bf21cd93STycho Nightingale assert((sizeof(enc_msg) - 1) == 3); 2724c87aefeSPatrick Mooney (void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1); 273bf21cd93STycho Nightingale 2744c87aefeSPatrick Mooney for (i = 0; i < htons(enc_msg.numencs); i++) { 2754c87aefeSPatrick Mooney (void)stream_read(cfd, &encoding, sizeof(encoding)); 2764c87aefeSPatrick Mooney switch (htonl(encoding)) { 277bf21cd93STycho Nightingale case RFB_ENCODING_RAW: 278bf21cd93STycho Nightingale rc->enc_raw_ok = true; 279bf21cd93STycho Nightingale break; 2804c87aefeSPatrick Mooney case RFB_ENCODING_ZLIB: 281*84659b24SMichael Zeller if (!rc->enc_zlib_ok) { 282*84659b24SMichael Zeller deflateInit(&rc->zstream, Z_BEST_SPEED); 283*84659b24SMichael Zeller rc->enc_zlib_ok = true; 284*84659b24SMichael Zeller } 2854c87aefeSPatrick Mooney break; 286bf21cd93STycho Nightingale case RFB_ENCODING_RESIZE: 287bf21cd93STycho Nightingale rc->enc_resize_ok = true; 288bf21cd93STycho Nightingale break; 289bf21cd93STycho Nightingale } 290bf21cd93STycho Nightingale } 291bf21cd93STycho Nightingale } 292bf21cd93STycho Nightingale 2934c87aefeSPatrick Mooney /* 2944c87aefeSPatrick Mooney * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only 2954c87aefeSPatrick Mooney */ 2964c87aefeSPatrick Mooney static __inline uint32_t 2974c87aefeSPatrick Mooney fast_crc32(void *buf, int len, uint32_t crcval) 2984c87aefeSPatrick Mooney { 2994c87aefeSPatrick Mooney uint32_t q = len / sizeof(uint32_t); 3004c87aefeSPatrick Mooney uint32_t *p = (uint32_t *)buf; 3014c87aefeSPatrick Mooney 3024c87aefeSPatrick Mooney while (q--) { 3034c87aefeSPatrick Mooney asm volatile ( 3044c87aefeSPatrick Mooney ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" 3054c87aefeSPatrick Mooney :"=S" (crcval) 3064c87aefeSPatrick Mooney :"0" (crcval), "c" (*p) 3074c87aefeSPatrick Mooney ); 3084c87aefeSPatrick Mooney p++; 3094c87aefeSPatrick Mooney } 3104c87aefeSPatrick Mooney 3114c87aefeSPatrick Mooney return (crcval); 3124c87aefeSPatrick Mooney } 3134c87aefeSPatrick Mooney 3144c87aefeSPatrick Mooney 3154c87aefeSPatrick Mooney static int 3164c87aefeSPatrick Mooney rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc, 3174c87aefeSPatrick Mooney int x, int y, int w, int h) 3184c87aefeSPatrick Mooney { 3194c87aefeSPatrick Mooney struct rfb_srvr_updt_msg supdt_msg; 3204c87aefeSPatrick Mooney struct rfb_srvr_rect_hdr srect_hdr; 3214c87aefeSPatrick Mooney unsigned long zlen; 3224c87aefeSPatrick Mooney ssize_t nwrite, total; 3234c87aefeSPatrick Mooney int err; 3244c87aefeSPatrick Mooney uint32_t *p; 3254c87aefeSPatrick Mooney uint8_t *zbufp; 3264c87aefeSPatrick Mooney 3274c87aefeSPatrick Mooney /* 3284c87aefeSPatrick Mooney * Send a single rectangle of the given x, y, w h dimensions. 3294c87aefeSPatrick Mooney */ 3304c87aefeSPatrick Mooney 3314c87aefeSPatrick Mooney /* Number of rectangles: 1 */ 3324c87aefeSPatrick Mooney supdt_msg.type = 0; 3334c87aefeSPatrick Mooney supdt_msg.pad = 0; 3344c87aefeSPatrick Mooney supdt_msg.numrects = htons(1); 3354c87aefeSPatrick Mooney nwrite = stream_write(cfd, &supdt_msg, 3364c87aefeSPatrick Mooney sizeof(struct rfb_srvr_updt_msg)); 3374c87aefeSPatrick Mooney if (nwrite <= 0) 3384c87aefeSPatrick Mooney return (nwrite); 3394c87aefeSPatrick Mooney 3404c87aefeSPatrick Mooney 3414c87aefeSPatrick Mooney /* Rectangle header */ 3424c87aefeSPatrick Mooney srect_hdr.x = htons(x); 3434c87aefeSPatrick Mooney srect_hdr.y = htons(y); 3444c87aefeSPatrick Mooney srect_hdr.width = htons(w); 3454c87aefeSPatrick Mooney srect_hdr.height = htons(h); 3464c87aefeSPatrick Mooney 3474c87aefeSPatrick Mooney h = y + h; 3484c87aefeSPatrick Mooney w *= sizeof(uint32_t); 3494c87aefeSPatrick Mooney if (rc->enc_zlib_ok) { 3504c87aefeSPatrick Mooney zbufp = rc->zbuf; 3514c87aefeSPatrick Mooney rc->zstream.total_in = 0; 3524c87aefeSPatrick Mooney rc->zstream.total_out = 0; 3534c87aefeSPatrick Mooney for (p = &gc->data[y * gc->width + x]; y < h; y++) { 3544c87aefeSPatrick Mooney rc->zstream.next_in = (Bytef *)p; 3554c87aefeSPatrick Mooney rc->zstream.avail_in = w; 3564c87aefeSPatrick Mooney rc->zstream.next_out = (Bytef *)zbufp; 3574c87aefeSPatrick Mooney rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16 - 3584c87aefeSPatrick Mooney rc->zstream.total_out; 3594c87aefeSPatrick Mooney rc->zstream.data_type = Z_BINARY; 3604c87aefeSPatrick Mooney 3614c87aefeSPatrick Mooney /* Compress with zlib */ 3624c87aefeSPatrick Mooney err = deflate(&rc->zstream, Z_SYNC_FLUSH); 3634c87aefeSPatrick Mooney if (err != Z_OK) { 3644c87aefeSPatrick Mooney WPRINTF(("zlib[rect] deflate err: %d\n", err)); 3654c87aefeSPatrick Mooney rc->enc_zlib_ok = false; 3664c87aefeSPatrick Mooney deflateEnd(&rc->zstream); 3674c87aefeSPatrick Mooney goto doraw; 3684c87aefeSPatrick Mooney } 3694c87aefeSPatrick Mooney zbufp = rc->zbuf + rc->zstream.total_out; 3704c87aefeSPatrick Mooney p += gc->width; 3714c87aefeSPatrick Mooney } 3724c87aefeSPatrick Mooney srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB); 3734c87aefeSPatrick Mooney nwrite = stream_write(cfd, &srect_hdr, 3744c87aefeSPatrick Mooney sizeof(struct rfb_srvr_rect_hdr)); 3754c87aefeSPatrick Mooney if (nwrite <= 0) 3764c87aefeSPatrick Mooney return (nwrite); 3774c87aefeSPatrick Mooney 3784c87aefeSPatrick Mooney zlen = htonl(rc->zstream.total_out); 3794c87aefeSPatrick Mooney nwrite = stream_write(cfd, &zlen, sizeof(uint32_t)); 3804c87aefeSPatrick Mooney if (nwrite <= 0) 3814c87aefeSPatrick Mooney return (nwrite); 3824c87aefeSPatrick Mooney return (stream_write(cfd, rc->zbuf, rc->zstream.total_out)); 3834c87aefeSPatrick Mooney } 3844c87aefeSPatrick Mooney 3854c87aefeSPatrick Mooney doraw: 3864c87aefeSPatrick Mooney 3874c87aefeSPatrick Mooney total = 0; 3884c87aefeSPatrick Mooney zbufp = rc->zbuf; 3894c87aefeSPatrick Mooney for (p = &gc->data[y * gc->width + x]; y < h; y++) { 3904c87aefeSPatrick Mooney memcpy(zbufp, p, w); 3914c87aefeSPatrick Mooney zbufp += w; 3924c87aefeSPatrick Mooney total += w; 3934c87aefeSPatrick Mooney p += gc->width; 3944c87aefeSPatrick Mooney } 3954c87aefeSPatrick Mooney 3964c87aefeSPatrick Mooney srect_hdr.encoding = htonl(RFB_ENCODING_RAW); 3974c87aefeSPatrick Mooney nwrite = stream_write(cfd, &srect_hdr, 3984c87aefeSPatrick Mooney sizeof(struct rfb_srvr_rect_hdr)); 3994c87aefeSPatrick Mooney if (nwrite <= 0) 4004c87aefeSPatrick Mooney return (nwrite); 4014c87aefeSPatrick Mooney 4024c87aefeSPatrick Mooney total = stream_write(cfd, rc->zbuf, total); 4034c87aefeSPatrick Mooney 4044c87aefeSPatrick Mooney return (total); 4054c87aefeSPatrick Mooney } 4064c87aefeSPatrick Mooney 4074c87aefeSPatrick Mooney static int 4084c87aefeSPatrick Mooney rfb_send_all(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc) 409bf21cd93STycho Nightingale { 410bf21cd93STycho Nightingale struct rfb_srvr_updt_msg supdt_msg; 411bf21cd93STycho Nightingale struct rfb_srvr_rect_hdr srect_hdr; 4124c87aefeSPatrick Mooney ssize_t nwrite; 4134c87aefeSPatrick Mooney unsigned long zlen; 4144c87aefeSPatrick Mooney int err; 4154c87aefeSPatrick Mooney 4164c87aefeSPatrick Mooney /* 4174c87aefeSPatrick Mooney * Send the whole thing 4184c87aefeSPatrick Mooney */ 419bf21cd93STycho Nightingale 420bf21cd93STycho Nightingale /* Number of rectangles: 1 */ 421bf21cd93STycho Nightingale supdt_msg.type = 0; 422bf21cd93STycho Nightingale supdt_msg.pad = 0; 4234c87aefeSPatrick Mooney supdt_msg.numrects = htons(1); 4244c87aefeSPatrick Mooney nwrite = stream_write(cfd, &supdt_msg, 4254c87aefeSPatrick Mooney sizeof(struct rfb_srvr_updt_msg)); 4264c87aefeSPatrick Mooney if (nwrite <= 0) 4274c87aefeSPatrick Mooney return (nwrite); 428bf21cd93STycho Nightingale 429bf21cd93STycho Nightingale /* Rectangle header */ 4304c87aefeSPatrick Mooney srect_hdr.x = 0; 4314c87aefeSPatrick Mooney srect_hdr.y = 0; 4324c87aefeSPatrick Mooney srect_hdr.width = htons(gc->width); 4334c87aefeSPatrick Mooney srect_hdr.height = htons(gc->height); 4344c87aefeSPatrick Mooney if (rc->enc_zlib_ok) { 4354c87aefeSPatrick Mooney rc->zstream.next_in = (Bytef *)gc->data; 4364c87aefeSPatrick Mooney rc->zstream.avail_in = gc->width * gc->height * 4374c87aefeSPatrick Mooney sizeof(uint32_t); 4384c87aefeSPatrick Mooney rc->zstream.next_out = (Bytef *)rc->zbuf; 4394c87aefeSPatrick Mooney rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16; 4404c87aefeSPatrick Mooney rc->zstream.data_type = Z_BINARY; 4414c87aefeSPatrick Mooney 4424c87aefeSPatrick Mooney rc->zstream.total_in = 0; 4434c87aefeSPatrick Mooney rc->zstream.total_out = 0; 4444c87aefeSPatrick Mooney 4454c87aefeSPatrick Mooney /* Compress with zlib */ 4464c87aefeSPatrick Mooney err = deflate(&rc->zstream, Z_SYNC_FLUSH); 4474c87aefeSPatrick Mooney if (err != Z_OK) { 4484c87aefeSPatrick Mooney WPRINTF(("zlib deflate err: %d\n", err)); 4494c87aefeSPatrick Mooney rc->enc_zlib_ok = false; 4504c87aefeSPatrick Mooney deflateEnd(&rc->zstream); 4514c87aefeSPatrick Mooney goto doraw; 4524c87aefeSPatrick Mooney } 4534c87aefeSPatrick Mooney 4544c87aefeSPatrick Mooney srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB); 4554c87aefeSPatrick Mooney nwrite = stream_write(cfd, &srect_hdr, 4564c87aefeSPatrick Mooney sizeof(struct rfb_srvr_rect_hdr)); 4574c87aefeSPatrick Mooney if (nwrite <= 0) 4584c87aefeSPatrick Mooney return (nwrite); 4594c87aefeSPatrick Mooney 4604c87aefeSPatrick Mooney zlen = htonl(rc->zstream.total_out); 4614c87aefeSPatrick Mooney nwrite = stream_write(cfd, &zlen, sizeof(uint32_t)); 4624c87aefeSPatrick Mooney if (nwrite <= 0) 4634c87aefeSPatrick Mooney return (nwrite); 4644c87aefeSPatrick Mooney return (stream_write(cfd, rc->zbuf, rc->zstream.total_out)); 4654c87aefeSPatrick Mooney } 4664c87aefeSPatrick Mooney 4674c87aefeSPatrick Mooney doraw: 4684c87aefeSPatrick Mooney srect_hdr.encoding = htonl(RFB_ENCODING_RAW); 4694c87aefeSPatrick Mooney nwrite = stream_write(cfd, &srect_hdr, 4704c87aefeSPatrick Mooney sizeof(struct rfb_srvr_rect_hdr)); 4714c87aefeSPatrick Mooney if (nwrite <= 0) 4724c87aefeSPatrick Mooney return (nwrite); 4734c87aefeSPatrick Mooney 4744c87aefeSPatrick Mooney nwrite = stream_write(cfd, gc->data, 4754c87aefeSPatrick Mooney gc->width * gc->height * sizeof(uint32_t)); 4764c87aefeSPatrick Mooney 4774c87aefeSPatrick Mooney return (nwrite); 478bf21cd93STycho Nightingale } 479bf21cd93STycho Nightingale 4804c87aefeSPatrick Mooney #define PIX_PER_CELL 32 4814c87aefeSPatrick Mooney #define PIXCELL_SHIFT 5 4824c87aefeSPatrick Mooney #define PIXCELL_MASK 0x1F 4834c87aefeSPatrick Mooney 4844c87aefeSPatrick Mooney static int 4854c87aefeSPatrick Mooney rfb_send_screen(struct rfb_softc *rc, int cfd, int all) 4864c87aefeSPatrick Mooney { 4874c87aefeSPatrick Mooney struct bhyvegc_image *gc_image; 4884c87aefeSPatrick Mooney ssize_t nwrite; 4894c87aefeSPatrick Mooney int x, y; 4904c87aefeSPatrick Mooney int celly, cellwidth; 4914c87aefeSPatrick Mooney int xcells, ycells; 4924c87aefeSPatrick Mooney int w, h; 4934c87aefeSPatrick Mooney uint32_t *p; 4944c87aefeSPatrick Mooney int rem_x, rem_y; /* remainder for resolutions not x32 pixels ratio */ 4954c87aefeSPatrick Mooney int retval; 4964c87aefeSPatrick Mooney uint32_t *crc_p, *orig_crc; 4974c87aefeSPatrick Mooney int changes; 4984c87aefeSPatrick Mooney 4994c87aefeSPatrick Mooney console_refresh(); 5004c87aefeSPatrick Mooney gc_image = console_get_image(); 5014c87aefeSPatrick Mooney 5024c87aefeSPatrick Mooney pthread_mutex_lock(&rc->mtx); 5034c87aefeSPatrick Mooney if (rc->sending) { 5044c87aefeSPatrick Mooney pthread_mutex_unlock(&rc->mtx); 5054c87aefeSPatrick Mooney return (1); 5064c87aefeSPatrick Mooney } 5074c87aefeSPatrick Mooney rc->sending = 1; 5084c87aefeSPatrick Mooney pthread_mutex_unlock(&rc->mtx); 5094c87aefeSPatrick Mooney 5104c87aefeSPatrick Mooney retval = 0; 5114c87aefeSPatrick Mooney 5124c87aefeSPatrick Mooney if (all) { 5134c87aefeSPatrick Mooney retval = rfb_send_all(rc, cfd, gc_image); 5144c87aefeSPatrick Mooney goto done; 5154c87aefeSPatrick Mooney } 5164c87aefeSPatrick Mooney 5174c87aefeSPatrick Mooney /* 5184c87aefeSPatrick Mooney * Calculate the checksum for each 32x32 cell. Send each that 5194c87aefeSPatrick Mooney * has changed since the last scan. 5204c87aefeSPatrick Mooney */ 5214c87aefeSPatrick Mooney 5224c87aefeSPatrick Mooney /* Resolution changed */ 5234c87aefeSPatrick Mooney 5244c87aefeSPatrick Mooney rc->crc_width = gc_image->width; 5254c87aefeSPatrick Mooney rc->crc_height = gc_image->height; 5264c87aefeSPatrick Mooney 5274c87aefeSPatrick Mooney w = rc->crc_width; 5284c87aefeSPatrick Mooney h = rc->crc_height; 5294c87aefeSPatrick Mooney xcells = howmany(rc->crc_width, PIX_PER_CELL); 5304c87aefeSPatrick Mooney ycells = howmany(rc->crc_height, PIX_PER_CELL); 5314c87aefeSPatrick Mooney 5324c87aefeSPatrick Mooney rem_x = w & PIXCELL_MASK; 5334c87aefeSPatrick Mooney 5344c87aefeSPatrick Mooney rem_y = h & PIXCELL_MASK; 5354c87aefeSPatrick Mooney if (!rem_y) 5364c87aefeSPatrick Mooney rem_y = PIX_PER_CELL; 5374c87aefeSPatrick Mooney 5384c87aefeSPatrick Mooney p = gc_image->data; 5394c87aefeSPatrick Mooney 5404c87aefeSPatrick Mooney /* 5414c87aefeSPatrick Mooney * Go through all cells and calculate crc. If significant number 5424c87aefeSPatrick Mooney * of changes, then send entire screen. 5434c87aefeSPatrick Mooney * crc_tmp is dual purpose: to store the new crc and to flag as 5444c87aefeSPatrick Mooney * a cell that has changed. 5454c87aefeSPatrick Mooney */ 5464c87aefeSPatrick Mooney crc_p = rc->crc_tmp - xcells; 5474c87aefeSPatrick Mooney orig_crc = rc->crc - xcells; 5484c87aefeSPatrick Mooney changes = 0; 5494c87aefeSPatrick Mooney memset(rc->crc_tmp, 0, sizeof(uint32_t) * xcells * ycells); 5504c87aefeSPatrick Mooney for (y = 0; y < h; y++) { 5514c87aefeSPatrick Mooney if ((y & PIXCELL_MASK) == 0) { 5524c87aefeSPatrick Mooney crc_p += xcells; 5534c87aefeSPatrick Mooney orig_crc += xcells; 5544c87aefeSPatrick Mooney } 5554c87aefeSPatrick Mooney 5564c87aefeSPatrick Mooney for (x = 0; x < xcells; x++) { 5574c87aefeSPatrick Mooney if (x == (xcells - 1) && rem_x > 0) 5584c87aefeSPatrick Mooney cellwidth = rem_x; 5594c87aefeSPatrick Mooney else 5604c87aefeSPatrick Mooney cellwidth = PIX_PER_CELL; 5614c87aefeSPatrick Mooney 5624c87aefeSPatrick Mooney if (rc->hw_crc) 5634c87aefeSPatrick Mooney crc_p[x] = fast_crc32(p, 5644c87aefeSPatrick Mooney cellwidth * sizeof(uint32_t), 5654c87aefeSPatrick Mooney crc_p[x]); 5664c87aefeSPatrick Mooney else 5674c87aefeSPatrick Mooney crc_p[x] = (uint32_t)crc32(crc_p[x], 5684c87aefeSPatrick Mooney (Bytef *)p, 5694c87aefeSPatrick Mooney cellwidth * sizeof(uint32_t)); 5704c87aefeSPatrick Mooney 5714c87aefeSPatrick Mooney p += cellwidth; 5724c87aefeSPatrick Mooney 5734c87aefeSPatrick Mooney /* check for crc delta if last row in cell */ 5744c87aefeSPatrick Mooney if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) { 5754c87aefeSPatrick Mooney if (orig_crc[x] != crc_p[x]) { 5764c87aefeSPatrick Mooney orig_crc[x] = crc_p[x]; 5774c87aefeSPatrick Mooney crc_p[x] = 1; 5784c87aefeSPatrick Mooney changes++; 5794c87aefeSPatrick Mooney } else { 5804c87aefeSPatrick Mooney crc_p[x] = 0; 5814c87aefeSPatrick Mooney } 5824c87aefeSPatrick Mooney } 5834c87aefeSPatrick Mooney } 5844c87aefeSPatrick Mooney } 5854c87aefeSPatrick Mooney 5864c87aefeSPatrick Mooney /* If number of changes is > THRESH percent, send the whole screen */ 5874c87aefeSPatrick Mooney if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) { 5884c87aefeSPatrick Mooney retval = rfb_send_all(rc, cfd, gc_image); 5894c87aefeSPatrick Mooney goto done; 5904c87aefeSPatrick Mooney } 5914c87aefeSPatrick Mooney 5924c87aefeSPatrick Mooney /* Go through all cells, and send only changed ones */ 5934c87aefeSPatrick Mooney crc_p = rc->crc_tmp; 5944c87aefeSPatrick Mooney for (y = 0; y < h; y += PIX_PER_CELL) { 5954c87aefeSPatrick Mooney /* previous cell's row */ 5964c87aefeSPatrick Mooney celly = (y >> PIXCELL_SHIFT); 5974c87aefeSPatrick Mooney 5984c87aefeSPatrick Mooney /* Delta check crc to previous set */ 5994c87aefeSPatrick Mooney for (x = 0; x < xcells; x++) { 6004c87aefeSPatrick Mooney if (*crc_p++ == 0) 6014c87aefeSPatrick Mooney continue; 6024c87aefeSPatrick Mooney 6034c87aefeSPatrick Mooney if (x == (xcells - 1) && rem_x > 0) 6044c87aefeSPatrick Mooney cellwidth = rem_x; 6054c87aefeSPatrick Mooney else 6064c87aefeSPatrick Mooney cellwidth = PIX_PER_CELL; 6074c87aefeSPatrick Mooney nwrite = rfb_send_rect(rc, cfd, 6084c87aefeSPatrick Mooney gc_image, 6094c87aefeSPatrick Mooney x * PIX_PER_CELL, 6104c87aefeSPatrick Mooney celly * PIX_PER_CELL, 6114c87aefeSPatrick Mooney cellwidth, 6124c87aefeSPatrick Mooney y + PIX_PER_CELL >= h ? rem_y : PIX_PER_CELL); 6134c87aefeSPatrick Mooney if (nwrite <= 0) { 6144c87aefeSPatrick Mooney retval = nwrite; 6154c87aefeSPatrick Mooney goto done; 6164c87aefeSPatrick Mooney } 6174c87aefeSPatrick Mooney } 6184c87aefeSPatrick Mooney } 6194c87aefeSPatrick Mooney retval = 1; 6204c87aefeSPatrick Mooney 6214c87aefeSPatrick Mooney done: 6224c87aefeSPatrick Mooney pthread_mutex_lock(&rc->mtx); 6234c87aefeSPatrick Mooney rc->sending = 0; 6244c87aefeSPatrick Mooney pthread_mutex_unlock(&rc->mtx); 6254c87aefeSPatrick Mooney 6264c87aefeSPatrick Mooney return (retval); 6274c87aefeSPatrick Mooney } 6284c87aefeSPatrick Mooney 6294c87aefeSPatrick Mooney 630bf21cd93STycho Nightingale static void 6314c87aefeSPatrick Mooney rfb_recv_update_msg(struct rfb_softc *rc, int cfd, int discardonly) 632bf21cd93STycho Nightingale { 633bf21cd93STycho Nightingale struct rfb_updt_msg updt_msg; 634bf21cd93STycho Nightingale struct bhyvegc_image *gc_image; 635bf21cd93STycho Nightingale 6364c87aefeSPatrick Mooney (void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1); 637bf21cd93STycho Nightingale 638bf21cd93STycho Nightingale console_refresh(); 639bf21cd93STycho Nightingale gc_image = console_get_image(); 640bf21cd93STycho Nightingale 6414c87aefeSPatrick Mooney updt_msg.x = htons(updt_msg.x); 6424c87aefeSPatrick Mooney updt_msg.y = htons(updt_msg.y); 6434c87aefeSPatrick Mooney updt_msg.width = htons(updt_msg.width); 6444c87aefeSPatrick Mooney updt_msg.height = htons(updt_msg.height); 6454c87aefeSPatrick Mooney 6464c87aefeSPatrick Mooney if (updt_msg.width != gc_image->width || 6474c87aefeSPatrick Mooney updt_msg.height != gc_image->height) { 648bf21cd93STycho Nightingale rc->width = gc_image->width; 649bf21cd93STycho Nightingale rc->height = gc_image->height; 6504c87aefeSPatrick Mooney if (rc->enc_resize_ok) 6514c87aefeSPatrick Mooney rfb_send_resize_update_msg(rc, cfd); 652bf21cd93STycho Nightingale } 653bf21cd93STycho Nightingale 6544c87aefeSPatrick Mooney if (discardonly) 6554c87aefeSPatrick Mooney return; 656bf21cd93STycho Nightingale 6574c87aefeSPatrick Mooney rfb_send_screen(rc, cfd, 1); 658bf21cd93STycho Nightingale } 659bf21cd93STycho Nightingale 660bf21cd93STycho Nightingale static void 661bf21cd93STycho Nightingale rfb_recv_key_msg(struct rfb_softc *rc, int cfd) 662bf21cd93STycho Nightingale { 663bf21cd93STycho Nightingale struct rfb_key_msg key_msg; 664bf21cd93STycho Nightingale 6654c87aefeSPatrick Mooney (void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1); 666bf21cd93STycho Nightingale 6674c87aefeSPatrick Mooney console_key_event(key_msg.down, htonl(key_msg.code)); 668bf21cd93STycho Nightingale } 669bf21cd93STycho Nightingale 670bf21cd93STycho Nightingale static void 671bf21cd93STycho Nightingale rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd) 672bf21cd93STycho Nightingale { 673bf21cd93STycho Nightingale struct rfb_ptr_msg ptr_msg; 6744c87aefeSPatrick Mooney 6754c87aefeSPatrick Mooney (void)stream_read(cfd, ((void *)&ptr_msg) + 1, sizeof(ptr_msg) - 1); 6764c87aefeSPatrick Mooney 6774c87aefeSPatrick Mooney console_ptr_event(ptr_msg.button, htons(ptr_msg.x), htons(ptr_msg.y)); 6784c87aefeSPatrick Mooney } 6794c87aefeSPatrick Mooney 6804c87aefeSPatrick Mooney static void 6814c87aefeSPatrick Mooney rfb_recv_cuttext_msg(struct rfb_softc *rc, int cfd) 6824c87aefeSPatrick Mooney { 6834c87aefeSPatrick Mooney struct rfb_cuttext_msg ct_msg; 6844c87aefeSPatrick Mooney unsigned char buf[32]; 685bf21cd93STycho Nightingale int len; 686bf21cd93STycho Nightingale 6874c87aefeSPatrick Mooney len = stream_read(cfd, ((void *)&ct_msg) + 1, sizeof(ct_msg) - 1); 6884c87aefeSPatrick Mooney ct_msg.length = htonl(ct_msg.length); 6894c87aefeSPatrick Mooney while (ct_msg.length > 0) { 6904c87aefeSPatrick Mooney len = stream_read(cfd, buf, ct_msg.length > sizeof(buf) ? 6914c87aefeSPatrick Mooney sizeof(buf) : ct_msg.length); 6924c87aefeSPatrick Mooney ct_msg.length -= len; 6934c87aefeSPatrick Mooney } 6944c87aefeSPatrick Mooney } 695bf21cd93STycho Nightingale 6964c87aefeSPatrick Mooney static int64_t 6974c87aefeSPatrick Mooney timeval_delta(struct timeval *prev, struct timeval *now) 6984c87aefeSPatrick Mooney { 6994c87aefeSPatrick Mooney int64_t n1, n2; 7004c87aefeSPatrick Mooney n1 = now->tv_sec * 1000000 + now->tv_usec; 7014c87aefeSPatrick Mooney n2 = prev->tv_sec * 1000000 + prev->tv_usec; 7024c87aefeSPatrick Mooney return (n1 - n2); 7034c87aefeSPatrick Mooney } 7044c87aefeSPatrick Mooney 7054c87aefeSPatrick Mooney static void * 7064c87aefeSPatrick Mooney rfb_wr_thr(void *arg) 7074c87aefeSPatrick Mooney { 7084c87aefeSPatrick Mooney struct rfb_softc *rc; 7094c87aefeSPatrick Mooney fd_set rfds; 7104c87aefeSPatrick Mooney struct timeval tv; 7114c87aefeSPatrick Mooney struct timeval prev_tv; 7124c87aefeSPatrick Mooney int64_t tdiff; 7134c87aefeSPatrick Mooney int cfd; 7144c87aefeSPatrick Mooney int err; 7154c87aefeSPatrick Mooney 7164c87aefeSPatrick Mooney rc = arg; 7174c87aefeSPatrick Mooney cfd = rc->cfd; 7184c87aefeSPatrick Mooney 7194c87aefeSPatrick Mooney prev_tv.tv_sec = 0; 7204c87aefeSPatrick Mooney prev_tv.tv_usec = 0; 7214c87aefeSPatrick Mooney while (rc->cfd >= 0) { 7224c87aefeSPatrick Mooney FD_ZERO(&rfds); 7234c87aefeSPatrick Mooney FD_SET(cfd, &rfds); 7244c87aefeSPatrick Mooney tv.tv_sec = 0; 7254c87aefeSPatrick Mooney tv.tv_usec = 10000; 7264c87aefeSPatrick Mooney 7274c87aefeSPatrick Mooney err = select(cfd+1, &rfds, NULL, NULL, &tv); 7284c87aefeSPatrick Mooney if (err < 0) 7294c87aefeSPatrick Mooney return (NULL); 7304c87aefeSPatrick Mooney 7314c87aefeSPatrick Mooney /* Determine if its time to push screen; ~24hz */ 7324c87aefeSPatrick Mooney gettimeofday(&tv, NULL); 7334c87aefeSPatrick Mooney tdiff = timeval_delta(&prev_tv, &tv); 7344c87aefeSPatrick Mooney if (tdiff > 40000) { 7354c87aefeSPatrick Mooney prev_tv.tv_sec = tv.tv_sec; 7364c87aefeSPatrick Mooney prev_tv.tv_usec = tv.tv_usec; 7374c87aefeSPatrick Mooney if (rfb_send_screen(rc, cfd, 0) <= 0) { 7384c87aefeSPatrick Mooney return (NULL); 7394c87aefeSPatrick Mooney } 7404c87aefeSPatrick Mooney } else { 7414c87aefeSPatrick Mooney /* sleep */ 7424c87aefeSPatrick Mooney usleep(40000 - tdiff); 7434c87aefeSPatrick Mooney } 7444c87aefeSPatrick Mooney } 7454c87aefeSPatrick Mooney 7464c87aefeSPatrick Mooney return (NULL); 747bf21cd93STycho Nightingale } 748bf21cd93STycho Nightingale 749bf21cd93STycho Nightingale void 750bf21cd93STycho Nightingale rfb_handle(struct rfb_softc *rc, int cfd) 751bf21cd93STycho Nightingale { 752bf21cd93STycho Nightingale const char *vbuf = "RFB 003.008\n"; 753bf21cd93STycho Nightingale unsigned char buf[80]; 7544c87aefeSPatrick Mooney unsigned char *message = NULL; 7554c87aefeSPatrick Mooney 7564c87aefeSPatrick Mooney #ifndef NO_OPENSSL 7574c87aefeSPatrick Mooney unsigned char challenge[AUTH_LENGTH]; 7584c87aefeSPatrick Mooney unsigned char keystr[PASSWD_LENGTH]; 7594c87aefeSPatrick Mooney unsigned char crypt_expected[AUTH_LENGTH]; 7604c87aefeSPatrick Mooney 7614c87aefeSPatrick Mooney DES_key_schedule ks; 7624c87aefeSPatrick Mooney int i; 7634c87aefeSPatrick Mooney #endif 7644c87aefeSPatrick Mooney 7654c87aefeSPatrick Mooney pthread_t tid; 7664c87aefeSPatrick Mooney uint32_t sres = 0; 767bf21cd93STycho Nightingale int len; 7684c87aefeSPatrick Mooney int perror = 1; 7694c87aefeSPatrick Mooney 7704c87aefeSPatrick Mooney rc->cfd = cfd; 771bf21cd93STycho Nightingale 772bf21cd93STycho Nightingale /* 1a. Send server version */ 7734c87aefeSPatrick Mooney stream_write(cfd, vbuf, strlen(vbuf)); 774bf21cd93STycho Nightingale 775bf21cd93STycho Nightingale /* 1b. Read client version */ 776bf21cd93STycho Nightingale len = read(cfd, buf, sizeof(buf)); 777bf21cd93STycho Nightingale 7784c87aefeSPatrick Mooney /* 2a. Send security type */ 779bf21cd93STycho Nightingale buf[0] = 1; 7804c87aefeSPatrick Mooney #ifndef NO_OPENSSL 7814c87aefeSPatrick Mooney if (rc->password) 7824c87aefeSPatrick Mooney buf[1] = SECURITY_TYPE_VNC_AUTH; 7834c87aefeSPatrick Mooney else 7844c87aefeSPatrick Mooney buf[1] = SECURITY_TYPE_NONE; 7854c87aefeSPatrick Mooney #else 7864c87aefeSPatrick Mooney buf[1] = SECURITY_TYPE_NONE; 7874c87aefeSPatrick Mooney #endif 7884c87aefeSPatrick Mooney 7894c87aefeSPatrick Mooney stream_write(cfd, buf, 2); 790bf21cd93STycho Nightingale 791bf21cd93STycho Nightingale /* 2b. Read agreed security type */ 7924c87aefeSPatrick Mooney len = stream_read(cfd, buf, 1); 7934c87aefeSPatrick Mooney 7944c87aefeSPatrick Mooney /* 2c. Do VNC authentication */ 7954c87aefeSPatrick Mooney switch (buf[0]) { 7964c87aefeSPatrick Mooney case SECURITY_TYPE_NONE: 7974c87aefeSPatrick Mooney sres = 0; 7984c87aefeSPatrick Mooney break; 7994c87aefeSPatrick Mooney case SECURITY_TYPE_VNC_AUTH: 8004c87aefeSPatrick Mooney /* 8014c87aefeSPatrick Mooney * The client encrypts the challenge with DES, using a password 8024c87aefeSPatrick Mooney * supplied by the user as the key. 8034c87aefeSPatrick Mooney * To form the key, the password is truncated to 8044c87aefeSPatrick Mooney * eight characters, or padded with null bytes on the right. 8054c87aefeSPatrick Mooney * The client then sends the resulting 16-bytes response. 8064c87aefeSPatrick Mooney */ 8074c87aefeSPatrick Mooney #ifndef NO_OPENSSL 8084c87aefeSPatrick Mooney strncpy(keystr, rc->password, PASSWD_LENGTH); 8094c87aefeSPatrick Mooney 8104c87aefeSPatrick Mooney /* VNC clients encrypts the challenge with all the bit fields 8114c87aefeSPatrick Mooney * in each byte of the password mirrored. 8124c87aefeSPatrick Mooney * Here we flip each byte of the keystr. 8134c87aefeSPatrick Mooney */ 8144c87aefeSPatrick Mooney for (i = 0; i < PASSWD_LENGTH; i++) { 8154c87aefeSPatrick Mooney keystr[i] = (keystr[i] & 0xF0) >> 4 8164c87aefeSPatrick Mooney | (keystr[i] & 0x0F) << 4; 8174c87aefeSPatrick Mooney keystr[i] = (keystr[i] & 0xCC) >> 2 8184c87aefeSPatrick Mooney | (keystr[i] & 0x33) << 2; 8194c87aefeSPatrick Mooney keystr[i] = (keystr[i] & 0xAA) >> 1 8204c87aefeSPatrick Mooney | (keystr[i] & 0x55) << 1; 8214c87aefeSPatrick Mooney } 8224c87aefeSPatrick Mooney 8234c87aefeSPatrick Mooney /* Initialize a 16-byte random challenge */ 8244c87aefeSPatrick Mooney arc4random_buf(challenge, sizeof(challenge)); 8254c87aefeSPatrick Mooney stream_write(cfd, challenge, AUTH_LENGTH); 8264c87aefeSPatrick Mooney 8274c87aefeSPatrick Mooney /* Receive the 16-byte challenge response */ 8284c87aefeSPatrick Mooney stream_read(cfd, buf, AUTH_LENGTH); 8294c87aefeSPatrick Mooney 8304c87aefeSPatrick Mooney memcpy(crypt_expected, challenge, AUTH_LENGTH); 8314c87aefeSPatrick Mooney 8324c87aefeSPatrick Mooney /* Encrypt the Challenge with DES */ 8334c87aefeSPatrick Mooney DES_set_key((const_DES_cblock *)keystr, &ks); 8344c87aefeSPatrick Mooney DES_ecb_encrypt((const_DES_cblock *)challenge, 8354c87aefeSPatrick Mooney (const_DES_cblock *)crypt_expected, 8364c87aefeSPatrick Mooney &ks, DES_ENCRYPT); 8374c87aefeSPatrick Mooney DES_ecb_encrypt((const_DES_cblock *)(challenge + PASSWD_LENGTH), 8384c87aefeSPatrick Mooney (const_DES_cblock *)(crypt_expected + 8394c87aefeSPatrick Mooney PASSWD_LENGTH), 8404c87aefeSPatrick Mooney &ks, DES_ENCRYPT); 8414c87aefeSPatrick Mooney 8424c87aefeSPatrick Mooney if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) { 8434c87aefeSPatrick Mooney message = "Auth Failed: Invalid Password."; 8444c87aefeSPatrick Mooney sres = htonl(1); 8454c87aefeSPatrick Mooney } else 8464c87aefeSPatrick Mooney sres = 0; 8474c87aefeSPatrick Mooney #else 8484c87aefeSPatrick Mooney sres = 0; 8494c87aefeSPatrick Mooney WPRINTF(("Auth not supported, no OpenSSL in your system")); 8504c87aefeSPatrick Mooney #endif 851bf21cd93STycho Nightingale 8524c87aefeSPatrick Mooney break; 8534c87aefeSPatrick Mooney } 8544c87aefeSPatrick Mooney 8554c87aefeSPatrick Mooney /* 2d. Write back a status */ 8564c87aefeSPatrick Mooney stream_write(cfd, &sres, 4); 8574c87aefeSPatrick Mooney 8584c87aefeSPatrick Mooney if (sres) { 8594c87aefeSPatrick Mooney #ifdef __FreeBSD__ 8604c87aefeSPatrick Mooney be32enc(buf, strlen(message)); 8614c87aefeSPatrick Mooney stream_write(cfd, buf, 4); 8624c87aefeSPatrick Mooney stream_write(cfd, message, strlen(message)); 8634c87aefeSPatrick Mooney #else 8644c87aefeSPatrick Mooney be32enc(buf, strlen((char *)message)); 8654c87aefeSPatrick Mooney stream_write(cfd, buf, 4); 8664c87aefeSPatrick Mooney stream_write(cfd, message, strlen((char *)message)); 8674c87aefeSPatrick Mooney #endif 8684c87aefeSPatrick Mooney goto done; 8694c87aefeSPatrick Mooney } 870bf21cd93STycho Nightingale 871bf21cd93STycho Nightingale /* 3a. Read client shared-flag byte */ 8724c87aefeSPatrick Mooney len = stream_read(cfd, buf, 1); 873bf21cd93STycho Nightingale 874bf21cd93STycho Nightingale /* 4a. Write server-init info */ 875bf21cd93STycho Nightingale rfb_send_server_init_msg(cfd); 876bf21cd93STycho Nightingale 8774c87aefeSPatrick Mooney if (!rc->zbuf) { 8784c87aefeSPatrick Mooney rc->zbuf = malloc(RFB_ZLIB_BUFSZ + 16); 8794c87aefeSPatrick Mooney assert(rc->zbuf != NULL); 8804c87aefeSPatrick Mooney } 8814c87aefeSPatrick Mooney 8824c87aefeSPatrick Mooney rfb_send_screen(rc, cfd, 1); 8834c87aefeSPatrick Mooney 8844c87aefeSPatrick Mooney perror = pthread_create(&tid, NULL, rfb_wr_thr, rc); 8854c87aefeSPatrick Mooney if (perror == 0) 8864c87aefeSPatrick Mooney pthread_set_name_np(tid, "rfbout"); 8874c87aefeSPatrick Mooney 888bf21cd93STycho Nightingale /* Now read in client requests. 1st byte identifies type */ 889bf21cd93STycho Nightingale for (;;) { 890bf21cd93STycho Nightingale len = read(cfd, buf, 1); 891bf21cd93STycho Nightingale if (len <= 0) { 8924c87aefeSPatrick Mooney DPRINTF(("rfb client exiting\r\n")); 893bf21cd93STycho Nightingale break; 894bf21cd93STycho Nightingale } 895bf21cd93STycho Nightingale 896bf21cd93STycho Nightingale switch (buf[0]) { 897bf21cd93STycho Nightingale case 0: 898bf21cd93STycho Nightingale rfb_recv_set_pixfmt_msg(rc, cfd); 899bf21cd93STycho Nightingale break; 900bf21cd93STycho Nightingale case 2: 901bf21cd93STycho Nightingale rfb_recv_set_encodings_msg(rc, cfd); 902bf21cd93STycho Nightingale break; 903bf21cd93STycho Nightingale case 3: 9044c87aefeSPatrick Mooney rfb_recv_update_msg(rc, cfd, 1); 905bf21cd93STycho Nightingale break; 906bf21cd93STycho Nightingale case 4: 907bf21cd93STycho Nightingale rfb_recv_key_msg(rc, cfd); 908bf21cd93STycho Nightingale break; 909bf21cd93STycho Nightingale case 5: 910bf21cd93STycho Nightingale rfb_recv_ptr_msg(rc, cfd); 911bf21cd93STycho Nightingale break; 9124c87aefeSPatrick Mooney case 6: 9134c87aefeSPatrick Mooney rfb_recv_cuttext_msg(rc, cfd); 9144c87aefeSPatrick Mooney break; 915bf21cd93STycho Nightingale default: 9164c87aefeSPatrick Mooney WPRINTF(("rfb unknown cli-code %d!\n", buf[0] & 0xff)); 9174c87aefeSPatrick Mooney goto done; 918bf21cd93STycho Nightingale } 919bf21cd93STycho Nightingale } 9204c87aefeSPatrick Mooney done: 9214c87aefeSPatrick Mooney rc->cfd = -1; 9224c87aefeSPatrick Mooney if (perror == 0) 9234c87aefeSPatrick Mooney pthread_join(tid, NULL); 9244c87aefeSPatrick Mooney if (rc->enc_zlib_ok) 9254c87aefeSPatrick Mooney deflateEnd(&rc->zstream); 926bf21cd93STycho Nightingale } 927bf21cd93STycho Nightingale 928bf21cd93STycho Nightingale static void * 929bf21cd93STycho Nightingale rfb_thr(void *arg) 930bf21cd93STycho Nightingale { 931bf21cd93STycho Nightingale struct rfb_softc *rc; 932bf21cd93STycho Nightingale sigset_t set; 933bf21cd93STycho Nightingale 934bf21cd93STycho Nightingale int cfd; 935bf21cd93STycho Nightingale 936bf21cd93STycho Nightingale rc = arg; 937bf21cd93STycho Nightingale 938bf21cd93STycho Nightingale sigemptyset(&set); 939bf21cd93STycho Nightingale sigaddset(&set, SIGPIPE); 940bf21cd93STycho Nightingale if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { 941bf21cd93STycho Nightingale perror("pthread_sigmask"); 942bf21cd93STycho Nightingale return (NULL); 943bf21cd93STycho Nightingale } 944bf21cd93STycho Nightingale 945bf21cd93STycho Nightingale for (;;) { 9464c87aefeSPatrick Mooney rc->enc_raw_ok = false; 9474c87aefeSPatrick Mooney rc->enc_zlib_ok = false; 9484c87aefeSPatrick Mooney rc->enc_resize_ok = false; 9494c87aefeSPatrick Mooney 950bf21cd93STycho Nightingale cfd = accept(rc->sfd, NULL, NULL); 9514c87aefeSPatrick Mooney if (rc->conn_wait) { 9524c87aefeSPatrick Mooney pthread_mutex_lock(&rc->mtx); 9534c87aefeSPatrick Mooney pthread_cond_signal(&rc->cond); 9544c87aefeSPatrick Mooney pthread_mutex_unlock(&rc->mtx); 9554c87aefeSPatrick Mooney rc->conn_wait = 0; 9564c87aefeSPatrick Mooney } 957bf21cd93STycho Nightingale rfb_handle(rc, cfd); 9584c87aefeSPatrick Mooney close(cfd); 959bf21cd93STycho Nightingale } 960bf21cd93STycho Nightingale 961bf21cd93STycho Nightingale /* NOTREACHED */ 962bf21cd93STycho Nightingale return (NULL); 963bf21cd93STycho Nightingale } 964bf21cd93STycho Nightingale 9654c87aefeSPatrick Mooney static int 9664c87aefeSPatrick Mooney sse42_supported(void) 9674c87aefeSPatrick Mooney { 9684c87aefeSPatrick Mooney u_int cpu_registers[4], ecx; 9694c87aefeSPatrick Mooney 9704c87aefeSPatrick Mooney do_cpuid(1, cpu_registers); 9714c87aefeSPatrick Mooney 9724c87aefeSPatrick Mooney ecx = cpu_registers[2]; 9734c87aefeSPatrick Mooney 9744c87aefeSPatrick Mooney return ((ecx & CPUID2_SSE42) != 0); 9754c87aefeSPatrick Mooney } 9764c87aefeSPatrick Mooney 977bf21cd93STycho Nightingale int 9784c87aefeSPatrick Mooney rfb_init(char *hostname, int port, int wait, char *password) 979bf21cd93STycho Nightingale { 9804c87aefeSPatrick Mooney int e; 9814c87aefeSPatrick Mooney char servname[6]; 982bf21cd93STycho Nightingale struct rfb_softc *rc; 983*84659b24SMichael Zeller struct addrinfo *ai = NULL; 9844c87aefeSPatrick Mooney struct addrinfo hints; 985bf21cd93STycho Nightingale int on = 1; 9864c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 9874c87aefeSPatrick Mooney cap_rights_t rights; 9884c87aefeSPatrick Mooney #endif 989bf21cd93STycho Nightingale 990bf21cd93STycho Nightingale rc = calloc(1, sizeof(struct rfb_softc)); 991bf21cd93STycho Nightingale 9924c87aefeSPatrick Mooney rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 9934c87aefeSPatrick Mooney sizeof(uint32_t)); 9944c87aefeSPatrick Mooney rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 9954c87aefeSPatrick Mooney sizeof(uint32_t)); 9964c87aefeSPatrick Mooney rc->crc_width = RFB_MAX_WIDTH; 9974c87aefeSPatrick Mooney rc->crc_height = RFB_MAX_HEIGHT; 998*84659b24SMichael Zeller rc->sfd = -1; 9994c87aefeSPatrick Mooney 10004c87aefeSPatrick Mooney rc->password = password; 10014c87aefeSPatrick Mooney 10024c87aefeSPatrick Mooney snprintf(servname, sizeof(servname), "%d", port ? port : 5900); 10034c87aefeSPatrick Mooney 10044c87aefeSPatrick Mooney if (!hostname || strlen(hostname) == 0) 10054c87aefeSPatrick Mooney #if defined(INET) 10064c87aefeSPatrick Mooney hostname = "127.0.0.1"; 10074c87aefeSPatrick Mooney #elif defined(INET6) 10084c87aefeSPatrick Mooney hostname = "[::1]"; 10094c87aefeSPatrick Mooney #endif 10104c87aefeSPatrick Mooney 10114c87aefeSPatrick Mooney memset(&hints, 0, sizeof(hints)); 10124c87aefeSPatrick Mooney hints.ai_family = AF_UNSPEC; 10134c87aefeSPatrick Mooney hints.ai_socktype = SOCK_STREAM; 10144c87aefeSPatrick Mooney hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; 10154c87aefeSPatrick Mooney 10164c87aefeSPatrick Mooney if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { 10174c87aefeSPatrick Mooney fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(e)); 1018*84659b24SMichael Zeller goto error; 10194c87aefeSPatrick Mooney } 10204c87aefeSPatrick Mooney 10214c87aefeSPatrick Mooney rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0); 1022bf21cd93STycho Nightingale if (rc->sfd < 0) { 1023bf21cd93STycho Nightingale perror("socket"); 1024*84659b24SMichael Zeller goto error; 1025bf21cd93STycho Nightingale } 1026bf21cd93STycho Nightingale 1027bf21cd93STycho Nightingale setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 1028bf21cd93STycho Nightingale 10294c87aefeSPatrick Mooney if (bind(rc->sfd, ai->ai_addr, ai->ai_addrlen) < 0) { 1030bf21cd93STycho Nightingale perror("bind"); 1031*84659b24SMichael Zeller goto error; 1032bf21cd93STycho Nightingale } 1033bf21cd93STycho Nightingale 1034bf21cd93STycho Nightingale if (listen(rc->sfd, 1) < 0) { 1035bf21cd93STycho Nightingale perror("listen"); 1036*84659b24SMichael Zeller goto error; 1037bf21cd93STycho Nightingale } 1038bf21cd93STycho Nightingale 10394c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 10404c87aefeSPatrick Mooney cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE); 10414c87aefeSPatrick Mooney if (caph_rights_limit(rc->sfd, &rights) == -1) 10424c87aefeSPatrick Mooney errx(EX_OSERR, "Unable to apply rights for sandbox"); 10434c87aefeSPatrick Mooney #endif 10444c87aefeSPatrick Mooney 10454c87aefeSPatrick Mooney rc->hw_crc = sse42_supported(); 10464c87aefeSPatrick Mooney 10474c87aefeSPatrick Mooney rc->conn_wait = wait; 10484c87aefeSPatrick Mooney if (wait) { 10494c87aefeSPatrick Mooney pthread_mutex_init(&rc->mtx, NULL); 10504c87aefeSPatrick Mooney pthread_cond_init(&rc->cond, NULL); 10514c87aefeSPatrick Mooney } 10524c87aefeSPatrick Mooney 1053bf21cd93STycho Nightingale pthread_create(&rc->tid, NULL, rfb_thr, rc); 10544c87aefeSPatrick Mooney pthread_set_name_np(rc->tid, "rfb"); 10554c87aefeSPatrick Mooney 10564c87aefeSPatrick Mooney if (wait) { 10574c87aefeSPatrick Mooney DPRINTF(("Waiting for rfb client...\n")); 10584c87aefeSPatrick Mooney pthread_mutex_lock(&rc->mtx); 10594c87aefeSPatrick Mooney pthread_cond_wait(&rc->cond, &rc->mtx); 10604c87aefeSPatrick Mooney pthread_mutex_unlock(&rc->mtx); 10614c87aefeSPatrick Mooney } 1062bf21cd93STycho Nightingale 10634c87aefeSPatrick Mooney freeaddrinfo(ai); 1064bf21cd93STycho Nightingale return (0); 1065*84659b24SMichael Zeller 1066*84659b24SMichael Zeller error: 1067*84659b24SMichael Zeller if (ai != NULL) 1068*84659b24SMichael Zeller freeaddrinfo(ai); 1069*84659b24SMichael Zeller if (rc->sfd != -1) 1070*84659b24SMichael Zeller close(rc->sfd); 1071*84659b24SMichael Zeller free(rc->crc); 1072*84659b24SMichael Zeller free(rc->crc_tmp); 1073*84659b24SMichael Zeller free(rc); 1074*84659b24SMichael Zeller return (-1); 1075bf21cd93STycho Nightingale } 10764c87aefeSPatrick Mooney 10774c87aefeSPatrick Mooney #ifndef __FreeBSD__ 10784c87aefeSPatrick Mooney int 10794c87aefeSPatrick Mooney rfb_init_unix(char *path, int wait, char *password) 10804c87aefeSPatrick Mooney { 10814c87aefeSPatrick Mooney struct rfb_softc *rc; 10824c87aefeSPatrick Mooney struct sockaddr_un sock; 10834c87aefeSPatrick Mooney 10844c87aefeSPatrick Mooney if ((rc = calloc(1, sizeof (struct rfb_softc))) == NULL) { 10854c87aefeSPatrick Mooney perror("calloc"); 10864c87aefeSPatrick Mooney return (-1); 10874c87aefeSPatrick Mooney } 10884c87aefeSPatrick Mooney rc->sfd = -1; 10894c87aefeSPatrick Mooney 10904c87aefeSPatrick Mooney if ((rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 10914c87aefeSPatrick Mooney sizeof (uint32_t))) == NULL) { 10924c87aefeSPatrick Mooney perror("calloc"); 10934c87aefeSPatrick Mooney goto fail; 10944c87aefeSPatrick Mooney } 10954c87aefeSPatrick Mooney if ((rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 10964c87aefeSPatrick Mooney sizeof (uint32_t))) == NULL) { 10974c87aefeSPatrick Mooney perror("calloc"); 10984c87aefeSPatrick Mooney goto fail; 10994c87aefeSPatrick Mooney } 11004c87aefeSPatrick Mooney rc->crc_width = RFB_MAX_WIDTH; 11014c87aefeSPatrick Mooney rc->crc_height = RFB_MAX_HEIGHT; 11024c87aefeSPatrick Mooney 11034c87aefeSPatrick Mooney rc->password = password; 11044c87aefeSPatrick Mooney 11054c87aefeSPatrick Mooney rc->sfd = socket(PF_UNIX, SOCK_STREAM, 0); 11064c87aefeSPatrick Mooney if (rc->sfd < 0) { 11074c87aefeSPatrick Mooney perror("socket"); 11084c87aefeSPatrick Mooney goto fail; 11094c87aefeSPatrick Mooney } 11104c87aefeSPatrick Mooney 11114c87aefeSPatrick Mooney sock.sun_family = AF_UNIX; 11124c87aefeSPatrick Mooney if (strlcpy(sock.sun_path, path, sizeof (sock.sun_path)) >= 11134c87aefeSPatrick Mooney sizeof (sock.sun_path)) { 11144c87aefeSPatrick Mooney (void) fprintf(stderr, "socket path '%s' too long\n", path); 11154c87aefeSPatrick Mooney goto fail; 11164c87aefeSPatrick Mooney } 11174c87aefeSPatrick Mooney 11184c87aefeSPatrick Mooney (void) unlink(path); 11194c87aefeSPatrick Mooney if (bind(rc->sfd, (struct sockaddr *)&sock, sizeof (sock)) < 0) { 11204c87aefeSPatrick Mooney perror("bind"); 11214c87aefeSPatrick Mooney goto fail; 11224c87aefeSPatrick Mooney } 11234c87aefeSPatrick Mooney 11244c87aefeSPatrick Mooney if (listen(rc->sfd, 1) < 0) { 11254c87aefeSPatrick Mooney perror("listen"); 11264c87aefeSPatrick Mooney goto fail; 11274c87aefeSPatrick Mooney } 11284c87aefeSPatrick Mooney 11294c87aefeSPatrick Mooney rc->hw_crc = sse42_supported(); 11304c87aefeSPatrick Mooney 11314c87aefeSPatrick Mooney rc->conn_wait = wait; 11324c87aefeSPatrick Mooney if (wait) { 11334c87aefeSPatrick Mooney VERIFY3S(pthread_mutex_init(&rc->mtx, NULL), ==, 0); 11344c87aefeSPatrick Mooney VERIFY3S(pthread_cond_init(&rc->cond, NULL), ==, 0); 11354c87aefeSPatrick Mooney } 11364c87aefeSPatrick Mooney 11374c87aefeSPatrick Mooney VERIFY3S(pthread_create(&rc->tid, NULL, rfb_thr, rc), ==, 0); 11384c87aefeSPatrick Mooney pthread_set_name_np(rc->tid, "rfb"); 11394c87aefeSPatrick Mooney 11404c87aefeSPatrick Mooney if (wait) { 11414c87aefeSPatrick Mooney DPRINTF(("Waiting for rfb client...\n")); 11424c87aefeSPatrick Mooney VERIFY3S(pthread_mutex_lock(&rc->mtx), ==, 0); 11434c87aefeSPatrick Mooney VERIFY3S(pthread_cond_wait(&rc->cond, &rc->mtx), ==, 0); 11444c87aefeSPatrick Mooney VERIFY3S(pthread_mutex_unlock(&rc->mtx), ==, 0); 11454c87aefeSPatrick Mooney } 11464c87aefeSPatrick Mooney 11474c87aefeSPatrick Mooney return (0); 11484c87aefeSPatrick Mooney 11494c87aefeSPatrick Mooney fail: 11504c87aefeSPatrick Mooney if (rc->sfd != -1) { 11514c87aefeSPatrick Mooney VERIFY3S(close(rc->sfd), ==, 0); 11524c87aefeSPatrick Mooney } 11534c87aefeSPatrick Mooney free(rc->crc); 11544c87aefeSPatrick Mooney free(rc->crc_tmp); 11554c87aefeSPatrick Mooney free(rc); 11564c87aefeSPatrick Mooney return (-1); 11574c87aefeSPatrick Mooney } 11584c87aefeSPatrick Mooney #endif 1159