logo.png
mORMot2 API Reference

mormot.net.async.pas unit

Purpose: Asynchronous Network Layer for Event-Driven Clients or Servers
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md

1.1. Units used in the mormot.net.async unit

Unit NameDescription
mormot.core.baseFramework Core Shared Types and RTL-like Functions
mormot.core.buffersFramework Core Low-Level Memory Buffer Process
mormot.core.dataFramework Core Low-Level Data Processing Functions
mormot.core.datetimeFramework Core Low-Level Date and Time Support
mormot.core.jsonFramework Core Low-Level JSON Processing
mormot.core.logFramework Core Logging
mormot.core.osFramework Core Low-Level Wrappers to the Operating-System API
mormot.core.perfFramework Core Performance and Monitoring Classes
mormot.core.rttiFramework Core Low-Level Cross-Compiler RTTI Definitions
mormot.core.searchFramework Core Text, Binary and Time Search Engines
mormot.core.textFramework Core Low-Level Text Processing
mormot.core.threadsFramework Core Multi-Threading Support
mormot.core.unicodeFramework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion
mormot.core.zipFramework Core Zip/Deflate Compression Support
mormot.crypt.secureFramework Core Authentication and Security Features
mormot.net.clientHTTP/HTTPS Client Classes
mormot.net.httpHTTP/HTTPS Abstract Process Classes and Definitions
mormot.net.serverHTTP/HTTPS Server Classes
mormot.net.sockLow-level access to the OperatingSystem Sockets API (e.g. WinSock2)

1.2. mormot.net.async class hierarchy

TSynThreadTAsyncConnectionsThreadTHttpAsyncConnectionTHttpAsyncServerConnectionTHttpAsyncClientConnectionTAsyncConnectionTPollAsyncConnectionTSynPersistentTHttpProxyMemTHttpAsyncClientConnectionsTHttpProxyDiskTSynAutoCreateFieldsTHttpProxyUrlTHttpProxyServerSettingsTHttpProxyServerMainSettingsTHttpProxyServerTPollAsyncSocketsTAsyncConnectionsSocketsTObjectTAsyncServerTHttpAsyncConnectionsTAsyncConnectionsTAsyncClientTNotifiedThreadTHttpServerSocketGenericTHttpAsyncServerESynExceptionEHttpProxyServerEAsyncConnectionsEHttpAsyncConnections
mormot.net.async class hierarchy

1.3. Objects implemented in the mormot.net.async unit

ObjectsDescription
EAsyncConnectionsException associated with TAsyncConnection / TAsyncConnections process
EHttpAsyncConnectionsException associated with Event-Driven HTTP Server process
TAsyncClientImplements thread-pooled high-performance TCP multiple clients
TAsyncConnectionAbstract class to store one TAsyncConnections connection
TAsyncConnectionsImplements an abstract thread-pooled high-performance TCP clients or server
TAsyncConnectionsSocketsHandle multiple non-blocking connections using TAsyncConnection instances
TAsyncConnectionsThreadUsed to implement a thread poll to process TAsyncConnection instances
TAsyncServerImplements a thread-pooled high-performance TCP server
THttpAsyncClientConnectionHandle one HTTP client connection handled by our non-blocking THttpAsyncServer
THttpAsyncClientConnectionsImplement HTTP async client requests
THttpAsyncConnectionAbstract HTTP server or client connection to our non-blocking THttpAsyncServer
THttpAsyncConnectionsEvent-driven process of HTTP/WebSockets connections
THttpAsyncServerHTTP server using non-blocking sockets
THttpAsyncServerConnectionHandle one HTTP server connection to our non-blocking THttpAsyncServer
THttpProxyDiskDefine disk cache settings of content for THttpProxyServer
THttpProxyMemDefine the caching settings of content for THttpProxyServer
THttpProxyServerImplements a HTTP server with forward proxy and caching
THttpProxyServerMainSettingsDefine the THttpProxyServer HTTP(S) server settings
THttpProxyServerSettingsDefine the THttpProxyServer forward proxy process
THttpProxyUrlDefine one URL content setting for THttpProxyServer
TPollAsyncConnectionAbstract parent to store information aboout one TPollAsyncSockets connection
TPollAsyncConnectionsThread-safe storage of several connections
TPollAsyncSocketsRead/write buffer-oriented process of multiple non-blocking connections

1.3.1. TPollAsyncConnection

TPollAsyncConnection = class(TSynPersistent)

Abstract parent to store information aboout one TPollAsyncSockets connection


destructor Destroy; override;

Finalize the instance


function IsClosed: boolean;

Quick check if this instance is still open


function IsDangling: boolean;

Quick check if this instance seems still active, i.e. its Handle <> 0


function Recv(buf: pointer; var len: integer): TNetResult;

Receive some buffer from the connection, using TLS if possible


function ReleaseMemoryOnIdle: PtrInt;

Called after TAsyncConnections.LastOperationReleaseMemorySeconds


function Send(buf: pointer; var len: integer): TNetResult;

Send some buffer to the connection, using TLS if possible


function TryLock(writer: boolean): boolean;

Acquire an exclusive R/W access to this connection
- returns true if connection has been acquired, setting the wasactive flag
- returns false if it is used by another thread


function WaitLock(writer: boolean; timeoutMS: cardinal): boolean;

Try to acquire an exclusive R/W access to this connection
- returns true if connection has been acquired
- returns false if it is used by another thread, after the timeoutMS period
- only with writer=true after a locked read + process, so unlikely to sleep


procedure UnLock(writer: boolean);

