mORMot2 DailyDaily read of upstream commits

SChannel and HTTP caches settle, but heartbeats regress

Windows SChannel receives concurrency, handshake, renegotiation and memory-use repairs, while HTTP clients gain opt-in redirect restrictions and both proxy caches correct status handling. Async WebSocket heartbeat timing is moved to HeartbeatDelay, but two follow-up edits leave the final idle-loop comparison disabling those callbacks once the default memory-release threshold is reached. Teams using custom INetTls implementations or the removed LastOperationIdleSeconds property also have source migrations to make.

TL;DR

  • Land on upstream head c94dba6c18f6a0c5b225734af210da678cc59167 at build 2.4.17161 for the completed SChannel, redirect and cache fixes.
  • Async WebSocket heartbeat callbacks are disabled after the default idle-memory threshold; set LastOperationReleaseMemorySeconds to 0 until the comparison is corrected.
  • Custom INetTls implementations must add ReleaseBuffers, and callers of TAsyncConnections.LastOperationIdleSeconds must migrate to GetLastOperationIdleSeconds.
  • THttpRequestExtendedOptions.RedirectOptions adds opt-in cross-origin credential purging and redirect rejection while preserving unrestricted defaults.
  • Proxy-cache downloads now reject non-GET-success statuses, abort progressive readers on failure and verify the final file size.
  • Avoid build 2.4.17143 and the incomplete redirect builds 2.4.17159–2.4.17160.

Upgrade advice

Land on build 2.4.17161 at head c94dba6c18f6a0c5b225734af210da678cc59167 for SChannel, redirect and proxy-cache fixes. Before upgrading, implement INetTls.ReleaseBuffers in custom TLS backends and replace LastOperationIdleSeconds usage. Async WebSocket servers should set LastOperationReleaseMemorySeconds to 0 and test heartbeat traffic until the idle cutoff comparison receives a successor fix.

Build2.4.17135 → 2.4.17161
Commits22
Lines+595 -335
Read6 min

22 of 22 entries · 22 commits upstream

Stories
# Entry Category Units
1 High WebSocket heartbeat timing moves to HeartbeatDelay TAsyncConnections removes LastOperationIdleSeconds and adds virtual GetLastOperationIdleSeconds. TWebSocketAsyncConnections overrides it to return Settings.HeartbeatDelay in seconds, and HeartbeatDelay=0 disables ping/pong. Breaking changes mormot.net.async+1 efb27161+37-23

net: fixed WebSockets HeartbeatDelay async server support

Impact

Code assigning LastOperationIdleSeconds no longer compiles. WebSocket servers derive the interval from their settings, but final-head scheduling needs the documented workaround because later commits regress the cutoff.

Migration required

Grep for LastOperationIdleSeconds. Use TWebSocketProtocol.Settings.HeartbeatDelay for WebSockets or override GetLastOperationIdleSeconds in a TAsyncConnections descendant.

Public API

  • TAsyncConnections.LastOperationIdleSecondsremoved — The writable property is replaced by a virtual getter.
  • TAsyncConnections.GetLastOperationIdleSecondsadded — Returns zero by default and can be overridden by descendants.

Arnaud Bouchez · 12:52 UTC · view the commit on GitHub →

2 High INetTls gains an idle-buffer release contract The public INetTls interface adds ReleaseBuffers: PtrInt. TSChannelNetTls releases empty input, data and output buffers; TOpenSslNetTls returns zero because SSL_MODE_RELEASE_BUFFERS is already enabled and SSL_free_buffers is unsafe. Breaking changes mormot.lib.openssl11+2 ef8aa8a5+31-2

net: introducing INetTls.ReleaseBuffers method

Impact

Any external class implementing INetTls fails to compile until it implements the new method. Built-in OpenSSL and SChannel implementations are complete.

Migration required

Grep for classes implementing INetTls and add function ReleaseBuffers: PtrInt; return 0 when the backend has no safe explicit release operation.

