Current section
Files
Jump to
Current section
Files
lib/connection/settings.ex
defmodule Kadabra.Connection.Settings do
@moduledoc false
@default_header_table_size 4096
@default_initial_window_size round(:math.pow(2, 16) - 1)
@default_max_frame_size round(:math.pow(2, 14))
defstruct enable_push: true,
header_table_size: @default_header_table_size,
initial_window_size: @default_initial_window_size,
max_concurrent_streams: :infinite,
max_frame_size: @default_max_frame_size,
max_header_list_size: nil
alias Kadabra.Error
@type t :: %__MODULE__{
header_table_size: non_neg_integer,
enable_push: boolean,
max_concurrent_streams: non_neg_integer | :infinite,
initial_window_size: non_neg_integer,
max_frame_size: non_neg_integer,
max_header_list_size: non_neg_integer
}
@table_header_size 0x1
@enable_push 0x2
@max_concurrent_streams 0x3
@initial_window_size 0x4
@max_frame_size 0x5
@max_header_list_size 0x6
@max_initial_window_size round(:math.pow(2, 31) - 1)
@max_max_frame_size round(:math.pow(2, 24) - 1)
def default do
%__MODULE__{}
end
def fastest do
%__MODULE__{
initial_window_size: @max_initial_window_size,
max_frame_size: @max_max_frame_size
}
end
@doc ~S"""
Puts setting value, returning an error if present.
## Examples
iex> s = %Kadabra.Connection.Settings{}
iex> enable_push = 0x2
iex> Kadabra.Connection.Settings.put(s, enable_push, 1)
{:ok, %Kadabra.Connection.Settings{enable_push: true}}
iex> Kadabra.Connection.Settings.put(s, enable_push, :bad)
{:error, Kadabra.Error.protocol_error, s}
iex> s = %Kadabra.Connection.Settings{}
iex> init_window_size = 0x4
iex> Kadabra.Connection.Settings.put(s, init_window_size, 70_000)
{:ok, %Kadabra.Connection.Settings{initial_window_size: 70_000}}
iex> Kadabra.Connection.Settings.put(s, init_window_size, 5_000_000_000)
{:error, Kadabra.Error.flow_control_error, s}
iex> s = %Kadabra.Connection.Settings{}
iex> max_frame_size = 0x5
iex> Kadabra.Connection.Settings.put(s, max_frame_size, 20_000)
{:ok, %Kadabra.Connection.Settings{max_frame_size: 20_000}}
iex> Kadabra.Connection.Settings.put(s, max_frame_size, 20_000_000)
{:error, Kadabra.Error.protocol_error, s}
iex> Kadabra.Connection.Settings.put(s, max_frame_size, 2_000)
{:error, Kadabra.Error.protocol_error, s}
"""
@spec put(t, non_neg_integer, term) :: {:ok, t} | {:error, binary, t}
def put(settings, @table_header_size, value) do
{:ok, %{settings | header_table_size: value}}
end
def put(settings, @enable_push, 1) do
{:ok, %{settings | enable_push: true}}
end
def put(settings, @enable_push, 0) do
{:ok, %{settings | enable_push: false}}
end
def put(settings, @enable_push, _else) do
{:error, Error.protocol_error(), settings}
end
def put(settings, @max_concurrent_streams, value) do
{:ok, %{settings | max_concurrent_streams: value}}
end
def put(settings, @initial_window_size, value)
when value > @max_initial_window_size do
{:error, Error.flow_control_error(), settings}
end
def put(settings, @initial_window_size, value) do
{:ok, %{settings | initial_window_size: value}}
end
def put(settings, @max_frame_size, value)
when value < @default_max_frame_size or value > @max_max_frame_size do
{:error, Error.protocol_error(), settings}
end
def put(settings, @max_frame_size, value) do
{:ok, %{settings | max_frame_size: value}}
end
def put(settings, @max_header_list_size, value) do
{:ok, %{settings | max_header_list_size: value}}
end
def put(settings, _else, _value), do: {:ok, settings}
def merge(nil, new_settings), do: new_settings
def merge(old_settings, new_settings) do
Map.merge(old_settings, new_settings, fn k, v1, v2 ->
cond do
k == :__struct__ -> v1
v1 == nil -> v2
v2 == nil -> v1
true -> v2
end
end)
end
end