Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package neatvnc for openSUSE:Factory checked in at 2026-10-08 15:14:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/neatvnc (Old) and /work/SRC/openSUSE:Factory/.neatvnc.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "neatvnc" Thu Oct 8 15:14:03 2026 rev:23 rq:1383307 version:1.0.3 Changes: -------- --- /work/SRC/openSUSE:Factory/neatvnc/neatvnc.changes 2026-09-28 10:49:29.865607483 +0200 +++ /work/SRC/openSUSE:Factory/.neatvnc.new.3698736/neatvnc.changes 2026-10-08 15:14:43.575119096 +0200 @@ -1,0 +2,23 @@ +Thu Oct 8 12:25:49 UTC 2026 - Dominique Leuenberger <[email protected]> + +- Add 5b190f0.patch: backport from master: Use nettle & hogweed version 4; + Fixes build against libnettle 4.x. + +------------------------------------------------------------------- +Thu Oct 8 11:59:41 UTC 2026 - Michael Vetter <[email protected]> + +- Update to 1.0.3: + * stream: Fix message ordering, stalls and leaks + * stream: Remove local send queue + * stream: Do callbacks last on close + * stream: Add weakref guard around stream_close in remote_closed + * stream: ws: Return early on read failure + * stream: rsa-aes: Return early on read failure + * stream: ws: Return early on header send failure + * stream: ws: Queue frame header with payload + * stream: ws: Wait for complete ping before replying + * stream: ws: Keep mask phase across payload chunks + * stream: ws: Handle control frames between fragments + * stream: ws: Keep reading after empty frame + +------------------------------------------------------------------- Old: ---- neatvnc-1.0.2.tar.xz New: ---- 5b190f0.patch neatvnc-1.0.3.tar.xz ----------(New B)---------- New: - Add 5b190f0.patch: backport from master: Use nettle & hogweed version 4; Fixes build against libnettle 4.x. ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ neatvnc.spec ++++++ --- /var/tmp/diff_new_pack.fAlHaB/_old 2026-10-08 15:14:44.937176164 +0200 +++ /var/tmp/diff_new_pack.fAlHaB/_new 2026-10-08 15:14:44.938176205 +0200 @@ -19,7 +19,7 @@ %define libsoname libneatvnc1 Name: neatvnc -Version: 1.0.2 +Version: 1.0.3 Release: 0 Summary: A VNC server library License: ISC @@ -27,6 +27,8 @@ URL: https://github.com/any1/neatvnc Source0: %{name}-%{version}.tar.xz Patch0: fix-build-in-15.6.patch +# PATCH-FIX-UPSTREAM -- Use nettle & hogweed version 4; backported from https://github.com/any1/neatvnc/commit/5b190f0.patch +Patch1: 5b190f0.patch BuildRequires: meson BuildRequires: pkgconfig ++++++ 5b190f0.patch ++++++ >From 5b190f0fd9e6b0bfd32752a9115242f87ec36c59 Mon Sep 17 00:00:00 2001 From: Andri Yngvason <[email protected]> Date: Sun, 17 May 2026 09:57:07 +0000 Subject: [PATCH] Use nettle & hogweed version 4 --- meson.build | 6 ++++-- src/crypto/nettle/cipher.c | 8 ++++---- src/crypto/nettle/hash.c | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) Index: neatvnc-1.0.3/meson.build =================================================================== --- neatvnc-1.0.3.orig/meson.build +++ neatvnc-1.0.3/meson.build @@ -61,8 +61,10 @@ libm = cc.find_library('m', required: fa pixman = dependency('pixman-1') libturbojpeg = dependency('libturbojpeg', required: get_option('jpeg')) gnutls = dependency('gnutls', required: get_option('tls')) -nettle = dependency('nettle', required: get_option('nettle')) -hogweed = dependency('hogweed', required: get_option('nettle')) +nettle = dependency('nettle', required: get_option('nettle'), + version: ['>=4.0', '<5.0']) +hogweed = dependency('hogweed', required: get_option('nettle'), + version: ['>=4.0', '<5.0']) gmp = cc.find_library('gmp') zlib = dependency('zlib') gbm = dependency('gbm', required: get_option('gbm')) Index: neatvnc-1.0.3/src/crypto/nettle/cipher.c =================================================================== --- neatvnc-1.0.3.orig/src/crypto/nettle/cipher.c +++ neatvnc-1.0.3/src/crypto/nettle/cipher.c @@ -119,7 +119,7 @@ static bool crypto_cipher_aes_eax_encryp (uint8_t*)dst->data + dst->len, src); dst->len += src_len; - nettle_eax_aes128_digest(&self->enc_ctx.aes_eax.ctx, 16, mac); + nettle_eax_aes128_digest(&self->enc_ctx.aes_eax.ctx, mac); return true; } @@ -131,7 +131,7 @@ static ssize_t crypto_cipher_aes_eax_dec crypto_aes_eax_update_nonce(&self->dec_ctx.aes_eax); nettle_eax_aes128_update(&self->dec_ctx.aes_eax.ctx, ad_len, ad); nettle_eax_aes128_decrypt(&self->dec_ctx.aes_eax.ctx, len, dst, src); - nettle_eax_aes128_digest(&self->dec_ctx.aes_eax.ctx, 16, mac); + nettle_eax_aes128_digest(&self->dec_ctx.aes_eax.ctx, mac); return len; } @@ -179,7 +179,7 @@ static bool crypto_cipher_aes256_eax_enc (uint8_t*)dst->data + dst->len, src); dst->len += src_len; - EAX_DIGEST(&self->enc_ctx.aes256_eax.ctx, aes256_encrypt, 16, mac); + EAX_DIGEST(&self->enc_ctx.aes256_eax.ctx, aes256_encrypt, mac); return true; } @@ -191,7 +191,7 @@ static ssize_t crypto_cipher_aes256_eax_ crypto_aes256_eax_update_nonce(&self->dec_ctx.aes256_eax); EAX_UPDATE(&self->dec_ctx.aes256_eax.ctx, aes256_encrypt, ad_len, ad); EAX_DECRYPT(&self->dec_ctx.aes256_eax.ctx, aes256_encrypt, len, dst, src); - EAX_DIGEST(&self->dec_ctx.aes256_eax.ctx, aes256_encrypt, 16, mac); + EAX_DIGEST(&self->dec_ctx.aes256_eax.ctx, aes256_encrypt, mac); return len; } Index: neatvnc-1.0.3/src/crypto/nettle/hash.c =================================================================== --- neatvnc-1.0.3.orig/src/crypto/nettle/hash.c +++ neatvnc-1.0.3/src/crypto/nettle/hash.c @@ -21,7 +21,7 @@ #include <stdlib.h> #include <nettle/md5.h> #include <nettle/sha1.h> -#include <nettle/sha.h> +#include <nettle/sha2.h> struct crypto_hash { union { ++++++ _service ++++++ --- /var/tmp/diff_new_pack.fAlHaB/_old 2026-10-08 15:14:44.991178426 +0200 +++ /var/tmp/diff_new_pack.fAlHaB/_new 2026-10-08 15:14:44.998178719 +0200 @@ -3,8 +3,8 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://github.com/any1/neatvnc.git</param> - <param name="revision">4d6d09b544d84b836cf1906735354b4e694a0c1c</param> - <param name="versionformat">1.0.2</param> + <param name="revision">783437adc56c2d7ce2cac1ec584acad798594267</param> + <param name="versionformat">1.0.3</param> </service> <service name="tar" mode="manual"/> <service name="recompress" mode="manual"> ++++++ neatvnc-1.0.2.tar.xz -> neatvnc-1.0.3.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/include/stream/stream.h new/neatvnc-1.0.3/include/stream/stream.h --- old/neatvnc-1.0.2/include/stream/stream.h 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/include/stream/stream.h 2026-10-03 18:25:04.000000000 +0200 @@ -20,6 +20,7 @@ #include "sys/queue.h" #include "rcbuf.h" #include "vec.h" +#include "weakref.h" #ifdef HAVE_CRYPTO #include "crypto.h" @@ -78,7 +79,7 @@ struct stream { struct stream_impl *impl; - int ref; + struct weakref_subject weakref; enum stream_state state; @@ -104,7 +105,6 @@ struct stream* stream_new(int fd, stream_event_fn on_event, void* userdata); void stream_init(struct stream* self); -void stream_ref(struct stream* self); int stream_close(struct stream* self); void stream_destroy(struct stream* self); ssize_t stream_read(struct stream* self, void* dst, size_t size); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/meson.build new/neatvnc-1.0.3/meson.build --- old/neatvnc-1.0.2/meson.build 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/meson.build 2026-10-03 18:25:04.000000000 +0200 @@ -1,7 +1,7 @@ project( 'neatvnc', 'c', - version: '1.0.1', + version: '1.0.3', license: 'ISC', default_options: [ 'c_std=gnu11', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/src/server.c new/neatvnc-1.0.3/src/server.c --- old/neatvnc-1.0.2/src/server.c 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/src/server.c 2026-10-03 18:25:04.000000000 +0200 @@ -1255,7 +1255,7 @@ int height = ntohs(msg->height); if (incremental && client->continuous_updates_enabled) - return 0; + return sizeof(*msg); client->n_pending_requests++; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/src/stream/common.c new/neatvnc-1.0.3/src/stream/common.c --- old/neatvnc-1.0.2/src/stream/common.c 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/src/stream/common.c 2026-10-03 18:25:04.000000000 +0200 @@ -21,7 +21,7 @@ void stream_init(struct stream* self) { - self->ref = 1; + weakref_subject_init(&self->weakref); } void stream_req__finish(struct stream_req* req, enum stream_req_status status) @@ -39,8 +39,13 @@ void stream__remote_closed(struct stream* self) { + struct weakref_observer ref; + weakref_observer_init(&ref, &self->weakref); + stream_close(self); - if (self->on_event) + if (ref.subject && self->on_event) self->on_event(self, STREAM_EVENT_REMOTE_CLOSED); + + weakref_observer_deinit(&ref); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/src/stream/gnutls.c new/neatvnc-1.0.3/src/stream/gnutls.c --- old/neatvnc-1.0.2/src/stream/gnutls.c 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/src/stream/gnutls.c 2026-10-03 18:25:04.000000000 +0200 @@ -54,14 +54,6 @@ self->base.state = STREAM_STATE_CLOSED; - stream_ref(&self->base); - - while (!TAILQ_EMPTY(&self->base.send_queue)) { - struct stream_req* req = TAILQ_FIRST(&self->base.send_queue); - TAILQ_REMOVE(&self->base.send_queue, req, link); - stream_req__finish(req, STREAM_REQ_FAILED); - } - if (self->session) gnutls_deinit(self->session); self->session = NULL; @@ -70,8 +62,15 @@ close(self->base.fd); self->base.fd = -1; - // unref - stream_destroy(&self->base); + struct stream_send_queue send_queue; + TAILQ_INIT(&send_queue); + TAILQ_CONCAT(&send_queue, &self->base.send_queue, link); + + while (!TAILQ_EMPTY(&send_queue)) { + struct stream_req* req = TAILQ_FIRST(&send_queue); + TAILQ_REMOVE(&send_queue, req, link); + stream_req__finish(req, STREAM_REQ_FAILED); + } return 0; } @@ -85,15 +84,20 @@ static int stream_gnutls__flush(struct stream* base) { + if (base->cork) + return 0; + struct stream_gnutls* self = (struct stream_gnutls*)base; - stream_ref(base); + struct weakref_observer ref; + weakref_observer_init(&ref, &base->weakref); + int rc = -1; - while (!TAILQ_EMPTY(&self->base.send_queue)) { - assert(self->base.state != STREAM_STATE_CLOSED); + base->cork = true; - struct stream_req* req = TAILQ_FIRST(&self->base.send_queue); + while (!TAILQ_EMPTY(&base->send_queue)) { + struct stream_req* req = TAILQ_FIRST(&base->send_queue); /* GnuTLS returns an error when sending with 0 data_size */ if (req->payload->size == 0) @@ -129,17 +133,24 @@ assert(remaining == 0); req_done: - TAILQ_REMOVE(&self->base.send_queue, req, link); + TAILQ_REMOVE(&base->send_queue, req, link); stream_req__finish(req, STREAM_REQ_DONE); + if (!ref.subject || base->state == STREAM_STATE_CLOSED) + goto done; } - if (TAILQ_EMPTY(&base->send_queue) && base->state != STREAM_STATE_CLOSED) - stream__poll_r(base); - rc = 1; done: - // unref - stream_destroy(base); + if (ref.subject && base->state != STREAM_STATE_CLOSED) { + base->cork = false; + + if (TAILQ_EMPTY(&base->send_queue)) + stream__poll_r(base); + else + stream__poll_rw(base); + } + + weakref_observer_deinit(&ref); return rc; } @@ -181,15 +192,16 @@ struct stream* self = aml_get_userdata(handler); uint32_t events = aml_get_revents(handler); - stream_ref(self); + struct weakref_observer ref; + weakref_observer_init(&ref, &self->weakref); if (events & AML_EVENT_READ) stream_gnutls__on_readable(self); - if (events & AML_EVENT_WRITE) + if ((events & AML_EVENT_WRITE) && ref.subject) stream_gnutls__on_writable(self); - stream_destroy(self); + weakref_observer_deinit(&ref); } static int stream_gnutls_send(struct stream* self, struct rcbuf* payload, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/src/stream/interface.c new/neatvnc-1.0.3/src/stream/interface.c --- old/neatvnc-1.0.2/src/stream/interface.c 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/src/stream/interface.c 2026-10-03 18:25:04.000000000 +0200 @@ -18,11 +18,6 @@ #include <assert.h> -void stream_ref(struct stream* self) -{ - self->ref++; -} - int stream_close(struct stream* self) { assert(self->impl && self->impl->close); @@ -32,8 +27,8 @@ void stream_destroy(struct stream* self) { assert(self->impl && self->impl->destroy); - if (--self->ref == 0) - return self->impl->destroy(self); + weakref_subject_deinit(&self->weakref); + self->impl->destroy(self); } int stream_send(struct stream* self, struct rcbuf* payload, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/src/stream/rsa-aes.c new/neatvnc-1.0.3/src/stream/rsa-aes.c --- old/neatvnc-1.0.2/src/stream/rsa-aes.c 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/src/stream/rsa-aes.c 2026-10-03 18:25:04.000000000 +0200 @@ -52,13 +52,14 @@ stream_tcp_destroy(base); } -static void stream_rsa_aes_read_into_buffer(struct stream_rsa_aes* self) +static ssize_t stream_rsa_aes_read_into_buffer(struct stream_rsa_aes* self) { ssize_t n_read = stream_tcp_read(&self->base, self->read_buffer + self->read_index, RSA_AES_BUFFER_SIZE - self->read_index); if (n_read > 0) self->read_index += n_read; + return n_read; } static ssize_t stream_rsa_aes_parse_header(struct stream_rsa_aes* self) @@ -121,9 +122,9 @@ { struct stream_rsa_aes* self = (struct stream_rsa_aes*)base; - stream_rsa_aes_read_into_buffer(self); - if (self->base.state == STREAM_STATE_CLOSED) - return 0; + ssize_t n_read = stream_rsa_aes_read_into_buffer(self); + if (n_read <= 0) + return n_read; size_t total_read = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/src/stream/tcp.c new/neatvnc-1.0.3/src/stream/tcp.c --- old/neatvnc-1.0.2/src/stream/tcp.c 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/src/stream/tcp.c 2026-10-03 18:25:04.000000000 +0200 @@ -45,20 +45,19 @@ self->state = STREAM_STATE_CLOSED; self->cork = true; - stream_ref(self); - - while (!TAILQ_EMPTY(&self->send_queue)) { - struct stream_req* req = TAILQ_FIRST(&self->send_queue); - TAILQ_REMOVE(&self->send_queue, req, link); - stream_req__finish(req, STREAM_REQ_FAILED); - } - aml_stop(aml_get_default(), self->handler); close(self->fd); self->fd = -1; - // unref - stream_destroy(self); + struct stream_send_queue send_queue; + TAILQ_INIT(&send_queue); + TAILQ_CONCAT(&send_queue, &self->send_queue, link); + + while (!TAILQ_EMPTY(&send_queue)) { + struct stream_req* req = TAILQ_FIRST(&send_queue); + TAILQ_REMOVE(&send_queue, req, link); + stream_req__finish(req, STREAM_REQ_FAILED); + } return 0; } @@ -125,7 +124,8 @@ // Don't flush while flushing self->cork = true; - stream_ref(self); + struct weakref_observer ref; + weakref_observer_init(&ref, &self->weakref); struct stream_req* tmp; TAILQ_FOREACH_SAFE(req, &self->send_queue, link, tmp) { @@ -134,6 +134,8 @@ if (bytes_left >= 0) { TAILQ_REMOVE(&self->send_queue, req, link); stream_req__finish(req, STREAM_REQ_DONE); + if (!ref.subject || self->state == STREAM_STATE_CLOSED) + break; } else { if (req->exec) { free(req->userdata); @@ -151,15 +153,18 @@ break; } - self->cork = false; + if (ref.subject && self->state != STREAM_STATE_CLOSED) { + self->cork = false; - if (bytes_left == 0 && self->state != STREAM_STATE_CLOSED) - stream__poll_r(self); + if (TAILQ_EMPTY(&self->send_queue)) + stream__poll_r(self); + else + stream__poll_rw(self); - assert(bytes_left <= 0); + assert(bytes_left <= 0); + } - // unref - stream_destroy(self); + weakref_observer_deinit(&ref); return bytes_sent; } @@ -198,16 +203,16 @@ // We hold a reference here in case the stream gets destroyed inside // callback. - stream_ref(self); + struct weakref_observer ref; + weakref_observer_init(&ref, &self->weakref); if (events & AML_EVENT_READ) stream_tcp__on_readable(self); - if (events & AML_EVENT_WRITE) + if ((events & AML_EVENT_WRITE) && ref.subject) stream_tcp__on_writable(self); - // unref - stream_destroy(self); + weakref_observer_deinit(&ref); } ssize_t stream_tcp_read(struct stream* self, void* dst, size_t size) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/neatvnc-1.0.2/src/stream/ws/ws.c new/neatvnc-1.0.3/src/stream/ws/ws.c --- old/neatvnc-1.0.2/src/stream/ws/ws.c 2026-07-09 20:55:08.000000000 +0200 +++ new/neatvnc-1.0.3/src/stream/ws/ws.c 2026-10-03 18:25:04.000000000 +0200 @@ -47,13 +47,14 @@ uint8_t read_buffer[4096]; // TODO: Is this a reasonable size? }; -static void stream_ws_read_into_buffer(struct stream_ws* ws) +static ssize_t stream_ws_read_into_buffer(struct stream_ws* ws) { ssize_t n_read = stream_tcp_read(&ws->base, ws->read_buffer + ws->read_index, sizeof(ws->read_buffer) - ws->read_index); if (n_read > 0) ws->read_index += n_read; + return n_read; } static void stream_ws_advance_read_buffer(struct stream_ws* ws, size_t size, @@ -66,6 +67,11 @@ memmove(ws->read_buffer, ws->read_buffer + offset + payload_len, ws->read_index); ws->header.payload_length -= payload_len; + + uint8_t key[4]; + memcpy(key, ws->header.masking_key, sizeof(key)); + for (int i = 0; i < 4; ++i) + ws->header.masking_key[i] = key[(i + payload_len) % 4]; } static ssize_t stream_ws_copy_payload(struct stream_ws* ws, void* dst, @@ -79,6 +85,15 @@ return payload_len; } +static int stream_ws_queue(struct stream_ws* ws, struct rcbuf* payload) +{ + bool cork = ws->base.cork; + ws->base.cork = true; + int rc = stream_tcp_send(&ws->base, payload, NULL, NULL); + ws->base.cork = cork; + return rc; +} + static ssize_t stream_ws_process_ping(struct stream_ws* ws, size_t offset) { if (offset > 0) { @@ -91,8 +106,8 @@ uint8_t buf[WS_HEADER_MIN_SIZE]; int reply_len = ws_write_frame_header(buf, &reply); - stream_tcp_send(&ws->base, rcbuf_from_mem(buf, reply_len), - NULL, NULL); + if (stream_ws_queue(ws, rcbuf_from_mem(buf, reply_len)) < 0) + return -1; } int payload_len = MIN(ws->read_index - offset, ws->header.payload_length); @@ -102,7 +117,8 @@ assert(rcbuf && rcbuf->payload); ws_copy_payload(&ws->header, rcbuf->payload, ws->read_buffer + offset, payload_len); - stream_tcp_send(&ws->base, rcbuf, NULL, NULL); + if (stream_tcp_send(&ws->base, rcbuf, NULL, NULL) < 0) + return -1; stream_ws_advance_read_buffer(ws, payload_len, offset); return 0; @@ -111,7 +127,10 @@ static ssize_t stream_ws_process_payload(struct stream_ws* ws, void* dst, size_t size, size_t offset) { - switch (ws->current_opcode) { + enum ws_opcode opcode = ws->header.opcode == WS_OPCODE_CONT ? + ws->current_opcode : ws->header.opcode; + + switch (opcode) { case WS_OPCODE_CONT: // Remote end started with a continuation frame. This is // unexpected, so we'll just close. @@ -152,7 +171,15 @@ return 0; } - if (ws->header.opcode != WS_OPCODE_CONT) { + if (ws->header.opcode == WS_OPCODE_PING && + ws->read_index - ws->header.header_length < + ws->header.payload_length) { + ws->header.payload_length = 0; + return 0; + } + + if (ws->header.opcode == WS_OPCODE_TEXT || + ws->header.opcode == WS_OPCODE_BIN) { ws->current_opcode = ws->header.opcode; } @@ -165,18 +192,28 @@ static ssize_t stream_ws_read_ready(struct stream_ws* ws, void* dst, size_t size) { - size_t total_read = 0; + struct weakref_observer ref; + weakref_observer_init(&ref, &ws->base.weakref); + + ssize_t total_read = 0; while (true) { + size_t read_index = ws->read_index; ssize_t n_read = stream_ws_read_frame(ws, dst, size); - if (n_read == 0) + if (!ref.subject) break; - if (n_read < 0) { - if (errno == EAGAIN) { + if (n_read == 0) { + if (ws->base.state == STREAM_STATE_CLOSED || + ws->read_index == read_index) break; - } - return -1; + continue; + } + + if (n_read < 0) { + if (errno != EAGAIN) + total_read = -1; + break; } total_read += n_read; @@ -184,6 +221,7 @@ size -= n_read; } + weakref_observer_deinit(&ref); return total_read; } @@ -218,9 +256,9 @@ { struct stream_ws* ws = (struct stream_ws*)self; - stream_ws_read_into_buffer(ws); - if (self->state == STREAM_STATE_CLOSED) - return 0; + ssize_t n_read = stream_ws_read_into_buffer(ws); + if (n_read <= 0) + return n_read; switch (ws->ws_state) { case STREAM_WS_STATE_HANDSHAKE: @@ -246,8 +284,11 @@ uint8_t raw_head[WS_HEADER_MIN_SIZE]; int head_len = ws_write_frame_header(raw_head, &head); - stream_tcp_send(&ws->base, rcbuf_from_mem(&raw_head, head_len), - NULL, NULL); + if (stream_ws_queue(ws, rcbuf_from_mem(&raw_head, head_len)) < 0) { + rcbuf_unref(payload); + return -1; + } + return stream_tcp_send(&ws->base, payload, on_done, userdata); } ++++++ neatvnc.obsinfo ++++++ --- /var/tmp/diff_new_pack.fAlHaB/_old 2026-10-08 15:14:45.183186471 +0200 +++ /var/tmp/diff_new_pack.fAlHaB/_new 2026-10-08 15:14:45.190186764 +0200 @@ -1,5 +1,5 @@ name: neatvnc -version: 1.0.2 -mtime: 1783623308 -commit: 4d6d09b544d84b836cf1906735354b4e694a0c1c +version: 1.0.3 +mtime: 1791044704 +commit: 783437adc56c2d7ce2cac1ec584acad798594267