Public API

  • INetTls.ReleaseBuffersadded — Required method returning the known number of released bytes.

Arnaud Bouchez · 10:37 UTC · view the commit on GitHub →

3 High Concurrent SChannel send and renegotiation are serialized TSChannelNetTls adds fSspiSafe around Receive handling of SEC_I_RENEGOTIATE and Send encryption. Send returns nrRetry when Receive owns the lock, preventing simultaneous SSPI context use by WebSocket read and write paths. Fixes mormot.net.sock.windows 3e2819e1+95-63

net: hardened TSChannelNetTls thread safety

Impact

Windows WebSocket connections no longer race SSPI when TLS 1.3 post-handshake data arrives during a send. Callers already handling nrRetry need no source change.

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

4 High Failed proxy downloads now abort readers and remove partial files The proxy cache accepts only 200, 204 or 206 for GET data, tracks the expected size, aborts every THttpPartial reader on setup or background failure, and deletes incomplete files after status or size mismatch. Fixes mormot.net.async e3a44702+51-11

net: fixed Proxy Cache process

Impact

Progressive clients no longer wait on a failed origin transfer or consume a truncated cache object as complete. Redirect or error bodies are not stored as successful resources.

Arnaud Bouchez · 15:46 UTC · view the commit on GitHub →

5 High Fragmented ClientHello no longer restarts SChannel accept TSChannelNetTls tracks fAcceptFirst and passes the existing SSPI context after AcceptSecurityContext returns SEC_I_CONTINUE_NEEDED, instead of treating an incomplete first ClientHello as a fresh negotiation. Fixes mormot.net.sock.windows 7f17ffe4+12-4

net: fixed SChannel partial initial negotiation

Impact

SChannel servers can complete handshakes when ClientHello arrives in multiple TCP reads rather than failing or corrupting the negotiation context.

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

6 High HEAD redirects are fixed while the heartbeat cutoff remains wrong THttpClientSocket keeps HEAD and OPTIONS on 301/303 and changes body-bearing methods to GET. The same commit changes the async idle guard to allowed < gc; after gc becomes the absolute 60-second memory cutoff, that condition sets allowed to zero and skips heartbeat callbacks. Fixes mormot.net.async+1 edf01585+5-4

net: THttpClientSocket should keep HEAD for HTTP_MOVEDPERMANENTLY

Impact

HEAD requests now retain method semantics across redirects. With the default LastOperationReleaseMemorySeconds of 60, async WebSocket servers stop scheduling OnLastOperationIdle once the process passes that threshold; setting it to 0 avoids this branch.

Worth a look

Test HEAD redirects. For async WebSocket servers, set LastOperationReleaseMemorySeconds to 0 and verify ping/pong traffic until upstream corrects the cutoff comparison.

Public API

  • THttpClientSocket.Request redirect handlingbehaviour-changed — 301 and 303 retain methods that have no body, including HEAD and OPTIONS.

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

7 High Same-origin redirects now send the redirected path THttpClientSocket.Request moves ctxt.Url assignment outside the reconnect-only block, so a redirect on the existing connection updates the next request URL even when host, port and TLS mode are unchanged. Fixes mormot.net.client 30f397da+3-3

net: fixed THttpClientSocket redirections on the same server

Impact

Same-server redirects no longer repeat the original path or return the wrong resource while reusing the socket.

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

8 High SChannel renegotiation again preserves decrypted buffers The SEC_I_RENEGOTIATE branch in TSChannelNetTls.Receive now calls ProcessBuffers before checking pending output and continuing the TLS 1.3 post-handshake exchange. Fixes mormot.net.sock.windows c6dc158f+3-2

net: fixed previous commit

Impact

Build 2.4.17143 could lose or fail to expose decrypted data accompanying renegotiation. Build 2.4.17144 restores that processing.

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

