Packages
glisten
0.8.2
9.0.1
9.0.0
9.0.0-rc1
8.0.3
8.0.2
8.0.1
8.0.0
8.0.0-rc1
7.0.1
7.0.0
6.0.0
5.0.0
4.0.0
3.0.0
2.0.0
1.0.0
0.11.0
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.0
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.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
a shiny Gleam TCP/TLS server
Current section
Files
Jump to
Current section
Files
src/glisten@handler.erl
-module(glisten@handler).
-compile([no_auto_import, nowarn_unused_vars]).
-export([start/1, func/1]).
-export_type([handler_message/0, loop_state/1, handler/1]).
-type handler_message() :: close |
ready |
{receive_message, bitstring()} |
{send_message, gleam@bit_builder:bit_builder()} |
{ssl, gleam@otp@port:port_(), bitstring()} |
ssl_closed |
{tcp, gleam@otp@port:port_(), bitstring()} |
tcp_closed.
-type loop_state(HEC) :: {loop_state,
{ok, {{integer(), integer(), integer(), integer()}, integer()}} |
{error, nil},
glisten@socket:socket(),
gleam@erlang@process:subject(handler_message()),
glisten@socket@transport:transport(),
HEC}.
-type handler(HED) :: {handler,
glisten@socket:socket(),
HED,
fun((handler_message(), loop_state(HED)) -> gleam@otp@actor:next(handler_message(), loop_state(HED))),
gleam@option:option(fun((gleam@erlang@process:subject(handler_message())) -> nil)),
gleam@option:option(fun((gleam@erlang@process:subject(handler_message())) -> nil)),
glisten@socket@transport:transport()}.
-spec start(handler(any())) -> {ok,
gleam@erlang@process:subject(handler_message())} |
{error, gleam@otp@actor:start_error()}.
start(Handler) ->
gleam@otp@actor:start_spec(
{spec,
fun() ->
Subject = gleam@erlang@process:new_subject(),
Selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
_pipe@4 = gleam@erlang@process:selecting_record3(
_pipe,
erlang:binary_to_atom(<<"tcp"/utf8>>),
fun(_, Data) -> _pipe@1 = Data,
_pipe@2 = gleam@dynamic:bit_string(_pipe@1),
_pipe@3 = gleam@result:unwrap(_pipe@2, <<>>),
{receive_message, _pipe@3} end
),
_pipe@8 = gleam@erlang@process:selecting_record3(
_pipe@4,
erlang:binary_to_atom(<<"ssl"/utf8>>),
fun(_, Data@1) -> _pipe@5 = Data@1,
_pipe@6 = gleam@dynamic:bit_string(_pipe@5),
_pipe@7 = gleam@result:unwrap(_pipe@6, <<>>),
{receive_message, _pipe@7} end
),
_pipe@9 = gleam@erlang@process:selecting_record2(
_pipe@8,
erlang:binary_to_atom(<<"ssl_closed"/utf8>>),
fun(_) -> ssl_closed end
),
_pipe@10 = gleam@erlang@process:selecting_record2(
_pipe@9,
erlang:binary_to_atom(<<"tcp_closed"/utf8>>),
fun(_) -> tcp_closed end
),
gleam@erlang@process:selecting(
_pipe@10,
Subject,
fun gleam@function:identity/1
)
end,
{ready,
{loop_state,
(erlang:element(9, erlang:element(7, Handler)))(
erlang:element(2, Handler)
),
erlang:element(2, Handler),
Subject,
erlang:element(7, Handler),
erlang:element(3, Handler)},
Selector}
end,
1000,
fun(Msg, State) -> case Msg of
tcp_closed ->
case (erlang:element(4, erlang:element(5, State)))(
erlang:element(3, State)
) of
{ok, nil} ->
_ = case erlang:element(6, Handler) of
{some, On_close} ->
On_close(erlang:element(4, State));
_ ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
ssl_closed ->
case (erlang:element(4, erlang:element(5, State)))(
erlang:element(3, State)
) of
{ok, nil} ->
_ = case erlang:element(6, Handler) of
{some, On_close} ->
On_close(erlang:element(4, State));
_ ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
close ->
case (erlang:element(4, erlang:element(5, State)))(
erlang:element(3, State)
) of
{ok, nil} ->
_ = case erlang:element(6, Handler) of
{some, On_close} ->
On_close(erlang:element(4, State));
_ ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
ready ->
_pipe@11 = erlang:element(3, State),
_pipe@12 = (erlang:element(6, erlang:element(5, State)))(
_pipe@11
),
_pipe@13 = gleam@result:replace_error(
_pipe@12,
<<"Failed to handshake socket"/utf8>>
),
_pipe@14 = gleam@result:map(
_pipe@13,
fun(_) -> _ = case erlang:element(5, Handler) of
{some, On_init} ->
On_init(erlang:element(4, State));
_ ->
nil
end end
),
_pipe@16 = gleam@result:then(
_pipe@14,
fun(_) ->
_pipe@15 = (erlang:element(
13,
erlang:element(5, State)
))(
erlang:element(3, State),
[{active_mode, once}]
),
gleam@result:replace_error(
_pipe@15,
<<"Failed to set socket active"/utf8>>
)
end
),
_pipe@17 = gleam@result:replace(
_pipe@16,
gleam@otp@actor:continue(State)
),
_pipe@18 = gleam@result:map_error(
_pipe@17,
fun(Reason) -> {stop, {abnormal, Reason}} end
),
gleam@result:unwrap_both(_pipe@18);
Msg@1 ->
case (erlang:element(4, Handler))(Msg@1, State) of
{continue, Next_state, Selector@1} ->
_assert_subject = (erlang:element(
13,
erlang:element(5, State)
))(
erlang:element(3, State),
[{active_mode, once}]
),
{ok, nil} = case _assert_subject of
{ok, nil} -> _assert_subject;
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"glisten/handler"/utf8>>,
function => <<"start"/utf8>>,
line => 143}
)
end,
{continue, Next_state, Selector@1};
Msg@2 ->
Msg@2
end
end end}
).
-spec func(
fun((bitstring(), loop_state(HEW)) -> gleam@otp@actor:next(handler_message(), loop_state(HEW)))
) -> fun((handler_message(), loop_state(HEW)) -> gleam@otp@actor:next(handler_message(), loop_state(HEW))).
func(Func) ->
fun(Msg, State) -> case Msg of
{tcp, _, _} ->
glisten@logger:error(
{<<"Received an unexpected TCP message"/utf8>>, Msg}
),
gleam@otp@actor:continue(State);
ready ->
glisten@logger:error(
{<<"Received an unexpected TCP message"/utf8>>, Msg}
),
gleam@otp@actor:continue(State);
{receive_message, Data} ->
Func(Data, State);
{send_message, Data@1} ->
case (erlang:element(12, erlang:element(5, State)))(
erlang:element(3, State),
Data@1
) of
{ok, _} ->
gleam@otp@actor:continue(State);
{error, Reason} ->
glisten@logger:error(
{<<"Failed to send data"/utf8>>, Reason}
),
{stop, {abnormal, <<"Failed to send data"/utf8>>}}
end;
Msg@1 ->
glisten@logger:error({<<"Unhandled TCP message"/utf8>>, Msg@1}),
{stop, {abnormal, <<"Unhandled TCP message"/utf8>>}}
end end.