libnetplus (20260711+25) unstable; urgency=high

  * tls::CertificateBundle::loadFromFile(): detect PEM vs DER by content
    (sniff for "-----BEGIN ") instead of by file extension. The non-
    ".pem" branch called x509cert::loadFromFile(), which parses only the
    first certificate block and never touches `chain` — so a multi-cert
    PEM bundle (leaf + intermediate CA) shipped under any other
    extension (fullchain.crt, server.cer, ...) had its intermediate
    silently dropped. The server then handshook with a leaf-only chain:
    clients that don't chase the missing intermediate via AIA reject it
    with a fatal certificate_unknown (tls13 alert desc=46) — reproduced
    on two separate mediadb nodes.

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 11 Jul 2026 19:00:00 +0200

libnetplus (20260629+24) unstable; urgency=medium

  * tls: extend TLS 1.2 ECDHE support with ECDHE_RSA suites
    (0xC02F/0xC030) alongside ECDHE_ECDSA, and add AES-256-GCM variants
    (0xC02C/0xC030) — server picks ECDHE_ECDSA when the loaded cert
    bundle has an EC key, ECDHE_RSA (falling back to static RSA) when
    it has an RSA key; key-block derivation now sizes client/server
    write keys per chosen suite (16 or 32 bytes) for both CBC and GCM
  * tls: add TLS 1.2 client-side ECDHE_ECDSA handshake path — client
    detects an EC server certificate via x509::isECKey(), waits for
    ServerKeyExchange, generates an ephemeral P-256 key pair, computes
    the ECDH shared secret and sends the client EC point in
    ClientKeyExchange instead of RSA-encrypted PreMasterSecret
  * x509: add isECKey()/extractECPublicKey() to detect the
    ecPublicKey OID (1.2.840.10045.2.1) and pull the raw EC point out
    of SubjectPublicKeyInfo
  * tls: implement RFC 7627 Extended Master Secret — negotiate the
    extended_master_secret extension on both ClientHello/ServerHello
    and derive master_secret from PRF(PMS, "extended master secret",
    session_hash) instead of client/server random when both sides
    support it; add handshake_transcript tracking for ServerHello,
    Certificate, ServerKeyExchange and ServerHelloDone needed for the
    session hash
  * tls: fix ServerHello parser rejecting legacy TLS 1.2 servers that
    omit the extensions block entirely — length check required the
    2-byte extensions length field unconditionally and the SID-overflow
    check didn't account for the trailing cipher_suite+compression
    bytes, causing valid short ServerHellos to be misparsed or rejected
  * tls: fix client-side GCM cipher suites failing handshake because
    the "MAC key missing for TLS 1.2" check ran unconditionally even
    though GCM suites carry no separate MAC key
  * tls: fix recvData() deadlock when a prior non-blocking sendData()
    left TLS records queued — flush pending output before reading so
    the peer actually receives what was queued instead of both sides
    waiting on each other
  * ssl: add 15s deadline to the blocking ssl::connect() handshake
    drive loop to avoid hanging indefinitely on an unresponsive peer,
    and fix the added wait loop busy-spinning handshake_after_connect()
    on NetException::Note by waiting on socket readability
    (socketwait::waitRead, 100ms) instead of retrying immediately
  * windows/tcp: fix blocking tcp::connect() relying on WSAConnect()
    blocking indefinitely — switch to non-blocking connect + select()
    with a 10s timeout, checking SO_ERROR for real connect failure
  * windows/socket: fix setTimeout() misinterpreting its argument as
    microseconds and dividing by 1000 — all four event backends
    (epoll/iocp/kqueue/poll) already pass a millisecond timeout
    directly, so on Windows small timeouts (e.g. 500ms) were truncated
    to 0
  * event: add event::requestStop() across all backends (epoll, iocp,
    kqueue, poll) for thread-safe, immediate event-loop shutdown —
    epoll/kqueue register a wakeup eventfd/pipe that a SIGINT handler
    or requestStop() writes to, unblocking epoll_wait()/kevent()
    immediately instead of waiting for the poll timeout; iocp posts a
    zero-length completion per worker via PostQueuedCompletionStatus
  * iocp: fix accepted sockets not entering non-blocking mode and
    missing TCP keep-alive (SIO_KEEPALIVE_VALS, 60s idle/10s interval);
    fix failed IOCP completions (ok==false) falling through unhandled
    instead of clearing pending-I/O flags and cleaning up the
    connection
  * iocp: fix TLS handshake flights getting stuck under IOCP — flush
    queued records before and after each handshake_after_accept() step
    and correctly re-arm WritePending instead of silently dropping
    still-queued data when a write is already in flight
  * iocp: replace O(n) erase()-per-chunk send buffer compaction with
    position-based tracking to avoid repeated large memmoves on big
    responses; convert conMutex to std::shared_mutex so connection
    lookups no longer serialize against each other; fix EWOULDBLOCK on
    send silently dropping buffered data — now posts a completion to
    retry the send later
  * posix/tcp, posix/udp: disable IPV6_V6ONLY on IPv6 listening
    sockets so binding to "::" also serves IPv4-mapped clients
    (dual-stack), regardless of the system's bindv6only sysctl default
  * rsa: rewrite modInverse() from binary Extended Euclidean (unsigned,
    parity-based) to signed Extended Euclidean algorithm; rsa now
    stores p/q and exposes getP()/getQ() so certgen can compute real
    CRT parameters (exponent1/exponent2/coefficient) instead of writing
    zero placeholders into the PKCS#1 RSAPrivateKey DER
  * exception: make NetException derive from std::exception and
    implement what() as const char* noexcept override, so generic
    catch (std::exception&) handlers (e.g. epoll's connection-error
    logging) now also catch NetException instead of only catch (...)

 -- Jan Koester <jan.koester@tuxist.de>  Sun, 28 Jun 2026 12:00:00 +0200

