📄 rfbproto.c
字号:
/* * Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory * * 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. *//* * rfbproto.c - functions to deal with client side of RFB protocol. */#include <unistd.h>#include <errno.h>#include <pwd.h>#include <vncviewer.h>#ifndef NANOX#include <X11/Xatom.h>#endif#include <vncauth.h>static Bool HandleHextileEncoding8(int x, int y, int w, int h);static Bool HandleHextileEncoding16(int x, int y, int w, int h);static Bool HandleHextileEncoding32(int x, int y, int w, int h);int rfbsock;char *desktopName;rfbPixelFormat myFormat;rfbServerInitMsg si;struct timeval updateRequestTime;Bool sendUpdateRequest;int endianTest = 1;/* note that the CoRRE encoding uses this buffer and assumes it is big enough to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes *//* also hextile assumes it is big enough to hold 16 * 16 * 32 bits */#define BUFFER_SIZE (640*480)static char buffer[BUFFER_SIZE];void PrintPixelFormat(rfbPixelFormat *format);/* * ConnectToRFBServer. */BoolConnectToRFBServer(const char *hostname, int port){ unsigned int host; if (!StringToIPAddr(hostname, &host)) { fprintf(stderr,"%s: couldn't convert '%s' to host address\n", programName,hostname); return False; } rfbsock = ConnectToTcpAddr(host, port); if (rfbsock < 0) { fprintf(stderr,"%s: unable to connect to VNC server\n", programName); return False; } return True;}/* * InitialiseRFBConnection. */BoolInitialiseRFBConnection(int sock){ rfbProtocolVersionMsg pv; int major,minor; Bool authWillWork = True; CARD32 authScheme, reasonLen, authResult; char *reason; CARD8 challenge[CHALLENGESIZE]; char *passwd; int i; rfbClientInitMsg ci; /* if the connection is immediately closed, don't report anything, so that pmw's monitor can make test connections */ if (listenSpecified) errorMessageFromReadExact = False; if (!ReadExact(sock, pv, sz_rfbProtocolVersionMsg)) return False; errorMessageFromReadExact = True; pv[sz_rfbProtocolVersionMsg] = 0; if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { fprintf(stderr,"%s: Not a valid VNC server\n",programName); return False; } fprintf(stderr,"%s: VNC server supports protocol version %d.%d " "(viewer %d.%d)\n", programName,major,minor,rfbProtocolMajorVersion, rfbProtocolMinorVersion); if ((major == 3) && (minor < 3)) { /* if server is before 3.3 authentication won't work */ authWillWork = False; } else { /* any other server version, just tell it what we want */ major = rfbProtocolMajorVersion; minor = rfbProtocolMinorVersion; } sprintf(pv,rfbProtocolVersionFormat,major,minor); if (!WriteExact(sock, pv, sz_rfbProtocolVersionMsg)) return False; if (!ReadExact(sock, (char *)&authScheme, 4)) return False; authScheme = Swap32IfLE(authScheme); switch (authScheme) { case rfbConnFailed: if (!ReadExact(sock, (char *)&reasonLen, 4)) return False; reasonLen = Swap32IfLE(reasonLen); reason = malloc(reasonLen); if (!ReadExact(sock, reason, reasonLen)) return False; fprintf(stderr,"%s: VNC connection failed: %.*s\n", programName, (int)reasonLen, reason); return False; case rfbNoAuth: fprintf(stderr,"%s: No authentication needed\n",programName); break; case rfbVncAuth: if (!authWillWork) { fprintf(stderr, "\n%s: VNC server uses the old authentication scheme.\n" "You should kill your old desktop(s) and restart.\n" "If you really need to connect to this desktop use " "vncviewer3.2\n\n", programName); return False; } if (!ReadExact(sock, (char *)challenge, CHALLENGESIZE)) return False; if (passwdFile) { passwd = vncDecryptPasswdFromFile(passwdFile); } else { static char pass[32] = {"foobar2"}; passwd = pass; /* passwd = getpass("Password: "); */ if (strlen(passwd) == 0) { fprintf(stderr,"%s: Reading password failed\n",programName); return False; } if (strlen(passwd) > 8) { passwd[8] = '\0'; } } vncEncryptBytes(challenge, passwd); /* Lose the password from memory */ for (i=0; i<strlen(passwd); i++) { passwd[i] = '\0'; } if (!WriteExact(sock, (char *)challenge, CHALLENGESIZE)) return False; if (!ReadExact(sock, (char *)&authResult, 4)) return False; authResult = Swap32IfLE(authResult); switch (authResult) { case rfbVncAuthOK: fprintf(stderr,"%s: VNC authentication succeeded\n",programName); break; case rfbVncAuthFailed: fprintf(stderr,"%s: VNC authentication failed\n",programName); return False; case rfbVncAuthTooMany: fprintf(stderr,"%s: VNC authentication failed - too many tries\n", programName); return False; default: fprintf(stderr,"%s: Unknown VNC authentication result: %d\n", programName,(int)authResult); return False; } break; default: fprintf(stderr, "%s: Unknown authentication scheme from VNC server: %d\n", programName,(int)authScheme); return False; } ci.shared = (shareDesktop ? 1 : 0); if (!WriteExact(sock, (char *)&ci, sz_rfbClientInitMsg)) return False; if (!ReadExact(sock, (char *)&si, sz_rfbServerInitMsg)) return False; si.framebufferWidth = Swap16IfLE(si.framebufferWidth); si.framebufferHeight = Swap16IfLE(si.framebufferHeight); si.format.redMax = Swap16IfLE(si.format.redMax); si.format.greenMax = Swap16IfLE(si.format.greenMax); si.format.blueMax = Swap16IfLE(si.format.blueMax); si.nameLength = Swap32IfLE(si.nameLength); if (((updateRequestX + updateRequestW) > si.framebufferWidth) || ((updateRequestY + updateRequestH) > si.framebufferHeight)) { fprintf(stderr, "%s: region requested is outside server's framebuffer\n", programName); return False; } if (updateRequestW == 0) updateRequestW = si.framebufferWidth - updateRequestX; if (updateRequestH == 0) updateRequestH = si.framebufferHeight - updateRequestY; desktopName = malloc(si.nameLength + 1); if (!ReadExact(sock, desktopName, si.nameLength)) return False; desktopName[si.nameLength] = 0; fprintf(stderr,"%s: Desktop name \"%s\"\n",programName,desktopName); fprintf(stderr, "%s: Connected to VNC server, using protocol version %d.%d\n", programName, rfbProtocolMajorVersion, rfbProtocolMinorVersion); fprintf(stderr,"%s: VNC server default format:\n",programName); PrintPixelFormat(&si.format); return True;}/* * SetFormatAndEncodings. */BoolSetFormatAndEncodings(){ rfbSetPixelFormatMsg spf; char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4]; rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf; CARD32 *encs = (CARD32 *)(&buf[sz_rfbSetEncodingsMsg]); int len = 0; int i; spf.type = rfbSetPixelFormat; spf.format = myFormat; spf.format.redMax = Swap16IfLE(spf.format.redMax); spf.format.greenMax = Swap16IfLE(spf.format.greenMax); spf.format.blueMax = Swap16IfLE(spf.format.blueMax); if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg)) return False; se->type = rfbSetEncodings; se->nEncodings = 0; for (i = 0; i < nExplicitEncodings; i++) { encs[se->nEncodings++] = Swap32IfLE(explicitEncodings[i]); } if (SameMachine(rfbsock)) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); } if (addCopyRect) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); if (addHextile) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); if (addCoRRE) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); if (addRRE) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; se->nEncodings = Swap16IfLE(se->nEncodings); if (!WriteExact(rfbsock, buf, len)) return False; return True;}/* * SendIncrementalFramebufferUpdateRequest. */BoolSendIncrementalFramebufferUpdateRequest(){ return SendFramebufferUpdateRequest(updateRequestX, updateRequestY, updateRequestW, updateRequestH, True);}/* * SendFramebufferUpdateRequest. */BoolSendFramebufferUpdateRequest(int x, int y, int w, int h, Bool incremental){ rfbFramebufferUpdateRequestMsg fur; fur.type = rfbFramebufferUpdateRequest; fur.incremental = incremental ? 1 : 0; fur.x = Swap16IfLE(x); fur.y = Swap16IfLE(y); fur.w = Swap16IfLE(w); fur.h = Swap16IfLE(h); if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) return False; gettimeofday(&updateRequestTime, NULL); sendUpdateRequest = False; return True;}/* * SendPointerEvent. */BoolSendPointerEvent(int x, int y, int buttonMask){ rfbPointerEventMsg pe; pe.type = rfbPointerEvent; pe.buttonMask = buttonMask; if (x < 0) x = 0; if (y < 0) y = 0; pe.x = Swap16IfLE(x); pe.y = Swap16IfLE(y); return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);}/* * SendKeyEvent. */BoolSendKeyEvent(CARD32 key, Bool down){ rfbKeyEventMsg ke; ke.type = rfbKeyEvent; ke.down = down ? 1 : 0; ke.key = Swap32IfLE(key); return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);}/* * SendClientCutText. */BoolSendClientCutText(char *str, int len){ rfbClientCutTextMsg cct; cct.type = rfbClientCutText; cct.length = Swap32IfLE(len); return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && WriteExact(rfbsock, str, len));}/* * HandleRFBServerMessage. */BoolHandleRFBServerMessage(){ rfbServerToClientMsg msg; if (!ReadExact(rfbsock, (char *)&msg, 1)) return False; switch (msg.type) { case rfbSetColourMapEntries: { int i; CARD16 rgb[3]; XColor xc; if (!ReadExact(rfbsock, ((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) return False; msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); msg.scme.nColours = Swap16IfLE(msg.scme.nColours); for (i = 0; i < msg.scme.nColours; i++) { if (!ReadExact(rfbsock, (char *)rgb, 6)) return False; xc.pixel = msg.scme.firstColour + i; xc.red = Swap16IfLE(rgb[0]); xc.green = Swap16IfLE(rgb[1]); xc.blue = Swap16IfLE(rgb[2]); xc.flags = DoRed|DoGreen|DoBlue;/* printf("XStoreColor (%d,%d,%d) = %d\n", xc.red>>8, xc.green>>8, xc.blue>>8, xc.pixel); */ XStoreColor(dpy, cmap, &xc); } break; } case rfbFramebufferUpdate: { rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; if (!ReadExact(rfbsock, ((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); for (i = 0; i < msg.fu.nRects; i++) { if (!ReadExact(rfbsock, (char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); rect.encoding = Swap32IfLE(rect.encoding); if ((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"%s: rect too large: %dx%d at (%d, %d)\n", programName, rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if ((rect.r.h * rect.r.w) == 0) { fprintf(stderr,"%s: zero size rect - ignoring\n",programName); continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -