mORMot2 DailyDaily read of upstream commits

Tunnel sessions become unpredictable and demand-driven sockets arrive

Tunnel users get the largest changes: TTunnelRelay now allocates unpredictable session identifiers, while TTunnelLocal gains event-driven handshake waiting and ownership of an existing connected socket. The batch also makes tunnel caches, transient cleanup and asynchronous-server shutdown safer under concurrent or repeated calls. Delphi 10–10.3 and FPC users receive targeted compiler, build and thread-destruction corrections.

TL;DR

  • TTunnelRelay session IDs now come from Random128 through Random9Digits instead of the predictable NetRandom32 generator.
  • TTunnelLocal adds WaitForHandshake and OpenSocket for demand-driven forwarding; land on build 2.4.16776, not the incomplete build 2.4.16768.
  • Tunnel cache refresh, transient purge and asynchronous-server Shutdown paths now reject competing or duplicate execution.
  • Delphi 10–10.3 avoids known pointer-expression and inlining compiler bugs, while FPC POSIX thread destruction avoids an unnecessary 100 ms wait.

Upgrade advice

Tunnel and asynchronous-server deployments should take build 2.4.16776 as a complete set. Do not stop on build 2.4.16768: it contains the TTunnelLocal.WaitForHandshake implementation before its class declaration is added in the following build. Delphi 10–10.3 users should also take the head for the compiler workarounds.

Build2.4.16753 → 2.4.16776
Commits23
Lines+706 -211
Read7 min

22 of 22 entries · 23 commits upstream

Stories
# Entry Category Units
1 High Handshake waiting becomes event-driven, but this intermediate build is incomplete TTunnelLocal gains fHandshakeEvent and an implementation of WaitForHandshake that checks the queue under fSendSafe, waits on TSynEvent without consuming the frame, validates the session trailer and wakes on ClosePort. In this revision the method implementation exists, but its declaration is not yet present in TTunnelLocal; that declaration arrives in c38c36d. Breaking changesinterp mormot.net.tunnel d2419079+63-5

net: new TTunnelLocal.WaitForHandshake method

Impact

The event design removes polling and preserves an early notification, but build 2.4.16768 is not a valid stopping point because the class method is implemented before being declared. Build 2.4.16769 completes the public class surface.

Worth a look

Do not pin build 2.4.16768; use build 2.4.16776 so the declaration and later close-path fix are included.

Arnaud Bouchez · 16:47 UTC · view the commit on GitHub →

2 High Tunnel session allocation stops using a predictable PRNG TTunnelRelay.PrepareNewSession in mormot.net.tunnel replaces NetRandom32 shr 4 with values derived from Random128. It tests up to three 32-bit words for a non-zero candidate, keeps the existing collision checks under fConsoleSafe and clears the temporary random buffer. Security mormot.net.tunnel 34791460+13-6

net: fixed TTunnelRelay.PrepareNewSession number predicability

Impact

A relay no longer issues session identifiers from the explicitly non-cryptographic NetRandom32 sequence. This removes their straightforward predictability without changing TTunnelSession size or the relay service signatures; the diff does not establish a complete session-hijacking exploit.

Public API

  • TTunnelRelay.PrepareNewSessionbehaviour-changed — Session identifiers now come from Random128 rather than NetRandom32.

Arnaud Bouchez · 18:30 UTC · view the commit on GitHub →

3 High Repeated asynchronous-server shutdown no longer re-enters cleanup TLoggedThread in mormot.core.threads gains three protected byte flags. TAsyncConnections.Shutdown and both TAsyncServer.Shutdown backends use separate flags to return on duplicate calls, while THttpAsyncServer.DoExecute also exits when fShutdownInProgress is set. Fixes mormot.core.threads+1 93b26a97+16-5

net: fixed nested Shutdown calls of async servers

Impact

Destructor and explicit shutdown paths can no longer repeat IOCP unsubscribe, socket termination or accept-release work on the same instance. This reduces shutdown races and duplicate cleanup on Delphi and FPC asynchronous HTTP/WebSocket servers.

