Current section

Files

Jump to
pgl src pgl@internal@socket.erl
Raw

src/pgl@internal@socket.erl

-module(pgl@internal@socket).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/pgl/internal/socket.gleam").
-export([host/2, port/2, timeout/2, ipv6/2, with_send/2, with_receive/2, with_shutdown/2, parameter/3, connect/1, to_ssl/2, send/2, 'receive'/2, shutdown/1, supervised/1, new/0, factory/1]).
-export_type([tcp_socket/0, ssl_socket/0, internal_socket/0, builder/0, socket/0, msg/0, factory/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-type tcp_socket() :: any().
-type ssl_socket() :: any().
-opaque internal_socket() :: {tcp, tcp_socket()} | {ssl, ssl_socket()}.
-opaque builder() :: {builder,
binary(),
integer(),
boolean(),
integer(),
fun((internal_socket(), bitstring()) -> {ok, nil} |
{error, pgl@internal:posix_error()}),
fun((internal_socket(), integer(), integer()) -> {ok, bitstring()} |
{error, pgl@internal:posix_error()}),
fun((internal_socket()) -> {ok, nil} |
{error, pgl@internal:posix_error()})}.
-opaque socket() :: {socket,
gleam@erlang@process:subject(msg()),
binary(),
integer(),
gleam@dict:dict(binary(), binary()),
fun((internal_socket(), bitstring()) -> {ok, nil} |
{error, pgl@internal:posix_error()}),
fun((internal_socket(), integer(), integer()) -> {ok, bitstring()} |
{error, pgl@internal:posix_error()}),
fun((internal_socket()) -> {ok, nil} |
{error, pgl@internal:posix_error()})}.
-opaque msg() :: {ssl_upgrade,
gleam@erlang@process:subject({ok, nil} |
{error, pgl@internal:internal_error()}),
binary(),
boolean()} |
{send,
gleam@erlang@process:subject({ok, nil} |
{error, pgl@internal:posix_error()}),
fun((internal_socket(), bitstring()) -> {ok, nil} |
{error, pgl@internal:posix_error()}),
bitstring()} |
{'receive',
gleam@erlang@process:subject({ok, bitstring()} |
{error, pgl@internal:posix_error()}),
fun((internal_socket(), integer(), integer()) -> {ok, bitstring()} |
{error, pgl@internal:posix_error()}),
integer(),
integer()} |
{shutdown,
gleam@erlang@process:subject({ok, nil} |
{error, pgl@internal:posix_error()}),
fun((internal_socket()) -> {ok, nil} |
{error, pgl@internal:posix_error()})}.
-opaque factory() :: {factory,
gleam@erlang@process:name(gleam@otp@factory_supervisor:message(builder(), socket())),
builder()}.
-file("src/pgl/internal/socket.gleam", 78).
?DOC(false).
-spec host(builder(), binary()) -> builder().
host(Builder, Host) ->
{builder,
Host,
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder)}.
-file("src/pgl/internal/socket.gleam", 82).
?DOC(false).
-spec port(builder(), integer()) -> builder().
port(Builder, Port) ->
{builder,
erlang:element(2, Builder),
Port,
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder)}.
-file("src/pgl/internal/socket.gleam", 86).
?DOC(false).
-spec timeout(builder(), integer()) -> builder().
timeout(Builder, Timeout) ->
{builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
Timeout,
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder)}.
-file("src/pgl/internal/socket.gleam", 90).
?DOC(false).
-spec ipv6(builder(), boolean()) -> builder().
ipv6(Builder, Ipv6) ->
{builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
Ipv6,
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder)}.
-file("src/pgl/internal/socket.gleam", 103).
?DOC(false).
-spec with_send(
builder(),
fun((internal_socket(), bitstring()) -> {ok, nil} |
{error, pgl@internal:posix_error()})
) -> builder().
with_send(Builder, Send) ->
{builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
Send,
erlang:element(7, Builder),
erlang:element(8, Builder)}.
-file("src/pgl/internal/socket.gleam", 107).
?DOC(false).
-spec with_receive(
builder(),
fun((internal_socket(), integer(), integer()) -> {ok, bitstring()} |
{error, pgl@internal:posix_error()})
) -> builder().
with_receive(Builder, Receive) ->
{builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
Receive,
erlang:element(8, Builder)}.
-file("src/pgl/internal/socket.gleam", 111).
?DOC(false).
-spec with_shutdown(
builder(),
fun((internal_socket()) -> {ok, nil} | {error, pgl@internal:posix_error()})
) -> builder().
with_shutdown(Builder, Shutdown) ->
{builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
Shutdown}.
-file("src/pgl/internal/socket.gleam", 131).
?DOC(false).
-spec parameter(socket(), binary(), binary()) -> socket().
parameter(Sock, Key, Value) ->
Parameters = begin
_pipe = erlang:element(5, Sock),
gleam@dict:insert(_pipe, Key, Value)
end,
{socket,
erlang:element(2, Sock),
erlang:element(3, Sock),
erlang:element(4, Sock),
Parameters,
erlang:element(6, Sock),
erlang:element(7, Sock),
erlang:element(8, Sock)}.
-file("src/pgl/internal/socket.gleam", 136).
?DOC(false).
-spec connect(factory()) -> {ok, socket()} |
{error, gleam@otp@actor:start_error()}.
connect(Factory) ->
_pipe = gleam@otp@factory_supervisor:get_by_name(erlang:element(2, Factory)),
_pipe@1 = gleam@otp@factory_supervisor:start_child(
_pipe,
erlang:element(3, Factory)
),
gleam@result:map(_pipe@1, fun(Started) -> erlang:element(3, Started) end).
-file("src/pgl/internal/socket.gleam", 181).
?DOC(false).
-spec to_ssl(socket(), boolean()) -> {ok, socket()} |
{error, pgl@internal:internal_error()}.
to_ssl(Socket, Verified) ->
_pipe = gleam@otp@actor:call(
erlang:element(2, Socket),
1000,
fun(_capture) ->
{ssl_upgrade, _capture, erlang:element(3, Socket), Verified}
end
),
gleam@result:replace(_pipe, Socket).
-file("src/pgl/internal/socket.gleam", 189).
?DOC(false).
-spec send(socket(), bitstring()) -> {ok, socket()} |
{error, pgl@internal:internal_error()}.
send(Socket, Payload) ->
_pipe = gleam@otp@actor:call(
erlang:element(2, Socket),
1000,
fun(_capture) ->
{send, _capture, erlang:element(6, Socket), Payload}
end
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Code) -> {socket_error, Code, <<"Failed to send"/utf8>>} end
),
gleam@result:replace(_pipe@1, Socket).
-file("src/pgl/internal/socket.gleam", 200).
?DOC(false).
-spec 'receive'(socket(), integer()) -> {ok, bitstring()} |
{error, pgl@internal:internal_error()}.
'receive'(Conn, Length) ->
_pipe = gleam@otp@actor:call(
erlang:element(2, Conn),
erlang:element(4, Conn),
fun(_capture) ->
{'receive',
_capture,
erlang:element(7, Conn),
Length,
erlang:element(4, Conn)}
end
),
gleam@result:map_error(
_pipe,
fun(Code) -> {socket_error, Code, <<"Failed to receive"/utf8>>} end
).
-file("src/pgl/internal/socket.gleam", 215).
?DOC(false).
-spec shutdown(socket()) -> {ok, nil} | {error, pgl@internal:internal_error()}.
shutdown(Conn) ->
_pipe = gleam@otp@actor:call(
erlang:element(2, Conn),
1000,
fun(_capture) -> {shutdown, _capture, erlang:element(8, Conn)} end
),
gleam@result:map_error(
_pipe,
fun(Code) -> {socket_error, Code, <<"Failed to shutdown"/utf8>>} end
).
-file("src/pgl/internal/socket.gleam", 282).
?DOC(false).
-spec tcp_connect(binary(), integer(), boolean()) -> {ok, internal_socket()} |
{error, pgl@internal:internal_error()}.
tcp_connect(Host, Port, Ipv6) ->
_pipe = Host,
_pipe@1 = unicode:characters_to_list(_pipe),
_pipe@2 = pgl_ffi:gen_tcp_connect(_pipe@1, Port, Ipv6),
_pipe@3 = gleam@result:map(_pipe@2, fun(Field@0) -> {tcp, Field@0} end),
gleam@result:map_error(
_pipe@3,
fun(Code) -> {socket_error, Code, <<"Failed to connect"/utf8>>} end
).
-file("src/pgl/internal/socket.gleam", 264).
?DOC(false).
-spec tcp_to_ssl(internal_socket(), binary(), boolean()) -> {ok,
internal_socket()} |
{error, pgl@internal:internal_error()}.
tcp_to_ssl(Socket, Host, Verified) ->
_pipe@2 = case Socket of
{tcp, Sock} ->
_pipe = Sock,
_pipe@1 = pgl_ffi:ssl_connect(_pipe, Host, Verified),
gleam@result:map(_pipe@1, fun(Field@0) -> {ssl, Field@0} end);
_ ->
{ok, Socket}
end,
gleam@result:map_error(
_pipe@2,
fun(Code) -> {socket_error, Code, <<"Failed to connect SSL"/utf8>>} end
).
-file("src/pgl/internal/socket.gleam", 222).
?DOC(false).
-spec handle_message(internal_socket(), msg()) -> gleam@otp@actor:next(internal_socket(), msg()).
handle_message(Sock, Msg) ->
case Msg of
{ssl_upgrade, Client, Host, Verified} ->
_pipe = case tcp_to_ssl(Sock, Host, Verified) of
{ok, Ssl} ->
gleam@otp@actor:send(Client, {ok, nil}),
Ssl;
{error, Err} ->
gleam@otp@actor:send(Client, {error, Err}),
Sock
end,
gleam@otp@actor:continue(_pipe);
{send, Client@1, Send, Payload} ->
_pipe@1 = Send(Sock, Payload),
_pipe@2 = gleam@result:replace(_pipe@1, nil),
gleam@otp@actor:send(Client@1, _pipe@2),
gleam@otp@actor:continue(Sock);
{'receive', Client@2, Receive, Length, Timeout} ->
_pipe@3 = Receive(Sock, Length, Timeout),
gleam@otp@actor:send(Client@2, _pipe@3),
gleam@otp@actor:continue(Sock);
{shutdown, Client@3, Shutdown} ->
_pipe@4 = Shutdown(Sock),
gleam@otp@actor:send(Client@3, _pipe@4),
gleam@otp@actor:stop()
end.
-file("src/pgl/internal/socket.gleam", 150).
?DOC(false).
-spec start_socket(builder()) -> {ok, gleam@otp@actor:started(socket())} |
{error, gleam@otp@actor:start_error()}.
start_socket(Builder) ->
{builder, Host, Port, Ipv6, Timeout, Send, Receive, Shutdown} = Builder,
_pipe@6 = gleam@otp@actor:new_with_initialiser(
1000,
fun(Subject) -> _pipe = tcp_connect(Host, Port, Ipv6),
_pipe@1 = gleam@result:map_error(
_pipe,
fun pgl@internal:error_to_string/1
),
gleam@result:map(
_pipe@1,
fun(Sock) ->
Selector = begin
_pipe@2 = gleam_erlang_ffi:new_selector(),
gleam@erlang@process:select(_pipe@2, Subject)
end,
Socket = {socket,
Subject,
Host,
Timeout,
maps:new(),
Send,
Receive,
Shutdown},
_pipe@3 = Sock,
_pipe@4 = gleam@otp@actor:initialised(_pipe@3),
_pipe@5 = gleam@otp@actor:selecting(_pipe@4, Selector),
gleam@otp@actor:returning(_pipe@5, Socket)
end
) end
),
_pipe@7 = gleam@otp@actor:on_message(_pipe@6, fun handle_message/2),
gleam@otp@actor:start(_pipe@7).
-file("src/pgl/internal/socket.gleam", 142).
?DOC(false).
-spec supervised(factory()) -> gleam@otp@supervision:child_specification(gleam@otp@factory_supervisor:supervisor(builder(), socket())).
supervised(Factory) ->
_pipe = gleam@otp@factory_supervisor:worker_child(fun start_socket/1),
_pipe@1 = gleam@otp@factory_supervisor:named(
_pipe,
erlang:element(2, Factory)
),
gleam@otp@factory_supervisor:supervised(_pipe@1).
-file("src/pgl/internal/socket.gleam", 296).
?DOC(false).
-spec socket_send(internal_socket(), bitstring()) -> {ok, nil} |
{error, pgl@internal:posix_error()}.
socket_send(Socket, Payload) ->
case Socket of
{tcp, Sock} ->
pgl_ffi:gen_tcp_send(Sock, Payload);
{ssl, Sock@1} ->
pgl_ffi:ssl_send(Sock@1, Payload)
end.
-file("src/pgl/internal/socket.gleam", 306).
?DOC(false).
-spec socket_receive(internal_socket(), integer(), integer()) -> {ok,
bitstring()} |
{error, pgl@internal:posix_error()}.
socket_receive(Socket, Length, Timeout) ->
case Socket of
{tcp, Sock} ->
pgl_ffi:gen_tcp_recv(Sock, Length, Timeout);
{ssl, Sock@1} ->
pgl_ffi:ssl_recv(Sock@1, Length)
end.
-file("src/pgl/internal/socket.gleam", 317).
?DOC(false).
-spec socket_shutdown(internal_socket()) -> {ok, nil} |
{error, pgl@internal:posix_error()}.
socket_shutdown(Socket) ->
case Socket of
{tcp, Sock} ->
pgl_ffi:gen_tcp_shutdown(Sock);
{ssl, Sock@1} ->
pgl_ffi:ssl_shutdown(Sock@1)
end.
-file("src/pgl/internal/socket.gleam", 66).
?DOC(false).
-spec new() -> builder().
new() ->
{builder,
<<"127.0.0.1"/utf8>>,
5432,
false,
1000,
fun socket_send/2,
fun socket_receive/3,
fun socket_shutdown/1}.
-file("src/pgl/internal/socket.gleam", 124).
?DOC(false).
-spec factory(builder()) -> factory().
factory(Builder) ->
_pipe = <<"pgl_sockets"/utf8>>,
_pipe@1 = gleam_erlang_ffi:new_name(_pipe),
{factory, _pipe@1, Builder}.