Packages
glisten
0.9.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, nowarn_unused_function]).
-export([start/1]).
-export_type([internal_message/0, message/1, loop_message/1, loop_state/2, connection/1, handler/2]).
-type internal_message() :: close |
ready |
{receive_message, bitstring()} |
{ssl, gleam@otp@port:port_(), bitstring()} |
ssl_closed |
{tcp, gleam@otp@port:port_(), bitstring()} |
tcp_closed.
-type message(HHP) :: {internal, internal_message()} | {user, HHP}.
-type loop_message(HHQ) :: {packet, bitstring()} | {custom, HHQ}.
-type loop_state(HHR, HHS) :: {loop_state,
{ok, {{integer(), integer(), integer(), integer()}, integer()}} |
{error, nil},
glisten@socket:socket(),
gleam@erlang@process:subject(message(HHR)),
glisten@socket@transport:transport(),
HHS}.
-type connection(HHT) :: {connection,
{ok, {{integer(), integer(), integer(), integer()}, integer()}} |
{error, nil},
glisten@socket:socket(),
glisten@socket@transport:transport(),
gleam@erlang@process:subject(message(HHT))}.
-type handler(HHU, HHV) :: {handler,
glisten@socket:socket(),
fun((loop_message(HHU), HHV, connection(HHU)) -> gleam@otp@actor:next(loop_message(HHU), HHV)),
fun(() -> {HHV, gleam@option:option(gleam@erlang@process:selector(HHU))}),
gleam@option:option(fun((HHV) -> nil)),
glisten@socket@transport:transport()}.
-spec start(handler(HIF, any())) -> {ok,
gleam@erlang@process:subject(message(HIF))} |
{error, gleam@otp@actor:start_error()}.
start(Handler) ->
gleam@otp@actor:start_spec(
{spec,
fun() ->
Subject = gleam@erlang@process:new_subject(),
{Initial_state, User_selector} = (erlang:element(4, Handler))(),
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_array(_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_array(_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
),
_pipe@11 = gleam_erlang_ffi:map_selector(
_pipe@10,
fun(Field@0) -> {internal, Field@0} end
),
gleam@erlang@process:selecting(
_pipe@11,
Subject,
fun gleam@function:identity/1
)
end,
Selector@1 = case User_selector of
{some, Sel} ->
_pipe@12 = Sel,
_pipe@13 = gleam_erlang_ffi:map_selector(
_pipe@12,
fun(Field@0) -> {user, Field@0} end
),
gleam_erlang_ffi:merge_selector(Selector, _pipe@13);
_ ->
Selector
end,
{ready,
{loop_state,
(erlang:element(9, erlang:element(6, Handler)))(
erlang:element(2, Handler)
),
erlang:element(2, Handler),
Subject,
erlang:element(6, Handler),
Initial_state},
Selector@1}
end,
1000,
fun(Msg, State) ->
Connection = {connection,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(5, State),
erlang:element(4, State)},
case Msg of
{internal, tcp_closed} ->
case (erlang:element(4, erlang:element(5, State)))(
erlang:element(3, State)
) of
{ok, nil} ->
_ = case erlang:element(5, Handler) of
{some, On_close} ->
On_close(erlang:element(6, State));
_ ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
{internal, ssl_closed} ->
case (erlang:element(4, erlang:element(5, State)))(
erlang:element(3, State)
) of
{ok, nil} ->
_ = case erlang:element(5, Handler) of
{some, On_close} ->
On_close(erlang:element(6, State));
_ ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
{internal, close} ->
case (erlang:element(4, erlang:element(5, State)))(
erlang:element(3, State)
) of
{ok, nil} ->
_ = case erlang:element(5, Handler) of
{some, On_close} ->
On_close(erlang:element(6, State));
_ ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
{internal, ready} ->
_pipe@14 = erlang:element(3, State),
_pipe@15 = (erlang:element(6, erlang:element(5, State)))(
_pipe@14
),
_pipe@16 = gleam@result:replace_error(
_pipe@15,
<<"Failed to handshake socket"/utf8>>
),
_pipe@18 = gleam@result:then(
_pipe@16,
fun(_) ->
_pipe@17 = (erlang:element(
13,
erlang:element(5, State)
))(
erlang:element(3, State),
[{active_mode, once}]
),
gleam@result:replace_error(
_pipe@17,
<<"Failed to set socket active"/utf8>>
)
end
),
_pipe@19 = gleam@result:replace(
_pipe@18,
gleam@otp@actor:continue(State)
),
_pipe@20 = gleam@result:map_error(
_pipe@19,
fun(Reason) -> {stop, {abnormal, Reason}} end
),
gleam@result:unwrap_both(_pipe@20);
{user, Msg@1} ->
Msg@2 = {custom, Msg@1},
case (erlang:element(3, Handler))(
Msg@2,
erlang:element(6, State),
Connection
) of
{continue, Next_state, _} ->
_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 => 173}
)
end,
gleam@otp@actor:continue(
erlang:setelement(6, State, Next_state)
);
{stop, Reason@1} ->
{stop, Reason@1}
end;
{internal, {receive_message, Msg@3}} ->
Msg@4 = {packet, Msg@3},
case (erlang:element(3, Handler))(
Msg@4,
erlang:element(6, State),
Connection
) of
{continue, Next_state@1, _} ->
_assert_subject@1 = (erlang:element(
13,
erlang:element(5, State)
))(
erlang:element(3, State),
[{active_mode, once}]
),
{ok, nil} = case _assert_subject@1 of
{ok, nil} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"glisten/handler"/utf8>>,
function => <<"start"/utf8>>,
line => 187}
)
end,
gleam@otp@actor:continue(
erlang:setelement(6, State, Next_state@1)
);
{stop, Reason@2} ->
{stop, Reason@2}
end
end
end}
).