silk.http.http2.
A transport-independent HTTP/2 connection for clients and servers (RFC 9113).
Feed incoming bytes to Connection.receive, send Connection.output, and acknowledge sent bytes
with Connection.consumeOutput. Each call returns at most one application event. Keep calling
with the unconsumed input. SETTINGS and PING acknowledgments are queued automatically.
DATA uses connection and stream flow control. Call Connection.release only after consuming
received data. A zero return from Connection.sendData means flow control or queued output blocks progress.
Streams can progress independently. Field blocks remain contiguous on the wire.
Use prior knowledge on cleartext transports. On TLS, select h2 with ALPN before creating this
connection. The obsolete HTTP/1.1 Upgrade handshake is not part of RFC 9113.
Examples#
Queue two requests on one connection#
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }
import silk.http.hpack { Field }
import silk.http.http2 { Connection, Limits, Role }
import silk.http.http2_frame { ProtocolError }
import silk.num.u32
import silk.num.usize
effect fn requests() -> i32
! ProtocolError | OutOfMemoryError
? &mut Allocator {
let mut connection = run Connection.make(Role.Client, Limits.defaults())
let fields = [
Field { name: b":method", value: b"GET", sensitive: false },
Field { name: b":scheme", value: b"https", sensitive: false },
Field { name: b":authority", value: b"example.com", sensitive: false },
Field { name: b":path", value: b"/", sensitive: false }
]
let first = run Connection.open(&mut connection, &fields, true)
let second = run Connection.open(&mut connection, &fields, true)
// Send these queued bytes over the authenticated h2 transport.
let wire = Connection.output(&connection)
if first != 1 || second != 3 || wire.length < 24 {
return 1
}
return 0
}
effect fn failed<E>(error: E) -> i32 {
drop error
return 1
}
pub fn main() -> i32 {
let mut allocator = Allocator.systemAllocatorProvider()
return run Effect.catchAll(requests(), failed) |> Effect.provideMut<Allocator>(&mut allocator)
}Import as Connection with import silk.http.http2 { Connection }.
Public declarations: 5.
Role#
pub enum RoleThe endpoint role. Clients allocate odd stream identifiers; servers allocate even identifiers for push.
Client#
ClientSends the client preface and initiates requests.
Server#
ServerChecks the client preface and accepts requests.
Limits#
pub struct LimitsConnection resource limits. The receiver advertises the applicable limits in SETTINGS.
Field streams#
pub streams: u32Maximum simultaneous peer-initiated streams.
Field frameBytes#
pub frameBytes: u32Maximum accepted frame payload, from 16384 through 16777215 bytes.
Field fields#
pub fields: usizeMaximum decoded field count per block.
Field headerBytes#
pub headerBytes: u32Maximum decoded field-list size, including 32 bytes per field.
Field compressedBytes#
pub compressedBytes: usizeMaximum compressed field block bytes across HEADERS and CONTINUATION frames.
Field tableBytes#
pub tableBytes: u32Maximum HPACK dynamic table bytes.
Field windowBytes#
pub windowBytes: u32Initial receive window for each stream, at most 2147483647 bytes.
Field outputBytes#
pub outputBytes: usizeMaximum unsent wire bytes. Drain output before queuing more application data.
Field push#
pub push: boolWhether a client accepts push for the exact authority and scheme of the associated request. Servers ignore this field.
Implementation Copy for Limits#
impl Copy for LimitsImplementation Limits#
impl LimitsAssociated function defaults#
pub fn defaults() -> LimitsReturns limits of 100 streams, 16 KiB frames, 64 KiB field lists, and 1 MiB queued output.
Event#
pub union EventOne event from the peer. DATA storage belongs to the event until the application drops it.
None#
NoneNo application event. Continue with the unconsumed input, or wait for more bytes.
Headers#
HeadersA complete initial, informational, or trailing field section.
Field stream#
pub stream: u32The stream identifier.
Field fields#
pub fields: List<Header>Decoded fields in wire order.
Field endStream#
pub endStream: boolTrue if this section ends the peer's side of the stream.
Data#
DataStream body bytes with frame padding removed.
Field stream#
pub stream: u32The stream identifier.
Field bytes#
pub bytes: BytesThe body bytes. Call release after consuming them.
Field endStream#
pub endStream: boolTrue if the peer finished this stream.
Push#
PushA server push request. A client can reject it with reset.
Field stream#
pub stream: u32The associated request stream.
Field promised#
pub promised: u32The promised even stream identifier.
Field fields#
pub fields: List<Header>The promised request fields.
Reset#
ResetThe peer reset one stream.
Field stream#
pub stream: u32The reset stream.
Field code#
pub code: u32The wire error code, including unknown extension codes.
Pong#
PongA PING acknowledgment with its opaque payload.
Field bytes#
pub bytes: BytesThe eight bytes supplied by the peer.
Goaway#
GoawayThe peer started graceful shutdown. Existing eligible streams can still finish.
Field lastStream#
pub lastStream: u32The last locally initiated stream the peer might have processed.
Field code#
pub code: u32The peer's wire error code.
Field debug#
pub debug: BytesOpaque diagnostic bytes.
Settings#
SettingsThe peer's settings changed or it acknowledged local settings.
StreamError#
StreamErrorA rejected stream. RST_STREAM is queued; other streams remain usable.
Field stream#
pub stream: u32The rejected stream identifier.
Field code#
pub code: u32The wire error code.
Writable#
WritableThe peer granted connection or stream send credit.
Progress#
pub struct ProgressThe result of feeding incoming wire bytes.
Field consumed#
pub consumed: usizeBytes consumed from the supplied input.
Field event#
pub event: EventAt most one complete event.
Connection#
pub struct ConnectionAn owned HTTP/2 state machine. It does no I/O and needs no compiler or native protocol support. Connection errors queue GOAWAY and make the connection terminal. Stream errors queue RST_STREAM.
Implementation Connection#
impl ConnectionAssociated function make#
pub effect fn make(endpoint: Role, limits: Limits) -> Connection
! ProtocolError | OutOfMemoryError
? &mut AllocatorCreates a connection and queues its preface and initial SETTINGS.
Invalid limits fail with PROTOCOL_ERROR. TLS callers must first verify ALPN selected h2.
Method output#
pub fn output(self: &Self) -> &[u8]Borrows all unsent bytes. Send them in order before calling consumeOutput.
Method consumeOutput#
pub effect fn consumeOutput(self: &mut Self, count: usize) -> ()
! ProtocolErrorMarks bytes as sent. A count beyond the available output fails with PROTOCOL_ERROR.
Method failed#
pub fn failed(self: &Self) -> boolTrue after a connection error. Drain the queued GOAWAY, then close the transport.
Method receive#
pub effect<'call> fn receive<'call>(self: &'call mut Self, input: &'call [u8]) -> Progress
! ProtocolError | OutOfMemoryError
? &mut AllocatorConsumes a wire fragment and returns at most one event. Partial frames are retained within the frame limit. Stream errors queue RST_STREAM; connection errors queue GOAWAY and reject subsequent input.
Method finishInput#
pub effect fn finishInput(self: &mut Self) -> ()
! ProtocolErrorReports EOF. A truncated preface, frame, field block, or open stream fails with PROTOCOL_ERROR.
Method open#
pub effect fn open(self: &mut Self, fields: &[Field], endStream: bool) -> u32
! ProtocolError | OutOfMemoryError
? &mut AllocatorOpens a client request stream. GOAWAY, exhausted identifiers, and peer stream limits refuse new streams.
Method sendHeaders#
pub effect fn sendHeaders(self: &mut Self, id: u32, fields: &[Field], endStream: bool) -> ()
! ProtocolError | OutOfMemoryError
? &mut AllocatorQueues response fields or trailers on an existing stream. Trailers must end the stream. Informational responses leave the stream ready for a final response and cannot end it.
Method sendData#
pub effect fn sendData(self: &mut Self, id: u32, input: &[u8], endStream: bool) -> usize
! ProtocolError | OutOfMemoryError
? &mut AllocatorQueues as many body bytes as flow control, the frame size, and output space allow. END_STREAM is sent only when all input bytes fit. A zero return with nonempty input means backpressure.
Method release#
pub effect fn release(self: &mut Self, id: u32, count: u32) -> ()
! ProtocolError | OutOfMemoryError
? &mut AllocatorReturns consumed DATA credit to the peer. Padding credit is returned automatically. The count cannot exceed unreleased body bytes for this stream. Closed streams return connection credit only.
Method reset#
pub effect fn reset(self: &mut Self, id: u32, code: u32) -> ()
! ProtocolError | OutOfMemoryError
? &mut AllocatorCancels an existing stream and queues RST_STREAM. Queued incoming body credit is returned to the connection.
Method ping#
pub effect fn ping(self: &mut Self, bytes: &[u8]) -> ()
! ProtocolError | OutOfMemoryError
? &mut AllocatorSends a PING with exactly eight opaque bytes. Other lengths fail with FRAME_SIZE_ERROR.
Method shutdown#
pub effect fn shutdown(self: &mut Self, code: u32, debug: &[u8]) -> ()
! ProtocolError | OutOfMemoryError
? &mut AllocatorStops accepting new streams and queues GOAWAY. Existing streams can finish when the code is NO_ERROR.
Method settingsTimeout#
pub effect fn settingsTimeout(self: &mut Self) -> ()
! ProtocolError | OutOfMemoryError
? &mut AllocatorFails the connection if the initial SETTINGS acknowledgment has not arrived by the caller's deadline.
Method push#
pub effect fn push(self: &mut Self, associated: u32, fields: &[Field]) -> u32
! ProtocolError | OutOfMemoryError
? &mut AllocatorReserves a server push stream and queues PUSH_PROMISE. The request must use GET or HEAD without a body.
Category: HTTP.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.