Release exclusive R/W access to this connection


procedure UnLockFinal(writer: boolean);

Release all R/W nested locks
- used when the connection is closed and inactive


property Handle: TPollAsyncConnectionHandle read fHandle;

Read-only access to the handle number associated with this connection


property Secure: INetTls read fSecure;

Read-only access to the low-level TLS context


property Socket: TNetSocket read fSocket;

Read-only access to the socket number associated with this connection


1.3.2. TPollAsyncConnections

TPollAsyncConnections = record

Thread-safe storage of several connections
- use e.g. by TPollAsyncSockets.ProcessWaitingWrite or to implement generational garbage collector of TAsyncConnection instances


1.3.3. TPollAsyncSockets

TPollAsyncSockets = class(TObject)

Read/write buffer-oriented process of multiple non-blocking connections
- to be used e.g. for stream protocols (e.g. WebSockets or IoT communication)
- assigned sockets will be set in non-blocking mode, so that polling will work as expected: you should then never use direclty the socket (e.g. via blocking TCrtSocket), but rely on this class for asynchronous process: TPollAsyncConnection.OnRead() overriden method will receive all incoming data from input buffer, and Write() should be called to add send some data, potentially asynchronous with an internal buffer
- ProcessRead/ProcessWrite methods are to be run for actual communication: either you call those methods from multiple threads, or you run them in loop from a single thread, then define a TSynThreadPool for running any blocking process (e.g. computing requests answers) from OnRead callbacks


constructor Create(aOptions: TPollAsyncSocketsOptions; aThreadCount: integer); virtual;

Pending soWaitWrite initialize the read/write sockets polling
- fRead and fWrite TPollSocketsBuffer instances will track pseRead or pseWrite events, and maintain input and output data buffers


destructor Destroy; override;

Finalize buffer-oriented sockets polling, and release all used memory


function ProcessRead(Sender: TSynThread; const notif: TPollSocketResult): boolean;

One or several threads should execute this method
- thread-safe handle of any notified incoming packet
- return true if something has been read or closed, false to retry later


function Start(connection: TPollAsyncConnection): boolean; virtual;

Assign a new connection to the internal reading poll
- the TSocket handle will be set in non-blocking mode from now on - it is not recommended to access it directly any more, but use Write() and handle OnRead() callback
- fRead will poll incoming packets, then call OnRead to handle them, or Unsubscribe and delete the socket when pseClosed is notified
- fWrite will poll for outgoing packets as specified by Write(), then send any pending data once the socket is ready
- any manual call of Start() should ensure the connection is non-blocking


function Stop(connection: TPollAsyncConnection; const caller: shortstring): boolean; virtual;

Remove a connection from the internal poll, and shutdown its socket
- most of the time, the connection is released by OnClosed when the other end shutdown the socket; but you can explicitly call this method when the connection (and its socket) is to be shutdown
- this method won't call OnClosed, since it is initiated by the class


function Write(connection: TPollAsyncConnection; data: pointer; datalen: integer; timeout: integer = 5000): boolean; virtual;

Add some data to the asynchronous output buffer of a given connection
- this method may block if the connection is currently writing from another thread (which is not possible from TPollAsyncSockets.Write), up to timeout milliseconds


function WriteString(connection: TPollAsyncConnection; const data: RawByteString; timeout: integer = 5000): boolean;

Add some data to the asynchronous output buffer of a given connection


procedure ProcessWrite(const notif: TPollSocketResult; sent: integer);

One thread should execute this method with the proper pseWrite notif
- thread-safe handle of any outgoing packets
- sent is the number of bytes already sent from connection.fWr buffer, e.g. via TWinIocp.PrepareNext(wieSend)


procedure Terminate(waitforMS: integer);

Notify internal socket polls to stop their polling loop ASAP


property Count: integer read GetCount;

How many connections are currently managed by this instance


property Iocp: TWinIocp read fIocp;

Low-level access to the IOCP polling class used for all events


property OnFirstRead: TOnPollAsyncProc read fOnFirstRead write fOnFirstRead;

Event called on first ProcessRead() on a given connection
- is assigned e.g. to TAsyncServer.OnFirstReadDoTls to setup the TLS in one sub-thread of the thread pool


property OnStart: TOnPollAsyncFunc read fOnStart write fOnStart;

Event called on Start() method success
- warning: this callback should be very quick because it is blocking


property OnStop: TOnPollAsyncProc read fOnStop write fOnStop;

Event called on Stop() method success
- warning: this callback should be very quick because it is blocking


property Options: TPollAsyncSocketsOptions read fOptions write fOptions;

Some processing options


property ReadBytes: Int64 read fReadBytes;

How many data bytes have been received by this instance


property ReadCount: Int64 read fReadCount;

How many times data has been received by this instance


property ReadWaitMs: integer read fReadWaitMs write fReadWaitMs;

Enable WaitFor() during recv() in ProcessRead
- may enhance responsiveness especially on HTTP/1.0 connections
- equals 0 ms by default, but could be tuned e.g. to 50 or 100 if needed
- use with care: performance degrades with highly concurrent HTTP/1.1


property WriteBytes: Int64 read fWriteBytes;

How many data bytes have been sent by this instance


property WriteCount: Int64 read fWriteCount;

How many times data has been sent by this instance


1.3.4. EAsyncConnections

EAsyncConnections = class(ESynException)

Exception associated with TAsyncConnection / TAsyncConnections process


1.3.5. TAsyncConnection

TAsyncConnection = class(TPollAsyncConnection)

