Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package neatvnc for openSUSE:Factory checked 
in at 2024-02-26 19:45:33
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/neatvnc (Old)
 and      /work/SRC/openSUSE:Factory/.neatvnc.new.1770 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "neatvnc"

Mon Feb 26 19:45:33 2024 rev:12 rq:1150570 version:0.8.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/neatvnc/neatvnc.changes  2024-02-04 
19:08:08.082301887 +0100
+++ /work/SRC/openSUSE:Factory/.neatvnc.new.1770/neatvnc.changes        
2024-02-26 19:46:23.328073363 +0100
@@ -1,0 +2,17 @@
+Mon Feb 26 07:10:51 UTC 2024 - Michael Vetter <mvet...@suse.com>
+
+- Update to 0.8.0:
+  Highlights:
+  * The colour map pixel format as described in RFC 6143 has been
+    implemented. Before, the client would just get disconnected if
+    they requested it. Now they get a map that emulates RGB332.
+  * Momentary interception of log messages. The user can now set a
+    thread-local log hander and then set it back to the default.
+  * Philip Zabel made the code more consistent with the style guide.
+  Breaking Changes:
+  * nvnc_client_get_hostname has been replaced with nvnc_client_get_address
+  Bugfixes:
+  * Apple's Diffie-Hellman authentication (security type 30) has been fixed.
+  * A new client connection no longer causes a DNS lookup.
+
+-------------------------------------------------------------------

Old:
----
  v0.7.2.tar.gz

New:
----
  v0.8.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ neatvnc.spec ++++++
--- /var/tmp/diff_new_pack.pgox5h/_old  2024-02-26 19:46:23.940095489 +0100
+++ /var/tmp/diff_new_pack.pgox5h/_new  2024-02-26 19:46:23.944095633 +0100
@@ -19,7 +19,7 @@
 %define libsoname libneatvnc0
 
 Name:           neatvnc
-Version:        0.7.2
+Version:        0.8.0
 Release:        0
 Summary:        A VNC server library
 License:        ISC

++++++ v0.7.2.tar.gz -> v0.8.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/README.md new/neatvnc-0.8.0/README.md
--- old/neatvnc-0.7.2/README.md 2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/README.md 2024-02-25 12:11:28.000000000 +0100
@@ -18,6 +18,9 @@
  * gnutls (optional)
  * libdrm (optional)
  * libturbojpeg (optional)
+ * nettle (optional)
+ * hogweed (optional)
+ * gmp (optional)
  * pixman
  * zlib
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/bench/zrle-bench.c 
new/neatvnc-0.8.0/bench/zrle-bench.c
--- old/neatvnc-0.7.2/bench/zrle-bench.c        2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/bench/zrle-bench.c        2024-02-25 12:11:28.000000000 
+0100
@@ -71,10 +71,10 @@
        z_stream zs = { 0 };
 
        deflateInit2(&zs, /* compression level: */ 1,
-                         /*            method: */ Z_DEFLATED,
-                         /*       window bits: */ 15,
-                         /*         mem level: */ 9,
-                         /*          strategy: */ Z_DEFAULT_STRATEGY);
+                       /*            method: */ Z_DEFLATED,
+                       /*       window bits: */ 15,
+                       /*         mem level: */ 9,
+                       /*          strategy: */ Z_DEFAULT_STRATEGY);
 
        void *dummy = malloc(stride * height * 4);
        if (!dummy)
@@ -86,7 +86,7 @@
 
        uint64_t end_time = gettime_us(CLOCK_PROCESS_CPUTIME_ID);
        printf("memcpy baseline for %s took %"PRIu64" micro seconds\n", image,
-              end_time - start_time);
+                       end_time - start_time);
 
        free(dummy);
 
@@ -95,7 +95,7 @@
 
        end_time = gettime_us(CLOCK_PROCESS_CPUTIME_ID);
        printf("Encoding %s took %"PRIu64" micro seconds\n", image,
-              end_time - start_time);
+                       end_time - start_time);
 
        double orig_size = stride * height * 4;
        double compressed_size = frame.len;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/examples/draw.c 
new/neatvnc-0.8.0/examples/draw.c
--- old/neatvnc-0.7.2/examples/draw.c   2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/examples/draw.c   2024-02-25 12:11:28.000000000 +0100
@@ -198,7 +198,7 @@
                }
 
        pixman_region_init_rect(damage, start.x, start.y,
-                               stop.x - start.x, stop.y - start.y);
+                       stop.x - start.x, stop.y - start.y);
 }
 
 static void draw_dot(struct draw *draw, struct coord coord, int radius,
@@ -219,7 +219,7 @@
 }
 
 static void on_pointer_event(struct nvnc_client* client, uint16_t x, uint16_t 
y,
-                             enum nvnc_button_mask buttons)
+               enum nvnc_button_mask buttons)
 {
        if (!(buttons & NVNC_BUTTON_LEFT))
                return;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/include/common.h 
new/neatvnc-0.8.0/include/common.h
--- old/neatvnc-0.7.2/include/common.h  2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/include/common.h  2024-02-25 12:11:28.000000000 +0100
@@ -83,7 +83,6 @@
        struct nvnc_common common;
        int ref;
        struct stream* net_stream;
-       char hostname[256];
        char username[256];
        struct nvnc* server;
        enum nvnc_client_state state;
@@ -109,6 +108,7 @@
        struct encoder* tight_encoder;
        uint32_t cursor_seq;
        int quality;
+       bool formats_changed;
 
 #ifdef HAVE_CRYPTO
        struct crypto_key* apple_dh_secret;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/include/neatvnc.h 
new/neatvnc-0.8.0/include/neatvnc.h
--- old/neatvnc-0.7.2/include/neatvnc.h 2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/include/neatvnc.h 2024-02-25 12:11:28.000000000 +0100
@@ -22,6 +22,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <sys/socket.h>
 
 #define NVNC_NO_PTS UINT64_MAX
 
@@ -141,7 +142,8 @@
 
 struct nvnc* nvnc_client_get_server(const struct nvnc_client* client);
 bool nvnc_client_supports_cursor(const struct nvnc_client* client);
-const char* nvnc_client_get_hostname(const struct nvnc_client* client);
+int nvnc_client_get_address(const struct nvnc_client* client,
+               struct sockaddr* restrict addr, socklen_t* restrict addrlen);
 const char* nvnc_client_get_auth_username(const struct nvnc_client* client);
 
 struct nvnc_client* nvnc_client_first(struct nvnc* self);
@@ -235,6 +237,9 @@
                     uint16_t height, uint16_t hotspot_x, uint16_t hotspot_y,
                     bool is_damaged);
 
+void nvnc_default_logger(const struct nvnc_log_data* meta, const char* 
message);
+
 void nvnc_set_log_fn(nvnc_log_fn);
+void nvnc_set_log_fn_thread_local(nvnc_log_fn fn);
 void nvnc_set_log_level(enum nvnc_log_level);
 void nvnc__log(const struct nvnc_log_data*, const char* fmt, ...);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/include/pixels.h 
new/neatvnc-0.8.0/include/pixels.h
--- old/neatvnc-0.7.2/include/pixels.h  2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/include/pixels.h  2024-02-25 12:11:28.000000000 +0100
@@ -22,6 +22,7 @@
 #include <stdbool.h>
 
 struct rfb_pixel_format;
