diff options
author | Pierre Ossman <ossman@cendio.se> | 2023-03-02 11:09:57 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2023-03-02 11:09:57 +0100 |
commit | 15a0da6157d5d34362e68591124324ba5a77ad66 (patch) | |
tree | eb5aa106e2b64fd5845d4a38370383ca0181814c /common/rfb | |
parent | cbed625888eb1ef87272dac39472b67dccf677b4 (diff) | |
parent | 4c9b0ba913e77d295e8047181fc7fe0d029a27a7 (diff) | |
download | tigervnc-15a0da6157d5d34362e68591124324ba5a77ad66.tar.gz tigervnc-15a0da6157d5d34362e68591124324ba5a77ad66.zip |
Merge branch 'types' of https://github.com/CendioOssman/tigervnc
Diffstat (limited to 'common/rfb')
139 files changed, 3229 insertions, 3794 deletions
diff --git a/common/rfb/Blacklist.cxx b/common/rfb/Blacklist.cxx index f052eafb..12a54c45 100644 --- a/common/rfb/Blacklist.cxx +++ b/common/rfb/Blacklist.cxx @@ -45,11 +45,6 @@ Blacklist::Blacklist() { } Blacklist::~Blacklist() { - // Free the map keys - BlacklistMap::iterator i; - for (i=blm.begin(); i!=blm.end(); i++) { - strFree((char*)(*i).first); - } } bool Blacklist::isBlackmarked(const char* name) { @@ -65,7 +60,7 @@ bool Blacklist::isBlackmarked(const char* name) { bi.marks = 1; bi.blockUntil = 0; bi.blockTimeout = initialTimeout; - blm[strDup(name)] = bi; + blm[name] = bi; i = blm.find(name); } @@ -92,9 +87,5 @@ bool Blacklist::isBlackmarked(const char* name) { } void Blacklist::clearBlackmark(const char* name) { - BlacklistMap::iterator i = blm.find(name); - if (i != blm.end()) { - strFree((char*)(*i).first); - blm.erase(i); - } + blm.erase(name); } diff --git a/common/rfb/Blacklist.h b/common/rfb/Blacklist.h index 45e36a0e..c1699f29 100644 --- a/common/rfb/Blacklist.h +++ b/common/rfb/Blacklist.h @@ -30,9 +30,9 @@ #include <string.h> #include <time.h> #include <map> +#include <string> #include <rfb/Configuration.h> -#include <rfb/util.h> namespace rfb { @@ -68,17 +68,12 @@ namespace rfb { void clearBlackmark(const char* name); protected: - struct ltStr { - bool operator()(const char* s1, const char* s2) const { - return strcmp(s1, s2) < 0; - }; - }; struct BlacklistInfo { int marks; time_t blockUntil; unsigned int blockTimeout; }; - typedef std::map<const char*,BlacklistInfo,ltStr> BlacklistMap; + typedef std::map<std::string,BlacklistInfo> BlacklistMap; BlacklistMap blm; }; diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx index 27942764..521649ac 100644 --- a/common/rfb/CConnection.cxx +++ b/common/rfb/CConnection.cxx @@ -52,14 +52,14 @@ CConnection::CConnection() supportsDesktopResize(false), supportsLEDState(false), is(0), os(0), reader_(0), writer_(0), shared(false), - state_(RFBSTATE_UNINITIALISED), serverName(strDup("")), + state_(RFBSTATE_UNINITIALISED), pendingPFChange(false), preferredEncoding(encodingTight), compressLevel(2), qualityLevel(-1), formatChange(false), encodingChange(false), firstUpdate(true), pendingUpdate(false), continuousUpdates(false), forceNonincremental(true), framebuffer(NULL), decoder(this), - serverClipboard(NULL), hasLocalClipboard(false) + hasRemoteClipboard(false), hasLocalClipboard(false) { } @@ -72,7 +72,7 @@ void CConnection::setServerName(const char* name_) { if (name_ == NULL) name_ = ""; - serverName.replaceBuf(strDup(name_)); + serverName = name_; } void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_) @@ -93,10 +93,10 @@ void CConnection::setFramebuffer(ModifiablePixelBuffer* fb) if ((framebuffer != NULL) && (fb != NULL)) { Rect rect; - const rdr::U8* data; + const uint8_t* data; int stride; - const rdr::U8 black[4] = { 0, 0, 0, 0 }; + const uint8_t black[4] = { 0, 0, 0, 0 }; // Copy still valid area @@ -210,7 +210,7 @@ bool CConnection::processSecurityTypesMsg() int secType = secTypeInvalid; - std::list<rdr::U8> secTypes; + std::list<uint8_t> secTypes; secTypes = security.GetEnabledSecTypes(); if (server.isVersion(3,3)) { @@ -225,7 +225,7 @@ bool CConnection::processSecurityTypesMsg() state_ = RFBSTATE_SECURITY_REASON; return true; } else if (secType == secTypeNone || secType == secTypeVncAuth) { - std::list<rdr::U8>::iterator i; + std::list<uint8_t>::iterator i; for (i = secTypes.begin(); i != secTypes.end(); i++) if (*i == secType) { secType = *i; @@ -259,10 +259,10 @@ bool CConnection::processSecurityTypesMsg() return true; } - std::list<rdr::U8>::iterator j; + std::list<uint8_t>::iterator j; for (int i = 0; i < nServerSecTypes; i++) { - rdr::U8 serverSecType = is->readU8(); + uint8_t serverSecType = is->readU8(); vlog.debug("Server offers security type %s(%d)", secTypeName(serverSecType), serverSecType); @@ -355,17 +355,17 @@ bool CConnection::processSecurityReasonMsg() is->setRestorePoint(); - rdr::U32 len = is->readU32(); + uint32_t len = is->readU32(); if (!is->hasDataOrRestore(len)) return false; is->clearRestorePoint(); - CharArray reason(len + 1); - is->readBytes(reason.buf, len); - reason.buf[len] = '\0'; + std::vector<char> reason(len + 1); + is->readBytes(reason.data(), len); + reason[len] = '\0'; state_ = RFBSTATE_INVALID; - throw AuthFailureException(reason.buf); + throw AuthFailureException(reason.data()); } bool CConnection::processInitMsg() @@ -405,8 +405,6 @@ void CConnection::close() reader_ = NULL; delete writer_; writer_ = NULL; - strFree(serverClipboard); - serverClipboard = NULL; } void CConnection::setDesktopSize(int w, int h) @@ -545,18 +543,16 @@ void CConnection::serverCutText(const char* str) { hasLocalClipboard = false; - strFree(serverClipboard); - serverClipboard = NULL; - serverClipboard = latin1ToUTF8(str); + hasRemoteClipboard = true; handleClipboardAnnounce(true); } -void CConnection::handleClipboardCaps(rdr::U32 flags, - const rdr::U32* lengths) +void CConnection::handleClipboardCaps(uint32_t flags, + const uint32_t* lengths) { - rdr::U32 sizes[] = { 0 }; + uint32_t sizes[] = { 0 }; CMsgHandler::handleClipboardCaps(flags, lengths); @@ -568,7 +564,7 @@ void CConnection::handleClipboardCaps(rdr::U32 flags, sizes); } -void CConnection::handleClipboardRequest(rdr::U32 flags) +void CConnection::handleClipboardRequest(uint32_t flags) { if (!(flags & rfb::clipboardUTF8)) { vlog.debug("Ignoring clipboard request for unsupported formats 0x%x", flags); @@ -587,10 +583,9 @@ void CConnection::handleClipboardPeek() writer()->writeClipboardNotify(hasLocalClipboard ? rfb::clipboardUTF8 : 0); } -void CConnection::handleClipboardNotify(rdr::U32 flags) +void CConnection::handleClipboardNotify(uint32_t flags) { - strFree(serverClipboard); - serverClipboard = NULL; + hasRemoteClipboard = false; if (flags & rfb::clipboardUTF8) { hasLocalClipboard = false; @@ -600,22 +595,20 @@ void CConnection::handleClipboardNotify(rdr::U32 flags) } } -void CConnection::handleClipboardProvide(rdr::U32 flags, +void CConnection::handleClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data) + const uint8_t* const* data) { if (!(flags & rfb::clipboardUTF8)) { vlog.debug("Ignoring clipboard provide with unsupported formats 0x%x", flags); return; } - strFree(serverClipboard); - serverClipboard = NULL; - serverClipboard = convertLF((const char*)data[0], lengths[0]); + hasRemoteClipboard = true; // FIXME: Should probably verify that this data was actually requested - handleClipboardData(serverClipboard); + handleClipboardData(serverClipboard.c_str()); } void CConnection::authSuccess() @@ -645,8 +638,8 @@ void CConnection::handleClipboardData(const char* /*data*/) void CConnection::requestClipboard() { - if (serverClipboard != NULL) { - handleClipboardData(serverClipboard); + if (hasRemoteClipboard) { + handleClipboardData(serverClipboard.c_str()); return; } @@ -681,9 +674,9 @@ void CConnection::announceClipboard(bool available) void CConnection::sendClipboardData(const char* data) { if (server.clipboardFlags() & rfb::clipboardProvide) { - CharArray filtered(convertCRLF(data)); - size_t sizes[1] = { strlen(filtered.buf) + 1 }; - const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf }; + std::string filtered(convertCRLF(data)); + size_t sizes[1] = { filtered.size() + 1 }; + const uint8_t* data[1] = { (const uint8_t*)filtered.c_str() }; if (unsolicitedClipboardAttempt) { unsolicitedClipboardAttempt = false; @@ -697,9 +690,9 @@ void CConnection::sendClipboardData(const char* data) writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data); } else { - CharArray latin1(utf8ToLatin1(data)); + std::string latin1(utf8ToLatin1(data)); - writer()->writeClientCutText(latin1.buf); + writer()->writeClientCutText(latin1.c_str()); } } @@ -747,14 +740,14 @@ void CConnection::setQualityLevel(int level) void CConnection::setPF(const PixelFormat& pf) { - if (server.pf().equal(pf) && !formatChange) + if (server.pf() == pf && !formatChange) return; nextPF = pf; formatChange = true; } -void CConnection::fence(rdr::U32 flags, unsigned len, const char data[]) +void CConnection::fence(uint32_t flags, unsigned len, const char data[]) { CMsgHandler::fence(flags, len, data); @@ -819,7 +812,7 @@ void CConnection::requestNewUpdate() void CConnection::updateEncodings() { - std::list<rdr::U32> encodings; + std::list<uint32_t> encodings; if (supportsLocalCursor) { encodings.push_back(pseudoEncodingCursorWithAlpha); diff --git a/common/rfb/CConnection.h b/common/rfb/CConnection.h index f6818628..71da175e 100644 --- a/common/rfb/CConnection.h +++ b/common/rfb/CConnection.h @@ -24,10 +24,11 @@ #ifndef __RFB_CCONNECTION_H__ #define __RFB_CCONNECTION_H__ +#include <string> + #include <rfb/CMsgHandler.h> #include <rfb/DecodeManager.h> #include <rfb/SecurityClient.h> -#include <rfb/util.h> namespace rfb { @@ -116,14 +117,14 @@ namespace rfb { virtual void serverCutText(const char* str); - virtual void handleClipboardCaps(rdr::U32 flags, - const rdr::U32* lengths); - virtual void handleClipboardRequest(rdr::U32 flags); + virtual void handleClipboardCaps(uint32_t flags, + const uint32_t* lengths); + virtual void handleClipboardRequest(uint32_t flags); virtual void handleClipboardPeek(); - virtual void handleClipboardNotify(rdr::U32 flags); - virtual void handleClipboardProvide(rdr::U32 flags, + virtual void handleClipboardNotify(uint32_t flags); + virtual void handleClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data); + const uint8_t* const* data); // Methods to be overridden in a derived class @@ -206,7 +207,7 @@ namespace rfb { // Access method used by SSecurity implementations that can verify servers' // Identities, to determine the unique(ish) name of the server. - const char* getServerName() const { return serverName.buf; } + const char* getServerName() const { return serverName.c_str(); } bool isSecure() const { return csecurity ? csecurity->isSecure() : false; } @@ -248,7 +249,7 @@ namespace rfb { // responds to requests, stating no support for synchronisation. // When overriding, call CMsgHandler::fence() directly in order to // state correct support for fence flags. - virtual void fence(rdr::U32 flags, unsigned len, const char data[]); + virtual void fence(uint32_t flags, unsigned len, const char data[]); private: bool processVersionMsg(); @@ -271,7 +272,7 @@ namespace rfb { bool shared; stateEnum state_; - CharArray serverName; + std::string serverName; bool pendingPFChange; rfb::PixelFormat pendingPF; @@ -293,7 +294,8 @@ namespace rfb { ModifiablePixelBuffer* framebuffer; DecodeManager decoder; - char* serverClipboard; + std::string serverClipboard; + bool hasRemoteClipboard; bool hasLocalClipboard; bool unsolicitedClipboardAttempt; }; diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt index e18cff34..85cdc2db 100644 --- a/common/rfb/CMakeLists.txt +++ b/common/rfb/CMakeLists.txt @@ -32,7 +32,6 @@ add_library(rfb STATIC Logger.cxx Logger_file.cxx Logger_stdio.cxx - Password.cxx PixelBuffer.cxx PixelFormat.cxx RREEncoder.cxx @@ -64,6 +63,7 @@ add_library(rfb STATIC ZRLEEncoder.cxx ZRLEDecoder.cxx encodings.cxx + obfuscate.cxx util.cxx) target_link_libraries(rfb os rdr) diff --git a/common/rfb/CMsgHandler.cxx b/common/rfb/CMsgHandler.cxx index f4f785b2..e37811f9 100644 --- a/common/rfb/CMsgHandler.cxx +++ b/common/rfb/CMsgHandler.cxx @@ -28,6 +28,7 @@ #include <rfb/CMsgHandler.h> #include <rfb/clipboardTypes.h> #include <rfb/screenTypes.h> +#include <rfb/util.h> static rfb::LogWriter vlog("CMsgHandler"); @@ -68,7 +69,7 @@ void CMsgHandler::setName(const char* name) server.setName(name); } -void CMsgHandler::fence(rdr::U32 /*flags*/, unsigned /*len*/, +void CMsgHandler::fence(uint32_t /*flags*/, unsigned /*len*/, const char /*data*/ []) { server.supportsFence = true; @@ -106,7 +107,7 @@ void CMsgHandler::setLEDState(unsigned int state) server.setLEDState(state); } -void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) +void CMsgHandler::handleClipboardCaps(uint32_t flags, const uint32_t* lengths) { int i; @@ -139,11 +140,8 @@ void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) if (lengths[i] == 0) vlog.debug(" %s (only notify)", type); else { - char bytes[1024]; - - iecPrefix(lengths[i], "B", bytes, sizeof(bytes)); vlog.debug(" %s (automatically send up to %s)", - type, bytes); + type, iecPrefix(lengths[i], "B").c_str()); } } } @@ -151,7 +149,7 @@ void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) server.setClipboardCaps(flags, lengths); } -void CMsgHandler::handleClipboardRequest(rdr::U32 /*flags*/) +void CMsgHandler::handleClipboardRequest(uint32_t /*flags*/) { } @@ -159,12 +157,12 @@ void CMsgHandler::handleClipboardPeek() { } -void CMsgHandler::handleClipboardNotify(rdr::U32 /*flags*/) +void CMsgHandler::handleClipboardNotify(uint32_t /*flags*/) { } -void CMsgHandler::handleClipboardProvide(rdr::U32 /*flags*/, +void CMsgHandler::handleClipboardProvide(uint32_t /*flags*/, const size_t* /*lengths*/, - const rdr::U8* const* /*data*/) + const uint8_t* const* /*data*/) { } diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h index e358a4f4..c427749f 100644 --- a/common/rfb/CMsgHandler.h +++ b/common/rfb/CMsgHandler.h @@ -24,8 +24,8 @@ #ifndef __RFB_CMSGHANDLER_H__ #define __RFB_CMSGHANDLER_H__ -#include <rdr/types.h> -#include <rfb/Pixel.h> +#include <stdint.h> + #include <rfb/ServerParams.h> #include <rfb/Rect.h> #include <rfb/ScreenSet.h> @@ -51,11 +51,11 @@ namespace rfb { int w, int h, const ScreenSet& layout); virtual void setCursor(int width, int height, const Point& hotspot, - const rdr::U8* data) = 0; + const uint8_t* data) = 0; virtual void setCursorPos(const Point& pos) = 0; virtual void setPixelFormat(const PixelFormat& pf); virtual void setName(const char* name); - virtual void fence(rdr::U32 flags, unsigned len, const char data[]); + virtual void fence(uint32_t flags, unsigned len, const char data[]); virtual void endOfContinuousUpdates(); virtual void supportsQEMUKeyEvent(); virtual void serverInit(int width, int height, @@ -70,20 +70,20 @@ namespace rfb { virtual bool dataRect(const Rect& r, int encoding) = 0; virtual void setColourMapEntries(int firstColour, int nColours, - rdr::U16* rgbs) = 0; + uint16_t* rgbs) = 0; virtual void bell() = 0; virtual void serverCutText(const char* str) = 0; virtual void setLEDState(unsigned int state); - virtual void handleClipboardCaps(rdr::U32 flags, - const rdr::U32* lengths); - virtual void handleClipboardRequest(rdr::U32 flags); + virtual void handleClipboardCaps(uint32_t flags, + const uint32_t* lengths); + virtual void handleClipboardRequest(uint32_t flags); virtual void handleClipboardPeek(); - virtual void handleClipboardNotify(rdr::U32 flags); - virtual void handleClipboardProvide(rdr::U32 flags, + virtual void handleClipboardNotify(uint32_t flags); + virtual void handleClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data); + const uint8_t* const* data); ServerParams server; }; diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx index 1c175584..be5133cf 100644 --- a/common/rfb/CMsgReader.cxx +++ b/common/rfb/CMsgReader.cxx @@ -24,14 +24,16 @@ #include <assert.h> #include <stdio.h> +#include <vector> + #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/util.h> #include <rfb/CMsgHandler.h> #include <rfb/CMsgReader.h> @@ -54,7 +56,7 @@ CMsgReader::~CMsgReader() bool CMsgReader::readServerInit() { int width, height; - rdr::U32 len; + uint32_t len; if (!is->hasData(2 + 2 + 16 + 4)) return false; @@ -71,10 +73,10 @@ bool CMsgReader::readServerInit() if (!is->hasDataOrRestore(len)) return false; is->clearRestorePoint(); - CharArray name(len + 1); - is->readBytes(name.buf, len); - name.buf[len] = '\0'; - handler->serverInit(width, height, pf, name.buf); + std::vector<char> name(len + 1); + is->readBytes(name.data(), len); + name[len] = '\0'; + handler->serverInit(width, height, pf, name.data()); return true; } @@ -228,10 +230,10 @@ bool CMsgReader::readSetColourMapEntries() return false; is->clearRestorePoint(); - rdr::U16Array rgbs(nColours * 3); - for (int i = 0; i < nColours * 3; i++) - rgbs.buf[i] = is->readU16(); - handler->setColourMapEntries(firstColour, nColours, rgbs.buf); + std::vector<uint16_t> rgbs(nColours * 3); + for (size_t i = 0; i < rgbs.size(); i++) + rgbs[i] = is->readU16(); + handler->setColourMapEntries(firstColour, nColours, rgbs.data()); return true; } @@ -250,10 +252,10 @@ bool CMsgReader::readServerCutText() is->setRestorePoint(); is->skip(3); - rdr::U32 len = is->readU32(); + uint32_t len = is->readU32(); if (len & 0x80000000) { - rdr::S32 slen = len; + int32_t slen = len; slen = -slen; if (readExtendedClipboard(slen)) { is->clearRestorePoint(); @@ -273,18 +275,18 @@ bool CMsgReader::readServerCutText() vlog.error("cut text too long (%d bytes) - ignoring",len); return true; } - CharArray ca(len); - is->readBytes(ca.buf, len); - CharArray filtered(convertLF(ca.buf, len)); - handler->serverCutText(filtered.buf); + std::vector<char> ca(len); + is->readBytes(ca.data(), len); + std::string filtered(convertLF(ca.data(), len)); + handler->serverCutText(filtered.c_str()); return true; } -bool CMsgReader::readExtendedClipboard(rdr::S32 len) +bool CMsgReader::readExtendedClipboard(int32_t len) { - rdr::U32 flags; - rdr::U32 action; + uint32_t flags; + uint32_t action; if (!is->hasData(len)) return false; @@ -303,7 +305,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len) if (action & clipboardCaps) { int i; size_t num; - rdr::U32 lengths[16]; + uint32_t lengths[16]; num = 0; for (i = 0;i < 16;i++) { @@ -311,7 +313,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len) num++; } - if (len < (rdr::S32)(4 + 4*num)) + if (len < (int32_t)(4 + 4*num)) throw Exception("Invalid extended clipboard message"); num = 0; @@ -327,7 +329,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len) int i; size_t num; size_t lengths[16]; - rdr::U8* buffers[16]; + uint8_t* buffers[16]; zis.setUnderlying(is, len - 4); @@ -368,7 +370,7 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len) if (!zis.hasData(lengths[num])) throw Exception("Extended clipboard decode error"); - buffers[num] = new rdr::U8[lengths[num]]; + buffers[num] = new uint8_t[lengths[num]]; zis.readBytes(buffers[num], lengths[num]); num++; } @@ -405,8 +407,8 @@ bool CMsgReader::readExtendedClipboard(rdr::S32 len) bool CMsgReader::readFence() { - rdr::U32 flags; - rdr::U8 len; + uint32_t flags; + uint8_t len; char data[64]; if (!is->hasData(3 + 4 + 1)) @@ -476,18 +478,18 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot) if (width > maxCursorSize || height > maxCursorSize) throw Exception("Too big cursor"); - rdr::U8Array rgba(width*height*4); + std::vector<uint8_t> rgba(width*height*4); if (width * height > 0) { - rdr::U8 pr, pg, pb; - rdr::U8 sr, sg, sb; + uint8_t pr, pg, pb; + uint8_t sr, sg, sb; int data_len = ((width+7)/8) * height; int mask_len = ((width+7)/8) * height; - rdr::U8Array data(data_len); - rdr::U8Array mask(mask_len); + std::vector<uint8_t> data(data_len); + std::vector<uint8_t> mask(mask_len); int x, y; - rdr::U8* out; + uint8_t* out; if (!is->hasData(3 + 3 + data_len + mask_len)) return false; @@ -500,17 +502,17 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot) sg = is->readU8(); sb = is->readU8(); - is->readBytes(data.buf, data_len); - is->readBytes(mask.buf, mask_len); + is->readBytes(data.data(), data.size()); + is->readBytes(mask.data(), mask.size()); int maskBytesPerRow = (width+7)/8; - out = rgba.buf; + out = rgba.data(); for (y = 0;y < height;y++) { for (x = 0;x < width;x++) { int byte = y * maskBytesPerRow + x / 8; int bit = 7 - x % 8; - if (data.buf[byte] & (1 << bit)) { + if (data[byte] & (1 << bit)) { out[0] = pr; out[1] = pg; out[2] = pb; @@ -520,7 +522,7 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot) out[2] = sb; } - if (mask.buf[byte] & (1 << bit)) + if (mask[byte] & (1 << bit)) out[3] = 255; else out[3] = 0; @@ -530,7 +532,7 @@ bool CMsgReader::readSetXCursor(int width, int height, const Point& hotspot) } } - handler->setCursor(width, height, hotspot, rgba.buf); + handler->setCursor(width, height, hotspot, rgba.data()); return true; } @@ -542,23 +544,23 @@ bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot) int data_len = width * height * (handler->server.pf().bpp/8); int mask_len = ((width+7)/8) * height; - rdr::U8Array data(data_len); - rdr::U8Array mask(mask_len); + std::vector<uint8_t> data(data_len); + std::vector<uint8_t> mask(mask_len); int x, y; - rdr::U8Array rgba(width*height*4); - rdr::U8* in; - rdr::U8* out; + std::vector<uint8_t> rgba(width*height*4); + uint8_t* in; + uint8_t* out; if (!is->hasData(data_len + mask_len)) return false; - is->readBytes(data.buf, data_len); - is->readBytes(mask.buf, mask_len); + is->readBytes(data.data(), data.size()); + is->readBytes(mask.data(), mask.size()); int maskBytesPerRow = (width+7)/8; - in = data.buf; - out = rgba.buf; + in = data.data(); + out = rgba.data(); for (y = 0;y < height;y++) { for (x = 0;x < width;x++) { int byte = y * maskBytesPerRow + x / 8; @@ -566,7 +568,7 @@ bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot) handler->server.pf().rgbFromBuffer(out, in, 1); - if (mask.buf[byte] & (1 << bit)) + if (mask[byte] & (1 << bit)) out[3] = 255; else out[3] = 0; @@ -576,7 +578,7 @@ bool CMsgReader::readSetCursor(int width, int height, const Point& hotspot) } } - handler->setCursor(width, height, hotspot, rgba.buf); + handler->setCursor(width, height, hotspot, rgba.data()); return true; } @@ -592,7 +594,7 @@ bool CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hots bool ret; - rdr::U8* buf; + uint8_t* buf; int stride; // We can't use restore points as the decoder likely wants to as well, so @@ -621,7 +623,7 @@ bool CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hots assert(stride == width); for (int i = 0;i < pb.area();i++) { - rdr::U8 alpha; + uint8_t alpha; alpha = buf[3]; if (alpha == 0) @@ -647,7 +649,7 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot if (width > maxCursorSize || height > maxCursorSize) throw Exception("Too big cursor"); - rdr::U8 type; + uint8_t type; if (!is->hasData(1 + 1)) return false; @@ -659,26 +661,26 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot if (type == 0) { int len = width * height * (handler->server.pf().bpp/8); - rdr::U8Array andMask(len); - rdr::U8Array xorMask(len); + std::vector<uint8_t> andMask(len); + std::vector<uint8_t> xorMask(len); - rdr::U8Array data(width*height*4); + std::vector<uint8_t> data(width*height*4); - rdr::U8* andIn; - rdr::U8* xorIn; - rdr::U8* out; + uint8_t* andIn; + uint8_t* xorIn; + uint8_t* out; int Bpp; if (!is->hasDataOrRestore(len + len)) return false; is->clearRestorePoint(); - is->readBytes(andMask.buf, len); - is->readBytes(xorMask.buf, len); + is->readBytes(andMask.data(), andMask.size()); + is->readBytes(xorMask.data(), xorMask.size()); - andIn = andMask.buf; - xorIn = xorMask.buf; - out = data.buf; + andIn = andMask.data(); + xorIn = xorMask.data(); + out = data.data(); Bpp = handler->server.pf().bpp/8; for (int y = 0;y < height;y++) { for (int x = 0;x < width;x++) { @@ -690,7 +692,7 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot xorIn += Bpp; if (andPixel == 0) { - rdr::U8 r, g, b; + uint8_t r, g, b; // Opaque pixel @@ -726,18 +728,18 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot } } - handler->setCursor(width, height, hotspot, data.buf); + handler->setCursor(width, height, hotspot, data.data()); } else if (type == 1) { - rdr::U8Array data(width*height*4); + std::vector<uint8_t> data(width*height*4); if (!is->hasDataOrRestore(width*height*4)) return false; is->clearRestorePoint(); // FIXME: Is alpha premultiplied? - is->readBytes(data.buf, width*height*4); + is->readBytes(data.data(), data.size()); - handler->setCursor(width, height, hotspot, data.buf); + handler->setCursor(width, height, hotspot, data.data()); } else { throw Exception("Unknown cursor type"); } @@ -747,7 +749,7 @@ bool CMsgReader::readSetVMwareCursor(int width, int height, const Point& hotspot bool CMsgReader::readSetDesktopName(int x, int y, int w, int h) { - rdr::U32 len; + uint32_t len; if (!is->hasData(4)) return false; @@ -760,14 +762,14 @@ bool CMsgReader::readSetDesktopName(int x, int y, int w, int h) return false; is->clearRestorePoint(); - CharArray name(len + 1); - is->readBytes(name.buf, len); - name.buf[len] = '\0'; + std::vector<char> name(len + 1); + is->readBytes(name.data(), len); + name[len] = '\0'; if (x || y || w || h) { vlog.error("Ignoring DesktopName rect with non-zero position/size"); } else { - handler->setName(name.buf); + handler->setName(name.data()); } return true; @@ -776,7 +778,7 @@ bool CMsgReader::readSetDesktopName(int x, int y, int w, int h) bool CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h) { unsigned int screens, i; - rdr::U32 id, flags; + uint32_t id, flags; int sx, sy, sw, sh; ScreenSet layout; @@ -810,7 +812,7 @@ bool CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h) bool CMsgReader::readLEDState() { - rdr::U8 state; + uint8_t state; if (!is->hasData(1)) return false; @@ -824,7 +826,7 @@ bool CMsgReader::readLEDState() bool CMsgReader::readVMwareLEDState() { - rdr::U32 state; + uint32_t state; if (!is->hasData(4)) return false; diff --git a/common/rfb/CMsgReader.h b/common/rfb/CMsgReader.h index ab55aed8..3b1c0ddb 100644 --- a/common/rfb/CMsgReader.h +++ b/common/rfb/CMsgReader.h @@ -24,7 +24,7 @@ #ifndef __RFB_CMSGREADER_H__ #define __RFB_CMSGREADER_H__ -#include <rdr/types.h> +#include <stdint.h> #include <rfb/Rect.h> #include <rfb/encodings.h> @@ -53,7 +53,7 @@ namespace rfb { bool readSetColourMapEntries(); bool readBell(); bool readServerCutText(); - bool readExtendedClipboard(rdr::S32 len); + bool readExtendedClipboard(int32_t len); bool readFence(); bool readEndOfContinuousUpdates(); @@ -83,7 +83,7 @@ namespace rfb { stateEnum state; - rdr::U8 currentMsgType; + uint8_t currentMsgType; int nUpdateRectsLeft; Rect dataRect; int rectEncoding; diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx index 0ac1bd73..246c5dbe 100644 --- a/common/rfb/CMsgWriter.cxx +++ b/common/rfb/CMsgWriter.cxx @@ -62,9 +62,9 @@ void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf) endMsg(); } -void CMsgWriter::writeSetEncodings(const std::list<rdr::U32> encodings) +void CMsgWriter::writeSetEncodings(const std::list<uint32_t> encodings) { - std::list<rdr::U32>::const_iterator iter; + std::list<uint32_t>::const_iterator iter; startMsg(msgTypeSetEncodings); os->pad(1); os->writeU16(encodings.size()); @@ -130,7 +130,7 @@ void CMsgWriter::writeEnableContinuousUpdates(bool enable, endMsg(); } -void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[]) +void CMsgWriter::writeFence(uint32_t flags, unsigned len, const char data[]) { if (!server->supportsFence) throw Exception("Server does not support fences"); @@ -150,7 +150,7 @@ void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[]) endMsg(); } -void CMsgWriter::writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) +void CMsgWriter::writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down) { if (!server->supportsQEMUKeyEvent || !keycode) { /* This event isn't meaningful without a valid keysym */ @@ -204,8 +204,8 @@ void CMsgWriter::writeClientCutText(const char* str) endMsg(); } -void CMsgWriter::writeClipboardCaps(rdr::U32 caps, - const rdr::U32* lengths) +void CMsgWriter::writeClipboardCaps(uint32_t caps, + const uint32_t* lengths) { size_t i, count; @@ -233,7 +233,7 @@ void CMsgWriter::writeClipboardCaps(rdr::U32 caps, endMsg(); } -void CMsgWriter::writeClipboardRequest(rdr::U32 flags) +void CMsgWriter::writeClipboardRequest(uint32_t flags) { if (!(server->clipboardFlags() & clipboardRequest)) throw Exception("Server does not support clipboard \"request\" action"); @@ -245,7 +245,7 @@ void CMsgWriter::writeClipboardRequest(rdr::U32 flags) endMsg(); } -void CMsgWriter::writeClipboardPeek(rdr::U32 flags) +void CMsgWriter::writeClipboardPeek(uint32_t flags) { if (!(server->clipboardFlags() & clipboardPeek)) throw Exception("Server does not support clipboard \"peek\" action"); @@ -257,7 +257,7 @@ void CMsgWriter::writeClipboardPeek(rdr::U32 flags) endMsg(); } -void CMsgWriter::writeClipboardNotify(rdr::U32 flags) +void CMsgWriter::writeClipboardNotify(uint32_t flags) { if (!(server->clipboardFlags() & clipboardNotify)) throw Exception("Server does not support clipboard \"notify\" action"); @@ -269,9 +269,9 @@ void CMsgWriter::writeClipboardNotify(rdr::U32 flags) endMsg(); } -void CMsgWriter::writeClipboardProvide(rdr::U32 flags, +void CMsgWriter::writeClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data) + const uint8_t* const* data) { rdr::MemOutStream mos; rdr::ZlibOutStream zos; diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h index 7b839393..7e7a9a17 100644 --- a/common/rfb/CMsgWriter.h +++ b/common/rfb/CMsgWriter.h @@ -25,7 +25,7 @@ #include <list> -#include <rdr/types.h> +#include <stdint.h> namespace rdr { class OutStream; } @@ -45,25 +45,25 @@ namespace rfb { void writeClientInit(bool shared); void writeSetPixelFormat(const PixelFormat& pf); - void writeSetEncodings(const std::list<rdr::U32> encodings); + 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 writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h); - void writeFence(rdr::U32 flags, unsigned len, const char data[]); + void writeFence(uint32_t flags, unsigned len, const char data[]); - void writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); + void writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down); void writePointerEvent(const Point& pos, int buttonMask); void writeClientCutText(const char* str); - void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths); - void writeClipboardRequest(rdr::U32 flags); - void writeClipboardPeek(rdr::U32 flags); - void writeClipboardNotify(rdr::U32 flags); - void writeClipboardProvide(rdr::U32 flags, const size_t* lengths, - const rdr::U8* const* data); + void writeClipboardCaps(uint32_t caps, const uint32_t* lengths); + void writeClipboardRequest(uint32_t flags); + void writeClipboardPeek(uint32_t flags); + void writeClipboardNotify(uint32_t flags); + void writeClipboardProvide(uint32_t flags, const size_t* lengths, + const uint8_t* const* data); protected: void startMsg(int type); diff --git a/common/rfb/CSecurityDH.cxx b/common/rfb/CSecurityDH.cxx index d9b09bfb..9e67885c 100644 --- a/common/rfb/CSecurityDH.cxx +++ b/common/rfb/CSecurityDH.cxx @@ -83,7 +83,7 @@ bool CSecurityDH::readKey() if (!is->hasData(4)) return false; is->setRestorePoint(); - rdr::U16 gen = is->readU16(); + uint16_t gen = is->readU16(); keyLength = is->readU16(); if (keyLength < MinKeyLength) throw AuthFailureException("DH key is too short"); @@ -93,38 +93,39 @@ bool CSecurityDH::readKey() return false; is->clearRestorePoint(); mpz_set_ui(g, gen); - rdr::U8Array pBytes(keyLength); - rdr::U8Array ABytes(keyLength); - is->readBytes(pBytes.buf, keyLength); - is->readBytes(ABytes.buf, keyLength); - nettle_mpz_set_str_256_u(p, keyLength, pBytes.buf); - nettle_mpz_set_str_256_u(A, keyLength, ABytes.buf); + std::vector<uint8_t> pBytes(keyLength); + std::vector<uint8_t> ABytes(keyLength); + is->readBytes(pBytes.data(), pBytes.size()); + is->readBytes(ABytes.data(), ABytes.size()); + nettle_mpz_set_str_256_u(p, pBytes.size(), pBytes.data()); + nettle_mpz_set_str_256_u(A, ABytes.size(), ABytes.data()); return true; } void CSecurityDH::writeCredentials() { - CharArray username; - CharArray password; + std::string username; + std::string password; rdr::RandomStream rs; - (CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); - rdr::U8Array bBytes(keyLength); + (CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); + + std::vector<uint8_t> bBytes(keyLength); if (!rs.hasData(keyLength)) throw ConnFailedException("failed to generate DH private key"); - rs.readBytes(bBytes.buf, keyLength); - nettle_mpz_set_str_256_u(b, keyLength, bBytes.buf); + rs.readBytes(bBytes.data(), bBytes.size()); + nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data()); mpz_powm(k, A, b, p); mpz_powm(B, g, b, p); - rdr::U8Array sharedSecret(keyLength); - rdr::U8Array BBytes(keyLength); - nettle_mpz_get_str_256(keyLength, sharedSecret.buf, k); - nettle_mpz_get_str_256(keyLength, BBytes.buf, B); - rdr::U8 key[16]; + std::vector<uint8_t> sharedSecret(keyLength); + std::vector<uint8_t> BBytes(keyLength); + nettle_mpz_get_str_256(sharedSecret.size(), sharedSecret.data(), k); + nettle_mpz_get_str_256(BBytes.size(), BBytes.data(), B); + uint8_t key[16]; struct md5_ctx md5Ctx; md5_init(&md5Ctx); - md5_update(&md5Ctx, keyLength, sharedSecret.buf); + md5_update(&md5Ctx, sharedSecret.size(), sharedSecret.data()); md5_digest(&md5Ctx, 16, key); struct aes128_ctx aesCtx; aes128_set_encrypt_key(&aesCtx, key); @@ -133,18 +134,16 @@ void CSecurityDH::writeCredentials() if (!rs.hasData(128)) throw ConnFailedException("failed to generate random padding"); rs.readBytes(buf, 128); - size_t len = strlen(username.buf); - if (len >= 64) + if (username.size() >= 64) throw AuthFailureException("username is too long"); - memcpy(buf, username.buf, len + 1); - len = strlen(password.buf); - if (len >= 64) + memcpy(buf, username.c_str(), username.size() + 1); + if (password.size() >= 64) throw AuthFailureException("password is too long"); - memcpy(buf + 64, password.buf, len + 1); - aes128_encrypt(&aesCtx, 128, (rdr::U8 *)buf, (rdr::U8 *)buf); + memcpy(buf + 64, password.c_str(), password.size() + 1); + aes128_encrypt(&aesCtx, 128, (uint8_t *)buf, (uint8_t *)buf); rdr::OutStream* os = cc->getOutStream(); os->writeBytes(buf, 128); - os->writeBytes(BBytes.buf, keyLength); + os->writeBytes(BBytes.data(), BBytes.size()); os->flush(); } diff --git a/common/rfb/CSecurityMSLogonII.cxx b/common/rfb/CSecurityMSLogonII.cxx index a1faab85..d7e23715 100644 --- a/common/rfb/CSecurityMSLogonII.cxx +++ b/common/rfb/CSecurityMSLogonII.cxx @@ -79,9 +79,9 @@ bool CSecurityMSLogonII::readKey() rdr::InStream* is = cc->getInStream(); if (!is->hasData(24)) return false; - rdr::U8 gBytes[8]; - rdr::U8 pBytes[8]; - rdr::U8 ABytes[8]; + uint8_t gBytes[8]; + uint8_t pBytes[8]; + uint8_t ABytes[8]; is->readBytes(gBytes, 8); is->readBytes(pBytes, 8); is->readBytes(ABytes, 8); @@ -93,28 +93,29 @@ bool CSecurityMSLogonII::readKey() void CSecurityMSLogonII::writeCredentials() { - CharArray username; - CharArray password; + std::string username; + std::string password; rdr::RandomStream rs; - (CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); - rdr::U8Array bBytes(8); + (CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); + + std::vector<uint8_t> bBytes(8); if (!rs.hasData(8)) throw ConnFailedException("failed to generate DH private key"); - rs.readBytes(bBytes.buf, 8); - nettle_mpz_set_str_256_u(b, 8, bBytes.buf); + rs.readBytes(bBytes.data(), bBytes.size()); + nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data()); mpz_powm(k, A, b, p); mpz_powm(B, g, b, p); - rdr::U8 key[8]; - rdr::U8 reversedKey[8]; - rdr::U8 BBytes[8]; - rdr::U8 user[256]; - rdr::U8 pass[64]; + uint8_t key[8]; + uint8_t reversedKey[8]; + uint8_t BBytes[8]; + uint8_t user[256]; + uint8_t pass[64]; nettle_mpz_get_str_256(8, key, k); nettle_mpz_get_str_256(8, BBytes, B); for (int i = 0; i < 8; ++i) { - rdr::U8 x = 0; + uint8_t x = 0; for (int j = 0; j < 8; ++j) { x |= ((key[i] >> j) & 1) << (7 - j); } @@ -125,14 +126,12 @@ void CSecurityMSLogonII::writeCredentials() throw ConnFailedException("failed to generate random padding"); rs.readBytes(user, 256); rs.readBytes(pass, 64); - size_t len = strlen(username.buf); - if (len >= 256) + if (username.size() >= 256) throw AuthFailureException("username is too long"); - memcpy(user, username.buf, len + 1); - len = strlen(password.buf); - if (len >= 64) + memcpy(user, username.c_str(), username.size() + 1); + if (password.size() >= 64) throw AuthFailureException("password is too long"); - memcpy(pass, password.buf, len + 1); + memcpy(pass, password.c_str(), password.size() + 1); // DES-CBC with the original key as IV, and the reversed one as the DES key struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx; diff --git a/common/rfb/CSecurityPlain.cxx b/common/rfb/CSecurityPlain.cxx index 464dfcb5..7b75ef86 100644 --- a/common/rfb/CSecurityPlain.cxx +++ b/common/rfb/CSecurityPlain.cxx @@ -24,7 +24,6 @@ #include <rfb/CConnection.h> #include <rfb/CSecurityPlain.h> #include <rfb/UserPasswdGetter.h> -#include <rfb/util.h> #include <rdr/OutStream.h> @@ -34,16 +33,16 @@ bool CSecurityPlain::processMsg() { rdr::OutStream* os = cc->getOutStream(); - CharArray username; - CharArray password; + std::string username; + std::string password; - (CSecurity::upg)->getUserPasswd(cc->isSecure(), &username.buf, &password.buf); + (CSecurity::upg)->getUserPasswd(cc->isSecure(), &username, &password); // Return the response to the server - os->writeU32(strlen(username.buf)); - os->writeU32(strlen(password.buf)); - os->writeBytes(username.buf,strlen(username.buf)); - os->writeBytes(password.buf,strlen(password.buf)); + os->writeU32(username.size()); + os->writeU32(password.size()); + os->writeBytes(username.data(), username.size()); + os->writeBytes(password.data(), password.size()); os->flush(); return true; } diff --git a/common/rfb/CSecurityRSAAES.cxx b/common/rfb/CSecurityRSAAES.cxx index c84422b6..6194caab 100644 --- a/common/rfb/CSecurityRSAAES.cxx +++ b/common/rfb/CSecurityRSAAES.cxx @@ -39,6 +39,7 @@ #include <rfb/LogWriter.h> #include <rfb/Exception.h> #include <rfb/UserMsgBox.h> +#include <rfb/util.h> #include <rdr/AESInStream.h> #include <rdr/AESOutStream.h> #include <os/os.h> @@ -55,7 +56,7 @@ const int MaxKeyLength = 8192; using namespace rfb; -CSecurityRSAAES::CSecurityRSAAES(CConnection* cc, rdr::U32 _secType, +CSecurityRSAAES::CSecurityRSAAES(CConnection* cc, uint32_t _secType, int _keySize, bool _isAllEncrypted) : CSecurity(cc), state(ReadPublicKey), keySize(_keySize), isAllEncrypted(_isAllEncrypted), secType(_secType), @@ -155,8 +156,8 @@ void CSecurityRSAAES::writePublicKey() if (!rsa_generate_keypair(&clientPublicKey, &clientKey, &rs, random_func, NULL, NULL, clientKeyLength, 0)) throw AuthFailureException("failed to generate key"); - clientKeyN = new rdr::U8[rsaKeySize]; - clientKeyE = new rdr::U8[rsaKeySize]; + clientKeyN = new uint8_t[rsaKeySize]; + clientKeyE = new uint8_t[rsaKeySize]; nettle_mpz_get_str_256(rsaKeySize, clientKeyN, clientPublicKey.n); nettle_mpz_get_str_256(rsaKeySize, clientKeyE, clientPublicKey.e); os->writeU32(clientKeyLength); @@ -180,8 +181,8 @@ bool CSecurityRSAAES::readPublicKey() if (!is->hasDataOrRestore(size * 2)) return false; is->clearRestorePoint(); - serverKeyE = new rdr::U8[size]; - serverKeyN = new rdr::U8[size]; + serverKeyE = new uint8_t[size]; + serverKeyN = new uint8_t[size]; is->readBytes(serverKeyN, size); is->readBytes(serverKeyE, size); rsa_public_key_init(&serverKey); @@ -194,13 +195,13 @@ bool CSecurityRSAAES::readPublicKey() void CSecurityRSAAES::verifyServer() { - rdr::U8 lenServerKey[4] = { - (rdr::U8)((serverKeyLength & 0xff000000) >> 24), - (rdr::U8)((serverKeyLength & 0xff0000) >> 16), - (rdr::U8)((serverKeyLength & 0xff00) >> 8), - (rdr::U8)(serverKeyLength & 0xff) + uint8_t lenServerKey[4] = { + (uint8_t)((serverKeyLength & 0xff000000) >> 24), + (uint8_t)((serverKeyLength & 0xff0000) >> 16), + (uint8_t)((serverKeyLength & 0xff00) >> 8), + (uint8_t)(serverKeyLength & 0xff) }; - rdr::U8 f[8]; + uint8_t f[8]; struct sha1_ctx ctx; sha1_init(&ctx); sha1_update(&ctx, 4, lenServerKey); @@ -208,13 +209,12 @@ void CSecurityRSAAES::verifyServer() sha1_update(&ctx, serverKey.size, serverKeyE); sha1_digest(&ctx, sizeof(f), f); const char *title = "Server key fingerprint"; - CharArray text; - text.format( + std::string text = 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\". " "Otherwise press \"No\"", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, title, text.buf)) + if (!msg->showMsgBox(UserMsgBox::M_YESNO, title, text.c_str())) throw AuthFailureException("server key mismatch"); } @@ -238,7 +238,7 @@ void CSecurityRSAAES::writeRandom() mpz_clear(x); throw AuthFailureException("failed to encrypt random"); } - rdr::U8* buffer = new rdr::U8[serverKey.size]; + uint8_t* buffer = new uint8_t[serverKey.size]; nettle_mpz_get_str_256(serverKey.size, buffer, x); mpz_clear(x); os->writeU16(serverKey.size); @@ -259,7 +259,7 @@ bool CSecurityRSAAES::readRandom() if (!is->hasDataOrRestore(size)) return false; is->clearRestorePoint(); - rdr::U8* buffer = new rdr::U8[size]; + uint8_t* buffer = new uint8_t[size]; is->readBytes(buffer, size); size_t randomSize = keySize / 8; mpz_t x; @@ -278,7 +278,7 @@ void CSecurityRSAAES::setCipher() { rawis = cc->getInStream(); rawos = cc->getOutStream(); - rdr::U8 key[32]; + uint8_t key[32]; if (keySize == 128) { struct sha1_ctx ctx; sha1_init(&ctx); @@ -310,20 +310,20 @@ void CSecurityRSAAES::setCipher() void CSecurityRSAAES::writeHash() { - rdr::U8 hash[32]; + uint8_t hash[32]; size_t len = serverKeyLength; - rdr::U8 lenServerKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenServerKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; len = clientKeyLength; - rdr::U8 lenClientKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenClientKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; int hashSize; if (keySize == 128) { @@ -355,25 +355,25 @@ void CSecurityRSAAES::writeHash() bool CSecurityRSAAES::readHash() { - rdr::U8 hash[32]; - rdr::U8 realHash[32]; + uint8_t hash[32]; + uint8_t realHash[32]; int hashSize = keySize == 128 ? 20 : 32; if (!rais->hasData(hashSize)) return false; rais->readBytes(hash, hashSize); size_t len = serverKeyLength; - rdr::U8 lenServerKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenServerKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; len = clientKeyLength; - rdr::U8 lenClientKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenClientKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; if (keySize == 128) { struct sha1_ctx ctx; @@ -433,29 +433,26 @@ bool CSecurityRSAAES::readSubtype() void CSecurityRSAAES::writeCredentials() { - CharArray username; - CharArray password; + std::string username; + std::string password; - (CSecurity::upg)->getUserPasswd( - isSecure(), - subtype == secTypeRA2UserPass ? &username.buf : NULL, &password.buf - ); - size_t len; - if (username.buf) { - len = strlen(username.buf); - if (len > 255) + if (subtype == secTypeRA2UserPass) + (CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); + else + (CSecurity::upg)->getUserPasswd(isSecure(), NULL, &password); + + if (subtype == secTypeRA2UserPass) { + if (username.size() > 255) throw AuthFailureException("username is too long"); - raos->writeU8(len); - if (len) - raos->writeBytes(username.buf, len); + raos->writeU8(username.size()); + raos->writeBytes(username.data(), username.size()); } else { raos->writeU8(0); } - len = strlen(password.buf); - if (len > 255) + + if (password.size() > 255) throw AuthFailureException("password is too long"); - raos->writeU8(len); - if (len) - raos->writeBytes(password.buf, len); + raos->writeU8(password.size()); + raos->writeBytes(password.data(), password.size()); raos->flush(); -}
\ No newline at end of file +} diff --git a/common/rfb/CSecurityRSAAES.h b/common/rfb/CSecurityRSAAES.h index f58bb87f..543b0152 100644 --- a/common/rfb/CSecurityRSAAES.h +++ b/common/rfb/CSecurityRSAAES.h @@ -36,7 +36,7 @@ namespace rfb { class UserMsgBox; class CSecurityRSAAES : public CSecurity { public: - CSecurityRSAAES(CConnection* cc, rdr::U32 secType, + CSecurityRSAAES(CConnection* cc, uint32_t secType, int keySize, bool isAllEncrypted); virtual ~CSecurityRSAAES(); virtual bool processMsg(); @@ -62,19 +62,19 @@ namespace rfb { int state; int keySize; bool isAllEncrypted; - rdr::U32 secType; - rdr::U8 subtype; + uint32_t secType; + uint8_t subtype; struct rsa_private_key clientKey; struct rsa_public_key clientPublicKey; struct rsa_public_key serverKey; - rdr::U32 serverKeyLength; - rdr::U8* serverKeyN; - rdr::U8* serverKeyE; - rdr::U32 clientKeyLength; - rdr::U8* clientKeyN; - rdr::U8* clientKeyE; - rdr::U8 serverRandom[32]; - rdr::U8 clientRandom[32]; + uint32_t serverKeyLength; + uint8_t* serverKeyN; + uint8_t* serverKeyE; + uint32_t clientKeyLength; + uint8_t* clientKeyN; + uint8_t* clientKeyE; + uint8_t serverRandom[32]; + uint8_t clientRandom[32]; rdr::InStream* rais; rdr::OutStream* raos; diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx index ca1c919b..e24f9d71 100644 --- a/common/rfb/CSecurityTLS.cxx +++ b/common/rfb/CSecurityTLS.cxx @@ -39,6 +39,7 @@ #include <rfb/LogWriter.h> #include <rfb/Exception.h> #include <rfb/UserMsgBox.h> +#include <rfb/util.h> #include <rdr/TLSInStream.h> #include <rdr/TLSOutStream.h> #include <os/os.h> @@ -76,14 +77,13 @@ static LogWriter vlog("TLS"); static const char* homedirfn(const char* fn) { static char full_path[PATH_MAX]; - char* homedir = NULL; + const char* homedir; - if (getvnchomedir(&homedir) == -1) + homedir = os::getvnchomedir(); + if (homedir == NULL) return ""; - snprintf(full_path, sizeof(full_path), "%s%s", homedir, fn); - - delete [] homedir; + snprintf(full_path, sizeof(full_path), "%s/%s", homedir, fn); return full_path; } @@ -92,9 +92,6 @@ CSecurityTLS::CSecurityTLS(CConnection* cc, bool _anon) : CSecurity(cc), session(NULL), anon_cred(NULL), cert_cred(NULL), anon(_anon), tlsis(NULL), tlsos(NULL), rawis(NULL), rawos(NULL) { - cafile = X509CA.getData(); - crlfile = X509CRL.getData(); - if (gnutls_global_init() != GNUTLS_E_SUCCESS) throw AuthFailureException("gnutls_global_init failed"); } @@ -146,9 +143,6 @@ CSecurityTLS::~CSecurityTLS() { shutdown(); - delete[] cafile; - delete[] crlfile; - gnutls_global_deinit(); } @@ -287,10 +281,10 @@ void CSecurityTLS::setParam() if (gnutls_certificate_set_x509_system_trust(cert_cred) < 1) vlog.error("Could not load system certificate trust store"); - if (*cafile && gnutls_certificate_set_x509_trust_file(cert_cred,cafile,GNUTLS_X509_FMT_PEM) < 0) + if (gnutls_certificate_set_x509_trust_file(cert_cred, X509CA, GNUTLS_X509_FMT_PEM) < 0) vlog.error("Could not load user specified certificate authority"); - if (*crlfile && gnutls_certificate_set_x509_crl_file(cert_cred,crlfile,GNUTLS_X509_FMT_PEM) < 0) + if (gnutls_certificate_set_x509_crl_file(cert_cred, X509CRL, GNUTLS_X509_FMT_PEM) < 0) vlog.error("Could not load user specified certificate revocation list"); if (gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred) != GNUTLS_E_SUCCESS) @@ -316,7 +310,7 @@ void CSecurityTLS::checkSession() unsigned int cert_list_size = 0; int err; - char *homeDir; + const char *homeDir; gnutls_datum_t info; size_t len; @@ -361,12 +355,14 @@ void CSecurityTLS::checkSession() throw AuthFailureException("decoding of certificate failed"); if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) { - CharArray text; + std::string text; vlog.debug("hostname mismatch"); - text.format("Hostname (%s) does not match the server certificate, " - "do you want to continue?", client->getServerName()); + text = format("Hostname (%s) does not match the server " + "certificate, do you want to continue?", + client->getServerName()); if (!msg->showMsgBox(UserMsgBox::M_YESNO, - "Certificate hostname mismatch", text.buf)) + "Certificate hostname mismatch", + text.c_str())) throw AuthFailureException("Certificate hostname mismatch"); } @@ -396,17 +392,16 @@ void CSecurityTLS::checkSession() /* Certificate is fine, except we don't know the issuer, so TOFU time */ - homeDir = NULL; - if (getvnchomedir(&homeDir) == -1) { + homeDir = os::getvnchomedir(); + if (homeDir == NULL) { throw AuthFailureException("Could not obtain VNC home directory " "path for known hosts storage"); } - CharArray dbPath(strlen(homeDir) + 16 + 1); - sprintf(dbPath.buf, "%sx509_known_hosts", homeDir); - delete [] homeDir; + std::string dbPath; + dbPath = (std::string)homeDir + "/x509_known_hosts"; - err = gnutls_verify_stored_pubkey(dbPath.buf, NULL, + err = gnutls_verify_stored_pubkey(dbPath.c_str(), NULL, client->getServerName(), NULL, GNUTLS_CRT_X509, &cert_list[0], 0); @@ -433,73 +428,93 @@ void CSecurityTLS::checkSession() /* New host */ if (err == GNUTLS_E_NO_CERTIFICATE_FOUND) { - CharArray text; + std::string text; vlog.debug("Server host not previously known"); vlog.debug("%s", info.data); if (status & (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\nSomeone could be trying to " - "impersonate the site and you should not " - "continue.\n\nDo you want to make an exception " - "for this server?", info.data); + 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); if (!msg->showMsgBox(UserMsgBox::M_YESNO, "Unknown certificate issuer", - text.buf)) + text.c_str())) throw AuthFailureException("Unknown certificate issuer"); } if (status & GNUTLS_CERT_EXPIRED) { - text.format("This certificate has expired:\n\n%s\n\nSomeone " - "could be trying to impersonate the site and you " - "should not continue.\n\nDo you want to make an " - "exception for this server?", info.data); + 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); if (!msg->showMsgBox(UserMsgBox::M_YESNO, "Expired certificate", - text.buf)) + text.c_str())) throw AuthFailureException("Expired certificate"); } } else if (err == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) { - CharArray text; + std::string text; vlog.debug("Server host key mismatch"); vlog.debug("%s", info.data); if (status & (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\nSomeone " - "could be trying to impersonate the site and you " - "should not continue.\n\nDo you want to make an " - "exception for this server?", info.data); + 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); if (!msg->showMsgBox(UserMsgBox::M_YESNO, "Unexpected server certificate", - text.buf)) + text.c_str())) throw AuthFailureException("Unexpected server certificate"); } 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\nSomeone could be trying to impersonate " - "the site and you should not continue.\n\nDo you " - "want to make an exception for this server?", - info.data); + 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); if (!msg->showMsgBox(UserMsgBox::M_YESNO, "Unexpected server certificate", - text.buf)) + text.c_str())) throw AuthFailureException("Unexpected server certificate"); } } - if (gnutls_store_pubkey(dbPath.buf, NULL, client->getServerName(), + if (gnutls_store_pubkey(dbPath.c_str(), NULL, client->getServerName(), NULL, GNUTLS_CRT_X509, &cert_list[0], 0, 0)) vlog.error("Failed to store server certificate to known hosts database"); diff --git a/common/rfb/CSecurityTLS.h b/common/rfb/CSecurityTLS.h index fb317748..b9c345cf 100644 --- a/common/rfb/CSecurityTLS.h +++ b/common/rfb/CSecurityTLS.h @@ -58,8 +58,6 @@ namespace rfb { gnutls_certificate_credentials_t cert_cred; bool anon; - char *cafile, *crlfile; - rdr::InStream* tlsis; rdr::OutStream* tlsos; diff --git a/common/rfb/CSecurityVeNCrypt.cxx b/common/rfb/CSecurityVeNCrypt.cxx index 046cd8d0..59be49a0 100644 --- a/common/rfb/CSecurityVeNCrypt.cxx +++ b/common/rfb/CSecurityVeNCrypt.cxx @@ -86,7 +86,8 @@ bool CSecurityVeNCrypt::processMsg() } /* major version in upper 8 bits and minor version in lower 8 bits */ - U16 Version = (((U16) majorVersion) << 8) | ((U16) minorVersion); + uint16_t Version = (((uint16_t) majorVersion) << 8) | + ((uint16_t) minorVersion); if (!haveSentVersion) { /* Currently we don't support former VeNCrypt 0.1 */ @@ -131,7 +132,7 @@ bool CSecurityVeNCrypt::processMsg() if (!nAvailableTypes) throw AuthFailureException("The server reported no VeNCrypt sub-types"); - availableTypes = new rdr::U32[nAvailableTypes]; + availableTypes = new uint32_t[nAvailableTypes]; haveNumberOfTypes = true; } @@ -154,9 +155,9 @@ bool CSecurityVeNCrypt::processMsg() /* make a choice and send it to the server, meanwhile set up the stack */ if (!haveChosenType) { chosenType = secTypeInvalid; - U8 i; - list<U32>::iterator j; - list<U32> secTypes; + uint8_t i; + list<uint32_t>::iterator j; + list<uint32_t> secTypes; secTypes = security->GetEnabledExtSecTypes(); diff --git a/common/rfb/CSecurityVeNCrypt.h b/common/rfb/CSecurityVeNCrypt.h index d087b2a4..476bf813 100644 --- a/common/rfb/CSecurityVeNCrypt.h +++ b/common/rfb/CSecurityVeNCrypt.h @@ -25,9 +25,10 @@ #ifndef __CSECURITYVENCRYPT_H__ #define __CSECURITYVENCRYPT_H__ +#include <stdint.h> + #include <rfb/CSecurity.h> #include <rfb/SecurityClient.h> -#include <rdr/types.h> namespace rfb { @@ -50,10 +51,10 @@ namespace rfb { bool haveListOfTypes; bool haveNumberOfTypes; bool haveChosenType; - rdr::U8 majorVersion, minorVersion; - rdr::U32 chosenType; - rdr::U8 nAvailableTypes; - rdr::U32 *availableTypes; + uint8_t majorVersion, minorVersion; + uint32_t chosenType; + uint8_t nAvailableTypes; + uint32_t *availableTypes; }; } #endif diff --git a/common/rfb/CSecurityVncAuth.cxx b/common/rfb/CSecurityVncAuth.cxx index a899b5e7..f6a5e07a 100644 --- a/common/rfb/CSecurityVncAuth.cxx +++ b/common/rfb/CSecurityVncAuth.cxx @@ -29,9 +29,7 @@ #include <stdio.h> #include <rfb/CConnection.h> -#include <rfb/Password.h> #include <rfb/CSecurityVncAuth.h> -#include <rfb/util.h> #include <rfb/Security.h> extern "C" { #include <rfb/d3des.h> @@ -53,16 +51,15 @@ bool CSecurityVncAuth::processMsg() return false; // Read the challenge & obtain the user's password - rdr::U8 challenge[vncAuthChallengeSize]; + uint8_t challenge[vncAuthChallengeSize]; is->readBytes(challenge, vncAuthChallengeSize); - PlainPasswd passwd; - (CSecurity::upg)->getUserPasswd(cc->isSecure(), 0, &passwd.buf); + std::string passwd; + (CSecurity::upg)->getUserPasswd(cc->isSecure(), 0, &passwd); // Calculate the correct response - rdr::U8 key[8]; - int pwdLen = strlen(passwd.buf); - for (int i=0; i<8; i++) - key[i] = i<pwdLen ? passwd.buf[i] : 0; + uint8_t key[8]; + for (size_t i=0; i<8; i++) + key[i] = i<passwd.size() ? passwd[i] : 0; deskey(key, EN0); for (int j = 0; j < vncAuthChallengeSize; j += 8) des(challenge+j, challenge+j); diff --git a/common/rfb/ClientParams.cxx b/common/rfb/ClientParams.cxx index d933aa34..ade99018 100644 --- a/common/rfb/ClientParams.cxx +++ b/common/rfb/ClientParams.cxx @@ -34,7 +34,7 @@ ClientParams::ClientParams() : majorVersion(0), minorVersion(0), compressLevel(2), qualityLevel(-1), fineQualityLevel(-1), subsampling(subsampleUndefined), - width_(0), height_(0), name_(0), + width_(0), height_(0), cursorPos_(0, 0), ledState_(ledUnknown) { setName(""); @@ -49,7 +49,6 @@ ClientParams::ClientParams() ClientParams::~ClientParams() { - delete [] name_; delete cursor_; } @@ -80,8 +79,7 @@ void ClientParams::setPF(const PixelFormat& pf) void ClientParams::setName(const char* name) { - delete [] name_; - name_ = strDup(name); + name_ = name; } void ClientParams::setCursor(const Cursor& other) @@ -95,12 +93,12 @@ void ClientParams::setCursorPos(const Point& pos) cursorPos_ = pos; } -bool ClientParams::supportsEncoding(rdr::S32 encoding) const +bool ClientParams::supportsEncoding(int32_t encoding) const { return encodings_.count(encoding) != 0; } -void ClientParams::setEncodings(int nEncodings, const rdr::S32* encodings) +void ClientParams::setEncodings(int nEncodings, const int32_t* encodings) { compressLevel = -1; qualityLevel = -1; @@ -153,7 +151,7 @@ void ClientParams::setLEDState(unsigned int state) ledState_ = state; } -rdr::U32 ClientParams::clipboardSize(unsigned int format) const +uint32_t ClientParams::clipboardSize(unsigned int format) const { int i; @@ -165,7 +163,7 @@ rdr::U32 ClientParams::clipboardSize(unsigned int format) const throw Exception("Invalid clipboard format 0x%x", format); } -void ClientParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) +void ClientParams::setClipboardCaps(uint32_t flags, const uint32_t* lengths) { int i, num; diff --git a/common/rfb/ClientParams.h b/common/rfb/ClientParams.h index a78ad14c..ea86ea78 100644 --- a/common/rfb/ClientParams.h +++ b/common/rfb/ClientParams.h @@ -24,8 +24,10 @@ #define __RFB_CLIENTPARAMS_H__ #include <set> +#include <string> + +#include <stdint.h> -#include <rdr/types.h> #include <rfb/Cursor.h> #include <rfb/PixelFormat.h> #include <rfb/ScreenSet.h> @@ -71,7 +73,7 @@ namespace rfb { const PixelFormat& pf() const { return pf_; } void setPF(const PixelFormat& pf); - const char* name() const { return name_; } + const char* name() const { return name_.c_str(); } void setName(const char* name); const Cursor& cursor() const { return *cursor_; } @@ -80,16 +82,16 @@ namespace rfb { const Point& cursorPos() const { return cursorPos_; } void setCursorPos(const Point& pos); - bool supportsEncoding(rdr::S32 encoding) const; + bool supportsEncoding(int32_t encoding) const; - void setEncodings(int nEncodings, const rdr::S32* encodings); + void setEncodings(int nEncodings, const int32_t* encodings); unsigned int ledState() { return ledState_; } void setLEDState(unsigned int state); - rdr::U32 clipboardFlags() const { return clipFlags; } - rdr::U32 clipboardSize(unsigned int format) const; - void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths); + uint32_t clipboardFlags() const { return clipFlags; } + uint32_t clipboardSize(unsigned int format) const; + void setClipboardCaps(uint32_t flags, const uint32_t* lengths); // Wrappers to check for functionality rather than specific // encodings @@ -112,13 +114,13 @@ namespace rfb { ScreenSet screenLayout_; PixelFormat pf_; - char* name_; + std::string name_; Cursor* cursor_; Point cursorPos_; - std::set<rdr::S32> encodings_; + std::set<int32_t> encodings_; unsigned int ledState_; - rdr::U32 clipFlags; - rdr::U32 clipSizes[16]; + uint32_t clipFlags; + uint32_t clipSizes[16]; }; } #endif diff --git a/common/rfb/ComparingUpdateTracker.cxx b/common/rfb/ComparingUpdateTracker.cxx index e0964ac2..dab5e6aa 100644 --- a/common/rfb/ComparingUpdateTracker.cxx +++ b/common/rfb/ComparingUpdateTracker.cxx @@ -23,9 +23,11 @@ #include <stdio.h> #include <string.h> #include <vector> -#include <rdr/types.h> + #include <rfb/Exception.h> #include <rfb/LogWriter.h> +#include <rfb/util.h> + #include <rfb/ComparingUpdateTracker.h> using namespace rfb; @@ -62,7 +64,7 @@ bool ComparingUpdateTracker::compare() for (int y=0; y<fb->height(); y+=BLOCK_SIZE) { Rect pos(0, y, fb->width(), __rfbmin(fb->height(), y+BLOCK_SIZE)); int srcStride; - const rdr::U8* srcData = fb->getBuffer(pos, &srcStride); + const uint8_t* srcData = fb->getBuffer(pos, &srcStride); oldFb.imageRect(pos, srcData, srcStride); } @@ -88,7 +90,7 @@ bool ComparingUpdateTracker::compare() for (i = rects.begin(); i != rects.end(); i++) missedPixels += i->area(); - if (changed.equals(newChanged)) + if (changed == newChanged) return false; changed = newChanged; @@ -122,7 +124,7 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) int bytesPerPixel = fb->getPF().bpp/8; int oldStride; - rdr::U8* oldData = oldFb.getBufferRW(r, &oldStride); + uint8_t* oldData = oldFb.getBufferRW(r, &oldStride); int oldStrideBytes = oldStride * bytesPerPixel; // Used to efficiently crop the left and right of the change rectangle @@ -134,16 +136,16 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) // Get a strip of the source buffer Rect pos(r.tl.x, blockTop, r.br.x, __rfbmin(r.br.y, blockTop+BLOCK_SIZE)); int fbStride; - const rdr::U8* newBlockPtr = fb->getBuffer(pos, &fbStride); + const uint8_t* newBlockPtr = fb->getBuffer(pos, &fbStride); int newStrideBytes = fbStride * bytesPerPixel; - rdr::U8* oldBlockPtr = oldData; + uint8_t* oldBlockPtr = oldData; int blockBottom = __rfbmin(blockTop+BLOCK_SIZE, r.br.y); for (int blockLeft = r.tl.x; blockLeft < r.br.x; blockLeft += BLOCK_SIZE) { - const rdr::U8* newPtr = newBlockPtr; - rdr::U8* oldPtr = oldBlockPtr; + const uint8_t* newPtr = newBlockPtr; + uint8_t* oldPtr = oldBlockPtr; int blockRight = __rfbmin(blockLeft+BLOCK_SIZE, r.br.x); int blockWidthInBytes = (blockRight-blockLeft) * bytesPerPixel; @@ -160,8 +162,8 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) // For every unchanged row at the bottom of the block, decrement change height { - const rdr::U8* newRowPtr = newPtr + ((changeHeight - 1) * newStrideBytes); - const rdr::U8* oldRowPtr = oldPtr + ((changeHeight - 1) * oldStrideBytes); + const uint8_t* newRowPtr = newPtr + ((changeHeight - 1) * newStrideBytes); + const uint8_t* oldRowPtr = oldPtr + ((changeHeight - 1) * oldStrideBytes); while (changeHeight > 1 && memcmp(oldRowPtr, newRowPtr, blockWidthInBytes) == 0) { newRowPtr -= newStrideBytes; @@ -173,12 +175,12 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) // For every unchanged column at the left of the block, increment change left { - const rdr::U8* newColumnPtr = newPtr; - const rdr::U8* oldColumnPtr = oldPtr; + const uint8_t* newColumnPtr = newPtr; + const uint8_t* oldColumnPtr = oldPtr; while (changeLeft + minCompareWidthInPixels < changeRight) { - const rdr::U8* newRowPtr = newColumnPtr; - const rdr::U8* oldRowPtr = oldColumnPtr; + const uint8_t* newRowPtr = newColumnPtr; + const uint8_t* oldRowPtr = oldColumnPtr; for (int row = 0; row < changeHeight; row++) { if (memcmp(oldRowPtr, newRowPtr, minCompareWidthInBytes) != 0) @@ -198,15 +200,15 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) // For every unchanged column at the right of the block, decrement change right { - const rdr::U8* newColumnPtr = newPtr + blockWidthInBytes; - const rdr::U8* oldColumnPtr = oldPtr + blockWidthInBytes; + const uint8_t* newColumnPtr = newPtr + blockWidthInBytes; + const uint8_t* oldColumnPtr = oldPtr + blockWidthInBytes; while (changeLeft + minCompareWidthInPixels < changeRight) { newColumnPtr -= minCompareWidthInBytes; oldColumnPtr -= minCompareWidthInBytes; - const rdr::U8* newRowPtr = newColumnPtr; - const rdr::U8* oldRowPtr = oldColumnPtr; + const uint8_t* newRowPtr = newColumnPtr; + const uint8_t* oldRowPtr = oldColumnPtr; for (int row = 0; row < changeHeight; row++) { if (memcmp(oldRowPtr, newRowPtr, minCompareWidthInBytes) != 0) @@ -253,14 +255,12 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) void ComparingUpdateTracker::logStats() { double ratio; - char a[1024], b[1024]; - - siPrefix(totalPixels, "pixels", a, sizeof(a)); - siPrefix(missedPixels, "pixels", b, sizeof(b)); ratio = (double)totalPixels / missedPixels; - vlog.info("%s in / %s out", a, b); + vlog.info("%s in / %s out", + siPrefix(totalPixels, "pixels").c_str(), + siPrefix(missedPixels, "pixels").c_str()); vlog.info("(1:%g ratio)", ratio); totalPixels = missedPixels = 0; diff --git a/common/rfb/Configuration.cxx b/common/rfb/Configuration.cxx index 8848e08d..1c215c7f 100644 --- a/common/rfb/Configuration.cxx +++ b/common/rfb/Configuration.cxx @@ -1,6 +1,7 @@ /* 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 @@ -24,6 +25,7 @@ #include <config.h> #endif +#include <assert.h> #include <stdlib.h> #include <ctype.h> #include <string.h> @@ -131,9 +133,9 @@ VoidParameter* Configuration::get(const char* param) void Configuration::list(int width, int nameWidth) { VoidParameter* current = head; - fprintf(stderr, "%s Parameters:\n", name.buf); + fprintf(stderr, "%s Parameters:\n", name.c_str()); while (current) { - char* def_str = current->getDefaultStr(); + std::string def_str = current->getDefaultStr(); const char* desc = current->getDescription(); fprintf(stderr," %-*s -", nameWidth, current->getName()); int column = strlen(current->getName()); @@ -155,11 +157,10 @@ void Configuration::list(int width, int nameWidth) { if (!s) break; } - if (def_str) { - if (column + (int)strlen(def_str) + 11 > width) + 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); - strFree(def_str); + fprintf(stderr," (default=%s)\n",def_str.c_str()); } else { fprintf(stderr,"\n"); } @@ -255,12 +256,11 @@ bool AliasParameter::setParam() { return param->setParam(); } -char* -AliasParameter::getDefaultStr() const { - return 0; +std::string AliasParameter::getDefaultStr() const { + return ""; } -char* AliasParameter::getValueStr() const { +std::string AliasParameter::getValueStr() const { return param->getValueStr(); } @@ -288,16 +288,15 @@ BoolParameter::setParam(const char* v) { if (*v == 0 || strcasecmp(v, "1") == 0 || strcasecmp(v, "on") == 0 || strcasecmp(v, "true") == 0 || strcasecmp(v, "yes") == 0) - value = 1; + setParam(true); else if (strcasecmp(v, "0") == 0 || strcasecmp(v, "off") == 0 || strcasecmp(v, "false") == 0 || strcasecmp(v, "no") == 0) - value = 0; + setParam(false); else { vlog.error("Bool parameter %s: invalid value '%s'", getName(), v); return false; } - vlog.debug("set %s(Bool) to %s(%d)", getName(), v, value); return true; } @@ -312,13 +311,12 @@ void BoolParameter::setParam(bool b) { vlog.debug("set %s(Bool) to %d", getName(), value); } -char* -BoolParameter::getDefaultStr() const { - return strDup(def_value ? "1" : "0"); +std::string BoolParameter::getDefaultStr() const { + return def_value ? "1" : "0"; } -char* BoolParameter::getValueStr() const { - return strDup(value ? "1" : "0"); +std::string BoolParameter::getValueStr() const { + return value ? "1" : "0"; } bool BoolParameter::isBool() const { @@ -341,12 +339,7 @@ IntParameter::IntParameter(const char* name_, const char* desc_, int v, bool IntParameter::setParam(const char* v) { if (immutable) return true; - vlog.debug("set %s(Int) to %s", getName(), v); - int i = strtol(v, NULL, 0); - if (i < minValue || i > maxValue) - return false; - value = i; - return true; + return setParam(strtol(v, NULL, 0)); } bool @@ -359,15 +352,14 @@ IntParameter::setParam(int v) { return true; } -char* -IntParameter::getDefaultStr() const { - char* result = new char[16]; +std::string IntParameter::getDefaultStr() const { + char result[16]; sprintf(result, "%d", def_value); return result; } -char* IntParameter::getValueStr() const { - char* result = new char[16]; +std::string IntParameter::getValueStr() const { + char result[16]; sprintf(result, "%d", value); return result; } @@ -380,7 +372,7 @@ IntParameter::operator int() const { StringParameter::StringParameter(const char* name_, const char* desc_, const char* v, ConfigurationObject co) - : VoidParameter(name_, desc_, co), value(strDup(v)), def_value(strDup(v)) + : VoidParameter(name_, desc_, co), value(v), def_value(v) { if (!v) { vlog.error("Default value <null> for %s not allowed",name_); @@ -389,8 +381,6 @@ StringParameter::StringParameter(const char* name_, const char* desc_, } StringParameter::~StringParameter() { - strFree(value); - strFree(def_value); } bool StringParameter::setParam(const char* v) { @@ -399,34 +389,34 @@ bool StringParameter::setParam(const char* v) { if (!v) throw rfb::Exception("setParam(<null>) not allowed"); vlog.debug("set %s(String) to %s", getName(), v); - CharArray oldValue(value); - value = strDup(v); - return value != 0; + value = v; + return true; } -char* StringParameter::getDefaultStr() const { - return strDup(def_value); +std::string StringParameter::getDefaultStr() const { + return def_value; } -char* StringParameter::getValueStr() const { +std::string StringParameter::getValueStr() const { LOCK_CONFIG; - return strDup(value); + return value; } StringParameter::operator const char *() const { - return value; + return value.c_str(); } // -=- BinaryParameter BinaryParameter::BinaryParameter(const char* name_, const char* desc_, - const void* v, size_t l, ConfigurationObject co) + const uint8_t* v, size_t l, ConfigurationObject co) : VoidParameter(name_, desc_, co), value(0), length(0), def_value(0), def_length(0) { if (l) { - value = new char[l]; + assert(v); + value = new uint8_t[l]; length = l; memcpy(value, v, l); - def_value = new char[l]; + def_value = new uint8_t[l]; def_length = l; memcpy(def_value, v, l); } @@ -437,38 +427,41 @@ BinaryParameter::~BinaryParameter() { } bool BinaryParameter::setParam(const char* v) { - LOCK_CONFIG; if (immutable) return true; - vlog.debug("set %s(Binary) to %s", getName(), v); - return rdr::HexInStream::hexStrToBin(v, &value, &length); + 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 void* v, size_t len) { +void BinaryParameter::setParam(const uint8_t* v, size_t len) { LOCK_CONFIG; if (immutable) return; vlog.debug("set %s(Binary)", getName()); - delete [] value; value = 0; + delete [] value; + value = NULL; + length = 0; if (len) { - value = new char[len]; + assert(v); + value = new uint8_t[len]; length = len; memcpy(value, v, len); } } -char* BinaryParameter::getDefaultStr() const { - return rdr::HexOutStream::binToHexStr(def_value, def_length); +std::string BinaryParameter::getDefaultStr() const { + return binToHex(def_value, def_length); } -char* BinaryParameter::getValueStr() const { +std::string BinaryParameter::getValueStr() const { LOCK_CONFIG; - return rdr::HexOutStream::binToHexStr(value, length); + return binToHex(value, length); } -void BinaryParameter::getData(void** data_, size_t* length_) const { +std::vector<uint8_t> BinaryParameter::getData() const { LOCK_CONFIG; - if (length_) *length_ = length; - if (data_) { - *data_ = new char[length]; - memcpy(*data_, value, length); - } + 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 index 396e40dd..d73d8005 100644 --- a/common/rfb/Configuration.h +++ b/common/rfb/Configuration.h @@ -1,4 +1,5 @@ /* 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 @@ -43,7 +44,11 @@ #ifndef __RFB_CONFIGURATION_H__ #define __RFB_CONFIGURATION_H__ -#include <rfb/util.h> +#include <limits.h> +#include <stdint.h> + +#include <string> +#include <vector> namespace os { class Mutex; } @@ -59,10 +64,10 @@ namespace rfb { class Configuration { public: // - Create a new Configuration object - Configuration(const char* name_) : name(strDup(name_)), head(0), _next(0) {} + Configuration(const char* name_) : name(name_), head(0), _next(0) {} // - Return the buffer containing the Configuration's name - const char* getName() const { return name.buf; } + const char* getName() const { return name.c_str(); } // - Set named parameter to value bool set(const char* param, const char* value, bool immutable=false); @@ -128,7 +133,7 @@ namespace rfb { friend struct ParameterIterator; // Name for this Configuration - CharArray name; + std::string name; // - Pointer to first Parameter in this group VoidParameter* head; @@ -168,8 +173,8 @@ namespace rfb { virtual bool setParam(const char* value) = 0; virtual bool setParam(); - virtual char* getDefaultStr() const = 0; - virtual char* getValueStr() const = 0; + virtual std::string getDefaultStr() const = 0; + virtual std::string getValueStr() const = 0; virtual bool isBool() const; virtual void setImmutable(); @@ -192,8 +197,8 @@ namespace rfb { ConfigurationObject co=ConfGlobal); virtual bool setParam(const char* value); virtual bool setParam(); - virtual char* getDefaultStr() const; - virtual char* getValueStr() const; + virtual std::string getDefaultStr() const; + virtual std::string getValueStr() const; virtual bool isBool() const; virtual void setImmutable(); private: @@ -207,8 +212,8 @@ namespace rfb { virtual bool setParam(const char* value); virtual bool setParam(); virtual void setParam(bool b); - virtual char* getDefaultStr() const; - virtual char* getValueStr() const; + virtual std::string getDefaultStr() const; + virtual std::string getValueStr() const; virtual bool isBool() const; operator bool() const; protected: @@ -224,8 +229,8 @@ namespace rfb { using VoidParameter::setParam; virtual bool setParam(const char* value); virtual bool setParam(int v); - virtual char* getDefaultStr() const; - virtual char* getValueStr() const; + virtual std::string getDefaultStr() const; + virtual std::string getValueStr() const; operator int() const; protected: int value; @@ -241,38 +246,32 @@ namespace rfb { ConfigurationObject co=ConfGlobal); virtual ~StringParameter(); virtual bool setParam(const char* value); - virtual char* getDefaultStr() const; - virtual char* getValueStr() const; + virtual std::string getDefaultStr() const; + virtual std::string getValueStr() const; operator const char*() const; - - // getData() returns a copy of the data - it must be delete[]d by the - // caller. - char* getData() const { return getValueStr(); } protected: - char* value; - char* def_value; + std::string value; + std::string def_value; }; class BinaryParameter : public VoidParameter { public: BinaryParameter(const char* name_, const char* desc_, - const void* v, size_t l, + const uint8_t* v, size_t l, ConfigurationObject co=ConfGlobal); using VoidParameter::setParam; virtual ~BinaryParameter(); virtual bool setParam(const char* value); - virtual void setParam(const void* v, size_t l); - virtual char* getDefaultStr() const; - virtual char* getValueStr() const; + virtual void setParam(const uint8_t* v, size_t l); + virtual std::string getDefaultStr() const; + virtual std::string getValueStr() const; - // getData() will return length zero if there is no data - // NB: data may be set to zero, OR set to a zero-length buffer - void getData(void** data, size_t* length) const; + std::vector<uint8_t> getData() const; protected: - char* value; + uint8_t* value; size_t length; - char* def_value; + uint8_t* def_value; size_t def_length; }; diff --git a/common/rfb/Congestion.cxx b/common/rfb/Congestion.cxx index f642752e..1e252165 100644 --- a/common/rfb/Congestion.cxx +++ b/common/rfb/Congestion.cxx @@ -38,6 +38,7 @@ #endif #include <assert.h> +#include <string.h> #include <sys/time.h> #ifdef __linux__ diff --git a/common/rfb/Cursor.cxx b/common/rfb/Cursor.cxx index 425cc8c4..f0c72eed 100644 --- a/common/rfb/Cursor.cxx +++ b/common/rfb/Cursor.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2014-2017 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -23,6 +23,7 @@ #include <assert.h> #include <string.h> + #include <rfb/Cursor.h> #include <rfb/LogWriter.h> #include <rfb/Exception.h> @@ -32,10 +33,10 @@ using namespace rfb; static LogWriter vlog("Cursor"); Cursor::Cursor(int width, int height, const Point& hotspot, - const rdr::U8* data) : + const uint8_t* data) : width_(width), height_(height), hotspot_(hotspot) { - this->data = new rdr::U8[width_*height_*4]; + this->data = new uint8_t[width_*height_*4]; memcpy(this->data, data, width_*height_*4); } @@ -43,7 +44,7 @@ Cursor::Cursor(const Cursor& other) : width_(other.width_), height_(other.height_), hotspot_(other.hotspot_) { - data = new rdr::U8[width_*height_*4]; + data = new uint8_t[width_*height_*4]; memcpy(data, other.data, width_*height_*4); } @@ -81,7 +82,7 @@ static unsigned short srgb_to_lin(unsigned char srgb) } // Floyd-Steinberg dithering -static void dither(int width, int height, rdr::S32* data) +static void dither(int width, int height, int32_t* data) { for (int y = 0; y < height; y++) { for (int x_ = 0; x_ < width; x_++) { @@ -124,21 +125,21 @@ static void dither(int width, int height, rdr::S32* data) } } -rdr::U8* Cursor::getBitmap() const +std::vector<uint8_t> Cursor::getBitmap() const { // First step is converting to luminance - rdr::S32Array luminance(width()*height()); - rdr::S32 *lum_ptr = luminance.buf; - const rdr::U8 *data_ptr = data; + std::vector<int32_t> luminance(width()*height()); + int32_t *lum_ptr = luminance.data(); + const uint8_t *data_ptr = data; for (int y = 0; y < height(); y++) { for (int x = 0; x < width(); x++) { - rdr::S32 lum; + int32_t lum; // Use BT.709 coefficients for grayscale lum = 0; - lum += (rdr::U32)srgb_to_lin(data_ptr[0]) * 6947; // 0.2126 - lum += (rdr::U32)srgb_to_lin(data_ptr[1]) * 23436; // 0.7152 - lum += (rdr::U32)srgb_to_lin(data_ptr[2]) * 2366; // 0.0722 + lum += (uint32_t)srgb_to_lin(data_ptr[0]) * 6947; // 0.2126 + lum += (uint32_t)srgb_to_lin(data_ptr[1]) * 23436; // 0.7152 + lum += (uint32_t)srgb_to_lin(data_ptr[2]) * 2366; // 0.0722 lum /= 32768; *lum_ptr++ = lum; @@ -147,62 +148,62 @@ rdr::U8* Cursor::getBitmap() const } // Then diterhing - dither(width(), height(), luminance.buf); + dither(width(), height(), luminance.data()); // Then conversion to a bit mask - rdr::U8Array source((width()+7)/8*height()); - memset(source.buf, 0, (width()+7)/8*height()); + std::vector<uint8_t> source((width()+7)/8*height()); + memset(source.data(), 0, source.size()); int maskBytesPerRow = (width() + 7) / 8; - lum_ptr = luminance.buf; + lum_ptr = luminance.data(); data_ptr = data; for (int y = 0; y < height(); y++) { for (int x = 0; x < width(); x++) { int byte = y * maskBytesPerRow + x / 8; int bit = 7 - x % 8; if (*lum_ptr > 32767) - source.buf[byte] |= (1 << bit); + source[byte] |= (1 << bit); lum_ptr++; data_ptr += 4; } } - return source.takeBuf(); + return source; } -rdr::U8* Cursor::getMask() const +std::vector<uint8_t> Cursor::getMask() const { // First step is converting to integer array - rdr::S32Array alpha(width()*height()); - rdr::S32 *alpha_ptr = alpha.buf; - const rdr::U8 *data_ptr = data; + std::vector<int32_t> alpha(width()*height()); + int32_t *alpha_ptr = alpha.data(); + const uint8_t *data_ptr = data; for (int y = 0; y < height(); y++) { for (int x = 0; x < width(); x++) { - *alpha_ptr++ = (rdr::U32)data_ptr[3] * 65535 / 255; + *alpha_ptr++ = (uint32_t)data_ptr[3] * 65535 / 255; data_ptr += 4; } } // Then diterhing - dither(width(), height(), alpha.buf); + dither(width(), height(), alpha.data()); // Then conversion to a bit mask - rdr::U8Array mask((width()+7)/8*height()); - memset(mask.buf, 0, (width()+7)/8*height()); + std::vector<uint8_t> mask((width()+7)/8*height()); + memset(mask.data(), 0, mask.size()); int maskBytesPerRow = (width() + 7) / 8; - alpha_ptr = alpha.buf; + alpha_ptr = alpha.data(); data_ptr = data; for (int y = 0; y < height(); y++) { for (int x = 0; x < width(); x++) { int byte = y * maskBytesPerRow + x / 8; int bit = 7 - x % 8; if (*alpha_ptr > 32767) - mask.buf[byte] |= (1 << bit); + mask[byte] |= (1 << bit); alpha_ptr++; data_ptr += 4; } } - return mask.takeBuf(); + return mask; } // crop() determines the "busy" rectangle for the cursor - the minimum bounding @@ -217,7 +218,7 @@ void Cursor::crop() busy = busy.intersect(Rect(hotspot_.x, hotspot_.y, hotspot_.x+1, hotspot_.y+1)); int x, y; - rdr::U8 *data_ptr = data; + uint8_t *data_ptr = data; for (y = 0; y < height(); y++) { for (x = 0; x < width(); x++) { if (data_ptr[3] > 0) { @@ -234,7 +235,7 @@ void Cursor::crop() // Copy the pixel data int newDataLen = busy.area() * 4; - rdr::U8* newData = new rdr::U8[newDataLen]; + uint8_t* newData = new uint8_t[newDataLen]; data_ptr = newData; for (y = busy.tl.y; y < busy.br.y; y++) { memcpy(data_ptr, data + y*width()*4 + busy.tl.x*4, busy.width()*4); @@ -253,7 +254,7 @@ RenderedCursor::RenderedCursor() { } -const rdr::U8* RenderedCursor::getBuffer(const Rect& _r, int* stride) const +const uint8_t* RenderedCursor::getBuffer(const Rect& _r, int* stride) const { Rect r; @@ -270,7 +271,7 @@ void RenderedCursor::update(PixelBuffer* framebuffer, Point rawOffset, diff; Rect clippedRect; - const rdr::U8* data; + const uint8_t* data; int stride; assert(framebuffer); @@ -300,8 +301,8 @@ void RenderedCursor::update(PixelBuffer* framebuffer, for (int y = 0;y < buffer.height();y++) { for (int x = 0;x < buffer.width();x++) { size_t idx; - rdr::U8 bg[4], fg[4]; - rdr::U8 rgb[3]; + uint8_t bg[4], fg[4]; + uint8_t rgb[3]; idx = (y+diff.y)*cursor->width() + (x+diff.x); memcpy(fg, cursor->getBuffer() + idx*4, 4); diff --git a/common/rfb/Cursor.h b/common/rfb/Cursor.h index 6c6db7ee..31d6fda9 100644 --- a/common/rfb/Cursor.h +++ b/common/rfb/Cursor.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2014-2017 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -24,25 +24,27 @@ #ifndef __RFB_CURSOR_H__ #define __RFB_CURSOR_H__ +#include <vector> + #include <rfb/PixelBuffer.h> namespace rfb { class Cursor { public: - Cursor(int width, int height, const Point& hotspot, const rdr::U8* data); + Cursor(int width, int height, const 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 rdr::U8* getBuffer() const { return data; }; + const uint8_t* getBuffer() const { return data; }; // getBitmap() returns a monochrome version of the cursor - rdr::U8* getBitmap() const; + std::vector<uint8_t> getBitmap() const; // getMask() returns a simple mask version of the alpha channel - rdr::U8* getMask() const; + std::vector<uint8_t> getMask() const; // crop() crops the cursor down to the smallest possible size, based on the // mask. @@ -51,7 +53,7 @@ namespace rfb { protected: int width_, height_; Point hotspot_; - rdr::U8* data; + uint8_t* data; }; class RenderedCursor : public PixelBuffer { @@ -60,7 +62,7 @@ namespace rfb { Rect getEffectiveRect() const { return buffer.getRect(offset); } - virtual const rdr::U8* getBuffer(const Rect& r, int* stride) const; + virtual const uint8_t* getBuffer(const Rect& r, int* stride) const; void update(PixelBuffer* framebuffer, Cursor* cursor, const Point& pos); diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx index b9faf689..e39a3943 100644 --- a/common/rfb/DecodeManager.cxx +++ b/common/rfb/DecodeManager.cxx @@ -28,8 +28,8 @@ #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> @@ -211,8 +211,6 @@ void DecodeManager::logStats() double ratio; - char a[1024], b[1024]; - rects = 0; pixels = bytes = equivalent = 0; @@ -228,22 +226,21 @@ void DecodeManager::logStats() ratio = (double)stats[i].equivalent / stats[i].bytes; - siPrefix(stats[i].rects, "rects", a, sizeof(a)); - siPrefix(stats[i].pixels, "pixels", b, sizeof(b)); - vlog.info(" %s: %s, %s", encodingName(i), a, b); - iecPrefix(stats[i].bytes, "B", a, sizeof(a)); + vlog.info(" %s: %s, %s", encodingName(i), + siPrefix(stats[i].rects, "rects").c_str(), + siPrefix(stats[i].pixels, "pixels").c_str()); vlog.info(" %*s %s (1:%g ratio)", (int)strlen(encodingName(i)), "", - a, ratio); + iecPrefix(stats[i].bytes, "B").c_str(), ratio); } ratio = (double)equivalent / bytes; - siPrefix(rects, "rects", a, sizeof(a)); - siPrefix(pixels, "pixels", b, sizeof(b)); - vlog.info(" Total: %s, %s", a, b); - iecPrefix(bytes, "B", a, sizeof(a)); - vlog.info(" %s (1:%g ratio)", a, ratio); + vlog.info(" Total: %s, %s", + siPrefix(rects, "rects").c_str(), + siPrefix(pixels, "pixels").c_str()); + vlog.info(" %s (1:%g ratio)", + iecPrefix(bytes, "B").c_str(), ratio); } void DecodeManager::setThreadException(const rdr::Exception& e) diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index 6a78939e..bc15e74a 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2014-2018 Pierre Ossman for Cendio AB + * Copyright 2014-2022 Pierre Ossman for Cendio AB * Copyright 2018 Peter Astrand for Cendio AB * * This is free software; you can redistribute it and/or modify @@ -33,6 +33,7 @@ #include <rfb/UpdateTracker.h> #include <rfb/LogWriter.h> #include <rfb/Exception.h> +#include <rfb/util.h> #include <rfb/RawEncoder.h> #include <rfb/RREEncoder.h> @@ -177,8 +178,6 @@ void EncodeManager::logStats() double ratio; - char a[1024], b[1024]; - rects = 0; pixels = bytes = equivalent = 0; @@ -194,13 +193,12 @@ void EncodeManager::logStats() ratio = (double)copyStats.equivalent / copyStats.bytes; - siPrefix(copyStats.rects, "rects", a, sizeof(a)); - siPrefix(copyStats.pixels, "pixels", b, sizeof(b)); - vlog.info(" %s: %s, %s", "Copies", a, b); - iecPrefix(copyStats.bytes, "B", a, sizeof(a)); + vlog.info(" %s: %s, %s", "Copies", + siPrefix(copyStats.rects, "rects").c_str(), + siPrefix(copyStats.pixels, "pixels").c_str()); vlog.info(" %*s %s (1:%g ratio)", (int)strlen("Copies"), "", - a, ratio); + iecPrefix(copyStats.bytes, "B").c_str(), ratio); } for (i = 0;i < stats.size();i++) { @@ -225,23 +223,22 @@ void EncodeManager::logStats() ratio = (double)stats[i][j].equivalent / stats[i][j].bytes; - siPrefix(stats[i][j].rects, "rects", a, sizeof(a)); - siPrefix(stats[i][j].pixels, "pixels", b, sizeof(b)); - vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j), a, b); - iecPrefix(stats[i][j].bytes, "B", a, sizeof(a)); + vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j), + siPrefix(stats[i][j].rects, "rects").c_str(), + siPrefix(stats[i][j].pixels, "pixels").c_str()); vlog.info(" %*s %s (1:%g ratio)", (int)strlen(encoderTypeName((EncoderType)j)), "", - a, ratio); + iecPrefix(stats[i][j].bytes, "B").c_str(), ratio); } } ratio = (double)equivalent / bytes; - siPrefix(rects, "rects", a, sizeof(a)); - siPrefix(pixels, "pixels", b, sizeof(b)); - vlog.info(" Total: %s, %s", a, b); - iecPrefix(bytes, "B", a, sizeof(a)); - vlog.info(" %s (1:%g ratio)", a, ratio); + vlog.info(" Total: %s, %s", + siPrefix(rects, "rects").c_str(), + siPrefix(pixels, "pixels").c_str()); + vlog.info(" %s (1:%g ratio)", + iecPrefix(bytes, "B").c_str(), ratio); } bool EncodeManager::supported(int encoding) @@ -377,7 +374,7 @@ void EncodeManager::prepareEncoders(bool allowLossy) bool allowJPEG; - rdr::S32 preferred; + int32_t preferred; std::vector<int>::iterator iter; @@ -678,8 +675,8 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed, for (dx = rect.tl.x; dx < rect.br.x; dx += SolidSearchBlock) { // We define it like this to guarantee alignment - rdr::U32 _buffer; - rdr::U8* colourValue = (rdr::U8*)&_buffer; + uint32_t _buffer; + uint8_t* colourValue = (uint8_t*)&_buffer; dw = SolidSearchBlock; if (dx + dw > rect.br.x) @@ -700,7 +697,7 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed, extendSolidAreaByBlock(sr, colourValue, pb, &erb); // Did we end up getting the entire rectangle? - if (erb.equals(rect)) + if (erb == rect) erp = erb; else { // Don't bother with sending tiny rectangles @@ -718,8 +715,8 @@ void EncodeManager::findSolidRect(const Rect& rect, Region *changed, encoder->writeSolidRect(erp.width(), erp.height(), pb->getPF(), colourValue); } else { - rdr::U32 _buffer2; - rdr::U8* converted = (rdr::U8*)&_buffer2; + uint32_t _buffer2; + uint8_t* converted = (uint8_t*)&_buffer2; conn->client.pf().bufferFromBuffer(converted, pb->getPF(), colourValue, 1); @@ -886,21 +883,21 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb) endRect(); } -bool EncodeManager::checkSolidTile(const Rect& r, const rdr::U8* colourValue, +bool EncodeManager::checkSolidTile(const Rect& r, const uint8_t* colourValue, const PixelBuffer *pb) { switch (pb->getPF().bpp) { case 32: - return checkSolidTile(r, *(const rdr::U32*)colourValue, pb); + return checkSolidTile(r, *(const uint32_t*)colourValue, pb); case 16: - return checkSolidTile(r, *(const rdr::U16*)colourValue, pb); + return checkSolidTile(r, *(const uint16_t*)colourValue, pb); default: - return checkSolidTile(r, *(const rdr::U8*)colourValue, pb); + return checkSolidTile(r, *(const uint8_t*)colourValue, pb); } } void EncodeManager::extendSolidAreaByBlock(const Rect& r, - const rdr::U8* colourValue, + const uint8_t* colourValue, const PixelBuffer *pb, Rect* er) { int dx, dy, dw, dh; @@ -956,7 +953,7 @@ void EncodeManager::extendSolidAreaByBlock(const Rect& r, } void EncodeManager::extendSolidAreaByPixel(const Rect& r, const Rect& sr, - const rdr::U8* colourValue, + const uint8_t* colourValue, const PixelBuffer *pb, Rect* er) { int cx, cy; @@ -999,11 +996,11 @@ PixelBuffer* EncodeManager::preparePixelBuffer(const Rect& rect, const PixelBuffer *pb, bool convert) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; // Do wo need to convert the data? - if (convert && !conn->client.pf().equal(pb->getPF())) { + if (convert && conn->client.pf() != pb->getPF()) { convertedPixelBuffer.setPF(conn->client.pf()); convertedPixelBuffer.setSize(rect.width(), rect.height()); @@ -1029,7 +1026,7 @@ PixelBuffer* EncodeManager::preparePixelBuffer(const Rect& rect, bool EncodeManager::analyseRect(const PixelBuffer *pb, struct RectInfo *info, int maxColours) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; buffer = pb->getBuffer(pb->getRect(), &stride); @@ -1037,42 +1034,106 @@ bool EncodeManager::analyseRect(const PixelBuffer *pb, switch (pb->getPF().bpp) { case 32: return analyseRect(pb->width(), pb->height(), - (const rdr::U32*)buffer, stride, + (const uint32_t*)buffer, stride, info, maxColours); case 16: return analyseRect(pb->width(), pb->height(), - (const rdr::U16*)buffer, stride, + (const uint16_t*)buffer, stride, info, maxColours); default: return analyseRect(pb->width(), pb->height(), - (const rdr::U8*)buffer, stride, + (const uint8_t*)buffer, stride, info, maxColours); } } void EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf, int width, int height, - const rdr::U8* data_, + const uint8_t* data_, int stride_) { format = pf; // Forced cast. We never write anything though, so it should be safe. - setBuffer(width, height, (rdr::U8*)data_, stride_); + setBuffer(width, height, (uint8_t*)data_, stride_); } -rdr::U8* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& /*r*/, int* /*stride*/) +uint8_t* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& /*r*/, int* /*stride*/) { throw rfb::Exception("Invalid write attempt to OffsetPixelBuffer"); } -// Preprocessor generated, optimised methods - -#define BPP 8 -#include "EncodeManagerBPP.cxx" -#undef BPP -#define BPP 16 -#include "EncodeManagerBPP.cxx" -#undef BPP -#define BPP 32 -#include "EncodeManagerBPP.cxx" -#undef BPP +template<class T> +inline bool EncodeManager::checkSolidTile(const Rect& r, + const T colourValue, + const PixelBuffer *pb) +{ + int w, h; + const T* buffer; + int stride, pad; + + w = r.width(); + h = r.height(); + + buffer = (const T*)pb->getBuffer(r, &stride); + pad = stride - w; + + while (h--) { + int w_ = w; + while (w_--) { + if (*buffer != colourValue) + return false; + buffer++; + } + buffer += pad; + } + + return true; +} + +template<class T> +inline bool EncodeManager::analyseRect(int width, int height, + const T* buffer, int stride, + struct RectInfo *info, int maxColours) +{ + int pad; + + T colour; + int count; + + info->rleRuns = 0; + info->palette.clear(); + + pad = stride - width; + + // For efficiency, we only update the palette on changes in colour + colour = buffer[0]; + count = 0; + while (height--) { + int w_ = width; + while (w_--) { + if (*buffer != colour) { + if (!info->palette.insert(colour, count)) + return false; + if (info->palette.size() > maxColours) + return false; + + // FIXME: This doesn't account for switching lines + info->rleRuns++; + + colour = *buffer; + count = 0; + } + buffer++; + count++; + } + buffer += pad; + } + + // Make sure the final pixels also get counted + if (!info->palette.insert(colour, count)) + return false; + if (info->palette.size() > maxColours) + return false; + + return true; +} diff --git a/common/rfb/EncodeManager.h b/common/rfb/EncodeManager.h index f8201c34..f2fd4ca4 100644 --- a/common/rfb/EncodeManager.h +++ b/common/rfb/EncodeManager.h @@ -1,6 +1,6 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2014-2018 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -22,7 +22,8 @@ #include <vector> -#include <rdr/types.h> +#include <stdint.h> + #include <rfb/PixelBuffer.h> #include <rfb/Region.h> #include <rfb/Timer.h> @@ -82,12 +83,12 @@ namespace rfb { void writeSubRect(const Rect& rect, const PixelBuffer *pb); - bool checkSolidTile(const Rect& r, const rdr::U8* colourValue, + bool checkSolidTile(const Rect& r, const uint8_t* colourValue, const PixelBuffer *pb); - void extendSolidAreaByBlock(const Rect& r, const rdr::U8* colourValue, + void extendSolidAreaByBlock(const Rect& r, const uint8_t* colourValue, const PixelBuffer *pb, Rect* er); void extendSolidAreaByPixel(const Rect& r, const Rect& sr, - const rdr::U8* colourValue, + const uint8_t* colourValue, const PixelBuffer *pb, Rect* er); PixelBuffer* preparePixelBuffer(const Rect& rect, @@ -97,22 +98,13 @@ namespace rfb { struct RectInfo *info, int maxColours); protected: - // Preprocessor generated, optimised methods - inline bool checkSolidTile(const Rect& r, rdr::U8 colourValue, - const PixelBuffer *pb); - inline bool checkSolidTile(const Rect& r, rdr::U16 colourValue, + // Templated, optimised methods + template<class T> + inline bool checkSolidTile(const Rect& r, const T, const PixelBuffer *pb); - inline bool checkSolidTile(const Rect& r, rdr::U32 colourValue, - const PixelBuffer *pb); - - inline bool analyseRect(int width, int height, - const rdr::U8* buffer, int stride, - struct RectInfo *info, int maxColours); - inline bool analyseRect(int width, int height, - const rdr::U16* buffer, int stride, - struct RectInfo *info, int maxColours); + template<class T> inline bool analyseRect(int width, int height, - const rdr::U32* buffer, int stride, + const T* buffer, int stride, struct RectInfo *info, int maxColours); protected: @@ -147,10 +139,10 @@ namespace rfb { virtual ~OffsetPixelBuffer() {} void update(const PixelFormat& pf, int width, int height, - const rdr::U8* data_, int stride); + const uint8_t* data_, int stride); private: - virtual rdr::U8* getBufferRW(const Rect& r, int* stride); + virtual uint8_t* getBufferRW(const Rect& r, int* stride); }; OffsetPixelBuffer offsetPixelBuffer; diff --git a/common/rfb/EncodeManagerBPP.cxx b/common/rfb/EncodeManagerBPP.cxx deleted file mode 100644 index 03612914..00000000 --- a/common/rfb/EncodeManagerBPP.cxx +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. - * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) - -#define UBPP CONCAT2E(U,BPP) - -inline bool EncodeManager::checkSolidTile(const Rect& r, - rdr::UBPP colourValue, - const PixelBuffer *pb) -{ - int w, h; - const rdr::UBPP* buffer; - int stride, pad; - - w = r.width(); - h = r.height(); - - buffer = (const rdr::UBPP*)pb->getBuffer(r, &stride); - pad = stride - w; - - while (h--) { - int w_ = w; - while (w_--) { - if (*buffer != colourValue) - return false; - buffer++; - } - buffer += pad; - } - - return true; -} - -inline bool EncodeManager::analyseRect(int width, int height, - const rdr::UBPP* buffer, int stride, - struct RectInfo *info, int maxColours) -{ - int pad; - - rdr::UBPP colour; - int count; - - info->rleRuns = 0; - info->palette.clear(); - - pad = stride - width; - - // For efficiency, we only update the palette on changes in colour - colour = buffer[0]; - count = 0; - while (height--) { - int w_ = width; - while (w_--) { - if (*buffer != colour) { - if (!info->palette.insert(colour, count)) - return false; - if (info->palette.size() > maxColours) - return false; - - // FIXME: This doesn't account for switching lines - info->rleRuns++; - - colour = *buffer; - count = 0; - } - buffer++; - count++; - } - buffer += pad; - } - - // Make sure the final pixels also get counted - if (!info->palette.insert(colour, count)) - return false; - if (info->palette.size() > maxColours) - return false; - - return true; -} diff --git a/common/rfb/Encoder.cxx b/common/rfb/Encoder.cxx index d6d4a81d..35aa3d05 100644 --- a/common/rfb/Encoder.cxx +++ b/common/rfb/Encoder.cxx @@ -41,12 +41,12 @@ Encoder::~Encoder() } void Encoder::writeSolidRect(int width, int height, - const PixelFormat& pf, const rdr::U8* colour) + const PixelFormat& pf, const uint8_t* colour) { ManagedPixelBuffer buffer(pf, width, height); Palette palette; - rdr::U32 palcol; + uint32_t palcol; buffer.fillRect(buffer.getRect(), colour); @@ -59,27 +59,27 @@ void Encoder::writeSolidRect(int width, int height, void Encoder::writeSolidRect(const PixelBuffer* pb, const Palette& palette) { - rdr::U32 col32; - rdr::U16 col16; - rdr::U8 col8; + uint32_t col32; + uint16_t col16; + uint8_t col8; - rdr::U8* buffer; + uint8_t* buffer; assert(palette.size() == 1); // The Palette relies on implicit up and down conversion switch (pb->getPF().bpp) { case 32: - col32 = (rdr::U32)palette.getColour(0); - buffer = (rdr::U8*)&col32; + col32 = (uint32_t)palette.getColour(0); + buffer = (uint8_t*)&col32; break; case 16: - col16 = (rdr::U16)palette.getColour(0); - buffer = (rdr::U8*)&col16; + col16 = (uint16_t)palette.getColour(0); + buffer = (uint8_t*)&col16; break; default: - col8 = (rdr::U8)palette.getColour(0); - buffer = (rdr::U8*)&col8; + col8 = (uint8_t)palette.getColour(0); + buffer = (uint8_t*)&col8; break; } diff --git a/common/rfb/Encoder.h b/common/rfb/Encoder.h index 76079930..5e066323 100644 --- a/common/rfb/Encoder.h +++ b/common/rfb/Encoder.h @@ -20,7 +20,8 @@ #ifndef __RFB_ENCODER_H__ #define __RFB_ENCODER_H__ -#include <rdr/types.h> +#include <stdint.h> + #include <rfb/Rect.h> namespace rfb { @@ -83,7 +84,7 @@ namespace rfb { // efficient short cut. virtual void writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour)=0; + const uint8_t* colour)=0; protected: // Helper method for redirecting a single colour palette to the diff --git a/common/rfb/H264Decoder.cxx b/common/rfb/H264Decoder.cxx index 92231fcd..9de73422 100644 --- a/common/rfb/H264Decoder.cxx +++ b/common/rfb/H264Decoder.cxx @@ -70,7 +70,7 @@ bool H264Decoder::readRect(const Rect& /*r*/, const ServerParams& /*server*/, rdr::OutStream* os) { - rdr::U32 len; + uint32_t len; if (!is->hasData(8)) return false; @@ -79,7 +79,7 @@ bool H264Decoder::readRect(const Rect& /*r*/, len = is->readU32(); os->writeU32(len); - rdr::U32 flags = is->readU32(); + uint32_t flags = is->readU32(); os->writeU32(flags); @@ -99,8 +99,8 @@ void H264Decoder::decodeRect(const Rect& r, const void* buffer, ModifiablePixelBuffer* pb) { rdr::MemInStream is(buffer, buflen); - rdr::U32 len = is.readU32(); - rdr::U32 flags = is.readU32(); + uint32_t len = is.readU32(); + uint32_t flags = is.readU32(); H264DecoderContext* ctx = NULL; if (flags & resetAllContexts) diff --git a/common/rfb/H264DecoderContext.h b/common/rfb/H264DecoderContext.h index f261f4f2..88c2396c 100644 --- a/common/rfb/H264DecoderContext.h +++ b/common/rfb/H264DecoderContext.h @@ -21,8 +21,9 @@ #ifndef __RFB_H264DECODERCONTEXT_H__ #define __RFB_H264DECODERCONTEXT_H__ +#include <stdint.h> + #include <os/Mutex.h> -#include <rdr/types.h> #include <rfb/Rect.h> #include <rfb/Decoder.h> @@ -33,12 +34,12 @@ namespace rfb { virtual ~H264DecoderContext() = 0; - virtual void decode(const rdr::U8* /*h264_buffer*/, - rdr::U32 /*len*/, + virtual void decode(const uint8_t* /*h264_buffer*/, + uint32_t /*len*/, ModifiablePixelBuffer* /*pb*/) {} void reset(); - inline bool isEqualRect(const Rect &r) const { return r.equals(rect); } + inline bool isEqualRect(const Rect &r) const { return r == rect; } bool isReady(); protected: diff --git a/common/rfb/H264LibavDecoderContext.cxx b/common/rfb/H264LibavDecoderContext.cxx index 67c14991..8697a5a5 100644 --- a/common/rfb/H264LibavDecoderContext.cxx +++ b/common/rfb/H264LibavDecoderContext.cxx @@ -110,13 +110,13 @@ void H264LibavDecoderContext::freeCodec() { // We need to reallocate buffer because AVPacket uses non-const pointer. // We don't want to const_cast our buffer somewhere. So we would rather to maintain context's own buffer // Also avcodec requires a right padded buffer -rdr::U8* H264LibavDecoderContext::makeH264WorkBuffer(const rdr::U8* buffer, rdr::U32 len) +uint8_t* H264LibavDecoderContext::makeH264WorkBuffer(const uint8_t* buffer, uint32_t len) { - rdr::U32 reserve_len = len + len % AV_INPUT_BUFFER_PADDING_SIZE; + uint32_t reserve_len = len + len % AV_INPUT_BUFFER_PADDING_SIZE; if (!h264WorkBuffer || reserve_len > h264WorkBufferLength) { - h264WorkBuffer = (rdr::U8*)realloc(h264WorkBuffer, reserve_len); + h264WorkBuffer = (uint8_t*)realloc(h264WorkBuffer, reserve_len); if (h264WorkBuffer == NULL) { throw Exception("H264LibavDecoderContext: Unable to allocate memory"); } @@ -128,13 +128,13 @@ rdr::U8* H264LibavDecoderContext::makeH264WorkBuffer(const rdr::U8* buffer, rdr: return h264WorkBuffer; } -void H264LibavDecoderContext::decode(const rdr::U8* h264_in_buffer, - rdr::U32 len, +void H264LibavDecoderContext::decode(const uint8_t* h264_in_buffer, + uint32_t len, ModifiablePixelBuffer* pb) { os::AutoMutex lock(&mutex); if (!initialized) return; - rdr::U8* h264_work_buffer = makeH264WorkBuffer(h264_in_buffer, len); + uint8_t* h264_work_buffer = makeH264WorkBuffer(h264_in_buffer, len); #ifdef FFMPEG_INIT_PACKET_DEPRECATED AVPacket *packet = av_packet_alloc(); @@ -154,7 +154,7 @@ void H264LibavDecoderContext::decode(const rdr::U8* h264_in_buffer, break; } // We need to slap on tv to make it work here (don't ask me why) - if (!packet->size && len == static_cast<rdr::U32>(ret)) + 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); if (ret < 0) { diff --git a/common/rfb/H264LibavDecoderContext.h b/common/rfb/H264LibavDecoderContext.h index 1f005e4b..148ba1ad 100644 --- a/common/rfb/H264LibavDecoderContext.h +++ b/common/rfb/H264LibavDecoderContext.h @@ -34,7 +34,7 @@ namespace rfb { H264LibavDecoderContext(const Rect &r) : H264DecoderContext(r) {} ~H264LibavDecoderContext() { freeCodec(); } - virtual void decode(const rdr::U8* h264_buffer, rdr::U32 len, + virtual void decode(const uint8_t* h264_buffer, uint32_t len, ModifiablePixelBuffer* pb); protected: @@ -42,15 +42,15 @@ namespace rfb { virtual void freeCodec(); private: - rdr::U8* makeH264WorkBuffer(const rdr::U8* buffer, rdr::U32 len); + uint8_t* makeH264WorkBuffer(const uint8_t* buffer, uint32_t len); AVCodecContext *avctx; AVCodecParserContext *parser; AVFrame* frame; SwsContext* sws; uint8_t* swsBuffer; - rdr::U8* h264WorkBuffer; - rdr::U32 h264WorkBufferLength; + uint8_t* h264WorkBuffer; + uint32_t h264WorkBufferLength; }; } diff --git a/common/rfb/H264WinDecoderContext.cxx b/common/rfb/H264WinDecoderContext.cxx index a6855c0d..bb29edb6 100644 --- a/common/rfb/H264WinDecoderContext.cxx +++ b/common/rfb/H264WinDecoderContext.cxx @@ -154,8 +154,8 @@ void H264WinDecoderContext::freeCodec() { initialized = false; } -void H264WinDecoderContext::decode(const rdr::U8* h264_buffer, - rdr::U32 len, +void H264WinDecoderContext::decode(const uint8_t* h264_buffer, + uint32_t len, ModifiablePixelBuffer* pb) { os::AutoMutex lock(&mutex); if (!initialized) @@ -351,7 +351,7 @@ void H264WinDecoderContext::decode(const rdr::U8* h264_buffer, } // "7.3.2.1.1 Sequence parameter set data syntax" on page 66 of https://www.itu.int/rec/T-REC-H.264-202108-I/en -void H264WinDecoderContext::ParseSPS(const rdr::U8* buffer, int length) +void H264WinDecoderContext::ParseSPS(const uint8_t* buffer, int length) { #define EXPECT(cond) if (!(cond)) return; @@ -404,14 +404,14 @@ void H264WinDecoderContext::ParseSPS(const rdr::U8* buffer, int length) // NAL unit type EXPECT(length > 1); - rdr::U8 type = buffer[0]; + uint8_t type = buffer[0]; EXPECT((type & 0x80) == 0); // forbidden zero bit EXPECT((type & 0x1f) == 7); // SPS NAL unit type buffer++; length--; int available = 0; - rdr::U8 byte = 0; + uint8_t byte = 0; unsigned profile_idc; unsigned seq_parameter_set_id; diff --git a/common/rfb/H264WinDecoderContext.h b/common/rfb/H264WinDecoderContext.h index 96e7bf00..de51576c 100644 --- a/common/rfb/H264WinDecoderContext.h +++ b/common/rfb/H264WinDecoderContext.h @@ -33,7 +33,7 @@ namespace rfb { H264WinDecoderContext(const Rect &r) : H264DecoderContext(r) {}; ~H264WinDecoderContext() { freeCodec(); } - virtual void decode(const rdr::U8* h264_buffer, rdr::U32 len, + virtual void decode(const uint8_t* h264_buffer, uint32_t len, ModifiablePixelBuffer* pb); protected: @@ -42,12 +42,12 @@ namespace rfb { private: LONG stride; - rdr::U32 full_width = 0; - rdr::U32 full_height = 0; - rdr::U32 crop_width = 0; - rdr::U32 crop_height = 0; - rdr::U32 offset_x = 0; - rdr::U32 offset_y = 0; + uint32_t full_width = 0; + uint32_t full_height = 0; + uint32_t crop_width = 0; + uint32_t crop_height = 0; + uint32_t offset_x = 0; + uint32_t offset_y = 0; IMFTransform *decoder = NULL; IMFTransform *converter = NULL; IMFSample *input_sample = NULL; @@ -57,7 +57,7 @@ namespace rfb { IMFMediaBuffer *decoded_buffer = NULL; IMFMediaBuffer *converted_buffer = NULL; - void ParseSPS(const rdr::U8* buffer, int length); + void ParseSPS(const uint8_t* buffer, int length); }; } diff --git a/common/rfb/HextileDecoder.cxx b/common/rfb/HextileDecoder.cxx index 73655da0..f7cbc46a 100644 --- a/common/rfb/HextileDecoder.cxx +++ b/common/rfb/HextileDecoder.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014-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 @@ -24,22 +25,14 @@ #include <rdr/MemInStream.h> #include <rdr/OutStream.h> +#include <rfb/Exception.h> #include <rfb/ServerParams.h> #include <rfb/PixelBuffer.h> #include <rfb/HextileDecoder.h> +#include <rfb/hextileConstants.h> using namespace rfb; -#define BPP 8 -#include <rfb/hextileDecode.h> -#undef BPP -#define BPP 16 -#include <rfb/hextileDecode.h> -#undef BPP -#define BPP 32 -#include <rfb/hextileDecode.h> -#undef BPP - HextileDecoder::HextileDecoder() : Decoder(DecoderPlain) { } @@ -63,7 +56,7 @@ bool HextileDecoder::readRect(const Rect& r, rdr::InStream* is, t.br.y = __rfbmin(r.br.y, t.tl.y + 16); for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) { - rdr::U8 tileType; + uint8_t tileType; t.br.x = __rfbmin(r.br.x, t.tl.x + 16); @@ -94,7 +87,7 @@ bool HextileDecoder::readRect(const Rect& r, rdr::InStream* is, } if (tileType & hextileAnySubrects) { - rdr::U8 nSubrects; + uint8_t nSubrects; if (!is->hasDataOrRestore(1)) return false; @@ -127,8 +120,87 @@ void HextileDecoder::decodeRect(const Rect& r, const void* buffer, rdr::MemInStream is(buffer, buflen); const PixelFormat& pf = server.pf(); switch (pf.bpp) { - case 8: hextileDecode8 (r, &is, pf, pb); break; - case 16: hextileDecode16(r, &is, pf, pb); break; - case 32: hextileDecode32(r, &is, pf, pb); break; + case 8: hextileDecode<uint8_t >(r, &is, pf, pb); break; + case 16: hextileDecode<uint16_t>(r, &is, pf, pb); break; + case 32: hextileDecode<uint32_t>(r, &is, pf, pb); break; + } +} + +template<class T> +inline T HextileDecoder::readPixel(rdr::InStream* is) +{ + if (sizeof(T) == 1) + return is->readOpaque8(); + if (sizeof(T) == 2) + return is->readOpaque16(); + if (sizeof(T) == 4) + return is->readOpaque32(); +} + +template<class T> +void HextileDecoder::hextileDecode(const Rect& r, rdr::InStream* is, + const PixelFormat& pf, + ModifiablePixelBuffer* pb) +{ + 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); + + 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); + + int tileType = is->readU8(); + + if (tileType & hextileRaw) { + is->readBytes(buf, t.area() * sizeof(T)); + pb->imageRect(pf, t, buf); + continue; + } + + if (tileType & hextileBgSpecified) + bg = readPixel<T>(is); + + int len = t.area(); + T* ptr = buf; + while (len-- > 0) *ptr++ = bg; + + if (tileType & hextileFgSpecified) + fg = readPixel<T>(is); + + if (tileType & hextileAnySubrects) { + int nSubrects = is->readU8(); + + for (int i = 0; i < nSubrects; i++) { + + if (tileType & hextileSubrectsColoured) + fg = readPixel<T>(is); + + int xy = is->readU8(); + int wh = is->readU8(); + + int x = ((xy >> 4) & 15); + int y = (xy & 15); + int w = ((wh >> 4) & 15) + 1; + int h = (wh & 15) + 1; + if (x + w > 16 || y + h > 16) { + throw rfb::Exception("HEXTILE_DECODE: Hextile out of bounds"); + } + T* ptr = buf + y * t.width() + x; + int rowAdd = t.width() - w; + while (h-- > 0) { + int len = w; + while (len-- > 0) *ptr++ = fg; + ptr += rowAdd; + } + } + } + pb->imageRect(pf, t, buf); + } } } diff --git a/common/rfb/HextileDecoder.h b/common/rfb/HextileDecoder.h index 2c42be54..e8961d73 100644 --- a/common/rfb/HextileDecoder.h +++ b/common/rfb/HextileDecoder.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014-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 @@ -22,6 +23,8 @@ namespace rfb { + class PixelFormat; + class HextileDecoder : public Decoder { public: HextileDecoder(); @@ -31,6 +34,13 @@ namespace rfb { virtual void decodeRect(const Rect& r, const void* buffer, size_t buflen, const ServerParams& server, ModifiablePixelBuffer* pb); + private: + template<class T> + inline T readPixel(rdr::InStream* is); + template<class T> + void hextileDecode(const Rect& r, rdr::InStream* is, + const PixelFormat& pf, + ModifiablePixelBuffer* pb); }; } #endif diff --git a/common/rfb/HextileEncoder.cxx b/common/rfb/HextileEncoder.cxx index f9db06b8..90e59962 100644 --- a/common/rfb/HextileEncoder.cxx +++ b/common/rfb/HextileEncoder.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2005 Constantin Kaplinsky. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -25,8 +25,10 @@ #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; @@ -36,19 +38,6 @@ BoolParameter improvedHextile("ImprovedHextile", "ratios by the cost of using more CPU time", true); -#define BPP 8 -#include <rfb/hextileEncode.h> -#include <rfb/hextileEncodeBetter.h> -#undef BPP -#define BPP 16 -#include <rfb/hextileEncode.h> -#include <rfb/hextileEncodeBetter.h> -#undef BPP -#define BPP 32 -#include <rfb/hextileEncode.h> -#include <rfb/hextileEncodeBetter.h> -#undef BPP - HextileEncoder::HextileEncoder(SConnection* conn) : Encoder(conn, encodingHextile, EncoderPlain) { @@ -70,23 +59,23 @@ void HextileEncoder::writeRect(const PixelBuffer* pb, switch (pb->getPF().bpp) { case 8: if (improvedHextile) { - hextileEncodeBetter8(os, pb); + hextileEncodeBetter<uint8_t>(os, pb); } else { - hextileEncode8(os, pb); + hextileEncode<uint8_t>(os, pb); } break; case 16: if (improvedHextile) { - hextileEncodeBetter16(os, pb); + hextileEncodeBetter<uint16_t>(os, pb); } else { - hextileEncode16(os, pb); + hextileEncode<uint16_t>(os, pb); } break; case 32: if (improvedHextile) { - hextileEncodeBetter32(os, pb); + hextileEncodeBetter<uint32_t>(os, pb); } else { - hextileEncode32(os, pb); + hextileEncode<uint32_t>(os, pb); } break; } @@ -94,7 +83,7 @@ void HextileEncoder::writeRect(const PixelBuffer* pb, void HextileEncoder::writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour) + const uint8_t* colour) { rdr::OutStream* os; int tiles; @@ -110,3 +99,496 @@ void HextileEncoder::writeSolidRect(int width, int height, while (tiles--) os->writeU8(0); } + +template<class T> +inline void HextileEncoder::writePixel(rdr::OutStream* os, T pixel) +{ + if (sizeof(T) == 1) + os->writeOpaque8(pixel); + else if (sizeof(T) == 2) + os->writeOpaque16(pixel); + else if (sizeof(T) == 4) + os->writeOpaque32(pixel); +} + +template<class T> +void HextileEncoder::hextileEncode(rdr::OutStream* os, + const PixelBuffer* pb) +{ + Rect t; + T buf[256]; + T oldBg = 0, oldFg = 0; + bool oldBgValid = false; + bool oldFgValid = false; + uint8_t encoded[256*sizeof(T)]; + + for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) { + + t.br.y = __rfbmin(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); + + pb->getImage(buf, t); + + T bg = 0, fg = 0; + int tileType = testTileType(buf, t.width(), t.height(), &bg, &fg); + + if (!oldBgValid || oldBg != bg) { + tileType |= hextileBgSpecified; + oldBg = bg; + oldBgValid = true; + } + + int encodedLen = 0; + + if (tileType & hextileAnySubrects) { + + if (tileType & hextileSubrectsColoured) { + oldFgValid = false; + } else { + if (!oldFgValid || oldFg != fg) { + tileType |= hextileFgSpecified; + oldFg = fg; + oldFgValid = true; + } + } + + encodedLen = hextileEncodeTile(buf, t.width(), t.height(), + tileType, encoded, bg); + + if (encodedLen < 0) { + pb->getImage(buf, t); + os->writeU8(hextileRaw); + os->writeBytes(buf, t.width() * t.height() * sizeof(T)); + oldBgValid = oldFgValid = false; + continue; + } + } + + os->writeU8(tileType); + if (tileType & hextileBgSpecified) writePixel(os, bg); + if (tileType & hextileFgSpecified) writePixel(os, fg); + if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen); + } + } +} + +template<class T> +int HextileEncoder::hextileEncodeTile(T* data, int w, int h, + int tileType, uint8_t* encoded, + T bg) +{ + uint8_t* nSubrectsPtr = encoded; + *nSubrectsPtr = 0; + encoded++; + + for (int y = 0; y < h; y++) + { + int x = 0; + while (x < w) { + if (*data == bg) { + x++; + data++; + continue; + } + + // Find horizontal subrect first + T* ptr = data+1; + T* eol = data+w-x; + while (ptr < eol && *ptr == *data) ptr++; + int sw = ptr - data; + + ptr = data + w; + int sh = 1; + while (sh < h-y) { + eol = ptr + sw; + while (ptr < eol) + if (*ptr++ != *data) goto endOfSubrect; + ptr += w - sw; + sh++; + } + endOfSubrect: + + (*nSubrectsPtr)++; + + if (tileType & hextileSubrectsColoured) { + if (encoded - nSubrectsPtr + sizeof(T) > w*h*sizeof(T)) + return -1; + + if (sizeof(T) == 1) { + *encoded++ = *data; + } else if (sizeof(T) == 2) { + *encoded++ = ((uint8_t*)data)[0]; + *encoded++ = ((uint8_t*)data)[1]; + } else if (sizeof(T) == 4) { + *encoded++ = ((uint8_t*)data)[0]; + *encoded++ = ((uint8_t*)data)[1]; + *encoded++ = ((uint8_t*)data)[2]; + *encoded++ = ((uint8_t*)data)[3]; + } + } + + if ((size_t)(encoded - nSubrectsPtr + 2) > w*h*sizeof(T)) + return -1; + *encoded++ = (x << 4) | y; + *encoded++ = ((sw-1) << 4) | (sh-1); + + ptr = data+w; + T* eor = data+w*sh; + while (ptr < eor) { + eol = ptr + sw; + while (ptr < eol) *ptr++ = bg; + ptr += w - sw; + } + x += sw; + data += sw; + } + } + return encoded - nSubrectsPtr; +} + +template<class T> +int HextileEncoder::testTileType(T* data, int w, int h, T* bg, T* fg) +{ + T pix1 = *data; + T* end = data + w * h; + + T* ptr = data + 1; + while (ptr < end && *ptr == pix1) + ptr++; + + if (ptr == end) { + *bg = pix1; + return 0; // solid-color tile + } + + int count1 = ptr - data; + int count2 = 1; + T pix2 = *ptr++; + int tileType = hextileAnySubrects; + + for (; ptr < end; ptr++) { + if (*ptr == pix1) { + count1++; + } else if (*ptr == pix2) { + count2++; + } else { + tileType |= hextileSubrectsColoured; + break; + } + } + + if (count1 >= count2) { + *bg = pix1; *fg = pix2; + } else { + *bg = pix2; *fg = pix1; + } + return tileType; +} + +// +// This class analyzes a separate tile and encodes its subrectangles. +// + +template<class T> +class HextileTile { + + public: + + HextileTile (); + + // + // Initialize existing object instance with new tile data. + // + void newTile(const T *src, int w, int h); + + // + // Flags can include: hextileRaw, hextileAnySubrects and + // hextileSubrectsColoured. Note that if hextileRaw is set, other + // flags make no sense. Also, hextileSubrectsColoured is meaningful + // only when hextileAnySubrects is set as well. + // + int getFlags() const { return m_flags; } + + // + // Returns the size of encoded subrects data, including subrect count. + // The size is zero if flags do not include hextileAnySubrects. + // + size_t getSize() const { return m_size; } + + // + // Return optimal background. + // + int getBackground() const { return m_background; } + + // + // Return foreground if flags include hextileSubrectsColoured. + // + int getForeground() const { return m_foreground; } + + // + // Encode subrects. This function may be called only if + // hextileAnySubrects bit is set in flags. The buffer size should be + // big enough to store at least the number of bytes returned by the + // getSize() method. + // + void encode(uint8_t* dst) const; + + protected: + + // + // Analyze the tile pixels, fill in all the data fields. + // + void analyze(); + + const T *m_tile; + int m_width; + int m_height; + + size_t m_size; + int m_flags; + T m_background; + T m_foreground; + + int m_numSubrects; + uint8_t m_coords[256 * 2]; + T m_colors[256]; + + private: + + bool m_processed[16][16]; + Palette m_pal; +}; + +template<class T> +HextileTile<T>::HextileTile() + : m_tile(NULL), m_width(0), m_height(0), + m_size(0), m_flags(0), m_background(0), m_foreground(0), + m_numSubrects(0) +{ +} + +template<class T> +void HextileTile<T>::newTile(const T *src, int w, int h) +{ + m_tile = src; + m_width = w; + m_height = h; + + analyze(); +} + +template<class T> +void HextileTile<T>::analyze() +{ + assert(m_tile && m_width && m_height); + + const T *ptr = m_tile; + const T *end = &m_tile[m_width * m_height]; + T color = *ptr++; + while (ptr != end && *ptr == color) + ptr++; + + // Handle solid tile + if (ptr == end) { + m_background = m_tile[0]; + m_flags = 0; + m_size = 0; + return; + } + + // Compute number of complete rows of the same color, at the top + int y = (ptr - m_tile) / m_width; + + T *colorsPtr = m_colors; + uint8_t *coordsPtr = m_coords; + m_pal.clear(); + m_numSubrects = 0; + + // Have we found the first subrect already? + if (y > 0) { + *colorsPtr++ = color; + *coordsPtr++ = 0; + *coordsPtr++ = (uint8_t)(((m_width - 1) << 4) | ((y - 1) & 0x0F)); + m_pal.insert(color, 1); + m_numSubrects++; + } + + memset(m_processed, 0, 16 * 16 * sizeof(bool)); + + int x, sx, sy, sw, sh, max_x; + + for (; y < m_height; y++) { + for (x = 0; x < m_width; x++) { + // Skip pixels that were processed earlier + if (m_processed[y][x]) { + continue; + } + // Determine dimensions of the horizontal subrect + color = m_tile[y * m_width + x]; + for (sx = x + 1; sx < m_width; sx++) { + if (m_tile[y * m_width + sx] != color) + break; + } + sw = sx - x; + max_x = sx; + for (sy = y + 1; sy < m_height; sy++) { + for (sx = x; sx < max_x; sx++) { + if (m_tile[sy * m_width + sx] != color) + goto done; + } + } + done: + sh = sy - y; + + // Save properties of this subrect + *colorsPtr++ = color; + *coordsPtr++ = (uint8_t)((x << 4) | (y & 0x0F)); + *coordsPtr++ = (uint8_t)(((sw - 1) << 4) | ((sh - 1) & 0x0F)); + + if (!m_pal.insert(color, 1) || + ((size_t)m_pal.size() > (48 + 2 * sizeof(T)*8))) { + // Handle palette overflow + m_flags = hextileRaw; + m_size = 0; + return; + } + + m_numSubrects++; + + // Mark pixels of this subrect as processed, below this row + for (sy = y + 1; sy < y + sh; sy++) { + for (sx = x; sx < x + sw; sx++) + m_processed[sy][sx] = true; + } + + // Skip processed pixels of this row + x += (sw - 1); + } + } + + // Save number of colors in this tile (should be no less than 2) + int numColors = m_pal.size(); + assert(numColors >= 2); + + m_background = (T)m_pal.getColour(0); + m_flags = hextileAnySubrects; + int numSubrects = m_numSubrects - m_pal.getCount(0); + + if (numColors == 2) { + // Monochrome tile + m_foreground = (T)m_pal.getColour(1); + m_size = 1 + 2 * numSubrects; + } else { + // Colored tile + m_flags |= hextileSubrectsColoured; + m_size = 1 + (2 + sizeof(T)) * numSubrects; + } +} + +template<class T> +void HextileTile<T>::encode(uint8_t *dst) const +{ + assert(m_numSubrects && (m_flags & hextileAnySubrects)); + + // Zero subrects counter + uint8_t *numSubrectsPtr = dst; + *dst++ = 0; + + for (int i = 0; i < m_numSubrects; i++) { + if (m_colors[i] == m_background) + continue; + + if (m_flags & hextileSubrectsColoured) { + if (sizeof(T) == 1) { + *dst++ = m_colors[i]; + } else if (sizeof(T) == 2) { + *dst++ = ((uint8_t*)&m_colors[i])[0]; + *dst++ = ((uint8_t*)&m_colors[i])[1]; + } else if (sizeof(T) == 4) { + *dst++ = ((uint8_t*)&m_colors[i])[0]; + *dst++ = ((uint8_t*)&m_colors[i])[1]; + *dst++ = ((uint8_t*)&m_colors[i])[2]; + *dst++ = ((uint8_t*)&m_colors[i])[3]; + } + } + *dst++ = m_coords[i * 2]; + *dst++ = m_coords[i * 2 + 1]; + + (*numSubrectsPtr)++; + } + + assert((size_t)(dst - numSubrectsPtr) == m_size); +} + +// +// Main encoding function. +// + +template<class T> +void HextileEncoder::hextileEncodeBetter(rdr::OutStream* os, + const PixelBuffer* pb) +{ + Rect t; + T buf[256]; + T oldBg = 0, oldFg = 0; + bool oldBgValid = false; + bool oldFgValid = false; + uint8_t encoded[256*sizeof(T)]; + + HextileTile<T> tile; + + for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) { + + t.br.y = __rfbmin(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); + + pb->getImage(buf, t); + + tile.newTile(buf, t.width(), t.height()); + int tileType = tile.getFlags(); + size_t encodedLen = tile.getSize(); + + if ( (tileType & hextileRaw) != 0 || + encodedLen >= t.width() * t.height() * sizeof(T)) { + os->writeU8(hextileRaw); + os->writeBytes(buf, t.width() * t.height() * sizeof(T)); + oldBgValid = oldFgValid = false; + continue; + } + + T bg = tile.getBackground(); + T fg = 0; + + if (!oldBgValid || oldBg != bg) { + tileType |= hextileBgSpecified; + oldBg = bg; + oldBgValid = true; + } + + if (tileType & hextileAnySubrects) { + if (tileType & hextileSubrectsColoured) { + oldFgValid = false; + } else { + fg = tile.getForeground(); + if (!oldFgValid || oldFg != fg) { + tileType |= hextileFgSpecified; + oldFg = fg; + oldFgValid = true; + } + } + tile.encode(encoded); + } + + os->writeU8(tileType); + if (tileType & hextileBgSpecified) writePixel(os, bg); + if (tileType & hextileFgSpecified) writePixel(os, fg); + if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen); + } + } +} diff --git a/common/rfb/HextileEncoder.h b/common/rfb/HextileEncoder.h index 393ab23b..20721b7c 100644 --- a/common/rfb/HextileEncoder.h +++ b/common/rfb/HextileEncoder.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -31,7 +31,21 @@ namespace rfb { virtual void writeRect(const PixelBuffer* pb, const Palette& palette); virtual void writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour); + const uint8_t* colour); + private: + template<class T> + inline void writePixel(rdr::OutStream* os, T pixel); + + template<class T> + void hextileEncode(rdr::OutStream* os, const PixelBuffer* pb); + template<class T> + int hextileEncodeTile(T* data, int w, int h, int tileType, + uint8_t* encoded, T bg); + template<class T> + int testTileType(T* data, int w, int h, T* bg, T* fg); + + template<class T> + void hextileEncodeBetter(rdr::OutStream* os, const PixelBuffer* pb); }; } #endif diff --git a/common/rfb/Hostname.h b/common/rfb/Hostname.h index 341f69e1..1971e343 100644 --- a/common/rfb/Hostname.h +++ b/common/rfb/Hostname.h @@ -22,6 +22,7 @@ #include <assert.h> #include <ctype.h> #include <stdlib.h> +#include <string.h> #include <rdr/Exception.h> #include <rfb/util.h> @@ -38,7 +39,9 @@ namespace rfb { return true; } - static void getHostAndPort(const char* hi, char** host, int* port, int basePort=5900) { + static void getHostAndPort(const char* hi, std::string* host, + int* port, int basePort=5900) + { const char* hostStart; const char* hostEnd; const char* portStart; @@ -86,14 +89,9 @@ namespace rfb { hostEnd--; if (hostStart == hostEnd) - *host = strDup("localhost"); - else { - size_t len; - len = hostEnd - hostStart + 1; - *host = new char[len]; - strncpy(*host, hostStart, len-1); - (*host)[len-1] = '\0'; - } + *host = "localhost"; + else + *host = std::string(hostStart, hostEnd - hostStart); if (portStart == NULL) *port = basePort; diff --git a/common/rfb/InputHandler.h b/common/rfb/InputHandler.h index 4719eca0..ad6c4be5 100644 --- a/common/rfb/InputHandler.h +++ b/common/rfb/InputHandler.h @@ -23,16 +23,16 @@ #ifndef __RFB_INPUTHANDLER_H__ #define __RFB_INPUTHANDLER_H__ -#include <rdr/types.h> +#include <stdint.h> + #include <rfb/Rect.h> -#include <rfb/util.h> namespace rfb { class InputHandler { public: virtual ~InputHandler() {} - virtual void keyEvent(rdr::U32 /*keysym*/, rdr::U32 /*keycode*/, + virtual void keyEvent(uint32_t /*keysym*/, uint32_t /*keycode*/, bool /*down*/) { } virtual void pointerEvent(const Point& /*pos*/, int /*buttonMask*/) { } diff --git a/common/rfb/JpegCompressor.cxx b/common/rfb/JpegCompressor.cxx index efb26a77..d5c5fd0d 100644 --- a/common/rfb/JpegCompressor.cxx +++ b/common/rfb/JpegCompressor.cxx @@ -155,14 +155,14 @@ JpegCompressor::~JpegCompressor(void) delete cinfo; } -void JpegCompressor::compress(const rdr::U8 *buf, volatile int stride, +void JpegCompressor::compress(const uint8_t *buf, volatile int stride, const Rect& r, const PixelFormat& pf, int quality, int subsamp) { int w = r.width(); int h = r.height(); int pixelsize; - rdr::U8 * volatile srcBuf = NULL; + uint8_t * volatile srcBuf = NULL; volatile bool srcBufIsTemp = false; JSAMPROW * volatile rowPointer = NULL; @@ -182,17 +182,17 @@ void JpegCompressor::compress(const rdr::U8 *buf, volatile int stride, #ifdef JCS_EXTENSIONS // Try to have libjpeg output directly to our native format // libjpeg can only handle some "standard" formats - if (pfRGBX.equal(pf)) + if (pfRGBX == pf) cinfo->in_color_space = JCS_EXT_RGBX; - else if (pfBGRX.equal(pf)) + else if (pfBGRX == pf) cinfo->in_color_space = JCS_EXT_BGRX; - else if (pfXRGB.equal(pf)) + else if (pfXRGB == pf) cinfo->in_color_space = JCS_EXT_XRGB; - else if (pfXBGR.equal(pf)) + else if (pfXBGR == pf) cinfo->in_color_space = JCS_EXT_XBGR; if (cinfo->in_color_space != JCS_RGB) { - srcBuf = (rdr::U8 *)buf; + srcBuf = (uint8_t *)buf; pixelsize = 4; } #endif @@ -201,9 +201,9 @@ void JpegCompressor::compress(const rdr::U8 *buf, volatile int stride, stride = w; if (cinfo->in_color_space == JCS_RGB) { - srcBuf = new rdr::U8[w * h * pixelsize]; + srcBuf = new uint8_t[w * h * pixelsize]; srcBufIsTemp = true; - pf.rgbFromBuffer(srcBuf, (const rdr::U8 *)buf, w, stride, h); + pf.rgbFromBuffer(srcBuf, (const uint8_t *)buf, w, stride, h); stride = w; } diff --git a/common/rfb/JpegCompressor.h b/common/rfb/JpegCompressor.h index de201732..d4978fdf 100644 --- a/common/rfb/JpegCompressor.h +++ b/common/rfb/JpegCompressor.h @@ -43,7 +43,7 @@ namespace rfb { JpegCompressor(int bufferLen = 128*1024); virtual ~JpegCompressor(); - void compress(const rdr::U8 *, int, const Rect&, const PixelFormat&, int, int); + void compress(const uint8_t *, int, const Rect&, const PixelFormat&, int, int); void writeBytes(const void*, int); diff --git a/common/rfb/JpegDecompressor.cxx b/common/rfb/JpegDecompressor.cxx index ea148b94..44c54fb2 100644 --- a/common/rfb/JpegDecompressor.cxx +++ b/common/rfb/JpegDecompressor.cxx @@ -150,8 +150,8 @@ JpegDecompressor::~JpegDecompressor(void) delete dinfo; } -void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, - int jpegBufLen, rdr::U8 *buf, +void JpegDecompressor::decompress(const uint8_t *jpegBuf, + int jpegBufLen, uint8_t *buf, volatile int stride, const Rect& r, const PixelFormat& pf) { @@ -159,7 +159,7 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, int h = r.height(); int pixelsize; int dstBufStride; - rdr::U8 * volatile dstBuf = NULL; + uint8_t * volatile dstBuf = NULL; volatile bool dstBufIsTemp = false; JSAMPROW * volatile rowPointer = NULL; @@ -184,23 +184,23 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, #ifdef JCS_EXTENSIONS // Try to have libjpeg output directly to our native format // libjpeg can only handle some "standard" formats - if (pfRGBX.equal(pf)) + if (pfRGBX == pf) dinfo->out_color_space = JCS_EXT_RGBX; - else if (pfBGRX.equal(pf)) + else if (pfBGRX == pf) dinfo->out_color_space = JCS_EXT_BGRX; - else if (pfXRGB.equal(pf)) + else if (pfXRGB == pf) dinfo->out_color_space = JCS_EXT_XRGB; - else if (pfXBGR.equal(pf)) + else if (pfXBGR == pf) dinfo->out_color_space = JCS_EXT_XBGR; if (dinfo->out_color_space != JCS_RGB) { - dstBuf = (rdr::U8 *)buf; + dstBuf = (uint8_t *)buf; pixelsize = 4; } #endif if (dinfo->out_color_space == JCS_RGB) { - dstBuf = new rdr::U8[w * h * pixelsize]; + dstBuf = new uint8_t[w * h * pixelsize]; dstBufIsTemp = true; dstBufStride = w; } @@ -226,7 +226,7 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, } if (dinfo->out_color_space == JCS_RGB) - pf.bufferFromRGB((rdr::U8*)buf, dstBuf, w, stride, h); + pf.bufferFromRGB((uint8_t*)buf, dstBuf, w, stride, h); jpeg_finish_decompress(dinfo); diff --git a/common/rfb/JpegDecompressor.h b/common/rfb/JpegDecompressor.h index ed367786..5d4f0c21 100644 --- a/common/rfb/JpegDecompressor.h +++ b/common/rfb/JpegDecompressor.h @@ -43,7 +43,7 @@ namespace rfb { JpegDecompressor(void); virtual ~JpegDecompressor(); - void decompress(const rdr::U8 *, int, rdr::U8 *, int, const Rect&, + void decompress(const uint8_t *, int, uint8_t *, int, const Rect&, const PixelFormat&); private: diff --git a/common/rfb/KeyRemapper.cxx b/common/rfb/KeyRemapper.cxx index 1431a21e..762eb413 100644 --- a/common/rfb/KeyRemapper.cxx +++ b/common/rfb/KeyRemapper.cxx @@ -21,6 +21,7 @@ #endif #include <stdio.h> +#include <string.h> #include <os/Mutex.h> @@ -72,10 +73,10 @@ void KeyRemapper::setMapping(const char* m) { } } -rdr::U32 KeyRemapper::remapKey(rdr::U32 key) const { +uint32_t KeyRemapper::remapKey(uint32_t key) const { os::AutoMutex a(mutex); - std::map<rdr::U32,rdr::U32>::const_iterator i = mapping.find(key); + std::map<uint32_t,uint32_t>::const_iterator i = mapping.find(key); if (i != mapping.end()) return i->second; return key; @@ -86,7 +87,7 @@ class KeyMapParameter : public StringParameter { public: KeyMapParameter() : StringParameter("RemapKeys", "Comma-separated list of incoming keysyms to remap. Mappings are expressed as two hex values, prefixed by 0x, and separated by ->", "") { - setParam(value); + KeyRemapper::defInstance.setMapping(""); } bool setParam(const char* v) { KeyRemapper::defInstance.setMapping(v); diff --git a/common/rfb/KeyRemapper.h b/common/rfb/KeyRemapper.h index 1406bad2..89853721 100644 --- a/common/rfb/KeyRemapper.h +++ b/common/rfb/KeyRemapper.h @@ -20,7 +20,8 @@ #define __RFB_KEYREMAPPER_H__ #include <map> -#include <rdr/types.h> + +#include <stdint.h> namespace os { class Mutex; } @@ -31,10 +32,10 @@ namespace rfb { KeyRemapper(const char* m=""); ~KeyRemapper(); void setMapping(const char* m); - rdr::U32 remapKey(rdr::U32 key) const; + uint32_t remapKey(uint32_t key) const; static KeyRemapper defInstance; private: - std::map<rdr::U32,rdr::U32> mapping; + std::map<uint32_t,uint32_t> mapping; os::Mutex* mutex; }; diff --git a/common/rfb/LogWriter.cxx b/common/rfb/LogWriter.cxx index 6df82d8e..dc9db9d1 100644 --- a/common/rfb/LogWriter.cxx +++ b/common/rfb/LogWriter.cxx @@ -76,19 +76,20 @@ LogWriter::getLogWriter(const char* name) { } bool LogWriter::setLogParams(const char* params) { - CharArray logwriterName, loggerName, logLevel; - if (!strSplit(params, ':', &logwriterName.buf, &loggerName.buf) || - !strSplit(loggerName.buf, ':', &loggerName.buf, &logLevel.buf)) { + 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(logLevel.buf); + int level = atoi(parts[2].c_str()); Logger* logger = 0; - if (strcmp("", loggerName.buf) != 0) { - logger = Logger::getLogger(loggerName.buf); - if (!logger) fprintf(stderr,"no logger found! %s\n",loggerName.buf); + 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 (strcmp("*", logwriterName.buf) == 0) { + if (parts[0] == "*") { LogWriter* current = log_writers; while (current) { current->setLog(logger); @@ -97,9 +98,9 @@ bool LogWriter::setLogParams(const char* params) { } return true; } else { - LogWriter* logwriter = getLogWriter(logwriterName.buf); + LogWriter* logwriter = getLogWriter(parts[0].c_str()); if (!logwriter) { - fprintf(stderr,"no logwriter found! %s\n",logwriterName.buf); + fprintf(stderr, "no logwriter found! %s\n", parts[0].c_str()); } else { logwriter->setLog(logger); logwriter->setLevel(level); @@ -122,11 +123,12 @@ bool LogParameter::setParam(const char* v) { if (immutable) return true; LogWriter::setLogParams("*::0"); StringParameter::setParam(v); - CharArray logParam; - CharArray params(getData()); - while (params.buf) { - strSplit(params.buf, ',', &logParam.buf, ¶ms.buf); - if (strlen(logParam.buf) && !LogWriter::setLogParams(logParam.buf)) + 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/Logger.cxx b/common/rfb/Logger.cxx index e815dad4..7e0895e4 100644 --- a/common/rfb/Logger.cxx +++ b/common/rfb/Logger.cxx @@ -28,7 +28,6 @@ #include <rfb/Logger.h> #include <rfb/LogWriter.h> -#include <rfb/util.h> using namespace rfb; diff --git a/common/rfb/Logger_file.cxx b/common/rfb/Logger_file.cxx index 684614cc..9859eb04 100644 --- a/common/rfb/Logger_file.cxx +++ b/common/rfb/Logger_file.cxx @@ -22,20 +22,21 @@ #include <config.h> #endif +#include <limits.h> #include <stdlib.h> #include <string.h> #include <os/Mutex.h> -#include <rfb/util.h> #include <rfb/Logger_file.h> using namespace rfb; Logger_File::Logger_File(const char* loggerName) - : Logger(loggerName), indent(13), width(79), m_filename(0), m_file(0), + : Logger(loggerName), indent(13), width(79), m_file(0), m_lastLogTime(0) { + m_filename[0] = '\0'; mutex = new os::Mutex(); } @@ -50,11 +51,16 @@ void Logger_File::write(int /*level*/, const char *logname, const char *message) os::AutoMutex a(mutex); if (!m_file) { - if (!m_filename) return; - CharArray bakFilename(strlen(m_filename) + 1 + 4); - sprintf(bakFilename.buf, "%s.bak", m_filename); - remove(bakFilename.buf); - rename(m_filename, bakFilename.buf); + 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; } @@ -93,7 +99,10 @@ void Logger_File::write(int /*level*/, const char *logname, const char *message) void Logger_File::setFilename(const char* filename) { closeFile(); - m_filename = strDup(filename); + m_filename[0] = '\0'; + if (strlen(filename) >= sizeof(filename)) + return; + strcpy(m_filename, filename); } void Logger_File::setFile(FILE* file) @@ -104,13 +113,9 @@ void Logger_File::setFile(FILE* file) void Logger_File::closeFile() { - if (m_filename) { - if (m_file) { - fclose(m_file); - m_file = 0; - } - strFree(m_filename); - m_filename = 0; + if (m_file) { + fclose(m_file); + m_file = 0; } } diff --git a/common/rfb/Logger_file.h b/common/rfb/Logger_file.h index 5b5c34e1..4542d23c 100644 --- a/common/rfb/Logger_file.h +++ b/common/rfb/Logger_file.h @@ -22,6 +22,8 @@ #define __RFB_LOGGER_FILE_H__ #include <time.h> +#include <limits.h> + #include <rfb/Logger.h> namespace os { class Mutex; } @@ -42,7 +44,7 @@ namespace rfb { protected: void closeFile(); - char* m_filename; + char m_filename[PATH_MAX]; FILE* m_file; time_t m_lastLogTime; os::Mutex* mutex; diff --git a/common/rfb/Logger_syslog.cxx b/common/rfb/Logger_syslog.cxx index 0f5c8423..320ab4b0 100644 --- a/common/rfb/Logger_syslog.cxx +++ b/common/rfb/Logger_syslog.cxx @@ -26,7 +26,6 @@ #include <string.h> #include <syslog.h> -#include <rfb/util.h> #include <rfb/Logger_syslog.h> #include <rfb/LogWriter.h> diff --git a/common/rfb/Palette.h b/common/rfb/Palette.h index a9003354..6b8cc57e 100644 --- a/common/rfb/Palette.h +++ b/common/rfb/Palette.h @@ -22,8 +22,7 @@ #include <assert.h> #include <string.h> - -#include <rdr/types.h> +#include <stdint.h> namespace rfb { class Palette { @@ -35,13 +34,13 @@ namespace rfb { void clear() { numColours = 0; memset(hash, 0, sizeof(hash)); } - inline bool insert(rdr::U32 colour, int numPixels); - inline unsigned char lookup(rdr::U32 colour) const; - inline rdr::U32 getColour(unsigned char index) const; + inline bool insert(uint32_t colour, int numPixels); + inline unsigned char lookup(uint32_t colour) const; + inline uint32_t getColour(unsigned char index) const; inline int getCount(unsigned char index) const; protected: - inline unsigned char genHash(rdr::U32 colour) const; + inline unsigned char genHash(uint32_t colour) const; protected: int numColours; @@ -49,7 +48,7 @@ namespace rfb { struct PaletteListNode { PaletteListNode *next; unsigned char idx; - rdr::U32 colour; + uint32_t colour; }; struct PaletteEntry { @@ -67,7 +66,7 @@ namespace rfb { }; } -inline bool rfb::Palette::insert(rdr::U32 colour, int numPixels) +inline bool rfb::Palette::insert(uint32_t colour, int numPixels) { PaletteListNode* pnode; PaletteListNode* prev_pnode; @@ -145,7 +144,7 @@ inline bool rfb::Palette::insert(rdr::U32 colour, int numPixels) return true; } -inline unsigned char rfb::Palette::lookup(rdr::U32 colour) const +inline unsigned char rfb::Palette::lookup(uint32_t colour) const { unsigned char hash_key; PaletteListNode* pnode; @@ -165,7 +164,7 @@ inline unsigned char rfb::Palette::lookup(rdr::U32 colour) const return 0; } -inline rdr::U32 rfb::Palette::getColour(unsigned char index) const +inline uint32_t rfb::Palette::getColour(unsigned char index) const { return entry[index].listNode->colour; } @@ -175,7 +174,7 @@ inline int rfb::Palette::getCount(unsigned char index) const return entry[index].numPixels; } -inline unsigned char rfb::Palette::genHash(rdr::U32 colour) const +inline unsigned char rfb::Palette::genHash(uint32_t colour) const { unsigned char hash_key; diff --git a/common/rfb/Password.h b/common/rfb/Password.h deleted file mode 100644 index 712bc813..00000000 --- a/common/rfb/Password.h +++ /dev/null @@ -1,47 +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_PASSWORD_H__ -#define __RFB_PASSWORD_H__ - -#include <rfb/util.h> - -namespace rfb { - - class ObfuscatedPasswd; - - class PlainPasswd : public CharArray { - public: - PlainPasswd(); - PlainPasswd(char* pwd); - PlainPasswd(size_t len); - PlainPasswd(const ObfuscatedPasswd& obfPwd); - ~PlainPasswd(); - void replaceBuf(char* b); - }; - - class ObfuscatedPasswd : public CharArray { - public: - ObfuscatedPasswd(); - ObfuscatedPasswd(size_t l); - ObfuscatedPasswd(const PlainPasswd& plainPwd); - ~ObfuscatedPasswd(); - size_t length; - }; - -} -#endif diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx index 1b534b7b..c8b5f3d7 100644 --- a/common/rfb/PixelBuffer.cxx +++ b/common/rfb/PixelBuffer.cxx @@ -26,6 +26,8 @@ #include <config.h> #endif +#include <string.h> + #include <rfb/Exception.h> #include <rfb/LogWriter.h> #include <rfb/PixelBuffer.h> @@ -63,10 +65,10 @@ void PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const { int inStride; - const U8* data; + const uint8_t* data; int bytesPerPixel, inBytesPerRow, outBytesPerRow, bytesPerMemCpy; - U8* imageBufPos; - const U8* end; + uint8_t* imageBufPos; + const uint8_t* end; if (!r.enclosed_by(getRect())) throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d", @@ -83,7 +85,7 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const outBytesPerRow = outStride * bytesPerPixel; bytesPerMemCpy = r.width() * bytesPerPixel; - imageBufPos = (U8*)imageBuf; + imageBufPos = (uint8_t*)imageBuf; end = data + (inBytesPerRow * r.height()); while (data < end) { @@ -96,10 +98,10 @@ 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 rdr::U8* srcBuffer; + const uint8_t* srcBuffer; int srcStride; - if (format.equal(pf)) { + if (format == pf) { getImage(imageBuf, r, stride); return; } @@ -114,8 +116,8 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf, srcBuffer = getBuffer(r, &srcStride); - pf.bufferFromBuffer((U8*)imageBuf, format, srcBuffer, r.width(), r.height(), - stride, srcStride); + pf.bufferFromBuffer((uint8_t*)imageBuf, format, srcBuffer, + r.width(), r.height(), stride, srcStride); } void PixelBuffer::setSize(int width, int height) @@ -148,7 +150,7 @@ ModifiablePixelBuffer::~ModifiablePixelBuffer() void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix) { int stride; - U8 *buf; + uint8_t *buf; int w, h, b; if (!r.enclosed_by(getRect())) @@ -166,11 +168,11 @@ void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix) if (b == 1) { while (h--) { - memset(buf, *(const U8*)pix, w); + memset(buf, *(const uint8_t*)pix, w); buf += stride * b; } } else { - U8 *start; + uint8_t *start; int w1; start = buf; @@ -195,11 +197,11 @@ void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix) void ModifiablePixelBuffer::imageRect(const Rect& r, const void* pixels, int srcStride) { - U8* dest; + uint8_t* dest; int destStride; int bytesPerPixel, bytesPerDestRow, bytesPerSrcRow, bytesPerFill; - const U8* src; - U8* end; + const uint8_t* src; + uint8_t* end; if (!r.enclosed_by(getRect())) throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d", @@ -217,7 +219,7 @@ void ModifiablePixelBuffer::imageRect(const Rect& r, bytesPerSrcRow = bytesPerPixel * srcStride; bytesPerFill = bytesPerPixel * r.width(); - src = (const U8*)pixels; + src = (const uint8_t*)pixels; end = dest + (bytesPerDestRow * r.height()); while (dest < end) { @@ -234,8 +236,8 @@ void ModifiablePixelBuffer::copyRect(const Rect &rect, { int srcStride, dstStride; int bytesPerPixel; - const U8* srcData; - U8* dstData; + const uint8_t* srcData; + uint8_t* dstData; Rect drect, srect; @@ -290,15 +292,15 @@ void ModifiablePixelBuffer::copyRect(const Rect &rect, void ModifiablePixelBuffer::fillRect(const PixelFormat& pf, const Rect &dest, const void* pix) { - rdr::U8 buf[4]; - format.bufferFromBuffer(buf, pf, (const rdr::U8*)pix, 1); + uint8_t buf[4]; + format.bufferFromBuffer(buf, pf, (const uint8_t*)pix, 1); fillRect(dest, buf); } void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest, const void* pixels, int stride) { - rdr::U8* dstBuffer; + uint8_t* dstBuffer; int dstStride; if (!dest.enclosed_by(getRect())) @@ -310,7 +312,7 @@ void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest, stride = dest.width(); dstBuffer = getBufferRW(dest, &dstStride); - format.bufferFromBuffer(dstBuffer, pf, (const rdr::U8*)pixels, + format.bufferFromBuffer(dstBuffer, pf, (const uint8_t*)pixels, dest.width(), dest.height(), dstStride, stride); commitBufferRW(dest); @@ -319,7 +321,7 @@ void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest, // -=- Simple pixel buffer with a continuous block of memory FullFramePixelBuffer::FullFramePixelBuffer(const PixelFormat& pf, int w, int h, - rdr::U8* data_, int stride_) + uint8_t* data_, int stride_) : ModifiablePixelBuffer(pf, w, h), data(data_), stride(stride_) { } @@ -328,7 +330,7 @@ FullFramePixelBuffer::FullFramePixelBuffer() : data(0) {} FullFramePixelBuffer::~FullFramePixelBuffer() {} -rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_) +uint8_t* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_) { if (!r.enclosed_by(getRect())) throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d", @@ -343,7 +345,7 @@ void FullFramePixelBuffer::commitBufferRW(const Rect& /*r*/) { } -const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) const +const uint8_t* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) const { if (!r.enclosed_by(getRect())) throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d", @@ -355,7 +357,7 @@ const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) cons } void FullFramePixelBuffer::setBuffer(int width, int height, - rdr::U8* data_, int stride_) + uint8_t* data_, int stride_) { if ((width < 0) || (width > maxPixelBufferWidth)) throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested", width); @@ -415,7 +417,7 @@ void ManagedPixelBuffer::setSize(int w, int h) datasize = 0; } if (new_datasize) { - data_ = new U8[new_datasize]; + data_ = new uint8_t[new_datasize]; datasize = new_datasize; } } diff --git a/common/rfb/PixelBuffer.h b/common/rfb/PixelBuffer.h index b12a734e..33a9c7ae 100644 --- a/common/rfb/PixelBuffer.h +++ b/common/rfb/PixelBuffer.h @@ -27,8 +27,6 @@ #include <rfb/PixelFormat.h> #include <rfb/Rect.h> -#include <rfb/Pixel.h> -#include <rfb/util.h> namespace rfb { @@ -66,7 +64,7 @@ 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 rdr::U8* getBuffer(const Rect& r, int* stride) const = 0; + virtual const uint8_t* getBuffer(const 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 @@ -112,7 +110,7 @@ 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 rdr::U8* getBufferRW(const Rect& r, int* stride) = 0; + virtual uint8_t* getBufferRW(const 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 @@ -149,23 +147,23 @@ namespace rfb { class FullFramePixelBuffer : public ModifiablePixelBuffer { public: FullFramePixelBuffer(const PixelFormat& pf, int width, int height, - rdr::U8* data_, int stride); + uint8_t* data_, int stride); virtual ~FullFramePixelBuffer(); public: - virtual const rdr::U8* getBuffer(const Rect& r, int* stride) const; - virtual rdr::U8* getBufferRW(const Rect& r, int* stride); + virtual const uint8_t* getBuffer(const Rect& r, int* stride) const; + virtual uint8_t* getBufferRW(const Rect& r, int* stride); virtual void commitBufferRW(const Rect& r); protected: FullFramePixelBuffer(); - virtual void setBuffer(int width, int height, rdr::U8* data, int stride); + virtual void setBuffer(int width, int height, uint8_t* data, int stride); private: virtual void setSize(int w, int h); private: - rdr::U8* data; + uint8_t* data; int stride; }; @@ -183,7 +181,7 @@ namespace rfb { virtual void setSize(int w, int h); private: - rdr::U8* data_; // Mirrors FullFramePixelBuffer::data + uint8_t* data_; // Mirrors FullFramePixelBuffer::data unsigned long datasize; }; diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx index 0abf53b6..b90fc206 100644 --- a/common/rfb/PixelFormat.cxx +++ b/common/rfb/PixelFormat.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2009-2014 Pierre Ossman for Cendio AB + * Copyright 2009-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 @@ -30,7 +30,6 @@ #include <rdr/OutStream.h> #include <rfb/Exception.h> #include <rfb/PixelFormat.h> -#include <rfb/util.h> #ifdef _WIN32 #define strcasecmp _stricmp @@ -38,8 +37,8 @@ using namespace rfb; -rdr::U8 PixelFormat::upconvTable[256*8]; -rdr::U8 PixelFormat::downconvTable[256*8]; +uint8_t PixelFormat::upconvTable[256*8]; +uint8_t PixelFormat::downconvTable[256*8]; class PixelFormat::Init { public: @@ -59,8 +58,8 @@ PixelFormat::Init::Init() for (bits = 1;bits <= 8;bits++) { int i, maxVal; - rdr::U8 *subUpTable; - rdr::U8 *subDownTable; + uint8_t *subUpTable; + uint8_t *subDownTable; maxVal = (1 << bits) - 1; subUpTable = &upconvTable[(bits-1)*256]; @@ -100,7 +99,7 @@ PixelFormat::PixelFormat() updateState(); } -bool PixelFormat::equal(const PixelFormat& other) const +bool PixelFormat::operator==(const PixelFormat& other) const { if (bpp != other.bpp || depth != other.depth) return false; @@ -149,6 +148,11 @@ bool PixelFormat::equal(const PixelFormat& other) const return true; } +bool PixelFormat::operator!=(const PixelFormat& other) const +{ + return !(*this == other); +} + void PixelFormat::read(rdr::InStream* is) { bpp = is->readU8(); @@ -234,17 +238,17 @@ bool PixelFormat::isLittleEndian(void) const } -void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const +void PixelFormat::bufferFromRGB(uint8_t *dst, const uint8_t* src, int pixels) const { bufferFromRGB(dst, src, pixels, pixels, 1); } -void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, +void PixelFormat::bufferFromRGB(uint8_t *dst, const uint8_t* src, int w, int stride, int h) const { if (is888()) { // Optimised common case - rdr::U8 *r, *g, *b, *x; + uint8_t *r, *g, *b, *x; if (bigEndian) { r = dst + (24 - redShift)/8; @@ -283,7 +287,7 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int w_ = w; while (w_--) { Pixel p; - rdr::U8 r, g, b; + uint8_t r, g, b; r = *(src++); g = *(src++); @@ -300,18 +304,18 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, } -void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const +void PixelFormat::rgbFromBuffer(uint8_t* dst, const uint8_t* src, int pixels) const { rgbFromBuffer(dst, src, pixels, pixels, 1); } -void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, +void PixelFormat::rgbFromBuffer(uint8_t* dst, const uint8_t* src, int w, int stride, int h) const { if (is888()) { // Optimised common case - const rdr::U8 *r, *g, *b; + const uint8_t *r, *g, *b; if (bigEndian) { r = src + (24 - redShift)/8; @@ -345,7 +349,7 @@ void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int w_ = w; while (w_--) { Pixel p; - rdr::U8 r, g, b; + uint8_t r, g, b; p = pixelFromBuffer(src); @@ -364,25 +368,25 @@ void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, Pixel PixelFormat::pixelFromPixel(const PixelFormat &srcPF, Pixel src) const { - rdr::U16 r, g, b; + uint16_t r, g, b; srcPF.rgbFromPixel(src, &r, &g, &b); return pixelFromRGB(r, g, b); } -void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U8* src, int pixels) const +void PixelFormat::bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF, + const uint8_t* src, int pixels) const { bufferFromBuffer(dst, srcPF, src, pixels, 1, pixels, pixels); } #define IS_ALIGNED(v, a) (((intptr_t)v & (a-1)) == 0) -void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U8* src, int w, int h, +void PixelFormat::bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF, + const uint8_t* src, int w, int h, int dstStride, int srcStride) const { - if (equal(srcPF)) { + if (*this == srcPF) { // Trivial case while (h--) { memcpy(dst, src, w * bpp/8); @@ -391,7 +395,7 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, } } else if (is888() && srcPF.is888()) { // Optimised common case A: byte shuffling (e.g. endian conversion) - rdr::U8 *d[4], *s[4]; + uint8_t *d[4], *s[4]; int dstPad, srcPad; if (bigEndian) { @@ -442,15 +446,15 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, // Optimised common case B: 888 source switch (bpp) { case 8: - directBufferFromBufferFrom888((rdr::U8*)dst, srcPF, src, + directBufferFromBufferFrom888((uint8_t*)dst, srcPF, src, w, h, dstStride, srcStride); break; case 16: - directBufferFromBufferFrom888((rdr::U16*)dst, srcPF, src, + directBufferFromBufferFrom888((uint16_t*)dst, srcPF, src, w, h, dstStride, srcStride); break; case 32: - directBufferFromBufferFrom888((rdr::U32*)dst, srcPF, src, + directBufferFromBufferFrom888((uint32_t*)dst, srcPF, src, w, h, dstStride, srcStride); break; } @@ -458,15 +462,15 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, // Optimised common case C: 888 destination switch (srcPF.bpp) { case 8: - directBufferFromBufferTo888(dst, srcPF, (rdr::U8*)src, + directBufferFromBufferTo888(dst, srcPF, (uint8_t*)src, w, h, dstStride, srcStride); break; case 16: - directBufferFromBufferTo888(dst, srcPF, (rdr::U16*)src, + directBufferFromBufferTo888(dst, srcPF, (uint16_t*)src, w, h, dstStride, srcStride); break; case 32: - directBufferFromBufferTo888(dst, srcPF, (rdr::U32*)src, + directBufferFromBufferTo888(dst, srcPF, (uint32_t*)src, w, h, dstStride, srcStride); break; } @@ -478,7 +482,7 @@ void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, int w_ = w; while (w_--) { Pixel p; - rdr::U8 r, g, b; + uint8_t r, g, b; p = srcPF.pixelFromBuffer(src); srcPF.rgbFromPixel(p, &r, &g, &b); @@ -579,8 +583,8 @@ bool PixelFormat::parse(const char* str) depth = bits1 + bits2 + bits3; bpp = depth <= 8 ? 8 : ((depth <= 16) ? 16 : 32); trueColour = true; - rdr::U32 endianTest = 1; - bigEndian = (*(rdr::U8*)&endianTest == 0); + uint32_t endianTest = 1; + bigEndian = (*(uint8_t*)&endianTest == 0); greenShift = bits3; greenMax = (1 << bits2) - 1; @@ -607,7 +611,7 @@ bool PixelFormat::parse(const char* str) } -static int bits(rdr::U16 value) +static int bits(uint16_t value) { int bits; @@ -710,41 +714,133 @@ bool PixelFormat::isSane(void) return true; } -// Preprocessor generated, optimised methods - -#define INBPP 8 -#define OUTBPP 8 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#define OUTBPP 16 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#define OUTBPP 32 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#undef INBPP - -#define INBPP 16 -#define OUTBPP 8 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#define OUTBPP 16 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#define OUTBPP 32 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#undef INBPP - -#define INBPP 32 -#define OUTBPP 8 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#define OUTBPP 16 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#define OUTBPP 32 -#include "PixelFormatBPP.cxx" -#undef OUTBPP -#undef INBPP +static inline uint8_t swap(uint8_t n) +{ + return n; +} + +static inline uint16_t swap(uint16_t n) +{ + return (((n) & 0xff) << 8) | (((n) >> 8) & 0xff); +} + +static inline uint32_t swap(uint32_t n) +{ + return ((n) >> 24) | (((n) & 0x00ff0000) >> 8) | + (((n) & 0x0000ff00) << 8) | ((n) << 24); +} + +template<class T> +void PixelFormat::directBufferFromBufferFrom888(T* dst, + const PixelFormat &srcPF, + const uint8_t* src, + int w, int h, + int dstStride, + int srcStride) const +{ + const uint8_t *r, *g, *b; + int dstPad, srcPad; + + const uint8_t *redDownTable, *greenDownTable, *blueDownTable; + + redDownTable = &downconvTable[(redBits-1)*256]; + greenDownTable = &downconvTable[(greenBits-1)*256]; + blueDownTable = &downconvTable[(blueBits-1)*256]; + + if (srcPF.bigEndian) { + r = src + (24 - srcPF.redShift)/8; + g = src + (24 - srcPF.greenShift)/8; + b = src + (24 - srcPF.blueShift)/8; + } else { + r = src + srcPF.redShift/8; + g = src + srcPF.greenShift/8; + b = src + srcPF.blueShift/8; + } + + dstPad = (dstStride - w); + srcPad = (srcStride - w) * 4; + while (h--) { + int w_ = w; + while (w_--) { + T d; + + d = redDownTable[*r] << redShift; + d |= greenDownTable[*g] << greenShift; + d |= blueDownTable[*b] << blueShift; + + if (endianMismatch) + d = swap(d); + + *dst = d; + + dst++; + r += 4; + g += 4; + b += 4; + } + dst += dstPad; + r += srcPad; + g += srcPad; + b += srcPad; + } +} + +template<class T> +void PixelFormat::directBufferFromBufferTo888(uint8_t* dst, + const PixelFormat &srcPF, + const T* src, + int w, int h, + int dstStride, + int srcStride) const +{ + uint8_t *r, *g, *b, *x; + int dstPad, srcPad; + + const uint8_t *redUpTable, *greenUpTable, *blueUpTable; + + redUpTable = &upconvTable[(srcPF.redBits-1)*256]; + greenUpTable = &upconvTable[(srcPF.greenBits-1)*256]; + blueUpTable = &upconvTable[(srcPF.blueBits-1)*256]; + if (bigEndian) { + r = dst + (24 - redShift)/8; + g = dst + (24 - greenShift)/8; + b = dst + (24 - blueShift)/8; + x = dst + (24 - (48 - redShift - greenShift - blueShift))/8; + } else { + r = dst + redShift/8; + g = dst + greenShift/8; + b = dst + blueShift/8; + x = dst + (48 - redShift - greenShift - blueShift)/8; + } + + dstPad = (dstStride - w) * 4; + srcPad = (srcStride - w); + while (h--) { + int w_ = w; + while (w_--) { + T s; + + s = *src; + + if (srcPF.endianMismatch) + s = swap(s); + + *r = redUpTable[(s >> srcPF.redShift) & 0xff]; + *g = greenUpTable[(s >> srcPF.greenShift) & 0xff]; + *b = blueUpTable[(s >> srcPF.blueShift) & 0xff]; + *x = 0; + + r += 4; + g += 4; + b += 4; + x += 4; + src++; + } + r += dstPad; + g += dstPad; + b += dstPad; + x += dstPad; + src += srcPad; + } +} diff --git a/common/rfb/PixelFormat.h b/common/rfb/PixelFormat.h index 5b4b6332..f0a16767 100644 --- a/common/rfb/PixelFormat.h +++ b/common/rfb/PixelFormat.h @@ -1,6 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2009-2014 Pierre Ossman for Cendio AB + * Copyright 2009-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 @@ -34,12 +34,14 @@ #ifndef __RFB_PIXELFORMAT_H__ #define __RFB_PIXELFORMAT_H__ -#include <rfb/Pixel.h> +#include <stdint.h> namespace rdr { class InStream; class OutStream; } namespace rfb { + typedef uint32_t Pixel; // must be big enough to hold any pixel value + class PixelFormat { public: PixelFormat(int b, int d, bool e, bool t, @@ -49,7 +51,8 @@ namespace rfb { // Checks if the formats have identical buffer representation. // They might still have different pixel representation, endianness // or true colour state. - bool equal(const PixelFormat& other) const; + bool operator==(const PixelFormat& other) const; + bool operator!=(const PixelFormat& other) const; void read(rdr::InStream* is); void write(rdr::OutStream* os) const; @@ -58,29 +61,29 @@ namespace rfb { bool isBigEndian(void) const; bool isLittleEndian(void) const; - inline Pixel pixelFromBuffer(const rdr::U8* buffer) const; - inline void bufferFromPixel(rdr::U8* buffer, Pixel pixel) const; + inline Pixel pixelFromBuffer(const uint8_t* buffer) const; + inline void bufferFromPixel(uint8_t* buffer, Pixel pixel) const; - inline Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const; - inline Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) const; + inline Pixel pixelFromRGB(uint16_t red, uint16_t green, uint16_t blue) const; + inline Pixel pixelFromRGB(uint8_t red, uint8_t green, uint8_t blue) const; - void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const; - void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, + void bufferFromRGB(uint8_t *dst, const uint8_t* src, int pixels) const; + void bufferFromRGB(uint8_t *dst, const uint8_t* src, int w, int stride, int h) const; - inline void rgbFromPixel(Pixel pix, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const; - inline void rgbFromPixel(Pixel pix, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const; + inline void rgbFromPixel(Pixel pix, uint16_t *r, uint16_t *g, uint16_t *b) const; + inline void rgbFromPixel(Pixel pix, uint8_t *r, uint8_t *g, uint8_t *b) const; - void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const; - void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, + void rgbFromBuffer(uint8_t* dst, const uint8_t* src, int pixels) const; + void rgbFromBuffer(uint8_t* dst, const uint8_t* src, int w, int stride, int h) const; Pixel pixelFromPixel(const PixelFormat &srcPF, Pixel src) const; - void bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U8* src, int pixels) const; - void bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U8* src, int w, int h, + void bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF, + const uint8_t* src, int pixels) const; + void bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF, + const uint8_t* src, int w, int h, int dstStride, int srcStride) const; void print(char* str, int len) const; @@ -91,26 +94,14 @@ namespace rfb { bool isSane(void); private: - // Preprocessor generated, optimised methods - - void directBufferFromBufferFrom888(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U8* src, int w, int h, - int dstStride, int srcStride) const; - void directBufferFromBufferFrom888(rdr::U16* dst, const PixelFormat &srcPF, - const rdr::U8* src, int w, int h, - int dstStride, int srcStride) const; - void directBufferFromBufferFrom888(rdr::U32* dst, const PixelFormat &srcPF, - const rdr::U8* src, int w, int h, + // Templated, optimised methods + template<class T> + void directBufferFromBufferFrom888(T* dst, const PixelFormat &srcPF, + const uint8_t* src, int w, int h, int dstStride, int srcStride) const; - - void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U8* src, int w, int h, - int dstStride, int srcStride) const; - void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U16* src, int w, int h, - int dstStride, int srcStride) const; - void directBufferFromBufferTo888(rdr::U8* dst, const PixelFormat &srcPF, - const rdr::U32* src, int w, int h, + template<class T> + void directBufferFromBufferTo888(uint8_t* dst, const PixelFormat &srcPF, + const T* src, int w, int h, int dstStride, int srcStride) const; public: @@ -136,18 +127,18 @@ namespace rfb { int maxBits, minBits; bool endianMismatch; - static rdr::U8 upconvTable[256*8]; - static rdr::U8 downconvTable[256*8]; + static uint8_t upconvTable[256*8]; + static uint8_t downconvTable[256*8]; class Init; friend class Init; static Init _init; /* Only for testing this class */ - friend void makePixel(const rfb::PixelFormat &, rdr::U8 *); + friend void makePixel(const rfb::PixelFormat &, uint8_t *); friend bool verifyPixel(const rfb::PixelFormat &, const rfb::PixelFormat &, - const rdr::U8 *); + const uint8_t *); }; } diff --git a/common/rfb/PixelFormat.inl b/common/rfb/PixelFormat.inl index 3a0bfe49..beec096a 100644 --- a/common/rfb/PixelFormat.inl +++ b/common/rfb/PixelFormat.inl @@ -19,7 +19,7 @@ namespace rfb { -inline Pixel PixelFormat::pixelFromBuffer(const rdr::U8* buffer) const +inline Pixel PixelFormat::pixelFromBuffer(const uint8_t* buffer) const { Pixel p; @@ -52,7 +52,7 @@ inline Pixel PixelFormat::pixelFromBuffer(const rdr::U8* buffer) const } -inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const +inline void PixelFormat::bufferFromPixel(uint8_t* buffer, Pixel p) const { if (bigEndian) { switch (bpp) { @@ -79,7 +79,7 @@ inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const } -inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const +inline Pixel PixelFormat::pixelFromRGB(uint16_t red, uint16_t green, uint16_t blue) const { Pixel p; @@ -91,7 +91,7 @@ inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 bl } -inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) const +inline Pixel PixelFormat::pixelFromRGB(uint8_t red, uint8_t green, uint8_t blue) const { Pixel p; @@ -103,9 +103,9 @@ inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) } -inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const +inline void PixelFormat::rgbFromPixel(Pixel p, uint16_t *r, uint16_t *g, uint16_t *b) const { - rdr::U8 _r, _g, _b; + uint8_t _r, _g, _b; _r = p >> redShift; _g = p >> greenShift; @@ -121,9 +121,9 @@ inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U16 *r, rdr::U16 *g, rdr::U1 } -inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const +inline void PixelFormat::rgbFromPixel(Pixel p, uint8_t *r, uint8_t *g, uint8_t *b) const { - rdr::U8 _r, _g, _b; + uint8_t _r, _g, _b; _r = p >> redShift; _g = p >> greenShift; diff --git a/common/rfb/PixelFormatBPP.cxx b/common/rfb/PixelFormatBPP.cxx deleted file mode 100644 index c8e432df..00000000 --- a/common/rfb/PixelFormatBPP.cxx +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright 2014 Pierre Ossman for Cendio AB - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) - -#define UIN CONCAT2E(U,INBPP) -#define UOUT CONCAT2E(U,OUTBPP) - -#define SWAP16(n) ((((n) & 0xff) << 8) | (((n) >> 8) & 0xff)) -#define SWAP32(n) (((n) >> 24) | (((n) & 0x00ff0000) >> 8) | \ - (((n) & 0x0000ff00) << 8) | ((n) << 24)) - -#define SWAPIN CONCAT2E(SWAP,INBPP) -#define SWAPOUT CONCAT2E(SWAP,OUTBPP) - -#if INBPP == 32 - -void PixelFormat::directBufferFromBufferFrom888(rdr::UOUT* dst, - const PixelFormat &srcPF, - const rdr::U8* src, - int w, int h, - int dstStride, - int srcStride) const -{ - const rdr::U8 *r, *g, *b; - int dstPad, srcPad; - - const rdr::U8 *redDownTable, *greenDownTable, *blueDownTable; - - redDownTable = &downconvTable[(redBits-1)*256]; - greenDownTable = &downconvTable[(greenBits-1)*256]; - blueDownTable = &downconvTable[(blueBits-1)*256]; - - if (srcPF.bigEndian) { - r = src + (24 - srcPF.redShift)/8; - g = src + (24 - srcPF.greenShift)/8; - b = src + (24 - srcPF.blueShift)/8; - } else { - r = src + srcPF.redShift/8; - g = src + srcPF.greenShift/8; - b = src + srcPF.blueShift/8; - } - - dstPad = (dstStride - w); - srcPad = (srcStride - w) * 4; - while (h--) { - int w_ = w; - while (w_--) { - rdr::UOUT d; - - d = redDownTable[*r] << redShift; - d |= greenDownTable[*g] << greenShift; - d |= blueDownTable[*b] << blueShift; - -#if OUTBPP != 8 - if (endianMismatch) - d = SWAPOUT(d); -#endif - - *dst = d; - - dst++; - r += 4; - g += 4; - b += 4; - } - dst += dstPad; - r += srcPad; - g += srcPad; - b += srcPad; - } -} - -#endif /* INBPP == 32 */ - -#if OUTBPP == 32 - -void PixelFormat::directBufferFromBufferTo888(rdr::U8* dst, - const PixelFormat &srcPF, - const rdr::UIN* src, - int w, int h, - int dstStride, - int srcStride) const -{ - rdr::U8 *r, *g, *b, *x; - int dstPad, srcPad; - - const rdr::U8 *redUpTable, *greenUpTable, *blueUpTable; - - redUpTable = &upconvTable[(srcPF.redBits-1)*256]; - greenUpTable = &upconvTable[(srcPF.greenBits-1)*256]; - blueUpTable = &upconvTable[(srcPF.blueBits-1)*256]; - - if (bigEndian) { - r = dst + (24 - redShift)/8; - g = dst + (24 - greenShift)/8; - b = dst + (24 - blueShift)/8; - x = dst + (24 - (48 - redShift - greenShift - blueShift))/8; - } else { - r = dst + redShift/8; - g = dst + greenShift/8; - b = dst + blueShift/8; - x = dst + (48 - redShift - greenShift - blueShift)/8; - } - - dstPad = (dstStride - w) * 4; - srcPad = (srcStride - w); - while (h--) { - int w_ = w; - while (w_--) { - rdr::UIN s; - - s = *src; - -#if INBPP != 8 - if (srcPF.endianMismatch) - s = SWAPIN(s); -#endif - - *r = redUpTable[(s >> srcPF.redShift) & 0xff]; - *g = greenUpTable[(s >> srcPF.greenShift) & 0xff]; - *b = blueUpTable[(s >> srcPF.blueShift) & 0xff]; - *x = 0; - - r += 4; - g += 4; - b += 4; - x += 4; - src++; - } - r += dstPad; - g += dstPad; - b += dstPad; - x += dstPad; - src += srcPad; - } -} - -#endif /* OUTBPP == 32 */ diff --git a/common/rfb/RREDecoder.cxx b/common/rfb/RREDecoder.cxx index a01cbe74..c85c015c 100644 --- a/common/rfb/RREDecoder.cxx +++ b/common/rfb/RREDecoder.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014-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 @@ -24,22 +25,13 @@ #include <rdr/MemInStream.h> #include <rdr/OutStream.h> +#include <rfb/Exception.h> #include <rfb/ServerParams.h> #include <rfb/PixelBuffer.h> #include <rfb/RREDecoder.h> using namespace rfb; -#define BPP 8 -#include <rfb/rreDecode.h> -#undef BPP -#define BPP 16 -#include <rfb/rreDecode.h> -#undef BPP -#define BPP 32 -#include <rfb/rreDecode.h> -#undef BPP - RREDecoder::RREDecoder() : Decoder(DecoderPlain) { } @@ -51,7 +43,7 @@ RREDecoder::~RREDecoder() bool RREDecoder::readRect(const Rect& /*r*/, rdr::InStream* is, const ServerParams& server, rdr::OutStream* os) { - rdr::U32 numRects; + uint32_t numRects; size_t len; if (!is->hasData(4)) @@ -81,8 +73,42 @@ void RREDecoder::decodeRect(const Rect& r, const void* buffer, rdr::MemInStream is(buffer, buflen); const PixelFormat& pf = server.pf(); switch (pf.bpp) { - case 8: rreDecode8 (r, &is, pf, pb); break; - case 16: rreDecode16(r, &is, pf, pb); break; - case 32: rreDecode32(r, &is, pf, pb); break; + case 8: rreDecode<uint8_t >(r, &is, pf, pb); break; + case 16: rreDecode<uint16_t>(r, &is, pf, pb); break; + case 32: rreDecode<uint32_t>(r, &is, pf, pb); break; + } +} + +template<class T> +inline T RREDecoder::readPixel(rdr::InStream* is) +{ + if (sizeof(T) == 1) + return is->readOpaque8(); + if (sizeof(T) == 2) + return is->readOpaque16(); + if (sizeof(T) == 4) + return is->readOpaque32(); +} + +template<class T> +void RREDecoder::rreDecode(const Rect& r, rdr::InStream* is, + const PixelFormat& pf, + ModifiablePixelBuffer* pb) +{ + int nSubrects = is->readU32(); + T bg = readPixel<T>(is); + pb->fillRect(pf, r, &bg); + + for (int i = 0; i < nSubrects; i++) { + T pix = readPixel<T>(is); + int x = is->readU16(); + int y = is->readU16(); + int w = is->readU16(); + int h = is->readU16(); + + if (((x+w) > r.width()) || ((y+h) > r.height())) + throw Exception ("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); } } diff --git a/common/rfb/RREDecoder.h b/common/rfb/RREDecoder.h index b8ec18f6..05acbc24 100644 --- a/common/rfb/RREDecoder.h +++ b/common/rfb/RREDecoder.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014-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 @@ -22,6 +23,8 @@ namespace rfb { + class PixelFormat; + class RREDecoder : public Decoder { public: RREDecoder(); @@ -31,6 +34,12 @@ namespace rfb { virtual void decodeRect(const Rect& r, const void* buffer, size_t buflen, const ServerParams& server, ModifiablePixelBuffer* pb); + private: + template<class T> + inline T readPixel(rdr::InStream* is); + template<class T> + void rreDecode(const Rect& r, rdr::InStream* is, + const PixelFormat& pf, ModifiablePixelBuffer* pb); }; } #endif diff --git a/common/rfb/RREEncoder.cxx b/common/rfb/RREEncoder.cxx index 31f94e7c..e73a23bf 100644 --- a/common/rfb/RREEncoder.cxx +++ b/common/rfb/RREEncoder.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -31,16 +31,6 @@ using namespace rfb; -#define BPP 8 -#include <rfb/rreEncode.h> -#undef BPP -#define BPP 16 -#include <rfb/rreEncode.h> -#undef BPP -#define BPP 32 -#include <rfb/rreEncode.h> -#undef BPP - RREEncoder::RREEncoder(SConnection* conn) : Encoder(conn, encodingRRE, EncoderPlain) { @@ -57,9 +47,9 @@ bool RREEncoder::isSupported() void RREEncoder::writeRect(const PixelBuffer* pb, const Palette& palette) { - rdr::U8* imageBuf; + uint8_t* imageBuf; int stride; - rdr::U32 bg; + uint32_t bg; int w = pb->width(); int h = pb->height(); @@ -89,13 +79,13 @@ void RREEncoder::writeRect(const PixelBuffer* pb, const Palette& palette) int nSubrects = -1; switch (pb->getPF().bpp) { case 8: - nSubrects = rreEncode8((rdr::U8*)imageBuf, w, h, &mos, bg); + nSubrects = rreEncode<uint8_t>((uint8_t*)imageBuf, w, h, &mos, bg); break; case 16: - nSubrects = rreEncode16((rdr::U16*)imageBuf, w, h, &mos, bg); + nSubrects = rreEncode<uint16_t>((uint16_t*)imageBuf, w, h, &mos, bg); break; case 32: - nSubrects = rreEncode32((rdr::U32*)imageBuf, w, h, &mos, bg); + nSubrects = rreEncode<uint32_t>((uint32_t*)imageBuf, w, h, &mos, bg); break; } @@ -109,7 +99,7 @@ void RREEncoder::writeRect(const PixelBuffer* pb, const Palette& palette) void RREEncoder::writeSolidRect(int /*width*/, int /*height*/, const PixelFormat& pf, - const rdr::U8* colour) + const uint8_t* colour) { rdr::OutStream* os; @@ -118,3 +108,93 @@ void RREEncoder::writeSolidRect(int /*width*/, int /*height*/, os->writeU32(0); os->writeBytes(colour, pf.bpp/8); } + +template<class T> +inline void RREEncoder::writePixel(rdr::OutStream* os, T pixel) +{ + if (sizeof(T) == 1) + os->writeOpaque8(pixel); + else if (sizeof(T) == 2) + os->writeOpaque16(pixel); + else if (sizeof(T) == 4) + os->writeOpaque32(pixel); +} + +template<class T> +int RREEncoder::rreEncode(T* data, int w, int h, + rdr::OutStream* os, T bg) +{ + writePixel(os, bg); + + int nSubrects = 0; + + for (int y = 0; y < h; y++) + { + int x = 0; + while (x < w) { + if (*data == bg) { + x++; + data++; + continue; + } + + // Find horizontal subrect first + T* ptr = data+1; + T* eol = data+w-x; + while (ptr < eol && *ptr == *data) ptr++; + int sw = ptr - data; + + ptr = data + w; + int sh = 1; + while (sh < h-y) { + eol = ptr + sw; + while (ptr < eol) + if (*ptr++ != *data) goto endOfHorizSubrect; + ptr += w - sw; + sh++; + } + endOfHorizSubrect: + + // Find vertical subrect + int vh; + for (vh = sh; vh < h-y; vh++) + if (data[vh*w] != *data) break; + + if (vh != sh) { + ptr = data+1; + int vw; + for (vw = 1; vw < sw; vw++) { + for (int i = 0; i < vh; i++) + if (ptr[i*w] != *data) goto endOfVertSubrect; + ptr++; + } + endOfVertSubrect: + + // If vertical subrect bigger than horizontal then use that. + if (sw*sh < vw*vh) { + sw = vw; + sh = vh; + } + } + + nSubrects++; + writePixel(os, *data); + os->writeU16(x); + os->writeU16(y); + os->writeU16(sw); + os->writeU16(sh); + + ptr = data+w; + T* eor = data+w*sh; + while (ptr < eor) { + eol = ptr + sw; + while (ptr < eol) *ptr++ = bg; + ptr += w - sw; + } + x += sw; + data += sw; + } + } + + return nSubrects; +} diff --git a/common/rfb/RREEncoder.h b/common/rfb/RREEncoder.h index c0de9995..b13135b4 100644 --- a/common/rfb/RREEncoder.h +++ b/common/rfb/RREEncoder.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -33,7 +33,12 @@ namespace rfb { virtual void writeRect(const PixelBuffer* pb, const Palette& palette); virtual void writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour); + const uint8_t* colour); + private: + template<class T> + inline void writePixel(rdr::OutStream* os, T pixel); + template<class T> + int rreEncode(T* data, int w, int h, rdr::OutStream* os, T bg); private: rdr::MemOutStream mos; ManagedPixelBuffer bufferCopy; diff --git a/common/rfb/RawEncoder.cxx b/common/rfb/RawEncoder.cxx index 28115588..2fa1af36 100644 --- a/common/rfb/RawEncoder.cxx +++ b/common/rfb/RawEncoder.cxx @@ -47,7 +47,7 @@ bool RawEncoder::isSupported() void RawEncoder::writeRect(const PixelBuffer* pb, const Palette& /*palette*/) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; rdr::OutStream* os; @@ -68,7 +68,7 @@ void RawEncoder::writeRect(const PixelBuffer* pb, void RawEncoder::writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour) + const uint8_t* colour) { rdr::OutStream* os; int pixels, pixel_size; diff --git a/common/rfb/RawEncoder.h b/common/rfb/RawEncoder.h index ee98d4ad..76da4c5b 100644 --- a/common/rfb/RawEncoder.h +++ b/common/rfb/RawEncoder.h @@ -31,7 +31,7 @@ namespace rfb { virtual void writeRect(const PixelBuffer* pb, const Palette& palette); virtual void writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour); + const uint8_t* colour); }; } #endif diff --git a/common/rfb/Rect.h b/common/rfb/Rect.h index b5ae2548..b82ed274 100644 --- a/common/rfb/Rect.h +++ b/common/rfb/Rect.h @@ -47,10 +47,17 @@ namespace rfb { struct Point { Point() : x(0), y(0) {} Point(int x_, int y_) : x(x_), y(y_) {} - inline Point negate() const {return Point(-x, -y);} - inline bool equals(const Point &p) const {return x==p.x && y==p.y;} - inline Point translate(const Point &p) const {return Point(x+p.x, y+p.y);} - inline Point subtract(const Point &p) const {return Point(x-p.x, y-p.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; }; @@ -72,7 +79,9 @@ namespace rfb { 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 { + 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); @@ -80,7 +89,9 @@ namespace rfb { result.br.y = __rfbmax(__rfbmin(br.y, r.br.y), result.tl.y); return result; } - inline Rect union_boundary(const Rect &r) const { + 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; @@ -90,10 +101,13 @@ namespace rfb { result.br.y = __rfbmax(br.y, r.br.y); return result; } - inline Rect translate(const Point &p) const { + inline Rect translate(const Point &p) const + __attribute__ ((warn_unused_result)) + { return Rect(tl.translate(p), br.translate(p)); } - inline bool equals(const Rect &r) const {return r.tl.equals(tl) && r.br.equals(br);} + 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 { diff --git a/common/rfb/Region.cxx b/common/rfb/Region.cxx index fecc881e..cfdf0ca2 100644 --- a/common/rfb/Region.cxx +++ b/common/rfb/Region.cxx @@ -101,10 +101,14 @@ rfb::Region rfb::Region::subtract(const rfb::Region& r) const { return ret; } -bool rfb::Region::equals(const rfb::Region& r) const { +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); } diff --git a/common/rfb/Region.h b/common/rfb/Region.h index 6ac3a75b..38de67ce 100644 --- a/common/rfb/Region.h +++ b/common/rfb/Region.h @@ -53,11 +53,15 @@ namespace rfb { // the following three operations return a new region: - Region intersect(const Region& r) const; - Region union_(const Region& r) const; - Region subtract(const Region& r) const; - - bool equals(const Region& b) const; + 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; } diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx index 0bb8e4a9..e5d40e9d 100644 --- a/common/rfb/SConnection.cxx +++ b/common/rfb/SConnection.cxx @@ -35,6 +35,7 @@ #include <rfb/encodings.h> #include <rfb/EncodeManager.h> #include <rfb/SSecurity.h> +#include <rfb/util.h> #include <rfb/LogWriter.h> @@ -59,7 +60,8 @@ SConnection::SConnection() is(0), os(0), reader_(0), writer_(0), ssecurity(0), authFailureTimer(this, &SConnection::handleAuthFailureTimeout), state_(RFBSTATE_UNINITIALISED), preferredEncoding(encodingRaw), - accessRights(0x0000), clientClipboard(NULL), hasLocalClipboard(false), + accessRights(0x0000), hasRemoteClipboard(false), + hasLocalClipboard(false), unsolicitedClipboardAttempt(false) { defaultMajorVersion = 3; @@ -160,8 +162,8 @@ bool SConnection::processVersionMsg() versionReceived(); - std::list<rdr::U8> secTypes; - std::list<rdr::U8>::iterator i; + std::list<uint8_t> secTypes; + std::list<uint8_t>::iterator i; secTypes = security.GetEnabledSecTypes(); if (client.isVersion(3,3)) { @@ -215,8 +217,8 @@ bool SConnection::processSecurityTypeMsg() void SConnection::processSecurityType(int secType) { // Verify that the requested security type should be offered - std::list<rdr::U8> secTypes; - std::list<rdr::U8>::iterator i; + std::list<uint8_t> secTypes; + std::list<uint8_t>::iterator i; secTypes = security.GetEnabledSecTypes(); for (i=secTypes.begin(); i!=secTypes.end(); i++) @@ -246,7 +248,7 @@ bool SConnection::processSecurityMsg() state_ = RFBSTATE_SECURITY_FAILURE; // Introduce a slight delay of the authentication failure response // to make it difficult to brute force a password - authFailureMsg.replaceBuf(strDup(e.str())); + authFailureMsg = e.str(); authFailureTimer.start(100); return true; } @@ -295,9 +297,8 @@ bool SConnection::handleAuthFailureTimeout(Timer* /*t*/) try { os->writeU32(secResultFailed); if (!client.beforeVersion(3,8)) { // 3.8 onwards have failure message - const char* reason = authFailureMsg.buf; - os->writeU32(strlen(reason)); - os->writeBytes(reason, strlen(reason)); + os->writeU32(authFailureMsg.size()); + os->writeBytes(authFailureMsg.data(), authFailureMsg.size()); } os->flush(); } catch (rdr::Exception& e) { @@ -305,7 +306,7 @@ bool SConnection::handleAuthFailureTimeout(Timer* /*t*/) return false; } - close(authFailureMsg.buf); + close(authFailureMsg.c_str()); return false; } @@ -352,7 +353,7 @@ bool SConnection::accessCheck(AccessRights ar) const return (accessRights & ar) == ar; } -void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings) +void SConnection::setEncodings(int nEncodings, const int32_t* encodings) { int i; @@ -367,7 +368,7 @@ void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings) SMsgHandler::setEncodings(nEncodings, encodings); if (client.supportsEncoding(pseudoEncodingExtendedClipboard)) { - rdr::U32 sizes[] = { 0 }; + uint32_t sizes[] = { 0 }; writer()->writeClipboardCaps(rfb::clipboardUTF8 | rfb::clipboardRequest | rfb::clipboardPeek | @@ -381,15 +382,13 @@ void SConnection::clientCutText(const char* str) { hasLocalClipboard = false; - strFree(clientClipboard); - clientClipboard = NULL; - clientClipboard = latin1ToUTF8(str); + hasRemoteClipboard = true; handleClipboardAnnounce(true); } -void SConnection::handleClipboardRequest(rdr::U32 flags) +void SConnection::handleClipboardRequest(uint32_t flags) { if (!(flags & rfb::clipboardUTF8)) { vlog.debug("Ignoring clipboard request for unsupported formats 0x%x", flags); @@ -408,10 +407,9 @@ void SConnection::handleClipboardPeek() writer()->writeClipboardNotify(hasLocalClipboard ? rfb::clipboardUTF8 : 0); } -void SConnection::handleClipboardNotify(rdr::U32 flags) +void SConnection::handleClipboardNotify(uint32_t flags) { - strFree(clientClipboard); - clientClipboard = NULL; + hasRemoteClipboard = false; if (flags & rfb::clipboardUTF8) { hasLocalClipboard = false; @@ -421,22 +419,20 @@ void SConnection::handleClipboardNotify(rdr::U32 flags) } } -void SConnection::handleClipboardProvide(rdr::U32 flags, +void SConnection::handleClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data) + const uint8_t* const* data) { if (!(flags & rfb::clipboardUTF8)) { vlog.debug("Ignoring clipboard provide with unsupported formats 0x%x", flags); return; } - strFree(clientClipboard); - clientClipboard = NULL; - clientClipboard = convertLF((const char*)data[0], lengths[0]); + hasRemoteClipboard = true; // FIXME: Should probably verify that this data was actually requested - handleClipboardData(clientClipboard); + handleClipboardData(clientClipboard.c_str()); } void SConnection::supportsQEMUKeyEvent() @@ -523,7 +519,7 @@ void SConnection::framebufferUpdateRequest(const Rect& /*r*/, } } -void SConnection::fence(rdr::U32 flags, unsigned len, const char data[]) +void SConnection::fence(uint32_t flags, unsigned len, const char data[]) { if (!(flags & fenceFlagRequest)) return; @@ -554,8 +550,8 @@ void SConnection::handleClipboardData(const char* /*data*/) void SConnection::requestClipboard() { - if (clientClipboard != NULL) { - handleClipboardData(clientClipboard); + if (hasRemoteClipboard) { + handleClipboardData(clientClipboard.c_str()); return; } @@ -594,9 +590,9 @@ void SConnection::sendClipboardData(const char* data) { if (client.supportsEncoding(pseudoEncodingExtendedClipboard) && (client.clipboardFlags() & rfb::clipboardProvide)) { - CharArray filtered(convertCRLF(data)); - size_t sizes[1] = { strlen(filtered.buf) + 1 }; - const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf }; + std::string filtered(convertCRLF(data)); + size_t sizes[1] = { filtered.size() + 1 }; + const uint8_t* data[1] = { (const uint8_t*)filtered.c_str() }; if (unsolicitedClipboardAttempt) { unsolicitedClipboardAttempt = false; @@ -610,9 +606,9 @@ void SConnection::sendClipboardData(const char* data) writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data); } else { - CharArray latin1(utf8ToLatin1(data)); + std::string latin1(utf8ToLatin1(data)); - writer()->writeServerCutText(latin1.buf); + writer()->writeServerCutText(latin1.c_str()); } } @@ -624,14 +620,12 @@ void SConnection::cleanup() reader_ = NULL; delete writer_; writer_ = NULL; - strFree(clientClipboard); - clientClipboard = NULL; } void SConnection::writeFakeColourMap(void) { int i; - rdr::U16 red[256], green[256], blue[256]; + uint16_t red[256], green[256], blue[256]; for (i = 0;i < 256;i++) client.pf().rgbFromPixel(i, &red[i], &green[i], &blue[i]); diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h index b7e30c6a..08574069 100644 --- a/common/rfb/SConnection.h +++ b/common/rfb/SConnection.h @@ -24,6 +24,8 @@ #ifndef __RFB_SCONNECTION_H__ #define __RFB_SCONNECTION_H__ +#include <string> + #include <rdr/InStream.h> #include <rdr/OutStream.h> @@ -80,16 +82,16 @@ namespace rfb { // Overridden from SMsgHandler - virtual void setEncodings(int nEncodings, const rdr::S32* encodings); + virtual void setEncodings(int nEncodings, const int32_t* encodings); virtual void clientCutText(const char* str); - virtual void handleClipboardRequest(rdr::U32 flags); + virtual void handleClipboardRequest(uint32_t flags); virtual void handleClipboardPeek(); - virtual void handleClipboardNotify(rdr::U32 flags); - virtual void handleClipboardProvide(rdr::U32 flags, + virtual void handleClipboardNotify(uint32_t flags); + virtual void handleClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data); + const uint8_t* const* data); virtual void supportsQEMUKeyEvent(); @@ -130,7 +132,7 @@ namespace rfb { // it responds directly to requests (stating it doesn't support any // synchronisation) and drops responses. Override to implement more proper // support. - virtual void fence(rdr::U32 flags, unsigned len, const char data[]); + virtual void fence(uint32_t flags, unsigned len, const char data[]); // enableContinuousUpdates() is called when the client wants to enable // or disable continuous updates, or change the active area. @@ -177,7 +179,7 @@ namespace rfb { // of a SConnection to the server. How the access rights are treated // is up to the derived class. - typedef rdr::U16 AccessRights; + typedef uint16_t AccessRights; static const AccessRights AccessView; // View display contents static const AccessRights AccessKeyEvents; // Send key events static const AccessRights AccessPtrEvents; // Send pointer events @@ -216,7 +218,7 @@ namespace rfb { stateEnum state() { return state_; } - rdr::S32 getPreferredEncoding() { return preferredEncoding; } + int32_t getPreferredEncoding() { return preferredEncoding; } protected: // throwConnFailedException() prints a message to the log, sends a conn @@ -257,13 +259,14 @@ namespace rfb { SSecurity* ssecurity; MethodTimer<SConnection> authFailureTimer; - CharArray authFailureMsg; + std::string authFailureMsg; stateEnum state_; - rdr::S32 preferredEncoding; + int32_t preferredEncoding; AccessRights accessRights; - char* clientClipboard; + std::string clientClipboard; + bool hasRemoteClipboard; bool hasLocalClipboard; bool unsolicitedClipboardAttempt; }; diff --git a/common/rfb/SDesktop.h b/common/rfb/SDesktop.h index 6d2a5dd8..9db08116 100644 --- a/common/rfb/SDesktop.h +++ b/common/rfb/SDesktop.h @@ -41,16 +41,12 @@ #include <rfb/PixelBuffer.h> #include <rfb/VNCServer.h> #include <rfb/InputHandler.h> -#include <rfb/Exception.h> #include <rfb/screenTypes.h> -#include <rfb/util.h> namespace network { class Socket; } namespace rfb { - class VNCServer; - class SDesktop : public InputHandler { public: // start() is called by the server when the first client authenticates @@ -125,13 +121,13 @@ namespace rfb { public: SStaticDesktop(const Point& size) : server(0), buffer(0) { PixelFormat pf; - const rdr::U8 black[4] = { 0, 0, 0, 0 }; + 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(0) { - const rdr::U8 black[4] = { 0, 0, 0, 0 }; + const uint8_t black[4] = { 0, 0, 0, 0 }; buffer = new ManagedPixelBuffer(pf, size.x, size.y); if (buffer) buffer->fillRect(buffer->getRect(), black); diff --git a/common/rfb/SMsgHandler.cxx b/common/rfb/SMsgHandler.cxx index 4f008039..4ecfc2b2 100644 --- a/common/rfb/SMsgHandler.cxx +++ b/common/rfb/SMsgHandler.cxx @@ -27,6 +27,7 @@ #include <rfb/ScreenSet.h> #include <rfb/clipboardTypes.h> #include <rfb/encodings.h> +#include <rfb/util.h> using namespace rfb; @@ -49,7 +50,7 @@ void SMsgHandler::setPixelFormat(const PixelFormat& pf) client.setPF(pf); } -void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings) +void SMsgHandler::setEncodings(int nEncodings, const int32_t* encodings) { bool firstFence, firstContinuousUpdates, firstLEDState, firstQEMUKeyEvent; @@ -73,7 +74,7 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings) supportsQEMUKeyEvent(); } -void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) +void SMsgHandler::handleClipboardCaps(uint32_t flags, const uint32_t* lengths) { int i; @@ -106,11 +107,8 @@ void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) if (lengths[i] == 0) vlog.debug(" %s (only notify)", type); else { - char bytes[1024]; - - iecPrefix(lengths[i], "B", bytes, sizeof(bytes)); vlog.debug(" %s (automatically send up to %s)", - type, bytes); + type, iecPrefix(lengths[i], "B").c_str()); } } } @@ -118,7 +116,7 @@ void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) client.setClipboardCaps(flags, lengths); } -void SMsgHandler::handleClipboardRequest(rdr::U32 /*flags*/) +void SMsgHandler::handleClipboardRequest(uint32_t /*flags*/) { } @@ -126,13 +124,13 @@ void SMsgHandler::handleClipboardPeek() { } -void SMsgHandler::handleClipboardNotify(rdr::U32 /*flags*/) +void SMsgHandler::handleClipboardNotify(uint32_t /*flags*/) { } -void SMsgHandler::handleClipboardProvide(rdr::U32 /*flags*/, +void SMsgHandler::handleClipboardProvide(uint32_t /*flags*/, const size_t* /*lengths*/, - const rdr::U8* const* /*data*/) + const uint8_t* const* /*data*/) { } diff --git a/common/rfb/SMsgHandler.h b/common/rfb/SMsgHandler.h index 274a1c3c..ec8040d2 100644 --- a/common/rfb/SMsgHandler.h +++ b/common/rfb/SMsgHandler.h @@ -23,7 +23,8 @@ #ifndef __RFB_SMSGHANDLER_H__ #define __RFB_SMSGHANDLER_H__ -#include <rdr/types.h> +#include <stdint.h> + #include <rfb/PixelFormat.h> #include <rfb/ClientParams.h> #include <rfb/InputHandler.h> @@ -46,22 +47,22 @@ namespace rfb { virtual void clientInit(bool shared); virtual void setPixelFormat(const PixelFormat& pf); - virtual void setEncodings(int nEncodings, const rdr::S32* encodings); + virtual void setEncodings(int nEncodings, const int32_t* encodings); virtual void framebufferUpdateRequest(const Rect& r, bool incremental) = 0; virtual void setDesktopSize(int fb_width, int fb_height, const ScreenSet& layout) = 0; - virtual void fence(rdr::U32 flags, unsigned len, const char data[]) = 0; + virtual void fence(uint32_t flags, unsigned len, const char data[]) = 0; virtual void enableContinuousUpdates(bool enable, int x, int y, int w, int h) = 0; - virtual void handleClipboardCaps(rdr::U32 flags, - const rdr::U32* lengths); - virtual void handleClipboardRequest(rdr::U32 flags); + virtual void handleClipboardCaps(uint32_t flags, + const uint32_t* lengths); + virtual void handleClipboardRequest(uint32_t flags); virtual void handleClipboardPeek(); - virtual void handleClipboardNotify(rdr::U32 flags); - virtual void handleClipboardProvide(rdr::U32 flags, + virtual void handleClipboardNotify(uint32_t flags); + virtual void handleClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data); + const uint8_t* const* data); // InputHandler interface // The InputHandler methods will be called for the corresponding messages. diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx index e7c78c4e..8cd8d147 100644 --- a/common/rfb/SMsgReader.cxx +++ b/common/rfb/SMsgReader.cxx @@ -23,6 +23,8 @@ #include <stdio.h> +#include <vector> + #include <rdr/InStream.h> #include <rdr/ZlibInStream.h> @@ -30,11 +32,11 @@ #include <rfb/qemuTypes.h> #include <rfb/clipboardTypes.h> #include <rfb/Exception.h> -#include <rfb/util.h> #include <rfb/SMsgHandler.h> #include <rfb/SMsgReader.h> #include <rfb/Configuration.h> #include <rfb/LogWriter.h> +#include <rfb/util.h> using namespace rfb; @@ -140,11 +142,11 @@ bool SMsgReader::readSetEncodings() return false; is->clearRestorePoint(); - rdr::S32Array encodings(nEncodings); - for (int i = 0; i < nEncodings; i++) - encodings.buf[i] = is->readU32(); + std::vector<int32_t> encodings(nEncodings); + for (size_t i = 0; i < encodings.size(); i++) + encodings[i] = is->readU32(); - handler->setEncodings(nEncodings, encodings.buf); + handler->setEncodings(nEncodings, encodings.data()); return true; } @@ -153,7 +155,7 @@ bool SMsgReader::readSetDesktopSize() { int width, height; int screens, i; - rdr::U32 id, flags; + uint32_t id, flags; int sx, sy, sw, sh; ScreenSet layout; @@ -225,8 +227,8 @@ bool SMsgReader::readEnableContinuousUpdates() bool SMsgReader::readFence() { - rdr::U32 flags; - rdr::U8 len; + uint32_t flags; + uint8_t len; char data[64]; if (!is->hasData(3 + 4 + 1)) @@ -263,7 +265,7 @@ bool SMsgReader::readKeyEvent() return false; bool down = is->readU8(); is->skip(2); - rdr::U32 key = is->readU32(); + uint32_t key = is->readU32(); handler->keyEvent(key, 0, down); return true; } @@ -288,10 +290,10 @@ bool SMsgReader::readClientCutText() is->setRestorePoint(); is->skip(3); - rdr::U32 len = is->readU32(); + uint32_t len = is->readU32(); if (len & 0x80000000) { - rdr::S32 slen = len; + int32_t slen = len; slen = -slen; if (readExtendedClipboard(slen)) { is->clearRestorePoint(); @@ -312,18 +314,18 @@ bool SMsgReader::readClientCutText() return true; } - CharArray ca(len); - is->readBytes(ca.buf, len); - CharArray filtered(convertLF(ca.buf, len)); - handler->clientCutText(filtered.buf); + std::vector<char> ca(len); + is->readBytes(ca.data(), len); + std::string filtered(convertLF(ca.data(), len)); + handler->clientCutText(filtered.c_str()); return true; } -bool SMsgReader::readExtendedClipboard(rdr::S32 len) +bool SMsgReader::readExtendedClipboard(int32_t len) { - rdr::U32 flags; - rdr::U32 action; + uint32_t flags; + uint32_t action; if (!is->hasData(len)) return false; @@ -342,7 +344,7 @@ bool SMsgReader::readExtendedClipboard(rdr::S32 len) if (action & clipboardCaps) { int i; size_t num; - rdr::U32 lengths[16]; + uint32_t lengths[16]; num = 0; for (i = 0;i < 16;i++) { @@ -350,7 +352,7 @@ bool SMsgReader::readExtendedClipboard(rdr::S32 len) num++; } - if (len < (rdr::S32)(4 + 4*num)) + if (len < (int32_t)(4 + 4*num)) throw Exception("Invalid extended clipboard message"); num = 0; @@ -366,7 +368,7 @@ bool SMsgReader::readExtendedClipboard(rdr::S32 len) int i; size_t num; size_t lengths[16]; - rdr::U8* buffers[16]; + uint8_t* buffers[16]; zis.setUnderlying(is, len - 4); @@ -407,7 +409,7 @@ bool SMsgReader::readExtendedClipboard(rdr::S32 len) if (!zis.hasData(lengths[num])) throw Exception("Extended clipboard decode error"); - buffers[num] = new rdr::U8[lengths[num]]; + buffers[num] = new uint8_t[lengths[num]]; zis.readBytes(buffers[num], lengths[num]); num++; } @@ -476,8 +478,8 @@ bool SMsgReader::readQEMUKeyEvent() if (!is->hasData(2 + 4 + 4)) return false; bool down = is->readU16(); - rdr::U32 keysym = is->readU32(); - rdr::U32 keycode = is->readU32(); + uint32_t keysym = is->readU32(); + uint32_t keycode = is->readU32(); if (!keycode) { vlog.error("Key event without keycode - ignoring"); return true; diff --git a/common/rfb/SMsgReader.h b/common/rfb/SMsgReader.h index acc872ed..f99b6627 100644 --- a/common/rfb/SMsgReader.h +++ b/common/rfb/SMsgReader.h @@ -54,7 +54,7 @@ namespace rfb { bool readKeyEvent(); bool readPointerEvent(); bool readClientCutText(); - bool readExtendedClipboard(rdr::S32 len); + bool readExtendedClipboard(int32_t len); bool readQEMUMessage(); bool readQEMUKeyEvent(); @@ -70,7 +70,7 @@ namespace rfb { stateEnum state; - rdr::U8 currentMsgType; + uint8_t currentMsgType; }; } #endif diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx index c8b50b67..1172ac4d 100644 --- a/common/rfb/SMsgWriter.cxx +++ b/common/rfb/SMsgWriter.cxx @@ -56,7 +56,7 @@ SMsgWriter::~SMsgWriter() { } -void SMsgWriter::writeServerInit(rdr::U16 width, rdr::U16 height, +void SMsgWriter::writeServerInit(uint16_t width, uint16_t height, const PixelFormat& pf, const char* name) { os->writeU16(width); @@ -68,9 +68,9 @@ void SMsgWriter::writeServerInit(rdr::U16 width, rdr::U16 height, } void SMsgWriter::writeSetColourMapEntries(int firstColour, int nColours, - const rdr::U16 red[], - const rdr::U16 green[], - const rdr::U16 blue[]) + const uint16_t red[], + const uint16_t green[], + const uint16_t blue[]) { startMsg(msgTypeSetColourMapEntries); os->pad(1); @@ -105,8 +105,8 @@ void SMsgWriter::writeServerCutText(const char* str) endMsg(); } -void SMsgWriter::writeClipboardCaps(rdr::U32 caps, - const rdr::U32* lengths) +void SMsgWriter::writeClipboardCaps(uint32_t caps, + const uint32_t* lengths) { size_t i, count; @@ -134,7 +134,7 @@ void SMsgWriter::writeClipboardCaps(rdr::U32 caps, endMsg(); } -void SMsgWriter::writeClipboardRequest(rdr::U32 flags) +void SMsgWriter::writeClipboardRequest(uint32_t flags) { if (!client->supportsEncoding(pseudoEncodingExtendedClipboard)) throw Exception("Client does not support extended clipboard"); @@ -148,7 +148,7 @@ void SMsgWriter::writeClipboardRequest(rdr::U32 flags) endMsg(); } -void SMsgWriter::writeClipboardPeek(rdr::U32 flags) +void SMsgWriter::writeClipboardPeek(uint32_t flags) { if (!client->supportsEncoding(pseudoEncodingExtendedClipboard)) throw Exception("Client does not support extended clipboard"); @@ -162,7 +162,7 @@ void SMsgWriter::writeClipboardPeek(rdr::U32 flags) endMsg(); } -void SMsgWriter::writeClipboardNotify(rdr::U32 flags) +void SMsgWriter::writeClipboardNotify(uint32_t flags) { if (!client->supportsEncoding(pseudoEncodingExtendedClipboard)) throw Exception("Client does not support extended clipboard"); @@ -176,9 +176,9 @@ void SMsgWriter::writeClipboardNotify(rdr::U32 flags) endMsg(); } -void SMsgWriter::writeClipboardProvide(rdr::U32 flags, +void SMsgWriter::writeClipboardProvide(uint32_t flags, const size_t* lengths, - const rdr::U8* const* data) + const uint8_t* const* data) { rdr::MemOutStream mos; rdr::ZlibOutStream zos; @@ -211,7 +211,7 @@ void SMsgWriter::writeClipboardProvide(rdr::U32 flags, endMsg(); } -void SMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[]) +void SMsgWriter::writeFence(uint32_t flags, unsigned len, const char data[]) { if (!client->supportsEncoding(pseudoEncodingFence)) throw Exception("Client does not support fences"); @@ -242,7 +242,7 @@ void SMsgWriter::writeEndOfContinuousUpdates() endMsg(); } -void SMsgWriter::writeDesktopSize(rdr::U16 reason, rdr::U16 result) +void SMsgWriter::writeDesktopSize(uint16_t reason, uint16_t result) { ExtendedDesktopSizeMsg msg; @@ -442,14 +442,16 @@ void SMsgWriter::writePseudoRects() cursor.hotspot().x, cursor.hotspot().y, cursor.getBuffer()); } else if (client->supportsEncoding(pseudoEncodingCursor)) { - rdr::U8Array data(cursor.width()*cursor.height() * (client->pf().bpp/8)); - rdr::U8Array mask(cursor.getMask()); + size_t data_len = cursor.width()*cursor.height() * + (client->pf().bpp/8); + std::vector<uint8_t> data(data_len); + std::vector<uint8_t> mask(cursor.getMask()); - const rdr::U8* in; - rdr::U8* out; + const uint8_t* in; + uint8_t* out; in = cursor.getBuffer(); - out = data.buf; + out = data.data(); for (int i = 0;i < cursor.width()*cursor.height();i++) { client->pf().bufferFromRGB(out, in, 1); in += 4; @@ -458,14 +460,14 @@ void SMsgWriter::writePseudoRects() writeSetCursorRect(cursor.width(), cursor.height(), cursor.hotspot().x, cursor.hotspot().y, - data.buf, mask.buf); + data.data(), mask.data()); } else if (client->supportsEncoding(pseudoEncodingXCursor)) { - rdr::U8Array bitmap(cursor.getBitmap()); - rdr::U8Array mask(cursor.getMask()); + std::vector<uint8_t> bitmap(cursor.getBitmap()); + std::vector<uint8_t> mask(cursor.getMask()); writeSetXCursorRect(cursor.width(), cursor.height(), cursor.hotspot().x, cursor.hotspot().y, - bitmap.buf, mask.buf); + bitmap.data(), mask.data()); } else { throw Exception("Client does not support local cursor"); } @@ -538,8 +540,8 @@ void SMsgWriter::writeSetDesktopSizeRect(int width, int height) os->writeU32(pseudoEncodingDesktopSize); } -void SMsgWriter::writeExtendedDesktopSizeRect(rdr::U16 reason, - rdr::U16 result, +void SMsgWriter::writeExtendedDesktopSizeRect(uint16_t reason, + uint16_t result, int fb_width, int fb_height, const ScreenSet& layout) @@ -632,7 +634,7 @@ void SMsgWriter::writeSetXCursorRect(int width, int height, void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height, int hotspotX, int hotspotY, - const rdr::U8* data) + const uint8_t* data) { if (!client->supportsEncoding(pseudoEncodingCursorWithAlpha)) throw Exception("Client does not support local cursors"); @@ -660,7 +662,7 @@ void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height, void SMsgWriter::writeSetVMwareCursorRect(int width, int height, int hotspotX, int hotspotY, - const rdr::U8* data) + const uint8_t* data) { if (!client->supportsEncoding(pseudoEncodingVMwareCursor)) throw Exception("Client does not support local cursors"); @@ -694,7 +696,7 @@ void SMsgWriter::writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY) os->writeU32(pseudoEncodingVMwareCursorPosition); } -void SMsgWriter::writeLEDStateRect(rdr::U8 state) +void SMsgWriter::writeLEDStateRect(uint8_t state) { if (!client->supportsEncoding(pseudoEncodingLEDState) && !client->supportsEncoding(pseudoEncodingVMwareLEDState)) diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h index 49381bad..07f7cf23 100644 --- a/common/rfb/SMsgWriter.h +++ b/common/rfb/SMsgWriter.h @@ -23,7 +23,8 @@ #ifndef __RFB_SMSGWRITER_H__ #define __RFB_SMSGWRITER_H__ -#include <rdr/types.h> +#include <stdint.h> + #include <rfb/encodings.h> #include <rfb/ScreenSet.h> @@ -42,7 +43,7 @@ namespace rfb { // writeServerInit() must only be called at the appropriate time in the // protocol initialisation. - void writeServerInit(rdr::U16 width, rdr::U16 height, + void writeServerInit(uint16_t width, uint16_t height, const PixelFormat& pf, const char* name); // Methods to write normal protocol messages @@ -50,24 +51,24 @@ namespace rfb { // writeSetColourMapEntries() writes a setColourMapEntries message, using // the given colour entries. void writeSetColourMapEntries(int firstColour, int nColours, - const rdr::U16 red[], - const rdr::U16 green[], - const rdr::U16 blue[]); + const uint16_t red[], + const uint16_t green[], + const uint16_t blue[]); // writeBell() does the obvious thing. void writeBell(); void writeServerCutText(const char* str); - void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths); - void writeClipboardRequest(rdr::U32 flags); - void writeClipboardPeek(rdr::U32 flags); - void writeClipboardNotify(rdr::U32 flags); - void writeClipboardProvide(rdr::U32 flags, const size_t* lengths, - const rdr::U8* const* data); + void writeClipboardCaps(uint32_t caps, const uint32_t* lengths); + void writeClipboardRequest(uint32_t flags); + void writeClipboardPeek(uint32_t flags); + void writeClipboardNotify(uint32_t flags); + void writeClipboardProvide(uint32_t flags, const size_t* lengths, + const uint8_t* const* data); // writeFence() sends a new fence request or response to the client. - void writeFence(rdr::U32 flags, unsigned len, const char data[]); + void writeFence(uint32_t flags, unsigned len, const char data[]); // writeEndOfContinuousUpdates() indicates that we have left continuous // updates mode. @@ -75,7 +76,7 @@ namespace rfb { // writeDesktopSize() won't actually write immediately, but will // write the relevant pseudo-rectangle as part of the next update. - void writeDesktopSize(rdr::U16 reason, rdr::U16 result=0); + void writeDesktopSize(uint16_t reason, uint16_t result=0); void writeSetDesktopName(); @@ -128,7 +129,7 @@ namespace rfb { void writeNoDataRects(); void writeSetDesktopSizeRect(int width, int height); - void writeExtendedDesktopSizeRect(rdr::U16 reason, rdr::U16 result, + void writeExtendedDesktopSizeRect(uint16_t reason, uint16_t result, int fb_width, int fb_height, const ScreenSet& layout); void writeSetDesktopNameRect(const char *name); @@ -140,12 +141,12 @@ namespace rfb { const void* data, const void* mask); void writeSetCursorWithAlphaRect(int width, int height, int hotspotX, int hotspotY, - const rdr::U8* data); + const uint8_t* data); void writeSetVMwareCursorRect(int width, int height, int hotspotX, int hotspotY, - const rdr::U8* data); + const uint8_t* data); void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY); - void writeLEDStateRect(rdr::U8 state); + void writeLEDStateRect(uint8_t state); void writeQEMUKeyEventRect(); ClientParams* client; @@ -161,7 +162,7 @@ namespace rfb { bool needQEMUKeyEvent; typedef struct { - rdr::U16 reason, result; + uint16_t reason, result; } ExtendedDesktopSizeMsg; std::list<ExtendedDesktopSizeMsg> extendedDesktopSizeMsgs; diff --git a/common/rfb/SSecurity.h b/common/rfb/SSecurity.h index cef2027f..fbc3de6f 100644 --- a/common/rfb/SSecurity.h +++ b/common/rfb/SSecurity.h @@ -43,9 +43,8 @@ #ifndef __RFB_SSECURITY_H__ #define __RFB_SSECURITY_H__ -#include <rdr/types.h> #include <rfb/SConnection.h> -#include <rfb/util.h> + #include <list> namespace rfb { diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx index 6f65e87a..e65b6d3b 100644 --- a/common/rfb/SSecurityPlain.cxx +++ b/common/rfb/SSecurityPlain.cxx @@ -24,6 +24,7 @@ #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> @@ -45,21 +46,15 @@ StringParameter PasswordValidator::plainUsers bool PasswordValidator::validUser(const char* username) { - CharArray users(plainUsers.getValueStr()), user; + std::vector<std::string> users; - while (users.buf) { - strSplit(users.buf, ',', &user.buf, &users.buf); -#ifdef WIN32 - if (0 == stricmp(user.buf, "*")) - return true; - if (0 == stricmp(user.buf, username)) - return true; -#else - if (!strcmp(user.buf, "*")) - return true; - if (!strcmp(user.buf, username)) - return true; -#endif + users = split(plainUsers, ','); + + for (size_t i = 0; i < users.size(); i++) { + if (users[i] == "*") + return true; + if (users[i] == username) + return true; } return false; } @@ -80,9 +75,7 @@ SSecurityPlain::SSecurityPlain(SConnection* sc) : SSecurity(sc) bool SSecurityPlain::processMsg() { rdr::InStream* is = sc->getInStream(); - char* pw; - char *uname; - CharArray password; + char password[1024]; if (!valid) throw AuthFailureException("No password validator configured"); @@ -92,11 +85,11 @@ bool SSecurityPlain::processMsg() return false; ulen = is->readU32(); - if (ulen > MaxSaneUsernameLength) + if (ulen >= sizeof(username)) throw AuthFailureException("Too long username"); plen = is->readU32(); - if (plen > MaxSanePasswordLength) + if (plen >= sizeof(password)) throw AuthFailureException("Too long password"); state = 1; @@ -106,16 +99,12 @@ bool SSecurityPlain::processMsg() if (!is->hasData(ulen + plen)) return false; state = 2; - pw = new char[plen + 1]; - uname = new char[ulen + 1]; - username.replaceBuf(uname); - password.replaceBuf(pw); - is->readBytes(uname, ulen); - is->readBytes(pw, plen); - pw[plen] = 0; - uname[ulen] = 0; + is->readBytes(username, ulen); + is->readBytes(password, plen); + password[plen] = 0; + username[ulen] = 0; plen = 0; - if (!valid->validate(sc, uname, pw)) + if (!valid->validate(sc, username, password)) throw AuthFailureException("invalid password or username"); } diff --git a/common/rfb/SSecurityPlain.h b/common/rfb/SSecurityPlain.h index 1a81adda..4ca72781 100644 --- a/common/rfb/SSecurityPlain.h +++ b/common/rfb/SSecurityPlain.h @@ -23,7 +23,6 @@ #include <rfb/SConnection.h> #include <rfb/SSecurity.h> #include <rfb/SSecurityVeNCrypt.h> -#include <rfb/util.h> #include <rfb/Configuration.h> namespace rfb { @@ -46,17 +45,14 @@ namespace rfb { SSecurityPlain(SConnection* sc); virtual bool processMsg(); virtual int getType() const { return secTypePlain; }; - virtual const char* getUserName() const { return username.buf; } + virtual const char* getUserName() const { return username; } virtual ~SSecurityPlain() { } private: PasswordValidator* valid; unsigned int ulen, plen, state; - CharArray username; - - static const unsigned int MaxSaneUsernameLength = 1024; - static const unsigned int MaxSanePasswordLength = 1024; + char username[1024]; }; } diff --git a/common/rfb/SSecurityRSAAES.cxx b/common/rfb/SSecurityRSAAES.cxx index 3211f12f..042e4838 100644 --- a/common/rfb/SSecurityRSAAES.cxx +++ b/common/rfb/SSecurityRSAAES.cxx @@ -28,6 +28,8 @@ #include <stdlib.h> #include <assert.h> +#include <vector> + #include <nettle/bignum.h> #include <nettle/sha1.h> #include <nettle/sha2.h> @@ -68,7 +70,7 @@ BoolParameter SSecurityRSAAES::requireUsername ("RequireUsername", "Require username for the RSA-AES security types", false, ConfServer); -SSecurityRSAAES::SSecurityRSAAES(SConnection* sc, rdr::U32 _secType, +SSecurityRSAAES::SSecurityRSAAES(SConnection* sc, uint32_t _secType, int _keySize, bool _isAllEncrypted) : SSecurity(sc), state(SendPublicKey), keySize(_keySize), isAllEncrypted(_isAllEncrypted), secType(_secType), @@ -107,7 +109,7 @@ void SSecurityRSAAES::cleanup() delete raos; } -static inline ssize_t findSubstr(rdr::U8* data, size_t size, const char *pattern) +static inline ssize_t findSubstr(uint8_t* data, size_t size, const char *pattern) { size_t patternLength = strlen(pattern); for (size_t i = 0; i + patternLength < size; ++i) { @@ -121,8 +123,8 @@ next: return -1; } -static bool loadPEM(rdr::U8* data, size_t size, const char *begin, - const char *end, rdr::U8** der, size_t *derSize) +static bool loadPEM(uint8_t* data, size_t size, const char *begin, + const char *end, std::vector<uint8_t> *der) { ssize_t pos1 = findSubstr(data, size, begin); if (pos1 == -1) @@ -134,19 +136,23 @@ static bool loadPEM(rdr::U8* data, size_t size, const char *begin, char *derBase64 = (char *)data + pos1; if (!base64Size) return false; - *der = new rdr::U8[BASE64_DECODE_LENGTH(base64Size)]; + der->resize(BASE64_DECODE_LENGTH(base64Size)); struct base64_decode_ctx ctx; + size_t derSize; base64_decode_init(&ctx); - if (!base64_decode_update(&ctx, derSize, *der, base64Size, derBase64)) + if (!base64_decode_update(&ctx, &derSize, der->data(), + base64Size, derBase64)) return false; if (!base64_decode_final(&ctx)) return false; + assert(derSize <= der->size()); + der->resize(derSize); return true; } void SSecurityRSAAES::loadPrivateKey() { - FILE* file = fopen(keyFile.getData(), "rb"); + FILE* file = fopen(keyFile, "rb"); if (!file) throw ConnFailedException("failed to open key file"); fseek(file, 0, SEEK_END); @@ -156,31 +162,30 @@ void SSecurityRSAAES::loadPrivateKey() throw ConnFailedException("size of key file is zero or too big"); } fseek(file, 0, SEEK_SET); - rdr::U8Array data(size); - if (fread(data.buf, 1, size, file) != size) { + std::vector<uint8_t> data(size); + if (fread(data.data(), 1, data.size(), file) != size) { fclose(file); throw ConnFailedException("failed to read key"); } fclose(file); - rdr::U8Array der; - size_t derSize; - if (loadPEM(data.buf, size, "-----BEGIN RSA PRIVATE KEY-----\n", - "-----END RSA PRIVATE KEY-----", &der.buf, &derSize)) { - loadPKCS1Key(der.buf, derSize); + std::vector<uint8_t> der; + if (loadPEM(data.data(), data.size(), + "-----BEGIN RSA PRIVATE KEY-----\n", + "-----END RSA PRIVATE KEY-----", &der)) { + loadPKCS1Key(der.data(), der.size()); return; } - if (der.buf) - delete[] der.takeBuf(); - if (loadPEM(data.buf, size, "-----BEGIN PRIVATE KEY-----\n", - "-----END PRIVATE KEY-----", &der.buf, &derSize)) { - loadPKCS8Key(der.buf, derSize); + if (loadPEM(data.data(), data.size(), + "-----BEGIN PRIVATE KEY-----\n", + "-----END PRIVATE KEY-----", &der)) { + loadPKCS8Key(der.data(), der.size()); return; } throw ConnFailedException("failed to import key"); } -void SSecurityRSAAES::loadPKCS1Key(const rdr::U8* data, size_t size) +void SSecurityRSAAES::loadPKCS1Key(const uint8_t* data, size_t size) { struct rsa_public_key pub; rsa_private_key_init(&serverKey); @@ -191,14 +196,14 @@ void SSecurityRSAAES::loadPKCS1Key(const rdr::U8* data, size_t size) throw ConnFailedException("failed to import key"); } serverKeyLength = serverKey.size * 8; - serverKeyN = new rdr::U8[serverKey.size]; - serverKeyE = new rdr::U8[serverKey.size]; + serverKeyN = new uint8_t[serverKey.size]; + serverKeyE = new uint8_t[serverKey.size]; nettle_mpz_get_str_256(serverKey.size, serverKeyN, pub.n); nettle_mpz_get_str_256(serverKey.size, serverKeyE, pub.e); rsa_public_key_clear(&pub); } -void SSecurityRSAAES::loadPKCS8Key(const rdr::U8* data, size_t size) +void SSecurityRSAAES::loadPKCS8Key(const uint8_t* data, size_t size) { struct asn1_der_iterator i, j; uint32_t version; @@ -296,8 +301,8 @@ bool SSecurityRSAAES::readPublicKey() if (!is->hasDataOrRestore(size * 2)) return false; is->clearRestorePoint(); - clientKeyE = new rdr::U8[size]; - clientKeyN = new rdr::U8[size]; + clientKeyE = new uint8_t[size]; + clientKeyN = new uint8_t[size]; is->readBytes(clientKeyN, size); is->readBytes(clientKeyE, size); rsa_public_key_init(&clientKey); @@ -336,7 +341,7 @@ void SSecurityRSAAES::writeRandom() mpz_clear(x); throw ConnFailedException("failed to encrypt random"); } - rdr::U8* buffer = new rdr::U8[clientKey.size]; + uint8_t* buffer = new uint8_t[clientKey.size]; nettle_mpz_get_str_256(clientKey.size, buffer, x); mpz_clear(x); os->writeU16(clientKey.size); @@ -357,7 +362,7 @@ bool SSecurityRSAAES::readRandom() if (!is->hasDataOrRestore(size)) return false; is->clearRestorePoint(); - rdr::U8* buffer = new rdr::U8[size]; + uint8_t* buffer = new uint8_t[size]; is->readBytes(buffer, size); size_t randomSize = keySize / 8; mpz_t x; @@ -376,7 +381,7 @@ void SSecurityRSAAES::setCipher() { rawis = sc->getInStream(); rawos = sc->getOutStream(); - rdr::U8 key[32]; + uint8_t key[32]; if (keySize == 128) { struct sha1_ctx ctx; sha1_init(&ctx); @@ -408,20 +413,20 @@ void SSecurityRSAAES::setCipher() void SSecurityRSAAES::writeHash() { - rdr::U8 hash[32]; + uint8_t hash[32]; size_t len = serverKeyLength; - rdr::U8 lenServerKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenServerKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; len = clientKeyLength; - rdr::U8 lenClientKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenClientKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; int hashSize; if (keySize == 128) { @@ -453,25 +458,25 @@ void SSecurityRSAAES::writeHash() bool SSecurityRSAAES::readHash() { - rdr::U8 hash[32]; - rdr::U8 realHash[32]; + uint8_t hash[32]; + uint8_t realHash[32]; int hashSize = keySize == 128 ? 20 : 32; if (!rais->hasData(hashSize)) return false; rais->readBytes(hash, hashSize); size_t len = serverKeyLength; - rdr::U8 lenServerKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenServerKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; len = clientKeyLength; - rdr::U8 lenClientKey[4] = { - (rdr::U8)((len & 0xff000000) >> 24), - (rdr::U8)((len & 0xff0000) >> 16), - (rdr::U8)((len & 0xff00) >> 8), - (rdr::U8)(len & 0xff) + uint8_t lenClientKey[4] = { + (uint8_t)((len & 0xff000000) >> 24), + (uint8_t)((len & 0xff0000) >> 16), + (uint8_t)((len & 0xff00) >> 8), + (uint8_t)(len & 0xff) }; if (keySize == 128) { struct sha1_ctx ctx; @@ -531,22 +536,16 @@ bool SSecurityRSAAES::readCredentials() rais->setRestorePoint(); if (!rais->hasData(1)) return false; - rdr::U8 lenUsername = rais->readU8(); + uint8_t lenUsername = rais->readU8(); if (!rais->hasDataOrRestore(lenUsername + 1)) return false; - if (!username.buf) { - username.replaceBuf(new char[lenUsername + 1]); - rais->readBytes(username.buf, lenUsername); - username.buf[lenUsername] = 0; - } else { - rais->skip(lenUsername); - } - rdr::U8 lenPassword = rais->readU8(); + rais->readBytes(username, lenUsername); + username[lenUsername] = 0; + uint8_t lenPassword = rais->readU8(); if (!rais->hasDataOrRestore(lenPassword)) return false; - password.replaceBuf(new char[lenPassword + 1]); - rais->readBytes(password.buf, lenPassword); - password.buf[lenPassword] = 0; + rais->readBytes(password, lenPassword); + password[lenPassword] = 0; rais->clearRestorePoint(); return true; } @@ -559,7 +558,7 @@ void SSecurityRSAAES::verifyUserPass() #elif !defined(__APPLE__) UnixPasswordValidator *valid = new UnixPasswordValidator(); #endif - if (!valid->validate(sc, username.buf, password.buf)) { + if (!valid->validate(sc, username, password)) { delete valid; throw AuthFailureException("invalid password or username"); } @@ -572,18 +571,18 @@ void SSecurityRSAAES::verifyUserPass() void SSecurityRSAAES::verifyPass() { VncAuthPasswdGetter* pg = &SSecurityVncAuth::vncAuthPasswd; - PlainPasswd passwd, passwdReadOnly; + std::string passwd, passwdReadOnly; pg->getVncAuthPasswd(&passwd, &passwdReadOnly); - if (!passwd.buf) + if (passwd.empty()) throw AuthFailureException("No password configured for VNC Auth"); - if (strcmp(password.buf, passwd.buf) == 0) { + if (password == passwd) { accessRights = SConnection::AccessDefault; return; } - if (passwdReadOnly.buf && strcmp(password.buf, passwdReadOnly.buf) == 0) { + if (!passwdReadOnly.empty() && password == passwdReadOnly) { accessRights = SConnection::AccessView; return; } @@ -593,5 +592,5 @@ void SSecurityRSAAES::verifyPass() const char* SSecurityRSAAES::getUserName() const { - return username.buf; + return username; } diff --git a/common/rfb/SSecurityRSAAES.h b/common/rfb/SSecurityRSAAES.h index 17e0d407..eaeb13a1 100644 --- a/common/rfb/SSecurityRSAAES.h +++ b/common/rfb/SSecurityRSAAES.h @@ -33,7 +33,7 @@ namespace rfb { class SSecurityRSAAES : public SSecurity { public: - SSecurityRSAAES(SConnection* sc, rdr::U32 secType, + SSecurityRSAAES(SConnection* sc, uint32_t secType, int keySize, bool isAllEncrypted); virtual ~SSecurityRSAAES(); virtual bool processMsg(); @@ -50,8 +50,8 @@ namespace rfb { private: void cleanup(); void loadPrivateKey(); - void loadPKCS1Key(const rdr::U8* data, size_t size); - void loadPKCS8Key(const rdr::U8* data, size_t size); + void loadPKCS1Key(const uint8_t* data, size_t size); + void loadPKCS8Key(const uint8_t* data, size_t size); void writePublicKey(); bool readPublicKey(); void writeRandom(); @@ -68,20 +68,20 @@ namespace rfb { int state; int keySize; bool isAllEncrypted; - rdr::U32 secType; + uint32_t secType; struct rsa_private_key serverKey; struct rsa_public_key clientKey; - rdr::U32 serverKeyLength; - rdr::U8* serverKeyN; - rdr::U8* serverKeyE; - rdr::U32 clientKeyLength; - rdr::U8* clientKeyN; - rdr::U8* clientKeyE; - rdr::U8 serverRandom[32]; - rdr::U8 clientRandom[32]; + uint32_t serverKeyLength; + uint8_t* serverKeyN; + uint8_t* serverKeyE; + uint32_t clientKeyLength; + uint8_t* clientKeyN; + uint8_t* clientKeyE; + uint8_t serverRandom[32]; + uint8_t clientRandom[32]; - CharArray username; - CharArray password; + char username[256]; + char password[256]; SConnection::AccessRights accessRights; rdr::InStream* rais; diff --git a/common/rfb/SSecurityTLS.cxx b/common/rfb/SSecurityTLS.cxx index f3d58ae0..1abfd774 100644 --- a/common/rfb/SSecurityTLS.cxx +++ b/common/rfb/SSecurityTLS.cxx @@ -75,9 +75,6 @@ SSecurityTLS::SSecurityTLS(SConnection* sc, bool _anon) dh_params = NULL; #endif - certfile = X509_CertFile.getData(); - keyfile = X509_KeyFile.getData(); - if (gnutls_global_init() != GNUTLS_E_SUCCESS) throw AuthFailureException("gnutls_global_init failed"); } @@ -136,9 +133,6 @@ SSecurityTLS::~SSecurityTLS() { shutdown(); - delete[] keyfile; - delete[] certfile; - gnutls_global_deinit(); } @@ -293,7 +287,7 @@ void SSecurityTLS::setParams(gnutls_session_t session) gnutls_certificate_set_dh_params(cert_cred, dh_params); #endif - switch (gnutls_certificate_set_x509_key_file(cert_cred, certfile, keyfile, GNUTLS_X509_FMT_PEM)) { + switch (gnutls_certificate_set_x509_key_file(cert_cred, X509_CertFile, X509_KeyFile, GNUTLS_X509_FMT_PEM)) { case GNUTLS_E_SUCCESS: break; case GNUTLS_E_CERTIFICATE_KEY_MISMATCH: diff --git a/common/rfb/SSecurityTLS.h b/common/rfb/SSecurityTLS.h index 4e06d6ba..d0f735fe 100644 --- a/common/rfb/SSecurityTLS.h +++ b/common/rfb/SSecurityTLS.h @@ -63,7 +63,6 @@ namespace rfb { #endif gnutls_anon_server_credentials_t anon_cred; gnutls_certificate_credentials_t cert_cred; - char *keyfile, *certfile; bool anon; diff --git a/common/rfb/SSecurityVeNCrypt.cxx b/common/rfb/SSecurityVeNCrypt.cxx index 70d50d20..c126d82f 100644 --- a/common/rfb/SSecurityVeNCrypt.cxx +++ b/common/rfb/SSecurityVeNCrypt.cxx @@ -64,7 +64,7 @@ bool SSecurityVeNCrypt::processMsg() { rdr::InStream* is = sc->getInStream(); rdr::OutStream* os = sc->getOutStream(); - rdr::U8 i; + uint8_t i; /* VeNCrypt initialization */ @@ -93,7 +93,7 @@ bool SSecurityVeNCrypt::processMsg() haveRecvdMinorVersion = true; /* WORD value with major version in upper 8 bits and minor version in lower 8 bits */ - U16 Version = (((U16)majorVersion) << 8) | ((U16)minorVersion); + uint16_t Version = (((uint16_t)majorVersion) << 8) | ((uint16_t)minorVersion); switch (Version) { case 0x0000: /* 0.0 - The client cannot support us! */ @@ -115,16 +115,16 @@ bool SSecurityVeNCrypt::processMsg() } /* - * send number of supported VeNCrypt authentication types (U8) followed - * by authentication types (U32s) + * send number of supported VeNCrypt authentication types (uint8_t) + * followed by authentication types (uint32_t:s) */ if (!haveSentTypes) { - list<U32> listSubTypes; + list<uint32_t> listSubTypes; listSubTypes = security->GetEnabledExtSecTypes(); numTypes = listSubTypes.size(); - subTypes = new U32[numTypes]; + subTypes = new uint32_t[numTypes]; for (i = 0; i < numTypes; i++) { subTypes[i] = listSubTypes.front(); diff --git a/common/rfb/SSecurityVeNCrypt.h b/common/rfb/SSecurityVeNCrypt.h index afbf7247..86cf420a 100644 --- a/common/rfb/SSecurityVeNCrypt.h +++ b/common/rfb/SSecurityVeNCrypt.h @@ -44,8 +44,8 @@ namespace rfb { SecurityServer *security; bool haveSentVersion, haveRecvdMajorVersion, haveRecvdMinorVersion; bool haveSentTypes, haveChosenType; - rdr::U8 majorVersion, minorVersion, numTypes; - rdr::U32 *subTypes, chosenType; + uint8_t majorVersion, minorVersion, numTypes; + uint32_t *subTypes, chosenType; }; } #endif diff --git a/common/rfb/SSecurityVncAuth.cxx b/common/rfb/SSecurityVncAuth.cxx index a19404d3..cbd0ccd2 100644 --- a/common/rfb/SSecurityVncAuth.cxx +++ b/common/rfb/SSecurityVncAuth.cxx @@ -28,11 +28,11 @@ #include <rfb/SSecurityVncAuth.h> #include <rdr/RandomStream.h> #include <rfb/SConnection.h> -#include <rfb/Password.h> #include <rfb/Configuration.h> #include <rfb/LogWriter.h> -#include <rfb/util.h> #include <rfb/Exception.h> +#include <rfb/obfuscate.h> +#include <assert.h> #include <string.h> #include <stdio.h> extern "C" { @@ -58,15 +58,15 @@ SSecurityVncAuth::SSecurityVncAuth(SConnection* sc) { } -bool SSecurityVncAuth::verifyResponse(const PlainPasswd &password) +bool SSecurityVncAuth::verifyResponse(const char* password) { - rdr::U8 expectedResponse[vncAuthChallengeSize]; + uint8_t expectedResponse[vncAuthChallengeSize]; // Calculate the expected response - rdr::U8 key[8]; - int pwdLen = strlen(password.buf); + uint8_t key[8]; + int pwdLen = strlen(password); for (int i=0; i<8; i++) - key[i] = i<pwdLen ? password.buf[i] : 0; + key[i] = i<pwdLen ? password[i] : 0; deskey(key, EN0); for (int j = 0; j < vncAuthChallengeSize; j += 8) des(challenge+j, expectedResponse+j); @@ -96,18 +96,19 @@ bool SSecurityVncAuth::processMsg() is->readBytes(response, vncAuthChallengeSize); - PlainPasswd passwd, passwdReadOnly; + std::string passwd, passwdReadOnly; pg->getVncAuthPasswd(&passwd, &passwdReadOnly); - if (!passwd.buf) + if (passwd.empty()) throw AuthFailureException("No password configured for VNC Auth"); - if (verifyResponse(passwd)) { + if (verifyResponse(passwd.c_str())) { accessRights = SConnection::AccessDefault; return true; } - if (passwdReadOnly.buf && verifyResponse(passwdReadOnly)) { + if (!passwdReadOnly.empty() && + verifyResponse(passwdReadOnly.c_str())) { accessRights = SConnection::AccessView; return true; } @@ -121,40 +122,41 @@ VncAuthPasswdParameter::VncAuthPasswdParameter(const char* name, : BinaryParameter(name, desc, 0, 0, ConfServer), passwdFile(passwdFile_) { } -void VncAuthPasswdParameter::getVncAuthPasswd(PlainPasswd *password, PlainPasswd *readOnlyPassword) { - ObfuscatedPasswd obfuscated, obfuscatedReadOnly; - getData((void**)&obfuscated.buf, &obfuscated.length); +void VncAuthPasswdParameter::getVncAuthPasswd(std::string *password, std::string *readOnlyPassword) { + std::vector<uint8_t> obfuscated, obfuscatedReadOnly; + obfuscated = getData(); - if (obfuscated.length == 0) { + if (obfuscated.size() == 0) { if (passwdFile) { - CharArray fname(passwdFile->getData()); - if (!fname.buf[0]) { + const char *fname = *passwdFile; + if (!fname[0]) { vlog.info("neither %s nor %s params set", getName(), passwdFile->getName()); return; } - FILE* fp = fopen(fname.buf, "r"); + FILE* fp = fopen(fname, "r"); if (!fp) { - vlog.error("opening password file '%s' failed",fname.buf); + vlog.error("opening password file '%s' failed", fname); return; } vlog.debug("reading password file"); - obfuscated.buf = new char[8]; - obfuscated.length = fread(obfuscated.buf, 1, 8, fp); - obfuscatedReadOnly.buf = new char[8]; - obfuscatedReadOnly.length = fread(obfuscatedReadOnly.buf, 1, 8, fp); + obfuscated.resize(8); + obfuscated.resize(fread(obfuscated.data(), 1, 8, fp)); + obfuscatedReadOnly.resize(8); + obfuscatedReadOnly.resize(fread(obfuscatedReadOnly.data(), 1, 8, fp)); fclose(fp); } else { vlog.info("%s parameter not set", getName()); } } + assert(password != NULL); + assert(readOnlyPassword != NULL); + try { - PlainPasswd plainPassword(obfuscated); - password->replaceBuf(plainPassword.takeBuf()); - PlainPasswd plainPasswordReadOnly(obfuscatedReadOnly); - readOnlyPassword->replaceBuf(plainPasswordReadOnly.takeBuf()); + *password = deobfuscate(obfuscated.data(), obfuscated.size()); + *readOnlyPassword = deobfuscate(obfuscatedReadOnly.data(), obfuscatedReadOnly.size()); } catch (...) { } } diff --git a/common/rfb/SSecurityVncAuth.h b/common/rfb/SSecurityVncAuth.h index 94d5aaf2..2bd27791 100644 --- a/common/rfb/SSecurityVncAuth.h +++ b/common/rfb/SSecurityVncAuth.h @@ -24,11 +24,11 @@ #ifndef __RFB_SSECURITYVNCAUTH_H__ #define __RFB_SSECURITYVNCAUTH_H__ +#include <stdint.h> + #include <rfb/Configuration.h> -#include <rfb/Password.h> #include <rfb/SSecurity.h> #include <rfb/Security.h> -#include <rdr/types.h> namespace rfb { @@ -36,7 +36,7 @@ namespace rfb { public: // getVncAuthPasswd() fills buffer of given password and readOnlyPassword. // If there was no read only password in the file, readOnlyPassword buffer is null. - virtual void getVncAuthPasswd(PlainPasswd *password, PlainPasswd *readOnlyPassword)=0; + virtual void getVncAuthPasswd(std::string *password, std::string *readOnlyPassword)=0; virtual ~VncAuthPasswdGetter() { } }; @@ -44,7 +44,7 @@ namespace rfb { class VncAuthPasswdParameter : public VncAuthPasswdGetter, BinaryParameter { public: VncAuthPasswdParameter(const char* name, const char* desc, StringParameter* passwdFile_); - virtual void getVncAuthPasswd(PlainPasswd *password, PlainPasswd *readOnlyPassword); + virtual void getVncAuthPasswd(std::string *password, std::string *readOnlyPassword); protected: StringParameter* passwdFile; }; @@ -59,10 +59,10 @@ namespace rfb { static StringParameter vncAuthPasswdFile; static VncAuthPasswdParameter vncAuthPasswd; private: - bool verifyResponse(const PlainPasswd &password); + bool verifyResponse(const char* password); enum {vncAuthChallengeSize = 16}; - rdr::U8 challenge[vncAuthChallengeSize]; - rdr::U8 response[vncAuthChallengeSize]; + uint8_t challenge[vncAuthChallengeSize]; + uint8_t response[vncAuthChallengeSize]; bool sentChallenge; VncAuthPasswdGetter* pg; SConnection::AccessRights accessRights; diff --git a/common/rfb/ScreenSet.h b/common/rfb/ScreenSet.h index 9680b6e7..fb93e5c2 100644 --- a/common/rfb/ScreenSet.h +++ b/common/rfb/ScreenSet.h @@ -23,8 +23,8 @@ #include <stdio.h> #include <string.h> +#include <stdint.h> -#include <rdr/types.h> #include <rfb/Rect.h> #include <list> #include <set> @@ -38,22 +38,22 @@ namespace rfb { struct Screen { Screen(void) : id(0), flags(0) {}; - Screen(rdr::U32 id_, int x_, int y_, int w_, int h_, rdr::U32 flags_) : + Screen(uint32_t id_, int x_, int y_, int w_, int h_, uint32_t flags_) : id(id_), dimensions(x_, y_, x_+w_, y_+h_), flags(flags_) {}; inline bool operator==(const Screen& r) const { if (id != r.id) return false; - if (!dimensions.equals(r.dimensions)) + if (dimensions != r.dimensions) return false; if (flags != r.flags) return false; return true; } - rdr::U32 id; + uint32_t id; Rect dimensions; - rdr::U32 flags; + uint32_t flags; }; // rfb::ScreenSet @@ -75,7 +75,7 @@ namespace rfb { inline int num_screens(void) const { return screens.size(); }; inline void add_screen(const Screen screen) { screens.push_back(screen); }; - inline void remove_screen(rdr::U32 id) { + inline void remove_screen(uint32_t id) { std::list<Screen>::iterator iter, nextiter; for (iter = screens.begin();iter != screens.end();iter = nextiter) { nextiter = iter; nextiter++; @@ -86,7 +86,7 @@ namespace rfb { inline bool validate(int fb_width, int fb_height) const { std::list<Screen>::const_iterator iter; - std::set<rdr::U32> seen_ids; + std::set<uint32_t> seen_ids; Rect fb_rect; if (screens.empty()) diff --git a/common/rfb/Security.cxx b/common/rfb/Security.cxx index efed0cd0..caf6420f 100644 --- a/common/rfb/Security.cxx +++ b/common/rfb/Security.cxx @@ -61,18 +61,13 @@ Security::Security() Security::Security(StringParameter &secTypes) { - char *secTypesStr; - - secTypesStr = secTypes.getData(); - enabledSecTypes = parseSecTypes(secTypesStr); - - delete [] secTypesStr; + enabledSecTypes = parseSecTypes(secTypes); } -const std::list<rdr::U8> Security::GetEnabledSecTypes(void) +const std::list<uint8_t> Security::GetEnabledSecTypes(void) { - list<rdr::U8> result; - list<U32>::iterator i; + list<uint8_t> result; + list<uint32_t>::iterator i; /* Partial workaround for Vino's stupid behaviour. It doesn't allow * the basic authentication types as part of the VeNCrypt handshake, @@ -93,10 +88,10 @@ const std::list<rdr::U8> Security::GetEnabledSecTypes(void) return result; } -const std::list<rdr::U32> Security::GetEnabledExtSecTypes(void) +const std::list<uint32_t> Security::GetEnabledExtSecTypes(void) { - list<rdr::U32> result; - list<U32>::iterator i; + list<uint32_t> result; + list<uint32_t>::iterator i; for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++) if (*i != secTypeVeNCrypt) /* Do not include VeNCrypt type to avoid loops */ @@ -105,9 +100,9 @@ const std::list<rdr::U32> Security::GetEnabledExtSecTypes(void) return result; } -void Security::EnableSecType(U32 secType) +void Security::EnableSecType(uint32_t secType) { - list<U32>::iterator i; + list<uint32_t>::iterator i; for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++) if (*i == secType) @@ -116,9 +111,9 @@ void Security::EnableSecType(U32 secType) enabledSecTypes.push_back(secType); } -bool Security::IsSupported(U32 secType) +bool Security::IsSupported(uint32_t secType) { - list<U32>::iterator i; + list<uint32_t>::iterator i; for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++) if (*i == secType) @@ -131,7 +126,7 @@ bool Security::IsSupported(U32 secType) char *Security::ToString(void) { - list<U32>::iterator i; + list<uint32_t>::iterator i; static char out[128]; /* Should be enough */ bool firstpass = true; const char *name; @@ -153,7 +148,7 @@ char *Security::ToString(void) return out; } -rdr::U32 rfb::secTypeNum(const char* name) +uint32_t rfb::secTypeNum(const char* name) { if (strcasecmp(name, "None") == 0) return secTypeNone; if (strcasecmp(name, "VncAuth") == 0) return secTypeVncAuth; @@ -180,7 +175,7 @@ rdr::U32 rfb::secTypeNum(const char* name) return secTypeInvalid; } -const char* rfb::secTypeName(rdr::U32 num) +const char* rfb::secTypeName(uint32_t num) { switch (num) { case secTypeNone: return "None"; @@ -208,13 +203,13 @@ const char* rfb::secTypeName(rdr::U32 num) } } -std::list<rdr::U32> rfb::parseSecTypes(const char* types_) +std::list<uint32_t> rfb::parseSecTypes(const char* types_) { - std::list<rdr::U32> result; - CharArray types(strDup(types_)), type; - while (types.buf) { - strSplit(types.buf, ',', &type.buf, &types.buf); - rdr::U32 typeNum = secTypeNum(type.buf); + 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); } diff --git a/common/rfb/Security.h b/common/rfb/Security.h index 57800ffd..430a1d89 100644 --- a/common/rfb/Security.h +++ b/common/rfb/Security.h @@ -22,33 +22,34 @@ #ifndef __RFB_SECTYPES_H__ #define __RFB_SECTYPES_H__ -#include <rdr/types.h> +#include <stdint.h> + #include <rfb/Configuration.h> #include <list> namespace rfb { - const rdr::U8 secTypeInvalid = 0; - const rdr::U8 secTypeNone = 1; - const rdr::U8 secTypeVncAuth = 2; + const uint8_t secTypeInvalid = 0; + const uint8_t secTypeNone = 1; + const uint8_t secTypeVncAuth = 2; - const rdr::U8 secTypeRA2 = 5; - const rdr::U8 secTypeRA2ne = 6; + const uint8_t secTypeRA2 = 5; + const uint8_t secTypeRA2ne = 6; - const rdr::U8 secTypeSSPI = 7; - const rdr::U8 secTypeSSPIne = 8; + const uint8_t secTypeSSPI = 7; + const uint8_t secTypeSSPIne = 8; - const rdr::U8 secTypeTight = 16; - const rdr::U8 secTypeUltra = 17; - const rdr::U8 secTypeTLS = 18; - const rdr::U8 secTypeVeNCrypt = 19; + const uint8_t secTypeTight = 16; + const uint8_t secTypeUltra = 17; + const uint8_t secTypeTLS = 18; + const uint8_t secTypeVeNCrypt = 19; - const rdr::U8 secTypeDH = 30; + const uint8_t secTypeDH = 30; - const rdr::U8 secTypeMSLogonII = 113; + const uint8_t secTypeMSLogonII = 113; - const rdr::U8 secTypeRA256 = 129; - const rdr::U8 secTypeRAne256 = 130; + const uint8_t secTypeRA256 = 129; + const uint8_t secTypeRAne256 = 130; /* VeNCrypt subtypes */ const int secTypePlain = 256; @@ -65,9 +66,9 @@ namespace rfb { // result types - const rdr::U32 secResultOK = 0; - const rdr::U32 secResultFailed = 1; - const rdr::U32 secResultTooMany = 2; // deprecated + const uint32_t secResultOK = 0; + const uint32_t secResultFailed = 1; + const uint32_t secResultTooMany = 2; // deprecated class Security { public: @@ -87,18 +88,18 @@ namespace rfb { */ /* Enable/Disable certain security type */ - void EnableSecType(rdr::U32 secType); - void DisableSecType(rdr::U32 secType) { enabledSecTypes.remove(secType); } + void EnableSecType(uint32_t secType); + void DisableSecType(uint32_t secType) { enabledSecTypes.remove(secType); } - void SetSecTypes(std::list<rdr::U32> &secTypes) { enabledSecTypes = secTypes; } + void SetSecTypes(std::list<uint32_t> &secTypes) { enabledSecTypes = secTypes; } /* Check if certain type is supported */ - bool IsSupported(rdr::U32 secType); + bool IsSupported(uint32_t secType); /* Get list of enabled security types without VeNCrypt subtypes */ - const std::list<rdr::U8> GetEnabledSecTypes(void); + const std::list<uint8_t> GetEnabledSecTypes(void); /* Get list of enabled VeNCrypt subtypes */ - const std::list<rdr::U32> GetEnabledExtSecTypes(void); + const std::list<uint32_t> GetEnabledExtSecTypes(void); /* Output char* is stored in static array */ char *ToString(void); @@ -108,12 +109,12 @@ namespace rfb { #endif private: - std::list<rdr::U32> enabledSecTypes; + std::list<uint32_t> enabledSecTypes; }; - const char* secTypeName(rdr::U32 num); - rdr::U32 secTypeNum(const char* name); - std::list<rdr::U32> parseSecTypes(const char* types); + 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 80165f57..1350640d 100644 --- a/common/rfb/SecurityClient.cxx +++ b/common/rfb/SecurityClient.cxx @@ -65,7 +65,7 @@ StringParameter SecurityClient::secTypes "VncAuth,None", ConfViewer); -CSecurity* SecurityClient::GetCSecurity(CConnection* cc, U32 secType) +CSecurity* SecurityClient::GetCSecurity(CConnection* cc, uint32_t secType) { assert (CSecurity::upg != NULL); /* (upg == NULL) means bug in the viewer */ #if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE) diff --git a/common/rfb/SecurityClient.h b/common/rfb/SecurityClient.h index b13afa42..b86fcb35 100644 --- a/common/rfb/SecurityClient.h +++ b/common/rfb/SecurityClient.h @@ -33,7 +33,7 @@ namespace rfb { SecurityClient(void) : Security(secTypes) {} /* Create client side CSecurity class instance */ - CSecurity* GetCSecurity(CConnection* cc, rdr::U32 secType); + CSecurity* GetCSecurity(CConnection* cc, uint32_t secType); static StringParameter secTypes; }; diff --git a/common/rfb/SecurityServer.cxx b/common/rfb/SecurityServer.cxx index 1d1150ad..3e23a89d 100644 --- a/common/rfb/SecurityServer.cxx +++ b/common/rfb/SecurityServer.cxx @@ -54,7 +54,7 @@ StringParameter SecurityServer::secTypes "VncAuth", ConfServer); -SSecurity* SecurityServer::GetSSecurity(SConnection* sc, U32 secType) +SSecurity* SecurityServer::GetSSecurity(SConnection* sc, uint32_t secType) { if (!IsSupported(secType)) goto bail; diff --git a/common/rfb/SecurityServer.h b/common/rfb/SecurityServer.h index 354f6420..a51ee23c 100644 --- a/common/rfb/SecurityServer.h +++ b/common/rfb/SecurityServer.h @@ -33,7 +33,7 @@ namespace rfb { SecurityServer(void) : Security(secTypes) {} /* Create server side SSecurity class instance */ - SSecurity* GetSSecurity(SConnection* sc, rdr::U32 secType); + SSecurity* GetSSecurity(SConnection* sc, uint32_t secType); static StringParameter secTypes; }; diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index 274458fa..5bb6b9c9 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -26,7 +26,6 @@ #endif #include <string.h> -#include <rfb/util.h> #include <rfb/ServerCore.h> rfb::IntParameter rfb::Server::idleTimeout diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h index 20a740a8..69cad39f 100644 --- a/common/rfb/ServerCore.h +++ b/common/rfb/ServerCore.h @@ -25,7 +25,6 @@ #define __RFB_SERVER_CORE_H__ #include <rfb/Configuration.h> -#include <rfb/util.h> namespace rfb { diff --git a/common/rfb/ServerParams.cxx b/common/rfb/ServerParams.cxx index 729b3cfb..6af446c2 100644 --- a/common/rfb/ServerParams.cxx +++ b/common/rfb/ServerParams.cxx @@ -33,7 +33,7 @@ ServerParams::ServerParams() supportsQEMUKeyEvent(false), supportsSetDesktopSize(false), supportsFence(false), supportsContinuousUpdates(false), - width_(0), height_(0), name_(0), + width_(0), height_(0), ledState_(ledUnknown) { setName(""); @@ -46,7 +46,6 @@ ServerParams::ServerParams() ServerParams::~ServerParams() { - delete [] name_; delete cursor_; } @@ -77,8 +76,7 @@ void ServerParams::setPF(const PixelFormat& pf) void ServerParams::setName(const char* name) { - delete [] name_; - name_ = strDup(name); + name_ = name; } void ServerParams::setCursor(const Cursor& other) @@ -92,7 +90,7 @@ void ServerParams::setLEDState(unsigned int state) ledState_ = state; } -rdr::U32 ServerParams::clipboardSize(unsigned int format) const +uint32_t ServerParams::clipboardSize(unsigned int format) const { int i; @@ -104,7 +102,7 @@ rdr::U32 ServerParams::clipboardSize(unsigned int format) const throw Exception("Invalid clipboard format 0x%x", format); } -void ServerParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) +void ServerParams::setClipboardCaps(uint32_t flags, const uint32_t* lengths) { int i, num; diff --git a/common/rfb/ServerParams.h b/common/rfb/ServerParams.h index dba8b9a1..791e3e7f 100644 --- a/common/rfb/ServerParams.h +++ b/common/rfb/ServerParams.h @@ -23,6 +23,8 @@ #ifndef __RFB_SERVERPARAMS_H__ #define __RFB_SERVERPARAMS_H__ +#include <string> + #include <rfb/Cursor.h> #include <rfb/PixelFormat.h> #include <rfb/ScreenSet.h> @@ -60,7 +62,7 @@ namespace rfb { const PixelFormat& pf() const { return pf_; } void setPF(const PixelFormat& pf); - const char* name() const { return name_; } + const char* name() const { return name_.c_str(); } void setName(const char* name); const Cursor& cursor() const { return *cursor_; } @@ -69,9 +71,9 @@ namespace rfb { unsigned int ledState() { return ledState_; } void setLEDState(unsigned int state); - rdr::U32 clipboardFlags() const { return clipFlags; } - rdr::U32 clipboardSize(unsigned int format) const; - void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths); + uint32_t clipboardFlags() const { return clipFlags; } + uint32_t clipboardSize(unsigned int format) const; + void setClipboardCaps(uint32_t flags, const uint32_t* lengths); bool supportsQEMUKeyEvent; bool supportsSetDesktopSize; @@ -85,11 +87,11 @@ namespace rfb { ScreenSet screenLayout_; PixelFormat pf_; - char* name_; + std::string name_; Cursor* cursor_; unsigned int ledState_; - rdr::U32 clipFlags; - rdr::U32 clipSizes[16]; + uint32_t clipFlags; + uint32_t clipSizes[16]; }; } #endif diff --git a/common/rfb/TightDecoder.cxx b/common/rfb/TightDecoder.cxx index 69971dbc..acc9d5a5 100644 --- a/common/rfb/TightDecoder.cxx +++ b/common/rfb/TightDecoder.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright 2004-2005 Cendio AB. - * Copyright 2009-2015 Pierre Ossman for Cendio AB + * Copyright 2009-2022 Pierre Ossman for Cendio AB * Copyright (C) 2011 D. R. Commander. All Rights Reserved. * * This is free software; you can redistribute it and/or modify @@ -25,6 +25,8 @@ #include <assert.h> +#include <vector> + #include <rdr/InStream.h> #include <rdr/MemInStream.h> #include <rdr/OutStream.h> @@ -40,16 +42,6 @@ using namespace rfb; static const int TIGHT_MAX_WIDTH = 2048; static const int TIGHT_MIN_TO_COMPRESS = 12; -#define BPP 8 -#include <rfb/tightDecode.h> -#undef BPP -#define BPP 16 -#include <rfb/tightDecode.h> -#undef BPP -#define BPP 32 -#include <rfb/tightDecode.h> -#undef BPP - TightDecoder::TightDecoder() : Decoder(DecoderPartiallyOrdered) { } @@ -61,7 +53,7 @@ TightDecoder::~TightDecoder() bool TightDecoder::readRect(const Rect& r, rdr::InStream* is, const ServerParams& server, rdr::OutStream* os) { - rdr::U8 comp_ctl; + uint8_t comp_ctl; if (!is->hasData(1)) return false; @@ -90,7 +82,7 @@ bool TightDecoder::readRect(const Rect& r, rdr::InStream* is, // "JPEG" compression type. if (comp_ctl == tightJpeg) { - rdr::U32 len; + uint32_t len; // FIXME: Might be less than 3 bytes if (!is->hasDataOrRestore(3)) @@ -122,7 +114,7 @@ bool TightDecoder::readRect(const Rect& r, rdr::InStream* is, // Possible palette if ((comp_ctl & tightExplicitFilter) != 0) { - rdr::U8 filterId; + uint8_t filterId; if (!is->hasDataOrRestore(1)) return false; @@ -179,7 +171,7 @@ bool TightDecoder::readRect(const Rect& r, rdr::InStream* is, return false; os->copyBytes(is, dataSize); } else { - rdr::U32 len; + uint32_t len; // FIXME: Might be less than 3 bytes if (!is->hasDataOrRestore(3)) @@ -207,13 +199,13 @@ bool TightDecoder::doRectsConflict(const Rect& /*rectA*/, size_t buflenB, const ServerParams& /*server*/) { - rdr::U8 comp_ctl_a, comp_ctl_b; + uint8_t comp_ctl_a, comp_ctl_b; assert(buflenA >= 1); assert(buflenB >= 1); - comp_ctl_a = *(const rdr::U8*)bufferA; - comp_ctl_b = *(const rdr::U8*)bufferB; + comp_ctl_a = *(const uint8_t*)bufferA; + comp_ctl_b = *(const uint8_t*)bufferB; // Resets or use of zlib pose the same problem, so merge them if ((comp_ctl_a & 0x80) == 0x00) @@ -231,12 +223,12 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, size_t buflen, const ServerParams& server, ModifiablePixelBuffer* pb) { - const rdr::U8* bufptr; + const uint8_t* bufptr; const PixelFormat& pf = server.pf(); - rdr::U8 comp_ctl; + uint8_t comp_ctl; - bufptr = (const rdr::U8*)buffer; + bufptr = (const uint8_t*)buffer; assert(buflen >= 1); @@ -255,7 +247,7 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, // "Fill" compression type. if (comp_ctl == tightFill) { if (pf.is888()) { - rdr::U8 pix[4]; + uint8_t pix[4]; assert(buflen >= 3); @@ -270,10 +262,10 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, // "JPEG" compression type. if (comp_ctl == tightJpeg) { - rdr::U32 len; + uint32_t len; int stride; - rdr::U8 *buf; + uint8_t *buf; JpegDecompressor jd; @@ -296,11 +288,11 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, // "Basic" compression type. int palSize = 0; - rdr::U8 palette[256 * 4]; + uint8_t palette[256 * 4]; bool useGradient = false; if ((comp_ctl & tightExplicitFilter) != 0) { - rdr::U8 filterId; + uint8_t filterId; assert(buflen >= 1); @@ -318,15 +310,15 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, if (pf.is888()) { size_t len = palSize * 3; - rdr::U8Array tightPalette(len); + std::vector<uint8_t> tightPalette(len); assert(buflen >= len); - memcpy(tightPalette.buf, bufptr, len); + memcpy(tightPalette.data(), bufptr, len); bufptr += len; buflen -= len; - pf.bufferFromRGB(palette, tightPalette.buf, palSize); + pf.bufferFromRGB(palette, tightPalette.data(), palSize); } else { size_t len; @@ -351,7 +343,7 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, // Determine if the data should be decompressed or just copied. size_t rowSize, dataSize; - rdr::U8* netbuf; + uint8_t* netbuf; netbuf = NULL; @@ -371,7 +363,7 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, if (dataSize < TIGHT_MIN_TO_COMPRESS) assert(buflen >= dataSize); else { - rdr::U32 len; + uint32_t len; int streamId; rdr::MemInStream* ms; @@ -388,7 +380,7 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, zis[streamId].setUnderlying(ms, len); // Allocate buffer and decompress the data - netbuf = new rdr::U8[dataSize]; + netbuf = new uint8_t[dataSize]; if (!zis[streamId].hasData(dataSize)) throw Exception("Tight decode error"); @@ -405,10 +397,10 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, // Time to decode the actual data bool directDecode; - rdr::U8* outbuf; + uint8_t* outbuf; int stride; - if (pb->getPF().equal(pf)) { + if (pb->getPF() == pf) { // Decode directly into the framebuffer (fast path) directDecode = true; } else { @@ -419,7 +411,7 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, if (directDecode) outbuf = pb->getBufferRW(r, &stride); else { - outbuf = new rdr::U8[r.area() * (pf.bpp/8)]; + outbuf = new uint8_t[r.area() * (pf.bpp/8)]; stride = r.width(); } @@ -427,24 +419,24 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, // Truecolor data if (useGradient) { if (pf.is888()) - FilterGradient24(bufptr, pf, (rdr::U32*)outbuf, stride, r); + FilterGradient24(bufptr, pf, (uint32_t*)outbuf, stride, r); else { switch (pf.bpp) { case 8: assert(false); break; case 16: - FilterGradient(bufptr, pf, (rdr::U16*)outbuf, stride, r); + FilterGradient(bufptr, pf, (uint16_t*)outbuf, stride, r); break; case 32: - FilterGradient(bufptr, pf, (rdr::U32*)outbuf, stride, r); + FilterGradient(bufptr, pf, (uint32_t*)outbuf, stride, r); break; } } } else { // Copy - rdr::U8* ptr = outbuf; - const rdr::U8* srcPtr = bufptr; + uint8_t* ptr = outbuf; + const uint8_t* srcPtr = bufptr; int w = r.width(); int h = r.height(); if (pf.is888()) { @@ -467,16 +459,16 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, // Indexed color switch (pf.bpp) { case 8: - FilterPalette((const rdr::U8*)palette, palSize, - bufptr, (rdr::U8*)outbuf, stride, r); + FilterPalette((const uint8_t*)palette, palSize, + bufptr, (uint8_t*)outbuf, stride, r); break; case 16: - FilterPalette((const rdr::U16*)palette, palSize, - bufptr, (rdr::U16*)outbuf, stride, r); + FilterPalette((const uint16_t*)palette, palSize, + bufptr, (uint16_t*)outbuf, stride, r); break; case 32: - FilterPalette((const rdr::U32*)palette, palSize, - bufptr, (rdr::U32*)outbuf, stride, r); + FilterPalette((const uint32_t*)palette, palSize, + bufptr, (uint32_t*)outbuf, stride, r); break; } } @@ -491,10 +483,10 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, delete [] netbuf; } -rdr::U32 TightDecoder::readCompact(rdr::InStream* is) +uint32_t TightDecoder::readCompact(rdr::InStream* is) { - rdr::U8 b; - rdr::U32 result; + uint8_t b; + uint32_t result; b = is->readU8(); result = (int)b & 0x7F; @@ -509,3 +501,144 @@ rdr::U32 TightDecoder::readCompact(rdr::InStream* is) return result; } + +void +TightDecoder::FilterGradient24(const uint8_t *inbuf, + const PixelFormat& pf, uint32_t* outbuf, + int stride, const Rect& r) +{ + int x, y, c; + uint8_t prevRow[TIGHT_MAX_WIDTH*3]; + uint8_t thisRow[TIGHT_MAX_WIDTH*3]; + uint8_t pix[3]; + int est[3]; + + memset(prevRow, 0, sizeof(prevRow)); + + // Set up shortcut variables + int rectHeight = r.height(); + int rectWidth = r.width(); + + for (y = 0; y < rectHeight; y++) { + for (x = 0; x < rectWidth; x++) { + /* First pixel in a row */ + if (x == 0) { + for (c = 0; c < 3; c++) { + pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c]; + thisRow[c] = pix[c]; + } + pf.bufferFromRGB((uint8_t*)&outbuf[y*stride], pix, 1); + continue; + } + + for (c = 0; c < 3; c++) { + est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; + if (est[c] > 0xff) { + est[c] = 0xff; + } else if (est[c] < 0) { + est[c] = 0; + } + pix[c] = inbuf[(y*rectWidth+x)*3+c] + est[c]; + thisRow[x*3+c] = pix[c]; + } + pf.bufferFromRGB((uint8_t*)&outbuf[y*stride+x], pix, 1); + } + + memcpy(prevRow, thisRow, sizeof(prevRow)); + } +} + +template<class T> +void TightDecoder::FilterGradient(const uint8_t* inbuf, + const PixelFormat& pf, T* outbuf, + int stride, const Rect& r) +{ + int x, y, c; + static uint8_t prevRow[TIGHT_MAX_WIDTH*3]; + static uint8_t thisRow[TIGHT_MAX_WIDTH*3]; + uint8_t pix[3]; + int est[3]; + + memset(prevRow, 0, sizeof(prevRow)); + + // Set up shortcut variables + int rectHeight = r.height(); + int rectWidth = r.width(); + + for (y = 0; y < rectHeight; y++) { + for (x = 0; x < rectWidth; x++) { + /* First pixel in a row */ + if (x == 0) { + pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1); + for (c = 0; c < 3; c++) + pix[c] += prevRow[c]; + + memcpy(thisRow, pix, sizeof(pix)); + + pf.bufferFromRGB((uint8_t*)&outbuf[y*stride], pix, 1); + + continue; + } + + for (c = 0; c < 3; c++) { + est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; + if (est[c] > 255) { + est[c] = 255; + } else if (est[c] < 0) { + est[c] = 0; + } + } + + pf.rgbFromBuffer(pix, &inbuf[y*rectWidth+x], 1); + for (c = 0; c < 3; c++) + pix[c] += est[c]; + + memcpy(&thisRow[x*3], pix, sizeof(pix)); + + pf.bufferFromRGB((uint8_t*)&outbuf[y*stride+x], pix, 1); + } + + memcpy(prevRow, thisRow, sizeof(prevRow)); + } +} + +template<class T> +void TightDecoder::FilterPalette(const T* palette, int palSize, + const uint8_t* inbuf, T* outbuf, + int stride, const Rect& r) +{ + // Indexed color + int x, h = r.height(), w = r.width(), b, pad = stride - w; + T* ptr = outbuf; + uint8_t bits; + const uint8_t* srcPtr = inbuf; + if (palSize <= 2) { + // 2-color palette + while (h > 0) { + for (x = 0; x < w / 8; x++) { + bits = *srcPtr++; + for (b = 7; b >= 0; b--) { + *ptr++ = palette[bits >> b & 1]; + } + } + if (w % 8 != 0) { + bits = *srcPtr++; + for (b = 7; b >= 8 - w % 8; b--) { + *ptr++ = palette[bits >> b & 1]; + } + } + ptr += pad; + h--; + } + } else { + // 256-color palette + while (h > 0) { + T *endOfRow = ptr + w; + while (ptr < endOfRow) { + *ptr++ = palette[*srcPtr++]; + } + ptr += pad; + h--; + } + } +} diff --git a/common/rfb/TightDecoder.h b/common/rfb/TightDecoder.h index 763c82d6..03b61daf 100644 --- a/common/rfb/TightDecoder.h +++ b/common/rfb/TightDecoder.h @@ -1,6 +1,6 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2009-2015 Pierre Ossman for Cendio AB + * Copyright 2009-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 @@ -45,24 +45,18 @@ namespace rfb { ModifiablePixelBuffer* pb); private: - rdr::U32 readCompact(rdr::InStream* is); + uint32_t readCompact(rdr::InStream* is); - void FilterGradient24(const rdr::U8* inbuf, const PixelFormat& pf, - rdr::U32* outbuf, int stride, const Rect& r); + void FilterGradient24(const uint8_t* inbuf, const PixelFormat& pf, + uint32_t* outbuf, int stride, const Rect& r); - void FilterGradient(const rdr::U8* inbuf, const PixelFormat& pf, - rdr::U16* outbuf, int stride, const Rect& r); - void FilterGradient(const rdr::U8* inbuf, const PixelFormat& pf, - rdr::U32* outbuf, int stride, const Rect& r); + template<class T> + void FilterGradient(const uint8_t* inbuf, const PixelFormat& pf, + T* outbuf, int stride, const Rect& r); - void FilterPalette(const rdr::U8* palette, int palSize, - const rdr::U8* inbuf, rdr::U8* outbuf, - int stride, const Rect& r); - void FilterPalette(const rdr::U16* palette, int palSize, - const rdr::U8* inbuf, rdr::U16* outbuf, - int stride, const Rect& r); - void FilterPalette(const rdr::U32* palette, int palSize, - const rdr::U8* inbuf, rdr::U32* outbuf, + template<class T> + void FilterPalette(const T* palette, int palSize, + const uint8_t* inbuf, T* outbuf, int stride, const Rect& r); private: diff --git a/common/rfb/TightEncoder.cxx b/common/rfb/TightEncoder.cxx index 94acd3d1..1a169a3d 100644 --- a/common/rfb/TightEncoder.cxx +++ b/common/rfb/TightEncoder.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -104,7 +104,7 @@ void TightEncoder::writeRect(const PixelBuffer* pb, const Palette& palette) void TightEncoder::writeSolidRect(int /*width*/, int /*height*/, const PixelFormat& pf, - const rdr::U8* colour) + const uint8_t* colour) { rdr::OutStream* os; @@ -116,40 +116,40 @@ void TightEncoder::writeSolidRect(int /*width*/, int /*height*/, void TightEncoder::writeMonoRect(const PixelBuffer* pb, const Palette& palette) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; buffer = pb->getBuffer(pb->getRect(), &stride); switch (pb->getPF().bpp) { case 32: - writeMonoRect(pb->width(), pb->height(), (rdr::U32*)buffer, stride, + writeMonoRect(pb->width(), pb->height(), (uint32_t*)buffer, stride, pb->getPF(), palette); break; case 16: - writeMonoRect(pb->width(), pb->height(), (rdr::U16*)buffer, stride, + writeMonoRect(pb->width(), pb->height(), (uint16_t*)buffer, stride, pb->getPF(), palette); break; default: - writeMonoRect(pb->width(), pb->height(), (rdr::U8*)buffer, stride, + writeMonoRect(pb->width(), pb->height(), (uint8_t*)buffer, stride, pb->getPF(), palette); } } void TightEncoder::writeIndexedRect(const PixelBuffer* pb, const Palette& palette) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; buffer = pb->getBuffer(pb->getRect(), &stride); switch (pb->getPF().bpp) { case 32: - writeIndexedRect(pb->width(), pb->height(), (rdr::U32*)buffer, stride, + writeIndexedRect(pb->width(), pb->height(), (uint32_t*)buffer, stride, pb->getPF(), palette); break; case 16: - writeIndexedRect(pb->width(), pb->height(), (rdr::U16*)buffer, stride, + writeIndexedRect(pb->width(), pb->height(), (uint16_t*)buffer, stride, pb->getPF(), palette); break; default: @@ -166,7 +166,7 @@ void TightEncoder::writeFullColourRect(const PixelBuffer* pb) rdr::OutStream* zos; int length; - const rdr::U8* buffer; + const uint8_t* buffer; int stride, h; os = conn->getOutStream(); @@ -194,10 +194,10 @@ void TightEncoder::writeFullColourRect(const PixelBuffer* pb) flushZlibOutStream(zos); } -void TightEncoder::writePixels(const rdr::U8* buffer, const PixelFormat& pf, +void TightEncoder::writePixels(const uint8_t* buffer, const PixelFormat& pf, unsigned int count, rdr::OutStream* os) { - rdr::U8 rgb[2048]; + uint8_t rgb[2048]; if ((pf.bpp != 32) || !pf.is888()) { os->writeBytes(buffer, count * pf.bpp/8); @@ -219,9 +219,9 @@ void TightEncoder::writePixels(const rdr::U8* buffer, const PixelFormat& pf, } } -void TightEncoder::writeCompact(rdr::OutStream* os, rdr::U32 value) +void TightEncoder::writeCompact(rdr::OutStream* os, uint32_t value) { - rdr::U8 b; + uint8_t b; b = value & 0x7F; if (value <= 0x7F) { os->writeU8(b); @@ -274,16 +274,143 @@ void TightEncoder::flushZlibOutStream(rdr::OutStream* os_) memStream.clear(); } -// -// Including BPP-dependent implementation of the encoder. -// +template<class T> +void TightEncoder::writeMonoRect(int width, int height, + const T* buffer, int stride, + const PixelFormat& pf, + const Palette& palette) +{ + rdr::OutStream* os; + + const int streamId = 1; + T pal[2]; + + int length; + rdr::OutStream* zos; + + assert(palette.size() == 2); + + os = conn->getOutStream(); + + os->writeU8((streamId | tightExplicitFilter) << 4); + os->writeU8(tightFilterPalette); -#define BPP 8 -#include <rfb/TightEncoderBPP.cxx> -#undef BPP -#define BPP 16 -#include <rfb/TightEncoderBPP.cxx> -#undef BPP -#define BPP 32 -#include <rfb/TightEncoderBPP.cxx> -#undef BPP + // Write the palette + pal[0] = (T)palette.getColour(0); + pal[1] = (T)palette.getColour(1); + + os->writeU8(1); + writePixels((uint8_t*)pal, pf, 2, os); + + // Set up compression + length = (width + 7)/8 * height; + zos = getZlibOutStream(streamId, monoZlibLevel, length); + + // Encode the data + T bg; + unsigned int value, mask; + int pad, aligned_width; + int x, y, bg_bits; + + bg = pal[0]; + aligned_width = width - width % 8; + pad = stride - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < aligned_width; x += 8) { + for (bg_bits = 0; bg_bits < 8; bg_bits++) { + if (*buffer++ != bg) + break; + } + if (bg_bits == 8) { + zos->writeU8(0); + continue; + } + mask = 0x80 >> bg_bits; + value = mask; + for (bg_bits++; bg_bits < 8; bg_bits++) { + mask >>= 1; + if (*buffer++ != bg) { + value |= mask; + } + } + zos->writeU8(value); + } + + if (x < width) { + mask = 0x80; + value = 0; + + for (; x < width; x++) { + if (*buffer++ != bg) { + value |= mask; + } + mask >>= 1; + } + zos->writeU8(value); + } + + buffer += pad; + } + + // Finish the zlib stream + flushZlibOutStream(zos); +} + +template<class T> +void TightEncoder::writeIndexedRect(int width, int height, + const T* buffer, int stride, + const PixelFormat& pf, + const Palette& palette) +{ + rdr::OutStream* os; + + const int streamId = 2; + T pal[256]; + + rdr::OutStream* zos; + + int pad; + T prevColour; + unsigned char idx; + + assert(palette.size() > 0); + assert(palette.size() <= 256); + + os = conn->getOutStream(); + + os->writeU8((streamId | tightExplicitFilter) << 4); + os->writeU8(tightFilterPalette); + + // Write the palette + for (int i = 0; i < palette.size(); i++) + pal[i] = (T)palette.getColour(i); + + os->writeU8(palette.size() - 1); + writePixels((uint8_t*)pal, pf, palette.size(), os); + + // Set up compression + zos = getZlibOutStream(streamId, idxZlibLevel, width * height); + + // Encode the data + pad = stride - width; + + prevColour = *buffer; + idx = palette.lookup(*buffer); + + while (height--) { + int w = width; + while (w--) { + if (*buffer != prevColour) { + prevColour = *buffer; + idx = palette.lookup(*buffer); + } + zos->writeU8(idx); + buffer++; + } + buffer += pad; + } + + // Finish the zlib stream + flushZlibOutStream(zos); +} diff --git a/common/rfb/TightEncoder.h b/common/rfb/TightEncoder.h index b96bc4c6..0608eb09 100644 --- a/common/rfb/TightEncoder.h +++ b/common/rfb/TightEncoder.h @@ -1,6 +1,6 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright (C) 2011 D. R. Commander - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -38,38 +38,30 @@ namespace rfb { virtual void writeRect(const PixelBuffer* pb, const Palette& palette); virtual void writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour); + const uint8_t* colour); protected: void writeMonoRect(const PixelBuffer* pb, const Palette& palette); void writeIndexedRect(const PixelBuffer* pb, const Palette& palette); void writeFullColourRect(const PixelBuffer* pb); - void writePixels(const rdr::U8* buffer, const PixelFormat& pf, + void writePixels(const uint8_t* buffer, const PixelFormat& pf, unsigned int count, rdr::OutStream* os); - void writeCompact(rdr::OutStream* os, rdr::U32 value); + void writeCompact(rdr::OutStream* os, uint32_t value); rdr::OutStream* getZlibOutStream(int streamId, int level, size_t length); void flushZlibOutStream(rdr::OutStream* os); protected: - // Preprocessor generated, optimised methods + // Templated, optimised methods + template<class T> void writeMonoRect(int width, int height, - const rdr::U8* buffer, int stride, + const T* buffer, int stride, const PixelFormat& pf, const Palette& palette); - void writeMonoRect(int width, int height, - const rdr::U16* buffer, int stride, - const PixelFormat& pf, const Palette& palette); - void writeMonoRect(int width, int height, - const rdr::U32* buffer, int stride, - const PixelFormat& pf, const Palette& palette); - - void writeIndexedRect(int width, int height, - const rdr::U16* buffer, int stride, - const PixelFormat& pf, const Palette& palette); + template<class T> void writeIndexedRect(int width, int height, - const rdr::U32* buffer, int stride, + const T* buffer, int stride, const PixelFormat& pf, const Palette& palette); rdr::ZlibOutStream zlibStreams[4]; diff --git a/common/rfb/TightEncoderBPP.cxx b/common/rfb/TightEncoderBPP.cxx deleted file mode 100644 index 8874662c..00000000 --- a/common/rfb/TightEncoderBPP.cxx +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. - * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) - -#define UBPP CONCAT2E(U,BPP) - -void TightEncoder::writeMonoRect(int width, int height, - const rdr::UBPP* buffer, int stride, - const PixelFormat& pf, - const Palette& palette) -{ - rdr::OutStream* os; - - const int streamId = 1; - rdr::UBPP pal[2]; - - int length; - rdr::OutStream* zos; - - assert(palette.size() == 2); - - os = conn->getOutStream(); - - os->writeU8((streamId | tightExplicitFilter) << 4); - os->writeU8(tightFilterPalette); - - // Write the palette - pal[0] = (rdr::UBPP)palette.getColour(0); - pal[1] = (rdr::UBPP)palette.getColour(1); - - os->writeU8(1); - writePixels((rdr::U8*)pal, pf, 2, os); - - // Set up compression - length = (width + 7)/8 * height; - zos = getZlibOutStream(streamId, monoZlibLevel, length); - - // Encode the data - rdr::UBPP bg; - unsigned int value, mask; - int pad, aligned_width; - int x, y, bg_bits; - - bg = pal[0]; - aligned_width = width - width % 8; - pad = stride - width; - - for (y = 0; y < height; y++) { - for (x = 0; x < aligned_width; x += 8) { - for (bg_bits = 0; bg_bits < 8; bg_bits++) { - if (*buffer++ != bg) - break; - } - if (bg_bits == 8) { - zos->writeU8(0); - continue; - } - mask = 0x80 >> bg_bits; - value = mask; - for (bg_bits++; bg_bits < 8; bg_bits++) { - mask >>= 1; - if (*buffer++ != bg) { - value |= mask; - } - } - zos->writeU8(value); - } - - if (x < width) { - mask = 0x80; - value = 0; - - for (; x < width; x++) { - if (*buffer++ != bg) { - value |= mask; - } - mask >>= 1; - } - zos->writeU8(value); - } - - buffer += pad; - } - - // Finish the zlib stream - flushZlibOutStream(zos); -} - -#if (BPP != 8) -void TightEncoder::writeIndexedRect(int width, int height, - const rdr::UBPP* buffer, int stride, - const PixelFormat& pf, - const Palette& palette) -{ - rdr::OutStream* os; - - const int streamId = 2; - rdr::UBPP pal[256]; - - rdr::OutStream* zos; - - int pad; - rdr::UBPP prevColour; - unsigned char idx; - - assert(palette.size() > 0); - assert(palette.size() <= 256); - - os = conn->getOutStream(); - - os->writeU8((streamId | tightExplicitFilter) << 4); - os->writeU8(tightFilterPalette); - - // Write the palette - for (int i = 0; i < palette.size(); i++) - pal[i] = (rdr::UBPP)palette.getColour(i); - - os->writeU8(palette.size() - 1); - writePixels((rdr::U8*)pal, pf, palette.size(), os); - - // Set up compression - zos = getZlibOutStream(streamId, idxZlibLevel, width * height); - - // Encode the data - pad = stride - width; - - prevColour = *buffer; - idx = palette.lookup(*buffer); - - while (height--) { - int w = width; - while (w--) { - if (*buffer != prevColour) { - prevColour = *buffer; - idx = palette.lookup(*buffer); - } - zos->writeU8(idx); - buffer++; - } - buffer += pad; - } - - // Finish the zlib stream - flushZlibOutStream(zos); -} -#endif // #if (BPP != 8) diff --git a/common/rfb/TightJPEGEncoder.cxx b/common/rfb/TightJPEGEncoder.cxx index 976601f7..5c8706ee 100644 --- a/common/rfb/TightJPEGEncoder.cxx +++ b/common/rfb/TightJPEGEncoder.cxx @@ -115,7 +115,7 @@ int TightJPEGEncoder::getQualityLevel() void TightJPEGEncoder::writeRect(const PixelBuffer* pb, const Palette& /*palette*/) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; int quality, subsampling; @@ -152,17 +152,17 @@ void TightJPEGEncoder::writeRect(const PixelBuffer* pb, void TightJPEGEncoder::writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour) + const uint8_t* colour) { // FIXME: Add a shortcut in the JPEG compressor to handle this case // without having to use the default fallback which is very slow. Encoder::writeSolidRect(width, height, pf, colour); } -void TightJPEGEncoder::writeCompact(rdr::U32 value, rdr::OutStream* os) +void TightJPEGEncoder::writeCompact(uint32_t value, rdr::OutStream* os) { // Copied from TightEncoder as it's overkill to inherit just for this - rdr::U8 b; + uint8_t b; b = value & 0x7F; if (value <= 0x7F) { diff --git a/common/rfb/TightJPEGEncoder.h b/common/rfb/TightJPEGEncoder.h index 3d8fa8c1..002deabb 100644 --- a/common/rfb/TightJPEGEncoder.h +++ b/common/rfb/TightJPEGEncoder.h @@ -40,10 +40,10 @@ namespace rfb { virtual void writeRect(const PixelBuffer* pb, const Palette& palette); virtual void writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour); + const uint8_t* colour); protected: - void writeCompact(rdr::U32 value, rdr::OutStream* os); + void writeCompact(uint32_t value, rdr::OutStream* os); protected: JpegCompressor jc; diff --git a/common/rfb/UnixPasswordValidator.cxx b/common/rfb/UnixPasswordValidator.cxx index fa1513a4..57fa9b39 100644 --- a/common/rfb/UnixPasswordValidator.cxx +++ b/common/rfb/UnixPasswordValidator.cxx @@ -41,6 +41,5 @@ bool UnixPasswordValidator::validateInternal(SConnection * /*sc*/, const char *username, const char *password) { - CharArray service(strDup(pamService.getData())); - return do_pam_auth(service.buf, username, password); + return do_pam_auth(pamService, username, password); } diff --git a/common/rfb/UserPasswdGetter.h b/common/rfb/UserPasswdGetter.h index 27775cc3..db7df396 100644 --- a/common/rfb/UserPasswdGetter.h +++ b/common/rfb/UserPasswdGetter.h @@ -17,16 +17,20 @@ */ #ifndef __RFB_USERPASSWDGETTER_H__ #define __RFB_USERPASSWDGETTER_H__ + +#include <string> + namespace rfb { class UserPasswdGetter { public: // getUserPasswd gets the username and password. This might involve a // dialog, getpass(), etc. The user buffer pointer can be null, in which - // case no user name will be retrieved. The caller MUST delete [] the - // result(s). - virtual void getUserPasswd(bool secure, char** user, char** password)=0; + // case no user name will be retrieved. + virtual void getUserPasswd(bool secure, std::string* user, + std::string* password)=0; virtual ~UserPasswdGetter() {} }; } + #endif diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index 23024c5e..5d047e6a 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -26,6 +26,7 @@ #include <rfb/ComparingUpdateTracker.h> #include <rfb/Encoder.h> +#include <rfb/Exception.h> #include <rfb/KeyRemapper.h> #include <rfb/LogWriter.h> #include <rfb/Security.h> @@ -40,6 +41,7 @@ #define XK_MISCELLANY #define XK_XKB_KEYS #include <rfb/keysymdef.h> +#include <rfb/util.h> using namespace rfb; @@ -59,7 +61,7 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, pointerEventTime(0), clientHasCursor(false) { setStreams(&sock->inStream(), &sock->outStream()); - peerEndpoint.buf = sock->getPeerEndpoint(); + peerEndpoint = sock->getPeerEndpoint(); // Kick off the idle timer if (rfb::Server::idleTimeout) { @@ -75,12 +77,13 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, VNCSConnectionST::~VNCSConnectionST() { // If we reach here then VNCServerST is deleting us! - if (closeReason.buf) - vlog.info("closing %s: %s", peerEndpoint.buf, closeReason.buf); + if (!closeReason.empty()) + vlog.info("closing %s: %s", peerEndpoint.c_str(), + closeReason.c_str()); // Release any keys the client still had pressed while (!pressedKeys.empty()) { - rdr::U32 keysym, keycode; + uint32_t keysym, keycode; keysym = pressedKeys.begin()->second; keycode = pressedKeys.begin()->first; @@ -112,10 +115,10 @@ void VNCSConnectionST::close(const char* reason) SConnection::close(reason); // Log the reason for the close - if (!closeReason.buf) - closeReason.buf = strDup(reason); + if (closeReason.empty()) + closeReason = reason; else - vlog.debug("second close: %s (%s)", peerEndpoint.buf, reason); + vlog.debug("second close: %s (%s)", peerEndpoint.c_str(), reason); try { if (sock->outStream().hasBufferedData()) { @@ -261,7 +264,7 @@ void VNCSConnectionST::writeFramebufferUpdateOrClose() } } -void VNCSConnectionST::screenLayoutChangeOrClose(rdr::U16 reason) +void VNCSConnectionST::screenLayoutChangeOrClose(uint16_t reason) { try { screenLayoutChange(reason); @@ -400,7 +403,7 @@ bool VNCSConnectionST::needRenderedCursor() if (!client.supportsLocalCursor()) return true; - if (!server->getCursorPos().equals(pointerEventPos) && + if ((server->getCursorPos() != pointerEventPos) && (time(0) - pointerEventTime) > 0) return true; @@ -502,8 +505,8 @@ public: // keyEvent() - record in the pressedKeys which keys were pressed. Allow // multiple down events (for autorepeat), but only allow a single up event. -void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { - rdr::U32 lookup; +void VNCSConnectionST::keyEvent(uint32_t keysym, uint32_t keycode, bool down) { + uint32_t lookup; if (rfb::Server::idleTimeout) idleTimer.start(secsToMillis(rfb::Server::idleTimeout)); @@ -669,9 +672,9 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height, writer()->writeDesktopSize(reasonClient, result); } -void VNCSConnectionST::fence(rdr::U32 flags, unsigned len, const char data[]) +void VNCSConnectionST::fence(uint32_t flags, unsigned len, const char data[]) { - rdr::U8 type; + uint8_t type; if (flags & fenceFlagRequest) { if (flags & fenceFlagSyncNext) { @@ -808,7 +811,7 @@ bool VNCSConnectionST::handleTimeout(Timer* t) bool VNCSConnectionST::isShiftPressed() { - std::map<rdr::U32, rdr::U32>::const_iterator iter; + std::map<uint32_t, uint32_t>::const_iterator iter; for (iter = pressedKeys.begin(); iter != pressedKeys.end(); ++iter) { if (iter->second == XK_Shift_L) @@ -1108,7 +1111,7 @@ void VNCSConnectionST::writeLosslessRefresh() } -void VNCSConnectionST::screenLayoutChange(rdr::U16 reason) +void VNCSConnectionST::screenLayoutChange(uint16_t reason) { if (!authenticated()) return; diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h index 72b0c529..79f0b4fe 100644 --- a/common/rfb/VNCSConnectionST.h +++ b/common/rfb/VNCSConnectionST.h @@ -71,7 +71,7 @@ namespace rfb { // Wrappers to make these methods "safe" for VNCServerST. void writeFramebufferUpdateOrClose(); - void screenLayoutChangeOrClose(rdr::U16 reason); + void screenLayoutChangeOrClose(uint16_t reason); void setCursorOrClose(); void bellOrClose(); void setDesktopNameOrClose(const char *name); @@ -112,7 +112,7 @@ namespace rfb { updates.add_copied(dest, delta); } - const char* getPeerEndpoint() const {return peerEndpoint.buf;} + const char* getPeerEndpoint() const {return peerEndpoint.c_str();} private: // SConnection callbacks @@ -124,11 +124,11 @@ namespace rfb { virtual void clientInit(bool shared); virtual void setPixelFormat(const PixelFormat& pf); virtual void pointerEvent(const Point& pos, int buttonMask); - virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); + virtual void keyEvent(uint32_t keysym, uint32_t keycode, bool down); virtual void framebufferUpdateRequest(const Rect& r, bool incremental); virtual void setDesktopSize(int fb_width, int fb_height, const ScreenSet& layout); - virtual void fence(rdr::U32 flags, unsigned len, const char data[]); + virtual void fence(uint32_t flags, unsigned len, const char data[]); virtual void enableContinuousUpdates(bool enable, int x, int y, int w, int h); virtual void handleClipboardRequest(); @@ -158,7 +158,7 @@ namespace rfb { void writeDataUpdate(); void writeLosslessRefresh(); - void screenLayoutChange(rdr::U16 reason); + void screenLayoutChange(uint16_t reason); void setCursor(); void setCursorPos(); void setDesktopName(const char *name); @@ -166,13 +166,13 @@ namespace rfb { private: network::Socket* sock; - CharArray peerEndpoint; + std::string peerEndpoint; bool reverseConnection; bool inProcessMessages; bool pendingSyncFence, syncFence; - rdr::U32 fenceFlags; + uint32_t fenceFlags; unsigned fenceDataLen; char *fenceData; @@ -189,7 +189,7 @@ namespace rfb { Region cuRegion; EncodeManager encodeManager; - std::map<rdr::U32, rdr::U32> pressedKeys; + std::map<uint32_t, uint32_t> pressedKeys; Timer idleTimer; @@ -197,7 +197,7 @@ namespace rfb { Point pointerEventPos; bool clientHasCursor; - CharArray closeReason; + std::string closeReason; }; } #endif diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h index 4535b562..3f97634b 100644 --- a/common/rfb/VNCServer.h +++ b/common/rfb/VNCServer.h @@ -95,7 +95,7 @@ namespace rfb { // cursorData argument contains width*height rgba quadruplets with // non-premultiplied alpha. virtual void setCursor(int width, int height, const Point& hotspot, - const rdr::U8* cursorData) = 0; + 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 diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index 411cfd5e..5f5ee34a 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -56,6 +56,7 @@ #include <stdlib.h> #include <rfb/ComparingUpdateTracker.h> +#include <rfb/Exception.h> #include <rfb/KeyRemapper.h> #include <rfb/LogWriter.h> #include <rfb/Security.h> @@ -65,7 +66,6 @@ #include <rfb/util.h> #include <rfb/ledStates.h> -#include <rdr/types.h> using namespace rfb; @@ -81,14 +81,14 @@ static LogWriter connectionsLog("Connections"); VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_) : blHosts(&blacklist), desktop(desktop_), desktopStarted(false), blockCounter(0), pb(0), ledState(ledUnknown), - name(strDup(name_)), pointerClient(0), clipboardClient(0), + name(name_), pointerClient(0), clipboardClient(0), comparer(0), cursor(new Cursor(0, 0, Point(), NULL)), renderedCursorInvalid(false), keyRemapper(&KeyRemapper::defInstance), idleTimer(this), disconnectTimer(this), connectTimer(this), frameTimer(this) { - slog.debug("creating single-threaded server %s", name.buf); + slog.debug("creating single-threaded server %s", name.c_str()); // FIXME: Do we really want to kick off these right away? if (rfb::Server::maxIdleTime) @@ -99,7 +99,7 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_) VNCServerST::~VNCServerST() { - slog.debug("shutting down server %s", name.buf); + slog.debug("shutting down server %s", name.c_str()); // Close any active clients, with appropriate logging & cleanup closeClients("Server shutdown"); @@ -132,9 +132,9 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing) { // - Check the connection isn't black-marked // *** do this in getSecurity instead? - CharArray address(sock->getPeerAddress()); - if (blHosts->isBlackmarked(address.buf)) { - connectionsLog.error("blacklisted: %s", address.buf); + const char *address = sock->getPeerAddress(); + if (blHosts->isBlackmarked(address)) { + connectionsLog.error("blacklisted: %s", address); try { rdr::OutStream& os = sock->outStream(); @@ -152,9 +152,7 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing) return; } - CharArray name; - name.buf = sock->getPeerEndpoint(); - connectionsLog.status("accepted: %s", name.buf); + connectionsLog.status("accepted: %s", sock->getPeerEndpoint()); // Adjust the exit timers if (rfb::Server::maxConnectionTime && clients.empty()) @@ -178,14 +176,14 @@ void VNCServerST::removeSocket(network::Socket* sock) { handleClipboardAnnounce(*ci, false); clipboardRequestors.remove(*ci); - CharArray name(strDup((*ci)->getPeerEndpoint())); + std::string name((*ci)->getPeerEndpoint()); // - Delete the per-Socket resources delete *ci; clients.remove(*ci); - connectionsLog.status("closed: %s", name.buf); + connectionsLog.status("closed: %s", name.c_str()); // - Check that the desktop object is still required if (authClientCount() == 0) @@ -389,7 +387,7 @@ void VNCServerST::bell() void VNCServerST::setName(const char* name_) { - name.replaceBuf(strDup(name_)); + name = name_; std::list<VNCSConnectionST*>::iterator ci, ci_next; for (ci = clients.begin(); ci != clients.end(); ci = ci_next) { ci_next = ci; ci_next++; @@ -416,7 +414,7 @@ void VNCServerST::add_copied(const Region& dest, const Point& delta) } void VNCServerST::setCursor(int width, int height, const Point& newHotspot, - const rdr::U8* data) + const uint8_t* data) { delete cursor; cursor = new Cursor(width, height, newHotspot, data); @@ -434,7 +432,7 @@ void VNCServerST::setCursor(int width, int height, const Point& newHotspot, void VNCServerST::setCursorPos(const Point& pos, bool warped) { - if (!cursorPos.equals(pos)) { + if (cursorPos != pos) { cursorPos = pos; renderedCursorInvalid = true; std::list<VNCSConnectionST*>::iterator ci; @@ -463,14 +461,14 @@ void VNCServerST::setLEDState(unsigned int state) // Event handlers -void VNCServerST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) +void VNCServerST::keyEvent(uint32_t keysym, uint32_t keycode, bool down) { if (rfb::Server::maxIdleTime) idleTimer.start(secsToMillis(rfb::Server::maxIdleTime)); // Remap the key if required if (keyRemapper) { - rdr::U32 newkey; + uint32_t newkey; newkey = keyRemapper->remapKey(keysym); if (newkey != keysym) { slog.debug("Key remapped to 0x%x", newkey); @@ -652,9 +650,7 @@ void VNCServerST::queryConnection(VNCSConnectionST* client, const char* userName) { // - Authentication succeeded - clear from blacklist - CharArray name; - name.buf = client->getSock()->getPeerAddress(); - blHosts->clearBlackmark(name.buf); + blHosts->clearBlackmark(client->getSock()->getPeerAddress()); // - Prepare the desktop for that the client will start requiring // resources after this diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h index 159e3a4b..028903c9 100644 --- a/common/rfb/VNCServerST.h +++ b/common/rfb/VNCServerST.h @@ -98,7 +98,7 @@ namespace rfb { virtual void add_changed(const Region ®ion); virtual void add_copied(const Region &dest, const Point &delta); virtual void setCursor(int width, int height, const Point& hotspot, - const rdr::U8* data); + const uint8_t* data); virtual void setCursorPos(const Point& p, bool warped); virtual void setName(const char* name_); virtual void setLEDState(unsigned state); @@ -112,11 +112,11 @@ namespace rfb { const ScreenSet& getScreenLayout() const { return screenLayout; } const Cursor* getCursor() const { return cursor; } const Point& getCursorPos() const { return cursorPos; } - const char* getName() const { return name.buf; } + const char* getName() const { return name.c_str(); } unsigned getLEDState() const { return ledState; } // Event handlers - void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); + void keyEvent(uint32_t keysym, uint32_t keycode, bool down); void pointerEvent(VNCSConnectionST* client, const Point& pos, int buttonMask); void handleClipboardRequest(VNCSConnectionST* client); @@ -183,7 +183,7 @@ namespace rfb { ScreenSet screenLayout; unsigned int ledState; - CharArray name; + std::string name; std::list<VNCSConnectionST*> clients; VNCSConnectionST* pointerClient; diff --git a/common/rfb/WinPasswdValidator.cxx b/common/rfb/WinPasswdValidator.cxx index f07c27e8..84832e81 100644 --- a/common/rfb/WinPasswdValidator.cxx +++ b/common/rfb/WinPasswdValidator.cxx @@ -24,7 +24,6 @@ #include <rfb/WinPasswdValidator.h> #include <windows.h> -#include <tchar.h> using namespace rfb; @@ -33,17 +32,10 @@ bool WinPasswdValidator::validateInternal(rfb::SConnection* /*sc*/, const char* username, const char* password) { - TCHAR* user = (TCHAR*) strDup(username); - TCHAR* pass = (TCHAR*) strDup(password); - TCHAR* domain = (TCHAR*) strDup("."); HANDLE handle; - BOOL ret = LogonUser(user, domain, pass, LOGON32_LOGON_NETWORK, + BOOL ret = LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &handle); - delete [] user; - delete [] pass; - delete [] domain; - if (ret != 0) { CloseHandle(handle); return true; diff --git a/common/rfb/ZRLEDecoder.cxx b/common/rfb/ZRLEDecoder.cxx index f5120e9c..6dad55f4 100644 --- a/common/rfb/ZRLEDecoder.cxx +++ b/common/rfb/ZRLEDecoder.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2017 Pierre Ossman for Cendio AB + * Copyright 2009-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 @@ -32,46 +32,41 @@ using namespace rfb; -static inline rdr::U32 readOpaque24A(rdr::InStream* is) +static inline uint32_t readOpaque24A(rdr::InStream* is) { - rdr::U32 r=0; - ((rdr::U8*)&r)[0] = is->readU8(); - ((rdr::U8*)&r)[1] = is->readU8(); - ((rdr::U8*)&r)[2] = is->readU8(); + uint32_t r=0; + ((uint8_t*)&r)[0] = is->readU8(); + ((uint8_t*)&r)[1] = is->readU8(); + ((uint8_t*)&r)[2] = is->readU8(); return r; } -static inline rdr::U32 readOpaque24B(rdr::InStream* is) +static inline uint32_t readOpaque24B(rdr::InStream* is) { - rdr::U32 r=0; - ((rdr::U8*)&r)[1] = is->readU8(); - ((rdr::U8*)&r)[2] = is->readU8(); - ((rdr::U8*)&r)[3] = is->readU8(); + uint32_t r=0; + ((uint8_t*)&r)[1] = is->readU8(); + ((uint8_t*)&r)[2] = is->readU8(); + ((uint8_t*)&r)[3] = is->readU8(); return r; } +template<class T> +static inline T readPixel(rdr::ZlibInStream* zis) +{ + if (sizeof(T) == 1) + return zis->readOpaque8(); + if (sizeof(T) == 2) + return zis->readOpaque16(); + if (sizeof(T) == 4) + return zis->readOpaque32(); +} + static inline void zlibHasData(rdr::ZlibInStream* zis, size_t length) { if (!zis->hasData(length)) throw Exception("ZRLE decode error"); } -#define BPP 8 -#include <rfb/zrleDecode.h> -#undef BPP -#define BPP 16 -#include <rfb/zrleDecode.h> -#undef BPP -#define BPP 32 -#include <rfb/zrleDecode.h> -#define CPIXEL 24A -#include <rfb/zrleDecode.h> -#undef CPIXEL -#define CPIXEL 24B -#include <rfb/zrleDecode.h> -#undef CPIXEL -#undef BPP - ZRLEDecoder::ZRLEDecoder() : Decoder(DecoderOrdered) { } @@ -84,7 +79,7 @@ bool ZRLEDecoder::readRect(const Rect& /*r*/, rdr::InStream* is, const ServerParams& /*server*/, rdr::OutStream* os) { - rdr::U32 len; + uint32_t len; if (!is->hasData(4)) return false; @@ -111,32 +106,185 @@ void ZRLEDecoder::decodeRect(const Rect& r, const void* buffer, rdr::MemInStream is(buffer, buflen); const rfb::PixelFormat& pf = server.pf(); switch (pf.bpp) { - case 8: zrleDecode8 (r, &is, &zis, pf, pb); break; - case 16: zrleDecode16(r, &is, &zis, pf, pb); break; - case 32: - { - if (pf.depth <= 24) { - Pixel maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1); - bool fitsInLS3Bytes = maxPixel < (1<<24); - bool fitsInMS3Bytes = (maxPixel & 0xff) == 0; - - if ((fitsInLS3Bytes && pf.isLittleEndian()) || - (fitsInMS3Bytes && pf.isBigEndian())) - { - zrleDecode24A(r, &is, &zis, pf, pb); - break; + case 8: zrleDecode<uint8_t>(r, &is, &zis, pf, pb); break; + case 16: zrleDecode<uint16_t>(r, &is, &zis, pf, pb); break; + case 32: zrleDecode<uint32_t>(r, &is, &zis, pf, pb); break; + } +} + +template<class T> +void ZRLEDecoder::zrleDecode(const Rect& r, rdr::InStream* is, + rdr::ZlibInStream* zis, + const PixelFormat& pf, + ModifiablePixelBuffer* pb) +{ + int length = is->readU32(); + zis->setUnderlying(is, length); + Rect t; + T buf[64 * 64]; + + Pixel maxPixel = pf.pixelFromRGB((uint16_t)-1, (uint16_t)-1, (uint16_t)-1); + bool fitsInLS3Bytes = maxPixel < (1<<24); + bool fitsInMS3Bytes = (maxPixel & 0xff) == 0; + bool isLowCPixel = (sizeof(T) == 4) && + ((fitsInLS3Bytes && pf.isLittleEndian()) || + (fitsInMS3Bytes && pf.isBigEndian())); + bool isHighCPixel = (sizeof(T) == 4) && + ((fitsInLS3Bytes && pf.isBigEndian()) || + (fitsInMS3Bytes && pf.isLittleEndian())); + + 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); + + 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); + + zlibHasData(zis, 1); + int mode = zis->readU8(); + bool rle = mode & 128; + int palSize = mode & 127; + T palette[128]; + + if (isLowCPixel || isHighCPixel) + zlibHasData(zis, 3 * palSize); + else + zlibHasData(zis, sizeof(T) * palSize); + + for (int i = 0; i < palSize; i++) { + if (isLowCPixel) + palette[i] = readOpaque24A(zis); + else if (isHighCPixel) + palette[i] = readOpaque24B(zis); + else + palette[i] = readPixel<T>(zis); + } + + if (palSize == 1) { + T pix = palette[0]; + pb->fillRect(pf, t, &pix); + continue; + } + + if (!rle) { + if (palSize == 0) { + + // raw + + if (isLowCPixel || isHighCPixel) + zlibHasData(zis, 3 * t.area()); + else + zlibHasData(zis, sizeof(T) * t.area()); + + if (isLowCPixel || isHighCPixel) { + for (T* ptr = buf; ptr < buf+t.area(); ptr++) { + if (isLowCPixel) + *ptr = readOpaque24A(zis); + else + *ptr = readOpaque24B(zis); + } + } else { + zis->readBytes(buf, t.area() * sizeof(T)); + } + + } else { + + // packed pixels + int bppp = ((palSize > 16) ? 8 : + ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1))); + + T* ptr = buf; + + for (int i = 0; i < t.height(); i++) { + T* eol = ptr + t.width(); + uint8_t byte = 0; + uint8_t nbits = 0; + + while (ptr < eol) { + if (nbits == 0) { + zlibHasData(zis, 1); + byte = zis->readU8(); + nbits = 8; + } + nbits -= bppp; + uint8_t index = (byte >> nbits) & ((1 << bppp) - 1) & 127; + *ptr++ = palette[index]; + } + } } - if ((fitsInLS3Bytes && pf.isBigEndian()) || - (fitsInMS3Bytes && pf.isLittleEndian())) - { - zrleDecode24B(r, &is, &zis, pf, pb); - break; + } else { + + if (palSize == 0) { + + // plain RLE + + T* ptr = buf; + T* end = ptr + t.area(); + while (ptr < end) { + T pix; + if (isLowCPixel || isHighCPixel) + zlibHasData(zis, 3); + else + zlibHasData(zis, sizeof(T)); + if (isLowCPixel) + pix = readOpaque24A(zis); + else if (isHighCPixel) + pix = readOpaque24B(zis); + else + pix = readPixel<T>(zis); + int len = 1; + int b; + do { + zlibHasData(zis, 1); + b = zis->readU8(); + len += b; + } while (b == 255); + + if (end - ptr < len) { + throw Exception ("ZRLE decode error"); + } + + while (len-- > 0) *ptr++ = pix; + + } + } else { + + // palette RLE + + T* ptr = buf; + T* end = ptr + t.area(); + while (ptr < end) { + zlibHasData(zis, 1); + int index = zis->readU8(); + int len = 1; + if (index & 128) { + int b; + do { + zlibHasData(zis, 1); + b = zis->readU8(); + len += b; + } while (b == 255); + + if (end - ptr < len) { + throw Exception ("ZRLE decode error"); + } + } + + index &= 127; + + T pix = palette[index]; + + while (len-- > 0) *ptr++ = pix; + } } } - zrleDecode32(r, &is, &zis, pf, pb); - break; + pb->imageRect(pf, t, buf); } } + + zis->flushUnderlying(); + zis->setUnderlying(NULL, 0); } diff --git a/common/rfb/ZRLEDecoder.h b/common/rfb/ZRLEDecoder.h index 115f8fb8..3885124a 100644 --- a/common/rfb/ZRLEDecoder.h +++ b/common/rfb/ZRLEDecoder.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014-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 @@ -23,6 +24,8 @@ namespace rfb { + class PixelFormat; + class ZRLEDecoder : public Decoder { public: ZRLEDecoder(); @@ -32,6 +35,13 @@ namespace rfb { virtual void decodeRect(const Rect& r, const void* buffer, size_t buflen, const ServerParams& server, ModifiablePixelBuffer* pb); + + private: + template<class T> + void zrleDecode(const Rect& r, rdr::InStream* is, + rdr::ZlibInStream* zis, + const PixelFormat& pf, ModifiablePixelBuffer* pb); + private: rdr::ZlibInStream zis; }; diff --git a/common/rfb/ZRLEEncoder.cxx b/common/rfb/ZRLEEncoder.cxx index 7d985401..4e25d49f 100644 --- a/common/rfb/ZRLEEncoder.cxx +++ b/common/rfb/ZRLEEncoder.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -96,7 +96,7 @@ void ZRLEEncoder::writeRect(const PixelBuffer* pb, const Palette& palette) void ZRLEEncoder::writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour) + const uint8_t* colour) { int tiles; @@ -122,7 +122,7 @@ void ZRLEEncoder::writeSolidRect(int width, int height, void ZRLEEncoder::writePaletteTile(const Rect& tile, const PixelBuffer* pb, const Palette& palette) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; buffer = pb->getBuffer(tile, &stride); @@ -130,17 +130,17 @@ void ZRLEEncoder::writePaletteTile(const Rect& tile, const PixelBuffer* pb, switch (pb->getPF().bpp) { case 32: writePaletteTile(tile.width(), tile.height(), - (rdr::U32*)buffer, stride, + (uint32_t*)buffer, stride, pb->getPF(), palette); break; case 16: writePaletteTile(tile.width(), tile.height(), - (rdr::U16*)buffer, stride, + (uint16_t*)buffer, stride, pb->getPF(), palette); break; default: writePaletteTile(tile.width(), tile.height(), - (rdr::U8*)buffer, stride, + (uint8_t*)buffer, stride, pb->getPF(), palette); } } @@ -148,7 +148,7 @@ void ZRLEEncoder::writePaletteTile(const Rect& tile, const PixelBuffer* pb, void ZRLEEncoder::writePaletteRLETile(const Rect& tile, const PixelBuffer* pb, const Palette& palette) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; buffer = pb->getBuffer(tile, &stride); @@ -156,24 +156,24 @@ void ZRLEEncoder::writePaletteRLETile(const Rect& tile, const PixelBuffer* pb, switch (pb->getPF().bpp) { case 32: writePaletteRLETile(tile.width(), tile.height(), - (rdr::U32*)buffer, stride, + (uint32_t*)buffer, stride, pb->getPF(), palette); break; case 16: writePaletteRLETile(tile.width(), tile.height(), - (rdr::U16*)buffer, stride, + (uint16_t*)buffer, stride, pb->getPF(), palette); break; default: writePaletteRLETile(tile.width(), tile.height(), - (rdr::U8*)buffer, stride, + (uint8_t*)buffer, stride, pb->getPF(), palette); } } void ZRLEEncoder::writeRawTile(const Rect& tile, const PixelBuffer* pb) { - const rdr::U8* buffer; + const uint8_t* buffer; int stride; int w, h, stride_bytes; @@ -193,22 +193,22 @@ void ZRLEEncoder::writeRawTile(const Rect& tile, const PixelBuffer* pb) void ZRLEEncoder::writePalette(const PixelFormat& pf, const Palette& palette) { - rdr::U8 buffer[256*4]; + uint8_t buffer[256*4]; int i; if (pf.bpp == 32) { - rdr::U32* buf; - buf = (rdr::U32*)buffer; + uint32_t* buf; + buf = (uint32_t*)buffer; for (i = 0;i < palette.size();i++) *buf++ = palette.getColour(i); } else if (pf.bpp == 16) { - rdr::U16* buf; - buf = (rdr::U16*)buffer; + uint16_t* buf; + buf = (uint16_t*)buffer; for (i = 0;i < palette.size();i++) *buf++ = palette.getColour(i); } else { - rdr::U8* buf; - buf = (rdr::U8*)buffer; + uint8_t* buf; + buf = (uint8_t*)buffer; for (i = 0;i < palette.size();i++) *buf++ = palette.getColour(i); } @@ -216,13 +216,13 @@ void ZRLEEncoder::writePalette(const PixelFormat& pf, const Palette& palette) writePixels(buffer, pf, palette.size()); } -void ZRLEEncoder::writePixels(const rdr::U8* buffer, const PixelFormat& pf, +void ZRLEEncoder::writePixels(const uint8_t* buffer, const PixelFormat& pf, unsigned int count) { Pixel maxPixel; - rdr::U8 pixBuf[4]; + uint8_t pixBuf[4]; - maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1); + maxPixel = pf.pixelFromRGB((uint16_t)-1, (uint16_t)-1, (uint16_t)-1); pf.bufferFromPixel(pixBuf, maxPixel); if ((pf.bpp != 32) || ((pixBuf[0] != 0) && (pixBuf[3] != 0))) { @@ -239,16 +239,110 @@ void ZRLEEncoder::writePixels(const rdr::U8* buffer, const PixelFormat& pf, } } -// -// Including BPP-dependent implementation of the encoder. -// - -#define BPP 8 -#include <rfb/ZRLEEncoderBPP.cxx> -#undef BPP -#define BPP 16 -#include <rfb/ZRLEEncoderBPP.cxx> -#undef BPP -#define BPP 32 -#include <rfb/ZRLEEncoderBPP.cxx> -#undef BPP +template<class T> +void ZRLEEncoder::writePaletteTile(int width, int height, + const T* buffer, int stride, + const PixelFormat& pf, + const Palette& palette) +{ + const int bitsPerPackedPixel[] = { + 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + }; + + int bppp; + int pad; + + assert(palette.size() > 1); + assert(palette.size() <= 16); + + zos.writeU8(palette.size()); + writePalette(pf, palette); + + bppp = bitsPerPackedPixel[palette.size()-1]; + pad = stride - width; + + for (int i = 0; i < height; i++) { + int w; + + uint8_t nbits = 0; + uint8_t byte = 0; + + w = width; + while (w--) { + T pix = *buffer++; + uint8_t index = palette.lookup(pix); + byte = (byte << bppp) | index; + nbits += bppp; + if (nbits >= 8) { + zos.writeU8(byte); + nbits = 0; + } + } + if (nbits > 0) { + byte <<= 8 - nbits; + zos.writeU8(byte); + } + + buffer += pad; + } +} + +template<class T> +void ZRLEEncoder::writePaletteRLETile(int width, int height, + const T* buffer, int stride, + const PixelFormat& pf, + const Palette& palette) +{ + int pad; + + T prevColour; + int runLength; + + assert(palette.size() > 1); + assert(palette.size() <= 127); + + zos.writeU8(palette.size() | 0x80); + writePalette(pf, palette); + + pad = stride - width; + + prevColour = *buffer; + runLength = 0; + + while (height--) { + int w = width; + while (w--) { + if (prevColour != *buffer) { + if (runLength == 1) + zos.writeU8(palette.lookup(prevColour)); + else { + zos.writeU8(palette.lookup(prevColour) | 0x80); + + while (runLength > 255) { + zos.writeU8(255); + runLength -= 255; + } + zos.writeU8(runLength - 1); + } + + prevColour = *buffer; + runLength = 0; + } + + runLength++; + buffer++; + } + buffer += pad; + } + if (runLength == 1) + zos.writeU8(palette.lookup(prevColour)); + else { + zos.writeU8(palette.lookup(prevColour) | 0x80); + + while (runLength > 255) { + zos.writeU8(255); + runLength -= 255; + } + zos.writeU8(runLength - 1); + } +} diff --git a/common/rfb/ZRLEEncoder.h b/common/rfb/ZRLEEncoder.h index 37a3be2d..4cfff75d 100644 --- a/common/rfb/ZRLEEncoder.h +++ b/common/rfb/ZRLEEncoder.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2014 Pierre Ossman for Cendio AB + * Copyright 2014-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 @@ -35,7 +35,7 @@ namespace rfb { virtual void writeRect(const PixelBuffer* pb, const Palette& palette); virtual void writeSolidRect(int width, int height, const PixelFormat& pf, - const rdr::U8* colour); + const uint8_t* colour); protected: void writePaletteTile(const Rect& tile, const PixelBuffer* pb, @@ -46,30 +46,18 @@ namespace rfb { void writePalette(const PixelFormat& pf, const Palette& palette); - void writePixels(const rdr::U8* buffer, const PixelFormat& pf, + void writePixels(const uint8_t* buffer, const PixelFormat& pf, unsigned int count); protected: - // Preprocessor generated, optimised methods - - void writePaletteTile(int width, int height, - const rdr::U8* buffer, int stride, - const PixelFormat& pf, const Palette& palette); - void writePaletteTile(int width, int height, - const rdr::U16* buffer, int stride, - const PixelFormat& pf, const Palette& palette); + // Templated, optimised methods + template<class T> void writePaletteTile(int width, int height, - const rdr::U32* buffer, int stride, + const T* buffer, int stride, const PixelFormat& pf, const Palette& palette); - - void writePaletteRLETile(int width, int height, - const rdr::U8* buffer, int stride, - const PixelFormat& pf, const Palette& palette); - void writePaletteRLETile(int width, int height, - const rdr::U16* buffer, int stride, - const PixelFormat& pf, const Palette& palette); + template<class T> void writePaletteRLETile(int width, int height, - const rdr::U32* buffer, int stride, + const T* buffer, int stride, const PixelFormat& pf, const Palette& palette); protected: diff --git a/common/rfb/ZRLEEncoderBPP.cxx b/common/rfb/ZRLEEncoderBPP.cxx deleted file mode 100644 index 90f395b3..00000000 --- a/common/rfb/ZRLEEncoderBPP.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. - */ - -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) - -#define UBPP CONCAT2E(U,BPP) - -void ZRLEEncoder::writePaletteTile(int width, int height, - const rdr::UBPP* buffer, int stride, - const PixelFormat& pf, - const Palette& palette) -{ - const int bitsPerPackedPixel[] = { - 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 - }; - - int bppp; - int pad; - - assert(palette.size() > 1); - assert(palette.size() <= 16); - - zos.writeU8(palette.size()); - writePalette(pf, palette); - - bppp = bitsPerPackedPixel[palette.size()-1]; - pad = stride - width; - - for (int i = 0; i < height; i++) { - int w; - - rdr::U8 nbits = 0; - rdr::U8 byte = 0; - - w = width; - while (w--) { - rdr::UBPP pix = *buffer++; - rdr::U8 index = palette.lookup(pix); - byte = (byte << bppp) | index; - nbits += bppp; - if (nbits >= 8) { - zos.writeU8(byte); - nbits = 0; - } - } - if (nbits > 0) { - byte <<= 8 - nbits; - zos.writeU8(byte); - } - - buffer += pad; - } -} - -void ZRLEEncoder::writePaletteRLETile(int width, int height, - const rdr::UBPP* buffer, int stride, - const PixelFormat& pf, - const Palette& palette) -{ - int pad; - - rdr::UBPP prevColour; - int runLength; - - assert(palette.size() > 1); - assert(palette.size() <= 127); - - zos.writeU8(palette.size() | 0x80); - writePalette(pf, palette); - - pad = stride - width; - - prevColour = *buffer; - runLength = 0; - - while (height--) { - int w = width; - while (w--) { - if (prevColour != *buffer) { - if (runLength == 1) - zos.writeU8(palette.lookup(prevColour)); - else { - zos.writeU8(palette.lookup(prevColour) | 0x80); - - while (runLength > 255) { - zos.writeU8(255); - runLength -= 255; - } - zos.writeU8(runLength - 1); - } - - prevColour = *buffer; - runLength = 0; - } - - runLength++; - buffer++; - } - buffer += pad; - } - if (runLength == 1) - zos.writeU8(palette.lookup(prevColour)); - else { - zos.writeU8(palette.lookup(prevColour) | 0x80); - - while (runLength > 255) { - zos.writeU8(255); - runLength -= 255; - } - zos.writeU8(runLength - 1); - } -} diff --git a/common/rfb/encodings.cxx b/common/rfb/encodings.cxx index b33dc6df..4acb569e 100644 --- a/common/rfb/encodings.cxx +++ b/common/rfb/encodings.cxx @@ -22,7 +22,6 @@ #include <string.h> #include <rfb/encodings.h> -#include <rfb/util.h> int rfb::encodingNum(const char* name) { diff --git a/common/rfb/fenceTypes.h b/common/rfb/fenceTypes.h index 41778602..fa507472 100644 --- a/common/rfb/fenceTypes.h +++ b/common/rfb/fenceTypes.h @@ -18,16 +18,16 @@ #ifndef __RFB_FENCETYPES_H__ #define __RFB_FENCETYPES_H__ -#include <rdr/types.h> +#include <stdint.h> namespace rfb { - const rdr::U32 fenceFlagBlockBefore = 1<<0; - const rdr::U32 fenceFlagBlockAfter = 1<<1; - const rdr::U32 fenceFlagSyncNext = 1<<2; + const uint32_t fenceFlagBlockBefore = 1<<0; + const uint32_t fenceFlagBlockAfter = 1<<1; + const uint32_t fenceFlagSyncNext = 1<<2; - const rdr::U32 fenceFlagRequest = 1<<31; + const uint32_t fenceFlagRequest = 1<<31; - const rdr::U32 fenceFlagsSupported = (fenceFlagBlockBefore | + const uint32_t fenceFlagsSupported = (fenceFlagBlockBefore | fenceFlagBlockAfter | fenceFlagSyncNext | fenceFlagRequest); diff --git a/common/rfb/hextileDecode.h b/common/rfb/hextileDecode.h deleted file mode 100644 index 402cd031..00000000 --- a/common/rfb/hextileDecode.h +++ /dev/null @@ -1,111 +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. - */ -// -// Hextile decoding function. -// -// This file is #included after having set the following macro: -// BPP - 8, 16 or 32 - -#include <rdr/InStream.h> -#include <rfb/Exception.h> -#include <rfb/hextileConstants.h> - -namespace rfb { - -// CONCAT2E concatenates its arguments, expanding them if they are macros - -#ifndef CONCAT2E -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) -#endif - -#define PIXEL_T rdr::CONCAT2E(U,BPP) -#define READ_PIXEL CONCAT2E(readOpaque,BPP) -#define HEXTILE_DECODE CONCAT2E(hextileDecode,BPP) - -static void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, - const PixelFormat& pf, - ModifiablePixelBuffer* pb) -{ - Rect t; - PIXEL_T bg = 0; - PIXEL_T fg = 0; - PIXEL_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); - - 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); - - int tileType = is->readU8(); - - if (tileType & hextileRaw) { - is->readBytes(buf, t.area() * (BPP/8)); - pb->imageRect(pf, t, buf); - continue; - } - - if (tileType & hextileBgSpecified) - bg = is->READ_PIXEL(); - - int len = t.area(); - PIXEL_T* ptr = buf; - while (len-- > 0) *ptr++ = bg; - - if (tileType & hextileFgSpecified) - fg = is->READ_PIXEL(); - - if (tileType & hextileAnySubrects) { - int nSubrects = is->readU8(); - - for (int i = 0; i < nSubrects; i++) { - - if (tileType & hextileSubrectsColoured) - fg = is->READ_PIXEL(); - - int xy = is->readU8(); - int wh = is->readU8(); - - int x = ((xy >> 4) & 15); - int y = (xy & 15); - int w = ((wh >> 4) & 15) + 1; - int h = (wh & 15) + 1; - if (x + w > 16 || y + h > 16) { - throw rfb::Exception("HEXTILE_DECODE: Hextile out of bounds"); - } - PIXEL_T* ptr = buf + y * t.width() + x; - int rowAdd = t.width() - w; - while (h-- > 0) { - int len = w; - while (len-- > 0) *ptr++ = fg; - ptr += rowAdd; - } - } - } - pb->imageRect(pf, t, buf); - } - } -} - -#undef PIXEL_T -#undef READ_PIXEL -#undef HEXTILE_DECODE -} diff --git a/common/rfb/hextileEncode.h b/common/rfb/hextileEncode.h deleted file mode 100644 index aa5926cc..00000000 --- a/common/rfb/hextileEncode.h +++ /dev/null @@ -1,223 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright (C) 2005 Constantin Kaplinsky. All Rights Reserved. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (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. - */ -// -// Hextile encoding function. -// -// This file is #included after having set the following macro: -// BPP - 8, 16 or 32 - -#include <rdr/OutStream.h> -#include <rfb/hextileConstants.h> - -namespace rfb { - -// CONCAT2E concatenates its arguments, expanding them if they are macros - -#ifndef CONCAT2E -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) -#endif - -#define PIXEL_T rdr::CONCAT2E(U,BPP) -#define WRITE_PIXEL CONCAT2E(writeOpaque,BPP) -#define HEXTILE_ENCODE CONCAT2E(hextileEncode,BPP) -#define HEXTILE_ENCODE_TILE CONCAT2E(hextileEncodeTile,BPP) -#define TEST_TILE_TYPE CONCAT2E(hextileTestTileType,BPP) - -int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg); -int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType, - rdr::U8* encoded, PIXEL_T bg); - -void HEXTILE_ENCODE(rdr::OutStream* os, const PixelBuffer* pb) -{ - Rect t; - PIXEL_T buf[256]; - PIXEL_T oldBg = 0, oldFg = 0; - bool oldBgValid = false; - bool oldFgValid = false; - rdr::U8 encoded[256*(BPP/8)]; - - for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) { - - t.br.y = __rfbmin(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); - - pb->getImage(buf, t); - - PIXEL_T bg = 0, fg = 0; - int tileType = TEST_TILE_TYPE(buf, t.width(), t.height(), &bg, &fg); - - if (!oldBgValid || oldBg != bg) { - tileType |= hextileBgSpecified; - oldBg = bg; - oldBgValid = true; - } - - int encodedLen = 0; - - if (tileType & hextileAnySubrects) { - - if (tileType & hextileSubrectsColoured) { - oldFgValid = false; - } else { - if (!oldFgValid || oldFg != fg) { - tileType |= hextileFgSpecified; - oldFg = fg; - oldFgValid = true; - } - } - - encodedLen = HEXTILE_ENCODE_TILE(buf, t.width(), t.height(), tileType, - encoded, bg); - - if (encodedLen < 0) { - pb->getImage(buf, t); - os->writeU8(hextileRaw); - os->writeBytes(buf, t.width() * t.height() * (BPP/8)); - oldBgValid = oldFgValid = false; - continue; - } - } - - os->writeU8(tileType); - if (tileType & hextileBgSpecified) os->WRITE_PIXEL(bg); - if (tileType & hextileFgSpecified) os->WRITE_PIXEL(fg); - if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen); - } - } -} - - -int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType, - rdr::U8* encoded, PIXEL_T bg) -{ - rdr::U8* nSubrectsPtr = encoded; - *nSubrectsPtr = 0; - encoded++; - - for (int y = 0; y < h; y++) - { - int x = 0; - while (x < w) { - if (*data == bg) { - x++; - data++; - continue; - } - - // Find horizontal subrect first - PIXEL_T* ptr = data+1; - PIXEL_T* eol = data+w-x; - while (ptr < eol && *ptr == *data) ptr++; - int sw = ptr - data; - - ptr = data + w; - int sh = 1; - while (sh < h-y) { - eol = ptr + sw; - while (ptr < eol) - if (*ptr++ != *data) goto endOfSubrect; - ptr += w - sw; - sh++; - } - endOfSubrect: - - (*nSubrectsPtr)++; - - if (tileType & hextileSubrectsColoured) { - if (encoded - nSubrectsPtr + (BPP/8) > w*h*(BPP/8)) return -1; -#if (BPP == 8) - *encoded++ = *data; -#elif (BPP == 16) - *encoded++ = ((rdr::U8*)data)[0]; - *encoded++ = ((rdr::U8*)data)[1]; -#elif (BPP == 32) - *encoded++ = ((rdr::U8*)data)[0]; - *encoded++ = ((rdr::U8*)data)[1]; - *encoded++ = ((rdr::U8*)data)[2]; - *encoded++ = ((rdr::U8*)data)[3]; -#endif - } - - if (encoded - nSubrectsPtr + 2 > w*h*(BPP/8)) return -1; - *encoded++ = (x << 4) | y; - *encoded++ = ((sw-1) << 4) | (sh-1); - - ptr = data+w; - PIXEL_T* eor = data+w*sh; - while (ptr < eor) { - eol = ptr + sw; - while (ptr < eol) *ptr++ = bg; - ptr += w - sw; - } - x += sw; - data += sw; - } - } - return encoded - nSubrectsPtr; -} - - -int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg) -{ - PIXEL_T pix1 = *data; - PIXEL_T* end = data + w * h; - - PIXEL_T* ptr = data + 1; - while (ptr < end && *ptr == pix1) - ptr++; - - if (ptr == end) { - *bg = pix1; - return 0; // solid-color tile - } - - int count1 = ptr - data; - int count2 = 1; - PIXEL_T pix2 = *ptr++; - int tileType = hextileAnySubrects; - - for (; ptr < end; ptr++) { - if (*ptr == pix1) { - count1++; - } else if (*ptr == pix2) { - count2++; - } else { - tileType |= hextileSubrectsColoured; - break; - } - } - - if (count1 >= count2) { - *bg = pix1; *fg = pix2; - } else { - *bg = pix2; *fg = pix1; - } - return tileType; -} - -#undef PIXEL_T -#undef WRITE_PIXEL -#undef HEXTILE_ENCODE -#undef HEXTILE_ENCODE_TILE -#undef TEST_TILE_TYPE -} diff --git a/common/rfb/hextileEncodeBetter.h b/common/rfb/hextileEncodeBetter.h deleted file mode 100644 index bc9dcaca..00000000 --- a/common/rfb/hextileEncodeBetter.h +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. - * Copyright (C) 2005 Constantin Kaplinsky. All Rights Reserved. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (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. - */ -// -// Hextile encoding function. -// -// This file is #included after having set the following macro: -// BPP - 8, 16 or 32 - -#include <rdr/OutStream.h> -#include <rfb/hextileConstants.h> -#include <rfb/Palette.h> - -#include <assert.h> - -namespace rfb { - -// CONCAT2E concatenates its arguments, expanding them if they are macros - -#ifndef CONCAT2E -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) -#endif - -#define PIXEL_T rdr::CONCAT2E(U,BPP) -#define WRITE_PIXEL CONCAT2E(writeOpaque,BPP) -#define HEXTILE_TILE CONCAT2E(HextileTile,BPP) -#define HEXTILE_ENCODE CONCAT2E(hextileEncodeBetter,BPP) - -// -// This class analyzes a separate tile and encodes its subrectangles. -// - -class HEXTILE_TILE { - - public: - - HEXTILE_TILE (); - - // - // Initialize existing object instance with new tile data. - // - void newTile(const PIXEL_T *src, int w, int h); - - // - // Flags can include: hextileRaw, hextileAnySubrects and - // hextileSubrectsColoured. Note that if hextileRaw is set, other - // flags make no sense. Also, hextileSubrectsColoured is meaningful - // only when hextileAnySubrects is set as well. - // - int getFlags() const { return m_flags; } - - // - // Returns the size of encoded subrects data, including subrect count. - // The size is zero if flags do not include hextileAnySubrects. - // - int getSize() const { return m_size; } - - // - // Return optimal background. - // - int getBackground() const { return m_background; } - - // - // Return foreground if flags include hextileSubrectsColoured. - // - int getForeground() const { return m_foreground; } - - // - // Encode subrects. This function may be called only if - // hextileAnySubrects bit is set in flags. The buffer size should be - // big enough to store at least the number of bytes returned by the - // getSize() method. - // - void encode(rdr::U8* dst) const; - - protected: - - // - // Analyze the tile pixels, fill in all the data fields. - // - void analyze(); - - const PIXEL_T *m_tile; - int m_width; - int m_height; - - int m_size; - int m_flags; - PIXEL_T m_background; - PIXEL_T m_foreground; - - int m_numSubrects; - rdr::U8 m_coords[256 * 2]; - PIXEL_T m_colors[256]; - - private: - - bool m_processed[16][16]; - Palette m_pal; -}; - -HEXTILE_TILE::HEXTILE_TILE() - : m_tile(NULL), m_width(0), m_height(0), - m_size(0), m_flags(0), m_background(0), m_foreground(0), - m_numSubrects(0) -{ -} - -void HEXTILE_TILE::newTile(const PIXEL_T *src, int w, int h) -{ - m_tile = src; - m_width = w; - m_height = h; - - analyze(); -} - -void HEXTILE_TILE::analyze() -{ - assert(m_tile && m_width && m_height); - - const PIXEL_T *ptr = m_tile; - const PIXEL_T *end = &m_tile[m_width * m_height]; - PIXEL_T color = *ptr++; - while (ptr != end && *ptr == color) - ptr++; - - // Handle solid tile - if (ptr == end) { - m_background = m_tile[0]; - m_flags = 0; - m_size = 0; - return; - } - - // Compute number of complete rows of the same color, at the top - int y = (ptr - m_tile) / m_width; - - PIXEL_T *colorsPtr = m_colors; - rdr::U8 *coordsPtr = m_coords; - m_pal.clear(); - m_numSubrects = 0; - - // Have we found the first subrect already? - if (y > 0) { - *colorsPtr++ = color; - *coordsPtr++ = 0; - *coordsPtr++ = (rdr::U8)(((m_width - 1) << 4) | ((y - 1) & 0x0F)); - m_pal.insert(color, 1); - m_numSubrects++; - } - - memset(m_processed, 0, 16 * 16 * sizeof(bool)); - - int x, sx, sy, sw, sh, max_x; - - for (; y < m_height; y++) { - for (x = 0; x < m_width; x++) { - // Skip pixels that were processed earlier - if (m_processed[y][x]) { - continue; - } - // Determine dimensions of the horizontal subrect - color = m_tile[y * m_width + x]; - for (sx = x + 1; sx < m_width; sx++) { - if (m_tile[y * m_width + sx] != color) - break; - } - sw = sx - x; - max_x = sx; - for (sy = y + 1; sy < m_height; sy++) { - for (sx = x; sx < max_x; sx++) { - if (m_tile[sy * m_width + sx] != color) - goto done; - } - } - done: - sh = sy - y; - - // Save properties of this subrect - *colorsPtr++ = color; - *coordsPtr++ = (rdr::U8)((x << 4) | (y & 0x0F)); - *coordsPtr++ = (rdr::U8)(((sw - 1) << 4) | ((sh - 1) & 0x0F)); - - if (!m_pal.insert(color, 1) || (m_pal.size() > (48 + 2 * BPP))) { - // Handle palette overflow - m_flags = hextileRaw; - m_size = 0; - return; - } - - m_numSubrects++; - - // Mark pixels of this subrect as processed, below this row - for (sy = y + 1; sy < y + sh; sy++) { - for (sx = x; sx < x + sw; sx++) - m_processed[sy][sx] = true; - } - - // Skip processed pixels of this row - x += (sw - 1); - } - } - - // Save number of colors in this tile (should be no less than 2) - int numColors = m_pal.size(); - assert(numColors >= 2); - - m_background = (PIXEL_T)m_pal.getColour(0); - m_flags = hextileAnySubrects; - int numSubrects = m_numSubrects - m_pal.getCount(0); - - if (numColors == 2) { - // Monochrome tile - m_foreground = (PIXEL_T)m_pal.getColour(1); - m_size = 1 + 2 * numSubrects; - } else { - // Colored tile - m_flags |= hextileSubrectsColoured; - m_size = 1 + (2 + (BPP/8)) * numSubrects; - } -} - -void HEXTILE_TILE::encode(rdr::U8 *dst) const -{ - assert(m_numSubrects && (m_flags & hextileAnySubrects)); - - // Zero subrects counter - rdr::U8 *numSubrectsPtr = dst; - *dst++ = 0; - - for (int i = 0; i < m_numSubrects; i++) { - if (m_colors[i] == m_background) - continue; - - if (m_flags & hextileSubrectsColoured) { -#if (BPP == 8) - *dst++ = m_colors[i]; -#elif (BPP == 16) - *dst++ = ((rdr::U8*)&m_colors[i])[0]; - *dst++ = ((rdr::U8*)&m_colors[i])[1]; -#elif (BPP == 32) - *dst++ = ((rdr::U8*)&m_colors[i])[0]; - *dst++ = ((rdr::U8*)&m_colors[i])[1]; - *dst++ = ((rdr::U8*)&m_colors[i])[2]; - *dst++ = ((rdr::U8*)&m_colors[i])[3]; -#endif - } - *dst++ = m_coords[i * 2]; - *dst++ = m_coords[i * 2 + 1]; - - (*numSubrectsPtr)++; - } - - assert(dst - numSubrectsPtr == m_size); -} - -// -// Main encoding function. -// - -void HEXTILE_ENCODE(rdr::OutStream* os, const PixelBuffer* pb) -{ - Rect t; - PIXEL_T buf[256]; - PIXEL_T oldBg = 0, oldFg = 0; - bool oldBgValid = false; - bool oldFgValid = false; - rdr::U8 encoded[256*(BPP/8)]; - - HEXTILE_TILE tile; - - for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) { - - t.br.y = __rfbmin(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); - - pb->getImage(buf, t); - - tile.newTile(buf, t.width(), t.height()); - int tileType = tile.getFlags(); - int encodedLen = tile.getSize(); - - if ( (tileType & hextileRaw) != 0 || - encodedLen >= t.width() * t.height() * (BPP/8)) { - os->writeU8(hextileRaw); - os->writeBytes(buf, t.width() * t.height() * (BPP/8)); - oldBgValid = oldFgValid = false; - continue; - } - - PIXEL_T bg = tile.getBackground(); - PIXEL_T fg = 0; - - if (!oldBgValid || oldBg != bg) { - tileType |= hextileBgSpecified; - oldBg = bg; - oldBgValid = true; - } - - if (tileType & hextileAnySubrects) { - if (tileType & hextileSubrectsColoured) { - oldFgValid = false; - } else { - fg = tile.getForeground(); - if (!oldFgValid || oldFg != fg) { - tileType |= hextileFgSpecified; - oldFg = fg; - oldFgValid = true; - } - } - tile.encode(encoded); - } - - os->writeU8(tileType); - if (tileType & hextileBgSpecified) os->WRITE_PIXEL(bg); - if (tileType & hextileFgSpecified) os->WRITE_PIXEL(fg); - if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen); - } - } -} - -#undef PIXEL_T -#undef WRITE_PIXEL -#undef HEXTILE_TILE -#undef HEXTILE_ENCODE -} diff --git a/common/rfb/Password.cxx b/common/rfb/obfuscate.cxx index a7aaeccc..1f785893 100644 --- a/common/rfb/Password.cxx +++ b/common/rfb/obfuscate.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 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 @@ -24,61 +25,45 @@ #include <config.h> #endif +#include <assert.h> #include <string.h> + extern "C" { #include <rfb/d3des.h> } -#include <rdr/types.h> -#include <rdr/Exception.h> -#include <rfb/Password.h> -using namespace rfb; +#include <rdr/Exception.h> +#include <rfb/obfuscate.h> static unsigned char d3desObfuscationKey[] = {23,82,107,6,35,78,88,7}; +std::vector<uint8_t> rfb::obfuscate(const char *str) +{ + std::vector<uint8_t> buf(8); -PlainPasswd::PlainPasswd() {} - -PlainPasswd::PlainPasswd(char* pwd) : CharArray(pwd) { -} - -PlainPasswd::PlainPasswd(size_t len) : CharArray(len) { -} - -PlainPasswd::PlainPasswd(const ObfuscatedPasswd& obfPwd) : CharArray(9) { - if (obfPwd.length < 8) - throw rdr::Exception("bad obfuscated password length"); - deskey(d3desObfuscationKey, DE1); - des((rdr::U8*)obfPwd.buf, (rdr::U8*)buf); - buf[8] = 0; -} + assert(str != NULL); -PlainPasswd::~PlainPasswd() { - replaceBuf(0); -} + size_t l = strlen(str), i; + for (i=0; i<8; i++) + buf[i] = i<l ? str[i] : 0; + deskey(d3desObfuscationKey, EN0); + des(buf.data(), buf.data()); -void PlainPasswd::replaceBuf(char* b) { - if (buf) - memset(buf, 0, strlen(buf)); - CharArray::replaceBuf(b); + return buf; } +std::string rfb::deobfuscate(const uint8_t *data, size_t len) +{ + char buf[9]; -ObfuscatedPasswd::ObfuscatedPasswd() : length(0) { -} + assert(data != NULL); -ObfuscatedPasswd::ObfuscatedPasswd(size_t len) : CharArray(len), length(len) { -} + if (len != 8) + throw rdr::Exception("bad obfuscated password length"); -ObfuscatedPasswd::ObfuscatedPasswd(const PlainPasswd& plainPwd) : CharArray(8), length(8) { - size_t l = strlen(plainPwd.buf), i; - for (i=0; i<8; i++) - buf[i] = i<l ? plainPwd.buf[i] : 0; - deskey(d3desObfuscationKey, EN0); - des((rdr::U8*)buf, (rdr::U8*)buf); -} + deskey(d3desObfuscationKey, DE1); + des((uint8_t*)data, (uint8_t*)buf); + buf[8] = 0; -ObfuscatedPasswd::~ObfuscatedPasswd() { - if (buf) - memset(buf, 0, length); + return buf; } diff --git a/common/rfb/Pixel.h b/common/rfb/obfuscate.h index 4e9d1644..96a90e44 100644 --- a/common/rfb/Pixel.h +++ b/common/rfb/obfuscate.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 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 @@ -15,12 +16,20 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ -#ifndef __RFB_PIXEL_H__ -#define __RFB_PIXEL_H__ -#include <rdr/types.h> +#ifndef __RFB_OBFUSCATE_H__ +#define __RFB_OBFUSCATE_H__ + +#include <stdint.h> + +#include <string> +#include <vector> namespace rfb { - typedef rdr::U32 Pixel; // must be big enough to hold any pixel value + + std::vector<uint8_t> obfuscate(const char *str); + std::string deobfuscate(const uint8_t *data, size_t len); + } + #endif diff --git a/common/rfb/rreDecode.h b/common/rfb/rreDecode.h deleted file mode 100644 index f9fdcfc9..00000000 --- a/common/rfb/rreDecode.h +++ /dev/null @@ -1,64 +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. - */ -// -// RRE decoding function. -// -// This file is #included after having set the following macro: -// BPP - 8, 16 or 32 - -#include <rdr/InStream.h> -#include <rfb/Exception.h> - -namespace rfb { - -// CONCAT2E concatenates its arguments, expanding them if they are macros - -#ifndef CONCAT2E -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) -#endif - -#define PIXEL_T rdr::CONCAT2E(U,BPP) -#define READ_PIXEL CONCAT2E(readOpaque,BPP) -#define RRE_DECODE CONCAT2E(rreDecode,BPP) - -void RRE_DECODE (const Rect& r, rdr::InStream* is, - const PixelFormat& pf, ModifiablePixelBuffer* pb) -{ - int nSubrects = is->readU32(); - PIXEL_T bg = is->READ_PIXEL(); - pb->fillRect(pf, r, &bg); - - for (int i = 0; i < nSubrects; i++) { - PIXEL_T pix = is->READ_PIXEL(); - int x = is->readU16(); - int y = is->readU16(); - int w = is->readU16(); - int h = is->readU16(); - - if (((x+w) > r.width()) || ((y+h) > r.height())) - throw Exception ("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); - } -} - -#undef PIXEL_T -#undef READ_PIXEL -#undef RRE_DECODE -} diff --git a/common/rfb/rreEncode.h b/common/rfb/rreEncode.h deleted file mode 100644 index c8bbee7a..00000000 --- a/common/rfb/rreEncode.h +++ /dev/null @@ -1,124 +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. - */ -// -// RRE encoding function. -// -// This file is #included after having set the following macro: -// BPP - 8, 16 or 32 -// -// The data argument to RRE_ENCODE contains the pixel data, and it writes the -// encoded version to the given OutStream. If the encoded version exceeds w*h -// it aborts and returns -1, otherwise it returns the number of subrectangles. -// - -#include <rdr/OutStream.h> - -namespace rfb { - -// CONCAT2E concatenates its arguments, expanding them if they are macros - -#ifndef CONCAT2E -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) -#endif - -#define PIXEL_T rdr::CONCAT2E(U,BPP) -#define WRITE_PIXEL CONCAT2E(writeOpaque,BPP) -#define RRE_ENCODE CONCAT2E(rreEncode,BPP) - -int RRE_ENCODE (PIXEL_T* data, int w, int h, rdr::OutStream* os, PIXEL_T bg) -{ - os->WRITE_PIXEL(bg); - - int nSubrects = 0; - - for (int y = 0; y < h; y++) - { - int x = 0; - while (x < w) { - if (*data == bg) { - x++; - data++; - continue; - } - - // Find horizontal subrect first - PIXEL_T* ptr = data+1; - PIXEL_T* eol = data+w-x; - while (ptr < eol && *ptr == *data) ptr++; - int sw = ptr - data; - - ptr = data + w; - int sh = 1; - while (sh < h-y) { - eol = ptr + sw; - while (ptr < eol) - if (*ptr++ != *data) goto endOfHorizSubrect; - ptr += w - sw; - sh++; - } - endOfHorizSubrect: - - // Find vertical subrect - int vh; - for (vh = sh; vh < h-y; vh++) - if (data[vh*w] != *data) break; - - if (vh != sh) { - ptr = data+1; - int vw; - for (vw = 1; vw < sw; vw++) { - for (int i = 0; i < vh; i++) - if (ptr[i*w] != *data) goto endOfVertSubrect; - ptr++; - } - endOfVertSubrect: - - // If vertical subrect bigger than horizontal then use that. - if (sw*sh < vw*vh) { - sw = vw; - sh = vh; - } - } - - nSubrects++; - os->WRITE_PIXEL(*data); - os->writeU16(x); - os->writeU16(y); - os->writeU16(sw); - os->writeU16(sh); - - ptr = data+w; - PIXEL_T* eor = data+w*sh; - while (ptr < eor) { - eol = ptr + sw; - while (ptr < eol) *ptr++ = bg; - ptr += w - sw; - } - x += sw; - data += sw; - } - } - - return nSubrects; -} - -#undef PIXEL_T -#undef WRITE_PIXEL -#undef RRE_ENCODE -} diff --git a/common/rfb/tightDecode.h b/common/rfb/tightDecode.h deleted file mode 100644 index 8f77aebd..00000000 --- a/common/rfb/tightDecode.h +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. - * Copyright 2004-2005 Cendio AB. - * Copyright 2009-2015 Pierre Ossman for Cendio AB - * Copyright (C) 2011 D. R. Commander. All Rights Reserved. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -// -// Tight decoding functions. -// -// This file is #included after having set the following macro: -// BPP - 8, 16 or 32 - -namespace rfb { - -// CONCAT2E concatenates its arguments, expanding them if they are macros - -#ifndef CONCAT2E -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) -#endif - -#define PIXEL_T rdr::CONCAT2E(U,BPP) - -#if BPP == 32 - -void -TightDecoder::FilterGradient24(const rdr::U8 *inbuf, - const PixelFormat& pf, PIXEL_T* outbuf, - int stride, const Rect& r) -{ - int x, y, c; - rdr::U8 prevRow[TIGHT_MAX_WIDTH*3]; - rdr::U8 thisRow[TIGHT_MAX_WIDTH*3]; - rdr::U8 pix[3]; - int est[3]; - - memset(prevRow, 0, sizeof(prevRow)); - - // Set up shortcut variables - int rectHeight = r.height(); - int rectWidth = r.width(); - - for (y = 0; y < rectHeight; y++) { - for (x = 0; x < rectWidth; x++) { - /* First pixel in a row */ - if (x == 0) { - for (c = 0; c < 3; c++) { - pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c]; - thisRow[c] = pix[c]; - } - pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1); - continue; - } - - for (c = 0; c < 3; c++) { - est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; - if (est[c] > 0xff) { - est[c] = 0xff; - } else if (est[c] < 0) { - est[c] = 0; - } - pix[c] = inbuf[(y*rectWidth+x)*3+c] + est[c]; - thisRow[x*3+c] = pix[c]; - } - pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1); - } - - memcpy(prevRow, thisRow, sizeof(prevRow)); - } -} - -#endif - -#if BPP != 8 - -void TightDecoder::FilterGradient(const rdr::U8* inbuf, - const PixelFormat& pf, PIXEL_T* outbuf, - int stride, const Rect& r) -{ - int x, y, c; - static rdr::U8 prevRow[TIGHT_MAX_WIDTH*3]; - static rdr::U8 thisRow[TIGHT_MAX_WIDTH*3]; - rdr::U8 pix[3]; - int est[3]; - - memset(prevRow, 0, sizeof(prevRow)); - - // Set up shortcut variables - int rectHeight = r.height(); - int rectWidth = r.width(); - - for (y = 0; y < rectHeight; y++) { - for (x = 0; x < rectWidth; x++) { - /* First pixel in a row */ - if (x == 0) { - pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1); - for (c = 0; c < 3; c++) - pix[c] += prevRow[c]; - - memcpy(thisRow, pix, sizeof(pix)); - - pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1); - - continue; - } - - for (c = 0; c < 3; c++) { - est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; - if (est[c] > 255) { - est[c] = 255; - } else if (est[c] < 0) { - est[c] = 0; - } - } - - pf.rgbFromBuffer(pix, &inbuf[y*rectWidth+x], 1); - for (c = 0; c < 3; c++) - pix[c] += est[c]; - - memcpy(&thisRow[x*3], pix, sizeof(pix)); - - pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride+x], pix, 1); - } - - memcpy(prevRow, thisRow, sizeof(prevRow)); - } -} - -#endif - -void TightDecoder::FilterPalette(const PIXEL_T* palette, int palSize, - const rdr::U8* inbuf, PIXEL_T* outbuf, - int stride, const Rect& r) -{ - // Indexed color - int x, h = r.height(), w = r.width(), b, pad = stride - w; - PIXEL_T* ptr = outbuf; - rdr::U8 bits; - const rdr::U8* srcPtr = inbuf; - if (palSize <= 2) { - // 2-color palette - while (h > 0) { - for (x = 0; x < w / 8; x++) { - bits = *srcPtr++; - for (b = 7; b >= 0; b--) { - *ptr++ = palette[bits >> b & 1]; - } - } - if (w % 8 != 0) { - bits = *srcPtr++; - for (b = 7; b >= 8 - w % 8; b--) { - *ptr++ = palette[bits >> b & 1]; - } - } - ptr += pad; - h--; - } - } else { - // 256-color palette - while (h > 0) { - PIXEL_T *endOfRow = ptr + w; - while (ptr < endOfRow) { - *ptr++ = palette[*srcPtr++]; - } - ptr += pad; - h--; - } - } -} - -#undef PIXEL_T -} diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx index 649eb0ba..c5c00bbd 100644 --- a/common/rfb/util.cxx +++ b/common/rfb/util.cxx @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2019 Pierre Ossman for Cendio AB + * 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 @@ -21,110 +21,148 @@ #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 { - void CharArray::format(const char *fmt, ...) { + std::string format(const char *fmt, ...) + { va_list ap; int len; + char *buf; + std::string out; va_start(ap, fmt); len = vsnprintf(NULL, 0, fmt, ap); va_end(ap); - delete [] buf; - - if (len < 0) { - buf = new char[1]; - buf[0] = '\0'; - return; - } + 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; } - char* strDup(const char* s) { - if (!s) return 0; - int l = strlen(s); - char* r = new char[l+1]; - memcpy(r, s, l+1); - return r; - }; + 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 == NULL) { + out.push_back(start); + } else { + out.push_back(std::string(start, stop-start)); + start = stop + 1; + } + } while (stop != NULL); - void strFree(char* s) { - delete [] s; + return out; } - void strFree(wchar_t* s) { - delete [] s; + 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; - bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) { - CharArray out1old, out2old; - if (out1) out1old.buf = *out1; - if (out2) out2old.buf = *out2; - int len = strlen(src); - int i=0, increment=1, limit=len; - if (fromEnd) { - i=len-1; increment = -1; limit = -1; + if (inlen > 0) { + assert(in); + assert(out); } - while (i!=limit) { - if (src[i] == limiter) { - if (out1) { - *out1 = new char[i+1]; - if (i) memcpy(*out1, src, i); - (*out1)[i] = 0; - } - if (out2) { - *out2 = new char[len-i]; - if (len-i-1) memcpy(*out2, &src[i+1], len-i-1); - (*out2)[len-i-1] = 0; - } - return true; - } - i+=increment; + + for (size_t i=0; i<inlen; i++) { + out[i*2] = intToHex((in[i] >> 4) & 15); + out[i*2+1] = intToHex((in[i] & 15)); } - if (out1) *out1 = strDup(src); - if (out2) *out2 = 0; - return false; } - bool strContains(const char* src, char c) { - int l=strlen(src); - for (int i=0; i<l; i++) - if (src[i] == c) return true; - return false; + 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; } - void strCopy(char* dest, const char* src, int destlen) { - if (src) - strncpy(dest, src, destlen-1); - dest[src ? destlen-1 : 0] = 0; + bool hexToBin(const char* in, size_t inlen, + uint8_t* out, size_t outlen) { + assert(in); + assert(out); + + 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; } - char* convertLF(const char* src, size_t bytes) + 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) { - char* buffer; size_t sz; + std::string out; - char* out; const char* in; size_t in_len; - // Always include space for a NULL - sz = 1; - // Compute output size + sz = 0; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { @@ -142,44 +180,39 @@ namespace rfb { in_len--; } - // Alloc - buffer = new char[sz]; - memset(buffer, 0, sz); + // Reserve space + out.reserve(sz); // And convert - out = buffer; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { if (*in != '\r') { - *out++ = *in++; + out += *in++; in_len--; continue; } if ((in_len < 2) || (*(in+1) != '\n')) - *out++ = '\n'; + out += '\n'; in++; in_len--; } - return buffer; + return out; } - char* convertCRLF(const char* src, size_t bytes) + std::string convertCRLF(const char* src, size_t bytes) { - char* buffer; + std::string out; size_t sz; - char* out; const char* in; size_t in_len; - // Always include space for a NULL - sz = 1; - // Compute output size + sz = 0; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { @@ -197,38 +230,33 @@ namespace rfb { in_len--; } - // Alloc - buffer = new char[sz]; - memset(buffer, 0, sz); + // Reserve space + out.reserve(sz); // And convert - out = buffer; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { if (*in == '\n') { if ((in == src) || (*(in-1) != '\r')) - *out++ = '\r'; + out += '\r'; } - *out = *in; + out += *in; if (*in == '\r') { - if ((in_len < 2) || (*(in+1) != '\n')) { - out++; - *out = '\n'; - } + if ((in_len < 2) || (*(in+1) != '\n')) + out += '\n'; } - out++; in++; in_len--; } - return buffer; + return out; } - size_t ucs4ToUTF8(unsigned src, char* dst) { + size_t ucs4ToUTF8(unsigned src, char dst[5]) { if (src < 0x80) { *dst++ = src; *dst++ = '\0'; @@ -309,7 +337,7 @@ namespace rfb { return consumed; } - size_t ucs4ToUTF16(unsigned src, wchar_t* dst) { + size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]) { if ((src < 0xd800) || ((src >= 0xe000) && (src < 0x10000))) { *dst++ = src; *dst++ = L'\0'; @@ -365,18 +393,15 @@ namespace rfb { return 2; } - char* latin1ToUTF8(const char* src, size_t bytes) { - char* buffer; + std::string latin1ToUTF8(const char* src, size_t bytes) { + std::string out; size_t sz; - char* out; const char* in; size_t in_len; - // Always include space for a NULL - sz = 1; - // Compute output size + sz = 0; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { @@ -386,35 +411,32 @@ namespace rfb { in_len--; } - // Alloc - buffer = new char[sz]; - memset(buffer, 0, sz); + // Reserve space + out.reserve(sz); // And convert - out = buffer; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { - out += ucs4ToUTF8(*(const unsigned char*)in, out); + char buf[5]; + ucs4ToUTF8(*(const unsigned char*)in, buf); + out += buf; in++; in_len--; } - return buffer; + return out; } - char* utf8ToLatin1(const char* src, size_t bytes) { - char* buffer; + std::string utf8ToLatin1(const char* src, size_t bytes) { + std::string out; size_t sz; - char* out; const char* in; size_t in_len; - // Always include space for a NULL - sz = 1; - // Compute output size + sz = 0; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { @@ -427,12 +449,10 @@ namespace rfb { sz++; } - // Alloc - buffer = new char[sz]; - memset(buffer, 0, sz); + // Reserve space + out.reserve(sz); // And convert - out = buffer; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { @@ -444,27 +464,24 @@ namespace rfb { in_len -= len; if (ucs > 0xff) - *out++ = '?'; + out += '?'; else - *out++ = (unsigned char)ucs; + out += (unsigned char)ucs; } - return buffer; + return out; } - char* utf16ToUTF8(const wchar_t* src, size_t units) + std::string utf16ToUTF8(const wchar_t* src, size_t units) { - char* buffer; + std::string out; size_t sz; - char* out; const wchar_t* in; size_t in_len; - // Always include space for a NULL - sz = 1; - // Compute output size + sz = 0; in = src; in_len = units; while ((in_len > 0) && (*in != '\0')) { @@ -479,41 +496,38 @@ namespace rfb { sz += ucs4ToUTF8(ucs, buf); } - // Alloc - buffer = new char[sz]; - memset(buffer, 0, sz); + // Reserve space + out.reserve(sz); // And convert - out = buffer; 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; - out += ucs4ToUTF8(ucs, out); + ucs4ToUTF8(ucs, buf); + out += buf; } - return buffer; + return out; } - wchar_t* utf8ToUTF16(const char* src, size_t bytes) + std::wstring utf8ToUTF16(const char* src, size_t bytes) { - wchar_t* buffer; + std::wstring out; size_t sz; - wchar_t* out; const char* in; size_t in_len; - // Always include space for a NULL - sz = 1; - // Compute output size + sz = 0; in = src; in_len = bytes; while ((in_len > 0) && (*in != '\0')) { @@ -528,26 +542,26 @@ namespace rfb { sz += ucs4ToUTF16(ucs, buf); } - // Alloc - buffer = new wchar_t[sz]; - memset(buffer, 0, sz * sizeof(wchar_t)); + // Reserve space + out.reserve(sz); // And convert - out = buffer; 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; - out += ucs4ToUTF16(ucs, out); + ucs4ToUTF16(ucs, buf); + out += buf; } - return buffer; + return out; } unsigned msBetween(const struct timeval *first, @@ -584,12 +598,12 @@ namespace rfb { return false; } - static size_t doPrefix(long long value, const char *unit, - char *buffer, size_t maxlen, - unsigned divisor, const char **prefixes, - size_t prefixCount, int precision) { + 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, len; + size_t prefix; newValue = value; prefix = 0; @@ -600,11 +614,11 @@ namespace rfb { prefix++; } - len = snprintf(buffer, maxlen, "%.*g %s%s", precision, newValue, - (prefix == 0) ? "" : prefixes[prefix-1], unit); - buffer[maxlen-1] = '\0'; + snprintf(buffer, sizeof(buffer), "%.*g %s%s", precision, newValue, + (prefix == 0) ? "" : prefixes[prefix-1], unit); + buffer[sizeof(buffer)-1] = '\0'; - return len; + return buffer; } static const char *siPrefixes[] = @@ -612,16 +626,16 @@ namespace rfb { static const char *iecPrefixes[] = { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; - size_t siPrefix(long long value, const char *unit, - char *buffer, size_t maxlen, int precision) { - return doPrefix(value, unit, buffer, maxlen, 1000, siPrefixes, + std::string siPrefix(long long value, const char *unit, + int precision) { + return doPrefix(value, unit, 1000, siPrefixes, sizeof(siPrefixes)/sizeof(*siPrefixes), precision); } - size_t iecPrefix(long long value, const char *unit, - char *buffer, size_t maxlen, int precision) { - return doPrefix(value, unit, buffer, maxlen, 1024, iecPrefixes, + 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 index 99d350e3..34811e3f 100644 --- a/common/rfb/util.h +++ b/common/rfb/util.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2019 Pierre Ossman for Cendio AB + * 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 @@ -25,73 +25,48 @@ #define __RFB_UTIL_H__ #include <limits.h> -#include <string.h> +#include <stdint.h> + +#include <string> +#include <vector> struct timeval; namespace rfb { - // -=- Class to handle cleanup of arrays of characters - class CharArray { - public: - CharArray() : buf(0) {} - CharArray(char* str) : buf(str) {} // note: assumes ownership - CharArray(size_t len) { - buf = new char[len](); - memset(buf, 0, len); - } - ~CharArray() { - delete [] buf; - } - void format(const char *fmt, ...) - __attribute__((__format__ (__printf__, 2, 3))); - // Get the buffer pointer & clear it (i.e. caller takes ownership) - char* takeBuf() {char* tmp = buf; buf = 0; return tmp;} - void replaceBuf(char* b) {delete [] buf; buf = b;} - char* buf; - private: - CharArray(const CharArray&); - CharArray& operator=(const CharArray&); - }; - - char* strDup(const char* s); - void strFree(char* s); - void strFree(wchar_t* s); - - // Returns true if split successful. Returns false otherwise. - // ALWAYS *copies* first part of string to out1 buffer. - // If limiter not found, leaves out2 alone (null) and just copies to out1. - // If out1 or out2 non-zero, calls strFree and zeroes them. - // If fromEnd is true, splits at end of string rather than beginning. - // Either out1 or out2 may be null, in which case the split will not return - // that part of the string. Obviously, setting both to 0 is not useful... - bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd=false); - - // Returns true if src contains c - bool strContains(const char* src, char c); - - // Copies src to dest, up to specified length-1, and guarantees termination - void strCopy(char* dest, const char* src, int destlen); + // 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 - char* convertLF(const char* src, size_t bytes = (size_t)-1); - char* convertCRLF(const char* src, size_t bytes = (size_t)-1); + 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. The returned strings are - // always null terminated and must be freed using strFree(). + // Convertions between various Unicode formats - size_t ucs4ToUTF8(unsigned src, char* dst); + 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); + size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]); size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst); - char* latin1ToUTF8(const char* src, size_t bytes = (size_t)-1); - char* utf8ToLatin1(const char* src, size_t bytes = (size_t)-1); + std::string latin1ToUTF8(const char* src, size_t bytes = (size_t)-1); + std::string utf8ToLatin1(const char* src, size_t bytes = (size_t)-1); - char* utf16ToUTF8(const wchar_t* src, size_t units = (size_t)-1); - wchar_t* utf8ToUTF16(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); // HELPER functions for timeout handling @@ -119,10 +94,10 @@ namespace rfb { bool isBefore(const struct timeval *first, const struct timeval *second); - size_t siPrefix(long long value, const char *unit, - char *buffer, size_t maxlen, int precision=6); - size_t iecPrefix(long long value, const char *unit, - char *buffer, size_t maxlen, int precision=6); + 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 diff --git a/common/rfb/zrleDecode.h b/common/rfb/zrleDecode.h deleted file mode 100644 index 998e51ed..00000000 --- a/common/rfb/zrleDecode.h +++ /dev/null @@ -1,196 +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. - */ - -// -// ZRLE decoding function. -// -// This file is #included after having set the following macro: -// BPP - 8, 16 or 32 - -namespace rfb { - -// CONCAT2E concatenates its arguments, expanding them if they are macros - -#ifndef CONCAT2E -#define CONCAT2(a,b) a##b -#define CONCAT2E(a,b) CONCAT2(a,b) -#endif - -#ifdef CPIXEL -#define PIXEL_T rdr::CONCAT2E(U,BPP) -#define READ_PIXEL(is) CONCAT2E(readOpaque,CPIXEL)(is) -#define ZRLE_DECODE CONCAT2E(zrleDecode,CPIXEL) -#else -#define PIXEL_T rdr::CONCAT2E(U,BPP) -#define READ_PIXEL(is) is->CONCAT2E(readOpaque,BPP)() -#define ZRLE_DECODE CONCAT2E(zrleDecode,BPP) -#endif - -void ZRLE_DECODE (const Rect& r, rdr::InStream* is, - rdr::ZlibInStream* zis, - const PixelFormat& pf, ModifiablePixelBuffer* pb) -{ - int length = is->readU32(); - zis->setUnderlying(is, length); - Rect t; - PIXEL_T buf[64 * 64]; - - 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); - - 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); - - zlibHasData(zis, 1); - int mode = zis->readU8(); - bool rle = mode & 128; - int palSize = mode & 127; - PIXEL_T palette[128]; - -#ifdef CPIXEL - zlibHasData(zis, 3 * palSize); -#else - zlibHasData(zis, BPP/8 * palSize); -#endif - for (int i = 0; i < palSize; i++) { - palette[i] = READ_PIXEL(zis); - } - - if (palSize == 1) { - PIXEL_T pix = palette[0]; - pb->fillRect(pf, t, &pix); - continue; - } - - if (!rle) { - if (palSize == 0) { - - // raw - -#ifdef CPIXEL - zlibHasData(zis, 3 * t.area()); - for (PIXEL_T* ptr = buf; ptr < buf+t.area(); ptr++) { - *ptr = READ_PIXEL(zis); - } -#else - zlibHasData(zis, BPP/8 * t.area()); - zis->readBytes(buf, t.area() * (BPP / 8)); -#endif - - } else { - - // packed pixels - int bppp = ((palSize > 16) ? 8 : - ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1))); - - PIXEL_T* ptr = buf; - - for (int i = 0; i < t.height(); i++) { - PIXEL_T* eol = ptr + t.width(); - rdr::U8 byte = 0; - rdr::U8 nbits = 0; - - while (ptr < eol) { - if (nbits == 0) { - zlibHasData(zis, 1); - byte = zis->readU8(); - nbits = 8; - } - nbits -= bppp; - rdr::U8 index = (byte >> nbits) & ((1 << bppp) - 1) & 127; - *ptr++ = palette[index]; - } - } - } - - } else { - - if (palSize == 0) { - - // plain RLE - - PIXEL_T* ptr = buf; - PIXEL_T* end = ptr + t.area(); - while (ptr < end) { -#ifdef CPIXEL - zlibHasData(zis, 3); -#else - zlibHasData(zis, BPP/8); -#endif - PIXEL_T pix = READ_PIXEL(zis); - int len = 1; - int b; - do { - zlibHasData(zis, 1); - b = zis->readU8(); - len += b; - } while (b == 255); - - if (end - ptr < len) { - throw Exception ("ZRLE decode error"); - } - - while (len-- > 0) *ptr++ = pix; - - } - } else { - - // palette RLE - - PIXEL_T* ptr = buf; - PIXEL_T* end = ptr + t.area(); - while (ptr < end) { - zlibHasData(zis, 1); - int index = zis->readU8(); - int len = 1; - if (index & 128) { - int b; - do { - zlibHasData(zis, 1); - b = zis->readU8(); - len += b; - } while (b == 255); - - if (end - ptr < len) { - throw Exception ("ZRLE decode error"); - } - } - - index &= 127; - - PIXEL_T pix = palette[index]; - - while (len-- > 0) *ptr++ = pix; - } - } - } - - pb->imageRect(pf, t, buf); - } - } - - zis->flushUnderlying(); - zis->setUnderlying(NULL, 0); -} - -#undef ZRLE_DECODE -#undef READ_PIXEL -#undef PIXEL_T -} |