diff options
author | Linus Nordberg <linus@sunet.se> | 2019-06-24 16:04:53 +0200 |
---|---|---|
committer | Linus Nordberg <linus@sunet.se> | 2019-06-24 16:04:53 +0200 |
commit | 5ce12907073082be03c25707e2d6fc0703db9f1f (patch) | |
tree | f4990c0d09688d06b68fb947c1e9148b38ae1735 | |
parent | 6e90bceab4a3a6e4b9d4496b810324867d533ce1 (diff) |
start one sock_server per token; give servers a chance to clean up
still not rm'ing the socket file though. wonder where that should happen.
-rw-r--r-- | p11p-daemon/src/p11p_server.erl | 62 | ||||
-rw-r--r-- | p11p-daemon/src/p11p_server_sup.erl | 32 |
2 files changed, 63 insertions, 31 deletions
diff --git a/p11p-daemon/src/p11p_server.erl b/p11p-daemon/src/p11p_server.erl index 726e97b..c2422dc 100644 --- a/p11p-daemon/src/p11p_server.erl +++ b/p11p-daemon/src/p11p_server.erl @@ -1,7 +1,5 @@ %% Create an AF_UNIX socket and accept connections. On connect, spawn -%% a p11p_server process. - -%% FIXME: Run _one_ socket per instance of this server! +%% another p11p_server process. -module(p11p_server). -behaviour(gen_server). @@ -15,41 +13,69 @@ %% Records and types. -include("p11p_defs.hrl"). --record(state, {socket :: gen_tcp:socket()}). +-record(state, { + sockpath :: string(), % FIXME: filename(3erl) + socket :: gen_tcp:socket() + }). %% API. -spec start_link(gen_tcp:socket()) -> {ok, pid()} | {error, term()}. -start_link(Socket) -> - gen_server:start_link(?MODULE, Socket, []). +start_link(Args) -> + lager:debug("~p: p11p_server:start_link enter", [self()]), + gen_server:start_link(?MODULE, Args, []). %% Genserver callbacks. -init(Socket) -> +init([SocketPath, Socket]) -> + lager:debug("~p: p11p_server:init: ~s", [self(), SocketPath]), + process_flag(trap_exit, true), % We want terminate(). gen_server:cast(self(), accept), % Perform accept in gen-server loop. - {ok, #state{socket = Socket}}. + {ok, #state{sockpath = SocketPath, socket = Socket}}. handle_call(Request, _From, State) -> lager:debug("Unhandled call: ~p~n", [Request]), {reply, unhandled, State}. -handle_cast(accept, State = #state{socket = ListenSocket}) -> - {ok, Sock} = gen_tcp:accept(ListenSocket), - %% TODO: authz - lager:debug("new connection accepted: ~p", [Sock]), - p11p_server_sup:start_server(), % New acceptor. - {noreply, State#state{socket = Sock}}; +handle_cast(accept, State = #state{sockpath = SocketPath, socket = ListenSocket}) -> + %% Blocking until client connects or timeout fires. Without a + %% timeout our supervisor cannot terminate us. + case gen_tcp:accept(ListenSocket, 900) of + {ok, Sock} -> + %% TODO: authz + lager:debug("~p: ~p: new connection accepted", [self(), Sock]), + p11p_server_sup:start_server([SocketPath, ListenSocket]), % Start a new acceptor. + {noreply, State#state{socket = Sock}}; % Use the new socket. + {error, timeout} -> + gen_server:cast(self(), accept), % Try again. + {noreply, State}; + {error, closed} -> + lager:debug("~p: listening socket closed", [self()]), + {stop, normal, State} + end; handle_cast(Request, State) -> lager:debug("Unhandled cast: ~p~n", [Request]), {noreply, State}. -handle_info({tcp, _Socket, Data}, State) -> +handle_info({tcp, Port, Data}, State) -> lager:debug("~p: received: ~s", [self(), Data]), - {noreply, State}; + case Data of + <<"q\n">> -> + gen_tcp:send(Port, "ok, bye\n"), %DEBUG + {stop, {shutdown, quit_by_client}, State}; + _ -> + gen_tcp:send(Port, "ok, thanks: " ++ Data), %DEBUG + {noreply, State} + end; +handle_info({tcp_closed, Port}, State) -> + lager:debug("~p: ~p: closed", [self(), Port]), + {stop, {shutdown, close_by_client}, State}; handle_info(Info, State) -> lager:debug("Unhandled info: ~p~n", [Info]), {noreply, State}. -terminate(_Reason, #state{socket = Socket}) -> - gen_tcp:close(Socket), % FIXME: correct? +terminate(_Reason, #state{sockpath = _SocketPath, socket = Socket}) -> + lager:debug("~p: ~p: terminated", [self(), Socket]), + gen_tcp:close(Socket), + %%FIXME: clean up socket file where? file:delete(SocketPath), ok. code_change(_OldVersion, State, _Extra) -> diff --git a/p11p-daemon/src/p11p_server_sup.erl b/p11p-daemon/src/p11p_server_sup.erl index 924123b..18f1247 100644 --- a/p11p-daemon/src/p11p_server_sup.erl +++ b/p11p-daemon/src/p11p_server_sup.erl @@ -1,28 +1,34 @@ -module(p11p_server_sup). -behaviour(supervisor). --export([start_link/0, start_server/0]). +-export([start_link/0, start_server/1]). -export([init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> - Name = "vtoken0", % FIXME - SocketPath = socket_path(mkdir_socket_basepath(), Name), - file:delete(SocketPath), - % TODO: consider flow control through {active, once} - {ok, ListenSocket} = gen_tcp:listen(0, [{ifaddr, {local, SocketPath}}, - binary]), - spawn_link(fun start_server/0), - {ok, {{simple_one_for_one, 60, 3600}, - [{sock_server, - {p11p_server, start_link, [ListenSocket]}, + Names = ["vtoken0", "vtoken1"], % FIXME: get from config + ok = start_servers(Names), + {ok, {{simple_one_for_one, 1, 5}, + [{sock_server, % Ignored childspec id. + {p11p_server, start_link, []}, temporary, 1000, worker, [p11p_server]} ]}}. -start_server() -> - supervisor:start_child(?MODULE, []). +start_servers([]) -> + ok; +start_servers([Name|T]) -> + Path = socket_path(mkdir_socket_basepath(), Name), + file:delete(Path), + % TODO: consider flow control through {active, once}, don't forget activating after read! + {ok, Socket} = gen_tcp:listen(0, [{ifaddr, {local, Path}}, binary]), + spawn_link(?MODULE, start_server, [[Path, Socket]]), + start_servers(T). + +start_server(Args) -> + {ok, Pid} = supervisor:start_child(?MODULE, [Args]), + Pid. %% Private functions. mkdir_socket_basepath() -> |