libnetplus (20260528+23) unstable; urgency=medium

  * ecc: fix mod_n256 infinite loop in ECDSA signing — replace O(2^32)
    repeated subtraction with O(512) bit-by-bit long division
  * tls: implement ECDHE-ECDSA-AES128-GCM-SHA256 cipher suite for
    TLS 1.2 with Let's Encrypt ECDSA certificates
  * tls: fix TLS 1.3 key buffer overflow (16→32 bytes for AES-256)
  * tls: add GCM record encryption/decryption for TLS 1.2

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 28 May 2026 12:00:00 +0200

libnetplus (20260521+22) unstable; urgency=medium

  * x509: add getNotAfter() method for certificate expiry checking
  * ssl: add setCertificates() for runtime TLS certificate hot-reload
  * sha: fix CPU feature detection (SHA-NI) for musl libc using
    inline cpuid assembly instead of __builtin_cpu_supports

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 21 May 2026 12:00:00 +0200

libnetplus (20260516+21) unstable; urgency=medium

  * RSA Montgomery multiplication: add BMI2+ADX hardware-accelerated
    CIOS path (MULX/ADCX/ADOX) with runtime CPU detection fallback

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 16 May 2026 12:00:00 +0200

libnetplus (20260515+20) unstable; urgency=medium

  * RSA modPow: skip multiply-accumulate when limb is zero
  * RSA modPow: fix bigInt one allocation to avoid reallocation

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 15 May 2026 14:00:00 +0200

libnetplus (20260514+18) unstable; urgency=high

  * Fix base64 decode bug in pemCertToDer (x509) and pemKeyToDer (rsa):
    operator<< encodes raw data to base64, but was used to store already-
    encoded base64 text — replace with setEncodedData() so operator>>
    correctly decodes PEM body to DER binary
  * Same fix applied to inline PEM key parsing in tls.cpp

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 14 May 2026 14:00:00 +0200

