rfb.c (7bb0eb348e1119aed76a61d633a9106b6b9912f1) | rfb.c (1aa1f41fe10c6220a7fbef328fac1b72a8355a01) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 5 * Copyright (c) 2015 Leon Dang 6 * Copyright 2020 Joyent, Inc. | 1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 5 * Copyright (c) 2015 Leon Dang 6 * Copyright 2020 Joyent, Inc. |
7 * Copyright 2021 OmniOS Community Edition (OmniOSce) Association. | |
8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ | 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ |
30/* 31 * This file and its contents are supplied under the terms of the 32 * Common Development and Distribution License ("CDDL"), version 1.0. 33 * You may only use this file in accordance with the terms of version 34 * 1.0 of the CDDL. 35 * 36 * A full copy of the text of the CDDL should have accompanied this 37 * source. A copy of the CDDL is also available via the Internet at 38 * http://www.illumos.org/license/CDDL. 39 * 40 * Copyright 2022 OmniOS Community Edition (OmniOSce) Association. 41 */ |
|
31 | 42 |
32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD$"); | 43/* 44 * References to the RFB protocol specification refer to: 45 * - [1] https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst 46 */ |
34 | 47 |
35#include <sys/param.h> 36#ifndef WITHOUT_CAPSICUM 37#include <sys/capsicum.h> 38#endif 39#include <sys/endian.h> 40#include <sys/socket.h> 41#include <sys/select.h> 42#include <sys/time.h> 43#include <arpa/inet.h> 44#include <stdatomic.h> 45#include <machine/cpufunc.h> 46#include <machine/specialreg.h> 47#include <netinet/in.h> 48#include <netdb.h> 49 50#include <assert.h> 51#ifndef WITHOUT_CAPSICUM 52#include <capsicum_helpers.h> 53#endif | |
54#include <err.h> 55#include <errno.h> | 48#include <err.h> 49#include <errno.h> |
50#include <libidspace.h> 51#include <netdb.h> |
|
56#include <pthread.h> 57#include <pthread_np.h> 58#include <signal.h> | 52#include <pthread.h> 53#include <pthread_np.h> 54#include <signal.h> |
55#include <stdatomic.h> |
|
59#include <stdbool.h> | 56#include <stdbool.h> |
60#include <stdlib.h> | |
61#include <stdio.h> | 57#include <stdio.h> |
58#include <stdlib.h> |
|
62#include <string.h> | 59#include <string.h> |
63#include <sysexits.h> | |
64#include <unistd.h> | 60#include <unistd.h> |
65 | |
66#include <zlib.h> | 61#include <zlib.h> |
67 68#ifndef __FreeBSD__ | 62#include <machine/cpufunc.h> 63#include <machine/specialreg.h> 64#include <netinet/in.h> 65#ifndef NO_OPENSSL 66#include <openssl/des.h> 67#endif |
69#include <sys/debug.h> | 68#include <sys/debug.h> |
69#include <sys/endian.h> 70#include <sys/list.h> 71#include <sys/socket.h> 72#include <sys/types.h> 73#ifndef WITHOUT_CAPSICUM 74#include <sysexits.h> 75#include <sys/capsicum.h> 76#include <capsicum_helpers.h> |
|
70#endif 71 72#include "bhyvegc.h" | 77#endif 78 79#include "bhyvegc.h" |
80#include "config.h" |
|
73#include "debug.h" 74#include "console.h" 75#include "rfb.h" | 81#include "debug.h" 82#include "console.h" 83#include "rfb.h" |
84#include "rfb_impl.h" |
|
76#include "sockstream.h" 77 | 85#include "sockstream.h" 86 |
78#ifndef NO_OPENSSL 79#include <openssl/des.h> 80#endif | 87static uint_t rfb_debug = 0; 88static list_t rfb_list; 89static id_space_t *rfb_idspace; |
81 | 90 |
82/* Delays in microseconds */ 83#define CFD_SEL_DELAY 10000 84#define SCREEN_REFRESH_DELAY 33300 /* 30Hz */ 85#define SCREEN_POLL_DELAY (SCREEN_REFRESH_DELAY / 2) | 91static bool rfb_sse42; 92static pthread_once_t rfb_once = PTHREAD_ONCE_INIT; |
86 | 93 |
87static int rfb_debug = 0; 88#define DPRINTF(params) if (rfb_debug) PRINTLN params 89#define WPRINTF(params) PRINTLN params | 94extern int raw_stdio; |
90 | 95 |
91#define VERSION_LENGTH 12 92#define AUTH_LENGTH 16 93#define PASSWD_LENGTH 8 | 96static void rfb_send_extended_keyevent_update_msg(rfb_client_t *); |
94 | 97 |
95/* Protocol versions */ 96#define CVERS_3_3 '3' 97#define CVERS_3_7 '7' 98#define CVERS_3_8 '8' | 98static void 99rfb_printf(rfb_client_t *c, rfb_loglevel_t level, const char *fmt, ...) 100{ 101 FILE *fp = stdout; 102 va_list ap; |
99 | 103 |
100/* Client-to-server msg types */ 101#define CS_SET_PIXEL_FORMAT 0 102#define CS_SET_ENCODINGS 2 103#define CS_UPDATE_MSG 3 104#define CS_KEY_EVENT 4 105#define CS_POINTER_EVENT 5 106#define CS_CUT_TEXT 6 107#define CS_MSG_CLIENT_QEMU 255 | 104 switch (level) { 105 case RFB_LOGDEBUG: 106 if (rfb_debug == 0) 107 return; 108 /* FALLTHROUGH */ 109 case RFB_LOGERR: 110 fp = stderr; 111 /* FALLTHROUGH */ 112 case RFB_LOGWARN: 113 if (c != NULL) 114 (void) fprintf(fp, "rfb%u: ", c->rc_instance); 115 else 116 (void) fprintf(fp, "rfb: "); 117 va_start(ap, fmt); 118 (void) vfprintf(fp, fmt, ap); 119 va_end(ap); 120 if (raw_stdio) 121 (void) fprintf(fp, "\r\n"); 122 else 123 (void) fprintf(fp, "\n"); 124 (void) fflush(fp); 125 } 126} |
108 | 127 |
109#define SECURITY_TYPE_NONE 1 110#define SECURITY_TYPE_VNC_AUTH 2 | 128static void 129rfb_init_once(void) 130{ 131 uint_t cpu_registers[4], ecx; |
111 | 132 |
112#define AUTH_FAILED_UNAUTH 1 113#define AUTH_FAILED_ERROR 2 | 133 do_cpuid(1, cpu_registers); 134 ecx = cpu_registers[2]; 135 rfb_sse42 = (ecx & CPUID2_SSE42) != 0; |
114 | 136 |
115struct rfb_softc { 116 int sfd; 117 pthread_t tid; | 137 if (rfb_sse42) 138 rfb_printf(NULL, RFB_LOGDEBUG, "enabled fast crc32"); 139 else 140 rfb_printf(NULL, RFB_LOGWARN, "no support for fast crc32"); |
118 | 141 |
119 int cfd; | 142 if (get_config_bool_default("rfb.debug", false)) 143 rfb_debug = 1; |
120 | 144 |
121 int width, height; | 145 list_create(&rfb_list, sizeof (rfb_server_t), 146 offsetof(rfb_server_t, rs_node)); |
122 | 147 |
123 char *password; | 148 rfb_idspace = id_space_create("rfb", 0, INT32_MAX); 149} |
124 | 150 |
125 bool enc_raw_ok; 126 bool enc_zlib_ok; 127 bool enc_resize_ok; 128 bool enc_extkeyevent_ok; | 151static void 152rfb_free_client(rfb_client_t *c) 153{ 154 free(c->rc_crc); 155 free(c->rc_crc_tmp); 156 free(c->rc_zbuf); 157 free(c->rc_gci.data); |
129 | 158 |
130 bool enc_extkeyevent_send; | 159 if (c->rc_encodings & RFB_ENCODING_ZLIB) 160 (void) deflateEnd(&c->rc_zstream); |
131 | 161 |
132 z_stream zstream; 133 uint8_t *zbuf; 134 int zbuflen; | 162 if (c->rc_fd != -1) 163 (void) close(c->rc_fd); |
135 | 164 |
136 int conn_wait; 137 int wrcount; | 165 free(c); 166} |
138 | 167 |
139 atomic_bool sending; 140 atomic_bool pending; 141 atomic_bool update_all; 142 atomic_bool input_detected; | 168/* 169 * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only 170 */ 171static inline uint32_t 172fast_crc32(void *buf, int len, uint32_t crcval) 173{ 174 uint32_t q = len / sizeof (uint32_t); 175 uint32_t *p = (uint32_t *)buf; |
143 | 176 |
144 pthread_mutex_t mtx; 145 pthread_cond_t cond; | 177 while (q--) { 178 /* BEGIN CSTYLED */ 179 asm volatile ( 180 /* crc32l %ecx,%esi */ 181 ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" 182 :"=S" (crcval) 183 :"0" (crcval), "c" (*p) 184 ); 185 /* END CSTYLED */ 186 p++; 187 } |
146 | 188 |
147 int hw_crc; 148 uint32_t *crc; /* WxH crc cells */ 149 uint32_t *crc_tmp; /* buffer to store single crc row */ 150 int crc_width, crc_height; 151#ifndef __FreeBSD__ 152 const char *name; 153#endif 154}; | 189 return (crcval); 190} |
155 | 191 |
156struct rfb_pixfmt { 157 uint8_t bpp; 158 uint8_t depth; 159 uint8_t bigendian; 160 uint8_t truecolor; 161 uint16_t red_max; 162 uint16_t green_max; 163 uint16_t blue_max; 164 uint8_t red_shift; 165 uint8_t green_shift; 166 uint8_t blue_shift; 167 uint8_t pad[3]; 168}; | 192static void 193rfb_send_client_status(rfb_client_t *c, uint32_t status, const char *msg) 194{ 195 status = htonl(status); |
169 | 196 |
170struct rfb_srvr_info { 171 uint16_t width; 172 uint16_t height; 173 struct rfb_pixfmt pixfmt; 174 uint32_t namelen; 175}; | 197 (void) stream_write(c->rc_fd, &status, sizeof (status)); |
176 | 198 |
177struct rfb_pixfmt_msg { 178 uint8_t type; 179 uint8_t pad[3]; 180 struct rfb_pixfmt pixfmt; 181}; | 199 if (msg != NULL && status != 0 && c->rc_cver == RFB_CVER_3_8) { 200 char buf[4]; |
182 | 201 |
183#define RFB_ENCODING_RAW 0 184#define RFB_ENCODING_ZLIB 6 185#define RFB_ENCODING_RESIZE -223 186#define RFB_ENCODING_EXT_KEYEVENT -258 | 202 rfb_printf(c, RFB_LOGWARN, msg); |
187 | 203 |
188#define RFB_CLIENTMSG_EXT_KEYEVENT 0 | 204 be32enc(buf, strlen((char *)msg)); 205 (void) stream_write(c->rc_fd, buf, 4); 206 (void) stream_write(c->rc_fd, msg, strlen((char *)msg)); 207 } 208} |
189 | 209 |
190#define RFB_MAX_WIDTH 2000 191#define RFB_MAX_HEIGHT 1200 192#define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4 | 210static bool 211rfb_handshake_version(rfb_client_t *c) 212{ 213 unsigned char buf[RFB_VERSION_LEN]; 214 ssize_t l; |
193 | 215 |
194/* percentage changes to screen before sending the entire screen */ 195#define RFB_SEND_ALL_THRESH 25 | 216 rfb_printf(c, RFB_LOGDEBUG, "handshake version"); |
196 | 217 |
197struct rfb_enc_msg { 198 uint8_t type; 199 uint8_t pad; 200 uint16_t numencs; 201}; | 218 if (stream_write(c->rc_fd, RFB_VERSION, RFB_VERSION_LEN) != 219 RFB_VERSION_LEN) { 220 rfb_printf(c, RFB_LOGWARN, "could not send server version."); 221 return (false); 222 } |
202 | 223 |
203struct rfb_updt_msg { 204 uint8_t type; 205 uint8_t incremental; 206 uint16_t x; 207 uint16_t y; 208 uint16_t width; 209 uint16_t height; 210}; | 224 l = stream_read(c->rc_fd, buf, sizeof (buf)); 225 if (l <= 0) { 226 rfb_printf(c, RFB_LOGWARN, "client version not read"); 227 return (false); 228 } else if (l != RFB_VERSION_LEN) { 229 rfb_printf(c, RFB_LOGWARN, "client sent short version - '%.*s'", 230 l, buf); 231 return (false); 232 } |
211 | 233 |
212struct rfb_key_msg { 213 uint8_t type; 214 uint8_t down; 215 uint16_t pad; 216 uint32_t sym; 217}; | 234 rfb_printf(c, RFB_LOGDEBUG, "version handshake, client ver '%.*s'", 235 l - 1, buf); |
218 | 236 |
219struct rfb_client_msg { 220 uint8_t type; 221 uint8_t subtype; 222}; | 237 if (strncmp(RFB_VERSION, (char *)buf, RFB_VERSION_LEN - 2) != 0) { 238 rfb_printf(c, RFB_LOGERR, "bad client version '%.*s'", l, buf); 239 return (false); 240 } |
223 | 241 |
224struct rfb_extended_key_msg { 225 uint8_t type; 226 uint8_t subtype; 227 uint16_t down; 228 uint32_t sym; 229 uint32_t code; 230}; | 242 switch (buf[RFB_VERSION_LEN - 2]) { 243 case '8': 244 c->rc_cver = RFB_CVER_3_8; 245 break; 246 case '7': 247 c->rc_cver = RFB_CVER_3_7; 248 break; 249 case '5': 250 /* 251 * From the RFB specification[1], section 7.1.1: 252 * "version 3.5 was wrongly reported by some clients, but this 253 * should be interpreted by all servers as 3.3." 254 */ 255 case '3': 256 c->rc_cver = RFB_CVER_3_3; 257 break; 258 default: 259 rfb_printf(c, RFB_LOGERR, "unsupported client version '%.*s'", 260 l - 1, buf); 261 return (false); 262 } |
231 | 263 |
232struct rfb_ptr_msg { 233 uint8_t type; 234 uint8_t button; 235 uint16_t x; 236 uint16_t y; 237}; | 264 return (true); 265} |
238 | 266 |
239struct rfb_srvr_updt_msg { 240 uint8_t type; 241 uint8_t pad; 242 uint16_t numrects; 243}; | 267static bool 268rfb_handshake_auth(rfb_client_t *c) 269{ 270 unsigned char buf[RFBP_SECURITY_VNC_AUTH_LEN]; 271 int auth_type; |
244 | 272 |
245struct rfb_srvr_rect_hdr { 246 uint16_t x; 247 uint16_t y; 248 uint16_t width; 249 uint16_t height; 250 uint32_t encoding; 251}; | 273 rfb_printf(c, RFB_LOGDEBUG, "handshake auth"); |
252 | 274 |
253struct rfb_cuttext_msg { 254 uint8_t type; 255 uint8_t padding[3]; 256 uint32_t length; 257}; 258 259static void 260#ifndef __FreeBSD__ 261rfb_send_server_init_msg(int cfd, struct rfb_softc *rc) 262#else 263rfb_send_server_init_msg(int cfd) | 275 auth_type = RFBP_SECURITY_NONE; 276#ifndef NO_OPENSSL 277 if (c->rc_s->rs_password != NULL) 278 auth_type = RFBP_SECURITY_VNC_AUTH; |
264#endif | 279#endif |
265{ 266 struct bhyvegc_image *gc_image; 267 struct rfb_srvr_info sinfo; | |
268 | 280 |
269 gc_image = console_get_image(); | 281 switch (c->rc_cver) { 282 case RFB_CVER_3_3: 283 /* 284 * RFB specification[1] section 7.1.2: 285 * The server decides the security type and sends a single word. 286 */ 287 be32enc(buf, auth_type); 288 (void) stream_write(c->rc_fd, buf, 4); |
270 | 289 |
271 sinfo.width = htons(gc_image->width); 272 sinfo.height = htons(gc_image->height); 273 sinfo.pixfmt.bpp = 32; 274 sinfo.pixfmt.depth = 32; 275 sinfo.pixfmt.bigendian = 0; 276 sinfo.pixfmt.truecolor = 1; 277 sinfo.pixfmt.red_max = htons(255); 278 sinfo.pixfmt.green_max = htons(255); 279 sinfo.pixfmt.blue_max = htons(255); 280 sinfo.pixfmt.red_shift = 16; 281 sinfo.pixfmt.green_shift = 8; 282 sinfo.pixfmt.blue_shift = 0; 283 sinfo.pixfmt.pad[0] = 0; 284 sinfo.pixfmt.pad[1] = 0; 285 sinfo.pixfmt.pad[2] = 0; | 290 break; |
286 | 291 |
287#ifndef __FreeBSD__ 288 const char *name = rc->name != NULL ? rc->name : "bhyve"; | 292 case RFB_CVER_3_7: 293 case RFB_CVER_3_8: 294 /* Send list of supported types. */ 295 buf[0] = 1; /* list length */ 296 buf[1] = auth_type; 297 (void) stream_write(c->rc_fd, buf, 2); |
289 | 298 |
290 sinfo.namelen = htonl(strlen(name)); 291 (void)stream_write(cfd, &sinfo, sizeof(sinfo)); 292 (void)stream_write(cfd, name, strlen(name)); | 299 /* Read agreed security type. */ 300 if (stream_read(c->rc_fd, buf, 1) != 1) { 301 rfb_printf(c, RFB_LOGWARN, 302 "auth fail, no type from client"); 303 return (false); 304 } 305 306 if (buf[0] != auth_type) { 307 rfb_send_client_status(c, 1, 308 "Auth failed: authentication type mismatch"); 309 return (false); 310 } 311 312 break; 313 } 314 315 if (auth_type == RFBP_SECURITY_NONE) { 316 /* 317 * According to the RFB specification[1], section 7.2.1, for a 318 * security type of 'None', client versions 3.3 and 3.7 expect 319 * to move straight to the ClientInit phase, without the server 320 * sending a response. For version 3.8, a SecurityResult word 321 * needs to be sent indicating success. 322 */ 323 switch (c->rc_cver) { 324 case RFB_CVER_3_3: 325 case RFB_CVER_3_7: 326 break; 327 case RFB_CVER_3_8: 328 rfb_send_client_status(c, 0, NULL); 329 break; 330 } 331 return (true); 332 } 333 334 /* Perform VNC authentication. */ 335 336#ifdef NO_OPENSSL 337 rfb_printf(c, RFB_LOGERR, 338 "Auth not supported, no OpenSSL in your system"); 339 rfb_send_client_status(c, 1, "Auth failed."); 340 return (false); |
293#else | 341#else |
294 sinfo.namelen = htonl(strlen("bhyve")); 295 (void)stream_write(cfd, &sinfo, sizeof(sinfo)); 296 (void)stream_write(cfd, "bhyve", strlen("bhyve")); | 342 unsigned char challenge[RFBP_SECURITY_VNC_AUTH_LEN]; 343 unsigned char keystr[RFBP_SECURITY_VNC_PASSWD_LEN]; 344 unsigned char crypt_expected[RFBP_SECURITY_VNC_AUTH_LEN]; 345 DES_key_schedule ks; 346 347 /* 348 * The client encrypts the challenge with DES, using a password 349 * supplied by the user as the key. 350 * To form the key, the password is truncated to eight characters, or 351 * padded with null bytes on the right. 352 * The client then sends the resulting 16-bytes response. 353 */ 354 (void) strncpy((char *)keystr, c->rc_s->rs_password, 355 RFBP_SECURITY_VNC_PASSWD_LEN); 356 357 /* 358 * VNC clients encrypt the challenge with all the bit fields in each 359 * byte of the password mirrored. 360 * Here we flip each byte of the keystr. 361 */ 362 for (uint_t i = 0; i < RFBP_SECURITY_VNC_PASSWD_LEN; i++) { 363 keystr[i] = (keystr[i] & 0xf0) >> 4 | (keystr[i] & 0x0f) << 4; 364 keystr[i] = (keystr[i] & 0xcc) >> 2 | (keystr[i] & 0x33) << 2; 365 keystr[i] = (keystr[i] & 0xaa) >> 1 | (keystr[i] & 0x55) << 1; 366 } 367 368 /* Initialize a 16-byte random challenge. */ 369 arc4random_buf(challenge, sizeof (challenge)); 370 (void) stream_write(c->rc_fd, challenge, RFBP_SECURITY_VNC_AUTH_LEN); 371 372 /* Receive the 16-byte challenge response. */ 373 if (stream_read(c->rc_fd, buf, RFBP_SECURITY_VNC_AUTH_LEN) 374 != RFBP_SECURITY_VNC_AUTH_LEN) { 375 rfb_send_client_status(c, 1, "response read failed"); 376 return (false); 377 } 378 379 memcpy(crypt_expected, challenge, RFBP_SECURITY_VNC_AUTH_LEN); 380 381 /* Encrypt the Challenge with DES. */ 382 DES_set_key_unchecked((const_DES_cblock *)keystr, &ks); 383 DES_ecb_encrypt((const_DES_cblock *)challenge, 384 (const_DES_cblock *)crypt_expected, &ks, DES_ENCRYPT); 385 DES_ecb_encrypt( 386 (const_DES_cblock *)(challenge + RFBP_SECURITY_VNC_PASSWD_LEN), 387 (const_DES_cblock *)(crypt_expected + RFBP_SECURITY_VNC_PASSWD_LEN), 388 &ks, DES_ENCRYPT); 389 390 if (memcmp(crypt_expected, buf, RFBP_SECURITY_VNC_AUTH_LEN) != 0) { 391 rfb_send_client_status(c, 1, "Auth failed: Invalid password."); 392 return (false); 393 } 394 395 rfb_printf(c, RFB_LOGDEBUG, "authentication succeeded"); 396 rfb_send_client_status(c, 0, NULL); |
297#endif | 397#endif |
398 399 return (true); |
|
298} 299 | 400} 401 |
300static void 301rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd) | 402static bool 403rfb_handshake_init_message(rfb_client_t *c) |
302{ | 404{ |
303 struct rfb_srvr_updt_msg supdt_msg; 304 struct rfb_srvr_rect_hdr srect_hdr; | 405 struct bhyvegc_image *gci; 406 char buf[1]; 407 char *name; |
305 | 408 |
306 /* Number of rectangles: 1 */ 307 supdt_msg.type = 0; 308 supdt_msg.pad = 0; 309 supdt_msg.numrects = htons(1); 310 stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg)); | 409 rfb_printf(c, RFB_LOGDEBUG, "handshake server init"); |
311 | 410 |
312 /* Rectangle header */ 313 srect_hdr.x = htons(0); 314 srect_hdr.y = htons(0); 315 srect_hdr.width = htons(rc->width); 316 srect_hdr.height = htons(rc->height); 317 srect_hdr.encoding = htonl(RFB_ENCODING_RESIZE); 318 stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr)); | 411 /* Read the client init message. */ 412 if (stream_read(c->rc_fd, buf, 1) != 1) { 413 rfb_printf(c, RFB_LOGWARN, "client did not send init"); 414 return (false); 415 } 416 417 if (buf[0] == 0) { 418 rfb_client_t *oc; 419 420 rfb_printf(c, RFB_LOGDEBUG, 421 "client requested exclusive access"); 422 423 pthread_mutex_lock(&c->rc_s->rs_clientlock); 424 c->rc_s->rs_exclusive = true; 425 /* Disconnect all other clients. */ 426 for (oc = list_head(&c->rc_s->rs_clients); oc != NULL; 427 oc = list_next(&c->rc_s->rs_clients, oc)) { 428 if (oc != c) 429 oc->rc_closing = true; 430 } 431 pthread_mutex_unlock(&c->rc_s->rs_clientlock); 432 } else { 433 rfb_printf(c, RFB_LOGDEBUG, "client requested shared access"); 434 435 pthread_mutex_lock(&c->rc_s->rs_clientlock); 436 if (c->rc_s->rs_exclusive) { 437 rfb_printf(c, RFB_LOGWARN, 438 "deny due to existing exclusive session"); 439 pthread_mutex_unlock(&c->rc_s->rs_clientlock); 440 return (false); 441 } 442 pthread_mutex_unlock(&c->rc_s->rs_clientlock); 443 } 444 445 gci = console_get_image(); 446 447 c->rc_sinfo.rsi_width = htons(gci->width); 448 c->rc_sinfo.rsi_height = htons(gci->height); 449 c->rc_width = gci->width; 450 c->rc_height = gci->height; 451 452 if (c->rc_s->rs_name != NULL) 453 name = (char *)c->rc_s->rs_name; 454 else 455 name = "bhyve"; 456 457 c->rc_sinfo.rsi_namelen = htonl(strlen(name)); 458 (void) stream_write(c->rc_fd, &c->rc_sinfo, sizeof (c->rc_sinfo)); 459 (void) stream_write(c->rc_fd, name, strlen(name)); 460 461 return (true); |
319} 320 | 462} 463 |
321static void 322rfb_send_extended_keyevent_update_msg(struct rfb_softc *rc, int cfd) | 464static bool 465rfb_handshake(rfb_client_t *c) |
323{ | 466{ |
324 struct rfb_srvr_updt_msg supdt_msg; 325 struct rfb_srvr_rect_hdr srect_hdr; | 467 if (!rfb_handshake_version(c)) 468 return (false); |
326 | 469 |
327 /* Number of rectangles: 1 */ 328 supdt_msg.type = 0; 329 supdt_msg.pad = 0; 330 supdt_msg.numrects = htons(1); 331 stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg)); | 470 if (!rfb_handshake_auth(c)) 471 return (false); |
332 | 472 |
333 /* Rectangle header */ 334 srect_hdr.x = htons(0); 335 srect_hdr.y = htons(0); 336 srect_hdr.width = htons(rc->width); 337 srect_hdr.height = htons(rc->height); 338 srect_hdr.encoding = htonl(RFB_ENCODING_EXT_KEYEVENT); 339 stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr)); | 473 if (!rfb_handshake_init_message(c)) 474 return (false); 475 476 return (true); |
340} 341 342static void | 477} 478 479static void |
343rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd) | 480rfb_print_pixfmt(rfb_client_t *c, rfb_pixfmt_t *px, rfb_loglevel_t level) |
344{ | 481{ |
345 struct rfb_pixfmt_msg pixfmt_msg; 346 347 (void)stream_read(cfd, ((void *)&pixfmt_msg)+1, sizeof(pixfmt_msg)-1); | 482 rfb_printf(c, level, "%20s: %u", "bpp", px->rp_bpp); 483 rfb_printf(c, level, "%20s: %u", "depth", px->rp_depth); 484 rfb_printf(c, level, "%20s: %u", "bigendian", px->rp_bigendian); 485 rfb_printf(c, level, "%20s: %u", "truecolour", px->rp_truecolour); 486 rfb_printf(c, level, "%20s: %u", "r_max", ntohs(px->rp_r_max)); 487 rfb_printf(c, level, "%20s: %u", "g_max", ntohs(px->rp_g_max)); 488 rfb_printf(c, level, "%20s: %u", "b_max", ntohs(px->rp_b_max)); 489 rfb_printf(c, level, "%20s: %u", "r_shift", px->rp_r_shift); 490 rfb_printf(c, level, "%20s: %u", "g_shift", px->rp_g_shift); 491 rfb_printf(c, level, "%20s: %u", "b_shift", px->rp_b_shift); |
348} 349 | 492} 493 |
494static bool 495rfb_recv_set_pixel_format(rfb_client_t *c) 496{ 497 rfb_cs_pixfmt_msg_t msg; 498 rfb_pixfmt_t *newpx = &msg.rp_pixfmt; 499 rfb_pixfmt_t *oldpx = &c->rc_sinfo.rsi_pixfmt; 500 rfb_pixfmt_t *spx = &c->rc_s->rs_pixfmt; |
|
350 | 501 |
351static void 352rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd) | 502 rfb_printf(c, RFB_LOGDEBUG, "received pixel format"); 503 504 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg)) 505 return (false); 506 507 /* 508 * The client has sent its desired pixel format. The protocol does not 509 * have a mechanism to reject this, we are supposed to just start using 510 * the requested format from the next update. 511 * 512 * At present, we can only support alternative rgb-shift values and 513 * will accept (and ignore) a new depth value. 514 */ 515 516 if (oldpx->rp_bpp != newpx->rp_bpp || 517 oldpx->rp_bigendian != newpx->rp_bigendian || 518 oldpx->rp_truecolour != newpx->rp_truecolour || 519 oldpx->rp_r_max != newpx->rp_r_max || 520 oldpx->rp_g_max != newpx->rp_g_max || 521 oldpx->rp_b_max != newpx->rp_b_max) { 522 rfb_printf(c, RFB_LOGWARN, "unsupported pixfmt from client"); 523 rfb_print_pixfmt(c, newpx, RFB_LOGWARN); 524 return (false); 525 } 526 527 rfb_print_pixfmt(c, newpx, RFB_LOGDEBUG); 528 529 /* Check if the new shifts match the server's native values. */ 530 if (newpx->rp_r_shift != spx->rp_r_shift || 531 newpx->rp_g_shift != spx->rp_g_shift || 532 newpx->rp_b_shift != spx->rp_b_shift) { 533 c->rc_custom_pixfmt = true; 534 rfb_printf(c, RFB_LOGDEBUG, "Using custom pixfmt"); 535 } else { 536 c->rc_custom_pixfmt = false; 537 rfb_printf(c, RFB_LOGDEBUG, "Using native pixfmt"); 538 } 539 540 c->rc_sinfo.rsi_pixfmt = msg.rp_pixfmt; 541 c->rc_crc_reset = true; 542 543 return (true); 544} 545 546static bool 547rfb_recv_set_encodings(rfb_client_t *c) |
353{ | 548{ |
354 struct rfb_enc_msg enc_msg; 355 int i; 356 uint32_t encoding; | 549 rfb_cs_encodings_msg_t msg; |
357 | 550 |
358 (void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1); | 551 rfb_printf(c, RFB_LOGDEBUG, "received encodings"); |
359 | 552 |
360 for (i = 0; i < htons(enc_msg.numencs); i++) { 361 (void)stream_read(cfd, &encoding, sizeof(encoding)); 362 switch (htonl(encoding)) { 363 case RFB_ENCODING_RAW: 364 rc->enc_raw_ok = true; | 553 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg)) 554 return (false); 555 556 msg.re_numencs = htons(msg.re_numencs); 557 558 rfb_printf(c, RFB_LOGDEBUG, "%d values", msg.re_numencs); 559 560 for (uint_t i = 0; i < msg.re_numencs; i++) { 561 uint32_t enc; 562 563 if (stream_read(c->rc_fd, &enc, sizeof (enc)) != sizeof (enc)) 564 return (false); 565 566 enc = htonl(enc); 567 568 switch (enc) { 569 case RFBP_ENCODING_RAW: 570 rfb_printf(c, RFB_LOGDEBUG, 571 "client supports raw encoding"); 572 c->rc_encodings |= RFB_ENCODING_RAW; |
365 break; | 573 break; |
366 case RFB_ENCODING_ZLIB: 367 if (!rc->enc_zlib_ok) { 368 deflateInit(&rc->zstream, Z_BEST_SPEED); 369 rc->enc_zlib_ok = true; | 574 case RFBP_ENCODING_ZLIB: 575 rfb_printf(c, RFB_LOGDEBUG, 576 "client supports zlib encoding"); 577 if (!(c->rc_encodings & RFB_ENCODING_ZLIB)) { 578 if (deflateInit(&c->rc_zstream, Z_BEST_SPEED) 579 != Z_OK) { 580 return (false); 581 } 582 c->rc_encodings |= RFB_ENCODING_ZLIB; |
370 } 371 break; | 583 } 584 break; |
372 case RFB_ENCODING_RESIZE: 373 rc->enc_resize_ok = true; | 585 case RFBP_ENCODING_RESIZE: 586 rfb_printf(c, RFB_LOGDEBUG, "client supports resize"); 587 c->rc_encodings |= RFB_ENCODING_RESIZE; |
374 break; | 588 break; |
375 case RFB_ENCODING_EXT_KEYEVENT: 376 rc->enc_extkeyevent_ok = true; | 589 case RFBP_ENCODING_EXT_KEVENT: 590 rfb_printf(c, RFB_LOGDEBUG, 591 "client supports ext key event"); 592 c->rc_encodings |= RFB_ENCODING_EXT_KEVENT; |
377 break; | 593 break; |
594 case RFBP_ENCODING_DESKTOP_NAME: 595 rfb_printf(c, RFB_LOGDEBUG, 596 "client supports desktop name"); 597 c->rc_encodings |= RFB_ENCODING_DESKTOP_NAME; 598 break; 599 default: 600 rfb_printf(c, RFB_LOGDEBUG, 601 "client supports encoding %d", (int32_t)enc); |
|
378 } 379 } | 602 } 603 } |
604 605 return (true); |
|
380} 381 | 606} 607 |
382/* 383 * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only 384 */ 385static __inline uint32_t 386fast_crc32(void *buf, int len, uint32_t crcval) | 608static bool 609rfb_recv_update(rfb_client_t *c) |
387{ | 610{ |
388 uint32_t q = len / sizeof(uint32_t); 389 uint32_t *p = (uint32_t *)buf; | 611 rfb_cs_update_msg_t msg; |
390 | 612 |
391 while (q--) { 392 asm volatile ( 393 ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" 394 :"=S" (crcval) 395 :"0" (crcval), "c" (*p) 396 ); 397 p++; | 613 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg)) 614 return (false); 615 616 if (!c->rc_keyevent_sent && 617 (c->rc_encodings & RFB_ENCODING_EXT_KEVENT)) { 618 /* 619 * Take this opportunity to tell the client that we 620 * accept QEMU Extended Key Event Pseudo-encoding. 621 */ 622 c->rc_keyevent_sent = true; 623 rfb_send_extended_keyevent_update_msg(c); |
398 } 399 | 624 } 625 |
400 return (crcval); | 626 c->rc_pending = true; 627 if (msg.rum_incremental == 0) { 628 rfb_printf(c, RFB_LOGDEBUG, 629 "client requested full screen update"); 630 c->rc_send_fullscreen = true; 631 } 632 633 return (true); |
401} 402 | 634} 635 |
403static int 404rfb_send_update_header(struct rfb_softc *rc, int cfd, int numrects) | 636static bool 637rfb_recv_key_event(rfb_client_t *c) |
405{ | 638{ |
406 struct rfb_srvr_updt_msg supdt_msg; | 639 rfb_cs_key_event_msg_t msg; |
407 | 640 |
408 supdt_msg.type = 0; 409 supdt_msg.pad = 0; 410 supdt_msg.numrects = htons(numrects); | 641 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg)) 642 return (false); |
411 | 643 |
412 return stream_write(cfd, &supdt_msg, 413 sizeof(struct rfb_srvr_updt_msg)); | 644 msg.rke_sym = htonl(msg.rke_sym); 645 646 rfb_printf(c, RFB_LOGDEBUG, "received key %s %x", 647 msg.rke_down == 0 ? "up" : "down", msg.rke_sym); 648 649 console_key_event(msg.rke_down, msg.rke_sym, htonl(0)); 650 c->rc_input_detected = true; 651 652 return (true); |
414} 415 | 653} 654 |
416static int 417rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc, 418 int x, int y, int w, int h) | 655static bool 656rfb_recv_pointer_event(rfb_client_t *c) |
419{ | 657{ |
420 struct rfb_srvr_rect_hdr srect_hdr; | 658 rfb_cs_pointer_event_msg_t msg; 659 660 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg)) 661 return (false); 662 663 msg.rpe_x = htons(msg.rpe_x); 664 msg.rpe_y = htons(msg.rpe_y); 665 666 if (rfb_debug > 1) { 667 rfb_printf(c, RFB_LOGDEBUG, "received pointer event @ %dx%d", 668 msg.rpe_x, msg.rpe_y); 669 } 670 671 console_ptr_event(msg.rpe_button, msg.rpe_x, msg.rpe_y); 672 c->rc_input_detected = true; 673 674 return (true); 675} 676 677static bool 678rfb_recv_cut_text(rfb_client_t *c) 679{ 680 rfb_cs_cut_text_msg_t msg; 681 unsigned char buf[32]; 682 683 rfb_printf(c, RFB_LOGDEBUG, "received cut text event"); 684 685 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg)) 686 return (false); 687 688 msg.rct_length = htonl(msg.rct_length); 689 rfb_printf(c, RFB_LOGDEBUG, "%u bytes in buffer", msg.rct_length); 690 /* Consume the buffer */ 691 while (msg.rct_length > 0) { 692 ssize_t l; 693 694 l = stream_read(c->rc_fd, buf, 695 MIN(sizeof (buf), msg.rct_length)); 696 if (l <= 0) 697 return (false); 698 msg.rct_length -= l; 699 } 700 701 return (true); 702} 703 704static bool 705rfb_recv_qemu(rfb_client_t *c) 706{ 707 rfb_cs_qemu_msg_t msg; 708 709 rfb_printf(c, RFB_LOGDEBUG, "received QEMU event"); 710 711 if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg)) 712 return (false); 713 714 switch (msg.rq_subtype) { 715 case RFBP_CS_QEMU_KEVENT: { 716 rfb_cs_qemu_extended_key_msg_t keymsg; 717 718 if (stream_read(c->rc_fd, &keymsg, sizeof (keymsg)) != 719 sizeof (keymsg)) { 720 return (false); 721 } 722 723 keymsg.rqek_sym = htonl(keymsg.rqek_sym); 724 keymsg.rqek_code = htonl(keymsg.rqek_code); 725 726 rfb_printf(c, RFB_LOGDEBUG, "QEMU key %s %x / %x", 727 keymsg.rqek_down == 0 ? "up" : "down", 728 keymsg.rqek_sym, keymsg.rqek_code); 729 730 console_key_event((int)keymsg.rqek_down, keymsg.rqek_sym, 731 keymsg.rqek_code); 732 c->rc_input_detected = true; 733 break; 734 } 735 default: 736 rfb_printf(c, RFB_LOGWARN, "Unknown QEMU event subtype: %d\n", 737 msg.rq_subtype); 738 return (false); 739 } 740 741 return (true); 742} 743 744static bool 745rfb_send_update_header(rfb_client_t *c, int numrects) 746{ 747 rfb_server_update_msg_t msg; 748 749 msg.rss_type = RFBP_SC_UPDATE; 750 msg.rss_pad = 0; 751 msg.rss_numrects = htons(numrects); 752 753 return (stream_write(c->rc_fd, &msg, sizeof (msg)) == sizeof (msg)); 754} 755 756static void 757rfb_send_resize_update_msg(rfb_client_t *c) 758{ 759 rfb_rect_hdr_t rect; 760 761 rfb_printf(c, RFB_LOGDEBUG, "sending screen resize %dx%d", 762 c->rc_width, c->rc_height); 763 764 (void) rfb_send_update_header(c, 1); 765 766 rect.rr_x = htons(0); 767 rect.rr_y = htons(0); 768 rect.rr_width = htons(c->rc_width); 769 rect.rr_height = htons(c->rc_height); 770 rect.rr_encoding = htonl(RFBP_ENCODING_RESIZE); 771 772 (void) stream_write(c->rc_fd, &rect, sizeof (rect)); 773} 774 775static void 776rfb_send_extended_keyevent_update_msg(rfb_client_t *c) 777{ 778 rfb_rect_hdr_t rect; 779 780 rfb_printf(c, RFB_LOGDEBUG, "sending extended keyevent update message"); 781 782 (void) rfb_send_update_header(c, 1); 783 784 rect.rr_x = htons(0); 785 rect.rr_y = htons(0); 786 rect.rr_width = htons(c->rc_width); 787 rect.rr_height = htons(c->rc_height); 788 rect.rr_encoding = htonl(RFBP_ENCODING_EXT_KEVENT); 789 790 (void) stream_write(c->rc_fd, &rect, sizeof (rect)); 791} 792 793static void 794translate_pixels(rfb_client_t *c, struct bhyvegc_image *gci, 795 int x1, int y1, int x2, int y2) 796{ 797 rfb_pixfmt_t *px = &c->rc_sinfo.rsi_pixfmt; 798 rfb_pixfmt_t *spx = &c->rc_s->rs_pixfmt; 799 int w, h; 800 801 w = gci->width; 802 h = gci->height; 803 VERIFY3S(gci->width, ==, c->rc_gci.width); 804 VERIFY3S(gci->height, ==, c->rc_gci.height); 805 806 for (uint_t y = y1; y < h && y < y2; y++) { 807 for (uint_t x = x1; x < w && x < x2; x++) { 808 uint32_t p; 809 810 p = gci->data[y * w + x]; 811 c->rc_gci.data[y * w + x] = 812 0xff000000 | 813 ((p >> spx->rp_r_shift) & 0xff) << px->rp_r_shift | 814 ((p >> spx->rp_g_shift) & 0xff) << px->rp_g_shift | 815 ((p >> spx->rp_b_shift) & 0xff) << px->rp_b_shift; 816 } 817 } 818} 819 820static bool 821rfb_send_rect(rfb_client_t *c, struct bhyvegc_image *gci, 822 int x, int y, int w, int h) 823{ 824 rfb_rect_hdr_t rect; |
421 unsigned long zlen; 422 ssize_t nwrite, total; 423 int err; 424 uint32_t *p; 425 uint8_t *zbufp; 426 | 825 unsigned long zlen; 826 ssize_t nwrite, total; 827 int err; 828 uint32_t *p; 829 uint8_t *zbufp; 830 |
427 /* 428 * Send a single rectangle of the given x, y, w h dimensions. 429 */ | 831 if (rfb_debug > 1) { 832 rfb_printf(c, RFB_LOGDEBUG, "send rect %dx%d %dx%d", 833 x, y, w, h); 834 } |
430 | 835 |
431 /* Rectangle header */ 432 srect_hdr.x = htons(x); 433 srect_hdr.y = htons(y); 434 srect_hdr.width = htons(w); 435 srect_hdr.height = htons(h); | 836 /* Rectangle header. */ 837 rect.rr_x = htons(x); 838 rect.rr_y = htons(y); 839 rect.rr_width = htons(w); 840 rect.rr_height = htons(h); |
436 | 841 |
842 uint32_t *data = gci->data; 843 if (c->rc_custom_pixfmt) { 844 translate_pixels(c, gci, x, y, x + w, y + h); 845 data = c->rc_gci.data; 846 } 847 |
|
437 h = y + h; | 848 h = y + h; |
438 w *= sizeof(uint32_t); 439 if (rc->enc_zlib_ok) { 440 zbufp = rc->zbuf; 441 rc->zstream.total_in = 0; 442 rc->zstream.total_out = 0; 443 for (p = &gc->data[y * gc->width + x]; y < h; y++) { 444 rc->zstream.next_in = (Bytef *)p; 445 rc->zstream.avail_in = w; 446 rc->zstream.next_out = (Bytef *)zbufp; 447 rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16 - 448 rc->zstream.total_out; 449 rc->zstream.data_type = Z_BINARY; | 849 w *= sizeof (uint32_t); |
450 | 850 |
451 /* Compress with zlib */ 452 err = deflate(&rc->zstream, Z_SYNC_FLUSH); | 851 if (c->rc_encodings & RFB_ENCODING_ZLIB) { 852 zbufp = c->rc_zbuf; 853 c->rc_zstream.total_in = 0; 854 c->rc_zstream.total_out = 0; 855 for (p = &data[y * gci->width + x]; y < h; y++) { 856 c->rc_zstream.next_in = (Bytef *)p; 857 c->rc_zstream.avail_in = w; 858 c->rc_zstream.next_out = (Bytef *)zbufp; 859 c->rc_zstream.avail_out = RFB_ZLIB_BUFSZ + 16 - 860 c->rc_zstream.total_out; 861 c->rc_zstream.data_type = Z_BINARY; 862 863 /* Compress with zlib. */ 864 err = deflate(&c->rc_zstream, Z_SYNC_FLUSH); |
453 if (err != Z_OK) { | 865 if (err != Z_OK) { |
454 WPRINTF(("zlib[rect] deflate err: %d", err)); 455 rc->enc_zlib_ok = false; 456 deflateEnd(&rc->zstream); | 866 rfb_printf(c, RFB_LOGWARN, 867 "zlib[rect] deflate err: %d", err); |
457 goto doraw; 458 } | 868 goto doraw; 869 } |
459 zbufp = rc->zbuf + rc->zstream.total_out; 460 p += gc->width; | 870 zbufp = c->rc_zbuf + c->rc_zstream.total_out; 871 p += gci->width; |
461 } | 872 } |
462 srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB); 463 nwrite = stream_write(cfd, &srect_hdr, 464 sizeof(struct rfb_srvr_rect_hdr)); | 873 rect.rr_encoding = htonl(RFBP_ENCODING_ZLIB); 874 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect)); |
465 if (nwrite <= 0) | 875 if (nwrite <= 0) |
466 return (nwrite); | 876 return (false); |
467 | 877 |
468 zlen = htonl(rc->zstream.total_out); 469 nwrite = stream_write(cfd, &zlen, sizeof(uint32_t)); | 878 zlen = htonl(c->rc_zstream.total_out); 879 nwrite = stream_write(c->rc_fd, &zlen, sizeof (uint32_t)); |
470 if (nwrite <= 0) | 880 if (nwrite <= 0) |
471 return (nwrite); 472 return (stream_write(cfd, rc->zbuf, rc->zstream.total_out)); | 881 return (false); 882 return (stream_write(c->rc_fd, c->rc_zbuf, 883 c->rc_zstream.total_out) == c->rc_zstream.total_out); |
473 } 474 475doraw: 476 477 total = 0; | 884 } 885 886doraw: 887 888 total = 0; |
478 zbufp = rc->zbuf; 479 for (p = &gc->data[y * gc->width + x]; y < h; y++) { | 889 zbufp = c->rc_zbuf; 890 for (p = &data[y * gci->width + x]; y < h; y++) { |
480 memcpy(zbufp, p, w); 481 zbufp += w; 482 total += w; | 891 memcpy(zbufp, p, w); 892 zbufp += w; 893 total += w; |
483 p += gc->width; | 894 p += gci->width; |
484 } 485 | 895 } 896 |
486 srect_hdr.encoding = htonl(RFB_ENCODING_RAW); 487 nwrite = stream_write(cfd, &srect_hdr, 488 sizeof(struct rfb_srvr_rect_hdr)); | 897 rect.rr_encoding = htonl(RFBP_ENCODING_RAW); 898 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect)); |
489 if (nwrite <= 0) | 899 if (nwrite <= 0) |
490 return (nwrite); | 900 return (false); |
491 | 901 |
492 total = stream_write(cfd, rc->zbuf, total); 493 494 return (total); | 902 return (stream_write(c->rc_fd, c->rc_zbuf, total) == total); |
495} 496 | 903} 904 |
497static int 498rfb_send_all(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc) | 905 906static bool 907rfb_send_all(rfb_client_t *c, struct bhyvegc_image *gci) |
499{ | 908{ |
500 struct rfb_srvr_updt_msg supdt_msg; 501 struct rfb_srvr_rect_hdr srect_hdr; | 909 rfb_rect_hdr_t rect; |
502 ssize_t nwrite; 503 unsigned long zlen; 504 int err; 505 | 910 ssize_t nwrite; 911 unsigned long zlen; 912 int err; 913 |
506 /* 507 * Send the whole thing 508 */ | 914 rfb_printf(c, RFB_LOGDEBUG, "send entire screen"); |
509 | 915 |
510 /* Number of rectangles: 1 */ 511 supdt_msg.type = 0; 512 supdt_msg.pad = 0; 513 supdt_msg.numrects = htons(1); 514 nwrite = stream_write(cfd, &supdt_msg, 515 sizeof(struct rfb_srvr_updt_msg)); 516 if (nwrite <= 0) 517 return (nwrite); | 916 /* Just the one (big) rect. */ 917 if (!rfb_send_update_header(c, 1)) 918 return (false); |
518 | 919 |
519 /* Rectangle header */ 520 srect_hdr.x = 0; 521 srect_hdr.y = 0; 522 srect_hdr.width = htons(gc->width); 523 srect_hdr.height = htons(gc->height); 524 if (rc->enc_zlib_ok) { 525 rc->zstream.next_in = (Bytef *)gc->data; 526 rc->zstream.avail_in = gc->width * gc->height * 527 sizeof(uint32_t); 528 rc->zstream.next_out = (Bytef *)rc->zbuf; 529 rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16; 530 rc->zstream.data_type = Z_BINARY; | 920 rect.rr_x = 0; 921 rect.rr_y = 0; 922 rect.rr_width = htons(gci->width); 923 rect.rr_height = htons(gci->height); |
531 | 924 |
532 rc->zstream.total_in = 0; 533 rc->zstream.total_out = 0; | 925 uint32_t *data = gci->data; 926 if (c->rc_custom_pixfmt) { 927 translate_pixels(c, gci, 0, 0, gci->width, gci->height); 928 data = c->rc_gci.data; 929 } |
534 | 930 |
535 /* Compress with zlib */ 536 err = deflate(&rc->zstream, Z_SYNC_FLUSH); | 931 if (c->rc_encodings & RFB_ENCODING_ZLIB) { 932 c->rc_zstream.next_in = (Bytef *)data; 933 c->rc_zstream.avail_in = gci->width * gci->height * 934 sizeof (uint32_t); 935 c->rc_zstream.next_out = (Bytef *)c->rc_zbuf; 936 c->rc_zstream.avail_out = RFB_ZLIB_BUFSZ + 16; 937 c->rc_zstream.data_type = Z_BINARY; 938 939 c->rc_zstream.total_in = 0; 940 c->rc_zstream.total_out = 0; 941 942 /* Compress with zlib. */ 943 err = deflate(&c->rc_zstream, Z_SYNC_FLUSH); |
537 if (err != Z_OK) { | 944 if (err != Z_OK) { |
538 WPRINTF(("zlib deflate err: %d", err)); 539 rc->enc_zlib_ok = false; 540 deflateEnd(&rc->zstream); | 945 rfb_printf(c, RFB_LOGWARN, "zlib deflate err: %d", err); |
541 goto doraw; 542 } 543 | 946 goto doraw; 947 } 948 |
544 srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB); 545 nwrite = stream_write(cfd, &srect_hdr, 546 sizeof(struct rfb_srvr_rect_hdr)); | 949 rect.rr_encoding = htonl(RFBP_ENCODING_ZLIB); 950 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect)); |
547 if (nwrite <= 0) | 951 if (nwrite <= 0) |
548 return (nwrite); | 952 return (false); |
549 | 953 |
550 zlen = htonl(rc->zstream.total_out); 551 nwrite = stream_write(cfd, &zlen, sizeof(uint32_t)); | 954 zlen = htonl(c->rc_zstream.total_out); 955 nwrite = stream_write(c->rc_fd, &zlen, sizeof (uint32_t)); |
552 if (nwrite <= 0) | 956 if (nwrite <= 0) |
553 return (nwrite); 554 return (stream_write(cfd, rc->zbuf, rc->zstream.total_out)); | 957 return (false); 958 return (stream_write(c->rc_fd, c->rc_zbuf, 959 c->rc_zstream.total_out) == c->rc_zstream.total_out); |
555 } 556 557doraw: | 960 } 961 962doraw: |
558 srect_hdr.encoding = htonl(RFB_ENCODING_RAW); 559 nwrite = stream_write(cfd, &srect_hdr, 560 sizeof(struct rfb_srvr_rect_hdr)); | 963 rect.rr_encoding = htonl(RFBP_ENCODING_RAW); 964 nwrite = stream_write(c->rc_fd, &rect, sizeof (rect)); |
561 if (nwrite <= 0) | 965 if (nwrite <= 0) |
562 return (nwrite); | 966 return (false); |
563 | 967 |
564 nwrite = stream_write(cfd, gc->data, 565 gc->width * gc->height * sizeof(uint32_t)); 566 567 return (nwrite); | 968 nwrite = gci->width * gci->height * sizeof (uint32_t); 969 return (stream_write(c->rc_fd, data, nwrite) == nwrite); |
568} 569 | 970} 971 |
570#define PIX_PER_CELL 32 571#define PIXCELL_SHIFT 5 572#define PIXCELL_MASK 0x1F 573 574static int 575rfb_send_screen(struct rfb_softc *rc, int cfd) | 972static bool 973rfb_send_screen(rfb_client_t *c) |
576{ | 974{ |
577 struct bhyvegc_image *gc_image; 578 ssize_t nwrite; 579 int x, y; 580 int celly, cellwidth; | 975 struct bhyvegc_image *gci; 976 bool retval = true; 977 bool sendall = false; |
581 int xcells, ycells; | 978 int xcells, ycells; |
582 int w, h; 583 uint32_t *p; 584 int rem_x, rem_y; /* remainder for resolutions not x32 pixels ratio */ 585 int retval; 586 uint32_t *crc_p, *orig_crc; 587 int changes; 588 bool expected; | 979 int rem_x, rem_y; 980 uint32_t *p, *ncrc, *ocrc; 981 uint_t changes, perc, x, y; |
589 | 982 |
590 /* Return if another thread sending */ 591 expected = false; 592 if (atomic_compare_exchange_strong(&rc->sending, &expected, true) == false) 593 return (1); | 983 /* Updates require a preceding client update request. */ 984 if (atomic_exchange(&c->rc_pending, false) == false) 985 return (true); |
594 | 986 |
595 retval = 1; | 987 console_refresh(); 988 gci = console_get_image(); |
596 | 989 |
597 /* Updates require a preceding update request */ 598 if (atomic_exchange(&rc->pending, false) == false) 599 goto done; | 990 /* 991 * It's helpful if the image size or data address does not change 992 * underneath us. 993 */ 994 pthread_mutex_lock(&gci->mtx); |
600 | 995 |
601 console_refresh(); 602 gc_image = console_get_image(); | 996 /* Check for screen resolution changes. */ 997 if (c->rc_width != gci->width || 998 c->rc_height != gci->height) { 999 c->rc_width = gci->width; 1000 c->rc_height = gci->height; 1001 c->rc_crc_reset = true; 1002 c->rc_send_fullscreen = true; |
603 | 1003 |
604 /* Clear old CRC values when the size changes */ 605 if (rc->crc_width != gc_image->width || 606 rc->crc_height != gc_image->height) { 607 memset(rc->crc, 0, sizeof(uint32_t) * 608 howmany(RFB_MAX_WIDTH, PIX_PER_CELL) * 609 howmany(RFB_MAX_HEIGHT, PIX_PER_CELL)); 610 rc->crc_width = gc_image->width; 611 rc->crc_height = gc_image->height; | 1004 /* If the client supports it, send a resize event. */ 1005 if (c->rc_encodings & RFB_ENCODING_RESIZE) { 1006 rfb_send_resize_update_msg(c); 1007 /* 1008 * A resize message counts as an update in response to 1009 * the client's preceding request so rc->pending does 1010 * not need to be reset here. 1011 */ 1012 goto done; 1013 } |
612 } 613 | 1014 } 1015 |
614 /* A size update counts as an update in itself */ 615 if (rc->width != gc_image->width || 616 rc->height != gc_image->height) { 617 rc->width = gc_image->width; 618 rc->height = gc_image->height; 619 if (rc->enc_resize_ok) { 620 rfb_send_resize_update_msg(rc, cfd); 621 rc->update_all = true; | 1016 /* Clear old CRC values. */ 1017 if (atomic_exchange(&c->rc_crc_reset, false)) 1018 memset(c->rc_crc, '\0', c->rc_cells * sizeof (uint32_t)); 1019 1020 if (c->rc_custom_pixfmt && (c->rc_gci.data == NULL || 1021 c->rc_gci.width != c->rc_width || 1022 c->rc_gci.height != c->rc_height)) { 1023 c->rc_gci.data = reallocarray(c->rc_gci.data, 1024 c->rc_width * c->rc_height, sizeof (uint32_t)); 1025 if (c->rc_gci.data == NULL) { 1026 retval = false; |
622 goto done; 623 } | 1027 goto done; 1028 } |
1029 c->rc_gci.width = c->rc_width; 1030 c->rc_gci.height = c->rc_height; 1031 } else if (!c->rc_custom_pixfmt && c->rc_gci.data != NULL) { 1032 free(c->rc_gci.data); 1033 c->rc_gci.data = NULL; |
|
624 } 625 | 1034 } 1035 |
626 if (atomic_exchange(&rc->update_all, false) == true) { 627 retval = rfb_send_all(rc, cfd, gc_image); 628 goto done; 629 } | 1036 sendall = atomic_exchange(&c->rc_send_fullscreen, false); |
630 631 /* | 1037 1038 /* |
632 * Calculate the checksum for each 32x32 cell. Send each that 633 * has changed since the last scan. | 1039 * Calculate a checksum for each 32x32 cell. Send all that have 1040 * changed since the last scan. |
634 */ 635 | 1041 */ 1042 |
636 w = rc->crc_width; 637 h = rc->crc_height; 638 xcells = howmany(rc->crc_width, PIX_PER_CELL); 639 ycells = howmany(rc->crc_height, PIX_PER_CELL); | 1043 xcells = howmany(gci->width, RFB_PIX_PER_CELL); 1044 ycells = howmany(gci->height, RFB_PIX_PER_CELL); 1045 rem_x = gci->width & RFB_PIXCELL_MASK; 1046 rem_y = gci->height & RFB_PIXCELL_MASK; 1047 if (rem_y == 0) 1048 rem_y = RFB_PIX_PER_CELL; |
640 | 1049 |
641 rem_x = w & PIXCELL_MASK; | 1050 p = gci->data; |
642 | 1051 |
643 rem_y = h & PIXCELL_MASK; 644 if (!rem_y) 645 rem_y = PIX_PER_CELL; 646 647 p = gc_image->data; 648 649 /* 650 * Go through all cells and calculate crc. If significant number 651 * of changes, then send entire screen. 652 * crc_tmp is dual purpose: to store the new crc and to flag as 653 * a cell that has changed. 654 */ 655 crc_p = rc->crc_tmp - xcells; 656 orig_crc = rc->crc - xcells; | 1052 ncrc = c->rc_crc_tmp - xcells; 1053 ocrc = c->rc_crc - xcells; |
657 changes = 0; | 1054 changes = 0; |
658 memset(rc->crc_tmp, 0, sizeof(uint32_t) * xcells * ycells); 659 for (y = 0; y < h; y++) { 660 if ((y & PIXCELL_MASK) == 0) { 661 crc_p += xcells; 662 orig_crc += xcells; | 1055 memset(c->rc_crc_tmp, '\0', sizeof (uint32_t) * xcells * ycells); 1056 for (y = 0; y < gci->height; y++) { 1057 if ((y & RFB_PIXCELL_MASK) == 0) { 1058 ncrc += xcells; 1059 ocrc += xcells; |
663 } 664 665 for (x = 0; x < xcells; x++) { | 1060 } 1061 1062 for (x = 0; x < xcells; x++) { |
666 if (x == (xcells - 1) && rem_x > 0) | 1063 uint_t cellwidth; 1064 1065 if (x == xcells - 1 && rem_x > 0) |
667 cellwidth = rem_x; 668 else | 1066 cellwidth = rem_x; 1067 else |
669 cellwidth = PIX_PER_CELL; | 1068 cellwidth = RFB_PIX_PER_CELL; |
670 | 1069 |
671 if (rc->hw_crc) 672 crc_p[x] = fast_crc32(p, 673 cellwidth * sizeof(uint32_t), 674 crc_p[x]); 675 else 676 crc_p[x] = (uint32_t)crc32(crc_p[x], 677 (Bytef *)p, 678 cellwidth * sizeof(uint32_t)); | 1070 if (rfb_sse42) { 1071 ncrc[x] = fast_crc32(p, 1072 cellwidth * sizeof (uint32_t), ncrc[x]); 1073 } else { 1074 ncrc[x] = (uint32_t)crc32(ncrc[x], 1075 (Bytef *)p, cellwidth * sizeof (uint32_t)); 1076 } |
679 680 p += cellwidth; 681 | 1077 1078 p += cellwidth; 1079 |
682 /* check for crc delta if last row in cell */ 683 if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) { 684 if (orig_crc[x] != crc_p[x]) { 685 orig_crc[x] = crc_p[x]; 686 crc_p[x] = 1; | 1080 /* check for crc delta if last row in cell. */ 1081 if ((y & RFB_PIXCELL_MASK) == RFB_PIXCELL_MASK || 1082 y == gci->height - 1) { 1083 if (ocrc[x] != ncrc[x]) { 1084 ocrc[x] = ncrc[x]; 1085 ncrc[x] = 1; |
687 changes++; 688 } else { | 1086 changes++; 1087 } else { |
689 crc_p[x] = 0; | 1088 ncrc[x] = 0; |
690 } 691 } 692 } 693 } 694 | 1089 } 1090 } 1091 } 1092 } 1093 |
695 /* 696 * We only send the update if there are changes. 697 * Restore the pending flag since it was unconditionally cleared 698 * above. 699 */ 700 if (!changes) { 701 rc->pending = true; | 1094 perc = (changes * 100) / (xcells * ycells); 1095 if (rfb_debug > 1 && changes > 0) { 1096 rfb_printf(c, RFB_LOGDEBUG, 1097 "scanned and found %u changed cell(s) - %u%%", 1098 changes, perc); 1099 } 1100 1101 /* 1102 * If there are no changes, don't send an update. Restore the pending 1103 * flag since we still owe the client an update. 1104 */ 1105 if (!sendall && !changes) { 1106 c->rc_pending = true; |
702 goto done; 703 } 704 | 1107 goto done; 1108 } 1109 |
705 /* If number of changes is > THRESH percent, send the whole screen */ 706 if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) { 707 retval = rfb_send_all(rc, cfd, gc_image); | 1110 /* If there are a lot of changes, send the whole screen. */ 1111 if (perc >= RFB_SENDALL_THRESH) 1112 sendall = true; 1113 1114 if (sendall) { 1115 retval = rfb_send_all(c, gci); |
708 goto done; 709 } 710 | 1116 goto done; 1117 } 1118 |
711 rfb_send_update_header(rc, cfd, changes); | 1119 if (!rfb_send_update_header(c, changes)) { 1120 retval = false; 1121 goto done; 1122 } |
712 | 1123 |
713 /* Go through all cells, and send only changed ones */ 714 crc_p = rc->crc_tmp; 715 for (y = 0; y < h; y += PIX_PER_CELL) { 716 /* previous cell's row */ 717 celly = (y >> PIXCELL_SHIFT); | 1124 /* Send the changed cells as separate rects. */ 1125 ncrc = c->rc_crc_tmp; 1126 for (y = 0; y < gci->height; y += RFB_PIX_PER_CELL) { 1127 /* Previous cell's row. */ 1128 int celly = (y >> RFB_PIXCELL_SHIFT); |
718 | 1129 |
719 /* Delta check crc to previous set */ | 1130 /* Delta check crc to previous set. */ |
720 for (x = 0; x < xcells; x++) { | 1131 for (x = 0; x < xcells; x++) { |
721 if (*crc_p++ == 0) | 1132 uint_t cellwidth; 1133 1134 if (*ncrc++ == 0) |
722 continue; 723 | 1135 continue; 1136 |
724 if (x == (xcells - 1) && rem_x > 0) | 1137 if (x == xcells - 1 && rem_x > 0) |
725 cellwidth = rem_x; 726 else | 1138 cellwidth = rem_x; 1139 else |
727 cellwidth = PIX_PER_CELL; 728 nwrite = rfb_send_rect(rc, cfd, 729 gc_image, 730 x * PIX_PER_CELL, 731 celly * PIX_PER_CELL, 732 cellwidth, 733 y + PIX_PER_CELL >= h ? rem_y : PIX_PER_CELL); 734 if (nwrite <= 0) { 735 retval = nwrite; | 1140 cellwidth = RFB_PIX_PER_CELL; 1141 1142 if (!rfb_send_rect(c, gci, 1143 x * RFB_PIX_PER_CELL, celly * RFB_PIX_PER_CELL, 1144 cellwidth, y + RFB_PIX_PER_CELL >= gci->height ? 1145 rem_y : RFB_PIX_PER_CELL)) { 1146 retval = false; |
736 goto done; 737 } 738 } 739 } 740 741done: | 1147 goto done; 1148 } 1149 } 1150 } 1151 1152done: |
742 rc->sending = false; | 1153 pthread_mutex_unlock(&gci->mtx); |
743 744 return (retval); 745} 746 | 1154 1155 return (retval); 1156} 1157 |
747 748static void 749rfb_recv_update_msg(struct rfb_softc *rc, int cfd) | 1158static void * 1159rfb_client_rx_thread(void *arg) |
750{ | 1160{ |
751 struct rfb_updt_msg updt_msg; | 1161 rfb_client_t *c = arg; 1162 unsigned char cmd; 1163 bool ret = true; |
752 | 1164 |
753 (void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1); 754 755 if (rc->enc_extkeyevent_ok && (!rc->enc_extkeyevent_send)) { 756 rfb_send_extended_keyevent_update_msg(rc, cfd); 757 rc->enc_extkeyevent_send = true; | 1165 while (ret && !c->rc_closing && (read(c->rc_fd, &cmd, 1) == 1)) { 1166 switch (cmd) { 1167 case RFBP_CS_SET_PIXEL_FORMAT: 1168 ret = rfb_recv_set_pixel_format(c); 1169 break; 1170 case RFBP_CS_SET_ENCODINGS: 1171 ret = rfb_recv_set_encodings(c); 1172 break; 1173 case RFBP_CS_UPDATE_REQUEST: 1174 ret = rfb_recv_update(c); 1175 break; 1176 case RFBP_CS_KEY_EVENT: 1177 ret = rfb_recv_key_event(c); 1178 break; 1179 case RFBP_CS_POINTER_EVENT: 1180 ret = rfb_recv_pointer_event(c); 1181 break; 1182 case RFBP_CS_CUT_TEXT: 1183 ret = rfb_recv_cut_text(c); 1184 break; 1185 case RFBP_CS_QEMU: 1186 ret = rfb_recv_qemu(c); 1187 break; 1188 default: 1189 rfb_printf(c, RFB_LOGWARN, "unknown cs code %d", 1190 cmd & 0xff); 1191 ret = false; 1192 } |
758 } 759 | 1193 } 1194 |
760 rc->pending = true; 761 if (!updt_msg.incremental) 762 rc->update_all = true; | 1195 rfb_printf(c, RFB_LOGDEBUG, "client rx thread exiting"); 1196 c->rc_closing = true; 1197 1198 return (NULL); |
763} 764 | 1199} 1200 |
765static void 766rfb_recv_key_msg(struct rfb_softc *rc, int cfd) | 1201static void * 1202rfb_client_tx_thread(void *arg) |
767{ | 1203{ |
768 struct rfb_key_msg key_msg; | 1204 rfb_client_t *c = arg; 1205 rfb_server_t *s = c->rc_s; 1206 char tname[MAXCOMLEN + 1]; 1207 uint_t counter = 0; 1208 hrtime_t tprev; 1209 void *status; 1210 int err; |
769 | 1211 |
770 (void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1); | 1212 (void) snprintf(tname, sizeof (tname), "rfb%u tx", c->rc_instance); 1213 (void) pthread_set_name_np(c->rc_tx_tid, tname); |
771 | 1214 |
772 console_key_event(key_msg.down, htonl(key_msg.sym), htonl(0)); 773 rc->input_detected = true; 774} | 1215 c->rc_sinfo.rsi_pixfmt = c->rc_s->rs_pixfmt; 1216 c->rc_encodings = RFB_ENCODING_RAW; |
775 | 1217 |
776static void 777rfb_recv_client_msg(struct rfb_softc *rc, int cfd) 778{ 779 struct rfb_client_msg client_msg; 780 struct rfb_extended_key_msg extkey_msg; | 1218 if (!rfb_handshake(c)) 1219 goto out; |
781 | 1220 |
782 (void)stream_read(cfd, ((void *)&client_msg) + 1, sizeof(client_msg) - 1); 783 784 if (client_msg.subtype == RFB_CLIENTMSG_EXT_KEYEVENT ) { 785 (void)stream_read(cfd, ((void *)&extkey_msg) + 2, sizeof(extkey_msg) - 2); 786 console_key_event((int)extkey_msg.down, htonl(extkey_msg.sym), htonl(extkey_msg.code)); 787 rc->input_detected = true; | 1221 c->rc_cells = howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, RFB_PIX_PER_CELL); 1222 if ((c->rc_crc = calloc(c->rc_cells, sizeof (uint32_t))) == NULL || 1223 (c->rc_crc_tmp = calloc(c->rc_cells, sizeof (uint32_t))) == NULL) { 1224 perror("calloc crc"); 1225 goto out; |
788 } | 1226 } |
789} | |
790 | 1227 |
791static void 792rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd) 793{ 794 struct rfb_ptr_msg ptr_msg; 795 796 (void)stream_read(cfd, ((void *)&ptr_msg) + 1, sizeof(ptr_msg) - 1); 797 798 console_ptr_event(ptr_msg.button, htons(ptr_msg.x), htons(ptr_msg.y)); 799 rc->input_detected = true; 800} 801 802static void 803rfb_recv_cuttext_msg(struct rfb_softc *rc, int cfd) 804{ 805 struct rfb_cuttext_msg ct_msg; 806 unsigned char buf[32]; 807 int len; 808 809 len = stream_read(cfd, ((void *)&ct_msg) + 1, sizeof(ct_msg) - 1); 810 ct_msg.length = htonl(ct_msg.length); 811 while (ct_msg.length > 0) { 812 len = stream_read(cfd, buf, ct_msg.length > sizeof(buf) ? 813 sizeof(buf) : ct_msg.length); 814 ct_msg.length -= len; | 1228 err = pthread_create(&c->rc_rx_tid, NULL, rfb_client_rx_thread, c); 1229 if (err != 0) { 1230 perror("pthread_create client rx thread"); 1231 goto out; |
815 } | 1232 } |
816} | |
817 | 1233 |
818static int64_t 819timeval_delta(struct timeval *prev, struct timeval *now) 820{ 821 int64_t n1, n2; 822 n1 = now->tv_sec * 1000000 + now->tv_usec; 823 n2 = prev->tv_sec * 1000000 + prev->tv_usec; 824 return (n1 - n2); 825} | 1234 (void) snprintf(tname, sizeof (tname), "rfb%u rx", c->rc_instance); 1235 (void) pthread_set_name_np(c->rc_rx_tid, tname); |
826 | 1236 |
827static void * 828rfb_wr_thr(void *arg) 829{ 830 struct rfb_softc *rc; 831 fd_set rfds; 832 struct timeval tv; 833 struct timeval prev_tv; 834 int64_t tdiff; 835 int cfd; 836 int err; | 1237 tprev = gethrtime(); |
837 | 1238 |
838 rc = arg; 839 cfd = rc->cfd; | 1239 while (!c->rc_closing) { 1240 struct timeval tv; 1241 hrtime_t tnow; 1242 int64_t tdiff; 1243 fd_set rfds; 1244 int err; |
840 | 1245 |
841 prev_tv.tv_sec = 0; 842 prev_tv.tv_usec = 0; 843 while (rc->cfd >= 0) { | |
844 FD_ZERO(&rfds); | 1246 FD_ZERO(&rfds); |
845 FD_SET(cfd, &rfds); | 1247 FD_SET(c->rc_fd, &rfds); |
846 tv.tv_sec = 0; | 1248 tv.tv_sec = 0; |
847 tv.tv_usec = CFD_SEL_DELAY; | 1249 tv.tv_usec = RFB_SEL_DELAY_US; |
848 | 1250 |
849 err = select(cfd+1, &rfds, NULL, NULL, &tv); | 1251 err = select(c->rc_fd + 1, &rfds, NULL, NULL, &tv); |
850 if (err < 0) | 1252 if (err < 0) |
851 return (NULL); | 1253 break; |
852 | 1254 |
853 /* Determine if its time to push screen; ~24hz */ 854 gettimeofday(&tv, NULL); 855 tdiff = timeval_delta(&prev_tv, &tv); 856 if (tdiff >= SCREEN_POLL_DELAY) { | 1255 /* Determine if its time to push the screen; ~24hz. */ 1256 tnow = gethrtime(); 1257 tdiff = NSEC2USEC(tnow - tprev); 1258 if (tdiff >= RFB_SCREEN_POLL_DELAY) { |
857 bool input; | 1259 bool input; |
858 prev_tv.tv_sec = tv.tv_sec; 859 prev_tv.tv_usec = tv.tv_usec; 860 input = atomic_exchange(&rc->input_detected, false); | 1260 1261 tprev = tnow; 1262 1263 input = atomic_exchange(&c->rc_input_detected, false); |
861 /* | 1264 /* |
862 * Refresh the screen on every second trip through the loop, 863 * or if keyboard/mouse input has been detected. | 1265 * Refresh the screen on every second trip through the 1266 * loop, or if keyboard/mouse input has been detected. |
864 */ | 1267 */ |
865 if ((++rc->wrcount & 1) || input) { 866 if (rfb_send_screen(rc, cfd) <= 0) { 867 return (NULL); 868 } | 1268 if ((++counter & 1) != 0 || input) { 1269 if (!rfb_send_screen(c)) 1270 break; |
869 } 870 } else { | 1271 } 1272 } else { |
871 /* sleep */ 872 usleep(SCREEN_POLL_DELAY - tdiff); | 1273 (void) usleep(RFB_SCREEN_POLL_DELAY - tdiff); |
873 } 874 } 875 | 1274 } 1275 } 1276 |
1277 rfb_printf(c, RFB_LOGWARN, "disconnected"); 1278 1279out: 1280 1281 (void) pthread_join(c->rc_rx_tid, &status); 1282 pthread_mutex_lock(&s->rs_clientlock); 1283 s->rs_clientcount--; 1284 list_remove(&s->rs_clients, c); 1285 if (s->rs_exclusive && s->rs_clientcount == 0) 1286 s->rs_exclusive = false; 1287 id_free(rfb_idspace, c->rc_instance); 1288 pthread_mutex_unlock(&s->rs_clientlock); 1289 1290 rfb_free_client(c); |
|
876 return (NULL); 877} 878 | 1291 return (NULL); 1292} 1293 |
879void 880rfb_handle(struct rfb_softc *rc, int cfd) | 1294static void 1295rfb_accept(int sfd, enum ev_type event, void *arg) |
881{ | 1296{ |
882 const char *vbuf = "RFB 003.008\n"; 883 unsigned char buf[80]; 884 unsigned char *message = NULL; | 1297 rfb_server_t *s = arg; 1298 rfb_client_t *c = NULL; 1299 struct sockaddr_storage cliaddr; 1300 socklen_t len; 1301 char host[NI_MAXHOST], port[NI_MAXSERV]; 1302 int cfd, err; 1303 uint_t cc; |
885 | 1304 |
886#ifndef NO_OPENSSL 887 unsigned char challenge[AUTH_LENGTH]; 888 unsigned char keystr[PASSWD_LENGTH]; 889 unsigned char crypt_expected[AUTH_LENGTH]; | 1305 rfb_printf(c, RFB_LOGDEBUG, "incoming connection"); |
890 | 1306 |
891 DES_key_schedule ks; 892 int i; 893#endif 894 uint8_t client_ver; 895 uint8_t auth_type; 896 pthread_t tid; 897 uint32_t sres = 0; 898 int len; 899 int perror = 1; 900 901 rc->cfd = cfd; 902 903 /* 1a. Send server version */ 904 stream_write(cfd, vbuf, strlen(vbuf)); 905 906 /* 1b. Read client version */ 907 len = stream_read(cfd, buf, VERSION_LENGTH); 908#ifdef __FreeBSD__ 909 if (len == VERSION_LENGTH && !strncmp(vbuf, buf, VERSION_LENGTH - 2)) { 910 client_ver = buf[VERSION_LENGTH - 2]; | 1307 len = sizeof (cliaddr); 1308 cfd = accept(sfd, (struct sockaddr *)&cliaddr, &len); 1309 if (cfd == -1) { 1310 perror("client accept"); 1311 return; |
911 } | 1312 } |
912#else 913 /* Work around gcc7 maybe-uninitialized warning */ 914 client_ver = CVERS_3_3; 915 if (len == VERSION_LENGTH && !strncmp(vbuf, (char *)buf, 916 VERSION_LENGTH - 2)) { 917 client_ver = buf[VERSION_LENGTH - 2]; 918 } 919#endif 920 if (client_ver != CVERS_3_8 && client_ver != CVERS_3_7) { 921 /* only recognize 3.3, 3.7 & 3.8. Others dflt to 3.3 */ 922 client_ver = CVERS_3_3; 923 } | |
924 | 1313 |
925 /* 2a. Send security type */ 926 buf[0] = 1; 927 928 /* In versions 3.7 & 3.8, it's 2-way handshake */ 929 /* For version 3.3, server says what the authentication type must be */ 930#ifndef NO_OPENSSL 931 if (rc->password) { 932 auth_type = SECURITY_TYPE_VNC_AUTH; | 1314 *host = *port = '\0'; 1315 if (cliaddr.ss_family == AF_UNIX) { 1316 rfb_printf(NULL, RFB_LOGDEBUG, "connection on UNIX socket"); 1317 (void) strlcpy(host, "<UNIX>", sizeof (host)); |
933 } else { | 1318 } else { |
934 auth_type = SECURITY_TYPE_NONE; | 1319 err = getnameinfo((struct sockaddr *)&cliaddr, len, 1320 host, sizeof (host), port, sizeof (port), 1321 NI_NUMERICHOST | NI_NUMERICSERV); 1322 if (err != 0) { 1323 rfb_printf(NULL, RFB_LOGERR, "getnameinfo: %s", 1324 gai_strerror(err)); 1325 *host = *port = '\0'; 1326 } else { 1327 rfb_printf(NULL, RFB_LOGDEBUG, "connection from %s:%s", 1328 host, port); 1329 } |
935 } | 1330 } |
936#else 937 auth_type = SECURITY_TYPE_NONE; 938#endif | |
939 | 1331 |
940 switch (client_ver) { 941 case CVERS_3_7: 942 case CVERS_3_8: 943 buf[0] = 1; 944 buf[1] = auth_type; 945 stream_write(cfd, buf, 2); | 1332 pthread_mutex_lock(&s->rs_clientlock); 1333 cc = s->rs_clientcount; 1334 pthread_mutex_unlock(&s->rs_clientlock); 1335 if (cc >= RFB_MAX_CLIENTS) { 1336 rfb_printf(NULL, RFB_LOGERR, 1337 "too many clients, closing connection."); 1338 goto fail; 1339 } |
946 | 1340 |
947 /* 2b. Read agreed security type */ 948 len = stream_read(cfd, buf, 1); 949 if (buf[0] != auth_type) { 950 /* deny */ 951 sres = htonl(1); 952#ifdef __FreeBSD__ 953 message = "Auth failed: authentication type mismatch"; 954#else 955 message = (unsigned char *) 956 "Auth failed: authentication type mismatch"; 957#endif 958 goto report_and_done; 959 } 960 break; 961 case CVERS_3_3: 962 default: 963 be32enc(buf, auth_type); 964 stream_write(cfd, buf, 4); 965 break; | 1341 if ((c = calloc(1, sizeof (rfb_client_t))) == NULL) { 1342 perror("calloc client"); 1343 goto fail; |
966 } 967 | 1344 } 1345 |
968 /* 2c. Do VNC authentication */ 969 switch (auth_type) { 970 case SECURITY_TYPE_NONE: 971 break; 972 case SECURITY_TYPE_VNC_AUTH: 973 /* 974 * The client encrypts the challenge with DES, using a password 975 * supplied by the user as the key. 976 * To form the key, the password is truncated to 977 * eight characters, or padded with null bytes on the right. 978 * The client then sends the resulting 16-bytes response. 979 */ 980#ifndef NO_OPENSSL 981#ifdef __FreeBSD__ 982 strncpy(keystr, rc->password, PASSWD_LENGTH); 983#else 984 strncpy((char *)keystr, rc->password, PASSWD_LENGTH); 985#endif | 1346 c->rc_fd = cfd; 1347 c->rc_s = s; 1348 c->rc_zbuf = malloc(RFB_ZLIB_BUFSZ + 16); 1349 if (c->rc_zbuf == NULL) 1350 goto fail; |
986 | 1351 |
987 /* VNC clients encrypts the challenge with all the bit fields 988 * in each byte of the password mirrored. 989 * Here we flip each byte of the keystr. 990 */ 991 for (i = 0; i < PASSWD_LENGTH; i++) { 992 keystr[i] = (keystr[i] & 0xF0) >> 4 993 | (keystr[i] & 0x0F) << 4; 994 keystr[i] = (keystr[i] & 0xCC) >> 2 995 | (keystr[i] & 0x33) << 2; 996 keystr[i] = (keystr[i] & 0xAA) >> 1 997 | (keystr[i] & 0x55) << 1; 998 } | 1352 pthread_mutex_lock(&s->rs_clientlock); |
999 | 1353 |
1000 /* Initialize a 16-byte random challenge */ 1001 arc4random_buf(challenge, sizeof(challenge)); 1002 stream_write(cfd, challenge, AUTH_LENGTH); 1003 1004 /* Receive the 16-byte challenge response */ 1005 stream_read(cfd, buf, AUTH_LENGTH); 1006 1007 memcpy(crypt_expected, challenge, AUTH_LENGTH); 1008 1009 /* Encrypt the Challenge with DES */ 1010 DES_set_key((const_DES_cblock *)keystr, &ks); 1011 DES_ecb_encrypt((const_DES_cblock *)challenge, 1012 (const_DES_cblock *)crypt_expected, 1013 &ks, DES_ENCRYPT); 1014 DES_ecb_encrypt((const_DES_cblock *)(challenge + PASSWD_LENGTH), 1015 (const_DES_cblock *)(crypt_expected + 1016 PASSWD_LENGTH), 1017 &ks, DES_ENCRYPT); 1018 1019 if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) { 1020#ifdef __FreeBSD__ 1021 message = "Auth Failed: Invalid Password."; 1022#else 1023 message = 1024 (unsigned char *)"Auth Failed: Invalid Password."; 1025#endif 1026 sres = htonl(1); 1027 } else { 1028 sres = 0; 1029 } 1030#else 1031 sres = htonl(1); 1032 WPRINTF(("Auth not supported, no OpenSSL in your system")); 1033#endif 1034 1035 break; | 1354 err = pthread_create(&c->rc_tx_tid, NULL, rfb_client_tx_thread, c); 1355 if (err != 0) { 1356 perror("pthread_create client tx thread"); 1357 pthread_mutex_unlock(&s->rs_clientlock); 1358 goto fail; |
1036 } 1037 | 1359 } 1360 |
1038 switch (client_ver) { 1039 case CVERS_3_7: 1040 case CVERS_3_8: 1041report_and_done: 1042 /* 2d. Write back a status */ 1043 stream_write(cfd, &sres, 4); | 1361 s->rs_clientcount++; 1362 list_insert_tail(&s->rs_clients, c); 1363 c->rc_instance = id_allocff(rfb_idspace); 1364 pthread_mutex_unlock(&s->rs_clientlock); |
1044 | 1365 |
1045 if (sres) { 1046 /* 3.7 does not want string explaining cause */ 1047 if (client_ver == CVERS_3_8) { 1048#ifdef __FreeBSD__ 1049 be32enc(buf, strlen(message)); 1050 stream_write(cfd, buf, 4); 1051 stream_write(cfd, message, strlen(message)); 1052#else 1053 be32enc(buf, strlen((char *)message)); 1054 stream_write(cfd, buf, 4); 1055 stream_write(cfd, message, 1056 strlen((char *)message)); 1057#endif 1058 } 1059 goto done; 1060 } 1061 break; 1062 case CVERS_3_3: 1063 default: 1064 /* for VNC auth case send status */ 1065 if (auth_type == SECURITY_TYPE_VNC_AUTH) { 1066 /* 2d. Write back a status */ 1067 stream_write(cfd, &sres, 4); 1068 } 1069 if (sres) { 1070 goto done; 1071 } 1072 break; 1073 } 1074 /* 3a. Read client shared-flag byte */ 1075 len = stream_read(cfd, buf, 1); | 1366 (void) pthread_detach(c->rc_tx_tid); |
1076 | 1367 |
1077 /* 4a. Write server-init info */ 1078#ifndef __FreeBSD__ 1079 rfb_send_server_init_msg(cfd, rc); 1080#else 1081 rfb_send_server_init_msg(cfd); 1082#endif | 1368 rfb_printf(c, RFB_LOGWARN, "connection from %s", host); |
1083 | 1369 |
1084 if (!rc->zbuf) { 1085 rc->zbuf = malloc(RFB_ZLIB_BUFSZ + 16); 1086 assert(rc->zbuf != NULL); 1087 } | 1370 return; |
1088 | 1371 |
1089 perror = pthread_create(&tid, NULL, rfb_wr_thr, rc); 1090 if (perror == 0) 1091 pthread_set_name_np(tid, "rfbout"); 1092 1093 /* Now read in client requests. 1st byte identifies type */ 1094 for (;;) { 1095 len = read(cfd, buf, 1); 1096 if (len <= 0) { 1097 DPRINTF(("rfb client exiting")); 1098 break; 1099 } 1100 1101 switch (buf[0]) { 1102 case CS_SET_PIXEL_FORMAT: 1103 rfb_recv_set_pixfmt_msg(rc, cfd); 1104 break; 1105 case CS_SET_ENCODINGS: 1106 rfb_recv_set_encodings_msg(rc, cfd); 1107 break; 1108 case CS_UPDATE_MSG: 1109 rfb_recv_update_msg(rc, cfd); 1110 break; 1111 case CS_KEY_EVENT: 1112 rfb_recv_key_msg(rc, cfd); 1113 break; 1114 case CS_POINTER_EVENT: 1115 rfb_recv_ptr_msg(rc, cfd); 1116 break; 1117 case CS_CUT_TEXT: 1118 rfb_recv_cuttext_msg(rc, cfd); 1119 break; 1120 case CS_MSG_CLIENT_QEMU: 1121 rfb_recv_client_msg(rc, cfd); 1122 break; 1123 default: 1124 WPRINTF(("rfb unknown cli-code %d!", buf[0] & 0xff)); 1125 goto done; 1126 } 1127 } 1128done: 1129 rc->cfd = -1; 1130 if (perror == 0) 1131 pthread_join(tid, NULL); 1132 if (rc->enc_zlib_ok) 1133 deflateEnd(&rc->zstream); | 1372fail: 1373 (void) close(cfd); 1374 free(c); |
1134} 1135 | 1375} 1376 |
1136static void * 1137rfb_thr(void *arg) | 1377int 1378rfb_init(char *hostname, int port, int wait, const char *password, 1379 const char *name) |
1138{ | 1380{ |
1139 struct rfb_softc *rc; 1140 sigset_t set; | 1381 rfb_server_t *s; 1382#ifndef WITHOUT_CAPSICUM 1383 cap_rights_t rights; 1384#endif |
1141 | 1385 |
1142 int cfd; | 1386 (void) pthread_once(&rfb_once, rfb_init_once); |
1143 | 1387 |
1144 rc = arg; | 1388 if (rfb_idspace == NULL) { 1389 rfb_printf(NULL, RFB_LOGERR, 1390 "rfb_idspace could not be allocated"); 1391 return (-1); 1392 } |
1145 | 1393 |
1146 sigemptyset(&set); 1147 sigaddset(&set, SIGPIPE); 1148 if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { 1149 perror("pthread_sigmask"); 1150 return (NULL); | 1394 if ((s = calloc(1, sizeof (rfb_server_t))) == NULL) { 1395 perror("calloc"); 1396 return (-1); |
1151 } | 1397 } |
1398 s->rs_fd = -1; 1399 s->rs_name = name; |
|
1152 | 1400 |
1153 for (;;) { 1154 rc->enc_raw_ok = false; 1155 rc->enc_zlib_ok = false; 1156 rc->enc_resize_ok = false; 1157 rc->enc_extkeyevent_ok = false; | 1401 if (password != NULL && strlen(password) > 0) 1402 s->rs_password = password; |
1158 | 1403 |
1159 rc->enc_extkeyevent_send = false; 1160 1161 cfd = accept(rc->sfd, NULL, NULL); 1162 if (rc->conn_wait) { 1163 pthread_mutex_lock(&rc->mtx); 1164 pthread_cond_signal(&rc->cond); 1165 pthread_mutex_unlock(&rc->mtx); 1166 rc->conn_wait = 0; 1167 } 1168 rfb_handle(rc, cfd); 1169 close(cfd); | 1404 if (pthread_mutex_init(&s->rs_clientlock, NULL) != 0) { 1405 perror("pthread_mutex_init"); 1406 free(s); 1407 return (-1); |
1170 } 1171 | 1408 } 1409 |
1172 /* NOTREACHED */ 1173 return (NULL); 1174} | 1410 list_create(&s->rs_clients, sizeof (rfb_client_t), 1411 offsetof(rfb_client_t, rc_node)); |
1175 | 1412 |
1176static int 1177sse42_supported(void) 1178{ 1179 u_int cpu_registers[4], ecx; | 1413 /* Server pixel format. */ 1414 s->rs_pixfmt.rp_bpp = RFB_PIX_BPP; 1415 s->rs_pixfmt.rp_depth = RFB_PIX_DEPTH; 1416 s->rs_pixfmt.rp_bigendian = 0; 1417 s->rs_pixfmt.rp_truecolour = 1; 1418 s->rs_pixfmt.rp_r_max = htons(RFB_PIX_RMAX); 1419 s->rs_pixfmt.rp_g_max = htons(RFB_PIX_GMAX); 1420 s->rs_pixfmt.rp_b_max = htons(RFB_PIX_BMAX); 1421 s->rs_pixfmt.rp_r_shift = RFB_PIX_RSHIFT; 1422 s->rs_pixfmt.rp_g_shift = RFB_PIX_GSHIFT; 1423 s->rs_pixfmt.rp_b_shift = RFB_PIX_BSHIFT; |
1180 | 1424 |
1181 do_cpuid(1, cpu_registers); | 1425 /* UNIX socket. */ 1426 if (port == -1 && hostname != NULL && *hostname == '/') { 1427 struct sockaddr_un sock; |
1182 | 1428 |
1183 ecx = cpu_registers[2]; | 1429 s->rs_fd = socket(PF_UNIX, SOCK_STREAM, 0); 1430 if (s->rs_fd < 0) { 1431 perror("socket"); 1432 goto fail; 1433 } |
1184 | 1434 |
1185 return ((ecx & CPUID2_SSE42) != 0); 1186} | 1435 sock.sun_family = AF_UNIX; 1436 if (strlcpy(sock.sun_path, hostname, sizeof (sock.sun_path)) >= 1437 sizeof (sock.sun_path)) { 1438 rfb_printf(NULL, RFB_LOGERR, 1439 "socket path '%s' too long\n", hostname); 1440 goto fail; 1441 } |
1187 | 1442 |
1188int 1189#ifndef __FreeBSD__ 1190rfb_init(char *hostname, int port, int wait, char *password, const char *name) 1191#else 1192rfb_init(char *hostname, int port, int wait, char *password) 1193#endif 1194{ 1195 int e; 1196 char servname[6]; 1197 struct rfb_softc *rc; 1198 struct addrinfo *ai = NULL; 1199 struct addrinfo hints; 1200 int on = 1; 1201 int cnt; 1202#ifndef WITHOUT_CAPSICUM 1203 cap_rights_t rights; 1204#endif | 1443 (void) unlink(hostname); 1444 if (bind(s->rs_fd, (struct sockaddr *)&sock, 1445 sizeof (sock)) < 0) { 1446 perror("bind"); 1447 goto fail; 1448 } 1449 } else { 1450 struct addrinfo hints, *ai = NULL; 1451 char servname[6]; 1452 int e; |
1205 | 1453 |
1206 rc = calloc(1, sizeof(struct rfb_softc)); | 1454 (void) snprintf(servname, sizeof (servname), "%d", 1455 port ? port : RFB_DEFAULT_PORT); |
1207 | 1456 |
1208 cnt = howmany(RFB_MAX_WIDTH, PIX_PER_CELL) * 1209 howmany(RFB_MAX_HEIGHT, PIX_PER_CELL); 1210 rc->crc = calloc(cnt, sizeof(uint32_t)); 1211 rc->crc_tmp = calloc(cnt, sizeof(uint32_t)); 1212 rc->crc_width = RFB_MAX_WIDTH; 1213 rc->crc_height = RFB_MAX_HEIGHT; 1214 rc->sfd = -1; 1215 1216 rc->password = password; 1217 1218#ifndef __FreeBSD__ 1219 rc->name = name; 1220#endif 1221 1222 snprintf(servname, sizeof(servname), "%d", port ? port : 5900); 1223 1224 if (!hostname || strlen(hostname) == 0) | 1457 if (hostname == NULL || strlen(hostname) == 0) { |
1225#if defined(INET) | 1458#if defined(INET) |
1226 hostname = "127.0.0.1"; | 1459 hostname = "127.0.0.1"; |
1227#elif defined(INET6) | 1460#elif defined(INET6) |
1228 hostname = "[::1]"; | 1461 hostname = "[::1]"; |
1229#endif | 1462#endif |
1463 } |
|
1230 | 1464 |
1231 memset(&hints, 0, sizeof(hints)); 1232 hints.ai_family = AF_UNSPEC; 1233 hints.ai_socktype = SOCK_STREAM; 1234 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; | 1465 memset(&hints, '\0', sizeof (hints)); 1466 hints.ai_family = AF_UNSPEC; 1467 hints.ai_socktype = SOCK_STREAM; 1468 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; |
1235 | 1469 |
1236 if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { 1237 EPRINTLN("getaddrinfo: %s", gai_strerror(e)); 1238 goto error; 1239 } | 1470 if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { 1471 rfb_printf(NULL, RFB_LOGERR, "getaddrinfo: %s", 1472 gai_strerror(e)); 1473 goto fail; 1474 } |
1240 | 1475 |
1241 rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0); 1242 if (rc->sfd < 0) { 1243 perror("socket"); 1244 goto error; 1245 } | 1476 s->rs_fd = socket(ai->ai_family, ai->ai_socktype, 0); 1477 if (s->rs_fd < 0) { 1478 perror("socket"); 1479 freeaddrinfo(ai); 1480 goto fail; 1481 } |
1246 | 1482 |
1247 setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | 1483 e = 1; 1484 (void) setsockopt(s->rs_fd, SOL_SOCKET, SO_REUSEADDR, 1485 &e, sizeof (e)); |
1248 | 1486 |
1249 if (bind(rc->sfd, ai->ai_addr, ai->ai_addrlen) < 0) { 1250 perror("bind"); 1251 goto error; | 1487 if (bind(s->rs_fd, ai->ai_addr, ai->ai_addrlen) < 0) { 1488 perror("bind"); 1489 freeaddrinfo(ai); 1490 goto fail; 1491 } 1492 freeaddrinfo(ai); |
1252 } 1253 | 1493 } 1494 |
1254 if (listen(rc->sfd, 1) < 0) { | 1495 if (listen(s->rs_fd, 5) < 0) { |
1255 perror("listen"); | 1496 perror("listen"); |
1256 goto error; | 1497 goto fail; |
1257 } 1258 1259#ifndef WITHOUT_CAPSICUM 1260 cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE); | 1498 } 1499 1500#ifndef WITHOUT_CAPSICUM 1501 cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE); |
1261 if (caph_rights_limit(rc->sfd, &rights) == -1) | 1502 if (caph_rights_limit(s->rs_fd, &rights) == -1) |
1262 errx(EX_OSERR, "Unable to apply rights for sandbox"); 1263#endif 1264 | 1503 errx(EX_OSERR, "Unable to apply rights for sandbox"); 1504#endif 1505 |
1265 rc->hw_crc = sse42_supported(); 1266 1267 rc->conn_wait = wait; 1268 if (wait) { 1269 pthread_mutex_init(&rc->mtx, NULL); 1270 pthread_cond_init(&rc->cond, NULL); 1271 } 1272 1273 pthread_create(&rc->tid, NULL, rfb_thr, rc); 1274 pthread_set_name_np(rc->tid, "rfb"); 1275 1276 if (wait) { 1277 DPRINTF(("Waiting for rfb client...")); 1278 pthread_mutex_lock(&rc->mtx); 1279 pthread_cond_wait(&rc->cond, &rc->mtx); 1280 pthread_mutex_unlock(&rc->mtx); 1281 DPRINTF(("rfb client connected")); 1282 } 1283 1284 freeaddrinfo(ai); 1285 return (0); 1286 1287 error: 1288 if (ai != NULL) 1289 freeaddrinfo(ai); 1290 if (rc->sfd != -1) 1291 close(rc->sfd); 1292 free(rc->crc); 1293 free(rc->crc_tmp); 1294 free(rc); 1295 return (-1); 1296} 1297 1298#ifndef __FreeBSD__ 1299int 1300rfb_init_unix(const char *path, int wait, char *password, const char *name) 1301{ 1302 struct rfb_softc *rc; 1303 struct sockaddr_un sock; 1304 1305 if ((rc = calloc(1, sizeof (struct rfb_softc))) == NULL) { 1306 perror("calloc"); 1307 return (-1); 1308 } 1309 rc->sfd = -1; 1310 1311 if ((rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 1312 sizeof (uint32_t))) == NULL) { 1313 perror("calloc"); | 1506 s->rs_connevent = mevent_add(s->rs_fd, EVF_READ, rfb_accept, s); 1507 if (s->rs_connevent == NULL) { 1508 rfb_printf(NULL, RFB_LOGERR, 1509 "Failed to set up rfb connection mevent"); |
1314 goto fail; 1315 } | 1510 goto fail; 1511 } |
1316 if ((rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 1317 sizeof (uint32_t))) == NULL) { 1318 perror("calloc"); 1319 goto fail; 1320 } 1321 rc->crc_width = RFB_MAX_WIDTH; 1322 rc->crc_height = RFB_MAX_HEIGHT; | |
1323 | 1512 |
1324 rc->password = password; 1325 rc->name = name; | 1513 list_insert_tail(&rfb_list, s); |
1326 | 1514 |
1327 rc->sfd = socket(PF_UNIX, SOCK_STREAM, 0); 1328 if (rc->sfd < 0) { 1329 perror("socket"); 1330 goto fail; 1331 } | 1515 /* 1516 * Wait for first connection. Since the mevent thread is 1517 * not yet running, we can't rely on normal incoming connection 1518 * handling. 1519 */ 1520 if (wait != 0) { 1521 fd_set rfds; 1522 int e; |
1332 | 1523 |
1333 sock.sun_family = AF_UNIX; 1334 if (strlcpy(sock.sun_path, path, sizeof (sock.sun_path)) >= 1335 sizeof (sock.sun_path)) { 1336 (void) fprintf(stderr, "socket path '%s' too long\n", path); 1337 goto fail; 1338 } | 1524 rfb_printf(NULL, RFB_LOGWARN, 1525 "holding boot until first client connection"); |
1339 | 1526 |
1340 (void) unlink(path); 1341 if (bind(rc->sfd, (struct sockaddr *)&sock, sizeof (sock)) < 0) { 1342 perror("bind"); 1343 goto fail; 1344 } | 1527 for (;;) { 1528 FD_ZERO(&rfds); 1529 FD_SET(s->rs_fd, &rfds); |
1345 | 1530 |
1346 if (listen(rc->sfd, 1) < 0) { 1347 perror("listen"); 1348 goto fail; | 1531 e = select(s->rs_fd + 1, &rfds, NULL, NULL, NULL); 1532 if (e < 0 && errno == EINTR) 1533 continue; 1534 if (e < 0 || FD_ISSET(s->rs_fd, &rfds)) 1535 break; 1536 } 1537 rfb_printf(NULL, RFB_LOGWARN, "continuing boot"); |
1349 } 1350 | 1538 } 1539 |
1351 rc->hw_crc = sse42_supported(); 1352 1353 rc->conn_wait = wait; 1354 if (wait) { 1355 VERIFY3S(pthread_mutex_init(&rc->mtx, NULL), ==, 0); 1356 VERIFY3S(pthread_cond_init(&rc->cond, NULL), ==, 0); 1357 } 1358 1359 VERIFY3S(pthread_create(&rc->tid, NULL, rfb_thr, rc), ==, 0); 1360 pthread_set_name_np(rc->tid, "rfb"); 1361 1362 if (wait) { 1363 DPRINTF(("Waiting for rfb client...\n")); 1364 pthread_mutex_lock(&rc->mtx); 1365 VERIFY3S(pthread_cond_wait(&rc->cond, &rc->mtx), ==, 0); 1366 pthread_mutex_unlock(&rc->mtx); 1367 } 1368 | |
1369 return (0); 1370 1371fail: | 1540 return (0); 1541 1542fail: |
1372 if (rc->sfd != -1) { 1373 VERIFY3S(close(rc->sfd), ==, 0); 1374 } 1375 free(rc->crc); 1376 free(rc->crc_tmp); 1377 free(rc); | 1543 if (s->rs_fd != -1) 1544 VERIFY3S(close(s->rs_fd), ==, 0); 1545 (void) pthread_mutex_destroy(&s->rs_clientlock); 1546 list_destroy(&s->rs_clients); 1547 free(s); |
1378 return (-1); 1379} | 1548 return (-1); 1549} |
1380#endif | |