vnc-server.c

00001 /*
00002  * Copyright (c) 2001, Adam Dunkels.
00003  * All rights reserved. 
00004  *
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions 
00007  * are met: 
00008  * 1. Redistributions of source code must retain the above copyright 
00009  *    notice, this list of conditions and the following disclaimer. 
00010  * 2. Redistributions in binary form must reproduce the above copyright 
00011  *    notice, this list of conditions and the following disclaimer in the 
00012  *    documentation and/or other materials provided with the distribution. 
00013  * 3. The name of the author may not be used to endorse or promote
00014  *    products derived from this software without specific prior
00015  *    written permission.  
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00018  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00021  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00023  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00025  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00026  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
00028  *
00029  * This file is part of the uIP TCP/IP stack.
00030  *
00031  * $Id: vnc-server.c,v 1.3 2010/10/19 18:29:04 adamdunkels Exp $
00032  *
00033  */
00034 
00035 /* A micro implementation of a VNC server. VNC is a protocol for
00036    remote network displays. See http://www.uk.research.att.com/vnc/
00037    for information about VNC.
00038 
00039    Initialization states:
00040 
00041    VNC_VERSION (send version string)
00042    VNC_AUTH    (send auth message)
00043    VNC_INIT    (send init message)
00044 
00045    Steady state:
00046    
00047    VNC_RUNNING (send RFB updates, parse incoming messages)
00048 
00049    What kind of message should be sent:
00050 
00051    SEND_NONE   (No message)
00052    SEND_BLANK  (Blank screen initially)
00053    SEND_SCREEN (Send entire screen, initially)
00054    SEND_UPDATE (Send incremental update)
00055 
00056 */
00057 
00058 #include "contiki-net.h"
00059 #include "ctk/vnc-server.h"
00060 #include "ctk/vnc-out.h"
00061 
00062 #include <string.h>
00063 
00064 /* RFB server initial handshaking string. */
00065 #define RFB_SERVER_VERSION_STRING rfb_server_version_string
00066 
00067 /* "RFB 003.003" */
00068 static u8_t rfb_server_version_string[12] = {82,70,66,32,48,48,51,46,48,48,51,10};
00069 
00070 /* uVNC */
00071 static u8_t uvnc_name[4] = {117,86,78,67};
00072 #if 1
00073 #define PRINTF(x)
00074 #else
00075 #define PRINTF(x) printf x
00076 #endif
00077 
00078 /*-----------------------------------------------------------------------------------*/
00079 u8_t
00080 vnc_server_draw_rect(u8_t *ptr, u16_t x, u16_t y, u16_t w, u16_t h, u8_t c)
00081 {
00082   register struct rfb_fb_update_rect_hdr *recthdr;
00083   struct rfb_rre_hdr *rrehdr;
00084 
00085   recthdr = (struct rfb_fb_update_rect_hdr *)ptr;
00086   rrehdr = (struct rfb_rre_hdr *)(ptr + sizeof(struct rfb_fb_update_rect_hdr));
00087   
00088   recthdr->rect.x = x;
00089   recthdr->rect.y = y;
00090   recthdr->rect.w = w;
00091   recthdr->rect.h = h; 
00092   recthdr->encoding[0] =
00093     recthdr->encoding[1] =
00094     recthdr->encoding[2] = 0;
00095   recthdr->encoding[3] = RFB_ENC_RRE;
00096       
00097   rrehdr->subrects[0] =
00098     rrehdr->subrects[1] = 0;
00099   rrehdr->bgpixel = c;
00100       
00101   return sizeof(struct rfb_fb_update_rect_hdr) + sizeof(struct rfb_rre_hdr);
00102 }
00103 /*-----------------------------------------------------------------------------------*/
00104 void
00105 vnc_server_init(void)
00106 {
00107   vnc_out_init();
00108 }
00109 /*-----------------------------------------------------------------------------------*/
00110 static void
00111 vnc_send_blank(struct vnc_server_state *vs)
00112 {
00113   switch(vs->type) {
00114   case 0:       
00115     vnc_out_send_blank(vs);
00116     break;
00117     /*  case 1:
00118     vnc_stats_send_blank(vs);
00119     break;   */
00120   }
00121 }
00122 /*-----------------------------------------------------------------------------------*/
00123 static void
00124 vnc_send_screen(struct vnc_server_state *vs)
00125 {
00126   switch(vs->type) {
00127   case 0:       
00128     vnc_out_send_screen(vs);
00129     break;
00130     /*  case 1:
00131     vnc_stats_send_screen(vs);
00132     break;*/
00133   }
00134 }
00135 /*-----------------------------------------------------------------------------------*/
00136 static void
00137 vnc_send_update(struct vnc_server_state *vs)
00138 {
00139   switch(vs->type) {
00140   case 0:       
00141     vnc_out_send_update(vs);
00142     break;
00143     /*  case 1:
00144     vnc_stats_send_update(vs);
00145     break;*/
00146   }
00147 }
00148 /*-----------------------------------------------------------------------------------*/
00149 void
00150 vnc_server_send_data(struct vnc_server_state *vs)
00151 {
00152   register struct rfb_server_init *initmsg;
00153   
00154   switch(vs->state) {
00155   case VNC_VERSION:
00156     uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING));
00157     break;
00158   case VNC_AUTH:
00159     ((char *)uip_appdata)[0] = 0;
00160     ((char *)uip_appdata)[1] = 0;
00161     ((char *)uip_appdata)[2] = 0;
00162     ((char *)uip_appdata)[3] = RFB_AUTH_NONE;
00163     uip_send(uip_appdata, 4);
00164     break;
00165   case VNC_INIT:
00166     initmsg = (struct rfb_server_init *)uip_appdata;
00167     initmsg->width = uip_htons(vs->width);
00168     initmsg->height = uip_htons(vs->height);
00169     /* BGR233 pixel format. */
00170     initmsg->format.bps = 8;
00171     initmsg->format.depth = 8;
00172     initmsg->format.endian = 1;
00173     initmsg->format.truecolor = 1;
00174     initmsg->format.red_max = uip_htons(7);
00175     initmsg->format.green_max = uip_htons(7);
00176     initmsg->format.blue_max = uip_htons(3);
00177     initmsg->format.red_shift = 0;
00178     initmsg->format.green_shift = 3;
00179     initmsg->format.blue_shift = 6;
00180     initmsg->namelength[0] = 0;
00181     initmsg->namelength[1] = 0;
00182     initmsg->namelength[2] = 0;     
00183     initmsg->namelength[3] = 4;
00184     memcpy(&((char *)uip_appdata)[sizeof(struct rfb_server_init)], uvnc_name, 4);
00185     /*    ((char *)uip_appdata)[sizeof(struct rfb_server_init)+0] = 'u';
00186     ((char *)uip_appdata)[sizeof(struct rfb_server_init)+1] = 'V';
00187     ((char *)uip_appdata)[sizeof(struct rfb_server_init)+2] = 'N';
00188     ((char *)uip_appdata)[sizeof(struct rfb_server_init)+3] = 'C';*/
00189     uip_send(uip_appdata, sizeof(struct rfb_server_init) + 4);
00190     break;
00191   case VNC_RUNNING:
00192     switch(vs->sendmsg) {
00193     case SEND_NONE:
00194       PRINTF(("Sending none\n"));
00195       break;
00196       
00197     case SEND_BLANK:
00198     case SENT_BLANK:
00199       PRINTF(("Sending blank\n"));
00200       vnc_send_blank(vs);
00201       break;
00202       
00203     case SEND_SCREEN:
00204       PRINTF(("Sending screen\n"));
00205       vnc_send_screen(vs);
00206       break;
00207 
00208     case SEND_UPDATE:
00209       PRINTF(("Sending update\n"));
00210       vnc_send_update(vs);
00211       break;
00212     }
00213     break;
00214     
00215   default:
00216     break;
00217   }
00218 
00219 }
00220 /*-----------------------------------------------------------------------------------*/
00221 static void
00222 vnc_key_event(struct vnc_server_state *vs)
00223 {
00224   switch(vs->type) {
00225   case 0:       
00226     vnc_out_key_event(vs);
00227     break;
00228     /*  case 1:
00229     vnc_stats_key_event(vs);
00230     break;*/
00231   }
00232 }
00233 /*-----------------------------------------------------------------------------------*/
00234 static void
00235 vnc_pointer_event(struct vnc_server_state *vs)
00236 {
00237   switch(vs->type) {
00238   case 0:       
00239     vnc_out_pointer_event(vs);
00240     break;
00241     /*  case 1:
00242     vnc_stats_pointer_event(vs);
00243     break;*/
00244   }
00245 }
00246 /*-----------------------------------------------------------------------------------*/
00247 static u8_t
00248 vnc_read_data(CC_REGISTER_ARG struct vnc_server_state *vs)
00249 {
00250   u8_t *appdata;
00251   u16_t len;
00252   struct rfb_fb_update_request *req;
00253   /*  u8_t niter;*/
00254   
00255   len = uip_datalen();
00256   appdata = (u8_t *)uip_appdata;
00257   
00258   /* First, check if there is data left to discard since last read. */
00259   if(vs->readlen > 0) {
00260     appdata += vs->readlen;
00261     if(len > vs->readlen) {
00262       len -= vs->readlen;
00263       vs->readlen = 0;
00264     } else {
00265       vs->readlen -= len;
00266       len = 0;
00267     }
00268   }
00269 
00270   if(vs->readlen != 0) {
00271     return 1;
00272   }
00273 
00274   /* All data read and ignored, parse next message. */
00275   /*  for(niter = 32; niter > 0 && len > 0; --niter) {*/
00276   while(len > 0) {
00277     switch(vs->state) {
00278     case VNC_VERSION:
00279     case VNC_VERSION2:
00280       PRINTF(("Read in version\n"));
00281       /* Receive and ignore client version string (12 bytes). */
00282       vs->state = VNC_AUTH;
00283       vs->readlen = 12;
00284       break;
00285       
00286     case VNC_AUTH:
00287     case VNC_AUTH2:
00288       PRINTF(("Read in auth \n"));
00289       /* Read and discard initialization from client (1 byte). */
00290       vs->readlen = 1;
00291       vs->state = VNC_INIT;
00292       break;
00293       
00294     case VNC_INIT:
00295     case VNC_INIT2:
00296       PRINTF(("Read in init \n"));
00297       vs->readlen = 0;
00298       vs->state = VNC_RUNNING;
00299       
00300     case VNC_RUNNING:
00301       /* Handle all client events. */
00302       switch(*appdata) {
00303       case RFB_SET_PIXEL_FORMAT:
00304         PRINTF(("Set pixel format\n"));
00305         vs->readlen = sizeof(struct rfb_set_pixel_format);
00306         /* Check if client runs with BGR233 format. If not, abort the
00307            connection. */
00308         /* XXX: not implemented yet. */
00309         break;
00310         
00311       case RFB_FIX_COLORMAP_ENTRIES:
00312         PRINTF(("Fix colormap entries\n"));
00313         return 0;
00314         
00315       case RFB_SET_ENCODINGS:
00316         PRINTF(("Set encodings\n"));
00317         vs->readlen = sizeof(struct rfb_set_encoding);
00318         vs->readlen += uip_htons(((struct rfb_set_encoding *)appdata)->encodings) * 4;
00319         /* Make sure that client supports the encodings we use. */
00320         /* XXX: not implemented yet. */
00321         break;
00322         
00323       case RFB_FB_UPDATE_REQ:
00324         PRINTF(("Update request\n"));
00325         vs->update_requested = 1;
00326         vs->readlen = sizeof(struct rfb_fb_update_request);
00327         /* blank the screen initially */
00328         req = (struct rfb_fb_update_request *)appdata;
00329         if(req->incremental == 0) {
00330           /*      vs->sendmsg = SEND_BLANK;*/
00331           vnc_out_update_area(vs, 0, 0, vs->w, vs->h);
00332         }
00333         break;
00334         
00335       case RFB_KEY_EVENT:
00336         vs->readlen = sizeof(struct rfb_key_event);
00337         vnc_key_event(vs);
00338         break;
00339         
00340       case RFB_POINTER_EVENT:
00341         vs->readlen = sizeof(struct rfb_pointer_event);
00342         vnc_pointer_event(vs);
00343         break;
00344         
00345       case RFB_CLIENT_CUT_TEXT:
00346         PRINTF(("Client cut text\n"));
00347 
00348         if(((struct rfb_client_cut_text *)appdata)->len[0] != 0 ||
00349            ((struct rfb_client_cut_text *)appdata)->len[1] != 0) {
00350           return 0;
00351           
00352         }
00353         vs->readlen = sizeof(struct rfb_client_cut_text) +
00354           (((struct rfb_client_cut_text *)appdata)->len[2] << 8) +
00355           ((struct rfb_client_cut_text *)appdata)->len[3];
00356         /*      return 0;*/
00357         break;
00358         
00359       default:
00360         PRINTF(("Unknown message %d\n", *appdata));
00361         return 0;
00362       }
00363       break;
00364       
00365     default:
00366       return 0;
00367     }
00368 
00369     if(vs->readlen > 0) {
00370       if(len > vs->readlen) {
00371         len -= vs->readlen;
00372         appdata += vs->readlen;
00373         vs->readlen = 0;
00374       } else {
00375         vs->readlen -= len;
00376         len = 0;
00377       }
00378     } else {
00379       /* Lost data. */
00380       break;
00381     }
00382     
00383   }
00384 
00385   /*  if(vs->readlen > 0) {
00386     printf("More data %d\n", vs->readlen);
00387     }*/
00388   
00389   /*  uip_appdata = appdata;*/
00390 
00391   return 1;
00392 }
00393 /*-----------------------------------------------------------------------------------*/
00394 static void
00395 vnc_new(CC_REGISTER_ARG struct vnc_server_state *vs)
00396 {
00397   vs->counter = 0;
00398   vs->readlen = 0;
00399   vs->sendmsg = SEND_NONE;
00400   vs->update_requested = 1;
00401   switch(vs->type) {
00402   case 0:       
00403     vnc_out_new(vs);
00404     break;
00405     /*  case 1:
00406     vnc_stats_new(vs);
00407     break;*/
00408   }
00409 }
00410 /*-----------------------------------------------------------------------------------*/
00411 static void
00412 vnc_acked(CC_REGISTER_ARG struct vnc_server_state *vs)
00413 {
00414   switch(vs->state) {
00415   case VNC_VERSION:
00416     vs->state = VNC_VERSION2;
00417     break;
00418     
00419   case VNC_AUTH:
00420     vs->state = VNC_AUTH2;
00421     break;
00422     
00423   case VNC_INIT:
00424     vs->state = VNC_INIT2;
00425     break;
00426 
00427   case VNC_RUNNING:
00428     switch(vs->type) {
00429     case 0:     
00430       vnc_out_acked(vs);
00431       break;
00432       /*    case 1:
00433       vnc_stats_acked(vs);
00434       break;*/
00435     }
00436     break;
00437   }
00438 }
00439 /*-----------------------------------------------------------------------------------*/
00440 void
00441 vnc_server_appcall(struct vnc_server_state *vs)
00442 {
00443   
00444   vs->type = uip_htons(uip_conn->lport) - 5900;
00445   
00446   if(uip_connected()) {      
00447     vnc_new(vs);
00448     vs->state = VNC_VERSION;
00449     vnc_server_send_data(vs);
00450     return;
00451   }
00452   if(uip_acked()) {
00453     PRINTF(("Acked\n"));
00454     vnc_acked(vs);
00455   }
00456   
00457   if(uip_newdata()) {
00458     PRINTF(("Newdata\n"));
00459     vs->counter = 0;
00460     if(vnc_read_data(vs) == 0) {
00461       uip_abort();
00462       return;
00463     }
00464   }
00465   
00466   if(uip_rexmit()) {
00467     PRINTF(("Rexmit\n"));
00468   }
00469   
00470   
00471   if(uip_newdata() ||
00472      uip_rexmit() ||
00473      uip_acked()) {
00474     vnc_server_send_data(vs);
00475   } else if(uip_poll()) {
00476     ++vs->counter;
00477     /* Abort connection after about 20 seconds of inactivity. */
00478     if(vs->counter >= 40) {
00479       uip_abort();
00480       return;
00481     }
00482     
00483     vnc_out_poll(vs);
00484   }
00485   
00486 }
00487 /*-----------------------------------------------------------------------------------*/

Generated on Mon Apr 11 14:23:27 2011 for Contiki 2.5 by  doxygen 1.6.1