+struct rfb_set_colour_map_entries_msg;
 
 void pixel_to_cpixel(uint8_t* restrict dst,
                        const struct rfb_pixel_format* dst_fmt,
@@ -41,3 +42,4 @@
 
 const char* drm_format_to_string(uint32_t fmt);
 const char* rfb_pixfmt_to_string(const struct rfb_pixel_format* fmt);
+void make_rgb332_pal8_map(struct rfb_set_colour_map_entries_msg* msg);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/include/rfb-proto.h 
new/neatvnc-0.8.0/include/rfb-proto.h
--- old/neatvnc-0.7.2/include/rfb-proto.h       2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/include/rfb-proto.h       2024-02-25 12:11:28.000000000 
+0100
@@ -266,3 +266,15 @@
        uint16_t length;
        uint8_t challenge[0];
 } RFB_PACKED;
+
+struct rfb_colour_map_entry {
+       uint16_t r, g, b;
+} RFB_PACKED;
+
+struct rfb_set_colour_map_entries_msg {
+       uint8_t type;
+       uint8_t padding;
+       uint16_t first_colour;
+       uint16_t n_colours;
+       struct rfb_colour_map_entry colours[0];
+} RFB_PACKED;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/meson.build 
new/neatvnc-0.8.0/meson.build
--- old/neatvnc-0.7.2/meson.build       2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/meson.build       2024-02-25 12:11:28.000000000 +0100
@@ -1,7 +1,7 @@
 project(
        'neatvnc',
        'c',
-       version: '0.7.2',
+       version: '0.8.0',
        license: 'ISC',
        default_options: [
                'c_std=gnu11',
@@ -13,7 +13,6 @@
 host_system = host_machine.system()
 
 c_args = [
-       '-DPROJECT_VERSION="@0@"'.format(meson.project_version()),
        '-D_GNU_SOURCE',
        '-fvisibility=hidden',
        '-DAML_UNSTABLE_API=1',
@@ -27,17 +26,20 @@
        c_args += '-DNDEBUG'
 endif
 
+version = '"@0@"'.format(meson.project_version())
 git = find_program('git', native: true, required: false)
 if git.found()
-       git_describe = run_command([git, 'describe', '--tags', '--long'], 
check: false)
-       git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], 
check: false)
-       if git_describe.returncode() == 0 and git_branch.returncode() == 0
-               c_args += '-DGIT_VERSION="@0@ (@1@)"'.format(
-                       git_describe.stdout().strip(),
+       git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'])
+       git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'])
+       if git_commit.returncode() == 0 and git_branch.returncode() == 0
+               version = '"v@0@-@1@ (@2@)"'.format(
+                       meson.project_version(),
+                       git_commit.stdout().strip(),
                        git_branch.stdout().strip(),
                )
        endif
 endif
+add_project_arguments('-DPROJECT_VERSION=@0@'.format(version), language: 'c')
 
 libdrm_inc = dependency('libdrm').partial_dependency(compile_args: true)
 
@@ -153,6 +155,13 @@
        config.set('ENABLE_WEBSOCKET', true)
 endif
 
+if get_option('experimental')
+       if buildtype == 'release'
+               warning('Experimental features enabled in release build')
+       endif
+       config.set('ENABLE_EXPERIMENTAL', true)
+endif
+
 configure_file(
        output: 'config.h',
        configuration: config,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/meson_options.txt 
new/neatvnc-0.8.0/meson_options.txt
--- old/neatvnc-0.7.2/meson_options.txt 2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/meson_options.txt 2024-02-25 12:11:28.000000000 +0100
@@ -7,3 +7,4 @@
 option('systemtap', type: 'boolean', value: false, description: 'Enable 
tracing using sdt')
 option('gbm', type: 'feature', value: 'auto', description: 'Enable GBM 
integration')
 option('h264', type: 'feature', value: 'auto', description: 'Enable open h264 
encoding')
+option('experimental', type: 'boolean', value: false, description: 'Enable 
experimental features')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/crypto-nettle.c 
new/neatvnc-0.8.0/src/crypto-nettle.c
--- old/neatvnc-0.7.2/src/crypto-nettle.c       2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/src/crypto-nettle.c       2024-02-25 12:11:28.000000000 
+0100
@@ -658,7 +658,7 @@
 void crypto_rsa_pub_key_modulus(const struct crypto_rsa_pub_key* key,
                uint8_t* dst, size_t dst_size)
 {
-        crypto_export(dst, dst_size, key->key.n);
+       crypto_export(dst, dst_size, key->key.n);
 }
 
 void crypto_rsa_pub_key_exponent(const struct crypto_rsa_pub_key* key,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/cursor.c 
new/neatvnc-0.8.0/src/cursor.c
--- old/neatvnc-0.7.2/src/cursor.c      2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/cursor.c      2024-02-25 12:11:28.000000000 +0100
@@ -112,8 +112,8 @@
 
        for (uint32_t y = 0; y < height; ++y) {
                if (!extract_alpha_mask(dstdata + y * UDIV_UP(width, 8),
-                                       (uint32_t*)image->addr + y * 
image->stride,
-                                       image->fourcc_format, width))
+                               (uint32_t*)image->addr + y * image->stride,
+                               image->fourcc_format, width))
                        goto failure;
 
                dst->len += UDIV_UP(width, 8);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/damage-refinery.c 
new/neatvnc-0.8.0/src/damage-refinery.c
--- old/neatvnc-0.7.2/src/damage-refinery.c     2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/src/damage-refinery.c     2024-02-25 12:11:28.000000000 
+0100
@@ -133,12 +133,12 @@
 }
 
 void damage_refine(struct damage_refinery* self,
-               struct pixman_region16* refined, 
+               struct pixman_region16* refined,
                struct pixman_region16* hint,
                struct nvnc_fb* buffer)
 {
        assert(self->width == (uint32_t)buffer->width &&
-              self->height == (uint32_t)buffer->height);
+                       self->height == (uint32_t)buffer->height);
 
        nvnc_fb_map(buffer);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/enc-util.c 
new/neatvnc-0.8.0/src/enc-util.c
--- old/neatvnc-0.7.2/src/enc-util.c    2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/enc-util.c    2024-02-25 12:11:28.000000000 +0100
@@ -50,7 +50,7 @@
 
        int n_rects = 0;
        struct pixman_box16* rects = pixman_region_rectangles(region,
-               &n_rects);
+                       &n_rects);
 
        for (int i = 0; i < n_rects; ++i) {
                int width = rects[i].x2 - rects[i].x1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/fb.c new/neatvnc-0.8.0/src/fb.c
--- old/neatvnc-0.7.2/src/fb.c  2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/fb.c  2024-02-25 12:11:28.000000000 +0100
@@ -35,7 +35,7 @@
 
 EXPORT
 struct nvnc_fb* nvnc_fb_new(uint16_t width, uint16_t height,
-                            uint32_t fourcc_format, uint16_t stride)
+               uint32_t fourcc_format, uint16_t stride)
 {
        struct nvnc_fb* fb = calloc(1, sizeof(*fb));
        if (!fb)
@@ -66,7 +66,7 @@
 
 EXPORT
 struct nvnc_fb* nvnc_fb_from_buffer(void* buffer, uint16_t width, uint16_t 
height,
-                            uint32_t fourcc_format, int32_t stride)
+               uint32_t fourcc_format, int32_t stride)
 {
        struct nvnc_fb* fb = calloc(1, sizeof(*fb));
        if (!fb)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/fb_pool.c 
new/neatvnc-0.8.0/src/fb_pool.c
--- old/neatvnc-0.7.2/src/fb_pool.c     2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/fb_pool.c     2024-02-25 12:11:28.000000000 +0100
@@ -165,7 +165,7 @@
        }
 
        nvnc_fb_ref(fb);
-       
+
        struct fbq_item* item = calloc(1, sizeof(*item));
        assert(item);
        item->fb = fb;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/h264-encoder.c 
new/neatvnc-0.8.0/src/h264-encoder.c
--- old/neatvnc-0.7.2/src/h264-encoder.c        2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/src/h264-encoder.c        2024-02-25 12:11:28.000000000 
+0100
@@ -328,7 +328,7 @@
        c->sw_format = drm_to_av_pixel_format(self->format);
        c->width = self->width;
        c->height = self->height;
-       
+
        if (av_hwframe_ctx_init(self->hw_frames_ctx) < 0)
                av_buffer_unref(&self->hw_frames_ctx);
 
@@ -409,10 +409,18 @@
        frame->hw_frames_ctx = av_buffer_ref(self->hw_frames_ctx);
 
        if (self->current_frame_is_keyframe) {
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 7, 100)
+               frame->flags |= AV_FRAME_FLAG_KEY;
+#else
                frame->key_frame = 1;
+#endif
                frame->pict_type = AV_PICTURE_TYPE_I;
        } else {
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 7, 100)
+               frame->flags &= ~AV_FRAME_FLAG_KEY;
+#else
                frame->key_frame = 0;
+#endif
                frame->pict_type = AV_PICTURE_TYPE_P;
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/logging.c 
new/neatvnc-0.8.0/src/logging.c
--- old/neatvnc-0.7.2/src/logging.c     2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/logging.c     2024-02-25 12:11:28.000000000 +0100
@@ -25,6 +25,7 @@
 #include <stdarg.h>
 #include <string.h>
 #include <ctype.h>
+#include <threads.h>
 
 #ifdef HAVE_LIBAVUTIL
 #include <libavutil/avutil.h>
@@ -32,10 +33,8 @@
 
 #define EXPORT __attribute__((visibility("default")))
 
-static void default_logger(const struct nvnc_log_data* meta,
-               const char* message);
-
-static nvnc_log_fn log_fn = default_logger;
+static nvnc_log_fn log_fn = nvnc_default_logger;
+static thread_local nvnc_log_fn thread_local_log_fn = NULL;
 
 #ifndef NDEBUG
 static enum nvnc_log_level log_level = NVNC_LOG_DEBUG;
@@ -45,6 +44,11 @@
 
 static bool is_initialised = false;
 
+static nvnc_log_fn get_log_fn(void)
+{
+       return thread_local_log_fn ? thread_local_log_fn : log_fn;
+}
+
 static char* trim_left(char* str)
 {
        while (isspace(*str))
@@ -100,14 +104,15 @@
 
        if (meta->level <= log_level) {
                vsnprintf(message, sizeof(message), fmt, args);
-               log_fn(meta, trim(message));
+               get_log_fn()(meta, trim(message));
        }
 
        if (meta->level == NVNC_LOG_PANIC)
                abort();
 }
 
-static void default_logger(const struct nvnc_log_data* meta,
+EXPORT
+void nvnc_default_logger(const struct nvnc_log_data* meta,
                const char* message)
 {
        const char* level = log_level_to_string(meta->level);
@@ -178,7 +183,13 @@
 EXPORT
 void nvnc_set_log_fn(nvnc_log_fn fn)
 {
-       log_fn = fn;
+       log_fn = fn ? fn : nvnc_default_logger;
+}
+
+EXPORT
+void nvnc_set_log_fn_thread_local(nvnc_log_fn fn)
+{
+       thread_local_log_fn = fn;
 }
 
 EXPORT
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/pixels.c 
new/neatvnc-0.8.0/src/pixels.c
--- old/neatvnc-0.7.2/src/pixels.c      2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/pixels.c      2024-02-25 12:11:28.000000000 +0100
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <libdrm/drm_fourcc.h>
+#include <math.h>
 
 #define POPCOUNT(x) __builtin_popcount(x)
 #define UDIV_UP(a, b) (((a) + (b) - 1) / (b))
@@ -26,10 +27,10 @@
 #define STR(s) #s
 
 static void pixel32_to_cpixel(uint8_t* restrict dst,
-             const struct rfb_pixel_format* dst_fmt,
-             const uint32_t* restrict src,
-             const struct rfb_pixel_format* src_fmt,
-             size_t bytes_per_cpixel, size_t len)
+               const struct rfb_pixel_format* dst_fmt,
+               const uint32_t* restrict src,
+               const struct rfb_pixel_format* src_fmt,
+               size_t bytes_per_cpixel, size_t len)
 {
        assert(src_fmt->true_colour_flag);
        assert(src_fmt->depth <= 32);
@@ -152,10 +153,10 @@
 }
 
 void pixel_to_cpixel(uint8_t* restrict dst,
-                       const struct rfb_pixel_format* dst_fmt,
-                       const uint8_t* restrict src,
-                       const struct rfb_pixel_format* src_fmt,
-                       size_t bytes_per_cpixel, size_t len)
+               const struct rfb_pixel_format* dst_fmt,
+               const uint8_t* restrict src,
+               const struct rfb_pixel_format* src_fmt,
+               size_t bytes_per_cpixel, size_t len)
 {
        if (src_fmt->bits_per_pixel == 32) {
                pixel32_to_cpixel(dst, dst_fmt, (uint32_t*)src, src_fmt, 
bytes_per_cpixel, len);
@@ -636,9 +637,6 @@
 // Not exact, but close enough for debugging
 const char* rfb_pixfmt_to_string(const struct rfb_pixel_format* fmt)
 {
-       if (!(fmt->red_max == fmt->green_max && fmt->red_max == fmt->blue_max))
-               goto failure;
-
        uint32_t profile = (fmt->red_shift << 16) | (fmt->green_shift << 8)
                | (fmt->blue_shift);
 
@@ -657,9 +655,25 @@
        CASE(8, 4, 0):   return "XRGB4444";
        CASE(0, 4, 8):   return "XBGR4444";
        CASE(11, 5, 0):  return "RGB565";
+       CASE(5, 2, 0):   return "RGB332";
+       CASE(0, 2, 5):   return "RGB332";
+       CASE(4, 2, 0):   return "RGB222";
+       CASE(0, 2, 4):   return "BGR222";
 #undef CASE
        }
-
-failure:
        return "UNKNOWN";
 }
+
+void make_rgb332_pal8_map(struct rfb_set_colour_map_entries_msg* msg)
+{
+       msg->type = RFB_SERVER_TO_CLIENT_SET_COLOUR_MAP_ENTRIES;
+       msg->padding = 0;
+       msg->first_colour = htons(0);
+       msg->n_colours = htons(256);
+
+       for (unsigned int i = 0; i < 256; ++i) {
+               msg->colours[i].r = htons(round(65535.0 / 7.0 * ((i >> 5) & 
7)));
+               msg->colours[i].g = htons(round(65535.0 / 7.0 * ((i >> 2) & 
7)));
+               msg->colours[i].b = htons(round(65535.0 / 3.0 * (i & 3)));
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/raw-encoding.c 
new/neatvnc-0.8.0/src/raw-encoding.c
--- old/neatvnc-0.7.2/src/raw-encoding.c        2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/src/raw-encoding.c        2024-02-25 12:11:28.000000000 
+0100
@@ -54,10 +54,10 @@
 }
 
 static int raw_encode_box(struct raw_encoder_work* ctx, struct vec* dst,
-                          const struct rfb_pixel_format* dst_fmt,
-                          const struct nvnc_fb* fb,
-                          const struct rfb_pixel_format* src_fmt, int x_start,
-                          int y_start, int stride, int width, int height)
+               const struct rfb_pixel_format* dst_fmt,
+               const struct nvnc_fb* fb,
+               const struct rfb_pixel_format* src_fmt, int x_start,
+               int y_start, int stride, int width, int height)
 {
        uint16_t x_pos = ctx->x_pos;
        uint16_t y_pos = ctx->y_pos;
@@ -84,8 +84,8 @@
 
        for (int y = y_start; y < y_start + height; ++y) {
                pixel_to_cpixel(d + dst->len, dst_fmt,
-                                 b + xoff + y * src_stride, src_fmt,
-                                 bpp, width);
+                               b + xoff + y * src_stride, src_fmt,
+                               bpp, width);
                dst->len += width * bpp;
        }
 
@@ -117,7 +117,7 @@
                int box_height = box[i].y2 - y;
 
                rc = raw_encode_box(ctx, dst, dst_fmt, src, src_fmt, x, y,
-                                   src->stride, box_width, box_height);
+                               src->stride, box_width, box_height);
                if (rc < 0)
                        return -1;
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/server.c 
new/neatvnc-0.8.0/src/server.c
--- old/neatvnc-0.7.2/src/server.c      2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/server.c      2024-02-25 12:11:28.000000000 +0100
@@ -77,17 +77,16 @@
 static int send_desktop_resize(struct nvnc_client* client, struct nvnc_fb* fb);
 static bool send_ext_support_frame(struct nvnc_client* client);
 static enum rfb_encodings choose_frame_encoding(struct nvnc_client* client,
-               struct nvnc_fb*);
+               const struct nvnc_fb*);
 static void on_encode_frame_done(struct encoder*, struct rcbuf*, uint64_t pts);
 static bool client_has_encoding(const struct nvnc_client* client,
                enum rfb_encodings encoding);
 static void process_fb_update_requests(struct nvnc_client* client);
 static void sockaddr_to_string(char* dst, size_t sz,
                const struct sockaddr* addr);
+static const char* encoding_to_string(enum rfb_encodings encoding);
 
-#if defined(GIT_VERSION)
-EXPORT const char nvnc_version[] = GIT_VERSION;
-#elif defined(PROJECT_VERSION)
+#if defined(PROJECT_VERSION)
 EXPORT const char nvnc_version[] = PROJECT_VERSION;
 #else
 EXPORT const char nvnc_version[] = "UNKNOWN";
@@ -211,7 +210,7 @@
 
        size_t len = 1 + sizeof(*reason) + strlen(reason_string);
        stream_write(client->net_stream, buffer, len, close_after_write,
-                    client);
+                       client);
 
        return 0;
 }
@@ -270,8 +269,15 @@
 }
 
 static int security_handshake_failed(struct nvnc_client* client,
-                                     const char* reason_string)
+               const char* username, const char* reason_string)
 {
+       if (username)
+               nvnc_log(NVNC_LOG_INFO, "Security handshake failed for \"%s\": 
%s",
+                               username, reason_string);
+       else
+               nvnc_log(NVNC_LOG_INFO, "Security handshake: %s",
+                               username, reason_string);
+
        char buffer[256];
 
        client->state = VNC_CLIENT_STATE_ERROR;
@@ -287,16 +293,23 @@
 
        size_t len = sizeof(*result) + sizeof(*reason) + strlen(reason_string);
        stream_write(client->net_stream, buffer, len, close_after_write,
-                    client);
+                       client);
 
        return 0;
 }
 
