aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2018-12-10 21:16:07 +0100
committerPierre Ossman <ossman@cendio.se>2018-12-10 21:16:07 +0100
commitd8bbbeb3b37c713a72a113f7ef78741e15cc4a4d (patch)
tree7d8076302c65cf6ffbd2ccbf9d581476412be36b
parent139b96741004adc92032a93b8ef6e5927a618f6d (diff)
parentc3826bb2fcb60efa495b54dd66296bc55ce28ecf (diff)
downloadtigervnc-d8bbbeb3b37c713a72a113f7ef78741e15cc4a4d.tar.gz
tigervnc-d8bbbeb3b37c713a72a113f7ef78741e15cc4a4d.zip
Merge branch 'connparams' of https://github.com/CendioOssman/tigervnc
-rw-r--r--common/rfb/CConnection.cxx307
-rw-r--r--common/rfb/CConnection.h70
-rw-r--r--common/rfb/CMakeLists.txt3
-rw-r--r--common/rfb/CMsgHandler.cxx33
-rw-r--r--common/rfb/CMsgHandler.h14
-rw-r--r--common/rfb/CMsgReader.cxx22
-rw-r--r--common/rfb/CMsgWriter.cxx105
-rw-r--r--common/rfb/CMsgWriter.h11
-rw-r--r--common/rfb/CSecurityTLS.cxx1
-rw-r--r--common/rfb/CSecurityTLS.h1
-rw-r--r--common/rfb/ClientParams.cxx178
-rw-r--r--common/rfb/ClientParams.h (renamed from common/rfb/ConnParams.h)55
-rw-r--r--common/rfb/ConnParams.cxx200
-rw-r--r--common/rfb/CopyRectDecoder.cxx8
-rw-r--r--common/rfb/CopyRectDecoder.h6
-rw-r--r--common/rfb/DecodeManager.cxx14
-rw-r--r--common/rfb/DecodeManager.h2
-rw-r--r--common/rfb/Decoder.cxx4
-rw-r--r--common/rfb/Decoder.h10
-rw-r--r--common/rfb/EncodeManager.cxx42
-rw-r--r--common/rfb/HextileDecoder.cxx10
-rw-r--r--common/rfb/HextileDecoder.h4
-rw-r--r--common/rfb/HextileEncoder.cxx2
-rw-r--r--common/rfb/JpegCompressor.cxx2
-rw-r--r--common/rfb/Logger.cxx11
-rw-r--r--common/rfb/RREDecoder.cxx10
-rw-r--r--common/rfb/RREDecoder.h4
-rw-r--r--common/rfb/RREEncoder.cxx2
-rw-r--r--common/rfb/RawDecoder.cxx12
-rw-r--r--common/rfb/RawDecoder.h4
-rw-r--r--common/rfb/SConnection.cxx70
-rw-r--r--common/rfb/SMsgHandler.cxx30
-rw-r--r--common/rfb/SMsgHandler.h8
-rw-r--r--common/rfb/SMsgWriter.cxx275
-rw-r--r--common/rfb/SMsgWriter.h39
-rw-r--r--common/rfb/ServerParams.cxx84
-rw-r--r--common/rfb/ServerParams.h89
-rw-r--r--common/rfb/TightDecoder.cxx24
-rw-r--r--common/rfb/TightDecoder.h6
-rw-r--r--common/rfb/TightEncoder.cxx3
-rw-r--r--common/rfb/TightJPEGEncoder.cxx8
-rw-r--r--common/rfb/UpdateTracker.cxx17
-rw-r--r--common/rfb/UpdateTracker.h5
-rw-r--r--common/rfb/VNCSConnectionST.cxx114
-rw-r--r--common/rfb/VNCServerST.cxx15
-rw-r--r--common/rfb/ZRLEDecoder.cxx8
-rw-r--r--common/rfb/ZRLEDecoder.h4
-rw-r--r--common/rfb/ZRLEEncoder.cxx3
-rw-r--r--tests/decperf.cxx10
-rw-r--r--tests/encperf.cxx14
-rw-r--r--unix/x0vncserver/XDesktop.cxx19
-rw-r--r--vncviewer/CConn.cxx265
-rw-r--r--vncviewer/CConn.h23
-rw-r--r--vncviewer/DesktopWindow.cxx28
-rw-r--r--vncviewer/Viewport.cxx10
55 files changed, 1234 insertions, 1084 deletions
diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx
index fb953775..3ea217fa 100644
--- a/common/rfb/CConnection.cxx
+++ b/common/rfb/CConnection.cxx
@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
+#include <assert.h>
#include <stdio.h>
#include <string.h>
@@ -24,6 +25,7 @@
#include <rfb/CMsgReader.h>
#include <rfb/CMsgWriter.h>
#include <rfb/CSecurity.h>
+#include <rfb/Decoder.h>
#include <rfb/Security.h>
#include <rfb/SecurityClient.h>
#include <rfb/CConnection.h>
@@ -39,9 +41,17 @@ using namespace rfb;
static LogWriter vlog("CConnection");
CConnection::CConnection()
- : csecurity(0), is(0), os(0), reader_(0), writer_(0),
+ : csecurity(0),
+ supportsLocalCursor(false), supportsDesktopResize(false),
+ supportsLEDState(false),
+ is(0), os(0), reader_(0), writer_(0),
shared(false),
state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
+ pendingPFChange(false), preferredEncoding(encodingTight),
+ compressLevel(2), qualityLevel(-1),
+ formatChange(false), encodingChange(false),
+ firstUpdate(true), pendingUpdate(false), continuousUpdates(false),
+ forceNonincremental(true),
framebuffer(NULL), decoder(this)
{
}
@@ -67,6 +77,11 @@ void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
{
decoder.flush();
+ if (fb) {
+ assert(fb->width() == server.width());
+ assert(fb->height() == server.height());
+ }
+
if ((framebuffer != NULL) && (fb != NULL)) {
Rect rect;
@@ -128,35 +143,51 @@ void CConnection::processMsg()
void CConnection::processVersionMsg()
{
+ char verStr[13];
+ int majorVersion;
+ int minorVersion;
+
vlog.debug("reading protocol version");
- bool done;
- if (!cp.readVersion(is, &done)) {
+
+ if (!is->checkNoWait(12))
+ return;
+
+ is->readBytes(verStr, 12);
+ verStr[12] = '\0';
+
+ if (sscanf(verStr, "RFB %03d.%03d\n",
+ &majorVersion, &minorVersion) != 2) {
state_ = RFBSTATE_INVALID;
throw Exception("reading version failed: not an RFB server?");
}
- if (!done) return;
+
+ server.setVersion(majorVersion, minorVersion);
vlog.info("Server supports RFB protocol version %d.%d",
- cp.majorVersion, cp.minorVersion);
+ server.majorVersion, server.minorVersion);
// The only official RFB protocol versions are currently 3.3, 3.7 and 3.8
- if (cp.beforeVersion(3,3)) {
+ if (server.beforeVersion(3,3)) {
vlog.error("Server gave unsupported RFB protocol version %d.%d",
- cp.majorVersion, cp.minorVersion);
+ server.majorVersion, server.minorVersion);
state_ = RFBSTATE_INVALID;
throw Exception("Server gave unsupported RFB protocol version %d.%d",
- cp.majorVersion, cp.minorVersion);
- } else if (useProtocol3_3 || cp.beforeVersion(3,7)) {
- cp.setVersion(3,3);
- } else if (cp.afterVersion(3,8)) {
- cp.setVersion(3,8);
+ server.majorVersion, server.minorVersion);
+ } else if (useProtocol3_3 || server.beforeVersion(3,7)) {
+ server.setVersion(3,3);
+ } else if (server.afterVersion(3,8)) {
+ server.setVersion(3,8);
}
- cp.writeVersion(os);
+ sprintf(verStr, "RFB %03d.%03d\n",
+ server.majorVersion, server.minorVersion);
+ os->writeBytes(verStr, 12);
+ os->flush();
+
state_ = RFBSTATE_SECURITY_TYPES;
vlog.info("Using RFB protocol version %d.%d",
- cp.majorVersion, cp.minorVersion);
+ server.majorVersion, server.minorVersion);
}
@@ -169,7 +200,7 @@ void CConnection::processSecurityTypesMsg()
std::list<rdr::U8> secTypes;
secTypes = security.GetEnabledSecTypes();
- if (cp.isVersion(3,3)) {
+ if (server.isVersion(3,3)) {
// legacy 3.3 server may only offer "vnc authentication" or "none"
@@ -252,7 +283,7 @@ void CConnection::processSecurityResultMsg()
{
vlog.debug("processing security result message");
int result;
- if (cp.beforeVersion(3,8) && csecurity->getType() == secTypeNone) {
+ if (server.beforeVersion(3,8) && csecurity->getType() == secTypeNone) {
result = secResultOK;
} else {
if (!is->checkNoWait(1)) return;
@@ -272,7 +303,7 @@ void CConnection::processSecurityResultMsg()
throw Exception("Unknown security result from server");
}
state_ = RFBSTATE_INVALID;
- if (cp.beforeVersion(3,8))
+ if (server.beforeVersion(3,8))
throw AuthFailureException();
CharArray reason(is->readString());
throw AuthFailureException(reason.buf);
@@ -296,7 +327,7 @@ void CConnection::securityCompleted()
{
state_ = RFBSTATE_INITIALISATION;
reader_ = new CMsgReader(this, is);
- writer_ = new CMsgWriter(&cp, os);
+ writer_ = new CMsgWriter(&server, os);
vlog.debug("Authentication success!");
authSuccess();
writer_->writeClientInit(shared);
@@ -307,6 +338,16 @@ void CConnection::setDesktopSize(int w, int h)
decoder.flush();
CMsgHandler::setDesktopSize(w,h);
+
+ if (continuousUpdates)
+ writer()->writeEnableContinuousUpdates(true, 0, 0,
+ server.width(),
+ server.height());
+
+ resizeFramebuffer();
+ assert(framebuffer != NULL);
+ assert(framebuffer->width() == server.width());
+ assert(framebuffer->height() == server.height());
}
void CConnection::setExtendedDesktopSize(unsigned reason,
@@ -317,6 +358,59 @@ void CConnection::setExtendedDesktopSize(unsigned reason,
decoder.flush();
CMsgHandler::setExtendedDesktopSize(reason, result, w, h, layout);
+
+ if (continuousUpdates)
+ writer()->writeEnableContinuousUpdates(true, 0, 0,
+ server.width(),
+ server.height());
+
+ resizeFramebuffer();
+ assert(framebuffer != NULL);
+ assert(framebuffer->width() == server.width());
+ assert(framebuffer->height() == server.height());
+}
+
+void CConnection::endOfContinuousUpdates()
+{
+ CMsgHandler::endOfContinuousUpdates();
+
+ // We've gotten the marker for a format change, so make the pending
+ // one active
+ if (pendingPFChange) {
+ server.setPF(pendingPF);
+ pendingPFChange = false;
+
+ // We might have another change pending
+ if (formatChange)
+ requestNewUpdate();
+ }
+}
+
+void CConnection::serverInit(int width, int height,
+ const PixelFormat& pf,
+ const char* name)
+{
+ CMsgHandler::serverInit(width, height, pf, name);
+
+ state_ = RFBSTATE_NORMAL;
+ vlog.debug("initialisation done");
+
+ initDone();
+ assert(framebuffer != NULL);
+ assert(framebuffer->width() == server.width());
+ assert(framebuffer->height() == server.height());
+
+ // We want to make sure we call SetEncodings at least once
+ encodingChange = true;
+
+ requestNewUpdate();
+
+ // This initial update request is a bit of a corner case, so we need
+ // to help out setting the correct format here.
+ if (pendingPFChange) {
+ server.setPF(pendingPF);
+ pendingPFChange = false;
+ }
}
void CConnection::readAndDecodeRect(const Rect& r, int encoding,
@@ -329,6 +423,13 @@ void CConnection::readAndDecodeRect(const Rect& r, int encoding,
void CConnection::framebufferUpdateStart()
{
CMsgHandler::framebufferUpdateStart();
+
+ assert(framebuffer != NULL);
+
+ // Note: This might not be true if continuous updates are supported
+ pendingUpdate = false;
+
+ requestNewUpdate();
}
void CConnection::framebufferUpdateEnd()
@@ -336,6 +437,25 @@ void CConnection::framebufferUpdateEnd()
decoder.flush();
CMsgHandler::framebufferUpdateEnd();
+
+ // A format change has been scheduled and we are now past the update
+ // with the old format. Time to active the new one.
+ if (pendingPFChange && !continuousUpdates) {
+ server.setPF(pendingPF);
+ pendingPFChange = false;
+ }
+
+ if (firstUpdate) {
+ if (server.supportsContinuousUpdates) {
+ vlog.info("Enabling continuous updates");
+ continuousUpdates = true;
+ writer()->writeEnableContinuousUpdates(true, 0, 0,
+ server.width(),
+ server.height());
+ }
+
+ firstUpdate = false;
+ }
}
void CConnection::dataRect(const Rect& r, int encoding)
@@ -347,10 +467,64 @@ void CConnection::authSuccess()
{
}
-void CConnection::serverInit()
+void CConnection::initDone()
{
- state_ = RFBSTATE_NORMAL;
- vlog.debug("initialisation done");
+}
+
+void CConnection::resizeFramebuffer()
+{
+ assert(false);
+}
+
+void CConnection::refreshFramebuffer()
+{
+ forceNonincremental = true;
+
+ // Without continuous updates we have to make sure we only have a
+ // single update in flight, so we'll have to wait to do the refresh
+ if (continuousUpdates)
+ requestNewUpdate();
+}
+
+void CConnection::setPreferredEncoding(int encoding)
+{
+ if (preferredEncoding == encoding)
+ return;
+
+ preferredEncoding = encoding;
+ encodingChange = true;
+}
+
+int CConnection::getPreferredEncoding()
+{
+ return preferredEncoding;
+}
+
+void CConnection::setCompressLevel(int level)
+{
+ if (compressLevel == level)
+ return;
+
+ compressLevel = level;
+ encodingChange = true;
+}
+
+void CConnection::setQualityLevel(int level)
+{
+ if (qualityLevel == level)
+ return;
+
+ qualityLevel = level;
+ encodingChange = true;
+}
+
+void CConnection::setPF(const PixelFormat& pf)
+{
+ if (server.pf().equal(pf) && !formatChange)
+ return;
+
+ nextPF = pf;
+ formatChange = true;
}
void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
@@ -365,3 +539,94 @@ void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
writer()->writeFence(flags, len, data);
}
+
+// requestNewUpdate() requests an update from the server, having set the
+// format and encoding appropriately.
+void CConnection::requestNewUpdate()
+{
+ if (formatChange && !pendingPFChange) {
+ /* Catch incorrect requestNewUpdate calls */
+ assert(!pendingUpdate || continuousUpdates);
+
+ // We have to make sure we switch the internal format at a safe
+ // time. For continuous updates we temporarily disable updates and
+ // look for a EndOfContinuousUpdates message to see when to switch.
+ // For classical updates we just got a new update right before this
+ // function was called, so we need to make sure we finish that
+ // update before we can switch.
+
+ pendingPFChange = true;
+ pendingPF = nextPF;
+
+ if (continuousUpdates)
+ writer()->writeEnableContinuousUpdates(false, 0, 0, 0, 0);
+
+ writer()->writeSetPixelFormat(pendingPF);
+
+ if (continuousUpdates)
+ writer()->writeEnableContinuousUpdates(true, 0, 0,
+ server.width(),
+ server.height());
+
+ formatChange = false;
+ }
+
+ if (encodingChange) {
+ updateEncodings();
+ encodingChange = false;
+ }
+
+ if (forceNonincremental || !continuousUpdates) {
+ pendingUpdate = true;
+ writer()->writeFramebufferUpdateRequest(Rect(0, 0,
+ server.width(),
+ server.height()),
+ !forceNonincremental);
+ }
+
+ forceNonincremental = false;
+}
+
+// Ask for encodings based on which decoders are supported. Assumes higher
+// encoding numbers are more desirable.
+
+void CConnection::updateEncodings()
+{
+ std::list<rdr::U32> encodings;
+
+ if (supportsLocalCursor) {
+ encodings.push_back(pseudoEncodingCursorWithAlpha);
+ encodings.push_back(pseudoEncodingCursor);
+ encodings.push_back(pseudoEncodingXCursor);
+ }
+ if (supportsDesktopResize) {
+ encodings.push_back(pseudoEncodingDesktopSize);
+ encodings.push_back(pseudoEncodingExtendedDesktopSize);
+ }
+ if (supportsLEDState)
+ encodings.push_back(pseudoEncodingLEDState);
+
+ encodings.push_back(pseudoEncodingDesktopName);
+ encodings.push_back(pseudoEncodingLastRect);
+ encodings.push_back(pseudoEncodingContinuousUpdates);
+ encodings.push_back(pseudoEncodingFence);
+ encodings.push_back(pseudoEncodingQEMUKeyEvent);
+
+ if (Decoder::supported(preferredEncoding)) {
+ encodings.push_back(preferredEncoding);
+ }
+
+ encodings.push_back(encodingCopyRect);
+
+ for (int i = encodingMax; i >= 0; i--) {
+ if ((i != preferredEncoding) && Decoder::supported(i))
+ encodings.push_back(i);
+ }
+
+ if (compressLevel >= 0 && compressLevel <= 9)
+ encodings.push_back(pseudoEncodingCompressLevel0 + compressLevel);
+ if (qualityLevel >= 0 && qualityLevel <= 9)
+ encodings.push_back(pseudoEncodingQualityLevel0 + qualityLevel);
+
+ writer()->writeSetEncodings(encodings);
+}
diff --git a/common/rfb/CConnection.h b/common/rfb/CConnection.h
index e29c0331..5a3ef919 100644
--- a/common/rfb/CConnection.h
+++ b/common/rfb/CConnection.h
@@ -100,6 +100,12 @@ namespace rfb {
int w, int h,
const ScreenSet& layout);
+ virtual void endOfContinuousUpdates();
+
+ virtual void serverInit(int width, int height,
+ const PixelFormat& pf,
+ const char* name);
+
virtual void readAndDecodeRect(const Rect& r, int encoding,
ModifiablePixelBuffer* pb);
@@ -110,20 +116,43 @@ namespace rfb {
// Methods to be overridden in a derived class
- // getIdVerifier() returns the identity verifier associated with the connection.
- // Ownership of the IdentityVerifier is retained by the CConnection instance.
- virtual IdentityVerifier* getIdentityVerifier() {return 0;}
-
// authSuccess() is called when authentication has succeeded.
virtual void authSuccess();
- // serverInit() is called when the ServerInit message is received. The
- // derived class must call on to CConnection::serverInit().
- virtual void serverInit();
+ // initDone() is called when the connection is fully established
+ // and standard messages can be sent. This is called before the
+ // initial FramebufferUpdateRequest giving a derived class the
+ // chance to modify pixel format and settings. The derived class
+ // must also make sure it has provided a valid framebuffer before
+ // returning.
+ virtual void initDone() = 0;
+
+ // resizeFramebuffer() is called whenever the framebuffer
+ // dimensions or the screen layout changes. A subclass must make
+ // sure the pixel buffer has been updated once this call returns.
+ virtual void resizeFramebuffer();
// Other methods
+ // refreshFramebuffer() forces a complete refresh of the entire
+ // framebuffer
+ void refreshFramebuffer();
+
+ // setPreferredEncoding()/getPreferredEncoding() adjusts which
+ // encoding is listed first as a hint to the server that it is the
+ // preferred one
+ void setPreferredEncoding(int encoding);
+ int getPreferredEncoding();
+ // setCompressLevel()/setQualityLevel() controls the encoding hints
+ // sent to the server
+ void setCompressLevel(int level);
+ void setQualityLevel(int level);
+ // setPF() controls the pixel format requested from the server.
+ // server.pf() will automatically be adjusted once the new format
+ // is active.
+ void setPF(const PixelFormat& pf);
+
CMsgReader* reader() { return reader_; }
CMsgWriter* writer() { return writer_; }
@@ -159,6 +188,13 @@ namespace rfb {
ModifiablePixelBuffer* getFramebuffer() { return framebuffer; }
+ protected:
+ // Optional capabilities that a subclass is expected to set to true
+ // if supported
+ bool supportsLocalCursor;
+ bool supportsDesktopResize;
+ bool supportsLEDState;
+
private:
// This is a default implementation of fences that automatically
// responds to requests, stating no support for synchronisation.
@@ -176,6 +212,9 @@ namespace rfb {
void throwConnFailedException();
void securityCompleted();
+ void requestNewUpdate();
+ void updateEncodings();
+
rdr::InStream* is;
rdr::OutStream* os;
CMsgReader* reader_;
@@ -188,6 +227,23 @@ namespace rfb {
bool useProtocol3_3;
+ bool pendingPFChange;
+ rfb::PixelFormat pendingPF;
+
+ int preferredEncoding;
+ int compressLevel;
+ int qualityLevel;
+
+ bool formatChange;
+ rfb::PixelFormat nextPF;
+ bool encodingChange;
+
+ bool firstUpdate;
+ bool pendingUpdate;
+ bool continuousUpdates;
+
+ bool forceNonincremental;
+
ModifiablePixelBuffer* framebuffer;
DecodeManager decoder;
};
diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt
index b8d08137..8e532a28 100644
--- a/common/rfb/CMakeLists.txt
+++ b/common/rfb/CMakeLists.txt
@@ -11,9 +11,9 @@ set(RFB_SOURCES
CSecurityStack.cxx
CSecurityVeNCrypt.cxx
CSecurityVncAuth.cxx
+ ClientParams.cxx
ComparingUpdateTracker.cxx
Configuration.cxx
- ConnParams.cxx
CopyRectDecoder.cxx
Cursor.cxx
DecodeManager.cxx
@@ -43,6 +43,7 @@ set(RFB_SOURCES
SMsgReader.cxx
SMsgWriter.cxx
ServerCore.cxx
+ ServerParams.cxx
Security.cxx
SecurityServer.cxx
SecurityClient.cxx
diff --git a/common/rfb/CMsgHandler.cxx b/common/rfb/CMsgHandler.cxx
index b89bc184..4fe50414 100644
--- a/common/rfb/CMsgHandler.cxx
+++ b/common/rfb/CMsgHandler.cxx
@@ -34,50 +34,53 @@ CMsgHandler::~CMsgHandler()
void CMsgHandler::setDesktopSize(int width, int height)
{
- cp.width = width;
- cp.height = height;
+ server.setDimensions(width, height);
}
void CMsgHandler::setExtendedDesktopSize(unsigned reason, unsigned result,
int width, int height,
const ScreenSet& layout)
{
- cp.supportsSetDesktopSize = true;
+ server.supportsSetDesktopSize = true;
if ((reason == reasonClient) && (result != resultSuccess))
return;
- if (!layout.validate(width, height))
- fprintf(stderr, "Server sent us an invalid screen layout\n");
-
- cp.width = width;
- cp.height = height;
- cp.screenLayout = layout;
+ server.setDimensions(width, height, layout);
}
void CMsgHandler::setPixelFormat(const PixelFormat& pf)
{
- cp.setPF(pf);
+ server.setPF(pf);
}
void CMsgHandler::setName(const char* name)
{
- cp.setName(name);
+ server.setName(name);
}
void CMsgHandler::fence(rdr::U32 flags, unsigned len, const char data[])
{
- cp.supportsFence = true;
+ server.supportsFence = true;
}
void CMsgHandler::endOfContinuousUpdates()
{
- cp.supportsContinuousUpdates = true;
+ server.supportsContinuousUpdates = true;
}
void CMsgHandler::supportsQEMUKeyEvent()
{
- cp.supportsQEMUKeyEvent = true;
+ server.supportsQEMUKeyEvent = true;
+}
+
+void CMsgHandler::serverInit(int width, int height,
+ const PixelFormat& pf,
+ const char* name)
+{
+ server.setDimensions(width, height);
+ server.setPF(pf);
+ server.setName(name);
}
void CMsgHandler::framebufferUpdateStart()
@@ -90,5 +93,5 @@ void CMsgHandler::framebufferUpdateEnd()
void CMsgHandler::setLEDState(unsigned int state)
{
- cp.setLEDState(state);
+ server.setLEDState(state);
}
diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h
index 903ee156..effdaabf 100644
--- a/common/rfb/CMsgHandler.h
+++ b/common/rfb/CMsgHandler.h
@@ -26,7 +26,7 @@
#include <rdr/types.h>
#include <rfb/Pixel.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ServerParams.h>
#include <rfb/Rect.h>
#include <rfb/ScreenSet.h>
@@ -41,9 +41,9 @@ namespace rfb {
// The following methods are called as corresponding messages are read. A
// derived class should override these methods as desired. Note that for
- // the setDesktopSize(), setExtendedDesktopSize(), setPixelFormat() and
- // setName() methods, a derived class should call on to CMsgHandler's
- // methods to set the members of cp appropriately.
+ // the setDesktopSize(), setExtendedDesktopSize(), setPixelFormat(),
+ // setName() and serverInit() methods, a derived class should call on to
+ // CMsgHandler's methods to set the members of "server" appropriately.
virtual void setDesktopSize(int w, int h);
virtual void setExtendedDesktopSize(unsigned reason, unsigned result,
@@ -56,7 +56,9 @@ namespace rfb {
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
virtual void endOfContinuousUpdates();
virtual void supportsQEMUKeyEvent();
- virtual void serverInit() = 0;
+ virtual void serverInit(int width, int height,
+ const PixelFormat& pf,
+ const char* name) = 0;
virtual void readAndDecodeRect(const Rect& r, int encoding,
ModifiablePixelBuffer* pb) = 0;
@@ -72,7 +74,7 @@ namespace rfb {
virtual void setLEDState(unsigned int state);
- ConnParams cp;
+ ServerParams server;
};
}
#endif
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx
index e42546d4..3422ebf5 100644
--- a/common/rfb/CMsgReader.cxx
+++ b/common/rfb/CMsgReader.cxx
@@ -43,13 +43,10 @@ void CMsgReader::readServerInit()
{
int width = is->readU16();
int height = is->readU16();
- handler->setDesktopSize(width, height);
PixelFormat pf;
pf.read(is);
- handler->setPixelFormat(pf);
CharArray name(is->readString());
- handler->setName(name.buf);
- handler->serverInit();
+ handler->serverInit(width, height, pf, name.buf);
}
void CMsgReader::readMsg()
@@ -192,10 +189,11 @@ void CMsgReader::readFramebufferUpdate()
void CMsgReader::readRect(const Rect& r, int encoding)
{
- if ((r.br.x > handler->cp.width) || (r.br.y > handler->cp.height)) {
+ if ((r.br.x > handler->server.width()) ||
+ (r.br.y > handler->server.height())) {
fprintf(stderr, "Rect too big: %dx%d at %d,%d exceeds %dx%d\n",
r.width(), r.height(), r.tl.x, r.tl.y,
- handler->cp.width, handler->cp.height);
+ handler->server.width(), handler->server.height());
throw Exception("Rect too big");
}
@@ -269,7 +267,7 @@ void CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
if (width > maxCursorSize || height > maxCursorSize)
throw Exception("Too big cursor");
- int data_len = width * height * (handler->cp.pf().bpp/8);
+ int data_len = width * height * (handler->server.pf().bpp/8);
int mask_len = ((width+7)/8) * height;
rdr::U8Array data(data_len);
rdr::U8Array mask(mask_len);
@@ -290,14 +288,14 @@ void CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
int byte = y * maskBytesPerRow + x / 8;
int bit = 7 - x % 8;
- handler->cp.pf().rgbFromBuffer(out, in, 1);
+ handler->server.pf().rgbFromBuffer(out, in, 1);
if (mask.buf[byte] & (1 << bit))
out[3] = 255;
else
out[3] = 0;
- in += handler->cp.pf().bpp/8;
+ in += handler->server.pf().bpp/8;
out += 4;
}
}
@@ -321,10 +319,10 @@ void CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hots
encoding = is->readS32();
- origPF = handler->cp.pf();
- handler->cp.setPF(rgbaPF);
+ origPF = handler->server.pf();
+ handler->server.setPF(rgbaPF);
handler->readAndDecodeRect(pb.getRect(), encoding, &pb);
- handler->cp.setPF(origPF);
+ handler->server.setPF(origPF);
// On-wire data has pre-multiplied alpha, but we store it
// non-pre-multiplied
diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx
index 44b73dab..d357c976 100644
--- a/common/rfb/CMsgWriter.cxx
+++ b/common/rfb/CMsgWriter.cxx
@@ -20,19 +20,17 @@
#include <rdr/OutStream.h>
#include <rfb/msgTypes.h>
#include <rfb/fenceTypes.h>
-#include <rfb/encodings.h>
#include <rfb/qemuTypes.h>
#include <rfb/Exception.h>
#include <rfb/PixelFormat.h>
#include <rfb/Rect.h>
-#include <rfb/ConnParams.h>
-#include <rfb/Decoder.h>
+#include <rfb/ServerParams.h>
#include <rfb/CMsgWriter.h>
using namespace rfb;
-CMsgWriter::CMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
- : cp(cp_), os(os_)
+CMsgWriter::CMsgWriter(ServerParams* server_, rdr::OutStream* os_)
+ : server(server_), os(os_)
{
}
@@ -54,96 +52,21 @@ void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
endMsg();
}
-void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
+void CMsgWriter::writeSetEncodings(const std::list<rdr::U32> encodings)
{
+ std::list<rdr::U32>::const_iterator iter;
startMsg(msgTypeSetEncodings);
os->skip(1);
- os->writeU16(nEncodings);
- for (int i = 0; i < nEncodings; i++)
- os->writeU32(encodings[i]);
+ os->writeU16(encodings.size());
+ for (iter = encodings.begin(); iter != encodings.end(); ++iter)
+ os->writeU32(*iter);
endMsg();
}
-// Ask for encodings based on which decoders are supported. Assumes higher
-// encoding numbers are more desirable.
-
-void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
-{
- int nEncodings = 0;
- rdr::U32 encodings[encodingMax+3];
-
- if (cp->supportsLocalCursor) {
- encodings[nEncodings++] = pseudoEncodingCursorWithAlpha;
- encodings[nEncodings++] = pseudoEncodingCursor;
- encodings[nEncodings++] = pseudoEncodingXCursor;
- }
- if (cp->supportsDesktopResize)
- encodings[nEncodings++] = pseudoEncodingDesktopSize;
- if (cp->supportsExtendedDesktopSize)
- encodings[nEncodings++] = pseudoEncodingExtendedDesktopSize;
- if (cp->supportsDesktopRename)
- encodings[nEncodings++] = pseudoEncodingDesktopName;
- if (cp->supportsLEDState)
- encodings[nEncodings++] = pseudoEncodingLEDState;
-
- encodings[nEncodings++] = pseudoEncodingLastRect;
- encodings[nEncodings++] = pseudoEncodingContinuousUpdates;
- encodings[nEncodings++] = pseudoEncodingFence;
- encodings[nEncodings++] = pseudoEncodingQEMUKeyEvent;
-
- if (Decoder::supported(preferredEncoding)) {
- encodings[nEncodings++] = preferredEncoding;
- }
-
- if (useCopyRect) {
- encodings[nEncodings++] = encodingCopyRect;
- }
-
- /*
- * Prefer encodings in this order:
- *
- * Tight, ZRLE, Hextile, *
- */
-
- if ((preferredEncoding != encodingTight) &&
- Decoder::supported(encodingTight))
- encodings[nEncodings++] = encodingTight;
-
- if ((preferredEncoding != encodingZRLE) &&
- Decoder::supported(encodingZRLE))
- encodings[nEncodings++] = encodingZRLE;
-
- if ((preferredEncoding != encodingHextile) &&
- Decoder::supported(encodingHextile))
- encodings[nEncodings++] = encodingHextile;
-
- // Remaining encodings
- for (int i = encodingMax; i >= 0; i--) {
- switch (i) {
- case encodingCopyRect:
- case encodingTight:
- case encodingZRLE:
- case encodingHextile:
- /* These have already been sent earlier */
- break;
- default:
- if ((i != preferredEncoding) && Decoder::supported(i))
- encodings[nEncodings++] = i;
- }
- }
-
- if (cp->compressLevel >= 0 && cp->compressLevel <= 9)
- encodings[nEncodings++] = pseudoEncodingCompressLevel0 + cp->compressLevel;
- if (cp->qualityLevel >= 0 && cp->qualityLevel <= 9)
- encodings[nEncodings++] = pseudoEncodingQualityLevel0 + cp->qualityLevel;
-
- writeSetEncodings(nEncodings, encodings);
-}
-
void CMsgWriter::writeSetDesktopSize(int width, int height,
const ScreenSet& layout)
{
- if (!cp->supportsSetDesktopSize)
+ if (!server->supportsSetDesktopSize)
throw Exception("Server does not support SetDesktopSize");
startMsg(msgTypeSetDesktopSize);
@@ -182,7 +105,7 @@ void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
void CMsgWriter::writeEnableContinuousUpdates(bool enable,
int x, int y, int w, int h)
{
- if (!cp->supportsContinuousUpdates)
+ if (!server->supportsContinuousUpdates)
throw Exception("Server does not support continuous updates");
startMsg(msgTypeEnableContinuousUpdates);
@@ -199,7 +122,7 @@ void CMsgWriter::writeEnableContinuousUpdates(bool enable,
void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
{
- if (!cp->supportsFence)
+ if (!server->supportsFence)
throw Exception("Server does not support fences");
if (len > 64)
throw Exception("Too large fence payload");
@@ -219,7 +142,7 @@ void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
void CMsgWriter::writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
{
- if (!cp->supportsQEMUKeyEvent || !keycode) {
+ if (!server->supportsQEMUKeyEvent || !keycode) {
/* This event isn't meaningful without a valid keysym */
if (!keysym)
return;
@@ -245,8 +168,8 @@ void CMsgWriter::writePointerEvent(const Point& pos, int buttonMask)
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;
+ if (p.x >= server->width()) p.x = server->width() - 1;
+ if (p.y >= server->height()) p.y = server->height() - 1;
startMsg(msgTypePointerEvent);
os->writeU8(buttonMask);
diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h
index 1322186a..4d533d42 100644
--- a/common/rfb/CMsgWriter.h
+++ b/common/rfb/CMsgWriter.h
@@ -23,6 +23,8 @@
#ifndef __RFB_CMSGWRITER_H__
#define __RFB_CMSGWRITER_H__
+#include <list>
+
#include <rdr/types.h>
namespace rdr { class OutStream; }
@@ -30,21 +32,20 @@ namespace rdr { class OutStream; }
namespace rfb {
class PixelFormat;
- class ConnParams;
+ class ServerParams;
struct ScreenSet;
struct Point;
struct Rect;
class CMsgWriter {
public:
- CMsgWriter(ConnParams* cp, rdr::OutStream* os);
+ CMsgWriter(ServerParams* server, rdr::OutStream* os);
virtual ~CMsgWriter();
void writeClientInit(bool shared);
void writeSetPixelFormat(const PixelFormat& pf);
- void writeSetEncodings(int nEncodings, rdr::U32* encodings);
- void writeSetEncodings(int preferredEncoding, bool useCopyRect);
+ void writeSetEncodings(const std::list<rdr::U32> encodings);
void writeSetDesktopSize(int width, int height, const ScreenSet& layout);
void writeFramebufferUpdateRequest(const Rect& r,bool incremental);
@@ -60,7 +61,7 @@ namespace rfb {
void startMsg(int type);
void endMsg();
- ConnParams* cp;
+ ServerParams* server;
rdr::OutStream* os;
};
}
diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx
index d6a8d7f8..c6d1e310 100644
--- a/common/rfb/CSecurityTLS.cxx
+++ b/common/rfb/CSecurityTLS.cxx
@@ -34,7 +34,6 @@
#endif
#include <rfb/CSecurityTLS.h>
-#include <rfb/SSecurityVeNCrypt.h>
#include <rfb/CConnection.h>
#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
diff --git a/common/rfb/CSecurityTLS.h b/common/rfb/CSecurityTLS.h
index 4932c078..476d0ef8 100644
--- a/common/rfb/CSecurityTLS.h
+++ b/common/rfb/CSecurityTLS.h
@@ -31,7 +31,6 @@
#endif
#include <rfb/CSecurity.h>
-#include <rfb/SSecurityVeNCrypt.h>
#include <rfb/Security.h>
#include <rfb/UserMsgBox.h>
#include <rdr/InStream.h>
diff --git a/common/rfb/ClientParams.cxx b/common/rfb/ClientParams.cxx
new file mode 100644
index 00000000..2f8783bb
--- /dev/null
+++ b/common/rfb/ClientParams.cxx
@@ -0,0 +1,178 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ * Copyright 2014-2018 Pierre Ossman for Cendio AB
+ *
+ * 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 <rfb/Exception.h>
+#include <rfb/encodings.h>
+#include <rfb/ledStates.h>
+#include <rfb/ClientParams.h>
+
+using namespace rfb;
+
+ClientParams::ClientParams()
+ : majorVersion(0), minorVersion(0),
+ compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
+ subsampling(subsampleUndefined),
+ width_(0), height_(0), name_(0),
+ ledState_(ledUnknown)
+{
+ setName("");
+ cursor_ = new Cursor(0, 0, Point(), NULL);
+}
+
+ClientParams::~ClientParams()
+{
+ delete [] name_;
+ delete cursor_;
+}
+
+void ClientParams::setDimensions(int width, int height)
+{
+ ScreenSet layout;
+ layout.add_screen(rfb::Screen(0, 0, 0, width, height, 0));
+ setDimensions(width, height, layout);
+}
+
+void ClientParams::setDimensions(int width, int height, const ScreenSet& layout)
+{
+ if (!layout.validate(width, height))
+ throw Exception("Attempted to configure an invalid screen layout");
+
+ width_ = width;
+ height_ = height;
+ screenLayout_ = layout;
+}
+
+void ClientParams::setPF(const PixelFormat& pf)
+{
+ pf_ = pf;
+
+ if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)
+ throw Exception("setPF: not 8, 16 or 32 bpp?");
+}
+
+void ClientParams::setName(const char* name)
+{
+ delete [] name_;
+ name_ = strDup(name);
+}
+
+void ClientParams::setCursor(const Cursor& other)
+{
+ delete cursor_;
+ cursor_ = new Cursor(other);
+}
+
+bool ClientParams::supportsEncoding(rdr::S32 encoding) const
+{
+ return encodings_.count(encoding) != 0;
+}
+
+void ClientParams::setEncodings(int nEncodings, const rdr::S32* encodings)
+{
+ compressLevel = -1;
+ qualityLevel = -1;
+ fineQualityLevel = -1;
+ subsampling = subsampleUndefined;
+
+ encodings_.clear();
+ encodings_.insert(encodingRaw);
+
+ for (int i = nEncodings-1; i >= 0; i--) {
+ switch (encodings[i]) {
+ case pseudoEncodingSubsamp1X:
+ subsampling = subsampleNone;
+ break;
+ case pseudoEncodingSubsampGray:
+ subsampling = subsampleGray;
+ break;
+ case pseudoEncodingSubsamp2X:
+ subsampling = subsample2X;
+ break;
+ case pseudoEncodingSubsamp4X:
+ subsampling = subsample4X;
+ break;
+ case pseudoEncodingSubsamp8X:
+ subsampling = subsample8X;
+ break;
+ case pseudoEncodingSubsamp16X:
+ subsampling = subsample16X;
+ break;
+ }
+
+ if (encodings[i] >= pseudoEncodingCompressLevel0 &&
+ encodings[i] <= pseudoEncodingCompressLevel9)
+ compressLevel = encodings[i] - pseudoEncodingCompressLevel0;
+
+ if (encodings[i] >= pseudoEncodingQualityLevel0 &&
+ encodings[i] <= pseudoEncodingQualityLevel9)
+ qualityLevel = encodings[i] - pseudoEncodingQualityLevel0;
+
+ if (encodings[i] >= pseudoEncodingFineQualityLevel0 &&
+ encodings[i] <= pseudoEncodingFineQualityLevel100)
+ fineQualityLevel = encodings[i] - pseudoEncodingFineQualityLevel0;
+
+ encodings_.insert(encodings[i]);
+ }
+}
+
+void ClientParams::setLEDState(unsigned int state)
+{
+ ledState_ = state;
+}
+
+bool ClientParams::supportsLocalCursor() const
+{
+ if (supportsEncoding(pseudoEncodingCursorWithAlpha))
+ return true;
+ if (supportsEncoding(pseudoEncodingCursor))
+ return true;
+ if (supportsEncoding(pseudoEncodingXCursor))
+ return true;
+ return false;
+}
+
+bool ClientParams::supportsDesktopSize() const
+{
+ if (supportsEncoding(pseudoEncodingExtendedDesktopSize))
+ return true;
+ if (supportsEncoding(pseudoEncodingDesktopSize))
+ return true;
+ return false;
+}
+
+bool ClientParams::supportsLEDState() const
+{
+ if (supportsEncoding(pseudoEncodingLEDState))
+ return true;
+ return false;
+}
+
+bool ClientParams::supportsFence() const
+{
+ if (supportsEncoding(pseudoEncodingFence))
+ return true;
+ return false;
+}
+
+bool ClientParams::supportsContinuousUpdates() const
+{
+ if (supportsEncoding(pseudoEncodingContinuousUpdates))
+ return true;
+ return false;
+}
diff --git a/common/rfb/ConnParams.h b/common/rfb/ClientParams.h
index b3222936..f7a7044b 100644
--- a/common/rfb/ConnParams.h
+++ b/common/rfb/ClientParams.h
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
+ * Copyright 2014-2018 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,11 +17,11 @@
* USA.
*/
//
-// ConnParams - structure containing the connection parameters.
+// ClientParams - structure describing the current state of the remote client
//
-#ifndef __RFB_CONNPARAMS_H__
-#define __RFB_CONNPARAMS_H__
+#ifndef __RFB_CLIENTPARAMS_H__
+#define __RFB_CLIENTPARAMS_H__
#include <set>
@@ -30,8 +30,6 @@
#include <rfb/PixelFormat.h>
#include <rfb/ScreenSet.h>
-namespace rdr { class InStream; }
-
namespace rfb {
const int subsampleUndefined = -1;
@@ -42,13 +40,10 @@ namespace rfb {
const int subsample8X = 4;
const int subsample16X = 5;
- class ConnParams {
+ class ClientParams {
public:
- ConnParams();
- ~ConnParams();
-
- bool readVersion(rdr::InStream* is, bool* done);
- void writeVersion(rdr::OutStream* os);
+ ClientParams();
+ ~ClientParams();
int majorVersion;
int minorVersion;
@@ -67,9 +62,11 @@ namespace rfb {
return !beforeVersion(major,minor+1);
}
- int width;
- int height;
- ScreenSet screenLayout;
+ const int width() const { return width_; }
+ const int height() const { return height_; }
+ const ScreenSet& screenLayout() const { return screenLayout_; }
+ void setDimensions(int width, int height);
+ void setDimensions(int width, int height, const ScreenSet& layout);
const PixelFormat& pf() const { return pf_; }
void setPF(const PixelFormat& pf);
@@ -87,21 +84,13 @@ namespace rfb {
unsigned int ledState() { return ledState_; }
void setLEDState(unsigned int state);
- bool useCopyRect;
-
- bool supportsLocalCursor;
- bool supportsLocalXCursor;
- bool supportsLocalCursorWithAlpha;
- bool supportsDesktopResize;
- bool supportsExtendedDesktopSize;
- bool supportsDesktopRename;
- bool supportsLastRect;
- bool supportsLEDState;
- bool supportsQEMUKeyEvent;
-
- bool supportsSetDesktopSize;
- bool supportsFence;
- bool supportsContinuousUpdates;
+ // Wrappers to check for functionality rather than specific
+ // encodings
+ bool supportsLocalCursor() const;
+ bool supportsDesktopSize() const;
+ bool supportsLEDState() const;
+ bool supportsFence() const;
+ bool supportsContinuousUpdates() const;
int compressLevel;
int qualityLevel;
@@ -110,12 +99,14 @@ namespace rfb {
private:
+ int width_;
+ int height_;
+ ScreenSet screenLayout_;
+
PixelFormat pf_;
char* name_;
Cursor* cursor_;
std::set<rdr::S32> encodings_;
- char verStr[13];
- int verStrPos;
unsigned int ledState_;
};
}
diff --git a/common/rfb/ConnParams.cxx b/common/rfb/ConnParams.cxx
deleted file mode 100644
index 80b4a5ac..00000000
--- a/common/rfb/ConnParams.cxx
+++ /dev/null
@@ -1,200 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
- * Copyright 2014 Pierre Ossman for Cendio AB
- *
- * 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 <rdr/InStream.h>
-#include <rdr/OutStream.h>
-#include <rfb/Exception.h>
-#include <rfb/encodings.h>
-#include <rfb/ledStates.h>
-#include <rfb/ConnParams.h>
-#include <rfb/util.h>
-
-using namespace rfb;
-
-ConnParams::ConnParams()
- : majorVersion(0), minorVersion(0),
- width(0), height(0), useCopyRect(false),
- supportsLocalCursor(false), supportsLocalXCursor(false),
- supportsLocalCursorWithAlpha(false),
- supportsDesktopResize(false), supportsExtendedDesktopSize(false),
- supportsDesktopRename(false), supportsLastRect(false),
- supportsLEDState(false), supportsQEMUKeyEvent(false),
- supportsSetDesktopSize(false), supportsFence(false),
- supportsContinuousUpdates(false),
- compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
- subsampling(subsampleUndefined), name_(0), verStrPos(0),
- ledState_(ledUnknown)
-{
- setName("");
- cursor_ = new Cursor(0, 0, Point(), NULL);
-}
-
-ConnParams::~ConnParams()
-{
- delete [] name_;
- delete cursor_;
-}
-
-bool ConnParams::readVersion(rdr::InStream* is, bool* done)
-{
- if (verStrPos >= 12) return false;
- while (is->checkNoWait(1) && verStrPos < 12) {
- verStr[verStrPos++] = is->readU8();
- }
-
- if (verStrPos < 12) {
- *done = false;
- return true;
- }
- *done = true;
- verStr[12] = 0;
- return (sscanf(verStr, "RFB %03d.%03d\n", &majorVersion,&minorVersion) == 2);
-}
-
-void ConnParams::writeVersion(rdr::OutStream* os)
-{
- char str[13];
- sprintf(str, "RFB %03d.%03d\n", majorVersion, minorVersion);
- os->writeBytes(str, 12);
- os->flush();
-}
-
-void ConnParams::setPF(const PixelFormat& pf)
-{
- pf_ = pf;
-
- if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)
- throw Exception("setPF: not 8, 16 or 32 bpp?");
-}
-
-void ConnParams::setName(const char* name)
-{
- delete [] name_;
- name_ = strDup(name);
-}
-
-void ConnParams::setCursor(const Cursor& other)
-{
- delete cursor_;
- cursor_ = new Cursor(other);
-}
-
-bool ConnParams::supportsEncoding(rdr::S32 encoding) const
-{
- return encodings_.count(encoding) != 0;
-}
-
-void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
-{
- useCopyRect = false;
- supportsLocalCursor = false;
- supportsLocalCursorWithAlpha = false;
- supportsDesktopResize = false;
- supportsExtendedDesktopSize = false;
- supportsLocalXCursor = false;
- supportsLastRect = false;
- supportsQEMUKeyEvent = false;
- compressLevel = -1;
- qualityLevel = -1;
- fineQualityLevel = -1;
- subsampling = subsampleUndefined;
-
- encodings_.clear();
- encodings_.insert(encodingRaw);
-
- for (int i = nEncodings-1; i >= 0; i--) {
- switch (encodings[i]) {
- case encodingCopyRect:
- useCopyRect = true;
- break;
- case pseudoEncodingCursor:
- supportsLocalCursor = true;
- break;
- case pseudoEncodingXCursor:
- supportsLocalXCursor = true;
- break;
- case pseudoEncodingCursorWithAlpha:
- supportsLocalCursorWithAlpha = true;
- break;
- case pseudoEncodingDesktopSize:
- supportsDesktopResize = true;
- break;
- case pseudoEncodingExtendedDesktopSize:
- supportsExtendedDesktopSize = true;
- break;
- case pseudoEncodingDesktopName:
- supportsDesktopRename = true;
- break;
- case pseudoEncodingLastRect:
- supportsLastRect = true;
- break;
- case pseudoEncodingLEDState:
- supportsLEDState = true;
- break;
- case pseudoEncodingQEMUKeyEvent:
- supportsQEMUKeyEvent = true;
- break;
- case pseudoEncodingFence:
- supportsFence = true;
- break;
- case pseudoEncodingContinuousUpdates:
- supportsContinuousUpdates = true;
- break;
- case pseudoEncodingSubsamp1X:
- subsampling = subsampleNone;
- break;
- case pseudoEncodingSubsampGray:
- subsampling = subsampleGray;
- break;
- case pseudoEncodingSubsamp2X:
- subsampling = subsample2X;
- break;
- case pseudoEncodingSubsamp4X:
- subsampling = subsample4X;
- break;
- case pseudoEncodingSubsamp8X:
- subsampling = subsample8X;
- break;
- case pseudoEncodingSubsamp16X:
- subsampling = subsample16X;
- break;
- }
-
- if (encodings[i] >= pseudoEncodingCompressLevel0 &&
- encodings[i] <= pseudoEncodingCompressLevel9)
- compressLevel = encodings[i] - pseudoEncodingCompressLevel0;
-
- if (encodings[i] >= pseudoEncodingQualityLevel0 &&
- encodings[i] <= pseudoEncodingQualityLevel9)
- qualityLevel = encodings[i] - pseudoEncodingQualityLevel0;
-
- if (encodings[i] >= pseudoEncodingFineQualityLevel0 &&
- encodings[i] <= pseudoEncodingFineQualityLevel100)
- fineQualityLevel = encodings[i] - pseudoEncodingFineQualityLevel0;
-
- if (encodings[i] > 0)
- encodings_.insert(encodings[i]);
- }
-}
-
-void ConnParams::setLEDState(unsigned int state)
-{
- ledState_ = state;
-}
diff --git a/common/rfb/CopyRectDecoder.cxx b/common/rfb/CopyRectDecoder.cxx
index 23949a8b..ecf50323 100644
--- a/common/rfb/CopyRectDecoder.cxx
+++ b/common/rfb/CopyRectDecoder.cxx
@@ -32,7 +32,7 @@ CopyRectDecoder::~CopyRectDecoder()
}
void CopyRectDecoder::readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os)
+ const ServerParams& server, rdr::OutStream* os)
{
os->copyBytes(is, 4);
}
@@ -41,21 +41,21 @@ void CopyRectDecoder::readRect(const Rect& r, rdr::InStream* is,
void CopyRectDecoder::getAffectedRegion(const Rect& rect,
const void* buffer,
size_t buflen,
- const ConnParams& cp,
+ const ServerParams& server,
Region* region)
{
rdr::MemInStream is(buffer, buflen);
int srcX = is.readU16();
int srcY = is.readU16();
- Decoder::getAffectedRegion(rect, buffer, buflen, cp, region);
+ Decoder::getAffectedRegion(rect, buffer, buflen, server, region);
region->assign_union(Region(rect.translate(Point(srcX-rect.tl.x,
srcY-rect.tl.y))));
}
void CopyRectDecoder::decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
rdr::MemInStream is(buffer, buflen);
diff --git a/common/rfb/CopyRectDecoder.h b/common/rfb/CopyRectDecoder.h
index 1d2ce53b..546266e1 100644
--- a/common/rfb/CopyRectDecoder.h
+++ b/common/rfb/CopyRectDecoder.h
@@ -27,12 +27,12 @@ namespace rfb {
CopyRectDecoder();
virtual ~CopyRectDecoder();
virtual void readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os);
+ const ServerParams& server, rdr::OutStream* os);
virtual void getAffectedRegion(const Rect& rect, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
Region* region);
virtual void decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb);
};
}
diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx
index c509db09..98b6e790 100644
--- a/common/rfb/DecodeManager.cxx
+++ b/common/rfb/DecodeManager.cxx
@@ -132,9 +132,9 @@ void DecodeManager::decodeRect(const Rect& r, int encoding,
if (threads.empty()) {
bufferStream = freeBuffers.front();
bufferStream->clear();
- decoder->readRect(r, conn->getInStream(), conn->cp, bufferStream);
+ decoder->readRect(r, conn->getInStream(), conn->server, bufferStream);
decoder->decodeRect(r, bufferStream->data(), bufferStream->length(),
- conn->cp, pb);
+ conn->server, pb);
return;
}
@@ -155,7 +155,7 @@ void DecodeManager::decodeRect(const Rect& r, int encoding,
// Read the rect
bufferStream->clear();
- decoder->readRect(r, conn->getInStream(), conn->cp, bufferStream);
+ decoder->readRect(r, conn->getInStream(), conn->server, bufferStream);
// Then try to put it on the queue
entry = new QueueEntry;
@@ -164,12 +164,12 @@ void DecodeManager::decodeRect(const Rect& r, int encoding,
entry->rect = r;
entry->encoding = encoding;
entry->decoder = decoder;
- entry->cp = &conn->cp;
+ entry->server = &conn->server;
entry->pb = pb;
entry->bufferStream = bufferStream;
decoder->getAffectedRegion(r, bufferStream->data(),
- bufferStream->length(), conn->cp,
+ bufferStream->length(), conn->server,
&entry->affectedRegion);
queueMutex->lock();
@@ -276,7 +276,7 @@ void DecodeManager::DecodeThread::worker()
try {
entry->decoder->decodeRect(entry->rect, entry->bufferStream->data(),
entry->bufferStream->length(),
- *entry->cp, entry->pb);
+ *entry->server, entry->pb);
} catch (rdr::Exception& e) {
manager->setThreadException(e);
} catch(...) {
@@ -346,7 +346,7 @@ DecodeManager::QueueEntry* DecodeManager::DecodeThread::findEntry()
(*iter2)->rect,
(*iter2)->bufferStream->data(),
(*iter2)->bufferStream->length(),
- *entry->cp))
+ *entry->server))
goto next;
}
}
diff --git a/common/rfb/DecodeManager.h b/common/rfb/DecodeManager.h
index 2098063e..058d8240 100644
--- a/common/rfb/DecodeManager.h
+++ b/common/rfb/DecodeManager.h
@@ -65,7 +65,7 @@ namespace rfb {
Rect rect;
int encoding;
Decoder* decoder;
- const ConnParams* cp;
+ const ServerParams* server;
ModifiablePixelBuffer* pb;
rdr::MemOutStream* bufferStream;
Region affectedRegion;
diff --git a/common/rfb/Decoder.cxx b/common/rfb/Decoder.cxx
index 370e1f9a..9827a732 100644
--- a/common/rfb/Decoder.cxx
+++ b/common/rfb/Decoder.cxx
@@ -38,7 +38,7 @@ Decoder::~Decoder()
}
void Decoder::getAffectedRegion(const Rect& rect, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
Region* region)
{
region->reset(rect);
@@ -47,7 +47,7 @@ void Decoder::getAffectedRegion(const Rect& rect, const void* buffer,
bool Decoder::doRectsConflict(const Rect& rectA, const void* bufferA,
size_t buflenA, const Rect& rectB,
const void* bufferB, size_t buflenB,
- const ConnParams& cp)
+ const ServerParams& server)
{
return false;
}
diff --git a/common/rfb/Decoder.h b/common/rfb/Decoder.h
index 86ee4ef8..e074f3ec 100644
--- a/common/rfb/Decoder.h
+++ b/common/rfb/Decoder.h
@@ -25,7 +25,7 @@ namespace rdr {
}
namespace rfb {
- class ConnParams;
+ class ServerParams;
class ModifiablePixelBuffer;
class Region;
@@ -53,7 +53,7 @@ namespace rfb {
// make it easier to decode. This function will always be called in
// a serial manner on the main thread.
virtual void readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os)=0;
+ const ServerParams& server, rdr::OutStream* os)=0;
// These functions will be called from any of the worker threads.
// A lock will be held whilst these are called so it is safe to
@@ -63,7 +63,7 @@ namespace rfb {
// be either read from or written do when decoding this rect. The
// default implementation simply returns the given rectangle.
virtual void getAffectedRegion(const Rect& rect, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
Region* region);
// doesRectsConflict() determines if two rectangles must be decoded
@@ -75,14 +75,14 @@ namespace rfb {
const Rect& rectB,
const void* bufferB,
size_t buflenB,
- const ConnParams& cp);
+ const ServerParams& server);
// decodeRect() decodes the given rectangle with data from the
// given buffer, onto the ModifiablePixelBuffer. The PixelFormat of
// the PixelBuffer might not match the ConnParams and it is up to
// the decoder to do any necessary conversion.
virtual void decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)=0;
public:
diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx
index 02128f7f..735be072 100644
--- a/common/rfb/EncodeManager.cxx
+++ b/common/rfb/EncodeManager.cxx
@@ -325,6 +325,9 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
changed = changed_;
+ if (!conn->client.supportsEncoding(encodingCopyRect))
+ changed.assign_union(copied);
+
/*
* We need to render the cursor seperately as it has its own
* magical pixel buffer, so split it out from the changed region.
@@ -334,7 +337,7 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
changed.assign_subtract(renderedCursor->getEffectiveRect());
}
- if (conn->cp.supportsLastRect)
+ if (conn->client.supportsEncoding(pseudoEncodingLastRect))
nRects = 0xFFFF;
else {
nRects = copied.numRects();
@@ -344,13 +347,14 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
conn->writer()->writeFramebufferUpdateStart(nRects);
- writeCopyRects(copied, copyDelta);
+ if (conn->client.supportsEncoding(encodingCopyRect))
+ writeCopyRects(copied, copyDelta);
/*
* We start by searching for solid rects, which are then removed
* from the changed region.
*/
- if (conn->cp.supportsLastRect)
+ if (conn->client.supportsEncoding(pseudoEncodingLastRect))
writeSolidRects(&changed, pb);
writeRects(changed, pb);
@@ -373,7 +377,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
solid = bitmap = bitmapRLE = encoderRaw;
indexed = indexedRLE = fullColour = encoderRaw;
- allowJPEG = conn->cp.pf().bpp >= 16;
+ allowJPEG = conn->client.pf().bpp >= 16;
if (!allowLossy) {
if (encoders[encoderTightJPEG]->losslessQuality == -1)
allowJPEG = false;
@@ -447,7 +451,7 @@ void EncodeManager::prepareEncoders(bool allowLossy)
}
// JPEG is the only encoder that can reduce things to grayscale
- if ((conn->cp.subsampling == subsampleGray) &&
+ if ((conn->client.subsampling == subsampleGray) &&
encoders[encoderTightJPEG]->isSupported() && allowLossy) {
solid = bitmap = bitmapRLE = encoderTightJPEG;
indexed = indexedRLE = fullColour = encoderTightJPEG;
@@ -465,14 +469,14 @@ void EncodeManager::prepareEncoders(bool allowLossy)
encoder = encoders[*iter];
- encoder->setCompressLevel(conn->cp.compressLevel);
+ encoder->setCompressLevel(conn->client.compressLevel);
if (allowLossy) {
- encoder->setQualityLevel(conn->cp.qualityLevel);
- encoder->setFineQualityLevel(conn->cp.fineQualityLevel,
- conn->cp.subsampling);
+ encoder->setQualityLevel(conn->client.qualityLevel);
+ encoder->setFineQualityLevel(conn->client.fineQualityLevel,
+ conn->client.subsampling);
} else {
- int level = __rfbmax(conn->cp.qualityLevel,
+ int level = __rfbmax(conn->client.qualityLevel,
encoder->losslessQuality);
encoder->setQualityLevel(level);
encoder->setFineQualityLevel(-1, subsampleUndefined);
@@ -575,7 +579,7 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type)
stats[klass][activeType].rects++;
stats[klass][activeType].pixels += rect.area();
- equiv = 12 + rect.area() * (conn->cp.pf().bpp/8);
+ equiv = 12 + rect.area() * (conn->client.pf().bpp/8);
stats[klass][activeType].equivalent += equiv;
encoder = encoders[klass];
@@ -623,7 +627,7 @@ void EncodeManager::writeCopyRects(const Region& copied, const Point& delta)
copyStats.rects++;
copyStats.pixels += rect->area();
- equiv = 12 + rect->area() * (conn->cp.pf().bpp/8);
+ equiv = 12 + rect->area() * (conn->client.pf().bpp/8);
copyStats.equivalent += equiv;
conn->writer()->writeCopyRect(*rect, rect->tl.x - delta.x,
@@ -710,11 +714,11 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed,
rdr::U32 _buffer2;
rdr::U8* converted = (rdr::U8*)&_buffer2;
- conn->cp.pf().bufferFromBuffer(converted, pb->getPF(),
+ conn->client.pf().bufferFromBuffer(converted, pb->getPF(),
colourValue, 1);
encoder->writeSolidRect(erp.width(), erp.height(),
- conn->cp.pf(), converted);
+ conn->client.pf(), converted);
}
endRect();
@@ -808,10 +812,10 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb)
// compression setting means spending less effort in building
// a palette. It might be that they figured the increase in
// zlib setting compensated for the loss.
- if (conn->cp.compressLevel == -1)
+ if (conn->client.compressLevel == -1)
divisor = 2 * 8;
else
- divisor = conn->cp.compressLevel * 8;
+ divisor = conn->client.compressLevel * 8;
if (divisor < 4)
divisor = 4;
@@ -819,7 +823,7 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb)
// Special exception inherited from the Tight encoder
if (activeEncoders[encoderFullColour] == encoderTightJPEG) {
- if ((conn->cp.compressLevel != -1) && (conn->cp.compressLevel < 2))
+ if ((conn->client.compressLevel != -1) && (conn->client.compressLevel < 2))
maxColours = 24;
else
maxColours = 96;
@@ -992,8 +996,8 @@ PixelBuffer* EncodeManager::preparePixelBuffer(const Rect& rect,
int stride;
// Do wo need to convert the data?
- if (convert && !conn->cp.pf().equal(pb->getPF())) {
- convertedPixelBuffer.setPF(conn->cp.pf());
+ if (convert && !conn->client.pf().equal(pb->getPF())) {
+ convertedPixelBuffer.setPF(conn->client.pf());
convertedPixelBuffer.setSize(rect.width(), rect.height());
buffer = pb->getBuffer(rect, &stride);
diff --git a/common/rfb/HextileDecoder.cxx b/common/rfb/HextileDecoder.cxx
index eae00408..742dfb28 100644
--- a/common/rfb/HextileDecoder.cxx
+++ b/common/rfb/HextileDecoder.cxx
@@ -20,7 +20,7 @@
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ServerParams.h>
#include <rfb/PixelBuffer.h>
#include <rfb/HextileDecoder.h>
@@ -45,12 +45,12 @@ HextileDecoder::~HextileDecoder()
}
void HextileDecoder::readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os)
+ const ServerParams& server, rdr::OutStream* os)
{
Rect t;
size_t bytesPerPixel;
- bytesPerPixel = cp.pf().bpp/8;
+ bytesPerPixel = server.pf().bpp/8;
for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
@@ -91,11 +91,11 @@ void HextileDecoder::readRect(const Rect& r, rdr::InStream* is,
}
void HextileDecoder::decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
rdr::MemInStream is(buffer, buflen);
- const PixelFormat& pf = cp.pf();
+ const PixelFormat& pf = server.pf();
switch (pf.bpp) {
case 8: hextileDecode8 (r, &is, pf, pb); break;
case 16: hextileDecode16(r, &is, pf, pb); break;
diff --git a/common/rfb/HextileDecoder.h b/common/rfb/HextileDecoder.h
index bdc76bcc..b8515bfc 100644
--- a/common/rfb/HextileDecoder.h
+++ b/common/rfb/HextileDecoder.h
@@ -27,9 +27,9 @@ namespace rfb {
HextileDecoder();
virtual ~HextileDecoder();
virtual void readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os);
+ const ServerParams& server, rdr::OutStream* os);
virtual void decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb);
};
}
diff --git a/common/rfb/HextileEncoder.cxx b/common/rfb/HextileEncoder.cxx
index 47e52510..1e20eb92 100644
--- a/common/rfb/HextileEncoder.cxx
+++ b/common/rfb/HextileEncoder.cxx
@@ -55,7 +55,7 @@ HextileEncoder::~HextileEncoder()
bool HextileEncoder::isSupported()
{
- return conn->cp.supportsEncoding(encodingHextile);
+ return conn->client.supportsEncoding(encodingHextile);
}
void HextileEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
diff --git a/common/rfb/JpegCompressor.cxx b/common/rfb/JpegCompressor.cxx
index 27cb9de3..23b8f8cf 100644
--- a/common/rfb/JpegCompressor.cxx
+++ b/common/rfb/JpegCompressor.cxx
@@ -22,7 +22,7 @@
#include <rdr/Exception.h>
#include <rfb/Rect.h>
#include <rfb/PixelFormat.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ClientParams.h>
#include <stdio.h>
extern "C" {
diff --git a/common/rfb/Logger.cxx b/common/rfb/Logger.cxx
index 3daf2486..ad10a4cf 100644
--- a/common/rfb/Logger.cxx
+++ b/common/rfb/Logger.cxx
@@ -47,7 +47,16 @@ void Logger::write(int level, const char *logname, const char* format,
char buf1[4096];
vsnprintf(buf1, sizeof(buf1)-1, format, ap);
buf1[sizeof(buf1)-1] = 0;
- write(level, logname, buf1);
+ char *buf = buf1;
+ while (true) {
+ char *end = strchr(buf, '\n');
+ if (end)
+ *end = '\0';
+ write(level, logname, buf);
+ if (!end)
+ break;
+ buf = end + 1;
+ }
}
void
diff --git a/common/rfb/RREDecoder.cxx b/common/rfb/RREDecoder.cxx
index 218c9b0b..70a7ddb2 100644
--- a/common/rfb/RREDecoder.cxx
+++ b/common/rfb/RREDecoder.cxx
@@ -20,7 +20,7 @@
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ServerParams.h>
#include <rfb/PixelBuffer.h>
#include <rfb/RREDecoder.h>
@@ -45,22 +45,22 @@ RREDecoder::~RREDecoder()
}
void RREDecoder::readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os)
+ const ServerParams& server, rdr::OutStream* os)
{
rdr::U32 numRects;
numRects = is->readU32();
os->writeU32(numRects);
- os->copyBytes(is, cp.pf().bpp/8 + numRects * (cp.pf().bpp/8 + 8));
+ os->copyBytes(is, server.pf().bpp/8 + numRects * (server.pf().bpp/8 + 8));
}
void RREDecoder::decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
rdr::MemInStream is(buffer, buflen);
- const PixelFormat& pf = cp.pf();
+ const PixelFormat& pf = server.pf();
switch (pf.bpp) {
case 8: rreDecode8 (r, &is, pf, pb); break;
case 16: rreDecode16(r, &is, pf, pb); break;
diff --git a/common/rfb/RREDecoder.h b/common/rfb/RREDecoder.h
index f89fef4a..f47eddad 100644
--- a/common/rfb/RREDecoder.h
+++ b/common/rfb/RREDecoder.h
@@ -27,9 +27,9 @@ namespace rfb {
RREDecoder();
virtual ~RREDecoder();
virtual void readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os);
+ const ServerParams& server, rdr::OutStream* os);
virtual void decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb);
};
}
diff --git a/common/rfb/RREEncoder.cxx b/common/rfb/RREEncoder.cxx
index 7287e7eb..83585490 100644
--- a/common/rfb/RREEncoder.cxx
+++ b/common/rfb/RREEncoder.cxx
@@ -47,7 +47,7 @@ RREEncoder::~RREEncoder()
bool RREEncoder::isSupported()
{
- return conn->cp.supportsEncoding(encodingRRE);
+ return conn->client.supportsEncoding(encodingRRE);
}
void RREEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
diff --git a/common/rfb/RawDecoder.cxx b/common/rfb/RawDecoder.cxx
index ec0c68ee..61235047 100644
--- a/common/rfb/RawDecoder.cxx
+++ b/common/rfb/RawDecoder.cxx
@@ -19,7 +19,7 @@
#include <assert.h>
#include <rdr/OutStream.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ServerParams.h>
#include <rfb/PixelBuffer.h>
#include <rfb/RawDecoder.h>
@@ -34,15 +34,15 @@ RawDecoder::~RawDecoder()
}
void RawDecoder::readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os)
+ const ServerParams& server, rdr::OutStream* os)
{
- os->copyBytes(is, r.area() * (cp.pf().bpp/8));
+ os->copyBytes(is, r.area() * (server.pf().bpp/8));
}
void RawDecoder::decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
- assert(buflen >= (size_t)r.area() * (cp.pf().bpp/8));
- pb->imageRect(cp.pf(), r, buffer);
+ assert(buflen >= (size_t)r.area() * (server.pf().bpp/8));
+ pb->imageRect(server.pf(), r, buffer);
}
diff --git a/common/rfb/RawDecoder.h b/common/rfb/RawDecoder.h
index 21ea738b..4ab80717 100644
--- a/common/rfb/RawDecoder.h
+++ b/common/rfb/RawDecoder.h
@@ -26,9 +26,9 @@ namespace rfb {
RawDecoder();
virtual ~RawDecoder();
virtual void readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os);
+ const ServerParams& server, rdr::OutStream* os);
virtual void decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb);
};
}
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
index a79abeef..690653a2 100644
--- a/common/rfb/SConnection.cxx
+++ b/common/rfb/SConnection.cxx
@@ -59,7 +59,7 @@ SConnection::SConnection()
if (rfb::Server::protocol3_3)
defaultMinorVersion = 3;
- cp.setVersion(defaultMajorVersion, defaultMinorVersion);
+ client.setVersion(defaultMajorVersion, defaultMinorVersion);
}
SConnection::~SConnection()
@@ -80,7 +80,12 @@ void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
void SConnection::initialiseProtocol()
{
- cp.writeVersion(os);
+ char str[13];
+
+ sprintf(str, "RFB %03d.%03d\n", defaultMajorVersion, defaultMinorVersion);
+ os->writeBytes(str, 12);
+ os->flush();
+
state_ = RFBSTATE_PROTOCOL_VERSION;
}
@@ -104,35 +109,47 @@ void SConnection::processMsg()
void SConnection::processVersionMsg()
{
+ char verStr[13];
+ int majorVersion;
+ int minorVersion;
+
vlog.debug("reading protocol version");
- bool done;
- if (!cp.readVersion(is, &done)) {
+
+ if (!is->checkNoWait(12))
+ return;
+
+ is->readBytes(verStr, 12);
+ verStr[12] = '\0';
+
+ if (sscanf(verStr, "RFB %03d.%03d\n",
+ &majorVersion, &minorVersion) != 2) {
state_ = RFBSTATE_INVALID;
throw Exception("reading version failed: not an RFB client?");
}
- if (!done) return;
+
+ client.setVersion(majorVersion, minorVersion);
vlog.info("Client needs protocol version %d.%d",
- cp.majorVersion, cp.minorVersion);
+ client.majorVersion, client.minorVersion);
- if (cp.majorVersion != 3) {
+ if (client.majorVersion != 3) {
// unknown protocol version
throwConnFailedException("Client needs protocol version %d.%d, server has %d.%d",
- cp.majorVersion, cp.minorVersion,
+ client.majorVersion, client.minorVersion,
defaultMajorVersion, defaultMinorVersion);
}
- if (cp.minorVersion != 3 && cp.minorVersion != 7 && cp.minorVersion != 8) {
+ if (client.minorVersion != 3 && client.minorVersion != 7 && client.minorVersion != 8) {
vlog.error("Client uses unofficial protocol version %d.%d",
- cp.majorVersion,cp.minorVersion);
- if (cp.minorVersion >= 8)
- cp.minorVersion = 8;
- else if (cp.minorVersion == 7)
- cp.minorVersion = 7;
+ client.majorVersion,client.minorVersion);
+ if (client.minorVersion >= 8)
+ client.minorVersion = 8;
+ else if (client.minorVersion == 7)
+ client.minorVersion = 7;
else
- cp.minorVersion = 3;
+ client.minorVersion = 3;
vlog.error("Assuming compatibility with version %d.%d",
- cp.majorVersion,cp.minorVersion);
+ client.majorVersion,client.minorVersion);
}
versionReceived();
@@ -141,7 +158,7 @@ void SConnection::processVersionMsg()
std::list<rdr::U8>::iterator i;
secTypes = security.GetEnabledSecTypes();
- if (cp.isVersion(3,3)) {
+ if (client.isVersion(3,3)) {
// cope with legacy 3.3 client only if "no authentication" or "vnc
// authentication" is supported.
@@ -150,7 +167,7 @@ void SConnection::processVersionMsg()
}
if (i == secTypes.end()) {
throwConnFailedException("No supported security type for %d.%d client",
- cp.majorVersion, cp.minorVersion);
+ client.majorVersion, client.minorVersion);
}
os->writeU32(*i);
@@ -220,7 +237,7 @@ void SConnection::processSecurityMsg()
} catch (AuthFailureException& e) {
vlog.error("AuthFailureException: %s", e.str());
os->writeU32(secResultFailed);
- if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
+ if (!client.beforeVersion(3,8)) // 3.8 onwards have failure message
os->writeString(e.str());
os->flush();
throw;
@@ -245,7 +262,7 @@ void SConnection::throwConnFailedException(const char* format, ...)
vlog.info("Connection failed: %s", str);
if (state_ == RFBSTATE_PROTOCOL_VERSION) {
- if (cp.majorVersion == 3 && cp.minorVersion == 3) {
+ if (client.majorVersion == 3 && client.minorVersion == 3) {
os->writeU32(0);
os->writeString(str);
os->flush();
@@ -308,12 +325,12 @@ void SConnection::approveConnection(bool accept, const char* reason)
if (state_ != RFBSTATE_QUERYING)
throw Exception("SConnection::approveConnection: invalid state");
- if (!cp.beforeVersion(3,8) || ssecurity->getType() != secTypeNone) {
+ if (!client.beforeVersion(3,8) || ssecurity->getType() != secTypeNone) {
if (accept) {
os->writeU32(secResultOK);
} else {
os->writeU32(secResultFailed);
- if (!cp.beforeVersion(3,8)) { // 3.8 onwards have failure message
+ if (!client.beforeVersion(3,8)) { // 3.8 onwards have failure message
if (reason)
os->writeString(reason);
else
@@ -326,7 +343,7 @@ void SConnection::approveConnection(bool accept, const char* reason)
if (accept) {
state_ = RFBSTATE_INITIALISATION;
reader_ = new SMsgReader(this, is);
- writer_ = new SMsgWriter(&cp, os);
+ writer_ = new SMsgWriter(&client, os);
authSuccess();
} else {
state_ = RFBSTATE_INVALID;
@@ -339,7 +356,8 @@ void SConnection::approveConnection(bool accept, const char* reason)
void SConnection::clientInit(bool shared)
{
- writer_->writeServerInit();
+ writer_->writeServerInit(client.width(), client.height(),
+ client.pf(), client.name());
state_ = RFBSTATE_NORMAL;
}
@@ -360,7 +378,7 @@ void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental)
{
if (!readyForSetColourMapEntries) {
readyForSetColourMapEntries = true;
- if (!cp.pf().trueColour) {
+ if (!client.pf().trueColour) {
writeFakeColourMap();
}
}
@@ -388,7 +406,7 @@ void SConnection::writeFakeColourMap(void)
rdr::U16 red[256], green[256], blue[256];
for (i = 0;i < 256;i++)
- cp.pf().rgbFromPixel(i, &red[i], &green[i], &blue[i]);
+ client.pf().rgbFromPixel(i, &red[i], &green[i], &blue[i]);
writer()->writeSetColourMapEntries(0, 256, red, green, blue);
}
diff --git a/common/rfb/SMsgHandler.cxx b/common/rfb/SMsgHandler.cxx
index c38458c3..f952ec2b 100644
--- a/common/rfb/SMsgHandler.cxx
+++ b/common/rfb/SMsgHandler.cxx
@@ -19,6 +19,7 @@
#include <rfb/Exception.h>
#include <rfb/SMsgHandler.h>
#include <rfb/ScreenSet.h>
+#include <rfb/encodings.h>
using namespace rfb;
@@ -36,7 +37,7 @@ void SMsgHandler::clientInit(bool shared)
void SMsgHandler::setPixelFormat(const PixelFormat& pf)
{
- cp.setPF(pf);
+ client.setPF(pf);
}
void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
@@ -44,22 +45,22 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
bool firstFence, firstContinuousUpdates, firstLEDState,
firstQEMUKeyEvent;
- firstFence = !cp.supportsFence;
- firstContinuousUpdates = !cp.supportsContinuousUpdates;
- firstLEDState = !cp.supportsLEDState;
- firstQEMUKeyEvent = !cp.supportsQEMUKeyEvent;
+ firstFence = !client.supportsFence();
+ firstContinuousUpdates = !client.supportsContinuousUpdates();
+ firstLEDState = !client.supportsLEDState();
+ firstQEMUKeyEvent = !client.supportsEncoding(pseudoEncodingQEMUKeyEvent);
- cp.setEncodings(nEncodings, encodings);
+ client.setEncodings(nEncodings, encodings);
supportsLocalCursor();
- if (cp.supportsFence && firstFence)
+ if (client.supportsFence() && firstFence)
supportsFence();
- if (cp.supportsContinuousUpdates && firstContinuousUpdates)
+ if (client.supportsContinuousUpdates() && firstContinuousUpdates)
supportsContinuousUpdates();
- if (cp.supportsLEDState && firstLEDState)
+ if (client.supportsLEDState() && firstLEDState)
supportsLEDState();
- if (cp.supportsQEMUKeyEvent && firstQEMUKeyEvent)
+ if (client.supportsEncoding(pseudoEncodingQEMUKeyEvent) && firstQEMUKeyEvent)
supportsQEMUKeyEvent();
}
@@ -82,12 +83,3 @@ void SMsgHandler::supportsLEDState()
void SMsgHandler::supportsQEMUKeyEvent()
{
}
-
-void SMsgHandler::setDesktopSize(int fb_width, int fb_height,
- const ScreenSet& layout)
-{
- cp.width = fb_width;
- cp.height = fb_height;
- cp.screenLayout = layout;
-}
-
diff --git a/common/rfb/SMsgHandler.h b/common/rfb/SMsgHandler.h
index 749f0560..8548d911 100644
--- a/common/rfb/SMsgHandler.h
+++ b/common/rfb/SMsgHandler.h
@@ -25,7 +25,7 @@
#include <rdr/types.h>
#include <rfb/PixelFormat.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ClientParams.h>
#include <rfb/InputHandler.h>
#include <rfb/ScreenSet.h>
@@ -40,8 +40,8 @@ namespace rfb {
// The following methods are called as corresponding messages are read. A
// derived class should override these methods as desired. Note that for
- // the setPixelFormat(), setEncodings() and setDesktopSize() methods, a
- // derived class must call on to SMsgHandler's methods.
+ // the setPixelFormat(), and setEncodings() methods, a derived class must
+ // call on to SMsgHandler's methods.
virtual void clientInit(bool shared);
@@ -85,7 +85,7 @@ namespace rfb {
// handler will send a pseudo-rect back, signalling server support.
virtual void supportsQEMUKeyEvent();
- ConnParams cp;
+ ClientParams client;
};
}
#endif
diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx
index 3da9413f..a12a6d40 100644
--- a/common/rfb/SMsgWriter.cxx
+++ b/common/rfb/SMsgWriter.cxx
@@ -22,7 +22,7 @@
#include <rfb/msgTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/Exception.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ClientParams.h>
#include <rfb/UpdateTracker.h>
#include <rfb/Encoder.h>
#include <rfb/SMsgWriter.h>
@@ -33,12 +33,10 @@ using namespace rfb;
static LogWriter vlog("SMsgWriter");
-SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
- : cp(cp_), os(os_),
+SMsgWriter::SMsgWriter(ClientParams* client_, rdr::OutStream* os_)
+ : client(client_), os(os_),
nRectsInUpdate(0), nRectsInHeader(0),
- needSetDesktopSize(false), needExtendedDesktopSize(false),
- needSetDesktopName(false), needSetCursor(false),
- needSetXCursor(false), needSetCursorWithAlpha(false),
+ needSetDesktopName(false), needCursor(false),
needLEDState(false), needQEMUKeyEvent(false)
{
}
@@ -47,12 +45,13 @@ SMsgWriter::~SMsgWriter()
{
}
-void SMsgWriter::writeServerInit()
+void SMsgWriter::writeServerInit(rdr::U16 width, rdr::U16 height,
+ const PixelFormat& pf, const char* name)
{
- os->writeU16(cp->width);
- os->writeU16(cp->height);
- cp->pf().write(os);
- os->writeString(cp->name());
+ os->writeU16(width);
+ os->writeU16(height);
+ pf.write(os);
+ os->writeString(name);
endMsg();
}
@@ -90,7 +89,7 @@ void SMsgWriter::writeServerCutText(const char* str, int len)
void SMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
{
- if (!cp->supportsFence)
+ if (!client->supportsEncoding(pseudoEncodingFence))
throw Exception("Client does not support fences");
if (len > 64)
throw Exception("Too large fence payload");
@@ -112,116 +111,68 @@ void SMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
void SMsgWriter::writeEndOfContinuousUpdates()
{
- if (!cp->supportsContinuousUpdates)
+ if (!client->supportsEncoding(pseudoEncodingContinuousUpdates))
throw Exception("Client does not support continuous updates");
startMsg(msgTypeEndOfContinuousUpdates);
endMsg();
}
-bool SMsgWriter::writeSetDesktopSize() {
- if (!cp->supportsDesktopResize)
- return false;
-
- needSetDesktopSize = true;
-
- return true;
-}
-
-bool SMsgWriter::writeExtendedDesktopSize() {
- if (!cp->supportsExtendedDesktopSize)
- return false;
-
- needExtendedDesktopSize = true;
-
- return true;
-}
-
-bool SMsgWriter::writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
- int fb_width, int fb_height,
- const ScreenSet& layout) {
+void SMsgWriter::writeDesktopSize(rdr::U16 reason, rdr::U16 result)
+{
ExtendedDesktopSizeMsg msg;
- if (!cp->supportsExtendedDesktopSize)
- return false;
+ if (!client->supportsEncoding(pseudoEncodingDesktopSize) &&
+ !client->supportsEncoding(pseudoEncodingExtendedDesktopSize))
+ throw Exception("Client does not support desktop size changes");
msg.reason = reason;
msg.result = result;
- msg.fb_width = fb_width;
- msg.fb_height = fb_height;
- msg.layout = layout;
extendedDesktopSizeMsgs.push_back(msg);
-
- return true;
}
-bool SMsgWriter::writeSetDesktopName() {
- if (!cp->supportsDesktopRename)
- return false;
-
- needSetDesktopName = true;
-
- return true;
-}
-
-bool SMsgWriter::writeSetCursor()
-{
- if (!cp->supportsLocalCursor)
- return false;
-
- needSetCursor = true;
-
- return true;
-}
-
-bool SMsgWriter::writeSetXCursor()
+void SMsgWriter::writeSetDesktopName()
{
- if (!cp->supportsLocalXCursor)
- return false;
-
- needSetXCursor = true;
+ if (!client->supportsEncoding(pseudoEncodingDesktopName))
+ throw Exception("Client does not support desktop name changes");
- return true;
+ needSetDesktopName = true;
}
-bool SMsgWriter::writeSetCursorWithAlpha()
+void SMsgWriter::writeCursor()
{
- if (!cp->supportsLocalCursorWithAlpha)
- return false;
+ if (!client->supportsEncoding(pseudoEncodingCursor) &&
+ !client->supportsEncoding(pseudoEncodingXCursor) &&
+ !client->supportsEncoding(pseudoEncodingCursorWithAlpha))
+ throw Exception("Client does not support local cursor");
- needSetCursorWithAlpha = true;
-
- return true;
+ needCursor = true;
}
-bool SMsgWriter::writeLEDState()
+void SMsgWriter::writeLEDState()
{
- if (!cp->supportsLEDState)
- return false;
- if (cp->ledState() == ledUnknown)
- return false;
+ if (!client->supportsEncoding(pseudoEncodingLEDState))
+ throw Exception("Client does not support LED state");
+ if (client->ledState() == ledUnknown)
+ throw Exception("Server has not specified LED state");
needLEDState = true;
-
- return true;
}
-bool SMsgWriter::writeQEMUKeyEvent()
+void SMsgWriter::writeQEMUKeyEvent()
{
- if (!cp->supportsQEMUKeyEvent)
- return false;
+ if (!client->supportsEncoding(pseudoEncodingQEMUKeyEvent))
+ throw Exception("Client does not support QEMU key events");
needQEMUKeyEvent = true;
-
- return true;
}
bool SMsgWriter::needFakeUpdate()
{
if (needSetDesktopName)
return true;
- if (needSetCursor || needSetXCursor || needSetCursorWithAlpha)
+ if (needCursor)
return true;
if (needLEDState)
return true;
@@ -235,9 +186,7 @@ bool SMsgWriter::needFakeUpdate()
bool SMsgWriter::needNoDataUpdate()
{
- if (needSetDesktopSize)
- return true;
- if (needExtendedDesktopSize || !extendedDesktopSizeMsgs.empty())
+ if (!extendedDesktopSizeMsgs.empty())
return true;
return false;
@@ -249,12 +198,12 @@ void SMsgWriter::writeNoDataUpdate()
nRects = 0;
- if (needSetDesktopSize)
- nRects++;
- if (needExtendedDesktopSize)
- nRects++;
- if (!extendedDesktopSizeMsgs.empty())
- nRects += extendedDesktopSizeMsgs.size();
+ if (!extendedDesktopSizeMsgs.empty()) {
+ if (client->supportsEncoding(pseudoEncodingExtendedDesktopSize))
+ nRects += extendedDesktopSizeMsgs.size();
+ else
+ nRects++;
+ }
writeFramebufferUpdateStart(nRects);
writeNoDataRects();
@@ -269,11 +218,7 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
if (nRects != 0xFFFF) {
if (needSetDesktopName)
nRects++;
- if (needSetCursor)
- nRects++;
- if (needSetXCursor)
- nRects++;
- if (needSetCursorWithAlpha)
+ if (needCursor)
nRects++;
if (needLEDState)
nRects++;
@@ -347,56 +292,52 @@ void SMsgWriter::endMsg()
void SMsgWriter::writePseudoRects()
{
- if (needSetCursor) {
- const Cursor& cursor = cp->cursor();
-
- rdr::U8Array data(cursor.width()*cursor.height() * (cp->pf().bpp/8));
- rdr::U8Array mask(cursor.getMask());
-
- const rdr::U8* in;
- rdr::U8* out;
-
- in = cursor.getBuffer();
- out = data.buf;
- for (int i = 0;i < cursor.width()*cursor.height();i++) {
- cp->pf().bufferFromRGB(out, in, 1);
- in += 4;
- out += cp->pf().bpp/8;
+ if (needCursor) {
+ const Cursor& cursor = client->cursor();
+
+ if (client->supportsEncoding(pseudoEncodingCursorWithAlpha)) {
+ writeSetCursorWithAlphaRect(cursor.width(), cursor.height(),
+ cursor.hotspot().x, cursor.hotspot().y,
+ cursor.getBuffer());
+ } else if (client->supportsEncoding(pseudoEncodingCursor)) {
+ rdr::U8Array data(cursor.width()*cursor.height() * (client->pf().bpp/8));
+ rdr::U8Array mask(cursor.getMask());
+
+ const rdr::U8* in;
+ rdr::U8* out;
+
+ in = cursor.getBuffer();
+ out = data.buf;
+ for (int i = 0;i < cursor.width()*cursor.height();i++) {
+ client->pf().bufferFromRGB(out, in, 1);
+ in += 4;
+ out += client->pf().bpp/8;
+ }
+
+ writeSetCursorRect(cursor.width(), cursor.height(),
+ cursor.hotspot().x, cursor.hotspot().y,
+ data.buf, mask.buf);
+ } else if (client->supportsEncoding(pseudoEncodingXCursor)) {
+ rdr::U8Array bitmap(cursor.getBitmap());
+ rdr::U8Array mask(cursor.getMask());
+
+ writeSetXCursorRect(cursor.width(), cursor.height(),
+ cursor.hotspot().x, cursor.hotspot().y,
+ bitmap.buf, mask.buf);
+ } else {
+ throw Exception("Client does not support local cursor");
}
- writeSetCursorRect(cursor.width(), cursor.height(),
- cursor.hotspot().x, cursor.hotspot().y,
- data.buf, mask.buf);
- needSetCursor = false;
- }
-
- if (needSetXCursor) {
- const Cursor& cursor = cp->cursor();
- rdr::U8Array bitmap(cursor.getBitmap());
- rdr::U8Array mask(cursor.getMask());
-
- writeSetXCursorRect(cursor.width(), cursor.height(),
- cursor.hotspot().x, cursor.hotspot().y,
- bitmap.buf, mask.buf);
- needSetXCursor = false;
- }
-
- if (needSetCursorWithAlpha) {
- const Cursor& cursor = cp->cursor();
-
- writeSetCursorWithAlphaRect(cursor.width(), cursor.height(),
- cursor.hotspot().x, cursor.hotspot().y,
- cursor.getBuffer());
- needSetCursorWithAlpha = false;
+ needCursor = false;
}
if (needSetDesktopName) {
- writeSetDesktopNameRect(cp->name());
+ writeSetDesktopNameRect(client->name());
needSetDesktopName = false;
}
if (needLEDState) {
- writeLEDStateRect(cp->ledState());
+ writeLEDStateRect(client->ledState());
needLEDState = false;
}
@@ -408,36 +349,30 @@ void SMsgWriter::writePseudoRects()
void SMsgWriter::writeNoDataRects()
{
- // Start with specific ExtendedDesktopSize messages
if (!extendedDesktopSizeMsgs.empty()) {
- std::list<ExtendedDesktopSizeMsg>::const_iterator ri;
-
- for (ri = extendedDesktopSizeMsgs.begin();ri != extendedDesktopSizeMsgs.end();++ri) {
- writeExtendedDesktopSizeRect(ri->reason, ri->result,
- ri->fb_width, ri->fb_height, ri->layout);
+ if (client->supportsEncoding(pseudoEncodingExtendedDesktopSize)) {
+ std::list<ExtendedDesktopSizeMsg>::const_iterator ri;
+ for (ri = extendedDesktopSizeMsgs.begin();ri != extendedDesktopSizeMsgs.end();++ri) {
+ // FIXME: We can probably skip multiple reasonServer entries
+ writeExtendedDesktopSizeRect(ri->reason, ri->result,
+ client->width(), client->height(),
+ client->screenLayout());
+ }
+ } else if (client->supportsEncoding(pseudoEncodingDesktopSize)) {
+ // Some clients assume this is the last rectangle so don't send anything
+ // more after this
+ writeSetDesktopSizeRect(client->width(), client->height());
+ } else {
+ throw Exception("Client does not support desktop size changes");
}
extendedDesktopSizeMsgs.clear();
}
-
- // Send this before SetDesktopSize to make life easier on the clients
- if (needExtendedDesktopSize) {
- writeExtendedDesktopSizeRect(0, 0, cp->width, cp->height,
- cp->screenLayout);
- needExtendedDesktopSize = false;
- }
-
- // Some clients assume this is the last rectangle so don't send anything
- // more after this
- if (needSetDesktopSize) {
- writeSetDesktopSizeRect(cp->width, cp->height);
- needSetDesktopSize = false;
- }
}
void SMsgWriter::writeSetDesktopSizeRect(int width, int height)
{
- if (!cp->supportsDesktopResize)
+ if (!client->supportsEncoding(pseudoEncodingDesktopSize))
throw Exception("Client does not support desktop resize");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeSetDesktopSizeRect: nRects out of sync");
@@ -457,7 +392,7 @@ void SMsgWriter::writeExtendedDesktopSizeRect(rdr::U16 reason,
{
ScreenSet::const_iterator si;
- if (!cp->supportsExtendedDesktopSize)
+ if (!client->supportsEncoding(pseudoEncodingExtendedDesktopSize))
throw Exception("Client does not support extended desktop resize");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeExtendedDesktopSizeRect: nRects out of sync");
@@ -483,7 +418,7 @@ void SMsgWriter::writeExtendedDesktopSizeRect(rdr::U16 reason,
void SMsgWriter::writeSetDesktopNameRect(const char *name)
{
- if (!cp->supportsDesktopRename)
+ if (!client->supportsEncoding(pseudoEncodingDesktopName))
throw Exception("Client does not support desktop rename");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeSetDesktopNameRect: nRects out of sync");
@@ -500,7 +435,7 @@ void SMsgWriter::writeSetCursorRect(int width, int height,
int hotspotX, int hotspotY,
const void* data, const void* mask)
{
- if (!cp->supportsLocalCursor)
+ if (!client->supportsEncoding(pseudoEncodingCursor))
throw Exception("Client does not support local cursors");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeSetCursorRect: nRects out of sync");
@@ -510,7 +445,7 @@ void SMsgWriter::writeSetCursorRect(int width, int height,
os->writeU16(width);
os->writeU16(height);
os->writeU32(pseudoEncodingCursor);
- os->writeBytes(data, width * height * (cp->pf().bpp/8));
+ os->writeBytes(data, width * height * (client->pf().bpp/8));
os->writeBytes(mask, (width+7)/8 * height);
}
@@ -518,7 +453,7 @@ void SMsgWriter::writeSetXCursorRect(int width, int height,
int hotspotX, int hotspotY,
const void* data, const void* mask)
{
- if (!cp->supportsLocalXCursor)
+ if (!client->supportsEncoding(pseudoEncodingXCursor))
throw Exception("Client does not support local cursors");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeSetXCursorRect: nRects out of sync");
@@ -544,7 +479,7 @@ void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height,
int hotspotX, int hotspotY,
const rdr::U8* data)
{
- if (!cp->supportsLocalCursorWithAlpha)
+ if (!client->supportsEncoding(pseudoEncodingCursorWithAlpha))
throw Exception("Client does not support local cursors");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeSetCursorWithAlphaRect: nRects out of sync");
@@ -570,9 +505,9 @@ void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height,
void SMsgWriter::writeLEDStateRect(rdr::U8 state)
{
- if (!cp->supportsLEDState)
+ if (!client->supportsEncoding(pseudoEncodingLEDState))
throw Exception("Client does not support LED state updates");
- if (cp->ledState() == ledUnknown)
+ if (client->ledState() == ledUnknown)
throw Exception("Server does not support LED state updates");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeLEDStateRect: nRects out of sync");
@@ -587,7 +522,7 @@ void SMsgWriter::writeLEDStateRect(rdr::U8 state)
void SMsgWriter::writeQEMUKeyEventRect()
{
- if (!cp->supportsQEMUKeyEvent)
+ if (!client->supportsEncoding(pseudoEncodingQEMUKeyEvent))
throw Exception("Client does not support QEMU extended key events");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeQEMUKeyEventRect: nRects out of sync");
diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h
index e9859416..80f6de91 100644
--- a/common/rfb/SMsgWriter.h
+++ b/common/rfb/SMsgWriter.h
@@ -31,17 +31,19 @@ namespace rdr { class OutStream; }
namespace rfb {
- class ConnParams;
+ class ClientParams;
+ class PixelFormat;
struct ScreenSet;
class SMsgWriter {
public:
- SMsgWriter(ConnParams* cp, rdr::OutStream* os);
+ SMsgWriter(ClientParams* client, rdr::OutStream* os);
virtual ~SMsgWriter();
// writeServerInit() must only be called at the appropriate time in the
// protocol initialisation.
- void writeServerInit();
+ void writeServerInit(rdr::U16 width, rdr::U16 height,
+ const PixelFormat& pf, const char* name);
// Methods to write normal protocol messages
@@ -63,30 +65,21 @@ namespace rfb {
// updates mode.
void writeEndOfContinuousUpdates();
- // writeSetDesktopSize() won't actually write immediately, but will
+ // writeDesktopSize() won't actually write immediately, but will
// write the relevant pseudo-rectangle as part of the next update.
- bool writeSetDesktopSize();
- // Same thing for the extended version. The first version queues up a
- // generic update of the current server state, but the second queues a
- // specific message.
- bool writeExtendedDesktopSize();
- bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
- int fb_width, int fb_height,
- const ScreenSet& layout);
+ void writeDesktopSize(rdr::U16 reason, rdr::U16 result=0);
- bool writeSetDesktopName();
+ void writeSetDesktopName();
// Like setDesktopSize, we can't just write out a cursor message
// immediately.
- bool writeSetCursor();
- bool writeSetXCursor();
- bool writeSetCursorWithAlpha();
+ void writeCursor();
// Same for LED state message
- bool writeLEDState();
+ void writeLEDState();
// And QEMU keyboard event handshake
- bool writeQEMUKeyEvent();
+ void writeQEMUKeyEvent();
// needFakeUpdate() returns true when an immediate update is needed in
// order to flush out pseudo-rectangles to the client.
@@ -140,25 +133,19 @@ namespace rfb {
void writeLEDStateRect(rdr::U8 state);
void writeQEMUKeyEventRect();
- ConnParams* cp;
+ ClientParams* client;
rdr::OutStream* os;
int nRectsInUpdate;
int nRectsInHeader;
- bool needSetDesktopSize;
- bool needExtendedDesktopSize;
bool needSetDesktopName;
- bool needSetCursor;
- bool needSetXCursor;
- bool needSetCursorWithAlpha;
+ bool needCursor;
bool needLEDState;
bool needQEMUKeyEvent;
typedef struct {
rdr::U16 reason, result;
- int fb_width, fb_height;
- ScreenSet layout;
} ExtendedDesktopSizeMsg;
std::list<ExtendedDesktopSizeMsg> extendedDesktopSizeMsgs;
diff --git a/common/rfb/ServerParams.cxx b/common/rfb/ServerParams.cxx
new file mode 100644
index 00000000..bfeb80d6
--- /dev/null
+++ b/common/rfb/ServerParams.cxx
@@ -0,0 +1,84 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ * Copyright 2014-2018 Pierre Ossman for Cendio AB
+ *
+ * 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 <rfb/Exception.h>
+#include <rfb/ledStates.h>
+#include <rfb/ServerParams.h>
+
+using namespace rfb;
+
+ServerParams::ServerParams()
+ : majorVersion(0), minorVersion(0),
+ supportsQEMUKeyEvent(false),
+ supportsSetDesktopSize(false), supportsFence(false),
+ supportsContinuousUpdates(false),
+ width_(0), height_(0), name_(0),
+ ledState_(ledUnknown)
+{
+ setName("");
+ cursor_ = new Cursor(0, 0, Point(), NULL);
+}
+
+ServerParams::~ServerParams()
+{
+ delete [] name_;
+ delete cursor_;
+}
+
+void ServerParams::setDimensions(int width, int height)
+{
+ ScreenSet layout;
+ layout.add_screen(rfb::Screen(0, 0, 0, width, height, 0));
+ setDimensions(width, height, layout);
+}
+
+void ServerParams::setDimensions(int width, int height, const ScreenSet& layout)
+{
+ if (!layout.validate(width, height))
+ throw Exception("Attempted to configure an invalid screen layout");
+
+ width_ = width;
+ height_ = height;
+ screenLayout_ = layout;
+}
+
+void ServerParams::setPF(const PixelFormat& pf)
+{
+ pf_ = pf;
+
+ if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)
+ throw Exception("setPF: not 8, 16 or 32 bpp?");
+}
+
+void ServerParams::setName(const char* name)
+{
+ delete [] name_;
+ name_ = strDup(name);
+}
+
+void ServerParams::setCursor(const Cursor& other)
+{
+ delete cursor_;
+ cursor_ = new Cursor(other);
+}
+
+void ServerParams::setLEDState(unsigned int state)
+{
+ ledState_ = state;
+}
diff --git a/common/rfb/ServerParams.h b/common/rfb/ServerParams.h
new file mode 100644
index 00000000..7a58ea37
--- /dev/null
+++ b/common/rfb/ServerParams.h
@@ -0,0 +1,89 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2014-2018 Pierre Ossman for Cendio AB
+ *
+ * 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.
+ */
+//
+// ServerParams - structure describing the current state of the remote server
+//
+
+#ifndef __RFB_SERVERPARAMS_H__
+#define __RFB_SERVERPARAMS_H__
+
+#include <rfb/Cursor.h>
+#include <rfb/PixelFormat.h>
+#include <rfb/ScreenSet.h>
+
+namespace rfb {
+
+ class ServerParams {
+ public:
+ ServerParams();
+ ~ServerParams();
+
+ int majorVersion;
+ int minorVersion;
+
+ void setVersion(int major, int minor) {
+ majorVersion = major; minorVersion = minor;
+ }
+ bool isVersion(int major, int minor) const {
+ return majorVersion == major && minorVersion == minor;
+ }
+ bool beforeVersion(int major, int minor) const {
+ return (majorVersion < major ||
+ (majorVersion == major && minorVersion < minor));
+ }
+ bool afterVersion(int major, int minor) const {
+ return !beforeVersion(major,minor+1);
+ }
+
+ const int width() const { return width_; }
+ const int height() const { return height_; }
+ const ScreenSet& screenLayout() const { return screenLayout_; }
+ void setDimensions(int width, int height);
+ void setDimensions(int width, int height, const ScreenSet& layout);
+
+ const PixelFormat& pf() const { return pf_; }
+ void setPF(const PixelFormat& pf);
+
+ const char* name() const { return name_; }
+ void setName(const char* name);
+
+ const Cursor& cursor() const { return *cursor_; }
+ void setCursor(const Cursor& cursor);
+
+ unsigned int ledState() { return ledState_; }
+ void setLEDState(unsigned int state);
+
+ bool supportsQEMUKeyEvent;
+ bool supportsSetDesktopSize;
+ bool supportsFence;
+ bool supportsContinuousUpdates;
+
+ private:
+
+ int width_;
+ int height_;
+ ScreenSet screenLayout_;
+
+ PixelFormat pf_;
+ char* name_;
+ Cursor* cursor_;
+ unsigned int ledState_;
+ };
+}
+#endif
diff --git a/common/rfb/TightDecoder.cxx b/common/rfb/TightDecoder.cxx
index 548c1906..5b7c553d 100644
--- a/common/rfb/TightDecoder.cxx
+++ b/common/rfb/TightDecoder.cxx
@@ -25,7 +25,7 @@
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ServerParams.h>
#include <rfb/Exception.h>
#include <rfb/PixelBuffer.h>
#include <rfb/TightConstants.h>
@@ -55,7 +55,7 @@ TightDecoder::~TightDecoder()
}
void TightDecoder::readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os)
+ const ServerParams& server, rdr::OutStream* os)
{
rdr::U8 comp_ctl;
@@ -66,10 +66,10 @@ void TightDecoder::readRect(const Rect& r, rdr::InStream* is,
// "Fill" compression type.
if (comp_ctl == tightFill) {
- if (cp.pf().is888())
+ if (server.pf().is888())
os->copyBytes(is, 3);
else
- os->copyBytes(is, cp.pf().bpp/8);
+ os->copyBytes(is, server.pf().bpp/8);
return;
}
@@ -106,13 +106,13 @@ void TightDecoder::readRect(const Rect& r, rdr::InStream* is,
palSize = is->readU8() + 1;
os->writeU8(palSize - 1);
- if (cp.pf().is888())
+ if (server.pf().is888())
os->copyBytes(is, palSize * 3);
else
- os->copyBytes(is, palSize * cp.pf().bpp/8);
+ os->copyBytes(is, palSize * server.pf().bpp/8);
break;
case tightFilterGradient:
- if (cp.pf().bpp == 8)
+ if (server.pf().bpp == 8)
throw Exception("TightDecoder: invalid BPP for gradient filter");
break;
case tightFilterCopy:
@@ -129,10 +129,10 @@ void TightDecoder::readRect(const Rect& r, rdr::InStream* is,
rowSize = (r.width() + 7) / 8;
else
rowSize = r.width();
- } else if (cp.pf().is888()) {
+ } else if (server.pf().is888()) {
rowSize = r.width() * 3;
} else {
- rowSize = r.width() * cp.pf().bpp/8;
+ rowSize = r.width() * server.pf().bpp/8;
}
dataSize = r.height() * rowSize;
@@ -154,7 +154,7 @@ bool TightDecoder::doRectsConflict(const Rect& rectA,
const Rect& rectB,
const void* bufferB,
size_t buflenB,
- const ConnParams& cp)
+ const ServerParams& server)
{
rdr::U8 comp_ctl_a, comp_ctl_b;
@@ -177,11 +177,11 @@ bool TightDecoder::doRectsConflict(const Rect& rectA,
}
void TightDecoder::decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
const rdr::U8* bufptr;
- const PixelFormat& pf = cp.pf();
+ const PixelFormat& pf = server.pf();
rdr::U8 comp_ctl;
diff --git a/common/rfb/TightDecoder.h b/common/rfb/TightDecoder.h
index 6eb93d2a..28b6c30f 100644
--- a/common/rfb/TightDecoder.h
+++ b/common/rfb/TightDecoder.h
@@ -32,16 +32,16 @@ namespace rfb {
TightDecoder();
virtual ~TightDecoder();
virtual void readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os);
+ const ServerParams& server, rdr::OutStream* os);
virtual bool doRectsConflict(const Rect& rectA,
const void* bufferA,
size_t buflenA,
const Rect& rectB,
const void* bufferB,
size_t buflenB,
- const ConnParams& cp);
+ const ServerParams& server);
virtual void decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb);
private:
diff --git a/common/rfb/TightEncoder.cxx b/common/rfb/TightEncoder.cxx
index 0d428f16..1b0792c4 100644
--- a/common/rfb/TightEncoder.cxx
+++ b/common/rfb/TightEncoder.cxx
@@ -23,7 +23,6 @@
#include <rfb/PixelBuffer.h>
#include <rfb/Palette.h>
#include <rfb/encodings.h>
-#include <rfb/ConnParams.h>
#include <rfb/SConnection.h>
#include <rfb/TightEncoder.h>
#include <rfb/TightConstants.h>
@@ -68,7 +67,7 @@ TightEncoder::~TightEncoder()
bool TightEncoder::isSupported()
{
- return conn->cp.supportsEncoding(encodingTight);
+ return conn->client.supportsEncoding(encodingTight);
}
void TightEncoder::setCompressLevel(int level)
diff --git a/common/rfb/TightJPEGEncoder.cxx b/common/rfb/TightJPEGEncoder.cxx
index 38cb4eb7..75575389 100644
--- a/common/rfb/TightJPEGEncoder.cxx
+++ b/common/rfb/TightJPEGEncoder.cxx
@@ -76,15 +76,15 @@ TightJPEGEncoder::~TightJPEGEncoder()
bool TightJPEGEncoder::isSupported()
{
- if (!conn->cp.supportsEncoding(encodingTight))
+ if (!conn->client.supportsEncoding(encodingTight))
return false;
// Any one of these indicates support for JPEG
- if (conn->cp.qualityLevel != -1)
+ if (conn->client.qualityLevel != -1)
return true;
- if (conn->cp.fineQualityLevel != -1)
+ if (conn->client.fineQualityLevel != -1)
return true;
- if (conn->cp.subsampling != -1)
+ if (conn->client.subsampling != -1)
return true;
// Tight support, but not JPEG
diff --git a/common/rfb/UpdateTracker.cxx b/common/rfb/UpdateTracker.cxx
index b53b8509..28e916d5 100644
--- a/common/rfb/UpdateTracker.cxx
+++ b/common/rfb/UpdateTracker.cxx
@@ -60,32 +60,17 @@ void ClippingUpdateTracker::add_copied(const Region &dest, const Point &delta) {
// SimpleUpdateTracker
-SimpleUpdateTracker::SimpleUpdateTracker(bool use_copyrect) {
- copy_enabled = use_copyrect;
+SimpleUpdateTracker::SimpleUpdateTracker() {
}
SimpleUpdateTracker::~SimpleUpdateTracker() {
}
-void SimpleUpdateTracker::enable_copyrect(bool enable) {
- if (!enable && copy_enabled) {
- add_changed(copied);
- copied.clear();
- }
- copy_enabled=enable;
-}
-
void SimpleUpdateTracker::add_changed(const Region &region) {
changed.assign_union(region);
}
void SimpleUpdateTracker::add_copied(const Region &dest, const Point &delta) {
- // Do we support copyrect?
- if (!copy_enabled) {
- add_changed(dest);
- return;
- }
-
// Is there anything to do?
if (dest.is_empty()) return;
diff --git a/common/rfb/UpdateTracker.h b/common/rfb/UpdateTracker.h
index 8e96d55e..8983b378 100644
--- a/common/rfb/UpdateTracker.h
+++ b/common/rfb/UpdateTracker.h
@@ -68,11 +68,9 @@ namespace rfb {
class SimpleUpdateTracker : public UpdateTracker {
public:
- SimpleUpdateTracker(bool use_copyrect=true);
+ SimpleUpdateTracker();
virtual ~SimpleUpdateTracker();
- virtual void enable_copyrect(bool enable);
-
virtual void add_changed(const Region &region);
virtual void add_copied(const Region &dest, const Point &delta);
virtual void subtract(const Region& region);
@@ -94,7 +92,6 @@ namespace rfb {
Region changed;
Region copied;
Point copy_delta;
- bool copy_enabled;
};
}
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index dbbf1d80..ea5c52aa 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -49,7 +49,7 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
inProcessMessages(false),
pendingSyncFence(false), syncFence(false), fenceFlags(0),
fenceDataLen(0), fenceData(NULL), congestionTimer(this),
- losslessTimer(this), server(server_), updates(false),
+ losslessTimer(this), server(server_),
updateRenderedCursor(false), removeRenderedCursor(false),
continuousUpdates(false), encodeManager(this), idleTimer(this),
pointerEventTime(0), clientHasCursor(false)
@@ -199,9 +199,9 @@ void VNCSConnectionST::pixelBufferChange()
{
try {
if (!authenticated()) return;
- if (cp.width && cp.height &&
- (server->getPixelBuffer()->width() != cp.width ||
- server->getPixelBuffer()->height() != cp.height))
+ if (client.width() && client.height() &&
+ (server->getPixelBuffer()->width() != client.width() ||
+ server->getPixelBuffer()->height() != client.height()))
{
// We need to clip the next update to the new size, but also add any
// extra bits if it's bigger. If we wanted to do this exactly, something
@@ -211,26 +211,24 @@ void VNCSConnectionST::pixelBufferChange()
//updates.intersect(server->pb->getRect());
//
- //if (server->pb->width() > cp.width)
- // updates.add_changed(Rect(cp.width, 0, server->pb->width(),
+ //if (server->pb->width() > client.width())
+ // updates.add_changed(Rect(client.width(), 0, server->pb->width(),
// server->pb->height()));
- //if (server->pb->height() > cp.height)
- // updates.add_changed(Rect(0, cp.height, cp.width,
+ //if (server->pb->height() > client.height())
+ // updates.add_changed(Rect(0, client.height(), client.width(),
// server->pb->height()));
damagedCursorRegion.assign_intersect(server->getPixelBuffer()->getRect());
- cp.width = server->getPixelBuffer()->width();
- cp.height = server->getPixelBuffer()->height();
- cp.screenLayout = server->getScreenLayout();
+ client.setDimensions(server->getPixelBuffer()->width(),
+ server->getPixelBuffer()->height(),
+ server->getScreenLayout());
if (state() == RFBSTATE_NORMAL) {
- // We should only send EDS to client asking for both
- if (!writer()->writeExtendedDesktopSize()) {
- if (!writer()->writeSetDesktopSize()) {
- close("Client does not support desktop resize");
- return;
- }
+ if (!client.supportsDesktopSize()) {
+ close("Client does not support desktop resize");
+ return;
}
+ writer()->writeDesktopSize(reasonServer);
}
// Drop any lossy tracking that is now outside the framebuffer
@@ -325,7 +323,7 @@ bool VNCSConnectionST::getComparerState()
// We interpret a low compression level as an indication that the client
// wants to prioritise CPU usage over bandwidth, and hence disable the
// comparing update tracker.
- return (cp.compressLevel == -1) || (cp.compressLevel > 1);
+ return (client.compressLevel == -1) || (client.compressLevel > 1);
}
@@ -363,8 +361,7 @@ bool VNCSConnectionST::needRenderedCursor()
if (state() != RFBSTATE_NORMAL)
return false;
- if (!cp.supportsLocalCursorWithAlpha &&
- !cp.supportsLocalCursor && !cp.supportsLocalXCursor)
+ if (!client.supportsLocalCursor())
return true;
if (!server->getCursorPos().equals(pointerEventPos) &&
(time(0) - pointerEventTime) > 0)
@@ -394,16 +391,16 @@ void VNCSConnectionST::authSuccess()
idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
// - Set the connection parameters appropriately
- cp.width = server->getPixelBuffer()->width();
- cp.height = server->getPixelBuffer()->height();
- cp.screenLayout = server->getScreenLayout();
- cp.setName(server->getName());
- cp.setLEDState(server->getLEDState());
+ client.setDimensions(server->getPixelBuffer()->width(),
+ server->getPixelBuffer()->height(),
+ server->getScreenLayout());
+ client.setName(server->getName());
+ client.setLEDState(server->getLEDState());
// - Set the default pixel format
- cp.setPF(server->getPixelBuffer()->getPF());
+ client.setPF(server->getPixelBuffer()->getPF());
char buffer[256];
- cp.pf().print(buffer, 256);
+ client.pf().print(buffer, 256);
vlog.info("Server default pixel format %s", buffer);
// - Mark the entire display as "dirty"
@@ -492,7 +489,7 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
// Lock key heuristics
// (only for clients that do not support the LED state extension)
- if (!cp.supportsLEDState) {
+ if (!client.supportsLEDState()) {
// Always ignore ScrollLock as we don't have a heuristic
// for that
if (keysym == XK_Scroll_Lock) {
@@ -597,10 +594,11 @@ void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
SConnection::framebufferUpdateRequest(r, incremental);
// Check that the client isn't sending crappy requests
- if (!r.enclosed_by(Rect(0, 0, cp.width, cp.height))) {
+ if (!r.enclosed_by(Rect(0, 0, client.width(), client.height()))) {
vlog.error("FramebufferUpdateRequest %dx%d at %d,%d exceeds framebuffer %dx%d",
- r.width(), r.height(), r.tl.x, r.tl.y, cp.width, cp.height);
- safeRect = r.intersect(Rect(0, 0, cp.width, cp.height));
+ r.width(), r.height(), r.tl.x, r.tl.y,
+ client.width(), client.height());
+ safeRect = r.intersect(Rect(0, 0, client.width(), client.height()));
} else {
safeRect = r;
}
@@ -617,7 +615,8 @@ void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
// And send the screen layout to the client (which, unlike the
// framebuffer dimensions, the client doesn't get during init)
- writer()->writeExtendedDesktopSize();
+ if (client.supportsEncoding(pseudoEncodingExtendedDesktopSize))
+ writer()->writeDesktopSize(reasonServer);
// We do not send a DesktopSize since it only contains the
// framebuffer size (which the client already should know) and
@@ -635,8 +634,7 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,
if (!rfb::Server::acceptSetDesktopSize) return;
result = server->setDesktopSize(this, fb_width, fb_height, layout);
- writer()->writeExtendedDesktopSize(reasonClient, result,
- fb_width, fb_height, layout);
+ writer()->writeDesktopSize(reasonClient, result);
}
void VNCSConnectionST::fence(rdr::U32 flags, unsigned len, const char data[])
@@ -688,7 +686,7 @@ void VNCSConnectionST::enableContinuousUpdates(bool enable,
{
Rect rect;
- if (!cp.supportsFence || !cp.supportsContinuousUpdates)
+ if (!client.supportsFence() || !client.supportsContinuousUpdates())
throw Exception("Client tried to enable continuous updates when not allowed");
continuousUpdates = enable;
@@ -704,7 +702,7 @@ void VNCSConnectionST::enableContinuousUpdates(bool enable,
}
// supportsLocalCursor() is called whenever the status of
-// cp.supportsLocalCursor has changed. If the client does now support local
+// client.supportsLocalCursor() has changed. If the client does now support local
// cursor, we make sure that the old server-side rendered cursor is cleaned up
// and the cursor is sent to the client.
@@ -726,7 +724,7 @@ void VNCSConnectionST::supportsContinuousUpdates()
{
// We refuse to use continuous updates if we cannot monitor the buffer
// usage using fences.
- if (!cp.supportsFence)
+ if (!client.supportsFence())
return;
writer()->writeEndOfContinuousUpdates();
@@ -734,6 +732,9 @@ void VNCSConnectionST::supportsContinuousUpdates()
void VNCSConnectionST::supportsLEDState()
{
+ if (client.ledState() == ledUnknown)
+ return;
+
writer()->writeLEDState();
}
@@ -772,7 +773,7 @@ void VNCSConnectionST::writeRTTPing()
{
char type;
- if (!cp.supportsFence)
+ if (!client.supportsFence())
return;
congestion.updatePosition(sock->outStream().length());
@@ -799,7 +800,7 @@ bool VNCSConnectionST::isCongested()
if (sock->outStream().bufferUsage() > 0)
return true;
- if (!cp.supportsFence)
+ if (!client.supportsFence())
return false;
congestion.updatePosition(sock->outStream().length());
@@ -876,8 +877,6 @@ void VNCSConnectionST::writeDataUpdate()
bool needNewUpdateInfo;
const RenderedCursor *cursor;
- updates.enable_copyrect(cp.useCopyRect);
-
// See what the client has requested (if anything)
if (continuousUpdates)
req = cuRegion.union_(requested);
@@ -1063,13 +1062,13 @@ void VNCSConnectionST::screenLayoutChange(rdr::U16 reason)
if (!authenticated())
return;
- cp.screenLayout = server->getScreenLayout();
+ client.setDimensions(client.width(), client.height(),
+ server->getScreenLayout());
if (state() != RFBSTATE_NORMAL)
return;
- writer()->writeExtendedDesktopSize(reason, 0, cp.width, cp.height,
- cp.screenLayout);
+ writer()->writeDesktopSize(reason);
}
@@ -1084,34 +1083,26 @@ void VNCSConnectionST::setCursor()
// We need to blank out the client's cursor or there will be two
if (needRenderedCursor()) {
- cp.setCursor(emptyCursor);
+ client.setCursor(emptyCursor);
clientHasCursor = false;
} else {
- cp.setCursor(*server->getCursor());
+ client.setCursor(*server->getCursor());
clientHasCursor = true;
}
- if (!writer()->writeSetCursorWithAlpha()) {
- if (!writer()->writeSetCursor()) {
- if (!writer()->writeSetXCursor()) {
- // No client support
- return;
- }
- }
- }
+ if (client.supportsLocalCursor())
+ writer()->writeCursor();
}
void VNCSConnectionST::setDesktopName(const char *name)
{
- cp.setName(name);
+ client.setName(name);
if (state() != RFBSTATE_NORMAL)
return;
- if (!writer()->writeSetDesktopName()) {
- fprintf(stderr, "Client does not support desktop rename\n");
- return;
- }
+ if (client.supportsEncoding(pseudoEncodingDesktopName))
+ writer()->writeSetDesktopName();
}
void VNCSConnectionST::setLEDState(unsigned int ledstate)
@@ -1119,9 +1110,10 @@ void VNCSConnectionST::setLEDState(unsigned int ledstate)
if (state() != RFBSTATE_NORMAL)
return;
- cp.setLEDState(ledstate);
+ client.setLEDState(ledstate);
- writer()->writeLEDState();
+ if (client.supportsLEDState())
+ writer()->writeLEDState();
}
void VNCSConnectionST::setSocketTimeouts()
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index 40580b16..c95c14f0 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -255,8 +255,6 @@ void VNCServerST::setPixelBuffer(PixelBuffer* pb_, const ScreenSet& layout)
delete comparer;
comparer = 0;
- screenLayout = layout;
-
if (!pb) {
screenLayout = ScreenSet();
@@ -266,16 +264,17 @@ void VNCServerST::setPixelBuffer(PixelBuffer* pb_, const ScreenSet& layout)
return;
}
+ if (!layout.validate(pb->width(), pb->height()))
+ throw Exception("setPixelBuffer: invalid screen layout");
+
+ screenLayout = layout;
+
// Assume the framebuffer contents wasn't saved and reset everything
// that tracks its contents
comparer = new ComparingUpdateTracker(pb);
renderedCursorInvalid = true;
add_changed(pb->getRect());
- // Make sure that we have at least one screen
- if (screenLayout.num_screens() == 0)
- screenLayout.add_screen(Screen(0, 0, 0, pb->width(), pb->height(), 0));
-
std::list<VNCSConnectionST*>::iterator ci, ci_next;
for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
ci_next = ci; ci_next++;
@@ -309,6 +308,10 @@ void VNCServerST::setPixelBuffer(PixelBuffer* pb_)
}
}
+ // Make sure that we have at least one screen
+ if (layout.num_screens() == 0)
+ layout.add_screen(Screen(0, 0, 0, pb->width(), pb->height(), 0));
+
setPixelBuffer(pb_, layout);
}
diff --git a/common/rfb/ZRLEDecoder.cxx b/common/rfb/ZRLEDecoder.cxx
index 1dfb72af..9d1ff6b6 100644
--- a/common/rfb/ZRLEDecoder.cxx
+++ b/common/rfb/ZRLEDecoder.cxx
@@ -21,7 +21,7 @@
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
-#include <rfb/ConnParams.h>
+#include <rfb/ServerParams.h>
#include <rfb/PixelBuffer.h>
#include <rfb/ZRLEDecoder.h>
@@ -72,7 +72,7 @@ ZRLEDecoder::~ZRLEDecoder()
}
void ZRLEDecoder::readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os)
+ const ServerParams& server, rdr::OutStream* os)
{
rdr::U32 len;
@@ -82,11 +82,11 @@ void ZRLEDecoder::readRect(const Rect& r, rdr::InStream* is,
}
void ZRLEDecoder::decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
rdr::MemInStream is(buffer, buflen);
- const rfb::PixelFormat& pf = cp.pf();
+ const rfb::PixelFormat& pf = server.pf();
switch (pf.bpp) {
case 8: zrleDecode8 (r, &is, &zis, pf, pb); break;
case 16: zrleDecode16(r, &is, &zis, pf, pb); break;
diff --git a/common/rfb/ZRLEDecoder.h b/common/rfb/ZRLEDecoder.h
index 1e338510..a530586e 100644
--- a/common/rfb/ZRLEDecoder.h
+++ b/common/rfb/ZRLEDecoder.h
@@ -28,9 +28,9 @@ namespace rfb {
ZRLEDecoder();
virtual ~ZRLEDecoder();
virtual void readRect(const Rect& r, rdr::InStream* is,
- const ConnParams& cp, rdr::OutStream* os);
+ const ServerParams& server, rdr::OutStream* os);
virtual void decodeRect(const Rect& r, const void* buffer,
- size_t buflen, const ConnParams& cp,
+ size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb);
private:
rdr::ZlibInStream zis;
diff --git a/common/rfb/ZRLEEncoder.cxx b/common/rfb/ZRLEEncoder.cxx
index 8917d8ff..92fd13d1 100644
--- a/common/rfb/ZRLEEncoder.cxx
+++ b/common/rfb/ZRLEEncoder.cxx
@@ -19,7 +19,6 @@
#include <rdr/OutStream.h>
#include <rfb/Exception.h>
#include <rfb/encodings.h>
-#include <rfb/ConnParams.h>
#include <rfb/Palette.h>
#include <rfb/SConnection.h>
#include <rfb/ZRLEEncoder.h>
@@ -43,7 +42,7 @@ ZRLEEncoder::~ZRLEEncoder()
bool ZRLEEncoder::isSupported()
{
- return conn->cp.supportsEncoding(encodingZRLE);
+ return conn->client.supportsEncoding(encodingZRLE);
}
void ZRLEEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
diff --git a/tests/decperf.cxx b/tests/decperf.cxx
index 9061cb53..301e45e0 100644
--- a/tests/decperf.cxx
+++ b/tests/decperf.cxx
@@ -47,7 +47,7 @@ public:
CConn(const char *filename);
~CConn();
- virtual void setDesktopSize(int w, int h);
+ virtual void initDone();
virtual void setPixelFormat(const rfb::PixelFormat& pf);
virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*);
virtual void framebufferUpdateStart();
@@ -81,11 +81,11 @@ CConn::~CConn()
delete in;
}
-void CConn::setDesktopSize(int w, int h)
+void CConn::initDone()
{
- CConnection::setDesktopSize(w, h);
-
- setFramebuffer(new rfb::ManagedPixelBuffer(filePF, cp.width, cp.height));
+ setFramebuffer(new rfb::ManagedPixelBuffer(filePF,
+ server.width(),
+ server.height()));
}
void CConn::setPixelFormat(const rfb::PixelFormat& pf)
diff --git a/tests/encperf.cxx b/tests/encperf.cxx
index 733d55b6..6523eb72 100644
--- a/tests/encperf.cxx
+++ b/tests/encperf.cxx
@@ -89,7 +89,7 @@ public:
void getStats(double& ratio, unsigned long long& bytes,
unsigned long long& rawEquivalent);
- virtual void setDesktopSize(int w, int h);
+ virtual void initDone();
virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*);
virtual void framebufferUpdateStart();
virtual void framebufferUpdateEnd();
@@ -180,7 +180,7 @@ CConn::CConn(const char *filename)
setDesktopSize(width, height);
sc = new SConn();
- sc->cp.setPF((bool)translate ? fbPF : pf);
+ sc->client.setPF((bool)translate ? fbPF : pf);
sc->setEncodings(sizeof(encodings) / sizeof(*encodings), encodings);
}
@@ -196,14 +196,12 @@ void CConn::getStats(double& ratio, unsigned long long& bytes,
sc->getStats(ratio, bytes, rawEquivalent);
}
-void CConn::setDesktopSize(int w, int h)
+void CConn::initDone()
{
rfb::ModifiablePixelBuffer *pb;
- CConnection::setDesktopSize(w, h);
-
- pb = new rfb::ManagedPixelBuffer((bool)translate ? fbPF : cp.pf(),
- cp.width, cp.height);
+ pb = new rfb::ManagedPixelBuffer((bool)translate ? fbPF : server.pf(),
+ server.width(), server.height());
setFramebuffer(pb);
}
@@ -290,7 +288,7 @@ SConn::SConn()
out = new DummyOutStream;
setStreams(NULL, out);
- setWriter(new rfb::SMsgWriter(&cp, out));
+ setWriter(new rfb::SMsgWriter(&client, out));
manager = new Manager(this);
}
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
index 1fdc9e2c..564b2d51 100644
--- a/unix/x0vncserver/XDesktop.cxx
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -423,8 +423,27 @@ ScreenSet XDesktop::computeScreenLayout()
layout = ::computeScreenLayout(&outputIdMap);
XRRFreeScreenResources(res);
+
+ // Adjust the layout relative to the geometry
+ ScreenSet::iterator iter, iter_next;
+ Point offset(-geometry->offsetLeft(), -geometry->offsetTop());
+ for (iter = layout.begin();iter != layout.end();iter = iter_next) {
+ iter_next = iter; ++iter_next;
+ iter->dimensions = iter->dimensions.translate(offset);
+ if (iter->dimensions.enclosed_by(geometry->getRect()))
+ continue;
+ iter->dimensions = iter->dimensions.intersect(geometry->getRect());
+ if (iter->dimensions.is_empty()) {
+ layout.remove_screen(iter->id);
+ }
+ }
#endif
+ // Make sure that we have at least one screen
+ if (layout.num_screens() == 0)
+ layout.add_screen(rfb::Screen(0, 0, 0, geometry->width(),
+ geometry->height(), 0));
+
return layout;
}
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx
index 69186c55..b4610e6a 100644
--- a/vncviewer/CConn.cxx
+++ b/vncviewer/CConn.cxx
@@ -36,8 +36,6 @@
#include <rfb/screenTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/Timer.h>
-#include <rdr/MemInStream.h>
-#include <rdr/MemOutStream.h>
#include <network/TcpSocket.h>
#ifndef WIN32
#include <network/UnixSocket.h>
@@ -76,36 +74,21 @@ static const PixelFormat mediumColourPF(8, 8, false, true,
CConn::CConn(const char* vncServerName, network::Socket* socket=NULL)
: serverHost(0), serverPort(0), desktop(NULL),
- updateCount(0), pixelCount(0), pendingPFChange(false),
- currentEncoding(encodingTight), lastServerEncoding((unsigned int)-1),
- formatChange(false), encodingChange(false),
- firstUpdate(true), pendingUpdate(false), continuousUpdates(false),
- forceNonincremental(true), supportsSyncFence(false)
+ updateCount(0), pixelCount(0),
+ lastServerEncoding((unsigned int)-1)
{
setShared(::shared);
sock = socket;
- int encNum = encodingNum(preferredEncoding);
- if (encNum != -1)
- currentEncoding = encNum;
-
- cp.supportsLocalCursor = true;
-
- cp.supportsDesktopResize = true;
- cp.supportsExtendedDesktopSize = true;
- cp.supportsDesktopRename = true;
-
- cp.supportsLEDState = true;
+ supportsLocalCursor = true;
+ supportsDesktopResize = true;
+ supportsLEDState = true;
if (customCompressLevel)
- cp.compressLevel = compressLevel;
- else
- cp.compressLevel = -1;
+ setCompressLevel(::compressLevel);
if (!noJpeg)
- cp.qualityLevel = qualityLevel;
- else
- cp.qualityLevel = -1;
+ setQualityLevel(::qualityLevel);
if(sock == NULL) {
try {
@@ -158,16 +141,6 @@ CConn::~CConn()
delete sock;
}
-void CConn::refreshFramebuffer()
-{
- forceNonincremental = true;
-
- // Without fences, we cannot safely trigger an update request directly
- // but must wait for the next update to arrive.
- if (supportsSyncFence)
- requestNewUpdate();
-}
-
const char *CConn::connectionInfo()
{
static char infoText[1024] = "";
@@ -181,7 +154,7 @@ const char *CConn::connectionInfo()
infoText[0] = '\0';
snprintf(scratch, sizeof(scratch),
- _("Desktop name: %.80s"), cp.name());
+ _("Desktop name: %.80s"), server.name());
strcat(infoText, scratch);
strcat(infoText, "\n");
@@ -191,13 +164,13 @@ const char *CConn::connectionInfo()
strcat(infoText, "\n");
snprintf(scratch, sizeof(scratch),
- _("Size: %d x %d"), cp.width, cp.height);
+ _("Size: %d x %d"), server.width(), server.height());
strcat(infoText, scratch);
strcat(infoText, "\n");
// TRANSLATORS: Will be filled in with a string describing the
// protocol pixel format in a fairly language neutral way
- cp.pf().print(pfStr, 100);
+ server.pf().print(pfStr, 100);
snprintf(scratch, sizeof(scratch),
_("Pixel format: %s"), pfStr);
strcat(infoText, scratch);
@@ -211,7 +184,7 @@ const char *CConn::connectionInfo()
strcat(infoText, "\n");
snprintf(scratch, sizeof(scratch),
- _("Requested encoding: %s"), encodingName(currentEncoding));
+ _("Requested encoding: %s"), encodingName(getPreferredEncoding()));
strcat(infoText, scratch);
strcat(infoText, "\n");
@@ -226,7 +199,7 @@ const char *CConn::connectionInfo()
strcat(infoText, "\n");
snprintf(scratch, sizeof(scratch),
- _("Protocol version: %d.%d"), cp.majorVersion, cp.minorVersion);
+ _("Protocol version: %d.%d"), server.majorVersion, server.minorVersion);
strcat(infoText, scratch);
strcat(infoText, "\n");
@@ -310,34 +283,27 @@ void CConn::socketEvent(FL_SOCKET fd, void *data)
////////////////////// CConnection callback methods //////////////////////
-// serverInit() is called when the serverInit message has been received. At
+// initDone() is called when the serverInit message has been received. At
// this point we create the desktop window and display it. We also tell the
// server the pixel format and encodings to use and request the first update.
-void CConn::serverInit()
+void CConn::initDone()
{
- CConnection::serverInit();
-
// If using AutoSelect with old servers, start in FullColor
// mode. See comment in autoSelectFormatAndEncoding.
- if (cp.beforeVersion(3, 8) && autoSelect)
+ if (server.beforeVersion(3, 8) && autoSelect)
fullColour.setParam(true);
- serverPF = cp.pf();
+ serverPF = server.pf();
- desktop = new DesktopWindow(cp.width, cp.height, cp.name(), serverPF, this);
+ desktop = new DesktopWindow(server.width(), server.height(),
+ server.name(), serverPF, this);
fullColourPF = desktop->getPreferredPF();
// Force a switch to the format and encoding we'd like
- formatChange = encodingChange = true;
-
- // And kick off the update cycle
- requestNewUpdate();
-
- // This initial update request is a bit of a corner case, so we need
- // to help out setting the correct format here.
- assert(pendingPFChange);
- cp.setPF(pendingPF);
- pendingPFChange = false;
+ updatePixelFormat();
+ int encNum = encodingNum(::preferredEncoding);
+ if (encNum != -1)
+ setPreferredEncoding(encNum);
}
// setDesktopSize() is called when the desktop size changes (including when
@@ -366,8 +332,7 @@ void CConn::setExtendedDesktopSize(unsigned reason, unsigned result,
void CConn::setName(const char* name)
{
CConnection::setName(name);
- if (desktop)
- desktop->setName(name);
+ desktop->setName(name);
}
// framebufferUpdateStart() is called at the beginning of an update.
@@ -378,11 +343,6 @@ void CConn::framebufferUpdateStart()
{
CConnection::framebufferUpdateStart();
- // Note: This might not be true if sync fences are supported
- pendingUpdate = false;
-
- requestNewUpdate();
-
// Update the screen prematurely for very slow updates
Fl::add_timeout(1.0, handleUpdateTimeout, this);
}
@@ -400,22 +360,6 @@ void CConn::framebufferUpdateEnd()
Fl::remove_timeout(handleUpdateTimeout, this);
desktop->updateWindow();
- if (firstUpdate) {
- // We need fences to make extra update requests and continuous
- // updates "safe". See fence() for the next step.
- if (cp.supportsFence)
- writer()->writeFence(fenceFlagRequest | fenceFlagSyncNext, 0, NULL);
-
- firstUpdate = false;
- }
-
- // A format change has been scheduled and we are now past the update
- // with the old format. Time to active the new one.
- if (pendingPFChange) {
- cp.setPF(pendingPF);
- pendingPFChange = false;
- }
-
// Compute new settings based on updated bandwidth values
if (autoSelect)
autoSelectFormatAndEncoding();
@@ -469,27 +413,6 @@ void CConn::fence(rdr::U32 flags, unsigned len, const char data[])
writer()->writeFence(flags, len, data);
return;
}
-
- if (len == 0) {
- // Initial probe
- if (flags & fenceFlagSyncNext) {
- supportsSyncFence = true;
-
- if (cp.supportsContinuousUpdates) {
- vlog.info(_("Enabling continuous updates"));
- continuousUpdates = true;
- writer()->writeEnableContinuousUpdates(true, 0, 0, cp.width, cp.height);
- }
- }
- } else {
- // Pixel format change
- rdr::MemInStream memStream(data, len);
- PixelFormat pf;
-
- pf.read(&memStream);
-
- cp.setPF(pf);
- }
}
void CConn::setLEDState(unsigned int state)
@@ -504,13 +427,7 @@ void CConn::setLEDState(unsigned int state)
void CConn::resizeFramebuffer()
{
- if (!desktop)
- return;
-
- if (continuousUpdates)
- writer()->writeEnableContinuousUpdates(true, 0, 0, cp.width, cp.height);
-
- desktop->resizeFramebuffer(cp.width, cp.height);
+ desktop->resizeFramebuffer(server.width(), server.height());
}
// autoSelectFormatAndEncoding() chooses the format and encoding appropriate
@@ -533,13 +450,10 @@ void CConn::autoSelectFormatAndEncoding()
int kbitsPerSecond = sock->inStream().kbitsPerSecond();
unsigned int timeWaited = sock->inStream().timeWaited();
bool newFullColour = fullColour;
- int newQualityLevel = qualityLevel;
+ int newQualityLevel = ::qualityLevel;
// Always use Tight
- if (currentEncoding != encodingTight) {
- currentEncoding = encodingTight;
- encodingChange = true;
- }
+ setPreferredEncoding(encodingTight);
// Check that we have a decent bandwidth measurement
if ((kbitsPerSecond == 0) || (timeWaited < 10000))
@@ -552,16 +466,15 @@ void CConn::autoSelectFormatAndEncoding()
else
newQualityLevel = 6;
- if (newQualityLevel != qualityLevel) {
+ if (newQualityLevel != ::qualityLevel) {
vlog.info(_("Throughput %d kbit/s - changing to quality %d"),
kbitsPerSecond, newQualityLevel);
- cp.qualityLevel = newQualityLevel;
- qualityLevel.setParam(newQualityLevel);
- encodingChange = true;
+ ::qualityLevel.setParam(newQualityLevel);
+ setQualityLevel(newQualityLevel);
}
}
- if (cp.beforeVersion(3, 8)) {
+ if (server.beforeVersion(3, 8)) {
// Xvnc from TightVNC 1.2.9 sends out FramebufferUpdates with
// cursors "asynchronously". If this happens in the middle of a
// pixel format change, the server will encode the cursor with
@@ -582,76 +495,31 @@ void CConn::autoSelectFormatAndEncoding()
vlog.info(_("Throughput %d kbit/s - full color is now disabled"),
kbitsPerSecond);
fullColour.setParam(newFullColour);
- formatChange = true;
+ updatePixelFormat();
}
}
-// checkEncodings() sends a setEncodings message if one is needed.
-void CConn::checkEncodings()
-{
- if (encodingChange && writer()) {
- vlog.info(_("Using %s encoding"),encodingName(currentEncoding));
- writer()->writeSetEncodings(currentEncoding, true);
- encodingChange = false;
- }
-}
-
// requestNewUpdate() requests an update from the server, having set the
// format and encoding appropriately.
-void CConn::requestNewUpdate()
+void CConn::updatePixelFormat()
{
- if (formatChange) {
- PixelFormat pf;
-
- /* Catch incorrect requestNewUpdate calls */
- assert(!pendingUpdate || supportsSyncFence);
-
- if (fullColour) {
- pf = fullColourPF;
- } else {
- if (lowColourLevel == 0)
- pf = verylowColourPF;
- else if (lowColourLevel == 1)
- pf = lowColourPF;
- else
- pf = mediumColourPF;
- }
-
- if (supportsSyncFence) {
- // We let the fence carry the pixel format and switch once we
- // get the response back. That way we will be synchronised with
- // when the server switches.
- rdr::MemOutStream memStream;
-
- pf.write(&memStream);
-
- writer()->writeFence(fenceFlagRequest | fenceFlagSyncNext,
- memStream.length(), (const char*)memStream.data());
- } else {
- // New requests are sent out at the start of processing the last
- // one, so we cannot switch our internal format right now (doing so
- // would mean misdecoding the current update).
- pendingPFChange = true;
- pendingPF = pf;
- }
-
- char str[256];
- pf.print(str, 256);
- vlog.info(_("Using pixel format %s"),str);
- writer()->writeSetPixelFormat(pf);
+ PixelFormat pf;
- formatChange = false;
+ if (fullColour) {
+ pf = fullColourPF;
+ } else {
+ if (lowColourLevel == 0)
+ pf = verylowColourPF;
+ else if (lowColourLevel == 1)
+ pf = lowColourPF;
+ else
+ pf = mediumColourPF;
}
- checkEncodings();
-
- if (forceNonincremental || !continuousUpdates) {
- pendingUpdate = true;
- writer()->writeFramebufferUpdateRequest(Rect(0, 0, cp.width, cp.height),
- !forceNonincremental);
- }
-
- forceNonincremental = false;
+ char str[256];
+ pf.print(str, 256);
+ vlog.info(_("Using pixel format %s"),str);
+ setPF(pf);
}
void CConn::handleOptions(void *data)
@@ -663,50 +531,23 @@ void CConn::handleOptions(void *data)
// list is cheap. Avoid overriding what the auto logic has selected
// though.
if (!autoSelect) {
- int encNum = encodingNum(preferredEncoding);
+ int encNum = encodingNum(::preferredEncoding);
if (encNum != -1)
- self->currentEncoding = encNum;
+ self->setPreferredEncoding(encNum);
}
- self->cp.supportsLocalCursor = true;
-
if (customCompressLevel)
- self->cp.compressLevel = compressLevel;
+ self->setCompressLevel(::compressLevel);
else
- self->cp.compressLevel = -1;
+ self->setCompressLevel(-1);
if (!noJpeg && !autoSelect)
- self->cp.qualityLevel = qualityLevel;
+ self->setQualityLevel(::qualityLevel);
else
- self->cp.qualityLevel = -1;
-
- self->encodingChange = true;
-
- // Format changes refreshes the entire screen though and are therefore
- // very costly. It's probably worth the effort to see if it is necessary
- // here.
- PixelFormat pf;
+ self->setQualityLevel(-1);
- if (fullColour) {
- pf = self->fullColourPF;
- } else {
- if (lowColourLevel == 0)
- pf = verylowColourPF;
- else if (lowColourLevel == 1)
- pf = lowColourPF;
- else
- pf = mediumColourPF;
- }
-
- if (!pf.equal(self->cp.pf())) {
- self->formatChange = true;
-
- // Without fences, we cannot safely trigger an update request directly
- // but must wait for the next update to arrive.
- if (self->supportsSyncFence)
- self->requestNewUpdate();
- }
+ self->updatePixelFormat();
}
void CConn::handleUpdateTimeout(void *data)
diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h
index dd4ae893..2e3362ce 100644
--- a/vncviewer/CConn.h
+++ b/vncviewer/CConn.h
@@ -36,8 +36,6 @@ public:
CConn(const char* vncServerName, network::Socket* sock);
~CConn();
- void refreshFramebuffer();
-
const char *connectionInfo();
unsigned getUpdateCount();
@@ -51,7 +49,7 @@ public:
static void socketEvent(FL_SOCKET fd, void *data);
// CConnection callback methods
- void serverInit();
+ void initDone();
void setDesktopSize(int w, int h);
void setExtendedDesktopSize(unsigned reason, unsigned result,
@@ -81,8 +79,7 @@ private:
void resizeFramebuffer();
void autoSelectFormatAndEncoding();
- void checkEncodings();
- void requestNewUpdate();
+ void updatePixelFormat();
static void handleOptions(void *data);
@@ -101,21 +98,7 @@ private:
rfb::PixelFormat serverPF;
rfb::PixelFormat fullColourPF;
- bool pendingPFChange;
- rfb::PixelFormat pendingPF;
-
- int currentEncoding, lastServerEncoding;
-
- bool formatChange;
- bool encodingChange;
-
- bool firstUpdate;
- bool pendingUpdate;
- bool continuousUpdates;
-
- bool forceNonincremental;
-
- bool supportsSyncFence;
+ int lastServerEncoding;
};
#endif
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 1843485a..150c39bc 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -235,7 +235,7 @@ void DesktopWindow::setName(const char *name)
void DesktopWindow::updateWindow()
{
if (firstUpdate) {
- if (cc->cp.supportsSetDesktopSize) {
+ if (cc->server.supportsSetDesktopSize) {
// Hack: Wait until we're in the proper mode and position until
// resizing things, otherwise we might send the wrong thing.
if (delayedFullscreen)
@@ -487,7 +487,7 @@ void DesktopWindow::resize(int x, int y, int w, int h)
// d) We're not still waiting for startup fullscreen to kick in
//
if (not firstUpdate and not delayedFullscreen and
- ::remoteResize and cc->cp.supportsSetDesktopSize) {
+ ::remoteResize and cc->server.supportsSetDesktopSize) {
// We delay updating the remote desktop as we tend to get a flood
// of resize events as the user is dragging the window.
Fl::remove_timeout(handleResizeTimeout, this);
@@ -1014,14 +1014,14 @@ void DesktopWindow::handleResizeTimeout(void *data)
void DesktopWindow::remoteResize(int width, int height)
{
ScreenSet layout;
- ScreenSet::iterator iter;
+ ScreenSet::const_iterator iter;
if (!fullscreen_active() || (width > w()) || (height > h())) {
// In windowed mode (or the framebuffer is so large that we need
// to scroll) we just report a single virtual screen that covers
// the entire framebuffer.
- layout = cc->cp.screenLayout;
+ layout = cc->server.screenLayout();
// Not sure why we have no screens, but adding a new one should be
// safe as there is nothing to conflict with...
@@ -1077,8 +1077,8 @@ void DesktopWindow::remoteResize(int width, int height)
sy -= viewport_rect.tl.y;
// Look for perfectly matching existing screen...
- for (iter = cc->cp.screenLayout.begin();
- iter != cc->cp.screenLayout.end(); ++iter) {
+ for (iter = cc->server.screenLayout().begin();
+ iter != cc->server.screenLayout().end(); ++iter) {
if ((iter->dimensions.tl.x == sx) &&
(iter->dimensions.tl.y == sy) &&
(iter->dimensions.width() == sw) &&
@@ -1087,7 +1087,7 @@ void DesktopWindow::remoteResize(int width, int height)
}
// Found it?
- if (iter != cc->cp.screenLayout.end()) {
+ if (iter != cc->server.screenLayout().end()) {
layout.add_screen(*iter);
continue;
}
@@ -1095,13 +1095,13 @@ void DesktopWindow::remoteResize(int width, int height)
// Need to add a new one, which means we need to find an unused id
while (true) {
id = rand();
- for (iter = cc->cp.screenLayout.begin();
- iter != cc->cp.screenLayout.end(); ++iter) {
+ for (iter = cc->server.screenLayout().begin();
+ iter != cc->server.screenLayout().end(); ++iter) {
if (iter->id == id)
break;
}
- if (iter == cc->cp.screenLayout.end())
+ if (iter == cc->server.screenLayout().end())
break;
}
@@ -1115,14 +1115,14 @@ void DesktopWindow::remoteResize(int width, int height)
}
// Do we actually change anything?
- if ((width == cc->cp.width) &&
- (height == cc->cp.height) &&
- (layout == cc->cp.screenLayout))
+ if ((width == cc->server.width()) &&
+ (height == cc->server.height()) &&
+ (layout == cc->server.screenLayout()))
return;
char buffer[2048];
vlog.debug("Requesting framebuffer resize from %dx%d to %dx%d",
- cc->cp.width, cc->cp.height, width, height);
+ cc->server.width(), cc->server.height(), width, height);
layout.print(buffer, sizeof(buffer));
vlog.debug("%s", buffer);
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 18ed69e7..425cb9f2 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -425,7 +425,7 @@ void Viewport::pushLEDState()
unsigned int state;
// Server support?
- if (cc->cp.ledState() == ledUnknown)
+ if (cc->server.ledState() == ledUnknown)
return;
state = 0;
@@ -458,7 +458,7 @@ void Viewport::pushLEDState()
state |= ledNumLock;
// No support for Scroll Lock //
- state |= (cc->cp.ledState() & ledScrollLock);
+ state |= (cc->server.ledState() & ledScrollLock);
#else
unsigned int mask;
@@ -484,17 +484,17 @@ void Viewport::pushLEDState()
state |= ledScrollLock;
#endif
- if ((state & ledCapsLock) != (cc->cp.ledState() & ledCapsLock)) {
+ if ((state & ledCapsLock) != (cc->server.ledState() & ledCapsLock)) {
vlog.debug("Inserting fake CapsLock to get in sync with server");
handleKeyPress(0x3a, XK_Caps_Lock);
handleKeyRelease(0x3a);
}
- if ((state & ledNumLock) != (cc->cp.ledState() & ledNumLock)) {
+ if ((state & ledNumLock) != (cc->server.ledState() & ledNumLock)) {
vlog.debug("Inserting fake NumLock to get in sync with server");
handleKeyPress(0x45, XK_Num_Lock);
handleKeyRelease(0x45);
}
- if ((state & ledScrollLock) != (cc->cp.ledState() & ledScrollLock)) {
+ if ((state & ledScrollLock) != (cc->server.ledState() & ledScrollLock)) {
vlog.debug("Inserting fake ScrollLock to get in sync with server");
handleKeyPress(0x46, XK_Scroll_Lock);
handleKeyRelease(0x46);