📄 vnc-server.c
字号:
//==========================================================================
//
// vnc-server.c
//
//
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Chris Garry <cgarry@sweeneydesign.co.uk>
// Contributors:
// Date: 2003-08-22
// Purpose:
// Description: VNC server for eCos
//
//####DESCRIPTIONEND####
//
//========================================================================*/
#include <cyg/hal/hal_arch.h> /* CYGNUM_HAL_STACK_SIZE_MINIMUM & CYGNUM_HAL_STACK_SIZE_TYPICAL */
#include <pkgconf/system.h>
#include <cyg/infra/diag.h> /* diag_printf */
#include <string.h>
#include <stdlib.h>
#include <vnc-server.h>
#ifdef CYGPKG_NET
/* eCos (BSD stack) include */
#include <network.h>
#else
/* eCos (lwIP stack) include */
#include <lwip/sys.h> /* lwIP stack includes */
#define LWIP_COMPAT_SOCKETS 1
#include <lwip/sockets.h>
#include <lwip/inet.h>
#endif
#define BACKLOG 5 /* Number of pending connections queue will hold */
#define MESSAGE_BUFFER_SIZE 50
#define TILE_SIZE CYGNUM_VNC_SERVER_TILE_SIZE
#define TRUE_COLOUR_FLAG 1 /* True colour is set */
#define BIG_ENDIAN_FLAG 1 /* Always send colour data big endian */
/* Various definitions for different pixel types */
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB332
#define BITS_PER_PIXEL 8 /* Bits per pixel */
#define PIXEL_DEPTH 8 /* Usefull bits per pixel */
#define RED_MAX 7
#define GREEN_MAX 7
#define BLUE_MAX 3
#define RED_SHIFT 5
#define GREEN_SHIFT 2
#define BLUE_SHIFT 0
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_BGR233
#define BITS_PER_PIXEL 8 /* Bits per pixel */
#define PIXEL_DEPTH 8 /* Usefull bits per pixel */
#define RED_MAX 7
#define GREEN_MAX 7
#define BLUE_MAX 3
#define RED_SHIFT 0
#define GREEN_SHIFT 3
#define BLUE_SHIFT 6
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB555
#define BITS_PER_PIXEL 16 /* Bits per pixel */
#define PIXEL_DEPTH 15 /* Usefull bits per pixel */
#define RED_MAX 31
#define GREEN_MAX 31
#define BLUE_MAX 31
#define RED_SHIFT 10
#define GREEN_SHIFT 5
#define BLUE_SHIFT 0
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB565
#define BITS_PER_PIXEL 16 /* Bits per pixel */
#define PIXEL_DEPTH 16 /* Usefull bits per pixel */
#define RED_MAX 31
#define GREEN_MAX 63
#define BLUE_MAX 31
#define RED_SHIFT 11
#define GREEN_SHIFT 5
#define BLUE_SHIFT 0
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_TRUECOLOR0888
#define BITS_PER_PIXEL 32 /* Bits per pixel */
#define PIXEL_DEPTH 24 /* Usefull bits per pixel */
#define RED_MAX 255
#define GREEN_MAX 255
#define BLUE_MAX 255
#define RED_SHIFT 16
#define GREEN_SHIFT 8
#define BLUE_SHIFT 0
#endif
/* Client to Server message types */
#define SET_PIXEL_FORMAT 0
#define FIX_COLOUR_MAP_ENTRIES 1
#define SET_ENCODINGS 2
#define FRAME_BUFFER_UPDATE_REQ 3
#define KEY_EVENT 4
#define POINTER_EVENT 5
#define CLIENT_CUT_TEXT 6
/* Macros to split colour to bytes */
#define COLOUR2BYTE1(col) ((col>>8)&0xFF)
#define COLOUR2BYTE0(col) (col&0xFF)
/* Function prototype */
static int GetMessageData(int, char *, int);
static int GenTileUpdateData(cyg_uint8 *);
/* Mouse handler funcrion - in vnc_mouse.c */
void vnc_mouse_handler(cyg_uint8 *data);
/* Keyboard handler funcrion - in vnc_kbd.c */
void vnc_kbd_handler(cyg_uint8 *data);
/* Thread function prototypes */
#ifdef CYGPKG_NET
cyg_thread_entry_t client_handler, frame_update;
#else
cyg_thread_entry_t tMain;
static void client_handler(void *);
static void frame_update(void *);
#endif
#ifdef CYGPKG_NET
/* Handles for the threads */
cyg_handle_t client_handler_hndl, frame_update_hndl;
/* Thread objects for the system to manipulate threads */
cyg_thread thread_s[2];
#else
cyg_handle_t lwip_startup_hndl;
cyg_thread thread_s;
#endif
/* Define size of each thread's stack */
#define MIN_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM)
#define MAIN_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL)
/* Allocate space for stacks */
#ifdef CYGPKG_NET
static char client_handler_stack[MAIN_STACK_SIZE];
static char frame_update_stack[MAIN_STACK_SIZE];
#else
static char lwip_startup_stack[MIN_STACK_SIZE];
#endif
/* Messages */
char server_ProtocolVersion[] = "RFB 003.003\n";
char bad_protocol[] = "Unsupported ProtocolVersion";
char sound_bell[] = "\2";
char desktop_name[] = CYGDAT_VNC_DESKTOP_NAME;
/* Frame Buffer */
volatile vnc_colour_t frame_buffer[CYGNUM_VNC_SERVER_FRAME_HEIGHT][CYGNUM_VNC_SERVER_FRAME_WIDTH];
/* Calculate the number of tiles in the X and Y directions */
#if (CYGNUM_VNC_SERVER_FRAME_HEIGHT % TILE_SIZE) != 0
#define NUM_TILES_Y_AXIS (CYGNUM_VNC_SERVER_FRAME_HEIGHT/TILE_SIZE + 1)
#define LAST_TILE_HEIGHT (CYGNUM_VNC_SERVER_FRAME_HEIGHT % TILE_SIZE)
#else
#define NUM_TILES_Y_AXIS (CYGNUM_VNC_SERVER_FRAME_HEIGHT/TILE_SIZE)
#define LAST_TILE_HEIGHT TILE_SIZE
#endif
#if (CYGNUM_VNC_SERVER_FRAME_WIDTH % TILE_SIZE) != 0
#define NUM_TILES_X_AXIS (CYGNUM_VNC_SERVER_FRAME_WIDTH/TILE_SIZE + 1)
#define LAST_TILE_WIDTH (CYGNUM_VNC_SERVER_FRAME_WIDTH % TILE_SIZE)
#else
#define NUM_TILES_X_AXIS (CYGNUM_VNC_SERVER_FRAME_WIDTH/TILE_SIZE)
#define LAST_TILE_WIDTH TILE_SIZE
#endif
/* Array for marking tiles that have been updated */
volatile int tile_updated[NUM_TILES_Y_AXIS][NUM_TILES_X_AXIS];
/* Conditional variable to signal that a client is connected and initialised */
cyg_mutex_t client_active_lock;
cyg_cond_t client_active_wait;
volatile int update_req;
/* Mutex and variable for sounding the client's bell */
cyg_mutex_t SoundBell_lock;
volatile int SoundBellCount;
volatile int client_sock; /* Socket descriptor for client connection */
/* Variable to hold the frame format details */
vnc_frame_format_t frame_format = {CYGNUM_VNC_SERVER_FRAME_WIDTH,
CYGNUM_VNC_SERVER_FRAME_HEIGHT,
frame_buffer,
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB332
1,
#else
0,
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB555
1,
#else
0,
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB565
1,
#else
0,
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_BGR233
1,
#else
0,
#endif
#ifdef CYGNUM_VNC_SERVER_PIXEL_TRUECOLOR0888
1,
#else
0,
#endif
};
/* Structure to hold the encoding type details */
volatile struct encoding_type_struct
{
cyg_uint8 raw;
cyg_uint8 copy_rectangle;
cyg_uint8 rre;
cyg_uint8 corre;
cyg_uint8 hextile;
} encoding_type;
/*****************************************************************************/
/** System initializer
*
* This is called from the static constructor in init.cxx. It spawns
* the main server thread and makes it ready to run.
*
*****************************************************************************/
__externC void cyg_vnc_server_startup(void)
{
#ifdef CYGPKG_NET
/* BSD TCP/IP stack version */
cyg_thread_create(CYGNUM_VNC_SERVER_PRIORITY,
client_handler,
0,
"ClientHandler",
(void *) client_handler_stack,
MAIN_STACK_SIZE,
&client_handler_hndl,
&thread_s[0]);
cyg_thread_resume(client_handler_hndl);
#else
/* lwIP TCP/IP stack version */
cyg_thread_create(CYGNUM_VNC_SERVER_PRIORITY,
tMain,
0,
"lwIP_Startup",
(void *) lwip_startup_stack,
MIN_STACK_SIZE,
&lwip_startup_hndl,
&thread_s);
cyg_thread_resume(lwip_startup_hndl);
#endif
}
#ifndef CYGPKG_NET
/* Startup thread for lwIP stack */
void tMain(cyg_addrword_t data)
{
lwip_init();
sys_thread_new(client_handler, (void *) 0, CYGNUM_VNC_SERVER_PRIORITY);
}
#endif
/*****************************************************************************/
/** Client Handler Thread.
*
* @param data Ignored
*
* This thread handles the client initialisation sequence. Once the client
* is initialised this thread handles all received messages from the client,
* but does not send any data to the client.
*
*****************************************************************************/
#ifdef CYGPKG_NET
void client_handler(cyg_addrword_t data)
#else
static void client_handler(void *data)
#endif
{
int server_sock; /* Socket descriptor for server */
struct sockaddr_in server_addr; /* Details of my IP address and port */
struct sockaddr_in client_addr; /* Details of new connection IP address */
int client_addr_size;
int i, j;
long int temp_long;
char message_buffer[MESSAGE_BUFFER_SIZE];
char protocol_ver[8];
int message_len;
int ProtocolOkay;
cyg_uint32 *ptr_to_uint32;
cyg_uint16 *ptr_to_uint16;
if (CYGNUM_VNC_SERVER_DELAY)
{
cyg_thread_delay(CYGNUM_VNC_SERVER_DELAY);
}
/* Initialise mutex & cond vars */
cyg_mutex_init(&client_active_lock);
cyg_cond_init(&client_active_wait, &client_active_lock);
update_req = 0;
cyg_mutex_init(&SoundBell_lock);
/* Create thread to handle frame_updates */
#ifdef CYGPKG_NET
cyg_thread_create(CYGNUM_VNC_SERVER_PRIORITY,
frame_update,
0,
"FrameUpdate",
(void *) frame_update_stack,
MAIN_STACK_SIZE,
&frame_update_hndl,
&thread_s[1]);
cyg_thread_resume(frame_update_hndl);
#else
sys_thread_new(frame_update, (void *) 0, CYGNUM_VNC_SERVER_PRIORITY);
#endif
/* Clear the encoding type structure */
encoding_type.raw = 0;
encoding_type.copy_rectangle = 0;
encoding_type.rre = 0;
encoding_type.corre = 0;
encoding_type.hextile = 0;
/* Clear the sound bell counter */
SoundBellCount = 0;
#ifdef CYGPKG_NET
/* Initialisation routine for BSD TCP/IP stack */
init_all_network_interfaces();
#endif
/* Create socket for incomming connections */
if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
diag_printf("socket() function failed\n");
exit(1);
}
/* Construct the server address structure */
memset(&server_addr, 0, sizeof(server_addr)); /* Fill entire structure with 0's */
server_addr.sin_family = AF_INET; /* Internet address family */
server_addr.sin_addr.s_addr = INADDR_ANY; /* Autofill with my IP address */
server_addr.sin_port = htons(CYGNUM_VNC_SERVER_PORT);
/* Bind socket to local address */
if (bind(server_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
{
diag_printf("bind() function failed");
exit(1);
}
/* Set the socket to listen for incoming connections */
if (listen(server_sock, BACKLOG) < 0)
{
diag_printf("listen() function failed");
exit(1);
}
while(1)
{
/* Wait to accept a connection on this socket */
client_addr_size = sizeof(client_addr);
client_sock = (accept(server_sock, (struct sockaddr *) &client_addr, &client_addr_size));
if(client_sock < 0)
{
diag_printf("accept() function failed");
exit(1);
}
/*
ProtocolVersion Handshake - begin
*/
/* Send ProtocolVersion we want to use to client */
message_len = diag_sprintf(message_buffer, "RFB 003.003\n");
if (send(client_sock, message_buffer, message_len, 0) != message_len)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -