Contiki 2.5
vnc-server.c
1 /*
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. The name of the author may not be used to endorse or promote
14  * 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  *
31  * $Id: vnc-server.c,v 1.3 2010/10/19 18:29:04 adamdunkels Exp $
32  *
33  */
34 
35 /* A micro implementation of a VNC server. VNC is a protocol for
36  remote network displays. See http://www.uk.research.att.com/vnc/
37  for information about VNC.
38 
39  Initialization states:
40 
41  VNC_VERSION (send version string)
42  VNC_AUTH (send auth message)
43  VNC_INIT (send init message)
44 
45  Steady state:
46 
47  VNC_RUNNING (send RFB updates, parse incoming messages)
48 
49  What kind of message should be sent:
50 
51  SEND_NONE (No message)
52  SEND_BLANK (Blank screen initially)
53  SEND_SCREEN (Send entire screen, initially)
54  SEND_UPDATE (Send incremental update)
55 
56 */
57 
58 #include "contiki-net.h"
59 #include "ctk/vnc-server.h"
60 #include "ctk/vnc-out.h"
61 
62 #include <string.h>
63 
64 /* RFB server initial handshaking string. */
65 #define RFB_SERVER_VERSION_STRING rfb_server_version_string
66 
67 /* "RFB 003.003" */
68 static u8_t rfb_server_version_string[12] = {82,70,66,32,48,48,51,46,48,48,51,10};
69 
70 /* uVNC */
71 static u8_t uvnc_name[4] = {117,86,78,67};
72 #if 1
73 #define PRINTF(x)
74 #else
75 #define PRINTF(x) printf x
76 #endif
77 
78 /*-----------------------------------------------------------------------------------*/
79 u8_t
80 vnc_server_draw_rect(u8_t *ptr, u16_t x, u16_t y, u16_t w, u16_t h, u8_t c)
81 {
82  register struct rfb_fb_update_rect_hdr *recthdr;
83  struct rfb_rre_hdr *rrehdr;
84 
85  recthdr = (struct rfb_fb_update_rect_hdr *)ptr;
86  rrehdr = (struct rfb_rre_hdr *)(ptr + sizeof(struct rfb_fb_update_rect_hdr));
87 
88  recthdr->rect.x = x;
89  recthdr->rect.y = y;
90  recthdr->rect.w = w;
91  recthdr->rect.h = h;
92  recthdr->encoding[0] =
93  recthdr->encoding[1] =
94  recthdr->encoding[2] = 0;
95  recthdr->encoding[3] = RFB_ENC_RRE;
96 
97  rrehdr->subrects[0] =
98  rrehdr->subrects[1] = 0;
99  rrehdr->bgpixel = c;
100 
101  return sizeof(struct rfb_fb_update_rect_hdr) + sizeof(struct rfb_rre_hdr);
102 }
103 /*-----------------------------------------------------------------------------------*/
104 void
105 vnc_server_init(void)
106 {
107  vnc_out_init();
108 }
109 /*-----------------------------------------------------------------------------------*/
110 static void
111 vnc_send_blank(struct vnc_server_state *vs)
112 {
113  switch(vs->type) {
114  case 0:
115  vnc_out_send_blank(vs);
116  break;
117  /* case 1:
118  vnc_stats_send_blank(vs);
119  break; */
120  }
121 }
122 /*-----------------------------------------------------------------------------------*/
123 static void
124 vnc_send_screen(struct vnc_server_state *vs)
125 {
126  switch(vs->type) {
127  case 0:
128  vnc_out_send_screen(vs);
129  break;
130  /* case 1:
131  vnc_stats_send_screen(vs);
132  break;*/
133  }
134 }
135 /*-----------------------------------------------------------------------------------*/
136 static void
137 vnc_send_update(struct vnc_server_state *vs)
138 {
139  switch(vs->type) {
140  case 0:
141  vnc_out_send_update(vs);
142  break;
143  /* case 1:
144  vnc_stats_send_update(vs);
145  break;*/
146  }
147 }
148 /*-----------------------------------------------------------------------------------*/
149 void
150 vnc_server_send_data(struct vnc_server_state *vs)
151 {
152  register struct rfb_server_init *initmsg;
153 
154  switch(vs->state) {
155  case VNC_VERSION:
156  uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING));
157  break;
158  case VNC_AUTH:
159  ((char *)uip_appdata)[0] = 0;
160  ((char *)uip_appdata)[1] = 0;
161  ((char *)uip_appdata)[2] = 0;
162  ((char *)uip_appdata)[3] = RFB_AUTH_NONE;
163  uip_send(uip_appdata, 4);
164  break;
165  case VNC_INIT:
166  initmsg = (struct rfb_server_init *)uip_appdata;
167  initmsg->width = uip_htons(vs->width);
168  initmsg->height = uip_htons(vs->height);
169  /* BGR233 pixel format. */
170  initmsg->format.bps = 8;
171  initmsg->format.depth = 8;
172  initmsg->format.endian = 1;
173  initmsg->format.truecolor = 1;
174  initmsg->format.red_max = uip_htons(7);
175  initmsg->format.green_max = uip_htons(7);
176  initmsg->format.blue_max = uip_htons(3);
177  initmsg->format.red_shift = 0;
178  initmsg->format.green_shift = 3;
179  initmsg->format.blue_shift = 6;
180  initmsg->namelength[0] = 0;
181  initmsg->namelength[1] = 0;
182  initmsg->namelength[2] = 0;
183  initmsg->namelength[3] = 4;
184  memcpy(&((char *)uip_appdata)[sizeof(struct rfb_server_init)], uvnc_name, 4);
185  /* ((char *)uip_appdata)[sizeof(struct rfb_server_init)+0] = 'u';
186  ((char *)uip_appdata)[sizeof(struct rfb_server_init)+1] = 'V';
187  ((char *)uip_appdata)[sizeof(struct rfb_server_init)+2] = 'N';
188  ((char *)uip_appdata)[sizeof(struct rfb_server_init)+3] = 'C';*/
189  uip_send(uip_appdata, sizeof(struct rfb_server_init) + 4);
190  break;
191  case VNC_RUNNING:
192  switch(vs->sendmsg) {
193  case SEND_NONE:
194  PRINTF(("Sending none\n"));
195  break;
196 
197  case SEND_BLANK:
198  case SENT_BLANK:
199  PRINTF(("Sending blank\n"));
200  vnc_send_blank(vs);
201  break;
202 
203  case SEND_SCREEN:
204  PRINTF(("Sending screen\n"));
205  vnc_send_screen(vs);
206  break;
207 
208  case SEND_UPDATE:
209  PRINTF(("Sending update\n"));
210  vnc_send_update(vs);
211  break;
212  }
213  break;
214 
215  default:
216  break;
217  }
218 
219 }
220 /*-----------------------------------------------------------------------------------*/
221 static void
222 vnc_key_event(struct vnc_server_state *vs)
223 {
224  switch(vs->type) {
225  case 0:
226  vnc_out_key_event(vs);
227  break;
228  /* case 1:
229  vnc_stats_key_event(vs);
230  break;*/
231  }
232 }
233 /*-----------------------------------------------------------------------------------*/
234 static void
235 vnc_pointer_event(struct vnc_server_state *vs)
236 {
237  switch(vs->type) {
238  case 0:
239  vnc_out_pointer_event(vs);
240  break;
241  /* case 1:
242  vnc_stats_pointer_event(vs);
243  break;*/
244  }
245 }
246 /*-----------------------------------------------------------------------------------*/
247 static u8_t
248 vnc_read_data(CC_REGISTER_ARG struct vnc_server_state *vs)
249 {
250  u8_t *appdata;
251  u16_t len;
252  struct rfb_fb_update_request *req;
253  /* u8_t niter;*/
254 
255  len = uip_datalen();
256  appdata = (u8_t *)uip_appdata;
257 
258  /* First, check if there is data left to discard since last read. */
259  if(vs->readlen > 0) {
260  appdata += vs->readlen;
261  if(len > vs->readlen) {
262  len -= vs->readlen;
263  vs->readlen = 0;
264  } else {
265  vs->readlen -= len;
266  len = 0;
267  }
268  }
269 
270  if(vs->readlen != 0) {
271  return 1;
272  }
273 
274  /* All data read and ignored, parse next message. */
275  /* for(niter = 32; niter > 0 && len > 0; --niter) {*/
276  while(len > 0) {
277  switch(vs->state) {
278  case VNC_VERSION:
279  case VNC_VERSION2:
280  PRINTF(("Read in version\n"));
281  /* Receive and ignore client version string (12 bytes). */
282  vs->state = VNC_AUTH;
283  vs->readlen = 12;
284  break;
285 
286  case VNC_AUTH:
287  case VNC_AUTH2:
288  PRINTF(("Read in auth \n"));
289  /* Read and discard initialization from client (1 byte). */
290  vs->readlen = 1;
291  vs->state = VNC_INIT;
292  break;
293 
294  case VNC_INIT:
295  case VNC_INIT2:
296  PRINTF(("Read in init \n"));
297  vs->readlen = 0;
298  vs->state = VNC_RUNNING;
299 
300  case VNC_RUNNING:
301  /* Handle all client events. */
302  switch(*appdata) {
303  case RFB_SET_PIXEL_FORMAT:
304  PRINTF(("Set pixel format\n"));
305  vs->readlen = sizeof(struct rfb_set_pixel_format);
306  /* Check if client runs with BGR233 format. If not, abort the
307  connection. */
308  /* XXX: not implemented yet. */
309  break;
310 
311  case RFB_FIX_COLORMAP_ENTRIES:
312  PRINTF(("Fix colormap entries\n"));
313  return 0;
314 
315  case RFB_SET_ENCODINGS:
316  PRINTF(("Set encodings\n"));
317  vs->readlen = sizeof(struct rfb_set_encoding);
318  vs->readlen += uip_htons(((struct rfb_set_encoding *)appdata)->encodings) * 4;
319  /* Make sure that client supports the encodings we use. */
320  /* XXX: not implemented yet. */
321  break;
322 
323  case RFB_FB_UPDATE_REQ:
324  PRINTF(("Update request\n"));
325  vs->update_requested = 1;
326  vs->readlen = sizeof(struct rfb_fb_update_request);
327  /* blank the screen initially */
328  req = (struct rfb_fb_update_request *)appdata;
329  if(req->incremental == 0) {
330  /* vs->sendmsg = SEND_BLANK;*/
331  vnc_out_update_area(vs, 0, 0, vs->w, vs->h);
332  }
333  break;
334 
335  case RFB_KEY_EVENT:
336  vs->readlen = sizeof(struct rfb_key_event);
337  vnc_key_event(vs);
338  break;
339 
340  case RFB_POINTER_EVENT:
341  vs->readlen = sizeof(struct rfb_pointer_event);
342  vnc_pointer_event(vs);
343  break;
344 
345  case RFB_CLIENT_CUT_TEXT:
346  PRINTF(("Client cut text\n"));
347 
348  if(((struct rfb_client_cut_text *)appdata)->len[0] != 0 ||
349  ((struct rfb_client_cut_text *)appdata)->len[1] != 0) {
350  return 0;
351 
352  }
353  vs->readlen = sizeof(struct rfb_client_cut_text) +
354  (((struct rfb_client_cut_text *)appdata)->len[2] << 8) +
355  ((struct rfb_client_cut_text *)appdata)->len[3];
356  /* return 0;*/
357  break;
358 
359  default:
360  PRINTF(("Unknown message %d\n", *appdata));
361  return 0;
362  }
363  break;
364 
365  default:
366  return 0;
367  }
368 
369  if(vs->readlen > 0) {
370  if(len > vs->readlen) {
371  len -= vs->readlen;
372  appdata += vs->readlen;
373  vs->readlen = 0;
374  } else {
375  vs->readlen -= len;
376  len = 0;
377  }
378  } else {
379  /* Lost data. */
380  break;
381  }
382 
383  }
384 
385  /* if(vs->readlen > 0) {
386  printf("More data %d\n", vs->readlen);
387  }*/
388 
389  /* uip_appdata = appdata;*/
390 
391  return 1;
392 }
393 /*-----------------------------------------------------------------------------------*/
394 static void
395 vnc_new(CC_REGISTER_ARG struct vnc_server_state *vs)
396 {
397  vs->counter = 0;
398  vs->readlen = 0;
399  vs->sendmsg = SEND_NONE;
400  vs->update_requested = 1;
401  switch(vs->type) {
402  case 0:
403  vnc_out_new(vs);
404  break;
405  /* case 1:
406  vnc_stats_new(vs);
407  break;*/
408  }
409 }
410 /*-----------------------------------------------------------------------------------*/
411 static void
412 vnc_acked(CC_REGISTER_ARG struct vnc_server_state *vs)
413 {
414  switch(vs->state) {
415  case VNC_VERSION:
416  vs->state = VNC_VERSION2;
417  break;
418 
419  case VNC_AUTH:
420  vs->state = VNC_AUTH2;
421  break;
422 
423  case VNC_INIT:
424  vs->state = VNC_INIT2;
425  break;
426 
427  case VNC_RUNNING:
428  switch(vs->type) {
429  case 0:
430  vnc_out_acked(vs);
431  break;
432  /* case 1:
433  vnc_stats_acked(vs);
434  break;*/
435  }
436  break;
437  }
438 }
439 /*-----------------------------------------------------------------------------------*/
440 void
441 vnc_server_appcall(struct vnc_server_state *vs)
442 {
443 
444  vs->type = uip_htons(uip_conn->lport) - 5900;
445 
446  if(uip_connected()) {
447  vnc_new(vs);
448  vs->state = VNC_VERSION;
449  vnc_server_send_data(vs);
450  return;
451  }
452  if(uip_acked()) {
453  PRINTF(("Acked\n"));
454  vnc_acked(vs);
455  }
456 
457  if(uip_newdata()) {
458  PRINTF(("Newdata\n"));
459  vs->counter = 0;
460  if(vnc_read_data(vs) == 0) {
461  uip_abort();
462  return;
463  }
464  }
465 
466  if(uip_rexmit()) {
467  PRINTF(("Rexmit\n"));
468  }
469 
470 
471  if(uip_newdata() ||
472  uip_rexmit() ||
473  uip_acked()) {
474  vnc_server_send_data(vs);
475  } else if(uip_poll()) {
476  ++vs->counter;
477  /* Abort connection after about 20 seconds of inactivity. */
478  if(vs->counter >= 40) {
479  uip_abort();
480  return;
481  }
482 
483  vnc_out_poll(vs);
484  }
485 
486 }
487 /*-----------------------------------------------------------------------------------*/