libnetplus (20260514+17) unstable; urgency=high

  * CertificateBundle: add EC P-256 private key support — try RSA parse
    first, fall back to EC key extraction from PKCS#8/SEC1 DER
  * CertificateBundle: add ecPrivateKey/has_ec_key fields for ECDSA certs
  * TLS 1.3 CertificateVerify: load EC key from selected cert bundle
  * Fix crash on PEM key load when key is ECDSA (not RSA)

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 14 May 2026 13:00:00 +0200

libnetplus (20260514+16) unstable; urgency=medium

  * CertificateBundle::loadFromFile: support inline PEM data — auto-detect
    when certPath/keyPath contain "-----BEGIN" PEM text instead of file paths,
    parse certificate chain and private key directly from string data

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 14 May 2026 12:00:00 +0200

libnetplus (20260505+15) unstable; urgency=high

  * Windows: fix recvBatchAddr blocking indefinitely — use select() poll
    with zero timeout before each recvfrom to avoid blocking on sockets
    where MSG_DONTWAIT is not available
  * Windows: fix completeHandshake blocking on first recvData call —
    reorder to waitRead() before recv to ensure data is available

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 05 May 2026 18:45:00 +0200

libnetplus (20260505+14) unstable; urgency=high

  * Revert -fvisibility=hidden — breaks RTTI symbol export
    (netplus::NetException typeinfo missing at runtime for dependents)

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 05 May 2026 18:30:00 +0200

libnetplus (20260505+13) unstable; urgency=medium

  * Revert -O3/LTO/gc-sections — no measurable benefit, LTO causes
    spurious GCC warnings; keep -O2 -DNDEBUG
  * Disable all diagnostic logging ([QUIC-DIAG] cerr output removed)
  * Remove x509 certificate validation stdout messages
  * Remove pkcs12 parse warning stderr messages
  * Remove unused dumpHex debug helper from hkdf.cpp
  * Remove unused <iostream> includes from x509.cpp, pkcs12.cpp, hkdf.cpp

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 05 May 2026 18:00:00 +0200