-static int security_handshake_ok(struct nvnc_client* client)
+static int security_handshake_ok(struct nvnc_client* client, const char* 
username)
 {
+       if (username) {
+               nvnc_log(NVNC_LOG_INFO, "User \"%s\" authenticated", username);
+
+               strncpy(client->username, username, sizeof(client->username));
+               client->username[sizeof(client->username) - 1] = '\0';
+       }
+
        uint32_t result = htonl(RFB_SECURITY_HANDSHAKE_OK);
        return stream_write(client->net_stream, &result, sizeof(result), NULL,
-                           NULL);
+                       NULL);
 }
 
 #ifdef ENABLE_TLS
@@ -308,7 +321,7 @@
 static int send_byte_and_close(struct nvnc_client* client, uint8_t value)
 {
        return stream_write(client->net_stream, &value, 1, close_after_write,
-                           client);
+                       client);
 }
 
 static int vencrypt_send_version(struct nvnc_client* client)
@@ -330,7 +343,8 @@
                return 0;
 
        if (msg->major != 0 || msg->minor != 2) {
-               security_handshake_failed(client, "Unsupported VeNCrypt 
version");
+               security_handshake_failed(client, NULL,
+                               "Unsupported VeNCrypt version");
                return sizeof(*msg);
        }
 
@@ -399,16 +413,12 @@
        username[MIN(ulen, sizeof(username) - 1)] = '\0';
        password[MIN(plen, sizeof(password) - 1)] = '\0';
 
-       strncpy(client->username, username, sizeof(client->username));
-       client->username[sizeof(client->username) - 1] = '\0';
-
        if (server->auth_fn(username, password, server->auth_ud)) {
-               nvnc_log(NVNC_LOG_INFO, "User \"%s\" authenticated", username);
-               security_handshake_ok(client);
+               security_handshake_ok(client, username);
                client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT;
        } else {
-               nvnc_log(NVNC_LOG_INFO, "User \"%s\" rejected", username);
-               security_handshake_failed(client, "Invalid username or 
password");
+               security_handshake_failed(client, username,
+                               "Invalid username or password");
        }
 
        return sizeof(*msg) + ulen + plen;
@@ -492,12 +502,11 @@
        crypto_cipher_del(cipher);
 
        if (server->auth_fn(username, password, server->auth_ud)) {
-               nvnc_log(NVNC_LOG_INFO, "User \"%s\" authenticated", username);
-               security_handshake_ok(client);
+               security_handshake_ok(client, username);
                client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT;
        } else {
-               nvnc_log(NVNC_LOG_INFO, "User \"%s\" rejected", username);
-               security_handshake_failed(client, "Invalid username or 
password");
+               security_handshake_failed(client, username,
+                               "Invalid username or password");
        }
 
        return sizeof(*msg) + key_len;
@@ -769,12 +778,11 @@
        password[password_len] = '\0';
 
        if (server->auth_fn(username, password, server->auth_ud)) {
-               nvnc_log(NVNC_LOG_INFO, "User \"%s\" authenticated", username);
-               security_handshake_ok(client);
+               security_handshake_ok(client, username);
                client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT;
        } else {
-               nvnc_log(NVNC_LOG_INFO, "User \"%s\" rejected", username);
-               security_handshake_failed(client, "Invalid username or 
password");
+               security_handshake_failed(client, username,
+                               "Invalid username or password");
        }
 
        return 2 + username_len + password_len;
@@ -792,7 +800,7 @@
 
        switch (type) {
        case RFB_SECURITY_TYPE_NONE:
-               security_handshake_ok(client);
+               security_handshake_ok(client, NULL);
                client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT;
                break;
 #ifdef ENABLE_TLS
@@ -822,7 +830,8 @@
                break;
 #endif
        default:
-               security_handshake_failed(client, "Unsupported security type");
+               security_handshake_failed(client, NULL,
+                               "Unsupported security type");
                break;
        }
 
@@ -915,6 +924,30 @@
        return sizeof(shared_flag);
 }
 
+static int cook_pixel_map(struct nvnc_client* client)
+{
+       struct rfb_pixel_format* fmt = &client->pixfmt;
+
+       // We'll just pretend that this is rgb332
+       fmt->true_colour_flag = true;
+       fmt->big_endian_flag = false;
+       fmt->bits_per_pixel = 8;
+       fmt->depth = 8;
+       fmt->red_max = 7;
+       fmt->green_max = 7;
+       fmt->blue_max = 3;
+       fmt->red_shift = 5;
+       fmt->green_shift = 2;
+       fmt->blue_shift = 0;
+
+       uint8_t buf[sizeof(struct rfb_set_colour_map_entries_msg)
+               + 256 * sizeof(struct rfb_colour_map_entry)];
+       struct rfb_set_colour_map_entries_msg* msg =
+               (struct rfb_set_colour_map_entries_msg*)buf;
+       make_rgb332_pal8_map(msg);
+       return stream_write(client->net_stream, buf, sizeof(buf), NULL, NULL);
+}
+
 static int on_client_set_pixel_format(struct nvnc_client* client)
 {
        if (client->buffer_len - client->buffer_index <
@@ -925,23 +958,42 @@
                (struct rfb_pixel_format*)(client->msg_buffer +
                                           client->buffer_index + 4);
 
-       if (!fmt->true_colour_flag) {
-               /* We don't really know what to do with color maps right now */
-               nvnc_client_close(client);
-               return 0;
+       if (fmt->true_colour_flag) {
+               nvnc_log(NVNC_LOG_DEBUG, "Using color palette for client %p",
+                               client);
+               fmt->red_max = ntohs(fmt->red_max);
+               fmt->green_max = ntohs(fmt->green_max);
+               fmt->blue_max = ntohs(fmt->blue_max);
+               memcpy(&client->pixfmt, fmt, sizeof(client->pixfmt));
+       } else {
+               nvnc_log(NVNC_LOG_DEBUG, "Using color palette for client %p",
+                               client);
+               cook_pixel_map(client);
        }
 
-       fmt->red_max = ntohs(fmt->red_max);
-       fmt->green_max = ntohs(fmt->green_max);
-       fmt->blue_max = ntohs(fmt->blue_max);
-
-       memcpy(&client->pixfmt, fmt, sizeof(client->pixfmt));
-
        client->has_pixfmt = true;
+       client->formats_changed = true;
+
+       nvnc_log(NVNC_LOG_DEBUG, "Client %p chose pixel format: %s", client,
+                       rfb_pixfmt_to_string(&client->pixfmt));
 
        return 4 + sizeof(struct rfb_pixel_format);
 }
 
+static void encodings_to_string_list(char* dst, size_t len,
+               enum rfb_encodings* encodings, size_t n)
+{
+       size_t off = 0;
+
+       if (n > 0)
+               off += snprintf(dst, len, "%s",
+                               encoding_to_string(encodings[0]));
+
+       for (size_t i = 1; i < n; ++i)
+               off += snprintf(dst + off, len - off, ",%s",
+                               encoding_to_string(encodings[i]));
+}
+
 static int on_client_set_encodings(struct nvnc_client* client)
 {
        struct rfb_client_set_encodings_msg* msg =
@@ -973,10 +1025,16 @@
                case RFB_ENCODING_DESKTOPSIZE:
                case RFB_ENCODING_EXTENDEDDESKTOPSIZE:
                case RFB_ENCODING_QEMU_EXT_KEY_EVENT:
+#ifdef ENABLE_EXPERIMENTAL
+               case RFB_ENCODING_PTS:
+               case RFB_ENCODING_NTP:
+#endif
                        client->encodings[n++] = encoding;
+#ifndef ENABLE_EXPERIMENTAL
                case RFB_ENCODING_PTS:
                case RFB_ENCODING_NTP:
                        ;
+#endif
                }
 
                if (RFB_ENCODING_JPEG_LOWQ <= encoding &&
@@ -984,7 +1042,14 @@
                        client->quality = encoding - RFB_ENCODING_JPEG_LOWQ;
        }
 
+       char encoding_list[256] = {};
+       encodings_to_string_list(encoding_list, sizeof(encoding_list),
+                       client->encodings, n);
+       nvnc_log(NVNC_LOG_DEBUG, "Client %p set encodings: %s", client,
+                       encoding_list);
+
        client->n_encodings = n;
+       client->formats_changed = true;
 
        return sizeof(*msg) + 4 * n_encodings;
 }
@@ -1041,14 +1106,77 @@
 {
        switch (encoding) {
        case RFB_ENCODING_RAW: return "raw";
+       case RFB_ENCODING_COPYRECT: return "copyrect";
+       case RFB_ENCODING_RRE: return "rre";
+       case RFB_ENCODING_HEXTILE: return "hextile";
        case RFB_ENCODING_TIGHT: return "tight";
+       case RFB_ENCODING_TRLE: return "trle";
        case RFB_ENCODING_ZRLE: return "zrle";
        case RFB_ENCODING_OPEN_H264: return "open-h264";
+       case RFB_ENCODING_CURSOR: return "cursor";
+       case RFB_ENCODING_DESKTOPSIZE: return "desktop-size";
+       case RFB_ENCODING_EXTENDEDDESKTOPSIZE: return "extended-desktop-size";
+       case RFB_ENCODING_QEMU_EXT_KEY_EVENT: return "qemu-extended-key-event";
+       case RFB_ENCODING_PTS: return "pts";
+       case RFB_ENCODING_NTP: return "ntp";
+       }
+       return "UNKNOWN";
+}
+
+static bool ensure_encoder(struct nvnc_client* client, const struct nvnc_fb 
*fb)
+{
+       struct nvnc* server = client->server;
+
+       enum rfb_encodings encoding = choose_frame_encoding(client, fb);
+       if (client->encoder && encoding == encoder_get_type(client->encoder))
+               return true;
+
+       int width = server->display->buffer->width;
+       int height = server->display->buffer->height;
+       if (client->encoder) {
+               server->n_damage_clients -= !(client->encoder->impl->flags &
+                               ENCODER_IMPL_FLAG_IGNORES_DAMAGE);
+               client->encoder->on_done = NULL;
+       }
+       encoder_unref(client->encoder);
+
+       /* 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;
        }
 
-       return "UNKNOWN";
+       if (!client->encoder) {
+               nvnc_log(NVNC_LOG_ERROR, "Failed to allocate new encoder");
+               return false;
+       }
+
+       server->n_damage_clients += !(client->encoder->impl->flags &
+                       ENCODER_IMPL_FLAG_IGNORES_DAMAGE);
+
+       nvnc_log(NVNC_LOG_INFO, "Choosing %s encoding for client %p",
+                       encoding_to_string(encoding), client);
+
+       return true;
 }
 
 static void process_fb_update_requests(struct nvnc_client* client)
@@ -1100,63 +1228,17 @@
        if (!pixman_region_not_empty(&client->damage))
                return;
 
-       DTRACE_PROBE1(neatvnc, update_fb_start, client);
-
-       enum rfb_encodings encoding = choose_frame_encoding(client, fb);
-       if (!client->encoder || encoding != encoder_get_type(client->encoder)) {
-               int width = server->display->buffer->width;
-               int height = server->display->buffer->height;
-               if (client->encoder) {
-                       server->n_damage_clients -=
-                               !(client->encoder->impl->flags &
-                                               
ENCODER_IMPL_FLAG_IGNORES_DAMAGE);
-                       client->encoder->on_done = NULL;
-               }
-               encoder_unref(client->encoder);
-
-               /* 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;
-               }
-
-               server->n_damage_clients +=
-                       !(client->encoder->impl->flags &
-                                       ENCODER_IMPL_FLAG_IGNORES_DAMAGE);
+       if (!ensure_encoder(client, fb))
+               return;
 
-               nvnc_log(NVNC_LOG_INFO, "Choosing %s encoding for client %p",
-                               encoding_to_string(encoding), client);
-       }
+       DTRACE_PROBE1(neatvnc, update_fb_start, client);
 
        /* The client's damage is exchanged for an empty one */
        struct pixman_region16 damage = client->damage;
        pixman_region_init(&client->damage);
 
        client->is_updating = true;
+       client->formats_changed = false;
        client->current_fb = fb;
        nvnc_fb_hold(fb);
        nvnc_fb_ref(fb);
@@ -1178,6 +1260,7 @@
                nvnc_log(NVNC_LOG_ERROR, "Failed to encode current frame");
                client_unref(client);
                client->is_updating = false;
+               client->formats_changed = false;
                assert(client->current_fb);
                nvnc_fb_release(client->current_fb);
                nvnc_fb_unref(client->current_fb);
@@ -1211,7 +1294,7 @@
         */
        if (!incremental) {
                pixman_region_union_rect(&client->damage, &client->damage, x, y,
-                                        width, height);
+                               width, height);
 
                if (client->encoder)
                        encoder_request_key_frame(client->encoder);
@@ -1294,7 +1377,7 @@
        }
 
        nvnc_log(NVNC_LOG_WARNING, "Got uninterpretable qemu message from 
client: %p (ref %d)",
-                 client, client->ref);
+                       client, client->ref);
        nvnc_client_close(client);
        return 0;
 }
@@ -1353,7 +1436,7 @@
        /* Messages greater than this size are unsupported */
        if (length > max_length) {
                nvnc_log(NVNC_LOG_ERROR, "Copied text length (%d) is greater 
than max supported length (%d)",
-                       length, max_length);
+                               length, max_length);
                nvnc_client_close(client);
                return 0;
        }
@@ -1404,7 +1487,7 @@
        if (n_read < 0) {
                if (errno != EAGAIN) {
                        nvnc_log(NVNC_LOG_INFO, "Client connection error: %p 
(ref %d)",
-                                 client, client->ref);
+                                       client, client->ref);
                        nvnc_client_close(client);
                }
 
@@ -1518,7 +1601,7 @@
                        msg->number_of_screens, msg->screens);
 
        send_extended_desktop_size(client, RFB_RESIZE_INITIATOR_THIS_CLIENT,
-                                  status);
+                       status);
 
        return sizeof(*msg) + msg->number_of_screens * sizeof(struct 
rfb_screen);
 }