9 High Idle-loop cleanup introduces the heartbeat cutoff regression TAsyncConnections.IdleEverySecond adds underflow guards and shutdown checks, but the heartbeat guard compares sec against the already transformed gc value instead of the heartbeat delay. The next commit changes the operands without restoring the intended cutoff calculation. Under the hood mormot.net.async fab1dd9a+18-15

net: minor TAsyncConnections.IdleEverySecond cleanup

Impact

The cleanup starts the final-head condition that suppresses async WebSocket idle callbacks after the normal memory-release window; non-WebSocket idle cleanup otherwise gains safer termination checks.

Worth a look

Do not rely on this intermediate heartbeat logic; apply the LastOperationReleaseMemorySeconds workaround described for the final head.

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

10 Medium Proxy HEAD probing preserves 204 and redirect outcomes THttpProxyUrl.RemoteClientHead uses the Range GET fallback only for a 200 response without length, returns 204 and 3xx directly, and includes TSimpleHttpClient.RequestContext in later exception diagnostics. Fixes mormot.net.async+1 48940904+15-12

net: enhanced THttpProxyUrl.RemoteClientHead

Impact

Origins that intentionally return no content or a redirect are no longer replaced by a range probe, and proxy logs carry the redirect or socket context needed to diagnose failures.

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

11 Medium Redirect credential purging now covers generated Referer headers THttpClientSocket replaces one authorization flag with fAuthPurge, suppresses both generated Referer and Authorization values after cross-origin purging, and uses TUri.Same for origin comparison. Fixes mormot.net.client c94dba6c+11-11

net: some THttpRedirectOptions fixes

Impact

Applications enabling hroPurgeReferer or hroPurgeAuthorization no longer leak values regenerated by socket fields on the redirected request; default redirect behavior remains unchanged.

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

12 Medium Proxy HEAD and GET paths now preserve non-file status codes THttpProxyServer limits local-file and progressive-output setup to HTTP_GET_OK responses, emits Content-Length separately for other known-size statuses and moves option copying before output setup. Fixes mormot.net.async 597eea16+9-5

net: fixed THttpProxyServer HEAD/GET response codes

Impact

HEAD and GET callers receive the origin status instead of entering file-serving logic for redirects or other responses, reducing malformed proxy responses.

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

13 Medium Proxy-cache 204 responses no longer enter file delivery THttpProxyServer narrows size and progressive-file handling to HTTP 200 and 206, excluding HTTP 204 while retaining redirect responses and their headers. Fixes mormot.net.async 882e3435+7-5

net: fixed 204 responses for the Proxy Cache

Impact

A cached origin response with no content is returned as 204 instead of being treated like a downloadable file with an invalid or synthetic length.

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

14 Medium Range probing now normalizes 206 without rejecting redirects THttpProxyUrl.RemoteClientHead maps the synthetic Range GET 206 back to 200, while MakeHeadAndComputeFilename only rejects missing size for actual 200/206 downloads and lets 3xx pass through. Fixes mormot.net.async b98df07d+8-3

net: fixed some other Proxy Cache status issues

Impact

Dynamic resources probed with Range no longer expose a misleading 206 through the proxy, and redirects without a content length are not converted into an error.

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

15 Medium Peer-cache redirects retain their Location header THttpPeerCache.DirectFileNameHead assigns the client response headers to Ctxt.OutCustomHeaders before checking HTTP_GET_OK, so Location is preserved even when the status is 3xx. Fixes mormot.net.server 9b96345d+3-3

net: fixed THttpPeerCache to include Location: for 3xx redirections

Impact

Clients can follow redirects returned through THttpPeerCache instead of receiving a 3xx response without its target URL.

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

16 Medium HTTP clients gain opt-in redirect security policy mormot.net.client adds THttpRedirectOption, THttpRedirectOptions and THttpRequestExtendedOptions.RedirectOptions. THttpClientSocket can purge Authorization, Cookie or Referer across origins and reject downgrade, cross-origin or userinfo redirects. New features mormot.net.client 492aeccf+95-18

net: new THttpRedirectOptions set of options for THttpClientSocket

Impact

