blob: 3d60aaa19519d7c737e30c1ce70781508415a66c [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 *
34 * $Id: vnc-viewer.c,v 1.1 2003/04/08 19:41:23 adamdunkels Exp $
35 *
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
47#include <string.h> /* XXX for bcopy */
48#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
56#if 1
57#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));
89 conn = uip_connect(server, 5900 + display);
90 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
245 bcopy(data, &(vs->buffer[vs->buffersize]), datalen);
246
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. */
312static void
313recv_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;
332 return;
333
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;
344 return;
345
346 default:
347 break;
348 }
349
350 }
351 PRINTF(("Bad encoding %02x%02x%02x%02x\n", rhdr->encoding[0],
352 rhdr->encoding[1],rhdr->encoding[2],rhdr->encoding[3]));
353
354}
355/*-----------------------------------------------------------------------------------*/
356/* identify_data():
357 *
358 * This function looks at the state of the connection (i.e., if it is
359 * handshaking or in steady-state) as well as on the contents of the
360 * incoming message and sets in state of the connection
361 * accordingly.
362 */
363static u16_t
364identify_data(register u8_t *data, u16_t datalen)
365{
366 switch(vs->waitmsg) {
367 case VNC_WAIT_VERSION:
368 /* Expecting version string (12 bytes). */
369 return 12;
370 break;
371 case VNC_WAIT_AUTH:
372 return 4;
373 break;
374 case VNC_WAIT_AUTH_RESPONSE:
375 return 1;
376 break;
377 case VNC_WAIT_SINIT:
378 /* XXX: We should check that the entire message header is
379 received, otherwise we should buffer it. */
380 return sizeof(struct rfb_server_init) +
381 ((struct rfb_server_init *)uip_appdata)->namelength[3] +
382 ((struct rfb_server_init *)uip_appdata)->namelength[2];
383
384 case VNC_WAIT_UPDATE:
385 case VNC_WAIT_NONE:
386 switch(*data) {
387 case RFB_FB_UPDATE:
388 return sizeof(struct rfb_fb_update);
389
390 case RFB_BELL:
391 return 1;
392
393 case RFB_SERVER_CUT_TEXT:
394 PRINTF(("Cut text received, unhandled\n"));
395 return 8 + (data[6] << 8) + data[7];
396
397 case RFB_SET_COLORMAP_ENTRIES:
398 uip_abort();
399 PRINTF(("Set colormap entries received, unhandled\n"));
400 return 0;
401
402 default:
403 uip_abort();
404 PRINTF(("Weird message type received (%d)\n", *(u8_t *)uip_appdata));
405 return 0;
406 }
407 break;
408
409 case VNC_WAIT_UPDATE_RECT:
410 return sizeof(struct rfb_fb_update_rect_hdr);
411
412 default:
413 PRINTF(("identify: bad waitmsg %d\n", vs->waitmsg));
414 }
415
416 return 0;
417}
418/*-----------------------------------------------------------------------------------*/
419/* handle_data():
420 *
421 * Handles the data.
422 */
423static void
424handle_data(register u8_t *data, u16_t datalen)
425{
426
427 switch(vs->waitmsg) {
428 case VNC_WAIT_VERSION:
429 /* Make sure we get the right version string from the server. */
430 /* XXX: not implemented. */
431 PRINTF(("Got version, waiting for auth, sending version\n"));
432 vs->waitmsg = VNC_WAIT_AUTH;
433 vs->sendmsg = VNC_SEND_VERSION;
434 break;
435 case VNC_WAIT_AUTH:
436 switch(data[3]) {
437 case RFB_AUTH_FAILED:
438 PRINTF(("Connection failed.\n"));
439 uip_abort();
440 return;
441
442 case RFB_AUTH_NONE:
443 vs->sendmsg = VNC_SEND_CINIT;
444 vs->waitmsg = VNC_WAIT_SINIT;
445 PRINTF(("No authentication needed.\n"));
446 break;
447 case RFB_AUTH_VNC:
448 vs->sendmsg = VNC_SEND_AUTH;
449 vs->waitmsg = VNC_WAIT_AUTH_RESPONSE;
450 PRINTF(("VNC authentication needed.\n"));
451 break;
452 }
453 break;
454 case VNC_WAIT_SINIT:
455 /* PRINTF(("Server init: w %d h %d, bps %d, d %d, name '%s'\n",
456 htons(((struct rfb_server_init *)data)->width),
457 htons(((struct rfb_server_init *)data)->height),
458 ((struct rfb_server_init *)data)->format.bps,
459 ((struct rfb_server_init *)data)->format.depth,
460 ((u8_t *)data + sizeof(struct rfb_server_init))));*/
461 vs->w = htons(((struct rfb_server_init *)data)->width);
462 vs->h = htons(((struct rfb_server_init *)data)->height);
463 vs->sendmsg = VNC_SEND_PFMT;
464 vs->waitmsg = VNC_WAIT_NONE;
465 break;
466
467 case VNC_WAIT_UPDATE:
468 case VNC_WAIT_NONE:
469 switch(*data) {
470 case RFB_FB_UPDATE:
471 vs->waitmsg = VNC_WAIT_UPDATE_RECT;
472 vs->rectsleft = htons(((struct rfb_fb_update *)data)->rects);
473 break;
474
475 case RFB_BELL:
476 PRINTF(("BELL\n"));
477 break;
478
479 case RFB_SERVER_CUT_TEXT:
480 PRINTF(("Cut text received, unhandled\n"));
481 break;
482
483 case RFB_SET_COLORMAP_ENTRIES:
484 PRINTF(("Set colormap entries received, unhandled\n"));
485 break;
486
487 default:
488 PRINTF(("Weird message type received (%d)\n", *(u8_t *)data));
489 break;
490 }
491 break;
492
493 case VNC_WAIT_UPDATE_RECT:
494 --vs->rectsleft;
495 if(vs->rectsleft > 0) {
496 vs->waitmsg = VNC_WAIT_UPDATE_RECT;
497 } else {
498 vs->waitmsg = VNC_WAIT_NONE;
499 vs->sendmsg = VNC_SEND_NONE;
500 vs->rectstate = VNC_RECTSTATE_NONE;
501 }
502 recv_update_rect((struct rfb_fb_update_rect_hdr *)data, datalen);
503 break;
504 }
505}
506/*-----------------------------------------------------------------------------------*/
507/* newdata():
508 *
509 * Called whenever new data arrives.
510 *
511 * First, checks if data needs to be buffered before a previously
512 * identified request can be fulfilled. If so, the incoming data is
513 * buffered and the data handler is called. If no data needs to be
514 * buffered, the code proceeds to identify the incoming request. If
515 * the incoming request can be processed immediately (i.e., all data
516 * is contained in this message) the data handler is invoked. If data
517 * has to be buffered to fulfill the request, this is noted and taken
518 * care of the next time this function is invoked (i.e., for the next
519 * incoming data chunk).
520 */
521static u8_t
522newdata(void)
523{
524 u16_t datalen;
525 u16_t readlen;
526 u8_t *dataptr;
527
528 datalen = uip_datalen();
529 dataptr = (u8_t *)uip_appdata;
530
531 /* If we are in a "rectstate", meaning that the incoming data is
532 part of a rectangle that is being incrementaly drawn on the
533 screen, we handle that first. */
534 if(vs->rectstate != VNC_RECTSTATE_NONE) {
535 readlen = recv_rectstate(dataptr, datalen);
536 datalen -= readlen;
537 dataptr += readlen;
538 }
539
540 while(vs->bufferleft > 0 && datalen > 0) {
541 if(datalen >= vs->bufferleft) {
542 /* There is more data in the incoming chunk than we need to
543 buffer, so we buffer as much as we can and handle the
544 buffered data, and repeat the (identify->buffer->handle)
545 sequence for the data that is left in the incoming chunk. */
546 datalen -= vs->bufferleft;
547 dataptr += vs->bufferleft;
548 buffer_data((u8_t *)uip_appdata, vs->bufferleft);
549 handle_data(vs->buffer, vs->buffersize);
550 clearbuffer();
551 } else { /* datalen < vs->bufferleft */
552 /* We need to buffer more data than was received with this
553 chunk, so we buffer the avaliable data and return. */
554 buffer_data(dataptr, datalen);
555 return 0;
556 }
557 }
558
559 while(datalen > 0) {
560
561 if(vs->rectstate != VNC_RECTSTATE_NONE) {
562 readlen = recv_rectstate(dataptr, datalen);
563 datalen -= readlen;
564 dataptr += readlen;
565 } else {
566
567 /* We get here if there is data to be identified in the incoming
568 chunk. */
569 readlen = identify_data(dataptr, datalen);
570
571 if(readlen == 0) {
572 PRINTF(("Identify returned 0\n"));
573 return 0;
574 }
575
576 /* The data has been identified and the amount of data that
577 needs to be read to be able to process the data is in the
578 "readlen" variable. If the incoming chunk contains enough
579 data, we handle it directly, otherwise we buffer the incoming
580 data and set the state so that we know that there is more
581 data to be buffered. */
582 if(readlen > datalen) {
583 clearbuffer(); /* Should not be needed, but just in case... */
584 vs->bufferleft = readlen;
585 buffer_data(dataptr, datalen);
586 return 0;
587 }
588 if(readlen <= datalen) {
589 handle_data(dataptr, readlen);
590 datalen -= readlen;
591 dataptr += readlen;
592 }
593 }
594 }
595
596 return 0;
597}
598/*-----------------------------------------------------------------------------------*/
599/* Called when there is nothing else to do - checks for any pending
600 events (mouse movements or keypresses). If no events are found, it
601 makes sure that we send out an incremental update request. */
602static void
603check_events(void)
604{
605 if(vs->sendmsg == VNC_SEND_NONE &&
606 vs->eventptr_next != vs->eventptr_acked &&
607 vs->eventptr_acked == vs->eventptr_unacked) {
608 vs->sendmsg = VNC_SEND_EVENTS;
609 }
610}
611/*-----------------------------------------------------------------------------------*/
612static void
613request_update(void)
614{
615 if(vs->sendmsg == VNC_SEND_NONE) {
616 vs->sendmsg = VNC_SEND_UPDATERQ_INC;
617 vs->waitmsg = VNC_WAIT_UPDATE;
618 }
619}
620/*-----------------------------------------------------------------------------------*/
621static void
622acked(void)
623{
624 switch(vs->sendmsg) {
625 case VNC_SEND_PFMT:
626 vs->sendmsg = VNC_SEND_ENCODINGS;
627 break;
628 case VNC_SEND_ENCODINGS:
629 vs->sendmsg = VNC_SEND_UPDATERQ;
630 vs->waitmsg = VNC_WAIT_UPDATE;
631 clearbuffer();
632 break;
633 case VNC_SEND_EVENTS:
634 vs->eventptr_acked = vs->eventptr_unacked;
635 vs->sendmsg = VNC_SEND_NONE;
636 check_events();
637 break;
638 default:
639 vs->sendmsg = VNC_SEND_NONE;
640 break;
641 }
642}
643/*-----------------------------------------------------------------------------------*/
644void
645vnc_viewer_app(struct vnc_viewer_state *nullptr)
646{
647 if(vs->close == 1) {
648 uip_close();
649 return;
650 }
651
652 if(uip_connected()) {
653 vs->sendmsg = VNC_SEND_NONE;
654 vs->waitmsg = VNC_WAIT_VERSION;
655 return;
656 }
657
658 if(uip_acked()) {
659 acked();
660 }
661
662 if(uip_newdata()) {
663 newdata();
664 }
665
666 if(vs->sendmsg == VNC_SEND_NONE &&
667 vs->waitmsg == VNC_WAIT_NONE &&
668 vs->rectstate == VNC_RECTSTATE_NONE) {
669 check_events();
670 request_update();
671 }
672
673 if(uip_rexmit() ||
674 uip_newdata() ||
675 uip_acked()) {
676 senddata();
677 } else if(uip_poll()) {
678 check_events();
679 senddata();
680 }
681}
682/*-----------------------------------------------------------------------------------*/
683void
684vnc_viewer_post_event(u8_t type,
685 u16_t data1, u16_t data2,
686 u16_t data3, u16_t data4)
687{
688 register struct vnc_event *ev;
689 struct vnc_event *ev0;
690
691 ev0 = &(vs->event_queue[(vs->eventptr_next - 1) % VNC_EVENTQUEUE_SIZE]);
692
693 ev = &(vs->event_queue[vs->eventptr_next]);
694 switch(type) {
695 case VNC_POINTER_EVENT:
696 if(0 && vs->eventptr_next != vs->eventptr_acked &&
697 ev0->type == VNC_POINTER_EVENT &&
698 data1 == ev0->ev.ptr.buttonmask) {
699 ev0->ev.ptr.x = data2;
700 ev0->ev.ptr.y = data3;
701 return;
702 } else {
703 ev->type = type;
704 ev->ev.ptr.buttonmask = data1;
705 ev->ev.ptr.x = data2;
706 ev->ev.ptr.y = data3;
707 }
708 break;
709 case VNC_KEY_EVENT:
710 PRINTF(("Key event posted\n"));
711 ev->type = type;
712 ev->ev.key.down = data1;
713 ev->ev.key.key = data2;
714 break;
715 case VNC_UPDATERQ_EVENT:
716 PRINTF(("Update request event posted\n"));
717 ev->type = type;
718 ev->ev.urq.x = data1;
719 ev->ev.urq.y = data2;
720 ev->ev.urq.w = data3;
721 ev->ev.urq.h = data4;
722 break;
723 }
724 vs->eventptr_next = (vs->eventptr_next + 1) % VNC_EVENTQUEUE_SIZE;
725}
726/*-----------------------------------------------------------------------------------*/