Packages
bandit
0.5.4
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/websocket/handler.ex
defmodule Bandit.WebSocket.Handler do
@moduledoc false
# A WebSocket handler conforming to RFC6455. As a Handler, this works with raw
# ThousandIsland Sockets and supports HTTP/1.1-sourced WebSocket connections
use ThousandIsland.Handler
alias Bandit.WebSocket.{Connection, Frame}
@impl ThousandIsland.Handler
def handle_connection(socket, state) do
connection = Connection.init(state.sock)
Connection.handle_connection(state.conn, socket, connection)
|> case do
{:continue, connection} -> {:continue, update_state(state, connection)}
{:continue, connection, timeout} -> {:continue, update_state(state, connection), timeout}
{:close, _} -> {:close, state}
end
end
defp update_state(state, connection) do
state
|> Map.drop([:conn, :plug])
|> Map.put(:connection, connection)
|> Map.put(:buffer, <<>>)
end
@impl ThousandIsland.Handler
def handle_data(data, socket, state) do
(state.buffer <> data)
|> Stream.unfold(&Frame.deserialize(&1))
|> Enum.reduce_while({:continue, state}, fn
{:ok, frame}, {:continue, state} ->
case Connection.handle_frame(frame, socket, state.connection) do
{:continue, connection} ->
{:cont, {:continue, %{state | connection: connection, buffer: <<>>}}}
{:close, connection} ->
{:halt, {:close, %{state | connection: connection, buffer: <<>>}}}
{:error, reason, connection} ->
{:halt, {:error, reason, %{state | connection: connection, buffer: <<>>}}}
end
{:more, rest}, {:continue, state} ->
{:halt, {:continue, %{state | buffer: rest}}}
{:error, message}, {:continue, state} ->
{:halt, {:error, message, state}}
end)
end
@impl ThousandIsland.Handler
def handle_close(socket, %{connection: connection}),
do: Connection.handle_close(socket, connection)
def handle_close(_socket, _state), do: :ok
@impl ThousandIsland.Handler
def handle_shutdown(socket, state), do: Connection.handle_shutdown(socket, state.connection)
@impl ThousandIsland.Handler
def handle_error(reason, socket, state),
do: Connection.handle_error(reason, socket, state.connection)
@impl ThousandIsland.Handler
def handle_timeout(socket, state), do: Connection.handle_timeout(socket, state.connection)
def handle_info({:plug_conn, :sent}, {socket, state}),
do: {:noreply, {socket, state}, socket.read_timeout}
def handle_info({:EXIT, _pid, :normal}, state), do: {:noreply, state}
def handle_info(msg, {socket, state}) do
case Connection.handle_info(msg, socket, state.connection) do
{:continue, connection_state} ->
{:noreply, {socket, %{state | connection: connection_state}}, socket.read_timeout}
{:error, reason, connection_state} ->
{:stop, reason, {socket, %{state | connection: connection_state}}}
end
end
end