📄 vnc-server.c
字号:
/* * Copyright (c) 2001, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Adam Dunkels. * 4. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the uIP TCP/IP stack. * * $Id: vnc-server.c,v 1.2 2003/08/24 22:41:31 adamdunkels Exp $ * *//* A micro implementation of a VNC server. VNC is a protocol for remote network displays. See http://www.uk.research.att.com/vnc/ for information about VNC. Initialization states: VNC_VERSION (send version string) VNC_AUTH (send auth message) VNC_INIT (send init message) Steady state: VNC_RUNNING (send RFB updates, parse incoming messages) What kind of message should be sent: SEND_NONE (No message) SEND_BLANK (Blank screen initially) SEND_SCREEN (Send entire screen, initially) SEND_UPDATE (Send incremental update)*/#include "uip.h"#include "vnc-server.h"#include "vnc-out.h"/* RFB server initial handshaking string. */#define RFB_SERVER_VERSION_STRING rfb_server_version_string/* "RFB 003.003" */static u8_t rfb_server_version_string[12] = {82,70,66,32,48,48,51,46,48,48,51,10};/* uVNC */static u8_t uvnc_name[4] = {117,86,78,67};#if 1#define PRINTF(x)#else#define PRINTF(x) printf x#endif/*-----------------------------------------------------------------------------------*/u8_tvnc_server_draw_rect(u8_t *ptr, u16_t x, u16_t y, u16_t w, u16_t h, u8_t c){ struct rfb_fb_update_rect_hdr *recthdr; struct rfb_rre_hdr *rrehdr; recthdr = (struct rfb_fb_update_rect_hdr *)ptr; rrehdr = (struct rfb_rre_hdr *)(ptr + sizeof(struct rfb_fb_update_rect_hdr)); recthdr->rect.x = x; recthdr->rect.y = y; recthdr->rect.w = w; recthdr->rect.h = h; recthdr->encoding[0] = recthdr->encoding[1] = recthdr->encoding[2] = 0; recthdr->encoding[3] = RFB_ENC_RRE; rrehdr->subrects[0] = rrehdr->subrects[1] = 0; rrehdr->bgpixel = c; return sizeof(struct rfb_fb_update_rect_hdr) + sizeof(struct rfb_rre_hdr);}/*-----------------------------------------------------------------------------------*/voidvnc_server_init(void){ vnc_out_init();}/*-----------------------------------------------------------------------------------*/static voidvnc_send_blank(struct vnc_server_state *vs){ switch(vs->type) { case 0: vnc_out_send_blank(vs); break; /* case 1: vnc_stats_send_blank(vs); break; */ }}/*-----------------------------------------------------------------------------------*/static voidvnc_send_screen(struct vnc_server_state *vs){ switch(vs->type) { case 0: vnc_out_send_screen(vs); break; /* case 1: vnc_stats_send_screen(vs); break;*/ }}/*-----------------------------------------------------------------------------------*/static voidvnc_send_update(struct vnc_server_state *vs){ switch(vs->type) { case 0: vnc_out_send_update(vs); break; /* case 1: vnc_stats_send_update(vs); break;*/ }}/*-----------------------------------------------------------------------------------*/voidvnc_server_send_data(struct vnc_server_state *vs){ struct rfb_server_init *initmsg; switch(vs->state) { case VNC_VERSION: uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING)); break; case VNC_AUTH: uip_appdata[0] = 0; uip_appdata[1] = 0; uip_appdata[2] = 0; uip_appdata[3] = RFB_AUTH_NONE; uip_send(uip_appdata, 4); break; case VNC_INIT: initmsg = (struct rfb_server_init *)uip_appdata; initmsg->width = htons(vs->width); initmsg->height = htons(vs->height); /* BGR233 pixel format. */ initmsg->format.bps = 8; initmsg->format.depth = 8; initmsg->format.endian = 1; initmsg->format.truecolor = 1; initmsg->format.red_max = htons(7); initmsg->format.green_max = htons(7); initmsg->format.blue_max = htons(3); initmsg->format.red_shift = 0; initmsg->format.green_shift = 3; initmsg->format.blue_shift = 6; initmsg->namelength[0] = 0; initmsg->namelength[1] = 0; initmsg->namelength[2] = 0; initmsg->namelength[3] = 4; bcopy(uvnc_name, &uip_appdata[sizeof(struct rfb_server_init)], 4); /* uip_appdata[sizeof(struct rfb_server_init)+0] = 'u'; uip_appdata[sizeof(struct rfb_server_init)+1] = 'V'; uip_appdata[sizeof(struct rfb_server_init)+2] = 'N'; uip_appdata[sizeof(struct rfb_server_init)+3] = 'C';*/ uip_send(uip_appdata, sizeof(struct rfb_server_init) + 4); break; case VNC_RUNNING: switch(vs->sendmsg) { case SEND_NONE: PRINTF(("Sending none\n")); break; case SEND_BLANK: case SENT_BLANK: PRINTF(("Sending blank\n")); vnc_send_blank(vs); break; case SEND_SCREEN: PRINTF(("Sending screen\n")); vnc_send_screen(vs); break; case SEND_UPDATE: PRINTF(("Sending update\n")); vnc_send_update(vs); break; } break; default: break; }}/*-----------------------------------------------------------------------------------*/static voidvnc_key_event(struct vnc_server_state *vs){ switch(vs->type) { case 0: vnc_out_key_event(vs); break; /* case 1: vnc_stats_key_event(vs); break;*/ }}/*-----------------------------------------------------------------------------------*/static voidvnc_pointer_event(struct vnc_server_state *vs){ switch(vs->type) { case 0: vnc_out_pointer_event(vs); break; /* case 1: vnc_stats_pointer_event(vs); break;*/ }}/*-----------------------------------------------------------------------------------*/static u8_tvnc_read_data(struct vnc_server_state *vs){ u8_t *appdata; u16_t len; struct rfb_fb_update_request *req; /* u8_t niter;*/ len = uip_datalen(); appdata = (u8_t *)uip_appdata; /* First, check if there is data left to discard since last read. */ if(vs->readlen > 0) { appdata += vs->readlen; if(len > vs->readlen) { len -= vs->readlen; vs->readlen = 0; } else { vs->readlen -= len; len = 0; } } if(vs->readlen != 0) { return 1; } /* All data read and ignored, parse next message. */ /* for(niter = 32; niter > 0 && len > 0; --niter) {*/ while(len > 0) { switch(vs->state) { case VNC_VERSION: case VNC_VERSION2: PRINTF(("Read in version\n")); /* Receive and ignore client version string (12 bytes). */ vs->state = VNC_AUTH; vs->readlen = 12; break; case VNC_AUTH: case VNC_AUTH2: PRINTF(("Read in auth \n")); /* Read and discard initialization from client (1 byte). */ vs->readlen = 1; vs->state = VNC_INIT; break; case VNC_INIT: case VNC_INIT2: PRINTF(("Read in init \n")); vs->readlen = 0; vs->state = VNC_RUNNING; case VNC_RUNNING: /* Handle all client events. */ switch(*appdata) { case RFB_SET_PIXEL_FORMAT: PRINTF(("Set pixel format\n")); vs->readlen = sizeof(struct rfb_set_pixel_format); /* Check if client runs with BGR233 format. If not, abort the connection. */ /* XXX: not implemented yet. */ break; case RFB_FIX_COLORMAP_ENTRIES: PRINTF(("Fix colormap entries\n")); return 0; case RFB_SET_ENCODINGS: PRINTF(("Set encodings\n")); vs->readlen = sizeof(struct rfb_set_encoding); vs->readlen += htons(((struct rfb_set_encoding *)appdata)->encodings) * 4; /* Make sure that client supports the encodings we use. */ /* XXX: not implemented yet. */ break; case RFB_FB_UPDATE_REQ: PRINTF(("Update request\n")); vs->update_requested = 1; vs->readlen = sizeof(struct rfb_fb_update_request); /* blank the screen initially */ req = (struct rfb_fb_update_request *)appdata; if(req->incremental == 0) { /* vs->sendmsg = SEND_BLANK;*/ vnc_out_update_area(vs, 0, 0, vs->w, vs->h); } break; case RFB_KEY_EVENT: vs->readlen = sizeof(struct rfb_key_event); vnc_key_event(vs); break; case RFB_POINTER_EVENT: vs->readlen = sizeof(struct rfb_pointer_event); vnc_pointer_event(vs); break; case RFB_CLIENT_CUT_TEXT: PRINTF(("Client cut text\n")); if(((struct rfb_client_cut_text *)appdata)->len[0] != 0 || ((struct rfb_client_cut_text *)appdata)->len[1] != 0) { return 0; } vs->readlen = sizeof(struct rfb_client_cut_text) + (((struct rfb_client_cut_text *)appdata)->len[2] << 8) + ((struct rfb_client_cut_text *)appdata)->len[3]; /* return 0;*/ break; default: PRINTF(("Unknown message %d\n", *appdata)); return 0; } break; default: return 0; } if(vs->readlen > 0) { if(len > vs->readlen) { len -= vs->readlen; appdata += vs->readlen; vs->readlen = 0; } else { vs->readlen -= len; len = 0; } } else { /* Lost data. */ break; } } /* if(vs->readlen > 0) { printf("More data %d\n", vs->readlen); }*/ /* uip_appdata = appdata;*/ return 1;}/*-----------------------------------------------------------------------------------*/static voidvnc_new(struct vnc_server_state *vs){ vs->counter = 0; vs->readlen = 0; vs->sendmsg = SEND_NONE; vs->update_requested = 1; switch(vs->type) { case 0: vnc_out_new(vs); break; /* case 1: vnc_stats_new(vs); break;*/ }}/*-----------------------------------------------------------------------------------*/static voidvnc_acked(struct vnc_server_state *vs){ switch(vs->state) { case VNC_VERSION: vs->state = VNC_VERSION2; break; case VNC_AUTH: vs->state = VNC_AUTH2; break; case VNC_INIT: vs->state = VNC_INIT2; break; case VNC_RUNNING: switch(vs->type) { case 0: vnc_out_acked(vs); break; /* case 1: vnc_stats_acked(vs); break;*/ } break; }}/*-----------------------------------------------------------------------------------*/voidvnc_server_appcall(struct vnc_server_state *vs){ vs->type = htons(uip_conn->lport) - 5900; if(uip_connected()) { vnc_new(vs); vs->state = VNC_VERSION; vnc_server_send_data(vs); return; } if(uip_acked()) { PRINTF(("Acked\n")); vnc_acked(vs); } if(uip_newdata()) { PRINTF(("Newdata\n")); vs->counter = 0; if(vnc_read_data(vs) == 0) { uip_abort(); return; } } if(uip_rexmit()) { PRINTF(("Rexmit\n")); } if(uip_newdata() || uip_rexmit() || uip_acked()) { vnc_server_send_data(vs); } else if(uip_poll()) { ++vs->counter; /* Abort connection after about 20 seconds of inactivity. */ if(vs->counter >= 40) { uip_abort(); return; } vnc_out_poll(vs); } }/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -