Merge branch 'bugfix/KASM-5417_watermark_zlib_incomplete' into 'master'

Watermark refactoring, don't handle changes, only send when necessary

Closes KASM-5417

See merge request kasm-technologies/internal/KasmVNC!120
This commit is contained in:
Matthew McClaskey 2024-01-17 15:55:17 +00:00
commit fddaab5124
8 changed files with 51 additions and 50 deletions

View File

@ -423,9 +423,6 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
nRects++;
}
if (watermarkData)
packWatermark(changed);
conn->writer()->writeFramebufferUpdateStart(nRects);
writeCopyRects(copied, copyDelta);
@ -443,7 +440,7 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
if (!videoDetected) // In case detection happened between the calls
writeRects(cursorRegion, renderedCursor);
if (watermarkData) {
if (watermarkData && conn->sendWatermark()) {
beforeLength = conn->getOutStream(conn->cp.supportsUdp)->length();
const Rect rect(0, 0, pb->width(), pb->height());

View File

@ -198,6 +198,10 @@ namespace rfb {
std::vector<unsigned char> data;
};
virtual bool sendWatermark() const {
return false;
}
protected:
void setState(stateEnum s) { state_ = s; }

View File

@ -215,6 +215,10 @@ namespace rfb {
virtual void sendUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len);
bool sendWatermark() const {
return server->sendWatermark;
}
private:
// SConnection callbacks

View File

@ -135,7 +135,7 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
lastConnectionTime(0), disableclients(false),
frameTimer(this), apimessager(NULL), trackingFrameStats(0),
clipboardId(0)
clipboardId(0), sendWatermark(false)
{
lastUserInputTime = lastDisconnectTime = time(0);
slog.debug("creating single-threaded server %s", name.buf);
@ -223,6 +223,9 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
trackingClient[0] = 0;
if (watermarkData)
sendWatermark = true;
if (Server::selfBench)
SelfBench();
}
@ -279,6 +282,9 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing)
VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing);
client->init();
if (watermarkData)
sendWatermark = true;
}
void VNCServerST::removeSocket(network::Socket* sock) {
@ -975,8 +981,8 @@ void VNCServerST::writeUpdate()
}
if (watermarkData && Server::DLP_WatermarkText[0] && watermarkTextNeedsUpdate(true)) {
// If using a text watermark, we have to mark everything as changed...
refreshClients();
// The text may have changed
sendWatermark = true;
}
comparer->getUpdateInfo(&ui, pb->getRect());
@ -1104,6 +1110,8 @@ void VNCServerST::writeUpdate()
}
}
sendWatermark = false; // the client now caches it, only send once
if (trackingFrameStats) {
if (enctime) {
const unsigned totalMs = msSince(&start);

View File

@ -290,6 +290,8 @@ namespace rfb {
void checkAPIMessages(network::GetAPIMessager *apimessager,
rdr::U8 &trackingFrameStats, char trackingClient[]);
bool sendWatermark;
};
};

View File

@ -279,6 +279,31 @@ bool watermarkInit() {
return true;
}
static void packWatermark() {
// Take the expanded 4-bit data, filter it by the changed rects, pack
// to shared bytes, and compress with zlib
uint16_t x, y;
uint8_t pix[2], cur = 0;
uint8_t *dst = watermarkTmp;
for (y = 0; y < rh; y++) {
for (x = 0; x < rw; x++) {
pix[cur] = watermarkUnpacked[y * rw + x];
if (cur || (y == rh - 1 && x == rw - 1))
*dst++ = pix[0] | (pix[1] << 4);
cur ^= 1;
}
}
uLong destLen = MAXW * MAXH / 2;
if (compress2(watermarkData, &destLen, watermarkTmp, rw * rh / 2 + 1, 1) != Z_OK)
vlog.error("Zlib compression error");
watermarkDataLen = destLen;
}
// update the screen-size rendered watermark whenever the screen is resized
// or if using text, every frame
void VNCServerST::updateWatermark() {
@ -359,48 +384,10 @@ void VNCServerST::updateWatermark() {
rw - sx);
}
}
}
void packWatermark(const Region &changed) {
// Take the expanded 4-bit data, filter it by the changed rects, pack
// to shared bytes, and compress with zlib
packWatermark();
uint16_t x, y;
uint8_t pix[2], cur = 0;
uint8_t *dst = watermarkTmp;
const Rect &bounding = changed.get_bounding_rect();
for (y = 0; y < rh; y++) {
// Is the entire line outside the changed area?
if (bounding.tl.y > y || bounding.br.y < y) {
for (x = 0; x < rw; x++) {
pix[cur] = 0;
if (cur || (y == rh - 1 && x == rw - 1))
*dst++ = pix[0] | (pix[1] << 4);
cur ^= 1;
}
} else {
for (x = 0; x < rw; x++) {
pix[cur] = 0;
if (bounding.contains(Point(x, y)) && changed.contains(x, y))
pix[cur] = watermarkUnpacked[y * rw + x];
if (cur || (y == rh - 1 && x == rw - 1))
*dst++ = pix[0] | (pix[1] << 4);
cur ^= 1;
}
}
}
uLong destLen = MAXW * MAXH / 2;
if (compress2(watermarkData, &destLen, watermarkTmp, rw * rh / 2 + 1, 1) != Z_OK)
vlog.error("Zlib compression error");
watermarkDataLen = destLen;
sendWatermark = true;
}
// Limit changes to once per second
@ -412,5 +399,5 @@ bool watermarkTextNeedsUpdate(const bool early) {
if (early)
now = time(NULL);
return now != lastUpdate;
return now != lastUpdate && strchr(Server::DLP_WatermarkText, '%');
}

View File

@ -35,7 +35,6 @@ struct watermarkInfo_t {
extern watermarkInfo_t watermarkInfo;
bool watermarkInit();
void packWatermark(const rfb::Region &changed); // filter and pack the watermark for sending
bool watermarkTextNeedsUpdate(const bool early);
extern uint8_t *watermarkData;

@ -1 +1 @@
Subproject commit 246dbd49996db31be241db112c69d05d77523559
Subproject commit f6c1d8c668beeff3aeccad13933a5ef52f0d5c32