diff options
Diffstat (limited to 'p11p-daemon/src/p11p_remote_manager.erl')
-rw-r--r-- | p11p-daemon/src/p11p_remote_manager.erl | 100 |
1 files changed, 53 insertions, 47 deletions
diff --git a/p11p-daemon/src/p11p_remote_manager.erl b/p11p-daemon/src/p11p_remote_manager.erl index eabb67f..ad7fbaf 100644 --- a/p11p-daemon/src/p11p_remote_manager.erl +++ b/p11p-daemon/src/p11p_remote_manager.erl @@ -9,17 +9,16 @@ %% given vtoken and spawn a p11p_remote genserver "on demand". %% %% Provide a client event and a server event API for servers and -%% remotes, respectively, where events like "remote timing out" and +%% remotes, respectively, where events like "remote timed out" and %% "p11 client hung up" can be reported. %% - -%% Keep track of (successful) p11 requests which might cause state -%% changes in the token, like "logins". When switching token under the +%% Keep track of successful p11 requests which might cause state +%% changes in a token, like logins. When switching token under the %% feet of the p11 client, replay whatever is needed to the new -%% token. This goes for the p11-kit RPC protocol version octet too. +%% token. This includes the p11-kit RPC protocol version octet. %% Certain state changing p11 requests cannot be replayed, like -%% "generate new key". Any such (successful) request invalidates all -%% other remotes for the given token. +%% generation of a new key. Any such (successful) request invalidates +%% all other remotes for the given vtoken. -module(p11p_remote_manager). @@ -72,63 +71,70 @@ server_event(Event, Args) -> init([]) -> {ok, #state{tokens = init_tokens(p11p_config:tokens())}}. -handle_call({remote_for_token, TokName}, _From, #state{tokens = Tokens} = State) -> - #{TokName := Token} = Tokens, - lager:debug("all remotes: ~p", [Token#token.remotes]), - {Remotes, NewBC} = - case Token#token.balance_count of +handle_call({remote_for_token, TokNameIn}, _, #state{tokens = Tokens} = S) -> + #{TokNameIn := TokenIn} = Tokens, + RemotesIn = TokenIn#token.remotes, + lager:debug("all remotes: ~p", [RemotesIn]), + {Remotes, BalanceCount} = + case TokenIn#token.balance_count of 0 -> lager:debug("~p: balancing: next remote", [self()]), - R0 = rotate_remotes(Token#token.remotes), - R = hd(R0), - {R0, R#remote.balance - 1}; + Rotated = rotate_remotes(RemotesIn), + First = hd(Rotated), + {Rotated, First#remote.balance - 1}; N when N > 0 -> lager:debug("~p: balancing: ~B more invocations", [self(), N]), - {Token#token.remotes, N - 1}; + {RemotesIn, N - 1}; -1 -> - {Token#token.remotes, -1} + {RemotesIn, -1} end, - #remote{tokname = TokName, servid = ServId, modpath = ModPath, modenv = ModEnv, pid = Pid} = Remote = hd(Remotes), - case Pid of + #remote{tokname = TokNameIn, + servid = ServId, + modpath = ModPath, + modenv = ModEnv, + pid = PidIn} = SelectedRemote = hd(Remotes), + case PidIn of undefined -> - {ok, NewPid} = p11p_remote:start_link(ServId, TokName, ModPath, ModEnv), - NewRemote = Remote#remote{pid = NewPid}, - NewToken = Token#token{remotes = [NewRemote | tl(Remotes)], - balance_count = NewBC}, - NewState = State#state{tokens = Tokens#{TokName := NewToken}}, - {reply, NewPid, NewState}; + {ok, Pid} = + p11p_remote:start_link(ServId, TokNameIn, ModPath, ModEnv), + Remote = SelectedRemote#remote{pid = Pid}, + Token = TokenIn#token{remotes = [Remote | tl(Remotes)], + balance_count = BalanceCount}, + {reply, Pid, S#state{tokens = Tokens#{TokNameIn := Token}}}; _ -> - {reply, Pid, State} + {reply, PidIn, S} end; handle_call(Call, _From, State) -> lager:debug("Unhandled call: ~p~n", [Call]), {reply, unhandled, State}. -handle_cast({server_event, timeout, [TokName, Server]}, #state{tokens = Tokens} = State) -> - lager:debug("~p: ~s: timed out, stopping ~p", [self(), TokName, Server]), +handle_cast({server_event, timeout, [TokNameIn, Server]}, + #state{tokens = Tokens} = S) -> + lager:debug("~p: ~s: timed out, stopping ~p", [self(), TokNameIn, Server]), gen_server:stop(Server), % Hang up on p11 client. %% TODO: do some code dedup with remote_for_token? - #{TokName := Token} = Tokens, - Remotes = Token#token.remotes, - Remote = hd(Remotes), - NewRemote = Remote#remote{pid = undefined}, - NewToken = Token#token{remotes = tl(Remotes) ++ [NewRemote]}, - NewState = State#state{tokens = Tokens#{TokName := NewToken}}, - lager:debug("~p: ~s: updated token: ~p", [self(), TokName, NewToken]), - {noreply, NewState}; -handle_cast({client_event, client_gone, [TokName, Pid]}, #state{tokens = Tokens} = State) -> + #{TokNameIn := TokenIn} = Tokens, + Remotes = TokenIn#token.remotes, + SelectedRemote = hd(Remotes), + Remote = SelectedRemote#remote{pid = undefined}, + Token = TokenIn#token{remotes = tl(Remotes) ++ [Remote]}, + lager:debug("~p: ~s: updated token: ~p", [self(), TokNameIn, Token]), + {noreply, S#state{tokens = Tokens#{TokNameIn := Token}}}; + +handle_cast({client_event, client_gone, [TokName, Pid]}, + #state{tokens = Tokens} = S) -> lager:debug("~p: asking remote ~p to stop", [self(), Pid]), p11p_remote:stop(Pid, normal), - #{TokName := Token} = Tokens, - Remotes = Token#token.remotes, - NewRemotes = lists:map(fun(E) -> - case E#remote.pid of - Pid -> E#remote{pid = undefined}; - _ -> E - end end, Remotes), - NewToken = Token#token{remotes = NewRemotes}, - NewState = State#state{tokens = Tokens#{TokName := NewToken}}, - {noreply, NewState}; + #{TokName := TokenIn} = Tokens, + Remotes = lists:map(fun(E) -> + case E#remote.pid of + Pid -> E#remote{pid = undefined}; + _ -> E + end + end, TokenIn#token.remotes), + Token = TokenIn#token{remotes = Remotes}, + {noreply, S#state{tokens = Tokens#{TokName := Token}}}; + handle_cast(Cast, State) -> lager:debug("Unhandled cast: ~p~n", [Cast]), {noreply, State}. |