aboutsummaryrefslogtreecommitdiffstats
path: root/examples/tcp_reverse/src/reverse_protocol.erl
diff options
context:
space:
mode:
authorJan Uhlig <[email protected]>2021-09-01 14:01:47 +0200
committerLoïc Hoguin <[email protected]>2021-09-01 15:30:34 +0200
commit581b6954d344eaca2bfcdab663019796e852c778 (patch)
treea20ea9f96c9fbd9251fc8c570b4e0ff485bccb98 /examples/tcp_reverse/src/reverse_protocol.erl
parentc7a7cfb9b93f0db9c99ed21c34f67e0b6adfcb62 (diff)
downloadranch-581b6954d344eaca2bfcdab663019796e852c778.tar.gz
ranch-581b6954d344eaca2bfcdab663019796e852c778.tar.bz2
ranch-581b6954d344eaca2bfcdab663019796e852c778.zip
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
Diffstat (limited to 'examples/tcp_reverse/src/reverse_protocol.erl')
-rw-r--r--examples/tcp_reverse/src/reverse_protocol.erl38
1 files changed, 25 insertions, 13 deletions
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),
+ <<B1:Size/integer-little>> = B0,
+ case <<B1:Size/integer-big>> of
+ %% Take care of different possible line terminators.
+ <<$\n, $\r, B2/binary>> ->
+ %% CR/LF (Windows)
+ <<B2/binary, $\r, $\n>>;
+ <<$\n, B2/binary>> ->
+ %% LF (Linux, Mac OS X and later)
+ <<B2/binary, $\n>>;
+ <<$\r, B2/binary>> ->
+ %% CR (Mac Classic, ie prior to Mac OS X)
+ <<B2/binary, $\r>>
+ end.