@@ -1603,7 +1686,7 @@
        }
 
        nvnc_log(NVNC_LOG_WARNING, "Got uninterpretable message from client: %p 
(ref %d)",
-                 client, client->ref);
+                       client, client->ref);
        nvnc_client_close(client);
        return 0;
 }
@@ -1676,7 +1759,7 @@
        if (n_read < 0) {
                if (errno != EAGAIN) {
                        nvnc_log(NVNC_LOG_INFO, "Client connection error: %p 
(ref %d)",
-                                 client, client->ref);
+                                       client, client->ref);
                        nvnc_client_close(client);
                }
 
@@ -1698,30 +1781,10 @@
 
        client->buffer_len -= client->buffer_index;
        memmove(client->msg_buffer, client->msg_buffer + client->buffer_index,
-               client->buffer_len);
+                       client->buffer_len);
        client->buffer_index = 0;
 }
 
-// TODO: Remove this when nvnc_client_get_hostname gets renamed.
-static void record_peer_hostname(int fd, struct nvnc_client* client)
-{
-       struct sockaddr_storage storage;
-       struct sockaddr* peer = (struct sockaddr*)&storage;
-       socklen_t peerlen = sizeof(storage);
-       if (getpeername(fd, peer, &peerlen) < 0) {
-               nvnc_log(NVNC_LOG_WARNING, "Failed to get address for client: 
%m");
-               return;
-       }
-
-       if (peer->sa_family == AF_UNIX) {
-               snprintf(client->hostname, sizeof(client->hostname),
-                               "unix domain socket");
-       } else {
-               sockaddr_to_string(client->hostname, sizeof(client->hostname),
-                               peer);
-       }
-}
-
 static void on_connection(void* obj)
 {
        struct nvnc* server = aml_get_userdata(obj);
@@ -1743,8 +1806,6 @@
        int one = 1;
        setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
 
-       record_peer_hostname(fd, client);
-
 #ifdef ENABLE_WEBSOCKET
        if (server->socket_type == NVNC__SOCKET_WEBSOCKET)
        {
@@ -1779,7 +1840,14 @@
 
        client->state = VNC_CLIENT_STATE_WAITING_FOR_VERSION;
 
-       nvnc_log(NVNC_LOG_INFO, "New client connection from %s: %p (ref %d)", 
client->hostname, client, client->ref);
+       char ip_address[256];
+       struct sockaddr_storage addr;
+       socklen_t addrlen = sizeof(addr);
+       nvnc_client_get_address(client, (struct sockaddr*)&addr, &addrlen);
+       sockaddr_to_string(ip_address, sizeof(ip_address),
+                       (struct sockaddr*)&addr);
+       nvnc_log(NVNC_LOG_INFO, "New client connection from %s: %p (ref %d)",
+                       ip_address, client, client->ref);
 
        return;
 
@@ -2032,6 +2100,8 @@
 
 static void complete_fb_update(struct nvnc_client* client)
 {
+       if (!client->is_updating)
+               return;
        client->is_updating = false;
        assert(client->current_fb);
        nvnc_fb_release(client->current_fb);
@@ -2049,7 +2119,7 @@
 }
 
 static enum rfb_encodings choose_frame_encoding(struct nvnc_client* client,
-               struct nvnc_fb* fb)
+               const struct nvnc_fb* fb)
 {
        for (size_t i = 0; i < client->n_encodings; ++i)
                switch (client->encodings[i]) {
@@ -2089,6 +2159,17 @@
        if (client->net_stream->state == STREAM_STATE_CLOSED)
                goto complete;
 
+       if (client->formats_changed) {
+               /* Client has requested new pixel format or encoding in the
+                * meantime, so it probably won't know what to do with this
+                * frame. Pending requests get incremented because this one is
+                * dropped.
+                */
+               nvnc_log(NVNC_LOG_DEBUG, "Client changed pixel format or 
encoding with in-flight buffer");
+               client->n_pending_requests++;
+               goto complete;
+       }
+
        DTRACE_PROBE2(neatvnc, send_fb_start, client, pts);
        n_rects += will_send_pts(client, pts) ? 1 : 0;
        struct rfb_server_fb_update_msg update_msg = {
@@ -2104,7 +2185,7 @@
 
        rcbuf_ref(payload);
        if (stream_send(client->net_stream, payload,
-                               on_write_frame_done, client) < 0)
+                       on_write_frame_done, client) < 0)
                goto complete;
 
        DTRACE_PROBE2(neatvnc, send_fb_done, client, pts);
@@ -2204,7 +2285,7 @@
        LIST_FOREACH(client, &self->clients, link)
                if (client->net_stream->state != STREAM_STATE_CLOSED)
                        pixman_region_union(&client->damage, &client->damage,
-                                           (struct pixman_region16*)damage);
+                                       (struct pixman_region16*)damage);
 
        LIST_FOREACH(client, &self->clients, link)
                process_fb_update_requests(client);
@@ -2301,13 +2382,10 @@
        return client->server;
 }
 
-// TODO: This function should be renamed to nvnc_client_get_address and it
-// should return the sockaddr.
 EXPORT
-const char* nvnc_client_get_hostname(const struct nvnc_client* client) {
-       if (client->hostname[0] == '\0')
-               return NULL;
-       return client->hostname;
+int nvnc_client_get_address(const struct nvnc_client* client,
+               struct sockaddr* restrict addr, socklen_t* restrict addrlen) {
+       return getpeername(client->net_stream->fd, addr, addrlen);
 }
 
 EXPORT
@@ -2366,7 +2444,7 @@
 
 EXPORT
 int nvnc_set_tls_creds(struct nvnc* self, const char* privkey_path,
-                     const char* cert_path)
+               const char* cert_path)
 {
 #ifdef ENABLE_TLS
        if (self->tls_creds)
@@ -2378,22 +2456,22 @@
        int rc = gnutls_global_init();
        if (rc != GNUTLS_E_SUCCESS) {
                nvnc_log(NVNC_LOG_ERROR, "GnuTLS: Failed to initialise: %s",
-                         gnutls_strerror(rc));
+                               gnutls_strerror(rc));
                return -1;
        }
 
        rc = gnutls_certificate_allocate_credentials(&self->tls_creds);
        if (rc != GNUTLS_E_SUCCESS) {
                nvnc_log(NVNC_LOG_ERROR, "GnuTLS: Failed to allocate 
credentials: %s",
-                         gnutls_strerror(rc));
+                               gnutls_strerror(rc));
                goto cert_alloc_failure;
        }
 
        rc = gnutls_certificate_set_x509_key_file(
-               self->tls_creds, cert_path, privkey_path, GNUTLS_X509_FMT_PEM);
+                       self->tls_creds, cert_path, privkey_path, 
GNUTLS_X509_FMT_PEM);
        if (rc != GNUTLS_E_SUCCESS) {
                nvnc_log(NVNC_LOG_ERROR, "GnuTLS: Failed to load credentials: 
%s",
-                         gnutls_strerror(rc));
+                               gnutls_strerror(rc));
                goto cert_set_failure;
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/stream-gnutls.c 
new/neatvnc-0.8.0/src/stream-gnutls.c
--- old/neatvnc-0.7.2/src/stream-gnutls.c       2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/src/stream-gnutls.c       2024-02-25 12:11:28.000000000 
+0100
@@ -169,7 +169,7 @@
 }
 
 static int stream_gnutls_send(struct stream* self, struct rcbuf* payload,
-                stream_req_fn on_done, void* userdata)
+               stream_req_fn on_done, void* userdata)
 {
        if (self->state == STREAM_STATE_CLOSED)
                return -1;
@@ -266,7 +266,7 @@
                goto failure;
 
        rc = gnutls_credentials_set(self->session, GNUTLS_CRD_CERTIFICATE,
-                                   context);
+                       context);
        if (rc != GNUTLS_E_SUCCESS)
                goto failure;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/stream-rsa-aes.c 
