diff options
author | Constantin Kaplinsky <const@tightvnc.com> | 2006-04-16 06:53:44 +0000 |
---|---|---|
committer | Constantin Kaplinsky <const@tightvnc.com> | 2006-04-16 06:53:44 +0000 |
commit | de179d4ed74239bb64d6651fd24a39bbc29bd5d1 (patch) | |
tree | 368e0c2e675f017d92ecf92da93bf1a20ef2f417 /rfb | |
parent | 32d0d68a5304d7a461e9c34da1dae124a467a98a (diff) | |
download | tigervnc-de179d4ed74239bb64d6651fd24a39bbc29bd5d1.tar.gz tigervnc-de179d4ed74239bb64d6651fd24a39bbc29bd5d1.zip |
The "rfb" library merged with VNC 4.1.1 code.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/merge-with-vnc-4.1.1@522 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'rfb')
129 files changed, 1376 insertions, 1532 deletions
diff --git a/rfb/Blacklist.cxx b/rfb/Blacklist.cxx index 4c4f95b2..4590befe 100644 --- a/rfb/Blacklist.cxx +++ b/rfb/Blacklist.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Blacklist.h b/rfb/Blacklist.h index 4df7ec80..0eb38460 100644 --- a/rfb/Blacklist.h +++ b/rfb/Blacklist.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/CConnection.cxx b/rfb/CConnection.cxx index c6a3eed8..36778f02 100644 --- a/rfb/CConnection.cxx +++ b/rfb/CConnection.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -44,10 +44,6 @@ CConnection::~CConnection() deleteReaderAndWriter(); } -void CConnection::setServerName(const char* serverName_) { - serverName.buf = strDup(serverName_); -} - void CConnection::deleteReaderAndWriter() { delete reader_; @@ -207,10 +203,7 @@ void CConnection::processSecurityTypesMsg() void CConnection::processSecurityMsg() { vlog.debug("processing security message"); - bool done; - if (!security->processMsg(this, &done)) - throwAuthFailureException(); - if (done) { + if (security->processMsg(this)) { state_ = RFBSTATE_SECURITY_RESULT; processSecurityResultMsg(); } @@ -229,17 +222,23 @@ void CConnection::processSecurityResultMsg() switch (result) { case secResultOK: securityCompleted(); - break; + return; case secResultFailed: vlog.debug("auth failed"); - throwAuthFailureException(); + break; case secResultTooMany: vlog.debug("auth failed - too many tries"); - throwAuthFailureException(); + break; default: - vlog.error("unknown security result"); - throwAuthFailureException(); - }; + throw Exception("Unknown security result from server"); + } + CharArray reason; + if (cp.beforeVersion(3,8)) + reason.buf = strDup("Authentication failure"); + else + reason.buf = is->readString(); + state_ = RFBSTATE_INVALID; + throw AuthFailureException(reason.buf); } void CConnection::processInitMsg() @@ -248,20 +247,6 @@ void CConnection::processInitMsg() reader_->readServerInit(); } -void CConnection::throwAuthFailureException() -{ - CharArray reason; - vlog.debug("state=%d, ver=%d.%d", state(), cp.majorVersion, cp.minorVersion); - if (state()==RFBSTATE_SECURITY_RESULT && !cp.beforeVersion(3,8)) { - reason.buf = is->readString(); - } else { - reason.buf = strDup("Authentication failure"); - } - state_ = RFBSTATE_INVALID; - vlog.error(reason.buf); - throw AuthFailureException(reason.buf); -} - void CConnection::throwConnFailedException() { state_ = RFBSTATE_INVALID; diff --git a/rfb/CConnection.h b/rfb/CConnection.h index 480fca30..79110eb9 100644 --- a/rfb/CConnection.h +++ b/rfb/CConnection.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -41,11 +41,14 @@ namespace rfb { CConnection(); virtual ~CConnection(); - // *** - void setServerName(const char* serverName_); - // Methods to initialise the connection + // setServerName() is used to provide a unique(ish) name for the server to + // which we are connected. This might be the result of getPeerEndpoint on + // a TcpSocket, for example, or a host specified by DNS name & port. + // The serverName is used when verifying the Identity of a host (see RA2). + void setServerName(const char* name_) { serverName.replaceBuf(strDup(name_)); } + // setStreams() sets the streams to be used for the connection. These must // be set before initialiseProtocol() and processMsg() are called. The // CSecurity object may call setStreams() again to provide alternative @@ -129,7 +132,9 @@ namespace rfb { rdr::InStream* getInStream() { return is; } rdr::OutStream* getOutStream() { return os; } - char* getServerName() {return strDup(serverName.buf);} + // Access method used by SSecurity implementations that can verify servers' + // Identities, to determine the unique(ish) name of the server. + const char* getServerName() const { return serverName.buf; } enum stateEnum { RFBSTATE_UNINITIALISED, diff --git a/rfb/CMsgHandler.cxx b/rfb/CMsgHandler.cxx index cc7c11fe..bbc11763 100644 --- a/rfb/CMsgHandler.cxx +++ b/rfb/CMsgHandler.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -34,7 +34,7 @@ void CMsgHandler::setDesktopSize(int width, int height) cp.height = height; } -void CMsgHandler::setCursor(const Point& hotspot, const Point& size, void* data, void* mask) +void CMsgHandler::setCursor(int w, int h, const Point& hotspot, void* data, void* mask) { } diff --git a/rfb/CMsgHandler.h b/rfb/CMsgHandler.h index 29218c88..6c86df01 100644 --- a/rfb/CMsgHandler.h +++ b/rfb/CMsgHandler.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -36,8 +36,15 @@ namespace rfb { CMsgHandler(); virtual ~CMsgHandler(); + // The following methods are called as corresponding messages are read. A + // derived class should override these methods as desired. Note that for + // the setDesktopSize(), setPixelFormat() and setName() methods, a derived + // class should call on to CMsgHandler's methods to set the members of cp + // appropriately. + virtual void setDesktopSize(int w, int h); - virtual void setCursor(const Point& hotspot, const Point& size, void* data, void* mask); + virtual void setCursor(int width, int height, const Point& hotspot, + void* data, void* mask); virtual void setPixelFormat(const PixelFormat& pf); virtual void setName(const char* name); virtual void serverInit(); diff --git a/rfb/CMsgReader.cxx b/rfb/CMsgReader.cxx index 46973eb2..38547c0f 100644 --- a/rfb/CMsgReader.cxx +++ b/rfb/CMsgReader.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -41,10 +41,6 @@ CMsgReader::~CMsgReader() delete [] imageBuf; } -void CMsgReader::endMsg() -{ -} - void CMsgReader::readSetColourMapEntries() { is->skip(1); @@ -53,13 +49,11 @@ void CMsgReader::readSetColourMapEntries() rdr::U16Array rgbs(nColours * 3); for (int i = 0; i < nColours * 3; i++) rgbs.buf[i] = is->readU16(); - endMsg(); handler->setColourMapEntries(firstColour, nColours, rgbs.buf); } void CMsgReader::readBell() { - endMsg(); handler->bell(); } @@ -75,19 +69,16 @@ void CMsgReader::readServerCutText() CharArray ca(len+1); ca.buf[len] = 0; is->readBytes(ca.buf, len); - endMsg(); handler->serverCutText(ca.buf, len); } void CMsgReader::readFramebufferUpdateStart() { - endMsg(); handler->framebufferUpdateStart(); } void CMsgReader::readFramebufferUpdateEnd() { - endMsg(); handler->framebufferUpdateEnd(); } @@ -128,17 +119,17 @@ void CMsgReader::readCopyRect(const Rect& r) handler->copyRect(r, srcX, srcY); } -void CMsgReader::readSetCursor(const Point& hotspot, const Point& size) +void CMsgReader::readSetCursor(int width, int height, const Point& hotspot) { - int data_len = size.x * size.y * (handler->cp.pf().bpp/8); - int mask_len = ((size.x+7)/8) * size.y; + int data_len = width * height * (handler->cp.pf().bpp/8); + int mask_len = ((width+7)/8) * height; rdr::U8Array data(data_len); rdr::U8Array mask(mask_len); is->readBytes(data.buf, data_len); is->readBytes(mask.buf, mask_len); - handler->setCursor(hotspot, size, data.buf, mask.buf); + handler->setCursor(width, height, hotspot, data.buf, mask.buf); } rdr::U8* CMsgReader::getImageBuf(int required, int requested, int* nPixels) diff --git a/rfb/CMsgReader.h b/rfb/CMsgReader.h index 8b4638c7..7a611fc8 100644 --- a/rfb/CMsgReader.h +++ b/rfb/CMsgReader.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -53,15 +53,13 @@ namespace rfb { virtual void readBell(); virtual void readServerCutText(); - virtual void endMsg(); - virtual void readFramebufferUpdateStart(); virtual void readFramebufferUpdateEnd(); virtual void readRect(const Rect& r, unsigned int encoding); virtual void readCopyRect(const Rect& r); - virtual void readSetCursor(const Point& hotspot, const Point& size); + virtual void readSetCursor(int width, int height, const Point& hotspot); CMsgReader(CMsgHandler* handler, rdr::InStream* is); diff --git a/rfb/CMsgReaderV3.cxx b/rfb/CMsgReaderV3.cxx index 93708047..d0cfc89f 100644 --- a/rfb/CMsgReaderV3.cxx +++ b/rfb/CMsgReaderV3.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -21,6 +21,7 @@ #include <rdr/InStream.h> #include <rfb/CMsgReaderV3.h> #include <rfb/CMsgHandler.h> +#include <rfb/util.h> using namespace rfb; @@ -41,10 +42,8 @@ void CMsgReaderV3::readServerInit() PixelFormat pf; pf.read(is); handler->setPixelFormat(pf); - char* name = is->readString(); - handler->setName(name); - delete [] name; - endMsg(); + CharArray name(is->readString()); + handler->setName(name.buf); handler->serverInit(); } @@ -85,7 +84,7 @@ void CMsgReaderV3::readMsg() handler->setDesktopSize(w, h); break; case pseudoEncodingCursor: - readSetCursor(Point(x, y), Point(w, h)); + readSetCursor(w, h, Point(x,y)); break; case pseudoEncodingLastRect: nUpdateRectsLeft = 1; // this rectangle is the last one @@ -104,6 +103,5 @@ void CMsgReaderV3::readFramebufferUpdate() { is->skip(1); nUpdateRectsLeft = is->readU16(); - endMsg(); handler->framebufferUpdateStart(); } diff --git a/rfb/CMsgReaderV3.h b/rfb/CMsgReaderV3.h index 93c8c6a5..689bb650 100644 --- a/rfb/CMsgReaderV3.h +++ b/rfb/CMsgReaderV3.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/CMsgWriter.cxx b/rfb/CMsgWriter.cxx index fb272c4b..cdfb4e5f 100644 --- a/rfb/CMsgWriter.cxx +++ b/rfb/CMsgWriter.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -96,7 +96,7 @@ void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental) } -void CMsgWriter::writeKeyEvent(rdr::U32 key, bool down) +void CMsgWriter::keyEvent(rdr::U32 key, bool down) { startMsg(msgTypeKeyEvent); os->writeU8(down); @@ -106,22 +106,23 @@ void CMsgWriter::writeKeyEvent(rdr::U32 key, bool down) } -void CMsgWriter::writePointerEvent(int x, int y, int buttonMask) +void CMsgWriter::pointerEvent(const Point& pos, int buttonMask) { - if (x < 0) x = 0; - if (y < 0) y = 0; - if (x >= cp->width) x = cp->width - 1; - if (y >= cp->height) y = cp->height - 1; + Point p(pos); + if (p.x < 0) p.x = 0; + if (p.y < 0) p.y = 0; + if (p.x >= cp->width) p.x = cp->width - 1; + if (p.y >= cp->height) p.y = cp->height - 1; startMsg(msgTypePointerEvent); os->writeU8(buttonMask); - os->writeU16(x); - os->writeU16(y); + os->writeU16(p.x); + os->writeU16(p.y); endMsg(); } -void CMsgWriter::writeClientCutText(const char* str, int len) +void CMsgWriter::clientCutText(const char* str, int len) { startMsg(msgTypeClientCutText); os->pad(3); @@ -129,8 +130,3 @@ void CMsgWriter::writeClientCutText(const char* str, int len) os->writeBytes(str, len); endMsg(); } - -void CMsgWriter::setOutStream(rdr::OutStream* os_) -{ - os = os_; -} diff --git a/rfb/CMsgWriter.h b/rfb/CMsgWriter.h index 8d6e373c..19be8df9 100644 --- a/rfb/CMsgWriter.h +++ b/rfb/CMsgWriter.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -22,7 +22,7 @@ #ifndef __RFB_CMSGWRITER_H__ #define __RFB_CMSGWRITER_H__ -#include <rdr/types.h> +#include <rfb/InputHandler.h> namespace rdr { class OutStream; } @@ -32,24 +32,25 @@ namespace rfb { class ConnParams; struct Rect; - class CMsgWriter { + class CMsgWriter : public InputHandler { public: virtual ~CMsgWriter(); + // CMsgWriter abstract interface methods virtual void writeClientInit(bool shared)=0; + virtual void startMsg(int type)=0; + virtual void endMsg()=0; + // CMsgWriter implemented methods virtual void writeSetPixelFormat(const PixelFormat& pf); virtual void writeSetEncodings(int nEncodings, rdr::U32* encodings); virtual void writeSetEncodings(int preferredEncoding, bool useCopyRect); virtual void writeFramebufferUpdateRequest(const Rect& r,bool incremental); - virtual void writeKeyEvent(rdr::U32 key, bool down); - virtual void writePointerEvent(int x, int y, int buttonMask); - virtual void writeClientCutText(const char* str, int len); - - virtual void startMsg(int type)=0; - virtual void endMsg()=0; - virtual void setOutStream(rdr::OutStream* os); + // InputHandler implementation + virtual void keyEvent(rdr::U32 key, bool down); + virtual void pointerEvent(const Point& pos, int buttonMask); + virtual void clientCutText(const char* str, int len); ConnParams* getConnParams() { return cp; } rdr::OutStream* getOutStream() { return os; } diff --git a/rfb/CMsgWriterV3.cxx b/rfb/CMsgWriterV3.cxx index a6ad237c..a9807952 100644 --- a/rfb/CMsgWriterV3.cxx +++ b/rfb/CMsgWriterV3.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/CMsgWriterV3.h b/rfb/CMsgWriterV3.h index 0cf6157a..0b2f9afe 100644 --- a/rfb/CMsgWriterV3.h +++ b/rfb/CMsgWriterV3.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/CSecurity.h b/rfb/CSecurity.h index 639d550e..90a01d70 100644 --- a/rfb/CSecurity.h +++ b/rfb/CSecurity.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -18,10 +18,14 @@ // // CSecurity - class on the client side for handling security handshaking. A // derived class for a particular security type overrides the processMsg() -// method. processMsg() is called first when the security type has been -// decided on, and will keep being called whenever there is data to read from -// the server until either it returns false, indicating authentication/security -// failure, or it returns with done set to true, to indicate success. +// method. + +// processMsg() is called first when the security type has been decided on, and +// will keep being called whenever there is data to read from the server. It +// should return false when it needs more data, or true when the security +// handshaking is over and we are now waiting for the SecurityResult message +// from the server. In the event of failure a suitable exception should be +// thrown. // // Note that the first time processMsg() is called, there is no guarantee that // there is any data to read from the CConnection's InStream, but subsequent @@ -39,7 +43,7 @@ namespace rfb { class CSecurity { public: virtual ~CSecurity() {} - virtual bool processMsg(CConnection* cc, bool* done)=0; + virtual bool processMsg(CConnection* cc)=0; virtual void destroy() { delete this; } virtual int getType() const = 0; virtual const char* description() const = 0; diff --git a/rfb/CSecurityNone.h b/rfb/CSecurityNone.h index 23b36cee..54c10168 100644 --- a/rfb/CSecurityNone.h +++ b/rfb/CSecurityNone.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -28,9 +28,7 @@ namespace rfb { class CSecurityNone : public CSecurity { public: - virtual bool processMsg(CConnection* cc, bool* done) { - *done = true; return true; - } + virtual bool processMsg(CConnection* cc) { return true; } virtual int getType() const {return secTypeNone;} virtual const char* description() const {return "No Encryption";} }; diff --git a/rfb/CSecurityVncAuth.cxx b/rfb/CSecurityVncAuth.cxx index 3d6c87c5..ba5a30b7 100644 --- a/rfb/CSecurityVncAuth.cxx +++ b/rfb/CSecurityVncAuth.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -18,19 +18,25 @@ // // CSecurityVncAuth // +// XXX not thread-safe, because d3des isn't - do we need to worry about this? +// #include <string.h> #include <stdio.h> #include <rfb/CConnection.h> #include <rfb/UserPasswdGetter.h> -#include <rfb/vncAuth.h> +#include <rfb/Password.h> #include <rfb/CSecurityVncAuth.h> -#include <rfb/LogWriter.h> #include <rfb/util.h> +extern "C" { +#include <rfb/d3des.h> +} + using namespace rfb; -static LogWriter vlog("VncAuth"); +static const int vncAuthChallengeSize = 16; + CSecurityVncAuth::CSecurityVncAuth(UserPasswdGetter* upg_) : upg(upg_) @@ -41,23 +47,28 @@ CSecurityVncAuth::~CSecurityVncAuth() { } -bool CSecurityVncAuth::processMsg(CConnection* cc, bool* done) +bool CSecurityVncAuth::processMsg(CConnection* cc) { - *done = false; rdr::InStream* is = cc->getInStream(); rdr::OutStream* os = cc->getOutStream(); + // Read the challenge & obtain the user's password rdr::U8 challenge[vncAuthChallengeSize]; is->readBytes(challenge, vncAuthChallengeSize); - CharArray passwd; - if (!upg->getUserPasswd(0, &passwd.buf)) { - vlog.error("Getting password failed"); - return false; - } - vncAuthEncryptChallenge(challenge, passwd.buf); - memset(passwd.buf, 0, strlen(passwd.buf)); + PlainPasswd passwd; + upg->getUserPasswd(0, &passwd.buf); + + // Calculate the correct response + rdr::U8 key[8]; + int pwdLen = strlen(passwd.buf); + for (int i=0; i<8; i++) + key[i] = i<pwdLen ? passwd.buf[i] : 0; + deskey(key, EN0); + for (int j = 0; j < vncAuthChallengeSize; j += 8) + des(challenge+j, challenge+j); + + // Return the response to the server os->writeBytes(challenge, vncAuthChallengeSize); os->flush(); - *done = true; return true; } diff --git a/rfb/CSecurityVncAuth.h b/rfb/CSecurityVncAuth.h index bfa40b3b..8d38d878 100644 --- a/rfb/CSecurityVncAuth.h +++ b/rfb/CSecurityVncAuth.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -20,7 +20,6 @@ #include <rfb/CSecurity.h> #include <rfb/secTypes.h> -#include <rfb/vncAuth.h> namespace rfb { @@ -30,7 +29,7 @@ namespace rfb { public: CSecurityVncAuth(UserPasswdGetter* pg); virtual ~CSecurityVncAuth(); - virtual bool processMsg(CConnection* cc, bool* done); + virtual bool processMsg(CConnection* cc); virtual int getType() const {return secTypeVncAuth;}; virtual const char* description() const {return "No Encryption";} private: diff --git a/rfb/ColourCube.h b/rfb/ColourCube.h index 904256c4..b83cbba8 100644 --- a/rfb/ColourCube.h +++ b/rfb/ColourCube.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/ColourMap.h b/rfb/ColourMap.h index ee7783dc..da6cb126 100644 --- a/rfb/ColourMap.h +++ b/rfb/ColourMap.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/ComparingUpdateTracker.cxx b/rfb/ComparingUpdateTracker.cxx index 0b548a6c..ce3d68ae 100644 --- a/rfb/ComparingUpdateTracker.cxx +++ b/rfb/ComparingUpdateTracker.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -24,8 +24,7 @@ using namespace rfb; ComparingUpdateTracker::ComparingUpdateTracker(PixelBuffer* buffer) - : SimpleUpdateTracker(true), fb(buffer), - oldFb(fb->getPF(), 0, 0), firstCompare(true) + : fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true) { changed.assign_union(fb->getRect()); } @@ -35,19 +34,6 @@ ComparingUpdateTracker::~ComparingUpdateTracker() } -void ComparingUpdateTracker::flush_update(UpdateInfo* info, - const Region& cliprgn, int maxArea) -{ - throw rfb::Exception("flush_update(UpdateInfo*) not implemented"); -} - -void ComparingUpdateTracker::flush_update(UpdateTracker &ut, - const Region &cliprgn) -{ - throw rfb::Exception("flush_update(UpdateTracker&) not implemented"); -} - - #define BLOCK_SIZE 16 void ComparingUpdateTracker::compare() @@ -60,7 +46,7 @@ void ComparingUpdateTracker::compare() // since in effect the entire framebuffer has changed. oldFb.setSize(fb->width(), fb->height()); for (int y=0; y<fb->height(); y+=BLOCK_SIZE) { - Rect pos(0, y, fb->width(), vncmin(fb->height(), y+BLOCK_SIZE)); + Rect pos(0, y, fb->width(), __rfbmin(fb->height(), y+BLOCK_SIZE)); int srcStride; const rdr::U8* srcData = fb->getPixelsR(pos, &srcStride); oldFb.imageRect(pos, srcData, srcStride); @@ -100,20 +86,20 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) for (int blockTop = r.tl.y; blockTop < r.br.y; blockTop += BLOCK_SIZE) { // Get a strip of the source buffer - Rect pos(r.tl.x, blockTop, r.br.x, vncmin(r.br.y, blockTop+BLOCK_SIZE)); + Rect pos(r.tl.x, blockTop, r.br.x, __rfbmin(r.br.y, blockTop+BLOCK_SIZE)); int fbStride; const rdr::U8* newBlockPtr = fb->getPixelsR(pos, &fbStride); int newStrideBytes = fbStride * bytesPerPixel; rdr::U8* oldBlockPtr = oldData; - int blockBottom = vncmin(blockTop+BLOCK_SIZE, r.br.y); + int blockBottom = __rfbmin(blockTop+BLOCK_SIZE, r.br.y); for (int blockLeft = r.tl.x; blockLeft < r.br.x; blockLeft += BLOCK_SIZE) { const rdr::U8* newPtr = newBlockPtr; rdr::U8* oldPtr = oldBlockPtr; - int blockRight = vncmin(blockLeft+BLOCK_SIZE, r.br.x); + int blockRight = __rfbmin(blockLeft+BLOCK_SIZE, r.br.x); int blockWidthInBytes = (blockRight-blockLeft) * bytesPerPixel; for (int y = blockTop; y < blockBottom; y++) diff --git a/rfb/ComparingUpdateTracker.h b/rfb/ComparingUpdateTracker.h index bec93d1f..5d2e5edf 100644 --- a/rfb/ComparingUpdateTracker.h +++ b/rfb/ComparingUpdateTracker.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -32,10 +32,6 @@ namespace rfb { // as appropriate. virtual void compare(); - - virtual void flush_update(UpdateInfo* info, const Region& cliprgn, - int maxArea); - virtual void flush_update(UpdateTracker &info, const Region &cliprgn); private: void compareRect(const Rect& r, Region* newchanged); PixelBuffer* fb; diff --git a/rfb/Configuration.cxx b/rfb/Configuration.cxx index a08260dd..9ebc20a8 100644 --- a/rfb/Configuration.cxx +++ b/rfb/Configuration.cxx @@ -1,6 +1,6 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2004-2005 Cendio AB. 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 @@ -32,15 +32,19 @@ #include <rfb/Configuration.h> #include <rfb/LogWriter.h> #include <rfb/Exception.h> - -#ifdef WIN32 - -// Under Win32, we use these routines from several threads, -// so we must provide suitable locking. #include <rfb/Threading.h> -static rfb::Mutex configLock; - +#ifdef __RFB_THREADING_IMPL +// On platforms that support Threading, we use Locks to make getData safe +#define LOCK_CONFIG Lock l(*configLock()) +rfb::Mutex* configLock_ = 0; +static rfb::Mutex* configLock() { + if (!configLock_) + configLock_ = new rfb::Mutex; + return configLock_; +} +#else +#define LOCK_CONFIG #endif #include <rdr/HexOutStream.h> @@ -51,15 +55,47 @@ using namespace rfb; static LogWriter vlog("Config"); -// -=- Configuration +// -=- The Global Configuration object +Configuration* Configuration::global_ = 0; +Configuration* Configuration::global() { + if (!global_) + global_ = new Configuration("Global"); + return global_; +} -VoidParameter* Configuration::head = 0; -bool Configuration::setParam(const char* n, const char* v, bool immutable) { - return setParam(n, strlen(n), v, immutable); +// -=- Configuration implementation + +Configuration::Configuration(const char* name_, Configuration* attachToGroup) +: name(strDup(name_)), head(0), _next(0) { + if (attachToGroup) { + _next = attachToGroup->_next; + attachToGroup->_next = this; + } } -bool Configuration::setParam(const char* name, int len, +Configuration& Configuration::operator=(const Configuration& src) { + VoidParameter* current = head; + while (current) { + VoidParameter* srcParam = ((Configuration&)src).get(current->getName()); + if (srcParam) { + current->immutable = false; + CharArray value(srcParam->getValueStr()); + vlog.debug("operator=(%s, %s)", current->getName(), value.buf); + current->setParam(value.buf); + } + current = current->_next; + } + if (_next) + *_next=src; + return *this; +} + +bool Configuration::set(const char* n, const char* v, bool immutable) { + return set(n, strlen(n), v, immutable); +} + +bool Configuration::set(const char* name, int len, const char* val, bool immutable) { VoidParameter* current = head; @@ -75,10 +111,10 @@ bool Configuration::setParam(const char* name, int len, } current = current->_next; } - return false; + return _next ? _next->set(name, len, val, immutable) : false; } -bool Configuration::setParam(const char* config, bool immutable) { +bool Configuration::set(const char* config, bool immutable) { bool hyphen = false; if (config[0] == '-') { hyphen = true; @@ -87,7 +123,7 @@ bool Configuration::setParam(const char* config, bool immutable) { } const char* equal = strchr(config, '='); if (equal) { - return setParam(config, equal-config, equal+1, immutable); + return set(config, equal-config, equal+1, immutable); } else if (hyphen) { VoidParameter* current = head; while (current) { @@ -101,10 +137,10 @@ bool Configuration::setParam(const char* config, bool immutable) { current = current->_next; } } - return false; + return _next ? _next->set(config, immutable) : false; } -VoidParameter* Configuration::getParam(const char* param) +VoidParameter* Configuration::get(const char* param) { VoidParameter* current = head; while (current) { @@ -112,11 +148,13 @@ VoidParameter* Configuration::getParam(const char* param) return current; current = current->_next; } - return 0; + return _next ? _next->get(param) : 0; } -void Configuration::listParams(int width, int nameWidth) { +void Configuration::list(int width, int nameWidth) { VoidParameter* current = head; + + fprintf(stderr, "%s Parameters:\n", name.buf); while (current) { char* def_str = current->getDefaultStr(); const char* desc = current->getDescription(); @@ -150,14 +188,20 @@ void Configuration::listParams(int width, int nameWidth) { } current = current->_next; } + + if (_next) + _next->list(width, nameWidth); } + // -=- VoidParameter -VoidParameter::VoidParameter(const char* name_, const char* desc_) +VoidParameter::VoidParameter(const char* name_, const char* desc_, Configuration* conf) : immutable(false), _hasBeenSet(false), name(name_), description(desc_) { - _next = Configuration::head; - Configuration::head = this; + if (!conf) + conf = Configuration::global(); + _next = conf->head; + conf->head = this; } VoidParameter::~VoidParameter() { @@ -200,8 +244,8 @@ VoidParameter::hasBeenSet() { // -=- AliasParameter AliasParameter::AliasParameter(const char* name_, const char* desc_, - VoidParameter* param_) - : VoidParameter(name_, desc_), param(param_) { + VoidParameter* param_, Configuration* conf) + : VoidParameter(name_, desc_, conf), param(param_) { } bool @@ -235,8 +279,8 @@ AliasParameter::setImmutable() { // -=- BoolParameter -BoolParameter::BoolParameter(const char* name_, const char* desc_, bool v) -: VoidParameter(name_, desc_), value(v), def_value(v) { +BoolParameter::BoolParameter(const char* name_, const char* desc_, bool v, Configuration* conf) +: VoidParameter(name_, desc_, conf), value(v), def_value(v) { } bool @@ -271,15 +315,11 @@ void BoolParameter::setParam(bool b) { char* BoolParameter::getDefaultStr() const { - char* result = new char[8]; - sprintf(result, "%d", (int)def_value); - return result; + return strDup(def_value ? "1" : "0"); } char* BoolParameter::getValueStr() const { - char* result = new char[8]; - sprintf(result, "%d", (int)value); - return result; + return strDup(value ? "1" : "0"); } bool BoolParameter::isBool() const { @@ -292,15 +332,21 @@ BoolParameter::operator bool() const { // -=- IntParameter -IntParameter::IntParameter(const char* name_, const char* desc_, int v) -: VoidParameter(name_, desc_), value(v), def_value(v) { +IntParameter::IntParameter(const char* name_, const char* desc_, int v, + int minValue_, int maxValue_, Configuration* conf) + : VoidParameter(name_, desc_, conf), value(v), def_value(v), + minValue(minValue_), maxValue(maxValue_) +{ } bool IntParameter::setParam(const char* v) { if (immutable) return true; vlog.debug("set %s(Int) to %s", getName(), v); - value = atoi(v); + int i = atoi(v); + if (i < minValue || i > maxValue) + return false; + value = i; return true; } @@ -308,6 +354,8 @@ bool IntParameter::setParam(int v) { if (immutable) return true; vlog.debug("set %s(Int) to %d", getName(), v); + if (v < minValue || v > maxValue) + return false; value = v; return true; } @@ -332,8 +380,8 @@ IntParameter::operator int() const { // -=- StringParameter StringParameter::StringParameter(const char* name_, const char* desc_, - const char* v) - : VoidParameter(name_, desc_), value(strDup(v)), def_value(v) + const char* v, Configuration* conf) + : VoidParameter(name_, desc_, conf), value(strDup(v)), def_value(v) { if (!v) { fprintf(stderr,"Default value <null> for %s not allowed\n",name_); @@ -346,14 +394,12 @@ StringParameter::~StringParameter() { } bool StringParameter::setParam(const char* v) { -#ifdef WIN32 - Lock l(configLock); -#endif + LOCK_CONFIG; if (immutable) return true; if (!v) throw rfb::Exception("setParam(<null>) not allowed"); vlog.debug("set %s(String) to %s", getName(), v); - strFree(value); + CharArray oldValue(value); value = strDup(v); return value != 0; } @@ -363,16 +409,14 @@ char* StringParameter::getDefaultStr() const { } char* StringParameter::getValueStr() const { -#ifdef WIN32 - Lock l(configLock); -#endif + LOCK_CONFIG; return strDup(value); } // -=- BinaryParameter -BinaryParameter::BinaryParameter(const char* name_, const char* desc_, const void* v, int l) -: VoidParameter(name_, desc_), value(0), length(0), def_value((char*)v), def_length(l) { +BinaryParameter::BinaryParameter(const char* name_, const char* desc_, const void* v, int l, Configuration* conf) +: VoidParameter(name_, desc_, conf), value(0), length(0), def_value((char*)v), def_length(l) { if (l) { value = new char[l]; length = l; @@ -385,18 +429,14 @@ BinaryParameter::~BinaryParameter() { } bool BinaryParameter::setParam(const char* v) { -#ifdef WIN32 - Lock l(configLock); -#endif + LOCK_CONFIG; if (immutable) return true; vlog.debug("set %s(Binary) to %s", getName(), v); return rdr::HexInStream::hexStrToBin(v, &value, &length); } void BinaryParameter::setParam(const void* v, int len) { -#ifdef WIN32 - Lock l(configLock); -#endif + LOCK_CONFIG; if (immutable) return; vlog.debug("set %s(Binary)", getName()); delete [] value; value = 0; @@ -412,16 +452,12 @@ char* BinaryParameter::getDefaultStr() const { } char* BinaryParameter::getValueStr() const { -#ifdef WIN32 - Lock l(configLock); -#endif + LOCK_CONFIG; return rdr::HexOutStream::binToHexStr(value, length); } void BinaryParameter::getData(void** data_, int* length_) const { -#ifdef WIN32 - Lock l(configLock); -#endif + LOCK_CONFIG; if (length_) *length_ = length; if (data_) { *data_ = new char[length]; diff --git a/rfb/Configuration.h b/rfb/Configuration.h index d50c1cb1..e3b85b83 100644 --- a/rfb/Configuration.h +++ b/rfb/Configuration.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -27,38 +27,106 @@ // Simply defining a new parameter and associating it with a Configuration // will allow it to be configured by the user. // -// The Configuration class is used to allow multiple distinct configurations -// to co-exist at the same time. A process serving several desktops, for -// instance, can create a Configuration instance for each, to allow them -// to be configured independently, from the command-line, registry, etc. +// If no Configuration is specified when creating a Parameter, then the +// global Configuration will be assumed. +// +// Configurations can be "chained" into groups. Each group has a root +// Configuration, a pointer to which should be passed to the constructors +// of the other group members. set() and get() operations called on the +// root will iterate through all of the group's members. +// +// NB: On platforms that support Threading, locking is performed to protect +// complex parameter types from concurrent access (e.g. strings). +// NB: NO LOCKING is performed when linking Configurations to groups +// or when adding Parameters to Configurations. #ifndef __RFB_CONFIGURATION_H__ #define __RFB_CONFIGURATION_H__ +#include <rfb/util.h> + namespace rfb { class VoidParameter; + struct ParameterIterator; // -=- Configuration // Class used to access parameters. class Configuration { public: + // - Create a new Configuration object + Configuration(const char* name, Configuration* attachToGroup=0); + + // - Return the buffer containing the Configuration's name + const char* getName() const { return name.buf; } + + // - Assignment operator. For every Parameter in this Configuration's + // group, get()s the corresponding source parameter and copies its + // content. + Configuration& operator=(const Configuration& src); + // - Set named parameter to value - static bool setParam(const char* param, const char* value, bool immutable=false); + bool set(const char* param, const char* value, bool immutable=false); // - Set parameter to value (separated by "=") - static bool setParam(const char* config, bool immutable=false); + bool set(const char* config, bool immutable=false); // - Set named parameter to value, with name truncated at len - static bool setParam(const char* name, int len, - const char* val, bool immutable); + bool set(const char* name, int len, + const char* val, bool immutable); // - Get named parameter - static VoidParameter* getParam(const char* param); + VoidParameter* get(const char* param); + + // - List the parameters of this Configuration group + void list(int width=79, int nameWidth=10); + + // - readFromFile + // Read configuration parameters from the specified file. + void readFromFile(const char* filename); + + // - writeConfigToFile + // Write a new configuration parameters file, then mv it + // over the old file. + void writeToFile(const char* filename); + + + // - Get the Global Configuration object + // NB: This call does NOT lock the Configuration system. + // ALWAYS ensure that if you have ANY global Parameters, + // then they are defined as global objects, to ensure that + // global() is called when only the main thread is running. + static Configuration* global(); - static void listParams(int width=79, int nameWidth=10); + // - Container for process-wide Global parameters + static bool setParam(const char* param, const char* value, bool immutable=false) { + return global()->set(param, value, immutable); + } + static bool setParam(const char* config, bool immutable=false) { + return global()->set(config, immutable); + } + static bool setParam(const char* name, int len, + const char* val, bool immutable) { + return global()->set(name, len, val, immutable); + } + static VoidParameter* getParam(const char* param) { return global()->get(param); } + static void listParams(int width=79, int nameWidth=10) { global()->list(width, nameWidth); } + + protected: + friend class VoidParameter; + friend struct ParameterIterator; + + // Name for this Configuration + CharArray name; - static VoidParameter* head; + // - Pointer to first Parameter in this group + VoidParameter* head; + + // Pointer to next Configuration in this group + Configuration* _next; + + // The process-wide, Global Configuration object + static Configuration* global_; }; // -=- VoidParameter @@ -66,7 +134,7 @@ namespace rfb { class VoidParameter { public: - VoidParameter(const char* name_, const char* desc_); + VoidParameter(const char* name_, const char* desc_, Configuration* conf=0); virtual ~VoidParameter(); const char* getName() const; const char* getDescription() const; @@ -81,8 +149,11 @@ namespace rfb { virtual void setHasBeenSet(); bool hasBeenSet(); - VoidParameter* _next; protected: + friend class Configuration; + friend struct ParameterIterator; + + VoidParameter* _next; bool immutable; bool _hasBeenSet; const char* name; @@ -91,7 +162,7 @@ namespace rfb { class AliasParameter : public VoidParameter { public: - AliasParameter(const char* name_, const char* desc_,VoidParameter* param_); + AliasParameter(const char* name_, const char* desc_,VoidParameter* param_, Configuration* conf=0); virtual bool setParam(const char* value); virtual bool setParam(); virtual char* getDefaultStr() const; @@ -104,7 +175,7 @@ namespace rfb { class BoolParameter : public VoidParameter { public: - BoolParameter(const char* name_, const char* desc_, bool v); + BoolParameter(const char* name_, const char* desc_, bool v, Configuration* conf=0); virtual bool setParam(const char* value); virtual bool setParam(); virtual void setParam(bool b); @@ -119,7 +190,8 @@ namespace rfb { class IntParameter : public VoidParameter { public: - IntParameter(const char* name_, const char* desc_, int v); + IntParameter(const char* name_, const char* desc_, int v, + int minValue=INT_MIN, int maxValue=INT_MAX, Configuration* conf=0); virtual bool setParam(const char* value); virtual bool setParam(int v); virtual char* getDefaultStr() const; @@ -128,13 +200,14 @@ namespace rfb { protected: int value; int def_value; + int minValue, maxValue; }; class StringParameter : public VoidParameter { public: // StringParameter contains a null-terminated string, which CANNOT // be Null, and so neither can the default value! - StringParameter(const char* name_, const char* desc_, const char* v); + StringParameter(const char* name_, const char* desc_, const char* v, Configuration* conf=0); virtual ~StringParameter(); virtual bool setParam(const char* value); virtual char* getDefaultStr() const; @@ -150,13 +223,15 @@ namespace rfb { class BinaryParameter : public VoidParameter { public: - BinaryParameter(const char* name_, const char* desc_, const void* v, int l); + BinaryParameter(const char* name_, const char* desc_, const void* v, int l, Configuration* conf=0); virtual ~BinaryParameter(); virtual bool setParam(const char* value); virtual void setParam(const void* v, int l); virtual char* getDefaultStr() const; virtual char* getValueStr() const; + // getData() will return length zero if there is no data + // NB: data may be set to zero, OR set to a zero-length buffer void getData(void** data, int* length) const; protected: @@ -166,6 +241,25 @@ namespace rfb { int def_length; }; + // -=- ParameterIterator + // Iterates over all the Parameters in a Configuration group. The + // current Parameter is accessed via param, the current Configuration + // via config. The next() method moves on to the next Parameter. + + struct ParameterIterator { + ParameterIterator(Configuration* c) : config(c), param(c ? c->head : 0) {} + void next() { + param = param->_next; + while (!param) { + config = config->_next; + if (!config) break; + param = config->head; + } + } + Configuration* config; + VoidParameter* param; + }; + }; #endif // __RFB_CONFIGURATION_H__ diff --git a/rfb/ConnParams.cxx b/rfb/ConnParams.cxx index 4a8e5344..d4ae5894 100644 --- a/rfb/ConnParams.cxx +++ b/rfb/ConnParams.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -27,9 +27,10 @@ using namespace rfb; ConnParams::ConnParams() : majorVersion(0), minorVersion(0), width(0), height(0), useCopyRect(false), - supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(false), supportsLastRect(false), - customCompressLevel(false), compressLevel(6), noJpeg(false), qualityLevel(-1), - name_(0), nEncodings_(0), encodings_(0), + supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(true), + supportsLastRect(false), customCompressLevel(false), compressLevel(6), + noJpeg(false), qualityLevel(-1), + name_(0), nEncodings_(0), encodings_(0), currentEncoding_(encodingRaw), verStrPos(0) { setName(""); @@ -88,6 +89,7 @@ void ConnParams::setEncodings(int nEncodings, const rdr::U32* encodings) nEncodings_ = nEncodings; useCopyRect = false; supportsLocalCursor = false; + supportsDesktopResize = false; supportsLocalXCursor = false; supportsLastRect = false; customCompressLevel = false; diff --git a/rfb/ConnParams.h b/rfb/ConnParams.h index 09e79c25..47e6a5fb 100644 --- a/rfb/ConnParams.h +++ b/rfb/ConnParams.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Cursor.cxx b/rfb/Cursor.cxx index b50d9255..c8dc341b 100644 --- a/rfb/Cursor.cxx +++ b/rfb/Cursor.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -83,6 +83,7 @@ rdr::U8* Cursor::getBitmap(Pixel* pix0, Pixel* pix1) { bool gotPix0 = false; bool gotPix1 = false; + *pix0 = *pix1 = 0; rdr::U8Array source(maskLen()); memset(source.buf, 0, maskLen()); diff --git a/rfb/Cursor.h b/rfb/Cursor.h index 0f187750..7d94d705 100644 --- a/rfb/Cursor.h +++ b/rfb/Cursor.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Decoder.cxx b/rfb/Decoder.cxx index e04cbf97..b6e4fd5b 100644 --- a/rfb/Decoder.cxx +++ b/rfb/Decoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Decoder.h b/rfb/Decoder.h index 914b26a9..3fdba537 100644 --- a/rfb/Decoder.h +++ b/rfb/Decoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Encoder.cxx b/rfb/Encoder.cxx index aba38b33..53cb1709 100644 --- a/rfb/Encoder.cxx +++ b/rfb/Encoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Encoder.h b/rfb/Encoder.h index 71739ba2..df50dd6d 100644 --- a/rfb/Encoder.h +++ b/rfb/Encoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/HTTPServer.cxx b/rfb/HTTPServer.cxx index 3bac4f89..e40d4802 100644 --- a/rfb/HTTPServer.cxx +++ b/rfb/HTTPServer.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -20,11 +20,6 @@ #include <rfb/LogWriter.h> #include <rfb/util.h> #include <rdr/MemOutStream.h> -#include <time.h> - -// *** Shouldn't really link against this - only for ClientWaitTimeMillis -// and IdleTimeout -#include <rfb/ServerCore.h> #ifdef WIN32 #define strcasecmp _stricmp @@ -36,6 +31,9 @@ using namespace rdr; static LogWriter vlog("HTTPServer"); +const int clientWaitTimeMillis = 20000; +const int idleTimeoutSecs = 5 * 60; + // // -=- LineReader @@ -94,7 +92,8 @@ protected: class rfb::HTTPServer::Session { public: Session(network::Socket& s, rfb::HTTPServer& srv) - : contentType(0), line(s.inStream(), 256), sock(s), + : contentType(0), contentLength(-1), lastModified(-1), + line(s.inStream(), 256), sock(s), server(srv), state(ReadRequestLine), lastActive(time(0)) { } ~Session() { @@ -111,6 +110,8 @@ public: protected: CharArray uri; const char* contentType; + int contentLength; + time_t lastModified; LineReader line; network::Socket& sock; rfb::HTTPServer& server; @@ -140,6 +141,7 @@ void writeLine(OutStream& os, const char* text) { // - Write an HTTP-compliant response to the client + void HTTPServer::Session::writeResponse(int result, const char* text) { char buffer[1024]; @@ -149,6 +151,19 @@ HTTPServer::Session::writeResponse(int result, const char* text) { OutStream& os=sock.outStream(); writeLine(os, buffer); writeLine(os, "Server: TightVNC/4.0"); + time_t now = time(0); + struct tm* tm = gmtime(&now); + strftime(buffer, 1024, "Date: %a, %d %b %Y %H:%M:%S GMT", tm); + writeLine(os, buffer); + if (lastModified == (time_t)-1 || lastModified == 0) + lastModified = now; + tm = gmtime(&lastModified); + strftime(buffer, 1024, "Last-Modified: %a, %d %b %Y %H:%M:%S GMT", tm); + writeLine(os, buffer); + if (contentLength != -1) { + sprintf(buffer,"Content-Length: %d",contentLength); + writeLine(os, buffer); + } writeLine(os, "Connection: close"); os.writeBytes("Content-Type: ", 14); if (result == 200) { @@ -247,7 +262,10 @@ HTTPServer::Session::processHTTP() { { CharArray address(sock.getPeerAddress()); vlog.info("getting %s for %s", uri.buf, address.buf); - InStream* data = server.getFile(uri.buf, &contentType); + contentLength = -1; + lastModified = -1; + InStream* data = server.getFile(uri.buf, &contentType, &contentLength, + &lastModified); if (!data) return writeResponse(404); @@ -277,9 +295,9 @@ HTTPServer::Session::processHTTP() { int HTTPServer::Session::checkIdleTimeout() { time_t now = time(0); - int timeout = (lastActive + rfb::Server::idleTimeout) - now; + int timeout = (lastActive + idleTimeoutSecs) - now; if (timeout > 0) - return timeout * 1000; + return secsToMillis(timeout); sock.shutdown(); return 0; } @@ -291,28 +309,38 @@ HTTPServer::HTTPServer() { HTTPServer::~HTTPServer() { std::list<Session*>::iterator i; - for (i=sessions.begin(); i!=sessions.end(); i++) { - delete (*i)->getSock(); + for (i=sessions.begin(); i!=sessions.end(); i++) delete *i; - } } // -=- SocketServer interface implementation void -HTTPServer::addClient(network::Socket* sock) { +HTTPServer::addSocket(network::Socket* sock, bool) { Session* s = new Session(*sock, *this); if (!s) { sock->shutdown(); } else { - sock->inStream().setTimeout(rfb::Server::clientWaitTimeMillis); - sock->outStream().setTimeout(rfb::Server::clientWaitTimeMillis); + sock->inStream().setTimeout(clientWaitTimeMillis); + sock->outStream().setTimeout(clientWaitTimeMillis); sessions.push_front(s); } } -bool +void +HTTPServer::removeSocket(network::Socket* sock) { + std::list<Session*>::iterator i; + for (i=sessions.begin(); i!=sessions.end(); i++) { + if ((*i)->getSock() == sock) { + delete *i; + sessions.erase(i); + return; + } + } +} + +void HTTPServer::processSocketEvent(network::Socket* sock) { std::list<Session*>::iterator i; for (i=sessions.begin(); i!=sessions.end(); i++) { @@ -320,21 +348,16 @@ HTTPServer::processSocketEvent(network::Socket* sock) { try { if ((*i)->processHTTP()) { vlog.info("completed HTTP request"); - delete *i; - sessions.erase(i); - break; + sock->shutdown(); } - return true; } catch (rdr::Exception& e) { vlog.error("untrapped: %s", e.str()); - delete *i; - sessions.erase(i); - break; + sock->shutdown(); } + return; } } - delete sock; - return false; + throw rdr::Exception("invalid Socket in HTTPServer"); } void HTTPServer::getSockets(std::list<network::Socket*>* sockets) @@ -359,7 +382,9 @@ int HTTPServer::checkTimeouts() { // -=- Default getFile implementation InStream* -HTTPServer::getFile(const char* name, const char** contentType) { +HTTPServer::getFile(const char* name, const char** contentType, + int* contentLength, time_t* lastModified) +{ return 0; } diff --git a/rfb/HTTPServer.h b/rfb/HTTPServer.h index 9431195c..6412946a 100644 --- a/rfb/HTTPServer.h +++ b/rfb/HTTPServer.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -32,6 +32,7 @@ #include <rfb/UpdateTracker.h> #include <rfb/Configuration.h> #include <network/Socket.h> +#include <time.h> namespace rfb { @@ -46,32 +47,27 @@ namespace rfb { virtual ~HTTPServer(); - // -=- Client management + // SocketServer interface - // - Run a client connection on the supplied socket + // addSocket() // This causes the server to perform HTTP protocol on the // supplied socket. - // The socket will be closed if protocol initialisation - // fails. - virtual void addClient(network::Socket* sock); + virtual void addSocket(network::Socket* sock, bool outgoing=false); - // -=- Event processing methods + // removeSocket() + // Could clean up socket-specific resources here. + virtual void removeSocket(network::Socket* sock); - // - Process an input event on a particular Socket + // processSocketEvent() // The platform-specific side of the server implementation calls // this method whenever data arrives on one of the active // network sockets. - // The method returns true if the Socket is still in use by the - // server, or false if it is no longer required and should be - // deleted. - // NB: If false is returned then the Socket is deleted and must - // not be accessed again! - - virtual bool processSocketEvent(network::Socket* sock); + virtual void processSocketEvent(network::Socket* sock); - // - Check for socket timeouts + // Check for socket timeouts virtual int checkTimeouts(); + // getSockets() gets a list of sockets. This can be used to generate an // fd_set for calling select(). @@ -92,13 +88,15 @@ namespace rfb { // NB: The contentType is statically allocated by the getFile impl. // NB: contentType is *guaranteed* to be valid when getFile is called. - virtual rdr::InStream* getFile(const char* name, const char** contentType); + virtual rdr::InStream* getFile(const char* name, const char** contentType, + int* contentLength, time_t* lastModified); // - guessContentType is passed the name of a file and returns the // name of an HTTP content type, based on the file's extension. If // the extension isn't recognised then defType is returned. This can // be used from getFile to easily default to the supplied contentType, - // or by passing zero in to determine whether a type is recognised or not. + // or by passing zero in to determine whether a type is recognised or + // not. static const char* guessContentType(const char* name, const char* defType); diff --git a/rfb/HextileDecoder.cxx b/rfb/HextileDecoder.cxx index 97c7ca74..e817c732 100644 --- a/rfb/HextileDecoder.cxx +++ b/rfb/HextileDecoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/HextileDecoder.h b/rfb/HextileDecoder.h index 718bd38b..e7dd3d58 100644 --- a/rfb/HextileDecoder.h +++ b/rfb/HextileDecoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/HextileEncoder.cxx b/rfb/HextileEncoder.cxx index a96cf793..ba71d56d 100644 --- a/rfb/HextileEncoder.cxx +++ b/rfb/HextileEncoder.cxx @@ -1,6 +1,6 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2005 Constantin Kaplinsky. 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 diff --git a/rfb/HextileEncoder.h b/rfb/HextileEncoder.h index f09ead8e..c78107a4 100644 --- a/rfb/HextileEncoder.h +++ b/rfb/HextileEncoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Hostname.h b/rfb/Hostname.h index bdff474e..ebdf816f 100644 --- a/rfb/Hostname.h +++ b/rfb/Hostname.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -19,11 +19,13 @@ #ifndef __RFB_HOSTNAME_H__ #define __RFB_HOSTNAME_H__ +#include <stdlib.h> +#include <rdr/Exception.h> #include <rfb/util.h> namespace rfb { - void getHostAndPort(const char* hi, char** host, int* port, int basePort=5900) { + static void getHostAndPort(const char* hi, char** host, int* port, int basePort=5900) { CharArray portBuf; CharArray hostBuf; if (hi[0] == '[') { diff --git a/rfb/ImageGetter.h b/rfb/ImageGetter.h index b550a12f..290249f6 100644 --- a/rfb/ImageGetter.h +++ b/rfb/ImageGetter.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/InputHandler.h b/rfb/InputHandler.h new file mode 100644 index 00000000..b5e5e879 --- /dev/null +++ b/rfb/InputHandler.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. 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. + */ +// +// InputHandler - abstract interface for accepting keyboard & +// pointer input and clipboard data. +// + +#ifndef __RFB_INPUTHANDLER_H__ +#define __RFB_INPUTHANDLER_H__ + +#include <rdr/types.h> +#include <rfb/Rect.h> + +namespace rfb { + + class InputHandler { + public: + virtual ~InputHandler() {} + virtual void keyEvent(rdr::U32 key, bool down) {} + virtual void pointerEvent(const Point& pos, int buttonMask) {} + virtual void clientCutText(const char* str, int len) {} + }; + +} +#endif diff --git a/rfb/KeyRemapper.cxx b/rfb/KeyRemapper.cxx new file mode 100644 index 00000000..05f07632 --- /dev/null +++ b/rfb/KeyRemapper.cxx @@ -0,0 +1,84 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. 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. + */ + +#include <stdio.h> +#include <rfb/KeyRemapper.h> +#include <rfb/Configuration.h> +#include <rfb/LogWriter.h> + +using namespace rfb; + +static LogWriter vlog("KeyRemapper"); + +KeyRemapper KeyRemapper::defInstance; + +#ifdef __RFB_THREADING_IMPL +static Mutex mappingLock; +#endif + +void KeyRemapper::setMapping(const char* m) { +#ifdef __RFB_THREADING_IMPL + Lock l(mappingLock); +#endif + mapping.clear(); + while (m[0]) { + int from, to; + char bidi; + const char* nextComma = strchr(m, ','); + if (!nextComma) + nextComma = m + strlen(m); + if (sscanf(m, "0x%x%c>0x%x", &from, + &bidi, &to) == 3) { + if (bidi != '-' && bidi != '<') + vlog.error("warning: unknown operation %c>, assuming ->", bidi); + mapping[from] = to; + if (bidi == '<') + mapping[to] = from; + } else { + vlog.error("warning: bad mapping %.*s", nextComma-m, m); + } + m = nextComma; + if (nextComma[0]) + m++; + } +} + +rdr::U32 KeyRemapper::remapKey(rdr::U32 key) const { +#ifdef __RFB_THREADING_IMPL + Lock l(mappingLock); +#endif + std::map<rdr::U32,rdr::U32>::const_iterator i = mapping.find(key); + if (i != mapping.end()) + return i->second; + return key; +} + + +class KeyMapParameter : public StringParameter { +public: + KeyMapParameter() + : StringParameter("RemapKeys", "Comma-separated list of incoming keysyms to remap. Mappings are expressed as two hex values, prefixed by 0x, and separated by ->", "") { + setParam(value); + } + bool setParam(const char* v) { + KeyRemapper::defInstance.setMapping(v); + return StringParameter::setParam(v); + } +} defaultParam; + + diff --git a/rfb/vncAuth.h b/rfb/KeyRemapper.h index 18d87ade..a4b7aa01 100644 --- a/rfb/vncAuth.h +++ b/rfb/KeyRemapper.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -15,17 +15,25 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ -#ifndef __RFB_VNCAUTH_H__ -#define __RFB_VNCAUTH_H__ +#ifndef __RFB_KEYREMAPPER_H__ +#define __RFB_KEYREMAPPER_H__ + +#include <map> #include <rdr/types.h> namespace rfb { - const int vncAuthChallengeSize = 16; + class KeyRemapper { + public: + KeyRemapper(const char* m="") { setMapping(m); } + void setMapping(const char* m); + rdr::U32 remapKey(rdr::U32 key) const; + static KeyRemapper defInstance; + private: + std::map<rdr::U32,rdr::U32> mapping; + }; + +}; - void vncAuthEncryptChallenge(rdr::U8* challenge, const char* passwd); - void vncAuthObfuscatePasswd(char* passwd); - void vncAuthUnobfuscatePasswd(char* passwd); -} -#endif +#endif // __RFB_KEYREMAPPER_H__ diff --git a/rfb/LogWriter.cxx b/rfb/LogWriter.cxx index 6f267f12..c6461d14 100644 --- a/rfb/LogWriter.cxx +++ b/rfb/LogWriter.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -53,13 +53,13 @@ void LogWriter::listLogWriters(int width) { // *** make this respect width... LogWriter* current = log_writers; - printf(" "); + fprintf(stderr, " "); while (current) { - printf("%s", current->m_name); + fprintf(stderr, "%s", current->m_name); current = current->m_next; - if (current) printf(", "); + if (current) fprintf(stderr, ", "); } - printf("\n"); + fprintf(stderr, "\n"); } LogWriter* LogWriter::log_writers; diff --git a/rfb/LogWriter.h b/rfb/LogWriter.h index 58e81f28..124c58ec 100644 --- a/rfb/LogWriter.h +++ b/rfb/LogWriter.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Logger.cxx b/rfb/Logger.cxx index 84b8f559..8b3c6eef 100644 --- a/rfb/Logger.cxx +++ b/rfb/Logger.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Logger.h b/rfb/Logger.h index 4233964b..e53764b7 100644 --- a/rfb/Logger.h +++ b/rfb/Logger.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Logger_file.cxx b/rfb/Logger_file.cxx index ac249b39..8a109e4a 100644 --- a/rfb/Logger_file.cxx +++ b/rfb/Logger_file.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -53,6 +53,10 @@ void Logger_File::write(int level, const char *logname, const char *message) #endif if (!m_file) { if (!m_filename) return; + CharArray bakFilename(strlen(m_filename) + 1 + 4); + sprintf(bakFilename.buf, "%s.bak", m_filename); + remove(bakFilename.buf); + rename(m_filename, bakFilename.buf); m_file = fopen(m_filename, "w+"); if (!m_file) return; } diff --git a/rfb/Logger_file.h b/rfb/Logger_file.h index 30c3f402..5e0c917b 100644 --- a/rfb/Logger_file.h +++ b/rfb/Logger_file.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Logger_stdio.cxx b/rfb/Logger_stdio.cxx index ac9556e1..581dcd5b 100644 --- a/rfb/Logger_stdio.cxx +++ b/rfb/Logger_stdio.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Logger_stdio.h b/rfb/Logger_stdio.h index 68f795fc..a1d17a0f 100644 --- a/rfb/Logger_stdio.h +++ b/rfb/Logger_stdio.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Makefile.in b/rfb/Makefile.in index f2976c07..3f501a90 100644 --- a/rfb/Makefile.in +++ b/rfb/Makefile.in @@ -21,10 +21,12 @@ CXXSRCS = \ HTTPServer.cxx \ HextileDecoder.cxx \ HextileEncoder.cxx \ + KeyRemapper.cxx \ LogWriter.cxx \ Logger.cxx \ Logger_file.cxx \ Logger_stdio.cxx \ + Password.cxx \ PixelBuffer.cxx \ PixelFormat.cxx \ RREEncoder.cxx \ @@ -41,6 +43,7 @@ CXXSRCS = \ ServerCore.cxx \ SSecurityFactoryStandard.cxx \ SSecurityVncAuth.cxx \ + Timer.cxx \ TightDecoder.cxx \ TightEncoder.cxx \ TightPalette.cxx \ @@ -53,8 +56,7 @@ CXXSRCS = \ ZRLEDecoder.cxx \ encodings.cxx \ secTypes.cxx \ - util.cxx \ - vncAuth.cxx + util.cxx SRCS = d3des.c $(CXXSRCS) diff --git a/rfb/Password.cxx b/rfb/Password.cxx new file mode 100644 index 00000000..9127862d --- /dev/null +++ b/rfb/Password.cxx @@ -0,0 +1,77 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. 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. + */ + +// +// XXX not thread-safe, because d3des isn't - do we need to worry about this? +// + +#include <string.h> +extern "C" { +#include <rfb/d3des.h> +} +#include <rdr/types.h> +#include <rdr/Exception.h> +#include <rfb/Password.h> + +using namespace rfb; + +static unsigned char d3desObfuscationKey[] = {23,82,107,6,35,78,88,7}; + + +PlainPasswd::PlainPasswd() {} + +PlainPasswd::PlainPasswd(char* pwd) : CharArray(pwd) { +} + +PlainPasswd::PlainPasswd(const ObfuscatedPasswd& obfPwd) : CharArray(9) { + if (obfPwd.length < 8) + throw rdr::Exception("bad obfuscated password length"); + deskey(d3desObfuscationKey, DE1); + des((rdr::U8*)obfPwd.buf, (rdr::U8*)buf); + buf[8] = 0; +} + +PlainPasswd::~PlainPasswd() { + replaceBuf(0); +} + +void PlainPasswd::replaceBuf(char* b) { + if (buf) + memset(buf, 0, strlen(buf)); + CharArray::replaceBuf(b); +} + + +ObfuscatedPasswd::ObfuscatedPasswd() : length(0) { +} + +ObfuscatedPasswd::ObfuscatedPasswd(int len) : CharArray(len), length(len) { +} + +ObfuscatedPasswd::ObfuscatedPasswd(const PlainPasswd& plainPwd) : CharArray(8), length(8) { + int l = strlen(plainPwd.buf), i; + for (i=0; i<8; i++) + buf[i] = i<l ? plainPwd.buf[i] : 0; + deskey(d3desObfuscationKey, EN0); + des((rdr::U8*)buf, (rdr::U8*)buf); +} + +ObfuscatedPasswd::~ObfuscatedPasswd() { + if (buf) + memset(buf, 0, length); +} diff --git a/rfb/Password.h b/rfb/Password.h new file mode 100644 index 00000000..ab26903a --- /dev/null +++ b/rfb/Password.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. 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. + */ +#ifndef __RFB_PASSWORD_H__ +#define __RFB_PASSWORD_H__ + +#include <rfb/util.h> + +namespace rfb { + + class ObfuscatedPasswd; + + class PlainPasswd : public CharArray { + public: + PlainPasswd(); + PlainPasswd(char* pwd); + PlainPasswd(const ObfuscatedPasswd& obfPwd); + ~PlainPasswd(); + void replaceBuf(char* b); + }; + + class ObfuscatedPasswd : public CharArray { + public: + ObfuscatedPasswd(); + ObfuscatedPasswd(int l); + ObfuscatedPasswd(const PlainPasswd& plainPwd); + ~ObfuscatedPasswd(); + int length; + }; + +} +#endif diff --git a/rfb/Pixel.h b/rfb/Pixel.h index 2b1aaf0d..4e9d1644 100644 --- a/rfb/Pixel.h +++ b/rfb/Pixel.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/PixelBuffer.cxx b/rfb/PixelBuffer.cxx index fcad227e..d093426f 100644 --- a/rfb/PixelBuffer.cxx +++ b/rfb/PixelBuffer.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/PixelBuffer.h b/rfb/PixelBuffer.h index 2ba105a7..4a13923c 100644 --- a/rfb/PixelBuffer.h +++ b/rfb/PixelBuffer.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/PixelFormat.cxx b/rfb/PixelFormat.cxx index 8809fb5d..74b68372 100644 --- a/rfb/PixelFormat.cxx +++ b/rfb/PixelFormat.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/PixelFormat.h b/rfb/PixelFormat.h index 0f2edd26..111c38cb 100644 --- a/rfb/PixelFormat.h +++ b/rfb/PixelFormat.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RREDecoder.cxx b/rfb/RREDecoder.cxx index c613dbb8..da56ee7c 100644 --- a/rfb/RREDecoder.cxx +++ b/rfb/RREDecoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RREDecoder.h b/rfb/RREDecoder.h index 75a5e859..2309f754 100644 --- a/rfb/RREDecoder.h +++ b/rfb/RREDecoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RREEncoder.cxx b/rfb/RREEncoder.cxx index 612a869a..b000e9d3 100644 --- a/rfb/RREEncoder.cxx +++ b/rfb/RREEncoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RREEncoder.h b/rfb/RREEncoder.h index 40b203e3..1281410d 100644 --- a/rfb/RREEncoder.h +++ b/rfb/RREEncoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RawDecoder.cxx b/rfb/RawDecoder.cxx index 5a5d62b7..57cb37bc 100644 --- a/rfb/RawDecoder.cxx +++ b/rfb/RawDecoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RawDecoder.h b/rfb/RawDecoder.h index b3dd9b7c..9fdbb220 100644 --- a/rfb/RawDecoder.h +++ b/rfb/RawDecoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RawEncoder.cxx b/rfb/RawEncoder.cxx index d758ec6d..a2545b61 100644 --- a/rfb/RawEncoder.cxx +++ b/rfb/RawEncoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/RawEncoder.h b/rfb/RawEncoder.h index c8b6a62d..1b9ad929 100644 --- a/rfb/RawEncoder.h +++ b/rfb/RawEncoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -21,11 +21,16 @@ #ifndef __RFB_RECT_INCLUDED__ #define __RFB_RECT_INCLUDED__ -#ifndef vncmin -#define vncmin(a,b) (((a) < (b)) ? (a) : (b)) +// Some platforms (e.g. Windows) include max() and min() macros in their +// standard headers, but they are also standard C++ template functions, so some +// C++ headers will undefine them. So we steer clear of the names min and max +// and define __rfbmin and __rfbmax instead. + +#ifndef __rfbmax +#define __rfbmax(a,b) (((a) > (b)) ? (a) : (b)) #endif -#ifndef vncmax -#define vncmax(a,b) (((a) > (b)) ? (a) : (b)) +#ifndef __rfbmin +#define __rfbmin(a,b) (((a) < (b)) ? (a) : (b)) #endif namespace rfb { @@ -69,20 +74,20 @@ namespace rfb { } inline Rect intersect(const Rect &r) const { Rect result; - result.tl.x = vncmax(tl.x, r.tl.x); - result.tl.y = vncmax(tl.y, r.tl.y); - result.br.x = vncmax(vncmin(br.x, r.br.x), result.tl.x); - result.br.y = vncmax(vncmin(br.y, r.br.y), result.tl.y); + result.tl.x = __rfbmax(tl.x, r.tl.x); + result.tl.y = __rfbmax(tl.y, r.tl.y); + result.br.x = __rfbmax(__rfbmin(br.x, r.br.x), result.tl.x); + result.br.y = __rfbmax(__rfbmin(br.y, r.br.y), result.tl.y); return result; } inline Rect union_boundary(const Rect &r) const { if (r.is_empty()) return *this; if (is_empty()) return r; Rect result; - result.tl.x = vncmin(tl.x, r.tl.x); - result.tl.y = vncmin(tl.y, r.tl.y); - result.br.x = vncmax(br.x, r.br.x); - result.br.y = vncmax(br.y, r.br.y); + result.tl.x = __rfbmin(tl.x, r.tl.x); + result.tl.y = __rfbmin(tl.y, r.tl.y); + result.br.x = __rfbmax(br.x, r.br.x); + result.br.y = __rfbmax(br.y, r.br.y); return result; } inline Rect translate(const Point &p) const { diff --git a/rfb/Region.cxx b/rfb/Region.cxx index bbcc892c..7965a6c4 100644 --- a/rfb/Region.cxx +++ b/rfb/Region.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/Region.h b/rfb/Region.h index 8fb9889e..93375569 100644 --- a/rfb/Region.h +++ b/rfb/Region.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/SConnection.cxx b/rfb/SConnection.cxx index e969ed8c..f8a3f36a 100644 --- a/rfb/SConnection.cxx +++ b/rfb/SConnection.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -21,7 +21,6 @@ #include <rfb/secTypes.h> #include <rfb/SMsgReaderV3.h> #include <rfb/SMsgWriterV3.h> -#include <rfb/SSecurity.h> #include <rfb/SConnection.h> #include <rfb/ServerCore.h> @@ -41,10 +40,11 @@ const SConnection::AccessRights SConnection::AccessNoQuery = 0x0400; const SConnection::AccessRights SConnection::AccessFull = 0xffff; -SConnection::SConnection() +SConnection::SConnection(SSecurityFactory* secFact, bool reverseConnection_) : readyForSetColourMapEntries(false), is(0), os(0), reader_(0), writer_(0), - nSecTypes(0), security(0), state_(RFBSTATE_UNINITIALISED) + security(0), securityFactory(secFact), state_(RFBSTATE_UNINITIALISED), + reverseConnection(reverseConnection_) { defaultMajorVersion = 3; defaultMinorVersion = 8; @@ -74,15 +74,6 @@ void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_) os = os_; } -void SConnection::addSecType(rdr::U8 secType) -{ - if (nSecTypes == maxSecTypes) - throw Exception("too many security types"); - secTypes[nSecTypes++] = secType; - vlog.debug("Offering security type %s(%d)", - secTypeName(secType),secType); -} - void SConnection::initialiseProtocol() { cp.writeVersion(os); @@ -144,37 +135,40 @@ void SConnection::processVersionMsg() versionReceived(); + std::list<rdr::U8> secTypes; + std::list<rdr::U8>::iterator i; + securityFactory->getSecTypes(&secTypes, reverseConnection); + if (cp.isVersion(3,3)) { // cope with legacy 3.3 client only if "no authentication" or "vnc // authentication" is supported. - - int i; - for (i = 0; i < nSecTypes; i++) { - if (secTypes[i] == secTypeNone || secTypes[i] == secTypeVncAuth) break; + for (i=secTypes.begin(); i!=secTypes.end(); i++) { + if (*i == secTypeNone || *i == secTypeVncAuth) break; } - if (i == nSecTypes) { + if (i == secTypes.end()) { char msg[256]; sprintf(msg,"No supported security type for %d.%d client", cp.majorVersion, cp.minorVersion); throwConnFailedException(msg); } - os->writeU32(secTypes[i]); - if (secTypes[i] == secTypeNone) os->flush(); + os->writeU32(*i); + if (*i == secTypeNone) os->flush(); state_ = RFBSTATE_SECURITY; - security = getSSecurity(secTypes[i]); + security = securityFactory->getSSecurity(*i, reverseConnection); processSecurityMsg(); return; } // list supported security types for >=3.7 clients - if (nSecTypes == 0) + if (secTypes.empty()) throwConnFailedException("No supported security types"); - os->writeU8(nSecTypes); - os->writeBytes(secTypes, nSecTypes); + os->writeU8(secTypes.size()); + for (i=secTypes.begin(); i!=secTypes.end(); i++) + os->writeU8(*i); os->flush(); state_ = RFBSTATE_SECURITY_TYPE; } @@ -186,40 +180,33 @@ void SConnection::processSecurityTypeMsg() int secType = is->readU8(); vlog.info("Client requests security type %s(%d)", secTypeName(secType),secType); - int i; - for (i = 0; i < nSecTypes; i++) { - if (secType == secTypes[i]) break; - } - if (i == nSecTypes) { - char msg[256]; - sprintf(msg,"Security type %s(%d) from client not supported", - secTypeName(secType),secType); - throwConnFailedException(msg); + + try { + state_ = RFBSTATE_SECURITY; + security = securityFactory->getSSecurity(secType, reverseConnection); + } catch (rdr::Exception& e) { + throwConnFailedException(e.str()); } - state_ = RFBSTATE_SECURITY; - security = getSSecurity(secType); + processSecurityMsg(); } void SConnection::processSecurityMsg() { vlog.debug("processing security message"); - bool done; - bool ok = security->processMsg(this, &done); - if (done) { - state_ = RFBSTATE_QUERYING; - if (ok) { + try { + bool done = security->processMsg(this); + if (done) { + state_ = RFBSTATE_QUERYING; queryConnection(security->getUserName()); - } else { - const char* failureMsg = security->failureMessage(); - if (!failureMsg) failureMsg = "Authentication failure"; - approveConnection(false, failureMsg); } - } - if (!ok) { - state_ = RFBSTATE_INVALID; - authFailure(); - throw AuthFailureException(); + } catch (AuthFailureException& e) { + vlog.error("AuthFailureException: %s", e.str()); + os->writeU32(secResultFailed); + if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message + os->writeString(e.str()); + os->flush(); + throw; } } @@ -264,10 +251,6 @@ void SConnection::authSuccess() { } -void SConnection::authFailure() -{ -} - void SConnection::queryConnection(const char* userName) { approveConnection(true); @@ -298,7 +281,6 @@ void SConnection::approveConnection(bool accept, const char* reason) authSuccess(); } else { state_ = RFBSTATE_INVALID; - authFailure(); throw AuthFailureException(reason); } } diff --git a/rfb/SConnection.h b/rfb/SConnection.h index 19453c62..6b943f5e 100644 --- a/rfb/SConnection.h +++ b/rfb/SConnection.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -26,6 +26,7 @@ #include <rdr/InStream.h> #include <rdr/OutStream.h> #include <rfb/SMsgHandler.h> +#include <rfb/SSecurity.h> namespace rfb { @@ -36,7 +37,7 @@ namespace rfb { class SConnection : public SMsgHandler { public: - SConnection(); + SConnection(SSecurityFactory* sf, bool reverseConnection_); virtual ~SConnection(); // Methods to initialise the connection @@ -49,10 +50,6 @@ namespace rfb { // (i.e. SConnection will not delete them). void setStreams(rdr::InStream* is, rdr::OutStream* os); - // addSecType() should be called once for each security type which the - // server supports to this client. - void addSecType(rdr::U8 secType); - // initialiseProtocol() should be called once the streams and security // types are set. Subsequently, processMsg() should be called whenever // there is data to read on the InStream. @@ -78,19 +75,9 @@ namespace rfb { // to deal with unknown/bogus viewer protocol numbers. virtual void versionReceived(); - // getSSecurity() gets the SSecurity object for the given type. The type - // is guaranteed to be one of the secTypes passed in to addSecType(). The - // SSecurity object's destroy() method will be called by the SConnection - // from its destructor. - virtual SSecurity* getSSecurity(int secType)=0; - // authSuccess() is called when authentication has succeeded. virtual void authSuccess(); - // authFailure() is called when authentication has failed. This method is - // not normally overridden since an exception is thrown anyway. - virtual void authFailure(); - // queryConnection() is called when authentication has succeeded, but // before informing the client. It can be overridden to query a local user // to accept the incoming connection, for example. The userName argument @@ -178,7 +165,8 @@ namespace rfb { stateEnum state() { return state_; } - // ssecurity() returns a pointer to this connection's SSecurity object, if any + // ssecurity() returns a pointer to this connection's SSecurity object, if + // any const SSecurity* ssecurity() const { return security; } protected: @@ -186,7 +174,6 @@ namespace rfb { bool readyForSetColourMapEntries; - private: void processVersionMsg(); void processSecurityTypeMsg(); void processSecurityMsg(); @@ -197,11 +184,10 @@ namespace rfb { rdr::OutStream* os; SMsgReader* reader_; SMsgWriter* writer_; - enum { maxSecTypes = 8 }; - int nSecTypes; - rdr::U8 secTypes[maxSecTypes]; SSecurity* security; + SSecurityFactory* securityFactory; stateEnum state_; + bool reverseConnection; }; } #endif diff --git a/rfb/SDesktop.h b/rfb/SDesktop.h index eb17a529..7b054e37 100644 --- a/rfb/SDesktop.h +++ b/rfb/SDesktop.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -39,13 +39,14 @@ #include <rfb/PixelBuffer.h> #include <rfb/VNCServer.h> +#include <rfb/InputHandler.h> #include <rfb/Exception.h> namespace rfb { class VNCServer; - class SDesktop { + class SDesktop : public InputHandler { public: // start() is called by the server when the first client authenticates // successfully, and can be used to begin any expensive tasks which are not @@ -62,13 +63,6 @@ namespace rfb { virtual void stop() {} - // pointerEvent(), keyEvent() and clientCutText() are called in response to - // the relevant RFB protocol messages from clients. - - virtual void pointerEvent(const Point& pos, rdr::U8 buttonmask) {} - virtual void keyEvent(rdr::U32 key, bool down) {} - virtual void clientCutText(const char* str, int len) {} - // framebufferUpdateRequest() is called to let the desktop know that at // least one client has become ready for an update. Desktops can check // whether there are clients ready at any time by calling the VNCServer's @@ -81,6 +75,10 @@ namespace rfb { virtual Point getFbSize() = 0; + // InputHandler interface + // pointerEvent(), keyEvent() and clientCutText() are called in response to + // the relevant RFB protocol messages from clients. + // See InputHandler for method signatures. protected: virtual ~SDesktop() {} }; diff --git a/rfb/SMsgHandler.cxx b/rfb/SMsgHandler.cxx index d6a139c7..ccc97ad0 100644 --- a/rfb/SMsgHandler.cxx +++ b/rfb/SMsgHandler.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -47,18 +47,6 @@ void SMsgHandler::framebufferUpdateRequest(const Rect& r, bool incremental) { } -void SMsgHandler::keyEvent(rdr::U32 key, bool down) -{ -} - -void SMsgHandler::pointerEvent(int x, int y, int buttonMask) -{ -} - -void SMsgHandler::clientCutText(const char* str, int len) -{ -} - void SMsgHandler::supportsLocalCursor() { } diff --git a/rfb/SMsgHandler.h b/rfb/SMsgHandler.h index 148403f8..cf3377d5 100644 --- a/rfb/SMsgHandler.h +++ b/rfb/SMsgHandler.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -25,13 +25,13 @@ #include <rdr/types.h> #include <rfb/PixelFormat.h> #include <rfb/ConnParams.h> -#include <rfb/Rect.h> +#include <rfb/InputHandler.h> namespace rdr { class InStream; } namespace rfb { - class SMsgHandler { + class SMsgHandler : public InputHandler { public: SMsgHandler(); virtual ~SMsgHandler(); @@ -46,9 +46,9 @@ namespace rfb { virtual void setPixelFormat(const PixelFormat& pf); virtual void setEncodings(int nEncodings, rdr::U32* encodings); virtual void framebufferUpdateRequest(const Rect& r, bool incremental); - virtual void keyEvent(rdr::U32 key, bool down); - virtual void pointerEvent(int x, int y, int buttonMask); - virtual void clientCutText(const char* str, int len); + + // InputHandler interface + // The InputHandler methods will be called for the corresponding messages. // supportsLocalCursor() is called whenever the status of // cp.supportsLocalCursor has changed. At the moment this happens on a diff --git a/rfb/SMsgReader.cxx b/rfb/SMsgReader.cxx index 2939aa10..f89e0f4f 100644 --- a/rfb/SMsgReader.cxx +++ b/rfb/SMsgReader.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -21,9 +21,12 @@ #include <rfb/util.h> #include <rfb/SMsgHandler.h> #include <rfb/SMsgReader.h> +#include <rfb/Configuration.h> using namespace rfb; +static IntParameter maxCutText("MaxCutText", "Maximum permitted length of an incoming clipboard update", 256*1024); + SMsgReader::SMsgReader(SMsgHandler* handler_, rdr::InStream* is_) : handler(handler_), is(is_) { @@ -33,16 +36,11 @@ SMsgReader::~SMsgReader() { } -void SMsgReader::endMsg() -{ -} - void SMsgReader::readSetPixelFormat() { is->skip(3); PixelFormat pf; pf.read(is); - endMsg(); handler->setPixelFormat(pf); } @@ -50,12 +48,10 @@ void SMsgReader::readSetEncodings() { is->skip(1); int nEncodings = is->readU16(); - rdr::U32* encodings = new rdr::U32[nEncodings]; + rdr::U32Array encodings(nEncodings); for (int i = 0; i < nEncodings; i++) - encodings[i] = is->readU32(); - endMsg(); - handler->setEncodings(nEncodings, encodings); - delete [] encodings; + encodings.buf[i] = is->readU32(); + handler->setEncodings(nEncodings, encodings.buf); } void SMsgReader::readFramebufferUpdateRequest() @@ -65,7 +61,6 @@ void SMsgReader::readFramebufferUpdateRequest() int y = is->readU16(); int w = is->readU16(); int h = is->readU16(); - endMsg(); handler->framebufferUpdateRequest(Rect(x, y, x+w, y+h), inc); } @@ -74,7 +69,6 @@ void SMsgReader::readKeyEvent() bool down = is->readU8(); is->skip(2); rdr::U32 key = is->readU32(); - endMsg(); handler->keyEvent(key, down); } @@ -83,8 +77,7 @@ void SMsgReader::readPointerEvent() int mask = is->readU8(); int x = is->readU16(); int y = is->readU16(); - endMsg(); - handler->pointerEvent(x, y, mask); + handler->pointerEvent(Point(x, y), mask); } @@ -92,7 +85,7 @@ void SMsgReader::readClientCutText() { is->skip(3); int len = is->readU32(); - if (len > 256*1024) { + if (len > maxCutText) { is->skip(len); fprintf(stderr,"cut text too long (%d bytes) - ignoring\n",len); return; @@ -100,6 +93,5 @@ void SMsgReader::readClientCutText() CharArray ca(len+1); ca.buf[len] = 0; is->readBytes(ca.buf, len); - endMsg(); handler->clientCutText(ca.buf, len); } diff --git a/rfb/SMsgReader.h b/rfb/SMsgReader.h index 4d269380..e6e40448 100644 --- a/rfb/SMsgReader.h +++ b/rfb/SMsgReader.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -46,7 +46,6 @@ namespace rfb { virtual void readKeyEvent(); virtual void readPointerEvent(); virtual void readClientCutText(); - virtual void endMsg(); SMsgReader(SMsgHandler* handler, rdr::InStream* is); diff --git a/rfb/SMsgReaderV3.cxx b/rfb/SMsgReaderV3.cxx index 0ce1bcab..be01b5db 100644 --- a/rfb/SMsgReaderV3.cxx +++ b/rfb/SMsgReaderV3.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -36,7 +36,6 @@ SMsgReaderV3::~SMsgReaderV3() void SMsgReaderV3::readClientInit() { bool shared = is->readU8(); - endMsg(); handler->clientInit(shared); } diff --git a/rfb/SMsgReaderV3.h b/rfb/SMsgReaderV3.h index 28cc7a63..c6b7bf42 100644 --- a/rfb/SMsgReaderV3.h +++ b/rfb/SMsgReaderV3.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/SMsgWriter.cxx b/rfb/SMsgWriter.cxx index 067fb117..085dfc16 100644 --- a/rfb/SMsgWriter.cxx +++ b/rfb/SMsgWriter.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -176,11 +176,6 @@ void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY) endRect(); } -void SMsgWriter::setOutStream(rdr::OutStream* os_) -{ - os = os_; -} - rdr::U8* SMsgWriter::getImageBuf(int required, int requested, int* nPixels) { int requiredBytes = required * (cp->pf().bpp / 8); diff --git a/rfb/SMsgWriter.h b/rfb/SMsgWriter.h index 6dc272cf..ed8ad0ef 100644 --- a/rfb/SMsgWriter.h +++ b/rfb/SMsgWriter.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -80,8 +80,8 @@ namespace rfb { // in response to the writeSetCursorCallback() callback. For a V3 writer // this will happen when the next update is sent. virtual void cursorChange(WriteSetCursorCallback* cb)=0; - virtual void writeSetCursor(int width, int height, int hotspotX, - int hotspotY, void* data, void* mask)=0; + virtual void writeSetCursor(int width, int height, const Point& hotspot, + void* data, void* mask)=0; virtual void writeSetXCursor(int width, int height, int hotspotX, int hotspotY, void* data, void* mask)=0; @@ -127,9 +127,6 @@ namespace rfb { virtual void startRect(const Rect& r, unsigned int enc)=0; virtual void endRect()=0; - // setOutStream() changes the OutStream on the fly. - virtual void setOutStream(rdr::OutStream* os); - ConnParams* getConnParams() { return cp; } rdr::OutStream* getOutStream() { return os; } rdr::U8* getImageBuf(int required, int requested=0, int* nPixels=0); diff --git a/rfb/SMsgWriterV3.cxx b/rfb/SMsgWriterV3.cxx index e91e514f..a85f85ea 100644 --- a/rfb/SMsgWriterV3.cxx +++ b/rfb/SMsgWriterV3.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -69,14 +69,14 @@ void SMsgWriterV3::cursorChange(WriteSetCursorCallback* cb) wsccb = cb; } -void SMsgWriterV3::writeSetCursor(int width, int height, int hotspotX, - int hotspotY, void* data, void* mask) +void SMsgWriterV3::writeSetCursor(int width, int height, const Point& hotspot, + void* data, void* mask) { if (!wsccb) return; if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) throw Exception("SMsgWriterV3::writeSetCursor: nRects out of sync"); - os->writeS16(hotspotX); - os->writeS16(hotspotY); + os->writeS16(hotspot.x); + os->writeS16(hotspot.y); os->writeU16(width); os->writeU16(height); os->writeU32(pseudoEncodingCursor); @@ -138,6 +138,8 @@ void SMsgWriterV3::writeFramebufferUpdateStart() void SMsgWriterV3::writeFramebufferUpdateEnd() { if (needSetDesktopSize) { + if (!cp->supportsDesktopResize) + throw Exception("Client does not support desktop resize"); if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) throw Exception("SMsgWriterV3 setDesktopSize: nRects out of sync"); os->writeS16(0); @@ -193,9 +195,3 @@ void SMsgWriterV3::endRect() rectsSent[currentEncoding]++; } } - -void SMsgWriterV3::setOutStream(rdr::OutStream* os_) -{ - SMsgWriter::setOutStream(os_); - realOS = os; -} diff --git a/rfb/SMsgWriterV3.h b/rfb/SMsgWriterV3.h index fbd07d68..501fa489 100644 --- a/rfb/SMsgWriterV3.h +++ b/rfb/SMsgWriterV3.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -33,8 +33,8 @@ namespace rfb { virtual void endMsg(); virtual bool writeSetDesktopSize(); virtual void cursorChange(WriteSetCursorCallback* cb); - virtual void writeSetCursor(int width, int height, int hotspotX, - int hotspotY, void* data, void* mask); + virtual void writeSetCursor(int width, int height, const Point& hotspot, + void* data, void* mask); virtual void writeSetXCursor(int width, int height, int hotspotX, int hotspotY, void* data, void* mask); virtual void writeFramebufferUpdateStart(int nRects); @@ -44,8 +44,6 @@ namespace rfb { virtual void startRect(const Rect& r, unsigned int encoding); virtual void endRect(); - virtual void setOutStream(rdr::OutStream* os); - private: rdr::MemOutStream* updateOS; rdr::OutStream* realOS; diff --git a/rfb/SSecurity.h b/rfb/SSecurity.h index 2ca53449..108985b3 100644 --- a/rfb/SSecurity.h +++ b/rfb/SSecurity.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -18,10 +18,16 @@ // // SSecurity - class on the server side for handling security handshaking. A // derived class for a particular security type overrides the processMsg() -// method. processMsg() is called first when the security type has been -// decided on, and will keep being called whenever there is data to read from -// the client until either it returns false, indicating authentication/security -// failure, or it returns with done set to true, to indicate success. +// method. + +// processMsg() is called first when the security type has been decided on, and +// will keep being called whenever there is data to read from the client. It +// should return false when it needs more data, or true when the connection has +// been successfully authenticated. In the event of authentication failure an +// AuthFailureException should be thrown - this will result in a "failed" +// security result being sent to the client with the str() from the exception +// being sent as the reason. Any other type of failure should be indicated by +// some other kind of exception which will cause the connection to be aborted. // // processMsg() must never block (or at least must never block until the client // has been authenticated) - this is to prevent denial of service attacks. @@ -33,13 +39,13 @@ // getType() should return the secType value corresponding to the SSecurity // implementation. // -// failureMessage_.buf can be set to a string which will be passed to the client -// if processMsg returns false, to indicate the reason for the failure. #ifndef __RFB_SSECURITY_H__ #define __RFB_SSECURITY_H__ +#include <rdr/types.h> #include <rfb/util.h> +#include <list> namespace rfb { @@ -48,7 +54,7 @@ namespace rfb { class SSecurity { public: virtual ~SSecurity() {} - virtual bool processMsg(SConnection* sc, bool* done)=0; + virtual bool processMsg(SConnection* sc)=0; virtual void destroy() { delete this; } virtual int getType() const = 0; @@ -57,20 +63,21 @@ namespace rfb { // necessary. Null may be returned to indicate that there is no user name // for this security type. virtual const char* getUserName() const = 0; - - virtual const char* failureMessage() {return failureMessage_.buf;} - protected: - CharArray failureMessage_; }; // SSecurityFactory creates new SSecurity instances for // particular security types. // The instances must be destroyed by calling destroy() // on them when done. + // getSecTypes returns a list of the security types that are both configured + // and actually supported. Which configuration is considered depends on the + // reverseConnection parameter. class SSecurityFactory { public: virtual ~SSecurityFactory() {} - virtual SSecurity* getSSecurity(int secType, bool noAuth=false)=0; + virtual SSecurity* getSSecurity(rdr::U8 secType, bool noAuth=false)=0; + virtual void getSecTypes(std::list<rdr::U8>* secTypes, + bool reverseConnection) = 0; }; } diff --git a/rfb/SSecurityFactoryStandard.cxx b/rfb/SSecurityFactoryStandard.cxx index e3a40aa3..a0726986 100644 --- a/rfb/SSecurityFactoryStandard.cxx +++ b/rfb/SSecurityFactoryStandard.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -25,77 +25,104 @@ #include <rfb/LogWriter.h> #include <rfb/Exception.h> #include <rfb/SSecurityFactoryStandard.h> +#include <rfb/Password.h> using namespace rfb; static LogWriter vlog("SSecurityFactoryStandard"); -VncAuthPasswdParameter* SSecurityFactoryStandard::vncAuthPasswd = 0; +StringParameter SSecurityFactoryStandard::sec_types +("SecurityTypes", + "Specify which security scheme to use for incoming connections (None, VncAuth)", + "VncAuth"); + +StringParameter SSecurityFactoryStandard::rev_sec_types +("ReverseSecurityTypes", + "Specify encryption scheme to use for reverse connections (None)", + "None"); + +StringParameter SSecurityFactoryStandard::vncAuthPasswdFile +("PasswordFile", "Password file for VNC authentication", ""); +VncAuthPasswdParameter SSecurityFactoryStandard::vncAuthPasswd +("Password", "Obfuscated binary encoding of the password which clients must supply to " + "access the server", &SSecurityFactoryStandard::vncAuthPasswdFile); -SSecurity* SSecurityFactoryStandard::getSSecurity(int secType, bool noAuth) { + +SSecurity* SSecurityFactoryStandard::getSSecurity(rdr::U8 secType, bool reverseConnection) { switch (secType) { - case secTypeNone: return new SSecurityNone(); + case secTypeNone: return new SSecurityNone(); case secTypeVncAuth: - if (!vncAuthPasswd) - throw rdr::Exception("No VncAuthPasswdParameter defined!"); - return new SSecurityVncAuth(vncAuthPasswd); + return new SSecurityVncAuth(&vncAuthPasswd); default: - throw Exception("Unsupported secType?"); + throw Exception("Security type not supported"); } } -VncAuthPasswdParameter::VncAuthPasswdParameter() { - if (SSecurityFactoryStandard::vncAuthPasswd) - throw rdr::Exception("duplicate VncAuthPasswdParameter!"); - SSecurityFactoryStandard::vncAuthPasswd = this; -} - - -VncAuthPasswdConfigParameter::VncAuthPasswdConfigParameter() -: passwdParam("Password", - "Obfuscated binary encoding of the password which clients must supply to " - "access the server", 0, 0) { +void SSecurityFactoryStandard::getSecTypes(std::list<rdr::U8>* secTypes, bool reverseConnection) { + CharArray secTypesStr; + if (reverseConnection) + secTypesStr.buf = rev_sec_types.getData(); + else + secTypesStr.buf = sec_types.getData(); + std::list<int> configured = parseSecTypes(secTypesStr.buf); + std::list<int>::iterator i; + for (i=configured.begin(); i!=configured.end(); i++) { + if (isSecTypeSupported(*i)) + secTypes->push_back(*i); + } } -char* VncAuthPasswdConfigParameter::getVncAuthPasswd() { - CharArray obfuscated; - int len; - passwdParam.getData((void**)&obfuscated.buf, &len); - printf("vnc password len=%d\n", len); // *** - if (len == 8) { - CharArray password(9); - memcpy(password.buf, obfuscated.buf, 8); - vncAuthUnobfuscatePasswd(password.buf); - return password.takeBuf(); +bool SSecurityFactoryStandard::isSecTypeSupported(rdr::U8 secType) { + switch (secType) { + case secTypeNone: + case secTypeVncAuth: + return true; + default: + return false; } - return 0; } -VncAuthPasswdFileParameter::VncAuthPasswdFileParameter() - : param("PasswordFile", "Password file for VNC authentication", "") { +VncAuthPasswdParameter::VncAuthPasswdParameter(const char* name, + const char* desc, + StringParameter* passwdFile_) +: BinaryParameter(name, desc, 0, 0), passwdFile(passwdFile_) { } -char* VncAuthPasswdFileParameter::getVncAuthPasswd() { - CharArray fname(param.getData()); - if (!fname.buf[0]) { - vlog.error("passwordFile parameter not set"); - return 0; - } - FILE* fp = fopen(fname.buf, "r"); - if (!fp) { - vlog.error("opening password file '%s' failed",fname.buf); - return 0; +char* VncAuthPasswdParameter::getVncAuthPasswd() { + ObfuscatedPasswd obfuscated; + getData((void**)&obfuscated.buf, &obfuscated.length); + + if (obfuscated.length == 0) { + if (passwdFile) { + CharArray fname(passwdFile->getData()); + if (!fname.buf[0]) { + vlog.info("neither %s nor %s params set", getName(), passwdFile->getName()); + return 0; + } + + FILE* fp = fopen(fname.buf, "r"); + if (!fp) { + vlog.error("opening password file '%s' failed",fname.buf); + return 0; + } + + vlog.debug("reading password file"); + obfuscated.buf = new char[128]; + obfuscated.length = fread(obfuscated.buf, 1, 128, fp); + fclose(fp); + } else { + vlog.info("%s parameter not set", getName()); + } } - CharArray passwd(9); - int len = fread(passwd.buf, 1, 9, fp); - fclose(fp); - if (len != 8) { - vlog.error("password file '%s' is the wrong length",fname.buf); + + try { + PlainPasswd password(obfuscated); + return password.takeBuf(); + } catch (...) { return 0; } - vncAuthUnobfuscatePasswd(passwd.buf); - return passwd.takeBuf(); } + diff --git a/rfb/SSecurityFactoryStandard.h b/rfb/SSecurityFactoryStandard.h index 5fced046..165881ec 100644 --- a/rfb/SSecurityFactoryStandard.h +++ b/rfb/SSecurityFactoryStandard.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -44,31 +44,24 @@ namespace rfb { - class VncAuthPasswdParameter : public VncAuthPasswdGetter { - public: - VncAuthPasswdParameter(); - virtual ~VncAuthPasswdParameter() {} - }; - - class SSecurityFactoryStandard : public SSecurityFactory { + class VncAuthPasswdParameter : public VncAuthPasswdGetter, BinaryParameter { public: - virtual SSecurity* getSSecurity(int secType, bool noAuth); - static VncAuthPasswdParameter* vncAuthPasswd; - }; - - class VncAuthPasswdConfigParameter : public VncAuthPasswdParameter { - public: - VncAuthPasswdConfigParameter(); + VncAuthPasswdParameter(const char* name, const char* desc, StringParameter* passwdFile_); virtual char* getVncAuthPasswd(); protected: - BinaryParameter passwdParam; + StringParameter* passwdFile; }; - class VncAuthPasswdFileParameter : public VncAuthPasswdParameter { + class SSecurityFactoryStandard : public SSecurityFactory { public: - VncAuthPasswdFileParameter(); - virtual char* getVncAuthPasswd(); - StringParameter param; + virtual SSecurity* getSSecurity(rdr::U8 secType, bool reverse); + virtual void getSecTypes(std::list<rdr::U8>* secTypes, bool reverse); + static StringParameter sec_types; + static StringParameter rev_sec_types; + static StringParameter vncAuthPasswdFile; + static VncAuthPasswdParameter vncAuthPasswd; + protected: + virtual bool isSecTypeSupported(rdr::U8 secType); }; } diff --git a/rfb/SSecurityNone.h b/rfb/SSecurityNone.h index 09b2db4f..5c19f290 100644 --- a/rfb/SSecurityNone.h +++ b/rfb/SSecurityNone.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -28,9 +28,7 @@ namespace rfb { class SSecurityNone : public SSecurity { public: - virtual bool processMsg(SConnection* sc, bool* done) { - *done = true; return true; - } + virtual bool processMsg(SConnection* sc) { return true; } virtual int getType() const {return secTypeNone;} virtual const char* getUserName() const {return 0;} }; diff --git a/rfb/SSecurityVncAuth.cxx b/rfb/SSecurityVncAuth.cxx index 532d1a6a..29a3b964 100644 --- a/rfb/SSecurityVncAuth.cxx +++ b/rfb/SSecurityVncAuth.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -18,20 +18,27 @@ // // SSecurityVncAuth // +// XXX not thread-safe, because d3des isn't - do we need to worry about this? +// #include <rfb/SSecurityVncAuth.h> #include <rdr/RandomStream.h> #include <rfb/SConnection.h> -#include <rfb/vncAuth.h> +#include <rfb/Password.h> #include <rfb/Configuration.h> #include <rfb/LogWriter.h> #include <rfb/util.h> +#include <rfb/Exception.h> #include <string.h> #include <stdio.h> +extern "C" { +#include <rfb/d3des.h> +} + using namespace rfb; -static LogWriter vlog("VncAuth"); +static LogWriter vlog("SVncAuth"); SSecurityVncAuth::SSecurityVncAuth(VncAuthPasswdGetter* pg_) @@ -39,9 +46,8 @@ SSecurityVncAuth::SSecurityVncAuth(VncAuthPasswdGetter* pg_) { } -bool SSecurityVncAuth::processMsg(SConnection* sc, bool* done) +bool SSecurityVncAuth::processMsg(SConnection* sc) { - *done = false; rdr::InStream* is = sc->getInStream(); rdr::OutStream* os = sc->getOutStream(); @@ -51,33 +57,31 @@ bool SSecurityVncAuth::processMsg(SConnection* sc, bool* done) os->writeBytes(challenge, vncAuthChallengeSize); os->flush(); sentChallenge = true; - return true; + return false; } - if (responsePos >= vncAuthChallengeSize) return false; - while (is->checkNoWait(1) && responsePos < vncAuthChallengeSize) { + while (responsePos < vncAuthChallengeSize && is->checkNoWait(1)) response[responsePos++] = is->readU8(); - } - if (responsePos < vncAuthChallengeSize) return true; + if (responsePos < vncAuthChallengeSize) return false; - CharArray passwd(pg->getVncAuthPasswd()); + PlainPasswd passwd(pg->getVncAuthPasswd()); - // Beyond this point, there is no more VNCAuth protocol to perform. - *done = true; + if (!passwd.buf) + throw AuthFailureException("No password configured for VNC Auth"); - if (!passwd.buf) { - failureMessage_.buf = strDup("No password configured for VNC Auth"); - vlog.error(failureMessage_.buf); - return false; - } - - vncAuthEncryptChallenge(challenge, passwd.buf); - memset(passwd.buf, 0, strlen(passwd.buf)); + // Calculate the expected response + rdr::U8 key[8]; + int pwdLen = strlen(passwd.buf); + for (int i=0; i<8; i++) + key[i] = i<pwdLen ? passwd.buf[i] : 0; + deskey(key, EN0); + for (int j = 0; j < vncAuthChallengeSize; j += 8) + des(challenge+j, challenge+j); - if (memcmp(challenge, response, vncAuthChallengeSize) != 0) { - return false; - } + // Check the actual response + if (memcmp(challenge, response, vncAuthChallengeSize) != 0) + throw AuthFailureException(); return true; } diff --git a/rfb/SSecurityVncAuth.h b/rfb/SSecurityVncAuth.h index edbd7206..1d0a82de 100644 --- a/rfb/SSecurityVncAuth.h +++ b/rfb/SSecurityVncAuth.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -26,7 +26,7 @@ #include <rfb/SSecurity.h> #include <rfb/secTypes.h> -#include <rfb/vncAuth.h> +#include <rdr/types.h> namespace rfb { @@ -40,10 +40,11 @@ namespace rfb { class SSecurityVncAuth : public SSecurity { public: SSecurityVncAuth(VncAuthPasswdGetter* pg); - virtual bool processMsg(SConnection* sc, bool* done); + virtual bool processMsg(SConnection* sc); virtual int getType() const {return secTypeVncAuth;} virtual const char* getUserName() const {return 0;} private: + enum {vncAuthChallengeSize = 16}; rdr::U8 challenge[vncAuthChallengeSize]; rdr::U8 response[vncAuthChallengeSize]; bool sentChallenge; diff --git a/rfb/ServerCore.cxx b/rfb/ServerCore.cxx index fe61ecbd..750daae2 100644 --- a/rfb/ServerCore.cxx +++ b/rfb/ServerCore.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -24,38 +24,29 @@ #include <string.h> #include <rfb/util.h> #include <rfb/ServerCore.h> -#include <rfb/vncAuth.h> rfb::IntParameter rfb::Server::idleTimeout ("IdleTimeout", - "The number of seconds after which an idle VNC connection will be dropped", - 0); - + "The number of seconds after which an idle VNC connection will be dropped " + "(zero means no timeout)", + 0, 0); rfb::IntParameter rfb::Server::maxDisconnectionTime ("MaxDisconnectionTime", "Terminate when no client has been connected for s seconds", - 0); + 0, 0); rfb::IntParameter rfb::Server::maxConnectionTime ("MaxConnectionTime", "Terminate when a client has been connected for s seconds", - 0); + 0, 0); rfb::IntParameter rfb::Server::maxIdleTime ("MaxIdleTime", "Terminate after s seconds of user inactivity", - 0); + 0, 0); rfb::IntParameter rfb::Server::clientWaitTimeMillis ("ClientWaitTimeMillis", "The number of milliseconds to wait for a client which is no longer " "responding", - 20000); -rfb::StringParameter rfb::Server::sec_types -("SecurityTypes", - "Specify which security scheme to use for incoming connections (None, VncAuth)", - "VncAuth"); -rfb::StringParameter rfb::Server::rev_sec_types -("ReverseSecurityTypes", - "Specify encryption scheme to use for reverse connections (None)", - "None"); + 20000, 0); rfb::BoolParameter rfb::Server::compareFB ("CompareFB", "Perform pixel comparison on framebuffer to reduce unnecessary updates", @@ -101,8 +92,3 @@ rfb::BoolParameter rfb::Server::queryConnect ("QueryConnect", "Prompt the local user to accept or reject incoming connections.", false); -rfb::IntParameter rfb::Server::blacklistLevel -("BlacklistLevel", - "When to test whether particular host should be blacklisted. (0 = Never, " - "1 = Test before authentication, 2 = Test on connect)", - 1); diff --git a/rfb/ServerCore.h b/rfb/ServerCore.h index b01fcfd9..68d7b74b 100644 --- a/rfb/ServerCore.h +++ b/rfb/ServerCore.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -37,8 +37,6 @@ namespace rfb { static IntParameter maxConnectionTime; static IntParameter maxIdleTime; static IntParameter clientWaitTimeMillis; - static StringParameter sec_types; - static StringParameter rev_sec_types; static BoolParameter compareFB; static BoolParameter protocol3_3; static BoolParameter alwaysShared; @@ -49,7 +47,6 @@ namespace rfb { static BoolParameter acceptCutText; static BoolParameter sendCutText; static BoolParameter queryConnect; - static IntParameter blacklistLevel; }; diff --git a/rfb/Threading.h b/rfb/Threading.h index effc4363..66b3aa0f 100644 --- a/rfb/Threading.h +++ b/rfb/Threading.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -25,7 +25,7 @@ #define __RFB_THREADING_H__ #ifdef WIN32 -#include <rfb/win32/Threading_win32.h> +#include <rfb_win32/Threading.h> #endif #endif // __RFB_THREADING_H__ diff --git a/rfb/TransImageGetter.cxx b/rfb/TransImageGetter.cxx index 0b494a96..82c291b6 100644 --- a/rfb/TransImageGetter.cxx +++ b/rfb/TransImageGetter.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/TransImageGetter.h b/rfb/TransImageGetter.h index 60ab0699..5328e6d0 100644 --- a/rfb/TransImageGetter.h +++ b/rfb/TransImageGetter.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/TrueColourMap.h b/rfb/TrueColourMap.h index c0d49071..1e87fa4c 100644 --- a/rfb/TrueColourMap.h +++ b/rfb/TrueColourMap.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/UpdateTracker.cxx b/rfb/UpdateTracker.cxx index cc0fb101..14ac49d7 100644 --- a/rfb/UpdateTracker.cxx +++ b/rfb/UpdateTracker.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -30,34 +30,34 @@ using namespace rfb; static LogWriter vlog("UpdateTracker"); -// -=- ClippedUpdateTracker -void ClippedUpdateTracker::add_changed(const Region ®ion) { - child.add_changed(region.intersect(cliprgn)); +// -=- ClippingUpdateTracker + +void ClippingUpdateTracker::add_changed(const Region ®ion) { + ut->add_changed(region.intersect(clipRect)); } -void ClippedUpdateTracker::add_copied(const Region &dest, const Point &delta) { +void ClippingUpdateTracker::add_copied(const Region &dest, const Point &delta) { // Clip the destination to the display area - Region clipdest = dest.intersect(cliprgn); + Region clipdest = dest.intersect(clipRect); if (clipdest.is_empty()) return; // Clip the source to the screen Region tmp = clipdest; tmp.translate(delta.negate()); - tmp.assign_intersect(cliprgn); + tmp.assign_intersect(clipRect); if (!tmp.is_empty()) { // Translate the source back to a destination region tmp.translate(delta); // Pass the copy region to the child tracker - child.add_copied(tmp, delta); + ut->add_copied(tmp, delta); } // And add any bits that we had to remove to the changed region tmp = clipdest.subtract(tmp); - if (!tmp.is_empty()) { - child.add_changed(tmp); - } + if (!tmp.is_empty()) + ut->add_changed(tmp); } // SimpleUpdateTracker @@ -140,7 +140,7 @@ void SimpleUpdateTracker::subtract(const Region& region) { changed.assign_subtract(region); } -void SimpleUpdateTracker::get_update(UpdateInfo* info, const Region& clip) +void SimpleUpdateTracker::getUpdateInfo(UpdateInfo* info, const Region& clip) { copied.assign_subtract(changed); info->changed = changed.intersect(clip); @@ -148,25 +148,9 @@ void SimpleUpdateTracker::get_update(UpdateInfo* info, const Region& clip) info->copy_delta = copy_delta; } -void SimpleUpdateTracker::flush_update(UpdateTracker &info, - const Region &cliprgn) -{ - Region copied_clipped = copied.intersect(cliprgn); - Region changed_clipped = changed.intersect(cliprgn); - copied.assign_subtract(copied_clipped); - changed.assign_subtract(changed_clipped); - if (!copied_clipped.is_empty()) { - info.add_copied(copied_clipped, copy_delta); - } - if (!changed_clipped.is_empty()) - info.add_changed(changed_clipped); -} - -void SimpleUpdateTracker::get_update(UpdateTracker &to) const { - if (!copied.is_empty()) { - to.add_copied(copied, copy_delta); - } - if (!changed.is_empty()) { - to.add_changed(changed); - } +void SimpleUpdateTracker::copyTo(UpdateTracker* to) const { + if (!copied.is_empty()) + to->add_copied(copied, copy_delta); + if (!changed.is_empty()) + to->add_changed(changed); } diff --git a/rfb/UpdateTracker.h b/rfb/UpdateTracker.h index 5015a250..5b51317a 100644 --- a/rfb/UpdateTracker.h +++ b/rfb/UpdateTracker.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -47,25 +47,24 @@ namespace rfb { virtual void add_copied(const Region &dest, const Point &delta) = 0; }; - class ClippedUpdateTracker : public UpdateTracker { + class ClippingUpdateTracker : public UpdateTracker { public: - ClippedUpdateTracker(UpdateTracker &child_) : child(child_) {}; - ClippedUpdateTracker(UpdateTracker &child_, - const Region &cliprgn_) : child(child_), cliprgn(cliprgn_) {}; - virtual ~ClippedUpdateTracker() {}; - - virtual void set_clip_region(const Region cliprgn_) {cliprgn = cliprgn_;}; + ClippingUpdateTracker() : ut(0) {} + ClippingUpdateTracker(UpdateTracker* ut_, const Rect& r=Rect()) : ut(ut_), clipRect(r) {} + + void setUpdateTracker(UpdateTracker* ut_) {ut = ut_;} + void setClipRect(const Rect& cr) {clipRect = cr;} virtual void add_changed(const Region ®ion); virtual void add_copied(const Region &dest, const Point &delta); protected: - UpdateTracker &child; - Region cliprgn; + UpdateTracker* ut; + Region clipRect; }; class SimpleUpdateTracker : public UpdateTracker { public: - SimpleUpdateTracker(bool use_copyrect=false); + SimpleUpdateTracker(bool use_copyrect=true); virtual ~SimpleUpdateTracker(); virtual void enable_copyrect(bool enable); @@ -75,13 +74,10 @@ namespace rfb { virtual void subtract(const Region& region); // Fill the supplied UpdateInfo structure with update information - virtual void get_update(UpdateInfo* info, const Region& cliprgn); - - // Pass the current updates to the supplied tracker - virtual void get_update(UpdateTracker &to) const; + virtual void getUpdateInfo(UpdateInfo* info, const Region& cliprgn); - // Also removes the updates that are returned from this update tracker - virtual void flush_update(UpdateTracker &to, const Region &cliprgn); + // Copy the contained updates to another tracker + virtual void copyTo(UpdateTracker* to) const; // Get the changed/copied regions diff --git a/rfb/UserPasswdGetter.h b/rfb/UserPasswdGetter.h index c242ed0a..18b0bae3 100644 --- a/rfb/UserPasswdGetter.h +++ b/rfb/UserPasswdGetter.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -20,12 +20,11 @@ namespace rfb { class UserPasswdGetter { public: - // getUserPasswd gets the username and password. This might - // involve a dialog, getpass(), etc. The user buffer pointer - // can be null, in which case no user name will be retrieved. - // The caller MUST delete [] the result(s) iff the - // call succeeds (returns true), and ignore them if failed. - virtual bool getUserPasswd(char** user, char** password)=0; + // getUserPasswd gets the username and password. This might involve a + // dialog, getpass(), etc. The user buffer pointer can be null, in which + // case no user name will be retrieved. The caller MUST delete [] the + // result(s). + virtual void getUserPasswd(char** user, char** password)=0; }; } #endif diff --git a/rfb/VNCSConnectionST.cxx b/rfb/VNCSConnectionST.cxx index 98957615..37fb7447 100644 --- a/rfb/VNCSConnectionST.cxx +++ b/rfb/VNCSConnectionST.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -21,6 +21,7 @@ #include <rfb/secTypes.h> #include <rfb/ServerCore.h> #include <rfb/ComparingUpdateTracker.h> +#include <rfb/KeyRemapper.h> #define XK_MISCELLANY #define XK_XKB_KEYS #include <rfb/keysymdef.h> @@ -31,8 +32,8 @@ static LogWriter vlog("VNCSConnST"); VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, bool reverse) - : sock(s), reverseConnection(reverse), server(server_), - image_getter(server->useEconomicTranslate), + : SConnection(server_->securityFactory, reverse), sock(s), server(server_), + updates(false), image_getter(server->useEconomicTranslate), drawRenderedCursor(false), removeRenderedCursor(false), pointerEventTime(0), accessRights(AccessDefault), startTime(time(0)) @@ -41,21 +42,11 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, peerEndpoint.buf = sock->getPeerEndpoint(); VNCServerST::connectionsLog.write(1,"accepted: %s", peerEndpoint.buf); + // Configure the socket setSocketTimeouts(); lastEventTime = time(0); - // Initialise security - CharArray sec_types_str; - if (reverseConnection) - sec_types_str.buf = rfb::Server::rev_sec_types.getData(); - else - sec_types_str.buf = rfb::Server::sec_types.getData(); - std::list<int> sec_types = parseSecTypes(sec_types_str.buf); - std::list<int>::iterator i; - for (i=sec_types.begin(); i!=sec_types.end(); i++) { - addSecType(*i); - } - + // Add this client to the VNCServerST server->clients.push_front(this); } @@ -64,7 +55,8 @@ VNCSConnectionST::~VNCSConnectionST() { // If we reach here then VNCServerST is deleting us! VNCServerST::connectionsLog.write(1,"closed: %s (%s)", - peerEndpoint.buf, closeReason.buf); + peerEndpoint.buf, + (closeReason.buf) ? closeReason.buf : ""); // Release any keys the client still had pressed std::set<rdr::U32>::iterator i; @@ -103,16 +95,17 @@ void VNCSConnectionST::close(const char* reason) server->lastDisconnectTime = time(0); } - // Just shutdown the socket. This will cause processMessages to - // eventually fail, causing us and our socket to be deleted. + // Just shutdown the socket and mark our state as closing. Eventually the + // calling code will call VNCServerST's removeSocket() method causing us to + // be deleted. sock->shutdown(); setState(RFBSTATE_CLOSING); } -bool VNCSConnectionST::processMessages() +void VNCSConnectionST::processMessages() { - if (state() == RFBSTATE_CLOSING) return false; + if (state() == RFBSTATE_CLOSING) return; try { // - Now set appropriate socket timeouts and process data setSocketTimeouts(); @@ -124,15 +117,11 @@ bool VNCSConnectionST::processMessages() if (!clientsReadyBefore && !requested.is_empty()) server->desktop->framebufferUpdateRequest(); - - return true; - } catch (rdr::EndOfStream&) { close("Clean disconnection"); } catch (rdr::Exception &e) { close(e.str()); } - return false; } void VNCSConnectionST::writeFramebufferUpdateOrClose() @@ -170,9 +159,11 @@ void VNCSConnectionST::pixelBufferChange() cp.width = server->pb->width(); cp.height = server->pb->height(); - if (!writer()->writeSetDesktopSize()) { - close("Client does not support desktop resize"); - return; + if (state() == RFBSTATE_NORMAL) { + if (!writer()->writeSetDesktopSize()) { + close("Client does not support desktop resize"); + return; + } } } // Just update the whole screen at the moment because we're too lazy to @@ -248,13 +239,13 @@ int VNCSConnectionST::checkIdleTimeout() // now. vlog.info("Time has gone forwards - resetting idle timeout"); lastEventTime = now; - return idleTimeout; + return secsToMillis(idleTimeout); } if (timeLeft <= 0) { close("Idle timeout"); return 0; } - return timeLeft * 1000; + return secsToMillis(timeLeft); } // renderedCursorChange() is called whenever the server-side rendered cursor @@ -302,29 +293,10 @@ void VNCSConnectionST::approveConnectionOrClose(bool accept, // -=- Callbacks from SConnection -void VNCSConnectionST::versionReceived() { - CharArray address(sock->getPeerAddress()); - if ((rfb::Server::blacklistLevel == 1) && - server->blHosts->isBlackmarked(address.buf)) { - server->connectionsLog.error("blacklisted: %s", address.buf); - throwConnFailedException("Too many security failures"); - } -} - -SSecurity* VNCSConnectionST::getSSecurity(int secType) { - if (!server->securityFactory) - throw rdr::Exception("no SSecurityFactory registered!"); - return server->securityFactory->getSSecurity(secType, reverseConnection); -} - void VNCSConnectionST::authSuccess() { lastEventTime = time(0); - // - Authentication succeeded - clear from blacklist - CharArray name; name.buf = sock->getPeerAddress(); - server->blHosts->clearBlackmark(name.buf); - server->startDesktop(); // - Set the connection parameters appropriately @@ -346,18 +318,36 @@ void VNCSConnectionST::authSuccess() void VNCSConnectionST::queryConnection(const char* userName) { + // - Authentication succeeded - clear from blacklist + CharArray name; name.buf = sock->getPeerAddress(); + server->blHosts->clearBlackmark(name.buf); + + // - Special case to provide a more useful error message + if (rfb::Server::neverShared && !rfb::Server::disconnectClients && + server->authClientCount() > 0) { + approveConnection(false, "The server is already in use"); + return; + } + // - Does the client have the right to bypass the query? - if (reverseConnection || !rfb::Server::queryConnect || + if (reverseConnection || + !(rfb::Server::queryConnect || sock->requiresQuery()) || (accessRights & AccessNoQuery)) { approveConnection(true); return; } + // - Get the server to display an Accept/Reject dialog, if required + // If a dialog is displayed, the result will be PENDING, and the + // server will call approveConnection at a later time CharArray reason; VNCServerST::queryResult qr = server->queryConnection(sock, userName, &reason.buf); - if (qr == VNCServerST::PENDING) return; + if (qr == VNCServerST::PENDING) + return; + + // - If server returns ACCEPT/REJECT then pass result to SConnection approveConnection(qr == VNCServerST::ACCEPT, reason.buf); } @@ -372,7 +362,8 @@ void VNCSConnectionST::clientInit(bool shared) vlog.debug("non-shared connection - closing clients"); server->closeClients("Non-shared connection requested", getSock()); } else { - // - Refuse this connection if there are existing clients, in addition to this one + // - Refuse this connection if there are existing clients, in addition to + // this one if (server->authClientCount() > 1) { close("Server is already in use"); return; @@ -392,14 +383,14 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf) setCursor(); } -void VNCSConnectionST::pointerEvent(int x, int y, int buttonMask) +void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask) { pointerEventTime = lastEventTime = time(0); server->lastUserInputTime = lastEventTime; if (!(accessRights & AccessPtrEvents)) return; if (!rfb::Server::acceptPointerEvents) return; if (!server->pointerClient || server->pointerClient == this) { - pointerEventPos = Point(x, y); + pointerEventPos = pos; if (buttonMask) server->pointerClient = this; else @@ -432,6 +423,10 @@ void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) { if (!(accessRights & AccessKeyEvents)) return; if (!rfb::Server::acceptKeyEvents) return; + // Remap the key if required + if (server->keyRemapper) + key = server->keyRemapper->remapKey(key); + // Turn ISO_Left_Tab into shifted Tab. VNCSConnectionSTShiftPresser shiftPresser(server->desktop); if (key == XK_ISO_Left_Tab) { @@ -522,10 +517,9 @@ void VNCSConnectionST::writeSetCursorCallback() image_getter.translatePixels(server->cursor.data, transData, server->cursor.area()); writer()->writeSetCursor(server->cursor.width(), - server->cursor.height(), - server->cursor.hotspot.x, - server->cursor.hotspot.y, - transData, server->cursor.mask.buf); + server->cursor.height(), + server->cursor.hotspot, + transData, server->cursor.mask.buf); } @@ -574,7 +568,7 @@ void VNCSConnectionST::writeFramebufferUpdate() if (renderedCursorRect.is_empty()) { drawRenderedCursor = false; } else if (!updates.get_changed().union_(updates.get_copied()) - .intersect(renderedCursorRect).is_empty()) { + .intersect(renderedCursorRect).is_empty()) { drawRenderedCursor = true; } @@ -589,7 +583,7 @@ void VNCSConnectionST::writeFramebufferUpdate() UpdateInfo update; updates.enable_copyrect(cp.useCopyRect); - updates.get_update(&update, requested); + updates.getUpdateInfo(&update, requested); if (!update.is_empty() || writer()->needFakeUpdate() || drawRenderedCursor) { // Compute the number of rectangles. Tight encoder makes the things more // complicated as compared to the original RealVNC. @@ -660,11 +654,9 @@ void VNCSConnectionST::setCursor() void VNCSConnectionST::setSocketTimeouts() { int timeoutms = rfb::Server::clientWaitTimeMillis; - if (timeoutms == 0 || timeoutms > rfb::Server::idleTimeout * 1000) { - timeoutms = rfb::Server::idleTimeout * 1000; - if (timeoutms == 0) - timeoutms = -1; - } + soonestTimeout(&timeoutms, secsToMillis(rfb::Server::idleTimeout)); + if (timeoutms == 0) + timeoutms = -1; sock->inStream().setTimeout(timeoutms); sock->outStream().setTimeout(timeoutms); } diff --git a/rfb/VNCSConnectionST.h b/rfb/VNCSConnectionST.h index 7813c04e..a9a356cb 100644 --- a/rfb/VNCSConnectionST.h +++ b/rfb/VNCSConnectionST.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -56,9 +56,9 @@ namespace rfb { // processMessages() processes incoming messages from the client, invoking // various callbacks as a result. It continues to process messages until - // reading might block. Returns true if the client is still valid & - // active, or false if it has disconnected or an error has occurred. - bool processMessages(); + // reading might block. shutdown() will be called on the connection's + // Socket if an error occurs, via the close() call. + void processMessages(); void writeFramebufferUpdateOrClose(); void pixelBufferChange(); @@ -117,16 +117,14 @@ namespace rfb { // none of these methods should call any of the above methods which may // delete the SConnectionST object. - virtual void versionReceived(); - virtual SSecurity* getSSecurity(int secType); virtual void authSuccess(); virtual void queryConnection(const char* userName); virtual void clientInit(bool shared); virtual void setPixelFormat(const PixelFormat& pf); - virtual void pointerEvent(int x, int y, int buttonMask); + virtual void pointerEvent(const Point& pos, int buttonMask); virtual void keyEvent(rdr::U32 key, bool down); - virtual void framebufferUpdateRequest(const Rect& r, bool incremental); virtual void clientCutText(const char* str, int len); + virtual void framebufferUpdateRequest(const Rect& r, bool incremental); virtual void setInitialColourMap(); virtual void supportsLocalCursor(); @@ -153,7 +151,6 @@ namespace rfb { network::Socket* sock; CharArray peerEndpoint; - bool reverseConnection; VNCServerST* server; SimpleUpdateTracker updates; TransImageGetter image_getter; diff --git a/rfb/VNCServer.h b/rfb/VNCServer.h index e80044ce..df0fb0e5 100644 --- a/rfb/VNCServer.h +++ b/rfb/VNCServer.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -69,11 +69,11 @@ namespace rfb { // significant bit represents the leftmost pixel, and the bytes are simply // in left-to-right order. The server takes its own copy of the data in // cursorData and mask. - virtual void setCursor(int width, int height, int hotspotX, int hotspotY, + virtual void setCursor(int width, int height, const Point& hotspot, void* cursorData, void* mask) = 0; // setCursorPos() tells the server the current position of the cursor. - virtual void setCursorPos(int x, int y) = 0; + virtual void setCursorPos(const Point& p) = 0; // setSSecurityFactory() tells the server which factory to use when // attempting to authenticate connections. diff --git a/rfb/VNCServerST.cxx b/rfb/VNCServerST.cxx index 0721a3c9..7e3e0c67 100644 --- a/rfb/VNCServerST.cxx +++ b/rfb/VNCServerST.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -32,25 +32,19 @@ // reason for disconnecting clients is when the desktop size has changed as a // result of a call to setPixelBuffer(). // -// Because we don't want to mess up any data structures which the calling code -// may maintain regarding sockets with data to process, we can't just delete a -// socket when we decide to close the connection to a client. Instead, we only -// go as far as calling shutdown() on the socket. This should ensure that -// eventually the calling code will get round to calling processSocketEvent() -// for that socket. Then we can delete the VNCSConnectionST object and its -// associated network::Socket object, and return false from that call to let -// the calling code know that the socket has been deleted. This is the only -// way that these objects get deleted. -// -// It is possible that there are platforms where calling shutdown() cannot -// guarantee that processSocketEvent() will be called - if so then it may be -// necessary to introduce some kind of "socket closure callback", but we'll -// only do that if it proves absolutely necessary. +// The responsibility for creating and deleting sockets is entirely with the +// calling code. When VNCServerST wants to close a connection to a client it +// calls the VNCSConnectionST's close() method which calls shutdown() on the +// socket. Eventually the calling code will notice that the socket has been +// shut down and call removeSocket() so that we can delete the +// VNCSConnectionST. Note that the socket must not be deleted by the calling +// code until after removeSocket() has been called. // // One minor complication is that we don't allocate a VNCSConnectionST object // for a blacklisted host (since we want to minimise the resources used for -// dealing with such a connection). So we maintain a separate list of -// closingSockets for this purpose. +// dealing with such a connection). In order to properly implement the +// getSockets function, we must maintain a separate closingSockets list, +// otherwise blacklisted connections might be "forgotten". #include <rfb/ServerCore.h> @@ -58,6 +52,7 @@ #include <rfb/VNCSConnectionST.h> #include <rfb/ComparingUpdateTracker.h> #include <rfb/SSecurityFactoryStandard.h> +#include <rfb/KeyRemapper.h> #include <rfb/util.h> #include <rdr/types.h> @@ -80,7 +75,8 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_, name(strDup(name_)), pointerClient(0), comparer(0), renderedCursorInvalid(false), securityFactory(sf ? sf : &defaultSecurityFactory), - queryConnectionHandler(0), useEconomicTranslate(false), + queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance), + useEconomicTranslate(false), lastConnectionTime(0), disableclients(false) { lastUserInputTime = lastDisconnectTime = time(0); @@ -97,13 +93,8 @@ VNCServerST::~VNCServerST() // Delete all the clients, and their sockets, and any closing sockets // NB: Deleting a client implicitly removes it from the clients list while (!clients.empty()) { - delete clients.front()->getSock(); delete clients.front(); } - while (!closingSockets.empty()) { - delete closingSockets.front(); - closingSockets.pop_front(); - } // Stop the desktop object if active, *only* after deleting all clients! if (desktopStarted) { @@ -117,18 +108,12 @@ VNCServerST::~VNCServerST() // SocketServer methods -void VNCServerST::addClient(network::Socket* sock) -{ - addClient(sock, false); -} - -void VNCServerST::addClient(network::Socket* sock, bool reverse) +void VNCServerST::addSocket(network::Socket* sock, bool outgoing) { // - Check the connection isn't black-marked // *** do this in getSecurity instead? CharArray address(sock->getPeerAddress()); - if ((rfb::Server::blacklistLevel == 2) && - blHosts->isBlackmarked(address.buf)) { + if (blHosts->isBlackmarked(address.buf)) { connectionsLog.error("blacklisted: %s", address.buf); try { SConnection::writeConnFailedFromScratch("Too many security failures", @@ -144,37 +129,43 @@ void VNCServerST::addClient(network::Socket* sock, bool reverse) lastConnectionTime = time(0); } - VNCSConnectionST* client = new VNCSConnectionST(this, sock, reverse); + VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing); client->init(); } -bool VNCServerST::processSocketEvent(network::Socket* sock) -{ - // - Find the appropriate VNCSConnectionST and process the event +void VNCServerST::removeSocket(network::Socket* sock) { + // - If the socket has resources allocated to it, delete them std::list<VNCSConnectionST*>::iterator ci; for (ci = clients.begin(); ci != clients.end(); ci++) { if ((*ci)->getSock() == sock) { - if ((*ci)->processMessages()) - return true; - // processMessages failed, so delete the client + // - Delete the per-Socket resources delete *ci; - break; + + // - Check that the desktop object is still required + if (authClientCount() == 0 && desktopStarted) { + slog.debug("no authenticated clients - stopping desktop"); + desktopStarted = false; + desktop->stop(); + } + return; } } - // - If no client is using the Socket then delete it + // - If the Socket has no resources, it may have been a closingSocket closingSockets.remove(sock); - delete sock; +} - // - Check that the desktop object is still required - if (authClientCount() == 0 && desktopStarted) { - slog.debug("no authenticated clients - stopping desktop"); - desktopStarted = false; - desktop->stop(); +void VNCServerST::processSocketEvent(network::Socket* sock) +{ + // - Find the appropriate VNCSConnectionST and process the event + std::list<VNCSConnectionST*>::iterator ci; + for (ci = clients.begin(); ci != clients.end(); ci++) { + if ((*ci)->getSock() == sock) { + (*ci)->processMessages(); + return; + } } - - // - Inform the caller not to continue handling the Socket - return false; + throw rdr::Exception("invalid Socket in VNCServerST"); } int VNCServerST::checkTimeouts() @@ -342,11 +333,10 @@ void VNCServerST::tryUpdate() } } -void VNCServerST::setCursor(int width, int height, int newHotspotX, - int newHotspotY, void* data, void* mask) +void VNCServerST::setCursor(int width, int height, const Point& newHotspot, + void* data, void* mask) { - cursor.hotspot.x = newHotspotX; - cursor.hotspot.y = newHotspotY; + cursor.hotspot = newHotspot; cursor.setSize(width, height); memcpy(cursor.data, data, cursor.dataLen()); memcpy(cursor.mask.buf, mask, cursor.maskLen()); @@ -363,11 +353,10 @@ void VNCServerST::setCursor(int width, int height, int newHotspotX, } } -void VNCServerST::setCursorPos(int x, int y) +void VNCServerST::setCursorPos(const Point& pos) { - if (cursorPos.x != x || cursorPos.y != y) { - cursorPos.x = x; - cursorPos.y = y; + if (!cursorPos.equals(pos)) { + cursorPos = pos; renderedCursorInvalid = true; std::list<VNCSConnectionST*>::iterator ci; for (ci = clients.begin(); ci != clients.end(); ci++) diff --git a/rfb/VNCServerST.h b/rfb/VNCServerST.h index 3d25fcaa..162fa9a4 100644 --- a/rfb/VNCServerST.h +++ b/rfb/VNCServerST.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -39,6 +39,7 @@ namespace rfb { class VNCSConnectionST; class ComparingUpdateTracker; class PixelBuffer; + class KeyRemapper; class VNCServerST : public VNCServer, public network::SocketServer { public: @@ -52,30 +53,25 @@ namespace rfb { // Methods overridden from SocketServer - // - Run a client connection on the supplied socket - // This causes the server to allocate the required structures - // to handle a client connection, and to initialise the RFB - // protocol. - // NB: The server assumes ownership of the Socket object. - - virtual void addClient(network::Socket* sock); - - // - Process an input event on a particular Socket - // The platform-specific side of the server implementation calls - // this method whenever data arrives on one of the active - // network sockets. - // The method returns true if the Socket is still in use by the - // server, or false if it is no longer required and has been - // deleted. - // NB: If false is returned then the Socket is deleted and must - // not be accessed again! - - virtual bool processSocketEvent(network::Socket* sock); - - // - checkTimeouts() returns the number of milliseconds left until the next - // idle timeout expires. If any have already expired, the corresponding - // connections are closed. Zero is returned if there is no idle timeout. - + // addSocket + // Causes the server to allocate an RFB-protocol management + // structure for the socket & initialise it. + virtual void addSocket(network::Socket* sock, bool outgoing=false); + + // removeSocket + // Clean up any resources associated with the Socket + virtual void removeSocket(network::Socket* sock); + + // processSocketEvent + // Read more RFB data from the Socket. If an error occurs during + // processing then shutdown() is called on the Socket, causing + // removeSocket() to be called by the caller at a later time. + virtual void processSocketEvent(network::Socket* sock); + + // checkTimeouts + // Returns the number of milliseconds left until the next idle timeout + // expires. If any have already expired, the corresponding connections + // are closed. Zero is returned if there is no idle timeout. virtual int checkTimeouts(); @@ -88,9 +84,9 @@ namespace rfb { virtual void add_copied(const Region &dest, const Point &delta); virtual bool clientsReadyForUpdate(); virtual void tryUpdate(); - virtual void setCursor(int width, int height, int hotspotX, int hotspotY, + virtual void setCursor(int width, int height, const Point& hotspot, void* cursorData, void* mask); - virtual void setCursorPos(int x, int y); + virtual void setCursorPos(const Point& p); virtual void setSSecurityFactory(SSecurityFactory* f) {securityFactory=f;} virtual void bell(); @@ -101,17 +97,10 @@ namespace rfb { // VNCServerST-only methods - // If a particular VNCSConnectionST* is specified then - // that connection will NOT be closed. + // closeClients() closes all RFB sessions, except the specified one (if + // any), and logs the specified reason for closure. void closeClients(const char* reason, network::Socket* sock); - // addClient() with an extra flag to say if this is a reverse connection to - // a listening client. Reverse connections are not authenticated and are - // always shared (unless the NeverShared parameter is set). - - void addClient(network::Socket* sock, bool reverse); - - // getSockets() gets a list of sockets. This can be used to generate an // fd_set for calling select(). @@ -183,11 +172,15 @@ namespace rfb { void setBlacklist(Blacklist* bl) {blHosts = bl ? bl : &blacklist;} // setEconomicTranslate() determines (for new connections) whether pixels - // should be translated for <=16bpp clients using a large lookup table (fast) - // or separate, smaller R, G and B tables (slower). If set to true, small tables - // are used, to save memory. + // should be translated for <=16bpp clients using a large lookup table + // (fast) or separate, smaller R, G and B tables (slower). If set to true, + // small tables are used, to save memory. void setEconomicTranslate(bool et) { useEconomicTranslate = et; } + // setKeyRemapper() replaces the VNCServerST's default key remapper. + // NB: A null pointer is valid here. + void setKeyRemapper(KeyRemapper* kr) { keyRemapper = kr; } + void getConnInfo(ListConnInfo * listConn); void setConnStatus(ListConnInfo* listConn); @@ -231,6 +224,7 @@ namespace rfb { SSecurityFactory* securityFactory; QueryConnectionHandler* queryConnectionHandler; + KeyRemapper* keyRemapper; bool useEconomicTranslate; time_t lastUserInputTime; diff --git a/rfb/ZRLEDecoder.cxx b/rfb/ZRLEDecoder.cxx index 2dd4a129..b7c69129 100644 --- a/rfb/ZRLEDecoder.cxx +++ b/rfb/ZRLEDecoder.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/ZRLEDecoder.h b/rfb/ZRLEDecoder.h index c8b1febf..fe96c737 100644 --- a/rfb/ZRLEDecoder.h +++ b/rfb/ZRLEDecoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/ZRLEEncoder.h b/rfb/ZRLEEncoder.h index 17222a3c..7768917d 100644 --- a/rfb/ZRLEEncoder.h +++ b/rfb/ZRLEEncoder.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -34,7 +34,8 @@ namespace rfb { // can be used to stop the MemOutStream from growing too large. The value // must be large enough to allow for at least one row of ZRLE tiles. So // for example for a screen width of 2048 32-bit pixels this is 2K*4*64 = - // 512Kbytes plus a bit of overhead. + // 512Kbytes plus a bit of overhead (the overhead is about 1/16 of the + // width, in this example about 128 bytes). static void setMaxLen(int m) { maxLen = m; } // setSharedMos() sets a MemOutStream to be shared amongst all diff --git a/rfb/d3des.c b/rfb/d3des.c index 9227ddd3..eaca5816 100644 --- a/rfb/d3des.c +++ b/rfb/d3des.c @@ -173,14 +173,14 @@ static void unscrun(outof, into) register unsigned long *outof; register unsigned char *into; { - *into++ = (*outof >> 24) & 0xffL; - *into++ = (*outof >> 16) & 0xffL; - *into++ = (*outof >> 8) & 0xffL; - *into++ = *outof++ & 0xffL; - *into++ = (*outof >> 24) & 0xffL; - *into++ = (*outof >> 16) & 0xffL; - *into++ = (*outof >> 8) & 0xffL; - *into = *outof & 0xffL; + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into++ = (unsigned char)(*outof++ & 0xffL); + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into = (unsigned char)(*outof & 0xffL); return; } diff --git a/rfb/encodings.cxx b/rfb/encodings.cxx index d3b0ccb9..6aa81c4f 100644 --- a/rfb/encodings.cxx +++ b/rfb/encodings.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/encodings.h b/rfb/encodings.h index 20be0ae0..51f6f1ec 100644 --- a/rfb/encodings.h +++ b/rfb/encodings.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/hextileConstants.h b/rfb/hextileConstants.h index 272afbba..b8713cb6 100644 --- a/rfb/hextileConstants.h +++ b/rfb/hextileConstants.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/hextileDecode.h b/rfb/hextileDecode.h index 0c5559a4..77befc7d 100644 --- a/rfb/hextileDecode.h +++ b/rfb/hextileDecode.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -52,11 +52,11 @@ void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) { - t.br.y = vncmin(r.br.y, t.tl.y + 16); + t.br.y = __rfbmin(r.br.y, t.tl.y + 16); for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) { - t.br.x = vncmin(r.br.x, t.tl.x + 16); + t.br.x = __rfbmin(r.br.x, t.tl.x + 16); int tileType = is->readU8(); diff --git a/rfb/hextileEncode.h b/rfb/hextileEncode.h index 27c7e01f..9f8bd558 100644 --- a/rfb/hextileEncode.h +++ b/rfb/hextileEncode.h @@ -1,6 +1,6 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2005 Constantin Kaplinsky. 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 @@ -61,11 +61,11 @@ void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) { - t.br.y = vncmin(r.br.y, t.tl.y + 16); + t.br.y = __rfbmin(r.br.y, t.tl.y + 16); for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) { - t.br.x = vncmin(r.br.x, t.tl.x + 16); + t.br.x = __rfbmin(r.br.x, t.tl.x + 16); GET_IMAGE_INTO_BUF(t,buf); diff --git a/rfb/hextileEncodeBetter.h b/rfb/hextileEncodeBetter.h index 59df102a..2b6b160a 100644 --- a/rfb/hextileEncodeBetter.h +++ b/rfb/hextileEncodeBetter.h @@ -1,6 +1,6 @@ /* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2005 Constantin Kaplinsky. 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 @@ -294,11 +294,11 @@ void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) { - t.br.y = vncmin(r.br.y, t.tl.y + 16); + t.br.y = __rfbmin(r.br.y, t.tl.y + 16); for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) { - t.br.x = vncmin(r.br.x, t.tl.x + 16); + t.br.x = __rfbmin(r.br.x, t.tl.x + 16); GET_IMAGE_INTO_BUF(t,buf); diff --git a/rfb/msgTypes.h b/rfb/msgTypes.h index 2b05c75b..f6f8d5cf 100644 --- a/rfb/msgTypes.h +++ b/rfb/msgTypes.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/rfb.dsp b/rfb/rfb.dsp index 4e18c7bc..315236d8 100644 --- a/rfb/rfb.dsp +++ b/rfb/rfb.dsp @@ -202,6 +202,10 @@ SOURCE=.\HTTPServer.cxx # End Source File
# Begin Source File
+SOURCE=.\KeyRemapper.cxx
+# End Source File
+# Begin Source File
+
SOURCE=.\Logger.cxx
# End Source File
# Begin Source File
@@ -218,6 +222,10 @@ SOURCE=.\LogWriter.cxx # End Source File
# Begin Source File
+SOURCE=.\Password.cxx
+# End Source File
+# Begin Source File
+
SOURCE=.\PixelBuffer.cxx
# End Source File
# Begin Source File
@@ -298,10 +306,6 @@ SOURCE=.\SSecurityVncAuth.cxx # End Source File
# Begin Source File
-SOURCE=.\win32\Threading_win32.cxx
-# End Source File
-# Begin Source File
-
SOURCE=.\TightDecoder.cxx
# ADD CPP /I "../jpeg"
# End Source File
@@ -332,10 +336,6 @@ SOURCE=.\util.cxx # End Source File
# Begin Source File
-SOURCE=.\vncAuth.cxx
-# End Source File
-# Begin Source File
-
SOURCE=.\VNCSConnectionST.cxx
# End Source File
# Begin Source File
@@ -496,6 +496,14 @@ SOURCE=.\ImageGetter.h # End Source File
# Begin Source File
+SOURCE=.\InputHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\KeyRemapper.h
+# End Source File
+# Begin Source File
+
SOURCE=.\keysymdef.h
# End Source File
# Begin Source File
@@ -528,6 +536,10 @@ SOURCE=.\msvcwarning.h # End Source File
# Begin Source File
+SOURCE=.\Password.h
+# End Source File
+# Begin Source File
+
SOURCE=.\Pixel.h
# End Source File
# Begin Source File
@@ -640,10 +652,6 @@ SOURCE=.\Threading.h # End Source File
# Begin Source File
-SOURCE=.\win32\Threading_win32.h
-# End Source File
-# Begin Source File
-
SOURCE=.\tightDecode.h
# End Source File
# Begin Source File
@@ -696,14 +704,6 @@ SOURCE=.\util.h # End Source File
# Begin Source File
-SOURCE=.\win32\util_win32.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\vncAuth.h
-# End Source File
-# Begin Source File
-
SOURCE=.\VNCSConnectionST.h
# End Source File
# Begin Source File
diff --git a/rfb/rreDecode.h b/rfb/rreDecode.h index 9f69ceeb..1f5bdf8b 100644 --- a/rfb/rreDecode.h +++ b/rfb/rreDecode.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/rreEncode.h b/rfb/rreEncode.h index 4877a12d..3f834877 100644 --- a/rfb/rreEncode.h +++ b/rfb/rreEncode.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/secTypes.cxx b/rfb/secTypes.cxx index c850684a..830d8444 100644 --- a/rfb/secTypes.cxx +++ b/rfb/secTypes.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -29,6 +29,8 @@ int rfb::secTypeNum(const char* name) if (strcasecmp(name, "Tight") == 0) return secTypeTight; if (strcasecmp(name, "RA2") == 0) return secTypeRA2; if (strcasecmp(name, "RA2ne") == 0) return secTypeRA2ne; + if (strcasecmp(name, "SSPI") == 0) return secTypeSSPI; + if (strcasecmp(name, "SSPIne") == 0) return secTypeSSPIne; return secTypeInvalid; } @@ -40,6 +42,8 @@ const char* rfb::secTypeName(int num) case secTypeTight: return "Tight"; case secTypeRA2: return "RA2"; case secTypeRA2ne: return "RA2ne"; + case secTypeSSPI: return "SSPI"; + case secTypeSSPIne: return "SSPIne"; default: return "[unknown secType]"; } } @@ -47,8 +51,11 @@ const char* rfb::secTypeName(int num) bool rfb::secTypeEncrypts(int num) { switch (num) { - case secTypeRA2: return true; - default: return false; + case secTypeRA2: + case secTypeSSPI: + return true; + default: + return false; } } diff --git a/rfb/secTypes.h b/rfb/secTypes.h index f0b326e9..3cf783bd 100644 --- a/rfb/secTypes.h +++ b/rfb/secTypes.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -32,6 +32,9 @@ namespace rfb { const int secTypeRA2 = 5; const int secTypeRA2ne = 6; + const int secTypeSSPI = 7; + const int secTypeSSPIne = 8; + const int secTypeTight = 16; const int secTypeUltra = 17; const int secTypeTLS = 18; diff --git a/rfb/transInitTempl.h b/rfb/transInitTempl.h index 2658f9f0..464cfdfc 100644 --- a/rfb/transInitTempl.h +++ b/rfb/transInitTempl.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/transTempl.h b/rfb/transTempl.h index 907b8396..09dc7f95 100644 --- a/rfb/transTempl.h +++ b/rfb/transTempl.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 diff --git a/rfb/util.cxx b/rfb/util.cxx index 94aa6327..57454324 100644 --- a/rfb/util.cxx +++ b/rfb/util.cxx @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -23,13 +23,7 @@ #ifndef __RFB_UTIL_H__ #define __RFB_UTIL_H__ -#ifndef vncmin -#define vncmin(a,b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef vncmax -#define vncmax(a,b) (((a) > (b)) ? (a) : (b)) -#endif - +#include <limits.h> #include <string.h> namespace rfb { @@ -71,8 +65,36 @@ namespace rfb { // Copies src to dest, up to specified length-1, and guarantees termination void strCopy(char* dest, const char* src, int destlen); + + + // HELPER functions for timeout handling + + // soonestTimeout() is a function to help work out the soonest of several + // timeouts. + inline void soonestTimeout(int* timeout, int newTimeout) { + if (newTimeout && (!*timeout || newTimeout < *timeout)) + *timeout = newTimeout; + } + + // secsToMillis() turns seconds into milliseconds, capping the value so it + // can't wrap round and become -ve + inline int secsToMillis(int secs) { + return (secs < 0 || secs > (INT_MAX/1000) ? INT_MAX : secs * 1000); + } } +// Some platforms (e.g. Windows) include max() and min() macros in their +// standard headers, but they are also standard C++ template functions, so some +// C++ headers will undefine them. So we steer clear of the names min and max +// and define __rfbmin and __rfbmax instead. + +#ifndef __rfbmax +#define __rfbmax(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef __rfbmin +#define __rfbmin(a,b) (((a) < (b)) ? (a) : (b)) +#endif + // Declare strcasecmp() and/or strncasecmp() if absent on this system. #if !defined(WIN32) && !defined(HAVE_STRCASECMP) @@ -86,10 +108,4 @@ extern "C" { } #endif -#endif // __RFB_UTIL_H__ - -// -=- PLATFORM SPECIFIC UTILITY FUNCTIONS/IMPLEMENTATIONS -#ifdef WIN32 -#include "win32/util_win32.h" #endif - diff --git a/rfb/vncAuth.cxx b/rfb/vncAuth.cxx deleted file mode 100644 index 6bd6a620..00000000 --- a/rfb/vncAuth.cxx +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. 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. - */ -// -// vncAuth -// -// XXX not thread-safe, because d3des isn't - do we need to worry about this? -// - -#include <string.h> -extern "C" { -#include <rfb/d3des.h> -} -#include <rfb/vncAuth.h> - -using namespace rfb; - -void rfb::vncAuthEncryptChallenge(rdr::U8* challenge, const char* passwd) -{ - unsigned char key[8] = { 0, }; - int len = strlen(passwd); - if (len > 8) len = 8; - for (int i = 0; i < len; i++) - key[i] = passwd[i]; - - deskey(key, EN0); - - for (int j = 0; j < vncAuthChallengeSize; j += 8) - des(challenge+j, challenge+j); -} - -static unsigned char obfuscationKey[] = {23,82,107,6,35,78,88,7}; - -void rfb::vncAuthObfuscatePasswd(char* passwd) -{ - for (int i = strlen(passwd); i < 8; i++) - passwd[i] = 0; - deskey(obfuscationKey, EN0); - des((unsigned char*)passwd, (unsigned char*)passwd); -} - -void rfb::vncAuthUnobfuscatePasswd(char* passwd) -{ - deskey(obfuscationKey, DE1); - des((unsigned char*)passwd, (unsigned char*)passwd); - passwd[8] = 0; -} diff --git a/rfb/win32/Threading_win32.cxx b/rfb/win32/Threading_win32.cxx deleted file mode 100644 index 28cfdb7e..00000000 --- a/rfb/win32/Threading_win32.cxx +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. 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. - */ - -// -=- Threading_win32.cxx -// Win32 Threading interface implementation - -#include <malloc.h> - -#include <rdr/Exception.h> -#include <rfb/LogWriter.h> -#include <rfb/win32/Threading_win32.h> -#include <rfb/util.h> - -using namespace rfb; - -static LogWriter vlog("Threading"); - -static DWORD threadStorage = TlsAlloc(); - - -inline logAction(Thread* t, const char* action) { - vlog.debug("%-16.16s %s(%lx)", action, t->getName(), t); -} - -inline logError(Thread* t, const char* err) { - vlog.error("%-16.16s %s(%lx):%s", "failed", t->getName(), t, err); -} - - -DWORD WINAPI -Thread::threadProc(LPVOID lpParameter) { - Thread* thread = (Thread*) lpParameter; - TlsSetValue(threadStorage, thread); - logAction(thread, "started"); - try { - thread->run(); - logAction(thread, "stopped"); - } catch (rdr::Exception& e) { - logError(thread, e.str()); - } - bool deleteThread = false; - { - Lock l(thread->mutex); - thread->state = ThreadStopped; - thread->sig->signal(); - deleteThread = thread->deleteAfterRun; - } - if (deleteThread) - delete thread; - return 0; -} - -Thread::Thread(const char* name_) : sig(0), deleteAfterRun(false) { - sig = new Condition(mutex); - cond_event = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!name_) - name_ = "Unnamed"; - name = strDup(name_); - thread = CreateThread(NULL, 0, threadProc, this, CREATE_SUSPENDED, &thread_id); - state = ThreadCreated; - logAction(this, "created"); -} - -Thread::Thread(HANDLE thread_, DWORD thread_id_) : sig(0), deleteAfterRun(false), thread(thread_), thread_id(thread_id_) { - sig = new Condition(mutex); - cond_event = CreateEvent(NULL, TRUE, FALSE, NULL); - name = strDup("Native"); - state = ThreadNative; - logAction(this, "created"); -} - -Thread::~Thread() { - logAction(this, "destroying"); - if (!deleteAfterRun) this->join(); - if (sig) - delete sig; - if (cond_event) - CloseHandle(cond_event); - logAction(this, "destroyed"); - strFree(name); -} - -void -Thread::run() { -} - -void -Thread::start() { - Lock l(mutex); - if (state == ThreadCreated) { - state = ThreadStarted; - sig->signal(); - ResumeThread(thread); - } -} - -Thread* -Thread::join() { - if (deleteAfterRun) - throw rdr::Exception("attempt to join() with deleteAfterRun thread"); - Lock l(mutex); - if (!thread) { - logAction(this, "already joined"); - } else { - logAction(this, "joining"); - while (state == ThreadStarted) { - sig->wait(); - logAction(this, "checking"); - } - CloseHandle(thread); - thread = 0; - logAction(this, "joined"); - } - return this; -} - -const char* -Thread::getName() const { - return name; -} - -ThreadState -Thread::getState() const { - return state; -} - -unsigned long -Thread::getThreadId() const { - return thread_id; -} - -Thread* -Thread::self() { - Thread* thread = (Thread*) TlsGetValue(threadStorage); - if (!thread) { - thread = new Thread(GetCurrentThread(), GetCurrentThreadId()); - TlsSetValue(threadStorage, thread); - } - return thread; -}
\ No newline at end of file diff --git a/rfb/win32/Threading_win32.h b/rfb/win32/Threading_win32.h deleted file mode 100644 index e95e0f73..00000000 --- a/rfb/win32/Threading_win32.h +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. 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. - */ - -// -=- Threading_win32.h -// Win32 Threading interface implementation - -#ifndef __RFB_THREADING_IMPL_WIN32 -#define __RFB_THREADING_IMPL_WIN32 - -#define __RFB_THREADING_IMPL WIN32 - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -#include <stdio.h> - -namespace rfb { - - class Mutex { - public: - Mutex() { - InitializeCriticalSection(&crit); - } - ~Mutex() { - DeleteCriticalSection(&crit); - } - friend class Lock; - friend class Condition; - protected: - void enter() {EnterCriticalSection(&crit);} - void exit() {LeaveCriticalSection(&crit);} - CRITICAL_SECTION crit; - }; - - class Lock { - public: - Lock(Mutex& m) : mutex(m) {m.enter();} - ~Lock() {mutex.exit();} - protected: - Mutex& mutex; - }; - - enum ThreadState {ThreadCreated, ThreadStarted, ThreadStopped, ThreadNative}; - - class Thread { - public: - Thread(const char* name_=0); - virtual ~Thread(); - - virtual void run(); - - virtual void start(); - virtual Thread* join(); - - const char* getName() const; - ThreadState getState() const; - - // Determines whether the thread should delete itself when run() returns - // If you set this, you must NEVER call join()! - void setDeleteAfterRun() {deleteAfterRun = true;}; - - unsigned long getThreadId() const; - - static Thread* self(); - - friend class Condition; - - protected: - Thread(HANDLE thread_, DWORD thread_id_); - static DWORD WINAPI threadProc(LPVOID lpParameter); - - HANDLE thread; - DWORD thread_id; - char* name; - ThreadState state; - Condition* sig; - Mutex mutex; - - HANDLE cond_event; - Thread* cond_next; - - bool deleteAfterRun; - }; - - class Condition { - public: - Condition(Mutex& m) : mutex(m), waiting(0) { - } - ~Condition() { - } - void signal() { - Lock l(cond_lock); - if (waiting) { - SetEvent(waiting->cond_event); - waiting = waiting->cond_next; - } - } - // - MUST hold "mutex" to call wait() - // WIN32: if processMsg is true then wait will continue - // to process messages in the thread's queue. - // Avoid using this unless you have to! - void wait(bool processMsgs=false) { - Thread* self = Thread::self(); - ResetEvent(self->cond_event); - { Lock l(cond_lock); - self->cond_next = waiting; - waiting = self; - } - mutex.exit(); - if (processMsgs) { - while (1) { - DWORD result = MsgWaitForMultipleObjects(1, &self->cond_event, FALSE, INFINITE, QS_ALLINPUT); - if (result == WAIT_OBJECT_0) - break; - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { - DispatchMessage(&msg); - } - } - } else { - WaitForSingleObject(self->cond_event, INFINITE); - } - mutex.enter(); - } - - protected: - Mutex& mutex; - Mutex cond_lock; - Thread* waiting; - }; - -}; - -#endif // __RFB_THREADING_IMPL diff --git a/rfb/win32/util_win32.h b/rfb/win32/util_win32.h deleted file mode 100644 index 4bde5ec7..00000000 --- a/rfb/win32/util_win32.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. 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. - */ - -// -// util_win32.h - miscellaneous useful bits for Win32 only -// - -#ifndef __RFB_UTIL_WIN32_H__ -#define __RFB_UTIL_WIN32_H__ - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -// *** #include <iostream.h> - -#include <rfb/LogWriter.h> -#include <rfb/Exception.h> - -namespace rfb { - - // WIN32-ONLY PROFILING CODE - // - // CpuTime and CpuTimer provide a simple way to profile particular - // sections of code - // - // Use one CpuTime object per task to be profiled. CpuTime instances - // maintain a cumulative total of time spent in user and kernel space - // by threads. - // When a CpuTime object is created, a label must be specified to - // identify the task being profiled. - // When the object is destroyed, it will print debugging information - // containing the user and kernel times accumulated. - // - // Place a CpuTimer object in each section of code which is to be - // profiled. When the object is created, it snapshots the current - // kernel and user times and stores them. These are used when the - // object is destroyed to establish how much time has elapsed in the - // intervening period. The accumulated time is then added to the - // associated CpuTime object. - // - // This code works only on platforms providing __int64 - - class CpuTime { - public: - CpuTime(const char *name) - : timer_name(strDup(name)), - kernel_time(0), user_time(0), max_user_time(0), iterations(0) {} - ~CpuTime() { - g_log_writer.info("timer %s : %I64ums (krnl), %I64ums (user), %I64uus (user-max) (%I64u its)\n", - timer_name, kernel_time/10000, user_time/10000, max_user_time/10, - iterations); - delete [] timer_name; - } - static LogWriter g_log_writer; - char* timer_name; - __int64 kernel_time; - __int64 user_time; - __int64 iterations; - __int64 max_user_time; - }; - - class CpuTimer { - public: - inline CpuTimer(CpuTime &ct) : cputime(ct) { - FILETIME create_time, end_time; - if (!GetThreadTimes(GetCurrentThread(), - &create_time, &end_time, - (LPFILETIME)&start_kernel_time, - (LPFILETIME)&start_user_time)) { - throw rdr::SystemException("rfb::CpuTimer failed to initialise", GetLastError()); - } - } - inline ~CpuTimer() { - FILETIME create_time, end_time; - __int64 end_kernel_time, end_user_time; - if (!GetThreadTimes(GetCurrentThread(), - &create_time, &end_time, - (LPFILETIME)&end_kernel_time, - (LPFILETIME)&end_user_time)) { - throw rdr::SystemException("rfb::CpuTimer destructor failed", GetLastError()); - } - cputime.kernel_time += end_kernel_time - start_kernel_time; - cputime.user_time += end_user_time - start_user_time; - if (end_user_time - start_user_time > cputime.max_user_time) { - cputime.max_user_time = end_user_time - start_user_time; - } - cputime.iterations++; - } - private: - CpuTime& cputime; - __int64 start_kernel_time; - __int64 start_user_time; - }; - -}; - -#endif // __RFB_UTIL_WIN32_H__ diff --git a/rfb/zrleDecode.h b/rfb/zrleDecode.h index e1f85f77..15d27900 100644 --- a/rfb/zrleDecode.h +++ b/rfb/zrleDecode.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -61,11 +61,11 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is, for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) { - t.br.y = vncmin(r.br.y, t.tl.y + 64); + t.br.y = __rfbmin(r.br.y, t.tl.y + 64); for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) { - t.br.x = vncmin(r.br.x, t.tl.x + 64); + t.br.x = __rfbmin(r.br.x, t.tl.x + 64); int mode = zis->readU8(); bool rle = mode & 128; diff --git a/rfb/zrleEncode.h b/rfb/zrleEncode.h index 42505a31..9b7263b3 100644 --- a/rfb/zrleEncode.h +++ b/rfb/zrleEncode.h @@ -1,5 +1,5 @@ -/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. - * +/* Copyright (C) 2002-2005 RealVNC Ltd. 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 @@ -130,7 +130,7 @@ bool ZRLE_ENCODE (const Rect& r, rdr::OutStream* os, for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) { - t.br.y = vncmin(r.br.y, t.tl.y + 64); + t.br.y = __rfbmin(r.br.y, t.tl.y + 64); if (os->length() + worstCaseLine > maxLen) { if (t.tl.y == r.tl.y) @@ -143,7 +143,7 @@ bool ZRLE_ENCODE (const Rect& r, rdr::OutStream* os, for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) { - t.br.x = vncmin(r.br.x, t.tl.x + 64); + t.br.x = __rfbmin(r.br.x, t.tl.x + 64); GET_IMAGE_INTO_BUF(t,buf); |