Arnaud Bouchez · 16:39 UTC · view the commit on GitHub →

4 Medium Only one thread now refreshes the per-second tunnel information cache Despite the swapped commit title, this diff changes TTunnelList.GetAllInfo in mormot.net.tunnel. LockedExc32 on fInfoCacheTix32 elects one caller to build the current-second snapshot; other callers copy fInfoCache under fInfoCacheSafe. Fixes mormot.net.tunnel d1512dde+26-25

net: made TTunnelList.PurgeTransient atomic

Impact

Concurrent monitoring requests no longer rebuild and race to publish the same TunnelInfo snapshot. Application APIs are unchanged; relay status collection performs one callback pass per second.

Arnaud Bouchez · 16:45 UTC · view the commit on GitHub →

5 Medium Transient tunnel cleanup now has one atomic periodic owner Despite the swapped title, this diff changes TTunnelList.PurgeTransient. LockedExc32 atomically claims each 16-second purge interval before fSafe is acquired, timeout comparison becomes wrap-safe subtraction, and fInfoCacheTix32 is invalidated only when a tunnel was actually removed. Fixes mormot.net.tunnel 1915e014+14-14

net: made TTunnelList.GetAllInfo cache atomic

Impact

Concurrent callers cannot run the same purge cycle twice, and long uptimes do not break timeout detection at the cardinal wrap boundary. Relay cleanup does less locking and avoids duplicate callback release work.

Arnaud Bouchez · 16:44 UTC · view the commit on GitHub →

6 Medium A close frame now wakes and stops a tunnel still handshaking TTunnelLocal.TunnelSend in mormot.net.tunnel detects a session-only closure frame while fHandshake still exists. It records fClosePortNotified, signals fHandshakeEvent, marks fClosed and exits instead of pushing the empty frame into the handshake queue. Fixes mormot.net.tunnel 9609945c+12-2

net: fixed TTunnelLocal early shutdown

Impact

WaitForHandshake can return promptly when the remote endpoint closes before setup completes. Deferred tunnels no longer mistake a close notification for handshake data or wait until the timeout.

Arnaud Bouchez · 16:53 UTC · view the commit on GitHub →

7 Medium WebSocket frame logging no longer resets remote-log state unnecessarily TWebSocketProcess.Log in mormot.net.ws.core now calls TSynLog.DisableRemoteLog only when its DisableRemoteLog argument is true, both before and after writing the frame. SendFrame makes that true argument explicit in the call site. Fixes mormot.net.ws.core 72c81483+7-5

net: fixed TWebSocketProcess.Log() code

Impact

Receive-side or other log calls made with DisableRemoteLog=false no longer force the logger back to remote-enabled state. SendFrame still suppresses remote forwarding around its own trace to avoid recursive WebSocket logging.

Worth a look

If WebSocketLog forwards to a remote sink, verify that receive and send traces now preserve the intended remote-log suppression state.

Arnaud Bouchez · 08:36 UTC · view the commit on GitHub →

8 Medium ECDHE setup failure now raises a specific tunnel exception TTunnelLocal.OpenInternal in mormot.net.tunnel replaces a silent exit after Ecc256r1SharedSecret failure with ETunnel.RaiseUtf8. The exception identifies TTunnelLocal and includes the local port. Fixes mormot.net.tunnel 8d1d4fc7+4-3

net: another Tunnel logic improvement

Impact

An invalid peer ECDHE public key now produces an explicit failure rather than an ambiguous zero-like Open result. Callers that deliberately feed malformed handshakes should expect ETunnel on this path.

Worth a look

Review exception handling around TTunnelLocal.Open and OpenSocket if untrusted peers can supply handshake keys.

Public API

  • TTunnelLocal.Openbehaviour-changed — Ecc256r1SharedSecret failure now raises ETunnel instead of exiting silently.

Arnaud Bouchez · 16:53 UTC · view the commit on GitHub →