new/neatvnc-0.8.0/src/stream-rsa-aes.c
--- old/neatvnc-0.7.2/src/stream-rsa-aes.c      2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/src/stream-rsa-aes.c      2024-02-25 12:11:28.000000000 
+0100
@@ -148,7 +148,7 @@
 }
 
 static int stream_rsa_aes_send(struct stream* base, struct rcbuf* payload,
-                stream_req_fn on_done, void* userdata)
+               stream_req_fn on_done, void* userdata)
 {
        struct stream_rsa_aes* self = (struct stream_rsa_aes*)base;
        size_t n_msg = UDIV_UP(payload->size, RSA_AES_BUFFER_SIZE);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/stream-tcp.c 
new/neatvnc-0.8.0/src/stream-tcp.c
--- old/neatvnc-0.7.2/src/stream-tcp.c  2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/stream-tcp.c  2024-02-25 12:11:28.000000000 +0100
@@ -208,7 +208,7 @@
 }
 
 int stream_tcp_send(struct stream* self, struct rcbuf* payload,
-                stream_req_fn on_done, void* userdata)
+               stream_req_fn on_done, void* userdata)
 {
        if (self->state == STREAM_STATE_CLOSED)
                return -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/stream-ws.c 
new/neatvnc-0.8.0/src/stream-ws.c
--- old/neatvnc-0.7.2/src/stream-ws.c   2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/stream-ws.c   2024-02-25 12:11:28.000000000 +0100
@@ -145,7 +145,7 @@
        }
 
        if (!ws_parse_frame_header(&ws->header, ws->read_buffer,
-                               ws->read_index)) {
+                       ws->read_index)) {
                return 0;
        }
 
