mirror of
https://github.com/sheumann/VNCviewGS.git
synced 2024-11-28 11:50:59 +00:00
462b351425
I've encountered a server that sometimes sends zero-size cursor updates, which can trigger this case.
801 lines
27 KiB
C++
801 lines
27 KiB
C++
/*********************************************************************
|
|
* vncsession.cc - Routines for initiating/conducting a VNC session
|
|
* with the remote host
|
|
*********************************************************************/
|
|
|
|
#if __ORCAC__
|
|
#pragma lint -1
|
|
#pragma noroot
|
|
segment "VNCview GS";
|
|
#endif
|
|
|
|
#if DEBUG
|
|
/* #pragma debug 25 */
|
|
#endif
|
|
|
|
#include <types.h>
|
|
#include <orca.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <tcpip.h>
|
|
#include <quickdraw.h>
|
|
#include <qdaux.h>
|
|
#include <event.h>
|
|
#include <window.h>
|
|
#include <resources.h>
|
|
#include <misctool.h>
|
|
#include <desk.h>
|
|
#include <control.h>
|
|
#include <locator.h>
|
|
#include <memory.h>
|
|
#include <cryptotool.h>
|
|
#include <menu.h>
|
|
|
|
#include "vncview.h"
|
|
#include "vncsession.h"
|
|
#include "vncdisplay.h"
|
|
#include "menus.h"
|
|
#include "colortables.h"
|
|
|
|
#define linServer 3
|
|
#define linPassword 7
|
|
|
|
#define noCryptoError 2005
|
|
#define authFailedError 2006
|
|
#define authTooManyError 2007
|
|
#define noTCPIPConnectionError 2011
|
|
#define badGetIpidError 2012
|
|
#define badOptionNegotiationError 2013
|
|
#define badHandshakingError 2014
|
|
#define badReadTCPError 2015
|
|
|
|
GrafPortPtr connectStatusWindowPtr = NULL;
|
|
|
|
unsigned int hostIpid;
|
|
void ** readBufferHndl; /* Handle to the data read by the last
|
|
* DoReadTCP call. Copy this elsewhere if more
|
|
* data may be read while it is still in use.
|
|
*/
|
|
static BOOLEAN alerted = FALSE;
|
|
|
|
static void CloseConnectStatusWindow (void);
|
|
static BOOLEAN ConnectTCPIP (void);
|
|
static BOOLEAN GetIpid (void);
|
|
static BOOLEAN DoVNCHandshaking (void);
|
|
static BOOLEAN DoDES (void);
|
|
static BOOLEAN FinishVNCHandshaking (void);
|
|
static void TuneMarinetti (void);
|
|
static void UnTuneMarinetti (void);
|
|
|
|
#define buffTypePointer 0x0000 /* For TCPIPReadTCP() */
|
|
#define buffTypeHandle 0x0001
|
|
#define buffTypeNewHandle 0x0002
|
|
|
|
#define vncConnectionFailed SwapBytes4(0)
|
|
#define vncNoAuthentication SwapBytes4(1)
|
|
#define vncVNCAuthentication SwapBytes4(2)
|
|
|
|
/***************************************************************
|
|
* DoConnect - establish connection to server
|
|
***************************************************************/
|
|
|
|
void DoConnect (void) {
|
|
int i; /* loop counter */
|
|
|
|
if (colorTablesComplete == FALSE) {
|
|
DisplayConnectStatus("\pGenerating color tables...", FALSE);
|
|
MakeBigColorTables(0);
|
|
colorTablesComplete = TRUE;
|
|
CloseConnectStatusWindow();
|
|
}
|
|
|
|
TuneMarinetti();
|
|
|
|
/* Get server & password */
|
|
|
|
GetLETextByID(newConnWindow, linServer, (StringPtr) vncServer);
|
|
GetLETextByID(newConnWindow, linPassword, (StringPtr) vncPassword);
|
|
|
|
/* Try to establish connection before continuing; if unsuccessful, stop */
|
|
if (ConnectTCPIP() == FALSE) {
|
|
SysBeep();
|
|
AlertWindow(awResource, NULL, noTCPIPConnectionError);
|
|
goto errorReturn;
|
|
}
|
|
|
|
if (GetIpid() == FALSE) {
|
|
SysBeep();
|
|
AlertWindow(awResource, NULL, badGetIpidError);
|
|
goto errorReturn;
|
|
}
|
|
|
|
if (DoVNCHandshaking() == FALSE) {
|
|
CloseConnectStatusWindow();
|
|
InitCursor();
|
|
SysBeep();
|
|
if (alerted == FALSE)
|
|
AlertWindow(awResource, NULL, badHandshakingError);
|
|
else
|
|
alerted = FALSE;
|
|
goto errorReturn;
|
|
}
|
|
if (FinishVNCHandshaking() == FALSE) {
|
|
CloseConnectStatusWindow();
|
|
InitCursor();
|
|
AlertWindow(awResource, NULL, badOptionNegotiationError);
|
|
SysBeep();
|
|
goto errorReturn;
|
|
}
|
|
|
|
InitVNCWindow();
|
|
|
|
CloseConnectStatusWindow();
|
|
InitCursor();
|
|
|
|
DoClose(newConnWindow);
|
|
DisableMItem(fileNewConnection);
|
|
|
|
myEvent.wmTaskMask = 0x001D79FE; /* don't let TaskMaster process keys */
|
|
InitMenus(noKB);
|
|
vncConnected = TRUE;
|
|
return;
|
|
|
|
errorReturn:
|
|
UnTuneMarinetti();
|
|
return;
|
|
}
|
|
|
|
/*******************************************************************
|
|
* DisplayConnectStatus - Display modal dialog with status information
|
|
* statusString - P-String to display
|
|
* cancelMessage - determines whether to display string about OA-.
|
|
*******************************************************************/
|
|
|
|
void DisplayConnectStatus(char *statusString, BOOLEAN cancelMessage) {
|
|
#define wrNum 1002
|
|
#define cancelStr 10002
|
|
|
|
GrafPortPtr oldPort;
|
|
Rect bigRect = {0,9,15,293};
|
|
|
|
if (connectStatusWindowPtr == NULL) {
|
|
connectStatusWindowPtr = NewWindow2(NULL, NULL, NULL, NULL,
|
|
0x02, wrNum, rWindParam1);
|
|
}
|
|
|
|
if (connectStatusWindowPtr != NULL) { /* Only draw if window was */
|
|
if (GetMasterSCB() & 0x0080) /* If in 640 mode... */
|
|
MoveWindow(169, 85, connectStatusWindowPtr);
|
|
else /* If in 320 mode... */
|
|
MoveWindow(9, 85, connectStatusWindowPtr);
|
|
|
|
oldPort = GetPort(); /* created successfully */
|
|
SetPort(connectStatusWindowPtr);
|
|
EraseRect(&bigRect); /* Clipped to window's GrafPort */
|
|
MoveTo(bigRect.h1, 13);
|
|
DrawStringWidth(0x6000, (Long) statusString, bigRect.h2 - bigRect.h1);
|
|
if (cancelMessage) {
|
|
MoveTo(bigRect.h1, 24);
|
|
DrawStringWidth(0x0002, cancelStr, bigRect.h2 - bigRect.h1);
|
|
}
|
|
SetPort(oldPort);
|
|
}
|
|
|
|
#undef wrNum
|
|
#undef cancelStr
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DisplayConnectStatusFromTool - Can be passed to Marinetti
|
|
***********************************************************************/
|
|
#pragma databank 1 /* Set data bank register to access globals. */
|
|
#pragma toolparms 1 /* Use tool-style stack model */
|
|
static void DisplayConnectStatusFromTool (char *statusString) {
|
|
DisplayConnectStatus(statusString, TRUE);
|
|
}
|
|
#pragma toolparms 0 /* Use ORCA stack model */
|
|
#pragma databank 0 /* Must restore data bank register on exit */
|
|
|
|
/***********************************************************************
|
|
* CloseConnectStatusWindow - Close connect status window (if open)
|
|
***********************************************************************/
|
|
static void CloseConnectStatusWindow (void) {
|
|
if (connectStatusWindowPtr != NULL) {
|
|
CloseWindow(connectStatusWindowPtr);
|
|
connectStatusWindowPtr = NULL;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ConnectTCPIP - Try to establish a TCP/IP connection through Marinetti
|
|
***********************************************************************/
|
|
static BOOLEAN ConnectTCPIP (void)
|
|
{
|
|
BOOLEAN connected = FALSE; /* Are we connected to the network now? */
|
|
|
|
if (TCPIPGetConnectStatus() == FALSE) { /* If no TCP/IP connection... */
|
|
WaitCursor();
|
|
TCPIPConnect(&DisplayConnectStatusFromTool);
|
|
if (!toolerror())
|
|
connected = TRUE;
|
|
CloseConnectStatusWindow();
|
|
InitCursor();
|
|
}
|
|
else /* Already connected */
|
|
return TRUE;
|
|
|
|
if (connected)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* GetIpid() - parse the server name and attempt to get an ipid for it
|
|
***********************************************************************/
|
|
static BOOLEAN GetIpid (void)
|
|
{
|
|
#define baseDisplayNum 5900
|
|
|
|
int i;
|
|
long hostPort;
|
|
cvtRec hostInfo;
|
|
static dnrBuffer dnrInfo;
|
|
unsigned long initialTime;
|
|
|
|
/* Find ":" character that delimits name (or IP) from display number */
|
|
for (i = vncServer[0]; isdigit(vncServer[i]) && i>0; i--);
|
|
|
|
/* Set port to connect to */
|
|
if (sscanf(&vncServer[i], ":%ld", &hostPort) == 0)
|
|
hostPort = 0;
|
|
hostPort += baseDisplayNum;
|
|
|
|
/* Modify the string so it only contains the hostname or IP */
|
|
if (vncServer[i] == ':') {
|
|
vncServer[0] = i - 1;
|
|
vncServer[i] = 0;
|
|
}
|
|
|
|
/* If it's an IP address, then put it in the record */
|
|
if (TCPIPValidateIPString(vncServer))
|
|
TCPIPConvertIPToHex(&hostInfo, vncServer);
|
|
else { /* Do a DNS lookup */
|
|
hostInfo.cvtPort = TCPIPMangleDomainName(0xF800, vncServer);
|
|
TCPIPDNRNameToIP(vncServer, &dnrInfo);
|
|
if (toolerror())
|
|
return FALSE;
|
|
WaitCursor();
|
|
DisplayConnectStatus("\pResolving domain name...", FALSE);
|
|
initialTime = TickCount();
|
|
while (dnrInfo.DNRstatus == DNR_Pending) {
|
|
if (TickCount() >= initialTime + 15*60)
|
|
break;
|
|
TCPIPPoll(); /* Call TCPIPPoll() so that */
|
|
} /* Marinetti can process data */
|
|
CloseConnectStatusWindow();
|
|
InitCursor();
|
|
if (dnrInfo.DNRstatus == DNR_OK)
|
|
hostInfo.cvtIPAddress == dnrInfo.DNRIPaddress;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
hostIpid = TCPIPLogin(userid(), hostInfo.cvtIPAddress, (int) hostPort,
|
|
0x0010 /* minimize latency */,
|
|
0x0040 /* Normal TTL*/);
|
|
if (toolerror())
|
|
return FALSE;
|
|
|
|
if (TCPIPOpenTCP(hostIpid) == tcperrOK)
|
|
if (!toolerror())
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
#undef baseDisplayNum
|
|
}
|
|
|
|
static unsigned int tcperr;
|
|
|
|
/* Read data, waiting for up to 15 seconds for the data to be ready */
|
|
BOOLEAN DoWaitingReadTCP(unsigned long dataLength) {
|
|
unsigned long stopTime;
|
|
BOOLEAN result = FALSE;
|
|
|
|
stopTime = TickCount() + 15 * 60;
|
|
do {
|
|
result = DoReadTCP(dataLength);
|
|
} while (result == FALSE && tcperr == tcperrOK && TickCount() < stopTime);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/* Fix things when TCPIPReadTCP returns less data than it's supposed to */
|
|
static BOOLEAN ReadFixup (unsigned long requested, unsigned long returned) {
|
|
static rrBuff theRRBuff;
|
|
|
|
SetHandleSize(requested, readBufferHndl);
|
|
if (toolerror())
|
|
return FALSE;
|
|
HLock(readBufferHndl);
|
|
|
|
do {
|
|
TCPIPPoll();
|
|
if ((tcperr = TCPIPReadTCP(hostIpid, buffTypeNewHandle, NULL,
|
|
requested-returned, &theRRBuff)) != tcperrOK)
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
|
|
if (theRRBuff.rrBuffCount == 0) /* To avoid infinite loops */
|
|
return FALSE;
|
|
|
|
HandToPtr(theRRBuff.rrBuffHandle, (char *)*readBufferHndl + returned,
|
|
theRRBuff.rrBuffCount);
|
|
returned += theRRBuff.rrBuffCount;
|
|
|
|
DisposeHandle(theRRBuff.rrBuffHandle);
|
|
} while (returned < requested);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DoReadTCP() - Issue TCPIPReadTCP() call w/ appropriate parameters
|
|
* Return value = did the read succeed?
|
|
**********************************************************************/
|
|
BOOLEAN DoReadTCP (unsigned long dataLength) {
|
|
static srBuff theSRBuff;
|
|
static rrBuff theRRBuff;
|
|
|
|
if (dataLength == 0)
|
|
return TRUE;
|
|
DoneWithReadBuffer();
|
|
TCPIPPoll();
|
|
|
|
if ((tcperr = TCPIPStatusTCP(hostIpid, &theSRBuff)) != tcperrOK)
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
|
|
if (theSRBuff.srRcvQueued < dataLength)
|
|
return FALSE;
|
|
|
|
if ((tcperr = TCPIPReadTCP(hostIpid, buffTypeNewHandle, NULL,
|
|
dataLength, &theRRBuff)) != tcperrOK)
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
if (theRRBuff.rrBuffCount == 0)
|
|
return FALSE;
|
|
|
|
readBufferHndl = theRRBuff.rrBuffHandle;
|
|
|
|
if (theRRBuff.rrBuffCount != dataLength)
|
|
return ReadFixup(dataLength, theRRBuff.rrBuffCount);
|
|
|
|
HLock(readBufferHndl);
|
|
return TRUE;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DoReadMultipleTCP() - Read the largest available multiple of recLen bytes,
|
|
* up to a maximum multiple of maxN.
|
|
* Return value = the multiple n (meaning n * len bytes have been read)
|
|
**********************************************************************/
|
|
unsigned DoReadMultipleTCP(unsigned recLen, unsigned maxN) {
|
|
static srBuff theSRBuff;
|
|
unsigned long n, totalSize;
|
|
|
|
TCPIPPoll();
|
|
|
|
if ((tcperr = TCPIPStatusTCP(hostIpid, &theSRBuff)) != tcperrOK)
|
|
return 0;
|
|
if (toolerror())
|
|
return 0;
|
|
|
|
n = theSRBuff.srRcvQueued / recLen;
|
|
if (n > maxN)
|
|
n = maxN;
|
|
|
|
if (n && DoReadTCP(recLen * n))
|
|
return n;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DoVNCHandshaking() - Establish connection to VNC server
|
|
**********************************************************************/
|
|
static BOOLEAN DoVNCHandshaking (void) {
|
|
#define connectionFailedAlert 2004
|
|
#define badRFBVersionAlert 2008
|
|
#define badAuthTypeAlert 2009
|
|
static char versionString[12];
|
|
unsigned long reasonLength;
|
|
char *errorString;
|
|
|
|
WaitCursor();
|
|
DisplayConnectStatus("\pConnecting to VNC server...", FALSE);
|
|
|
|
/* Read RFB version string from the server */
|
|
strcpy(versionString, "");
|
|
if (! DoWaitingReadTCP(12))
|
|
return FALSE;
|
|
if ( ! ((strncmp((char *)*readBufferHndl, "RFB ", 4) == 0) &&
|
|
(strncmp((char *)*readBufferHndl+4, RFBMAJORVERSIONSTR, 3) >= 0) &&
|
|
(strncmp((char *)*readBufferHndl+7, ".", 1) == 0) &&
|
|
(strncmp((char *)*readBufferHndl+11, "\n", 1) == 0))) {
|
|
InitCursor();
|
|
AlertWindow(awResource, NULL, badRFBVersionAlert);
|
|
alerted = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(versionString, RFBVERSIONSTR);
|
|
if (TCPIPWriteTCP(hostIpid, versionString, 12, TRUE, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
if (toolerror()) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (! DoWaitingReadTCP(4)) { /* Read authentication type */
|
|
return FALSE;
|
|
}
|
|
switch ((unsigned long) (**readBufferHndl)) {
|
|
case vncConnectionFailed: if (! DoWaitingReadTCP(4))
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
reasonLength = SwapBytes4(**readBufferHndl);
|
|
if (! DoWaitingReadTCP(reasonLength))
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
HUnlock(readBufferHndl);
|
|
SetHandleSize(
|
|
GetHandleSize(readBufferHndl)+1,
|
|
readBufferHndl);
|
|
if (! toolerror()) {
|
|
HLock(readBufferHndl);
|
|
*((char *) *readBufferHndl+reasonLength)
|
|
= 0;
|
|
InitCursor();
|
|
AlertWindow(awResource,
|
|
(Pointer) readBufferHndl,
|
|
connectionFailedAlert);
|
|
alerted = TRUE;
|
|
}
|
|
return FALSE;
|
|
case vncNoAuthentication: break;
|
|
case vncVNCAuthentication: if (DoDES())
|
|
break;
|
|
return FALSE;
|
|
default: AlertWindow(awResource, NULL,
|
|
badAuthTypeAlert);
|
|
alerted = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
#undef connectionFailedAlert
|
|
#undef badRFBVersionAlert
|
|
#undef badAuthTypeAlert
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DoDES() - Try to do DES (aka VNC) authentication
|
|
**********************************************************************/
|
|
static BOOLEAN DoDES (void) {
|
|
/* This reverses the order of the low 7 bits of a byte. */
|
|
/* Uses the high bit (7) as scratch space. */
|
|
#define SwitchBits(x) do { x &= 0x7f; /* Clear 7 */ \
|
|
x ^= (x << 7) & 0x80; /* 0 -> 7 */ \
|
|
x &= 0xfe; /* Clear 0 */ \
|
|
x ^= (x >> 6) & 0x01; /* 6 -> 0 */ \
|
|
x &= 0xbf; /* Clear 6 */ \
|
|
x ^= (x >> 1) & 0x40; /* 7 -> 6 */ \
|
|
x &= 0x7f; /* Clear 7 */ \
|
|
x ^= (x << 6) & 0x80; /* 1 -> 7 */ \
|
|
x &= 0xfd; /* Clear 1 */ \
|
|
x ^= (x >> 4) & 0x02; /* 5 -> 1 */ \
|
|
x &= 0xdf; /* Clear 5 */ \
|
|
x ^= (x >> 2) & 0x20; /* 7 -> 5 */ \
|
|
x &= 0x7f; /* Clear 7 */ \
|
|
x ^= (x << 5) & 0x80; /* 2 -> 7 */ \
|
|
x &= 0xfb; /* Clear 2 */ \
|
|
x ^= (x >> 2) & 0x04; /* 4 -> 2 */ \
|
|
x &= 0xef; /* Clear 4 */ \
|
|
x ^= (x >> 3) & 0x10; /* 7 -> 4 */ \
|
|
} while (0)
|
|
#define statusOK SwapBytes4(0)
|
|
#define statusFailed SwapBytes4(1)
|
|
#define statusTooMany SwapBytes4(2)
|
|
unsigned char theResponse[16];
|
|
unsigned char theKey[8];
|
|
BOOLEAN success;
|
|
BOOLEAN startedCrypto = FALSE; /* True if we started CryptoTool */
|
|
Handle dpSpace;
|
|
int i;
|
|
|
|
DisplayConnectStatus("\pAuthenticating...", FALSE);
|
|
|
|
if (!(CryptoStatus() && !toolerror())) { /* if Crypto isn't started */
|
|
startedCrypto = TRUE;
|
|
LoadOneTool(129, 0x100); /* load Crypto tool 1.0+ */
|
|
if (toolerror()) { /* Check that it is available */
|
|
AlertWindow(awResource, NULL, noCryptoError);
|
|
alerted = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
dpSpace = NewHandle(0x0100, userid(),
|
|
attrLocked|attrFixed|attrNoCross|attrBank, 0x00000000);
|
|
CryptoStartUp((Word) *dpSpace);
|
|
}
|
|
|
|
if (! (DoWaitingReadTCP(16))) {
|
|
success = FALSE;
|
|
goto UnloadCrypto;
|
|
}
|
|
|
|
/* Pad password with nulls, as per VNC precedent */
|
|
for (i=vncPassword[0]+1; i<=8; i++)
|
|
vncPassword[i] = 0;
|
|
|
|
/* Flip bits around to be in format expected by CryptoTool */
|
|
for (i=1; i<9; i++)
|
|
SwitchBits(vncPassword[i]);
|
|
|
|
/* Shift password to form 56-bit key */
|
|
vncPassword[1] <<= 1;
|
|
vncPassword[1] += (vncPassword[2] & 0x7f) >> 6;
|
|
vncPassword[2] <<= 2;
|
|
vncPassword[2] += (vncPassword[3] & 0x7f) >> 5;
|
|
vncPassword[3] <<= 3;
|
|
vncPassword[3] += (vncPassword[4] & 0x7f) >> 4;
|
|
vncPassword[4] <<= 4;
|
|
vncPassword[4] += (vncPassword[5] & 0x7f) >> 3;
|
|
vncPassword[5] <<= 5;
|
|
vncPassword[5] += (vncPassword[6] & 0x7f) >> 2;
|
|
vncPassword[6] <<= 6;
|
|
vncPassword[6] += (vncPassword[7] & 0x7f) >> 1;
|
|
vncPassword[7] <<= 7;
|
|
vncPassword[7] += vncPassword[8] & 0x7f;
|
|
|
|
DESAddParity(theKey, &vncPassword[1]);
|
|
|
|
DESCipher(theResponse, theKey, *(char **)readBufferHndl, modeEncrypt);
|
|
DESCipher(&theResponse[8], theKey, *(char **)readBufferHndl+8, modeEncrypt);
|
|
|
|
if (TCPIPWriteTCP(hostIpid, theResponse, sizeof(theResponse), TRUE, FALSE))
|
|
{
|
|
success = FALSE;
|
|
goto UnloadCrypto;
|
|
}
|
|
if (toolerror()) {
|
|
success = FALSE;
|
|
goto UnloadCrypto;
|
|
}
|
|
if (! (DoWaitingReadTCP(4))) {
|
|
success = FALSE;
|
|
goto UnloadCrypto;
|
|
}
|
|
|
|
if ((**readBufferHndl) == statusOK) {
|
|
success = TRUE;
|
|
goto UnloadCrypto;
|
|
}
|
|
else if ((**readBufferHndl) == statusFailed) {
|
|
InitCursor();
|
|
AlertWindow(awResource, NULL, authFailedError);
|
|
alerted = TRUE;
|
|
success = FALSE;
|
|
goto UnloadCrypto;
|
|
}
|
|
else if ((**readBufferHndl) == statusTooMany) {
|
|
InitCursor();
|
|
AlertWindow(awResource, NULL, authTooManyError);
|
|
alerted = TRUE;
|
|
success = FALSE;
|
|
goto UnloadCrypto;
|
|
}
|
|
/* else */
|
|
success = FALSE;
|
|
|
|
UnloadCrypto:
|
|
|
|
if (startedCrypto) {
|
|
CryptoShutDown(); /* Shut down Crypto tool set */
|
|
DisposeHandle(dpSpace);
|
|
UnloadOneTool(129);
|
|
}
|
|
return success;
|
|
|
|
#undef statusOK
|
|
#undef statusFailed
|
|
#undef statusTooMany
|
|
#undef SwitchBits
|
|
}
|
|
|
|
/**********************************************************************
|
|
* FinishVNCHandshaking() - Complete VNC protocol initialization
|
|
**********************************************************************/
|
|
static BOOLEAN FinishVNCHandshaking (void) {
|
|
#define screenTooBigError 2010
|
|
unsigned char sharedFlag;
|
|
unsigned long serverNameLen;
|
|
unsigned long encodingInfoSize;
|
|
struct PixelFormat {
|
|
unsigned char messageType;
|
|
unsigned char padding1;
|
|
unsigned int padding2;
|
|
unsigned char bitsPerPixel;
|
|
unsigned char depth;
|
|
unsigned char bigEndianFlag;
|
|
unsigned char trueColorFlag;
|
|
unsigned int redMax;
|
|
unsigned int greenMax;
|
|
unsigned int blueMax;
|
|
unsigned char redShift;
|
|
unsigned char greenShift;
|
|
unsigned char blueShift;
|
|
unsigned char padding3;
|
|
unsigned int padding4;
|
|
} pixelFormat = {
|
|
0 /* message type - SetPixelFormat */,
|
|
0,0 /* padding */,
|
|
8 /* bpp */,
|
|
8 /* depth */,
|
|
0 /* big endian flag - irrelevant */,
|
|
TRUE /* true color flag */,
|
|
SwapBytes2(7) /* red-max */,
|
|
SwapBytes2(7) /* green-max */,
|
|
SwapBytes2(3) /* blue-max */,
|
|
0 /* red-shift */,
|
|
3 /* green-shift */,
|
|
6 /* blue-shift */,
|
|
0,0 /* padding */
|
|
};
|
|
|
|
struct Encodings {
|
|
unsigned char messageType;
|
|
unsigned char padding;
|
|
unsigned int numberOfEncodings;
|
|
unsigned long firstEncoding;
|
|
unsigned long secondEncoding;
|
|
unsigned long thirdEncoding;
|
|
unsigned long fourthEncoding;
|
|
} encodings = {
|
|
2, /* Message Type - SetEncodings */
|
|
0, /* padding */
|
|
0, /* number of encodings - set below */
|
|
SwapBytes4(0xffffff21), /* DesktopSize pseudo-encoding */
|
|
SwapBytes4(0xffffff11), /* Cursor pseudo-encoding */
|
|
SwapBytes4(1), /* CopyRect encoding */
|
|
SwapBytes4(5) /* Hextile encoding */
|
|
/* Per the spec, raw encoding is supported even though
|
|
* it is not listed here explicitly.
|
|
*/
|
|
};
|
|
|
|
DisplayConnectStatus("\pNegotiating protocol options...", FALSE);
|
|
|
|
/* ClientInitialisation */
|
|
sharedFlag = !!requestSharedSession;
|
|
if (TCPIPWriteTCP(hostIpid, &sharedFlag, sizeof(sharedFlag), TRUE, FALSE))
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
|
|
/* ServerInitialisation */
|
|
if (! DoWaitingReadTCP(2))
|
|
return FALSE;
|
|
fbWidth = SwapBytes2(**(unsigned **)readBufferHndl);
|
|
if (! DoWaitingReadTCP(2))
|
|
return FALSE;
|
|
fbHeight = SwapBytes2(**(unsigned **)readBufferHndl);
|
|
|
|
if ((fbWidth > 16384) || (fbHeight > 16384)) {
|
|
AlertWindow(awResource, NULL, screenTooBigError);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Ignore server's pixel format and display name */
|
|
if (! DoWaitingReadTCP(16))
|
|
return FALSE;
|
|
if (! DoWaitingReadTCP(4))
|
|
return FALSE;
|
|
serverNameLen = SwapBytes4(**(unsigned long **)readBufferHndl);
|
|
if (! DoWaitingReadTCP(serverNameLen))
|
|
return FALSE;
|
|
|
|
if (TCPIPWriteTCP(hostIpid, &pixelFormat.messageType, sizeof(pixelFormat),
|
|
TRUE, FALSE))
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
|
|
if (useHextile) {
|
|
encodings.numberOfEncodings = SwapBytes2(4);
|
|
encodingInfoSize = sizeof(encodings);
|
|
} else {
|
|
/* No Hextile */
|
|
encodings.numberOfEncodings = SwapBytes2(3);
|
|
encodingInfoSize = sizeof(encodings) - 4;
|
|
}
|
|
|
|
if (TCPIPWriteTCP(hostIpid, &encodings.messageType, encodingInfoSize,
|
|
TRUE, FALSE))
|
|
return FALSE;
|
|
if (toolerror())
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
#undef screenTooBigError
|
|
}
|
|
|
|
|
|
/* Marinetti tuning structures */
|
|
static tuneStruct oldTune;
|
|
static tuneStruct newTune;
|
|
|
|
/**********************************************************************
|
|
* TuneMarinetti() - Set Marinetti tuning options for max throughput
|
|
**********************************************************************/
|
|
void TuneMarinetti (void) {
|
|
if (tuneMarinetti) {
|
|
TCPIPGetTuningTable(&oldTune);
|
|
|
|
/* Tune to process max number of datagrams each time polled */
|
|
newTune.tcpTUNECOUNT = 10;
|
|
newTune.tcpTUNEIPUSERPOLLCT = 10;
|
|
newTune.tcpTUNEIPRUNQFREQ = oldTune.tcpTUNEIPRUNQFREQ;
|
|
newTune.tcpTUNEIPRUNQCT = 10;
|
|
newTune.tcpTUNETCPUSERPOLL = oldTune.tcpTUNETCPUSERPOLL;
|
|
TCPIPSetTuningTable(&newTune);
|
|
}
|
|
}
|
|
|
|
/**********************************************************************
|
|
* UnTuneMarinetti() - Set Marinetti tuning options back to old values
|
|
**********************************************************************/
|
|
void UnTuneMarinetti (void) {
|
|
tuneStruct currentTune;
|
|
|
|
if (tuneMarinetti) {
|
|
TCPIPGetTuningTable(¤tTune);
|
|
|
|
/* Restore original tuning table unless something else seems to have
|
|
* modified it in the meantime.
|
|
*/
|
|
if ( currentTune.tcpTUNEIPUSERPOLLCT == newTune.tcpTUNEIPUSERPOLLCT
|
|
&& currentTune.tcpTUNEIPRUNQFREQ == newTune.tcpTUNEIPRUNQFREQ
|
|
&& currentTune.tcpTUNEIPRUNQCT == newTune.tcpTUNEIPRUNQCT
|
|
&& currentTune.tcpTUNETCPUSERPOLL == newTune.tcpTUNETCPUSERPOLL)
|
|
{
|
|
TCPIPSetTuningTable(&oldTune);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CloseTCPConnection() - Close the TCP connection to the host
|
|
**********************************************************************/
|
|
void CloseTCPConnection (void) {
|
|
TCPIPCloseTCP(hostIpid);
|
|
WaitCursor();
|
|
DisplayConnectStatus("\pClosing VNC session...", FALSE);
|
|
do {
|
|
TCPIPPoll();
|
|
TCPIPLogout(hostIpid);
|
|
} while (toolerror() == terrSOCKETOPEN);
|
|
CloseConnectStatusWindow();
|
|
UnTuneMarinetti();
|
|
InitCursor();
|
|
}
|