Abstract class to store one TAsyncConnections connection
- may implement e.g. WebSockets frames, or IoT binary protocol
- each connection will be identified by a TPollAsyncConnectionHandle integer
- idea is to minimize the resources used per connection, and allow full customization of the process by overriding the OnRead virtual method (and, if needed, AfterCreate/AfterWrite/BeforeDestroy/OnLastOperationIdle)


constructor Create(aOwner: TAsyncConnections; const aRemoteIP: TNetAddr); reintroduce; virtual;

Initialize this instance


procedure Recycle(const aRemoteIP: TNetAddr); virtual;

Reuse this instance for a new incoming connection


property Owner: TAsyncConnections read fOwner;

Read-only access to the associated connections list


property RemoteIP: RawUtf8 read fRemoteIP;

The associated remote IP4/IP6, as text


1.3.6. TAsyncConnectionsSockets

TAsyncConnectionsSockets = class(TPollAsyncSockets)

Handle multiple non-blocking connections using TAsyncConnection instances


function Write(connection: TPollAsyncConnection; data: pointer; datalen: integer; timeout: integer = 5000): boolean; override;

Add some data to the asynchronous output buffer of a given connection
- this overriden method will also log the write operation if needed
- can be executed from an TAsyncConnection.OnRead method


property Total: integer read GetTotal;

How many connections have been handled by the poll, from the beginning


1.3.7. TAsyncConnectionsThread

TAsyncConnectionsThread = class(TSynThread)

Used to implement a thread poll to process TAsyncConnection instances


constructor Create(aOwner: TAsyncConnections; aProcess: TAsyncConnectionsThreadProcess; aIndex: integer); reintroduce;

Initialize the thread


destructor Destroy; override;

Finalize the thread resources


property CustomObject: TObject read fCustomObject write fCustomObject;

A TObject instance which will be owned by this thread once assigned
- Destroy will delete it when needed
- could be used to maintain some thread-speficic resource, e.g. a raw DB connection or a (set of) COM object(s)


property Index: integer read fIndex;

When used as a thread pool, the number of this thread


property Name: RawUtf8 read fName;

The low-level thread name


property Process: TAsyncConnectionsThreadProcess read fProcess;

Which kind of ProcessRead or ProcessWrite this thread is doing


1.3.8. TAsyncConnections

TAsyncConnections = class(TNotifiedThread)

Implements an abstract thread-pooled high-performance TCP clients or server
- internal TAsyncConnectionsSockets will handle high-performance process of a high number of long-living simultaneous connections
- will use a TAsyncConnection inherited class to maintain connection state
- don't use this abstract class but either TAsyncServer or TAsyncClient
- under Linux/POSIX, check your "ulimit -H -n" value: one socket consumes two file descriptors: you may better add the following line to your /etc/limits.conf or /etc/security/limits.conf system file:

 * hard nofile 65535

constructor Create(const OnStart, OnStop: TOnNotifyThread; aConnectionClass: TAsyncConnectionClass; const ProcessName: RawUtf8; aLog: TSynLogClass; aOptions: TAsyncConnectionsOptions; aThreadPoolCount: integer); reintroduce; virtual;

Initialize the multiple connections
- don't use this constructor but inherited client/server classes


destructor Destroy; override;

Shut down and finalize the instance, calling Shutdown


function ConnectionFind(aHandle: TPollAsyncConnectionHandle): TAsyncConnection;

High-level access to a connection instance, from its handle
- use efficient O(log(n)) binary search
- this method won't keep the main Lock, but this class will ensure that the returned pointer will last for at least 100ms until Free is called


function ConnectionFindAndLock(aHandle: TPollAsyncConnectionHandle; aLock: TRWLockContext; aIndex: PInteger = nil): TAsyncConnection;

High-level access to a connection instance, from its handle
- use efficient O(log(n)) binary search
- could be executed e.g. from a TAsyncConnection.OnRead method
- raise an exception if acoNoConnectionTrack option was defined
- returns nil if the handle was not found
- returns the maching instance, and caller should release the lock as:

 try ... finally UnLock(aLock); end;

function ConnectionRemove(aHandle: TPollAsyncConnectionHandle): boolean;

Remove an handle from the internal list, and close its connection
- raise an exception if acoNoConnectionTrack option was defined
- could be executed e.g. from a TAsyncConnection.OnRead method


function LockedConnectionSearch(aHandle: TPollAsyncConnectionHandle): TAsyncConnection;

Low-level access to a connection instance, from its handle
- use efficient O(log(n)) binary search, since handles are increasing
- caller should have called Lock before this method is done


function ThreadClientsConnect: TAsyncConnection;

Low-level method to connect a client to this server
- is called e.g. from fThreadClients


function Write(connection: TAsyncConnection; data: pointer; datalen: integer; timeout: integer = 5000): boolean;

Add some data to the asynchronous output buffer of a given connection
- could be executed e.g. from a TAsyncConnection.OnRead method


function WriteString(connection: TAsyncConnection; const data: RawByteString; timeout: integer = 5000): boolean;

Add some data to the asynchronous output buffer of a given connection
- could be executed e.g. from a TAsyncConnection.OnRead method


procedure EndConnection(connection: TAsyncConnection);

Call ConnectionRemove unless acoNoConnectionTrack is set


procedure LogVerbose(connection: TPollAsyncConnection; const ident: RawUtf8; const identargs: array of const; frame: pointer; framelen: integer); overload;