@@ -230,7 +230,7 @@
 }
 
 static int stream_ws_send(struct stream* self, struct rcbuf* payload,
-                stream_req_fn on_done, void* userdata)
+               stream_req_fn on_done, void* userdata)
 {
        struct stream_ws* ws = (struct stream_ws*)self;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/stream.c 
new/neatvnc-0.8.0/src/stream.c
--- old/neatvnc-0.7.2/src/stream.c      2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/stream.c      2024-02-25 12:11:28.000000000 +0100
@@ -31,7 +31,7 @@
 }
 
 int stream_send(struct stream* self, struct rcbuf* payload,
-                stream_req_fn on_done, void* userdata)
+               stream_req_fn on_done, void* userdata)
 {
        assert(self->impl && self->impl->send);
        return self->impl->send(self, payload, on_done, userdata);
@@ -44,7 +44,7 @@
 }
 
 int stream_write(struct stream* self, const void* payload, size_t len,
-                 stream_req_fn on_done, void* userdata)
+               stream_req_fn on_done, void* userdata)
 {
        struct rcbuf* buf = rcbuf_from_mem(payload, len);
        return buf ? stream_send(self, buf, on_done, userdata) : -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/tight.c 
new/neatvnc-0.8.0/src/tight.c
--- old/neatvnc-0.7.2/src/tight.c       2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/tight.c       2024-02-25 12:11:28.000000000 +0100
@@ -119,11 +119,11 @@
 static int tight_encoder_init_stream(z_stream* zs)
 {
        int rc = deflateInit2(zs,
-                             /* compression level: */ 1,
-                             /*            method: */ Z_DEFLATED,
-                             /*       window bits: */ 15,
-                             /*         mem level: */ 9,
-                             /*          strategy: */ Z_DEFAULT_STRATEGY);
+                       /* compression level: */ 1,
+                       /*            method: */ Z_DEFLATED,
+                       /*       window bits: */ 15,
+                       /*         mem level: */ 9,
+                       /*          strategy: */ Z_DEFAULT_STRATEGY);
        return rc == Z_OK ? 0 : -1;
 }
 
