xref: /illumos-gate/usr/src/cmd/bhyve/rfb_impl.h (revision 1aa1f41fe10c6220a7fbef328fac1b72a8355a01)
1*1aa1f41fSAndy Fiddaman /*
2*1aa1f41fSAndy Fiddaman  * This file and its contents are supplied under the terms of the
3*1aa1f41fSAndy Fiddaman  * Common Development and Distribution License ("CDDL"), version 1.0.
4*1aa1f41fSAndy Fiddaman  * You may only use this file in accordance with the terms of version
5*1aa1f41fSAndy Fiddaman  * 1.0 of the CDDL.
6*1aa1f41fSAndy Fiddaman  *
7*1aa1f41fSAndy Fiddaman  * A full copy of the text of the CDDL should have accompanied this
8*1aa1f41fSAndy Fiddaman  * source.  A copy of the CDDL is also available via the Internet at
9*1aa1f41fSAndy Fiddaman  * http://www.illumos.org/license/CDDL.
10*1aa1f41fSAndy Fiddaman  */
11*1aa1f41fSAndy Fiddaman 
12*1aa1f41fSAndy Fiddaman /*
13*1aa1f41fSAndy Fiddaman  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
14*1aa1f41fSAndy Fiddaman  */
15*1aa1f41fSAndy Fiddaman 
16*1aa1f41fSAndy Fiddaman #ifndef _RFB_IMPL_H
17*1aa1f41fSAndy Fiddaman #define	_RFB_IMPL_H
18*1aa1f41fSAndy Fiddaman 
19*1aa1f41fSAndy Fiddaman #include <stdatomic.h>
20*1aa1f41fSAndy Fiddaman #include <stdbool.h>
21*1aa1f41fSAndy Fiddaman #include <zlib.h>
22*1aa1f41fSAndy Fiddaman #include <sys/types.h>
23*1aa1f41fSAndy Fiddaman #include <sys/list.h>
24*1aa1f41fSAndy Fiddaman 
25*1aa1f41fSAndy Fiddaman #include "mevent.h"
26*1aa1f41fSAndy Fiddaman 
27*1aa1f41fSAndy Fiddaman /*
28*1aa1f41fSAndy Fiddaman  * The ProtocolVersion message consists of 12 bytes interpreted as a string of
29*1aa1f41fSAndy Fiddaman  * ASCII characters in the format "RFB xxx.yyy\n" where xxx and yyy are the
30*1aa1f41fSAndy Fiddaman  * major and minor version numbers, padded with zeros.
31*1aa1f41fSAndy Fiddaman  */
32*1aa1f41fSAndy Fiddaman #define	RFB_VERSION			"RFB 003.008\n"
33*1aa1f41fSAndy Fiddaman #define	RFB_VERSION_LEN			(sizeof (RFB_VERSION) - 1)
34*1aa1f41fSAndy Fiddaman 
35*1aa1f41fSAndy Fiddaman _Static_assert(RFB_VERSION_LEN == 12, "RFB_VERSION length incorrect");
36*1aa1f41fSAndy Fiddaman 
37*1aa1f41fSAndy Fiddaman /* Keep synchronised with pci_fbuf.c */
38*1aa1f41fSAndy Fiddaman #define	RFB_MAX_WIDTH			1920
39*1aa1f41fSAndy Fiddaman #define	RFB_MAX_HEIGHT			1200
40*1aa1f41fSAndy Fiddaman 
41*1aa1f41fSAndy Fiddaman #define	RFB_MAX_CLIENTS			10
42*1aa1f41fSAndy Fiddaman 
43*1aa1f41fSAndy Fiddaman /* Framebuffer pixel format */
44*1aa1f41fSAndy Fiddaman #define	RFB_PIX_BPP			32
45*1aa1f41fSAndy Fiddaman #define	RFB_PIX_DEPTH			24
46*1aa1f41fSAndy Fiddaman #define	RFB_PIX_RSHIFT			16
47*1aa1f41fSAndy Fiddaman #define	RFB_PIX_GSHIFT			8
48*1aa1f41fSAndy Fiddaman #define	RFB_PIX_BSHIFT			0
49*1aa1f41fSAndy Fiddaman #define	RFB_PIX_RMAX			255
50*1aa1f41fSAndy Fiddaman #define	RFB_PIX_GMAX			255
51*1aa1f41fSAndy Fiddaman #define	RFB_PIX_BMAX			255
52*1aa1f41fSAndy Fiddaman 
53*1aa1f41fSAndy Fiddaman #define	RFB_ZLIB_BUFSZ			(RFB_MAX_WIDTH * RFB_MAX_HEIGHT * 4)
54*1aa1f41fSAndy Fiddaman 
55*1aa1f41fSAndy Fiddaman #define	RFB_PIX_PER_CELL		32
56*1aa1f41fSAndy Fiddaman #define	RFB_PIXCELL_SHIFT		5
57*1aa1f41fSAndy Fiddaman #define	RFB_PIXCELL_MASK		0x1f
58*1aa1f41fSAndy Fiddaman #define	RFB_SENDALL_THRESH		25
59*1aa1f41fSAndy Fiddaman 
60*1aa1f41fSAndy Fiddaman #define	RFB_SEL_DELAY_US		10000
61*1aa1f41fSAndy Fiddaman #define	RFB_SCREEN_REFRESH_DELAY	33300   /* 30 Hz */
62*1aa1f41fSAndy Fiddaman #define	RFB_SCREEN_POLL_DELAY		(RFB_SCREEN_REFRESH_DELAY / 2)
63*1aa1f41fSAndy Fiddaman 
64*1aa1f41fSAndy Fiddaman /* Client-to-server message types */
65*1aa1f41fSAndy Fiddaman #define	RFBP_CS_SET_PIXEL_FORMAT	0
66*1aa1f41fSAndy Fiddaman #define	RFBP_CS_SET_ENCODINGS		2
67*1aa1f41fSAndy Fiddaman #define	RFBP_CS_UPDATE_REQUEST		3
68*1aa1f41fSAndy Fiddaman #define	RFBP_CS_KEY_EVENT		4
69*1aa1f41fSAndy Fiddaman #define	RFBP_CS_POINTER_EVENT		5
70*1aa1f41fSAndy Fiddaman #define	RFBP_CS_CUT_TEXT		6
71*1aa1f41fSAndy Fiddaman #define	RFBP_CS_QEMU			255
72*1aa1f41fSAndy Fiddaman #define	RFBP_CS_QEMU_KEVENT		0
73*1aa1f41fSAndy Fiddaman 
74*1aa1f41fSAndy Fiddaman /* Server-to-client message types */
75*1aa1f41fSAndy Fiddaman #define	RFBP_SC_UPDATE			0
76*1aa1f41fSAndy Fiddaman #define	RFBP_SC_SET_COLOURMAP_ENTRIES	1
77*1aa1f41fSAndy Fiddaman #define	RFBP_SC_BELL			2
78*1aa1f41fSAndy Fiddaman #define	RFBP_SC_CUT_TEXT		3
79*1aa1f41fSAndy Fiddaman 
80*1aa1f41fSAndy Fiddaman /* Encodings */
81*1aa1f41fSAndy Fiddaman #define	RFBP_ENCODING_RAW		0
82*1aa1f41fSAndy Fiddaman #define	RFBP_ENCODING_ZLIB		6
83*1aa1f41fSAndy Fiddaman /* Pseudo-encodings */
84*1aa1f41fSAndy Fiddaman #define	RFBP_ENCODING_RESIZE		-223
85*1aa1f41fSAndy Fiddaman #define	RFBP_ENCODING_EXT_KEVENT	-258	/* QEMU ext. key event */
86*1aa1f41fSAndy Fiddaman #define	RFBP_ENCODING_DESKTOP_NAME	-307
87*1aa1f41fSAndy Fiddaman 
88*1aa1f41fSAndy Fiddaman /* Security types */
89*1aa1f41fSAndy Fiddaman #define	RFBP_SECURITY_INVALID		0
90*1aa1f41fSAndy Fiddaman #define	RFBP_SECURITY_NONE		1
91*1aa1f41fSAndy Fiddaman #define	RFBP_SECURITY_VNC_AUTH		2
92*1aa1f41fSAndy Fiddaman 
93*1aa1f41fSAndy Fiddaman #define	RFBP_SECURITY_VNC_AUTH_LEN	16
94*1aa1f41fSAndy Fiddaman #define	RFBP_SECURITY_VNC_PASSWD_LEN	8
95*1aa1f41fSAndy Fiddaman 
96*1aa1f41fSAndy Fiddaman typedef enum rfb_loglevel {
97*1aa1f41fSAndy Fiddaman 	RFB_LOGDEBUG,
98*1aa1f41fSAndy Fiddaman 	RFB_LOGWARN,
99*1aa1f41fSAndy Fiddaman 	RFB_LOGERR
100*1aa1f41fSAndy Fiddaman } rfb_loglevel_t;
101*1aa1f41fSAndy Fiddaman 
102*1aa1f41fSAndy Fiddaman typedef enum rfb_encodings {
103*1aa1f41fSAndy Fiddaman 	RFB_ENCODING_RAW		= (1ULL << 0),
104*1aa1f41fSAndy Fiddaman 	RFB_ENCODING_ZLIB		= (1ULL << 1),
105*1aa1f41fSAndy Fiddaman 	RFB_ENCODING_RESIZE		= (1ULL << 2),
106*1aa1f41fSAndy Fiddaman 	RFB_ENCODING_EXT_KEVENT		= (1ULL << 3),
107*1aa1f41fSAndy Fiddaman 	RFB_ENCODING_DESKTOP_NAME	= (1ULL << 4)
108*1aa1f41fSAndy Fiddaman } rfb_encodings_t;
109*1aa1f41fSAndy Fiddaman 
110*1aa1f41fSAndy Fiddaman typedef enum rfb_cver {
111*1aa1f41fSAndy Fiddaman 	RFB_CVER_3_3,
112*1aa1f41fSAndy Fiddaman 	RFB_CVER_3_7,
113*1aa1f41fSAndy Fiddaman 	RFB_CVER_3_8
114*1aa1f41fSAndy Fiddaman } rfb_cver_t;
115*1aa1f41fSAndy Fiddaman 
116*1aa1f41fSAndy Fiddaman typedef struct rfb_pixfmt {
117*1aa1f41fSAndy Fiddaman 	uint8_t			rp_bpp;
118*1aa1f41fSAndy Fiddaman 	uint8_t			rp_depth;
119*1aa1f41fSAndy Fiddaman 	uint8_t			rp_bigendian;
120*1aa1f41fSAndy Fiddaman 	uint8_t			rp_truecolour;
121*1aa1f41fSAndy Fiddaman 	uint16_t		rp_r_max;
122*1aa1f41fSAndy Fiddaman 	uint16_t		rp_g_max;
123*1aa1f41fSAndy Fiddaman 	uint16_t		rp_b_max;
124*1aa1f41fSAndy Fiddaman 	uint8_t			rp_r_shift;
125*1aa1f41fSAndy Fiddaman 	uint8_t			rp_g_shift;
126*1aa1f41fSAndy Fiddaman 	uint8_t			rp_b_shift;
127*1aa1f41fSAndy Fiddaman 	uint8_t			rp_pad[3];
128*1aa1f41fSAndy Fiddaman } __packed rfb_pixfmt_t;
129*1aa1f41fSAndy Fiddaman 
130*1aa1f41fSAndy Fiddaman /* Server-to-client message formats */
131*1aa1f41fSAndy Fiddaman 
132*1aa1f41fSAndy Fiddaman typedef struct rfb_server_info {
133*1aa1f41fSAndy Fiddaman 	uint16_t		rsi_width;
134*1aa1f41fSAndy Fiddaman 	uint16_t		rsi_height;
135*1aa1f41fSAndy Fiddaman 	rfb_pixfmt_t		rsi_pixfmt;
136*1aa1f41fSAndy Fiddaman 	uint32_t		rsi_namelen;
137*1aa1f41fSAndy Fiddaman } __packed rfb_server_info_t;
138*1aa1f41fSAndy Fiddaman 
139*1aa1f41fSAndy Fiddaman typedef struct rfb_server_update_msg {
140*1aa1f41fSAndy Fiddaman 	uint8_t			rss_type;
141*1aa1f41fSAndy Fiddaman 	uint8_t			rss_pad;
142*1aa1f41fSAndy Fiddaman 	uint16_t		rss_numrects;
143*1aa1f41fSAndy Fiddaman } __packed rfb_server_update_msg_t;
144*1aa1f41fSAndy Fiddaman 
145*1aa1f41fSAndy Fiddaman typedef struct rfb_rect_hdr {
146*1aa1f41fSAndy Fiddaman 	uint16_t		rr_x;
147*1aa1f41fSAndy Fiddaman 	uint16_t		rr_y;
148*1aa1f41fSAndy Fiddaman 	uint16_t		rr_width;
149*1aa1f41fSAndy Fiddaman 	uint16_t		rr_height;
150*1aa1f41fSAndy Fiddaman 	uint32_t		rr_encoding;
151*1aa1f41fSAndy Fiddaman } __packed rfb_rect_hdr_t;
152*1aa1f41fSAndy Fiddaman 
153*1aa1f41fSAndy Fiddaman /* Client-to-server message formats */
154*1aa1f41fSAndy Fiddaman 
155*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_pixfmt_msg  {
156*1aa1f41fSAndy Fiddaman 	uint8_t			rp_pad[3];
157*1aa1f41fSAndy Fiddaman 	rfb_pixfmt_t		rp_pixfmt;
158*1aa1f41fSAndy Fiddaman } __packed rfb_cs_pixfmt_msg_t;
159*1aa1f41fSAndy Fiddaman 
160*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_update_msg {
161*1aa1f41fSAndy Fiddaman 	uint8_t			rum_incremental;
162*1aa1f41fSAndy Fiddaman 	uint16_t		rum_x;
163*1aa1f41fSAndy Fiddaman 	uint16_t		rum_y;
164*1aa1f41fSAndy Fiddaman 	uint16_t		rum_width;
165*1aa1f41fSAndy Fiddaman 	uint16_t		rum_height;
166*1aa1f41fSAndy Fiddaman } __packed rfb_cs_update_msg_t;
167*1aa1f41fSAndy Fiddaman 
168*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_encodings_msg {
169*1aa1f41fSAndy Fiddaman 	uint8_t			re_pad;
170*1aa1f41fSAndy Fiddaman 	uint16_t		re_numencs;
171*1aa1f41fSAndy Fiddaman } __packed rfb_cs_encodings_msg_t;
172*1aa1f41fSAndy Fiddaman 
173*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_key_event_msg {
174*1aa1f41fSAndy Fiddaman 	uint8_t			rke_down;
175*1aa1f41fSAndy Fiddaman 	uint16_t		rke_pad;
176*1aa1f41fSAndy Fiddaman 	uint32_t		rke_sym;
177*1aa1f41fSAndy Fiddaman } __packed rfb_cs_key_event_msg_t;
178*1aa1f41fSAndy Fiddaman 
179*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_pointer_event_msg {
180*1aa1f41fSAndy Fiddaman 	uint8_t			rpe_button;
181*1aa1f41fSAndy Fiddaman 	uint16_t		rpe_x;
182*1aa1f41fSAndy Fiddaman 	uint16_t		rpe_y;
183*1aa1f41fSAndy Fiddaman } __packed rfb_cs_pointer_event_msg_t;
184*1aa1f41fSAndy Fiddaman 
185*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_cut_text_msg {
186*1aa1f41fSAndy Fiddaman 	uint8_t			rct_padding[3];
187*1aa1f41fSAndy Fiddaman 	uint32_t		rct_length;
188*1aa1f41fSAndy Fiddaman } __packed rfb_cs_cut_text_msg_t;
189*1aa1f41fSAndy Fiddaman 
190*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_qemu_msg {
191*1aa1f41fSAndy Fiddaman 	uint8_t			rq_subtype;
192*1aa1f41fSAndy Fiddaman } __packed rfb_cs_qemu_msg_t;
193*1aa1f41fSAndy Fiddaman 
194*1aa1f41fSAndy Fiddaman typedef struct rfb_cs_qemu_extended_key_msg {
195*1aa1f41fSAndy Fiddaman 	uint16_t		rqek_down;
196*1aa1f41fSAndy Fiddaman 	uint32_t		rqek_sym;
197*1aa1f41fSAndy Fiddaman 	uint32_t		rqek_code;
198*1aa1f41fSAndy Fiddaman } __packed rfb_cs_qemu_extended_key_msg_t;
199*1aa1f41fSAndy Fiddaman 
200*1aa1f41fSAndy Fiddaman /* Client/server data structures */
201*1aa1f41fSAndy Fiddaman 
202*1aa1f41fSAndy Fiddaman typedef struct rfb_server {
203*1aa1f41fSAndy Fiddaman 	list_node_t		rs_node;
204*1aa1f41fSAndy Fiddaman 	int			rs_fd;
205*1aa1f41fSAndy Fiddaman 	const char		*rs_name;
206*1aa1f41fSAndy Fiddaman 	const char		*rs_password;
207*1aa1f41fSAndy Fiddaman 
208*1aa1f41fSAndy Fiddaman 	struct mevent		*rs_connevent;
209*1aa1f41fSAndy Fiddaman 
210*1aa1f41fSAndy Fiddaman 	uint_t			rs_clientcount;
211*1aa1f41fSAndy Fiddaman 	pthread_mutex_t		rs_clientlock;
212*1aa1f41fSAndy Fiddaman 	list_t			rs_clients;
213*1aa1f41fSAndy Fiddaman 
214*1aa1f41fSAndy Fiddaman 	bool			rs_exclusive;
215*1aa1f41fSAndy Fiddaman 
216*1aa1f41fSAndy Fiddaman 	rfb_pixfmt_t		rs_pixfmt;
217*1aa1f41fSAndy Fiddaman } rfb_server_t;
218*1aa1f41fSAndy Fiddaman 
219*1aa1f41fSAndy Fiddaman typedef struct rfb_client {
220*1aa1f41fSAndy Fiddaman 	list_node_t		rc_node;
221*1aa1f41fSAndy Fiddaman 	uint_t			rc_instance;
222*1aa1f41fSAndy Fiddaman 
223*1aa1f41fSAndy Fiddaman 	int			rc_fd;
224*1aa1f41fSAndy Fiddaman 	rfb_server_t		*rc_s;
225*1aa1f41fSAndy Fiddaman 	rfb_server_info_t	rc_sinfo;
226*1aa1f41fSAndy Fiddaman 	pthread_t		rc_rx_tid;
227*1aa1f41fSAndy Fiddaman 	pthread_t		rc_tx_tid;
228*1aa1f41fSAndy Fiddaman 
229*1aa1f41fSAndy Fiddaman 	int			rc_width;
230*1aa1f41fSAndy Fiddaman 	int			rc_height;
231*1aa1f41fSAndy Fiddaman 	size_t			rc_cells;
232*1aa1f41fSAndy Fiddaman 	uint32_t		*rc_crc;
233*1aa1f41fSAndy Fiddaman 	uint32_t		*rc_crc_tmp;
234*1aa1f41fSAndy Fiddaman 	z_stream		rc_zstream;
235*1aa1f41fSAndy Fiddaman 	uint8_t			*rc_zbuf;
236*1aa1f41fSAndy Fiddaman 
237*1aa1f41fSAndy Fiddaman 	struct bhyvegc_image	rc_gci;
238*1aa1f41fSAndy Fiddaman 
239*1aa1f41fSAndy Fiddaman 	rfb_cver_t		rc_cver;
240*1aa1f41fSAndy Fiddaman 	rfb_encodings_t		rc_encodings;
241*1aa1f41fSAndy Fiddaman 
242*1aa1f41fSAndy Fiddaman 	atomic_bool		rc_closing;
243*1aa1f41fSAndy Fiddaman 	atomic_bool		rc_pending;
244*1aa1f41fSAndy Fiddaman 	atomic_bool		rc_input_detected;
245*1aa1f41fSAndy Fiddaman 	atomic_bool		rc_crc_reset;
246*1aa1f41fSAndy Fiddaman 	atomic_bool		rc_send_fullscreen;
247*1aa1f41fSAndy Fiddaman 
248*1aa1f41fSAndy Fiddaman 	bool			rc_custom_pixfmt;
249*1aa1f41fSAndy Fiddaman 	bool			rc_keyevent_sent;
250*1aa1f41fSAndy Fiddaman } rfb_client_t;
251*1aa1f41fSAndy Fiddaman 
252*1aa1f41fSAndy Fiddaman #endif	/* _RFB_IMPL_H */
253