9 Medium Applications can hand an existing connected socket to TTunnelLocal mormot.net.tunnel exposes TTunnelLocal.WaitForHandshake and adds TTunnelLocal.OpenSocket. OpenSocket validates a non-nil socket and port, transfers ownership by clearing the caller variable, and shares handshake setup with Open through the protected OpenInternal method. The ITunnelOpen documentation now describes an SSH -R-like demand-driven sequence. New features mormot.net.tunnel c38c36da+158-44

net: introduced late access to the local Tunnel socket

Impact

VNC-style or other reverse forwarding can defer the backend connection until a real local client arrives. Existing Open callers keep their source contract; new OpenSocket callers must not close or reuse Socket after a valid call because ownership has moved to TTunnelLocal.

Worth a look

For demand-driven forwarding, test socket ownership, both handshake directions, timeout and peer-close paths before replacing an existing Open-based flow.

Public API

  • TTunnelLocal.WaitForHandshakeadded — Waits for the first queued peer handshake without consuming it.
  • TTunnelLocal.OpenSocketadded — Starts tunnelling over an already-connected TNetSocket and takes its ownership.

Arnaud Bouchez · 16:48 UTC · view the commit on GitHub →

10 Medium One helper now produces every unpredictable nine-digit session number mormot.crypt.core adds the public Random9Digits function. It takes three candidate cardinals from Random128, clears the temporary 128-bit buffer and returns 100000000..999999999, or zero only if every candidate is zero. TTunnelRelay.PrepareNewSession in mormot.net.tunnel now calls this helper. New features mormot.crypt.core+1 da7e1c2f+23-11

crypt: new Random9Digits() function

Impact

Tunnel session identifiers retain their 32-bit wire representation but now always have exactly nine decimal digits and use the framework CSPRNG. Other Delphi/FPC code may reuse the helper when that range and zero-as-failure contract are suitable.

Public API

  • Random9Digitsadded — Returns an unpredictable cardinal in 100000000..999999999, or zero if Random128 is unusable.

Arnaud · 21:54 UTC · view the commit on GitHub →

11 Medium Delphi 10–10.3 receives targeted pointer and inlining workarounds mormot.defines.inc defines ISDELPHI10_103 for compiler versions 30 through 33. mormot.core.buffers disables inline on FromVarInt32 for that range, and mormot.core.base rewrites typed pointer casts in AppendShortCurr64 from @p[index] to pointer arithmetic that those compilers accept. Compiler & platform mormot.core.base+1 92d840ee+10-6

core: circumvent Delphi 10.x compiler bugs

Impact

Projects compiled with Delphi 10, 10.1, 10.2 or 10.3 avoid known compiler failures in variable-integer decoding and currency text formatting. Generated behavior is intended to stay the same; FPC and other Delphi versions do not use the new conditional.

Arnaud Bouchez · 07:41 UTC · view the commit on GitHub →

12 Low TNetAddr recognizes the full IPv4 loopback block and IPv6 ::1 mormot.net.sock adds the public TNetAddr.IsLoopback method. It returns true for any AF_INET address whose first byte is 127 and for the AF_INET6 ::1 byte pattern, and false for other or undefined address families. New features mormot.net.sock be380064+20-2

net: new TNetAddr.IsLoopback method

Impact

Network code can perform one family-aware local-address check instead of comparing only 127.0.0.1. Existing callers are unaffected; the tunnel accept path adopts the helper in a later commit.

Public API

  • TNetAddr.IsLoopbackadded — Returns true for 127.x.x.x and ::1 addresses.

Arnaud Bouchez · 13:19 UTC · view the commit on GitHub →

13 Low CheckHash accepts raw buffers as well as managed strings mormot.core.test adds a TSynTestCase.CheckHash overload taking data: pointer and len: PtrInt. The existing RawByteString overload delegates to it, and the shared implementation computes Hash32(data, len) before producing the diagnostic assertion. New features mormot.core.test 3ad5bbe2+13-4

core: new TSynTestCase.CheckHash() overload

Impact

Tests can validate streams, short strings and arbitrary memory without first allocating a RawByteString. Production runtime behavior is unaffected because the addition is in the testing unit.

