Packages
bandit
1.7.0
1.12.1
1.12.0
1.11.1
1.11.0
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
retired
1.9.0
1.8.0
1.7.0
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.0
1.2.3
1.2.2
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
1.0.0-pre.18
1.0.0-pre.17
1.0.0-pre.16
1.0.0-pre.15
1.0.0-pre.14
1.0.0-pre.13
1.0.0-pre.12
1.0.0-pre.11
1.0.0-pre.10
1.0.0-pre.9
1.0.0-pre.8
1.0.0-pre.7
1.0.0-pre.6
1.0.0-pre.5
1.0.0-pre.4
1.0.0-pre.3
1.0.0-pre.2
1.0.0-pre.1
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.2.3
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
A pure-Elixir HTTP server built for Plug & WebSock apps
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/bandit/http2/stream_collection.ex
defmodule Bandit.HTTP2.StreamCollection do
@moduledoc false
# Represents a collection of stream IDs and what process IDs are running them. An instance of
# this struct is contained within each `Bandit.HTTP2.Connection` struct and is responsible for
# encapsulating the data about the streams which are currently active within the connection.
#
# This collection has a number of useful properties:
#
# * Process IDs are accessible by stream id
# * Process IDs are deletable by themselves (ie: deletion is via PID)
# * The collection is able to determine if a stream not currently contained in this collection
# represents a previously seen stream (in which case it is considered to be in a 'closed'
# state), or if it is a stream ID of a stream that has yet to be created
require Integer
defstruct last_stream_id: 0,
stream_count: 0,
id_to_pid: %{},
pid_to_id: %{}
@typedoc "A map from stream id to pid"
@type t :: %__MODULE__{
last_stream_id: Bandit.HTTP2.Stream.stream_id(),
stream_count: non_neg_integer(),
id_to_pid: %{Bandit.HTTP2.Stream.stream_id() => pid()},
pid_to_id: %{pid() => Bandit.HTTP2.Stream.stream_id()}
}
@spec get_pids(t()) :: [pid()]
def get_pids(collection), do: Map.values(collection.id_to_pid)
@spec get_pid(t(), Bandit.HTTP2.Stream.stream_id()) :: pid() | :new | :closed | :invalid
def get_pid(_collection, stream_id) when Integer.is_even(stream_id), do: :invalid
def get_pid(collection, stream_id) when stream_id > collection.last_stream_id, do: :new
def get_pid(collection, stream_id) do
case Map.get(collection.id_to_pid, stream_id) do
pid when is_pid(pid) -> pid
nil -> :closed
end
end
@spec insert(t(), Bandit.HTTP2.Stream.stream_id(), pid()) :: t()
def insert(collection, stream_id, pid) do
%__MODULE__{
last_stream_id: stream_id,
stream_count: collection.stream_count + 1,
id_to_pid: Map.put(collection.id_to_pid, stream_id, pid),
pid_to_id: Map.put(collection.pid_to_id, pid, stream_id)
}
end
# Dialyzer insists on the atom() here even though it doesn't make sense
@spec delete(t(), pid()) :: t() | atom()
def delete(collection, pid) do
case Map.pop(collection.pid_to_id, pid) do
{nil, _} ->
collection
{stream_id, new_pid_to_id} ->
%{
collection
| id_to_pid: Map.delete(collection.id_to_pid, stream_id),
pid_to_id: new_pid_to_id
}
end
end
@spec stream_count(t()) :: non_neg_integer()
def stream_count(collection), do: collection.stream_count
@spec last_stream_id(t()) :: Bandit.HTTP2.Stream.stream_id()
def last_stream_id(collection), do: collection.last_stream_id
end