Packages
glisten
0.6.7
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).
-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, nil} |
{tcp, gleam@otp@port:port_(), bitstring()} |
{tcp_closed, nil}.
-type loop_state(GHP) :: {loop_state,
glisten@socket:socket(),
gleam@erlang@process:subject(handler_message()),
glisten@socket@transport:transport(),
GHP}.
-type handler(GHU) :: {handler,
glisten@socket:socket(),
GHU,
fun((handler_message(), loop_state(GHU)) -> gleam@otp@actor:next(loop_state(GHU))),
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@1 = gleam@erlang@process:selecting(
_pipe,
Subject,
fun gleam@function:identity/1
),
gleam@erlang@process:selecting_anything(
_pipe@1,
fun(Msg) -> case gleam@dynamic:unsafe_coerce(Msg) of
{tcp, _@1, Data} ->
{receive_message, Data};
{ssl, _@1, Data} ->
{receive_message, Data};
Msg@1 ->
Msg@1
end end
)
end,
{ready,
{loop_state,
erlang:element(2, Handler),
Subject,
erlang:element(7, Handler),
erlang:element(3, Handler)},
Selector}
end,
1000,
fun(Msg@2, State) -> case Msg@2 of
{tcp_closed, _@2} ->
case (erlang:element(4, erlang:element(4, State)))(
erlang:element(2, State)
) of
{ok, nil} ->
_@4 = case erlang:element(6, Handler) of
{some, Func} ->
Func(erlang:element(3, State));
_@3 ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
{ssl_closed, _@2} ->
case (erlang:element(4, erlang:element(4, State)))(
erlang:element(2, State)
) of
{ok, nil} ->
_@4 = case erlang:element(6, Handler) of
{some, Func} ->
Func(erlang:element(3, State));
_@3 ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
close ->
case (erlang:element(4, erlang:element(4, State)))(
erlang:element(2, State)
) of
{ok, nil} ->
_@4 = case erlang:element(6, Handler) of
{some, Func} ->
Func(erlang:element(3, State));
_@3 ->
nil
end,
{stop, normal};
{error, Err} ->
{stop, {abnormal, gleam@string:inspect(Err)}}
end;
ready ->
_pipe@2 = erlang:element(2, State),
_pipe@3 = (erlang:element(6, erlang:element(4, State)))(
_pipe@2
),
_pipe@4 = gleam@result:replace_error(
_pipe@3,
<<"Failed to handshake socket"/utf8>>
),
_pipe@5 = gleam@result:map(
_pipe@4,
fun(_) -> _@6 = case erlang:element(5, Handler) of
{some, Func@1} ->
Func@1(erlang:element(3, State));
_@5 ->
nil
end end
),
_pipe@7 = gleam@result:then(
_pipe@5,
fun(_) ->
_pipe@6 = (erlang:element(
12,
erlang:element(4, State)
))(
erlang:element(2, State),
[{active_mode, once}]
),
gleam@result:replace_error(
_pipe@6,
<<"Failed to set socket active"/utf8>>
)
end
),
_pipe@8 = gleam@result:replace(
_pipe@7,
{continue, State}
),
_pipe@9 = gleam@result:map_error(
_pipe@8,
fun(Reason) -> {stop, {abnormal, Reason}} end
),
gleam@result:unwrap_both(_pipe@9);
Msg@3 ->
case (erlang:element(4, Handler))(Msg@3, State) of
{continue, Next_state} ->
{ok, nil} = case (erlang:element(
12,
erlang:element(4, State)
))(
erlang:element(2, State),
[{active_mode, once}]
) of
{ok, nil} -> {ok, nil};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"glisten/handler"/utf8>>,
function => <<"start"/utf8>>,
line => 116})
end,
{continue, Next_state};
Msg@4 ->
Msg@4
end
end end}
).
-spec func(
fun((bitstring(), loop_state(GIQ)) -> gleam@otp@actor:next(loop_state(GIQ)))
) -> fun((handler_message(), loop_state(GIQ)) -> gleam@otp@actor:next(loop_state(GIQ))).
func(Func) ->
fun(Msg, State) -> case Msg of
{tcp, _@1, _@2} ->
glisten@logger:error(
{<<"Received an unexpected TCP message"/utf8>>, Msg}
),
{continue, State};
ready ->
glisten@logger:error(
{<<"Received an unexpected TCP message"/utf8>>, Msg}
),
{continue, State};
{receive_message, Data} ->
Func(Data, State);
{send_message, Data@1} ->
case (erlang:element(11, erlang:element(4, State)))(
erlang:element(2, State),
Data@1
) of
{ok, _@3} ->
{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.