From a77ff634f01af3ab7ac37df359358e17be053711 Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Fri, 2 Feb 2024 22:09:57 +0000 Subject: [PATCH] Keep zlib streams when switching encodings Both RealVNC and TigerVNC clients expect zlib streams to remain when switching encodings, so when they switch back, inflate fails if the encoder is discared. fixes #109 --- include/common.h | 2 ++ src/server.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/common.h b/include/common.h index dd06813..0e8c014 100644 --- a/include/common.h +++ b/include/common.h @@ -105,6 +105,8 @@ struct nvnc_client { struct cut_text cut_text; bool is_ext_notified; struct encoder* encoder; + struct encoder* zrle_encoder; + struct encoder* tight_encoder; uint32_t cursor_seq; int quality; diff --git a/src/server.c b/src/server.c index 553885a..c35ed98 100644 --- a/src/server.c +++ b/src/server.c @@ -143,6 +143,8 @@ static void client_close(struct nvnc_client* client) client->encoder->on_done = NULL; } encoder_unref(client->encoder); + encoder_unref(client->zrle_encoder); + encoder_unref(client->tight_encoder); pixman_region_fini(&client->damage); free(client->cut_text.buffer); free(client); @@ -1111,7 +1113,32 @@ static void process_fb_update_requests(struct nvnc_client* client) client->encoder->on_done = NULL; } encoder_unref(client->encoder); - client->encoder = encoder_new(encoding, width, height); + + /* Zlib streams need to be saved so we keep encoders around that + * use them. + */ + switch (encoding) { + case RFB_ENCODING_ZRLE: + if (!client->zrle_encoder) { + client->zrle_encoder = encoder_new(encoding, + width, height); + } + client->encoder = client->zrle_encoder; + encoder_ref(client->encoder); + break; + case RFB_ENCODING_TIGHT: + if (!client->tight_encoder) { + client->tight_encoder = encoder_new(encoding, + width, height); + } + client->encoder = client->tight_encoder; + encoder_ref(client->encoder); + break; + default: + client->encoder = encoder_new(encoding, width, height); + break; + } + if (!client->encoder) { nvnc_log(NVNC_LOG_ERROR, "Failed to allocate new encoder"); return;