|
|
@ -3,6 +3,8 @@ |
|
|
|
-export([ |
|
|
|
start_link/1 |
|
|
|
, init/2 |
|
|
|
, accept_loop/2 |
|
|
|
, trace_loop/2 |
|
|
|
]). |
|
|
|
|
|
|
|
%% sys callbacks |
|
|
@ -31,7 +33,7 @@ init(Parent, Port) -> |
|
|
|
|
|
|
|
accept(State = #state{lSocket = LSocket}) -> |
|
|
|
{ok, AcceptRef} = prim_inet:async_accept(LSocket, -1), |
|
|
|
accept_loop(State, AcceptRef). |
|
|
|
?n>MODULE:accept_loop(State, AcceptRef). |
|
|
|
|
|
|
|
accept_loop(State = #state{parent = Parent, lSocket = LSocket}, AcceptRef) -> |
|
|
|
receive |
|
|
@ -40,13 +42,13 @@ accept_loop(State = #state{parent = Parent, lSocket = LSocket}, AcceptRef) -> |
|
|
|
{'EXIT', Parent, Reason} -> |
|
|
|
exit(Reason); |
|
|
|
{inet_async, LSocket, AcceptRef, {ok, CSocket}} -> |
|
|
|
trace_loop(set_timeout(State), CSocket); |
|
|
|
?n>MODULE:trace_loop(set_timeout(State), CSocket); |
|
|
|
{inet_async, LSocket, AcceptRef, Error} -> |
|
|
|
exit({accept_error, Error}); |
|
|
|
_ -> |
|
|
|
%% We discard all trace events when no client is connected. |
|
|
|
%% We may also end up discarding old timeouts or TCP messages. |
|
|
|
accept_loop(State, AcceptRef) |
|
|
|
?n>MODULE:accept_loop(State, AcceptRef) |
|
|
|
end. |
|
|
|
|
|
|
|
trace_loop(State = #state{parent = Parent, timerRef = TRef}, CSocket) -> |
|
|
@ -57,7 +59,7 @@ trace_loop(State = #state{parent = Parent, timerRef = TRef}, CSocket) -> |
|
|
|
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], {trace_loop, State, CSocket}); |
|
|
|
%% Reset the timeout when we receive data. |
|
|
|
{tcp, CSocket, _} -> |
|
|
|
trace_loop(reset_timeout(State), CSocket); |
|
|
|
?n>MODULE:trace_loop(reset_timeout(State), CSocket); |
|
|
|
{tcp_closed, CSocket} -> |
|
|
|
close(State, CSocket); |
|
|
|
{tcp_error, CSocket, _} -> |
|
|
@ -66,26 +68,26 @@ trace_loop(State = #state{parent = Parent, timerRef = TRef}, CSocket) -> |
|
|
|
close(State, CSocket); |
|
|
|
%% Discard the non-blocking send reply when successful. |
|
|
|
{inet_reply, CSocket, ok} -> |
|
|
|
trace_loop(State, CSocket); |
|
|
|
?n>MODULE:trace_loop(State, CSocket); |
|
|
|
%% And close the socket when an error occured. |
|
|
|
{inet_reply, CSocket, _} -> |
|
|
|
close(State, CSocket); |
|
|
|
%% Discard TCP messages from closed sockets. |
|
|
|
{tcp, _, _} -> |
|
|
|
trace_loop(State, CSocket); |
|
|
|
?n>MODULE:trace_loop(State, CSocket); |
|
|
|
{tcp_closed, _} -> |
|
|
|
trace_loop(State, CSocket); |
|
|
|
?n>MODULE:trace_loop(State, CSocket); |
|
|
|
{tcp_error, _, _} -> |
|
|
|
trace_loop(State, CSocket); |
|
|
|
?n>MODULE:trace_loop(State, CSocket); |
|
|
|
%% Discard any previous timeout. |
|
|
|
{timeout, _, ?MODULE} -> |
|
|
|
trace_loop(State, CSocket); |
|
|
|
?n>MODULE:trace_loop(State, CSocket); |
|
|
|
Msg -> |
|
|
|
Bin = term_to_binary(Msg), |
|
|
|
_ = byte_size(Bin), |
|
|
|
case erlang:port_command(CSocket, <<Bin/binary>>, [nosuspend]) of |
|
|
|
true -> |
|
|
|
trace_loop(State, CSocket); |
|
|
|
?n>MODULE:trace_loop(State, CSocket); |
|
|
|
%% The send buffer is full. |
|
|
|
false -> |
|
|
|
close(State, CSocket) |
|
|
@ -99,9 +101,9 @@ close(State, CSocket) -> |
|
|
|
system_continue(_, _, {LoopTag = accept_loop, State, LoopArgs}) -> |
|
|
|
case LoopTag of |
|
|
|
accept_loop -> |
|
|
|
accept_loop(State, LoopArgs); |
|
|
|
?n>MODULE:accept_loop(State, LoopArgs); |
|
|
|
trace_loop -> |
|
|
|
trace_loop(State, LoopArgs) |
|
|
|
?n>MODULE:trace_loop(State, LoopArgs) |
|
|
|
end. |
|
|
|
|
|
|
|
-spec system_terminate(any(), _, _, _) -> no_return(). |
|
|
|