@@ -261,7 +261,7 @@
 }
 
 static int tight_deflate(struct tight_tile* tile, void* src,
-                        size_t len, z_stream* zs, bool flush)
+               size_t len, z_stream* zs, bool flush)
 {
        zs->next_in = src;
        zs->avail_in = len;
@@ -310,7 +310,7 @@
        for (uint32_t y = y_start; y < y_start + height; ++y) {
                uint8_t* img = addr + xoff + y * byte_stride;
                pixel_to_cpixel(row, &cfmt, img, &self->sfmt,
-                       bytes_per_cpixel, width);
+                               bytes_per_cpixel, width);
 
                // TODO What to do if the buffer fills up?
                if (tight_deflate(tile, row, bytes_per_cpixel * width,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/ws-handshake.c 
new/neatvnc-0.8.0/src/ws-handshake.c
--- old/neatvnc-0.7.2/src/ws-handshake.c        2024-02-02 23:42:16.000000000 
+0100
+++ new/neatvnc-0.8.0/src/ws-handshake.c        2024-02-25 12:11:28.000000000 
+0100
@@ -88,15 +88,15 @@
        base64_encode(response, hash, sizeof(hash));
 
        size_t len = snprintf(output, output_maxlen,
-               "HTTP/1.1 101 Switching Protocols\r\n"
-               "Upgrade: websocket\r\n"
-               "Connection: Upgrade\r\n"
-               "Sec-WebSocket-Accept: %s\r\n"
-               "%s%s"
-               "\r\n",
-               response,
-               have_protocols ? "Sec-WebSocket-Protocol: char\r\n" : "",
-               have_versions ? "Sec-WebSocket-Version: 13\r\n" : "");
+                       "HTTP/1.1 101 Switching Protocols\r\n"
+                       "Upgrade: websocket\r\n"
+                       "Connection: Upgrade\r\n"
+                       "Sec-WebSocket-Accept: %s\r\n"
+                       "%s%s"
+                       "\r\n",
+                       response,
+                       have_protocols ? "Sec-WebSocket-Protocol: char\r\n" : 
"",
+                       have_versions ? "Sec-WebSocket-Version: 13\r\n" : "");
 
        ssize_t header_len = req.header_length;
        ok = len < output_maxlen;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/src/zrle.c new/neatvnc-0.8.0/src/zrle.c
--- old/neatvnc-0.7.2/src/zrle.c        2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/src/zrle.c        2024-02-25 12:11:28.000000000 +0100
@@ -62,7 +62,7 @@
 }
 
 static inline int find_colour_in_palette(uint8_t* palette, int len,
-                                         const uint8_t* colour, int bpp)
+               const uint8_t* colour, int bpp)
 {
        for (int i = 0; i < len; ++i)
                if (memcmp(palette + i * bpp, colour, bpp) == 0)
@@ -72,7 +72,7 @@
 }
 
 static int zrle_get_tile_palette(uint8_t* palette, const uint8_t* src,
-                                 const int src_bpp, size_t length)
+               const int src_bpp, size_t length)
 {
        int n = 0;
 
@@ -94,16 +94,16 @@
 }
 
 static void zrle_encode_unichrome_tile(struct vec* dst,
-                                       const struct rfb_pixel_format* dst_fmt,
-                                       uint8_t* colour,
-                                       const struct rfb_pixel_format* src_fmt)
+               const struct rfb_pixel_format* dst_fmt,
+               uint8_t* colour,
+               const struct rfb_pixel_format* src_fmt)
 {
        int bytes_per_cpixel = calc_bytes_per_cpixel(dst_fmt);
 
        vec_fast_append_8(dst, 1);
 
        pixel_to_cpixel(((uint8_t*)dst->data) + 1, dst_fmt, colour, src_fmt,
-                         bytes_per_cpixel, 1);
+                       bytes_per_cpixel, 1);
 
        dst->len += bytes_per_cpixel;
 }
