⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfbserver.c

📁 远程桌面连接工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * rfbserver.c - deal with server-side of the RFB protocol. *//* *  Copyright (C) 2000-2006 Constantin Kaplinsky.  All Rights Reserved. *  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved. *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved. * *  This 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 of the License, or *  (at your option) any later version. * *  This software 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 this software; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, *  USA. *//* Use ``#define CORBA'' to enable CORBA control interface */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <pwd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include "windowstr.h"#include "rfb.h"#include "input.h"#include "mipointer.h"#include "sprite.h"#ifdef CORBA#include <vncserverctrl.h>#endifchar updateBuf[UPDATE_BUF_SIZE];int ublen;rfbClientPtr rfbClientHead = NULL;rfbClientPtr pointerClient = NULL;  /* Mutex for pointer events */Bool rfbAlwaysShared = FALSE;Bool rfbNeverShared = FALSE;Bool rfbDontDisconnect = FALSE;Bool rfbViewOnly = FALSE; /* run server in view only mode - Ehud Karni SW */static rfbClientPtr rfbNewClient(int sock);static void rfbProcessClientProtocolVersion(rfbClientPtr cl);static void rfbProcessClientInitMessage(rfbClientPtr cl);static void rfbSendInteractionCaps(rfbClientPtr cl);static void rfbProcessClientNormalMessage(rfbClientPtr cl);static Bool rfbSendCopyRegion(rfbClientPtr cl, RegionPtr reg, int dx, int dy);static Bool rfbSendLastRectMarker(rfbClientPtr cl);/* * rfbNewClientConnection is called from sockets.c when a new connection * comes in. */voidrfbNewClientConnection(sock)    int sock;{    rfbClientPtr cl;    cl = rfbNewClient(sock);#ifdef CORBA    if (cl != NULL)	newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1);#endif}/* * rfbReverseConnection is called by the CORBA stuff to make an outward * connection to a "listening" RFB client. */rfbClientPtrrfbReverseConnection(host, port)    char *host;    int port;{    int sock;    rfbClientPtr cl;    if ((sock = rfbConnect(host, port)) < 0)	return (rfbClientPtr)NULL;    cl = rfbNewClient(sock);    if (cl) {	cl->reverseConnection = TRUE;    }    return cl;}/* * rfbNewClient is called when a new connection has been made by whatever * means. */static rfbClientPtrrfbNewClient(sock)    int sock;{    rfbProtocolVersionMsg pv;    rfbClientPtr cl;    BoxRec box;    struct sockaddr_in addr;    int addrlen = sizeof(struct sockaddr_in);    int i;    if (rfbClientHead == NULL) {	/* no other clients - make sure we don't think any keys are pressed */	KbdReleaseAllKeys();    } else {	rfbLog("  (other clients");	for (cl = rfbClientHead; cl; cl = cl->next) {	    fprintf(stderr," %s",cl->host);	}	fprintf(stderr,")\n");    }    cl = (rfbClientPtr)xalloc(sizeof(rfbClientRec));    cl->sock = sock;    getpeername(sock, (struct sockaddr *)&addr, &addrlen);    cl->host = strdup(inet_ntoa(addr.sin_addr));    cl->login = NULL;    /* Dispatch client input to rfbProcessClientProtocolVersion(). */    cl->state = RFB_PROTOCOL_VERSION;    cl->viewOnly = FALSE;    cl->reverseConnection = FALSE;    cl->readyForSetColourMapEntries = FALSE;    cl->useCopyRect = FALSE;    cl->preferredEncoding = rfbEncodingRaw;    cl->correMaxWidth = 48;    cl->correMaxHeight = 48;    REGION_INIT(pScreen,&cl->copyRegion,NullBox,0);    cl->copyDX = 0;    cl->copyDY = 0;    box.x1 = box.y1 = 0;    box.x2 = rfbScreen.width;    box.y2 = rfbScreen.height;    REGION_INIT(pScreen,&cl->modifiedRegion,&box,0);    REGION_INIT(pScreen,&cl->requestedRegion,NullBox,0);    cl->deferredUpdateScheduled = FALSE;    cl->deferredUpdateTimer = NULL;    cl->format = rfbServerFormat;    cl->translateFn = rfbTranslateNone;    cl->translateLookupTable = NULL;    cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;    cl->tightQualityLevel = -1;    for (i = 0; i < 4; i++)        cl->zsActive[i] = FALSE;    cl->enableCursorShapeUpdates = FALSE;    cl->enableCursorPosUpdates = FALSE;    cl->enableLastRectEncoding = FALSE;    cl->next = rfbClientHead;    rfbClientHead = cl;    rfbResetStats(cl);    cl->compStreamInited = FALSE;    cl->compStream.total_in = 0;    cl->compStream.total_out = 0;    cl->compStream.zalloc = Z_NULL;    cl->compStream.zfree = Z_NULL;    cl->compStream.opaque = Z_NULL;    cl->zlibCompressLevel = 5;    sprintf(pv, rfbProtocolVersionFormat, 3, 8);    if (WriteExact(sock, pv, sz_rfbProtocolVersionMsg) < 0) {	rfbLogPerror("rfbNewClient: write");	rfbCloseSock(sock);	return NULL;    }    return cl;}/* * rfbClientConnectionGone is called from sockets.c just after a connection * has gone away. */voidrfbClientConnectionGone(sock)    int sock;{    rfbClientPtr cl, prev;    int i;    for (prev = NULL, cl = rfbClientHead; cl; prev = cl, cl = cl->next) {	if (sock == cl->sock)	    break;    }    if (!cl) {	rfbLog("rfbClientConnectionGone: unknown socket %d\n",sock);	return;    }    if (cl->login != NULL) {	rfbLog("Client %s (%s) gone\n", cl->login, cl->host);	free(cl->login);    } else {	rfbLog("Client %s gone\n", cl->host);    }    free(cl->host);    /* Release the compression state structures if any. */    if ( cl->compStreamInited == TRUE ) {	deflateEnd( &(cl->compStream) );    }    for (i = 0; i < 4; i++) {	if (cl->zsActive[i])	    deflateEnd(&cl->zsStruct[i]);    }    if (pointerClient == cl)	pointerClient = NULL;#ifdef CORBA    destroyConnection(cl);#endif    if (prev)	prev->next = cl->next;    else	rfbClientHead = cl->next;    REGION_UNINIT(pScreen,&cl->copyRegion);    REGION_UNINIT(pScreen,&cl->modifiedRegion);    TimerFree(cl->deferredUpdateTimer);    rfbPrintStats(cl);    if (cl->translateLookupTable) free(cl->translateLookupTable);    xfree(cl);}/* * rfbProcessClientMessage is called when there is data to read from a client. */voidrfbProcessClientMessage(sock)    int sock;{    rfbClientPtr cl;    for (cl = rfbClientHead; cl; cl = cl->next) {	if (sock == cl->sock)	    break;    }    if (!cl) {	rfbLog("rfbProcessClientMessage: unknown socket %d\n",sock);	rfbCloseSock(sock);	return;    }#ifdef CORBA    if (isClosePending(cl)) {	rfbLog("Closing connection to client %s\n", cl->host);	rfbCloseSock(sock);	return;    }#endif    switch (cl->state) {    case RFB_PROTOCOL_VERSION:	rfbProcessClientProtocolVersion(cl);	break;    case RFB_SECURITY_TYPE:	/* protocol versions 3.7 and above */	rfbProcessClientSecurityType(cl);	break;    case RFB_TUNNELING_TYPE:	/* protocol versions 3.7t, 3.8t */	rfbProcessClientTunnelingType(cl);	break;    case RFB_AUTH_TYPE:		/* protocol versions 3.7t, 3.8t */	rfbProcessClientAuthType(cl);	break;    case RFB_AUTHENTICATION:	rfbVncAuthProcessResponse(cl);	break;    case RFB_INITIALISATION:	rfbProcessClientInitMessage(cl);	break;    default:	rfbProcessClientNormalMessage(cl);    }}/* * rfbProcessClientProtocolVersion is called when the client sends its * protocol version. */static voidrfbProcessClientProtocolVersion(cl)    rfbClientPtr cl;{    rfbProtocolVersionMsg pv;    int n, major, minor;    Bool mismatch;    if ((n = ReadExact(cl->sock, pv, sz_rfbProtocolVersionMsg)) <= 0) {	if (n == 0)	    rfbLog("rfbProcessClientProtocolVersion: client gone\n");	else	    rfbLogPerror("rfbProcessClientProtocolVersion: read");	rfbCloseSock(cl->sock);	return;    }    pv[sz_rfbProtocolVersionMsg] = 0;    if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) {	rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n");	rfbCloseSock(cl->sock);	return;    }    if (major != 3) {	rfbLog("Unsupported protocol version %d.%d\n", major, minor);	rfbCloseSock(cl->sock);	return;    }    /* Always use one of the three standard versions of the RFB protocol. */    cl->protocol_minor_ver = minor;    if (minor > 8) {		/* buggy client */	cl->protocol_minor_ver = 8;    } else if (minor > 3 && minor < 7) { /* non-standard client */	cl->protocol_minor_ver = 3;    } else if (minor < 3) {	/* ancient client */	cl->protocol_minor_ver = 3;    }    if (cl->protocol_minor_ver != minor) {	rfbLog("Non-standard protocol version 3.%d, using 3.%d instead\n",	       minor, cl->protocol_minor_ver);    } else {	rfbLog("Using protocol version 3.%d\n", cl->protocol_minor_ver);    }    /* TightVNC protocol extensions are not enabled yet. */    cl->protocol_tightvnc = FALSE;    rfbAuthNewClient(cl);}/* * rfbProcessClientInitMessage is called when the client sends its * initialisation message. */static voidrfbProcessClientInitMessage(cl)    rfbClientPtr cl;{    rfbClientInitMsg ci;    char buf[256];    rfbServerInitMsg *si = (rfbServerInitMsg *)buf;    struct passwd *user;    int len, n;    rfbClientPtr otherCl, nextCl;    if ((n = ReadExact(cl->sock, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {	if (n == 0)	    rfbLog("rfbProcessClientInitMessage: client gone\n");	else	    rfbLogPerror("rfbProcessClientInitMessage: read");	rfbCloseSock(cl->sock);	return;    }    si->framebufferWidth = Swap16IfLE(rfbScreen.width);    si->framebufferHeight = Swap16IfLE(rfbScreen.height);    si->format = rfbServerFormat;    si->format.redMax = Swap16IfLE(si->format.redMax);    si->format.greenMax = Swap16IfLE(si->format.greenMax);    si->format.blueMax = Swap16IfLE(si->format.blueMax);    user = getpwuid(getuid());    if (strlen(desktopName) > 128)	/* sanity check on desktop name len */	desktopName[128] = 0;    if (user) {	sprintf(buf + sz_rfbServerInitMsg, "%s's %s desktop (%s:%s)",		user->pw_name, desktopName, rfbThisHost, display);    } else {	sprintf(buf + sz_rfbServerInitMsg, "%s desktop (%s:%s)",		desktopName, rfbThisHost, display);    }    len = strlen(buf + sz_rfbServerInitMsg);    si->nameLength = Swap32IfLE(len);    if (WriteExact(cl->sock, buf, sz_rfbServerInitMsg + len) < 0) {	rfbLogPerror("rfbProcessClientInitMessage: write");	rfbCloseSock(cl->sock);	return;    }    if (cl->protocol_tightvnc)	rfbSendInteractionCaps(cl); /* protocol 3.7t */    /* Dispatch client input to rfbProcessClientNormalMessage(). */    cl->state = RFB_NORMAL;    if (!cl->reverseConnection &&			(rfbNeverShared || (!rfbAlwaysShared && !ci.shared))) {	if (rfbDontDisconnect) {	    for (otherCl = rfbClientHead; otherCl; otherCl = otherCl->next) {		if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {		    rfbLog("-dontdisconnect: Not shared & existing client\n");		    rfbLog("  refusing new client %s\n", cl->host);		    rfbCloseSock(cl->sock);		    return;		}	    }	} else {	    for (otherCl = rfbClientHead; otherCl; otherCl = nextCl) {		nextCl = otherCl->next;		if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {		    rfbLog("Not shared - closing connection to client %s\n",			   otherCl->host);		    rfbCloseSock(otherCl->sock);		}	    }	}    }}/* * rfbSendInteractionCaps is called after sending the server * initialisation message, only if TightVNC protocol extensions were * enabled (protocol versions 3.7t, 3.8t). In this function, we send * the lists of supported protocol messages and encodings. *//* Update these constants on changing capability lists below! */#define N_SMSG_CAPS  0#define N_CMSG_CAPS  0#define N_ENC_CAPS  12voidrfbSendInteractionCaps(cl)    rfbClientPtr cl;{    rfbInteractionCapsMsg intr_caps;    rfbCapabilityInfo enc_list[N_ENC_CAPS];    int i;    /* Fill in the header structure sent prior to capability lists. */    intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS);    intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS);    intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS);    intr_caps.pad = 0;    /* Supported server->client message types. */    /* For future file transfer support:    i = 0;    SetCapInfo(&smsg_list[i++], rfbFileListData,           rfbTightVncVendor);    SetCapInfo(&smsg_list[i++], rfbFileDownloadData,       rfbTightVncVendor);    SetCapInfo(&smsg_list[i++], rfbFileUploadCancel,       rfbTightVncVendor);    SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed,     rfbTightVncVendor);    if (i != N_SMSG_CAPS) {	rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n");	rfbCloseSock(cl->sock);	return;    }    */    /* Supported client->server message types. */    /* For future file transfer support:    i = 0;    SetCapInfo(&cmsg_list[i++], rfbFileListRequest,        rfbTightVncVendor);    SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest,    rfbTightVncVendor);    SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest,      rfbTightVncVendor);    SetCapInfo(&cmsg_list[i++], rfbFileUploadData,         rfbTightVncVendor);    SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel,     rfbTightVncVendor);    SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed,       rfbTightVncVendor);    if (i != N_CMSG_CAPS) {	rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n");	rfbCloseSock(cl->sock);	return;    }    */    /* Encoding types. */    i = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -