net/http2
The HTTP/2 protocol from the ground up: frames, HPACK header compression and streams.
import net.http2
This package implements HTTP/2 at the protocol level: it builds and reads frames, compresses the headers with HPACK and carries several requests at once over one connection as "streams". It is not a web server or a ready client. For an ordinary web server or one-off requests use net/http, which speaks HTTP/1.1; reach for this package when you need the protocol itself, for example to talk to a service that only offers HTTP/2, to test a server, or to send many requests over one connection.
How it goes: build a Transport over a TCP or TLS socket, take a connection with NewConn and do the handshake. Then the client sends a request with SendHeaders and reads the answer in StreamAt after AwaitStreamEnd. Over TLS, the client and the server must have agreed on h2 through ALPN.
What the package does for you, and what it leaves to you:
- It answers pings, sends window updates for flow control, waits for window space in
SendData, and refuses server push. - You write the pseudo-headers yourself:
:method,:scheme,:authorityand:pathon a request,:statuson an answer, before any normal header. - A stream's body is collected in memory in
s.datauntil the stream ends, and finished streams stay in the connection, so open a new connection now and then rather than keeping one for millions of requests. - A
Connbelongs to one thread; nothing in it is locked.
Many requests on one connection
The point of HTTP/2 is that one connection carries many requests at the same time. Each request is a stream with an odd id chosen by the client (1, 3, 5 and so on), and the frames of different streams can be interleaved in both directions. The client below sends three requests before reading anything; the server, in the same program, answers them in reverse order, and each answer still lands on the right stream.
import net.http2
import net.tcp
import compress
mut server := tcp.Server {}
func serve():
conn := tcp.Accept(server)
mut c := http2.NewConn(http2.PlainTransport(conn.fd), true)
if not http2.ServerHandshake(c):
ret
end
mut ids := Vector {} as Vector<int>
until ids.len() < 3:
ids.push(http2.AwaitAnyHeaders(c, 20))
end
mut i := ids.len() - 1
until i >= 0:
id := ids.get(i)
path := http2.HeadersGet(http2.StreamAt(c, id).headers, ":path")
mut h := http2.HeaderList {}
http2.HeadersAdd(h, ":status", "200")
_ := http2.SendHeaders(c, id, h, false)
_ := http2.SendData(c, id, compress.BufFromStr("page " + path), true)
i -= 1
end
_ := http2.AwaitStreamEnd(c, 0, 5)
http2.CloseConn(c)
end
func request(c &: http2.Conn, path: str): int:
id := http2.NextStreamId(c)
mut h := http2.HeaderList {}
http2.HeadersAdd(h, ":method", "GET")
http2.HeadersAdd(h, ":scheme", "http")
http2.HeadersAdd(h, ":path", path)
http2.HeadersAdd(h, ":authority", "127.0.0.1")
_ := http2.SendHeaders(c, id, h, true)
ret id
end
func main:
server = tcp.Bind(0)
t := spawn(serve)
conn := tcp.Dial("127.0.0.1", tcp.Port(server))
mut c := http2.NewConn(http2.PlainTransport(conn.fd), false)
if not http2.ClientHandshake(c):
println "handshake failed"
ret 1
end
mut ids := Vector {} as Vector<int>
each p in ["/a", "/b", "/c"]:
ids.push(request(c, p))
end
println "three requests sent on streams", ids.get(0), ids.get(1), ids.get(2)
each id in ids:
_ := http2.AwaitStreamEnd(c, id, 50)
s := http2.StreamAt(c, id)
println "stream", id, http2.HeadersGet(s.headers, ":status"), compress.BufToStrUnsafe(s.data)
end
println "connections used: 1, streams:", http2.StreamCount(c)
_ := http2.SendGoAway(c, http2.H2_NO_ERROR, "")
http2.CloseConn(c)
join(t)
tcp.CloseServer(server)
ret 0
endAwaitAnyHeaders on the server reads frames until one arrives for a stream whose headers are complete and returns that stream's id, or H2_POLL_ERROR when the connection fails. A request that also has a body sends more frames on the same stream, so a server that accepts bodies should remember which ids it has already seen. AwaitStreamEnd on the client reads frames, for any stream, until the one you asked about has ended; the frames of the others are kept in their streams for later. Its last argument is a limit on how many frames to read, so a broken peer cannot keep you waiting forever.
How much HPACK saves
Requests to one site repeat nearly the same headers every time. HPACK sends a header once, stores it in a table that both sides keep in step, and afterwards sends only its index. The first request below is already smaller than its HTTP/1.1 text because of the static table and the Huffman code; the second and third are about a quarter of the size, because almost everything is now in the dynamic table.
import net.http2
func request_headers(path: str): http2.HeaderList:
mut h := http2.HeaderList {}
http2.HeadersAdd(h, ":method", "GET")
http2.HeadersAdd(h, ":scheme", "https")
http2.HeadersAdd(h, ":authority", "shop.example.com")
http2.HeadersAdd(h, ":path", path)
http2.HeadersAdd(h, "user-agent", "salam-client/1.0")
http2.HeadersAdd(h, "accept", "application/json")
http2.HeadersAddSensitive(h, "authorization", "Bearer eyJhbGciOiJIUzI1NiJ9.e30.x")
ret h
end
func plain_size(h: http2.HeaderList): int:
mut n := 0
each item in h.items:
n += item.name.len() + item.value.len() + 4
end
ret n
end
func main:
mut table := http2.NewDynTable(4096)
each path in ["/cart", "/cart/items", "/checkout"]:
h := request_headers(path)
block := http2.EncodeHeaderList(table, h, true)
println path, "as HTTP/1.1 text:", plain_size(h), "bytes, HPACK:", block.len, "bytes, table entries:", http2.DynCount(table)
end
println "huffman alone, user-agent value:", "salam-client/1.0".len(), "->", http2.HuffmanEncodedLenStr("salam-client/1.0")
endThe authorization header is added with HeadersAddSensitive, so it is never put in the table and is sent in full every time. That costs a few bytes but stops an attacker who can influence other headers on the same connection from guessing the token by watching the compressed size, the attack known as CRIME.
HTTP/2 over TLS to a real server
Servers on the internet offer HTTP/2 only over TLS, and only to clients that ask for it during the TLS handshake. Set alpn to h2 in the tls config, connect with tls.Dial, and wrap the connection with TLSTransport. If the server did not pick h2, ClientHandshake fails and you should fall back to HTTP/1.1.
import net.http2
import tls
func main:
host := "www.cloudflare.com"
mut cfg := tls.NewConfig(host)
cfg.alpn = "h2"
secure := tls.Dial(host, 443, cfg)
if not tls.ConnOk(secure):
println "TLS failed:", tls.ConnError(secure)
ret 1
end
mut c := http2.NewConn(http2.TLSTransport(secure), false)
if not http2.ClientHandshake(c):
println "the server did not agree to HTTP/2"
ret 1
end
id := http2.NextStreamId(c)
mut h := http2.HeaderList {}
http2.HeadersAdd(h, ":method", "HEAD")
http2.HeadersAdd(h, ":scheme", "https")
http2.HeadersAdd(h, ":path", "/")
http2.HeadersAdd(h, ":authority", host)
_ := http2.SendHeaders(c, id, h, true)
if http2.AwaitStreamEnd(c, id, 100):
s := http2.StreamAt(c, id)
println "status:", http2.HeadersGet(s.headers, ":status")
println "server:", http2.HeadersGet(s.headers, "server")
println "body bytes:", s.data.len
end
http2.CloseConn(c)
ret 0
endIt needs network access, so it is only checked here. Run against Cloudflare, it printed:
status: 200
server: cloudflare
body bytes: 0
The body is empty because the request used HEAD. With GET, the page arrives in s.data as one buffer, after the package has already sent the window updates that flow control needs.
Types
Stream
struct Stream| Name | Type | Description |
|---|---|---|
id | int = 0 | The id; odd for the streams a client opens. |
state | int = 0 | The state, one of the stream state constants. |
send_window | int = 65535 | The sending window. |
recv_window | int = 65535 | The receiving window. |
headers | HeaderList | The headers received. |
trailers | HeaderList | The trailing headers received. |
data | compress.ByteBuf | The body received. |
got_headers | bool = false | The headers have arrived. |
got_trailers | bool = false | The trailing headers have arrived. |
end_stream | bool = false | The other side has ended the stream. |
reset | bool = false | The stream was closed with a reset frame. |
error_code | int = 0 | The reset's error code. |
live | bool = false | This slot of the table is in use. |
import net.http2
import net.tcp
import compress
mut server := tcp.Server {}
func answer():
conn := tcp.Accept(server)
mut c := http2.NewConn(http2.PlainTransport(conn.fd), true)
if not http2.ServerHandshake(c):
ret
end
id := http2.AwaitAnyHeaders(c, 20)
stream := http2.StreamAt(c, id)
mut headers := http2.HeaderList {}
http2.HeadersAdd(headers, ":status", "200")
http2.HeadersAdd(headers, "content-type", "text/plain")
_ := http2.SendHeaders(c, id, headers, false)
_ := http2.SendData(c, id, compress.BufFromStr("hello " + http2.HeadersGet(stream.headers, ":path")), false)
mut trailers := http2.HeaderList {}
http2.HeadersAdd(trailers, "x-done", "1")
_ := http2.SendTrailers(c, id, trailers)
_ := http2.AwaitStreamEnd(c, 0, 5)
http2.CloseConn(c)
end
func main:
server = tcp.Bind(0)
t := spawn(answer)
conn := tcp.Dial("127.0.0.1", tcp.Port(server))
tx := http2.PlainTransport(conn.fd)
println tx.ok, tx.kind == http2.H2_TRANSPORT_PLAIN
mut c := http2.NewConn(tx, false)
println http2.ClientHandshake(c), http2.ConnOk(c)
id := http2.NextStreamId(c)
mut headers := http2.HeaderList {}
http2.HeadersAdd(headers, ":method", "GET")
http2.HeadersAdd(headers, ":scheme", "http")
http2.HeadersAdd(headers, ":path", "/books")
http2.HeadersAdd(headers, ":authority", "127.0.0.1")
println id, http2.SendHeaders(c, id, headers, true)
println http2.AwaitStreamEnd(c, id, 20)
stream := http2.StreamAt(c, id)
println http2.HeadersGet(stream.headers, ":status"), compress.BufToStrUnsafe(stream.data), stream.got_trailers, http2.HeadersGet(stream.trailers, "x-done"), stream.end_stream
println http2.StreamCount(c) >= 1, c.remote.max_frame_size
_ := http2.SendPing(c, compress.BufFromStr("abcdefgh"))
println http2.Poll(c) >= http2.H2_POLL_CONNECTION
_ := http2.SendRstStream(c, http2.NextStreamId(c), http2.H2_CANCEL)
println http2.SendGoAway(c, http2.H2_NO_ERROR, "")
http2.CloseConn(c)
join(t)
tcp.CloseServer(server)
endStreamTable
struct StreamTable| Name | Type | Description |
|---|---|---|
items | Vector | The streams. |
The example for this item is shown with the ones above: net-http2-Conn.salam
Conn
struct Conn| Name | Type | Description |
|---|---|---|
tx | Transport | The transport underneath. |
is_server | bool = false | This side is the server. |
enc | DynTable | The HPACK table for sending. |
dec | DynTable | The HPACK table for receiving. |
local | Settings | This side's settings. |
remote | Settings | The other side's settings, after the handshake. |
next_id | int = 1 | The next stream id. |
streams | StreamTable | The streams. |
send_window | int = 65535 | The connection's sending window. |
recv_window | int = 65535 | The connection's receiving window. |
goaway | bool = false | A goaway frame arrived or was sent. |
last_error | int = 0 | The last error code. |
ok | bool = false | The connection is healthy. |
pending_stream | int = 0 | The stream whose headers block is not finished yet by a continuation frame. |
pending_block | compress.ByteBuf | The parts of that block that arrived. |
pending_end_stream | bool = false | Those headers end the stream. |
pending_trailers | bool = false | Those headers are trailing ones. |
The example for this item is shown with the ones above: net-http2-Conn.salam
Frame
struct Frame| Name | Type | Description |
|---|---|---|
kind | int = 0 | The frame type, one of the frame type constants. |
flags | int = 0 | The flags. |
stream_id | int = 0 | The stream id; zero means the whole connection. |
payload | compress.ByteBuf | The frame payload. |
ok | bool = false | The frame was read correctly. |
import net.http2
import compress
func main:
mut settings := http2.DefaultSettings()
println settings.header_table_size, settings.initial_window_size, settings.max_frame_size, settings.enable_push
frame := http2.MakeSettingsFrame(settings)
println http2.FrameTypeName(frame.kind), frame.stream_id, frame.payload.len
settings.max_frame_size = 32768
println http2.ApplySettings(settings, http2.MakeSettingsFrame(http2.DefaultSettings())), settings.max_frame_size
ack := http2.MakeSettingsAck()
println http2.FrameHasFlag(ack, http2.H2_FLAG_ACK)
win := http2.MakeWindowUpdate(3, 1024)
println http2.FrameTypeName(win.kind), http2.WindowIncrementOf(win)
rst := http2.MakeRstStream(5, http2.H2_CANCEL)
println http2.ErrorCodeOf(rst), http2.ErrorName(http2.ErrorCodeOf(rst))
away := http2.MakeGoAway(7, http2.H2_NO_ERROR, "bye")
println http2.FrameTypeName(away.kind), http2.ErrorCodeOf(away)
ping := http2.MakePing(compress.BufFromStr("12345678"), false)
println http2.FrameTypeName(ping.kind), ping.payload.len
mut data := http2.NewFrame(http2.H2_DATA, http2.H2_FLAG_END_STREAM, 1)
compress.BufPushBytes(data.payload, "hello" as void*, 5)
mut ok := true
println compress.BufToStrUnsafe(http2.DataOf(data, ok)), ok
bytes := http2.FrameEncode(data)
println bytes.len, compress.BufGet(bytes, 3)
mut head := http2.NewFrame(http2.H2_HEADERS, http2.H2_FLAG_END_HEADERS, 1)
compress.BufPush(head.payload, 130)
println http2.HeaderBlockOf(head, ok).len, ok
mut one := compress.NewByteBuf()
http2.PutSetting(one, http2.H2_SETTINGS_MAX_FRAME_SIZE, 16384)
println one.len
http2.FreeFrame(data)
println http2.H2_DATA, http2.H2_PING, http2.H2_PROTOCOL_ERROR, http2.H2_DEFAULT_FRAME_SIZE, http2.H2_DEFAULT_WINDOW, http2.H2_MAX_FRAME_LIMIT
println http2.FrameTypeName(http2.H2_PRIORITY), http2.FrameTypeName(http2.H2_RST_STREAM), http2.FrameTypeName(http2.H2_PUSH_PROMISE)
println http2.FrameTypeName(http2.H2_GOAWAY), http2.FrameTypeName(http2.H2_WINDOW_UPDATE), http2.FrameTypeName(http2.H2_CONTINUATION)
println http2.H2_SETTINGS_HEADER_TABLE_SIZE, http2.H2_SETTINGS_ENABLE_PUSH, http2.H2_SETTINGS_MAX_CONCURRENT_STREAMS, http2.H2_SETTINGS_INITIAL_WINDOW_SIZE, http2.H2_SETTINGS_MAX_HEADER_LIST_SIZE
println http2.ErrorName(http2.H2_INTERNAL_ERROR), http2.ErrorName(http2.H2_FLOW_CONTROL_ERROR), http2.ErrorName(http2.H2_SETTINGS_TIMEOUT), http2.ErrorName(http2.H2_STREAM_CLOSED)
println http2.ErrorName(http2.H2_FRAME_SIZE_ERROR), http2.ErrorName(http2.H2_REFUSED_STREAM), http2.ErrorName(http2.H2_COMPRESSION_ERROR), http2.ErrorName(http2.H2_CONNECT_ERROR)
println http2.ErrorName(http2.H2_ENHANCE_YOUR_CALM), http2.ErrorName(http2.H2_INADEQUATE_SECURITY), http2.ErrorName(http2.H2_HTTP_1_1_REQUIRED)
println http2.H2_STREAM_IDLE, http2.H2_STREAM_OPEN, http2.H2_STREAM_HALF_CLOSED_LOCAL, http2.H2_STREAM_HALF_CLOSED_REMOTE, http2.H2_STREAM_CLOSED_STATE
println http2.H2_DEFAULT_TABLE_SIZE, http2.H2_POLL_ERROR
endHeader
struct Header| Name | Type | Description |
|---|---|---|
name | str = "" | The name; in HTTP/2 always in lower case. |
value | str = "" | The value. |
sensitive | bool = false | It is sensitive and never goes into the HPACK table; for tokens and cookies. |
import net.http2
import compress
func main:
mut list := http2.HeaderList {}
http2.HeadersAdd(list, ":method", "GET")
http2.HeadersAdd(list, ":path", "/")
http2.HeadersAdd(list, "user-agent", "salam")
http2.HeadersAddSensitive(list, "authorization", "Bearer x")
println http2.HeadersCount(list), http2.HeadersGet(list, ":path"), http2.HeadersHas(list, "cookie")
mut sender := http2.NewDynTable(4096)
mut receiver := http2.NewDynTable(4096)
block := http2.EncodeHeaderList(sender, list, true)
println block.len, http2.DynCount(sender), http2.DynSize(sender)
mut ok := true
read := http2.DecodeHeaderList(receiver, block, ok)
println ok, read.items.len(), read.items[2].name, read.items[2].value, read.items[3].sensitive
block2 := http2.EncodeHeaderList(sender, list, true)
println block2.len < block.len
fixed := http2.StaticGet(2)
println fixed.name, fixed.value, http2.HPACK_STATIC_COUNT, http2.HPACK_ENTRY_OVERHEAD
dyn := http2.DynGet(receiver, 1)
println dyn.name
mut exact := false
println http2.TableFind(receiver, ":method", "GET", exact), exact
println http2.TableGet(receiver, 62, ok).name, ok
mut b := compress.NewByteBuf()
http2.EncodeTableSizeUpdate(b, sender, 256)
http2.DynSetMaxSize(receiver, 256)
println b.len, sender.max_size, receiver.max_size
mut b2 := compress.NewByteBuf()
http2.EncodeHeader(b2, sender, http2.NewHeader("x-id", "7"), false)
http2.DynInsert(receiver, http2.NewSensitiveHeader("k", "v"))
println b2.len, http2.DynCount(receiver)
endHeaderList
struct HeaderList| Name | Type | Description |
|---|---|---|
items | Vector | The headers. |
The example for this item is shown with the ones above: net-http2-Hpack.salam
DynTable
struct DynTable| Name | Type | Description |
|---|---|---|
items | Vector | The entries. |
head | int = 0 | The position of the newest entry in the ring. |
size | int = 0 | The current size in bytes, with the overhead. |
max_size | int = 4096 | The largest size; older entries are pushed out. |
The example for this item is shown with the ones above: net-http2-Hpack.salam
HufTables
struct HufTables| Name | Type | Description |
|---|---|---|
counts | Vector | The number of codes of each length. |
first | Vector | The first code of each length. |
syms | Vector | The symbols in code order. |
ready | bool = false | The tables are built. |
import net.http2
import encoding
import compress
func main:
b := http2.HuffmanEncodeStr("www.example.com")
println encoding.HexEncode(compress.BufToStrUnsafe(b))
println http2.HuffmanEncodedLenStr("www.example.com"), "www.example.com".len()
mut ok := true
println compress.BufToStrUnsafe(http2.HuffmanDecodeBuf(b, ok)), ok
text := compress.BufFromStr("no-cache")
println http2.HuffmanEncodedLen(text.data, text.len)
mut out := compress.NewByteBuf()
compress.BufPush(out, 0)
http2.HuffmanEncode(out, text.data, text.len)
println compress.BufToStrUnsafe(http2.HuffmanDecode(out, 1, out.len - 1, ok)), ok
endTlsBox
struct TlsBox| Name | Type | Description |
|---|---|---|
items | Vector | The connections. |
import net.http2
import net.tcp
func main:
secure := tcp.DialTLS("example.com", 443)
mut c := http2.NewConn(http2.TLSTransport(secure), false)
println http2.ClientHandshake(c), c.tx.kind == http2.H2_TRANSPORT_TLS
http2.CloseConn(c)
endSettings
struct Settings| Name | Type | Description |
|---|---|---|
header_table_size | int = 4096 | The HPACK table size. |
enable_push | int = 1 | Server push; 1 or 0. |
max_concurrent_streams | int = -1 | The most streams at once; -1 means no limit. |
initial_window_size | int = 65535 | The starting window. |
max_frame_size | int = 16384 | The largest frame size. |
max_header_list_size | int = -1 | The largest header size; -1 means no limit. |
The example for this item is shown with the ones above: net-http2-Frame.salam
Transport
struct Transport| Name | Type | Description |
|---|---|---|
kind | int = 0 | The transport type. |
fd | i64 = -1 | The socket descriptor. |
sec_id | int = -1 | The number of the TLS connection in the internal holder. |
ok | bool = false | The transport is healthy. |
The example for this item is shown with the ones above: net-http2-Conn.salam
Constants and variables
H2_POLL_ERROR
const H2_POLL_ERROR: i32 = -1Poll: an error, or the connection closed.The example for this item is shown with the ones above: net-http2-Frame.salam
H2_POLL_CONNECTION
const H2_POLL_CONNECTION: i32 = 0Poll: a frame for the whole connection arrived. A positive number is the id of the stream whose frame arrived.The example for this item is shown with the ones above: net-http2-Conn.salam
H2_PREFACE
const H2_PREFACE: str = "PRI * HTTP/2.0
SM
"import net.http2
import net.tcp
import compress
mut server := tcp.Server {}
func answer():
conn := tcp.Accept(server)
mut tx := http2.PlainTransport(conn.fd)
println "server preface:", http2.ReadPreface(tx)
frame := http2.ReadFrame(tx, http2.H2_DEFAULT_FRAME_SIZE)
println "server frame:", frame.ok, http2.FrameTypeName(frame.kind), frame.stream_id, compress.BufToStrUnsafe(frame.payload)
http2.CloseTransport(tx)
end
func main:
server = tcp.Bind(0)
t := spawn(answer)
conn := tcp.Dial("127.0.0.1", tcp.Port(server))
mut tx := http2.PlainTransport(conn.fd)
_ := http2.WritePreface(tx)
mut data := http2.NewFrame(http2.H2_DATA, 0, 3)
compress.BufPushBuf(data.payload, compress.BufFromStr("hi"))
_ := http2.WriteFrame(tx, data)
join(t)
http2.CloseTransport(tx)
tcp.CloseServer(server)
println http2.H2_PREFACE.len()
endH2_DATA
const H2_DATA: i32 = 0The example for this item is shown with the ones above: net-http2-Frame.salam
H2_HEADERS
const H2_HEADERS: i32 = 1The example for this item is shown with the ones above: net-http2-Frame.salam
H2_PRIORITY
const H2_PRIORITY: i32 = 2The example for this item is shown with the ones above: net-http2-Frame.salam
H2_RST_STREAM
const H2_RST_STREAM: i32 = 3The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS
const H2_SETTINGS: i32 = 4The example for this item is shown with the ones above: net-http2-Frame.salam
H2_PUSH_PROMISE
const H2_PUSH_PROMISE: i32 = 5The example for this item is shown with the ones above: net-http2-Frame.salam
H2_PING
const H2_PING: i32 = 6The example for this item is shown with the ones above: net-http2-Frame.salam
H2_GOAWAY
const H2_GOAWAY: i32 = 7The example for this item is shown with the ones above: net-http2-Frame.salam
H2_WINDOW_UPDATE
const H2_WINDOW_UPDATE: i32 = 8The example for this item is shown with the ones above: net-http2-Frame.salam
H2_CONTINUATION
const H2_CONTINUATION: i32 = 9The example for this item is shown with the ones above: net-http2-Frame.salam
The frame flags H2_FLAG_…
H2_FLAG_END_STREAM and H2_FLAG_ACK are both 1, one for a data or headers frame and the other for settings and ping. Check them with FrameHasFlag.| Name | Value |
|---|---|
H2_FLAG_END_STREAM | 1 |
H2_FLAG_ACK | 1 |
H2_FLAG_END_HEADERS | 4 |
H2_FLAG_PADDED | 8 |
H2_FLAG_PRIORITY | 32 |
The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS_HEADER_TABLE_SIZE
const H2_SETTINGS_HEADER_TABLE_SIZE: i32 = 1The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS_ENABLE_PUSH
const H2_SETTINGS_ENABLE_PUSH: i32 = 2The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS_MAX_CONCURRENT_STREAMS
const H2_SETTINGS_MAX_CONCURRENT_STREAMS: i32 = 3The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS_INITIAL_WINDOW_SIZE
const H2_SETTINGS_INITIAL_WINDOW_SIZE: i32 = 4The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS_MAX_FRAME_SIZE
const H2_SETTINGS_MAX_FRAME_SIZE: i32 = 5The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS_MAX_HEADER_LIST_SIZE
const H2_SETTINGS_MAX_HEADER_LIST_SIZE: i32 = 6The example for this item is shown with the ones above: net-http2-Frame.salam
H2_NO_ERROR
const H2_NO_ERROR: i32 = 0The example for this item is shown with the ones above: net-http2-Frame.salam
H2_PROTOCOL_ERROR
const H2_PROTOCOL_ERROR: i32 = 1The example for this item is shown with the ones above: net-http2-Frame.salam
H2_INTERNAL_ERROR
const H2_INTERNAL_ERROR: i32 = 2The example for this item is shown with the ones above: net-http2-Frame.salam
H2_FLOW_CONTROL_ERROR
const H2_FLOW_CONTROL_ERROR: i32 = 3The example for this item is shown with the ones above: net-http2-Frame.salam
H2_SETTINGS_TIMEOUT
const H2_SETTINGS_TIMEOUT: i32 = 4The example for this item is shown with the ones above: net-http2-Frame.salam
H2_STREAM_CLOSED
const H2_STREAM_CLOSED: i32 = 5The example for this item is shown with the ones above: net-http2-Frame.salam
H2_FRAME_SIZE_ERROR
const H2_FRAME_SIZE_ERROR: i32 = 6The example for this item is shown with the ones above: net-http2-Frame.salam
H2_REFUSED_STREAM
const H2_REFUSED_STREAM: i32 = 7The example for this item is shown with the ones above: net-http2-Frame.salam
H2_CANCEL
const H2_CANCEL: i32 = 8The example for this item is shown with the ones above: net-http2-Frame.salam
H2_COMPRESSION_ERROR
const H2_COMPRESSION_ERROR: i32 = 9The example for this item is shown with the ones above: net-http2-Frame.salam
H2_CONNECT_ERROR
const H2_CONNECT_ERROR: i32 = 10The example for this item is shown with the ones above: net-http2-Frame.salam
H2_ENHANCE_YOUR_CALM
const H2_ENHANCE_YOUR_CALM: i32 = 11The example for this item is shown with the ones above: net-http2-Frame.salam
H2_INADEQUATE_SECURITY
const H2_INADEQUATE_SECURITY: i32 = 12The example for this item is shown with the ones above: net-http2-Frame.salam
H2_HTTP_1_1_REQUIRED
const H2_HTTP_1_1_REQUIRED: i32 = 13The example for this item is shown with the ones above: net-http2-Frame.salam
H2_DEFAULT_FRAME_SIZE
const H2_DEFAULT_FRAME_SIZE: i32 = 16384The example for this item is shown with the ones above: net-http2-Frame.salam
H2_DEFAULT_WINDOW
const H2_DEFAULT_WINDOW: i32 = 65535The example for this item is shown with the ones above: net-http2-Frame.salam
H2_DEFAULT_TABLE_SIZE
const H2_DEFAULT_TABLE_SIZE: i32 = 4096The example for this item is shown with the ones above: net-http2-Frame.salam
H2_MAX_FRAME_LIMIT
const H2_MAX_FRAME_LIMIT: i32 = 16777215The example for this item is shown with the ones above: net-http2-Frame.salam
H2_STREAM_IDLE
const H2_STREAM_IDLE: i32 = 0The example for this item is shown with the ones above: net-http2-Frame.salam
H2_STREAM_OPEN
const H2_STREAM_OPEN: i32 = 1The example for this item is shown with the ones above: net-http2-Frame.salam
H2_STREAM_HALF_CLOSED_LOCAL
const H2_STREAM_HALF_CLOSED_LOCAL: i32 = 2The example for this item is shown with the ones above: net-http2-Frame.salam
H2_STREAM_HALF_CLOSED_REMOTE
const H2_STREAM_HALF_CLOSED_REMOTE: i32 = 3The example for this item is shown with the ones above: net-http2-Frame.salam
H2_STREAM_CLOSED_STATE
const H2_STREAM_CLOSED_STATE: i32 = 4The example for this item is shown with the ones above: net-http2-Frame.salam
HPACK_STATIC_COUNT
const HPACK_STATIC_COUNT: i32 = 61The example for this item is shown with the ones above: net-http2-Hpack.salam
HPACK_ENTRY_OVERHEAD
const HPACK_ENTRY_OVERHEAD: i32 = 32The example for this item is shown with the ones above: net-http2-Hpack.salam
H2_TRANSPORT_PLAIN
const H2_TRANSPORT_PLAIN: i32 = 0The example for this item is shown with the ones above: net-http2-Conn.salam
H2_TRANSPORT_TLS
const H2_TRANSPORT_TLS: i32 = 1The example for this item is shown with the ones above: net-http2-TLS.salam
Functions
NewConn
func NewConn(t: Transport, is_server: bool): ConnThe example for this item is shown with the ones above: net-http2-Conn.salam
ClientHandshake
func ClientHandshake(c &: Conn): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
ServerHandshake
func ServerHandshake(c &: Conn): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
NextStreamId
func NextStreamId(c &: Conn): intThe example for this item is shown with the ones above: net-http2-Conn.salam
StreamAt
func StreamAt(c: Conn, id: int): StreamThe example for this item is shown with the ones above: net-http2-Conn.salam
StreamCount
func StreamCount(c: Conn): intThe example for this item is shown with the ones above: net-http2-Conn.salam
ConnOk
func ConnOk(c: Conn): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
SendHeaders
func SendHeaders(c &: Conn, stream_id: int, hl: HeaderList, end_stream: bool): booltrue so the stream ends right here.The example for this item is shown with the ones above: net-http2-Conn.salam
SendTrailers
func SendTrailers(c &: Conn, stream_id: int, hl: HeaderList): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
SendData
func SendData(c &: Conn, stream_id: int, body: compress.ByteBuf, end_stream: bool): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
SendRstStream
func SendRstStream(c &: Conn, stream_id: int, error_code: int): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
SendGoAway
func SendGoAway(c &: Conn, error_code: int, debug: str): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
SendPing
func SendPing(c &: Conn, payload: compress.ByteBuf): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
Poll
func Poll(c &: Conn): intThe example for this item is shown with the ones above: net-http2-Conn.salam
AwaitStreamEnd
func AwaitStreamEnd(c &: Conn, stream_id: int, max_frames: int): boolThe example for this item is shown with the ones above: net-http2-Conn.salam
AwaitAnyHeaders
func AwaitAnyHeaders(c &: Conn, max_frames: int): intThe example for this item is shown with the ones above: net-http2-Conn.salam
CloseConn
func CloseConn(c &: Conn)The example for this item is shown with the ones above: net-http2-Conn.salam
HuffmanEncodedLen
func HuffmanEncodedLen(p: void*, n: int): intThe example for this item is shown with the ones above: net-http2-Huffman.salam
HuffmanEncodedLenStr
func HuffmanEncodedLenStr(s: str): intThe example for this item is shown with the ones above: net-http2-Huffman.salam
HuffmanEncode
func HuffmanEncode(out &: compress.ByteBuf, p: void*, n: int)The example for this item is shown with the ones above: net-http2-Huffman.salam
HuffmanEncodeStr
func HuffmanEncodeStr(s: str): compress.ByteBufThe example for this item is shown with the ones above: net-http2-Huffman.salam
HuffmanDecode
func HuffmanDecode(src: compress.ByteBuf, from: int, len: int, ok &: bool): compress.ByteBufok becomes false.The example for this item is shown with the ones above: net-http2-Huffman.salam
HuffmanDecodeBuf
func HuffmanDecodeBuf(src: compress.ByteBuf, ok &: bool): compress.ByteBufThe example for this item is shown with the ones above: net-http2-Huffman.salam
FrameTypeName
func FrameTypeName(kind: int): strDATA.The example for this item is shown with the ones above: net-http2-Frame.salam
ErrorName
func ErrorName(code: int): strCANCEL.The example for this item is shown with the ones above: net-http2-Frame.salam
NewHeader
func NewHeader(name: str, value: str): HeaderThe example for this item is shown with the ones above: net-http2-Hpack.salam
NewSensitiveHeader
func NewSensitiveHeader(name: str, value: str): HeaderThe example for this item is shown with the ones above: net-http2-Hpack.salam
HeadersAdd
func HeadersAdd(hl &: HeaderList, name: str, value: str)The example for this item is shown with the ones above: net-http2-Hpack.salam
HeadersAddSensitive
func HeadersAddSensitive(hl &: HeaderList, name: str, value: str)The example for this item is shown with the ones above: net-http2-Hpack.salam
HeadersGet
func HeadersGet(hl: HeaderList, name: str): strThe example for this item is shown with the ones above: net-http2-Hpack.salam
HeadersHas
func HeadersHas(hl: HeaderList, name: str): boolThe example for this item is shown with the ones above: net-http2-Hpack.salam
HeadersCount
func HeadersCount(hl: HeaderList): intThe example for this item is shown with the ones above: net-http2-Hpack.salam
DefaultSettings
func DefaultSettings(): SettingsThe example for this item is shown with the ones above: net-http2-Frame.salam
NewDynTable
func NewDynTable(max_size: int): DynTableThe example for this item is shown with the ones above: net-http2-Hpack.salam
DynCount
func DynCount(t: DynTable): intThe example for this item is shown with the ones above: net-http2-Hpack.salam
DynSize
func DynSize(t: DynTable): intThe example for this item is shown with the ones above: net-http2-Hpack.salam
DynGet
func DynGet(t: DynTable, index: int): HeaderThe example for this item is shown with the ones above: net-http2-Hpack.salam
DynInsert
func DynInsert(t &: DynTable, h: Header)The example for this item is shown with the ones above: net-http2-Hpack.salam
DynSetMaxSize
func DynSetMaxSize(t &: DynTable, max_size: int)The example for this item is shown with the ones above: net-http2-Hpack.salam
StaticGet
func StaticGet(index: int): Header:method GET.The example for this item is shown with the ones above: net-http2-Hpack.salam
TableGet
func TableGet(t: DynTable, index: int, ok &: bool): HeaderThe example for this item is shown with the ones above: net-http2-Hpack.salam
TableFind
func TableFind(t: DynTable, name: str, value: str, exact &: bool): intexact becomes false. If there is none, zero.The example for this item is shown with the ones above: net-http2-Hpack.salam
EncodeHeader
func EncodeHeader(out &: compress.ByteBuf, t &: DynTable, h: Header, use_huffman: bool)The example for this item is shown with the ones above: net-http2-Hpack.salam
EncodeHeaderList
func EncodeHeaderList(t &: DynTable, hl: HeaderList, use_huffman: bool): compress.ByteBufThe example for this item is shown with the ones above: net-http2-Hpack.salam
EncodeTableSizeUpdate
func EncodeTableSizeUpdate(out &: compress.ByteBuf, t &: DynTable, new_size: int)The example for this item is shown with the ones above: net-http2-Hpack.salam
DecodeHeaderList
func DecodeHeaderList(t &: DynTable, block: compress.ByteBuf, ok &: bool): HeaderListThe example for this item is shown with the ones above: net-http2-Hpack.salam
PlainTransport
func PlainTransport(fd: i64): TransportThe example for this item is shown with the ones above: net-http2-Conn.salam
TLSTransport
func TLSTransport(c: tls.Conn): TransportThe example for this item is shown with the ones above: net-http2-TLS.salam
CloseTransport
func CloseTransport(t &: Transport)The example for this item is shown with the ones above: net-http2-Transport.salam
NewFrame
func NewFrame(kind: int, flags: int, stream_id: int): FrameThe example for this item is shown with the ones above: net-http2-Frame.salam
FreeFrame
func FreeFrame(f &: Frame)The example for this item is shown with the ones above: net-http2-Frame.salam
FrameHasFlag
func FrameHasFlag(f: Frame, flag: int): boolThe example for this item is shown with the ones above: net-http2-Frame.salam
FrameEncode
func FrameEncode(f: Frame): compress.ByteBufThe example for this item is shown with the ones above: net-http2-Frame.salam
WriteFrame
func WriteFrame(t &: Transport, f: Frame): boolThe example for this item is shown with the ones above: net-http2-Transport.salam
ReadFrame
func ReadFrame(t &: Transport, max_frame_size: int): FrameThe example for this item is shown with the ones above: net-http2-Transport.salam
WritePreface
func WritePreface(t &: Transport): boolThe example for this item is shown with the ones above: net-http2-Transport.salam
ReadPreface
func ReadPreface(t &: Transport): boolThe example for this item is shown with the ones above: net-http2-Transport.salam
HeaderBlockOf
func HeaderBlockOf(f: Frame, ok &: bool): compress.ByteBufThe example for this item is shown with the ones above: net-http2-Frame.salam
DataOf
func DataOf(f: Frame, ok &: bool): compress.ByteBufThe example for this item is shown with the ones above: net-http2-Frame.salam
MakeSettingsFrame
func MakeSettingsFrame(s: Settings): FrameThe example for this item is shown with the ones above: net-http2-Frame.salam
MakeSettingsAck
func MakeSettingsAck(): FrameThe example for this item is shown with the ones above: net-http2-Frame.salam
ApplySettings
func ApplySettings(s &: Settings, f: Frame): boolThe example for this item is shown with the ones above: net-http2-Frame.salam
MakeWindowUpdate
func MakeWindowUpdate(stream_id: int, increment: int): FrameThe example for this item is shown with the ones above: net-http2-Frame.salam
WindowIncrementOf
func WindowIncrementOf(f: Frame): intThe example for this item is shown with the ones above: net-http2-Frame.salam
MakeRstStream
func MakeRstStream(stream_id: int, error_code: int): FrameThe example for this item is shown with the ones above: net-http2-Frame.salam
ErrorCodeOf
func ErrorCodeOf(f: Frame): intThe example for this item is shown with the ones above: net-http2-Frame.salam
MakeGoAway
func MakeGoAway(last_stream_id: int, error_code: int, debug: str): FrameThe example for this item is shown with the ones above: net-http2-Frame.salam
MakePing
func MakePing(payload: compress.ByteBuf, ack: bool): FrameThe example for this item is shown with the ones above: net-http2-Frame.salam
PutSetting
func PutSetting(out &: compress.ByteBuf, id: int, v: int)The example for this item is shown with the ones above: net-http2-Frame.salam