libnetplus (20260505+12) unstable; urgency=high

  * QUIC: fix crash "free(): invalid pointer" in quic::~quic() — child
    QUIC connections (accepted via the server's accept() method) shared
    the parent's socket file descriptor (_Socket).  When a child was
    destroyed (e.g. during server shutdown or stale connection cleanup),
    ~udp() called ::close() on the shared fd.  Subsequent children or
    the parent then operated on a closed/reused fd, causing heap
    corruption and the SIGABRT.  Fix: set _Socket = -1 in the child
    destructor when _parent != nullptr so ~udp() skips the close.

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 05 May 2026 16:00:00 +0200

libnetplus (20260505+11) unstable; urgency=medium

  * QUIC: fix stream resurrection on retransmitted packets — when both
    sides completed a stream (send_fin + recv_fin), the stream was
    erased from _streams.  Retransmitted packets for that stream then
    auto-created a new default Stream object, resetting recv_ranges to
    empty and recv_frame_count to 0.  This caused: (a) _data_recv
    double-counting despite the +9 overlap fix (empty recv_ranges →
    overlap=0 → full retransmitted data counted as new unique bytes),
    (b) _peer_streams_bidi_opened inflation, (c) potential re-dispatch
    of stale data to the application callback, and (d) repeated
    "[QUIC-DIAG] HEAD frame: frame_count=1" log spam.  Fix: track
    closed stream IDs in _closed_streams set; ignore STREAM frames for
    streams in that set.

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 05 May 2026 15:00:00 +0200

libnetplus (20260505+10) unstable; urgency=medium

  * QUIC: fix FIN-only STREAM frame never sent on the wire — when
    sendStreamData(sid, nullptr, 0, true) was called after prior data
    sends, the main send loop did not execute (send_len == 0) and no
    packet carrying the FIN bit was ever emitted.  The local stream
    state was marked send_fin=true but the peer never received the FIN,
    causing the remote side to wait indefinitely for stream completion.
    Fix: emit an empty STREAM frame with FIN+OFF when send_len == 0.
  * test: add RFC 9000 QUIC transport compliance test suite
    (quic_rfc9000_test) — 43 tests covering connection state machine,
    version negotiation, connection IDs, cipher selection, bidirectional
    and unidirectional stream types, FIN handling (inline, separate,
    empty), data integrity (1 B to 1 MB echo), connection-level and
    stream-level flow control, concurrent streams, rapid stream
    creation (MAX_STREAMS), and idle survival

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 05 May 2026 14:00:00 +0200

libnetplus (20260505+9) unstable; urgency=medium

  * QUIC: fix connection-level flow control double-counting — _data_recv
    was incremented by the full STREAM frame length on every receive,
    including retransmissions and overlapping data.  Over many streams
    (e.g. during long cluster imports) this inflated the counter and
    could trigger a spurious FLOW_CONTROL_ERROR that killed the
    connection mid-transfer.  Fix: compute overlap with existing
    recv_ranges to determine new unique bytes; only count those for
    _data_recv and the connection-level limit check.
  * QUIC: fix sendStreamData(vector) silent data loss on congestion
    control stall — after 50 stalls the function silently broke out of
    the send loop, losing remaining data with no error to the caller.
    Fix: throw NetException so callers (e.g. paritypp store_stripe)
    know the stream write failed and can retry.
  * QUIC: fix unidirectional stream dispatch before data complete —
    uni-stream callbacks fired on recv_fin (FIN frame arrival) instead
    of recv_complete (all data contiguous from offset 0).  If packets
    arrived out of order or needed retransmission, the callback received
    a buffer with zero-filled gaps.  Fix: check recv_complete (matching
    the bidi path) and std::move the buffer to avoid copy + memory waste.

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 05 May 2026 12:00:00 +0200

libnetplus (20260504+8) unstable; urgency=medium

  * QUIC: fix PTO re-queue spin loop — when sendPacket() failed (EAGAIN),
    the re-queued entry kept its original sent_time, causing
    checkLossAndRetransmit to fire PTO again immediately on the next call.
    This created an infinite hot loop that blocked the event loop.  Fix:
    reset sent_time to now and increment _pto_count for exponential
    back-off on send failure.

libnetplus (20260504+7) unstable; urgency=medium

  * QUIC: cap max_udp_payload_size to 1472 (Ethernet-safe) instead of
    16384.  The old value caused 16KB UDP datagrams that get fragmented
    into ~11 IP fragments each, amplifying packet loss ~11x on standard
    1500 MTU networks.  This was the primary cause of store_stripe
    hanging — the server received only ~30% of packets despite the
    client believing they were delivered.
  * QUIC: add post-HEAD range verification diagnostic — logs
    recv_contiguous and first range immediately after inserting offset-0
    data to trace the contig=0 mystery

libnetplus (20260504+6) unstable; urgency=medium

  * QUIC: add per-stream recv_frame_count diagnostic — tracks how many
    STREAM frames the server actually processes for each stream.  Logged
    in the FIN-gap diagnostic line and as "[QUIC-DIAG] stream N HEAD
    frame" when offset-0 data arrives.  This distinguishes "data never
    reached processStreamFrame" from "data was processed but lost in
    reassembly".

libnetplus (20260504+5) unstable; urgency=medium

  * QUIC: fix critical data-loss bug in loss-detection retransmit — if
    sendPacket() failed (EAGAIN / send-buffer full after a burst), the
    stream data was erased from _sent_packets but never re-inserted,
    causing permanent loss of ~47 in-flight packets.  Fix: on send
    failure, re-queue under the original PN so the next loss-detection
    cycle retries the retransmit.
  * QUIC: fix same data-loss bug in PTO retransmit path — only erase
    the original entry and increment _pto_count after sendPacket()
    succeeds; re-queue on failure.
  * QUIC: improve [QUIC-DIAG] retransmit logging — report retransmit_ok
    / retransmit_fail counts and PTO re-queue events

libnetplus (20260504+4) unstable; urgency=medium

  * QUIC: add client-side [QUIC-DIAG] logging for ACK processing (first
    ACK received, range count, sent_packets), PTO probes (age, threshold),
    and loss detection (lost count, retransmit stats) to trace why gaps
    in server-side stream receive are never filled
  * QUIC: add server-side [QUIC-DIAG] logging for large streams that
    have received FIN but are not yet contiguously complete — logs
    stream ID, FIN offset, contiguous bytes, range count, and first gap
    to diagnose store_stripe response-timeout on remote nodes
  * QUIC: implement PTO (Probe Timeout, RFC 9002 §6.2) — retransmit
    the oldest unacked packet with exponential back-off when the peer
    has not acknowledged tail packets, fixing the "tail loss" deadlock
    where both sides wait indefinitely after the last few UDP datagrams
    are lost
  * QUIC: pumpNetwork() now calls checkLossAndRetransmit() so that
    callers waiting for responses (e.g. parity store_stripe Phase 2)
    trigger retransmission of lost packets
  * QUIC: fix sendStreamData(vector) silently losing data on congestion
    control stall — now retries in a loop with pumpIncoming() between
    attempts until all data (including FIN) is delivered
  * QUIC: only mark stream send_fin when all data was actually sent on
    the wire, preventing incorrect state when CC breaks the send loop

 -- Jan Koester <jan.koester@tuxist.de>  Sun, 04 May 2026 19:30:00 +0200

libnetplus (20260502+1) unstable; urgency=medium

  * QUIC: add udp::recvBatchAddr() — batch receive with peer addresses
    via recvmmsg, with thread_local 4 MB flat buffer to avoid per-call
    heap allocation
  * QUIC: server accept() uses recvBatchAddr() instead of per-datagram
    recvfrom, cutting recv syscalls from ~73 K to ~1 K per benchmark run
  * QUIC: vector sendStreamData() delegates to fast-path variant with
    batching, congestion-control gating, and ACK piggybacking
  * QUIC: raise initial congestion window to 10 MB (avoids CC stalls on
    loopback / LAN); CC still engages on actual loss
  * QUIC: CC wait loop spins 8× before falling back to poll(1 ms),
    avoiding unnecessary syscalls when ACKs are already queued
  * QUIC: stream FIN cleanup (MAX_STREAMS replenish) added to fast-path
    sendStreamData
  * Benchmark echo throughput: 1 KB 0.2→40 MB/s, 16 KB 0.7→85 MB/s,
    65 KB 30→100 MB/s, 262 KB 31→129 MB/s

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 02 May 2026 12:00:00 +0200

libnetplus (20260501+1) unstable; urgency=medium

  * AES-GCM: implement 4-way pipelined AES-NI CTR encryption,
    exploiting counter-mode parallelism for higher throughput
  * AES-GCM: implement interleaved GHASH with encryption in a single
    pass, eliminating the second traversal over ciphertext
  * AES-GCM encrypt throughput improved ~3.5x (AES-128-GCM: 479 → 1720 MB/s,
    AES-256-GCM: 453 → 1565 MB/s at 256 KB payloads)

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 01 May 2026 12:00:00 +0200

libnetplus (20260425+5) unstable; urgency=high

  * RSA Montgomery CIOS: fix heap buffer over-read in
    montgomeryMultiply_into — b operand was indexed up to mod.used
    without bounds check (b.used may be smaller, e.g. the constant 1).
    Caused SEC_ERROR_BAD_SIGNATURE in TLS handshakes.

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 25 Apr 2026 20:00:00 +0200

libnetplus (20260425+4) unstable; urgency=medium

  * SHA-256 SHA-NI: fix message schedule bugs — double sha256msg1
    expansion, wrong W+K round pairing, and incorrect final register.
    All 12 NIST FIPS 180-4 test vectors now pass.

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 25 Apr 2026 19:00:00 +0200

libnetplus (20260425+3) unstable; urgency=medium

  * SHA-256: add SHA-NI hardware-accelerated path with runtime CPU
    dispatch via __builtin_cpu_supports("sha")
  * Build: raise optimisation level from -O1 to -O2, enabling
    auto-vectorisation and better __uint128_t codegen

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 25 Apr 2026 16:00:00 +0200

libnetplus (20260425+2) unstable; urgency=medium

  * RSA bigInt: switch from fixed 32-bit limbs to portable limb_t/dlimb_t
    typedefs — 64-bit limbs with __uint128_t accumulator on GCC/Clang,
    32-bit fallback on MSVC. Halves limb count for RSA-2048 (64→32),
    yielding ~4x fewer inner-loop iterations in Montgomery CIOS.

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 25 Apr 2026 14:00:00 +0200

libnetplus (20260425+1) unstable; urgency=medium

  * RSA: replace separate multiply + reduce with fused CIOS
    (Coarsely Integrated Operand Scanning) in montgomeryMultiply_into,
    eliminating a full schoolbook multiplication pass and improving
    cache locality

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 25 Apr 2026 12:00:00 +0200

libnetplus (20260424+22) unstable; urgency=medium

  * Fix remaining compiler warnings: remove unused derOctetString, enlarge
    snprintf buffer in derUtcTime, remove unused label in epoll.cpp,
    suppress GCC 14 false-positive -Wfree-nonheap-object in tls.cpp/quic.cpp

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 24 Apr 2026 18:00:00 +0200

libnetplus (20260424+21) unstable; urgency=medium

  * Fix compiler warnings: remove unused debug variables in quic.cpp

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 24 Apr 2026 17:30:00 +0200

libnetplus (20260424+20) unstable; urgency=medium

  * Disable QUIC_DBG macro after HTTP/3 debugging complete

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 24 Apr 2026 17:15:00 +0200

libnetplus (20260424+19) unstable; urgency=medium

  * Add accept() debug logging for QUIC remote connection diagnosis

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 24 Apr 2026 16:15:00 +0200

libnetplus (20260424+18) unstable; urgency=medium

  * Enable QUIC debug logging for HTTP/3 handshake diagnosis

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 24 Apr 2026 15:55:00 +0200

libnetplus (20260414+17) unstable; urgency=medium

  * Add utils/certgen: self-signed RSA certificate + key generation API
  * Add netplus-certgen CLI tool for certificate generation
  * Optimize RSA key generation: fix bit_count (p,q now half of target N)
  * Add trial division by small primes before Miller-Rabin
  * Optimize modPow: use repeated doubling for R^2 mod N computation
  * Optimize isProbablyPrime: direct squaring instead of modPow(x,2,n)
  * Optimize bigIntToBytesBE: direct word extraction O(n) vs O(n^2)
  * Optimize shiftLeft: in-place without temp vector allocation
  * Add RSA key accessors: getN(), getE(), getD()

 -- Jan Koester <jan.koester@tuxist.de>  Mon, 14 Apr 2026 00:00:00 +0200

libnetplus (20260410+16) unstable; urgency=medium

  * Add PEM auto-detection for x509cert::loadFromFile() and rsa constructors
  * Add x509cert::loadAllFromPem() for PEM chain/bundle files
  * Add PKCS#12 (.p12/.pfx) parser with 3DES-CBC and PBES2/AES support
  * Add CertificateBundle::loadFromFile() with auto-detect by file extension

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 10 Apr 2026 00:00:00 +0200

libnetplus (20260409+15) unstable; urgency=medium

  * Add netplus::isIPAddr() utility function (posix + windows)

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 09 Apr 2026 00:00:00 +0200

libnetplus (20260409+14) unstable; urgency=medium

  * Increase BLOCKSIZE from 16384 to 65536 for improved streaming throughput

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 09 Apr 2026 00:00:00 +0200

libnetplus (20260407+13) unstable; urgency=medium

  * New release

 -- Jan Koester <jan.koester@tuxist.de>  Tue, 07 Apr 2026 00:00:00 +0200

libnetplus (20260405+12) unstable; urgency=medium

  * Reduce QUIC sendStreamData flow-control stall limit from 5s to 500ms
    (MAX_FC_STALLS 5000 → 500) to prevent blocking on slow peers

 -- Jan Koester <jan.koester@tuxist.de>  Sun, 05 Apr 2026 00:00:00 +0000

libnetplus (20260405+11) unstable; urgency=medium

  * Add socketwait::waitReadMulti() to wait on multiple sockets at once
    using epoll/kqueue/select/poll (all 4 backends)

 -- Jan Koester <jan.koester@tuxist.de>  Sun, 05 Apr 2026 00:00:00 +0000

libnetplus (20260404+10) unstable; urgency=medium

  * Fix quic::pumpNetwork throwing NetException on EAGAIN/EWOULDBLOCK
    instead of returning gracefully; callers (paritypp store_stripe)
    treated the Note exception as a fatal error, failing all nodes

 -- Jan Koester <jan.koester@tuxist.de>  Sat, 04 Apr 2026 00:00:00 +0000

libnetplus (20260404+9) unstable; urgency=medium

  * Remove debug std::cerr logging from udp::bind() and epoll event workers
    to eliminate data races on _ZSt4cerr

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 00:00:00 +0000

libnetplus (20260404+8) unstable; urgency=medium

  * Fix QUIC stream limit exhaustion: increase initial_max_streams from 100 to 10M
  * Auto-cleanup completed streams and send MAX_STREAMS frames to replenish peer budget
  * Server sends MAX_STREAMS(bidi/uni) when peer-initiated streams are fully closed

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 23:00:00 +0200

libnetplus (20260404+7) unstable; urgency=medium

  * Remove [QUIC] server-side Initial/ServerHello debug logging

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 23:00:00 +0200

libnetplus (20260404+6) unstable; urgency=medium

  * Remove verbose [QUIC-client] debug logging from quic.cpp

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 20:30:00 +0200

libnetplus (20260403+5) unstable; urgency=medium

  * Handshake timeout tuning

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 05:00:00 +0200

libnetplus (20260403+4) unstable; urgency=medium

  * Use HANDSHAKE_TIMEOUT_MS (5000ms) in completeHandshake instead of
    hardcoded 1500ms — servers need time for crypto + key derivation

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 04:00:00 +0200

libnetplus (20260403+3) unstable; urgency=medium

  * Fix QUIC handshake packet loss: retry sendPacket on EAGAIN up to
    5 times with 1ms back-off instead of silently dropping packets

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 03:00:00 +0200

libnetplus (20260403+2) unstable; urgency=medium

  * Add client-side handshake debug logging: Initial/Handshake decrypt
    status, TLS message flow (ServerHello, EncryptedExtensions, etc.)

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 02:00:00 +0200

libnetplus (20260403+1) unstable; urgency=medium

  * Add udp::sendTo() method for unconnected socket sends
  * Rewrite quic::sendPacket() to use udp class methods instead of
    raw OS calls (sendto/send)

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 01:00:00 +0200

libnetplus (20260403) unstable; urgency=medium

  * Add QUIC handshake debug logging: log Initial packet reception
    (peer IP, port, length, version) and ServerHello send result

 -- Jan Koester <jan.koester@tuxist.de>  Fri, 04 Apr 2026 00:10:00 +0200

libnetplus (20260401) unstable; urgency=medium

  * Initial Debian packaging with multiarch support.

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 01 Apr 2026 00:00:00 +0200