Public API

  • TSynTestCase.CheckHash(pointer, PtrInt, cardinal, RawUtf8)added — New overload hashes an explicit memory buffer and length.

Arnaud Bouchez · 09:33 UTC · view the commit on GitHub →

14 Low Relay scans and cached-info copies use tighter pointer loops mormot.net.tunnel introduces PTunnelRelayConsole and rewrites HasConsolePrepared and ConsolesInfo to advance record pointers. TTunnelList.GetAllInfo also removes structured try/finally blocks around short lock-protected assignments while keeping the same lock and exit behavior. Performance mormot.net.tunnel 89996223+28-28

net: slightly optimized TTunnelRelay process

Impact

Relay metadata enumeration performs less index and exception-frame work. Public results and locking semantics are intended to remain unchanged, so no Delphi/FPC application update is required.

Arnaud Bouchez · 17:41 UTC · view the commit on GitHub →

15 Low FPC POSIX thread destruction avoids the RTL’s fixed wait when possible TThreadAbstract overrides Destroy only under FPCPOSIX. When the main thread frees an active non-suspended thread, it calls Terminate and briefly loops over CheckSynchronize and SleepHiRes until Finished or 100 ms, before invoking the inherited destructor. Performance mormot.core.threads efc0950e+28-2

core: override TThreadAbstract.Destroy on FPC POSIX

Impact

Short-lived FPC POSIX thread objects can finish before the inherited RTL path imposes its usual 100 ms WaitFor delay. Delphi and Windows code is not compiled through this override.

Public API

  • TThreadAbstract.Destroybehaviour-changed — On FPC POSIX, active threads receive a bounded cooperative finish loop before inherited destruction.

Arnaud Bouchez · 16:16 UTC · view the commit on GitHub →

16 Low The internal INI section matcher uses a Delphi-10-friendly loop IdemPChar2 in mormot.core.fmt is rewritten from a repeat loop with a temporary AnsiChar into a while loop that compares table[up[PtrUInt(p)]] directly and advances up only on a match. Compiler & platform mormot.core.fmt 00f6828c+12-13

core: refactored INI parsing for Delphi 10.x

Impact

INI section-name matching keeps the same case-normalized behavior while avoiding a code shape that caused problems in Delphi 10.x. FPC and newer Delphi application APIs are unchanged.

Arnaud Bouchez · 08:32 UTC · view the commit on GitHub →

17 Low Windows canary builds receive current desktop and server release labels mormot.core.os updates its build lookup tables: desktop build 29570 maps to Windows 11 27H2, desktop 26300 remains 26H2, and server build 29651 maps to Windows Server 26H2. The Delphi test batch also enables optimization and NO_UI for configured non-default compilers. Compiler & platform mormot.core.os 61a6fc1b+12-9

core: detect Windows 11 27H2 and Windows Server 26H2 canary versions

Impact

OSVersionText can report the intended labels on those preview builds instead of falling back to an older bucket. Runtime feature selection is unchanged because this diff only adjusts descriptive lookup tables.

Arnaud Bouchez · 14:35 UTC · view the commit on GitHub →

18 Low Command-line FPC Windows tests explicitly opt out of UI units test/build_fpc.sh adds -dNO_UI for win* targets, and test/build_winarm.bat adds the same define for aarch64-win64. This prevents mormot2tests from requiring Lazarus Interfaces and test.ui.pdf when no widgetset path is configured. Compiler & platform 55d28b7f+4-2

tests: define NO_UI in the command line FPC build scripts

Impact

The repository command-line test build works again on FPC Windows and aarch64-win64 without LCL. Lazarus package builds retain UI coverage, and application build flags are not changed.

Sven Harazim · 10:41 UTC · view the commit on GitHub →

19 Low Deferred tunnels gain direct and WebSocket end-to-end coverage test.net.proto adds TunnelDeferred. The test prepares both relay endpoints, accepts a viewer socket before connecting the backend, waits for the handshake, exchanges VNC-style banners in both directions and repeats the flow through SOA callbacks over WebSockets. Tests e22ca7df+186-2

