Packages
ace
0.11.0
0.19.0
0.18.10
0.18.9
0.18.8
0.18.7
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.1
0.17.0
0.16.8
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
retired
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
retired
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
HTTP web server and client, supports http1 and http2
Current section
Files
Jump to
Current section
Files
lib/ace/http2/frame.ex
defmodule Ace.HTTP2.Frame do
@moduledoc """
**Basic protocol unit of HTTP/2.**
All frames begin with a fixed 9-octet header followed by a variable-
length payload.
```txt
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
```
"""
@data 0
@headers 1
@priority 2
@rst_stream 3
@settings 4
@push_promise 5
@ping 6
@go_away 7
@window_update 8
@continuation 9
@doc """
Read the next available frame.
"""
def parse_from_buffer(<<length::24, _::binary>>, max_length: max_length)
when length > max_length
do
{:error, {:frame_size_error, "Frame greater than max allowed: (#{length} >= #{max_length})"}}
end
def parse_from_buffer(
<<
length::24,
type::8,
flags::bits-size(8),
_::1,
stream_id::31,
payload::binary-size(length),
rest::binary
>>, max_length: max_length)
when length <= max_length
do
{:ok, {{type, flags, stream_id, payload}, rest}}
end
def parse_from_buffer(buffer, max_length: _) when is_binary(buffer) do
{:ok, {nil, buffer}}
end
def decode(parsed_frame)
def decode(frame = {@data, _, _, _}), do: __MODULE__.Data.decode(frame)
def decode(frame = {@headers, _, _, _}), do: __MODULE__.Headers.decode(frame)
def decode(frame = {@priority, _, _, _}), do: __MODULE__.Priority.decode(frame)
def decode(frame = {@rst_stream, _, _, _}), do: __MODULE__.RstStream.decode(frame)
def decode(frame = {@settings, _, _, _}), do: __MODULE__.Settings.decode(frame)
def decode(frame = {@push_promise, _, _, _}), do: __MODULE__.PushPromise.decode(frame)
def decode(frame = {@ping, _, _, _}), do: __MODULE__.Ping.decode(frame)
def decode(frame = {@go_away, _, _, _}), do: __MODULE__.GoAway.decode(frame)
def decode(frame = {@window_update, _, _, _}), do: __MODULE__.WindowUpdate.decode(frame)
def decode(frame = {@continuation, _, _, _}), do: __MODULE__.Continuation.decode(frame)
def decode({type, _, _, _}), do: {:error, {:unknown_frame_type, type}}
@doc """
Transform HTTP2 frame to binary that can be transmitted over connection
"""
def serialize(http2_frame)
def serialize(frame = %__MODULE__.Data{}), do: __MODULE__.Data.serialize(frame)
def serialize(frame = %__MODULE__.Headers{}), do: __MODULE__.Headers.serialize(frame)
def serialize(frame = %__MODULE__.Priority{}), do: __MODULE__.Priority.serialize(frame)
def serialize(frame = %__MODULE__.RstStream{}), do: __MODULE__.RstStream.serialize(frame)
def serialize(frame = %__MODULE__.Settings{}), do: __MODULE__.Settings.serialize(frame)
def serialize(frame = %__MODULE__.PushPromise{}), do: __MODULE__.PushPromise.serialize(frame)
def serialize(frame = %__MODULE__.Ping{}), do: __MODULE__.Ping.serialize(frame)
def serialize(frame = %__MODULE__.GoAway{}), do: __MODULE__.GoAway.serialize(frame)
def serialize(frame = %__MODULE__.WindowUpdate{}), do: __MODULE__.WindowUpdate.serialize(frame)
def serialize(frame = %__MODULE__.Continuation{}), do: __MODULE__.Continuation.serialize(frame)
@doc """
Add padding to a frames data
"""
def pad_data(data, optional_pad_length)
def pad_data(data, nil) do
data
end
def pad_data(data, pad_length) when pad_length < 256 do
bit_pad_length = pad_length * 8
<<pad_length, data::binary, 0::size(bit_pad_length)>>
end
@doc """
Remove the padding from the payload of a frame
"""
def remove_padding(<<pad_length, rest::binary>>) do
rest_length = :erlang.iolist_size(rest)
data_length = rest_length - pad_length
bit_pad_length = pad_length * 8
<<data::binary-size(data_length), 0::size(bit_pad_length)>> = rest
data
end
end