From: Pierre Ossman Date: Thu, 16 Jan 2014 12:12:40 +0000 (+0100) Subject: Merge the "V3" message classes into the normal ones X-Git-Tag: v1.3.90~45^2~16 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7638e9c5b1c59abc98e27986b8178f19e5e6cf2a;p=tigervnc.git Merge the "V3" message classes into the normal ones We have no need for this abstraction so let's keep things simple. --- diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx index e73b02e6..1695c3a6 100644 --- a/common/rfb/CConnection.cxx +++ b/common/rfb/CConnection.cxx @@ -19,8 +19,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -254,8 +254,8 @@ void CConnection::throwConnFailedException() void CConnection::securityCompleted() { state_ = RFBSTATE_INITIALISATION; - reader_ = new CMsgReaderV3(this, is); - writer_ = new CMsgWriterV3(&cp, os); + reader_ = new CMsgReader(this, is); + writer_ = new CMsgWriter(&cp, os); vlog.debug("Authentication success!"); authSuccess(); writer_->writeClientInit(shared); diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt index 9f5b59ec..da68a278 100644 --- a/common/rfb/CMakeLists.txt +++ b/common/rfb/CMakeLists.txt @@ -5,9 +5,7 @@ set(RFB_SOURCES CConnection.cxx CMsgHandler.cxx CMsgReader.cxx - CMsgReaderV3.cxx CMsgWriter.cxx - CMsgWriterV3.cxx CSecurityPlain.cxx CSecurityStack.cxx CSecurityVeNCrypt.cxx @@ -41,9 +39,7 @@ set(RFB_SOURCES SConnection.cxx SMsgHandler.cxx SMsgReader.cxx - SMsgReaderV3.cxx SMsgWriter.cxx - SMsgWriterV3.cxx ServerCore.cxx Security.cxx SecurityServer.cxx diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx index 63d31d1a..8466c68c 100644 --- a/common/rfb/CMsgReader.cxx +++ b/common/rfb/CMsgReader.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2009-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 @@ -16,17 +17,19 @@ * USA. */ #include +#include #include #include #include #include #include +#include using namespace rfb; CMsgReader::CMsgReader(CMsgHandler* handler_, rdr::InStream* is_) : imageBufIdealSize(0), handler(handler_), is(is_), - imageBuf(0), imageBufSize(0) + imageBuf(0), imageBufSize(0), nUpdateRectsLeft(0) { for (int i = 0; i <= encodingMax; i++) { decoders[i] = 0; @@ -41,6 +44,81 @@ CMsgReader::~CMsgReader() delete [] imageBuf; } +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(); +} + +void CMsgReader::readMsg() +{ + if (nUpdateRectsLeft == 0) { + int type = is->readU8(); + + switch (type) { + case msgTypeSetColourMapEntries: + readSetColourMapEntries(); + break; + case msgTypeBell: + readBell(); + break; + case msgTypeServerCutText: + readServerCutText(); + break; + case msgTypeFramebufferUpdate: + readFramebufferUpdate(); + break; + case msgTypeServerFence: + readFence(); + break; + case msgTypeEndOfContinuousUpdates: + readEndOfContinuousUpdates(); + break; + default: + fprintf(stderr, "unknown message type %d\n", type); + throw Exception("unknown message type"); + } + } else { + int x = is->readU16(); + int y = is->readU16(); + int w = is->readU16(); + int h = is->readU16(); + int encoding = is->readS32(); + + switch (encoding) { + case pseudoEncodingLastRect: + nUpdateRectsLeft = 1; // this rectangle is the last one + break; + case pseudoEncodingCursor: + readSetCursor(w, h, Point(x,y)); + break; + case pseudoEncodingDesktopName: + readSetDesktopName(x, y, w, h); + break; + case pseudoEncodingDesktopSize: + handler->setDesktopSize(w, h); + break; + case pseudoEncodingExtendedDesktopSize: + readExtendedDesktopSize(x, y, w, h); + break; + default: + readRect(Rect(x, y, x+w, y+h), encoding); + break; + }; + + nUpdateRectsLeft--; + if (nUpdateRectsLeft == 0) + handler->framebufferUpdateEnd(); + } +} + void CMsgReader::readSetColourMapEntries() { is->skip(1); @@ -72,14 +150,38 @@ void CMsgReader::readServerCutText() handler->serverCutText(ca.buf, len); } -void CMsgReader::readFramebufferUpdateStart() +void CMsgReader::readFence() { - handler->framebufferUpdateStart(); + rdr::U32 flags; + rdr::U8 len; + char data[64]; + + is->skip(3); + + flags = is->readU32(); + + len = is->readU8(); + if (len > sizeof(data)) { + fprintf(stderr, "Ignoring fence with too large payload\n"); + is->skip(len); + return; + } + + is->readBytes(data, len); + + handler->fence(flags, len, data); } -void CMsgReader::readFramebufferUpdateEnd() +void CMsgReader::readEndOfContinuousUpdates() { - handler->framebufferUpdateEnd(); + handler->endOfContinuousUpdates(); +} + +void CMsgReader::readFramebufferUpdate() +{ + is->skip(1); + nUpdateRectsLeft = is->readU16(); + handler->framebufferUpdateStart(); } void CMsgReader::readRect(const Rect& r, int encoding) @@ -138,6 +240,43 @@ void CMsgReader::readSetCursor(int width, int height, const Point& hotspot) handler->setCursor(width, height, hotspot, data.buf, mask.buf); } +void CMsgReader::readSetDesktopName(int x, int y, int w, int h) +{ + char* name = is->readString(); + + if (x || y || w || h) { + fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n"); + } else { + handler->setName(name); + } + + delete [] name; +} + +void CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h) +{ + unsigned int screens, i; + rdr::U32 id, flags; + int sx, sy, sw, sh; + ScreenSet layout; + + screens = is->readU8(); + is->skip(3); + + for (i = 0;i < screens;i++) { + id = is->readU32(); + sx = is->readU16(); + sy = is->readU16(); + sw = is->readU16(); + sh = is->readU16(); + flags = is->readU32(); + + layout.add_screen(Screen(id, sx, sy, sw, sh, flags)); + } + + handler->setExtendedDesktopSize(x, y, w, h, layout); +} + rdr::U8* CMsgReader::getImageBuf(int required, int requested, int* nPixels) { int requiredBytes = required * (handler->cp.pf().bpp / 8); diff --git a/common/rfb/CMsgReader.h b/common/rfb/CMsgReader.h index 7b361609..650f1642 100644 --- a/common/rfb/CMsgReader.h +++ b/common/rfb/CMsgReader.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2009-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 @@ -24,23 +25,26 @@ #define __RFB_CMSGREADER_H__ #include + +#include #include -#include namespace rdr { class InStream; } namespace rfb { class CMsgHandler; + class Decoder; struct Rect; class CMsgReader { public: + CMsgReader(CMsgHandler* handler, rdr::InStream* is); virtual ~CMsgReader(); - virtual void readServerInit()=0; + void readServerInit(); // readMsg() reads a message, calling the handler as appropriate. - virtual void readMsg()=0; + void readMsg(); rdr::InStream* getInStream() { return is; } rdr::U8* getImageBuf(int required, int requested=0, int* nPixels=0); @@ -49,25 +53,27 @@ namespace rfb { int imageBufIdealSize; protected: - virtual void readSetColourMapEntries(); - virtual void readBell(); - virtual void readServerCutText(); + void readSetColourMapEntries(); + void readBell(); + void readServerCutText(); + void readFence(); + void readEndOfContinuousUpdates(); - virtual void readFramebufferUpdateStart(); - virtual void readFramebufferUpdateEnd(); - virtual void readRect(const Rect& r, int encoding); + void readFramebufferUpdate(); - virtual void readCopyRect(const Rect& r); + void readRect(const Rect& r, int encoding); + void readCopyRect(const Rect& r); - virtual void readSetCursor(int width, int height, const Point& hotspot); - - CMsgReader(CMsgHandler* handler, rdr::InStream* is); + void readSetCursor(int width, int height, const Point& hotspot); + void readSetDesktopName(int x, int y, int w, int h); + void readExtendedDesktopSize(int x, int y, int w, int h); CMsgHandler* handler; rdr::InStream* is; Decoder* decoders[encodingMax+1]; rdr::U8* imageBuf; int imageBufSize; + int nUpdateRectsLeft; }; } #endif diff --git a/common/rfb/CMsgReaderV3.cxx b/common/rfb/CMsgReaderV3.cxx deleted file mode 100644 index 085cc5ad..00000000 --- a/common/rfb/CMsgReaderV3.cxx +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 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 -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace rfb; - -CMsgReaderV3::CMsgReaderV3(CMsgHandler* handler, rdr::InStream* is) - : CMsgReader(handler, is), nUpdateRectsLeft(0) -{ -} - -CMsgReaderV3::~CMsgReaderV3() -{ -} - -void CMsgReaderV3::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(); -} - -void CMsgReaderV3::readMsg() -{ - if (nUpdateRectsLeft == 0) { - - int type = is->readU8(); - switch (type) { - case msgTypeFramebufferUpdate: readFramebufferUpdate(); break; - case msgTypeSetColourMapEntries: readSetColourMapEntries(); break; - case msgTypeBell: readBell(); break; - case msgTypeServerCutText: readServerCutText(); break; - case msgTypeServerFence: readFence(); break; - case msgTypeEndOfContinuousUpdates: readEndOfContinuousUpdates(); break; - - default: - fprintf(stderr, "unknown message type %d\n", type); - throw Exception("unknown message type"); - } - - } else { - - int x = is->readU16(); - int y = is->readU16(); - int w = is->readU16(); - int h = is->readU16(); - int encoding = is->readS32(); - - switch (encoding) { - case pseudoEncodingDesktopSize: - handler->setDesktopSize(w, h); - break; - case pseudoEncodingExtendedDesktopSize: - readExtendedDesktopSize(x, y, w, h); - break; - case pseudoEncodingDesktopName: - readSetDesktopName(x, y, w, h); - break; - case pseudoEncodingCursor: - readSetCursor(w, h, Point(x,y)); - break; - case pseudoEncodingLastRect: - nUpdateRectsLeft = 1; // this rectangle is the last one - break; - default: - readRect(Rect(x, y, x+w, y+h), encoding); - break; - }; - - nUpdateRectsLeft--; - if (nUpdateRectsLeft == 0) handler->framebufferUpdateEnd(); - } -} - -void CMsgReaderV3::readFramebufferUpdate() -{ - is->skip(1); - nUpdateRectsLeft = is->readU16(); - handler->framebufferUpdateStart(); -} - -void CMsgReaderV3::readSetDesktopName(int x, int y, int w, int h) -{ - char* name = is->readString(); - - if (x || y || w || h) { - fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n"); - } else { - handler->setName(name); - } - - delete [] name; -} - -void CMsgReaderV3::readExtendedDesktopSize(int x, int y, int w, int h) -{ - unsigned int screens, i; - rdr::U32 id, flags; - int sx, sy, sw, sh; - ScreenSet layout; - - screens = is->readU8(); - is->skip(3); - - for (i = 0;i < screens;i++) { - id = is->readU32(); - sx = is->readU16(); - sy = is->readU16(); - sw = is->readU16(); - sh = is->readU16(); - flags = is->readU32(); - - layout.add_screen(Screen(id, sx, sy, sw, sh, flags)); - } - - handler->setExtendedDesktopSize(x, y, w, h, layout); -} - -void CMsgReaderV3::readFence() -{ - rdr::U32 flags; - rdr::U8 len; - char data[64]; - - is->skip(3); - - flags = is->readU32(); - - len = is->readU8(); - if (len > sizeof(data)) { - fprintf(stderr, "Ignoring fence with too large payload\n"); - is->skip(len); - return; - } - - is->readBytes(data, len); - - handler->fence(flags, len, data); -} - -void CMsgReaderV3::readEndOfContinuousUpdates() -{ - handler->endOfContinuousUpdates(); -} diff --git a/common/rfb/CMsgReaderV3.h b/common/rfb/CMsgReaderV3.h deleted file mode 100644 index bff70ef4..00000000 --- a/common/rfb/CMsgReaderV3.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 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. - */ -#ifndef __RFB_CMSGREADERV3_H__ -#define __RFB_CMSGREADERV3_H__ - -#include - -namespace rfb { - class CMsgReaderV3 : public CMsgReader { - public: - CMsgReaderV3(CMsgHandler* handler, rdr::InStream* is); - virtual ~CMsgReaderV3(); - virtual void readServerInit(); - virtual void readMsg(); - private: - virtual void readFramebufferUpdate(); - virtual void readSetDesktopName(int x, int y, int w, int h); - virtual void readExtendedDesktopSize(int x, int y, int w, int h); - virtual void readFence(); - virtual void readEndOfContinuousUpdates(); - int nUpdateRectsLeft; - }; -} -#endif diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx index 9ee7a02f..3d51060f 100644 --- a/common/rfb/CMsgWriter.cxx +++ b/common/rfb/CMsgWriter.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2009-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 @@ -18,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -36,6 +39,12 @@ CMsgWriter::~CMsgWriter() { } +void CMsgWriter::writeClientInit(bool shared) +{ + os->writeU8(shared); + endMsg(); +} + void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf) { startMsg(msgTypeSetPixelFormat); @@ -121,7 +130,35 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect) writeSetEncodings(nEncodings, encodings); } - + +void CMsgWriter::writeSetDesktopSize(int width, int height, + const ScreenSet& layout) +{ + if (!cp->supportsSetDesktopSize) + throw Exception("Server does not support SetDesktopSize"); + + startMsg(msgTypeSetDesktopSize); + os->pad(1); + + os->writeU16(width); + os->writeU16(height); + + os->writeU8(layout.num_screens()); + os->pad(1); + + ScreenSet::const_iterator iter; + for (iter = layout.begin();iter != layout.end();++iter) { + os->writeU32(iter->id); + os->writeU16(iter->dimensions.tl.x); + os->writeU16(iter->dimensions.tl.y); + os->writeU16(iter->dimensions.width()); + os->writeU16(iter->dimensions.height()); + os->writeU32(iter->flags); + } + + endMsg(); +} + void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental) { startMsg(msgTypeFramebufferUpdateRequest); @@ -133,6 +170,43 @@ void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental) endMsg(); } +void CMsgWriter::writeEnableContinuousUpdates(bool enable, + int x, int y, int w, int h) +{ + if (!cp->supportsContinuousUpdates) + throw Exception("Server does not support continuous updates"); + + startMsg(msgTypeEnableContinuousUpdates); + + os->writeU8(!!enable); + + os->writeU16(x); + os->writeU16(y); + os->writeU16(w); + os->writeU16(h); + + endMsg(); +} + +void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[]) +{ + if (!cp->supportsFence) + throw Exception("Server does not support fences"); + if (len > 64) + throw Exception("Too large fence payload"); + if ((flags & ~fenceFlagsSupported) != 0) + throw Exception("Unknown fence flags"); + + startMsg(msgTypeClientFence); + os->pad(3); + + os->writeU32(flags); + + os->writeU8(len); + os->writeBytes(data, len); + + endMsg(); +} void CMsgWriter::keyEvent(rdr::U32 key, bool down) { @@ -168,3 +242,13 @@ void CMsgWriter::clientCutText(const char* str, rdr::U32 len) os->writeBytes(str, len); endMsg(); } + +void CMsgWriter::startMsg(int type) +{ + os->writeU8(type); +} + +void CMsgWriter::endMsg() +{ + os->flush(); +} diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h index 66174598..fb18cdf7 100644 --- a/common/rfb/CMsgWriter.h +++ b/common/rfb/CMsgWriter.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 Pierre Ossman for Cendio AB + * Copyright 2009-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 @@ -23,8 +23,9 @@ #ifndef __RFB_CMSGWRITER_H__ #define __RFB_CMSGWRITER_H__ +#include + #include -#include namespace rdr { class OutStream; } @@ -32,39 +33,38 @@ namespace rfb { class PixelFormat; class ConnParams; + class ScreenSet; struct Rect; class CMsgWriter : public InputHandler { public: + CMsgWriter(ConnParams* cp, rdr::OutStream* os); virtual ~CMsgWriter(); - // CMsgWriter abstract interface methods - virtual void writeClientInit(bool shared)=0; - virtual void startMsg(int type)=0; - virtual void endMsg()=0; + void writeClientInit(bool shared); + + void writeSetPixelFormat(const PixelFormat& pf); + void writeSetEncodings(int nEncodings, rdr::U32* encodings); + void writeSetEncodings(int preferredEncoding, bool useCopyRect); + void writeSetDesktopSize(int width, int height, const ScreenSet& layout); - virtual void writeSetDesktopSize(int width, int height, - const ScreenSet& layout)=0; - virtual void writeFence(rdr::U32 flags, unsigned len, const char data[])=0; - virtual void writeEnableContinuousUpdates(bool enable, - int x, int y, int w, int h)=0; + void writeFramebufferUpdateRequest(const Rect& r,bool incremental); + void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h); - // CMsgWriter implemented methods - virtual void writeSetPixelFormat(const PixelFormat& pf); - virtual void writeSetEncodings(int nEncodings, rdr::U32* encodings); - virtual void writeSetEncodings(int preferredEncoding, bool useCopyRect); - virtual void writeFramebufferUpdateRequest(const Rect& r,bool incremental); + void writeFence(rdr::U32 flags, unsigned len, const char data[]); + + ConnParams* getConnParams() { return cp; } + rdr::OutStream* getOutStream() { return os; } // InputHandler implementation + virtual void keyEvent(rdr::U32 key, bool down); virtual void pointerEvent(const Point& pos, int buttonMask); virtual void clientCutText(const char* str, rdr::U32 len); - ConnParams* getConnParams() { return cp; } - rdr::OutStream* getOutStream() { return os; } - protected: - CMsgWriter(ConnParams* cp, rdr::OutStream* os); + void startMsg(int type); + void endMsg(); ConnParams* cp; rdr::OutStream* os; diff --git a/common/rfb/CMsgWriterV3.cxx b/common/rfb/CMsgWriterV3.cxx deleted file mode 100644 index b96e2b37..00000000 --- a/common/rfb/CMsgWriterV3.cxx +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 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 -#include -#include -#include -#include -#include - -using namespace rfb; - -CMsgWriterV3::CMsgWriterV3(ConnParams* cp, rdr::OutStream* os) - : CMsgWriter(cp, os) -{ -} - -CMsgWriterV3::~CMsgWriterV3() -{ -} - -void CMsgWriterV3::writeClientInit(bool shared) -{ - os->writeU8(shared); - endMsg(); -} - -void CMsgWriterV3::startMsg(int type) -{ - os->writeU8(type); -} - -void CMsgWriterV3::endMsg() -{ - os->flush(); -} - -void CMsgWriterV3::writeSetDesktopSize(int width, int height, - const ScreenSet& layout) -{ - if (!cp->supportsSetDesktopSize) - throw Exception("Server does not support SetDesktopSize"); - - startMsg(msgTypeSetDesktopSize); - os->pad(1); - - os->writeU16(width); - os->writeU16(height); - - os->writeU8(layout.num_screens()); - os->pad(1); - - ScreenSet::const_iterator iter; - for (iter = layout.begin();iter != layout.end();++iter) { - os->writeU32(iter->id); - os->writeU16(iter->dimensions.tl.x); - os->writeU16(iter->dimensions.tl.y); - os->writeU16(iter->dimensions.width()); - os->writeU16(iter->dimensions.height()); - os->writeU32(iter->flags); - } - - endMsg(); -} - -void CMsgWriterV3::writeFence(rdr::U32 flags, unsigned len, const char data[]) -{ - if (!cp->supportsFence) - throw Exception("Server does not support fences"); - if (len > 64) - throw Exception("Too large fence payload"); - if ((flags & ~fenceFlagsSupported) != 0) - throw Exception("Unknown fence flags"); - - startMsg(msgTypeClientFence); - os->pad(3); - - os->writeU32(flags); - - os->writeU8(len); - os->writeBytes(data, len); - - endMsg(); -} - -void CMsgWriterV3::writeEnableContinuousUpdates(bool enable, - int x, int y, int w, int h) -{ - if (!cp->supportsContinuousUpdates) - throw Exception("Server does not support continuous updates"); - - startMsg(msgTypeEnableContinuousUpdates); - - os->writeU8(!!enable); - - os->writeU16(x); - os->writeU16(y); - os->writeU16(w); - os->writeU16(h); - - endMsg(); -} diff --git a/common/rfb/CMsgWriterV3.h b/common/rfb/CMsgWriterV3.h deleted file mode 100644 index fb1c42c0..00000000 --- a/common/rfb/CMsgWriterV3.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 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. - */ -#ifndef __RFB_CMSGWRITERV3_H__ -#define __RFB_CMSGWRITERV3_H__ - -#include - -namespace rfb { - class CMsgWriterV3 : public CMsgWriter { - public: - CMsgWriterV3(ConnParams* cp, rdr::OutStream* os); - virtual ~CMsgWriterV3(); - - virtual void writeClientInit(bool shared); - virtual void startMsg(int type); - virtual void endMsg(); - - virtual void writeSetDesktopSize(int width, int height, - const ScreenSet& layout); - virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]); - virtual void writeEnableContinuousUpdates(bool enable, - int x, int y, int w, int h); - }; -} -#endif diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx index ee573365..ed9f8459 100644 --- a/common/rfb/SConnection.cxx +++ b/common/rfb/SConnection.cxx @@ -22,8 +22,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -297,8 +297,8 @@ void SConnection::approveConnection(bool accept, const char* reason) if (accept) { state_ = RFBSTATE_INITIALISATION; - reader_ = new SMsgReaderV3(this, is); - writer_ = new SMsgWriterV3(&cp, os); + reader_ = new SMsgReader(this, is); + writer_ = new SMsgWriter(&cp, os); authSuccess(); } else { state_ = RFBSTATE_INVALID; diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx index 49d8dcf1..89c9a8fd 100644 --- a/common/rfb/SMsgReader.cxx +++ b/common/rfb/SMsgReader.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2009-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 @@ -17,6 +18,7 @@ */ #include #include +#include #include #include #include @@ -39,6 +41,49 @@ SMsgReader::~SMsgReader() { } +void SMsgReader::readClientInit() +{ + bool shared = is->readU8(); + handler->clientInit(shared); +} + +void SMsgReader::readMsg() +{ + int msgType = is->readU8(); + switch (msgType) { + case msgTypeSetPixelFormat: + readSetPixelFormat(); + break; + case msgTypeSetEncodings: + readSetEncodings(); + break; + case msgTypeSetDesktopSize: + readSetDesktopSize(); + break; + case msgTypeFramebufferUpdateRequest: + readFramebufferUpdateRequest(); + break; + case msgTypeEnableContinuousUpdates: + readEnableContinuousUpdates(); + break; + case msgTypeClientFence: + readFence(); + break; + case msgTypeKeyEvent: + readKeyEvent(); + break; + case msgTypePointerEvent: + readPointerEvent(); + break; + case msgTypeClientCutText: + readClientCutText(); + break; + default: + fprintf(stderr, "unknown message type %d\n", msgType); + throw Exception("unknown message type"); + } +} + void SMsgReader::readSetPixelFormat() { is->skip(3); @@ -57,6 +102,36 @@ void SMsgReader::readSetEncodings() handler->setEncodings(nEncodings, encodings.buf); } +void SMsgReader::readSetDesktopSize() +{ + int width, height; + int screens, i; + rdr::U32 id, flags; + int sx, sy, sw, sh; + ScreenSet layout; + + is->skip(1); + + width = is->readU16(); + height = is->readU16(); + + screens = is->readU8(); + is->skip(1); + + for (i = 0;i < screens;i++) { + id = is->readU32(); + sx = is->readU16(); + sy = is->readU16(); + sw = is->readU16(); + sh = is->readU16(); + flags = is->readU32(); + + layout.add_screen(Screen(id, sx, sy, sw, sh, flags)); + } + + handler->setDesktopSize(width, height, layout); +} + void SMsgReader::readFramebufferUpdateRequest() { bool inc = is->readU8(); @@ -67,6 +142,43 @@ void SMsgReader::readFramebufferUpdateRequest() handler->framebufferUpdateRequest(Rect(x, y, x+w, y+h), inc); } +void SMsgReader::readEnableContinuousUpdates() +{ + bool enable; + int x, y, w, h; + + enable = is->readU8(); + + x = is->readU16(); + y = is->readU16(); + w = is->readU16(); + h = is->readU16(); + + handler->enableContinuousUpdates(enable, x, y, w, h); +} + +void SMsgReader::readFence() +{ + rdr::U32 flags; + rdr::U8 len; + char data[64]; + + is->skip(3); + + flags = is->readU32(); + + len = is->readU8(); + if (len > sizeof(data)) { + fprintf(stderr, "Ignoring fence with too large payload\n"); + is->skip(len); + return; + } + + is->readBytes(data, len); + + handler->fence(flags, len, data); +} + void SMsgReader::readKeyEvent() { bool down = is->readU8(); diff --git a/common/rfb/SMsgReader.h b/common/rfb/SMsgReader.h index e6e40448..00cb3031 100644 --- a/common/rfb/SMsgReader.h +++ b/common/rfb/SMsgReader.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2009-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 @@ -30,24 +31,29 @@ namespace rfb { class SMsgReader { public: + SMsgReader(SMsgHandler* handler, rdr::InStream* is); virtual ~SMsgReader(); - virtual void readClientInit()=0; + void readClientInit(); // readMsg() reads a message, calling the handler as appropriate. - virtual void readMsg()=0; + void readMsg(); rdr::InStream* getInStream() { return is; } protected: - virtual void readSetPixelFormat(); - virtual void readSetEncodings(); - virtual void readFramebufferUpdateRequest(); - virtual void readKeyEvent(); - virtual void readPointerEvent(); - virtual void readClientCutText(); + void readSetPixelFormat(); + void readSetEncodings(); + void readSetDesktopSize(); - SMsgReader(SMsgHandler* handler, rdr::InStream* is); + void readFramebufferUpdateRequest(); + void readEnableContinuousUpdates(); + + void readFence(); + + void readKeyEvent(); + void readPointerEvent(); + void readClientCutText(); SMsgHandler* handler; rdr::InStream* is; diff --git a/common/rfb/SMsgReaderV3.cxx b/common/rfb/SMsgReaderV3.cxx deleted file mode 100644 index cd957b9a..00000000 --- a/common/rfb/SMsgReaderV3.cxx +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 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 -#include -#include -#include -#include -#include -#include -#include - -using namespace rfb; - -SMsgReaderV3::SMsgReaderV3(SMsgHandler* handler, rdr::InStream* is) - : SMsgReader(handler, is) -{ -} - -SMsgReaderV3::~SMsgReaderV3() -{ -} - -void SMsgReaderV3::readClientInit() -{ - bool shared = is->readU8(); - handler->clientInit(shared); -} - -void SMsgReaderV3::readMsg() -{ - int msgType = is->readU8(); - switch (msgType) { - case msgTypeSetPixelFormat: readSetPixelFormat(); break; - case msgTypeSetEncodings: readSetEncodings(); break; - case msgTypeFramebufferUpdateRequest: readFramebufferUpdateRequest(); break; - case msgTypeKeyEvent: readKeyEvent(); break; - case msgTypePointerEvent: readPointerEvent(); break; - case msgTypeClientCutText: readClientCutText(); break; - case msgTypeSetDesktopSize: readSetDesktopSize(); break; - case msgTypeClientFence: readFence(); break; - case msgTypeEnableContinuousUpdates: readEnableContinuousUpdates(); break; - - default: - fprintf(stderr, "unknown message type %d\n", msgType); - throw Exception("unknown message type"); - } -} - -void SMsgReaderV3::readSetDesktopSize() -{ - int width, height; - int screens, i; - rdr::U32 id, flags; - int sx, sy, sw, sh; - ScreenSet layout; - - is->skip(1); - - width = is->readU16(); - height = is->readU16(); - - screens = is->readU8(); - is->skip(1); - - for (i = 0;i < screens;i++) { - id = is->readU32(); - sx = is->readU16(); - sy = is->readU16(); - sw = is->readU16(); - sh = is->readU16(); - flags = is->readU32(); - - layout.add_screen(Screen(id, sx, sy, sw, sh, flags)); - } - - handler->setDesktopSize(width, height, layout); -} - -void SMsgReaderV3::readFence() -{ - rdr::U32 flags; - rdr::U8 len; - char data[64]; - - is->skip(3); - - flags = is->readU32(); - - len = is->readU8(); - if (len > sizeof(data)) { - fprintf(stderr, "Ignoring fence with too large payload\n"); - is->skip(len); - return; - } - - is->readBytes(data, len); - - handler->fence(flags, len, data); -} - -void SMsgReaderV3::readEnableContinuousUpdates() -{ - bool enable; - int x, y, w, h; - - enable = is->readU8(); - - x = is->readU16(); - y = is->readU16(); - w = is->readU16(); - h = is->readU16(); - - handler->enableContinuousUpdates(enable, x, y, w, h); -} diff --git a/common/rfb/SMsgReaderV3.h b/common/rfb/SMsgReaderV3.h deleted file mode 100644 index 805fd876..00000000 --- a/common/rfb/SMsgReaderV3.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 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. - */ -#ifndef __RFB_SMSGREADERV3_H__ -#define __RFB_SMSGREADERV3_H__ - -#include - -namespace rfb { - class SMsgReaderV3 : public SMsgReader { - public: - SMsgReaderV3(SMsgHandler* handler, rdr::InStream* is); - virtual ~SMsgReaderV3(); - virtual void readClientInit(); - virtual void readMsg(); - protected: - virtual void readSetDesktopSize(); - virtual void readFence(); - virtual void readEnableContinuousUpdates(); - }; -} -#endif diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx index 509ffbf5..c21f8bc5 100644 --- a/common/rfb/SMsgWriter.cxx +++ b/common/rfb/SMsgWriter.cxx @@ -1,5 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. + * Copyright 2009-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 @@ -20,9 +21,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include @@ -31,8 +35,11 @@ using namespace rfb; static LogWriter vlog("SMsgWriter"); SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_) - : imageBufIdealSize(0), cp(cp_), os(os_), lenBeforeRect(0), - currentEncoding(0), updatesSent(0), rawBytesEquivalent(0), + : imageBufIdealSize(0), cp(cp_), os(os_), currentEncoding(0), + nRectsInUpdate(0), nRectsInHeader(0), + wsccb(0), needSetDesktopSize(false), + needExtendedDesktopSize(false), needSetDesktopName(false), + lenBeforeRect(0), updatesSent(0), rawBytesEquivalent(0), imageBuf(0), imageBufSize(0) { for (int i = 0; i <= encodingMax; i++) { @@ -59,6 +66,15 @@ SMsgWriter::~SMsgWriter() delete [] imageBuf; } +void SMsgWriter::writeServerInit() +{ + os->writeU16(cp->width); + os->writeU16(cp->height); + cp->pf().write(os); + os->writeString(cp->name()); + endMsg(); +} + void SMsgWriter::writeSetColourMapEntries(int firstColour, int nColours, ColourMap* cm) { @@ -91,6 +107,35 @@ void SMsgWriter::writeServerCutText(const char* str, int len) endMsg(); } +void SMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[]) +{ + if (!cp->supportsFence) + throw Exception("Client does not support fences"); + if (len > 64) + throw Exception("Too large fence payload"); + if ((flags & ~fenceFlagsSupported) != 0) + throw Exception("Unknown fence flags"); + + startMsg(msgTypeServerFence); + os->pad(3); + + os->writeU32(flags); + + os->writeU8(len); + os->writeBytes(data, len); + + endMsg(); +} + +void SMsgWriter::writeEndOfContinuousUpdates() +{ + if (!cp->supportsContinuousUpdates) + throw Exception("Client does not support continuous updates"); + + startMsg(msgTypeEndOfContinuousUpdates); + endMsg(); +} + void SMsgWriter::setupCurrentEncoder() { int encoding = cp->currentEncoding(); @@ -117,20 +162,133 @@ int SMsgWriter::getNumRects(const Rect &r) return encoders[encoding]->getNumRects(r); } +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) { + ExtendedDesktopSizeMsg msg; + + if (!cp->supportsExtendedDesktopSize) + return false; + + 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; +} + +void SMsgWriter::cursorChange(WriteSetCursorCallback* cb) +{ + wsccb = cb; +} + +void SMsgWriter::writeSetCursor(int width, int height, const Point& hotspot, + void* data, void* mask) +{ + if (!wsccb) + return; + + if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::writeSetCursor: nRects out of sync"); + + os->writeS16(hotspot.x); + os->writeS16(hotspot.y); + os->writeU16(width); + os->writeU16(height); + os->writeU32(pseudoEncodingCursor); + os->writeBytes(data, width * height * (cp->pf().bpp/8)); + os->writeBytes(mask, (width+7)/8 * height); +} + +void SMsgWriter::writeSetXCursor(int width, int height, int hotspotX, + int hotspotY, void* data, void* mask) +{ + if (!wsccb) + return; + + if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::writeSetXCursor: nRects out of sync"); + + os->writeS16(hotspotX); + os->writeS16(hotspotY); + os->writeU16(width); + os->writeU16(height); + os->writeU32(pseudoEncodingXCursor); + // FIXME: We only support black and white cursors, currently. We + // could pass the correct color by using the pix0/pix1 values + // returned from getBitmap, in writeSetCursorCallback. However, we + // would then need to undo the conversion from rgb to Pixel that is + // done by FakeAllocColor. + if (width * height) { + os->writeU8(0); + os->writeU8(0); + os->writeU8(0); + os->writeU8(255); + os->writeU8(255); + os->writeU8(255); + os->writeBytes(data, (width+7)/8 * height); + os->writeBytes(mask, (width+7)/8 * height); + } +} + bool SMsgWriter::needFakeUpdate() { - return false; + return wsccb || needSetDesktopName || needNoDataUpdate(); } bool SMsgWriter::needNoDataUpdate() { - return false; + return needSetDesktopSize || needExtendedDesktopSize || + !extendedDesktopSizeMsgs.empty(); } void SMsgWriter::writeNoDataUpdate() { - // This class has no pseudo-rectangles so there is nothing to do here - vlog.error("writeNoDataUpdate() called"); + int nRects; + + nRects = 0; + + if (needSetDesktopSize) + nRects++; + if (needExtendedDesktopSize) + nRects++; + if (!extendedDesktopSizeMsgs.empty()) + nRects += extendedDesktopSizeMsgs.size(); + + writeFramebufferUpdateStart(nRects); + writeNoDataRects(); + writeFramebufferUpdateEnd(); } void SMsgWriter::writeRects(const UpdateInfo& ui, TransImageGetter* ig, @@ -155,6 +313,48 @@ void SMsgWriter::writeRects(const UpdateInfo& ui, TransImageGetter* ig, } } +void SMsgWriter::writeFramebufferUpdateStart(int nRects) +{ + startMsg(msgTypeFramebufferUpdate); + os->pad(1); + + if (nRects != 0xFFFF) { + if (wsccb) + nRects++; + if (needSetDesktopName) + nRects++; + } + + os->writeU16(nRects); + + nRectsInUpdate = 0; + if (nRects == 0xFFFF) + nRectsInHeader = 0; + else + nRectsInHeader = nRects; + + writePseudoRects(); +} + +void SMsgWriter::writeFramebufferUpdateEnd() +{ + if (nRectsInUpdate != nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::writeFramebufferUpdateEnd: " + "nRects out of sync"); + + if (nRectsInHeader == 0) { + // Send last rect. marker + os->writeS16(0); + os->writeS16(0); + os->writeU16(0); + os->writeU16(0); + os->writeU32(pseudoEncodingLastRect); + } + + updatesSent++; + endMsg(); +} + bool SMsgWriter::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual) { return writeRect(r, cp->currentEncoding(), ig, actual); @@ -178,6 +378,31 @@ void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY) endRect(); } +void SMsgWriter::startRect(const Rect& r, int encoding) +{ + if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::startRect: nRects out of sync"); + + currentEncoding = encoding; + lenBeforeRect = os->length(); + if (encoding != encodingCopyRect) + rawBytesEquivalent += 12 + r.width() * r.height() * (bpp()/8); + + os->writeS16(r.tl.x); + os->writeS16(r.tl.y); + os->writeU16(r.width()); + os->writeU16(r.height()); + os->writeU32(encoding); +} + +void SMsgWriter::endRect() +{ + if (currentEncoding <= encodingMax) { + bytesSent[currentEncoding] += os->length() - lenBeforeRect; + rectsSent[currentEncoding]++; + } +} + rdr::U8* SMsgWriter::getImageBuf(int required, int requested, int* nPixels) { int requiredBytes = required * (cp->pf().bpp / 8); @@ -202,3 +427,119 @@ int SMsgWriter::bpp() { return cp->pf().bpp; } + +void SMsgWriter::startMsg(int type) +{ + os->writeU8(type); +} + +void SMsgWriter::endMsg() +{ + os->flush(); +} + +void SMsgWriter::writePseudoRects() +{ + if (wsccb) { + wsccb->writeSetCursorCallback(); + wsccb = 0; + } + + if (needSetDesktopName) { + if (!cp->supportsDesktopRename) + throw Exception("Client does not support desktop rename"); + if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::setDesktopName: nRects out of sync"); + + os->writeS16(0); + os->writeS16(0); + os->writeU16(0); + os->writeU16(0); + os->writeU32(pseudoEncodingDesktopName); + os->writeString(cp->name()); + + needSetDesktopName = false; + } +} + +void SMsgWriter::writeNoDataRects() +{ + // Start with specific ExtendedDesktopSize messages + if (!extendedDesktopSizeMsgs.empty()) { + std::list::const_iterator ri; + ScreenSet::const_iterator si; + + if (!cp->supportsExtendedDesktopSize) + throw Exception("Client does not support extended desktop resize"); + if ((nRectsInUpdate += extendedDesktopSizeMsgs.size()) > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::SetDesktopSize reply: nRects out of sync"); + + for (ri = extendedDesktopSizeMsgs.begin();ri != extendedDesktopSizeMsgs.end();++ri) { + os->writeU16(ri->reason); + os->writeU16(ri->result); + os->writeU16(ri->fb_width); + os->writeU16(ri->fb_height); + os->writeU32(pseudoEncodingExtendedDesktopSize); + + os->writeU8(ri->layout.num_screens()); + os->pad(3); + + for (si = ri->layout.begin();si != ri->layout.end();++si) { + os->writeU32(si->id); + os->writeU16(si->dimensions.tl.x); + os->writeU16(si->dimensions.tl.y); + os->writeU16(si->dimensions.width()); + os->writeU16(si->dimensions.height()); + os->writeU32(si->flags); + } + } + + extendedDesktopSizeMsgs.clear(); + } + + // Send this before SetDesktopSize to make life easier on the clients + if (needExtendedDesktopSize) { + if (!cp->supportsExtendedDesktopSize) + throw Exception("Client does not support extended desktop resize"); + if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::setExtendedDesktopSize: nRects out of sync"); + + os->writeU16(0); + os->writeU16(0); + os->writeU16(cp->width); + os->writeU16(cp->height); + os->writeU32(pseudoEncodingExtendedDesktopSize); + + os->writeU8(cp->screenLayout.num_screens()); + os->pad(3); + + ScreenSet::const_iterator iter; + for (iter = cp->screenLayout.begin();iter != cp->screenLayout.end();++iter) { + os->writeU32(iter->id); + os->writeU16(iter->dimensions.tl.x); + os->writeU16(iter->dimensions.tl.y); + os->writeU16(iter->dimensions.width()); + os->writeU16(iter->dimensions.height()); + os->writeU32(iter->flags); + } + + needExtendedDesktopSize = false; + } + + // Some clients assume this is the last rectangle so don't send anything + // more after this + if (needSetDesktopSize) { + if (!cp->supportsDesktopResize) + throw Exception("Client does not support desktop resize"); + if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::setDesktopSize: nRects out of sync"); + + os->writeS16(0); + os->writeS16(0); + os->writeU16(cp->width); + os->writeU16(cp->height); + os->writeU32(pseudoEncodingDesktopSize); + + needSetDesktopSize = false; + } +} diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h index edf29447..a39cc4f7 100644 --- a/common/rfb/SMsgWriter.h +++ b/common/rfb/SMsgWriter.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 Pierre Ossman for Cendio AB + * Copyright 2009-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 @@ -25,21 +25,19 @@ #include #include -#include -#include -#include #include namespace rdr { class OutStream; } namespace rfb { - class PixelFormat; class ConnParams; - class ImageGetter; + class TransImageGetter; class ColourMap; class Region; class UpdateInfo; + class Encoder; + class ScreenSet; class WriteSetCursorCallback { public: @@ -48,30 +46,31 @@ namespace rfb { class SMsgWriter { public: + SMsgWriter(ConnParams* cp, rdr::OutStream* os); virtual ~SMsgWriter(); // writeServerInit() must only be called at the appropriate time in the // protocol initialisation. - virtual void writeServerInit()=0; + void writeServerInit(); // Methods to write normal protocol messages // writeSetColourMapEntries() writes a setColourMapEntries message, using // the given ColourMap object to lookup the RGB values of the given range // of colours. - virtual void writeSetColourMapEntries(int firstColour, int nColours, - ColourMap* cm); + void writeSetColourMapEntries(int firstColour, int nColours, + ColourMap* cm); // writeBell() and writeServerCutText() do the obvious thing. - virtual void writeBell(); - virtual void writeServerCutText(const char* str, int len); + void writeBell(); + void writeServerCutText(const char* str, int len); // writeFence() sends a new fence request or response to the client. - virtual void writeFence(rdr::U32 flags, unsigned len, const char data[])=0; + void writeFence(rdr::U32 flags, unsigned len, const char data[]); // writeEndOfContinuousUpdates() indicates that we have left continuous // updates mode. - virtual void writeEndOfContinuousUpdates()=0; + void writeEndOfContinuousUpdates(); // setupCurrentEncoder() should be called before each framebuffer update, // prior to calling getNumRects() or writeFramebufferUpdateStart(). @@ -81,43 +80,43 @@ namespace rfb { // given rectangle, for current encoder. int getNumRects(const Rect &r); - // writeSetDesktopSize() on a V3 writer won't actually write immediately, - // but will write the relevant pseudo-rectangle as part of the next update. - virtual bool writeSetDesktopSize()=0; + // writeSetDesktopSize() 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. - virtual bool writeExtendedDesktopSize()=0; - virtual bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result, - int fb_width, int fb_height, - const ScreenSet& layout)=0; + bool writeExtendedDesktopSize(); + bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result, + int fb_width, int fb_height, + const ScreenSet& layout); - virtual bool writeSetDesktopName()=0; + bool writeSetDesktopName(); // Like setDesktopSize, we can't just write out a setCursor message - // immediately on a V3 writer. Instead of calling writeSetCursor() - // directly, you must call cursorChange(), and then invoke writeSetCursor() - // in response to the writeSetCursorCallback() callback. For a V3 writer - // this will happen when the next update is sent. - virtual void cursorChange(WriteSetCursorCallback* cb)=0; - virtual void writeSetCursor(int width, int height, const Point& hotspot, - void* data, void* mask)=0; - virtual void writeSetXCursor(int width, int height, int hotspotX, - int hotspotY, void* data, void* mask)=0; + // immediately. Instead of calling writeSetCursor() directly, + // you must call cursorChange(), and then invoke writeSetCursor() + // in response to the writeSetCursorCallback() callback. This will + // happen when the next update is sent. + void cursorChange(WriteSetCursorCallback* cb); + void writeSetCursor(int width, int height, const Point& hotspot, + void* data, void* mask); + void writeSetXCursor(int width, int height, int hotspotX, int hotspotY, + void* data, void* mask); // needFakeUpdate() returns true when an immediate update is needed in // order to flush out pseudo-rectangles to the client. - virtual bool needFakeUpdate(); + bool needFakeUpdate(); // needNoDataUpdate() returns true when an update without any // framebuffer changes need to be sent (using writeNoDataUpdate()). // Commonly this is an update that modifies the size of the framebuffer // or the screen layout. - virtual bool needNoDataUpdate(); + bool needNoDataUpdate(); // writeNoDataUpdate() write a framebuffer update containing only // pseudo-rectangles. - virtual void writeNoDataUpdate(); + void writeNoDataUpdate(); // writeRects() accepts an UpdateInfo (changed & copied regions) and an // ImageGetter to fetch pixels from. It then calls writeCopyRect() and @@ -125,29 +124,26 @@ namespace rfb { // before the first writeRects() call and writeFrameBufferUpdateEnd() after // the last one. It returns the actual region sent to the client, which // may be smaller than the update passed in. - virtual void writeRects(const UpdateInfo& update, TransImageGetter* ig, - Region* updatedRegion); + void writeRects(const UpdateInfo& update, TransImageGetter* ig, + Region* updatedRegion); // To construct a framebuffer update you can call // writeFramebufferUpdateStart(), followed by a number of writeCopyRect()s - // and writeRect()s, finishing with writeFramebufferUpdateEnd(). If you - // know the exact number of rectangles ahead of time you can specify it to - // writeFramebufferUpdateStart() which can be more efficient. - virtual void writeFramebufferUpdateStart(int nRects)=0; - virtual void writeFramebufferUpdateStart()=0; - virtual void writeFramebufferUpdateEnd()=0; + // and writeRect()s, finishing with writeFramebufferUpdateEnd(). + void writeFramebufferUpdateStart(int nRects); + void writeFramebufferUpdateEnd(); // writeRect() tries to write the given rectangle. If it is unable to // write the whole rectangle it returns false and sets actual to the actual // rectangle which was updated. - virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); - virtual bool writeRect(const Rect& r, int encoding, - TransImageGetter* ig, Rect* actual); + bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); + bool writeRect(const Rect& r, int encoding, + TransImageGetter* ig, Rect* actual); - virtual void writeCopyRect(const Rect& r, int srcX, int srcY); + void writeCopyRect(const Rect& r, int srcX, int srcY); - virtual void startRect(const Rect& r, int enc)=0; - virtual void endRect()=0; + void startRect(const Rect& r, int enc); + void endRect(); ConnParams* getConnParams() { return cp; } rdr::OutStream* getOutStream() { return os; } @@ -162,17 +158,29 @@ namespace rfb { int imageBufIdealSize; protected: - SMsgWriter(ConnParams* cp, rdr::OutStream* os); + void startMsg(int type); + void endMsg(); - virtual void startMsg(int type)=0; - virtual void endMsg()=0; + void writePseudoRects(); + void writeNoDataRects(); ConnParams* cp; rdr::OutStream* os; Encoder* encoders[encodingMax+1]; - int lenBeforeRect; int currentEncoding; + + int nRectsInUpdate; + int nRectsInHeader; + + WriteSetCursorCallback* wsccb; + + bool needSetDesktopSize; + bool needExtendedDesktopSize; + bool needSetDesktopName; + bool needLastRect; + + int lenBeforeRect; int updatesSent; int bytesSent[encodingMax+1]; int rectsSent[encodingMax+1]; @@ -180,6 +188,14 @@ namespace rfb { rdr::U8* imageBuf; int imageBufSize; + + typedef struct { + rdr::U16 reason, result; + int fb_width, fb_height; + ScreenSet layout; + } ExtendedDesktopSizeMsg; + + std::list extendedDesktopSizeMsgs; }; } #endif diff --git a/common/rfb/SMsgWriterV3.cxx b/common/rfb/SMsgWriterV3.cxx deleted file mode 100644 index 86f35078..00000000 --- a/common/rfb/SMsgWriterV3.cxx +++ /dev/null @@ -1,399 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 Pierre Ossman for Cendio AB - * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace rfb; - -SMsgWriterV3::SMsgWriterV3(ConnParams* cp, rdr::OutStream* os) - : SMsgWriter(cp, os), updateOS(0), realOS(os), nRectsInUpdate(0), - nRectsInHeader(0), wsccb(0), needSetDesktopSize(false), - needExtendedDesktopSize(false), needSetDesktopName(false) -{ -} - -SMsgWriterV3::~SMsgWriterV3() -{ - delete updateOS; -} - -void SMsgWriterV3::writeServerInit() -{ - os->writeU16(cp->width); - os->writeU16(cp->height); - cp->pf().write(os); - os->writeString(cp->name()); - endMsg(); -} - -void SMsgWriterV3::startMsg(int type) -{ - if (os != realOS) - throw Exception("startMsg called while writing an update?"); - - os->writeU8(type); -} - -void SMsgWriterV3::endMsg() -{ - os->flush(); -} - -void SMsgWriterV3::writeFence(rdr::U32 flags, unsigned len, const char data[]) -{ - if (!cp->supportsFence) - throw Exception("Client does not support fences"); - if (len > 64) - throw Exception("Too large fence payload"); - if ((flags & ~fenceFlagsSupported) != 0) - throw Exception("Unknown fence flags"); - - startMsg(msgTypeServerFence); - os->pad(3); - - os->writeU32(flags); - - os->writeU8(len); - os->writeBytes(data, len); - - endMsg(); -} - -void SMsgWriterV3::writeEndOfContinuousUpdates() -{ - if (!cp->supportsContinuousUpdates) - throw Exception("Client does not support continuous updates"); - - startMsg(msgTypeEndOfContinuousUpdates); - endMsg(); -} - -bool SMsgWriterV3::writeSetDesktopSize() { - if (!cp->supportsDesktopResize) return false; - needSetDesktopSize = true; - return true; -} - -bool SMsgWriterV3::writeExtendedDesktopSize() { - if (!cp->supportsExtendedDesktopSize) return false; - needExtendedDesktopSize = true; - return true; -} - -bool SMsgWriterV3::writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result, - int fb_width, int fb_height, - const ScreenSet& layout) { - ExtendedDesktopSizeMsg msg; - - if (!cp->supportsExtendedDesktopSize) return false; - - 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 SMsgWriterV3::writeSetDesktopName() { - if (!cp->supportsDesktopRename) return false; - needSetDesktopName = true; - return true; -} - -void SMsgWriterV3::cursorChange(WriteSetCursorCallback* cb) -{ - wsccb = cb; -} - -void SMsgWriterV3::writeSetCursor(int width, int height, const Point& hotspot, - void* data, void* mask) -{ - if (!wsccb) return; - if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3::writeSetCursor: nRects out of sync"); - os->writeS16(hotspot.x); - os->writeS16(hotspot.y); - os->writeU16(width); - os->writeU16(height); - os->writeU32(pseudoEncodingCursor); - os->writeBytes(data, width * height * (cp->pf().bpp/8)); - os->writeBytes(mask, (width+7)/8 * height); -} - -void SMsgWriterV3::writeSetXCursor(int width, int height, int hotspotX, - int hotspotY, void* data, void* mask) -{ - if (!wsccb) return; - if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3::writeSetXCursor: nRects out of sync"); - os->writeS16(hotspotX); - os->writeS16(hotspotY); - os->writeU16(width); - os->writeU16(height); - os->writeU32(pseudoEncodingXCursor); - // FIXME: We only support black and white cursors, currently. We - // could pass the correct color by using the pix0/pix1 values - // returned from getBitmap, in writeSetCursorCallback. However, we - // would then need to undo the conversion from rgb to Pixel that is - // done by FakeAllocColor. - if (width * height) { - os->writeU8(0); - os->writeU8(0); - os->writeU8(0); - os->writeU8(255); - os->writeU8(255); - os->writeU8(255); - os->writeBytes(data, (width+7)/8 * height); - os->writeBytes(mask, (width+7)/8 * height); - } -} - -bool SMsgWriterV3::needFakeUpdate() -{ - return wsccb || needSetDesktopName || needNoDataUpdate(); -} - -bool SMsgWriterV3::needNoDataUpdate() -{ - return needSetDesktopSize || needExtendedDesktopSize || - !extendedDesktopSizeMsgs.empty(); -} - -void SMsgWriterV3::writeNoDataUpdate() -{ - int nRects; - - nRects = 0; - - if (needSetDesktopSize) - nRects++; - if (needExtendedDesktopSize) - nRects++; - if (!extendedDesktopSizeMsgs.empty()) - nRects += extendedDesktopSizeMsgs.size(); - - writeFramebufferUpdateStart(nRects); - writeNoDataRects(); - writeFramebufferUpdateEnd(); -} - -void SMsgWriterV3::writeFramebufferUpdateStart(int nRects) -{ - startMsg(msgTypeFramebufferUpdate); - os->pad(1); - - if (nRects != 0xFFFF) { - if (wsccb) - nRects++; - if (needSetDesktopName) - nRects++; - } - - os->writeU16(nRects); - - nRectsInUpdate = 0; - if (nRects == 0xFFFF) - nRectsInHeader = 0; - else - nRectsInHeader = nRects; - - writePseudoRects(); -} - -void SMsgWriterV3::writeFramebufferUpdateStart() -{ - nRectsInUpdate = nRectsInHeader = 0; - - if (!updateOS) - updateOS = new rdr::MemOutStream; - os = updateOS; - - writePseudoRects(); -} - -void SMsgWriterV3::writeFramebufferUpdateEnd() -{ - if (nRectsInUpdate != nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3::writeFramebufferUpdateEnd: " - "nRects out of sync"); - - if (nRectsInHeader == 0) { - // Send last rect. marker - os->writeS16(0); - os->writeS16(0); - os->writeU16(0); - os->writeU16(0); - os->writeU32(pseudoEncodingLastRect); - } - - if (os == updateOS) { - os = realOS; - startMsg(msgTypeFramebufferUpdate); - os->pad(1); - os->writeU16(nRectsInUpdate); - os->writeBytes(updateOS->data(), updateOS->length()); - updateOS->clear(); - } - - updatesSent++; - endMsg(); -} - -void SMsgWriterV3::startRect(const Rect& r, int encoding) -{ - if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3::startRect: nRects out of sync"); - - currentEncoding = encoding; - lenBeforeRect = os->length(); - if (encoding != encodingCopyRect) - rawBytesEquivalent += 12 + r.width() * r.height() * (bpp()/8); - - os->writeS16(r.tl.x); - os->writeS16(r.tl.y); - os->writeU16(r.width()); - os->writeU16(r.height()); - os->writeU32(encoding); -} - -void SMsgWriterV3::endRect() -{ - if (currentEncoding <= encodingMax) { - bytesSent[currentEncoding] += os->length() - lenBeforeRect; - rectsSent[currentEncoding]++; - } -} - -void SMsgWriterV3::writePseudoRects() -{ - if (wsccb) { - wsccb->writeSetCursorCallback(); - wsccb = 0; - } - - if (needSetDesktopName) { - if (!cp->supportsDesktopRename) - throw Exception("Client does not support desktop rename"); - if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3 setDesktopName: nRects out of sync"); - - os->writeS16(0); - os->writeS16(0); - os->writeU16(0); - os->writeU16(0); - os->writeU32(pseudoEncodingDesktopName); - os->writeString(cp->name()); - - needSetDesktopName = false; - } -} - -void SMsgWriterV3::writeNoDataRects() -{ - // Start with specific ExtendedDesktopSize messages - if (!extendedDesktopSizeMsgs.empty()) { - std::list::const_iterator ri; - ScreenSet::const_iterator si; - - if (!cp->supportsExtendedDesktopSize) - throw Exception("Client does not support extended desktop resize"); - if ((nRectsInUpdate += extendedDesktopSizeMsgs.size()) > nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3 SetDesktopSize reply: nRects out of sync"); - - for (ri = extendedDesktopSizeMsgs.begin();ri != extendedDesktopSizeMsgs.end();++ri) { - os->writeU16(ri->reason); - os->writeU16(ri->result); - os->writeU16(ri->fb_width); - os->writeU16(ri->fb_height); - os->writeU32(pseudoEncodingExtendedDesktopSize); - - os->writeU8(ri->layout.num_screens()); - os->pad(3); - - for (si = ri->layout.begin();si != ri->layout.end();++si) { - os->writeU32(si->id); - os->writeU16(si->dimensions.tl.x); - os->writeU16(si->dimensions.tl.y); - os->writeU16(si->dimensions.width()); - os->writeU16(si->dimensions.height()); - os->writeU32(si->flags); - } - } - - extendedDesktopSizeMsgs.clear(); - } - - // Send this before SetDesktopSize to make life easier on the clients - if (needExtendedDesktopSize) { - if (!cp->supportsExtendedDesktopSize) - throw Exception("Client does not support extended desktop resize"); - if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3 setExtendedDesktopSize: nRects out of sync"); - - os->writeU16(0); - os->writeU16(0); - os->writeU16(cp->width); - os->writeU16(cp->height); - os->writeU32(pseudoEncodingExtendedDesktopSize); - - os->writeU8(cp->screenLayout.num_screens()); - os->pad(3); - - ScreenSet::const_iterator iter; - for (iter = cp->screenLayout.begin();iter != cp->screenLayout.end();++iter) { - os->writeU32(iter->id); - os->writeU16(iter->dimensions.tl.x); - os->writeU16(iter->dimensions.tl.y); - os->writeU16(iter->dimensions.width()); - os->writeU16(iter->dimensions.height()); - os->writeU32(iter->flags); - } - - needExtendedDesktopSize = false; - } - - // Some clients assume this is the last rectangle so don't send anything - // more after this - if (needSetDesktopSize) { - if (!cp->supportsDesktopResize) - throw Exception("Client does not support desktop resize"); - if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) - throw Exception("SMsgWriterV3 setDesktopSize: nRects out of sync"); - - os->writeS16(0); - os->writeS16(0); - os->writeU16(cp->width); - os->writeU16(cp->height); - os->writeU32(pseudoEncodingDesktopSize); - - needSetDesktopSize = false; - } -} - diff --git a/common/rfb/SMsgWriterV3.h b/common/rfb/SMsgWriterV3.h deleted file mode 100644 index 6710fa6b..00000000 --- a/common/rfb/SMsgWriterV3.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2011 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. - */ -#ifndef __RFB_SMSGWRITERV3_H__ -#define __RFB_SMSGWRITERV3_H__ - -#include -#include - -#include - -namespace rdr { class MemOutStream; } - -namespace rfb { - class SMsgWriterV3 : public SMsgWriter { - public: - SMsgWriterV3(ConnParams* cp, rdr::OutStream* os); - virtual ~SMsgWriterV3(); - - virtual void writeServerInit(); - virtual void startMsg(int type); - virtual void endMsg(); - virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]); - virtual void writeEndOfContinuousUpdates(); - virtual bool writeSetDesktopSize(); - virtual bool writeExtendedDesktopSize(); - virtual bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result, - int fb_width, int fb_height, - const ScreenSet& layout); - virtual bool writeSetDesktopName(); - virtual void cursorChange(WriteSetCursorCallback* cb); - virtual void writeSetCursor(int width, int height, const Point& hotspot, - void* data, void* mask); - virtual void writeSetXCursor(int width, int height, int hotspotX, - int hotspotY, void* data, void* mask); - virtual bool needFakeUpdate(); - virtual bool needNoDataUpdate(); - virtual void writeNoDataUpdate(); - virtual void writeFramebufferUpdateStart(int nRects); - virtual void writeFramebufferUpdateStart(); - virtual void writeFramebufferUpdateEnd(); - virtual void startRect(const Rect& r, int encoding); - virtual void endRect(); - - protected: - virtual void writePseudoRects(); - virtual void writeNoDataRects(); - - private: - rdr::MemOutStream* updateOS; - rdr::OutStream* realOS; - int nRectsInUpdate; - int nRectsInHeader; - WriteSetCursorCallback* wsccb; - bool needSetDesktopSize; - bool needExtendedDesktopSize; - bool needSetDesktopName; - bool needLastRect; - - typedef struct { - rdr::U16 reason, result; - int fb_width, fb_height; - ScreenSet layout; - } ExtendedDesktopSizeMsg; - std::list extendedDesktopSizeMsgs; - - }; -} -#endif diff --git a/common/rfb/TightEncoder.cxx b/common/rfb/TightEncoder.cxx index 733365e0..1cff7a60 100644 --- a/common/rfb/TightEncoder.cxx +++ b/common/rfb/TightEncoder.cxx @@ -18,6 +18,7 @@ */ #include #include +#include #include #include #include