Log some binary data with proper escape
- can be executed from an TAsyncConnection.OnRead method to track content:

 if acoVerboseLog in Sender.Options then Sender.LogVerbose(self,...);

procedure LogVerbose(connection: TPollAsyncConnection; const ident: RawUtf8; const identargs: array of const; const frame: TRawByteStringBuffer); overload;

Log some binary data with proper escape
- can be executed from an TAsyncConnection.OnRead method to track content:

 if acoVerboseLog in Sender.Options then Sender.LogVerbose(...);

procedure SetCpuAffinity(CpuIndex: integer);

Ensure all threads of the pool is bound to a given CPU core
- may lower performance, but reduce global consumption


procedure SetOnIdle(const aOnIdle: TOnPollSocketsIdle; Remove: boolean = false);

Add or remove a callback run from ProcessIdleTix() internal method
- all callbacks will be triggered once with Sender=nil at shutdown


procedure SetSocketAffinity(SocketIndex: integer);

Ensure all threads of the pool is bound to a given CPU HW socket
- may enhance performance on multi-socket systems


procedure Shutdown; virtual;

Shut down the instance, releasing all associated threads and sockets


property Clients: TAsyncConnectionsSockets read fClients;

Access to the TCP client sockets poll
- TAsyncConnection.OnRead should rather use Write() and LogVerbose() methods of this TAsyncConnections class instead of using Clients


property Connection: TAsyncConnectionDynArray read fConnection;

Low-level unsafe direct access to the connection instances
- ensure this property is used in a thread-safe manner, i.e. calling ConnectionFindAndLock() high-level function, ot via manual

 ConnectionLock.ReadOnlyLock;
 try ... finally ConnectionLock.ReadOnlyUnLock; end;

property ConnectionClass: TAsyncConnectionClass read fConnectionClass write fConnectionClass;

Direct access to the class instantiated for each connection
- as supplied to the constructor, but may be overriden just after startup


property ConnectionCount: integer read fConnectionCount;

Current HTTP/1.1 / WebSockets connections count
- this is the number of long-living connections - may not appear just after accept, so never for a HTTP/1.0 short-living request


property ConnectionHigh: integer read fConnectionHigh;

Maximum number of concurrent long-living connections since started


property ConnectionLock: TRWLock read fConnectionLock;

Access to the R/W lock protecting the Connection[] array
- will WriteLock/block only on connection add/remove


property KeepConnectionInstanceMS: cardinal read fKeepConnectionInstanceMS write fKeepConnectionInstanceMS;

How many milliseconds a TAsyncConnection instance is kept alive after closing
- default is 100 ms before the internal GC calls Free on this instance


property LastOperationIdleSeconds: cardinal read fLastOperationIdleSeconds write fLastOperationIdleSeconds;

Will execute TAsyncConnection.OnLastOperationIdle after an idle period
- could be used to send heartbeats after read/write inactivity
- equals 0 (i.e. disabled) by default


property LastOperationReleaseMemorySeconds: cardinal read fLastOperationReleaseMemorySeconds write fLastOperationReleaseMemorySeconds;

Allow idle connection to release its internal Connection.rd/wr buffers
- default is 60 seconds, which is pretty conservative
- could be tuned in case of high numbers of concurrent connections and constrained memory, e.g. with a lower value like 2 seconds


property LastOperationSec: TAsyncConnectionSec read fLastOperationSec;

The current monotonic time elapsed, evaluated in seconds
- IdleEverySecond will set GetTickCount64 div 1000


property Log: TSynLogClass read fLog;

Access to the associated log class


property Options: TAsyncConnectionsOptions read fOptions write fOptions;

Allow to customize low-level options for processing


property ThreadPoolCount: integer read fThreadPoolCount;

How many read threads there are in this thread pool


property Threads: TAsyncConnectionsThreads read fThreads;

