Packages

A Gleam networking library for TCP, UDP, and SSL/TLS sockets

Current section

Files

Jump to
neon src neon@udp.erl
Raw

src/neon@udp.erl

-module(neon@udp).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/neon/udp.gleam").
-export([new/1, ip_address/2, ip_version/2, open/1, connect/3, send/2, 'receive'/3, controlling_process/2, close/1, port/1]).
-export_type([udp/0, udp_error/0, open_options/0, receive_data/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.
-type udp() :: any().
-type udp_error() :: closed |
timeout |
system_limit |
{posix, neon@net:posix()} |
invalid_pid |
{udp_error, binary()}.
-opaque open_options() :: {open_options,
neon@net:port_(),
gleam@option:option(neon@net:ip_address()),
neon@net:ip_version()}.
-type receive_data() :: {receive_data,
neon@net:ip_address(),
neon@net:port_(),
bitstring()}.
-file("src/neon/udp.gleam", 40).
?DOC(
" Creates open options for a UDP socket on the given port.\n"
"\n"
" Defaults to IPv4 with no specific IP address binding.\n"
).
-spec new(neon@net:port_()) -> open_options().
new(Port) ->
{open_options, Port, none, ipv4}.
-file("src/neon/udp.gleam", 48).
?DOC(
" Binds the socket to a specific IP address.\n"
"\n"
" When set, the IP version is derived from the address itself, and the\n"
" `ip_version` option is ignored.\n"
).
-spec ip_address(open_options(), neon@net:ip_address()) -> open_options().
ip_address(Opts, Ip_address) ->
{open_options,
erlang:element(2, Opts),
{some, Ip_address},
erlang:element(4, Opts)}.
-file("src/neon/udp.gleam", 56).
?DOC(
" Sets the IP version for the socket.\n"
"\n"
" Only used when no IP address is set. When an IP address is provided,\n"
" the version is derived from the address.\n"
).
-spec ip_version(open_options(), neon@net:ip_version()) -> open_options().
ip_version(Opts, Ip_version) ->
{open_options, erlang:element(2, Opts), erlang:element(3, Opts), Ip_version}.
-file("src/neon/udp.gleam", 61).
?DOC(" Opens a UDP socket with the given options.\n").
-spec open(open_options()) -> {ok, udp()} | {error, udp_error()}.
open(Opts) ->
udp_ffi:open(
erlang:element(2, Opts),
erlang:element(3, Opts),
erlang:element(4, Opts)
).
-file("src/neon/udp.gleam", 68).
?DOC(
" Associates a UDP socket with a remote address and port.\n"
"\n"
" After connecting, `send` can be used without specifying a destination.\n"
).
-spec connect(udp(), neon@net:address(), neon@net:port_()) -> {ok, nil} |
{error, udp_error()}.
connect(Socket, Address, Port) ->
udp_ffi:connect(Socket, Address, Port).
-file("src/neon/udp.gleam", 77).
?DOC(" Sends data over a connected UDP socket.\n").
-spec send(udp(), bitstring()) -> {ok, nil} | {error, udp_error()}.
send(Socket, Payload) ->
udp_ffi:send(Socket, Payload).
-file("src/neon/udp.gleam", 91).
?DOC(
" Receives data from a UDP socket.\n"
"\n"
" The `length` parameter specifies the number of bytes to receive. Use `0`\n"
" to receive whatever data is available. Must be non-negative.\n"
).
-spec 'receive'(udp(), integer(), neon@net:timeout_()) -> {ok, receive_data()} |
{error, udp_error()}.
'receive'(Socket, Length, Timeout) ->
case Length >= 0 of
true ->
_pipe = udp_ffi:recv(Socket, Length, Timeout),
gleam@result:map(
_pipe,
fun(Recv_data) ->
{Ip_address, Port, Payload} = Recv_data,
{receive_data, Ip_address, Port, Payload}
end
);
false ->
{error, {udp_error, <<"Length must be non-negative"/utf8>>}}
end.
-file("src/neon/udp.gleam", 111).
?DOC(
" Change the controlling process of a socket.\n"
"\n"
" The controlling process is the process that the socket sends messages to.\n"
).
-spec controlling_process(udp(), gleam@erlang@process:pid_()) -> {ok, nil} |
{error, udp_error()}.
controlling_process(Socket, Pid) ->
udp_ffi:controlling_process(Socket, Pid).
-file("src/neon/udp.gleam", 121).
?DOC(
" Closes a UDP socket.\n"
"\n"
" This function is idempotent and always returns `Nil`.\n"
).
-spec close(udp()) -> nil.
close(Socket) ->
udp_ffi:close(Socket).
-file("src/neon/udp.gleam", 128).
?DOC(
" Returns the port number assigned to a socket by the operating system.\n"
"\n"
" Useful when opening on port 0 (OS-assigned).\n"
).
-spec port(udp()) -> {ok, neon@net:port_()} | {error, nil}.
port(Socket) ->
_pipe = inet_ffi:port(Socket),
gleam@result:'try'(_pipe, fun neon@net:port/1).