From 581b6954d344eaca2bfcdab663019796e852c778 Mon Sep 17 00:00:00 2001 From: Jan Uhlig Date: Wed, 1 Sep 2021 14:01:47 +0200 Subject: Update docs and modernize examples * Use the map form for transport options everywhere * Remove mentions of the list form for transport options * Use a state enter call instead of gen_statem:enter_loop/4 and proc_lib:start_link/3 in the tcp_reverse example * Take care of different EOLs in the tcp_reverse example * Mention state enter calls, the next_event action, and {continue, ...} in the docs for how to use gen_statem and gen_server --- examples/tcp_reverse/src/reverse_protocol.erl | 38 ++++++++++++++++++--------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'examples') diff --git a/examples/tcp_reverse/src/reverse_protocol.erl b/examples/tcp_reverse/src/reverse_protocol.erl index d274b3a..73d7aff 100644 --- a/examples/tcp_reverse/src/reverse_protocol.erl +++ b/examples/tcp_reverse/src/reverse_protocol.erl @@ -16,28 +16,29 @@ -define(TIMEOUT, 60000). --record(state, {socket, transport}). +-record(state, {ref, transport, socket}). %% API. start_link(Ref, Transport, Opts) -> - {ok, proc_lib:spawn_link(?MODULE, init, [{Ref, Transport, Opts}])}. + gen_statem:start_link(?MODULE, {Ref, Transport, Opts}, []). %% gen_statem. callback_mode() -> - state_functions. + [state_functions, state_enter]. init({Ref, Transport, _Opts = []}) -> + {ok, connected, #state{ref=Ref, transport=Transport}, ?TIMEOUT}. + +connected(enter, connected, StateData=#state{ + ref=Ref, transport=Transport}) -> {ok, Socket} = ranch:handshake(Ref), ok = Transport:setopts(Socket, [{active, once}, {packet, line}]), - gen_statem:enter_loop(?MODULE, [], connected, - #state{socket=Socket, transport=Transport}, - [?TIMEOUT]). - + {keep_state, StateData#state{socket=Socket}}; connected(info, {tcp, Socket, Data}, _StateData=#state{ socket=Socket, transport=Transport}) - when byte_size(Data) > 1 -> + when byte_size(Data) >= 1 -> Transport:setopts(Socket, [{active, once}]), Transport:send(Socket, reverse_binary(Data)), {keep_state_and_data, ?TIMEOUT}; @@ -57,7 +58,7 @@ connected(_EventType, _Msg, _StateData) -> terminate(Reason, StateName, StateData=#state{ socket=Socket, transport=Transport}) - when Socket=/=undefined andalso Transport=/=undefined -> + when Socket=/=undefined, Transport=/=undefined -> catch Transport:close(Socket), terminate(Reason, StateName, StateData#state{socket=undefined, transport=undefined}); @@ -69,7 +70,18 @@ code_change(_OldVsn, StateName, StateData, _Extra) -> %% Internal. -reverse_binary(B) when is_binary(B) -> - [list_to_binary(lists:reverse(binary_to_list( - binary:part(B, {0, byte_size(B)-2}) - ))), "\r\n"]. +reverse_binary(B0) when is_binary(B0) -> + Size = bit_size(B0), + <> = B0, + case <> of + %% Take care of different possible line terminators. + <<$\n, $\r, B2/binary>> -> + %% CR/LF (Windows) + <>; + <<$\n, B2/binary>> -> + %% LF (Linux, Mac OS X and later) + <>; + <<$\r, B2/binary>> -> + %% CR (Mac Classic, ie prior to Mac OS X) + <> + end. -- cgit v1.2.3