@@ -126,18 +126,18 @@
 }
 
 static void zrle_encode_packed_tile(struct vec* dst,
-                                    const struct rfb_pixel_format* dst_fmt,
-                                    const uint8_t* src,
-                                    const struct rfb_pixel_format* src_fmt,
-                                    size_t length, uint8_t* palette,
-                                    int palette_size)
+               const struct rfb_pixel_format* dst_fmt,
+               const uint8_t* src,
+               const struct rfb_pixel_format* src_fmt,
+               size_t length, uint8_t* palette,
+               int palette_size)
 {
        int bytes_per_cpixel = calc_bytes_per_cpixel(dst_fmt);
        int src_bpp = src_fmt->bits_per_pixel / 8;
 
        uint8_t cpalette[16 * 3];
        pixel_to_cpixel(cpalette, dst_fmt, palette, src_fmt,
-                         bytes_per_cpixel, palette_size);
+                       bytes_per_cpixel, palette_size);
 
        vec_fast_append_8(dst, 128 | palette_size);
 
@@ -159,13 +159,13 @@
 
        if (run_length > 0) {
                index = find_colour_in_palette(palette, palette_size,
-                                              src + (length - 1) * src_bpp, 
src_bpp);
+                               src + (length - 1) * src_bpp, src_bpp);
                encode_run_length(dst, index, run_length);
        }
 }
 
 static void zrle_copy_tile(uint8_t* tile, const uint8_t* src, int src_bpp,
-                           int stride, int width, int height)
+               int stride, int width, int height)
 {
        int byte_stride = stride * src_bpp;
        for (int y = 0; y < height; ++y)
@@ -173,10 +173,10 @@
 }
 
 static void zrle_encode_tile(struct vec* dst,
-                             const struct rfb_pixel_format* dst_fmt,
-                             const uint8_t* src,
-                             const struct rfb_pixel_format* src_fmt,
-                             size_t length)
+               const struct rfb_pixel_format* dst_fmt,
+               const uint8_t* src,
+               const struct rfb_pixel_format* src_fmt,
+               size_t length)
 {
        int bytes_per_cpixel = calc_bytes_per_cpixel(dst_fmt);
        int src_bpp = src_fmt->bits_per_pixel / 8;
@@ -192,20 +192,20 @@
 
        if (palette_size > 1) {
                zrle_encode_packed_tile(dst, dst_fmt, src, src_fmt, length,
-                                       palette, palette_size);
+                               palette, palette_size);
                return;
        }
 
        vec_fast_append_8(dst, 0);
 
        pixel_to_cpixel(((uint8_t*)dst->data) + 1, dst_fmt, (uint8_t*)src, 
src_fmt,
-                         bytes_per_cpixel, length);
+                       bytes_per_cpixel, length);
 
        dst->len += bytes_per_cpixel * length;
 }
 
 static int zrle_deflate(struct vec* dst, const struct vec* src, z_stream* zs,
-                        bool flush)
+               bool flush)
 {
        zs->next_in = src->data;
        zs->avail_in = src->len;
@@ -230,10 +230,10 @@
 }
 
 static int zrle_encode_box(struct zrle_encoder* self, struct vec* out,
-                           const struct rfb_pixel_format* dst_fmt,
-                           const struct nvnc_fb* fb,
-                           const struct rfb_pixel_format* src_fmt, int x, int 
y,
-                           int stride, int width, int height, z_stream* zs)
+               const struct rfb_pixel_format* dst_fmt,
+               const struct nvnc_fb* fb,
+               const struct rfb_pixel_format* src_fmt, int x, int y,
+               int stride, int width, int height, z_stream* zs)
 {
        int r = -1;
        int bytes_per_cpixel = calc_bytes_per_cpixel(dst_fmt);
@@ -275,11 +275,11 @@
                int x_off = (x + tile_x) * src_bpp;
 
                zrle_copy_tile(tile,
-                              ((uint8_t*)fb->addr) + x_off + y_off, src_bpp,
-                              stride, tile_width, tile_height);
+                               ((uint8_t*)fb->addr) + x_off + y_off, src_bpp,
+                               stride, tile_width, tile_height);
 
                zrle_encode_tile(&in, dst_fmt, tile, src_fmt,
-                                tile_width * tile_height);
+                               tile_width * tile_height);
 
                r = zrle_deflate(out, &in, zs, i == n_tiles - 1);
                if (r < 0)
@@ -323,7 +323,7 @@
                int box_height = box[i].y2 - y;
 
                rc = zrle_encode_box(self, dst, dst_fmt, src, src_fmt, x, y,
-                                    src->stride, box_width, box_height, zs);
+                               src->stride, box_width, box_height, zs);
                if (rc < 0)
                        return -1;
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/neatvnc-0.7.2/test/meson.build 
new/neatvnc-0.8.0/test/meson.build
--- old/neatvnc-0.7.2/test/meson.build  2024-02-02 23:42:16.000000000 +0100
+++ new/neatvnc-0.8.0/test/meson.build  2024-02-25 12:11:28.000000000 +0100
@@ -7,6 +7,7 @@
        dependencies: [
                pixman,
                libdrm_inc,
+               libm,
        ],
 )
 test('pixels', pixels)

Reply via email to