aboutsummaryrefslogtreecommitdiffstats
path: root/common/rfb
diff options
context:
space:
mode:
Diffstat (limited to 'common/rfb')
-rw-r--r--common/rfb/Blacklist.cxx32
-rw-r--r--common/rfb/Blacklist.h4
-rw-r--r--common/rfb/CConnection.cxx182
-rw-r--r--common/rfb/CConnection.h199
-rw-r--r--common/rfb/CMakeLists.txt34
-rw-r--r--common/rfb/CMsgHandler.cxx168
-rw-r--r--common/rfb/CMsgHandler.h59
-rw-r--r--common/rfb/CMsgReader.cxx41
-rw-r--r--common/rfb/CMsgReader.h23
-rw-r--r--common/rfb/CMsgWriter.cxx16
-rw-r--r--common/rfb/CMsgWriter.h12
-rw-r--r--common/rfb/CSecurityDH.cxx1
-rw-r--r--common/rfb/CSecurityMSLogonII.cxx1
-rw-r--r--common/rfb/CSecurityRSAAES.cxx24
-rw-r--r--common/rfb/CSecurityRSAAES.h8
-rw-r--r--common/rfb/CSecurityStack.h1
-rw-r--r--common/rfb/CSecurityTLS.cxx450
-rw-r--r--common/rfb/CSecurityTLS.h11
-rw-r--r--common/rfb/CSecurityVeNCrypt.cxx5
-rw-r--r--common/rfb/CSecurityVeNCrypt.h3
-rw-r--r--common/rfb/ClientParams.cxx36
-rw-r--r--common/rfb/ClientParams.h22
-rw-r--r--common/rfb/ComparingUpdateTracker.cxx44
-rw-r--r--common/rfb/ComparingUpdateTracker.h3
-rw-r--r--common/rfb/Configuration.cxx469
-rw-r--r--common/rfb/Configuration.h300
-rw-r--r--common/rfb/Congestion.cxx35
-rw-r--r--common/rfb/CopyRectDecoder.cxx19
-rw-r--r--common/rfb/CopyRectDecoder.h8
-rw-r--r--common/rfb/Cursor.cxx30
-rw-r--r--common/rfb/Cursor.h18
-rw-r--r--common/rfb/DecodeManager.cxx126
-rw-r--r--common/rfb/DecodeManager.h37
-rw-r--r--common/rfb/Decoder.cxx12
-rw-r--r--common/rfb/Decoder.h23
-rw-r--r--common/rfb/EncodeManager.cxx159
-rw-r--r--common/rfb/EncodeManager.h73
-rw-r--r--common/rfb/Encoder.h2
-rw-r--r--common/rfb/H264Decoder.cxx24
-rw-r--r--common/rfb/H264Decoder.h12
-rw-r--r--common/rfb/H264DecoderContext.cxx29
-rw-r--r--common/rfb/H264DecoderContext.h23
-rw-r--r--common/rfb/H264LibavDecoderContext.cxx67
-rw-r--r--common/rfb/H264LibavDecoderContext.h8
-rw-r--r--common/rfb/H264WinDecoderContext.cxx80
-rw-r--r--common/rfb/H264WinDecoderContext.h8
-rw-r--r--common/rfb/HextileDecoder.cxx20
-rw-r--r--common/rfb/HextileDecoder.h6
-rw-r--r--common/rfb/HextileEncoder.cxx31
-rw-r--r--common/rfb/Hostname.h120
-rw-r--r--common/rfb/JpegCompressor.cxx6
-rw-r--r--common/rfb/JpegCompressor.h10
-rw-r--r--common/rfb/JpegDecompressor.cxx6
-rw-r--r--common/rfb/JpegDecompressor.h11
-rw-r--r--common/rfb/KeyRemapper.cxx78
-rw-r--r--common/rfb/KeyRemapper.h7
-rw-r--r--common/rfb/LogWriter.cxx136
-rw-r--r--common/rfb/LogWriter.h113
-rw-r--r--common/rfb/Logger.cxx95
-rw-r--r--common/rfb/Logger.h71
-rw-r--r--common/rfb/Logger_file.cxx128
-rw-r--r--common/rfb/Logger_file.h56
-rw-r--r--common/rfb/Logger_stdio.cxx36
-rw-r--r--common/rfb/Logger_stdio.h39
-rw-r--r--common/rfb/Logger_syslog.cxx67
-rw-r--r--common/rfb/Logger_syslog.h40
-rw-r--r--common/rfb/PixelBuffer.cxx121
-rw-r--r--common/rfb/PixelBuffer.h47
-rw-r--r--common/rfb/PixelFormat.h2
-rw-r--r--common/rfb/RREDecoder.cxx8
-rw-r--r--common/rfb/RREDecoder.h6
-rw-r--r--common/rfb/RawDecoder.cxx4
-rw-r--r--common/rfb/RawDecoder.h4
-rw-r--r--common/rfb/Rect.h130
-rw-r--r--common/rfb/Region.cxx183
-rw-r--r--common/rfb/Region.h81
-rw-r--r--common/rfb/SConnection.cxx137
-rw-r--r--common/rfb/SConnection.h157
-rw-r--r--common/rfb/SDesktop.h52
-rw-r--r--common/rfb/SMsgHandler.cxx176
-rw-r--r--common/rfb/SMsgHandler.h80
-rw-r--r--common/rfb/SMsgReader.cxx26
-rw-r--r--common/rfb/SMsgWriter.cxx18
-rw-r--r--common/rfb/SMsgWriter.h7
-rw-r--r--common/rfb/SSecurity.h6
-rw-r--r--common/rfb/SSecurityPlain.cxx27
-rw-r--r--common/rfb/SSecurityPlain.h20
-rw-r--r--common/rfb/SSecurityRSAAES.cxx26
-rw-r--r--common/rfb/SSecurityRSAAES.h11
-rw-r--r--common/rfb/SSecurityTLS.cxx117
-rw-r--r--common/rfb/SSecurityTLS.h12
-rw-r--r--common/rfb/SSecurityVeNCrypt.cxx9
-rw-r--r--common/rfb/SSecurityVeNCrypt.h6
-rw-r--r--common/rfb/SSecurityVncAuth.cxx22
-rw-r--r--common/rfb/SSecurityVncAuth.h11
-rw-r--r--common/rfb/ScreenSet.h7
-rw-r--r--common/rfb/Security.cxx34
-rw-r--r--common/rfb/Security.h14
-rw-r--r--common/rfb/SecurityClient.cxx21
-rw-r--r--common/rfb/SecurityClient.h7
-rw-r--r--common/rfb/SecurityServer.cxx20
-rw-r--r--common/rfb/SecurityServer.h3
-rw-r--r--common/rfb/ServerCore.cxx44
-rw-r--r--common/rfb/ServerCore.h34
-rw-r--r--common/rfb/ServerParams.cxx31
-rw-r--r--common/rfb/ServerParams.h16
-rw-r--r--common/rfb/TightDecoder.cxx21
-rw-r--r--common/rfb/TightDecoder.h15
-rw-r--r--common/rfb/Timer.cxx179
-rw-r--r--common/rfb/Timer.h136
-rw-r--r--common/rfb/UnixPasswordValidator.cxx117
-rw-r--r--common/rfb/UnixPasswordValidator.h14
-rw-r--r--common/rfb/UpdateTracker.cxx43
-rw-r--r--common/rfb/UpdateTracker.h45
-rw-r--r--common/rfb/VNCSConnectionST.cxx83
-rw-r--r--common/rfb/VNCSConnectionST.h30
-rw-r--r--common/rfb/VNCServer.h14
-rw-r--r--common/rfb/VNCServerST.cxx96
-rw-r--r--common/rfb/VNCServerST.h35
-rw-r--r--common/rfb/WinPasswdValidator.cxx3
-rw-r--r--common/rfb/WinPasswdValidator.h6
-rw-r--r--common/rfb/ZRLEDecoder.cxx14
-rw-r--r--common/rfb/ZRLEDecoder.h6
-rw-r--r--common/rfb/ZRLEEncoder.cxx24
-rw-r--r--common/rfb/ZRLEEncoder.h8
-rw-r--r--common/rfb/pam.c95
-rw-r--r--common/rfb/pam.h34
-rw-r--r--common/rfb/util.cxx682
-rw-r--r--common/rfb/util.h111
129 files changed, 2155 insertions, 5410 deletions
diff --git a/common/rfb/Blacklist.cxx b/common/rfb/Blacklist.cxx
index 68420ae2..19a9ed39 100644
--- a/common/rfb/Blacklist.cxx
+++ b/common/rfb/Blacklist.cxx
@@ -21,24 +21,26 @@
#endif
#include <rfb/Blacklist.h>
-#include <rfb/Configuration.h>
+#include <core/Configuration.h>
using namespace rfb;
-BoolParameter enabled("UseBlacklist",
- "Temporarily reject connections from a host if it "
- "repeatedly fails to authenticate.",
- true);
-IntParameter threshold("BlacklistThreshold",
- "The number of unauthenticated connection attempts "
- "allowed from any individual host before that host "
- "is black-listed",
- 5);
-IntParameter initialTimeout("BlacklistTimeout",
- "The initial timeout applied when a host is "
- "first black-listed. The host cannot re-attempt "
- "a connection until the timeout expires.",
- 10);
+core::BoolParameter enabled("UseBlacklist",
+ "Temporarily reject connections from a "
+ "host if it repeatedly fails to "
+ "authenticate.",
+ true);
+core::IntParameter threshold("BlacklistThreshold",
+ "The number of unauthenticated connection "
+ "attempts allowed from any individual "
+ "host before that host is black-listed",
+ 5, 0, INT_MAX);
+core::IntParameter initialTimeout("BlacklistTimeout",
+ "The initial timeout applied when a "
+ "host is first black-listed. The "
+ "host cannot re-attempt a connection "
+ "until the timeout expires.",
+ 10, 0, INT_MAX);
Blacklist::Blacklist() {
diff --git a/common/rfb/Blacklist.h b/common/rfb/Blacklist.h
index c1699f29..3c9660cc 100644
--- a/common/rfb/Blacklist.h
+++ b/common/rfb/Blacklist.h
@@ -27,13 +27,11 @@
#ifndef __RFB_BLACKLIST_H__
#define __RFB_BLACKLIST_H__
-#include <string.h>
#include <time.h>
+
#include <map>
#include <string>
-#include <rfb/Configuration.h>
-
namespace rfb {
//
diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx
index 5e7530c8..bbeef385 100644
--- a/common/rfb/CConnection.cxx
+++ b/common/rfb/CConnection.cxx
@@ -27,31 +27,34 @@
#include <algorithm>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rfb/Exception.h>
#include <rfb/clipboardTypes.h>
#include <rfb/fenceTypes.h>
+#include <rfb/screenTypes.h>
#include <rfb/CMsgReader.h>
#include <rfb/CMsgWriter.h>
#include <rfb/CSecurity.h>
+#include <rfb/Cursor.h>
#include <rfb/Decoder.h>
#include <rfb/KeysymStr.h>
+#include <rfb/PixelBuffer.h>
#include <rfb/Security.h>
#include <rfb/SecurityClient.h>
#include <rfb/CConnection.h>
-#include <rfb/util.h>
#define XK_MISCELLANY
#define XK_XKB_KEYS
#include <rfb/keysymdef.h>
-#include <rfb/LogWriter.h>
-
#include <rdr/InStream.h>
#include <rdr/OutStream.h>
using namespace rfb;
-static LogWriter vlog("CConnection");
+static core::LogWriter vlog("CConnection");
CConnection::CConnection()
: csecurity(nullptr),
@@ -98,7 +101,7 @@ void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
}
if ((framebuffer != nullptr) && (fb != nullptr)) {
- Rect rect;
+ core::Rect rect;
const uint8_t* data;
int stride;
@@ -107,9 +110,8 @@ void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
// Copy still valid area
- rect.setXYWH(0, 0,
- __rfbmin(fb->width(), framebuffer->width()),
- __rfbmin(fb->height(), framebuffer->height()));
+ rect = fb->getRect();
+ rect = rect.intersect(framebuffer->getRect());
data = framebuffer->getBuffer(framebuffer->getRect(), &stride);
fb->imageRect(rect, data, stride);
@@ -189,10 +191,9 @@ bool CConnection::processVersionMsg()
vlog.error("Server gave unsupported RFB protocol version %d.%d",
server.majorVersion, server.minorVersion);
state_ = RFBSTATE_INVALID;
- throw protocol_error(format("Server gave unsupported RFB protocol "
- "version %d.%d",
- server.majorVersion,
- server.minorVersion));
+ throw protocol_error(
+ core::format("Server gave unsupported RFB protocol version %d.%d",
+ server.majorVersion, server.minorVersion));
} else if (server.beforeVersion(3,7)) {
server.setVersion(3,3);
} else if (server.afterVersion(3,8)) {
@@ -379,7 +380,6 @@ void CConnection::securityCompleted()
reader_ = new CMsgReader(this, is);
writer_ = new CMsgWriter(&server, os);
vlog.debug("Authentication success!");
- authSuccess();
writer_->writeClientInit(shared);
}
@@ -410,7 +410,7 @@ void CConnection::setDesktopSize(int w, int h)
{
decoder.flush();
- CMsgHandler::setDesktopSize(w,h);
+ server.setDimensions(w, h);
if (continuousUpdates)
writer()->writeEnableContinuousUpdates(true, 0, 0,
@@ -430,7 +430,15 @@ void CConnection::setExtendedDesktopSize(unsigned reason,
{
decoder.flush();
- CMsgHandler::setExtendedDesktopSize(reason, result, w, h, layout);
+ server.supportsSetDesktopSize = true;
+
+ if ((reason != reasonClient) || (result == resultSuccess))
+ server.setDimensions(w, h, layout);
+
+ if ((reason == reasonClient) && (result != resultSuccess)) {
+ vlog.error("SetDesktopSize failed: %d", result);
+ return;
+ }
if (continuousUpdates)
writer()->writeEnableContinuousUpdates(true, 0, 0,
@@ -443,9 +451,41 @@ void CConnection::setExtendedDesktopSize(unsigned reason,
assert(framebuffer->height() == server.height());
}
+void CConnection::setCursor(int width, int height,
+ const core::Point& hotspot,
+ const uint8_t* data)
+{
+ Cursor cursor(width, height, hotspot, data);
+ server.setCursor(cursor);
+}
+
+void CConnection::setCursorPos(const core::Point& /*pos*/)
+{
+}
+
+void CConnection::setName(const char* name)
+{
+ server.setName(name);
+}
+
+void CConnection::fence(uint32_t flags, unsigned len, const uint8_t data[])
+{
+ server.supportsFence = true;
+
+ if (flags & fenceFlagRequest) {
+ // FIXME: We handle everything synchronously, and we assume anything
+ // using us also does so, which means we automatically handle
+ // these flags
+ flags = flags & (fenceFlagBlockBefore | fenceFlagBlockAfter);
+
+ writer()->writeFence(flags, len, data);
+ return;
+ }
+}
+
void CConnection::endOfContinuousUpdates()
{
- CMsgHandler::endOfContinuousUpdates();
+ server.supportsContinuousUpdates = true;
// We've gotten the marker for a format change, so make the pending
// one active
@@ -459,11 +499,23 @@ void CConnection::endOfContinuousUpdates()
}
}
+void CConnection::supportsQEMUKeyEvent()
+{
+ server.supportsQEMUKeyEvent = true;
+}
+
+void CConnection::supportsExtendedMouseButtons()
+{
+ server.supportsExtendedMouseButtons = true;
+}
+
void CConnection::serverInit(int width, int height,
const PixelFormat& pf,
const char* name)
{
- CMsgHandler::serverInit(width, height, pf, name);
+ server.setDimensions(width, height);
+ server.setPF(pf);
+ server.setName(name);
state_ = RFBSTATE_NORMAL;
vlog.debug("Initialisation done");
@@ -486,7 +538,7 @@ void CConnection::serverInit(int width, int height,
}
}
-bool CConnection::readAndDecodeRect(const Rect& r, int encoding,
+bool CConnection::readAndDecodeRect(const core::Rect& r, int encoding,
ModifiablePixelBuffer* pb)
{
if (!decoder.decodeRect(r, encoding, pb))
@@ -497,8 +549,6 @@ bool CConnection::readAndDecodeRect(const Rect& r, int encoding,
void CConnection::framebufferUpdateStart()
{
- CMsgHandler::framebufferUpdateStart();
-
assert(framebuffer != nullptr);
// Note: This might not be true if continuous updates are supported
@@ -511,8 +561,6 @@ 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) {
@@ -533,11 +581,18 @@ void CConnection::framebufferUpdateEnd()
}
}
-bool CConnection::dataRect(const Rect& r, int encoding)
+bool CConnection::dataRect(const core::Rect& r, int encoding)
{
return decoder.decodeRect(r, encoding, framebuffer);
}
+void CConnection::setColourMapEntries(int /*firstColour*/,
+ int /*nColours*/,
+ uint16_t* /*rgbs*/)
+{
+ vlog.error("Invalid SetColourMapEntries from server!");
+}
+
void CConnection::serverCutText(const char* str)
{
hasLocalClipboard = false;
@@ -548,12 +603,53 @@ void CConnection::serverCutText(const char* str)
handleClipboardAnnounce(true);
}
+void CConnection::setLEDState(unsigned int state)
+{
+ server.setLEDState(state);
+}
+
void CConnection::handleClipboardCaps(uint32_t flags,
const uint32_t* lengths)
{
+ int i;
uint32_t sizes[] = { 0 };
- CMsgHandler::handleClipboardCaps(flags, lengths);
+ vlog.debug("Got server clipboard capabilities:");
+ for (i = 0;i < 16;i++) {
+ if (flags & (1 << i)) {
+ const char *type;
+
+ switch (1 << i) {
+ case clipboardUTF8:
+ type = "Plain text";
+ break;
+ case clipboardRTF:
+ type = "Rich text";
+ break;
+ case clipboardHTML:
+ type = "HTML";
+ break;
+ case clipboardDIB:
+ type = "Images";
+ break;
+ case clipboardFiles:
+ type = "Files";
+ break;
+ default:
+ vlog.debug(" Unknown format 0x%x", 1 << i);
+ continue;
+ }
+
+ if (lengths[i] == 0)
+ vlog.debug(" %s (only notify)", type);
+ else {
+ vlog.debug(" %s (automatically send up to %s)",
+ type, core::iecPrefix(lengths[i], "B").c_str());
+ }
+ }
+ }
+
+ server.setClipboardCaps(flags, lengths);
writer()->writeClipboardCaps(rfb::clipboardUTF8 |
rfb::clipboardRequest |
@@ -604,21 +700,17 @@ void CConnection::handleClipboardProvide(uint32_t flags,
}
// FIXME: This conversion magic should be in CMsgReader
- if (!isValidUTF8((const char*)data[0], lengths[0])) {
+ if (!core::isValidUTF8((const char*)data[0], lengths[0])) {
vlog.error("Invalid UTF-8 sequence in clipboard - ignoring");
return;
}
- serverClipboard = convertLF((const char*)data[0], lengths[0]);
+ serverClipboard = core::convertLF((const char*)data[0], lengths[0]);
hasRemoteClipboard = true;
// FIXME: Should probably verify that this data was actually requested
handleClipboardData(serverClipboard.c_str());
}
-void CConnection::authSuccess()
-{
-}
-
void CConnection::initDone()
{
}
@@ -679,7 +771,7 @@ void CConnection::sendClipboardData(const char* data)
{
if (server.clipboardFlags() & rfb::clipboardProvide) {
// FIXME: This conversion magic should be in CMsgWriter
- std::string filtered(convertCRLF(data));
+ std::string filtered(core::convertCRLF(data));
size_t sizes[1] = { filtered.size() + 1 };
const uint8_t* datas[1] = { (const uint8_t*)filtered.c_str() };
@@ -815,6 +907,11 @@ void CConnection::setCompressLevel(int level)
encodingChange = true;
}
+int CConnection::getCompressLevel()
+{
+ return compressLevel;
+}
+
void CConnection::setQualityLevel(int level)
{
if (qualityLevel == level)
@@ -824,6 +921,11 @@ void CConnection::setQualityLevel(int level)
encodingChange = true;
}
+int CConnection::getQualityLevel()
+{
+ return qualityLevel;
+}
+
void CConnection::setPF(const PixelFormat& pf)
{
if (server.pf() == pf && !formatChange)
@@ -833,17 +935,9 @@ void CConnection::setPF(const PixelFormat& pf)
formatChange = true;
}
-void CConnection::fence(uint32_t flags, unsigned len, const uint8_t data[])
+bool CConnection::isSecure() const
{
- CMsgHandler::fence(flags, len, data);
-
- if (!(flags & fenceFlagRequest))
- return;
-
- // We cannot guarantee any synchronisation at this level
- flags = 0;
-
- writer()->writeFence(flags, len, data);
+ return csecurity ? csecurity->isSecure() : false;
}
// requestNewUpdate() requests an update from the server, having set the
@@ -884,9 +978,9 @@ void CConnection::requestNewUpdate()
if (forceNonincremental || !continuousUpdates) {
pendingUpdate = true;
- writer()->writeFramebufferUpdateRequest(Rect(0, 0,
- server.width(),
- server.height()),
+ writer()->writeFramebufferUpdateRequest({0, 0,
+ server.width(),
+ server.height()},
!forceNonincremental);
}
diff --git a/common/rfb/CConnection.h b/common/rfb/CConnection.h
index 07e47e39..b28c5aa9 100644
--- a/common/rfb/CConnection.h
+++ b/common/rfb/CConnection.h
@@ -29,8 +29,14 @@
#include <rfb/CMsgHandler.h>
#include <rfb/DecodeManager.h>
+#include <rfb/PixelFormat.h>
#include <rfb/SecurityClient.h>
+namespace rdr {
+ class InStream;
+ class OutStream;
+}
+
namespace rfb {
class CMsgReader;
@@ -99,89 +105,6 @@ namespace rfb {
// connection
void close();
-
- // Methods overridden from CMsgHandler
-
- // Note: These must be called by any deriving classes
-
- void setDesktopSize(int w, int h) override;
- void setExtendedDesktopSize(unsigned reason, unsigned result,
- int w, int h,
- const ScreenSet& layout) override;
-
- void endOfContinuousUpdates() override;
-
- void serverInit(int width, int height, const PixelFormat& pf,
- const char* name) override;
-
- bool readAndDecodeRect(const Rect& r, int encoding,
- ModifiablePixelBuffer* pb) override;
-
- void framebufferUpdateStart() override;
- void framebufferUpdateEnd() override;
- bool dataRect(const Rect& r, int encoding) override;
-
- void serverCutText(const char* str) override;
-
- void handleClipboardCaps(uint32_t flags,
- const uint32_t* lengths) override;
- void handleClipboardRequest(uint32_t flags) override;
- void handleClipboardPeek() override;
- void handleClipboardNotify(uint32_t flags) override;
- void handleClipboardProvide(uint32_t flags, const size_t* lengths,
- const uint8_t* const* data) override;
-
-
- // Methods to be overridden in a derived class
-
- // getUserPasswd() gets the username and password. This might
- // involve a dialog, getpass(), etc. The user buffer pointer can be
- // null, in which case no user name will be retrieved.
- virtual void getUserPasswd(bool secure, std::string* user,
- std::string* password) = 0;
-
- // showMsgBox() displays a message box with the specified style and
- // contents. The return value is true if the user clicked OK/Yes.
- virtual bool showMsgBox(MsgBoxFlags flags, const char *title,
- const char *text) = 0;
-
- // authSuccess() is called when authentication has succeeded.
- virtual void authSuccess();
-
- // 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();
-
- // handleClipboardRequest() is called whenever the server requests
- // the client to send over its clipboard data. It will only be
- // called after the client has first announced a clipboard change
- // via announceClipboard().
- virtual void handleClipboardRequest();
-
- // handleClipboardAnnounce() is called to indicate a change in the
- // clipboard on the server. Call requestClipboard() to access the
- // actual data.
- virtual void handleClipboardAnnounce(bool available);
-
- // handleClipboardData() is called when the server has sent over
- // the clipboard data as a result of a previous call to
- // requestClipboard(). Note that this function might never be
- // called if the clipboard data was no longer available when the
- // server received the request.
- virtual void handleClipboardData(const char* data);
-
-
- // Other methods
-
// requestClipboard() will result in a request to the server to
// transfer its clipboard data. A call to handleClipboardData()
// will be made once the data is available.
@@ -221,7 +144,9 @@ namespace rfb {
// setCompressLevel()/setQualityLevel() controls the encoding hints
// sent to the server
void setCompressLevel(int level);
+ int getCompressLevel();
void setQualityLevel(int level);
+ int getQualityLevel();
// setPF() controls the pixel format requested from the server.
// server.pf() will automatically be adjusted once the new format
// is active.
@@ -237,7 +162,7 @@ namespace rfb {
// Identities, to determine the unique(ish) name of the server.
const char* getServerName() const { return serverName.c_str(); }
- bool isSecure() const { return csecurity ? csecurity->isSecure() : false; }
+ bool isSecure() const;
enum stateEnum {
RFBSTATE_UNINITIALISED,
@@ -254,8 +179,107 @@ namespace rfb {
stateEnum state() { return state_; }
+ // Methods used by SSecurity classes
+
+ // getUserPasswd() gets the username and password. This might
+ // involve a dialog, getpass(), etc. The user buffer pointer can be
+ // null, in which case no user name will be retrieved.
+ virtual void getUserPasswd(bool secure, std::string* user,
+ std::string* password) = 0;
+
+ // showMsgBox() displays a message box with the specified style and
+ // contents. The return value is true if the user clicked OK/Yes.
+ virtual bool showMsgBox(MsgBoxFlags flags, const char *title,
+ const char *text) = 0;
+
+ protected:
+
+ // Methods overridden from CMsgHandler
+
+ // Note: These must be called by any deriving classes
+
+ void setDesktopSize(int w, int h) override;
+ void setExtendedDesktopSize(unsigned reason, unsigned result,
+ int w, int h,
+ const ScreenSet& layout) override;
+
+ void setCursor(int width, int height, const core::Point& hotspot,
+ const uint8_t* data) override;
+ void setCursorPos(const core::Point& pos) override;
+
+ void setName(const char* name) override;
+
+ void fence(uint32_t flags, unsigned len, const uint8_t data[]) override;
+
+ void endOfContinuousUpdates() override;
+
+ void supportsQEMUKeyEvent() override;
+
+ void supportsExtendedMouseButtons() override;
+
+ void serverInit(int width, int height, const PixelFormat& pf,
+ const char* name) override;
+
+ bool readAndDecodeRect(const core::Rect& r, int encoding,
+ ModifiablePixelBuffer* pb) override;
+
+ void framebufferUpdateStart() override;
+ void framebufferUpdateEnd() override;
+ bool dataRect(const core::Rect& r, int encoding) override;
+
+ void setColourMapEntries(int firstColour, int nColours,
+ uint16_t* rgbs) override;
+
+ void serverCutText(const char* str) override;
+
+ void setLEDState(unsigned int state) override;
+
+ void handleClipboardCaps(uint32_t flags,
+ const uint32_t* lengths) override;
+ void handleClipboardRequest(uint32_t flags) override;
+ void handleClipboardPeek() override;
+ void handleClipboardNotify(uint32_t flags) override;
+ void handleClipboardProvide(uint32_t flags, const size_t* lengths,
+ const uint8_t* const* data) override;
+
+
+ // Methods to be overridden in a derived class
+
+ // 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();
+
+ // handleClipboardRequest() is called whenever the server requests
+ // the client to send over its clipboard data. It will only be
+ // called after the client has first announced a clipboard change
+ // via announceClipboard().
+ virtual void handleClipboardRequest();
+
+ // handleClipboardAnnounce() is called to indicate a change in the
+ // clipboard on the server. Call requestClipboard() to access the
+ // actual data.
+ virtual void handleClipboardAnnounce(bool available);
+
+ // handleClipboardData() is called when the server has sent over
+ // the clipboard data as a result of a previous call to
+ // requestClipboard(). Note that this function might never be
+ // called if the clipboard data was no longer available when the
+ // server received the request.
+ virtual void handleClipboardData(const char* data);
+
+ protected:
CSecurity *csecurity;
SecurityClient security;
+
protected:
void setState(stateEnum s) { state_ = s; }
@@ -273,13 +297,6 @@ namespace rfb {
bool supportsLEDState;
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.
- void fence(uint32_t flags, unsigned len, const uint8_t data[]) override;
-
- private:
bool processVersionMsg();
bool processSecurityTypesMsg();
bool processSecurityMsg();
diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt
index 36535448..d7467421 100644
--- a/common/rfb/CMakeLists.txt
+++ b/common/rfb/CMakeLists.txt
@@ -3,7 +3,6 @@ add_library(rfb STATIC
Blacklist.cxx
Congestion.cxx
CConnection.cxx
- CMsgHandler.cxx
CMsgReader.cxx
CMsgWriter.cxx
CSecurityPlain.cxx
@@ -12,7 +11,6 @@ add_library(rfb STATIC
CSecurityVncAuth.cxx
ClientParams.cxx
ComparingUpdateTracker.cxx
- Configuration.cxx
CopyRectDecoder.cxx
Cursor.cxx
DecodeManager.cxx
@@ -26,19 +24,13 @@ add_library(rfb STATIC
JpegDecompressor.cxx
KeyRemapper.cxx
KeysymStr.c
- LogWriter.cxx
- Logger.cxx
- Logger_file.cxx
- Logger_stdio.cxx
PixelBuffer.cxx
PixelFormat.cxx
RREEncoder.cxx
RREDecoder.cxx
RawDecoder.cxx
RawEncoder.cxx
- Region.cxx
SConnection.cxx
- SMsgHandler.cxx
SMsgReader.cxx
SMsgWriter.cxx
ServerCore.cxx
@@ -50,7 +42,6 @@ add_library(rfb STATIC
SSecurityStack.cxx
SSecurityVncAuth.cxx
SSecurityVeNCrypt.cxx
- Timer.cxx
TightDecoder.cxx
TightEncoder.cxx
TightJPEGEncoder.cxx
@@ -60,15 +51,12 @@ add_library(rfb STATIC
ZRLEEncoder.cxx
ZRLEDecoder.cxx
encodings.cxx
- obfuscate.cxx
- util.cxx)
+ obfuscate.cxx)
target_include_directories(rfb PUBLIC ${CMAKE_SOURCE_DIR}/common)
target_include_directories(rfb SYSTEM PUBLIC ${JPEG_INCLUDE_DIR})
-target_include_directories(rfb SYSTEM PUBLIC ${PIXMAN_INCLUDE_DIRS})
-target_link_libraries(rfb os rdr network)
+target_link_libraries(rfb core rdr network)
target_link_libraries(rfb ${JPEG_LIBRARIES} ${PIXMAN_LIBRARIES})
-target_link_directories(rfb PUBLIC ${PIXMAN_LIBRARY_DIRS})
if(ENABLE_H264 AND NOT H264_LIBS STREQUAL "NONE")
target_sources(rfb PRIVATE H264Decoder.cxx H264DecoderContext.cxx)
@@ -79,11 +67,6 @@ if(ENABLE_H264 AND NOT H264_LIBS STREQUAL "NONE")
endif()
target_include_directories(rfb SYSTEM PUBLIC ${H264_INCLUDE_DIRS})
target_link_libraries(rfb ${H264_LIBRARIES})
- target_link_directories(rfb PUBLIC ${H264_LIBRARY_DIRS})
-endif()
-
-if(UNIX)
- target_sources(rfb PRIVATE Logger_syslog.cxx)
endif()
if(WIN32)
@@ -92,8 +75,9 @@ if(WIN32)
endif(WIN32)
if(UNIX AND NOT APPLE)
- target_sources(rfb PRIVATE UnixPasswordValidator.cxx pam.c)
- target_link_libraries(rfb ${PAM_LIBS})
+ target_sources(rfb PRIVATE UnixPasswordValidator.cxx)
+ target_include_directories(rfb SYSTEM PRIVATE ${PAM_INCLUDE_DIRS})
+ target_link_libraries(rfb ${PAM_LIBRARIES})
endif()
if(GNUTLS_FOUND)
@@ -109,12 +93,8 @@ endif()
if (NETTLE_FOUND)
target_sources(rfb PRIVATE CSecurityDH.cxx CSecurityMSLogonII.cxx
CSecurityRSAAES.cxx SSecurityRSAAES.cxx)
- target_include_directories(rfb SYSTEM PUBLIC ${NETTLE_INCLUDE_DIRS}
- ${GMP_INCLUDE_DIRS})
- target_link_libraries(rfb ${HOGWEED_LIBRARIES}
- ${NETTLE_LIBRARIES} ${GMP_LIBRARIES})
- target_link_directories(rfb PUBLIC ${HOGWEED_LIBRARY_DIRS}
- ${NETTLE_LIBRARY_DIRS} ${GMP_LIBRARY_DIRS})
+ target_include_directories(rfb SYSTEM PUBLIC ${NETTLE_INCLUDE_DIRS})
+ target_link_libraries(rfb ${HOGWEED_LIBRARIES} ${NETTLE_LIBRARIES})
endif()
if(UNIX)
diff --git a/common/rfb/CMsgHandler.cxx b/common/rfb/CMsgHandler.cxx
deleted file mode 100644
index 0f3f6cd5..00000000
--- a/common/rfb/CMsgHandler.cxx
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2019 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include <rfb/Exception.h>
-#include <rfb/LogWriter.h>
-#include <rfb/CMsgHandler.h>
-#include <rfb/clipboardTypes.h>
-#include <rfb/screenTypes.h>
-#include <rfb/util.h>
-
-static rfb::LogWriter vlog("CMsgHandler");
-
-using namespace rfb;
-
-CMsgHandler::CMsgHandler()
-{
-}
-
-CMsgHandler::~CMsgHandler()
-{
-}
-
-void CMsgHandler::setDesktopSize(int width, int height)
-{
- server.setDimensions(width, height);
-}
-
-void CMsgHandler::setExtendedDesktopSize(unsigned reason, unsigned result,
- int width, int height,
- const ScreenSet& layout)
-{
- server.supportsSetDesktopSize = true;
-
- if ((reason == reasonClient) && (result != resultSuccess))
- return;
-
- server.setDimensions(width, height, layout);
-}
-
-void CMsgHandler::setName(const char* name)
-{
- server.setName(name);
-}
-
-void CMsgHandler::fence(uint32_t /*flags*/, unsigned /*len*/,
- const uint8_t /*data*/ [])
-{
- server.supportsFence = true;
-}
-
-void CMsgHandler::endOfContinuousUpdates()
-{
- server.supportsContinuousUpdates = true;
-}
-
-void CMsgHandler::supportsExtendedMouseButtons()
-{
- server.supportsExtendedMouseButtons = true;
-}
-
-void CMsgHandler::supportsQEMUKeyEvent()
-{
- 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()
-{
-}
-
-void CMsgHandler::framebufferUpdateEnd()
-{
-}
-
-void CMsgHandler::setLEDState(unsigned int state)
-{
- server.setLEDState(state);
-}
-
-void CMsgHandler::handleClipboardCaps(uint32_t flags, const uint32_t* lengths)
-{
- int i;
-
- vlog.debug("Got server clipboard capabilities:");
- for (i = 0;i < 16;i++) {
- if (flags & (1 << i)) {
- const char *type;
-
- switch (1 << i) {
- case clipboardUTF8:
- type = "Plain text";
- break;
- case clipboardRTF:
- type = "Rich text";
- break;
- case clipboardHTML:
- type = "HTML";
- break;
- case clipboardDIB:
- type = "Images";
- break;
- case clipboardFiles:
- type = "Files";
- break;
- default:
- vlog.debug(" Unknown format 0x%x", 1 << i);
- continue;
- }
-
- if (lengths[i] == 0)
- vlog.debug(" %s (only notify)", type);
- else {
- vlog.debug(" %s (automatically send up to %s)",
- type, iecPrefix(lengths[i], "B").c_str());
- }
- }
- }
-
- server.setClipboardCaps(flags, lengths);
-}
-
-void CMsgHandler::handleClipboardRequest(uint32_t /*flags*/)
-{
-}
-
-void CMsgHandler::handleClipboardPeek()
-{
-}
-
-void CMsgHandler::handleClipboardNotify(uint32_t /*flags*/)
-{
-}
-
-void CMsgHandler::handleClipboardProvide(uint32_t /*flags*/,
- const size_t* /*lengths*/,
- const uint8_t* const* /*data*/)
-{
-}
diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h
index b484b695..d267ae47 100644
--- a/common/rfb/CMsgHandler.h
+++ b/common/rfb/CMsgHandler.h
@@ -27,63 +27,62 @@
#include <stdint.h>
#include <rfb/ServerParams.h>
-#include <rfb/Rect.h>
-#include <rfb/ScreenSet.h>
-namespace rdr { class InStream; }
+namespace core {
+ struct Point;
+ struct Rect;
+}
namespace rfb {
+ class ModifiablePixelBuffer;
+ struct ScreenSet;
+
class CMsgHandler {
public:
- CMsgHandler();
- virtual ~CMsgHandler();
-
// The following methods are called as corresponding messages are
- // read. A derived class should override these methods as desired.
- // Note that for the setDesktopSize(), setExtendedDesktopSize(),
- // setName(), serverInit() and handleClipboardCaps() methods, a
- // derived class should call on to CMsgHandler's methods to set the
- // members of "server" appropriately.
+ // read. A derived class must override these methods.
- virtual void setDesktopSize(int w, int h);
+ virtual void setDesktopSize(int w, int h) = 0;
virtual void setExtendedDesktopSize(unsigned reason, unsigned result,
int w, int h,
- const ScreenSet& layout);
- virtual void setCursor(int width, int height, const Point& hotspot,
+ const ScreenSet& layout) = 0;
+ virtual void setCursor(int width, int height, const
+ core::Point& hotspot,
const uint8_t* data) = 0;
- virtual void setCursorPos(const Point& pos) = 0;
- virtual void setName(const char* name);
- virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]);
- virtual void endOfContinuousUpdates();
- virtual void supportsQEMUKeyEvent();
- virtual void supportsExtendedMouseButtons();
+ virtual void setCursorPos(const core::Point& pos) = 0;
+ virtual void setName(const char* name) = 0;
+ virtual void fence(uint32_t flags, unsigned len,
+ const uint8_t data[]) = 0;
+ virtual void endOfContinuousUpdates() = 0;
+ virtual void supportsQEMUKeyEvent() = 0;
+ virtual void supportsExtendedMouseButtons() = 0;
virtual void serverInit(int width, int height,
const PixelFormat& pf,
const char* name) = 0;
- virtual bool readAndDecodeRect(const Rect& r, int encoding,
+ virtual bool readAndDecodeRect(const core::Rect& r, int encoding,
ModifiablePixelBuffer* pb) = 0;
- virtual void framebufferUpdateStart();
- virtual void framebufferUpdateEnd();
- virtual bool dataRect(const Rect& r, int encoding) = 0;
+ virtual void framebufferUpdateStart() = 0;
+ virtual void framebufferUpdateEnd() = 0;
+ virtual bool dataRect(const core::Rect& r, int encoding) = 0;
virtual void setColourMapEntries(int firstColour, int nColours,
uint16_t* rgbs) = 0;
virtual void bell() = 0;
virtual void serverCutText(const char* str) = 0;
- virtual void setLEDState(unsigned int state);
+ virtual void setLEDState(unsigned int state) = 0;
virtual void handleClipboardCaps(uint32_t flags,
- const uint32_t* lengths);
- virtual void handleClipboardRequest(uint32_t flags);
- virtual void handleClipboardPeek();
- virtual void handleClipboardNotify(uint32_t flags);
+ const uint32_t* lengths) = 0;
+ virtual void handleClipboardRequest(uint32_t flags) = 0;
+ virtual void handleClipboardPeek() = 0;
+ virtual void handleClipboardNotify(uint32_t flags) = 0;
virtual void handleClipboardProvide(uint32_t flags,
const size_t* lengths,
- const uint8_t* const* data);
+ const uint8_t* const* data) = 0;
ServerParams server;
};
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx
index a10f7c47..a5e28ea5 100644
--- a/common/rfb/CMsgReader.cxx
+++ b/common/rfb/CMsgReader.cxx
@@ -26,20 +26,27 @@
#include <vector>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rdr/InStream.h>
#include <rdr/ZlibInStream.h>
#include <rfb/msgTypes.h>
#include <rfb/clipboardTypes.h>
-#include <rfb/util.h>
#include <rfb/Exception.h>
-#include <rfb/LogWriter.h>
#include <rfb/CMsgHandler.h>
#include <rfb/CMsgReader.h>
+#include <rfb/PixelBuffer.h>
+#include <rfb/ScreenSet.h>
+#include <rfb/encodings.h>
-static rfb::LogWriter vlog("CMsgReader");
+static core::LogWriter vlog("CMsgReader");
-static rfb::IntParameter maxCutText("MaxCutText", "Maximum permitted length of an incoming clipboard update", 256*1024);
+static core::IntParameter maxCutText("MaxCutText",
+ "Maximum permitted length of an "
+ "incoming clipboard update",
+ 256*1024, 0, INT_MAX);
using namespace rfb;
@@ -77,11 +84,11 @@ bool CMsgReader::readServerInit()
is->readBytes((uint8_t*)name.data(), len);
name[len] = '\0';
- if (isValidUTF8(name.data()))
+ if (core::isValidUTF8(name.data()))
handler->serverInit(width, height, pf, name.data());
else
handler->serverInit(width, height, pf,
- latin1ToUTF8(name.data()).c_str());
+ core::latin1ToUTF8(name.data()).c_str());
return true;
}
@@ -119,7 +126,7 @@ bool CMsgReader::readMsg()
ret = readEndOfContinuousUpdates();
break;
default:
- throw protocol_error(format("Unknown message type %d", currentMsgType));
+ throw protocol_error(core::format("Unknown message type %d", currentMsgType));
}
if (ret)
@@ -288,8 +295,8 @@ bool CMsgReader::readServerCutText()
std::vector<char> ca(len);
is->readBytes((uint8_t*)ca.data(), len);
- std::string utf8(latin1ToUTF8(ca.data(), ca.size()));
- std::string filtered(convertLF(utf8.data(), utf8.size()));
+ std::string utf8(core::latin1ToUTF8(ca.data(), ca.size()));
+ std::string filtered(core::convertLF(utf8.data(), utf8.size()));
handler->serverCutText(filtered.c_str());
@@ -470,7 +477,7 @@ bool CMsgReader::readFramebufferUpdate()
return true;
}
-bool CMsgReader::readRect(const Rect& r, int encoding)
+bool CMsgReader::readRect(const core::Rect& r, int encoding)
{
if ((r.br.x > handler->server.width()) ||
(r.br.y > handler->server.height())) {
@@ -486,7 +493,8 @@ bool CMsgReader::readRect(const Rect& r, int encoding)
return handler->dataRect(r, encoding);
}
-bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
+bool CMsgReader::readSetXCursor(int width, int height,
+ const core::Point& hotspot)
{
if (width > maxCursorSize || height > maxCursorSize)
throw protocol_error("Too big cursor");
@@ -550,7 +558,8 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot)
return true;
}
-bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
+bool CMsgReader::readSetCursor(int width, int height,
+ const core::Point& hotspot)
{
if (width > maxCursorSize || height > maxCursorSize)
throw protocol_error("Too big cursor");
@@ -596,7 +605,8 @@ bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
return true;
}
-bool CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hotspot)
+bool CMsgReader::readSetCursorWithAlpha(int width, int height,
+ const core::Point& hotspot)
{
if (width > maxCursorSize || height > maxCursorSize)
throw protocol_error("Too big cursor");
@@ -657,7 +667,8 @@ bool CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hots
return true;
}
-bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot)
+bool CMsgReader::readSetVMwareCursor(int width, int height,
+ const core::Point& hotspot)
{
if (width > maxCursorSize || height > maxCursorSize)
throw protocol_error("Too big cursor");
@@ -784,7 +795,7 @@ bool CMsgReader::readSetDesktopName(int x, int y, int w, int h)
return true;
}
- if (!isValidUTF8(name.data())) {
+ if (!core::isValidUTF8(name.data())) {
vlog.error("Ignoring DesktopName rect with invalid UTF-8 sequence");
return true;
}
diff --git a/common/rfb/CMsgReader.h b/common/rfb/CMsgReader.h
index 3b1c0ddb..e33f701d 100644
--- a/common/rfb/CMsgReader.h
+++ b/common/rfb/CMsgReader.h
@@ -26,14 +26,13 @@
#include <stdint.h>
-#include <rfb/Rect.h>
-#include <rfb/encodings.h>
+#include <core/Rect.h>
namespace rdr { class InStream; }
namespace rfb {
+
class CMsgHandler;
- struct Rect;
class CMsgReader {
public:
@@ -59,12 +58,16 @@ namespace rfb {
bool readFramebufferUpdate();
- bool readRect(const Rect& r, int encoding);
+ bool readRect(const core::Rect& r, int encoding);
- bool readSetXCursor(int width, int height, const Point& hotspot);
- bool readSetCursor(int width, int height, const Point& hotspot);
- bool readSetCursorWithAlpha(int width, int height, const Point& hotspot);
- bool readSetVMwareCursor(int width, int height, const Point& hotspot);
+ bool readSetXCursor(int width, int height,
+ const core::Point& hotspot);
+ bool readSetCursor(int width, int height,
+ const core::Point& hotspot);
+ bool readSetCursorWithAlpha(int width, int height,
+ const core::Point& hotspot);
+ bool readSetVMwareCursor(int width, int height,
+ const core::Point& hotspot);
bool readSetDesktopName(int x, int y, int w, int h);
bool readExtendedDesktopSize(int x, int y, int w, int h);
bool readLEDState();
@@ -85,12 +88,14 @@ namespace rfb {
uint8_t currentMsgType;
int nUpdateRectsLeft;
- Rect dataRect;
+ core::Rect dataRect;
int rectEncoding;
int cursorEncoding;
static const int maxCursorSize = 256;
};
+
}
+
#endif
diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx
index 0128c431..c592a25e 100644
--- a/common/rfb/CMsgWriter.cxx
+++ b/common/rfb/CMsgWriter.cxx
@@ -24,6 +24,9 @@
#include <stdio.h>
#include <assert.h>
+#include <core/Rect.h>
+#include <core/string.h>
+
#include <rdr/OutStream.h>
#include <rdr/MemOutStream.h>
#include <rdr/ZlibOutStream.h>
@@ -33,10 +36,9 @@
#include <rfb/qemuTypes.h>
#include <rfb/clipboardTypes.h>
#include <rfb/PixelFormat.h>
-#include <rfb/Rect.h>
+#include <rfb/ScreenSet.h>
#include <rfb/ServerParams.h>
#include <rfb/CMsgWriter.h>
-#include <rfb/util.h>
using namespace rfb;
@@ -101,7 +103,8 @@ void CMsgWriter::writeSetDesktopSize(int width, int height,
endMsg();
}
-void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
+void CMsgWriter::writeFramebufferUpdateRequest(const core::Rect& r,
+ bool incremental)
{
startMsg(msgTypeFramebufferUpdateRequest);
os->writeU8(incremental);
@@ -173,9 +176,10 @@ void CMsgWriter::writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down)
}
-void CMsgWriter::writePointerEvent(const Point& pos, uint16_t buttonMask)
+void CMsgWriter::writePointerEvent(const core::Point& pos,
+ uint16_t buttonMask)
{
- Point p(pos);
+ core::Point p(pos);
bool extendedMouseButtons;
if (p.x < 0) p.x = 0;
@@ -223,7 +227,7 @@ void CMsgWriter::writeClientCutText(const char* str)
if (strchr(str, '\r') != nullptr)
throw std::invalid_argument("Invalid carriage return in clipboard data");
- std::string latin1(utf8ToLatin1(str));
+ std::string latin1(core::utf8ToLatin1(str));
startMsg(msgTypeClientCutText);
os->pad(3);
diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h
index 9cb4adec..d0378e62 100644
--- a/common/rfb/CMsgWriter.h
+++ b/common/rfb/CMsgWriter.h
@@ -27,6 +27,11 @@
#include <stdint.h>
+namespace core {
+ struct Point;
+ struct Rect;
+}
+
namespace rdr { class OutStream; }
namespace rfb {
@@ -34,8 +39,6 @@ namespace rfb {
class PixelFormat;
class ServerParams;
struct ScreenSet;
- struct Point;
- struct Rect;
class CMsgWriter {
public:
@@ -48,13 +51,14 @@ namespace rfb {
void writeSetEncodings(const std::list<uint32_t> encodings);
void writeSetDesktopSize(int width, int height, const ScreenSet& layout);
- void writeFramebufferUpdateRequest(const Rect& r,bool incremental);
+ void writeFramebufferUpdateRequest(const core::Rect& r,
+ bool incremental);
void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h);
void writeFence(uint32_t flags, unsigned len, const uint8_t data[]);
void writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down);
- void writePointerEvent(const Point& pos, uint16_t buttonMask);
+ void writePointerEvent(const core::Point& pos, uint16_t buttonMask);
void writeClientCutText(const char* str);
diff --git a/common/rfb/CSecurityDH.cxx b/common/rfb/CSecurityDH.cxx
index 2f0365a6..93cf6b26 100644
--- a/common/rfb/CSecurityDH.cxx
+++ b/common/rfb/CSecurityDH.cxx
@@ -40,7 +40,6 @@
#include <rdr/OutStream.h>
#include <rdr/RandomStream.h>
#include <rfb/Exception.h>
-#include <os/os.h>
using namespace rfb;
diff --git a/common/rfb/CSecurityMSLogonII.cxx b/common/rfb/CSecurityMSLogonII.cxx
index a5a99286..dfc0b658 100644
--- a/common/rfb/CSecurityMSLogonII.cxx
+++ b/common/rfb/CSecurityMSLogonII.cxx
@@ -39,7 +39,6 @@
#include <rdr/InStream.h>
#include <rdr/OutStream.h>
#include <rdr/RandomStream.h>
-#include <os/os.h>
using namespace rfb;
diff --git a/common/rfb/CSecurityRSAAES.cxx b/common/rfb/CSecurityRSAAES.cxx
index 0985d0f2..513d5605 100644
--- a/common/rfb/CSecurityRSAAES.cxx
+++ b/common/rfb/CSecurityRSAAES.cxx
@@ -34,14 +34,17 @@
#include <nettle/bignum.h>
#include <nettle/sha1.h>
#include <nettle/sha2.h>
+
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rfb/CSecurityRSAAES.h>
#include <rfb/CConnection.h>
-#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
-#include <rfb/util.h>
+
#include <rdr/AESInStream.h>
#include <rdr/AESOutStream.h>
-#include <os/os.h>
+#include <rdr/RandomStream.h>
enum {
ReadPublicKey,
@@ -55,7 +58,7 @@ const int MaxKeyLength = 8192;
using namespace rfb;
-static LogWriter vlog("CSecurityRSAAES");
+static core::LogWriter vlog("CSecurityRSAAES");
CSecurityRSAAES::CSecurityRSAAES(CConnection* cc_, uint32_t _secType,
int _keySize, bool _isAllEncrypted)
@@ -147,12 +150,12 @@ bool CSecurityRSAAES::processMsg()
return false;
}
-static void random_func(void* ctx, size_t length, uint8_t* dst)
+static void random_func(void*, size_t length, uint8_t* dst)
{
- rdr::RandomStream* rs = (rdr::RandomStream*)ctx;
- if (!rs->hasData(length))
+ rdr::RandomStream rs;
+ if (!rs.hasData(length))
throw std::runtime_error("Failed to generate random");
- rs->readBytes(dst, length);
+ rs.readBytes(dst, length);
}
void CSecurityRSAAES::writePublicKey()
@@ -170,7 +173,7 @@ void CSecurityRSAAES::writePublicKey()
// set e = 65537
mpz_set_ui(clientPublicKey.e, 65537);
if (!rsa_generate_keypair(&clientPublicKey, &clientKey,
- &rs, random_func, nullptr, nullptr,
+ nullptr, random_func, nullptr, nullptr,
clientKeyLength, 0))
throw std::runtime_error("Failed to generate key");
clientKeyN = new uint8_t[rsaKeySize];
@@ -226,7 +229,7 @@ void CSecurityRSAAES::verifyServer()
sha1_update(&ctx, serverKey.size, serverKeyE);
sha1_digest(&ctx, sizeof(f), f);
const char *title = "Server key fingerprint";
- std::string text = format(
+ std::string text = core::format(
"The server has provided the following identifying information:\n"
"Fingerprint: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n"
"Please verify that the information is correct and press \"Yes\". "
@@ -237,6 +240,7 @@ void CSecurityRSAAES::verifyServer()
void CSecurityRSAAES::writeRandom()
{
+ rdr::RandomStream rs;
rdr::OutStream* os = cc->getOutStream();
if (!rs.hasData(keySize / 8))
throw std::runtime_error("Failed to generate random");
diff --git a/common/rfb/CSecurityRSAAES.h b/common/rfb/CSecurityRSAAES.h
index af380bd3..ecbfdc4f 100644
--- a/common/rfb/CSecurityRSAAES.h
+++ b/common/rfb/CSecurityRSAAES.h
@@ -29,7 +29,7 @@
#include <rfb/CSecurity.h>
#include <rfb/Security.h>
-#include <rdr/RandomStream.h>
+namespace core { class IntParameter; }
namespace rdr {
class InStream;
@@ -39,6 +39,7 @@ namespace rdr {
}
namespace rfb {
+
class CSecurityRSAAES : public CSecurity {
public:
CSecurityRSAAES(CConnection* cc, uint32_t secType,
@@ -48,7 +49,7 @@ namespace rfb {
int getType() const override { return secType; }
bool isSecure() const override { return secType == secTypeRA256; }
- static IntParameter RSAKeyLength;
+ static core::IntParameter RSAKeyLength;
private:
void cleanup();
@@ -86,9 +87,8 @@ namespace rfb {
rdr::InStream* rawis;
rdr::OutStream* rawos;
-
- rdr::RandomStream rs;
};
+
}
#endif
diff --git a/common/rfb/CSecurityStack.h b/common/rfb/CSecurityStack.h
index 521597ec..aec800f9 100644
--- a/common/rfb/CSecurityStack.h
+++ b/common/rfb/CSecurityStack.h
@@ -21,7 +21,6 @@
#define __RFB_CSECURITYSTACK_H__
#include <rfb/CSecurity.h>
-#include <rfb/Security.h>
namespace rfb {
diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx
index 0c10a85d..6eefe73b 100644
--- a/common/rfb/CSecurityTLS.cxx
+++ b/common/rfb/CSecurityTLS.cxx
@@ -3,7 +3,7 @@
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
* Copyright (C) 2010 m-privacy GmbH
- * Copyright (C) 2012-2021 Pierre Ossman for Cendio AB
+ * Copyright 2012-2025 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
@@ -34,15 +34,16 @@
#include <unistd.h>
#endif
+#include <core/LogWriter.h>
+#include <core/string.h>
+#include <core/xdgdirs.h>
+
#include <rfb/CSecurityTLS.h>
#include <rfb/CConnection.h>
-#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
-#include <rfb/util.h>
+
#include <rdr/TLSException.h>
-#include <rdr/TLSInStream.h>
-#include <rdr/TLSOutStream.h>
-#include <os/os.h>
+#include <rdr/TLSSocket.h>
#include <gnutls/x509.h>
@@ -50,21 +51,19 @@ using namespace rfb;
static const char* configdirfn(const char* fn);
-StringParameter CSecurityTLS::X509CA("X509CA", "X509 CA certificate",
- configdirfn("x509_ca.pem"),
- ConfViewer);
-StringParameter CSecurityTLS::X509CRL("X509CRL", "X509 CRL file",
- configdirfn("x509_crl.pem"),
- ConfViewer);
+core::StringParameter CSecurityTLS::X509CA("X509CA", "X509 CA certificate",
+ configdirfn("x509_ca.pem"));
+core::StringParameter CSecurityTLS::X509CRL("X509CRL", "X509 CRL file",
+ configdirfn("x509_crl.pem"));
-static LogWriter vlog("TLS");
+static core::LogWriter vlog("TLS");
static const char* configdirfn(const char* fn)
{
static char full_path[PATH_MAX];
const char* configdir;
- configdir = os::getvncconfigdir();
+ configdir = core::getvncconfigdir();
if (configdir == nullptr)
return "";
@@ -75,7 +74,7 @@ static const char* configdirfn(const char* fn)
CSecurityTLS::CSecurityTLS(CConnection* cc_, bool _anon)
: CSecurity(cc_), session(nullptr),
anon_cred(nullptr), cert_cred(nullptr),
- anon(_anon), tlsis(nullptr), tlsos(nullptr),
+ anon(_anon), tlssock(nullptr),
rawis(nullptr), rawos(nullptr)
{
int err = gnutls_global_init();
@@ -85,27 +84,8 @@ CSecurityTLS::CSecurityTLS(CConnection* cc_, bool _anon)
void CSecurityTLS::shutdown()
{
- if (tlsos) {
- try {
- if (tlsos->hasBufferedData()) {
- tlsos->cork(false);
- tlsos->flush();
- if (tlsos->hasBufferedData())
- vlog.error("Failed to flush remaining socket data on close");
- }
- } catch (std::exception& e) {
- vlog.error("Failed to flush remaining socket data on close: %s", e.what());
- }
- }
-
- if (session) {
- int ret;
- // FIXME: We can't currently wait for the response, so we only send
- // our close and hope for the best
- ret = gnutls_bye(session, GNUTLS_SHUT_WR);
- if ((ret != GNUTLS_E_SUCCESS) && (ret != GNUTLS_E_INVALID_SESSION))
- vlog.error("TLS shutdown failed: %s", gnutls_strerror(ret));
- }
+ if (tlssock)
+ tlssock->shutdown();
if (anon_cred) {
gnutls_anon_free_client_credentials(anon_cred);
@@ -123,13 +103,9 @@ void CSecurityTLS::shutdown()
rawos = nullptr;
}
- if (tlsis) {
- delete tlsis;
- tlsis = nullptr;
- }
- if (tlsos) {
- delete tlsos;
- tlsos = nullptr;
+ if (tlssock) {
+ delete tlssock;
+ tlssock = nullptr;
}
if (session) {
@@ -171,26 +147,18 @@ bool CSecurityTLS::processMsg()
setParam();
- // Create these early as they set up the push/pull functions
- // for GnuTLS
- tlsis = new rdr::TLSInStream(is, session);
- tlsos = new rdr::TLSOutStream(os, session);
+ tlssock = new rdr::TLSSocket(is, os, session);
rawis = is;
rawos = os;
}
- int err;
- err = gnutls_handshake(session);
- if (err != GNUTLS_E_SUCCESS) {
- if (!gnutls_error_is_fatal(err)) {
- vlog.debug("Deferring completion of TLS handshake: %s", gnutls_strerror(err));
+ try {
+ if (!tlssock->handshake())
return false;
- }
-
- vlog.error("TLS Handshake failed: %s\n", gnutls_strerror (err));
+ } catch (std::exception&) {
shutdown();
- throw rdr::tls_error("TLS Handshake failed", err);
+ throw;
}
vlog.debug("TLS handshake completed with %s",
@@ -198,33 +166,29 @@ bool CSecurityTLS::processMsg()
checkSession();
- cc->setStreams(tlsis, tlsos);
+ cc->setStreams(&tlssock->inStream(), &tlssock->outStream());
return true;
}
void CSecurityTLS::setParam()
{
- static const char kx_anon_priority[] = ":+ANON-ECDH:+ANON-DH";
+ static const char kx_anon_priority[] = "+ANON-ECDH:+ANON-DH";
int ret;
// Custom priority string specified?
if (strcmp(Security::GnuTLSPriority, "") != 0) {
- char *prio;
+ std::string prio;
const char *err;
- prio = new char[strlen(Security::GnuTLSPriority) +
- strlen(kx_anon_priority) + 1];
-
- strcpy(prio, Security::GnuTLSPriority);
- if (anon)
- strcat(prio, kx_anon_priority);
-
- ret = gnutls_priority_set_direct(session, prio, &err);
-
- delete [] prio;
+ prio = (const char*)Security::GnuTLSPriority;
+ if (anon) {
+ prio += ":";
+ prio += kx_anon_priority;
+ }
+ ret = gnutls_priority_set_direct(session, prio.c_str(), &err);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
@@ -234,30 +198,22 @@ void CSecurityTLS::setParam()
const char *err;
#if GNUTLS_VERSION_NUMBER >= 0x030603
- // gnutls_set_default_priority_appends() expects a normal priority string that
- // doesn't start with ":".
- ret = gnutls_set_default_priority_append(session, kx_anon_priority + 1, &err, 0);
+ ret = gnutls_set_default_priority_append(session, kx_anon_priority, &err, 0);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
throw rdr::tls_error("gnutls_set_default_priority_append()", ret);
}
#else
+ std::string prio;
+
// We don't know what the system default priority is, so we guess
// it's what upstream GnuTLS has
- static const char gnutls_default_priority[] = "NORMAL";
- char *prio;
-
- prio = new char[malloc(strlen(gnutls_default_priority) +
- strlen(kx_anon_priority) + 1];
-
- strcpy(prio, gnutls_default_priority);
- strcat(prio, kx_anon_priority);
-
- ret = gnutls_priority_set_direct(session, prio, &err);
-
- delete [] prio;
+ prio = "NORMAL";
+ prio += ":";
+ prio += kx_anon_priority;
+ ret = gnutls_priority_set_direct(session, prio.c_str(), &err);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
@@ -277,6 +233,10 @@ void CSecurityTLS::setParam()
vlog.debug("Anonymous session has been set");
} else {
+ const char* hostname;
+ size_t len;
+ bool valid;
+
ret = gnutls_certificate_allocate_credentials(&cert_cred);
if (ret != GNUTLS_E_SUCCESS)
throw rdr::tls_error("gnutls_certificate_allocate_credentials()", ret);
@@ -294,10 +254,22 @@ void CSecurityTLS::setParam()
if (ret != GNUTLS_E_SUCCESS)
throw rdr::tls_error("gnutls_credentials_set()", ret);
- if (gnutls_server_name_set(session, GNUTLS_NAME_DNS,
- client->getServerName(),
- strlen(client->getServerName())) != GNUTLS_E_SUCCESS)
- vlog.error("Failed to configure the server name for TLS handshake");
+ // Only DNS hostnames are allowed, and some servers will reject the
+ // connection if we provide anything else (e.g. an IPv6 address)
+ hostname = client->getServerName();
+ len = strlen(hostname);
+ valid = true;
+ for (size_t i = 0; i < len; i++) {
+ if (!isalnum(hostname[i]) && hostname[i] != '.')
+ valid = false;
+ }
+
+ if (valid) {
+ if (gnutls_server_name_set(session, GNUTLS_NAME_DNS,
+ client->getServerName(),
+ strlen(client->getServerName())) != GNUTLS_E_SUCCESS)
+ vlog.error("Failed to configure the server name for TLS handshake");
+ }
vlog.debug("X509 session has been set");
}
@@ -324,12 +296,16 @@ void CSecurityTLS::checkSession()
if (anon)
return;
- if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
+ if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_UNSUPPORTED_CERTIFICATE);
throw protocol_error("Unsupported certificate type");
+ }
err = gnutls_certificate_verify_peers2(session, &status);
if (err != 0) {
vlog.error("Server certificate verification failed: %s", gnutls_strerror(err));
+ gnutls_alert_send_appropriate(session, err);
throw rdr::tls_error("Server certificate verification()", err);
}
@@ -346,23 +322,29 @@ void CSecurityTLS::checkSession()
GNUTLS_CRT_X509,
&status_str,
0);
- if (err != GNUTLS_E_SUCCESS)
+ if (err != GNUTLS_E_SUCCESS) {
+ gnutls_alert_send_appropriate(session, err);
throw rdr::tls_error("Failed to get certificate error description", err);
+ }
error = (const char*)status_str.data;
gnutls_free(status_str.data);
- throw protocol_error(format("Invalid server certificate: %s",
- error.c_str()));
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
+ throw protocol_error(
+ core::format("Invalid server certificate: %s", error.c_str()));
}
err = gnutls_certificate_verification_status_print(status,
GNUTLS_CRT_X509,
&status_str,
0);
- if (err != GNUTLS_E_SUCCESS)
+ if (err != GNUTLS_E_SUCCESS) {
+ gnutls_alert_send_appropriate(session, err);
throw rdr::tls_error("Failed to get certificate error description", err);
+ }
vlog.info("Server certificate errors: %s", status_str.data);
@@ -372,16 +354,21 @@ void CSecurityTLS::checkSession()
/* Process overridable errors later */
cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
- if (!cert_list_size)
+ if (!cert_list_size) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_UNSUPPORTED_CERTIFICATE);
throw protocol_error("Empty certificate chain");
+ }
/* Process only server's certificate, not issuer's certificate */
gnutls_x509_crt_t crt;
gnutls_x509_crt_init(&crt);
err = gnutls_x509_crt_import(crt, &cert_list[0], GNUTLS_X509_FMT_DER);
- if (err != GNUTLS_E_SUCCESS)
+ if (err != GNUTLS_E_SUCCESS) {
+ gnutls_alert_send_appropriate(session, err);
throw rdr::tls_error("Failed to decode server certificate", err);
+ }
if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) {
vlog.info("Server certificate doesn't match given server name");
@@ -398,7 +385,7 @@ void CSecurityTLS::checkSession()
/* Certificate has some user overridable problems, so TOFU time */
- hostsDir = os::getvncstatedir();
+ hostsDir = core::getvncstatedir();
if (hostsDir == nullptr) {
throw std::runtime_error("Could not obtain VNC state directory "
"path for known hosts storage");
@@ -420,12 +407,15 @@ void CSecurityTLS::checkSession()
if ((known != GNUTLS_E_NO_CERTIFICATE_FOUND) &&
(known != GNUTLS_E_CERTIFICATE_KEY_MISMATCH)) {
+ gnutls_alert_send_appropriate(session, known);
throw rdr::tls_error("Could not load known hosts database", known);
}
err = gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info);
- if (err != GNUTLS_E_SUCCESS)
+ if (err != GNUTLS_E_SUCCESS) {
+ gnutls_alert_send_appropriate(session, known);
throw rdr::tls_error("Could not find certificate to display", err);
+ }
len = strlen((char*)info.data);
for (size_t i = 0; i < len - 1; i++) {
@@ -443,21 +433,24 @@ void CSecurityTLS::checkSession()
if (status & (GNUTLS_CERT_INVALID |
GNUTLS_CERT_SIGNER_NOT_FOUND |
GNUTLS_CERT_SIGNER_NOT_CA)) {
- text = format("This certificate has been signed by an unknown "
- "authority:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This certificate has been signed by an unknown authority:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Unknown certificate issuer",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_UNKNOWN_CA);
throw auth_cancelled();
+ }
status &= ~(GNUTLS_CERT_INVALID |
GNUTLS_CERT_SIGNER_NOT_FOUND |
@@ -465,82 +458,101 @@ void CSecurityTLS::checkSession()
}
if (status & GNUTLS_CERT_NOT_ACTIVATED) {
- text = format("This certificate is not yet valid:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This certificate is not yet valid:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
+
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Certificate is not yet valid",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
status &= ~GNUTLS_CERT_NOT_ACTIVATED;
}
if (status & GNUTLS_CERT_EXPIRED) {
- text = format("This certificate has expired:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This certificate has expired:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Expired certificate",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
status &= ~GNUTLS_CERT_EXPIRED;
}
if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
- text = format("This certificate uses an insecure algorithm:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This certificate uses an insecure algorithm:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Insecure certificate algorithm",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
status &= ~GNUTLS_CERT_INSECURE_ALGORITHM;
}
if (status != 0) {
vlog.error("Unhandled certificate problems: 0x%x", status);
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw std::logic_error("Unhandled certificate problems");
}
if (!hostname_match) {
- text = format("The specified hostname \"%s\" does not match the "
- "certificate provided by the server:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", client->getServerName(), info.data);
+ text = core::format(
+ "The specified hostname \"%s\" does not match the certificate "
+ "provided by the server:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ client->getServerName(), info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Certificate hostname mismatch",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
}
} else if (known == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
std::string text;
@@ -551,22 +563,26 @@ void CSecurityTLS::checkSession()
if (status & (GNUTLS_CERT_INVALID |
GNUTLS_CERT_SIGNER_NOT_FOUND |
GNUTLS_CERT_SIGNER_NOT_CA)) {
- text = format("This host is previously known with a different "
- "certificate, and the new certificate has been "
- "signed by an unknown authority:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This host is previously known with a different certificate, "
+ "and the new certificate has been signed by an unknown "
+ "authority:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Unexpected server certificate",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_UNKNOWN_CA);
throw auth_cancelled();
+ }
status &= ~(GNUTLS_CERT_INVALID |
GNUTLS_CERT_SIGNER_NOT_FOUND |
@@ -574,91 +590,105 @@ void CSecurityTLS::checkSession()
}
if (status & GNUTLS_CERT_NOT_ACTIVATED) {
- text = format("This host is previously known with a different "
- "certificate, and the new certificate is not yet "
- "valid:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This host is previously known with a different certificate, "
+ "and the new certificate is not yet valid:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Unexpected server certificate",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
status &= ~GNUTLS_CERT_NOT_ACTIVATED;
}
if (status & GNUTLS_CERT_EXPIRED) {
- text = format("This host is previously known with a different "
- "certificate, and the new certificate has "
- "expired:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This host is previously known with a different certificate, "
+ "and the new certificate has expired:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Unexpected server certificate",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
status &= ~GNUTLS_CERT_EXPIRED;
}
if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
- text = format("This host is previously known with a different "
- "certificate, and the new certificate uses an "
- "insecure algorithm:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", info.data);
+ text = core::format(
+ "This host is previously known with a different certificate, "
+ "and the new certificate uses an insecure algorithm:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Unexpected server certificate",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
status &= ~GNUTLS_CERT_INSECURE_ALGORITHM;
}
if (status != 0) {
vlog.error("Unhandled certificate problems: 0x%x", status);
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw std::logic_error("Unhandled certificate problems");
}
if (!hostname_match) {
- text = format("This host is previously known with a different "
- "certificate, and the specified hostname \"%s\" "
- "does not match the new certificate provided by "
- "the server:\n"
- "\n"
- "%s\n"
- "\n"
- "Someone could be trying to impersonate the site "
- "and you should not continue.\n"
- "\n"
- "Do you want to make an exception for this "
- "server?", client->getServerName(), info.data);
+ text = core::format(
+ "This host is previously known with a different certificate, "
+ "and the specified hostname \"%s\" does not match the new "
+ "certificate provided by the server:\n"
+ "\n"
+ "%s\n"
+ "\n"
+ "Someone could be trying to impersonate the site and you "
+ "should not continue.\n"
+ "\n"
+ "Do you want to make an exception for this server?",
+ client->getServerName(), info.data);
if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,
"Unexpected server certificate",
- text.c_str()))
+ text.c_str())) {
+ gnutls_alert_send(session, GNUTLS_AL_FATAL,
+ GNUTLS_A_BAD_CERTIFICATE);
throw auth_cancelled();
+ }
}
}
diff --git a/common/rfb/CSecurityTLS.h b/common/rfb/CSecurityTLS.h
index 2464cb6c..51b7dac1 100644
--- a/common/rfb/CSecurityTLS.h
+++ b/common/rfb/CSecurityTLS.h
@@ -2,6 +2,7 @@
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
+ * Copyright 2012-2025 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
@@ -34,8 +35,7 @@
namespace rdr {
class InStream;
class OutStream;
- class TLSInStream;
- class TLSOutStream;
+ class TLSSocket;
}
namespace rfb {
@@ -47,8 +47,8 @@ namespace rfb {
int getType() const override { return anon ? secTypeTLSNone : secTypeX509None; }
bool isSecure() const override { return !anon; }
- static StringParameter X509CA;
- static StringParameter X509CRL;
+ static core::StringParameter X509CA;
+ static core::StringParameter X509CRL;
protected:
void shutdown();
@@ -63,8 +63,7 @@ namespace rfb {
gnutls_certificate_credentials_t cert_cred;
bool anon;
- rdr::TLSInStream* tlsis;
- rdr::TLSOutStream* tlsos;
+ rdr::TLSSocket* tlssock;
rdr::InStream* rawis;
rdr::OutStream* rawos;
diff --git a/common/rfb/CSecurityVeNCrypt.cxx b/common/rfb/CSecurityVeNCrypt.cxx
index 1b6ecf22..a6e30947 100644
--- a/common/rfb/CSecurityVeNCrypt.cxx
+++ b/common/rfb/CSecurityVeNCrypt.cxx
@@ -29,16 +29,17 @@
#include <algorithm>
#include <list>
+#include <core/LogWriter.h>
+
#include <rfb/Exception.h>
#include <rdr/InStream.h>
#include <rdr/OutStream.h>
#include <rfb/CConnection.h>
#include <rfb/CSecurityVeNCrypt.h>
-#include <rfb/LogWriter.h>
using namespace rfb;
-static LogWriter vlog("CVeNCrypt");
+static core::LogWriter vlog("CVeNCrypt");
CSecurityVeNCrypt::CSecurityVeNCrypt(CConnection* cc_,
SecurityClient* sec)
diff --git a/common/rfb/CSecurityVeNCrypt.h b/common/rfb/CSecurityVeNCrypt.h
index f73e7927..8e2c6d5e 100644
--- a/common/rfb/CSecurityVeNCrypt.h
+++ b/common/rfb/CSecurityVeNCrypt.h
@@ -28,10 +28,11 @@
#include <stdint.h>
#include <rfb/CSecurity.h>
-#include <rfb/SecurityClient.h>
namespace rfb {
+ class SecurityClient;
+
class CSecurityVeNCrypt : public CSecurity {
public:
diff --git a/common/rfb/ClientParams.cxx b/common/rfb/ClientParams.cxx
index e5fd105e..514b0b4e 100644
--- a/common/rfb/ClientParams.cxx
+++ b/common/rfb/ClientParams.cxx
@@ -24,14 +24,20 @@
#include <stdexcept>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rfb/encodings.h>
#include <rfb/ledStates.h>
#include <rfb/clipboardTypes.h>
#include <rfb/ClientParams.h>
-#include <rfb/util.h>
+#include <rfb/Cursor.h>
+#include <rfb/ScreenSet.h>
using namespace rfb;
+static core::LogWriter vlog("ClientParams");
+
ClientParams::ClientParams()
: majorVersion(0), minorVersion(0),
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
@@ -41,7 +47,11 @@ ClientParams::ClientParams()
{
setName("");
- cursor_ = new Cursor(0, 0, Point(), nullptr);
+ screenLayout_ = new ScreenSet();
+
+ pf_ = new PixelFormat();
+
+ cursor_ = new Cursor(0, 0, {}, nullptr);
clipFlags = clipboardUTF8 | clipboardRTF | clipboardHTML |
clipboardRequest | clipboardNotify | clipboardProvide;
@@ -51,7 +61,9 @@ ClientParams::ClientParams()
ClientParams::~ClientParams()
{
+ delete screenLayout_;
delete cursor_;
+ delete pf_;
}
void ClientParams::setDimensions(int width, int height)
@@ -63,17 +75,25 @@ void ClientParams::setDimensions(int width, int height)
void ClientParams::setDimensions(int width, int height, const ScreenSet& layout)
{
- if (!layout.validate(width, height))
+ if (!layout.validate(width, height)) {
+ char buffer[2048];
+ vlog.debug("Invalid screen layout for %dx%d:", width, height);
+ layout.print(buffer, sizeof(buffer));
+ vlog.debug("%s", buffer);
+
throw std::invalid_argument("Attempted to configure an invalid screen layout");
+ }
width_ = width;
height_ = height;
- screenLayout_ = layout;
+ delete screenLayout_;
+ screenLayout_ = new ScreenSet(layout);
}
void ClientParams::setPF(const PixelFormat& pf)
{
- pf_ = pf;
+ delete pf_;
+ pf_ = new PixelFormat(pf);
if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)
throw std::invalid_argument("setPF: Not 8, 16 or 32 bpp?");
@@ -90,7 +110,7 @@ void ClientParams::setCursor(const Cursor& other)
cursor_ = new Cursor(other);
}
-void ClientParams::setCursorPos(const Point& pos)
+void ClientParams::setCursorPos(const core::Point& pos)
{
cursorPos_ = pos;
}
@@ -162,7 +182,7 @@ uint32_t ClientParams::clipboardSize(unsigned int format) const
return clipSizes[i];
}
- throw std::invalid_argument(rfb::format("Invalid clipboard format 0x%x", format));
+ throw std::invalid_argument(core::format("Invalid clipboard format 0x%x", format));
}
void ClientParams::setClipboardCaps(uint32_t flags, const uint32_t* lengths)
@@ -236,4 +256,4 @@ bool ClientParams::supportsExtendedMouseButtons() const
if (supportsEncoding(pseudoEncodingExtendedMouseButtons))
return true;
return false;
-} \ No newline at end of file
+}
diff --git a/common/rfb/ClientParams.h b/common/rfb/ClientParams.h
index f715c47f..0910181b 100644
--- a/common/rfb/ClientParams.h
+++ b/common/rfb/ClientParams.h
@@ -28,12 +28,14 @@
#include <stdint.h>
-#include <rfb/Cursor.h>
-#include <rfb/PixelFormat.h>
-#include <rfb/ScreenSet.h>
+#include <core/Rect.h>
namespace rfb {
+ class Cursor;
+ class PixelFormat;
+ struct ScreenSet;
+
const int subsampleUndefined = -1;
const int subsampleNone = 0;
const int subsampleGray = 1;
@@ -66,11 +68,11 @@ namespace rfb {
int width() const { return width_; }
int height() const { return height_; }
- const ScreenSet& screenLayout() const { return screenLayout_; }
+ 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_; }
+ const PixelFormat& pf() const { return *pf_; }
void setPF(const PixelFormat& pf);
const char* name() const { return name_.c_str(); }
@@ -79,8 +81,8 @@ namespace rfb {
const Cursor& cursor() const { return *cursor_; }
void setCursor(const Cursor& cursor);
- const Point& cursorPos() const { return cursorPos_; }
- void setCursorPos(const Point& pos);
+ const core::Point& cursorPos() const { return cursorPos_; }
+ void setCursorPos(const core::Point& pos);
bool supportsEncoding(int32_t encoding) const;
@@ -112,12 +114,12 @@ namespace rfb {
int width_;
int height_;
- ScreenSet screenLayout_;
+ ScreenSet* screenLayout_;
- PixelFormat pf_;
+ PixelFormat* pf_;
std::string name_;
Cursor* cursor_;
- Point cursorPos_;
+ core::Point cursorPos_;
std::set<int32_t> encodings_;
unsigned int ledState_;
uint32_t clipFlags;
diff --git a/common/rfb/ComparingUpdateTracker.cxx b/common/rfb/ComparingUpdateTracker.cxx
index dab5e6aa..a89c3ec3 100644
--- a/common/rfb/ComparingUpdateTracker.cxx
+++ b/common/rfb/ComparingUpdateTracker.cxx
@@ -22,17 +22,18 @@
#include <stdio.h>
#include <string.h>
+
+#include <algorithm>
#include <vector>
-#include <rfb/Exception.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
+#include <core/LogWriter.h>
+#include <core/string.h>
#include <rfb/ComparingUpdateTracker.h>
using namespace rfb;
-static LogWriter vlog("ComparingUpdateTracker");
+static core::LogWriter vlog("ComparingUpdateTracker");
ComparingUpdateTracker::ComparingUpdateTracker(PixelBuffer* buffer)
: fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true),
@@ -50,8 +51,8 @@ ComparingUpdateTracker::~ComparingUpdateTracker()
bool ComparingUpdateTracker::compare()
{
- std::vector<Rect> rects;
- std::vector<Rect>::iterator i;
+ std::vector<core::Rect> rects;
+ std::vector<core::Rect>::iterator i;
if (!enabled)
return false;
@@ -62,7 +63,7 @@ bool ComparingUpdateTracker::compare()
oldFb.setSize(fb->width(), fb->height());
for (int y=0; y<fb->height(); y+=BLOCK_SIZE) {
- Rect pos(0, y, fb->width(), __rfbmin(fb->height(), y+BLOCK_SIZE));
+ core::Rect pos(0, y, fb->width(), std::min(fb->height(), y+BLOCK_SIZE));
int srcStride;
const uint8_t* srcData = fb->getBuffer(pos, &srcStride);
oldFb.imageRect(pos, srcData, srcStride);
@@ -79,7 +80,7 @@ bool ComparingUpdateTracker::compare()
changed.get_rects(&rects);
- Region newChanged;
+ core::Region newChanged;
for (i = rects.begin(); i != rects.end(); i++)
compareRect(*i, &newChanged);
@@ -111,10 +112,11 @@ void ComparingUpdateTracker::disable()
firstCompare = true;
}
-void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
+void ComparingUpdateTracker::compareRect(const core::Rect& r,
+ core::Region* newChanged)
{
if (!r.enclosed_by(fb->getRect())) {
- Rect safe;
+ core::Rect safe;
// Crop the rect and try again
safe = r.intersect(fb->getRect());
if (!safe.is_empty())
@@ -134,20 +136,20 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
for (int blockTop = r.tl.y; blockTop < r.br.y; blockTop += BLOCK_SIZE)
{
// Get a strip of the source buffer
- Rect pos(r.tl.x, blockTop, r.br.x, __rfbmin(r.br.y, blockTop+BLOCK_SIZE));
+ core::Rect pos(r.tl.x, blockTop, r.br.x, std::min(r.br.y, blockTop+BLOCK_SIZE));
int fbStride;
const uint8_t* newBlockPtr = fb->getBuffer(pos, &fbStride);
int newStrideBytes = fbStride * bytesPerPixel;
uint8_t* oldBlockPtr = oldData;
- int blockBottom = __rfbmin(blockTop+BLOCK_SIZE, r.br.y);
+ int blockBottom = std::min(blockTop+BLOCK_SIZE, r.br.y);
for (int blockLeft = r.tl.x; blockLeft < r.br.x; blockLeft += BLOCK_SIZE)
{
const uint8_t* newPtr = newBlockPtr;
uint8_t* oldPtr = oldBlockPtr;
- int blockRight = __rfbmin(blockLeft+BLOCK_SIZE, r.br.x);
+ int blockRight = std::min(blockLeft+BLOCK_SIZE, r.br.x);
int blockWidthInBytes = (blockRight-blockLeft) * bytesPerPixel;
// Scan the block top to bottom, to identify the first row of change
@@ -223,8 +225,10 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
}
endOfChangeRight:
- // Block change extends from (changeLeft, y) to (changeRight, y + changeHeight)
- newChanged->assign_union(Region(Rect(changeLeft, y, changeRight, y + changeHeight)));
+ // Block change extends from (changeLeft, y) to (changeRight,
+ // y + changeHeight)
+ newChanged->assign_union({{changeLeft, y,
+ changeRight, y + changeHeight}});
// Copy the change from fb to oldFb to allow future changes to be identified
for (int row = 0; row < changeHeight; row++)
@@ -258,10 +262,12 @@ void ComparingUpdateTracker::logStats()
ratio = (double)totalPixels / missedPixels;
- vlog.info("%s in / %s out",
- siPrefix(totalPixels, "pixels").c_str(),
- siPrefix(missedPixels, "pixels").c_str());
- vlog.info("(1:%g ratio)", ratio);
+ // FIXME: This gets spammed on each session resize, so we'll have to
+ // keep it on a debug level for now
+ vlog.debug("%s in / %s out",
+ core::siPrefix(totalPixels, "pixels").c_str(),
+ core::siPrefix(missedPixels, "pixels").c_str());
+ vlog.debug("(1:%g ratio)", ratio);
totalPixels = missedPixels = 0;
}
diff --git a/common/rfb/ComparingUpdateTracker.h b/common/rfb/ComparingUpdateTracker.h
index ca1dcc30..dbe7a4ef 100644
--- a/common/rfb/ComparingUpdateTracker.h
+++ b/common/rfb/ComparingUpdateTracker.h
@@ -19,6 +19,7 @@
#ifndef __RFB_COMPARINGUPDATETRACKER_H__
#define __RFB_COMPARINGUPDATETRACKER_H__
+#include <rfb/PixelBuffer.h>
#include <rfb/UpdateTracker.h>
namespace rfb {
@@ -44,7 +45,7 @@ namespace rfb {
void logStats();
private:
- void compareRect(const Rect& r, Region* newchanged);
+ void compareRect(const core::Rect& r, core::Region* newchanged);
PixelBuffer* fb;
ManagedPixelBuffer oldFb;
bool firstCompare;
diff --git a/common/rfb/Configuration.cxx b/common/rfb/Configuration.cxx
deleted file mode 100644
index 72947df1..00000000
--- a/common/rfb/Configuration.cxx
+++ /dev/null
@@ -1,469 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2004-2005 Cendio AB.
- * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
- * Copyright 2011-2022 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.
- */
-
-// -=- Configuration.cxx
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#include <stdexcept>
-
-#include <os/Mutex.h>
-
-#include <rfb/util.h>
-#include <rfb/Configuration.h>
-#include <rfb/LogWriter.h>
-
-#define LOCK_CONFIG os::AutoMutex a(mutex)
-
-#include <rdr/HexOutStream.h>
-#include <rdr/HexInStream.h>
-
-using namespace rfb;
-
-static LogWriter vlog("Config");
-
-
-// -=- The Global/server/viewer Configuration objects
-Configuration* Configuration::global_ = nullptr;
-Configuration* Configuration::server_ = nullptr;
-Configuration* Configuration::viewer_ = nullptr;
-
-Configuration* Configuration::global() {
- if (!global_)
- global_ = new Configuration("Global");
- return global_;
-}
-
-Configuration* Configuration::server() {
- if (!server_)
- server_ = new Configuration("Server");
- return server_;
-}
-
-Configuration* Configuration::viewer() {
- if (!viewer_)
- viewer_ = new Configuration("Viewer");
- return viewer_;
-}
-
-// -=- Configuration implementation
-
-bool Configuration::set(const char* n, const char* v, bool immutable) {
- return set(n, strlen(n), v, immutable);
-}
-
-bool Configuration::set(const char* paramName, int len,
- const char* val, bool immutable)
-{
- VoidParameter* current = head;
- while (current) {
- if ((int)strlen(current->getName()) == len &&
- strncasecmp(current->getName(), paramName, len) == 0)
- {
- bool b = current->setParam(val);
- if (b && immutable)
- current->setImmutable();
- return b;
- }
- current = current->_next;
- }
- return _next ? _next->set(paramName, len, val, immutable) : false;
-}
-
-bool Configuration::set(const char* config, bool immutable) {
- bool hyphen = false;
- if (config[0] == '-') {
- hyphen = true;
- config++;
- if (config[0] == '-') config++; // allow gnu-style --<option>
- }
- const char* equal = strchr(config, '=');
- if (equal) {
- return set(config, equal-config, equal+1, immutable);
- } else if (hyphen) {
- VoidParameter* current = head;
- while (current) {
- if (strcasecmp(current->getName(), config) == 0) {
- bool b = current->setParam();
- if (b && immutable)
- current->setImmutable();
- return b;
- }
- current = current->_next;
- }
- }
- return _next ? _next->set(config, immutable) : false;
-}
-
-VoidParameter* Configuration::get(const char* param)
-{
- VoidParameter* current = head;
- while (current) {
- if (strcasecmp(current->getName(), param) == 0)
- return current;
- current = current->_next;
- }
- return _next ? _next->get(param) : nullptr;
-}
-
-void Configuration::list(int width, int nameWidth) {
- VoidParameter* current = head;
-
- fprintf(stderr, "%s Parameters:\n", name.c_str());
- while (current) {
- std::string def_str = current->getDefaultStr();
- const char* desc = current->getDescription();
- fprintf(stderr," %-*s -", nameWidth, current->getName());
- int column = strlen(current->getName());
- if (column < nameWidth) column = nameWidth;
- column += 4;
- while (true) {
- const char* s = strchr(desc, ' ');
- int wordLen;
- if (s) wordLen = s-desc;
- else wordLen = strlen(desc);
-
- if (column + wordLen + 1 > width) {
- fprintf(stderr,"\n%*s",nameWidth+4,"");
- column = nameWidth+4;
- }
- fprintf(stderr," %.*s",wordLen,desc);
- column += wordLen + 1;
- desc += wordLen + 1;
- if (!s) break;
- }
-
- if (!def_str.empty()) {
- if (column + (int)def_str.size() + 11 > width)
- fprintf(stderr,"\n%*s",nameWidth+4,"");
- fprintf(stderr," (default=%s)\n",def_str.c_str());
- } else {
- fprintf(stderr,"\n");
- }
- current = current->_next;
- }
-
- if (_next)
- _next->list(width, nameWidth);
-}
-
-
-bool Configuration::remove(const char* param) {
- VoidParameter *current = head;
- VoidParameter **prevnext = &head;
-
- while (current) {
- if (strcasecmp(current->getName(), param) == 0) {
- *prevnext = current->_next;
- return true;
- }
- prevnext = &current->_next;
- current = current->_next;
- }
-
- return false;
-}
-
-
-// -=- VoidParameter
-
-VoidParameter::VoidParameter(const char* name_, const char* desc_,
- ConfigurationObject co)
- : immutable(false), name(name_), description(desc_)
-{
- Configuration *conf = nullptr;
-
- switch (co) {
- case ConfGlobal: conf = Configuration::global();
- break;
- case ConfServer: conf = Configuration::server();
- break;
- case ConfViewer: conf = Configuration::viewer();
- break;
- }
-
- _next = conf->head;
- conf->head = this;
-
- mutex = new os::Mutex();
-}
-
-VoidParameter::~VoidParameter() {
- delete mutex;
-}
-
-const char*
-VoidParameter::getName() const {
- return name;
-}
-
-const char*
-VoidParameter::getDescription() const {
- return description;
-}
-
-bool VoidParameter::setParam() {
- return false;
-}
-
-bool VoidParameter::isBool() const {
- return false;
-}
-
-void
-VoidParameter::setImmutable() {
- vlog.debug("Set immutable %s", getName());
- immutable = true;
-}
-
-// -=- AliasParameter
-
-AliasParameter::AliasParameter(const char* name_, const char* desc_,
- VoidParameter* param_, ConfigurationObject co)
- : VoidParameter(name_, desc_, co), param(param_) {
-}
-
-bool
-AliasParameter::setParam(const char* v) {
- return param->setParam(v);
-}
-
-bool AliasParameter::setParam() {
- return param->setParam();
-}
-
-std::string AliasParameter::getDefaultStr() const {
- return "";
-}
-
-std::string AliasParameter::getValueStr() const {
- return param->getValueStr();
-}
-
-bool AliasParameter::isBool() const {
- return param->isBool();
-}
-
-void
-AliasParameter::setImmutable() {
- vlog.debug("Set immutable %s (Alias)", getName());
- param->setImmutable();
-}
-
-
-// -=- BoolParameter
-
-BoolParameter::BoolParameter(const char* name_, const char* desc_, bool v,
- ConfigurationObject co)
-: VoidParameter(name_, desc_, co), value(v), def_value(v) {
-}
-
-bool
-BoolParameter::setParam(const char* v) {
- if (immutable) return true;
-
- if (*v == 0 || strcasecmp(v, "1") == 0 || strcasecmp(v, "on") == 0
- || strcasecmp(v, "true") == 0 || strcasecmp(v, "yes") == 0)
- setParam(true);
- else if (strcasecmp(v, "0") == 0 || strcasecmp(v, "off") == 0
- || strcasecmp(v, "false") == 0 || strcasecmp(v, "no") == 0)
- setParam(false);
- else {
- vlog.error("Bool parameter %s: Invalid value '%s'", getName(), v);
- return false;
- }
-
- return true;
-}
-
-bool BoolParameter::setParam() {
- setParam(true);
- return true;
-}
-
-void BoolParameter::setParam(bool b) {
- if (immutable) return;
- value = b;
- vlog.debug("Set %s(Bool) to %d", getName(), value);
-}
-
-std::string BoolParameter::getDefaultStr() const {
- return def_value ? "1" : "0";
-}
-
-std::string BoolParameter::getValueStr() const {
- return value ? "1" : "0";
-}
-
-bool BoolParameter::isBool() const {
- return true;
-}
-
-BoolParameter::operator bool() const {
- return value;
-}
-
-// -=- IntParameter
-
-IntParameter::IntParameter(const char* name_, const char* desc_, int v,
- int minValue_, int maxValue_, ConfigurationObject co)
- : VoidParameter(name_, desc_, co), value(v), def_value(v),
- minValue(minValue_), maxValue(maxValue_)
-{
-}
-
-bool
-IntParameter::setParam(const char* v) {
- if (immutable) return true;
- return setParam(strtol(v, nullptr, 0));
-}
-
-bool
-IntParameter::setParam(int v) {
- if (immutable) return true;
- vlog.debug("Set %s(Int) to %d", getName(), v);
- if (v < minValue || v > maxValue)
- return false;
- value = v;
- return true;
-}
-
-std::string IntParameter::getDefaultStr() const {
- char result[16];
- sprintf(result, "%d", def_value);
- return result;
-}
-
-std::string IntParameter::getValueStr() const {
- char result[16];
- sprintf(result, "%d", value);
- return result;
-}
-
-IntParameter::operator int() const {
- return value;
-}
-
-// -=- StringParameter
-
-StringParameter::StringParameter(const char* name_, const char* desc_,
- const char* v, ConfigurationObject co)
- : VoidParameter(name_, desc_, co), value(v), def_value(v)
-{
- if (!v) {
- vlog.error("Default value <null> for %s not allowed",name_);
- throw std::invalid_argument("Default value <null> not allowed");
- }
-}
-
-StringParameter::~StringParameter() {
-}
-
-bool StringParameter::setParam(const char* v) {
- LOCK_CONFIG;
- if (immutable) return true;
- if (!v)
- throw std::invalid_argument("setParam(<null>) not allowed");
- vlog.debug("Set %s(String) to %s", getName(), v);
- value = v;
- return true;
-}
-
-std::string StringParameter::getDefaultStr() const {
- return def_value;
-}
-
-std::string StringParameter::getValueStr() const {
- LOCK_CONFIG;
- return value;
-}
-
-StringParameter::operator const char *() const {
- return value.c_str();
-}
-
-// -=- BinaryParameter
-
-BinaryParameter::BinaryParameter(const char* name_, const char* desc_,
- const uint8_t* v, size_t l, ConfigurationObject co)
-: VoidParameter(name_, desc_, co),
- value(nullptr), length(0), def_value(nullptr), def_length(0) {
- if (l) {
- assert(v);
- value = new uint8_t[l];
- length = l;
- memcpy(value, v, l);
- def_value = new uint8_t[l];
- def_length = l;
- memcpy(def_value, v, l);
- }
-}
-BinaryParameter::~BinaryParameter() {
- delete [] value;
- delete [] def_value;
-}
-
-bool BinaryParameter::setParam(const char* v) {
- if (immutable) return true;
- std::vector<uint8_t> newValue = hexToBin(v, strlen(v));
- if (newValue.empty() && strlen(v) > 0)
- return false;
- setParam(newValue.data(), newValue.size());
- return true;
-}
-
-void BinaryParameter::setParam(const uint8_t* v, size_t len) {
- LOCK_CONFIG;
- if (immutable) return;
- vlog.debug("Set %s(Binary)", getName());
- delete [] value;
- value = nullptr;
- length = 0;
- if (len) {
- assert(v);
- value = new uint8_t[len];
- length = len;
- memcpy(value, v, len);
- }
-}
-
-std::string BinaryParameter::getDefaultStr() const {
- return binToHex(def_value, def_length);
-}
-
-std::string BinaryParameter::getValueStr() const {
- LOCK_CONFIG;
- return binToHex(value, length);
-}
-
-std::vector<uint8_t> BinaryParameter::getData() const {
- LOCK_CONFIG;
- std::vector<uint8_t> out(length);
- memcpy(out.data(), value, length);
- return out;
-}
diff --git a/common/rfb/Configuration.h b/common/rfb/Configuration.h
deleted file mode 100644
index ec8d789a..00000000
--- a/common/rfb/Configuration.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2022 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.
- */
-
-// -=- Configuration.h
-//
-// This header defines a set of classes used to represent configuration
-// parameters of different types. Instances of the different parameter
-// types are associated with instances of the Configuration class, and
-// are each given a unique name. The Configuration class provides a
-// generic API through which parameters may be located by name and their
-// value set, thus removing the need to write platform-specific code.
-// Simply defining a new parameter and associating it with a Configuration
-// will allow it to be configured by the user.
-//
-// If no Configuration is specified when creating a Parameter, then the
-// global Configuration will be assumed.
-//
-// Configurations can be "chained" into groups. Each group has a root
-// Configuration, a pointer to which should be passed to the constructors
-// of the other group members. set() and get() operations called on the
-// root will iterate through all of the group's members.
-//
-// NB: On platforms that support Threading, locking is performed to protect
-// complex parameter types from concurrent access (e.g. strings).
-// NB: NO LOCKING is performed when linking Configurations to groups
-// or when adding Parameters to Configurations.
-
-#ifndef __RFB_CONFIGURATION_H__
-#define __RFB_CONFIGURATION_H__
-
-#include <limits.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-namespace os { class Mutex; }
-
-namespace rfb {
- class VoidParameter;
- struct ParameterIterator;
-
- enum ConfigurationObject { ConfGlobal, ConfServer, ConfViewer };
-
- // -=- Configuration
- // Class used to access parameters.
-
- class Configuration {
- public:
- // - Create a new Configuration object
- Configuration(const char* name_)
- : name(name_), head(nullptr), _next(nullptr) {}
-
- // - Return the buffer containing the Configuration's name
- const char* getName() const { return name.c_str(); }
-
- // - Set named parameter to value
- bool set(const char* param, const char* value, bool immutable=false);
-
- // - Set parameter to value (separated by "=")
- bool set(const char* config, bool immutable=false);
-
- // - Set named parameter to value, with name truncated at len
- bool set(const char* name, int len,
- const char* val, bool immutable);
-
- // - Get named parameter
- VoidParameter* get(const char* param);
-
- // - List the parameters of this Configuration group
- void list(int width=79, int nameWidth=10);
-
- // - Remove a parameter from this Configuration group
- bool remove(const char* param);
-
- // - readFromFile
- // Read configuration parameters from the specified file.
- void readFromFile(const char* filename);
-
- // - writeConfigToFile
- // Write a new configuration parameters file, then mv it
- // over the old file.
- void writeToFile(const char* filename);
-
-
- // - Get the Global Configuration object
- // NB: This call does NOT lock the Configuration system.
- // ALWAYS ensure that if you have ANY global Parameters,
- // then they are defined as global objects, to ensure that
- // global() is called when only the main thread is running.
- static Configuration* global();
-
- // Enable server/viewer specific parameters
- static void enableServerParams() { global()->appendConfiguration(server()); }
- static void enableViewerParams() { global()->appendConfiguration(viewer()); }
-
- // - Container for process-wide Global parameters
- static bool setParam(const char* param, const char* value, bool immutable=false) {
- return global()->set(param, value, immutable);
- }
- static bool setParam(const char* config, bool immutable=false) {
- return global()->set(config, immutable);
- }
- static bool setParam(const char* name, int len,
- const char* val, bool immutable) {
- return global()->set(name, len, val, immutable);
- }
- static VoidParameter* getParam(const char* param) { return global()->get(param); }
- static void listParams(int width=79, int nameWidth=10) {
- global()->list(width, nameWidth);
- }
- static bool removeParam(const char* param) {
- return global()->remove(param);
- }
-
- private:
- friend class VoidParameter;
- friend struct ParameterIterator;
-
- // Name for this Configuration
- std::string name;
-
- // - Pointer to first Parameter in this group
- VoidParameter* head;
-
- // Pointer to next Configuration in this group
- Configuration* _next;
-
- // The process-wide, Global Configuration object
- static Configuration* global_;
-
- // The server only Configuration object
- static Configuration* server_;
-
- // The viewer only Configuration object
- static Configuration* viewer_;
-
- // Get server/viewer specific configuration object
- static Configuration* server();
- static Configuration* viewer();
-
- // Append configuration object to this instance.
- // NOTE: conf instance can be only one configuration object
- void appendConfiguration(Configuration *conf) {
- conf->_next = _next; _next = conf;
- }
- };
-
- // -=- VoidParameter
- // Configuration parameter base-class.
-
- class VoidParameter {
- public:
- VoidParameter(const char* name_, const char* desc_, ConfigurationObject co=ConfGlobal);
- virtual ~VoidParameter();
- const char* getName() const;
- const char* getDescription() const;
-
- virtual bool setParam(const char* value) = 0;
- virtual bool setParam();
- virtual std::string getDefaultStr() const = 0;
- virtual std::string getValueStr() const = 0;
- virtual bool isBool() const;
-
- virtual void setImmutable();
-
- protected:
- friend class Configuration;
- friend struct ParameterIterator;
-
- VoidParameter* _next;
- bool immutable;
- const char* name;
- const char* description;
-
- os::Mutex* mutex;
- };
-
- class AliasParameter : public VoidParameter {
- public:
- AliasParameter(const char* name_, const char* desc_,VoidParameter* param_,
- ConfigurationObject co=ConfGlobal);
- bool setParam(const char* value) override;
- bool setParam() override;
- std::string getDefaultStr() const override;
- std::string getValueStr() const override;
- bool isBool() const override;
- void setImmutable() override;
- private:
- VoidParameter* param;
- };
-
- class BoolParameter : public VoidParameter {
- public:
- BoolParameter(const char* name_, const char* desc_, bool v,
- ConfigurationObject co=ConfGlobal);
- bool setParam(const char* value) override;
- bool setParam() override;
- virtual void setParam(bool b);
- std::string getDefaultStr() const override;
- std::string getValueStr() const override;
- bool isBool() const override;
- operator bool() const;
- protected:
- bool value;
- bool def_value;
- };
-
- class IntParameter : public VoidParameter {
- public:
- IntParameter(const char* name_, const char* desc_, int v,
- int minValue=INT_MIN, int maxValue=INT_MAX,
- ConfigurationObject co=ConfGlobal);
- using VoidParameter::setParam;
- bool setParam(const char* value) override;
- virtual bool setParam(int v);
- std::string getDefaultStr() const override;
- std::string getValueStr() const override;
- operator int() const;
- protected:
- int value;
- int def_value;
- int minValue, maxValue;
- };
-
- class StringParameter : public VoidParameter {
- public:
- // StringParameter contains a null-terminated string, which CANNOT
- // be Null, and so neither can the default value!
- StringParameter(const char* name_, const char* desc_, const char* v,
- ConfigurationObject co=ConfGlobal);
- ~StringParameter() override;
- bool setParam(const char* value) override;
- std::string getDefaultStr() const override;
- std::string getValueStr() const override;
- operator const char*() const;
- protected:
- std::string value;
- std::string def_value;
- };
-
- class BinaryParameter : public VoidParameter {
- public:
- BinaryParameter(const char* name_, const char* desc_,
- const uint8_t* v, size_t l,
- ConfigurationObject co=ConfGlobal);
- using VoidParameter::setParam;
- ~BinaryParameter() override;
- bool setParam(const char* value) override;
- virtual void setParam(const uint8_t* v, size_t l);
- std::string getDefaultStr() const override;
- std::string getValueStr() const override;
-
- std::vector<uint8_t> getData() const;
-
- protected:
- uint8_t* value;
- size_t length;
- uint8_t* def_value;
- size_t def_length;
- };
-
- // -=- ParameterIterator
- // Iterates over all enabled parameters (global + server/viewer).
- // Current Parameter is accessed via param, the current Configuration
- // via config. The next() method moves on to the next Parameter.
-
- struct ParameterIterator {
- ParameterIterator() : config(Configuration::global()), param(config->head) {}
- void next() {
- param = param->_next;
- while (!param) {
- config = config->_next;
- if (!config) break;
- param = config->head;
- }
- }
- Configuration* config;
- VoidParameter* param;
- };
-
-};
-
-#endif // __RFB_CONFIGURATION_H__
diff --git a/common/rfb/Congestion.cxx b/common/rfb/Congestion.cxx
index 94f07055..46bae00d 100644
--- a/common/rfb/Congestion.cxx
+++ b/common/rfb/Congestion.cxx
@@ -49,9 +49,10 @@
#include <linux/sockios.h>
#endif
+#include <core/LogWriter.h>
+#include <core/time.h>
+
#include <rfb/Congestion.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
// Debug output on what the congestion control is up to
#undef CONGESTION_DEBUG
@@ -78,7 +79,7 @@ static inline bool isAfter(unsigned a, unsigned b) {
return a != b && a - b <= UINT_MAX / 2;
}
-static LogWriter vlog("Congestion");
+static core::LogWriter vlog("Congestion");
Congestion::Congestion() :
lastPosition(0), extraBuffer(0),
@@ -99,7 +100,7 @@ Congestion::~Congestion()
void Congestion::updatePosition(unsigned pos)
{
struct timeval now;
- unsigned delta, consumed;
+ unsigned idle, delta, consumed;
gettimeofday(&now, nullptr);
@@ -110,15 +111,17 @@ void Congestion::updatePosition(unsigned pos)
// Idle for too long?
// We use a very crude RTO calculation in order to keep things simple
// FIXME: should implement RFC 2861
- if (msBetween(&lastSent, &now) > __rfbmax(baseRTT*2, 100)) {
+ idle = core::msBetween(&lastSent, &now);
+ if (idle > 100 && idle > baseRTT*2) {
#ifdef CONGESTION_DEBUG
vlog.debug("Connection idle for %d ms, resetting congestion control",
- msBetween(&lastSent, &now));
+ idle);
#endif
// Close congestion window and redo wire latency measurement
- congWindow = __rfbmin(INITIAL_WINDOW, congWindow);
+ if (congWindow > INITIAL_WINDOW)
+ congWindow = INITIAL_WINDOW;
baseRTT = -1;
measurements = 0;
gettimeofday(&lastAdjustment, nullptr);
@@ -132,7 +135,7 @@ void Congestion::updatePosition(unsigned pos)
// (we cannot do this until we have a RTT measurement though)
if (baseRTT != (unsigned)-1) {
extraBuffer += delta;
- consumed = msBetween(&lastUpdate, &now) * congWindow / baseRTT;
+ consumed = core::msBetween(&lastUpdate, &now) * congWindow / baseRTT;
if (extraBuffer < consumed)
extraBuffer = 0;
else
@@ -174,7 +177,7 @@ void Congestion::gotPong()
lastPong = rttInfo;
lastPongArrival = now;
- rtt = msBetween(&rttInfo.tv, &now);
+ rtt = core::msBetween(&rttInfo.tv, &now);
if (rtt < 1)
rtt = 1;
@@ -184,7 +187,7 @@ void Congestion::gotPong()
// Pings sent before the last adjustment aren't interesting as they
// aren't a measurement of the current congestion window
- if (isBefore(&rttInfo.tv, &lastAdjustment))
+ if (core::isBefore(&rttInfo.tv, &lastAdjustment))
return;
// Estimate added delay because of overtaxed buffers (see above)
@@ -249,7 +252,7 @@ int Congestion::getUncongestedETA()
prevPing = &lastPong;
eta = 0;
- elapsed = msSince(&lastPongArrival);
+ elapsed = core::msSince(&lastPongArrival);
// Walk the ping queue and figure out which one we are waiting for to
// get to an uncongested state
@@ -268,7 +271,7 @@ int Congestion::getUncongestedETA()
curPing = *iter;
}
- etaNext = msBetween(&prevPing->tv, &curPing.tv);
+ etaNext = core::msBetween(&prevPing->tv, &curPing.tv);
// Compensate for buffering delays
delay = curPing.extra * baseRTT / congWindow;
etaNext += delay;
@@ -349,7 +352,7 @@ unsigned Congestion::getExtraBuffer()
if (baseRTT == (unsigned)-1)
return 0;
- elapsed = msSince(&lastUpdate);
+ elapsed = core::msSince(&lastUpdate);
consumed = elapsed * congWindow / baseRTT;
if (consumed >= extraBuffer)
@@ -389,7 +392,7 @@ unsigned Congestion::getInFlight()
// completely. Look at the next ping that should arrive and figure
// out how far behind it should be and interpolate the positions.
- etaNext = msBetween(&lastPong.tv, &nextPong.tv);
+ etaNext = core::msBetween(&lastPong.tv, &nextPong.tv);
// Compensate for buffering delays
delay = nextPong.extra * baseRTT / congWindow;
etaNext += delay;
@@ -399,7 +402,7 @@ unsigned Congestion::getInFlight()
else
etaNext -= delay;
- elapsed = msSince(&lastPongArrival);
+ elapsed = core::msSince(&lastPongArrival);
// The pong should be here any second. Be optimistic and assume
// we can already use its value.
@@ -430,7 +433,7 @@ void Congestion::updateCongestion()
diff = minRTT - baseRTT;
- if (diff > __rfbmax(100, baseRTT/2)) {
+ if (diff > 100 && diff > baseRTT/2) {
// We have no way of detecting loss, so assume massive latency
// spike means packet loss. Adjust the window and go directly
// to congestion avoidance.
diff --git a/common/rfb/CopyRectDecoder.cxx b/common/rfb/CopyRectDecoder.cxx
index a7383881..efc77c99 100644
--- a/common/rfb/CopyRectDecoder.cxx
+++ b/common/rfb/CopyRectDecoder.cxx
@@ -20,10 +20,12 @@
#include <config.h>
#endif
+#include <core/Region.h>
+
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
+
#include <rfb/PixelBuffer.h>
-#include <rfb/Region.h>
#include <rfb/CopyRectDecoder.h>
using namespace rfb;
@@ -36,7 +38,7 @@ CopyRectDecoder::~CopyRectDecoder()
{
}
-bool CopyRectDecoder::readRect(const Rect& /*r*/,
+bool CopyRectDecoder::readRect(const core::Rect& /*r*/,
rdr::InStream* is,
const ServerParams& /*server*/,
rdr::OutStream* os)
@@ -48,11 +50,11 @@ bool CopyRectDecoder::readRect(const Rect& /*r*/,
}
-void CopyRectDecoder::getAffectedRegion(const Rect& rect,
+void CopyRectDecoder::getAffectedRegion(const core::Rect& rect,
const uint8_t* buffer,
size_t buflen,
const ServerParams& server,
- Region* region)
+ core::Region* region)
{
rdr::MemInStream is(buffer, buflen);
int srcX = is.readU16();
@@ -60,11 +62,12 @@ void CopyRectDecoder::getAffectedRegion(const Rect& rect,
Decoder::getAffectedRegion(rect, buffer, buflen, server, region);
- region->assign_union(Region(rect.translate(Point(srcX-rect.tl.x,
- srcY-rect.tl.y))));
+ region->assign_union(rect.translate({srcX-rect.tl.x,
+ srcY-rect.tl.y}));
}
-void CopyRectDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
+void CopyRectDecoder::decodeRect(const core::Rect& r,
+ const uint8_t* buffer,
size_t buflen,
const ServerParams& /*server*/,
ModifiablePixelBuffer* pb)
@@ -72,5 +75,5 @@ void CopyRectDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
rdr::MemInStream is(buffer, buflen);
int srcX = is.readU16();
int srcY = is.readU16();
- pb->copyRect(r, Point(r.tl.x-srcX, r.tl.y-srcY));
+ pb->copyRect(r, {r.tl.x-srcX, r.tl.y-srcY});
}
diff --git a/common/rfb/CopyRectDecoder.h b/common/rfb/CopyRectDecoder.h
index 51651196..b1d0d38d 100644
--- a/common/rfb/CopyRectDecoder.h
+++ b/common/rfb/CopyRectDecoder.h
@@ -26,13 +26,13 @@ namespace rfb {
public:
CopyRectDecoder();
virtual ~CopyRectDecoder();
- bool readRect(const Rect& r, rdr::InStream* is,
+ bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server,
rdr::OutStream* os) override;
- void getAffectedRegion(const Rect& rect, const uint8_t* buffer,
+ void getAffectedRegion(const core::Rect& rect, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
- Region* region) override;
- void decodeRect(const Rect& r, const uint8_t* buffer,
+ core::Region* region) override;
+ void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb) override;
};
diff --git a/common/rfb/Cursor.cxx b/common/rfb/Cursor.cxx
index 94844144..e094e4ed 100644
--- a/common/rfb/Cursor.cxx
+++ b/common/rfb/Cursor.cxx
@@ -26,14 +26,15 @@
#include <stdexcept>
+#include <core/LogWriter.h>
+
#include <rfb/Cursor.h>
-#include <rfb/LogWriter.h>
using namespace rfb;
-static LogWriter vlog("Cursor");
+static core::LogWriter vlog("Cursor");
-Cursor::Cursor(int width, int height, const Point& hotspot,
+Cursor::Cursor(int width, int height, const core::Point& hotspot,
const uint8_t* data_) :
width_(width), height_(height), hotspot_(hotspot)
{
@@ -215,9 +216,9 @@ std::vector<uint8_t> Cursor::getMask() const
void Cursor::crop()
{
- Rect busy = Rect(0, 0, width_, height_);
- busy = busy.intersect(Rect(hotspot_.x, hotspot_.y,
- hotspot_.x+1, hotspot_.y+1));
+ core::Rect busy(0, 0, width_, height_);
+ busy = busy.intersect({hotspot_.x, hotspot_.y,
+ hotspot_.x+1, hotspot_.y+1});
int x, y;
uint8_t *data_ptr = data;
for (y = 0; y < height(); y++) {
@@ -255,9 +256,10 @@ RenderedCursor::RenderedCursor()
{
}
-const uint8_t* RenderedCursor::getBuffer(const Rect& _r, int* stride) const
+const uint8_t* RenderedCursor::getBuffer(const core::Rect& _r,
+ int* stride) const
{
- Rect r;
+ core::Rect r;
r = _r.translate(offset.negate());
if (!r.enclosed_by(buffer.getRect()))
@@ -267,10 +269,10 @@ const uint8_t* RenderedCursor::getBuffer(const Rect& _r, int* stride) const
}
void RenderedCursor::update(PixelBuffer* framebuffer,
- Cursor* cursor, const Point& pos)
+ Cursor* cursor, const core::Point& pos)
{
- Point rawOffset, diff;
- Rect clippedRect;
+ core::Point rawOffset, diff;
+ core::Rect clippedRect;
const uint8_t* data;
int stride;
@@ -282,7 +284,7 @@ void RenderedCursor::update(PixelBuffer* framebuffer,
setSize(framebuffer->width(), framebuffer->height());
rawOffset = pos.subtract(cursor->hotspot());
- clippedRect = Rect(0, 0, cursor->width(), cursor->height())
+ clippedRect = core::Rect(0, 0, cursor->width(), cursor->height())
.translate(rawOffset)
.intersect(framebuffer->getRect());
offset = clippedRect.tl;
@@ -313,7 +315,7 @@ void RenderedCursor::update(PixelBuffer* framebuffer,
else if (fg[3] == 0xff) {
memcpy(rgb, fg, 3);
} else {
- buffer.getImage(bg, Rect(x, y, x+1, y+1));
+ buffer.getImage(bg, {x, y, x+1, y+1});
format.rgbFromBuffer(rgb, bg, 1);
// FIXME: Gamma aware blending
for (int i = 0;i < 3;i++) {
@@ -323,7 +325,7 @@ void RenderedCursor::update(PixelBuffer* framebuffer,
}
format.bufferFromRGB(bg, rgb, 1);
- buffer.imageRect(Rect(x, y, x+1, y+1), bg);
+ buffer.imageRect({x, y, x+1, y+1}, bg);
}
}
}
diff --git a/common/rfb/Cursor.h b/common/rfb/Cursor.h
index c71f5a77..ef3c1b80 100644
--- a/common/rfb/Cursor.h
+++ b/common/rfb/Cursor.h
@@ -26,19 +26,22 @@
#include <vector>
+#include <core/Rect.h>
+
#include <rfb/PixelBuffer.h>
namespace rfb {
class Cursor {
public:
- Cursor(int width, int height, const Point& hotspot, const uint8_t* data);
+ Cursor(int width, int height, const core::Point& hotspot,
+ const uint8_t* data);
Cursor(const Cursor& other);
~Cursor();
int width() const { return width_; };
int height() const { return height_; };
- const Point& hotspot() const { return hotspot_; };
+ const core::Point& hotspot() const { return hotspot_; };
const uint8_t* getBuffer() const { return data; };
// getBitmap() returns a monochrome version of the cursor
@@ -52,7 +55,7 @@ namespace rfb {
protected:
int width_, height_;
- Point hotspot_;
+ core::Point hotspot_;
uint8_t* data;
};
@@ -60,15 +63,16 @@ namespace rfb {
public:
RenderedCursor();
- Rect getEffectiveRect() const { return buffer.getRect(offset); }
+ core::Rect getEffectiveRect() const { return buffer.getRect(offset); }
- const uint8_t* getBuffer(const Rect& r, int* stride) const override;
+ const uint8_t* getBuffer(const core::Rect& r, int* stride) const override;
- void update(PixelBuffer* framebuffer, Cursor* cursor, const Point& pos);
+ void update(PixelBuffer* framebuffer, Cursor* cursor,
+ const core::Point& pos);
protected:
ManagedPixelBuffer buffer;
- Point offset;
+ core::Point offset;
};
}
diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx
index 4effe985..48181f94 100644
--- a/common/rfb/DecodeManager.cxx
+++ b/common/rfb/DecodeManager.cxx
@@ -23,22 +23,20 @@
#include <assert.h>
#include <string.h>
+#include <core/LogWriter.h>
+#include <core/Region.h>
+#include <core/string.h>
+
#include <rfb/CConnection.h>
#include <rfb/DecodeManager.h>
#include <rfb/Decoder.h>
#include <rfb/Exception.h>
-#include <rfb/Region.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
-#include <rdr/Exception.h>
#include <rdr/MemOutStream.h>
-#include <os/Mutex.h>
-
using namespace rfb;
-static LogWriter vlog("DecodeManager");
+static core::LogWriter vlog("DecodeManager");
DecodeManager::DecodeManager(CConnection *conn_) :
conn(conn_), threadException(nullptr)
@@ -49,11 +47,7 @@ DecodeManager::DecodeManager(CConnection *conn_) :
memset(stats, 0, sizeof(stats));
- queueMutex = new os::Mutex();
- producerCond = new os::Condition(queueMutex);
- consumerCond = new os::Condition(queueMutex);
-
- cpuCount = os::Thread::getSystemCPUCount();
+ cpuCount = std::thread::hardware_concurrency();
if (cpuCount == 0) {
vlog.error("Unable to determine the number of CPU cores on this system");
cpuCount = 1;
@@ -86,22 +80,16 @@ DecodeManager::~DecodeManager()
threads.pop_back();
}
- delete threadException;
-
while (!freeBuffers.empty()) {
delete freeBuffers.back();
freeBuffers.pop_back();
}
- delete consumerCond;
- delete producerCond;
- delete queueMutex;
-
for (Decoder* decoder : decoders)
delete decoder;
}
-bool DecodeManager::decodeRect(const Rect& r, int encoding,
+bool DecodeManager::decodeRect(const core::Rect& r, int encoding,
ModifiablePixelBuffer* pb)
{
Decoder *decoder;
@@ -128,29 +116,25 @@ bool DecodeManager::decodeRect(const Rect& r, int encoding,
decoder = decoders[encoding];
// Wait for an available memory buffer
- queueMutex->lock();
+ std::unique_lock<std::mutex> lock(queueMutex);
// FIXME: Should we return and let other things run here?
while (freeBuffers.empty())
- producerCond->wait();
+ producerCond.wait(lock);
// Don't pop the buffer in case we throw an exception
// whilst reading
bufferStream = freeBuffers.front();
- queueMutex->unlock();
+ lock.unlock();
// First check if any thread has encountered a problem
throwThreadException();
// Read the rect
bufferStream->clear();
- try {
- if (!decoder->readRect(r, conn->getInStream(), conn->server, bufferStream))
- return false;
- } catch (std::exception& e) {
- throw std::runtime_error(format("Error reading rect: %s", e.what()));
- }
+ if (!decoder->readRect(r, conn->getInStream(), conn->server, bufferStream))
+ return false;
stats[encoding].rects++;
stats[encoding].bytes += 12 + bufferStream->length();
@@ -173,7 +157,7 @@ bool DecodeManager::decodeRect(const Rect& r, int encoding,
bufferStream->length(), conn->server,
&entry->affectedRegion);
- queueMutex->lock();
+ lock.lock();
// The workers add buffers to the end so it's safe to assume
// the front is still the same buffer
@@ -183,21 +167,21 @@ bool DecodeManager::decodeRect(const Rect& r, int encoding,
// We only put a single entry on the queue so waking a single
// thread is sufficient
- consumerCond->signal();
+ consumerCond.notify_one();
- queueMutex->unlock();
+ lock.unlock();
return true;
}
void DecodeManager::flush()
{
- queueMutex->lock();
+ std::unique_lock<std::mutex> lock(queueMutex);
while (!workQueue.empty())
- producerCond->wait();
+ producerCond.wait(lock);
- queueMutex->unlock();
+ lock.unlock();
throwThreadException();
}
@@ -227,49 +211,49 @@ void DecodeManager::logStats()
ratio = (double)stats[i].equivalent / stats[i].bytes;
vlog.info(" %s: %s, %s", encodingName(i),
- siPrefix(stats[i].rects, "rects").c_str(),
- siPrefix(stats[i].pixels, "pixels").c_str());
+ core::siPrefix(stats[i].rects, "rects").c_str(),
+ core::siPrefix(stats[i].pixels, "pixels").c_str());
vlog.info(" %*s %s (1:%g ratio)",
(int)strlen(encodingName(i)), "",
- iecPrefix(stats[i].bytes, "B").c_str(), ratio);
+ core::iecPrefix(stats[i].bytes, "B").c_str(), ratio);
}
ratio = (double)equivalent / bytes;
vlog.info(" Total: %s, %s",
- siPrefix(rects, "rects").c_str(),
- siPrefix(pixels, "pixels").c_str());
+ core::siPrefix(rects, "rects").c_str(),
+ core::siPrefix(pixels, "pixels").c_str());
vlog.info(" %s (1:%g ratio)",
- iecPrefix(bytes, "B").c_str(), ratio);
+ core::iecPrefix(bytes, "B").c_str(), ratio);
}
-void DecodeManager::setThreadException(const std::exception& e)
+void DecodeManager::setThreadException()
{
- os::AutoMutex a(queueMutex);
+ const std::lock_guard<std::mutex> lock(queueMutex);
- if (threadException != nullptr)
+ if (threadException)
return;
- threadException = new std::runtime_error(format("Exception on worker thread: %s", e.what()));
+ threadException = std::current_exception();
}
void DecodeManager::throwThreadException()
{
- os::AutoMutex a(queueMutex);
+ const std::lock_guard<std::mutex> lock(queueMutex);
- if (threadException == nullptr)
+ if (!threadException)
return;
- std::runtime_error e(threadException->what());
-
- delete threadException;
- threadException = nullptr;
-
- throw e;
+ try {
+ std::rethrow_exception(threadException);
+ } catch (...) {
+ threadException = nullptr;
+ throw;
+ }
}
DecodeManager::DecodeThread::DecodeThread(DecodeManager* manager_)
- : manager(manager_), stopRequested(false)
+ : manager(manager_), thread(nullptr), stopRequested(false)
{
start();
}
@@ -277,25 +261,35 @@ DecodeManager::DecodeThread::DecodeThread(DecodeManager* manager_)
DecodeManager::DecodeThread::~DecodeThread()
{
stop();
- wait();
+ if (thread != nullptr) {
+ thread->join();
+ delete thread;
+ }
+}
+
+void DecodeManager::DecodeThread::start()
+{
+ assert(thread == nullptr);
+
+ thread = new std::thread(&DecodeThread::worker, this);
}
void DecodeManager::DecodeThread::stop()
{
- os::AutoMutex a(manager->queueMutex);
+ const std::lock_guard<std::mutex> lock(manager->queueMutex);
- if (!isRunning())
+ if (thread == nullptr)
return;
stopRequested = true;
// We can't wake just this thread, so wake everyone
- manager->consumerCond->broadcast();
+ manager->consumerCond.notify_all();
}
void DecodeManager::DecodeThread::worker()
{
- manager->queueMutex->lock();
+ std::unique_lock<std::mutex> lock(manager->queueMutex);
while (!stopRequested) {
DecodeManager::QueueEntry *entry;
@@ -304,14 +298,14 @@ void DecodeManager::DecodeThread::worker()
entry = findEntry();
if (entry == nullptr) {
// Wait and try again
- manager->consumerCond->wait();
+ manager->consumerCond.wait(lock);
continue;
}
// This is ours now
entry->active = true;
- manager->queueMutex->unlock();
+ lock.unlock();
// Do the actual decoding
try {
@@ -319,12 +313,12 @@ void DecodeManager::DecodeThread::worker()
entry->bufferStream->length(),
*entry->server, entry->pb);
} catch (std::exception& e) {
- manager->setThreadException(e);
+ manager->setThreadException();
} catch(...) {
assert(false);
}
- manager->queueMutex->lock();
+ lock.lock();
// Remove the entry from the queue and give back the memory buffer
manager->freeBuffers.push_back(entry->bufferStream);
@@ -332,19 +326,17 @@ void DecodeManager::DecodeThread::worker()
delete entry;
// Wake the main thread in case it is waiting for a memory buffer
- manager->producerCond->signal();
+ manager->producerCond.notify_one();
// This rect might have been blocking multiple other rects, so
// wake up every worker thread
if (manager->workQueue.size() > 1)
- manager->consumerCond->broadcast();
+ manager->consumerCond.notify_all();
}
-
- manager->queueMutex->unlock();
}
DecodeManager::QueueEntry* DecodeManager::DecodeThread::findEntry()
{
- Region lockedRegion;
+ core::Region lockedRegion;
if (manager->workQueue.empty())
return nullptr;
diff --git a/common/rfb/DecodeManager.h b/common/rfb/DecodeManager.h
index b11b7044..146bf8ae 100644
--- a/common/rfb/DecodeManager.h
+++ b/common/rfb/DecodeManager.h
@@ -19,16 +19,18 @@
#ifndef __RFB_DECODEMANAGER_H__
#define __RFB_DECODEMANAGER_H__
+#include <condition_variable>
+#include <exception>
#include <list>
+#include <mutex>
+#include <thread>
-#include <os/Thread.h>
+#include <core/Region.h>
-#include <rfb/Region.h>
#include <rfb/encodings.h>
-namespace os {
- class Condition;
- class Mutex;
+namespace core {
+ struct Rect;
}
namespace rdr {
@@ -36,17 +38,17 @@ namespace rdr {
}
namespace rfb {
+
class CConnection;
class Decoder;
class ModifiablePixelBuffer;
- struct Rect;
class DecodeManager {
public:
DecodeManager(CConnection *conn);
~DecodeManager();
- bool decodeRect(const Rect& r, int encoding,
+ bool decodeRect(const core::Rect& r, int encoding,
ModifiablePixelBuffer* pb);
void flush();
@@ -54,7 +56,7 @@ namespace rfb {
private:
void logStats();
- void setThreadException(const std::exception& e);
+ void setThreadException();
void throwThreadException();
private:
@@ -72,43 +74,46 @@ namespace rfb {
struct QueueEntry {
bool active;
- Rect rect;
+ core::Rect rect;
int encoding;
Decoder* decoder;
const ServerParams* server;
ModifiablePixelBuffer* pb;
rdr::MemOutStream* bufferStream;
- Region affectedRegion;
+ core::Region affectedRegion;
};
std::list<rdr::MemOutStream*> freeBuffers;
std::list<QueueEntry*> workQueue;
- os::Mutex* queueMutex;
- os::Condition* producerCond;
- os::Condition* consumerCond;
+ std::mutex queueMutex;
+ std::condition_variable producerCond;
+ std::condition_variable consumerCond;
private:
- class DecodeThread : public os::Thread {
+ class DecodeThread {
public:
DecodeThread(DecodeManager* manager);
~DecodeThread();
+ void start();
void stop();
protected:
- void worker() override;
+ void worker();
DecodeManager::QueueEntry* findEntry();
private:
DecodeManager* manager;
+ std::thread* thread;
bool stopRequested;
};
std::list<DecodeThread*> threads;
- std::exception *threadException;
+ std::exception_ptr threadException;
};
+
}
#endif
diff --git a/common/rfb/Decoder.cxx b/common/rfb/Decoder.cxx
index e9bc9a4f..0f1cde89 100644
--- a/common/rfb/Decoder.cxx
+++ b/common/rfb/Decoder.cxx
@@ -22,8 +22,10 @@
#endif
#include <stdio.h>
+
+#include <core/Region.h>
+
#include <rfb/encodings.h>
-#include <rfb/Region.h>
#include <rfb/Decoder.h>
#include <rfb/RawDecoder.h>
#include <rfb/CopyRectDecoder.h>
@@ -45,19 +47,19 @@ Decoder::~Decoder()
{
}
-void Decoder::getAffectedRegion(const Rect& rect,
+void Decoder::getAffectedRegion(const core::Rect& rect,
const uint8_t* /*buffer*/,
size_t /*buflen*/,
const ServerParams& /*server*/,
- Region* region)
+ core::Region* region)
{
region->reset(rect);
}
-bool Decoder::doRectsConflict(const Rect& /*rectA*/,
+bool Decoder::doRectsConflict(const core::Rect& /*rectA*/,
const uint8_t* /*bufferA*/,
size_t /*buflenA*/,
- const Rect& /*rectB*/,
+ const core::Rect& /*rectB*/,
const uint8_t* /*bufferB*/,
size_t /*buflenB*/,
const ServerParams& /*server*/)
diff --git a/common/rfb/Decoder.h b/common/rfb/Decoder.h
index 77987737..17d5296b 100644
--- a/common/rfb/Decoder.h
+++ b/common/rfb/Decoder.h
@@ -19,19 +19,23 @@
#ifndef __RFB_DECODER_H__
#define __RFB_DECODER_H__
+#include <stddef.h>
#include <stdint.h>
+namespace core {
+ class Region;
+ struct Rect;
+}
+
namespace rdr {
class InStream;
class OutStream;
}
namespace rfb {
+
class ServerParams;
class ModifiablePixelBuffer;
- class Region;
-
- struct Rect;
enum DecoderFlags {
// A constant for decoders that don't need anything special
@@ -54,7 +58,7 @@ namespace rfb {
// InStream to the OutStream, possibly changing it along the way to
// make it easier to decode. This function will always be called in
// a serial manner on the main thread.
- virtual bool readRect(const Rect& r, rdr::InStream* is,
+ virtual bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server, rdr::OutStream* os)=0;
// These functions will be called from any of the worker threads.
@@ -64,17 +68,17 @@ namespace rfb {
// getAffectedRegion() returns the parts of the frame buffer will
// 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 uint8_t* buffer,
+ virtual void getAffectedRegion(const core::Rect& rect, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
- Region* region);
+ core::Region* region);
// doesRectsConflict() determines if two rectangles must be decoded
// in the order they were received. This will only be called if the
// DecoderPartiallyOrdered flag has been set.
- virtual bool doRectsConflict(const Rect& rectA,
+ virtual bool doRectsConflict(const core::Rect& rectA,
const uint8_t* bufferA,
size_t buflenA,
- const Rect& rectB,
+ const core::Rect& rectB,
const uint8_t* bufferB,
size_t buflenB,
const ServerParams& server);
@@ -83,7 +87,7 @@ namespace rfb {
// 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 uint8_t* buffer,
+ virtual void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)=0;
@@ -94,6 +98,7 @@ namespace rfb {
public:
const enum DecoderFlags flags;
};
+
}
#endif
diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx
index 67a32f5b..6a63fa6f 100644
--- a/common/rfb/EncodeManager.cxx
+++ b/common/rfb/EncodeManager.cxx
@@ -25,14 +25,17 @@
#include <stdlib.h>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
+#include <rfb/Cursor.h>
#include <rfb/EncodeManager.h>
#include <rfb/Encoder.h>
#include <rfb/Palette.h>
#include <rfb/SConnection.h>
#include <rfb/SMsgWriter.h>
#include <rfb/UpdateTracker.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
+#include <rfb/encodings.h>
#include <rfb/RawEncoder.h>
#include <rfb/RREEncoder.h>
@@ -43,7 +46,7 @@
using namespace rfb;
-static LogWriter vlog("EncodeManager");
+static core::LogWriter vlog("EncodeManager");
// Split each rectangle into smaller ones no larger than this area,
// and no wider than this width.
@@ -191,11 +194,11 @@ void EncodeManager::logStats()
ratio = (double)copyStats.equivalent / copyStats.bytes;
vlog.info(" %s: %s, %s", "Copies",
- siPrefix(copyStats.rects, "rects").c_str(),
- siPrefix(copyStats.pixels, "pixels").c_str());
+ core::siPrefix(copyStats.rects, "rects").c_str(),
+ core::siPrefix(copyStats.pixels, "pixels").c_str());
vlog.info(" %*s %s (1:%g ratio)",
(int)strlen("Copies"), "",
- iecPrefix(copyStats.bytes, "B").c_str(), ratio);
+ core::iecPrefix(copyStats.bytes, "B").c_str(), ratio);
}
for (i = 0;i < stats.size();i++) {
@@ -221,21 +224,21 @@ void EncodeManager::logStats()
ratio = (double)stats[i][j].equivalent / stats[i][j].bytes;
vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j),
- siPrefix(stats[i][j].rects, "rects").c_str(),
- siPrefix(stats[i][j].pixels, "pixels").c_str());
+ core::siPrefix(stats[i][j].rects, "rects").c_str(),
+ core::siPrefix(stats[i][j].pixels, "pixels").c_str());
vlog.info(" %*s %s (1:%g ratio)",
(int)strlen(encoderTypeName((EncoderType)j)), "",
- iecPrefix(stats[i][j].bytes, "B").c_str(), ratio);
+ core::iecPrefix(stats[i][j].bytes, "B").c_str(), ratio);
}
}
ratio = (double)equivalent / bytes;
vlog.info(" Total: %s, %s",
- siPrefix(rects, "rects").c_str(),
- siPrefix(pixels, "pixels").c_str());
+ core::siPrefix(rects, "rects").c_str(),
+ core::siPrefix(pixels, "pixels").c_str());
vlog.info(" %s (1:%g ratio)",
- iecPrefix(bytes, "B").c_str(), ratio);
+ core::iecPrefix(bytes, "B").c_str(), ratio);
}
bool EncodeManager::supported(int encoding)
@@ -252,12 +255,12 @@ bool EncodeManager::supported(int encoding)
}
}
-bool EncodeManager::needsLosslessRefresh(const Region& req)
+bool EncodeManager::needsLosslessRefresh(const core::Region& req)
{
return !lossyRegion.intersect(req).is_empty();
}
-int EncodeManager::getNextLosslessRefresh(const Region& req)
+int EncodeManager::getNextLosslessRefresh(const core::Region& req)
{
// Do we have something we can send right away?
if (!pendingRefreshRegion.intersect(req).is_empty())
@@ -269,12 +272,19 @@ int EncodeManager::getNextLosslessRefresh(const Region& req)
return recentChangeTimer.getNextTimeout();
}
-void EncodeManager::pruneLosslessRefresh(const Region& limits)
+void EncodeManager::pruneLosslessRefresh(const core::Region& limits)
{
lossyRegion.assign_intersect(limits);
pendingRefreshRegion.assign_intersect(limits);
}
+void EncodeManager::forceRefresh(const core::Region& req)
+{
+ lossyRegion.assign_union(req);
+ if (!recentChangeTimer.isStarted())
+ pendingRefreshRegion.assign_union(req);
+}
+
void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,
const RenderedCursor* renderedCursor)
{
@@ -286,15 +296,16 @@ void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,
recentChangeTimer.start(RecentChangeTimeout);
}
-void EncodeManager::writeLosslessRefresh(const Region& req, const PixelBuffer* pb,
+void EncodeManager::writeLosslessRefresh(const core::Region& req,
+ const PixelBuffer* pb,
const RenderedCursor* renderedCursor,
size_t maxUpdateSize)
{
doUpdate(false, getLosslessRefresh(req, maxUpdateSize),
- Region(), Point(), pb, renderedCursor);
+ {}, {}, pb, renderedCursor);
}
-void EncodeManager::handleTimeout(Timer* t)
+void EncodeManager::handleTimeout(core::Timer* t)
{
if (t == &recentChangeTimer) {
// Any lossy region that wasn't recently updated can
@@ -308,13 +319,15 @@ void EncodeManager::handleTimeout(Timer* t)
}
}
-void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
- const Region& copied, const Point& copyDelta,
+void EncodeManager::doUpdate(bool allowLossy, const
+ core::Region& changed_,
+ const core::Region& copied,
+ const core::Point& copyDelta,
const PixelBuffer* pb,
const RenderedCursor* renderedCursor)
{
int nRects;
- Region changed, cursorRegion;
+ core::Region changed, cursorRegion;
updates++;
@@ -475,19 +488,20 @@ void EncodeManager::prepareEncoders(bool allowLossy)
encoder->setFineQualityLevel(conn->client.fineQualityLevel,
conn->client.subsampling);
} else {
- int level = __rfbmax(conn->client.qualityLevel,
- encoder->losslessQuality);
- encoder->setQualityLevel(level);
+ if (conn->client.qualityLevel < encoder->losslessQuality)
+ encoder->setQualityLevel(encoder->losslessQuality);
+ else
+ encoder->setQualityLevel(conn->client.qualityLevel);
encoder->setFineQualityLevel(-1, subsampleUndefined);
}
}
}
-Region EncodeManager::getLosslessRefresh(const Region& req,
- size_t maxUpdateSize)
+core::Region EncodeManager::getLosslessRefresh(const core::Region& req,
+ size_t maxUpdateSize)
{
- std::vector<Rect> rects;
- Region refresh;
+ std::vector<core::Rect> rects;
+ core::Region refresh;
size_t area;
// We make a conservative guess at the compression ratio at 2:1
@@ -500,7 +514,7 @@ Region EncodeManager::getLosslessRefresh(const Region& req,
pendingRefreshRegion.intersect(req).get_rects(&rects);
while (!rects.empty()) {
size_t idx;
- Rect rect;
+ core::Rect rect;
// Grab a random rect so we don't keep damaging and restoring the
// same rect over and over
@@ -514,17 +528,21 @@ Region EncodeManager::getLosslessRefresh(const Region& req,
// Use the narrowest axis to avoid getting to thin rects
if (rect.width() > rect.height()) {
int width = (maxUpdateSize - area) / rect.height();
- rect.br.x = rect.tl.x + __rfbmax(1, width);
+ if (width < 1)
+ width = 1;
+ rect.br.x = rect.tl.x + width;
} else {
int height = (maxUpdateSize - area) / rect.width();
- rect.br.y = rect.tl.y + __rfbmax(1, height);
+ if (height < 1)
+ height = 1;
+ rect.br.y = rect.tl.y + height;
}
- refresh.assign_union(Region(rect));
+ refresh.assign_union(rect);
break;
}
area += rect.area();
- refresh.assign_union(Region(rect));
+ refresh.assign_union(rect);
rects.erase(rects.begin() + idx);
}
@@ -532,11 +550,11 @@ Region EncodeManager::getLosslessRefresh(const Region& req,
return refresh;
}
-int EncodeManager::computeNumRects(const Region& changed)
+int EncodeManager::computeNumRects(const core::Region& changed)
{
int numRects;
- std::vector<Rect> rects;
- std::vector<Rect>::const_iterator rect;
+ std::vector<core::Rect> rects;
+ std::vector<core::Rect>::const_iterator rect;
numRects = 0;
changed.get_rects(&rects);
@@ -566,7 +584,7 @@ int EncodeManager::computeNumRects(const Region& changed)
return numRects;
}
-Encoder *EncodeManager::startRect(const Rect& rect, int type)
+Encoder* EncodeManager::startRect(const core::Rect& rect, int type)
{
Encoder *encoder;
int klass, equiv;
@@ -587,13 +605,13 @@ Encoder *EncodeManager::startRect(const Rect& rect, int type)
if ((encoder->flags & EncoderLossy) &&
((encoder->losslessQuality == -1) ||
(encoder->getQualityLevel() < encoder->losslessQuality)))
- lossyRegion.assign_union(Region(rect));
+ lossyRegion.assign_union(rect);
else
- lossyRegion.assign_subtract(Region(rect));
+ lossyRegion.assign_subtract(rect);
// This was either a rect getting refreshed, or a rect that just got
// new content. Either way we should not try to refresh it anymore.
- pendingRefreshRegion.assign_subtract(Region(rect));
+ pendingRefreshRegion.assign_subtract(rect);
return encoder;
}
@@ -611,12 +629,13 @@ void EncodeManager::endRect()
stats[klass][activeType].bytes += length;
}
-void EncodeManager::writeCopyRects(const Region& copied, const Point& delta)
+void EncodeManager::writeCopyRects(const core::Region& copied,
+ const core::Point& delta)
{
- std::vector<Rect> rects;
- std::vector<Rect>::const_iterator rect;
+ std::vector<core::Rect> rects;
+ std::vector<core::Rect>::const_iterator rect;
- Region lossyCopy;
+ core::Region lossyCopy;
beforeLength = conn->getOutStream()->length();
@@ -645,20 +664,22 @@ void EncodeManager::writeCopyRects(const Region& copied, const Point& delta)
pendingRefreshRegion.assign_subtract(copied);
}
-void EncodeManager::writeSolidRects(Region *changed, const PixelBuffer* pb)
+void EncodeManager::writeSolidRects(core::Region* changed,
+ const PixelBuffer* pb)
{
- std::vector<Rect> rects;
- std::vector<Rect>::const_iterator rect;
+ std::vector<core::Rect> rects;
+ std::vector<core::Rect>::const_iterator rect;
changed->get_rects(&rects);
for (rect = rects.begin(); rect != rects.end(); ++rect)
findSolidRect(*rect, changed, pb);
}
-void EncodeManager::findSolidRect(const Rect& rect, Region *changed,
+void EncodeManager::findSolidRect(const core::Rect& rect,
+ core::Region* changed,
const PixelBuffer* pb)
{
- Rect sr;
+ core::Rect sr;
int dx, dy, dw, dh;
// We start by finding a solid 16x16 block
@@ -677,11 +698,11 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed,
if (dx + dw > rect.br.x)
dw = rect.br.x - dx;
- pb->getImage(colourValue, Rect(dx, dy, dx+1, dy+1));
+ pb->getImage(colourValue, {dx, dy, dx+1, dy+1});
sr.setXYWH(dx, dy, dw, dh);
if (checkSolidTile(sr, colourValue, pb)) {
- Rect erb, erp;
+ core::Rect erb, erp;
Encoder *encoder;
@@ -721,7 +742,7 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed,
}
endRect();
- changed->assign_subtract(Region(erp));
+ changed->assign_subtract(erp);
// Search remaining areas by recursion
// FIXME: Is this the best way to divide things up?
@@ -752,15 +773,16 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed,
}
}
-void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb)
+void EncodeManager::writeRects(const core::Region& changed,
+ const PixelBuffer* pb)
{
- std::vector<Rect> rects;
- std::vector<Rect>::const_iterator rect;
+ std::vector<core::Rect> rects;
+ std::vector<core::Rect>::const_iterator rect;
changed.get_rects(&rects);
for (rect = rects.begin(); rect != rects.end(); ++rect) {
int w, h, sw, sh;
- Rect sr;
+ core::Rect sr;
w = rect->width();
h = rect->height();
@@ -794,7 +816,8 @@ void EncodeManager::writeRects(const Region& changed, const PixelBuffer* pb)
}
}
-void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb)
+void EncodeManager::writeSubRect(const core::Rect& rect,
+ const PixelBuffer* pb)
{
PixelBuffer *ppb;
@@ -878,7 +901,8 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb)
endRect();
}
-bool EncodeManager::checkSolidTile(const Rect& r, const uint8_t* colourValue,
+bool EncodeManager::checkSolidTile(const core::Rect& r,
+ const uint8_t* colourValue,
const PixelBuffer *pb)
{
const uint8_t* buffer;
@@ -902,13 +926,14 @@ bool EncodeManager::checkSolidTile(const Rect& r, const uint8_t* colourValue,
}
}
-void EncodeManager::extendSolidAreaByBlock(const Rect& r,
+void EncodeManager::extendSolidAreaByBlock(const core::Rect& r,
const uint8_t* colourValue,
- const PixelBuffer *pb, Rect* er)
+ const PixelBuffer* pb,
+ core::Rect* er)
{
int dx, dy, dw, dh;
int w_prev;
- Rect sr;
+ core::Rect sr;
int w_best = 0, h_best = 0;
w_prev = r.width();
@@ -958,12 +983,14 @@ void EncodeManager::extendSolidAreaByBlock(const Rect& r,
er->br.y = er->tl.y + h_best;
}
-void EncodeManager::extendSolidAreaByPixel(const Rect& r, const Rect& sr,
+void EncodeManager::extendSolidAreaByPixel(const core::Rect& r,
+ const core::Rect& sr,
const uint8_t* colourValue,
- const PixelBuffer *pb, Rect* er)
+ const PixelBuffer* pb,
+ core::Rect* er)
{
int cx, cy;
- Rect tr;
+ core::Rect tr;
// Try to extend the area upwards.
for (cy = sr.tl.y - 1; cy >= r.tl.y; cy--) {
@@ -998,7 +1025,7 @@ void EncodeManager::extendSolidAreaByPixel(const Rect& r, const Rect& sr,
er->br.x = cx;
}
-PixelBuffer* EncodeManager::preparePixelBuffer(const Rect& rect,
+PixelBuffer* EncodeManager::preparePixelBuffer(const core::Rect& rect,
const PixelBuffer *pb,
bool convert)
{
@@ -1063,7 +1090,7 @@ void EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf,
setBuffer(width, height, (uint8_t*)data_, stride_);
}
-uint8_t* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& /*r*/, int* /*stride*/)
+uint8_t* EncodeManager::OffsetPixelBuffer::getBufferRW(const core::Rect& /*r*/, int* /*stride*/)
{
throw std::logic_error("Invalid write attempt to OffsetPixelBuffer");
}
diff --git a/common/rfb/EncodeManager.h b/common/rfb/EncodeManager.h
index 7ae9b5b8..4ce6d0ce 100644
--- a/common/rfb/EncodeManager.h
+++ b/common/rfb/EncodeManager.h
@@ -24,21 +24,22 @@
#include <stdint.h>
+#include <core/Region.h>
+#include <core/Timer.h>
+
#include <rfb/PixelBuffer.h>
-#include <rfb/Region.h>
-#include <rfb/Timer.h>
namespace rfb {
+
class SConnection;
class Encoder;
class UpdateInfo;
class PixelBuffer;
class RenderedCursor;
- struct Rect;
struct RectInfo;
- class EncodeManager : public Timer::Callback {
+ class EncodeManager : public core::Timer::Callback {
public:
EncodeManager(SConnection* conn);
~EncodeManager();
@@ -48,51 +49,60 @@ namespace rfb {
// Hack to let ConnParams calculate the client's preferred encoding
static bool supported(int encoding);
- bool needsLosslessRefresh(const Region& req);
- int getNextLosslessRefresh(const Region& req);
+ bool needsLosslessRefresh(const core::Region& req);
+ int getNextLosslessRefresh(const core::Region& req);
+
+ void pruneLosslessRefresh(const core::Region& limits);
- void pruneLosslessRefresh(const Region& limits);
+ void forceRefresh(const core::Region& req);
void writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,
const RenderedCursor* renderedCursor);
- void writeLosslessRefresh(const Region& req, const PixelBuffer* pb,
+ void writeLosslessRefresh(const core::Region& req,
+ const PixelBuffer* pb,
const RenderedCursor* renderedCursor,
size_t maxUpdateSize);
protected:
- void handleTimeout(Timer* t) override;
+ void handleTimeout(core::Timer* t) override;
- void doUpdate(bool allowLossy, const Region& changed,
- const Region& copied, const Point& copy_delta,
+ void doUpdate(bool allowLossy, const core::Region& changed,
+ const core::Region& copied,
+ const core::Point& copy_delta,
const PixelBuffer* pb,
const RenderedCursor* renderedCursor);
void prepareEncoders(bool allowLossy);
- Region getLosslessRefresh(const Region& req, size_t maxUpdateSize);
+ core::Region getLosslessRefresh(const core::Region& req,
+ size_t maxUpdateSize);
- int computeNumRects(const Region& changed);
+ int computeNumRects(const core::Region& changed);
- Encoder *startRect(const Rect& rect, int type);
+ Encoder* startRect(const core::Rect& rect, int type);
void endRect();
- void writeCopyRects(const Region& copied, const Point& delta);
- void writeSolidRects(Region *changed, const PixelBuffer* pb);
- void findSolidRect(const Rect& rect, Region *changed, const PixelBuffer* pb);
- void writeRects(const Region& changed, const PixelBuffer* pb);
+ void writeCopyRects(const core::Region& copied,
+ const core::Point& delta);
+ void writeSolidRects(core::Region* changed, const PixelBuffer* pb);
+ void findSolidRect(const core::Rect& rect, core::Region* changed,
+ const PixelBuffer* pb);
+ void writeRects(const core::Region& changed, const PixelBuffer* pb);
- void writeSubRect(const Rect& rect, const PixelBuffer *pb);
+ void writeSubRect(const core::Rect& rect, const PixelBuffer* pb);
- bool checkSolidTile(const Rect& r, const uint8_t* colourValue,
+ bool checkSolidTile(const core::Rect& r, const uint8_t* colourValue,
const PixelBuffer *pb);
- void extendSolidAreaByBlock(const Rect& r, const uint8_t* colourValue,
- const PixelBuffer *pb, Rect* er);
- void extendSolidAreaByPixel(const Rect& r, const Rect& sr,
+ void extendSolidAreaByBlock(const core::Rect& r,
const uint8_t* colourValue,
- const PixelBuffer *pb, Rect* er);
+ const PixelBuffer* pb, core::Rect* er);
+ void extendSolidAreaByPixel(const core::Rect& r,
+ const core::Rect& sr,
+ const uint8_t* colourValue,
+ const PixelBuffer* pb, core::Rect* er);
- PixelBuffer* preparePixelBuffer(const Rect& rect,
- const PixelBuffer *pb, bool convert);
+ PixelBuffer* preparePixelBuffer(const core::Rect& rect,
+ const PixelBuffer* pb, bool convert);
bool analyseRect(const PixelBuffer *pb,
struct RectInfo *info, int maxColours);
@@ -114,11 +124,11 @@ namespace rfb {
std::vector<Encoder*> encoders;
std::vector<int> activeEncoders;
- Region lossyRegion;
- Region recentlyChangedRegion;
- Region pendingRefreshRegion;
+ core::Region lossyRegion;
+ core::Region recentlyChangedRegion;
+ core::Region pendingRefreshRegion;
- Timer recentChangeTimer;
+ core::Timer recentChangeTimer;
struct EncoderStats {
unsigned rects;
@@ -143,12 +153,13 @@ namespace rfb {
const uint8_t* data_, int stride);
private:
- uint8_t* getBufferRW(const Rect& r, int* stride) override;
+ uint8_t* getBufferRW(const core::Rect& r, int* stride) override;
};
OffsetPixelBuffer offsetPixelBuffer;
ManagedPixelBuffer convertedPixelBuffer;
};
+
}
#endif
diff --git a/common/rfb/Encoder.h b/common/rfb/Encoder.h
index 5e066323..7fa2cc75 100644
--- a/common/rfb/Encoder.h
+++ b/common/rfb/Encoder.h
@@ -22,8 +22,6 @@
#include <stdint.h>
-#include <rfb/Rect.h>
-
namespace rfb {
class SConnection;
class PixelBuffer;
diff --git a/common/rfb/H264Decoder.cxx b/common/rfb/H264Decoder.cxx
index 89850ba4..d0d9b4df 100644
--- a/common/rfb/H264Decoder.cxx
+++ b/common/rfb/H264Decoder.cxx
@@ -29,14 +29,11 @@
#include <rdr/MemInStream.h>
#include <rdr/InStream.h>
#include <rdr/OutStream.h>
-#include <rfb/LogWriter.h>
#include <rfb/H264Decoder.h>
#include <rfb/H264DecoderContext.h>
using namespace rfb;
-static LogWriter vlog("H264Decoder");
-
enum rectFlags {
resetContext = 0x1,
resetAllContexts = 0x2,
@@ -53,22 +50,20 @@ H264Decoder::~H264Decoder()
void H264Decoder::resetContexts()
{
- os::AutoMutex lock(&mutex);
for (H264DecoderContext* context : contexts)
delete context;
contexts.clear();
}
-H264DecoderContext* H264Decoder::findContext(const Rect& r)
+H264DecoderContext* H264Decoder::findContext(const core::Rect& r)
{
- os::AutoMutex m(&mutex);
for (H264DecoderContext* context : contexts)
if (context->isEqualRect(r))
return context;
return nullptr;
}
-bool H264Decoder::readRect(const Rect& /*r*/,
+bool H264Decoder::readRect(const core::Rect& /*r*/,
rdr::InStream* is,
const ServerParams& /*server*/,
rdr::OutStream* os)
@@ -96,7 +91,7 @@ bool H264Decoder::readRect(const Rect& /*r*/,
return true;
}
-void H264Decoder::decodeRect(const Rect& r, const uint8_t* buffer,
+void H264Decoder::decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen,
const ServerParams& /*server*/,
ModifiablePixelBuffer* pb)
@@ -116,9 +111,14 @@ void H264Decoder::decodeRect(const Rect& r, const uint8_t* buffer,
ctx = findContext(r);
}
+ if (ctx && (reset & resetContext)) {
+ contexts.remove(ctx);
+ delete ctx;
+ ctx = nullptr;
+ }
+
if (!ctx)
{
- os::AutoMutex lock(&mutex);
if (contexts.size() >= MAX_H264_INSTANCES)
{
H264DecoderContext* excess_ctx = contexts.front();
@@ -131,12 +131,6 @@ void H264Decoder::decodeRect(const Rect& r, const uint8_t* buffer,
contexts.push_back(ctx);
}
- if (!ctx->isReady())
- throw std::runtime_error("H264Decoder: Context is not ready");
-
- if (reset & resetContext)
- ctx->reset();
-
if (!len)
return;
diff --git a/common/rfb/H264Decoder.h b/common/rfb/H264Decoder.h
index 8ba47799..bc1b9281 100644
--- a/common/rfb/H264Decoder.h
+++ b/common/rfb/H264Decoder.h
@@ -21,9 +21,8 @@
#ifndef __RFB_H264DECODER_H__
#define __RFB_H264DECODER_H__
-#include <deque>
+#include <list>
-#include <os/Mutex.h>
#include <rfb/Decoder.h>
namespace rfb {
@@ -33,19 +32,18 @@ namespace rfb {
public:
H264Decoder();
virtual ~H264Decoder();
- bool readRect(const Rect& r, rdr::InStream* is,
+ bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server,
rdr::OutStream* os) override;
- void decodeRect(const Rect& r, const uint8_t* buffer,
+ void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb) override;
private:
void resetContexts();
- H264DecoderContext* findContext(const Rect& r);
+ H264DecoderContext* findContext(const core::Rect& r);
- os::Mutex mutex;
- std::deque<H264DecoderContext*> contexts;
+ std::list<H264DecoderContext*> contexts;
};
}
diff --git a/common/rfb/H264DecoderContext.cxx b/common/rfb/H264DecoderContext.cxx
index b2054554..3ad8c343 100644
--- a/common/rfb/H264DecoderContext.cxx
+++ b/common/rfb/H264DecoderContext.cxx
@@ -22,11 +22,6 @@
#include <config.h>
#endif
-#include <stdexcept>
-
-#include <os/Mutex.h>
-#include <rfb/LogWriter.h>
-
#include <rfb/H264DecoderContext.h>
#ifdef H264_LIBAV
@@ -39,31 +34,11 @@
using namespace rfb;
-static LogWriter vlog("H264DecoderContext");
-
-H264DecoderContext *H264DecoderContext::createContext(const Rect &r)
+H264DecoderContext *H264DecoderContext::createContext(const core::Rect &r)
{
- H264DecoderContext *ret = new H264DecoderContextType(r);
- if (!ret->initCodec())
- {
- throw std::runtime_error("H264DecoderContext: Unable to create context");
- }
-
- return ret;
+ return new H264DecoderContextType(r);
}
H264DecoderContext::~H264DecoderContext()
{
}
-
-bool H264DecoderContext::isReady()
-{
- os::AutoMutex lock(&mutex);
- return initialized;
-}
-
-void H264DecoderContext::reset()
-{
- freeCodec();
- initCodec();
-}
diff --git a/common/rfb/H264DecoderContext.h b/common/rfb/H264DecoderContext.h
index 88c2396c..5ef46662 100644
--- a/common/rfb/H264DecoderContext.h
+++ b/common/rfb/H264DecoderContext.h
@@ -23,35 +23,30 @@
#include <stdint.h>
-#include <os/Mutex.h>
-#include <rfb/Rect.h>
-#include <rfb/Decoder.h>
+#include <core/Rect.h>
namespace rfb {
+
+ class ModifiablePixelBuffer;
+
class H264DecoderContext {
public:
- static H264DecoderContext *createContext(const Rect &r);
+ static H264DecoderContext* createContext(const core::Rect& r);
virtual ~H264DecoderContext() = 0;
virtual void decode(const uint8_t* /*h264_buffer*/,
uint32_t /*len*/,
ModifiablePixelBuffer* /*pb*/) {}
- void reset();
- inline bool isEqualRect(const Rect &r) const { return r == rect; }
- bool isReady();
+ inline bool isEqualRect(const core::Rect &r) const { return r == rect; }
protected:
- os::Mutex mutex;
- rfb::Rect rect;
- bool initialized;
+ core::Rect rect;
- H264DecoderContext(const Rect &r) : rect(r) { initialized = false; }
-
- virtual bool initCodec() { return false; }
- virtual void freeCodec() {}
+ H264DecoderContext(const core::Rect &r) : rect(r) {}
};
+
}
#endif
diff --git a/common/rfb/H264LibavDecoderContext.cxx b/common/rfb/H264LibavDecoderContext.cxx
index 2d8d03e7..ba1b1b6d 100644
--- a/common/rfb/H264LibavDecoderContext.cxx
+++ b/common/rfb/H264LibavDecoderContext.cxx
@@ -22,6 +22,9 @@
#include <config.h>
#endif
+#include <new>
+#include <stdexcept>
+
extern "C" {
#include <libavutil/imgutils.h>
#include <libavcodec/version.h>
@@ -33,41 +36,31 @@ extern "C" {
#define FFMPEG_INIT_PACKET_DEPRECATED
#endif
-#include <rfb/LogWriter.h>
#include <rfb/PixelBuffer.h>
#include <rfb/H264LibavDecoderContext.h>
using namespace rfb;
-static LogWriter vlog("H264LibavDecoderContext");
-
-bool H264LibavDecoderContext::initCodec() {
- os::AutoMutex lock(&mutex);
-
+H264LibavDecoderContext::H264LibavDecoderContext(const core::Rect& r)
+ : H264DecoderContext(r)
+{
sws = nullptr;
h264WorkBuffer = nullptr;
h264WorkBufferLength = 0;
const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec)
- {
- vlog.error("Codec not found");
- return false;
- }
+ throw std::runtime_error("Codec not found");
parser = av_parser_init(codec->id);
if (!parser)
- {
- vlog.error("Could not create H264 parser");
- return false;
- }
+ throw std::runtime_error("Could not create H264 parser");
avctx = avcodec_alloc_context3(codec);
if (!avctx)
{
av_parser_close(parser);
- vlog.error("Could not allocate video codec context");
- return false;
+ throw std::runtime_error("Could not allocate video codec context");
}
frame = av_frame_alloc();
@@ -75,8 +68,7 @@ bool H264LibavDecoderContext::initCodec() {
{
av_parser_close(parser);
avcodec_free_context(&avctx);
- vlog.error("Could not allocate video frame");
- return false;
+ throw std::runtime_error("Could not allocate video frame");
}
if (avcodec_open2(avctx, codec, nullptr) < 0)
@@ -84,26 +76,18 @@ bool H264LibavDecoderContext::initCodec() {
av_parser_close(parser);
avcodec_free_context(&avctx);
av_frame_free(&frame);
- vlog.error("Could not open codec");
- return false;
+ throw std::runtime_error("Could not open video codec");
}
-
- initialized = true;
- return true;
}
-void H264LibavDecoderContext::freeCodec() {
- os::AutoMutex lock(&mutex);
-
- if (!initialized)
- return;
+H264LibavDecoderContext::~H264LibavDecoderContext()
+{
av_parser_close(parser);
avcodec_free_context(&avctx);
av_frame_free(&rgbFrame);
av_frame_free(&frame);
sws_freeContext(sws);
free(h264WorkBuffer);
- initialized = false;
}
// We need to reallocate buffer because AVPacket uses non-const pointer.
@@ -130,9 +114,6 @@ uint8_t* H264LibavDecoderContext::makeH264WorkBuffer(const uint8_t* buffer, uint
void H264LibavDecoderContext::decode(const uint8_t* h264_in_buffer,
uint32_t len,
ModifiablePixelBuffer* pb) {
- os::AutoMutex lock(&mutex);
- if (!initialized)
- return;
uint8_t* h264_work_buffer = makeH264WorkBuffer(h264_in_buffer, len);
#ifdef FFMPEG_INIT_PACKET_DEPRECATED
@@ -147,19 +128,15 @@ void H264LibavDecoderContext::decode(const uint8_t* h264_in_buffer,
while (len)
{
ret = av_parser_parse2(parser, avctx, &packet->data, &packet->size, h264_work_buffer, len, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
+ // Silently ignore errors, hoping its a temporary encoding glitch
if (ret < 0)
- {
- vlog.error("Error while parsing");
break;
- }
// We need to slap on tv to make it work here (don't ask me why)
if (!packet->size && len == static_cast<uint32_t>(ret))
ret = av_parser_parse2(parser, avctx, &packet->data, &packet->size, h264_work_buffer, len, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
+ // Silently ignore errors, hoping its a temporary encoding glitch
if (ret < 0)
- {
- vlog.error("Error while parsing");
break;
- }
h264_work_buffer += ret;
len -= ret;
@@ -176,27 +153,21 @@ void H264LibavDecoderContext::decode(const uint8_t* h264_in_buffer,
#ifndef FFMPEG_DECODE_VIDEO2_DEPRECATED
int got_frame;
ret = avcodec_decode_video2(avctx, frame, &got_frame, packet);
+ // Silently ignore errors, hoping its a temporary encoding glitch
if (ret < 0 || !got_frame)
- {
- vlog.error("Error during decoding");
break;
- }
#else
ret = avcodec_send_packet(avctx, packet);
+ // Silently ignore errors, hoping its a temporary encoding glitch
if (ret < 0)
- {
- vlog.error("Error sending a packet to decoding");
break;
- }
ret = avcodec_receive_frame(avctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
- else if (ret < 0)
- {
- vlog.error("Error during decoding");
+ // Silently ignore errors, hoping its a temporary encoding glitch
+ if (ret < 0)
break;
- }
#endif
frames_received++;
}
diff --git a/common/rfb/H264LibavDecoderContext.h b/common/rfb/H264LibavDecoderContext.h
index 96558bee..c23fdf79 100644
--- a/common/rfb/H264LibavDecoderContext.h
+++ b/common/rfb/H264LibavDecoderContext.h
@@ -31,16 +31,12 @@ extern "C" {
namespace rfb {
class H264LibavDecoderContext : public H264DecoderContext {
public:
- H264LibavDecoderContext(const Rect &r) : H264DecoderContext(r) {}
- ~H264LibavDecoderContext() { freeCodec(); }
+ H264LibavDecoderContext(const core::Rect &r);
+ ~H264LibavDecoderContext();
void decode(const uint8_t* h264_buffer, uint32_t len,
ModifiablePixelBuffer* pb) override;
- protected:
- bool initCodec() override;
- void freeCodec() override;
-
private:
uint8_t* makeH264WorkBuffer(const uint8_t* buffer, uint32_t len);
diff --git a/common/rfb/H264WinDecoderContext.cxx b/common/rfb/H264WinDecoderContext.cxx
index a9b13942..71086fad 100644
--- a/common/rfb/H264WinDecoderContext.cxx
+++ b/common/rfb/H264WinDecoderContext.cxx
@@ -22,48 +22,38 @@
#include <config.h>
#endif
+#include <stdexcept>
+
#include <mfapi.h>
#include <mferror.h>
#include <wmcodecdsp.h>
#define SAFE_RELEASE(obj) if (obj) { obj->Release(); obj = nullptr; }
-#include <os/Mutex.h>
-#include <rfb/LogWriter.h>
#include <rfb/PixelBuffer.h>
#include <rfb/H264WinDecoderContext.h>
using namespace rfb;
-static LogWriter vlog("H264WinDecoderContext");
-
// Older MinGW lacks this definition
#ifndef HAVE_VIDEO_PROCESSOR_MFT
static GUID CLSID_VideoProcessorMFT = { 0x88753b26, 0x5b24, 0x49bd, { 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82 } };
#endif
-bool H264WinDecoderContext::initCodec() {
- os::AutoMutex lock(&mutex);
-
+H264WinDecoderContext::H264WinDecoderContext(const core::Rect &r)
+ : H264DecoderContext(r)
+{
if (FAILED(MFStartup(MF_VERSION, MFSTARTUP_LITE)))
- {
- vlog.error("Could not initialize MediaFoundation");
- return false;
- }
+ throw std::runtime_error("Could not initialize MediaFoundation");
if (FAILED(CoCreateInstance(CLSID_CMSH264DecoderMFT, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (LPVOID*)&decoder)))
- {
- vlog.error("MediaFoundation H264 codec not found");
- return false;
- }
+ throw std::runtime_error("MediaFoundation H264 codec not found");
if (FAILED(CoCreateInstance(CLSID_VideoProcessorMFT, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (LPVOID*)&converter)))
{
- vlog.error("Cannot create MediaFoundation Video Processor (available only on Windows 8+). Trying ColorConvert DMO.");
if (FAILED(CoCreateInstance(CLSID_CColorConvertDMO, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (LPVOID*)&converter)))
{
decoder->Release();
- vlog.error("ColorConvert DMO not found");
- return false;
+ throw std::runtime_error("MediaFoundation H264 codec not found");
}
}
@@ -72,10 +62,7 @@ bool H264WinDecoderContext::initCodec() {
if (SUCCEEDED(decoder->GetAttributes(&attributes)))
{
GUID MF_LOW_LATENCY = { 0x9c27891a, 0xed7a, 0x40e1, { 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee } };
- if (SUCCEEDED(attributes->SetUINT32(MF_LOW_LATENCY, TRUE)))
- {
- vlog.info("Enabled low latency mode");
- }
+ attributes->SetUINT32(MF_LOW_LATENCY, TRUE);
attributes->Release();
}
@@ -85,8 +72,7 @@ bool H264WinDecoderContext::initCodec() {
{
decoder->Release();
converter->Release();
- vlog.error("Could not create MF MediaType");
- return false;
+ throw std::runtime_error("Could not create MF MediaType");
}
input_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
input_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
@@ -113,8 +99,7 @@ bool H264WinDecoderContext::initCodec() {
decoder->Release();
converter->Release();
input_type->Release();
- vlog.error("Could not start H264 decoder");
- return false;
+ throw std::runtime_error("Could not start H264 decoder");
}
MFT_OUTPUT_STREAM_INFO info;
@@ -134,22 +119,14 @@ bool H264WinDecoderContext::initCodec() {
SAFE_RELEASE(converted_sample);
SAFE_RELEASE(input_buffer);
SAFE_RELEASE(decoded_buffer);
- vlog.error("Could not allocate media samples/buffers");
- return false;
+ throw std::runtime_error("Could not allocate media samples/buffers");
}
input_sample->AddBuffer(input_buffer);
decoded_sample->AddBuffer(decoded_buffer);
-
- initialized = true;
- return true;
}
-void H264WinDecoderContext::freeCodec() {
- os::AutoMutex lock(&mutex);
-
- if (!initialized)
- return;
+H264WinDecoderContext::~H264WinDecoderContext() {
SAFE_RELEASE(decoder)
SAFE_RELEASE(converter)
SAFE_RELEASE(input_sample)
@@ -159,24 +136,16 @@ void H264WinDecoderContext::freeCodec() {
SAFE_RELEASE(decoded_buffer)
SAFE_RELEASE(converted_buffer)
MFShutdown();
- initialized = false;
}
void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
uint32_t len,
ModifiablePixelBuffer* pb) {
- os::AutoMutex lock(&mutex);
- if (!initialized)
- return;
-
if (FAILED(input_buffer->SetCurrentLength(len)))
{
input_buffer->Release();
if (FAILED(MFCreateMemoryBuffer(len, &input_buffer)))
- {
- vlog.error("Could not allocate media buffer");
- return;
- }
+ throw std::runtime_error("Could not allocate media buffer");
input_buffer->SetCurrentLength(len);
input_sample->RemoveAllBuffers();
input_sample->AddBuffer(input_buffer);
@@ -187,14 +156,12 @@ void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
memcpy(locked, h264_buffer, len);
input_buffer->Unlock();
- vlog.debug("Received %u bytes, decoding", len);
-
// extract actual size, including possible cropping
ParseSPS(h264_buffer, len);
if (FAILED(decoder->ProcessInput(0, input_sample, 0)))
{
- vlog.error("Error sending a packet to decoding");
+ // Silently ignore errors, hoping its a temporary encoding glitch
return;
}
@@ -219,7 +186,6 @@ void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
if (SUCCEEDED(hr))
{
- vlog.debug("Frame decoded");
// successfully decoded next frame
// but do not exit loop, try again if there is next frame
decoded = true;
@@ -259,7 +225,7 @@ void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
UINT32 width, height;
if FAILED(MFGetAttributeSize(output_type, MF_MT_FRAME_SIZE, &width, &height))
{
- vlog.error("Error getting output type size");
+ // Silently ignore errors, hoping its a temporary encoding glitch
output_type->Release();
break;
}
@@ -279,13 +245,11 @@ void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
crop_height = height;
}
- vlog.debug("Setting up decoded output with %ux%u size", crop_width, crop_height);
-
// input type to converter, BGRX pixel format
IMFMediaType* converted_type;
if (FAILED(MFCreateMediaType(&converted_type)))
{
- vlog.error("Error creating media type");
+ // Silently ignore errors, hoping its a temporary encoding glitch
}
else
{
@@ -310,7 +274,7 @@ void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
if (FAILED(MFCreateMemoryBuffer(info.cbSize, &converted_buffer)))
{
- vlog.error("Error creating media buffer");
+ // Silently ignore errors, hoping its a temporary encoding glitch
}
else
{
@@ -327,7 +291,7 @@ void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
{
if (FAILED(converter->ProcessInput(0, decoded_sample, 0)))
{
- vlog.error("Error sending a packet to converter");
+ // Silently ignore errors, hoping its a temporary encoding glitch
return;
}
@@ -343,12 +307,10 @@ void H264WinDecoderContext::decode(const uint8_t* h264_buffer,
if (FAILED(hr))
{
- vlog.error("Error converting to RGB");
+ // Silently ignore errors, hoping its a temporary encoding glitch
}
else
{
- vlog.debug("Frame converted to RGB");
-
BYTE* out;
DWORD buflen;
converted_buffer->Lock(&out, nullptr, &buflen);
@@ -528,8 +490,6 @@ void H264WinDecoderContext::ParseSPS(const uint8_t* buffer, int length)
offset_x = frame_crop_left_offset;
offset_y = frame_crop_bottom_offset;
- vlog.debug("SPS parsing - full=%dx%d, cropped=%dx%d, offset=%d,%d", full_width, full_height, crop_width, crop_height, offset_x, offset_y);
-
#undef SKIP_BITS
#undef SKIP_UE
#undef GET_BITS
diff --git a/common/rfb/H264WinDecoderContext.h b/common/rfb/H264WinDecoderContext.h
index 92041781..b1dbf0e1 100644
--- a/common/rfb/H264WinDecoderContext.h
+++ b/common/rfb/H264WinDecoderContext.h
@@ -30,16 +30,12 @@
namespace rfb {
class H264WinDecoderContext : public H264DecoderContext {
public:
- H264WinDecoderContext(const Rect &r) : H264DecoderContext(r) {};
- ~H264WinDecoderContext() { freeCodec(); }
+ H264WinDecoderContext(const core::Rect &r);
+ ~H264WinDecoderContext();
void decode(const uint8_t* h264_buffer, uint32_t len,
ModifiablePixelBuffer* pb) override;
- protected:
- bool initCodec() override;
- void freeCodec() override;
-
private:
LONG stride;
uint32_t full_width = 0;
diff --git a/common/rfb/HextileDecoder.cxx b/common/rfb/HextileDecoder.cxx
index 35ec7928..c6eb428b 100644
--- a/common/rfb/HextileDecoder.cxx
+++ b/common/rfb/HextileDecoder.cxx
@@ -21,6 +21,8 @@
#include <config.h>
#endif
+#include <algorithm>
+
#include <rdr/InStream.h>
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
@@ -41,10 +43,10 @@ HextileDecoder::~HextileDecoder()
{
}
-bool HextileDecoder::readRect(const Rect& r, rdr::InStream* is,
+bool HextileDecoder::readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server, rdr::OutStream* os)
{
- Rect t;
+ core::Rect t;
size_t bytesPerPixel;
is->setRestorePoint();
@@ -53,12 +55,12 @@ bool HextileDecoder::readRect(const Rect& r, rdr::InStream* is,
for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
- t.br.y = __rfbmin(r.br.y, t.tl.y + 16);
+ t.br.y = std::min(r.br.y, t.tl.y + 16);
for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
uint8_t tileType;
- t.br.x = __rfbmin(r.br.x, t.tl.x + 16);
+ t.br.x = std::min(r.br.x, t.tl.x + 16);
if (!is->hasDataOrRestore(1))
return false;
@@ -113,7 +115,7 @@ bool HextileDecoder::readRect(const Rect& r, rdr::InStream* is,
return true;
}
-void HextileDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
+void HextileDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
@@ -138,22 +140,22 @@ inline T HextileDecoder::readPixel(rdr::InStream* is)
}
template<class T>
-void HextileDecoder::hextileDecode(const Rect& r, rdr::InStream* is,
+void HextileDecoder::hextileDecode(const core::Rect& r, rdr::InStream* is,
const PixelFormat& pf,
ModifiablePixelBuffer* pb)
{
- Rect t;
+ core::Rect t;
T bg = 0;
T fg = 0;
T buf[16 * 16];
for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
- t.br.y = __rfbmin(r.br.y, t.tl.y + 16);
+ t.br.y = std::min(r.br.y, t.tl.y + 16);
for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
- t.br.x = __rfbmin(r.br.x, t.tl.x + 16);
+ t.br.x = std::min(r.br.x, t.tl.x + 16);
int tileType = is->readU8();
diff --git a/common/rfb/HextileDecoder.h b/common/rfb/HextileDecoder.h
index 38e8b776..6ff94a1f 100644
--- a/common/rfb/HextileDecoder.h
+++ b/common/rfb/HextileDecoder.h
@@ -29,17 +29,17 @@ namespace rfb {
public:
HextileDecoder();
virtual ~HextileDecoder();
- bool readRect(const Rect& r, rdr::InStream* is,
+ bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server,
rdr::OutStream* os) override;
- void decodeRect(const Rect& r, const uint8_t* buffer,
+ void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb) override;
private:
template<class T>
inline T readPixel(rdr::InStream* is);
template<class T>
- void hextileDecode(const Rect& r, rdr::InStream* is,
+ void hextileDecode(const core::Rect& r, rdr::InStream* is,
const PixelFormat& pf,
ModifiablePixelBuffer* pb);
};
diff --git a/common/rfb/HextileEncoder.cxx b/common/rfb/HextileEncoder.cxx
index 0666d02d..5ee07a2d 100644
--- a/common/rfb/HextileEncoder.cxx
+++ b/common/rfb/HextileEncoder.cxx
@@ -22,21 +22,28 @@
#include <config.h>
#endif
+#include <algorithm>
+
+#include <core/Configuration.h>
+
+#include <rdr/OutStream.h>
+
#include <rfb/encodings.h>
#include <rfb/SConnection.h>
#include <rfb/HextileEncoder.h>
#include <rfb/Palette.h>
#include <rfb/PixelBuffer.h>
-#include <rfb/Configuration.h>
#include <rfb/hextileConstants.h>
using namespace rfb;
-BoolParameter improvedHextile("ImprovedHextile",
- "Use improved compression algorithm for Hextile "
- "encoding which achieves better compression "
- "ratios by the cost of using more CPU time",
- true);
+core::BoolParameter improvedHextile("ImprovedHextile",
+ "Use improved compression "
+ "algorithm for Hextile encoding "
+ "which achieves better compression "
+ "ratios by the cost of using more "
+ "CPU time",
+ true);
HextileEncoder::HextileEncoder(SConnection* conn_) :
Encoder(conn_, encodingHextile, EncoderPlain)
@@ -115,7 +122,7 @@ template<class T>
void HextileEncoder::hextileEncode(rdr::OutStream* os,
const PixelBuffer* pb)
{
- Rect t;
+ core::Rect t;
T buf[256];
T oldBg = 0, oldFg = 0;
bool oldBgValid = false;
@@ -124,11 +131,11 @@ void HextileEncoder::hextileEncode(rdr::OutStream* os,
for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {
- t.br.y = __rfbmin(pb->height(), t.tl.y + 16);
+ t.br.y = std::min(pb->height(), t.tl.y + 16);
for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {
- t.br.x = __rfbmin(pb->width(), t.tl.x + 16);
+ t.br.x = std::min(pb->width(), t.tl.x + 16);
pb->getImage(buf, t);
@@ -532,7 +539,7 @@ template<class T>
void HextileEncoder::hextileEncodeBetter(rdr::OutStream* os,
const PixelBuffer* pb)
{
- Rect t;
+ core::Rect t;
T buf[256];
T oldBg = 0, oldFg = 0;
bool oldBgValid = false;
@@ -543,11 +550,11 @@ void HextileEncoder::hextileEncodeBetter(rdr::OutStream* os,
for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {
- t.br.y = __rfbmin(pb->height(), t.tl.y + 16);
+ t.br.y = std::min(pb->height(), t.tl.y + 16);
for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {
- t.br.x = __rfbmin(pb->width(), t.tl.x + 16);
+ t.br.x = std::min(pb->width(), t.tl.x + 16);
pb->getImage(buf, t);
diff --git a/common/rfb/Hostname.h b/common/rfb/Hostname.h
deleted file mode 100644
index f43e5067..00000000
--- a/common/rfb/Hostname.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifndef __RFB_HOSTNAME_H__
-#define __RFB_HOSTNAME_H__
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <stdexcept>
-
-#include <rfb/util.h>
-
-namespace rfb {
-
- static bool isAllSpace(const char *string) {
- if (string == nullptr)
- return false;
- while(*string != '\0') {
- if (! isspace(*string))
- return false;
- string++;
- }
- return true;
- }
-
- static inline void getHostAndPort(const char* hi, std::string* host,
- int* port, int basePort=5900)
- {
- const char* hostStart;
- const char* hostEnd;
- const char* portStart;
-
- if (hi == nullptr)
- throw std::invalid_argument("NULL host specified");
-
- // Trim leading whitespace
- while(isspace(*hi))
- hi++;
-
- assert(host);
- assert(port);
-
- if (hi[0] == '[') {
- hostStart = &hi[1];
- hostEnd = strchr(hostStart, ']');
- if (hostEnd == nullptr)
- throw std::invalid_argument("Unmatched [ in host");
-
- portStart = hostEnd + 1;
- if (isAllSpace(portStart))
- portStart = nullptr;
- } else {
- hostStart = &hi[0];
- hostEnd = strrchr(hostStart, ':');
-
- if (hostEnd == nullptr) {
- hostEnd = hostStart + strlen(hostStart);
- portStart = nullptr;
- } else {
- if ((hostEnd > hostStart) && (hostEnd[-1] == ':'))
- hostEnd--;
- portStart = strchr(hostStart, ':');
- if (portStart != hostEnd) {
- // We found more : in the host. This is probably an IPv6 address
- hostEnd = hostStart + strlen(hostStart);
- portStart = nullptr;
- }
- }
- }
-
- // Back up past trailing space
- while(isspace(*(hostEnd - 1)) && hostEnd > hostStart)
- hostEnd--;
-
- if (hostStart == hostEnd)
- *host = "localhost";
- else
- *host = std::string(hostStart, hostEnd - hostStart);
-
- if (portStart == nullptr)
- *port = basePort;
- else {
- char* end;
-
- if (portStart[0] != ':')
- throw std::invalid_argument("Invalid port specified");
-
- if (portStart[1] != ':')
- *port = strtol(portStart + 1, &end, 10);
- else
- *port = strtol(portStart + 2, &end, 10);
- if (*end != '\0' && ! isAllSpace(end))
- throw std::invalid_argument("Invalid port specified");
-
- if ((portStart[1] != ':') && (*port < 100))
- *port += basePort;
- }
- }
-
-};
-
-#endif // __RFB_HOSTNAME_H__
diff --git a/common/rfb/JpegCompressor.cxx b/common/rfb/JpegCompressor.cxx
index 67a86cd9..d8216c99 100644
--- a/common/rfb/JpegCompressor.cxx
+++ b/common/rfb/JpegCompressor.cxx
@@ -24,8 +24,9 @@
#include <stdexcept>
+#include <core/Rect.h>
+
#include <rfb/JpegCompressor.h>
-#include <rfb/Rect.h>
#include <rfb/PixelFormat.h>
#include <rfb/ClientParams.h>
@@ -157,7 +158,8 @@ JpegCompressor::~JpegCompressor(void)
}
void JpegCompressor::compress(const uint8_t *buf, volatile int stride,
- const Rect& r, const PixelFormat& pf,
+ const core::Rect& r,
+ const PixelFormat& pf,
int quality, int subsamp)
{
int w = r.width();
diff --git a/common/rfb/JpegCompressor.h b/common/rfb/JpegCompressor.h
index 26194204..2460f62b 100644
--- a/common/rfb/JpegCompressor.h
+++ b/common/rfb/JpegCompressor.h
@@ -25,9 +25,9 @@
#ifndef __RFB_JPEGCOMPRESSOR_H__
#define __RFB_JPEGCOMPRESSOR_H__
+#include <core/Rect.h>
+
#include <rdr/MemOutStream.h>
-#include <rfb/PixelFormat.h>
-#include <rfb/Rect.h>
struct jpeg_compress_struct;
@@ -36,6 +36,9 @@ struct JPEG_DEST_MGR;
namespace rfb {
+ class PixelFormat;
+ struct Rect;
+
class JpegCompressor : public rdr::MemOutStream {
public:
@@ -43,7 +46,8 @@ namespace rfb {
JpegCompressor(int bufferLen = 128*1024);
virtual ~JpegCompressor();
- void compress(const uint8_t *, int, const Rect&, const PixelFormat&, int, int);
+ void compress(const uint8_t*, int, const core::Rect&,
+ const PixelFormat&, int, int);
void writeBytes(const uint8_t*, int);
diff --git a/common/rfb/JpegDecompressor.cxx b/common/rfb/JpegDecompressor.cxx
index 10c9e49c..ef548be0 100644
--- a/common/rfb/JpegDecompressor.cxx
+++ b/common/rfb/JpegDecompressor.cxx
@@ -23,9 +23,10 @@
#include <config.h>
#endif
+#include <core/Rect.h>
+
#include <rfb/JpegDecompressor.h>
#include <rfb/Exception.h>
-#include <rfb/Rect.h>
#include <rfb/PixelFormat.h>
#include <stdio.h>
@@ -153,7 +154,8 @@ JpegDecompressor::~JpegDecompressor(void)
void JpegDecompressor::decompress(const uint8_t *jpegBuf,
int jpegBufLen, uint8_t *buf,
volatile int stride,
- const Rect& r, const PixelFormat& pf)
+ const core::Rect& r,
+ const PixelFormat& pf)
{
int w = r.width();
int h = r.height();
diff --git a/common/rfb/JpegDecompressor.h b/common/rfb/JpegDecompressor.h
index 5d4f0c21..8e651b1c 100644
--- a/common/rfb/JpegDecompressor.h
+++ b/common/rfb/JpegDecompressor.h
@@ -26,16 +26,19 @@
#ifndef __RFB_JPEGDECOMPRESSOR_H__
#define __RFB_JPEGDECOMPRESSOR_H__
-#include <rfb/PixelFormat.h>
-#include <rfb/Rect.h>
+#include <stdint.h>
struct jpeg_decompress_struct;
struct JPEG_ERROR_MGR;
struct JPEG_SRC_MGR;
+namespace core { struct Rect; }
+
namespace rfb {
+ class PixelFormat;
+
class JpegDecompressor {
public:
@@ -43,8 +46,8 @@ namespace rfb {
JpegDecompressor(void);
virtual ~JpegDecompressor();
- void decompress(const uint8_t *, int, uint8_t *, int, const Rect&,
- const PixelFormat&);
+ void decompress(const uint8_t*, int, uint8_t*, int,
+ const core::Rect&, const PixelFormat&);
private:
diff --git a/common/rfb/KeyRemapper.cxx b/common/rfb/KeyRemapper.cxx
index 1c478178..24740321 100644
--- a/common/rfb/KeyRemapper.cxx
+++ b/common/rfb/KeyRemapper.cxx
@@ -23,59 +23,31 @@
#include <stdio.h>
#include <string.h>
-#include <os/Mutex.h>
+#include <core/Configuration.h>
+#include <core/LogWriter.h>
#include <rfb/KeyRemapper.h>
-#include <rfb/Configuration.h>
-#include <rfb/LogWriter.h>
using namespace rfb;
-static LogWriter vlog("KeyRemapper");
+static core::LogWriter vlog("KeyRemapper");
KeyRemapper KeyRemapper::defInstance;
-KeyRemapper::KeyRemapper(const char* m)
+KeyRemapper::KeyRemapper()
{
- mutex = new os::Mutex;
-
- setMapping(m);
}
KeyRemapper::~KeyRemapper()
{
- delete mutex;
}
-void KeyRemapper::setMapping(const char* m) {
- os::AutoMutex a(mutex);
-
- mapping.clear();
- while (m[0]) {
- int from, to;
- char bidi;
- const char* nextComma = strchr(m, ',');
- if (!nextComma)
- nextComma = m + strlen(m);
- if (sscanf(m, "0x%x%c>0x%x", &from,
- &bidi, &to) == 3) {
- if (bidi != '-' && bidi != '<')
- vlog.error("Warning: Unknown operation %c>, assuming ->", bidi);
- mapping[from] = to;
- if (bidi == '<')
- mapping[to] = from;
- } else {
- vlog.error("Warning: Bad mapping %.*s", (int)(nextComma-m), m);
- }
- m = nextComma;
- if (nextComma[0])
- m++;
- }
+void KeyRemapper::setMapping(const std::map<uint32_t,uint32_t>& m)
+{
+ mapping = m;
}
uint32_t KeyRemapper::remapKey(uint32_t key) const {
- os::AutoMutex a(mutex);
-
std::map<uint32_t,uint32_t>::const_iterator i = mapping.find(key);
if (i != mapping.end())
return i->second;
@@ -83,15 +55,41 @@ uint32_t KeyRemapper::remapKey(uint32_t key) const {
}
-class KeyMapParameter : public StringParameter {
+class KeyMapParameter : public core::StringListParameter {
public:
KeyMapParameter()
- : StringParameter("RemapKeys", "Comma-separated list of incoming keysyms to remap. Mappings are expressed as two hex values, prefixed by 0x, and separated by ->", "") {
- KeyRemapper::defInstance.setMapping("");
+ : core::StringListParameter("RemapKeys",
+ "Comma-separated list of incoming "
+ "keysyms to remap. Mappings are "
+ "expressed as two hex values, prefixed "
+ "by 0x, and separated by ->",
+ {}) {
+ KeyRemapper::defInstance.setMapping({});
}
bool setParam(const char* v) override {
- KeyRemapper::defInstance.setMapping(v);
- return StringParameter::setParam(v);
+ std::map<uint32_t,uint32_t> mapping;
+
+ if (!core::StringListParameter::setParam(v))
+ return false;
+
+ for (const char* m : *this) {
+ int from, to;
+ char bidi;
+ if (sscanf(m, "0x%x%c>0x%x", &from,
+ &bidi, &to) == 3) {
+ if (bidi != '-' && bidi != '<')
+ vlog.error("Warning: Unknown operation %c>, assuming ->", bidi);
+ mapping[from] = to;
+ if (bidi == '<')
+ mapping[to] = from;
+ } else {
+ vlog.error("Warning: Bad mapping %s", m);
+ }
+ }
+
+ KeyRemapper::defInstance.setMapping(mapping);
+
+ return true;
}
} defaultParam;
diff --git a/common/rfb/KeyRemapper.h b/common/rfb/KeyRemapper.h
index 89853721..71ef0a87 100644
--- a/common/rfb/KeyRemapper.h
+++ b/common/rfb/KeyRemapper.h
@@ -23,20 +23,17 @@
#include <stdint.h>
-namespace os { class Mutex; }
-
namespace rfb {
class KeyRemapper {
public:
- KeyRemapper(const char* m="");
+ KeyRemapper();
~KeyRemapper();
- void setMapping(const char* m);
+ void setMapping(const std::map<uint32_t,uint32_t>& m);
uint32_t remapKey(uint32_t key) const;
static KeyRemapper defInstance;
private:
std::map<uint32_t,uint32_t> mapping;
- os::Mutex* mutex;
};
};
diff --git a/common/rfb/LogWriter.cxx b/common/rfb/LogWriter.cxx
deleted file mode 100644
index 8e39d544..00000000
--- a/common/rfb/LogWriter.cxx
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- LogWriter.cxx - client-side logging interface
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <rfb/LogWriter.h>
-#include <rfb/Configuration.h>
-#include <rfb/util.h>
-#include <stdlib.h>
-
-rfb::LogParameter rfb::logParams;
-
-using namespace rfb;
-
-
-LogWriter::LogWriter(const char* name)
- : m_name(name), m_level(0), m_log(nullptr), m_next(log_writers) {
- log_writers = this;
-}
-
-LogWriter::~LogWriter() {
- // *** Should remove this logger here!
-}
-
-void LogWriter::setLog(Logger *logger) {
- m_log = logger;
-}
-
-void LogWriter::setLevel(int level) {
- m_level = level;
-}
-
-void
-LogWriter::listLogWriters(int /*width*/) {
- // *** make this respect width...
- LogWriter* current = log_writers;
- fprintf(stderr, " ");
- while (current) {
- fprintf(stderr, "%s", current->m_name);
- current = current->m_next;
- if (current) fprintf(stderr, ", ");
- }
- fprintf(stderr, "\n");
-}
-
-LogWriter* LogWriter::log_writers;
-
-LogWriter*
-LogWriter::getLogWriter(const char* name) {
- LogWriter* current = log_writers;
- while (current) {
- if (strcasecmp(name, current->m_name) == 0) return current;
- current = current->m_next;
- }
- return nullptr;
-}
-
-bool LogWriter::setLogParams(const char* params) {
- std::vector<std::string> parts;
- parts = split(params, ':');
- if (parts.size() != 3) {
- fprintf(stderr, "Failed to parse log params:%s\n",params);
- return false;
- }
- int level = atoi(parts[2].c_str());
- Logger* logger = nullptr;
- if (!parts[1].empty()) {
- logger = Logger::getLogger(parts[1].c_str());
- if (!logger)
- fprintf(stderr, "No logger found! %s\n", parts[1].c_str());
- }
- if (parts[0] == "*") {
- LogWriter* current = log_writers;
- while (current) {
- current->setLog(logger);
- current->setLevel(level);
- current = current->m_next;
- }
- return true;
- } else {
- LogWriter* logwriter = getLogWriter(parts[0].c_str());
- if (!logwriter) {
- fprintf(stderr, "No logwriter found! %s\n", parts[0].c_str());
- } else {
- logwriter->setLog(logger);
- logwriter->setLevel(level);
- return true;
- }
- }
- return false;
-}
-
-
-LogParameter::LogParameter()
- : StringParameter("Log",
- "Specifies which log output should be directed to "
- "which target logger, and the level of output to log. "
- "Format is <log>:<target>:<level>[, ...].",
- "") {
-}
-
-bool LogParameter::setParam(const char* v) {
- if (immutable) return true;
- LogWriter::setLogParams("*::0");
- StringParameter::setParam(v);
- std::vector<std::string> parts;
- parts = split(v, ',');
- for (size_t i = 0; i < parts.size(); i++) {
- if (parts[i].empty())
- continue;
- if (!LogWriter::setLogParams(parts[i].c_str()))
- return false;
- }
- return true;
-}
diff --git a/common/rfb/LogWriter.h b/common/rfb/LogWriter.h
deleted file mode 100644
index d1fd4990..00000000
--- a/common/rfb/LogWriter.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- LogWriter.h - The Log writer class.
-
-#ifndef __RFB_LOG_WRITER_H__
-#define __RFB_LOG_WRITER_H__
-
-#include <stdarg.h>
-#include <rfb/Logger.h>
-#include <rfb/Configuration.h>
-
-// Each log writer instance has a unique textual name,
-// and is attached to a particular Log instance and
-// is assigned a particular log level.
-
-#define DEF_LOGFUNCTION(name, level) \
- inline void v##name(const char* fmt, va_list ap) \
- __attribute__((__format__ (__printf__, 2, 0))) \
- { \
- if (m_log && (level <= m_level)) \
- m_log->write(level, m_name, fmt, ap); \
- } \
- inline void name(const char* fmt, ...) \
- __attribute__((__format__ (__printf__, 2, 3))) \
- { \
- if (m_log && (level <= m_level)) { \
- va_list ap; va_start(ap, fmt); \
- m_log->write(level, m_name, fmt, ap);\
- va_end(ap); \
- } \
- }
-
-namespace rfb {
-
- class LogWriter;
-
- class LogWriter {
- public:
- LogWriter(const char* name);
- ~LogWriter();
-
- const char *getName() {return m_name;}
-
- void setLog(Logger *logger);
- void setLevel(int level);
- int getLevel(void) { return m_level; }
-
- inline void write(int level, const char* format, ...)
- __attribute__((__format__ (__printf__, 3, 4)))
- {
- if (m_log && (level <= m_level)) {
- va_list ap;
- va_start(ap, format);
- m_log->write(level, m_name, format, ap);
- va_end(ap);
- }
- }
-
- static const int LEVEL_ERROR = 0;
- static const int LEVEL_STATUS = 10;
- static const int LEVEL_INFO = 30;
- static const int LEVEL_DEBUG = 100;
-
- DEF_LOGFUNCTION(error, LEVEL_ERROR)
- DEF_LOGFUNCTION(status, LEVEL_STATUS)
- DEF_LOGFUNCTION(info, LEVEL_INFO)
- DEF_LOGFUNCTION(debug, LEVEL_DEBUG)
-
- // -=- DIAGNOSTIC & HELPER ROUTINES
-
- static void listLogWriters(int width=79);
-
- // -=- CLASS FIELDS & FUNCTIONS
-
- static LogWriter* log_writers;
-
- static LogWriter* getLogWriter(const char* name);
-
- static bool setLogParams(const char* params);
-
- private:
- const char* m_name;
- int m_level;
- Logger* m_log;
- LogWriter* m_next;
- };
-
- class LogParameter : public StringParameter {
- public:
- LogParameter();
- bool setParam(const char* v) override;
- };
- extern LogParameter logParams;
-
-};
-
-#endif // __RFB_LOG_WRITER_H__
diff --git a/common/rfb/Logger.cxx b/common/rfb/Logger.cxx
deleted file mode 100644
index 25f7ccb7..00000000
--- a/common/rfb/Logger.cxx
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- Logger.cxx - support for the Logger and LogWriter classes
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <rfb/Logger.h>
-#include <rfb/LogWriter.h>
-
-using namespace rfb;
-
-Logger* Logger::loggers = nullptr;
-
-Logger::Logger(const char* name)
- : registered(false), m_name(name), m_next(nullptr)
-{
-}
-
-Logger::~Logger() {
- // *** Should remove this logger here!
-}
-
-void Logger::write(int level, const char *logname, const char* format,
- va_list ap)
-{
- // - Format the supplied data, and pass it to the
- // actual log_message function
- // The log level is included as a hint for loggers capable of representing
- // different log levels in some way.
- char buf1[4096];
- vsnprintf(buf1, sizeof(buf1)-1, format, ap);
- buf1[sizeof(buf1)-1] = 0;
- 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
-Logger::registerLogger() {
- if (!registered) {
- registered = true;
- m_next = loggers;
- loggers=this;
- }
-}
-
-Logger*
-Logger::getLogger(const char* name) {
- Logger* current = loggers;
- while (current) {
- if (strcasecmp(name, current->m_name) == 0) return current;
- current = current->m_next;
- }
- return nullptr;
-}
-
-void
-Logger::listLoggers() {
- Logger* current = loggers;
- while (current) {
- printf(" %s\n", current->m_name);
- current = current->m_next;
- }
-}
-
-
diff --git a/common/rfb/Logger.h b/common/rfb/Logger.h
deleted file mode 100644
index 76f03535..00000000
--- a/common/rfb/Logger.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- Logger.h - The Logger class.
-
-#ifndef __RFB_LOGGER_H__
-#define __RFB_LOGGER_H__
-
-#include <stdarg.h>
-#include <stdio.h>
-
-// Each log writer instance has a unique textual name,
-// and is attached to a particular Logger instance and
-// is assigned a particular log level.
-
-namespace rfb {
-
- class Logger {
- public:
-
- // -=- Create / Destroy a logger
-
- Logger(const char* name);
- virtual ~Logger();
-
- // -=- Get the name of a logger
-
- const char *getName() {return m_name;}
-
- // -=- Write data to a log
-
- virtual void write(int level, const char *logname, const char *text) = 0;
- void write(int level, const char *logname, const char* format, va_list ap)
- __attribute__((__format__ (__printf__, 4, 0)));
-
- // -=- Register a logger
-
- void registerLogger();
-
- // -=- CLASS FIELDS & FUNCTIONS
-
- static Logger* loggers;
-
- static Logger* getLogger(const char* name);
-
- static void listLoggers();
-
- private:
- bool registered;
- const char *m_name;
- Logger *m_next;
- };
-
-};
-
-#endif // __RFB_LOGGER_H__
diff --git a/common/rfb/Logger_file.cxx b/common/rfb/Logger_file.cxx
deleted file mode 100644
index eabe420a..00000000
--- a/common/rfb/Logger_file.cxx
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- Logger_file.cxx - Logger instance for a file
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <os/Mutex.h>
-
-#include <rfb/Logger_file.h>
-
-using namespace rfb;
-
-Logger_File::Logger_File(const char* loggerName)
- : Logger(loggerName), indent(13), width(79), m_file(nullptr),
- m_lastLogTime(0)
-{
- m_filename[0] = '\0';
- mutex = new os::Mutex();
-}
-
-Logger_File::~Logger_File()
-{
- closeFile();
- delete mutex;
-}
-
-void Logger_File::write(int /*level*/, const char *logname, const char *message)
-{
- os::AutoMutex a(mutex);
-
- if (!m_file) {
- if (m_filename[0] == '\0')
- return;
- char bakFilename[PATH_MAX];
- if (snprintf(bakFilename, sizeof(bakFilename),
- "%s.bak", m_filename) >= (int)sizeof(bakFilename)) {
- remove(m_filename);
- } else {
- remove(bakFilename);
- rename(m_filename, bakFilename);
- }
- m_file = fopen(m_filename, "w+");
- if (!m_file) return;
- }
-
- time_t current = time(nullptr);
- if (current != m_lastLogTime) {
- m_lastLogTime = current;
- fprintf(m_file, "\n%s", ctime(&m_lastLogTime));
- }
-
- fprintf(m_file," %s:", logname);
- int column = strlen(logname) + 2;
- if (column < indent) {
- fprintf(m_file,"%*s",indent-column,"");
- column = indent;
- }
- while (true) {
- const char* s = strchr(message, ' ');
- int wordLen;
- if (s) wordLen = s-message;
- else wordLen = strlen(message);
-
- if (column + wordLen + 1 > width) {
- fprintf(m_file,"\n%*s",indent,"");
- column = indent;
- }
- fprintf(m_file," %.*s",wordLen,message);
- column += wordLen + 1;
- message += wordLen + 1;
- if (!s) break;
- }
- fprintf(m_file,"\n");
- fflush(m_file);
-}
-
-void Logger_File::setFilename(const char* filename)
-{
- closeFile();
- m_filename[0] = '\0';
- if (strlen(filename) >= sizeof(m_filename))
- return;
- strcpy(m_filename, filename);
-}
-
-void Logger_File::setFile(FILE* file)
-{
- closeFile();
- m_file = file;
-}
-
-void Logger_File::closeFile()
-{
- if (m_file) {
- fclose(m_file);
- m_file = nullptr;
- }
-}
-
-static Logger_File logger("file");
-
-bool rfb::initFileLogger(const char* filename) {
- logger.setFilename(filename);
- logger.registerLogger();
- return true;
-}
diff --git a/common/rfb/Logger_file.h b/common/rfb/Logger_file.h
deleted file mode 100644
index 6f2a4ef6..00000000
--- a/common/rfb/Logger_file.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- Logger_file - log to a file
-
-#ifndef __RFB_LOGGER_FILE_H__
-#define __RFB_LOGGER_FILE_H__
-
-#include <time.h>
-#include <limits.h>
-
-#include <rfb/Logger.h>
-
-namespace os { class Mutex; }
-
-namespace rfb {
-
- class Logger_File : public Logger {
- public:
- Logger_File(const char* loggerName);
- ~Logger_File();
-
- void write(int level, const char *logname, const char *message) override;
- void setFilename(const char* filename);
- void setFile(FILE* file);
-
- int indent;
- int width;
-
- protected:
- void closeFile();
- char m_filename[PATH_MAX];
- FILE* m_file;
- time_t m_lastLogTime;
- os::Mutex* mutex;
- };
-
- bool initFileLogger(const char* filename);
-};
-
-#endif
diff --git a/common/rfb/Logger_stdio.cxx b/common/rfb/Logger_stdio.cxx
deleted file mode 100644
index 5e5c6dea..00000000
--- a/common/rfb/Logger_stdio.cxx
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- Logger_stdio.cxx - Logger instances for stderr and stdout
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <rfb/Logger_stdio.h>
-
-using namespace rfb;
-
-static Logger_StdIO logStdErr("stderr", stderr);
-static Logger_StdIO logStdOut("stdout", stdout);
-
-bool rfb::initStdIOLoggers() {
- logStdErr.registerLogger();
- logStdOut.registerLogger();
- return true;
-}
diff --git a/common/rfb/Logger_stdio.h b/common/rfb/Logger_stdio.h
deleted file mode 100644
index a1d17a0f..00000000
--- a/common/rfb/Logger_stdio.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// -=- Logger_stdio - standard output logger instances
-
-#ifndef __RFB_LOGGER_STDIO_H__
-#define __RFB_LOGGER_STDIO_H__
-
-#include <rfb/Logger_file.h>
-
-namespace rfb {
-
- class Logger_StdIO : public Logger_File {
- public:
- Logger_StdIO(const char *name, FILE* file) : Logger_File(name) {
- setFile(file);
- }
- };
-
- bool initStdIOLoggers();
-
-};
-
-#endif
diff --git a/common/rfb/Logger_syslog.cxx b/common/rfb/Logger_syslog.cxx
deleted file mode 100644
index de9e425e..00000000
--- a/common/rfb/Logger_syslog.cxx
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (C) 2015 TigerVNC
- *
- * 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.
- */
-
-// -=- Logger_syslog.cxx - Logger instance for a syslog
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-
-#include <rfb/Logger_syslog.h>
-#include <rfb/LogWriter.h>
-
-using namespace rfb;
-
-
-Logger_Syslog::Logger_Syslog(const char* loggerName)
- : Logger(loggerName)
-{
- openlog(nullptr, LOG_CONS | LOG_PID, LOG_USER);
-}
-
-Logger_Syslog::~Logger_Syslog()
-{
- closelog();
-}
-
-void Logger_Syslog::write(int level, const char *logname, const char *message)
-{
- // Convert our priority level into syslog level
- int priority;
- if (level >= LogWriter::LEVEL_DEBUG) {
- priority = LOG_DEBUG;
- } else if (level >= LogWriter::LEVEL_INFO) {
- priority = LOG_INFO;
- } else if (level >= LogWriter::LEVEL_STATUS) {
- priority = LOG_NOTICE;
- } else {
- priority = LOG_ERR;
- }
-
- syslog(priority, "%s: %s", logname, message);
-}
-
-static Logger_Syslog logger("syslog");
-
-void rfb::initSyslogLogger() {
- logger.registerLogger();
-}
diff --git a/common/rfb/Logger_syslog.h b/common/rfb/Logger_syslog.h
deleted file mode 100644
index 20c46a5f..00000000
--- a/common/rfb/Logger_syslog.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (C) 2015 TigerVNC
- *
- * 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.
- */
-
-// -=- Logger_syslog - log to syslog
-
-#ifndef __RFB_LOGGER_SYSLOG_H__
-#define __RFB_LOGGER_SYSLOG_H__
-
-#include <time.h>
-#include <rfb/Logger.h>
-
-namespace rfb {
-
- class Logger_Syslog : public Logger {
- public:
- Logger_Syslog(const char* loggerName);
- virtual ~Logger_Syslog();
-
- void write(int level, const char *logname, const char *message) override;
- };
-
- void initSyslogLogger();
-};
-
-#endif
diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx
index 5590c214..32b0ce2f 100644
--- a/common/rfb/PixelBuffer.cxx
+++ b/common/rfb/PixelBuffer.cxx
@@ -30,13 +30,14 @@
#include <stdexcept>
-#include <rfb/LogWriter.h>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rfb/PixelBuffer.h>
-#include <rfb/util.h>
using namespace rfb;
-static LogWriter vlog("PixelBuffer");
+static core::LogWriter vlog("PixelBuffer");
// We do a lot of byte offset calculations that assume the result fits
// inside a signed 32 bit integer. Limit the maximum size of pixel
@@ -63,7 +64,8 @@ PixelBuffer::~PixelBuffer() {}
void
-PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const
+PixelBuffer::getImage(void* imageBuf, const core::Rect& r,
+ int outStride) const
{
int inStride;
const uint8_t* data;
@@ -72,10 +74,9 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const
const uint8_t* end;
if (!r.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
- r.width(), r.height(),
- r.tl.x, r.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
+ r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));
data = getBuffer(r, &inStride);
@@ -98,7 +99,7 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const
}
void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,
- const Rect& r, int stride) const
+ const core::Rect& r, int stride) const
{
const uint8_t* srcBuffer;
int srcStride;
@@ -109,10 +110,9 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,
}
if (!r.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
- r.width(), r.height(),
- r.tl.x, r.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
+ r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));
if (stride == 0)
stride = r.width();
@@ -126,9 +126,11 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,
void PixelBuffer::setSize(int width, int height)
{
if ((width < 0) || (width > maxPixelBufferWidth))
- throw std::out_of_range(rfb::format("Invalid PixelBuffer width of %d pixels requested", width));
+ throw std::out_of_range(core::format(
+ "Invalid PixelBuffer width of %d pixels requested", width));
if ((height < 0) || (height > maxPixelBufferHeight))
- throw std::out_of_range(rfb::format("Invalid PixelBuffer height of %d pixels requested", height));
+ throw std::out_of_range(core::format(
+ "Invalid PixelBuffer height of %d pixels requested", height));
width_ = width;
height_ = height;
@@ -150,17 +152,17 @@ ModifiablePixelBuffer::~ModifiablePixelBuffer()
{
}
-void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix)
+void ModifiablePixelBuffer::fillRect(const core::Rect& r,
+ const void* pix)
{
int stride;
uint8_t *buf;
int w, h, b;
if (!r.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
- r.width(), r.height(),
- r.tl.x, r.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
+ r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));
w = r.width();
h = r.height();
@@ -199,7 +201,7 @@ void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix)
commitBufferRW(r);
}
-void ModifiablePixelBuffer::imageRect(const Rect& r,
+void ModifiablePixelBuffer::imageRect(const core::Rect& r,
const void* pixels, int srcStride)
{
uint8_t* dest;
@@ -209,10 +211,9 @@ void ModifiablePixelBuffer::imageRect(const Rect& r,
uint8_t* end;
if (!r.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
- r.width(), r.height(),
- r.tl.x, r.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
+ r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));
bytesPerPixel = getPF().bpp/8;
@@ -237,29 +238,29 @@ void ModifiablePixelBuffer::imageRect(const Rect& r,
commitBufferRW(r);
}
-void ModifiablePixelBuffer::copyRect(const Rect &rect,
- const Point &move_by_delta)
+void ModifiablePixelBuffer::copyRect(const core::Rect& rect,
+ const core::Point& move_by_delta)
{
int srcStride, dstStride;
int bytesPerPixel;
const uint8_t* srcData;
uint8_t* dstData;
- Rect drect, srect;
+ core::Rect drect, srect;
drect = rect;
if (!drect.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
- drect.width(), drect.height(),
- drect.tl.x, drect.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
+ drect.width(), drect.height(), drect.tl.x, drect.tl.y,
+ width(), height()));
srect = drect.translate(move_by_delta.negate());
if (!srect.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
- srect.width(), srect.height(),
- srect.tl.x, srect.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
+ srect.width(), srect.height(), srect.tl.x, srect.tl.y,
+ width(), height()));
bytesPerPixel = format.bpp/8;
@@ -297,7 +298,8 @@ void ModifiablePixelBuffer::copyRect(const Rect &rect,
commitBufferRW(drect);
}
-void ModifiablePixelBuffer::fillRect(const PixelFormat& pf, const Rect &dest,
+void ModifiablePixelBuffer::fillRect(const PixelFormat& pf,
+ const core::Rect& dest,
const void* pix)
{
uint8_t buf[4];
@@ -305,17 +307,18 @@ void ModifiablePixelBuffer::fillRect(const PixelFormat& pf, const Rect &dest,
fillRect(dest, buf);
}
-void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest,
+void ModifiablePixelBuffer::imageRect(const PixelFormat& pf,
+ const core::Rect& dest,
const void* pixels, int stride)
{
uint8_t* dstBuffer;
int dstStride;
if (!dest.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
- dest.width(), dest.height(),
- dest.tl.x, dest.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
+ dest.width(), dest.height(), dest.tl.x, dest.tl.y,
+ width(), height()));
if (stride == 0)
stride = dest.width();
@@ -339,29 +342,29 @@ FullFramePixelBuffer::FullFramePixelBuffer() : data(nullptr) {}
FullFramePixelBuffer::~FullFramePixelBuffer() {}
-uint8_t* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_)
+uint8_t* FullFramePixelBuffer::getBufferRW(const core::Rect& r,
+ int* stride_)
{
if (!r.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
- r.width(), r.height(),
- r.tl.x, r.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
+ r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));
*stride_ = stride;
return &data[(r.tl.x + (r.tl.y * stride)) * (format.bpp/8)];
}
-void FullFramePixelBuffer::commitBufferRW(const Rect& /*r*/)
+void FullFramePixelBuffer::commitBufferRW(const core::Rect& /*r*/)
{
}
-const uint8_t* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) const
+const uint8_t* FullFramePixelBuffer::getBuffer(const core::Rect& r,
+ int* stride_) const
{
if (!r.enclosed_by(getRect()))
- throw std::out_of_range(rfb::format("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
- r.width(), r.height(),
- r.tl.x, r.tl.y,
- width(), height()));
+ throw std::out_of_range(core::format(
+ "Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
+ r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));
*stride_ = stride;
return &data[(r.tl.x + (r.tl.y * stride)) * (format.bpp/8)];
@@ -371,13 +374,17 @@ void FullFramePixelBuffer::setBuffer(int width, int height,
uint8_t* data_, int stride_)
{
if ((width < 0) || (width > maxPixelBufferWidth))
- throw std::out_of_range(rfb::format("Invalid PixelBuffer width of %d pixels requested", width));
+ throw std::out_of_range(core::format(
+ "Invalid PixelBuffer width of %d pixels requested", width));
if ((height < 0) || (height > maxPixelBufferHeight))
- throw std::out_of_range(rfb::format("Invalid PixelBuffer height of %d pixels requested", height));
+ throw std::out_of_range(core::format(
+ "Invalid PixelBuffer height of %d pixels requested", height));
if ((stride_ < 0) || (stride_ > maxPixelBufferStride) || (stride_ < width))
- throw std::invalid_argument(rfb::format("Invalid PixelBuffer stride of %d pixels requested", stride_));
+ throw std::invalid_argument(core::format(
+ "Invalid PixelBuffer stride of %d pixels requested", stride_));
if ((width != 0) && (height != 0) && (data_ == nullptr))
- throw std::logic_error(rfb::format("PixelBuffer requested without a valid memory area"));
+ throw std::logic_error(core::format(
+ "PixelBuffer requested without a valid memory area"));
ModifiablePixelBuffer::setSize(width, height);
stride = stride_;
diff --git a/common/rfb/PixelBuffer.h b/common/rfb/PixelBuffer.h
index 963fbbf6..9fbea611 100644
--- a/common/rfb/PixelBuffer.h
+++ b/common/rfb/PixelBuffer.h
@@ -25,12 +25,13 @@
#ifndef __RFB_PIXEL_BUFFER_H__
#define __RFB_PIXEL_BUFFER_H__
+#include <core/Rect.h>
+
#include <rfb/PixelFormat.h>
-#include <rfb/Rect.h>
-namespace rfb {
+namespace core { class Region; }
- class Region;
+namespace rfb {
class PixelBuffer {
public:
@@ -52,9 +53,9 @@ namespace rfb {
// Get rectangle encompassing this buffer
// Top-left of rectangle is either at (0,0), or the specified point.
- Rect getRect() const { return Rect(0, 0, width_, height_); }
- Rect getRect(const Point& pos) const {
- return Rect(pos, pos.translate(Point(width_, height_)));
+ core::Rect getRect() const { return {0, 0, width_, height_}; }
+ core::Rect getRect(const core::Point& pos) const {
+ return {pos, pos.translate({width_, height_})};
}
///////////////////////////////////////////////
@@ -64,18 +65,20 @@ namespace rfb {
// Get a pointer into the buffer
// The pointer is to the top-left pixel of the specified Rect.
// The buffer stride (in pixels) is returned.
- virtual const uint8_t* getBuffer(const Rect& r, int* stride) const = 0;
+ virtual const uint8_t* getBuffer(const core::Rect& r,
+ int* stride) const = 0;
// Get pixel data for a given part of the buffer
// Data is copied into the supplied buffer, with the specified
// stride. Try to avoid using this though as getBuffer() will in
// most cases avoid the extra memory copy.
- void getImage(void* imageBuf, const Rect& r, int stride=0) const;
+ void getImage(void* imageBuf, const core::Rect& r,
+ int stride=0) const;
// Get pixel data in a given format
// Works just the same as getImage(), but guaranteed to be in a
// specific format.
void getImage(const PixelFormat& pf, void* imageBuf,
- const Rect& r, int stride=0) const;
+ const core::Rect& r, int stride=0) const;
///////////////////////////////////////////////
// Framebuffer update methods
@@ -84,7 +87,7 @@ namespace rfb {
// Ensure that the specified rectangle of buffer is up to date.
// Overridden by derived classes implementing framebuffer access
// to copy the required display data into place.
- virtual void grabRegion(const Region& /*region*/) {}
+ virtual void grabRegion(const core::Region& /*region*/) {}
protected:
PixelBuffer();
@@ -110,32 +113,35 @@ namespace rfb {
// Get a writeable pointer into the buffer
// Like getBuffer(), the pointer is to the top-left pixel of the
// specified Rect and the stride in pixels is returned.
- virtual uint8_t* getBufferRW(const Rect& r, int* stride) = 0;
+ virtual uint8_t* getBufferRW(const core::Rect& r, int* stride) = 0;
// Commit the modified contents
// Ensures that the changes to the specified Rect is properly
// stored away and any temporary buffers are freed. The Rect given
// here needs to match the Rect given to the earlier call to
// getBufferRW().
- virtual void commitBufferRW(const Rect& r) = 0;
+ virtual void commitBufferRW(const core::Rect& r) = 0;
///////////////////////////////////////////////
// Basic rendering operations
// These operations DO NOT clip to the pixelbuffer area, or trap overruns.
// Fill a rectangle
- void fillRect(const Rect &dest, const void* pix);
+ void fillRect(const core::Rect& dest, const void* pix);
// Copy pixel data to the buffer
- void imageRect(const Rect &dest, const void* pixels, int stride=0);
+ void imageRect(const core::Rect& dest, const void* pixels,
+ int stride=0);
// Copy pixel data from one PixelBuffer location to another
- void copyRect(const Rect &dest, const Point& move_by_delta);
+ void copyRect(const core::Rect& dest,
+ const core::Point& move_by_delta);
// Render in a specific format
// Does the exact same thing as the above methods, but the given
// pixel values are defined by the given PixelFormat.
- void fillRect(const PixelFormat& pf, const Rect &dest, const void* pix);
- void imageRect(const PixelFormat& pf, const Rect &dest,
+ void fillRect(const PixelFormat& pf, const core::Rect& dest,
+ const void* pix);
+ void imageRect(const PixelFormat& pf, const core::Rect& dest,
const void* pixels, int stride=0);
protected:
@@ -151,9 +157,10 @@ namespace rfb {
virtual ~FullFramePixelBuffer();
public:
- const uint8_t* getBuffer(const Rect& r, int* stride) const override;
- uint8_t* getBufferRW(const Rect& r, int* stride) override;
- void commitBufferRW(const Rect& r) override;
+ const uint8_t* getBuffer(const core::Rect& r,
+ int* stride) const override;
+ uint8_t* getBufferRW(const core::Rect& r, int* stride) override;
+ void commitBufferRW(const core::Rect& r) override;
protected:
FullFramePixelBuffer();
diff --git a/common/rfb/PixelFormat.h b/common/rfb/PixelFormat.h
index f0a16767..7b754da8 100644
--- a/common/rfb/PixelFormat.h
+++ b/common/rfb/PixelFormat.h
@@ -136,7 +136,7 @@ namespace rfb {
/* Only for testing this class */
friend void makePixel(const rfb::PixelFormat &, uint8_t *);
- friend bool verifyPixel(const rfb::PixelFormat &,
+ friend void verifyPixel(const rfb::PixelFormat &,
const rfb::PixelFormat &,
const uint8_t *);
};
diff --git a/common/rfb/RREDecoder.cxx b/common/rfb/RREDecoder.cxx
index 53ddc2da..d2c3d3e6 100644
--- a/common/rfb/RREDecoder.cxx
+++ b/common/rfb/RREDecoder.cxx
@@ -40,7 +40,7 @@ RREDecoder::~RREDecoder()
{
}
-bool RREDecoder::readRect(const Rect& /*r*/, rdr::InStream* is,
+bool RREDecoder::readRect(const core::Rect& /*r*/, rdr::InStream* is,
const ServerParams& server, rdr::OutStream* os)
{
uint32_t numRects;
@@ -66,7 +66,7 @@ bool RREDecoder::readRect(const Rect& /*r*/, rdr::InStream* is,
return true;
}
-void RREDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
+void RREDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
@@ -91,7 +91,7 @@ inline T RREDecoder::readPixel(rdr::InStream* is)
}
template<class T>
-void RREDecoder::rreDecode(const Rect& r, rdr::InStream* is,
+void RREDecoder::rreDecode(const core::Rect& r, rdr::InStream* is,
const PixelFormat& pf,
ModifiablePixelBuffer* pb)
{
@@ -109,6 +109,6 @@ void RREDecoder::rreDecode(const Rect& r, rdr::InStream* is,
if (((x+w) > r.width()) || ((y+h) > r.height()))
throw protocol_error("RRE decode error");
- pb->fillRect(pf, Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), &pix);
+ pb->fillRect(pf, {r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h}, &pix);
}
}
diff --git a/common/rfb/RREDecoder.h b/common/rfb/RREDecoder.h
index 8490146c..3fdcdd85 100644
--- a/common/rfb/RREDecoder.h
+++ b/common/rfb/RREDecoder.h
@@ -29,17 +29,17 @@ namespace rfb {
public:
RREDecoder();
virtual ~RREDecoder();
- bool readRect(const Rect& r, rdr::InStream* is,
+ bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server,
rdr::OutStream* os) override;
- void decodeRect(const Rect& r, const uint8_t* buffer,
+ void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb) override;
private:
template<class T>
inline T readPixel(rdr::InStream* is);
template<class T>
- void rreDecode(const Rect& r, rdr::InStream* is,
+ void rreDecode(const core::Rect& r, rdr::InStream* is,
const PixelFormat& pf, ModifiablePixelBuffer* pb);
};
}
diff --git a/common/rfb/RawDecoder.cxx b/common/rfb/RawDecoder.cxx
index f2ea586b..43ce15a4 100644
--- a/common/rfb/RawDecoder.cxx
+++ b/common/rfb/RawDecoder.cxx
@@ -37,7 +37,7 @@ RawDecoder::~RawDecoder()
{
}
-bool RawDecoder::readRect(const Rect& r, rdr::InStream* is,
+bool RawDecoder::readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server, rdr::OutStream* os)
{
if (!is->hasData(r.area() * (server.pf().bpp/8)))
@@ -46,7 +46,7 @@ bool RawDecoder::readRect(const Rect& r, rdr::InStream* is,
return true;
}
-void RawDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
+void RawDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
diff --git a/common/rfb/RawDecoder.h b/common/rfb/RawDecoder.h
index 2ac8b0bd..6c3a6357 100644
--- a/common/rfb/RawDecoder.h
+++ b/common/rfb/RawDecoder.h
@@ -25,10 +25,10 @@ namespace rfb {
public:
RawDecoder();
virtual ~RawDecoder();
- bool readRect(const Rect& r, rdr::InStream* is,
+ bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server,
rdr::OutStream* os) override;
- void decodeRect(const Rect& r, const uint8_t* buffer,
+ void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb) override;
};
diff --git a/common/rfb/Rect.h b/common/rfb/Rect.h
deleted file mode 100644
index b82ed274..00000000
--- a/common/rfb/Rect.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// rfb::Rect and rfb::Point structures
-
-#ifndef __RFB_RECT_INCLUDED__
-#define __RFB_RECT_INCLUDED__
-
-// Some platforms (e.g. Windows) include max() and min() macros in their
-// standard headers, but they are also standard C++ template functions, so some
-// C++ headers will undefine them. So we steer clear of the names min and max
-// and define __rfbmin and __rfbmax instead.
-
-#ifndef __rfbmax
-#define __rfbmax(a,b) (((a) > (b)) ? (a) : (b))
-#endif
-#ifndef __rfbmin
-#define __rfbmin(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-namespace rfb {
-
- // rfb::Point
- //
- // Represents a point in 2D space, by X and Y coordinates.
- // Can also be used to represent a delta, or offset, between
- // two Points.
- // Functions are provided to allow Points to be compared for
- // equality and translated by a supplied offset.
- // Functions are also provided to negate offset Points.
-
- struct Point {
- Point() : x(0), y(0) {}
- Point(int x_, int y_) : x(x_), y(y_) {}
- inline Point negate() const
- __attribute__ ((warn_unused_result))
- {return Point(-x, -y);}
- inline bool operator==(const Point &p) const {return x==p.x && y==p.y;}
- inline bool operator!=(const Point &p) const {return x!=p.x || y!=p.y;}
- inline Point translate(const Point &p) const
- __attribute__ ((warn_unused_result))
- {return Point(x+p.x, y+p.y);}
- inline Point subtract(const Point &p) const
- __attribute__ ((warn_unused_result))
- {return Point(x-p.x, y-p.y);}
- int x, y;
- };
-
- // rfb::Rect
- //
- // Represents a rectangular region defined by its top-left (tl)
- // and bottom-right (br) Points.
- // Rects may be compared for equality, checked to determine whether
- // or not they are empty, cleared (made empty), or intersected with
- // one another. The bounding rectangle of two existing Rects
- // may be calculated, as may the area of a Rect.
- // Rects may also be translated, in the same way as Points, by
- // an offset specified in a Point structure.
-
- struct Rect {
- Rect() {}
- Rect(Point tl_, Point br_) : tl(tl_), br(br_) {}
- Rect(int x1, int y1, int x2, int y2) : tl(x1, y1), br(x2, y2) {}
- inline void setXYWH(int x, int y, int w, int h) {
- tl.x = x; tl.y = y; br.x = x+w; br.y = y+h;
- }
- inline Rect intersect(const Rect &r) const
- __attribute__ ((warn_unused_result))
- {
- Rect result;
- result.tl.x = __rfbmax(tl.x, r.tl.x);
- result.tl.y = __rfbmax(tl.y, r.tl.y);
- result.br.x = __rfbmax(__rfbmin(br.x, r.br.x), result.tl.x);
- result.br.y = __rfbmax(__rfbmin(br.y, r.br.y), result.tl.y);
- return result;
- }
- inline Rect union_boundary(const Rect &r) const
- __attribute__ ((warn_unused_result))
- {
- if (r.is_empty()) return *this;
- if (is_empty()) return r;
- Rect result;
- result.tl.x = __rfbmin(tl.x, r.tl.x);
- result.tl.y = __rfbmin(tl.y, r.tl.y);
- result.br.x = __rfbmax(br.x, r.br.x);
- result.br.y = __rfbmax(br.y, r.br.y);
- return result;
- }
- inline Rect translate(const Point &p) const
- __attribute__ ((warn_unused_result))
- {
- return Rect(tl.translate(p), br.translate(p));
- }
- inline bool operator==(const Rect &r) const {return r.tl == tl && r.br == br;}
- inline bool operator!=(const Rect &r) const {return r.tl != tl || r.br != br;}
- inline bool is_empty() const {return (tl.x >= br.x) || (tl.y >= br.y);}
- inline void clear() {tl = Point(); br = Point();}
- inline bool enclosed_by(const Rect &r) const {
- return (tl.x>=r.tl.x) && (tl.y>=r.tl.y) && (br.x<=r.br.x) && (br.y<=r.br.y);
- }
- inline bool overlaps(const Rect &r) const {
- return tl.x < r.br.x && tl.y < r.br.y && br.x > r.tl.x && br.y > r.tl.y;
- }
- inline int area() const {return is_empty() ? 0 : (br.x-tl.x)*(br.y-tl.y);}
- inline Point dimensions() const {return Point(width(), height());}
- inline int width() const {return br.x-tl.x;}
- inline int height() const {return br.y-tl.y;}
- inline bool contains(const Point &p) const {
- return (tl.x<=p.x) && (tl.y<=p.y) && (br.x>p.x) && (br.y>p.y);
- }
- Point tl;
- Point br;
- };
-}
-#endif // __RFB_RECT_INCLUDED__
diff --git a/common/rfb/Region.cxx b/common/rfb/Region.cxx
deleted file mode 100644
index cfdf0ca2..00000000
--- a/common/rfb/Region.cxx
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2016-2020 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <rfb/Region.h>
-#include <rfb/LogWriter.h>
-
-extern "C" {
-#include <pixman.h>
-}
-
-static rfb::LogWriter vlog("Region");
-
-rfb::Region::Region() {
- rgn = new struct pixman_region16;
- pixman_region_init(rgn);
-}
-
-rfb::Region::Region(const Rect& r) {
- rgn = new struct pixman_region16;
- pixman_region_init_rect(rgn, r.tl.x, r.tl.y, r.width(), r.height());
-}
-
-rfb::Region::Region(const rfb::Region& r) {
- rgn = new struct pixman_region16;
- pixman_region_init(rgn);
- pixman_region_copy(rgn, r.rgn);
-}
-
-rfb::Region::~Region() {
- pixman_region_fini(rgn);
- delete rgn;
-}
-
-rfb::Region& rfb::Region::operator=(const rfb::Region& r) {
- pixman_region_copy(rgn, r.rgn);
- return *this;
-}
-
-void rfb::Region::clear() {
- // pixman_region_clear() isn't available on some older systems
- pixman_region_fini(rgn);
- pixman_region_init(rgn);
-}
-
-void rfb::Region::reset(const Rect& r) {
- pixman_region_fini(rgn);
- pixman_region_init_rect(rgn, r.tl.x, r.tl.y, r.width(), r.height());
-}
-
-void rfb::Region::translate(const Point& delta) {
- pixman_region_translate(rgn, delta.x, delta.y);
-}
-
-void rfb::Region::assign_intersect(const rfb::Region& r) {
- pixman_region_intersect(rgn, rgn, r.rgn);
-}
-
-void rfb::Region::assign_union(const rfb::Region& r) {
- pixman_region_union(rgn, rgn, r.rgn);
-}
-
-void rfb::Region::assign_subtract(const rfb::Region& r) {
- pixman_region_subtract(rgn, rgn, r.rgn);
-}
-
-rfb::Region rfb::Region::intersect(const rfb::Region& r) const {
- rfb::Region ret;
- pixman_region_intersect(ret.rgn, rgn, r.rgn);
- return ret;
-}
-
-rfb::Region rfb::Region::union_(const rfb::Region& r) const {
- rfb::Region ret;
- pixman_region_union(ret.rgn, rgn, r.rgn);
- return ret;
-}
-
-rfb::Region rfb::Region::subtract(const rfb::Region& r) const {
- rfb::Region ret;
- pixman_region_subtract(ret.rgn, rgn, r.rgn);
- return ret;
-}
-
-bool rfb::Region::operator==(const rfb::Region& r) const {
- return pixman_region_equal(rgn, r.rgn);
-}
-
-bool rfb::Region::operator!=(const rfb::Region& r) const {
- return !pixman_region_equal(rgn, r.rgn);
-}
-
-int rfb::Region::numRects() const {
- return pixman_region_n_rects(rgn);
-}
-
-bool rfb::Region::get_rects(std::vector<Rect>* rects,
- bool left2right, bool topdown) const
-{
- int nRects;
- const pixman_box16_t* boxes;
- int xInc, yInc, i;
-
- boxes = pixman_region_rectangles(rgn, &nRects);
-
- rects->clear();
- rects->reserve(nRects);
-
- xInc = left2right ? 1 : -1;
- yInc = topdown ? 1 : -1;
- i = topdown ? 0 : nRects-1;
-
- while (nRects > 0) {
- int firstInNextBand = i;
- int nRectsInBand = 0;
-
- while (nRects > 0 && boxes[firstInNextBand].y1 == boxes[i].y1)
- {
- firstInNextBand += yInc;
- nRects--;
- nRectsInBand++;
- }
-
- if (xInc != yInc)
- i = firstInNextBand - yInc;
-
- while (nRectsInBand > 0) {
- Rect r(boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);
- rects->push_back(r);
- i += xInc;
- nRectsInBand--;
- }
-
- i = firstInNextBand;
- }
-
- return !rects->empty();
-}
-
-rfb::Rect rfb::Region::get_bounding_rect() const {
- const pixman_box16_t* extents;
- extents = pixman_region_extents(rgn);
- return Rect(extents->x1, extents->y1, extents->x2, extents->y2);
-}
-
-
-void rfb::Region::debug_print(const char* prefix) const
-{
- Rect extents;
- std::vector<Rect> rects;
- std::vector<Rect>::const_iterator iter;
-
- extents = get_bounding_rect();
- get_rects(&rects);
-
- vlog.debug("%s num rects %3ld extents %3d,%3d %3dx%3d",
- prefix, (long)rects.size(), extents.tl.x, extents.tl.y,
- extents.width(), extents.height());
-
- for (iter = rects.begin(); iter != rects.end(); ++iter) {
- vlog.debug(" rect %3d,%3d %3dx%3d",
- iter->tl.x, iter->tl.y, iter->width(), iter->height());
- }
-}
diff --git a/common/rfb/Region.h b/common/rfb/Region.h
deleted file mode 100644
index 38de67ce..00000000
--- a/common/rfb/Region.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2016-2020 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.
- */
-
-// Region class wrapper around pixman's region operations
-
-#ifndef __RFB_REGION_INCLUDED__
-#define __RFB_REGION_INCLUDED__
-
-#include <rfb/Rect.h>
-#include <vector>
-
-struct pixman_region16;
-
-namespace rfb {
-
- class Region {
- public:
- // Create an empty region
- Region();
- // Create a rectangular region
- Region(const Rect& r);
-
- Region(const Region& r);
- Region &operator=(const Region& src);
-
- ~Region();
-
- // the following methods alter the region in place:
-
- void clear();
- void reset(const Rect& r);
- void translate(const rfb::Point& delta);
-
- void assign_intersect(const Region& r);
- void assign_union(const Region& r);
- void assign_subtract(const Region& r);
-
- // the following three operations return a new region:
-
- Region intersect(const Region& r) const
- __attribute__ ((warn_unused_result));
- Region union_(const Region& r) const
- __attribute__ ((warn_unused_result));
- Region subtract(const Region& r) const
- __attribute__ ((warn_unused_result));
-
- bool operator==(const Region& b) const;
- bool operator!=(const Region& b) const;
- int numRects() const;
- bool is_empty() const { return numRects() == 0; }
-
- bool get_rects(std::vector<Rect>* rects, bool left2right=true,
- bool topdown=true) const;
- Rect get_bounding_rect() const;
-
- void debug_print(const char *prefix) const;
-
- protected:
-
- struct pixman_region16* rgn;
- };
-
-};
-
-#endif // __RFB_REGION_INCLUDED__
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
index a0a1c373..c698b991 100644
--- a/common/rfb/SConnection.cxx
+++ b/common/rfb/SConnection.cxx
@@ -26,6 +26,11 @@
#include <algorithm>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
+#include <rdr/OutStream.h>
+
#include <rfb/Exception.h>
#include <rfb/Security.h>
#include <rfb/clipboardTypes.h>
@@ -38,13 +43,10 @@
#include <rfb/encodings.h>
#include <rfb/EncodeManager.h>
#include <rfb/SSecurity.h>
-#include <rfb/util.h>
-
-#include <rfb/LogWriter.h>
using namespace rfb;
-static LogWriter vlog("SConnection");
+static core::LogWriter vlog("SConnection");
SConnection::SConnection(AccessRights accessRights_)
: readyForSetColourMapEntries(false), is(nullptr), os(nullptr),
@@ -133,10 +135,10 @@ bool SConnection::processVersionMsg()
if (client.majorVersion != 3) {
// unknown protocol version
- failConnection(format("Client needs protocol version %d.%d, "
- "server has %d.%d",
- client.majorVersion, client.minorVersion,
- defaultMajorVersion, defaultMinorVersion));
+ failConnection(core::format(
+ "Client needs protocol version %d.%d, server has %d.%d",
+ client.majorVersion, client.minorVersion,
+ defaultMajorVersion, defaultMinorVersion));
}
if (client.minorVersion != 3 && client.minorVersion != 7 && client.minorVersion != 8) {
@@ -152,8 +154,6 @@ bool SConnection::processVersionMsg()
client.majorVersion,client.minorVersion);
}
- versionReceived();
-
std::list<uint8_t> secTypes;
std::list<uint8_t>::iterator i;
secTypes = security.GetEnabledSecTypes();
@@ -166,9 +166,9 @@ bool SConnection::processVersionMsg()
if (*i == secTypeNone || *i == secTypeVncAuth) break;
}
if (i == secTypes.end()) {
- failConnection(format("No supported security type for "
- "%d.%d client",
- client.majorVersion, client.minorVersion));
+ failConnection(
+ core::format("No supported security type for %d.%d client",
+ client.majorVersion, client.minorVersion));
}
os->writeU32(*i);
@@ -278,7 +278,7 @@ bool SConnection::processInitMsg()
return reader_->readClientInit();
}
-void SConnection::handleAuthFailureTimeout(Timer* /*t*/)
+void SConnection::handleAuthFailureTimeout(core::Timer* /*t*/)
{
if (state_ != RFBSTATE_SECURITY_FAILURE) {
close("SConnection::handleAuthFailureTimeout: Invalid state");
@@ -344,6 +344,8 @@ bool SConnection::accessCheck(AccessRights ar) const
void SConnection::setEncodings(int nEncodings, const int32_t* encodings)
{
int i;
+ bool firstFence, firstContinuousUpdates, firstLEDState,
+ firstQEMUKeyEvent, firstExtMouseButtonsEvent;
preferredEncoding = encodingRaw;
for (i = 0;i < nEncodings;i++) {
@@ -353,7 +355,26 @@ void SConnection::setEncodings(int nEncodings, const int32_t* encodings)
}
}
- SMsgHandler::setEncodings(nEncodings, encodings);
+ firstFence = !client.supportsFence();
+ firstContinuousUpdates = !client.supportsContinuousUpdates();
+ firstLEDState = !client.supportsLEDState();
+ firstQEMUKeyEvent = !client.supportsEncoding(pseudoEncodingQEMUKeyEvent);
+ firstExtMouseButtonsEvent = !client.supportsEncoding(pseudoEncodingExtendedMouseButtons);
+
+ client.setEncodings(nEncodings, encodings);
+
+ supportsLocalCursor();
+
+ if (client.supportsFence() && firstFence)
+ supportsFence();
+ if (client.supportsContinuousUpdates() && firstContinuousUpdates)
+ supportsContinuousUpdates();
+ if (client.supportsLEDState() && firstLEDState)
+ supportsLEDState();
+ if (client.supportsEncoding(pseudoEncodingQEMUKeyEvent) && firstQEMUKeyEvent)
+ writer()->writeQEMUKeyEvent();
+ if (client.supportsEncoding(pseudoEncodingExtendedMouseButtons) && firstExtMouseButtonsEvent)
+ writer()->writeExtendedMouseButtonsSupport();
if (client.supportsEncoding(pseudoEncodingExtendedClipboard)) {
uint32_t sizes[] = { 0 };
@@ -373,9 +394,54 @@ void SConnection::clientCutText(const char* str)
clientClipboard = str;
hasRemoteClipboard = true;
+ if (!accessCheck(AccessCutText))
+ return;
+
handleClipboardAnnounce(true);
}
+void SConnection::handleClipboardCaps(uint32_t flags, const uint32_t* lengths)
+{
+ int i;
+
+ vlog.debug("Got client clipboard capabilities:");
+ for (i = 0;i < 16;i++) {
+ if (flags & (1 << i)) {
+ const char *type;
+
+ switch (1 << i) {
+ case clipboardUTF8:
+ type = "Plain text";
+ break;
+ case clipboardRTF:
+ type = "Rich text";
+ break;
+ case clipboardHTML:
+ type = "HTML";
+ break;
+ case clipboardDIB:
+ type = "Images";
+ break;
+ case clipboardFiles:
+ type = "Files";
+ break;
+ default:
+ vlog.debug(" Unknown format 0x%x", 1 << i);
+ continue;
+ }
+
+ if (lengths[i] == 0)
+ vlog.debug(" %s (only notify)", type);
+ else {
+ vlog.debug(" %s (automatically send up to %s)",
+ type, core::iecPrefix(lengths[i], "B").c_str());
+ }
+ }
+ }
+
+ client.setClipboardCaps(flags, lengths);
+}
+
void SConnection::handleClipboardRequest(uint32_t flags)
{
if (!(flags & rfb::clipboardUTF8)) {
@@ -386,6 +452,8 @@ void SConnection::handleClipboardRequest(uint32_t flags)
vlog.debug("Ignoring unexpected clipboard request");
return;
}
+ if (!accessCheck(AccessCutText))
+ return;
handleClipboardRequest();
}
@@ -401,10 +469,15 @@ void SConnection::handleClipboardNotify(uint32_t flags)
if (flags & rfb::clipboardUTF8) {
hasLocalClipboard = false;
+ if (!accessCheck(AccessCutText))
+ return;
handleClipboardAnnounce(true);
} else {
+ if (!accessCheck(AccessCutText))
+ return;
handleClipboardAnnounce(false);
}
+
}
void SConnection::handleClipboardProvide(uint32_t flags,
@@ -417,28 +490,33 @@ void SConnection::handleClipboardProvide(uint32_t flags,
}
// FIXME: This conversion magic should be in SMsgReader
- if (!isValidUTF8((const char*)data[0], lengths[0])) {
+ if (!core::isValidUTF8((const char*)data[0], lengths[0])) {
vlog.error("Invalid UTF-8 sequence in clipboard - ignoring");
return;
}
- clientClipboard = convertLF((const char*)data[0], lengths[0]);
+ clientClipboard = core::convertLF((const char*)data[0], lengths[0]);
hasRemoteClipboard = true;
+ if (!accessCheck(AccessCutText))
+ return;
+
// FIXME: Should probably verify that this data was actually requested
handleClipboardData(clientClipboard.c_str());
}
-void SConnection::supportsQEMUKeyEvent()
+void SConnection::supportsLocalCursor()
{
- writer()->writeQEMUKeyEvent();
}
-void SConnection::supportsExtendedMouseButtons()
+void SConnection::supportsFence()
{
- writer()->writeExtendedMouseButtonsSupport();
}
-void SConnection::versionReceived()
+void SConnection::supportsContinuousUpdates()
+{
+}
+
+void SConnection::supportsLEDState()
{
}
@@ -500,13 +578,13 @@ void SConnection::close(const char* /*reason*/)
void SConnection::setPixelFormat(const PixelFormat& pf)
{
- SMsgHandler::setPixelFormat(pf);
+ client.setPF(pf);
readyForSetColourMapEntries = true;
if (!pf.trueColour)
writeFakeColourMap();
}
-void SConnection::framebufferUpdateRequest(const Rect& /*r*/,
+void SConnection::framebufferUpdateRequest(const core::Rect& /*r*/,
bool /*incremental*/)
{
if (!readyForSetColourMapEntries) {
@@ -549,6 +627,9 @@ void SConnection::handleClipboardData(const char* /*data*/)
void SConnection::requestClipboard()
{
+ if (!accessCheck(AccessCutText))
+ return;
+
if (hasRemoteClipboard) {
handleClipboardData(clientClipboard.c_str());
return;
@@ -561,6 +642,9 @@ void SConnection::requestClipboard()
void SConnection::announceClipboard(bool available)
{
+ if (!accessCheck(AccessCutText))
+ return;
+
hasLocalClipboard = available;
unsolicitedClipboardAttempt = false;
@@ -587,10 +671,13 @@ void SConnection::announceClipboard(bool available)
void SConnection::sendClipboardData(const char* data)
{
+ if (!accessCheck(AccessCutText))
+ return;
+
if (client.supportsEncoding(pseudoEncodingExtendedClipboard) &&
(client.clipboardFlags() & rfb::clipboardProvide)) {
// FIXME: This conversion magic should be in SMsgWriter
- std::string filtered(convertCRLF(data));
+ std::string filtered(core::convertCRLF(data));
size_t sizes[1] = { filtered.size() + 1 };
const uint8_t* datas[1] = { (const uint8_t*)filtered.c_str() };
diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h
index f030ae05..a90b37ca 100644
--- a/common/rfb/SConnection.h
+++ b/common/rfb/SConnection.h
@@ -26,13 +26,16 @@
#include <string>
-#include <rdr/InStream.h>
-#include <rdr/OutStream.h>
+#include <core/Timer.h>
#include <rfb/AccessRights.h>
#include <rfb/SMsgHandler.h>
#include <rfb/SecurityServer.h>
-#include <rfb/Timer.h>
+
+namespace rdr {
+ class InStream;
+ class OutStream;
+}
namespace rfb {
@@ -84,6 +87,59 @@ namespace rfb {
// cleanup of the SConnection object by the server
virtual void close(const char* reason);
+ // requestClipboard() will result in a request to the client to
+ // transfer its clipboard data. A call to handleClipboardData()
+ // will be made once the data is available.
+ virtual void requestClipboard();
+
+ // announceClipboard() informs the client of changes to the
+ // clipboard on the server. The client may later request the
+ // clipboard data via handleClipboardRequest().
+ virtual void announceClipboard(bool available);
+
+ // sendClipboardData() transfers the clipboard data to the client
+ // and should be called whenever the client has requested the
+ // clipboard via handleClipboardRequest().
+ virtual void sendClipboardData(const char* data);
+
+ // getAccessRights() returns the access rights of a SConnection to the server.
+ AccessRights getAccessRights() { return accessRights; }
+
+ // setAccessRights() allows a security package to limit the access rights
+ // of a SConnection to the server. How the access rights are treated
+ // is up to the derived class.
+ virtual void setAccessRights(AccessRights ar);
+ virtual bool accessCheck(AccessRights ar) const;
+
+ // authenticated() returns true if the client has authenticated
+ // successfully.
+ bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
+ state_ == RFBSTATE_NORMAL); }
+
+ SMsgReader* reader() { return reader_; }
+ SMsgWriter* writer() { return writer_; }
+
+ rdr::InStream* getInStream() { return is; }
+ rdr::OutStream* getOutStream() { return os; }
+
+ enum stateEnum {
+ RFBSTATE_UNINITIALISED,
+ RFBSTATE_PROTOCOL_VERSION,
+ RFBSTATE_SECURITY_TYPE,
+ RFBSTATE_SECURITY,
+ RFBSTATE_SECURITY_FAILURE,
+ RFBSTATE_QUERYING,
+ RFBSTATE_INITIALISATION,
+ RFBSTATE_NORMAL,
+ RFBSTATE_CLOSING,
+ RFBSTATE_INVALID
+ };
+
+ stateEnum state() { return state_; }
+
+ int32_t getPreferredEncoding() { return preferredEncoding; }
+
+ protected:
// Overridden from SMsgHandler
@@ -91,23 +147,38 @@ namespace rfb {
void clientCutText(const char* str) override;
+ void handleClipboardCaps(uint32_t flags,
+ const uint32_t* lengths) override;
void handleClipboardRequest(uint32_t flags) override;
void handleClipboardPeek() override;
void handleClipboardNotify(uint32_t flags) override;
void handleClipboardProvide(uint32_t flags, const size_t* lengths,
const uint8_t* const* data) override;
- void supportsQEMUKeyEvent() override;
-
- virtual void supportsExtendedMouseButtons() override;
-
-
// Methods to be overridden in a derived class
- // versionReceived() indicates that the version number has just been read
- // from the client. The version will already have been "cooked"
- // to deal with unknown/bogus viewer protocol numbers.
- virtual void versionReceived();
+ // supportsLocalCursor() is called whenever the status of
+ // cp.supportsLocalCursor has changed. At the moment this happens on a
+ // setEncodings message, but in the future this may be due to a message
+ // 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();
+
+ // supportsContinuousUpdates() is called the first time we detect that
+ // the client wants the continuous updates extension. A
+ // EndOfContinuousUpdates message should be sent back to the client at
+ // this point if it is supported.
+ virtual void supportsContinuousUpdates();
+
+ // supportsLEDState() is called the first time we detect that the
+ // client supports the LED state extension. A LEDState message
+ // should be sent back to the client to inform it of the current
+ // server state.
+ virtual void supportsLEDState();
// authSuccess() is called when authentication has succeeded.
virtual void authSuccess();
@@ -132,7 +203,7 @@ namespace rfb {
// framebufferUpdateRequest() is called when a FramebufferUpdateRequest
// message is received. The derived class must call on to
// SConnection::framebufferUpdateRequest().
- void framebufferUpdateRequest(const Rect& r, bool incremental) override;
+ void framebufferUpdateRequest(const core::Rect& r, bool incremental) override;
// fence() is called when we get a fence request or response. By default
// it responds directly to requests (stating it doesn't support any
@@ -163,62 +234,6 @@ namespace rfb {
// client received the request.
virtual void handleClipboardData(const char* data);
-
- // Other methods
-
- // requestClipboard() will result in a request to the client to
- // transfer its clipboard data. A call to handleClipboardData()
- // will be made once the data is available.
- virtual void requestClipboard();
-
- // announceClipboard() informs the client of changes to the
- // clipboard on the server. The client may later request the
- // clipboard data via handleClipboardRequest().
- virtual void announceClipboard(bool available);
-
- // sendClipboardData() transfers the clipboard data to the client
- // and should be called whenever the client has requested the
- // clipboard via handleClipboardRequest().
- virtual void sendClipboardData(const char* data);
-
- // getAccessRights() returns the access rights of a SConnection to the server.
- AccessRights getAccessRights() { return accessRights; }
-
- // setAccessRights() allows a security package to limit the access rights
- // of a SConnection to the server. How the access rights are treated
- // is up to the derived class.
- virtual void setAccessRights(AccessRights ar);
- virtual bool accessCheck(AccessRights ar) const;
-
- // authenticated() returns true if the client has authenticated
- // successfully.
- bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
- state_ == RFBSTATE_NORMAL); }
-
- SMsgReader* reader() { return reader_; }
- SMsgWriter* writer() { return writer_; }
-
- rdr::InStream* getInStream() { return is; }
- rdr::OutStream* getOutStream() { return os; }
-
- enum stateEnum {
- RFBSTATE_UNINITIALISED,
- RFBSTATE_PROTOCOL_VERSION,
- RFBSTATE_SECURITY_TYPE,
- RFBSTATE_SECURITY,
- RFBSTATE_SECURITY_FAILURE,
- RFBSTATE_QUERYING,
- RFBSTATE_INITIALISATION,
- RFBSTATE_NORMAL,
- RFBSTATE_CLOSING,
- RFBSTATE_INVALID
- };
-
- stateEnum state() { return state_; }
-
- int32_t getPreferredEncoding() { return preferredEncoding; }
-
- protected:
// failConnection() prints a message to the log, sends a connection
// failed message to the client (if possible) and throws an
// Exception.
@@ -243,7 +258,7 @@ namespace rfb {
bool processSecurityFailure();
bool processInitMsg();
- void handleAuthFailureTimeout(Timer* t);
+ void handleAuthFailureTimeout(core::Timer* t);
int defaultMajorVersion, defaultMinorVersion;
@@ -256,7 +271,7 @@ namespace rfb {
SecurityServer security;
SSecurity* ssecurity;
- MethodTimer<SConnection> authFailureTimer;
+ core::MethodTimer<SConnection> authFailureTimer;
std::string authFailureMsg;
stateEnum state_;
diff --git a/common/rfb/SDesktop.h b/common/rfb/SDesktop.h
index c97e788a..402a13af 100644
--- a/common/rfb/SDesktop.h
+++ b/common/rfb/SDesktop.h
@@ -38,14 +38,19 @@
#ifndef __RFB_SDESKTOP_H__
#define __RFB_SDESKTOP_H__
-#include <rfb/PixelBuffer.h>
-#include <rfb/VNCServer.h>
+#include <stdint.h>
+
#include <rfb/screenTypes.h>
+namespace core { struct Point; }
+
namespace network { class Socket; }
namespace rfb {
+ struct ScreenSet;
+ class VNCServer;
+
class SDesktop {
public:
// init() is called immediately when the VNCServer gets a reference
@@ -97,7 +102,7 @@ namespace rfb {
// pointerEvent() is called whenever a client sends an event that
// the pointer moved, or a button was pressed or released.
- virtual void pointerEvent(const Point& /*pos*/,
+ virtual void pointerEvent(const core::Point& /*pos*/,
uint16_t /*buttonMask*/) {};
// handleClipboardRequest() is called whenever a client requests
@@ -122,47 +127,6 @@ namespace rfb {
virtual ~SDesktop() {}
};
- // -=- SStaticDesktop
- // Trivial implementation of the SDesktop interface, which provides
- // dummy input handlers and event processing routine, and exports
- // a plain black desktop of the specified format.
- class SStaticDesktop : public SDesktop {
- public:
- SStaticDesktop(const Point& size)
- : server(nullptr), buffer(nullptr)
- {
- PixelFormat pf;
- const uint8_t black[4] = { 0, 0, 0, 0 };
- buffer = new ManagedPixelBuffer(pf, size.x, size.y);
- if (buffer)
- buffer->fillRect(buffer->getRect(), black);
- }
- SStaticDesktop(const Point& size, const PixelFormat& pf)
- : buffer(nullptr)
- {
- const uint8_t black[4] = { 0, 0, 0, 0 };
- buffer = new ManagedPixelBuffer(pf, size.x, size.y);
- if (buffer)
- buffer->fillRect(buffer->getRect(), black);
- }
- virtual ~SStaticDesktop() {
- if (buffer) delete buffer;
- }
-
- void init(VNCServer* vs) override {
- server = vs;
- server->setPixelBuffer(buffer);
- }
- void queryConnection(network::Socket* sock,
- const char* /*userName*/) override {
- server->approveConnection(sock, true, nullptr);
- }
-
- protected:
- VNCServer* server;
- ManagedPixelBuffer* buffer;
- };
-
};
#endif // __RFB_SDESKTOP_H__
diff --git a/common/rfb/SMsgHandler.cxx b/common/rfb/SMsgHandler.cxx
deleted file mode 100644
index 1dce634d..00000000
--- a/common/rfb/SMsgHandler.cxx
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2019 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <rfb/Exception.h>
-#include <rfb/LogWriter.h>
-#include <rfb/SMsgHandler.h>
-#include <rfb/ScreenSet.h>
-#include <rfb/clipboardTypes.h>
-#include <rfb/encodings.h>
-#include <rfb/util.h>
-
-using namespace rfb;
-
-static LogWriter vlog("SMsgHandler");
-
-SMsgHandler::SMsgHandler()
-{
-}
-
-SMsgHandler::~SMsgHandler()
-{
-}
-
-void SMsgHandler::clientInit(bool /*shared*/)
-{
-}
-
-void SMsgHandler::setPixelFormat(const PixelFormat& pf)
-{
- client.setPF(pf);
-}
-
-void SMsgHandler::setEncodings(int nEncodings, const int32_t* encodings)
-{
- bool firstFence, firstContinuousUpdates, firstLEDState,
- firstQEMUKeyEvent, firstExtMouseButtonsEvent;
-
- firstFence = !client.supportsFence();
- firstContinuousUpdates = !client.supportsContinuousUpdates();
- firstLEDState = !client.supportsLEDState();
- firstQEMUKeyEvent = !client.supportsEncoding(pseudoEncodingQEMUKeyEvent);
- firstExtMouseButtonsEvent = !client.supportsEncoding(pseudoEncodingExtendedMouseButtons);
-
- client.setEncodings(nEncodings, encodings);
-
- supportsLocalCursor();
-
- if (client.supportsFence() && firstFence)
- supportsFence();
- if (client.supportsContinuousUpdates() && firstContinuousUpdates)
- supportsContinuousUpdates();
- if (client.supportsLEDState() && firstLEDState)
- supportsLEDState();
- if (client.supportsEncoding(pseudoEncodingQEMUKeyEvent) && firstQEMUKeyEvent)
- supportsQEMUKeyEvent();
- if (client.supportsEncoding(pseudoEncodingExtendedMouseButtons) && firstExtMouseButtonsEvent)
- supportsExtendedMouseButtons();
-}
-
-void SMsgHandler::keyEvent(uint32_t /*keysym*/, uint32_t /*keycode*/,
- bool /*down*/)
-{
-}
-
-void SMsgHandler::pointerEvent(const Point& /*pos*/,
- uint16_t /*buttonMask*/)
-{
-}
-
-void SMsgHandler::clientCutText(const char* /*str*/)
-{
-}
-
-void SMsgHandler::handleClipboardCaps(uint32_t flags, const uint32_t* lengths)
-{
- int i;
-
- vlog.debug("Got client clipboard capabilities:");
- for (i = 0;i < 16;i++) {
- if (flags & (1 << i)) {
- const char *type;
-
- switch (1 << i) {
- case clipboardUTF8:
- type = "Plain text";
- break;
- case clipboardRTF:
- type = "Rich text";
- break;
- case clipboardHTML:
- type = "HTML";
- break;
- case clipboardDIB:
- type = "Images";
- break;
- case clipboardFiles:
- type = "Files";
- break;
- default:
- vlog.debug(" Unknown format 0x%x", 1 << i);
- continue;
- }
-
- if (lengths[i] == 0)
- vlog.debug(" %s (only notify)", type);
- else {
- vlog.debug(" %s (automatically send up to %s)",
- type, iecPrefix(lengths[i], "B").c_str());
- }
- }
- }
-
- client.setClipboardCaps(flags, lengths);
-}
-
-void SMsgHandler::handleClipboardRequest(uint32_t /*flags*/)
-{
-}
-
-void SMsgHandler::handleClipboardPeek()
-{
-}
-
-void SMsgHandler::handleClipboardNotify(uint32_t /*flags*/)
-{
-}
-
-void SMsgHandler::handleClipboardProvide(uint32_t /*flags*/,
- const size_t* /*lengths*/,
- const uint8_t* const* /*data*/)
-{
-}
-
-void SMsgHandler::supportsLocalCursor()
-{
-}
-
-void SMsgHandler::supportsFence()
-{
-}
-
-void SMsgHandler::supportsContinuousUpdates()
-{
-}
-
-void SMsgHandler::supportsLEDState()
-{
-}
-
-void SMsgHandler::supportsQEMUKeyEvent()
-{
-}
-
-void SMsgHandler::supportsExtendedMouseButtons()
-{
-} \ No newline at end of file
diff --git a/common/rfb/SMsgHandler.h b/common/rfb/SMsgHandler.h
index c5d13d78..d14a21c0 100644
--- a/common/rfb/SMsgHandler.h
+++ b/common/rfb/SMsgHandler.h
@@ -25,83 +25,47 @@
#include <stdint.h>
-#include <rfb/PixelFormat.h>
#include <rfb/ClientParams.h>
-#include <rfb/ScreenSet.h>
-
-namespace rdr { class InStream; }
namespace rfb {
class SMsgHandler {
public:
- SMsgHandler();
- virtual ~SMsgHandler();
+ virtual ~SMsgHandler() {}
- // 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 clipboardCaps() methods, a
- // derived class must call on to SMsgHandler's methods.
+ // The following methods are called as corresponding messages are
+ // read. A derived class must override these methods.
- virtual void clientInit(bool shared);
+ virtual void clientInit(bool shared) = 0;
- virtual void setPixelFormat(const PixelFormat& pf);
- virtual void setEncodings(int nEncodings, const int32_t* encodings);
- virtual void framebufferUpdateRequest(const Rect& r, bool incremental) = 0;
+ virtual void setPixelFormat(const PixelFormat& pf) = 0;
+ virtual void setEncodings(int nEncodings,
+ const int32_t* encodings) = 0;
+ virtual void framebufferUpdateRequest(const core::Rect& r,
+ bool incremental) = 0;
virtual void setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout) = 0;
- virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]) = 0;
+ virtual void fence(uint32_t flags, unsigned len,
+ const uint8_t data[]) = 0;
virtual void enableContinuousUpdates(bool enable,
- int x, int y, int w, int h) = 0;
+ int x, int y,
+ int w, int h) = 0;
virtual void keyEvent(uint32_t keysym, uint32_t keycode,
- bool down);
- virtual void pointerEvent(const Point& pos,
- uint16_t buttonMask);
+ bool down) = 0;
+ virtual void pointerEvent(const core::Point& pos,
+ uint16_t buttonMask) = 0;
- virtual void clientCutText(const char* str);
+ virtual void clientCutText(const char* str) = 0;
virtual void handleClipboardCaps(uint32_t flags,
- const uint32_t* lengths);
- virtual void handleClipboardRequest(uint32_t flags);
- virtual void handleClipboardPeek();
- virtual void handleClipboardNotify(uint32_t flags);
+ const uint32_t* lengths) = 0;
+ virtual void handleClipboardRequest(uint32_t flags) = 0;
+ virtual void handleClipboardPeek() = 0;
+ virtual void handleClipboardNotify(uint32_t flags) = 0;
virtual void handleClipboardProvide(uint32_t flags,
const size_t* lengths,
- const uint8_t* const* data);
-
- // supportsLocalCursor() is called whenever the status of
- // cp.supportsLocalCursor has changed. At the moment this happens on a
- // setEncodings message, but in the future this may be due to a message
- // 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();
-
- // supportsContinuousUpdates() is called the first time we detect that
- // the client wants the continuous updates extension. A
- // EndOfContinuousUpdates message should be sent back to the client at
- // this point if it is supported.
- virtual void supportsContinuousUpdates();
-
- // supportsLEDState() is called the first time we detect that the
- // client supports the LED state extension. A LEDState message
- // should be sent back to the client to inform it of the current
- // server state.
- virtual void supportsLEDState();
-
- // supportsQEMUKeyEvent() is called the first time we detect that the
- // client wants the QEMU Extended Key Event extension. The default
- // handler will send a pseudo-rect back, signalling server support.
- virtual void supportsQEMUKeyEvent();
-
- // supportsExtendedMouseButtons() is called the first time we detect that the
- // client supports sending 16 bit mouse button state. This lets us pass more button
- // states between server and client.
- virtual void supportsExtendedMouseButtons();
+ const uint8_t* const* data) = 0;
ClientParams client;
};
diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx
index 5df11153..9054bcc3 100644
--- a/common/rfb/SMsgReader.cxx
+++ b/common/rfb/SMsgReader.cxx
@@ -25,6 +25,10 @@
#include <vector>
+#include <core/Configuration.h>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rdr/InStream.h>
#include <rdr/ZlibInStream.h>
@@ -32,17 +36,19 @@
#include <rfb/qemuTypes.h>
#include <rfb/clipboardTypes.h>
#include <rfb/Exception.h>
+#include <rfb/PixelFormat.h>
+#include <rfb/ScreenSet.h>
#include <rfb/SMsgHandler.h>
#include <rfb/SMsgReader.h>
-#include <rfb/Configuration.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
using namespace rfb;
-static LogWriter vlog("SMsgReader");
+static core::LogWriter vlog("SMsgReader");
-static IntParameter maxCutText("MaxCutText", "Maximum permitted length of an incoming clipboard update", 256*1024);
+static core::IntParameter maxCutText("MaxCutText",
+ "Maximum permitted length of an "
+ "incoming clipboard update",
+ 256*1024, 0, INT_MAX);
SMsgReader::SMsgReader(SMsgHandler* handler_, rdr::InStream* is_)
: handler(handler_), is(is_), state(MSGSTATE_IDLE)
@@ -201,7 +207,7 @@ bool SMsgReader::readFramebufferUpdateRequest()
int y = is->readU16();
int w = is->readU16();
int h = is->readU16();
- handler->framebufferUpdateRequest(Rect(x, y, x+w, y+h), inc);
+ handler->framebufferUpdateRequest({x, y, x+w, y+h}, inc);
return true;
}
@@ -298,7 +304,7 @@ bool SMsgReader::readPointerEvent()
}
is->clearRestorePoint();
- handler->pointerEvent(Point(x, y), mask);
+ handler->pointerEvent({x, y}, mask);
return true;
}
@@ -338,8 +344,8 @@ bool SMsgReader::readClientCutText()
std::vector<char> ca(len);
is->readBytes((uint8_t*)ca.data(), len);
- std::string utf8(latin1ToUTF8(ca.data(), ca.size()));
- std::string filtered(convertLF(utf8.data(), utf8.size()));
+ std::string utf8(core::latin1ToUTF8(ca.data(), ca.size()));
+ std::string filtered(core::convertLF(utf8.data(), utf8.size()));
handler->clientCutText(filtered.c_str());
@@ -485,7 +491,7 @@ bool SMsgReader::readQEMUMessage()
ret = readQEMUKeyEvent();
break;
default:
- throw protocol_error(format("Unknown QEMU submessage type %d", subType));
+ throw protocol_error(core::format("Unknown QEMU submessage type %d", subType));
}
if (!ret) {
diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx
index 5ee0905b..d52df511 100644
--- a/common/rfb/SMsgWriter.cxx
+++ b/common/rfb/SMsgWriter.cxx
@@ -24,6 +24,9 @@
#include <stdio.h>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rdr/OutStream.h>
#include <rdr/MemOutStream.h>
#include <rdr/ZlibOutStream.h>
@@ -32,16 +35,17 @@
#include <rfb/fenceTypes.h>
#include <rfb/clipboardTypes.h>
#include <rfb/ClientParams.h>
+#include <rfb/Cursor.h>
#include <rfb/UpdateTracker.h>
#include <rfb/Encoder.h>
+#include <rfb/ScreenSet.h>
#include <rfb/SMsgWriter.h>
-#include <rfb/LogWriter.h>
+#include <rfb/encodings.h>
#include <rfb/ledStates.h>
-#include <rfb/util.h>
using namespace rfb;
-static LogWriter vlog("SMsgWriter");
+static core::LogWriter vlog("SMsgWriter");
SMsgWriter::SMsgWriter(ClientParams* client_, rdr::OutStream* os_)
: client(client_), os(os_),
@@ -95,7 +99,7 @@ void SMsgWriter::writeServerCutText(const char* str)
if (strchr(str, '\r') != nullptr)
throw std::invalid_argument("Invalid carriage return in clipboard data");
- std::string latin1(utf8ToLatin1(str));
+ std::string latin1(core::utf8ToLatin1(str));
startMsg(msgTypeServerCutText);
os->pad(3);
@@ -405,7 +409,7 @@ void SMsgWriter::writeFramebufferUpdateEnd()
endMsg();
}
-void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY)
+void SMsgWriter::writeCopyRect(const core::Rect& r, int srcX, int srcY)
{
startRect(r,encodingCopyRect);
os->writeU16(srcX);
@@ -413,7 +417,7 @@ void SMsgWriter::writeCopyRect(const Rect& r, int srcX, int srcY)
endRect();
}
-void SMsgWriter::startRect(const Rect& r, int encoding)
+void SMsgWriter::startRect(const core::Rect& r, int encoding)
{
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw std::logic_error("SMsgWriter::startRect: nRects out of sync");
@@ -488,7 +492,7 @@ void SMsgWriter::writePseudoRects()
}
if (needCursorPos) {
- const Point& cursorPos = client->cursorPos();
+ const core::Point& cursorPos = client->cursorPos();
if (client->supportsEncoding(pseudoEncodingVMwareCursorPosition)) {
writeSetVMwareCursorPositionRect(cursorPos.x, cursorPos.y);
diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h
index 7bc0ed6a..113a9370 100644
--- a/common/rfb/SMsgWriter.h
+++ b/common/rfb/SMsgWriter.h
@@ -25,8 +25,7 @@
#include <stdint.h>
-#include <rfb/encodings.h>
-#include <rfb/ScreenSet.h>
+namespace core { struct Rect; }
namespace rdr { class OutStream; }
@@ -117,11 +116,11 @@ namespace rfb {
void writeFramebufferUpdateEnd();
// There is no explicit encoder for CopyRect rects.
- void writeCopyRect(const Rect& r, int srcX, int srcY);
+ void writeCopyRect(const core::Rect& r, int srcX, int srcY);
// Encoders should call these to mark the start and stop of individual
// rects.
- void startRect(const Rect& r, int enc);
+ void startRect(const core::Rect& r, int enc);
void endRect();
protected:
diff --git a/common/rfb/SSecurity.h b/common/rfb/SSecurity.h
index 0911ecd8..edbe8185 100644
--- a/common/rfb/SSecurity.h
+++ b/common/rfb/SSecurity.h
@@ -44,12 +44,12 @@
#ifndef __RFB_SSECURITY_H__
#define __RFB_SSECURITY_H__
-#include <rfb/SConnection.h>
-
-#include <list>
+#include <rfb/AccessRights.h>
namespace rfb {
+ class SConnection;
+
class SSecurity {
public:
SSecurity(SConnection* sc_) : sc(sc_) {}
diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx
index e62e6d60..4fa63250 100644
--- a/common/rfb/SSecurityPlain.cxx
+++ b/common/rfb/SSecurityPlain.cxx
@@ -21,10 +21,12 @@
#include <config.h>
#endif
+#include <core/Configuration.h>
+#include <core/string.h>
+
#include <rfb/SSecurityPlain.h>
#include <rfb/SConnection.h>
#include <rfb/Exception.h>
-#include <rfb/util.h>
#include <rdr/InStream.h>
#if !defined(WIN32) && !defined(__APPLE__)
#include <rfb/UnixPasswordValidator.h>
@@ -37,32 +39,30 @@
using namespace rfb;
-StringParameter PasswordValidator::plainUsers
+core::StringListParameter PasswordValidator::plainUsers
("PlainUsers",
"Users permitted to access via Plain security type (including TLSPlain, X509Plain etc.)"
#ifdef HAVE_NETTLE
" or RSA-AES security types (RA2, RA2ne, RA2_256, RA2ne_256)"
#endif
,
- "");
+ {});
bool PasswordValidator::validUser(const char* username)
{
- std::vector<std::string> users;
-
- users = split(plainUsers, ',');
-
- for (size_t i = 0; i < users.size(); i++) {
- if (users[i] == "*")
+ for (const char* user : plainUsers) {
+ if (strcmp(user, "*") == 0)
return true;
#if !defined(WIN32) && !defined(__APPLE__)
- if (users[i] == "%u") {
+ if (strcmp(user, "%u") == 0) {
struct passwd *pw = getpwnam(username);
if (pw && pw->pw_uid == getuid())
return true;
}
#endif
- if (users[i] == username)
+ // FIXME: We should compare uid, as the usernames might not be case
+ // sensitive, or have other normalisation
+ if (strcmp(user, username) == 0)
return true;
}
return false;
@@ -113,8 +113,9 @@ bool SSecurityPlain::processMsg()
password[plen] = 0;
username[ulen] = 0;
plen = 0;
- if (!valid->validate(sc, username, password))
- throw auth_error("Authentication failed");
+ std::string msg = "Authentication failed";
+ if (!valid->validate(sc, username, password, msg))
+ throw auth_error(msg);
}
return true;
diff --git a/common/rfb/SSecurityPlain.h b/common/rfb/SSecurityPlain.h
index c0ac049b..4c030455 100644
--- a/common/rfb/SSecurityPlain.h
+++ b/common/rfb/SSecurityPlain.h
@@ -20,23 +20,29 @@
#ifndef __RFB_SSECURITYPLAIN_H__
#define __RFB_SSECURITYPLAIN_H__
-#include <rfb/SConnection.h>
+#include <rfb/Security.h>
#include <rfb/SSecurity.h>
-#include <rfb/SSecurityVeNCrypt.h>
-#include <rfb/Configuration.h>
+
+namespace core { class StringListParameter; }
namespace rfb {
class PasswordValidator {
public:
- bool validate(SConnection* sc, const char *username, const char *password)
- { return validUser(username) ? validateInternal(sc, username, password) : false; }
- static StringParameter plainUsers;
+ bool validate(SConnection* sc,
+ const char *username,
+ const char *password,
+ std::string &msg)
+ { return validUser(username) ? validateInternal(sc, username, password, msg) : false; }
+ static core::StringListParameter plainUsers;
virtual ~PasswordValidator() { }
protected:
- virtual bool validateInternal(SConnection* sc, const char *username, const char *password)=0;
+ virtual bool validateInternal(SConnection* sc,
+ const char *username,
+ const char *password,
+ std::string &msg) = 0;
static bool validUser(const char* username);
};
diff --git a/common/rfb/SSecurityRSAAES.cxx b/common/rfb/SSecurityRSAAES.cxx
index fed213ad..405005ab 100644
--- a/common/rfb/SSecurityRSAAES.cxx
+++ b/common/rfb/SSecurityRSAAES.cxx
@@ -37,13 +37,15 @@
#include <nettle/base64.h>
#include <nettle/asn1.h>
+#include <core/Exception.h>
+#include <core/LogWriter.h>
+
#include <rdr/AESInStream.h>
#include <rdr/AESOutStream.h>
-#include <rdr/Exception.h>
+#include <rdr/RandomStream.h>
#include <rfb/SSecurityRSAAES.h>
#include <rfb/SConnection.h>
-#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
#if !defined(WIN32) && !defined(__APPLE__)
#include <rfb/UnixPasswordValidator.h>
@@ -67,14 +69,14 @@ const size_t MaxKeyFileSize = 32 * 1024;
using namespace rfb;
-StringParameter SSecurityRSAAES::keyFile
+core::StringParameter SSecurityRSAAES::keyFile
("RSAKey", "Path to the RSA key for the RSA-AES security types in "
- "PEM format", "", ConfServer);
-BoolParameter SSecurityRSAAES::requireUsername
+ "PEM format", "");
+core::BoolParameter SSecurityRSAAES::requireUsername
("RequireUsername", "Require username for the RSA-AES security types",
- false, ConfServer);
+ false);
-static LogWriter vlog("CSecurityRSAAES");
+static core::LogWriter vlog("SSecurityRSAAES");
SSecurityRSAAES::SSecurityRSAAES(SConnection* sc_, uint32_t _secType,
int _keySize, bool _isAllEncrypted)
@@ -174,7 +176,7 @@ void SSecurityRSAAES::loadPrivateKey()
{
FILE* file = fopen(keyFile, "rb");
if (!file)
- throw rdr::posix_error("Failed to open key file", errno);
+ throw core::posix_error("Failed to open key file", errno);
fseek(file, 0, SEEK_END);
size_t size = ftell(file);
if (size == 0 || size > MaxKeyFileSize) {
@@ -185,7 +187,7 @@ void SSecurityRSAAES::loadPrivateKey()
std::vector<uint8_t> data(size);
if (fread(data.data(), 1, data.size(), file) != size) {
fclose(file);
- throw rdr::posix_error("Failed to read key", errno);
+ throw core::posix_error("Failed to read key", errno);
}
fclose(file);
@@ -345,6 +347,7 @@ static void random_func(void* ctx, size_t length, uint8_t* dst)
void SSecurityRSAAES::writeRandom()
{
+ rdr::RandomStream rs;
rdr::OutStream* os = sc->getOutStream();
if (!rs.hasData(keySize / 8))
throw std::runtime_error("Failed to generate random");
@@ -580,9 +583,10 @@ void SSecurityRSAAES::verifyUserPass()
#elif !defined(__APPLE__)
UnixPasswordValidator *valid = new UnixPasswordValidator();
#endif
- if (!valid->validate(sc, username, password)) {
+ std::string msg = "Authentication failed";
+ if (!valid->validate(sc, username, password, msg)) {
delete valid;
- throw auth_error("Authentication failed");
+ throw auth_error(msg);
}
delete valid;
#else
diff --git a/common/rfb/SSecurityRSAAES.h b/common/rfb/SSecurityRSAAES.h
index e3300cb7..283134db 100644
--- a/common/rfb/SSecurityRSAAES.h
+++ b/common/rfb/SSecurityRSAAES.h
@@ -27,7 +27,10 @@
#include <rfb/SSecurity.h>
-#include <rdr/RandomStream.h>
+namespace core {
+ class BoolParameter;
+ class StringParameter;
+}
namespace rdr {
class InStream;
@@ -51,8 +54,8 @@ namespace rfb {
return accessRights;
}
- static StringParameter keyFile;
- static BoolParameter requireUsername;
+ static core::StringParameter keyFile;
+ static core::BoolParameter requireUsername;
private:
void cleanup();
@@ -96,8 +99,6 @@ namespace rfb {
rdr::InStream* rawis;
rdr::OutStream* rawos;
-
- rdr::RandomStream rs;
};
}
diff --git a/common/rfb/SSecurityTLS.cxx b/common/rfb/SSecurityTLS.cxx
index b297242b..17497b8e 100644
--- a/common/rfb/SSecurityTLS.cxx
+++ b/common/rfb/SSecurityTLS.cxx
@@ -2,7 +2,7 @@
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
- * Copyright (C) 2012-2021 Pierre Ossman for Cendio AB
+ * Copyright 2012-2025 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,13 +30,15 @@
#include <stdlib.h>
+#include <core/LogWriter.h>
+
#include <rfb/SSecurityTLS.h>
#include <rfb/SConnection.h>
-#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
+
#include <rdr/TLSException.h>
-#include <rdr/TLSInStream.h>
-#include <rdr/TLSOutStream.h>
+#include <rdr/TLSSocket.h>
+
#include <gnutls/x509.h>
#if defined (SSECURITYTLS__USE_DEPRECATED_DH)
@@ -59,17 +61,17 @@ static const gnutls_datum_t ffdhe_pkcs3_param = {
using namespace rfb;
-StringParameter SSecurityTLS::X509_CertFile
-("X509Cert", "Path to the X509 certificate in PEM format", "", ConfServer);
+core::StringParameter SSecurityTLS::X509_CertFile
+("X509Cert", "Path to the X509 certificate in PEM format", "");
-StringParameter SSecurityTLS::X509_KeyFile
-("X509Key", "Path to the key of the X509 certificate in PEM format", "", ConfServer);
+core::StringParameter SSecurityTLS::X509_KeyFile
+("X509Key", "Path to the key of the X509 certificate in PEM format", "");
-static LogWriter vlog("TLS");
+static core::LogWriter vlog("TLS");
SSecurityTLS::SSecurityTLS(SConnection* sc_, bool _anon)
: SSecurity(sc_), session(nullptr), anon_cred(nullptr),
- cert_cred(nullptr), anon(_anon), tlsis(nullptr), tlsos(nullptr),
+ cert_cred(nullptr), anon(_anon), tlssock(nullptr),
rawis(nullptr), rawos(nullptr)
{
int ret;
@@ -85,32 +87,13 @@ SSecurityTLS::SSecurityTLS(SConnection* sc_, bool _anon)
void SSecurityTLS::shutdown()
{
- if (tlsos) {
- try {
- if (tlsos->hasBufferedData()) {
- tlsos->cork(false);
- tlsos->flush();
- if (tlsos->hasBufferedData())
- vlog.error("Failed to flush remaining socket data on close");
- }
- } catch (std::exception& e) {
- vlog.error("Failed to flush remaining socket data on close: %s", e.what());
- }
- }
-
- if (session) {
- int ret;
- // FIXME: We can't currently wait for the response, so we only send
- // our close and hope for the best
- ret = gnutls_bye(session, GNUTLS_SHUT_WR);
- if ((ret != GNUTLS_E_SUCCESS) && (ret != GNUTLS_E_INVALID_SESSION))
- vlog.error("TLS shutdown failed: %s", gnutls_strerror(ret));
- }
+ if (tlssock)
+ tlssock->shutdown();
#if defined (SSECURITYTLS__USE_DEPRECATED_DH)
if (dh_params) {
gnutls_dh_params_deinit(dh_params);
- dh_params = 0;
+ dh_params = nullptr;
}
#endif
@@ -130,13 +113,9 @@ void SSecurityTLS::shutdown()
rawos = nullptr;
}
- if (tlsis) {
- delete tlsis;
- tlsis = nullptr;
- }
- if (tlsos) {
- delete tlsos;
- tlsos = nullptr;
+ if (tlssock) {
+ delete tlssock;
+ tlssock = nullptr;
}
if (session) {
@@ -182,56 +161,46 @@ bool SSecurityTLS::processMsg()
os->writeU8(1);
os->flush();
- // Create these early as they set up the push/pull functions
- // for GnuTLS
- tlsis = new rdr::TLSInStream(is, session);
- tlsos = new rdr::TLSOutStream(os, session);
+ tlssock = new rdr::TLSSocket(is, os, session);
rawis = is;
rawos = os;
}
- err = gnutls_handshake(session);
- if (err != GNUTLS_E_SUCCESS) {
- if (!gnutls_error_is_fatal(err)) {
- vlog.debug("Deferring completion of TLS handshake: %s", gnutls_strerror(err));
+ try {
+ if (!tlssock->handshake())
return false;
- }
- vlog.error("TLS Handshake failed: %s", gnutls_strerror (err));
+ } catch (std::exception&) {
shutdown();
- throw rdr::tls_error("TLS Handshake failed", err);
+ throw;
}
vlog.debug("TLS handshake completed with %s",
gnutls_session_get_desc(session));
- sc->setStreams(tlsis, tlsos);
+ sc->setStreams(&tlssock->inStream(), &tlssock->outStream());
return true;
}
void SSecurityTLS::setParams()
{
- static const char kx_anon_priority[] = ":+ANON-ECDH:+ANON-DH";
+ static const char kx_anon_priority[] = "+ANON-ECDH:+ANON-DH";
int ret;
// Custom priority string specified?
if (strcmp(Security::GnuTLSPriority, "") != 0) {
- char *prio;
+ std::string prio;
const char *err;
- prio = new char[strlen(Security::GnuTLSPriority) +
- strlen(kx_anon_priority) + 1];
-
- strcpy(prio, Security::GnuTLSPriority);
- if (anon)
- strcat(prio, kx_anon_priority);
-
- ret = gnutls_priority_set_direct(session, prio, &err);
-
- delete [] prio;
+ prio = (const char*)Security::GnuTLSPriority;
+ if (anon) {
+ prio += ":";
+ prio += kx_anon_priority;
+ }
+ ret = gnutls_priority_set_direct(session, prio.c_str(), &err);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
@@ -241,30 +210,22 @@ void SSecurityTLS::setParams()
const char *err;
#if GNUTLS_VERSION_NUMBER >= 0x030603
- // gnutls_set_default_priority_appends() expects a normal priority string that
- // doesn't start with ":".
- ret = gnutls_set_default_priority_append(session, kx_anon_priority + 1, &err, 0);
+ ret = gnutls_set_default_priority_append(session, kx_anon_priority, &err, 0);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
throw rdr::tls_error("gnutls_set_default_priority_append()", ret);
}
#else
+ std::string prio;
+
// We don't know what the system default priority is, so we guess
// it's what upstream GnuTLS has
- static const char gnutls_default_priority[] = "NORMAL";
- char *prio;
-
- prio = new char[strlen(gnutls_default_priority) +
- strlen(kx_anon_priority) + 1];
-
- strcpy(prio, gnutls_default_priority);
- strcat(prio, kx_anon_priority);
-
- ret = gnutls_priority_set_direct(session, prio, &err);
-
- delete [] prio;
+ prio = "NORMAL";
+ prio += ":";
+ prio += kx_anon_priority;
+ ret = gnutls_priority_set_direct(session, prio.c_str(), &err);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
diff --git a/common/rfb/SSecurityTLS.h b/common/rfb/SSecurityTLS.h
index 1dc33cfd..61eec2a8 100644
--- a/common/rfb/SSecurityTLS.h
+++ b/common/rfb/SSecurityTLS.h
@@ -2,6 +2,7 @@
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
+ * Copyright 2012-2025 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
@@ -26,6 +27,7 @@
#error "This header should not be included without HAVE_GNUTLS defined"
#endif
+#include <rfb/Security.h>
#include <rfb/SSecurity.h>
#include <gnutls/gnutls.h>
@@ -40,8 +42,7 @@
namespace rdr {
class InStream;
class OutStream;
- class TLSInStream;
- class TLSOutStream;
+ class TLSSocket;
}
namespace rfb {
@@ -54,8 +55,8 @@ namespace rfb {
const char* getUserName() const override {return nullptr;}
int getType() const override { return anon ? secTypeTLSNone : secTypeX509None;}
- static StringParameter X509_CertFile;
- static StringParameter X509_KeyFile;
+ static core::StringParameter X509_CertFile;
+ static core::StringParameter X509_KeyFile;
protected:
void shutdown();
@@ -71,8 +72,7 @@ namespace rfb {
bool anon;
- rdr::TLSInStream* tlsis;
- rdr::TLSOutStream* tlsos;
+ rdr::TLSSocket* tlssock;
rdr::InStream* rawis;
rdr::OutStream* rawos;
diff --git a/common/rfb/SSecurityVeNCrypt.cxx b/common/rfb/SSecurityVeNCrypt.cxx
index 4617fddb..757acc06 100644
--- a/common/rfb/SSecurityVeNCrypt.cxx
+++ b/common/rfb/SSecurityVeNCrypt.cxx
@@ -26,15 +26,20 @@
#include <config.h>
#endif
+#include <core/LogWriter.h>
+
+#include <rfb/SConnection.h>
+#include <rfb/SecurityServer.h>
#include <rfb/SSecurityVeNCrypt.h>
#include <rfb/Exception.h>
-#include <rfb/LogWriter.h>
+#include <rfb/Security.h>
+
#include <rdr/InStream.h>
#include <rdr/OutStream.h>
using namespace rfb;
-static LogWriter vlog("SVeNCrypt");
+static core::LogWriter vlog("SVeNCrypt");
SSecurityVeNCrypt::SSecurityVeNCrypt(SConnection* sc_,
SecurityServer *sec)
diff --git a/common/rfb/SSecurityVeNCrypt.h b/common/rfb/SSecurityVeNCrypt.h
index ea2bb6fb..534f94a6 100644
--- a/common/rfb/SSecurityVeNCrypt.h
+++ b/common/rfb/SSecurityVeNCrypt.h
@@ -25,11 +25,13 @@
#ifndef __SSECURITYVENCRYPT_H__
#define __SSECURITYVENCRYPT_H__
-#include <rfb/SSecurityStack.h>
-#include <rfb/SConnection.h>
+#include <rfb/SSecurity.h>
namespace rfb {
+ class SConnection;
+ class SecurityServer;
+
class SSecurityVeNCrypt : public SSecurity {
public:
SSecurityVeNCrypt(SConnection* sc, SecurityServer *sec);
diff --git a/common/rfb/SSecurityVncAuth.cxx b/common/rfb/SSecurityVncAuth.cxx
index 22d88079..b267d5a0 100644
--- a/common/rfb/SSecurityVncAuth.cxx
+++ b/common/rfb/SSecurityVncAuth.cxx
@@ -25,13 +25,17 @@
#include <config.h>
#endif
+#include <core/Configuration.h>
+#include <core/LogWriter.h>
+
+#include <rdr/OutStream.h>
+
#include <rfb/SSecurityVncAuth.h>
#include <rdr/RandomStream.h>
#include <rfb/SConnection.h>
-#include <rfb/Configuration.h>
-#include <rfb/LogWriter.h>
#include <rfb/Exception.h>
#include <rfb/obfuscate.h>
+
#include <assert.h>
#include <string.h>
#include <stdio.h>
@@ -42,12 +46,12 @@ extern "C" {
using namespace rfb;
-static LogWriter vlog("SVncAuth");
+static core::LogWriter vlog("SVncAuth");
-StringParameter SSecurityVncAuth::vncAuthPasswdFile
-("PasswordFile", "Password file for VNC authentication", "", ConfServer);
-AliasParameter rfbauth("rfbauth", "Alias for PasswordFile",
- &SSecurityVncAuth::vncAuthPasswdFile, ConfServer);
+core::StringParameter SSecurityVncAuth::vncAuthPasswdFile
+("PasswordFile", "Password file for VNC authentication", "");
+core::AliasParameter rfbauth("rfbauth", "Alias for PasswordFile",
+ &SSecurityVncAuth::vncAuthPasswdFile);
VncAuthPasswdParameter SSecurityVncAuth::vncAuthPasswd
("Password", "Obfuscated binary encoding of the password which clients must supply to "
"access the server", &SSecurityVncAuth::vncAuthPasswdFile);
@@ -118,8 +122,8 @@ bool SSecurityVncAuth::processMsg()
VncAuthPasswdParameter::VncAuthPasswdParameter(const char* name_,
const char* desc,
- StringParameter* passwdFile_)
-: BinaryParameter(name_, desc, nullptr, 0, ConfServer),
+ core::StringParameter* passwdFile_)
+: core::BinaryParameter(name_, desc, nullptr, 0),
passwdFile(passwdFile_)
{
}
diff --git a/common/rfb/SSecurityVncAuth.h b/common/rfb/SSecurityVncAuth.h
index 532abe0a..e2845337 100644
--- a/common/rfb/SSecurityVncAuth.h
+++ b/common/rfb/SSecurityVncAuth.h
@@ -26,7 +26,8 @@
#include <stdint.h>
-#include <rfb/Configuration.h>
+#include <core/Configuration.h>
+
#include <rfb/SSecurity.h>
#include <rfb/Security.h>
@@ -41,12 +42,12 @@ namespace rfb {
virtual ~VncAuthPasswdGetter() { }
};
- class VncAuthPasswdParameter : public VncAuthPasswdGetter, BinaryParameter {
+ class VncAuthPasswdParameter : public VncAuthPasswdGetter, core::BinaryParameter {
public:
- VncAuthPasswdParameter(const char* name, const char* desc, StringParameter* passwdFile_);
+ VncAuthPasswdParameter(const char* name, const char* desc, core::StringParameter* passwdFile_);
void getVncAuthPasswd(std::string *password, std::string *readOnlyPassword) override;
protected:
- StringParameter* passwdFile;
+ core::StringParameter* passwdFile;
};
class SSecurityVncAuth : public SSecurity {
@@ -56,7 +57,7 @@ namespace rfb {
int getType() const override {return secTypeVncAuth;}
const char* getUserName() const override {return nullptr;}
AccessRights getAccessRights() const override { return accessRights; }
- static StringParameter vncAuthPasswdFile;
+ static core::StringParameter vncAuthPasswdFile;
static VncAuthPasswdParameter vncAuthPasswd;
private:
bool verifyResponse(const char* password);
diff --git a/common/rfb/ScreenSet.h b/common/rfb/ScreenSet.h
index fb93e5c2..10753b17 100644
--- a/common/rfb/ScreenSet.h
+++ b/common/rfb/ScreenSet.h
@@ -25,10 +25,11 @@
#include <string.h>
#include <stdint.h>
-#include <rfb/Rect.h>
#include <list>
#include <set>
+#include <core/Rect.h>
+
namespace rfb {
// rfb::Screen
@@ -52,7 +53,7 @@ namespace rfb {
}
uint32_t id;
- Rect dimensions;
+ core::Rect dimensions;
uint32_t flags;
};
@@ -87,7 +88,7 @@ namespace rfb {
inline bool validate(int fb_width, int fb_height) const {
std::list<Screen>::const_iterator iter;
std::set<uint32_t> seen_ids;
- Rect fb_rect;
+ core::Rect fb_rect;
if (screens.empty())
return false;
diff --git a/common/rfb/Security.cxx b/common/rfb/Security.cxx
index 3b0d95bf..1d4124f9 100644
--- a/common/rfb/Security.cxx
+++ b/common/rfb/Security.cxx
@@ -24,17 +24,19 @@
#include <string.h>
#include <algorithm>
+#include <stdexcept>
+
+#include <core/LogWriter.h>
+#include <core/string.h>
-#include <rfb/LogWriter.h>
#include <rfb/Security.h>
-#include <rfb/util.h>
using namespace rfb;
-static LogWriter vlog("Security");
+static core::LogWriter vlog("Security");
#ifdef HAVE_GNUTLS
-StringParameter Security::GnuTLSPriority("GnuTLSPriority",
+core::StringParameter Security::GnuTLSPriority("GnuTLSPriority",
"GnuTLS priority string that controls the TLS session’s handshake algorithms",
"");
#endif
@@ -43,9 +45,16 @@ Security::Security()
{
}
-Security::Security(StringParameter &secTypes)
+Security::Security(core::EnumListParameter &secTypes)
{
- enabledSecTypes = parseSecTypes(secTypes);
+ for (core::EnumListEntry type : secTypes) {
+ uint32_t typeNum = secTypeNum(type.getValueStr().c_str());
+ // Should have been filtered by EnumListParameter, but let's have
+ // a safety net
+ if (typeNum == secTypeInvalid)
+ throw std::logic_error("Unknown security type");
+ enabledSecTypes.push_back(typeNum);
+ }
}
const std::list<uint8_t> Security::GetEnabledSecTypes(void)
@@ -179,16 +188,3 @@ const char* rfb::secTypeName(uint32_t num)
default: return "[unknown secType]";
}
}
-
-std::list<uint32_t> rfb::parseSecTypes(const char* types_)
-{
- std::list<uint32_t> result;
- std::vector<std::string> types;
- types = split(types_, ',');
- for (size_t i = 0; i < types.size(); i++) {
- uint32_t typeNum = secTypeNum(types[i].c_str());
- if (typeNum != secTypeInvalid)
- result.push_back(typeNum);
- }
- return result;
-}
diff --git a/common/rfb/Security.h b/common/rfb/Security.h
index 430a1d89..40f54c36 100644
--- a/common/rfb/Security.h
+++ b/common/rfb/Security.h
@@ -24,11 +24,15 @@
#include <stdint.h>
-#include <rfb/Configuration.h>
-
#include <list>
+namespace core {
+ class EnumListParameter;
+ class StringParameter;
+}
+
namespace rfb {
+
const uint8_t secTypeInvalid = 0;
const uint8_t secTypeNone = 1;
const uint8_t secTypeVncAuth = 2;
@@ -76,7 +80,7 @@ namespace rfb {
* Create Security instance.
*/
Security();
- Security(StringParameter &secTypes);
+ Security(core::EnumListParameter& secTypes);
/*
* Note about security types.
@@ -105,7 +109,7 @@ namespace rfb {
char *ToString(void);
#ifdef HAVE_GNUTLS
- static StringParameter GnuTLSPriority;
+ static core::StringParameter GnuTLSPriority;
#endif
private:
@@ -114,7 +118,7 @@ namespace rfb {
const char* secTypeName(uint32_t num);
uint32_t secTypeNum(const char* name);
- std::list<uint32_t> parseSecTypes(const char* types);
+
}
#endif
diff --git a/common/rfb/SecurityClient.cxx b/common/rfb/SecurityClient.cxx
index 027d47df..d71941b5 100644
--- a/common/rfb/SecurityClient.cxx
+++ b/common/rfb/SecurityClient.cxx
@@ -25,12 +25,15 @@
#include <stdexcept>
+#include <core/Configuration.h>
+
#include <rfb/CSecurityNone.h>
#include <rfb/CSecurityStack.h>
#include <rfb/CSecurityVeNCrypt.h>
#include <rfb/CSecurityVncAuth.h>
#include <rfb/CSecurityPlain.h>
#include <rfb/Security.h>
+#include <rfb/SecurityClient.h>
#ifdef HAVE_GNUTLS
#include <rfb/CSecurityTLS.h>
#endif
@@ -42,7 +45,7 @@
using namespace rfb;
-StringParameter SecurityClient::secTypes
+core::EnumListParameter SecurityClient::secTypes
("SecurityTypes",
"Specify which security scheme to use (None, VncAuth, Plain"
#ifdef HAVE_GNUTLS
@@ -52,14 +55,22 @@ StringParameter SecurityClient::secTypes
", RA2, RA2ne, RA2_256, RA2ne_256, DH, MSLogonII"
#endif
")",
+ { "None", "VncAuth", "Plain",
+#ifdef HAVE_GNUTLS
+ "TLSNone", "TLSVnc", "TLSPlain", "X509None", "X509Vnc", "X509Plain",
+#endif
+#ifdef HAVE_NETTLE
+ "RA2", "RA2ne", "RA2_256", "RA2ne_256", "DH", "MSLogonII",
+#endif
+ },
+ { "None", "VncAuth", "Plain",
#ifdef HAVE_GNUTLS
- "X509Plain,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone,"
+ "TLSNone", "TLSVnc", "TLSPlain", "X509None", "X509Vnc", "X509Plain",
#endif
#ifdef HAVE_NETTLE
- "RA2,RA2_256,RA2ne,RA2ne_256,DH,MSLogonII,"
+ "RA2", "RA2ne", "RA2_256", "RA2ne_256", "DH", "MSLogonII",
#endif
- "VncAuth,None",
-ConfViewer);
+ });
CSecurity* SecurityClient::GetCSecurity(CConnection* cc, uint32_t secType)
{
diff --git a/common/rfb/SecurityClient.h b/common/rfb/SecurityClient.h
index b86fcb35..11fea417 100644
--- a/common/rfb/SecurityClient.h
+++ b/common/rfb/SecurityClient.h
@@ -22,12 +22,13 @@
#ifndef __RFB_SECURITYCLIENT_H__
#define __RFB_SECURITYCLIENT_H__
-#include <rfb/Configuration.h>
#include <rfb/Security.h>
-#include <rfb/CSecurity.h>
namespace rfb {
+ class CConnection;
+ class CSecurity;
+
class SecurityClient : public Security {
public:
SecurityClient(void) : Security(secTypes) {}
@@ -35,7 +36,7 @@ namespace rfb {
/* Create client side CSecurity class instance */
CSecurity* GetCSecurity(CConnection* cc, uint32_t secType);
- static StringParameter secTypes;
+ static core::EnumListParameter secTypes;
};
}
diff --git a/common/rfb/SecurityServer.cxx b/common/rfb/SecurityServer.cxx
index d692f4fc..207e70f8 100644
--- a/common/rfb/SecurityServer.cxx
+++ b/common/rfb/SecurityServer.cxx
@@ -21,7 +21,11 @@
#include <config.h>
#endif
+#include <stdexcept>
+
#include <rfb/Security.h>
+#include <rfb/SecurityServer.h>
+
#include <rfb/SSecurityNone.h>
#include <rfb/SSecurityStack.h>
#include <rfb/SSecurityPlain.h>
@@ -36,7 +40,7 @@
using namespace rfb;
-StringParameter SecurityServer::secTypes
+core::EnumListParameter SecurityServer::secTypes
("SecurityTypes",
"Specify which security scheme to use (None, VncAuth, Plain"
#ifdef HAVE_GNUTLS
@@ -46,11 +50,19 @@ StringParameter SecurityServer::secTypes
", RA2, RA2ne, RA2_256, RA2ne_256"
#endif
")",
+ { "None", "VncAuth", "Plain",
+#ifdef HAVE_GNUTLS
+ "TLSNone", "TLSVnc", "TLSPlain", "X509None", "X509Vnc", "X509Plain",
+#endif
+#ifdef HAVE_NETTLE
+ "RA2", "RA2ne", "RA2_256", "RA2ne_256",
+#endif
+ },
+ {
#ifdef HAVE_GNUTLS
- "TLSVnc,"
+ "TLSVnc",
#endif
- "VncAuth",
-ConfServer);
+ "VncAuth"});
SSecurity* SecurityServer::GetSSecurity(SConnection* sc, uint32_t secType)
{
diff --git a/common/rfb/SecurityServer.h b/common/rfb/SecurityServer.h
index a51ee23c..0239b36d 100644
--- a/common/rfb/SecurityServer.h
+++ b/common/rfb/SecurityServer.h
@@ -20,7 +20,6 @@
#ifndef __RFB_SECURITYSERVER_H__
#define __RFB_SECURITYSERVER_H__
-#include <rfb/Configuration.h>
#include <rfb/Security.h>
namespace rfb {
@@ -35,7 +34,7 @@ namespace rfb {
/* Create server side SSecurity class instance */
SSecurity* GetSSecurity(SConnection* sc, uint32_t secType);
- static StringParameter secTypes;
+ static core::EnumListParameter secTypes;
};
}
diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx
index 1a80dc0c..302dad71 100644
--- a/common/rfb/ServerCore.cxx
+++ b/common/rfb/ServerCore.cxx
@@ -28,74 +28,74 @@
#include <string.h>
#include <rfb/ServerCore.h>
-rfb::IntParameter rfb::Server::idleTimeout
+core::IntParameter rfb::Server::idleTimeout
("IdleTimeout",
"The number of seconds after which an idle VNC connection will be dropped "
"(zero means no timeout)",
- 0, 0);
-rfb::IntParameter rfb::Server::maxDisconnectionTime
+ 0, 0, INT_MAX);
+core::IntParameter rfb::Server::maxDisconnectionTime
("MaxDisconnectionTime",
"Terminate when no client has been connected for s seconds",
- 0, 0);
-rfb::IntParameter rfb::Server::maxConnectionTime
+ 0, 0, INT_MAX);
+core::IntParameter rfb::Server::maxConnectionTime
("MaxConnectionTime",
"Terminate when a client has been connected for s seconds",
- 0, 0);
-rfb::IntParameter rfb::Server::maxIdleTime
+ 0, 0, INT_MAX);
+core::IntParameter rfb::Server::maxIdleTime
("MaxIdleTime",
"Terminate after s seconds of user inactivity",
- 0, 0);
-rfb::IntParameter rfb::Server::compareFB
+ 0, 0, INT_MAX);
+core::IntParameter rfb::Server::compareFB
("CompareFB",
"Perform pixel comparison on framebuffer to reduce unnecessary updates "
"(0: never, 1: always, 2: auto)",
- 2);
-rfb::IntParameter rfb::Server::frameRate
+ 2, 0, 2);
+core::IntParameter rfb::Server::frameRate
("FrameRate",
"The maximum number of updates per second sent to each client",
- 60);
-rfb::BoolParameter rfb::Server::protocol3_3
+ 60, 0, INT_MAX);
+core::BoolParameter rfb::Server::protocol3_3
("Protocol3.3",
"Always use protocol version 3.3 for backwards compatibility with "
"badly-behaved clients",
false);
-rfb::BoolParameter rfb::Server::alwaysShared
+core::BoolParameter rfb::Server::alwaysShared
("AlwaysShared",
"Always treat incoming connections as shared, regardless of the client-"
"specified setting",
false);
-rfb::BoolParameter rfb::Server::neverShared
+core::BoolParameter rfb::Server::neverShared
("NeverShared",
"Never treat incoming connections as shared, regardless of the client-"
"specified setting",
false);
-rfb::BoolParameter rfb::Server::disconnectClients
+core::BoolParameter rfb::Server::disconnectClients
("DisconnectClients",
"Disconnect existing clients if an incoming connection is non-shared. "
"If combined with NeverShared then new connections will be refused "
"while there is a client active",
true);
-rfb::BoolParameter rfb::Server::acceptKeyEvents
+core::BoolParameter rfb::Server::acceptKeyEvents
("AcceptKeyEvents",
"Accept key press and release events from clients.",
true);
-rfb::BoolParameter rfb::Server::acceptPointerEvents
+core::BoolParameter rfb::Server::acceptPointerEvents
("AcceptPointerEvents",
"Accept pointer movement and button events from clients.",
true);
-rfb::BoolParameter rfb::Server::acceptCutText
+core::BoolParameter rfb::Server::acceptCutText
("AcceptCutText",
"Accept clipboard updates from clients.",
true);
-rfb::BoolParameter rfb::Server::sendCutText
+core::BoolParameter rfb::Server::sendCutText
("SendCutText",
"Send clipboard changes to clients.",
true);
-rfb::BoolParameter rfb::Server::acceptSetDesktopSize
+core::BoolParameter rfb::Server::acceptSetDesktopSize
("AcceptSetDesktopSize",
"Accept set desktop size events from clients.",
true);
-rfb::BoolParameter rfb::Server::queryConnect
+core::BoolParameter rfb::Server::queryConnect
("QueryConnect",
"Prompt the local user to accept or reject incoming connections.",
false);
diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h
index 69cad39f..a7c7f309 100644
--- a/common/rfb/ServerCore.h
+++ b/common/rfb/ServerCore.h
@@ -24,29 +24,29 @@
#ifndef __RFB_SERVER_CORE_H__
#define __RFB_SERVER_CORE_H__
-#include <rfb/Configuration.h>
+#include <core/Configuration.h>
namespace rfb {
class Server {
public:
- static IntParameter idleTimeout;
- static IntParameter maxDisconnectionTime;
- static IntParameter maxConnectionTime;
- static IntParameter maxIdleTime;
- static IntParameter compareFB;
- static IntParameter frameRate;
- static BoolParameter protocol3_3;
- static BoolParameter alwaysShared;
- static BoolParameter neverShared;
- static BoolParameter disconnectClients;
- static BoolParameter acceptKeyEvents;
- static BoolParameter acceptPointerEvents;
- static BoolParameter acceptCutText;
- static BoolParameter sendCutText;
- static BoolParameter acceptSetDesktopSize;
- static BoolParameter queryConnect;
+ static core::IntParameter idleTimeout;
+ static core::IntParameter maxDisconnectionTime;
+ static core::IntParameter maxConnectionTime;
+ static core::IntParameter maxIdleTime;
+ static core::IntParameter compareFB;
+ static core::IntParameter frameRate;
+ static core::BoolParameter protocol3_3;
+ static core::BoolParameter alwaysShared;
+ static core::BoolParameter neverShared;
+ static core::BoolParameter disconnectClients;
+ static core::BoolParameter acceptKeyEvents;
+ static core::BoolParameter acceptPointerEvents;
+ static core::BoolParameter acceptCutText;
+ static core::BoolParameter sendCutText;
+ static core::BoolParameter acceptSetDesktopSize;
+ static core::BoolParameter queryConnect;
};
diff --git a/common/rfb/ServerParams.cxx b/common/rfb/ServerParams.cxx
index b7432b8f..4b8f6136 100644
--- a/common/rfb/ServerParams.cxx
+++ b/common/rfb/ServerParams.cxx
@@ -24,12 +24,18 @@
#include <stdexcept>
+#include <core/LogWriter.h>
+#include <core/string.h>
+
#include <rfb/ledStates.h>
+#include <rfb/Cursor.h>
+#include <rfb/ScreenSet.h>
#include <rfb/ServerParams.h>
-#include <rfb/util.h>
using namespace rfb;
+static core::LogWriter vlog("ServerParams");
+
ServerParams::ServerParams()
: majorVersion(0), minorVersion(0),
supportsQEMUKeyEvent(false),
@@ -40,7 +46,11 @@ ServerParams::ServerParams()
{
setName("");
- cursor_ = new Cursor(0, 0, Point(), nullptr);
+ screenLayout_ = new ScreenSet();
+
+ pf_ = new PixelFormat();
+
+ cursor_ = new Cursor(0, 0, {}, nullptr);
clipFlags = 0;
memset(clipSizes, 0, sizeof(clipSizes));
@@ -60,17 +70,25 @@ void ServerParams::setDimensions(int width, int height)
void ServerParams::setDimensions(int width, int height, const ScreenSet& layout)
{
- if (!layout.validate(width, height))
+ if (!layout.validate(width, height)) {
+ char buffer[2048];
+ vlog.debug("Invalid screen layout for %dx%d:", width, height);
+ layout.print(buffer, sizeof(buffer));
+ vlog.debug("%s", buffer);
+
throw std::invalid_argument("Attempted to configure an invalid screen layout");
+ }
width_ = width;
height_ = height;
- screenLayout_ = layout;
+ delete screenLayout_;
+ screenLayout_ = new ScreenSet(layout);
}
void ServerParams::setPF(const PixelFormat& pf)
{
- pf_ = pf;
+ delete pf_;
+ pf_ = new PixelFormat(pf);
if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)
throw std::invalid_argument("setPF: Not 8, 16 or 32 bpp?");
@@ -101,7 +119,8 @@ uint32_t ServerParams::clipboardSize(unsigned int format) const
return clipSizes[i];
}
- throw std::invalid_argument(rfb::format("Invalid clipboard format 0x%x", format));
+ throw std::invalid_argument(
+ core::format("Invalid clipboard format 0x%x", format));
}
void ServerParams::setClipboardCaps(uint32_t flags, const uint32_t* lengths)
diff --git a/common/rfb/ServerParams.h b/common/rfb/ServerParams.h
index d730b891..6be9acd6 100644
--- a/common/rfb/ServerParams.h
+++ b/common/rfb/ServerParams.h
@@ -25,12 +25,12 @@
#include <string>
-#include <rfb/Cursor.h>
-#include <rfb/PixelFormat.h>
-#include <rfb/ScreenSet.h>
-
namespace rfb {
+ class Cursor;
+ class PixelFormat;
+ struct ScreenSet;
+
class ServerParams {
public:
ServerParams();
@@ -55,11 +55,11 @@ namespace rfb {
int width() const { return width_; }
int height() const { return height_; }
- const ScreenSet& screenLayout() const { return screenLayout_; }
+ 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_; }
+ const PixelFormat& pf() const { return *pf_; }
void setPF(const PixelFormat& pf);
const char* name() const { return name_.c_str(); }
@@ -85,9 +85,9 @@ namespace rfb {
int width_;
int height_;
- ScreenSet screenLayout_;
+ ScreenSet* screenLayout_;
- PixelFormat pf_;
+ PixelFormat* pf_;
std::string name_;
Cursor* cursor_;
unsigned int ledState_;
diff --git a/common/rfb/TightDecoder.cxx b/common/rfb/TightDecoder.cxx
index a26c0bfe..da0d5865 100644
--- a/common/rfb/TightDecoder.cxx
+++ b/common/rfb/TightDecoder.cxx
@@ -27,16 +27,18 @@
#include <vector>
+#include <core/string.h>
+
#include <rdr/InStream.h>
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
#include <rfb/ServerParams.h>
#include <rfb/Exception.h>
+#include <rfb/JpegDecompressor.h>
#include <rfb/PixelBuffer.h>
#include <rfb/TightConstants.h>
#include <rfb/TightDecoder.h>
-#include <rfb/util.h>
using namespace rfb;
@@ -51,7 +53,7 @@ TightDecoder::~TightDecoder()
{
}
-bool TightDecoder::readRect(const Rect& r, rdr::InStream* is,
+bool TightDecoder::readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server, rdr::OutStream* os)
{
uint8_t comp_ctl;
@@ -111,7 +113,8 @@ bool TightDecoder::readRect(const Rect& r, rdr::InStream* is,
int palSize = 0;
if (r.width() > TIGHT_MAX_WIDTH)
- throw protocol_error(format("TightDecoder: Too large rectangle (%d pixels)", r.width()));
+ throw protocol_error(core::format(
+ "TightDecoder: Too large rectangle (%d pixels)", r.width()));
// Possible palette
if ((comp_ctl & tightExplicitFilter) != 0) {
@@ -192,10 +195,10 @@ bool TightDecoder::readRect(const Rect& r, rdr::InStream* is,
return true;
}
-bool TightDecoder::doRectsConflict(const Rect& /*rectA*/,
+bool TightDecoder::doRectsConflict(const core::Rect& /*rectA*/,
const uint8_t* bufferA,
size_t buflenA,
- const Rect& /*rectB*/,
+ const core::Rect& /*rectB*/,
const uint8_t* bufferB,
size_t buflenB,
const ServerParams& /*server*/)
@@ -220,7 +223,7 @@ bool TightDecoder::doRectsConflict(const Rect& /*rectA*/,
return false;
}
-void TightDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
+void TightDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
@@ -506,7 +509,7 @@ uint32_t TightDecoder::readCompact(rdr::InStream* is)
void
TightDecoder::FilterGradient24(const uint8_t *inbuf,
const PixelFormat& pf, uint32_t* outbuf,
- int stride, const Rect& r)
+ int stride, const core::Rect& r)
{
int x, y, c;
uint8_t prevRow[TIGHT_MAX_WIDTH*3];
@@ -552,7 +555,7 @@ TightDecoder::FilterGradient24(const uint8_t *inbuf,
template<class T>
void TightDecoder::FilterGradient(const uint8_t* inbuf,
const PixelFormat& pf, T* outbuf,
- int stride, const Rect& r)
+ int stride, const core::Rect& r)
{
int x, y, c;
static uint8_t prevRow[TIGHT_MAX_WIDTH*3];
@@ -606,7 +609,7 @@ void TightDecoder::FilterGradient(const uint8_t* inbuf,
template<class T>
void TightDecoder::FilterPalette(const T* palette, int palSize,
const uint8_t* inbuf, T* outbuf,
- int stride, const Rect& r)
+ int stride, const core::Rect& r)
{
// Indexed color
int x, h = r.height(), w = r.width(), b, pad = stride - w;
diff --git a/common/rfb/TightDecoder.h b/common/rfb/TightDecoder.h
index d569a7fd..a75fc7da 100644
--- a/common/rfb/TightDecoder.h
+++ b/common/rfb/TightDecoder.h
@@ -22,7 +22,6 @@
#include <rdr/ZlibInStream.h>
#include <rfb/Decoder.h>
-#include <rfb/JpegDecompressor.h>
namespace rfb {
@@ -31,15 +30,15 @@ namespace rfb {
public:
TightDecoder();
virtual ~TightDecoder();
- bool readRect(const Rect& r, rdr::InStream* is,
+ bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server,
rdr::OutStream* os) override;
- bool doRectsConflict(const Rect& rectA,
+ bool doRectsConflict(const core::Rect& rectA,
const uint8_t* bufferA, size_t buflenA,
- const Rect& rectB,
+ const core::Rect& rectB,
const uint8_t* bufferB, size_t buflenB,
const ServerParams& server) override;
- void decodeRect(const Rect& r, const uint8_t* buffer,
+ void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb) override;
@@ -47,16 +46,16 @@ namespace rfb {
uint32_t readCompact(rdr::InStream* is);
void FilterGradient24(const uint8_t* inbuf, const PixelFormat& pf,
- uint32_t* outbuf, int stride, const Rect& r);
+ uint32_t* outbuf, int stride, const core::Rect& r);
template<class T>
void FilterGradient(const uint8_t* inbuf, const PixelFormat& pf,
- T* outbuf, int stride, const Rect& r);
+ T* outbuf, int stride, const core::Rect& r);
template<class T>
void FilterPalette(const T* palette, int palSize,
const uint8_t* inbuf, T* outbuf,
- int stride, const Rect& r);
+ int stride, const core::Rect& r);
private:
rdr::ZlibInStream zis[4];
diff --git a/common/rfb/Timer.cxx b/common/rfb/Timer.cxx
deleted file mode 100644
index 6f7ec7ba..00000000
--- a/common/rfb/Timer.cxx
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2016-2024 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.
- */
-
-// -=- Timer.cxx
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/time.h>
-
-#include <algorithm>
-
-#include <rfb/Timer.h>
-#include <rfb/util.h>
-#include <rfb/LogWriter.h>
-
-using namespace rfb;
-
-#ifndef __NO_DEFINE_VLOG__
-static LogWriter vlog("Timer");
-#endif
-
-
-// Millisecond timeout processing helper functions
-
-inline static timeval addMillis(timeval inTime, int millis) {
- int secs = millis / 1000;
- millis = millis % 1000;
- inTime.tv_sec += secs;
- inTime.tv_usec += millis * 1000;
- if (inTime.tv_usec >= 1000000) {
- inTime.tv_sec++;
- inTime.tv_usec -= 1000000;
- }
- return inTime;
-}
-
-inline static int diffTimeMillis(timeval later, timeval earlier) {
- long udiff;
- udiff = ((later.tv_sec - earlier.tv_sec) * 1000000) +
- (later.tv_usec - earlier.tv_usec);
- return (udiff + 999) / 1000;
-}
-
-std::list<Timer*> Timer::pending;
-
-int Timer::checkTimeouts() {
- timeval start;
-
- if (pending.empty())
- return -1;
-
- gettimeofday(&start, nullptr);
- while (pending.front()->isBefore(start)) {
- Timer* timer;
-
- timer = pending.front();
- pending.pop_front();
-
- timer->lastDueTime = timer->dueTime;
- timer->cb->handleTimeout(timer);
-
- if (pending.empty())
- return -1;
- }
- return getNextTimeout();
-}
-
-int Timer::getNextTimeout() {
- timeval now;
- gettimeofday(&now, nullptr);
-
- if (pending.empty())
- return -1;
-
- int toWait = pending.front()->getRemainingMs();
-
- if (toWait > pending.front()->timeoutMs) {
- if (toWait - pending.front()->timeoutMs < 1000) {
- vlog.info("gettimeofday is broken...");
- return toWait;
- }
- // Time has jumped backwards!
- vlog.info("Time has moved backwards!");
- pending.front()->dueTime = now;
- toWait = 0;
- }
-
- return toWait;
-}
-
-void Timer::insertTimer(Timer* t) {
- std::list<Timer*>::iterator i;
- for (i=pending.begin(); i!=pending.end(); i++) {
- if (t->isBefore((*i)->dueTime)) {
- pending.insert(i, t);
- return;
- }
- }
- pending.push_back(t);
-}
-
-void Timer::start(int timeoutMs_) {
- timeval now;
- gettimeofday(&now, nullptr);
- stop();
- timeoutMs = timeoutMs_;
- dueTime = addMillis(now, timeoutMs);
- insertTimer(this);
-}
-
-void Timer::repeat(int timeoutMs_) {
- timeval now;
-
- gettimeofday(&now, nullptr);
-
- if (isStarted()) {
- vlog.error("Incorrectly repeating already running timer");
- stop();
- }
-
- if (msBetween(&lastDueTime, &dueTime) != 0)
- vlog.error("Timer incorrectly modified whilst repeating");
-
- if (timeoutMs_ != -1)
- timeoutMs = timeoutMs_;
-
- dueTime = addMillis(lastDueTime, timeoutMs);
- if (isBefore(now)) {
- // Time has jumped forwards, or we're not getting enough
- // CPU time for the timers
- dueTime = now;
- }
-
- insertTimer(this);
-}
-
-void Timer::stop() {
- pending.remove(this);
-}
-
-bool Timer::isStarted() {
- return std::find(pending.begin(), pending.end(),
- this) != pending.end();
-}
-
-int Timer::getTimeoutMs() {
- return timeoutMs;
-}
-
-int Timer::getRemainingMs() {
- timeval now;
- gettimeofday(&now, nullptr);
- return __rfbmax(0, diffTimeMillis(dueTime, now));
-}
-
-bool Timer::isBefore(timeval other) {
- return (dueTime.tv_sec < other.tv_sec) ||
- ((dueTime.tv_sec == other.tv_sec) &&
- (dueTime.tv_usec < other.tv_usec));
-}
diff --git a/common/rfb/Timer.h b/common/rfb/Timer.h
deleted file mode 100644
index 362cb84e..00000000
--- a/common/rfb/Timer.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2018-2024 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_TIMER_H__
-#define __RFB_TIMER_H__
-
-#include <list>
-#include <sys/time.h>
-
-namespace rfb {
-
- /* Timer
-
- Cross-platform timeout handling. The caller creates instances of
- Timer and passes a Callback implementation to each. The Callback
- will then be called with a pointer to the Timer instance that
- timed-out when the timeout occurs.
-
- The static methods of Timer are used by the main loop of the
- application both to dispatch elapsed Timer callbacks and to
- determine how long to wait in select() for the next timeout to
- occur.
-
- For classes that can be derived it's best to use MethodTimer which
- can call a specific method on the class, thus avoiding conflicts
- when subclassing.
- */
-
- struct Timer {
-
- struct Callback {
- // handleTimeout
- // Passed a pointer to the Timer that has timed out. If the
- // handler returns true then the Timer is reset and left
- // running, causing another timeout after the appropriate
- // interval.
- // If the handler returns false then the Timer is cancelled.
- virtual void handleTimeout(Timer* t) = 0;
-
- virtual ~Callback() {}
- };
-
- // checkTimeouts()
- // Dispatches any elapsed Timers, and returns the number of
- // milliseconds until the next Timer will timeout.
- static int checkTimeouts();
-
- // getNextTimeout()
- // Returns the number of milliseconds until the next timeout,
- // without dispatching any elapsed Timers.
- static int getNextTimeout();
-
- // Create a Timer with the specified callback handler
- Timer(Callback* cb_) {cb = cb_;}
- ~Timer() {stop();}
-
- // start()
- // Starts the timer, causing a timeout after the specified number
- // of milliseconds. If the timer is already active then it will
- // be implicitly cancelled and re-started.
- void start(int timeoutMs_);
-
- // repeat()
- // Restarts the timer in a way that repeats that last timeout.
- // This allows you to have a periodic timer without the risk of
- // accumulating drift caused by processing delays.
- // A new interval can be specified, otherwise the previous
- // interval is reused.
- void repeat(int timeoutMs_=-1);
-
- // stop()
- // Cancels the timer.
- void stop();
-
- // isStarted()
- // Determines whether the timer is started.
- bool isStarted();
-
- // getTimeoutMs()
- // Determines the previously used timeout value, if any.
- // Usually used with isStarted() to get the _current_ timeout.
- int getTimeoutMs();
-
- // getRemainingMs()
- // Determines how many milliseconds are left before the Timer
- // will timeout. Only valid for an active timer.
- int getRemainingMs();
-
- // isBefore()
- // Determine whether the Timer will timeout before the specified
- // time.
- bool isBefore(timeval other);
-
- protected:
- timeval dueTime, lastDueTime;
- int timeoutMs;
- Callback* cb;
-
- static void insertTimer(Timer* t);
- // The list of currently active Timers, ordered by time left until
- // timeout.
- static std::list<Timer*> pending;
- };
-
- template<class T> class MethodTimer
- : public Timer, public Timer::Callback {
- public:
- MethodTimer(T* obj_, void (T::*cb_)(Timer*))
- : Timer(this), obj(obj_), cb(cb_) {}
-
- void handleTimeout(Timer* t) override { return (obj->*cb)(t); }
-
- private:
- T* obj;
- void (T::*cb)(Timer*);
- };
-
-};
-
-#endif
diff --git a/common/rfb/UnixPasswordValidator.cxx b/common/rfb/UnixPasswordValidator.cxx
index 57fa9b39..8239463a 100644
--- a/common/rfb/UnixPasswordValidator.cxx
+++ b/common/rfb/UnixPasswordValidator.cxx
@@ -22,24 +22,119 @@
#include <config.h>
#endif
-#include <rfb/Configuration.h>
-#include <rfb/Exception.h>
+#include <assert.h>
+#include <string.h>
+#include <security/pam_appl.h>
+
+#include <core/Configuration.h>
+#include <core/LogWriter.h>
+
#include <rfb/UnixPasswordValidator.h>
-#include <rfb/pam.h>
using namespace rfb;
-static StringParameter pamService
+static core::LogWriter vlog("UnixPasswordValidator");
+
+static core::StringParameter pamService
("PAMService", "Service name for PAM password validation", "vnc");
-AliasParameter pam_service("pam_service", "Alias for PAMService",
- &pamService);
+core::AliasParameter pam_service("pam_service", "Alias for PAMService",
+ &pamService);
-int do_pam_auth(const char *service, const char *username,
- const char *password);
+std::string UnixPasswordValidator::displayName;
-bool UnixPasswordValidator::validateInternal(SConnection * /*sc*/,
+typedef struct
+{
+ const char *username;
+ const char *password;
+ std::string &msg;
+} AuthData;
+
+#if defined(__sun)
+static int pam_callback(int count, struct pam_message **in,
+ struct pam_response **out, void *ptr)
+#else
+static int pam_callback(int count, const struct pam_message **in,
+ struct pam_response **out, void *ptr)
+#endif
+{
+ int i;
+ AuthData *auth = (AuthData *) ptr;
+ struct pam_response *resp =
+ (struct pam_response *) malloc (sizeof (struct pam_response) * count);
+
+ if (!resp && count)
+ return PAM_CONV_ERR;
+
+ for (i = 0; i < count; i++) {
+ resp[i].resp_retcode = PAM_SUCCESS;
+ switch (in[i]->msg_style) {
+ case PAM_TEXT_INFO:
+ vlog.info("%s info: %s", (const char *) pamService, in[i]->msg);
+ auth->msg = in[i]->msg;
+ resp[i].resp = nullptr;
+ break;
+ case PAM_ERROR_MSG:
+ vlog.error("%s error: %s", (const char *) pamService, in[i]->msg);
+ auth->msg = in[i]->msg;
+ resp[i].resp = nullptr;
+ break;
+ case PAM_PROMPT_ECHO_ON: /* Send Username */
+ resp[i].resp = strdup(auth->username);
+ break;
+ case PAM_PROMPT_ECHO_OFF: /* Send Password */
+ resp[i].resp = strdup(auth->password);
+ break;
+ default:
+ free(resp);
+ return PAM_CONV_ERR;
+ }
+ }
+
+ *out = resp;
+ return PAM_SUCCESS;
+}
+
+bool UnixPasswordValidator::validateInternal(SConnection * /* sc */,
const char *username,
- const char *password)
+ const char *password,
+ std::string &msg)
{
- return do_pam_auth(pamService, username, password);
+ int ret;
+ AuthData auth = { username, password, msg };
+ struct pam_conv conv = {
+ pam_callback,
+ &auth
+ };
+ pam_handle_t *pamh = nullptr;
+ ret = pam_start(pamService, username, &conv, &pamh);
+ if (ret != PAM_SUCCESS) {
+ /* Can't call pam_strerror() here because the content of pamh undefined */
+ vlog.error("pam_start(%s) failed: %d", (const char *) pamService, ret);
+ return false;
+ }
+#ifdef PAM_XDISPLAY
+ /* At this point, displayName should never be empty */
+ assert(displayName.length() > 0);
+ /* Pass the display name to PAM modules but PAM_XDISPLAY may not be
+ * recognized by modules built with old versions of PAM */
+ ret = pam_set_item(pamh, PAM_XDISPLAY, displayName.c_str());
+ if (ret != PAM_SUCCESS && ret != PAM_BAD_ITEM) {
+ vlog.error("pam_set_item(PAM_XDISPLAY) failed: %d (%s)", ret, pam_strerror(pamh, ret));
+ goto error;
+ }
+#endif
+ ret = pam_authenticate(pamh, 0);
+ if (ret != PAM_SUCCESS) {
+ vlog.error("pam_authenticate() failed: %d (%s)", ret, pam_strerror(pamh, ret));
+ goto error;
+ }
+ ret = pam_acct_mgmt(pamh, 0);
+ if (ret != PAM_SUCCESS) {
+ vlog.error("pam_acct_mgmt() failed: %d (%s)", ret, pam_strerror(pamh, ret));
+ goto error;
+ }
+ return true;
+error:
+ pam_end(pamh, ret);
+ return false;
}
diff --git a/common/rfb/UnixPasswordValidator.h b/common/rfb/UnixPasswordValidator.h
index 4d623d6c..a2cc89c5 100644
--- a/common/rfb/UnixPasswordValidator.h
+++ b/common/rfb/UnixPasswordValidator.h
@@ -26,9 +26,19 @@
namespace rfb
{
class UnixPasswordValidator: public PasswordValidator {
+ public:
+ static void setDisplayName(const std::string& display) {
+ displayName = display;
+ }
+
protected:
- bool validateInternal(SConnection * sc, const char *username,
- const char *password) override;
+ bool validateInternal(SConnection *sc,
+ const char *username,
+ const char *password,
+ std::string &msg) override;
+
+ private:
+ static std::string displayName;
};
}
diff --git a/common/rfb/UpdateTracker.cxx b/common/rfb/UpdateTracker.cxx
index 7c97a6b8..1aedf491 100644
--- a/common/rfb/UpdateTracker.cxx
+++ b/common/rfb/UpdateTracker.cxx
@@ -25,27 +25,31 @@
#include <config.h>
#endif
+#include <core/LogWriter.h>
+
#include <rfb/UpdateTracker.h>
-#include <rfb/LogWriter.h>
using namespace rfb;
-static LogWriter vlog("UpdateTracker");
+static core::LogWriter vlog("UpdateTracker");
// -=- ClippingUpdateTracker
-void ClippingUpdateTracker::add_changed(const Region &region) {
+void ClippingUpdateTracker::add_changed(const core::Region& region)
+{
ut->add_changed(region.intersect(clipRect));
}
-void ClippingUpdateTracker::add_copied(const Region &dest, const Point &delta) {
+void ClippingUpdateTracker::add_copied(const core::Region& dest,
+ const core::Point& delta)
+{
// Clip the destination to the display area
- Region clipdest = dest.intersect(clipRect);
+ core::Region clipdest = dest.intersect(clipRect);
if (clipdest.is_empty()) return;
// Clip the source to the screen
- Region tmp = clipdest;
+ core::Region tmp = clipdest;
tmp.translate(delta.negate());
tmp.assign_intersect(clipRect);
if (!tmp.is_empty()) {
@@ -70,25 +74,28 @@ SimpleUpdateTracker::SimpleUpdateTracker() {
SimpleUpdateTracker::~SimpleUpdateTracker() {
}
-void SimpleUpdateTracker::add_changed(const Region &region) {
+void SimpleUpdateTracker::add_changed(const core::Region& region)
+{
changed.assign_union(region);
}
-void SimpleUpdateTracker::add_copied(const Region &dest, const Point &delta) {
+void SimpleUpdateTracker::add_copied(const core::Region& dest,
+ const core::Point& delta)
+{
// Is there anything to do?
if (dest.is_empty()) return;
// Calculate whether any of this copy can be treated as a continuation
// of an earlier one
- Region src = dest;
+ core::Region src = dest;
src.translate(delta.negate());
- Region overlap = src.intersect(copied);
+ core::Region overlap = src.intersect(copied);
if (overlap.is_empty()) {
// There is no overlap
- Rect newbr = dest.get_bounding_rect();
- Rect oldbr = copied.get_bounding_rect();
+ core::Rect newbr = dest.get_bounding_rect();
+ core::Rect oldbr = copied.get_bounding_rect();
if (oldbr.area() > newbr.area()) {
// Old copyrect is (probably) bigger - use it
changed.assign_union(dest);
@@ -97,7 +104,7 @@ void SimpleUpdateTracker::add_copied(const Region &dest, const Point &delta) {
// Use the new one
// But be careful not to copy stuff that still needs
// to be updated.
- Region invalid_src = src.intersect(changed);
+ core::Region invalid_src = src.intersect(changed);
invalid_src.translate(delta);
changed.assign_union(invalid_src);
changed.assign_union(copied);
@@ -107,13 +114,13 @@ void SimpleUpdateTracker::add_copied(const Region &dest, const Point &delta) {
return;
}
- Region invalid_src = overlap.intersect(changed);
+ core::Region invalid_src = overlap.intersect(changed);
invalid_src.translate(delta);
changed.assign_union(invalid_src);
overlap.translate(delta);
- Region nonoverlapped_copied = dest.union_(copied).subtract(overlap);
+ core::Region nonoverlapped_copied = dest.union_(copied).subtract(overlap);
changed.assign_union(nonoverlapped_copied);
copied = overlap;
@@ -122,12 +129,14 @@ void SimpleUpdateTracker::add_copied(const Region &dest, const Point &delta) {
return;
}
-void SimpleUpdateTracker::subtract(const Region& region) {
+void SimpleUpdateTracker::subtract(const core::Region& region)
+{
copied.assign_subtract(region);
changed.assign_subtract(region);
}
-void SimpleUpdateTracker::getUpdateInfo(UpdateInfo* info, const Region& clip)
+void SimpleUpdateTracker::getUpdateInfo(UpdateInfo* info,
+ const core::Region& clip)
{
copied.assign_subtract(changed);
info->changed = changed.intersect(clip);
diff --git a/common/rfb/UpdateTracker.h b/common/rfb/UpdateTracker.h
index e91b9621..3d7a2fcd 100644
--- a/common/rfb/UpdateTracker.h
+++ b/common/rfb/UpdateTracker.h
@@ -19,17 +19,16 @@
#ifndef __RFB_UPDATETRACKER_INCLUDED__
#define __RFB_UPDATETRACKER_INCLUDED__
-#include <rfb/Rect.h>
-#include <rfb/Region.h>
-#include <rfb/PixelBuffer.h>
+#include <core/Rect.h>
+#include <core/Region.h>
namespace rfb {
class UpdateInfo {
public:
- Region changed;
- Region copied;
- Point copy_delta;
+ core::Region changed;
+ core::Region copied;
+ core::Point copy_delta;
bool is_empty() const {
return copied.is_empty() && changed.is_empty();
}
@@ -47,23 +46,25 @@ namespace rfb {
UpdateTracker() {};
virtual ~UpdateTracker() {};
- virtual void add_changed(const Region &region) = 0;
- virtual void add_copied(const Region &dest, const Point &delta) = 0;
+ virtual void add_changed(const core::Region& region) = 0;
+ virtual void add_copied(const core::Region& dest,
+ const core::Point& delta) = 0;
};
class ClippingUpdateTracker : public UpdateTracker {
public:
ClippingUpdateTracker() : ut(nullptr) {}
- ClippingUpdateTracker(UpdateTracker* ut_, const Rect& r=Rect()) : ut(ut_), clipRect(r) {}
+ ClippingUpdateTracker(UpdateTracker* ut_, const core::Rect& r={}) : ut(ut_), clipRect(r) {}
void setUpdateTracker(UpdateTracker* ut_) {ut = ut_;}
- void setClipRect(const Rect& cr) {clipRect = cr;}
+ void setClipRect(const core::Rect& cr) {clipRect = cr;}
- void add_changed(const Region &region) override;
- void add_copied(const Region &dest, const Point &delta) override;
+ void add_changed(const core::Region& region) override;
+ void add_copied(const core::Region& dest,
+ const core::Point& delta) override;
protected:
UpdateTracker* ut;
- Rect clipRect;
+ core::Rect clipRect;
};
class SimpleUpdateTracker : public UpdateTracker {
@@ -71,27 +72,29 @@ namespace rfb {
SimpleUpdateTracker();
virtual ~SimpleUpdateTracker();
- void add_changed(const Region &region) override;
- void add_copied(const Region &dest, const Point &delta) override;
- virtual void subtract(const Region& region);
+ void add_changed(const core::Region& region) override;
+ void add_copied(const core::Region& dest,
+ const core::Point& delta) override;
+ virtual void subtract(const core::Region& region);
// Fill the supplied UpdateInfo structure with update information
// FIXME: Provide getUpdateInfo() with no clipping, for better efficiency.
- virtual void getUpdateInfo(UpdateInfo* info, const Region& cliprgn);
+ virtual void getUpdateInfo(UpdateInfo* info,
+ const core::Region& cliprgn);
// Copy the contained updates to another tracker
virtual void copyTo(UpdateTracker* to) const;
// Move the entire update region by an offset
- void translate(const Point& p) {changed.translate(p); copied.translate(p);}
+ void translate(const core::Point& p) {changed.translate(p); copied.translate(p);}
virtual bool is_empty() const {return changed.is_empty() && copied.is_empty();}
virtual void clear() {changed.clear(); copied.clear();};
protected:
- Region changed;
- Region copied;
- Point copy_delta;
+ core::Region changed;
+ core::Region copied;
+ core::Point copy_delta;
};
}
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index a354f636..2d77fae6 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -22,7 +22,12 @@
#include <config.h>
#endif
-#include <rdr/Exception.h>
+#include <core/LogWriter.h>
+#include <core/string.h>
+#include <core/time.h>
+
+#include <rdr/FdInStream.h>
+#include <rdr/FdOutStream.h>
#include <network/TcpSocket.h>
@@ -31,12 +36,12 @@
#include <rfb/Exception.h>
#include <rfb/KeyRemapper.h>
#include <rfb/KeysymStr.h>
-#include <rfb/LogWriter.h>
#include <rfb/Security.h>
#include <rfb/ServerCore.h>
#include <rfb/SMsgWriter.h>
#include <rfb/VNCServerST.h>
#include <rfb/VNCSConnectionST.h>
+#include <rfb/encodings.h>
#include <rfb/screenTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/ledStates.h>
@@ -44,13 +49,12 @@
#define XK_MISCELLANY
#define XK_XKB_KEYS
#include <rfb/keysymdef.h>
-#include <rfb/util.h>
using namespace rfb;
-static LogWriter vlog("VNCSConnST");
+static core::LogWriter vlog("VNCSConnST");
-static Cursor emptyCursor(0, 0, Point(0, 0), nullptr);
+static Cursor emptyCursor(0, 0, {0, 0}, nullptr);
VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
bool reverse, AccessRights ar)
@@ -71,9 +75,9 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
if (rfb::Server::idleTimeout) {
// minimum of 15 seconds while authenticating
if (rfb::Server::idleTimeout < 15)
- idleTimer.start(secsToMillis(15));
+ idleTimer.start(core::secsToMillis(15));
else
- idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));
}
}
@@ -216,11 +220,11 @@ void VNCSConnectionST::pixelBufferChange()
//updates.intersect(server->pb->getRect());
//
//if (server->pb->width() > client.width())
- // updates.add_changed(Rect(client.width(), 0, server->pb->width(),
- // server->pb->height()));
+ // updates.add_changed({client.width(), 0, server->pb->width(),
+ // server->pb->height()});
//if (server->pb->height() > client.height())
- // updates.add_changed(Rect(0, client.height(), client.width(),
- // server->pb->height()));
+ // updates.add_changed({0, client.height(), client.width(),
+ // server->pb->height()});
damagedCursorRegion.assign_intersect(server->getPixelBuffer()->getRect());
@@ -236,7 +240,7 @@ void VNCSConnectionST::pixelBufferChange()
}
// Drop any lossy tracking that is now outside the framebuffer
- encodeManager.pruneLosslessRefresh(Region(server->getPixelBuffer()->getRect()));
+ encodeManager.pruneLosslessRefresh(server->getPixelBuffer()->getRect());
}
// Just update the whole screen at the moment because we're too lazy to
// work out what's actually changed.
@@ -310,8 +314,6 @@ void VNCSConnectionST::requestClipboardOrClose()
{
try {
if (state() != RFBSTATE_NORMAL) return;
- if (!accessCheck(AccessCutText)) return;
- if (!rfb::Server::acceptCutText) return;
requestClipboard();
} catch(std::exception& e) {
close(e.what());
@@ -322,8 +324,6 @@ void VNCSConnectionST::announceClipboardOrClose(bool available)
{
try {
if (state() != RFBSTATE_NORMAL) return;
- if (!accessCheck(AccessCutText)) return;
- if (!rfb::Server::sendCutText) return;
announceClipboard(available);
} catch(std::exception& e) {
close(e.what());
@@ -334,8 +334,6 @@ void VNCSConnectionST::sendClipboardDataOrClose(const char* data)
{
try {
if (state() != RFBSTATE_NORMAL) return;
- if (!accessCheck(AccessCutText)) return;
- if (!rfb::Server::sendCutText) return;
sendClipboardData(data);
} catch(std::exception& e) {
close(e.what());
@@ -421,7 +419,7 @@ void VNCSConnectionST::approveConnectionOrClose(bool accept,
void VNCSConnectionST::authSuccess()
{
if (rfb::Server::idleTimeout)
- idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));
// - Set the connection parameters appropriately
client.setDimensions(server->getPixelBuffer()->width(),
@@ -448,7 +446,7 @@ void VNCSConnectionST::queryConnection(const char* userName)
void VNCSConnectionST::clientInit(bool shared)
{
if (rfb::Server::idleTimeout)
- idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));
if (rfb::Server::alwaysShared || reverseConnection) shared = true;
if (!accessCheck(AccessNonShared)) shared = true;
if (rfb::Server::neverShared) shared = false;
@@ -463,15 +461,16 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf)
pf.print(buffer, 256);
vlog.info("Client pixel format %s", buffer);
setCursor();
+ encodeManager.forceRefresh(server->getPixelBuffer()->getRect());
}
-void VNCSConnectionST::pointerEvent(const Point& pos, uint16_t buttonMask)
+void VNCSConnectionST::pointerEvent(const core::Point& pos,
+ uint16_t buttonMask)
{
if (rfb::Server::idleTimeout)
- idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));
pointerEventTime = time(nullptr);
if (!accessCheck(AccessPtrEvents)) return;
- if (!rfb::Server::acceptPointerEvents) return;
pointerEventPos = pos;
server->pointerEvent(this, pointerEventPos, buttonMask);
}
@@ -502,8 +501,10 @@ void VNCSConnectionST::keyEvent(uint32_t keysym, uint32_t keycode, bool down) {
uint32_t lookup;
if (rfb::Server::idleTimeout)
- idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));
if (!accessCheck(AccessKeyEvents)) return;
+ // FIXME: This check isn't strictly needed, but we get a lot of
+ // confusing debug logging without it
if (!rfb::Server::acceptKeyEvents) return;
if (down)
@@ -605,27 +606,28 @@ void VNCSConnectionST::keyEvent(uint32_t keysym, uint32_t keycode, bool down) {
server->keyEvent(keysym, keycode, down);
}
-void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
+void VNCSConnectionST::framebufferUpdateRequest(const core::Rect& r,
+ bool incremental)
{
- Rect safeRect;
+ core::Rect safeRect;
if (!accessCheck(AccessView)) return;
SConnection::framebufferUpdateRequest(r, incremental);
// Check that the client isn't sending crappy requests
- if (!r.enclosed_by(Rect(0, 0, client.width(), client.height()))) {
+ if (!r.enclosed_by({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,
client.width(), client.height());
- safeRect = r.intersect(Rect(0, 0, client.width(), client.height()));
+ safeRect = r.intersect({0, 0, client.width(), client.height()});
} else {
safeRect = r;
}
// Just update the requested region.
// Framebuffer update will be sent a bit later, see processMessages().
- Region reqRgn(safeRect);
+ core::Region reqRgn(safeRect);
if (!incremental || !continuousUpdates)
requested.assign_union(reqRgn);
@@ -656,8 +658,7 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,
layout.print(buffer, sizeof(buffer));
vlog.debug("%s", buffer);
- if (!accessCheck(AccessSetDesktopSize) ||
- !rfb::Server::acceptSetDesktopSize) {
+ if (!accessCheck(AccessSetDesktopSize)) {
vlog.debug("Rejecting unauthorized framebuffer resize request");
result = resultProhibited;
} else {
@@ -716,7 +717,10 @@ void VNCSConnectionST::fence(uint32_t flags, unsigned len, const uint8_t data[])
void VNCSConnectionST::enableContinuousUpdates(bool enable,
int x, int y, int w, int h)
{
- Rect rect;
+ core::Rect rect;
+
+ if (!accessCheck(AccessView))
+ return;
if (!client.supportsFence() || !client.supportsContinuousUpdates())
throw protocol_error("Client tried to enable continuous updates when not allowed");
@@ -735,21 +739,16 @@ void VNCSConnectionST::enableContinuousUpdates(bool enable,
void VNCSConnectionST::handleClipboardRequest()
{
- if (!accessCheck(AccessCutText)) return;
server->handleClipboardRequest(this);
}
void VNCSConnectionST::handleClipboardAnnounce(bool available)
{
- if (!accessCheck(AccessCutText)) return;
- if (!rfb::Server::acceptCutText) return;
server->handleClipboardAnnounce(this, available);
}
void VNCSConnectionST::handleClipboardData(const char* data)
{
- if (!accessCheck(AccessCutText)) return;
- if (!rfb::Server::acceptCutText) return;
server->handleClipboardData(this, data);
}
@@ -790,7 +789,7 @@ void VNCSConnectionST::supportsLEDState()
writer()->writeLEDState();
}
-void VNCSConnectionST::handleTimeout(Timer* t)
+void VNCSConnectionST::handleTimeout(core::Timer* t)
{
try {
if ((t == &congestionTimer) ||
@@ -921,7 +920,7 @@ void VNCSConnectionST::writeNoDataUpdate()
void VNCSConnectionST::writeDataUpdate()
{
- Region req;
+ core::Region req;
UpdateInfo ui;
bool needNewUpdateInfo;
const RenderedCursor *cursor;
@@ -946,7 +945,7 @@ void VNCSConnectionST::writeDataUpdate()
// destination will be wrong, so add it to the changed region.
if (!ui.copied.is_empty() && !damagedCursorRegion.is_empty()) {
- Region bogusCopiedCursor;
+ core::Region bogusCopiedCursor;
bogusCopiedCursor = damagedCursorRegion;
bogusCopiedCursor.translate(ui.copy_delta);
@@ -993,7 +992,7 @@ void VNCSConnectionST::writeDataUpdate()
cursor = nullptr;
if (needRenderedCursor()) {
- Rect renderedCursorRect;
+ core::Rect renderedCursorRect;
cursor = server->getRenderedCursor();
renderedCursorRect = cursor->getEffectiveRect();
@@ -1033,7 +1032,7 @@ void VNCSConnectionST::writeDataUpdate()
void VNCSConnectionST::writeLosslessRefresh()
{
- Region req, pending;
+ core::Region req, pending;
const RenderedCursor *cursor;
int nextRefresh, nextUpdate;
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index 17de9d01..b618923f 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -29,16 +29,17 @@
#include <map>
+#include <core/Timer.h>
+
#include <rfb/Congestion.h>
#include <rfb/EncodeManager.h>
#include <rfb/SConnection.h>
-#include <rfb/Timer.h>
namespace rfb {
class VNCServerST;
class VNCSConnectionST : private SConnection,
- public Timer::Callback {
+ public core::Timer::Callback {
public:
VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse,
AccessRights ar);
@@ -108,8 +109,8 @@ namespace rfb {
// Change tracking
- void add_changed(const Region& region) { updates.add_changed(region); }
- void add_copied(const Region& dest, const Point& delta) {
+ void add_changed(const core::Region& region) { updates.add_changed(region); }
+ void add_copied(const core::Region& dest, const core::Point& delta) {
updates.add_copied(dest, delta);
}
@@ -123,10 +124,11 @@ namespace rfb {
void queryConnection(const char* userName) override;
void clientInit(bool shared) override;
void setPixelFormat(const PixelFormat& pf) override;
- void pointerEvent(const Point& pos, uint16_t buttonMask) override;
+ void pointerEvent(const core::Point& pos,
+ uint16_t buttonMask) override;
void keyEvent(uint32_t keysym, uint32_t keycode,
bool down) override;
- void framebufferUpdateRequest(const Rect& r,
+ void framebufferUpdateRequest(const core::Rect& r,
bool incremental) override;
void setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout) override;
@@ -143,7 +145,7 @@ namespace rfb {
void supportsLEDState() override;
// Timer callbacks
- void handleTimeout(Timer* t) override;
+ void handleTimeout(core::Timer* t) override;
// Internal methods
@@ -180,24 +182,24 @@ namespace rfb {
uint8_t *fenceData;
Congestion congestion;
- Timer congestionTimer;
- Timer losslessTimer;
+ core::Timer congestionTimer;
+ core::Timer losslessTimer;
VNCServerST* server;
SimpleUpdateTracker updates;
- Region requested;
+ core::Region requested;
bool updateRenderedCursor, removeRenderedCursor;
- Region damagedCursorRegion;
+ core::Region damagedCursorRegion;
bool continuousUpdates;
- Region cuRegion;
+ core::Region cuRegion;
EncodeManager encodeManager;
std::map<uint32_t, uint32_t> pressedKeys;
- Timer idleTimer;
+ core::Timer idleTimer;
time_t pointerEventTime;
- Point pointerEventPos;
+ core::Point pointerEventPos;
bool clientHasCursor;
std::string closeReason;
diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h
index 4e3a5b23..4d9b31ed 100644
--- a/common/rfb/VNCServer.h
+++ b/common/rfb/VNCServer.h
@@ -23,14 +23,19 @@
#ifndef __RFB_VNCSERVER_H__
#define __RFB_VNCSERVER_H__
+#include <list>
+
+#include <rfb/AccessRights.h>
#include <rfb/UpdateTracker.h>
-#include <rfb/SSecurity.h>
-#include <rfb/ScreenSet.h>
namespace network { class Socket; }
namespace rfb {
+ class PixelBuffer;
+ class SConnection;
+ struct ScreenSet;
+
class VNCServer : public UpdateTracker {
public:
// addSocket() tells the server to serve the Socket. The caller
@@ -128,13 +133,14 @@ namespace rfb {
// setCursor() tells the server that the cursor has changed. The
// cursorData argument contains width*height rgba quadruplets with
// non-premultiplied alpha.
- virtual void setCursor(int width, int height, const Point& hotspot,
+ virtual void setCursor(int width, int height,
+ const core::Point& hotspot,
const uint8_t* cursorData) = 0;
// setCursorPos() tells the server the current position of the cursor, and
// whether the server initiated that change (e.g. through another X11
// client calling XWarpPointer()).
- virtual void setCursorPos(const Point& p, bool warped) = 0;
+ virtual void setCursorPos(const core::Point& p, bool warped) = 0;
// setName() tells the server what desktop title to supply to clients
virtual void setName(const char* name) = 0;
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index b99d33b0..77d652b9 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -55,24 +55,28 @@
#include <assert.h>
#include <stdlib.h>
+#include <core/LogWriter.h>
+#include <core/time.h>
+
+#include <rdr/FdOutStream.h>
+
#include <network/Socket.h>
#include <rfb/ComparingUpdateTracker.h>
#include <rfb/KeyRemapper.h>
#include <rfb/KeysymStr.h>
-#include <rfb/LogWriter.h>
+#include <rfb/SDesktop.h>
#include <rfb/Security.h>
#include <rfb/ServerCore.h>
#include <rfb/VNCServerST.h>
#include <rfb/VNCSConnectionST.h>
-#include <rfb/util.h>
#include <rfb/ledStates.h>
using namespace rfb;
-static LogWriter slog("VNCServerST");
-static LogWriter connectionsLog("Connections");
+static core::LogWriter slog("VNCServerST");
+static core::LogWriter connectionsLog("Connections");
//
// -=- VNCServerST Implementation
@@ -85,7 +89,7 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
blockCounter(0), pb(nullptr), ledState(ledUnknown),
name(name_), pointerClient(nullptr), clipboardClient(nullptr),
pointerClientTime(0),
- comparer(nullptr), cursor(new Cursor(0, 0, Point(), nullptr)),
+ comparer(nullptr), cursor(new Cursor(0, 0, {}, nullptr)),
renderedCursorInvalid(false),
keyRemapper(&KeyRemapper::defInstance),
idleTimer(this), disconnectTimer(this), connectTimer(this),
@@ -97,9 +101,9 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
// FIXME: Do we really want to kick off these right away?
if (rfb::Server::maxIdleTime)
- idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));
+ idleTimer.start(core::secsToMillis(rfb::Server::maxIdleTime));
if (rfb::Server::maxDisconnectionTime)
- disconnectTimer.start(secsToMillis(rfb::Server::maxDisconnectionTime));
+ disconnectTimer.start(core::secsToMillis(rfb::Server::maxDisconnectionTime));
}
VNCServerST::~VNCServerST()
@@ -161,12 +165,18 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing, AccessRights a
// Adjust the exit timers
if (rfb::Server::maxConnectionTime && clients.empty())
- connectTimer.start(secsToMillis(rfb::Server::maxConnectionTime));
+ connectTimer.start(core::secsToMillis(rfb::Server::maxConnectionTime));
disconnectTimer.stop();
- VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing, accessRights);
- clients.push_front(client);
- client->init();
+ try {
+ VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing, accessRights);
+ clients.push_front(client);
+ client->init();
+ } catch (std::exception& e) {
+ connectionsLog.error("Error accepting client: %s", e.what());
+ sock->shutdown();
+ closingSockets.push_back(sock);
+ }
}
void VNCServerST::removeSocket(network::Socket* sock) {
@@ -203,7 +213,7 @@ void VNCServerST::removeSocket(network::Socket* sock) {
// Adjust the exit timers
connectTimer.stop();
if (rfb::Server::maxDisconnectionTime && clients.empty())
- disconnectTimer.start(secsToMillis(rfb::Server::maxDisconnectionTime));
+ disconnectTimer.start(core::secsToMillis(rfb::Server::maxDisconnectionTime));
return;
}
@@ -313,7 +323,7 @@ void VNCServerST::setPixelBuffer(PixelBuffer* pb_)
// Check that the screen layout is still valid
if (pb_ && !layout.validate(pb_->width(), pb_->height())) {
- Rect fbRect;
+ core::Rect fbRect;
ScreenSet::iterator iter, iter_next;
fbRect.setXYWH(0, 0, pb_->width(), pb_->height());
@@ -354,6 +364,9 @@ void VNCServerST::setScreenLayout(const ScreenSet& layout)
void VNCServerST::requestClipboard()
{
+ if (!rfb::Server::acceptCutText)
+ return;
+
if (clipboardClient == nullptr) {
slog.debug("Got request for client clipboard but no client currently owns the clipboard");
return;
@@ -368,6 +381,9 @@ void VNCServerST::announceClipboard(bool available)
clipboardRequestors.clear();
+ if (!rfb::Server::sendCutText)
+ return;
+
for (ci = clients.begin(); ci != clients.end(); ++ci)
(*ci)->announceClipboardOrClose(available);
}
@@ -376,6 +392,9 @@ void VNCServerST::sendClipboardData(const char* data)
{
std::list<VNCSConnectionST*>::iterator ci;
+ if (!rfb::Server::sendCutText)
+ return;
+
if (strchr(data, '\r') != nullptr)
throw std::invalid_argument("Invalid carriage return in clipboard data");
@@ -401,7 +420,7 @@ void VNCServerST::setName(const char* name_)
(*ci)->setDesktopNameOrClose(name_);
}
-void VNCServerST::add_changed(const Region& region)
+void VNCServerST::add_changed(const core::Region& region)
{
if (comparer == nullptr)
return;
@@ -410,7 +429,8 @@ void VNCServerST::add_changed(const Region& region)
startFrameClock();
}
-void VNCServerST::add_copied(const Region& dest, const Point& delta)
+void VNCServerST::add_copied(const core::Region& dest,
+ const core::Point& delta)
{
if (comparer == nullptr)
return;
@@ -419,7 +439,8 @@ void VNCServerST::add_copied(const Region& dest, const Point& delta)
startFrameClock();
}
-void VNCServerST::setCursor(int width, int height, const Point& newHotspot,
+void VNCServerST::setCursor(int width, int height,
+ const core::Point& newHotspot,
const uint8_t* data)
{
delete cursor;
@@ -435,7 +456,7 @@ void VNCServerST::setCursor(int width, int height, const Point& newHotspot,
}
}
-void VNCServerST::setCursorPos(const Point& pos, bool warped)
+void VNCServerST::setCursorPos(const core::Point& pos, bool warped)
{
if (cursorPos != pos) {
cursorPos = pos;
@@ -466,8 +487,11 @@ void VNCServerST::setLEDState(unsigned int state)
void VNCServerST::keyEvent(uint32_t keysym, uint32_t keycode, bool down)
{
+ if (!rfb::Server::acceptKeyEvents)
+ return;
+
if (rfb::Server::maxIdleTime)
- idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));
+ idleTimer.start(core::secsToMillis(rfb::Server::maxIdleTime));
// Remap the key if required
if (keyRemapper) {
@@ -484,11 +508,16 @@ void VNCServerST::keyEvent(uint32_t keysym, uint32_t keycode, bool down)
}
void VNCServerST::pointerEvent(VNCSConnectionST* client,
- const Point& pos, uint16_t buttonMask)
+ const core::Point& pos,
+ uint16_t buttonMask)
{
time_t now = time(nullptr);
+
+ if (!rfb::Server::acceptPointerEvents)
+ return;
+
if (rfb::Server::maxIdleTime)
- idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));
+ idleTimer.start(core::secsToMillis(rfb::Server::maxIdleTime));
// Let one client own the cursor whilst buttons are pressed in order
// to provide a bit more sane user experience. But limit the time to
@@ -516,9 +545,11 @@ void VNCServerST::handleClipboardRequest(VNCSConnectionST* client)
void VNCServerST::handleClipboardAnnounce(VNCSConnectionST* client,
bool available)
{
- if (available)
+ if (available) {
+ if (!rfb::Server::acceptCutText)
+ return;
clipboardClient = client;
- else {
+ } else {
if (client != clipboardClient)
return;
clipboardClient = nullptr;
@@ -529,6 +560,8 @@ void VNCServerST::handleClipboardAnnounce(VNCSConnectionST* client,
void VNCServerST::handleClipboardData(VNCSConnectionST* client,
const char* data)
{
+ if (!rfb::Server::acceptCutText)
+ return;
if (client != clipboardClient) {
slog.debug("Ignoring unexpected clipboard data");
return;
@@ -543,6 +576,11 @@ unsigned int VNCServerST::setDesktopSize(VNCSConnectionST* requester,
unsigned int result;
std::list<VNCSConnectionST*>::iterator ci;
+ if (!rfb::Server::acceptSetDesktopSize) {
+ slog.debug("Rejecting unauthorized framebuffer resize request");
+ return resultProhibited;
+ }
+
// We can't handle a framebuffer larger than this, so don't let a
// client set one (see PixelBuffer.cxx)
if ((fb_width > 16384) || (fb_height > 16384)) {
@@ -622,7 +660,7 @@ SConnection* VNCServerST::getConnection(network::Socket* sock) {
return nullptr;
}
-void VNCServerST::handleTimeout(Timer* t)
+void VNCServerST::handleTimeout(core::Timer* t)
{
if (t == &frameTimer) {
int timeout;
@@ -822,7 +860,7 @@ int VNCServerST::msToNextUpdate()
void VNCServerST::writeUpdate()
{
UpdateInfo ui;
- Region toCheck;
+ core::Region toCheck;
std::list<VNCSConnectionST*>::iterator ci;
@@ -834,9 +872,9 @@ void VNCServerST::writeUpdate()
toCheck = ui.changed.union_(ui.copied);
if (needRenderedCursor()) {
- Rect clippedCursorRect = Rect(0, 0, cursor->width(), cursor->height())
- .translate(cursorPos.subtract(cursor->hotspot()))
- .intersect(pb->getRect());
+ core::Rect clippedCursorRect = core::Rect(0, 0, cursor->width(), cursor->height())
+ .translate(cursorPos.subtract(cursor->hotspot()))
+ .intersect(pb->getRect());
if (!toCheck.intersect(clippedCursorRect).is_empty())
renderedCursorInvalid = true;
@@ -864,7 +902,7 @@ void VNCServerST::writeUpdate()
// checkUpdate() is called by clients to see if it is safe to read from
// the framebuffer at this time.
-Region VNCServerST::getPendingRegion()
+core::Region VNCServerST::getPendingRegion()
{
UpdateInfo ui;
@@ -876,7 +914,7 @@ Region VNCServerST::getPendingRegion()
// Block client from updating if there are pending updates
if (comparer->is_empty())
- return Region();
+ return {};
comparer->getUpdateInfo(&ui, pb->getRect());
diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h
index dc4f9aad..5db4513a 100644
--- a/common/rfb/VNCServerST.h
+++ b/common/rfb/VNCServerST.h
@@ -26,11 +26,11 @@
#include <sys/time.h>
-#include <rfb/SDesktop.h>
+#include <core/Timer.h>
+
#include <rfb/VNCServer.h>
#include <rfb/Blacklist.h>
#include <rfb/Cursor.h>
-#include <rfb/Timer.h>
#include <rfb/ScreenSet.h>
namespace rfb {
@@ -40,9 +40,10 @@ namespace rfb {
class ListConnInfo;
class PixelBuffer;
class KeyRemapper;
+ class SDesktop;
class VNCServerST : public VNCServer,
- public Timer::Callback {
+ public core::Timer::Callback {
public:
// -=- Constructors
@@ -95,11 +96,12 @@ namespace rfb {
void closeClients(const char* reason) override {closeClients(reason, nullptr);}
SConnection* getConnection(network::Socket* sock) override;
- void add_changed(const Region &region) override;
- void add_copied(const Region &dest, const Point &delta) override;
- void setCursor(int width, int height, const Point& hotspot,
+ void add_changed(const core::Region& region) override;
+ void add_copied(const core::Region& dest,
+ const core::Point& delta) override;
+ void setCursor(int width, int height, const core::Point& hotspot,
const uint8_t* data) override;
- void setCursorPos(const Point& p, bool warped) override;
+ void setCursorPos(const core::Point& p, bool warped) override;
void setName(const char* name_) override;
void setLEDState(unsigned state) override;
@@ -111,13 +113,14 @@ namespace rfb {
const ScreenSet& getScreenLayout() const { return screenLayout; }
const Cursor* getCursor() const { return cursor; }
- const Point& getCursorPos() const { return cursorPos; }
+ const core::Point& getCursorPos() const { return cursorPos; }
const char* getName() const { return name.c_str(); }
unsigned getLEDState() const { return ledState; }
// Event handlers
void keyEvent(uint32_t keysym, uint32_t keycode, bool down);
- void pointerEvent(VNCSConnectionST* client, const Point& pos, uint16_t buttonMask);
+ void pointerEvent(VNCSConnectionST* client,
+ const core::Point& pos, uint16_t buttonMask);
void handleClipboardRequest(VNCSConnectionST* client);
void handleClipboardAnnounce(VNCSConnectionST* client, bool available);
@@ -146,7 +149,7 @@ namespace rfb {
// Part of the framebuffer that has been modified but is not yet
// ready to be sent to clients
- Region getPendingRegion();
+ core::Region getPendingRegion();
// getRenderedCursor() returns an up to date version of the server
// side rendered cursor buffer
@@ -155,7 +158,7 @@ namespace rfb {
protected:
// Timer callbacks
- void handleTimeout(Timer* t) override;
+ void handleTimeout(core::Timer* t) override;
// - Internal methods
@@ -195,19 +198,19 @@ namespace rfb {
ComparingUpdateTracker* comparer;
- Point cursorPos;
+ core::Point cursorPos;
Cursor* cursor;
RenderedCursor renderedCursor;
bool renderedCursorInvalid;
KeyRemapper* keyRemapper;
- Timer idleTimer;
- Timer disconnectTimer;
- Timer connectTimer;
+ core::Timer idleTimer;
+ core::Timer disconnectTimer;
+ core::Timer connectTimer;
uint64_t msc, queuedMsc;
- Timer frameTimer;
+ core::Timer frameTimer;
};
};
diff --git a/common/rfb/WinPasswdValidator.cxx b/common/rfb/WinPasswdValidator.cxx
index 84832e81..a6281950 100644
--- a/common/rfb/WinPasswdValidator.cxx
+++ b/common/rfb/WinPasswdValidator.cxx
@@ -30,7 +30,8 @@ using namespace rfb;
// This method will only work for Windows NT, 2000, and XP (and possibly Vista)
bool WinPasswdValidator::validateInternal(rfb::SConnection* /*sc*/,
const char* username,
- const char* password)
+ const char* password,
+ std::string & /* msg */)
{
HANDLE handle;
diff --git a/common/rfb/WinPasswdValidator.h b/common/rfb/WinPasswdValidator.h
index 340a6234..993cafea 100644
--- a/common/rfb/WinPasswdValidator.h
+++ b/common/rfb/WinPasswdValidator.h
@@ -21,6 +21,7 @@
#ifndef __RFB_WINPASSWDVALIDATOR_H__
#define __RFB_WINPASSWDVALIDATOR_H__
+#include <string>
#include <rfb/SSecurityPlain.h>
namespace rfb
@@ -30,7 +31,10 @@ namespace rfb
WinPasswdValidator() {};
virtual ~WinPasswdValidator() {};
protected:
- bool validateInternal(SConnection *sc, const char* username, const char* password) override;
+ bool validateInternal(SConnection *sc,
+ const char *username,
+ const char *password,
+ std::string &msg) override;
};
}
diff --git a/common/rfb/ZRLEDecoder.cxx b/common/rfb/ZRLEDecoder.cxx
index 633d1c36..845bf4dc 100644
--- a/common/rfb/ZRLEDecoder.cxx
+++ b/common/rfb/ZRLEDecoder.cxx
@@ -21,6 +21,8 @@
#include <config.h>
#endif
+#include <algorithm>
+
#include <rdr/InStream.h>
#include <rdr/MemInStream.h>
#include <rdr/OutStream.h>
@@ -75,7 +77,7 @@ ZRLEDecoder::~ZRLEDecoder()
{
}
-bool ZRLEDecoder::readRect(const Rect& /*r*/, rdr::InStream* is,
+bool ZRLEDecoder::readRect(const core::Rect& /*r*/, rdr::InStream* is,
const ServerParams& /*server*/,
rdr::OutStream* os)
{
@@ -99,7 +101,7 @@ bool ZRLEDecoder::readRect(const Rect& /*r*/, rdr::InStream* is,
return true;
}
-void ZRLEDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
+void ZRLEDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb)
{
@@ -113,13 +115,13 @@ void ZRLEDecoder::decodeRect(const Rect& r, const uint8_t* buffer,
}
template<class T>
-void ZRLEDecoder::zrleDecode(const Rect& r, rdr::InStream* is,
+void ZRLEDecoder::zrleDecode(const core::Rect& r, rdr::InStream* is,
const PixelFormat& pf,
ModifiablePixelBuffer* pb)
{
int length = is->readU32();
zis.setUnderlying(is, length);
- Rect t;
+ core::Rect t;
T buf[64 * 64];
Pixel maxPixel = pf.pixelFromRGB((uint16_t)-1, (uint16_t)-1, (uint16_t)-1);
@@ -134,11 +136,11 @@ void ZRLEDecoder::zrleDecode(const Rect& r, rdr::InStream* is,
for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) {
- t.br.y = __rfbmin(r.br.y, t.tl.y + 64);
+ t.br.y = std::min(r.br.y, t.tl.y + 64);
for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {
- t.br.x = __rfbmin(r.br.x, t.tl.x + 64);
+ t.br.x = std::min(r.br.x, t.tl.x + 64);
zlibHasData(&zis, 1);
int mode = zis.readU8();
diff --git a/common/rfb/ZRLEDecoder.h b/common/rfb/ZRLEDecoder.h
index facf0adc..b9ebf771 100644
--- a/common/rfb/ZRLEDecoder.h
+++ b/common/rfb/ZRLEDecoder.h
@@ -30,16 +30,16 @@ namespace rfb {
public:
ZRLEDecoder();
virtual ~ZRLEDecoder();
- bool readRect(const Rect& r, rdr::InStream* is,
+ bool readRect(const core::Rect& r, rdr::InStream* is,
const ServerParams& server,
rdr::OutStream* os) override;
- void decodeRect(const Rect& r, const uint8_t* buffer,
+ void decodeRect(const core::Rect& r, const uint8_t* buffer,
size_t buflen, const ServerParams& server,
ModifiablePixelBuffer* pb) override;
private:
template<class T>
- void zrleDecode(const Rect& r, rdr::InStream* is,
+ void zrleDecode(const core::Rect& r, rdr::InStream* is,
const PixelFormat& pf, ModifiablePixelBuffer* pb);
private:
diff --git a/common/rfb/ZRLEEncoder.cxx b/common/rfb/ZRLEEncoder.cxx
index 1e2c6ef4..1908d7e3 100644
--- a/common/rfb/ZRLEEncoder.cxx
+++ b/common/rfb/ZRLEEncoder.cxx
@@ -21,20 +21,23 @@
#include <config.h>
#endif
+#include <core/Configuration.h>
+#include <core/LogWriter.h>
+
#include <rdr/OutStream.h>
-#include <rfb/Exception.h>
#include <rfb/encodings.h>
#include <rfb/Palette.h>
+#include <rfb/PixelBuffer.h>
#include <rfb/SConnection.h>
#include <rfb/ZRLEEncoder.h>
-#include <rfb/Configuration.h>
-#include <rfb/LogWriter.h>
using namespace rfb;
-static LogWriter vlog("ZRLEEncoder");
+static core::LogWriter vlog("ZRLEEncoder");
-IntParameter zlibLevel("ZlibLevel","[DEPRECATED] Zlib compression level",-1);
+core::IntParameter zlibLevel("ZlibLevel",
+ "[DEPRECATED] Zlib compression level",
+ -1, -1, -1);
ZRLEEncoder::ZRLEEncoder(SConnection* conn_)
: Encoder(conn_, encodingZRLE, EncoderPlain, 127),
@@ -66,7 +69,7 @@ void ZRLEEncoder::setCompressLevel(int level)
void ZRLEEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
{
int x, y;
- Rect tile;
+ core::Rect tile;
rdr::OutStream* os;
@@ -132,7 +135,8 @@ void ZRLEEncoder::writeSolidRect(int width, int height,
mos.clear();
}
-void ZRLEEncoder::writePaletteTile(const Rect& tile, const PixelBuffer* pb,
+void ZRLEEncoder::writePaletteTile(const core::Rect& tile,
+ const PixelBuffer* pb,
const Palette& palette)
{
const uint8_t* buffer;
@@ -158,7 +162,8 @@ void ZRLEEncoder::writePaletteTile(const Rect& tile, const PixelBuffer* pb,
}
}
-void ZRLEEncoder::writePaletteRLETile(const Rect& tile, const PixelBuffer* pb,
+void ZRLEEncoder::writePaletteRLETile(const core::Rect& tile,
+ const PixelBuffer* pb,
const Palette& palette)
{
const uint8_t* buffer;
@@ -184,7 +189,8 @@ void ZRLEEncoder::writePaletteRLETile(const Rect& tile, const PixelBuffer* pb,
}
}
-void ZRLEEncoder::writeRawTile(const Rect& tile, const PixelBuffer* pb)
+void ZRLEEncoder::writeRawTile(const core::Rect& tile,
+ const PixelBuffer* pb)
{
const uint8_t* buffer;
int stride;
diff --git a/common/rfb/ZRLEEncoder.h b/common/rfb/ZRLEEncoder.h
index 87d87e94..3be81ba3 100644
--- a/common/rfb/ZRLEEncoder.h
+++ b/common/rfb/ZRLEEncoder.h
@@ -40,11 +40,13 @@ namespace rfb {
const uint8_t* colour) override;
protected:
- void writePaletteTile(const Rect& tile, const PixelBuffer* pb,
+ void writePaletteTile(const core::Rect& tile,
+ const PixelBuffer* pb,
const Palette& palette);
- void writePaletteRLETile(const Rect& tile, const PixelBuffer* pb,
+ void writePaletteRLETile(const core::Rect& tile,
+ const PixelBuffer* pb,
const Palette& palette);
- void writeRawTile(const Rect& tile, const PixelBuffer* pb);
+ void writeRawTile(const core::Rect& tile, const PixelBuffer* pb);
void writePalette(const PixelFormat& pf, const Palette& palette);
diff --git a/common/rfb/pam.c b/common/rfb/pam.c
deleted file mode 100644
index f9e5ce74..00000000
--- a/common/rfb/pam.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2006 Martin Koegler
- * Copyright (C) 2010 TigerVNC Team
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <security/pam_appl.h>
-
-#include <rfb/pam.h>
-
-typedef struct
-{
- const char *username;
- const char *password;
-} AuthData;
-
-#if defined(__sun)
-static int pam_callback(int count, struct pam_message **in,
- struct pam_response **out, void *ptr)
-#else
-static int pam_callback(int count, const struct pam_message **in,
- struct pam_response **out, void *ptr)
-#endif
-{
- int i;
- AuthData *auth = (AuthData *) ptr;
- struct pam_response *resp =
- (struct pam_response *) malloc (sizeof (struct pam_response) * count);
-
- if (!resp && count)
- return PAM_CONV_ERR;
-
- for (i = 0; i < count; i++) {
- resp[i].resp_retcode = PAM_SUCCESS;
- switch (in[i]->msg_style) {
- case PAM_TEXT_INFO:
- case PAM_ERROR_MSG:
- resp[i].resp = 0;
- break;
- case PAM_PROMPT_ECHO_ON: /* Send Username */
- resp[i].resp = strdup(auth->username);
- break;
- case PAM_PROMPT_ECHO_OFF: /* Send Password */
- resp[i].resp = strdup(auth->password);
- break;
- default:
- free(resp);
- return PAM_CONV_ERR;
- }
- }
-
- *out = resp;
- return PAM_SUCCESS;
-}
-
-
-int do_pam_auth(const char *service, const char *username, const char *password)
-{
- int ret;
- AuthData auth = { username, password };
- struct pam_conv conv = {
- pam_callback,
- &auth
- };
- pam_handle_t *h = 0;
- ret = pam_start(service, username, &conv, &h);
- if (ret == PAM_SUCCESS)
- ret = pam_authenticate(h, 0);
- if (ret == PAM_SUCCESS)
- ret = pam_acct_mgmt(h, 0);
- pam_end(h, ret);
-
- return ret == PAM_SUCCESS ? 1 : 0;
-}
-
diff --git a/common/rfb/pam.h b/common/rfb/pam.h
deleted file mode 100644
index d378d19c..00000000
--- a/common/rfb/pam.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2006 Martin Koegler
- * Copyright (C) 2010 TigerVNC Team
- *
- * 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_PAM_H__
-#define __RFB_PAM_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int do_pam_auth(const char *service, const char *username, const char *password);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx
deleted file mode 100644
index 3c62b1df..00000000
--- a/common/rfb/util.cxx
+++ /dev/null
@@ -1,682 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2023 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include <rfb/util.h>
-
-namespace rfb {
-
- std::string format(const char *fmt, ...)
- {
- va_list ap;
- int len;
- char *buf;
- std::string out;
-
- va_start(ap, fmt);
- len = vsnprintf(nullptr, 0, fmt, ap);
- va_end(ap);
-
- if (len < 0)
- return "";
-
- buf = new char[len+1];
-
- va_start(ap, fmt);
- vsnprintf(buf, len+1, fmt, ap);
- va_end(ap);
-
- out = buf;
-
- delete [] buf;
-
- return out;
- }
-
- std::vector<std::string> split(const char* src,
- const char delimiter)
- {
- std::vector<std::string> out;
- const char *start, *stop;
-
- start = src;
- do {
- stop = strchr(start, delimiter);
- if (stop == nullptr) {
- out.push_back(start);
- } else {
- out.push_back(std::string(start, stop-start));
- start = stop + 1;
- }
- } while (stop != nullptr);
-
- return out;
- }
-
- static char intToHex(uint8_t i) {
- if (i<=9)
- return '0'+i;
- else if ((i>=10) && (i<=15))
- return 'a'+(i-10);
- assert(false);
- return '\0';
- }
-
- void binToHex(const uint8_t* in, size_t inlen,
- char* out, size_t outlen) {
- if (inlen > outlen/2)
- inlen = outlen/2;
-
- if (inlen > 0) {
- assert(in);
- assert(out);
- }
-
- for (size_t i=0; i<inlen; i++) {
- out[i*2] = intToHex((in[i] >> 4) & 15);
- out[i*2+1] = intToHex((in[i] & 15));
- }
- }
-
- std::string binToHex(const uint8_t* in, size_t inlen) {
- char* buffer = new char[inlen*2+1]();
- std::string out;
- binToHex(in, inlen, buffer, inlen*2);
- out = buffer;
- delete [] buffer;
- return out;
- }
-
- static bool readHexAndShift(char c, uint8_t* v) {
- c=tolower(c);
- if ((c >= '0') && (c <= '9'))
- *v = (*v << 4) + (c - '0');
- else if ((c >= 'a') && (c <= 'f'))
- *v = (*v << 4) + (c - 'a' + 10);
- else
- return false;
- return true;
- }
-
- bool hexToBin(const char* in, size_t inlen,
- uint8_t* out, size_t outlen) {
- assert(in || inlen == 0);
- assert(out || outlen == 0);
-
- if (inlen & 1)
- return false;
-
- if (inlen > outlen*2)
- inlen = outlen*2;
-
- for(size_t i=0; i<inlen; i+=2) {
- uint8_t byte = 0;
- if (!readHexAndShift(in[i], &byte) ||
- !readHexAndShift(in[i+1], &byte))
- return false;
- out[i/2] = byte;
- }
-
- return true;
- }
-
- std::vector<uint8_t> hexToBin(const char* in, size_t inlen) {
- std::vector<uint8_t> out(inlen/2);
- if (!hexToBin(in, inlen, out.data(), inlen/2))
- return std::vector<uint8_t>();
- return out;
- }
-
- std::string convertLF(const char* src, size_t bytes)
- {
- size_t sz;
- std::string out;
-
- const char* in;
- size_t in_len;
-
- // Compute output size
- sz = 0;
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- if (*in != '\r') {
- sz++;
- in++;
- in_len--;
- continue;
- }
-
- if ((in_len < 2) || (*(in+1) != '\n'))
- sz++;
-
- in++;
- in_len--;
- }
-
- // Reserve space
- out.reserve(sz);
-
- // And convert
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- if (*in != '\r') {
- out += *in++;
- in_len--;
- continue;
- }
-
- if ((in_len < 2) || (*(in+1) != '\n'))
- out += '\n';
-
- in++;
- in_len--;
- }
-
- return out;
- }
-
- std::string convertCRLF(const char* src, size_t bytes)
- {
- std::string out;
- size_t sz;
-
- const char* in;
- size_t in_len;
-
- // Compute output size
- sz = 0;
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- sz++;
-
- if (*in == '\r') {
- if ((in_len < 2) || (*(in+1) != '\n'))
- sz++;
- } else if (*in == '\n') {
- if ((in == src) || (*(in-1) != '\r'))
- sz++;
- }
-
- in++;
- in_len--;
- }
-
- // Reserve space
- out.reserve(sz);
-
- // And convert
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- if (*in == '\n') {
- if ((in == src) || (*(in-1) != '\r'))
- out += '\r';
- }
-
- out += *in;
-
- if (*in == '\r') {
- if ((in_len < 2) || (*(in+1) != '\n'))
- out += '\n';
- }
-
- in++;
- in_len--;
- }
-
- return out;
- }
-
- size_t ucs4ToUTF8(unsigned src, char dst[5]) {
- if (src < 0x80) {
- *dst++ = src;
- *dst++ = '\0';
- return 1;
- } else if (src < 0x800) {
- *dst++ = 0xc0 | (src >> 6);
- *dst++ = 0x80 | (src & 0x3f);
- *dst++ = '\0';
- return 2;
- } else if ((src >= 0xd800) && (src < 0xe000)) {
- return ucs4ToUTF8(0xfffd, dst);
- } else if (src < 0x10000) {
- *dst++ = 0xe0 | (src >> 12);
- *dst++ = 0x80 | ((src >> 6) & 0x3f);
- *dst++ = 0x80 | (src & 0x3f);
- *dst++ = '\0';
- return 3;
- } else if (src < 0x110000) {
- *dst++ = 0xf0 | (src >> 18);
- *dst++ = 0x80 | ((src >> 12) & 0x3f);
- *dst++ = 0x80 | ((src >> 6) & 0x3f);
- *dst++ = 0x80 | (src & 0x3f);
- *dst++ = '\0';
- return 4;
- } else {
- return ucs4ToUTF8(0xfffd, dst);
- }
- }
-
- size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst) {
- size_t count, consumed;
-
- *dst = 0xfffd;
-
- if (max == 0)
- return 0;
-
- consumed = 1;
-
- if ((*src & 0x80) == 0) {
- *dst = *src;
- count = 0;
- } else if ((*src & 0xe0) == 0xc0) {
- *dst = *src & 0x1f;
- count = 1;
- } else if ((*src & 0xf0) == 0xe0) {
- *dst = *src & 0x0f;
- count = 2;
- } else if ((*src & 0xf8) == 0xf0) {
- *dst = *src & 0x07;
- count = 3;
- } else {
- // Invalid sequence, consume all continuation characters
- src++;
- max--;
- while ((max-- > 0) && ((*src++ & 0xc0) == 0x80))
- consumed++;
- return consumed;
- }
-
- src++;
- max--;
-
- while (count--) {
- consumed++;
-
- // Invalid or truncated sequence?
- if ((max == 0) || ((*src & 0xc0) != 0x80)) {
- *dst = 0xfffd;
- return consumed;
- }
-
- *dst <<= 6;
- *dst |= *src & 0x3f;
-
- src++;
- max--;
- }
-
- // UTF-16 surrogate code point?
- if ((*dst >= 0xd800) && (*dst < 0xe000))
- *dst = 0xfffd;
-
- return consumed;
- }
-
- size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]) {
- if ((src < 0xd800) || ((src >= 0xe000) && (src < 0x10000))) {
- *dst++ = src;
- *dst++ = L'\0';
- return 1;
- } else if ((src >= 0x10000) && (src < 0x110000)) {
- src -= 0x10000;
- *dst++ = 0xd800 | ((src >> 10) & 0x03ff);
- *dst++ = 0xdc00 | (src & 0x03ff);
- *dst++ = L'\0';
- return 2;
- } else {
- return ucs4ToUTF16(0xfffd, dst);
- }
- }
-
- size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst) {
- *dst = 0xfffd;
-
- if (max == 0)
- return 0;
-
- if ((*src < 0xd800) || (*src >= 0xe000)) {
- *dst = *src;
- return 1;
- }
-
- if (*src & 0x0400) {
- size_t consumed;
-
- // Invalid sequence, consume all continuation characters
- consumed = 0;
- while ((max > 0) && (*src & 0x0400)) {
- src++;
- max--;
- consumed++;
- }
-
- return consumed;
- }
-
- *dst = *src++;
- max--;
-
- // Invalid or truncated sequence?
- if ((max == 0) || ((*src & 0xfc00) != 0xdc00)) {
- *dst = 0xfffd;
- return 1;
- }
-
- *dst = 0x10000 + ((*dst & 0x03ff) << 10);
- *dst |= *src & 0x3ff;
-
- return 2;
- }
-
- std::string latin1ToUTF8(const char* src, size_t bytes) {
- std::string out;
- size_t sz;
-
- const char* in;
- size_t in_len;
-
- // Compute output size
- sz = 0;
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- char buf[5];
- sz += ucs4ToUTF8(*(const unsigned char*)in, buf);
- in++;
- in_len--;
- }
-
- // Reserve space
- out.reserve(sz);
-
- // And convert
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- char buf[5];
- ucs4ToUTF8(*(const unsigned char*)in, buf);
- out += buf;
- in++;
- in_len--;
- }
-
- return out;
- }
-
- std::string utf8ToLatin1(const char* src, size_t bytes) {
- std::string out;
- size_t sz;
-
- const char* in;
- size_t in_len;
-
- // Compute output size
- sz = 0;
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- size_t len;
- unsigned ucs;
-
- len = utf8ToUCS4(in, in_len, &ucs);
- in += len;
- in_len -= len;
- sz++;
- }
-
- // Reserve space
- out.reserve(sz);
-
- // And convert
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- size_t len;
- unsigned ucs;
-
- len = utf8ToUCS4(in, in_len, &ucs);
- in += len;
- in_len -= len;
-
- if (ucs > 0xff)
- out += '?';
- else
- out += (unsigned char)ucs;
- }
-
- return out;
- }
-
- std::string utf16ToUTF8(const wchar_t* src, size_t units)
- {
- std::string out;
- size_t sz;
-
- const wchar_t* in;
- size_t in_len;
-
- // Compute output size
- sz = 0;
- in = src;
- in_len = units;
- while ((in_len > 0) && (*in != '\0')) {
- size_t len;
- unsigned ucs;
- char buf[5];
-
- len = utf16ToUCS4(in, in_len, &ucs);
- in += len;
- in_len -= len;
-
- sz += ucs4ToUTF8(ucs, buf);
- }
-
- // Reserve space
- out.reserve(sz);
-
- // And convert
- in = src;
- in_len = units;
- while ((in_len > 0) && (*in != '\0')) {
- size_t len;
- unsigned ucs;
- char buf[5];
-
- len = utf16ToUCS4(in, in_len, &ucs);
- in += len;
- in_len -= len;
-
- ucs4ToUTF8(ucs, buf);
- out += buf;
- }
-
- return out;
- }
-
- std::wstring utf8ToUTF16(const char* src, size_t bytes)
- {
- std::wstring out;
- size_t sz;
-
- const char* in;
- size_t in_len;
-
- // Compute output size
- sz = 0;
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- size_t len;
- unsigned ucs;
- wchar_t buf[3];
-
- len = utf8ToUCS4(in, in_len, &ucs);
- in += len;
- in_len -= len;
-
- sz += ucs4ToUTF16(ucs, buf);
- }
-
- // Reserve space
- out.reserve(sz);
-
- // And convert
- in = src;
- in_len = bytes;
- while ((in_len > 0) && (*in != '\0')) {
- size_t len;
- unsigned ucs;
- wchar_t buf[3];
-
- len = utf8ToUCS4(in, in_len, &ucs);
- in += len;
- in_len -= len;
-
- ucs4ToUTF16(ucs, buf);
- out += buf;
- }
-
- return out;
- }
-
- bool isValidUTF8(const char* str, size_t bytes)
- {
- while ((bytes > 0) && (*str != '\0')) {
- size_t len;
- unsigned ucs;
-
- len = utf8ToUCS4(str, bytes, &ucs);
- str += len;
- bytes -= len;
-
- if (ucs == 0xfffd)
- return false;
- }
-
- return true;
- }
-
- bool isValidUTF16(const wchar_t* wstr, size_t units)
- {
- while ((units > 0) && (*wstr != '\0')) {
- size_t len;
- unsigned ucs;
-
- len = utf16ToUCS4(wstr, units, &ucs);
- wstr += len;
- units -= len;
-
- if (ucs == 0xfffd)
- return false;
- }
-
- return true;
- }
-
- unsigned msBetween(const struct timeval *first,
- const struct timeval *second)
- {
- unsigned diff;
-
- diff = (second->tv_sec - first->tv_sec) * 1000;
-
- diff += second->tv_usec / 1000;
- diff -= first->tv_usec / 1000;
-
- return diff;
- }
-
- unsigned msSince(const struct timeval *then)
- {
- struct timeval now;
-
- gettimeofday(&now, nullptr);
-
- return msBetween(then, &now);
- }
-
- bool isBefore(const struct timeval *first,
- const struct timeval *second)
- {
- if (first->tv_sec < second->tv_sec)
- return true;
- if (first->tv_sec > second->tv_sec)
- return false;
- if (first->tv_usec < second->tv_usec)
- return true;
- return false;
- }
-
- static std::string doPrefix(long long value, const char *unit,
- unsigned divisor, const char **prefixes,
- size_t prefixCount, int precision) {
- char buffer[256];
- double newValue;
- size_t prefix;
-
- newValue = value;
- prefix = 0;
- while (newValue >= divisor) {
- if (prefix >= prefixCount)
- break;
- newValue /= divisor;
- prefix++;
- }
-
- snprintf(buffer, sizeof(buffer), "%.*g %s%s", precision, newValue,
- (prefix == 0) ? "" : prefixes[prefix-1], unit);
- buffer[sizeof(buffer)-1] = '\0';
-
- return buffer;
- }
-
- static const char *siPrefixes[] =
- { "k", "M", "G", "T", "P", "E", "Z", "Y" };
- static const char *iecPrefixes[] =
- { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
-
- std::string siPrefix(long long value, const char *unit,
- int precision) {
- return doPrefix(value, unit, 1000, siPrefixes,
- sizeof(siPrefixes)/sizeof(*siPrefixes),
- precision);
- }
-
- std::string iecPrefix(long long value, const char *unit,
- int precision) {
- return doPrefix(value, unit, 1024, iecPrefixes,
- sizeof(iecPrefixes)/sizeof(*iecPrefixes),
- precision);
- }
-};
diff --git a/common/rfb/util.h b/common/rfb/util.h
deleted file mode 100644
index b47ac4c9..00000000
--- a/common/rfb/util.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2023 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.
- */
-
-//
-// util.h - miscellaneous useful bits
-//
-
-#ifndef __RFB_UTIL_H__
-#define __RFB_UTIL_H__
-
-#include <limits.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-struct timeval;
-
-namespace rfb {
-
- // Formats according to printf(), with a dynamic allocation
- std::string format(const char *fmt, ...)
- __attribute__((__format__ (__printf__, 1, 2)));
-
- // Splits a string with the specified delimiter
- std::vector<std::string> split(const char* src,
- const char delimiter);
-
- // Conversion to and from a hex string
-
- void binToHex(const uint8_t* in, size_t inlen, char* out, size_t outlen);
- std::string binToHex(const uint8_t* in, size_t inlen);
- bool hexToBin(const char* in, size_t inlen, uint8_t* out, size_t outlen);
- std::vector<uint8_t> hexToBin(const char* in, size_t inlen);
-
- // Makes sure line endings are in a certain format
-
- std::string convertLF(const char* src, size_t bytes = (size_t)-1);
- std::string convertCRLF(const char* src, size_t bytes = (size_t)-1);
-
- // Convertions between various Unicode formats
-
- size_t ucs4ToUTF8(unsigned src, char dst[5]);
- size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst);
-
- size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]);
- size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst);
-
- std::string latin1ToUTF8(const char* src, size_t bytes = (size_t)-1);
- std::string utf8ToLatin1(const char* src, size_t bytes = (size_t)-1);
-
- std::string utf16ToUTF8(const wchar_t* src, size_t units = (size_t)-1);
- std::wstring utf8ToUTF16(const char* src, size_t bytes = (size_t)-1);
-
- bool isValidUTF8(const char* str, size_t bytes = (size_t)-1);
- bool isValidUTF16(const wchar_t* wstr, size_t units = (size_t)-1);
-
- // HELPER functions for timeout handling
-
- // secsToMillis() turns seconds into milliseconds, capping the value so it
- // can't wrap round and become -ve
- inline int secsToMillis(int secs) {
- return (secs < 0 || secs > (INT_MAX/1000) ? INT_MAX : secs * 1000);
- }
-
- // Returns time elapsed between two moments in milliseconds.
- unsigned msBetween(const struct timeval *first,
- const struct timeval *second);
-
- // Returns time elapsed since given moment in milliseconds.
- unsigned msSince(const struct timeval *then);
-
- // Returns true if first happened before seconds
- bool isBefore(const struct timeval *first,
- const struct timeval *second);
-
- std::string siPrefix(long long value, const char *unit,
- int precision=6);
- std::string iecPrefix(long long value, const char *unit,
- int precision=6);
-}
-
-// Some platforms (e.g. Windows) include max() and min() macros in their
-// standard headers, but they are also standard C++ template functions, so some
-// C++ headers will undefine them. So we steer clear of the names min and max
-// and define __rfbmin and __rfbmax instead.
-
-#ifndef __rfbmax
-#define __rfbmax(a,b) (((a) > (b)) ? (a) : (b))
-#endif
-#ifndef __rfbmin
-#define __rfbmin(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-#endif