10 #define SET_PIXEL_FORMAT 0
11 #define SET_ENCODINGS 2
12 #define FB_UPDATE_REQUEST 3
14 #define POINTER_EVENT 5
15 #define CLIENT_CUT_TEXT 6
17 #define RFB_BUF_SIZE 2048
33 struct server_init_message {
36 struct pixel_format fmt;
41 struct fb_update_req {
57 struct key_event_pkt {
64 struct pointer_event_pkt {
71 struct text_event_pkt {
87 char data[RFB_BUF_SIZE];
91 char next_update_incremental;
92 struct fb_update_req client_interest_area;
97 static struct server_init_message server_info;
99 static void init_server_info() {
100 server_info.name_length = 8;
101 memcpy(server_info.name_string, "NetWatch", 8);
104 static void update_server_info() {
106 server_info.fb_width = fb->curmode.xres;
107 server_info.fb_height = fb->curmode.yres;
108 switch (fb->curmode.format) {
110 server_info.fmt.bpp = 32;
111 server_info.fmt.depth = 24;
112 server_info.fmt.big_endian = 0;
113 server_info.fmt.true_color = 1;
114 server_info.fmt.red_max = 255;
115 server_info.fmt.green_max = 255;
116 server_info.fmt.blue_max = 255;
117 server_info.fmt.red_shift = 0;
118 server_info.fmt.green_shift = 8;
119 server_info.fmt.blue_shift = 16;
122 outputf("RFB: unknown fb fmt %d", fb->curmode.format);
128 static void close_conn(struct tcp_pcb *pcb, struct rfb_state *state) {
142 static enum fsm_result recv_fsm(struct tcp_pcb *pcb, struct rfb_state *state) {
144 switch(state->state) {
146 if (state->writepos < 12) return NEEDMORE;
148 if (!strncmp(state->data, "RFB 003.003\n", 12)) {
150 } else if (!strncmp(state->data, "RFB 003.005\n", 12)) {
151 /* Spec states that "RFB 003.005", an incorrect value,
152 * should be treated by the server as 3.3. */
154 } else if (!strncmp(state->data, "RFB 003.007\n", 12)) {
156 } else if (!strncmp(state->data, "RFB 003.008\n", 12)) {
159 outputf("RFB: Negotiation fail");
163 outputf("RFB: Negotiated v3.%d", state->version);
165 state->readpos += 12;
166 state->state = ST_CLIENTINIT;
168 /* We support one security type, currently "none". */
169 if (state->version >= 7) {
170 tcp_write(pcb, "\x01\x01", 2, 0);
172 tcp_write(pcb, "\x01", 1, 0);
175 /* ... and go right ahead and send SecurityResult message. */
176 tcp_write(pcb, "\x00\x00\x00\x01", 4, 0);
182 if (state->writepos < 1) return NEEDMORE;
184 state->state = ST_MAIN;
186 tcp_write(pcb, &server_info, sizeof(server_info), 0);
192 if (state->writepos < 1) return NEEDMORE;
194 switch (state->data[0]) {
196 case SET_PIXEL_FORMAT:
198 if (state->writepos < (sizeof(struct pixel_format) + 4))
201 struct pixel_format * new_fmt =
202 (struct pixel_format *)(&state->data[4]);
206 state->readpos += sizeof(struct pixel_format) + 4;
210 if (state->writepos < 4) return NEEDMORE;
212 struct set_encs_req * req = (struct set_encs_req *)state->data;
214 if (state->writepos < (sizeof(struct set_encs_req)
220 state->readpos += (4 * req->num) + sizeof(struct set_encs_req);
223 case FB_UPDATE_REQUEST:
224 if (state->writepos < sizeof(struct fb_update_req))
227 state->needs_updated = 1;
228 memcpy(&state->client_interest_area, state->data,
229 sizeof(struct fb_update_req));
231 state->readpos += sizeof(struct fb_update_req);
235 if (state->writepos < sizeof(struct key_event_pkt))
240 state->readpos += sizeof(struct key_event_pkt);
244 if (state->writepos < sizeof(struct pointer_event_pkt))
249 state->readpos += sizeof(struct pointer_event_pkt);
252 case CLIENT_CUT_TEXT:
253 if (state->writepos < sizeof(struct text_event_pkt))
256 struct text_event_pkt * pkt =
257 (struct text_event_pkt *)state->data;
259 if (state->writepos < sizeof(struct text_event_pkt)
265 state->readpos += sizeof(struct text_event_pkt)
270 outputf("RFB: Bad command: %d", state->data[0]);
273 outputf("RFB: Bad state");
278 static err_t rfb_recv(void *arg, struct tcp_pcb *pcb,
279 struct pbuf *p, err_t err) {
280 struct rfb_state *state = arg;
285 outputf("RFB: recv err %d", err);
286 /* FIXME do something better here? */
291 outputf("RFB: Connection closed");
292 close_conn(pcb, state);
296 if (p->tot_len > (RFB_BUF_SIZE - state->writepos)) {
298 outputf("RFB: Overflow!");
299 close_conn(pcb, state);
303 outputf("RFB: Processing %d", p->tot_len);
304 pbuf_copy_partial(p, state->data + state->writepos, p->tot_len, 0);
305 tcp_recved(pcb, p->tot_len);
309 switch (recv_fsm(pcb, state)) {
315 if (state->readpos == state->writepos) {
321 state->data + state->readpos,
322 state->writepos - state->readpos);
327 outputf("RFB: Protocol error");
328 close_conn(pcb, state);
334 static err_t rfb_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
335 struct rfb_state *state;
337 LWIP_UNUSED_ARG(arg);
338 LWIP_UNUSED_ARG(err);
340 state = (struct rfb_state *)mem_malloc(sizeof(struct rfb_state));
342 /* XXX: update_server_info() should be called from the 64ms timer, and deal
343 * with screen resizes appropriately. */
344 update_server_info();
348 outputf("rfb_accept: out of memory\n");
353 tcp_recv(pcb, rfb_recv);
355 tcp_err(pcb, rfb_err);
356 tcp_poll(pcb, rfb_poll, 2);
358 tcp_write(pcb, "RFB 003.008\n", 12, 0);
370 tcp_bind(pcb, IP_ADDR_ANY, RFB_PORT);
371 pcb = tcp_listen(pcb);
372 tcp_accept(pcb, rfb_accept);