Skip to content

Instantly share code, notes, and snippets.

@msantos
Created July 25, 2015 15:41
Show Gist options
  • Save msantos/b69b4534515f645580b9 to your computer and use it in GitHub Desktop.
Save msantos/b69b4534515f645580b9 to your computer and use it in GitHub Desktop.
-module(hawk_uds).
%% API
-export([start_link/1,
init/1]).
-export([accept/1, handle/1]).
start_link(File) ->
{ok, spawn_link(?MODULE, init, [File])}.
init(File0) ->
inert:start(),
File = iolist_to_binary(File0),
file:delete(File),
{ok, Fd} = procket:socket(unix, stream, 0),
Len = byte_size(File),
Sun = <<(procket:sockaddr_common(1, Len))/binary, File/binary, 0:((procket:unix_path_max() - Len) * 8)>>,
ok = procket:bind(Fd, Sun),
ok = procket:listen(Fd),
accept(Fd).
accept(Fd) ->
case inert:poll(Fd) of
{ok,read} -> ok;
Error ->
procket:close(Fd),
erlang:exit({accept, Error})
end,
case procket:accept(Fd) of
{error, eagain} ->
ok;
{ok, ClientFd} ->
spawn_opt(?MODULE, handle, [ClientFd], [{fullsweep_after, 0}])
end,
accept(Fd).
handle(Sock) ->
{ok, PackLen} = read_packet_len(Sock),
{ok, Binary} = read_packet(Sock, PackLen),
BinSize = byte_size(Binary),
case procket:write(Sock, <<BinSize:32/big-unsigned-integer, Binary/binary>>) of
{error, _} ->
procket:close(Sock),
erlang:exit({reason, connection_refused});
_ ->
ok
end,
handle(Sock).
read_packet_len(Fd) ->
case read_packet(Fd, 4, <<>>) of
{ok, <<Len:32/big-unsigned-integer>>} -> {ok, Len};
_Error ->
procket:close(Fd),
erlang:exit({reason, read_packet_len})
end.
read_packet(Fd, Len) ->
read_packet(Fd, Len, <<>>).
read_packet(_Fd, 0, Bin) ->
{ok, Bin};
read_packet(Fd, Len, Bin) ->
case procket:read(Fd, Len) of
{error, eagain} ->
case inert:poll(Fd) of
{ok, read} ->
read_packet(Fd, Len, Bin);
_ ->
procket:close(Fd),
ok
end;
{ok, <<>>} ->
procket:close(Fd),
erlang:exit({reason, connection_refused});
{ok, Data} when Len == erlang:byte_size(Data) ->
{ok, Data};
{ok, Data} ->
read_packet(Fd, Len - byte_size(Data), <<Bin/binary, Data/binary>>);
Error ->
error_logger:info_report({read_packet, Error}),
procket:close(Fd)
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment