From: Pierre Ossman Date: Mon, 14 Nov 2011 15:44:11 +0000 (+0000) Subject: Basic infrastructure to support fences. X-Git-Tag: v1.1.90~26 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c754cceeca839b7caeca9c62bb2e08688725c458;p=tigervnc.git Basic infrastructure to support fences. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4798 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx index 04e3439b..f2f19ca7 100644 --- a/common/rfb/CConnection.cxx +++ b/common/rfb/CConnection.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -269,3 +270,16 @@ void CConnection::serverInit() state_ = RFBSTATE_NORMAL; vlog.debug("initialisation done"); } + +void CConnection::fence(rdr::U32 flags, unsigned len, const char data[]) +{ + CMsgHandler::fence(flags, len, data); + + if (!(flags & fenceFlagRequest)) + return; + + // We cannot guarantee any synchronisation at this level + flags = 0; + + writer()->writeFence(flags, len, data); +} diff --git a/common/rfb/CConnection.h b/common/rfb/CConnection.h index db236bc9..8bd886aa 100644 --- a/common/rfb/CConnection.h +++ b/common/rfb/CConnection.h @@ -136,6 +136,13 @@ namespace rfb { protected: void setState(stateEnum s) { state_ = s; } + private: + // This is a default implementation of fences that automatically + // responds to requests, stating no support for synchronisation. + // When overriding, call CMsgHandler::fence() directly in order to + // state correct support for fence flags. + virtual void fence(rdr::U32 flags, unsigned len, const char data[]); + private: void processVersionMsg(); void processSecurityTypesMsg(); diff --git a/common/rfb/CMsgHandler.cxx b/common/rfb/CMsgHandler.cxx index de99abd8..53f496b0 100644 --- a/common/rfb/CMsgHandler.cxx +++ b/common/rfb/CMsgHandler.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -65,3 +65,7 @@ void CMsgHandler::setName(const char* name) cp.setName(name); } +void CMsgHandler::fence(rdr::U32 flags, unsigned len, const char data[]) +{ + cp.supportsFence = true; +} diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h index c81d55ef..1e30eebb 100644 --- a/common/rfb/CMsgHandler.h +++ b/common/rfb/CMsgHandler.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -53,6 +53,7 @@ namespace rfb { void* data, void* mask) = 0; virtual void setPixelFormat(const PixelFormat& pf); virtual void setName(const char* name); + virtual void fence(rdr::U32 flags, unsigned len, const char data[]); virtual void serverInit() = 0; virtual void framebufferUpdateStart() = 0; diff --git a/common/rfb/CMsgReaderV3.cxx b/common/rfb/CMsgReaderV3.cxx index ba516bfa..ebf08d32 100644 --- a/common/rfb/CMsgReaderV3.cxx +++ b/common/rfb/CMsgReaderV3.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -60,6 +60,7 @@ void CMsgReaderV3::readMsg() case msgTypeSetColourMapEntries: readSetColourMapEntries(); break; case msgTypeBell: readBell(); break; case msgTypeServerCutText: readServerCutText(); break; + case msgTypeServerFence: readFence(); break; default: fprintf(stderr, "unknown message type %d\n", type); @@ -144,3 +145,24 @@ void CMsgReaderV3::readExtendedDesktopSize(int x, int y, int w, int h) 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); +} diff --git a/common/rfb/CMsgReaderV3.h b/common/rfb/CMsgReaderV3.h index 8aecdea5..9f55c650 100644 --- a/common/rfb/CMsgReaderV3.h +++ b/common/rfb/CMsgReaderV3.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -32,6 +32,7 @@ namespace rfb { 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(); int nUpdateRectsLeft; }; } diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx index 3f968dea..f221f229 100644 --- a/common/rfb/CMsgWriter.cxx +++ b/common/rfb/CMsgWriter.cxx @@ -60,6 +60,7 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect) { int nEncodings = 0; rdr::U32 encodings[encodingMax+3]; + if (cp->supportsLocalCursor) encodings[nEncodings++] = pseudoEncodingCursor; if (cp->supportsDesktopResize) @@ -68,9 +69,14 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect) encodings[nEncodings++] = pseudoEncodingExtendedDesktopSize; if (cp->supportsDesktopRename) encodings[nEncodings++] = pseudoEncodingDesktopName; + + encodings[nEncodings++] = pseudoEncodingLastRect; + encodings[nEncodings++] = pseudoEncodingFence; + if (Decoder::supported(preferredEncoding)) { encodings[nEncodings++] = preferredEncoding; } + if (useCopyRect) { encodings[nEncodings++] = encodingCopyRect; } @@ -106,7 +112,6 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect) } } - encodings[nEncodings++] = pseudoEncodingLastRect; if (cp->customCompressLevel && cp->compressLevel >= 0 && cp->compressLevel <= 9) encodings[nEncodings++] = pseudoEncodingCompressLevel0 + cp->compressLevel; if (!cp->noJpeg && cp->qualityLevel >= 0 && cp->qualityLevel <= 9) diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h index 37755e77..e5cc590b 100644 --- a/common/rfb/CMsgWriter.h +++ b/common/rfb/CMsgWriter.h @@ -1,4 +1,5 @@ /* 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 @@ -44,6 +45,7 @@ namespace rfb { virtual void writeSetDesktopSize(int width, int height, const ScreenSet& layout)=0; + virtual void writeFence(rdr::U32 flags, unsigned len, const char data[])=0; // CMsgWriter implemented methods virtual void writeSetPixelFormat(const PixelFormat& pf); diff --git a/common/rfb/CMsgWriterV3.cxx b/common/rfb/CMsgWriterV3.cxx index 0a44fc65..ab3680a9 100644 --- a/common/rfb/CMsgWriterV3.cxx +++ b/common/rfb/CMsgWriterV3.cxx @@ -1,4 +1,5 @@ /* 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 @@ -17,6 +18,7 @@ */ #include #include +#include #include #include #include @@ -75,3 +77,23 @@ void CMsgWriterV3::writeSetDesktopSize(int width, int height, 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(); +} diff --git a/common/rfb/CMsgWriterV3.h b/common/rfb/CMsgWriterV3.h index 15c6d6df..a0b9cab8 100644 --- a/common/rfb/CMsgWriterV3.h +++ b/common/rfb/CMsgWriterV3.h @@ -1,4 +1,5 @@ /* 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 @@ -32,6 +33,7 @@ namespace rfb { virtual void writeSetDesktopSize(int width, int height, const ScreenSet& layout); + virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]); }; } #endif diff --git a/common/rfb/ConnParams.cxx b/common/rfb/ConnParams.cxx index e44facc9..35b0054f 100644 --- a/common/rfb/ConnParams.cxx +++ b/common/rfb/ConnParams.cxx @@ -33,7 +33,7 @@ ConnParams::ConnParams() supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(false), supportsExtendedDesktopSize(false), supportsDesktopRename(false), supportsLastRect(false), - supportsSetDesktopSize(false), + supportsSetDesktopSize(false), supportsFence(false), customCompressLevel(false), compressLevel(6), noJpeg(false), qualityLevel(-1), fineQualityLevel(-1), subsampling(SUBSAMP_UNDEFINED), @@ -125,6 +125,8 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings) supportsDesktopRename = true; else if (encodings[i] == pseudoEncodingLastRect) supportsLastRect = true; + else if (encodings[i] == pseudoEncodingFence) + supportsFence = true; else if (encodings[i] >= pseudoEncodingCompressLevel0 && encodings[i] <= pseudoEncodingCompressLevel9) { customCompressLevel = true; diff --git a/common/rfb/ConnParams.h b/common/rfb/ConnParams.h index f81a3584..35e06050 100644 --- a/common/rfb/ConnParams.h +++ b/common/rfb/ConnParams.h @@ -80,6 +80,7 @@ namespace rfb { bool supportsLastRect; bool supportsSetDesktopSize; + bool supportsFence; bool customCompressLevel; int compressLevel; diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx index 3762fbb0..ea565432 100644 --- a/common/rfb/SConnection.cxx +++ b/common/rfb/SConnection.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 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 @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -329,3 +331,14 @@ void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental) } } } + +void SConnection::fence(rdr::U32 flags, unsigned len, const char data[]) +{ + if (!(flags & fenceFlagRequest)) + return; + + // We cannot guarantee any synchronisation at this level + flags = 0; + + writer()->writeFence(flags, len, data); +} diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h index cdfde430..51ceac06 100644 --- a/common/rfb/SConnection.h +++ b/common/rfb/SConnection.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 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 @@ -106,6 +107,12 @@ namespace rfb { // accepts the server's default pixel format and it uses a colour map. virtual void setInitialColourMap(); + // fence() is called when we get a fence request or response. By default + // it responds directly to requests (stating it doesn't support any + // synchronisation) and drops responses. Override to implement more proper + // support. + virtual void fence(rdr::U32 flags, unsigned len, const char data[]); + // setAccessRights() allows a security package to limit the access rights // of a VNCSConnectionST to the server. How the access rights are treated // is up to the derived class. diff --git a/common/rfb/SMsgHandler.cxx b/common/rfb/SMsgHandler.cxx index 730bc2c0..ff15e196 100644 --- a/common/rfb/SMsgHandler.cxx +++ b/common/rfb/SMsgHandler.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -41,14 +41,26 @@ void SMsgHandler::setPixelFormat(const PixelFormat& pf) void SMsgHandler::setEncodings(int nEncodings, rdr::S32* encodings) { + bool firstFence; + + firstFence = !cp.supportsFence; + cp.setEncodings(nEncodings, encodings); + supportsLocalCursor(); + + if (cp.supportsFence && firstFence) + supportsFence(); } void SMsgHandler::supportsLocalCursor() { } +void SMsgHandler::supportsFence() +{ +} + void SMsgHandler::setDesktopSize(int fb_width, int fb_height, const ScreenSet& layout) { diff --git a/common/rfb/SMsgHandler.h b/common/rfb/SMsgHandler.h index a0bc64af..0b1fd7ee 100644 --- a/common/rfb/SMsgHandler.h +++ b/common/rfb/SMsgHandler.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -50,6 +50,7 @@ namespace rfb { virtual void framebufferUpdateRequest(const Rect& r, bool incremental) = 0; virtual void setDesktopSize(int fb_width, int fb_height, const ScreenSet& layout) = 0; + virtual void fence(rdr::U32 flags, unsigned len, const char data[]) = 0; // InputHandler interface // The InputHandler methods will be called for the corresponding messages. @@ -60,6 +61,11 @@ namespace rfb { // specially for this purpose. virtual void supportsLocalCursor(); + // supportsFence() is called the first time we detect support for fences + // in the client. A fence message should be sent at this point to notify + // the client of server support. + virtual void supportsFence(); + ConnParams cp; }; } diff --git a/common/rfb/SMsgReaderV3.cxx b/common/rfb/SMsgReaderV3.cxx index 168e6aab..eddeccf0 100644 --- a/common/rfb/SMsgReaderV3.cxx +++ b/common/rfb/SMsgReaderV3.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -54,6 +54,7 @@ void SMsgReaderV3::readMsg() case msgTypePointerEvent: readPointerEvent(); break; case msgTypeClientCutText: readClientCutText(); break; case msgTypeSetDesktopSize: readSetDesktopSize(); break; + case msgTypeClientFence: readFence(); break; default: fprintf(stderr, "unknown message type %d\n", msgType); @@ -91,3 +92,24 @@ void SMsgReaderV3::readSetDesktopSize() 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); +} diff --git a/common/rfb/SMsgReaderV3.h b/common/rfb/SMsgReaderV3.h index 8b52632b..f4cc7d7e 100644 --- a/common/rfb/SMsgReaderV3.h +++ b/common/rfb/SMsgReaderV3.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -30,6 +30,7 @@ namespace rfb { virtual void readMsg(); protected: virtual void readSetDesktopSize(); + virtual void readFence(); }; } #endif diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h index d7926880..aaa98e44 100644 --- a/common/rfb/SMsgWriter.h +++ b/common/rfb/SMsgWriter.h @@ -1,4 +1,5 @@ /* 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 @@ -65,6 +66,9 @@ namespace rfb { virtual void writeBell(); virtual 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; + // setupCurrentEncoder() should be called before each framebuffer update, // prior to calling getNumRects() or writeFramebufferUpdateStart(). void setupCurrentEncoder(); diff --git a/common/rfb/SMsgWriterV3.cxx b/common/rfb/SMsgWriterV3.cxx index af1187eb..0867b107 100644 --- a/common/rfb/SMsgWriterV3.cxx +++ b/common/rfb/SMsgWriterV3.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,26 @@ 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(); +} + bool SMsgWriterV3::writeSetDesktopSize() { if (!cp->supportsDesktopResize) return false; needSetDesktopSize = true; diff --git a/common/rfb/SMsgWriterV3.h b/common/rfb/SMsgWriterV3.h index 8918a04f..35f1f94b 100644 --- a/common/rfb/SMsgWriterV3.h +++ b/common/rfb/SMsgWriterV3.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB + * 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 @@ -35,6 +35,7 @@ namespace rfb { virtual void writeServerInit(); virtual void startMsg(int type); virtual void endMsg(); + virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]); virtual bool writeSetDesktopSize(); virtual bool writeExtendedDesktopSize(); virtual bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result, diff --git a/common/rfb/encodings.h b/common/rfb/encodings.h index 40f5f101..84844c53 100644 --- a/common/rfb/encodings.h +++ b/common/rfb/encodings.h @@ -36,6 +36,7 @@ namespace rfb { const int pseudoEncodingDesktopSize = -223; const int pseudoEncodingExtendedDesktopSize = -308; const int pseudoEncodingDesktopName = -307; + const int pseudoEncodingFence = -312; // TightVNC-specific const int pseudoEncodingLastRect = -224; diff --git a/common/rfb/fenceTypes.h b/common/rfb/fenceTypes.h new file mode 100644 index 00000000..41778602 --- /dev/null +++ b/common/rfb/fenceTypes.h @@ -0,0 +1,36 @@ +/* Copyright 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_FENCETYPES_H__ +#define __RFB_FENCETYPES_H__ + +#include + +namespace rfb { + const rdr::U32 fenceFlagBlockBefore = 1<<0; + const rdr::U32 fenceFlagBlockAfter = 1<<1; + const rdr::U32 fenceFlagSyncNext = 1<<2; + + const rdr::U32 fenceFlagRequest = 1<<31; + + const rdr::U32 fenceFlagsSupported = (fenceFlagBlockBefore | + fenceFlagBlockAfter | + fenceFlagSyncNext | + fenceFlagRequest); +} + +#endif diff --git a/common/rfb/msgTypes.h b/common/rfb/msgTypes.h index 6b4ae568..e42d95af 100644 --- a/common/rfb/msgTypes.h +++ b/common/rfb/msgTypes.h @@ -26,6 +26,8 @@ namespace rfb { const int msgTypeBell = 2; const int msgTypeServerCutText = 3; + const int msgTypeServerFence = 248; + // client to server const int msgTypeSetPixelFormat = 0; @@ -36,6 +38,8 @@ namespace rfb { const int msgTypePointerEvent = 5; const int msgTypeClientCutText = 6; + const int msgTypeClientFence = 248; + const int msgTypeSetDesktopSize = 251; } #endif