Existing code keeps unrestricted redirects because the default is an empty set. Security-sensitive callers can now prevent credential forwarding or unsafe destination changes without replacing the redirect loop.

Worth a look

Review clients that follow untrusted redirects and select the required hroPurge* and hroReject* flags; include build 2.4.17161 fixes.

Public API

  • THttpRedirectOptionadded — Adds six purge and rejection choices for redirects.
  • THttpRedirectOptionsadded — Set of THttpRedirectOption values.
  • THttpRequestExtendedOptions.RedirectOptionsadded — Defaults to an empty set and is currently implemented by THttpClientSocket.

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

17 Medium SChannel buffers use SSPI limits instead of fixed growth TSChannelNetTls records the exact maximum TLS record size, starts output data at 2 KB and expands missing input by the SECBUFFER_MISSING count up to the SSPI-reported maximum. Performance mormot.lib.sspi+1 8bcdf6c9+39-13

net: refined SChannel TLS buffer size

Impact

Typical Windows TLS connections retain less memory while large records still grow to the size required by SChannel; application behavior is unchanged.

Arnaud Bouchez · 10:31 UTC · view the commit on GitHub →

18 Medium SChannel receive processing is centralized around SSPI results TSChannelNetTls.Receive factors buffer extraction into ProcessBuffers and handles SEC_E_OK, SEC_I_RENEGOTIATE, context expiry and errors in one result switch. The commit also only rewords SQLite and changelog comments. Under the hood mormot.net.sock.windows+1 1ebf95e7+53-46

net: rewritten TSChannelNetTls.Receive core process

Impact

The receive path becomes easier to reason about and properly coordinates renegotiation with its lock, but this exact build needs the following ProcessBuffers repair. No database behavior changes.

Worth a look

Do not stop on build 2.4.17143; include c6dc158f3a9e1be0dd9a06e063800365f9d4bf45 or later.

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

19 Low SChannel connections start with smaller dynamic buffers The fixed 19 KB TLSRECMAXSIZE allocation is removed. TSChannelNetTls initializes input, data and output storage at 4 KB and grows it through EnsureLength as records arrive. Performance mormot.net.sock.windows f1785ad1+40-42

net: reduce TSChannelNetTls memory consumption per connection

Impact

Windows services with many mostly idle TLS connections consume less baseline memory; large transfers still allocate on demand.

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

20 Low Idle async connections release working memory only once TPollAsyncConnection.ReleaseMemoryOnIdle consolidates read, write and TLS cleanup under the correct locks and marks fMemClean after success. New activity clears the marker, avoiding a cleanup attempt every second. Performance mormot.net.async 85f08e29+32-39

net: rewritten TPollAsyncConnection.ReleaseMemoryOnIdle

Impact

Long-idle servers do less lock and cleanup work each second while still releasing per-connection buffers after activity stops; application code does not change.

Arnaud Bouchez · 12:15 UTC · view the commit on GitHub →

21 Low Idle async sockets now release SChannel buffers TPollAsyncConnection.ReleaseMemoryOnIdle acquires both read and write locks as required and invokes INetTls.ReleaseBuffers when no pending plain data remains. Performance mormot.net.async a03577b9+23-4

net: idle TPollAsyncConnection release its INetTls buffers

Impact

Windows SChannel servers can return unused TLS allocation from idle connections; OpenSSL remains a no-op because its release mode already handles buffers safely.

Arnaud Bouchez · 10:43 UTC · view the commit on GitHub →

22 Low SChannel renegotiation uses the Windows OS lock TSChannelNetTls replaces TLightLock with TOSLightLock around the Receive/Send SSPI renegotiation boundary and removes a redundant first-accept state assignment. Performance mormot.core.os+1 ef2fdc14+5-7

net: some TSChannelNetTls cleanup/optimization

Impact

A blocked Windows receiver can be scheduled promptly when the sender releases the lock; no application API or non-Windows backend changes.

Arnaud Bouchez · 07:17 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