summaryrefslogtreecommitdiff
path: root/p11p-daemon/src/p11p_client.erl
diff options
context:
space:
mode:
Diffstat (limited to 'p11p-daemon/src/p11p_client.erl')
-rw-r--r--p11p-daemon/src/p11p_client.erl117
1 files changed, 95 insertions, 22 deletions
diff --git a/p11p-daemon/src/p11p_client.erl b/p11p-daemon/src/p11p_client.erl
index 7dc3457..87c2949 100644
--- a/p11p-daemon/src/p11p_client.erl
+++ b/p11p-daemon/src/p11p_client.erl
@@ -23,14 +23,18 @@
code_change/3]).
%% Records and types.
+-type token_state() :: started | initialized | session | loggedin | opact | finalized.
+
-record(state, {
token :: string(), % Token name.
timeout :: non_neg_integer(),
port :: port(),
replyto :: pid() | undefined,
+
+ p11state = started :: token_state(),
timer :: reference() | undefined,
- msg :: p11rpc:msg() | undefined,
+ response :: p11rpc:msg() | undefined,
recv_count = 0 :: non_neg_integer(),
send_count = 0 :: non_neg_integer()
}).
@@ -43,7 +47,7 @@ start_link(ServName, TokName, Server, ModPath, ModEnv, Timeout) ->
gen_server:start_link({local, ServName}, ?MODULE,
[TokName, Server, ModPath, ModEnv, Timeout], []).
--spec request(pid(), p11rpc_msg()) -> {ok, non_neg_integer()}.
+-spec request(pid(), p11rpc_msg()) -> ack | nack | {ok, non_neg_integer()}.
request(Client, Request) ->
gen_server:call(Client, {request, Request}).
@@ -70,18 +74,46 @@ init([TokName, Server, ModPath, ModEnv, Timeout]) ->
lager:debug("~p: ~s: module: ~s, env: ~p", [self(), ProxyAppBinPath, ModPath, ModEnv]),
{ok, #state{port = Port, token = TokName, replyto = Server, timeout = Timeout}}.
-handle_call({request, Request}, {FromPid, _Tag},
- #state{port = Port, send_count = Sent} = S) ->
- %%lager:debug("~p: sending request from ~p to prxoy app ~p", [self(), FromPid, Port]),
- D = p11p_rpc:serialise(Request),
- Buf = case Sent of
- 0 -> <<?RPC_VERSION:8, D/binary>>;
- _ -> D
- end,
- {ok, _} = do_send(Port, Buf),
- {reply, {ok, sizeBuf}, S#state{replyto = FromPid,
- timer = start_timer(S#state.timeout, Port),
- send_count = Sent + 1}};
+handle_call({request, Request},
+ {FromPid, _Tag},
+ S = #state{port = Port, send_count = Sent}) ->
+ case
+ case S#state.p11state of
+ started ->
+ case p11p_rpc:req_id(Request) of
+ ?P11_RPC_CALL_C_Logout -> ack;
+ ?P11_RPC_CALL_C_CloseSession -> ack;
+ ?P11_RPC_CALL_C_Finalize -> ack;
+
+ ?P11_RPC_CALL_C_Initialize -> pass;
+ ?P11_RPC_CALL_C_OpenSession -> pass;
+ ?P11_RPC_CALL_C_Login -> pass;
+
+ _ -> nack
+ end;
+ _ ->
+ pass
+ end
+ of
+ ack ->
+ {reply, ack, S};
+ nack ->
+ {reply, nack, S};
+ pass ->
+ lager:debug("~p: sending request from ~p to prxoy app ~p", [self(), FromPid, Port]),
+ D = p11p_rpc:serialise(Request),
+ Buf = case Sent of
+ 0 -> <<?RPC_VERSION:8, D/binary>>;
+ _ -> D
+ end,
+ {ok, _} = do_send(Port, Buf),
+
+ {reply,
+ {ok, size(Buf)},
+ S#state{replyto = FromPid,
+ timer = start_timer(S#state.timeout, Port),
+ send_count = Sent + 1}}
+ end;
handle_call(Call, _From, State) ->
lager:debug("~p: Unhandled call: ~p~n", [self(), Call]),
@@ -96,10 +128,10 @@ handle_cast(Cast, State) ->
%% Receiving the very first response from proxy app since it was started.
handle_info({Port, {data, Data}}, State)
- when Port == State#state.port, State#state.msg == undefined ->
+ when Port == State#state.port, State#state.response == undefined ->
case hd(Data) of % First octet is RPC protocol version.
?RPC_VERSION ->
- {noreply, handle_token_data(State, p11p_rpc:new(), tl(Data))};
+ {noreply, response_in(State, p11p_rpc:new(), tl(Data))};
BadVersion ->
lager:info("~p: ~p: invalid RPC version: ~p", [self(), Port,
BadVersion]),
@@ -107,9 +139,9 @@ handle_info({Port, {data, Data}}, State)
end;
%% Receiving more data from proxy app.
-handle_info({Port, {data, Data}}, #state{msg = Msg} = State)
+handle_info({Port, {data, Data}}, #state{response = Msg} = State)
when Port == State#state.port ->
- {noreply, handle_token_data(State, Msg, Data)};
+ {noreply, response_in(State, Msg, Data)};
%% Proxy app timed out.
handle_info({timeout, Timer, Port}, S = #state{token = Tok})
@@ -144,17 +176,18 @@ do_send(Port, Buf) ->
end,
{ok, size(Buf)}.
-handle_token_data(#state{replyto = Pid, timer = Timer, recv_count = Recv} = S,
- MsgIn, DataIn) ->
+response_in(#state{replyto = Pid, timer = Timer, recv_count = Recv} = S,
+ MsgIn, DataIn) ->
case p11p_rpc:parse(MsgIn, list_to_binary(DataIn)) of
{needmore, Msg} ->
- S#state{msg = Msg};
+ S#state{response = Msg};
{done, Msg} ->
cancel_timer(Timer),
lager:debug("~p: <- ~s", [self(), p11p_rpc:dump(Msg)]),
{ok, _BytesSent} = p11p_server:reply(Pid, Msg),
%% Saving potential data not consumed by parse/2 in new message.
- S#state{msg = p11p_rpc:new(Msg#p11rpc_msg.buffer),
+ S#state{response = p11p_rpc:new(Msg#p11rpc_msg.buffer),
+ p11state = runstate(S#state.p11state, p11p_rpc:req_id(Msg)),
recv_count = Recv + 1}
end.
@@ -165,3 +198,43 @@ start_timer(Timeout, Port) ->
cancel_timer(Timer) ->
%%lager:debug("~p: canceling timer", [self()]),
erlang:cancel_timer(Timer, [{async, true}, {info, false}]).
+
+-spec runstate(token_state(), non_neg_integer()) -> token_state().
+runstate(started, ReqId) ->
+ case ReqId of
+ ?P11_RPC_CALL_C_Initialize ->
+ initialized;
+ _ ->
+ started
+ end;
+runstate(initialized, ReqId) ->
+ case ReqId of
+ ?P11_RPC_CALL_C_OpenSession ->
+ session;
+ ?P11_RPC_CALL_C_Finalize ->
+ finalized;
+ _ ->
+ initialized
+ end;
+runstate(session, ReqId) ->
+ case ReqId of
+ ?P11_RPC_CALL_C_Login ->
+ loggedin;
+ ?P11_RPC_CALL_C_CloseSession ->
+ initialized;
+ ?P11_RPC_CALL_C_Finalize ->
+ finalized;
+ _ ->
+ session
+ end;
+runstate(loggedin, ReqId) ->
+ case ReqId of
+ ?P11_RPC_CALL_C_Logout ->
+ session;
+ ?P11_RPC_CALL_C_CloseSession ->
+ initialized;
+ ?P11_RPC_CALL_C_Finalize ->
+ finalized;
+ _ ->
+ loggedin
+ end.