Direct access to the internal AsyncConnectionsThread`s


1.3.9. TAsyncServer

TAsyncServer = class(TAsyncConnections)

Implements a thread-pooled high-performance TCP server
- will use a TAsyncConnection inherited class to maintain connection state for server process


constructor Create(const aPort: RawUtf8; const OnStart, OnStop: TOnNotifyThread; aConnectionClass: TAsyncConnectionClass; const ProcessName: RawUtf8; aLog: TSynLogClass; aOptions: TAsyncConnectionsOptions; aThreadPoolCount: integer); reintroduce; virtual;

Run the TCP server, listening on a supplied IP port
- aThreadPoolCount = 1 is fine if the process is almost non-blocking, like our mormot.net.rtsphttp relay - but not e.g. for a REST/SOA server
- with aThreadPoolCount > 1, a thread will do atpReadPoll, and all other threads will do atpReadPending for socket reading and processing the data
- there will always be two other threads, one for Accept() and another for asynchronous data writing (i.e. sending to the socket)
- warning: should call WaitStarted() to let Execute bind and run
- for TLS support, set acoEnableTls, and once WaitStarted() returned, set Server.TLS.CertificateFile/PrivateKeyFile/PrivatePassword properties and call Server.DoTlsAfter(cstaBind)


destructor Destroy; override;

Shut down the server, releasing all associated threads and sockets


procedure Shutdown; override;

Prepare the server finalization


procedure WaitStarted(seconds: integer);

To be called just after Create to wait for Execute to Bind
- will raise an exception on timeout, or if the binding failed
- needed only for raw protocol implementation: THttpServerGeneric will have its own WaitStarted method


property Accepted: Int64 read fAccepted;

How many connections have been accepted since server startup
- ConnectionCount is the number of long-living connections, this counter is the absolute number of successful accept() calls, including short-living (e.g. HTTP/1.0) connections


property MaxConnections: integer read fMaxConnections write fMaxConnections;

Above how many active connections accept() would reject
- MaxPending applies to the actual thread-pool processing activity, whereas MaxConnections tracks the number of connections even in idle state


property MaxPending: integer read fMaxPending write fMaxPending;

Above how many fClients.fRead.PendingCount accept() would reject
- is mapped by the high-level THttpAsyncServer.HttpQueueLength property
- default is 10000, but could be a lower value e.g. for a load-balancer
- MaxConnections regulates the absolute number of (idle) connections, whereas this property tracks the actual REST/HTTP requests pending for the internal thread pool


property Server: TCrtSocket read fServer;

Access to the TCP server socket


1.3.10. TAsyncClient

TAsyncClient = class(TAsyncConnections)

Implements thread-pooled high-performance TCP multiple clients
- e.g. to run some load stress tests with optimized resource use
- will use a TAsyncConnection inherited class to maintain connection state of each connected client


constructor Create(const aServer, aPort: RawUtf8; aClientsCount, aClientsTimeoutSecs: integer; const OnStart, OnStop: TOnNotifyThread; aConnectionClass: TAsyncConnectionClass; const ProcessName: RawUtf8; aLog: TSynLogClass; aOptions: TAsyncConnectionsOptions; aThreadPoolCount: integer = 1); reintroduce; virtual;

Start the TCP client connections, connecting to the supplied IP server


property Port: RawUtf8 read fThreadClients.Port;

Server IP port


property Server: RawUtf8 read fThreadClients.Address;

Server IP address


1.3.11. EHttpAsyncConnections

EHttpAsyncConnections = class(EAsyncConnections)

Exception associated with Event-Driven HTTP Server process


1.3.12. THttpAsyncConnection

THttpAsyncConnection = class(TAsyncConnection)

Abstract HTTP server or client connection to our non-blocking THttpAsyncServer


1.3.13. THttpAsyncClientConnection

THttpAsyncClientConnection = class(THttpAsyncConnection)

Handle one HTTP client connection handled by our non-blocking THttpAsyncServer
- used e.g. for efficient reverse proxy support with another server


property OnStateChanged: TOnHttpClientAsync read fOnStateChanged;

Access to the associated progress event callback


property ResponseStatus: integer read fResponseStatus;

Server response HTTP status code (e.g. 200)


property Tls: TNetTlsContext read fTls write fTls;

Associated TLS options and informations


1.3.14. THttpAsyncServerConnection

THttpAsyncServerConnection = class(THttpAsyncConnection)

Handle one HTTP server connection to our non-blocking THttpAsyncServer


function GetConnectionOpaque: PHttpServerConnectionOpaque;

Access to the internal two PtrUInt tags of this connection
- may return nil e.g. behind a nginx proxy


procedure Recycle(const aRemoteIP: TNetAddr); override;

Reuse this instance for a new incoming connection


1.3.15. THttpAsyncConnections

THttpAsyncConnections = class(TAsyncServer)

Event-driven process of HTTP/WebSockets connections


property Banned: THttpAcceptBan read fBanned;

Set if hsoBan40xIP has been defined
- indicates e.g. how many accept() have been rejected from their IP
- you can customize its behavior once the server is started by resetting its Seconds/Max/WhiteIP properties, before any connections are made


1.3.16. THttpAsyncClientConnections

THttpAsyncClientConnections = class(TSynPersistent)

Implement HTTP async client requests
- reusing the threads pool and sockets polling of an associated TAsyncConnections instance (typically a THttpAsyncServer)


constructor Create(aOwner: TAsyncConnections; aConnectionTimeoutSec: integer); reintroduce;

Initialize the instance for a given TAsyncConnections
- connections will be kept alive up to aConnectionTimeoutSec seconds, ready to be reused


function StartRequest(const aUrl, aMethod, aHeaders: RawUtf8; const aOnStateChanged: TOnHttpClientAsync; aTls: PNetTlsContext; const aDestFileName: TFileName; out aConnection: THttpAsyncClientConnection; aOnStateChange: TOnHttpClientStates = [low(TOnHttpClientState) .. high(TOnHttpClientState)]): TNetResult;

Start an async connection to a remote HTTP server using a callback
- the aOnStateChanged event will be called after each http.State change


procedure Shutdown;

Called to notify that the main process is about to finish


property UserAgent: RawUtf8 read fUserAgent write fUserAgent;

Allow to customize the User-Agent used by each client connection


1.3.17. THttpAsyncServer

THttpAsyncServer = class(THttpServerSocketGeneric)

HTTP server using non-blocking sockets


constructor Create(const aPort: RawUtf8; const OnStart, OnStop: TOnNotifyThread; const ProcessName: RawUtf8; ServerThreadPoolCount: integer = 32; KeepAliveTimeOut: integer = 30000; ProcessOptions: THttpServerOptions = []); override;

'WinIocp' create an event-driven HTTP Server


destructor Destroy; override;

Finalize the HTTP Server


function Clients: THttpAsyncClientConnections;

Access async connections to any remote HTTP server
- will reuse the threads pool and sockets polling of this instance


property Async: THttpAsyncConnections read fAsync;

Direct access to the internal high-performance TCP server
- you could set e.g. Async.MaxConnections or Async.Banned properties


property HeadersDefaultBufferSize: integer read fHeadersDefaultBufferSize write fHeadersDefaultBufferSize;

Initial capacity of internal per-connection Headers buffer
- 2 KB by default is within the mormot.core.fpcx64mm SMALL blocks limit so will use up to 3 locks before contention


property HeadersMaximumSize: integer read fHeadersMaximumSize write fHeadersMaximumSize;

Maximum allowed size in bytes of incoming headers
- is set to 64KB by default, which seems conservative enough


property RequestClass: THttpServerRequestClass read fRequestClass write fRequestClass;

The class used for each THttpServerRequest instances


1.3.18. THttpProxyMem

THttpProxyMem = class(TSynPersistent)

Define the caching settings of content for THttpProxyServer
- set the memory cache settings if used as exact THttpProxyMem class


constructor Create; override;

Parsed fIgnoreCsv, fForceCsv setup the default values of this cache


function FromUri(const uri: TUriMatchName): THttpProxyCacheKind;

Check the IgnoreCsv and ForceCSv properties against a given URI


property ForceCsv: RawUtf8 read fForceCsv write fForceCsv;

CSV list of GLOB file names to be included in this cache even if its size does not match MaxSize
- e.g. '*.xml'


property IgnoreCsv: RawUtf8 read fIgnoreCsv write fIgnoreCsv;

CSV list of GLOB file names to be excluded to this cache
- e.g. '*.changelog,*.tmp'


property MaxSize: Int64 read fMaxSize write fMaxSize;

Size (in bytes) below which the file should be included in this cache
- default -1 will use the main THttpProxyServerSettings value


property TimeoutSec: integer read fTimeoutSec write fTimeoutSec;

How many seconds this file should remain in this cache
- default -1 will use the main THttpProxyServerSettings value


1.3.19. THttpProxyDisk

THttpProxyDisk = class(THttpProxyMem)

Define disk cache settings of content for THttpProxyServer


property Path: TFileName read fPath write fPath;

Default '' will use the main THttpProxyServerSettings value


1.3.20. THttpProxyUrl

THttpProxyUrl = class(TSynAutoCreateFields)

Define one URL content setting for THttpProxyServer


constructor Create; override;

Setup the default values of this URL


destructor Destroy; override;

Finalize this instance


property CacheControlMaxAgeSec: integer read fCacheControlMaxAgeSec write fCacheControlMaxAgeSec;

Support optional "Cache-Control: max-age=..." header timeout value
- default 0 value will disable this header transmission


property Disabled: boolean read fDisabled write fDisabled;

This source won't be processed if this property is set to true


property DiskCache: THttpProxyDisk read fDiskCache write fDiskCache;

Overwrite the main DiskCache setting to tune on-disk caching
- disk cache is available only for remote URI lookups, i.e. if Source is defined as 'http://...' and not as a local file


property IfModifiedSince: boolean read fIfModifiedSince write fIfModifiedSince;

Handle "if-modified-since:" client header as 304 HTTP_NOTMODIFIED
- default true will support 304 results against the resource timestamp


property MemCache: THttpProxyMem read fMemCache write fMemCache;

Overwrite the main MemCache setting to tune in-memory caching
- can be used for both local file or remote URI lookups


property Methods: TUriRouterMethods read fMethods write fMethods;

Which methods are applied to the local Source folder or relayed to the Remote server
- equals by default [urmGet, urmHead]


property RejectCsv: RawUtf8 read fRejectCsv write fRejectCsv;

CSV list of GLOB file or directly names to be rejected as not found
- e.g. '*.secret'


property Source: RawUtf8 read fSource write fSource;

A local folder name or remote origin URL to ask
- if Source is a local folder (e.g. 'd:/mysite' or '/var/www/mysite'), the Url prefix chars will be removed from the client request, then used to locate the file to be served
- if Source is a remote URI (like http://....), the Url prefix chars will be removed from the client request, then appended to this remote URI, which is e.g. 'http://ftp.debian.org/debian' or 'http://security.debian.org/debian-security' matching Local 'debian' or 'debian-security' prefixes, to compute a source remote URI


property Url: RawUtf8 read fUrl write fUrl;

The local URI prefix to use with the main HTTP(S) server of this instance
- a typical value is e.g. 'debian' for 'http://ftp.debian.org/debian'


1.3.21. THttpProxyServerMainSettings

THttpProxyServerMainSettings = class(TSynAutoCreateFields)

Define the THttpProxyServer HTTP(S) server settings


constructor Create; override;

Initialize the default settings


function SetupTls(var tls: TNetTlsContext): boolean;

Assign the HTTPS/TLS settings to a context


property CACertificatesFile: TFileName read fCACertificatesFile write fCACertificatesFile;

Optional HTTPS certificates authorities file


property CertificateFile: TFileName read fCertificateFile write fCertificateFile;

Optional HTTPS certificate file name
- should also set PrivateKeyFile and PrivateKeyPassword


property FaviconFile: TFileName read fFaviconFile write fFaviconFile;

Optional alternate favicon.ico file name


property Log: THttpLoggerSettings read fLog write fLog;

Custom log settings for the psoEnableLogging option
- e.g. to override default LOGFORMAT_COMBINED output, or rotation settings


property Options: THttpProxyServerOptions read fOptions write fOptions;

Customize this proxy cache HTTP/HTTPS process


property Port: RawUtf8 read fPort write fPort;

The local port used for HTTP/HTTPS content delivery
- is '8098' by default (THttpPeerCache uses 8099), unassigned by IANA
- you can bind to a specific 'IP:port' if needed


property PrivateKeyFile: TFileName read fPrivateKeyFile write fPrivateKeyFile;

Optional HTTPS private key file name


property PrivateKeyPassword: SpiUtf8 read fPrivateKeyPassword write fPrivateKeyPassword;

Optional HTTPS private key file password


property ServerName: RawUtf8 read fServerName write fServerName;

Optional Server name for HTTP/HTTPS
- to overwrite the default value set by the framework e.g. 'mORMot2 (Linux)'


property ThreadCount: integer read fThreadCount write fThreadCount;

The number of threads of the HTTP/HTTPS content delivery
- default value is 4 sub-threads which is enough to scale well if no content is to be generated


1.3.22. THttpProxyServerSettings

THttpProxyServerSettings = class(TSynAutoCreateFields)

Define the THttpProxyServer forward proxy process


constructor Create; override;

Initialize the default settings


procedure AddFolder(const folder: TFileName; const uri: RawUtf8 = ''; RaiseExceptionOnNonExistingFolder: ExceptionClass = nil);

Create a THttpProxyUrl definition to serve a local static folder
- if optional ExceptionClass is supplied, the local folder should exist


procedure AddUrl(one: THttpProxyUrl);

Append and own a given THttpProxyUrl definition at runtime
- this instance will be stored and owned in Url[] array


property DiskCache: THttpProxyDisk read fDiskCache write fDiskCache;

Default on-disk local cache settings
- can be overriden by Url[].DiskCache property


property MemCache: THttpProxyMem read fMemCache write fMemCache;

Default in-memory cache settings
- is set to MaxSize = 4KB and TimeoutSec = 5 minutes
- can be overriden by Url[].MemCache property


property Server: THttpProxyServerMainSettings read fServer write fServer;

Define the HTTP/HTTPS server configuration


property Url: THttpProxyUrlObjArray read fUrl;

Define the remote content sources


1.3.23. THttpProxyServer

THttpProxyServer = class(TSynAutoCreateFields)

Implements a HTTP server with forward proxy and caching


constructor Create(aSettings: THttpProxyServerSettings); reintroduce; virtual;

Initialize this forward proxy instance
- the supplied aSettings should be owned by the caller (e.g from a main settings class instance)


destructor Destroy; override;

Finalize this class instance


procedure Start(const aPrivateKeyPassword: SpiUtf8 = '');

Actually start the HTTP/HTTPS server
- you can specify a private key password if not already in Settings
- may raise some exceptions if the HTTP server cannot be started


procedure Stop;

Finalize the HTTP/HTTPS server


property Server: THttpAsyncServer read fServer;

The local HTTP(S) asynchronous server


property Settings: THttpProxyServerSettings read fSettings;

Access to the used settings


1.4. Types implemented in the mormot.net.async unit

1.4.1. TAsyncConnectionClass

TAsyncConnectionClass = class of TAsyncConnection;

Meta-class of one TAsyncConnections connection


1.4.2. TAsyncConnectionDynArray

TAsyncConnectionDynArray = array of TAsyncConnection;

Used to store a dynamic array of TAsyncConnection


1.4.3. TAsyncConnectionSec

TAsyncConnectionSec = type cardinal;

32-bit type used to store GetTickCount64 div 1000 values
- as used e.g. by TAsyncConnection.fLastOperation


1.4.4. TAsyncConnectionsOptions

TAsyncConnectionsOptions = set of ( acoOnErrorContinue, acoNoLogRead, acoNoLogWrite, acoVerboseLog, acoWritePollOnly, acoDebugReadWriteLog, acoNoConnectionTrack, acoEnableTls, acoThreadCpuAffinity, acoThreadSocketAffinity, acoReusePort, acoThreadSmooting );

Low-level options for TAsyncConnections processing
- TAsyncConnectionsSockets.OnError will shutdown the connection on any error, unless acoOnErrorContinue is defined
- acoNoLogRead and acoNoLogWrite could reduce the log verbosity
- acoVerboseLog will log transmitted frames content, for debugging purposes
- acoWritePollOnly will be translated into paoWritePollOnly on server
- acoDebugReadWriteLog would make low-level send/receive logging
- acoNoConnectionTrack would force to by-pass the internal Connections list if it is not needed - not used by now
- acoEnableTls flag for TLS support, via Windows SChannel or OpenSSL 1.1/3.x
- either acoThreadCpuAffinity or acoThreadSocketAffinity could be set: the first for thread affinity to one CPU logic core, the 2nd for affinity to all logical cores of each CPU HW socket (both exclusive)
- acoReusePort will set SO_REUSEPORT on POSIX, allowing to bind several TAsyncConnections on the same port, either within the same process, or as separated processes (e.g. to set process affinity to one CPU HW socket)
- acoThreadSmooting will change the ThreadPollingWakeup() algorithm to focus the process on the first threads of the pool - by design, this setting will disable both acoThreadCpuAffinity and acoThreadSocketAffinity


1.4.5. TAsyncConnectionsThreadProcess

TAsyncConnectionsThreadProcess = ( atpReadPending );

TAsyncConnectionsThread.Execute will directly call TWinIocp.GetNext()


1.4.6. TAsyncConnectionsThreads

TAsyncConnectionsThreads = array of TAsyncConnectionsThread;

Dynamic array of TAsyncConnectionsThread instances


1.4.7. THttpAsyncConnectionsClass

THttpAsyncConnectionsClass = class of THttpAsyncConnections;

Meta-class of THttpAsyncConnections type


1.4.8. THttpProxyCacheKind

THttpProxyCacheKind = set of ( pckIgnore, pckForce);

The result of THttpProxyMem.FromUri


1.4.9. THttpProxyServerOption

THttpProxyServerOption = ( psoLogVerbose, psoExcludeDateHeader, psoHttpsSelfSigned, psoReusePort, psoEnableLogging, psoDisableMemCache, psoNoFolderHtmlIndex, psoDisableFolderHtmlIndexCache, psoPublishSha256, psoPublishMd5 );

The available high-level options for THttpProxyServerMainSettings


1.4.10. THttpProxyServerOptions

THttpProxyServerOptions = set of THttpProxyServerOption;

A set of available options for THttpProxyServerMainSettings


1.4.11. THttpProxyUrlObjArray

THttpProxyUrlObjArray = array of THttpProxyUrl;

Define one or several remote content source(s) for THttpProxyServer


1.4.12. TOnHttpClientAsync

TOnHttpClientAsync = function(state: TOnHttpClientState; connection: THttpAsyncClientConnection): TPollAsyncSocketOnReadWrite of object;

Callback used e.g. by THttpAsyncClientConnection.OnStateChanged
- should return soContinue on success, or anything else to abort/close
- eventually hrsResponseDone or one hrsError* will mark the end of process


1.4.13. TOnHttpClientState

TOnHttpClientState = ( hcsBeforeTlsHandshake, hcsAfterTlsHandshake, hcsBeforeSendHeaders, hcsAfterSendHeaders, hcsReadStateChanged, hcsHeadersReceived, hcsFinished, hcsFailed );

Define the TOnHttpClientAsync callback state machine steps
- hcsBeforeTlsHandshake allows to change connection.Tls parameters
- hcsAfterTlsHandshake can validate the connection.Tls information
- hcsBeforeSendHeaders allows to change emitted connection.Http.Head
- hcsAfterSendHeaders is called just before read subscription
- hcsReadStateChanged is called by connection.OnRead when Http.State changed
- hcsHeadersReceived is called when response has set connection.ResponseStatus and connection.Http.Headers have been set
- hcsFinished is called when a response was received, maybe with a body
- hcsFailed is set on eventual error


1.4.14. TOnHttpClientStates

TOnHttpClientStates = set of TOnHttpClientState;

Define when the TOnHttpClientAsync callback is to be executed


1.4.15. TOnPollAsyncFunc

TOnPollAsyncFunc = function(Sender: TPollAsyncConnection): boolean of object;

Callback prototype for TPollAsyncSockets.OnStart events
- should return true if Start() should not subscribe for this connection


1.4.16. TOnPollAsyncProc

TOnPollAsyncProc = procedure(Sender: TPollAsyncConnection) of object;

Callback prototype for TPollAsyncSockets.OnStop events


1.4.17. TPollAsyncConnectionFlags

TPollAsyncConnectionFlags = set of ( fWasActive, fClosed, fFirstRead, fInList, fReadPending, fFromGC );

Low-level flags used by the state machine about one TPollAsyncConnection
- fWasActive is set by TAsyncConnections.IdleEverySecond to purge rd/wr unused buffers, to avoid calling GetTickCount64 for every activity
- fClosed is set by OnClose virtual method
- fFirstRead is set once TPollAsyncSockets.OnFirstRead is called
- fSubRead/fSubWrite flags are set when Subscribe() has been called
- fInList indicates that ConnectionAdd() did register the connection
- fReadPending states that there is a pending event for this connection
- fFromGC is set when the connection has been recycled from the GC list
- note: better keep it as 8 items to fit in a byte (faster access)


1.4.18. TPollAsyncConnectionHandle

TPollAsyncConnectionHandle = type integer;

32-bit integer value used to identify an asynchronous connection
- will start from 1, and increase during the TAsyncConnections live-time


1.4.19. TPollAsyncConnectionHandleDynArray

TPollAsyncConnectionHandleDynArray = array of TPollAsyncConnectionHandle;

A dynamic array of TPollAsyncConnectionHandle identifiers


1.4.20. TPollAsyncSocketOnReadWrite

TPollAsyncSocketOnReadWrite = ( soContinue, soWaitWrite, soDone, soClose );

Define the TPollAsyncSockets.OnRead/AfterWrite method result
- soContinue should continue reading/writing content from/to the socket
- soDone should unsubscribe for the current read/write phase, but should not shutdown the socket yet
- soWaitWrite (for AfterWrite) should wait a little then retry writing
- soClose would shutdown the socket


1.4.21. TPollAsyncSocketsOptions

TPollAsyncSocketsOptions = set of ( paoWritePollOnly );

Possible options for low-level TPollAsyncSockets process
- as translated from homonymous high-level acoWritePollOnly TAsyncConnectionsOptions item


1.5. Constants implemented in the mormot.net.async unit

1.5.1. ASYNC_OPTION_DEBUG

ASYNC_OPTION_DEBUG = [ ];

The TAsyncConnectionsOptions for debugging THttpAsyncServer
- with high-level receive/send block information


1.5.2. ASYNC_OPTION_PROD

ASYNC_OPTION_PROD = [ acoNoLogRead, acoNoLogWrite];

The TAsyncConnectionsOptions for THttpAsyncServer running on production
- with low verbosity of the logs - similar to a plain THttpServer


1.5.3. ASYNC_OPTION_VERBOSE

ASYNC_OPTION_VERBOSE = [ acoVerboseLog, acoDebugReadWriteLog];

The TAsyncConnectionsOptions for fully detailed debug of THttpAsyncServer
- with all possible - and very verbose - log information
- could be used to track performance or heisenbug issues