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