blob: 8deb6bb22946cdd79786f74f564fbf41831e37e4 [file] [log] [blame]
adamdunkelse0cc0582003-04-08 19:41:23 +00001/*
2 * Copyright (c) 2001, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
adamdunkels06f897e2004-06-06 05:59:20 +000013 * 3. The name of the author may not be used to endorse or promote
adamdunkelse0cc0582003-04-08 19:41:23 +000014 * products derived from this software without specific prior
15 * written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * This file is part of the uIP TCP/IP stack.
30 *
adamdunkels0c388812004-09-12 07:32:05 +000031 * $Id: vnc-viewer.c,v 1.9 2004/09/12 07:32:05 adamdunkels Exp $
adamdunkelse0cc0582003-04-08 19:41:23 +000032 *
33 */
34
35/* A micro implementation of a VNC client. VNC is a protocol for
36 remote network displays. See http://www.uk.research.att.com/vnc/
37 for information about VNC.
38*/
39
40#include "vnc-draw.h"
41#include "uip.h"
42#include "vnc-viewer.h"
43
adamdunkelsd00b45a2003-11-27 15:46:45 +000044#include <string.h> /* XXX for memcpy */
adamdunkelse0cc0582003-04-08 19:41:23 +000045#include <stdio.h> /* XXX for printf */
46
47/* RFB server initial handshaking string. */
48#define RFB_SERVER_VERSION_STRING rfb_server_version_string
49
50/* "RFB 003.003" */
adamdunkels0c388812004-09-12 07:32:05 +000051static u8_t rfb_server_version_string[12] =
52 {82,70,66,32,48,48,51,46,48,48,51,10};
adamdunkelse0cc0582003-04-08 19:41:23 +000053
adamdunkels0c388812004-09-12 07:32:05 +000054#if 0
adamdunkelse0cc0582003-04-08 19:41:23 +000055#define PRINTF(x)
56#else
57#define PRINTF(x) printf x
58#endif
59
60#ifndef NULL
61#define NULL (void *)0
62#endif
63
64static struct vnc_viewer_state vnc_viewer_state;
65#define vs (&vnc_viewer_state)
66
67/*-----------------------------------------------------------------------------------*/
68void
69vnc_viewer_init(void)
70{
71}
72/*-----------------------------------------------------------------------------------*/
73void
74vnc_viewer_close(void)
75{
76 vs->close = 1;
77}
78/*-----------------------------------------------------------------------------------*/
79void
80vnc_viewer_connect(u16_t *server, u8_t display)
81{
82 struct uip_conn *conn;
83
84 vnc_draw_init();
85
86 memset(vs, 0, sizeof(struct vnc_viewer_state));
adamdunkelsd5a69e62003-09-02 21:46:06 +000087 conn = uip_connect(server, htons(5900 + display));
adamdunkelse0cc0582003-04-08 19:41:23 +000088 if(conn == NULL) {
89 return;
90 }
adamdunkelsf2f8cb22004-07-04 11:35:07 +000091 tcp_markconn(conn, NULL);
adamdunkelse0cc0582003-04-08 19:41:23 +000092
93 vs->close = 0;
94}
95/*-----------------------------------------------------------------------------------*/
96static void
97senddata(void)
98{
99 register u8_t *dataptr;
100 u16_t dataleft;
101
102 dataptr = (u8_t *)uip_appdata;
103
104 switch(vs->sendmsg) {
105 case VNC_SEND_VERSION:
106 PRINTF(("Sending VERSION_STRING\n"));
107 uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING));
108 break;
109 case VNC_SEND_AUTH:
110 /* Send 16 bytes of encrypted challange response. */
111 /* XXX: not implemented. */
112 PRINTF(("Sending AUTH\n"));
113 uip_send(uip_appdata, 16);
114 break;
115 case VNC_SEND_CINIT:
116 PRINTF(("Sending CINIT\n"));
117 /* Send one byte of client init. */
118 *(u8_t *)dataptr = 1;
119 uip_send(uip_appdata, 1);
120 break;
121 case VNC_SEND_PFMT:
122 PRINTF(("Sending PFMT\n"));
123 ((struct rfb_set_pixel_format *)dataptr)->type = RFB_SET_PIXEL_FORMAT;
124
125 /* Set to BGR233 pixel format. */
126 ((struct rfb_set_pixel_format *)dataptr)->format.bps = 8;
127 ((struct rfb_set_pixel_format *)dataptr)->format.depth = 8;
128 ((struct rfb_set_pixel_format *)dataptr)->format.endian = 1;
129 ((struct rfb_set_pixel_format *)dataptr)->format.truecolor = 1;
130 ((struct rfb_set_pixel_format *)dataptr)->format.red_max = htons(7);
131 ((struct rfb_set_pixel_format *)dataptr)->format.green_max = htons(7);
132 ((struct rfb_set_pixel_format *)dataptr)->format.blue_max = htons(3);
133 ((struct rfb_set_pixel_format *)dataptr)->format.red_shift = 0;
134 ((struct rfb_set_pixel_format *)dataptr)->format.green_shift = 3;
135 ((struct rfb_set_pixel_format *)dataptr)->format.blue_shift = 6;
136
137 uip_send(uip_appdata, sizeof(struct rfb_set_pixel_format));
138
139 break;
140 case VNC_SEND_ENCODINGS:
141 PRINTF(("Sending ENCODINGS\n"));
142 ((struct rfb_set_encodings *)dataptr)->type = RFB_SET_ENCODINGS;
143 ((struct rfb_set_encodings *)dataptr)->encodings = htons(1);
144 dataptr += sizeof(struct rfb_set_encodings);
145 dataptr[0] = dataptr[1] = dataptr[2] = 0;
146 dataptr[3] = RFB_ENC_RAW;
147 /* ((u8_t *)dataptr + sizeof(struct rfb_set_encodings))[4] =
148 ((u8_t *)dataptr + sizeof(struct rfb_set_encodings))[5] =
149 ((u8_t *)dataptr + sizeof(struct rfb_set_encodings))[6] = 0;
150 ((u8_t *)dataptr + sizeof(struct rfb_set_encodings))[7] = RFB_ENC_RRE;*/
151 uip_send(uip_appdata, sizeof(struct rfb_set_encodings) + 4);
152 break;
153 case VNC_SEND_UPDATERQ:
154 ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ;
155 ((struct rfb_fb_update_request *)dataptr)->incremental = 0;
156 ((struct rfb_fb_update_request *)dataptr)->x = htons(vnc_draw_viewport_x());
157 ((struct rfb_fb_update_request *)dataptr)->y = htons(vnc_draw_viewport_y());
158 ((struct rfb_fb_update_request *)dataptr)->w = htons(vnc_draw_viewport_w());
159 ((struct rfb_fb_update_request *)dataptr)->h = htons(vnc_draw_viewport_h());
160 uip_send(uip_appdata, sizeof(struct rfb_fb_update_request));
161 break;
162 case VNC_SEND_UPDATERQ_INC:
163 ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ;
164 ((struct rfb_fb_update_request *)dataptr)->incremental = 1;
165 ((struct rfb_fb_update_request *)dataptr)->x = htons(vnc_draw_viewport_x());
166 ((struct rfb_fb_update_request *)dataptr)->y = htons(vnc_draw_viewport_y());
167 ((struct rfb_fb_update_request *)dataptr)->w = htons(vnc_draw_viewport_w());
168 ((struct rfb_fb_update_request *)dataptr)->h = htons(vnc_draw_viewport_h());
169 uip_send(uip_appdata, sizeof(struct rfb_fb_update_request));
170 break;
171
172 case VNC_SEND_EVENTS:
173
174 dataleft = uip_mss();
175
176 vs->eventptr_unacked = vs->eventptr_acked;
177 while(vs->eventptr_unacked != vs->eventptr_next &&
178 dataleft > sizeof(struct rfb_key_event)) {
179 switch(vs->event_queue[vs->eventptr_unacked].type) {
180 case VNC_POINTER_EVENT:
181 ((struct rfb_pointer_event *)dataptr)->type = RFB_POINTER_EVENT;
182 ((struct rfb_pointer_event *)dataptr)->buttonmask =
183 vs->event_queue[vs->eventptr_unacked].ev.ptr.buttonmask;
184 ((struct rfb_pointer_event *)dataptr)->x =
185 htons(vs->event_queue[vs->eventptr_unacked].ev.ptr.x);
186 ((struct rfb_pointer_event *)dataptr)->y =
187 htons(vs->event_queue[vs->eventptr_unacked].ev.ptr.y);
188 /* uip_send(uip_appdata, sizeof(struct rfb_pointer_event));*/
189 dataptr += sizeof(struct rfb_pointer_event);
190 dataleft -= sizeof(struct rfb_pointer_event);
191 break;
192 case VNC_KEY_EVENT:
193 PRINTF(("Send key event.\n"));
194 ((struct rfb_key_event *)dataptr)->type = RFB_KEY_EVENT;
195 ((struct rfb_key_event *)dataptr)->down =
196 vs->event_queue[vs->eventptr_unacked].ev.key.down;
197 ((struct rfb_key_event *)dataptr)->key[0] =
198 ((struct rfb_key_event *)dataptr)->key[1];
199 ((struct rfb_key_event *)dataptr)->key[2] =
200 vs->event_queue[vs->eventptr_unacked].ev.key.key >> 8;
201
202 ((struct rfb_key_event *)dataptr)->key[3] =
203 vs->event_queue[vs->eventptr_unacked].ev.key.key & 0xff;
204 /* uip_send(uip_appdata, sizeof(struct rfb_key_event));*/
205 dataptr += sizeof(struct rfb_key_event);
206 dataleft -= sizeof(struct rfb_key_event);
207 break;
208 case VNC_UPDATERQ_EVENT:
209 ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ;
210 ((struct rfb_fb_update_request *)dataptr)->incremental = 0;
211 ((struct rfb_fb_update_request *)dataptr)->x =
212 htons(vs->event_queue[vs->eventptr_unacked].ev.urq.x);
213 ((struct rfb_fb_update_request *)dataptr)->y =
214 htons(vs->event_queue[vs->eventptr_unacked].ev.urq.y);
215 ((struct rfb_fb_update_request *)dataptr)->w =
216 htons(vs->event_queue[vs->eventptr_unacked].ev.urq.w);
217 ((struct rfb_fb_update_request *)dataptr)->h =
218 htons(vs->event_queue[vs->eventptr_unacked].ev.urq.h);
219 /* uip_send(uip_appdata, sizeof(struct rfb_fb_update_request)); */
220 dataptr += sizeof(struct rfb_fb_update_request);
221 dataleft -= sizeof(struct rfb_fb_update_request);
222 break;
223 }
224 vs->eventptr_unacked = (vs->eventptr_unacked + 1) % VNC_EVENTQUEUE_SIZE;
225 }
226
227 uip_send(uip_appdata, uip_mss() - dataleft);
228 break;
229 }
230}
231/*-----------------------------------------------------------------------------------*/
232static void
233buffer_data(u8_t *data, u16_t datalen)
234{
235 PRINTF(("Buffering %d bytes of data\n", datalen));
236
237 if(vs->buffersize + datalen > VNC_BUFFERSIZE) {
238 PRINTF(("Out of buffer space!\n"));
239 vs->buffersize = 0;
240 return;
241 }
242
adamdunkelsd00b45a2003-11-27 15:46:45 +0000243 memcpy(&(vs->buffer[vs->buffersize]), data, datalen);
adamdunkelse0cc0582003-04-08 19:41:23 +0000244
245 vs->buffersize += datalen;
246 vs->bufferleft -= datalen;
247}
248/*-----------------------------------------------------------------------------------*/
249static void
250clearbuffer(void)
251{
252 PRINTF(("Clearing buffer\n"));
253 vs->buffersize = 0;
254}
255/*-----------------------------------------------------------------------------------*/
256/* Returns: the amount of bytes actually read. */
257static u16_t
258recv_rectstate(u8_t *dataptr, u16_t datalen)
259{
260 u16_t pixels;
261 u16_t pixelsleft;
262
263 switch(vs->rectstate) {
264 case VNC_RECTSTATE_RAW:
265
266 if(vs->rectstateleft > datalen) {
267 pixels = datalen;
268 vs->rectstateleft -= datalen;
269 } else {
270 pixels = vs->rectstateleft;
271 datalen = datalen - vs->rectstateleft;
272 vs->rectstateleft = 0;
273 vs->rectstate = VNC_RECTSTATE_NONE;
274 vs->sendmsg = VNC_SEND_NONE;
275 vs->waitmsg = VNC_WAIT_NONE;
276 vnc_viewer_refresh();
277 }
278
279
280 pixelsleft = pixels;
281 while(pixelsleft > 0) {
282 if(pixelsleft >= vs->rectstatex2 - vs->rectstatex) {
283 vnc_draw_pixelline(vs->rectstatex, vs->rectstatey,
284 dataptr,
285 vs->rectstatex2 - vs->rectstatex);
286 dataptr += vs->rectstatex2 - vs->rectstatex;
287 pixelsleft -= vs->rectstatex2 - vs->rectstatex;
288 vs->rectstatex = vs->rectstatex0;
289 ++vs->rectstatey;
290 vnc_viewer_refresh();
291 } else {
292 vnc_draw_pixelline(vs->rectstatex, vs->rectstatey,
293 dataptr,
294 pixelsleft);
295 vs->rectstatex += pixelsleft;
296 pixelsleft = 0;
297 }
298
299 }
300
301 break;
302 case VNC_RECTSTATE_RRE:
303 break;
304 }
305 return pixels;
306}
307/*-----------------------------------------------------------------------------------*/
308/* Returns: the amount of bytes that needs to be buffered before the
309 rect can be drawn. */
adamdunkels8539c152003-04-17 18:55:38 +0000310static unsigned short
adamdunkelse0cc0582003-04-08 19:41:23 +0000311recv_update_rect(register struct rfb_fb_update_rect_hdr *rhdr,
312 u16_t dataleft)
313{
314 struct rfb_rre_hdr *rrehdr;
315
316
317 if((rhdr->encoding[0] |
318 rhdr->encoding[1] |
319 rhdr->encoding[2]) == 0) {
320 switch(rhdr->encoding[3]) {
321 case RFB_ENC_RAW:
322 vs->rectstateleft = (u32_t)htons(rhdr->rect.w) * (u32_t)htons(rhdr->rect.h);
323 vs->rectstate = VNC_RECTSTATE_RAW;
324 vs->rectstatex0 = vs->rectstatex = htons(rhdr->rect.x);
325 vs->rectstatey0 = vs->rectstatey = htons(rhdr->rect.y);
326 vs->rectstatew = htons(rhdr->rect.w);
327 vs->rectstateh = htons(rhdr->rect.h);
328 vs->rectstatex2 = vs->rectstatex0 + vs->rectstatew;
329 vs->rectstatey2 = vs->rectstatey0 + vs->rectstateh;
adamdunkels8539c152003-04-17 18:55:38 +0000330 break;
adamdunkelse0cc0582003-04-08 19:41:23 +0000331
332 case RFB_ENC_RRE:
333 rrehdr = (struct rfb_rre_hdr *)((u8_t *)rhdr +
334 sizeof(struct rfb_fb_update_rect_hdr));
335 PRINTF(("Received RRE subrects %d (%d)\n",
336 (htons(rrehdr->subrects[1]) << 16) +
337 htons(rrehdr->subrects[0]),
338 rrehdr->bgpixel));
339 vs->rectstateleft = ((u32_t)(htons(rrehdr->subrects[1]) << 16) +
340 (u32_t)htons(rrehdr->subrects[0]));
341 vs->rectstate = VNC_RECTSTATE_RRE;
adamdunkels8539c152003-04-17 18:55:38 +0000342
343 break;
adamdunkelse0cc0582003-04-08 19:41:23 +0000344
345 default:
adamdunkels8539c152003-04-17 18:55:38 +0000346 PRINTF(("Bad encoding %02x%02x%02x%02x\n", rhdr->encoding[0],
347 rhdr->encoding[1],rhdr->encoding[2],rhdr->encoding[3]));
adamdunkelse0cc0582003-04-08 19:41:23 +0000348 break;
349 }
350
351 }
adamdunkelse0cc0582003-04-08 19:41:23 +0000352
adamdunkels8539c152003-04-17 18:55:38 +0000353 return 0;
354
355 PRINTF(("recv_update_rect: returning%d\n", vs->rectstateleft));
356 return sizeof(struct rfb_fb_update_rect_hdr) + vs->rectstateleft;
adamdunkelse0cc0582003-04-08 19:41:23 +0000357}
358/*-----------------------------------------------------------------------------------*/
359/* identify_data():
360 *
361 * This function looks at the state of the connection (i.e., if it is
362 * handshaking or in steady-state) as well as on the contents of the
adamdunkels8539c152003-04-17 18:55:38 +0000363 * incoming message and returns the number of bytes of data that is to
364 * be expected.
adamdunkelse0cc0582003-04-08 19:41:23 +0000365 */
366static u16_t
367identify_data(register u8_t *data, u16_t datalen)
368{
369 switch(vs->waitmsg) {
370 case VNC_WAIT_VERSION:
371 /* Expecting version string (12 bytes). */
372 return 12;
373 break;
374 case VNC_WAIT_AUTH:
375 return 4;
376 break;
377 case VNC_WAIT_AUTH_RESPONSE:
378 return 1;
379 break;
380 case VNC_WAIT_SINIT:
381 /* XXX: We should check that the entire message header is
382 received, otherwise we should buffer it. */
383 return sizeof(struct rfb_server_init) +
384 ((struct rfb_server_init *)uip_appdata)->namelength[3] +
385 ((struct rfb_server_init *)uip_appdata)->namelength[2];
386
387 case VNC_WAIT_UPDATE:
388 case VNC_WAIT_NONE:
389 switch(*data) {
390 case RFB_FB_UPDATE:
adamdunkels8539c152003-04-17 18:55:38 +0000391 PRINTF(("RFB FB UPDATE received\n"));
adamdunkelse0cc0582003-04-08 19:41:23 +0000392 return sizeof(struct rfb_fb_update);
393
394 case RFB_BELL:
395 return 1;
396
397 case RFB_SERVER_CUT_TEXT:
398 PRINTF(("Cut text received, unhandled\n"));
399 return 8 + (data[6] << 8) + data[7];
400
401 case RFB_SET_COLORMAP_ENTRIES:
402 uip_abort();
403 PRINTF(("Set colormap entries received, unhandled\n"));
404 return 0;
405
406 default:
407 uip_abort();
408 PRINTF(("Weird message type received (%d)\n", *(u8_t *)uip_appdata));
409 return 0;
410 }
411 break;
412
413 case VNC_WAIT_UPDATE_RECT:
414 return sizeof(struct rfb_fb_update_rect_hdr);
415
416 default:
417 PRINTF(("identify: bad waitmsg %d\n", vs->waitmsg));
418 }
419
420 return 0;
421}
422/*-----------------------------------------------------------------------------------*/
423/* handle_data():
424 *
425 * Handles the data.
426 */
adamdunkels8539c152003-04-17 18:55:38 +0000427static unsigned short
adamdunkelse0cc0582003-04-08 19:41:23 +0000428handle_data(register u8_t *data, u16_t datalen)
429{
430
431 switch(vs->waitmsg) {
432 case VNC_WAIT_VERSION:
433 /* Make sure we get the right version string from the server. */
434 /* XXX: not implemented. */
435 PRINTF(("Got version, waiting for auth, sending version\n"));
436 vs->waitmsg = VNC_WAIT_AUTH;
437 vs->sendmsg = VNC_SEND_VERSION;
438 break;
439 case VNC_WAIT_AUTH:
440 switch(data[3]) {
441 case RFB_AUTH_FAILED:
442 PRINTF(("Connection failed.\n"));
443 uip_abort();
adamdunkels8539c152003-04-17 18:55:38 +0000444 return 0;
adamdunkelse0cc0582003-04-08 19:41:23 +0000445
446 case RFB_AUTH_NONE:
447 vs->sendmsg = VNC_SEND_CINIT;
448 vs->waitmsg = VNC_WAIT_SINIT;
449 PRINTF(("No authentication needed.\n"));
450 break;
451 case RFB_AUTH_VNC:
452 vs->sendmsg = VNC_SEND_AUTH;
453 vs->waitmsg = VNC_WAIT_AUTH_RESPONSE;
454 PRINTF(("VNC authentication needed.\n"));
455 break;
456 }
457 break;
458 case VNC_WAIT_SINIT:
459 /* PRINTF(("Server init: w %d h %d, bps %d, d %d, name '%s'\n",
460 htons(((struct rfb_server_init *)data)->width),
461 htons(((struct rfb_server_init *)data)->height),
462 ((struct rfb_server_init *)data)->format.bps,
463 ((struct rfb_server_init *)data)->format.depth,
464 ((u8_t *)data + sizeof(struct rfb_server_init))));*/
465 vs->w = htons(((struct rfb_server_init *)data)->width);
466 vs->h = htons(((struct rfb_server_init *)data)->height);
467 vs->sendmsg = VNC_SEND_PFMT;
468 vs->waitmsg = VNC_WAIT_NONE;
469 break;
470
471 case VNC_WAIT_UPDATE:
472 case VNC_WAIT_NONE:
473 switch(*data) {
474 case RFB_FB_UPDATE:
475 vs->waitmsg = VNC_WAIT_UPDATE_RECT;
476 vs->rectsleft = htons(((struct rfb_fb_update *)data)->rects);
adamdunkels8539c152003-04-17 18:55:38 +0000477 PRINTF(("Handling RFB FB UPDATE for %d rects\n", vs->rectsleft));
adamdunkelse0cc0582003-04-08 19:41:23 +0000478 break;
479
480 case RFB_BELL:
481 PRINTF(("BELL\n"));
482 break;
483
484 case RFB_SERVER_CUT_TEXT:
485 PRINTF(("Cut text received, unhandled\n"));
486 break;
487
488 case RFB_SET_COLORMAP_ENTRIES:
489 PRINTF(("Set colormap entries received, unhandled\n"));
490 break;
491
492 default:
493 PRINTF(("Weird message type received (%d)\n", *(u8_t *)data));
494 break;
495 }
496 break;
497
498 case VNC_WAIT_UPDATE_RECT:
adamdunkels8539c152003-04-17 18:55:38 +0000499 PRINTF(("Handling data in WAIT_UPDATE_RECT, %d rects left (%d bytes)\n", vs->rectsleft, datalen));
adamdunkelse0cc0582003-04-08 19:41:23 +0000500 --vs->rectsleft;
501 if(vs->rectsleft > 0) {
502 vs->waitmsg = VNC_WAIT_UPDATE_RECT;
503 } else {
504 vs->waitmsg = VNC_WAIT_NONE;
505 vs->sendmsg = VNC_SEND_NONE;
506 vs->rectstate = VNC_RECTSTATE_NONE;
507 }
adamdunkels8539c152003-04-17 18:55:38 +0000508 return recv_update_rect((struct rfb_fb_update_rect_hdr *)data, datalen);
adamdunkelse0cc0582003-04-08 19:41:23 +0000509 break;
510 }
adamdunkels8539c152003-04-17 18:55:38 +0000511 return 0;
adamdunkelse0cc0582003-04-08 19:41:23 +0000512}
513/*-----------------------------------------------------------------------------------*/
514/* newdata():
515 *
516 * Called whenever new data arrives.
517 *
518 * First, checks if data needs to be buffered before a previously
519 * identified request can be fulfilled. If so, the incoming data is
520 * buffered and the data handler is called. If no data needs to be
521 * buffered, the code proceeds to identify the incoming request. If
522 * the incoming request can be processed immediately (i.e., all data
523 * is contained in this message) the data handler is invoked. If data
524 * has to be buffered to fulfill the request, this is noted and taken
525 * care of the next time this function is invoked (i.e., for the next
526 * incoming data chunk).
527 */
528static u8_t
529newdata(void)
530{
531 u16_t datalen;
532 u16_t readlen;
533 u8_t *dataptr;
534
535 datalen = uip_datalen();
536 dataptr = (u8_t *)uip_appdata;
537
adamdunkels8539c152003-04-17 18:55:38 +0000538 PRINTF(("newdata: %d bytes\n", datalen));
539
adamdunkelse0cc0582003-04-08 19:41:23 +0000540 /* If we are in a "rectstate", meaning that the incoming data is
541 part of a rectangle that is being incrementaly drawn on the
542 screen, we handle that first. */
543 if(vs->rectstate != VNC_RECTSTATE_NONE) {
544 readlen = recv_rectstate(dataptr, datalen);
adamdunkels8539c152003-04-17 18:55:38 +0000545 PRINTF(("newdata: vs->rectstate %d, datalen %d, readlen %d\n",
546 vs->rectstate, datalen, readlen));
adamdunkelse0cc0582003-04-08 19:41:23 +0000547 datalen -= readlen;
548 dataptr += readlen;
549 }
adamdunkels8539c152003-04-17 18:55:38 +0000550
551 /* Next, check if we are supposed to buffer data from the incoming
552 segment. */
adamdunkelse0cc0582003-04-08 19:41:23 +0000553 while(vs->bufferleft > 0 && datalen > 0) {
554 if(datalen >= vs->bufferleft) {
555 /* There is more data in the incoming chunk than we need to
556 buffer, so we buffer as much as we can and handle the
557 buffered data, and repeat the (identify->buffer->handle)
558 sequence for the data that is left in the incoming chunk. */
559 datalen -= vs->bufferleft;
560 dataptr += vs->bufferleft;
561 buffer_data((u8_t *)uip_appdata, vs->bufferleft);
562 handle_data(vs->buffer, vs->buffersize);
563 clearbuffer();
564 } else { /* datalen < vs->bufferleft */
565 /* We need to buffer more data than was received with this
566 chunk, so we buffer the avaliable data and return. */
567 buffer_data(dataptr, datalen);
568 return 0;
569 }
570 }
571
adamdunkels8539c152003-04-17 18:55:38 +0000572 /* Finally, if there is data left in the segment, we handle it. */
adamdunkelse0cc0582003-04-08 19:41:23 +0000573 while(datalen > 0) {
574
575 if(vs->rectstate != VNC_RECTSTATE_NONE) {
576 readlen = recv_rectstate(dataptr, datalen);
adamdunkels8539c152003-04-17 18:55:38 +0000577 PRINTF(("newdata (2): vs->rectstate %d, datalen %d, readlen %d\n",
578 vs->rectstate, datalen, readlen));
adamdunkelse0cc0582003-04-08 19:41:23 +0000579 datalen -= readlen;
580 dataptr += readlen;
581 } else {
582
583 /* We get here if there is data to be identified in the incoming
584 chunk. */
585 readlen = identify_data(dataptr, datalen);
586
587 if(readlen == 0) {
588 PRINTF(("Identify returned 0\n"));
589 return 0;
590 }
adamdunkels8539c152003-04-17 18:55:38 +0000591
592 PRINTF(("Reading %d bytes more\n", readlen));
adamdunkelse0cc0582003-04-08 19:41:23 +0000593 /* The data has been identified and the amount of data that
594 needs to be read to be able to process the data is in the
595 "readlen" variable. If the incoming chunk contains enough
596 data, we handle it directly, otherwise we buffer the incoming
597 data and set the state so that we know that there is more
598 data to be buffered. */
599 if(readlen > datalen) {
600 clearbuffer(); /* Should not be needed, but just in case... */
601 vs->bufferleft = readlen;
602 buffer_data(dataptr, datalen);
603 return 0;
adamdunkels8539c152003-04-17 18:55:38 +0000604 }
adamdunkelse0cc0582003-04-08 19:41:23 +0000605 if(readlen <= datalen) {
adamdunkels8539c152003-04-17 18:55:38 +0000606 PRINTF(("Before handle_data %d\n", readlen));
607 readlen += handle_data(dataptr, readlen);
608 PRINTF(("After handle_data %d\n", readlen));
adamdunkelse0cc0582003-04-08 19:41:23 +0000609 datalen -= readlen;
610 dataptr += readlen;
611 }
adamdunkels8539c152003-04-17 18:55:38 +0000612
adamdunkelse0cc0582003-04-08 19:41:23 +0000613 }
adamdunkels8539c152003-04-17 18:55:38 +0000614 if(datalen > 0) {
615 PRINTF(("newdata: there is more data left after first iteration... %d\n", datalen));
616 }
617
adamdunkelse0cc0582003-04-08 19:41:23 +0000618 }
619
620 return 0;
621}
622/*-----------------------------------------------------------------------------------*/
623/* Called when there is nothing else to do - checks for any pending
624 events (mouse movements or keypresses). If no events are found, it
625 makes sure that we send out an incremental update request. */
626static void
627check_events(void)
628{
629 if(vs->sendmsg == VNC_SEND_NONE &&
630 vs->eventptr_next != vs->eventptr_acked &&
631 vs->eventptr_acked == vs->eventptr_unacked) {
632 vs->sendmsg = VNC_SEND_EVENTS;
633 }
634}
635/*-----------------------------------------------------------------------------------*/
636static void
637request_update(void)
638{
639 if(vs->sendmsg == VNC_SEND_NONE) {
640 vs->sendmsg = VNC_SEND_UPDATERQ_INC;
641 vs->waitmsg = VNC_WAIT_UPDATE;
adamdunkels8539c152003-04-17 18:55:38 +0000642 PRINTF(("request_update: requesting\n"));
643 } else {
644 PRINTF(("request_update: not requesting\n"));
adamdunkelse0cc0582003-04-08 19:41:23 +0000645 }
646}
647/*-----------------------------------------------------------------------------------*/
648static void
649acked(void)
650{
651 switch(vs->sendmsg) {
652 case VNC_SEND_PFMT:
653 vs->sendmsg = VNC_SEND_ENCODINGS;
654 break;
655 case VNC_SEND_ENCODINGS:
656 vs->sendmsg = VNC_SEND_UPDATERQ;
657 vs->waitmsg = VNC_WAIT_UPDATE;
658 clearbuffer();
659 break;
660 case VNC_SEND_EVENTS:
661 vs->eventptr_acked = vs->eventptr_unacked;
662 vs->sendmsg = VNC_SEND_NONE;
663 check_events();
664 break;
665 default:
666 vs->sendmsg = VNC_SEND_NONE;
667 break;
668 }
669}
670/*-----------------------------------------------------------------------------------*/
adamdunkelsf2f8cb22004-07-04 11:35:07 +0000671void
adamdunkels0c388812004-09-12 07:32:05 +0000672vnc_viewer_appcall(void * nullptr)
adamdunkelse0cc0582003-04-08 19:41:23 +0000673{
674 if(vs->close == 1) {
675 uip_close();
676 return;
677 }
678
679 if(uip_connected()) {
680 vs->sendmsg = VNC_SEND_NONE;
681 vs->waitmsg = VNC_WAIT_VERSION;
682 return;
683 }
684
685 if(uip_acked()) {
686 acked();
687 }
688
689 if(uip_newdata()) {
690 newdata();
691 }
692
693 if(vs->sendmsg == VNC_SEND_NONE &&
694 vs->waitmsg == VNC_WAIT_NONE &&
695 vs->rectstate == VNC_RECTSTATE_NONE) {
696 check_events();
697 request_update();
698 }
adamdunkels8539c152003-04-17 18:55:38 +0000699 PRINTF(("vs->sendmsg %d, vs->waitmsg %d, vs->rectstate %d\n",
700 vs->sendmsg, vs->waitmsg, vs->rectstate));
adamdunkelse0cc0582003-04-08 19:41:23 +0000701
702 if(uip_rexmit() ||
703 uip_newdata() ||
704 uip_acked()) {
705 senddata();
706 } else if(uip_poll()) {
707 check_events();
708 senddata();
709 }
710}
711/*-----------------------------------------------------------------------------------*/
712void
713vnc_viewer_post_event(u8_t type,
714 u16_t data1, u16_t data2,
715 u16_t data3, u16_t data4)
716{
717 register struct vnc_event *ev;
718 struct vnc_event *ev0;
719
720 ev0 = &(vs->event_queue[(vs->eventptr_next - 1) % VNC_EVENTQUEUE_SIZE]);
721
722 ev = &(vs->event_queue[vs->eventptr_next]);
723 switch(type) {
724 case VNC_POINTER_EVENT:
725 if(0 && vs->eventptr_next != vs->eventptr_acked &&
726 ev0->type == VNC_POINTER_EVENT &&
727 data1 == ev0->ev.ptr.buttonmask) {
728 ev0->ev.ptr.x = data2;
729 ev0->ev.ptr.y = data3;
730 return;
731 } else {
732 ev->type = type;
733 ev->ev.ptr.buttonmask = data1;
734 ev->ev.ptr.x = data2;
735 ev->ev.ptr.y = data3;
736 }
737 break;
738 case VNC_KEY_EVENT:
739 PRINTF(("Key event posted\n"));
740 ev->type = type;
741 ev->ev.key.down = data1;
742 ev->ev.key.key = data2;
743 break;
744 case VNC_UPDATERQ_EVENT:
745 PRINTF(("Update request event posted\n"));
746 ev->type = type;
747 ev->ev.urq.x = data1;
748 ev->ev.urq.y = data2;
749 ev->ev.urq.w = data3;
750 ev->ev.urq.h = data4;
751 break;
752 }
753 vs->eventptr_next = (vs->eventptr_next + 1) % VNC_EVENTQUEUE_SIZE;
754}
755/*-----------------------------------------------------------------------------------*/