tests: cover deferred Tunnel connection

Impact

There is no application-code change. The new demand-driven TTunnelLocal path is now exercised both without transport serialization and through the real WebSocket callback route.

Arnaud Bouchez · 18:18 UTC · view the commit on GitHub →

20 Low The Lazarus test project recognizes ten expected exception classes test/mormot2tests.lpi registers ten exception class names, including EHttpSocket, EYamlException, EStreamError and EJsonObjectDecoder, in its Lazarus debugger configuration. Tests 1b9767fa+34-2

test: ease mormot2tests debugging by registering some exceptions

Impact

This only changes debugger handling in the Lazarus test project. Framework code, test behavior outside debugging and application builds are unchanged.

Arnaud · 21:16 UTC · view the commit on GitHub →

21 Low Regression hashes now report expected and actual values consistently Four test units replace direct Hash32 comparisons with TSynTestCase.CheckHash. Pointer-and-length buffers, serialized variants, SOA JSON and generated PDF memory now use the same diagnostic assertion, with PDF constants rewritten in hexadecimal. Tests 07032883+14-14

tests: use new CheckHash()

Impact

Failed regression tests provide clearer hash diagnostics, especially where PDF font embedding differs by system. Framework runtime and application code are unchanged.

Arnaud Bouchez · 09:44 UTC · view the commit on GitHub →

22 Low Loopback checks now use shared address helpers and constants mormot.net.sock replaces two uses of cLocalhost text with IP4local. TTunnelLocalThread.DoExecute in mormot.net.tunnel uses TNetAddr.IsLoopback instead of comparing only fClientAddr.IP4 with cLocalhost32. Housekeeping mormot.net.sock+1 0ce4b076+5-5

net: minor loopback definitions usage

Impact

Local tunnel admission now follows the shared IPv4 and IPv6 loopback definition, so ::1 is accepted as local. Existing IPv4 localhost behavior remains unchanged.

Arnaud Bouchez · 16:42 UTC · view the commit on GitHub →

Upstream activity commits per day · last 60 days
Commits977
Active days44/60
Busiest2026-09-30
Peak60
2026-08-15: 0 commits2026-08-16: 0 commits2026-08-17: 0 commits2026-08-18: 0 commits2026-08-19: 0 commits2026-08-20: 0 commits2026-08-21: 0 commits2026-08-22: 0 commits2026-08-23: 0 commits2026-08-24: 0 commits2026-08-25: 0 commits2026-08-26: 0 commits2026-08-27: 26 commits2026-08-28: 11 commits2026-08-29: 10 commits2026-08-30: 1 commit2026-08-31: 23 commits2026-09-01: 0 commits2026-09-02: 20 commits2026-09-03: 29 commits2026-09-04: 35 commits2026-09-05: 13 commits2026-09-06: 0 commits2026-09-07: 0 commits2026-09-08: 23 commits2026-09-09: 10 commits2026-09-10: 17 commits2026-09-11: 23 commits2026-09-12: 14 commits2026-09-13: 9 commits2026-09-14: 7 commits2026-09-15: 4 commits2026-09-16: 24 commits2026-09-17: 26 commits2026-09-18: 21 commits2026-09-19: 59 commits2026-09-20: 13 commits2026-09-21: 5 commits2026-09-22: 34 commits2026-09-23: 17 commits2026-09-24: 57 commits2026-09-25: 22 commits2026-09-26: 26 commits2026-09-27: 0 commits2026-09-28: 2 commits2026-09-29: 19 commits2026-09-30: 60 commits2026-10-01: 26 commits2026-10-02: 30 commits2026-10-03: 32 commits2026-10-04: 15 commits2026-10-05: 1 commit2026-10-06: 26 commits2026-10-07: 37 commits2026-10-08: 27 commits2026-10-09: 35 commits2026-10-10: 33 commits2026-10-11: 9 commits2026-10-12: 11 commits2026-10-13: 35 commits
2026-08-152026-10-13