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