λ

4 Implementation details (not part of API)

Here are some notes that try to explain how are things implemented. If this is out of sync or if it does not make sense at all, fixing it is not a hight priority, and definitely not a blocker.

λ

4.1 Overview

[in package HTTP2/CORE]

There are three core groups of classes:

Dispatcher create new connection instances as they receive requests, and connections create new stream instances to serve the streams to the clients.

Clients do not need dispatchers; they create the connection to the server explicitly.

λ

4.1.1 HTTP/2 Connections

At any point of time, a HTTP2-CONNECTION expects explicit number of octets as an input, i.e., 9 octets for a header, or frame size octets of the frame payload. This information is not stored in the connection (why?), but lexically in a loop in functions that make the update, together with a function that acts on the connection when the data are available. See HTTP2/STREAM-OVERLAY:PROCESS-PENDING-FRAMES that reads the input data from (Common Lisp) binary STREAM as one example. See Processing data frames.

λ

Data and flow control

HTTP streams can receive some data (content, body). We can see treat in several ways:

In both cases, one may want to work either with a string or with octets. The latter is default, for the former use UTF8-PARSER-MIXIN and/or FALLBACK-ALL-IS-ASCII.

The body can be gzipped; in such case derive the stream from GZIP-DECODING-MIXIN.

Data to write are send by WRITE-DATA-FRAME-MULTI or WRITE-DATA-FRAME. These do not take into account limits set up by the peer, so use WRITE-BINARY-PAYLOAD instead.

Send and received octets are accounted for and must be within some limits (window).

User in most cases probably prefers not to care about windows and data frames, and binary vs text and content encoding and compression of the data.

This poses several topics:

Starting from the low-level, options are:

λ

4.1.2 HTTP/2 Streams

λ

4.1.3 Classes

There are two parallel class hierarchies, one for HTTP2 connections, one for the HTTP2 streams.

In general, CLIENT- and SERVER- classes implement required minimal behaviour for the client, resp. server, and are supposed to be stable, while VANILLA classes implement "typical" or best practice behaviour and may change in time. They should be good for ad-hoc activities and experiments; for stable behaviour, make your class using appropriate mixins.

Class hierarchy

λ

4.1.4 Writing frames

There are two strategies how to write data that a connection produces - either write them to a stream, or store them for future. They specialize QUEUE-FRAME generic function to actually store the data.

λ

4.1.5 Processing data frames

λ

4.2 HPACK - RFC7541 implementation.

[in package HTTP2/HPACK]

HTTP2 headers can be compressed - and implementation needs to be able to decompress - by two (or maybe three) ways:

Dynamic headers table is implemented by HPACK-CONTEXT class that should be from API point considered opaque. Context is needed twice for each connection, once for each direction of communication.

λ

4.3 Data and flow control

[in package HTTP2/CORE]

HTTP streams can receive some data (content, body). We can see treat in several ways:

In both cases, one may want to work either with a string or with octets. The latter is default, for the former use UTF8-PARSER-MIXIN and/or FALLBACK-ALL-IS-ASCII.

The body can be gzipped; in such case derive the stream from GZIP-DECODING-MIXIN.

Data to write are send by WRITE-DATA-FRAME-MULTI or WRITE-DATA-FRAME. These do not take into account limits set up by the peer, so use WRITE-BINARY-PAYLOAD instead.

Send and received octets are accounted for and must be within some limits (window).

User in most cases probably prefers not to care about windows and data frames, and binary vs text and content encoding and compression of the data.

This poses several topics:

Starting from the low-level, options are:

λ

4.4 Server API reference

[in package HTTP2/SERVER with nicknames HTTP2/SERVER/SHARED, HTTP2/SERVER/POLL, HTTP2/SERVER/THREADED]

λ

4.4.1 Server classes

The server behaviour is defined by used dispatcher (server class). The class is specified as a parameter to the START function.

The dispatcher should be a subclass of the BASE-DISPATCHER and can use predefined mixins to specify:

Some predefined combinations are below.

λ

Server mixins and component classes

λ

4.5 Polling server overview

[in package HTTP2/SERVER with nicknames HTTP2/SERVER/SHARED, HTTP2/SERVER/POLL, HTTP2/SERVER/THREADED]

λ

4.5.1 Interface to the polling server

POLL-DISPATCHER-MIXIN tracks a pool of clients that are connected to a socket. Each client has a user registered callback function and required number of octets to have available to call the callback. Callbacks call SEND-UNENCRYPTED-BYTES to encrypt and send more data.

The central function is SERVE-TLS that orchestrates reading, decrypting, encrypting and writing of data for all the sockets.

λ

4.5.2 Client actions loop (implementation)

Each TLS-ENDPOINT has a STATE that encapsulates what actions are effectively possible.

SELECT-NEXT-ACTION selects appropriate action. When no new action is available, next client is handled and eventually POLL called when all clients were served.

The actions are in general indicated by arrows in the diagram:

λ

TLS endpoint

λ

Application loop

λ

Port to TLS

λ

TLS to port