reverse_protocol.erl 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. %% Feel free to use, reuse and abuse the code in this file.
  2. -module(reverse_protocol).
  3. -behaviour(gen_server).
  4. -behaviour(ranch_protocol).
  5. %% API.
  6. -export([start_link/4]).
  7. %% gen_server.
  8. -export([init/1]).
  9. -export([init/4]).
  10. -export([handle_call/3]).
  11. -export([handle_cast/2]).
  12. -export([handle_info/2]).
  13. -export([terminate/2]).
  14. -export([code_change/3]).
  15. -define(TIMEOUT, 5000).
  16. -record(state, {socket, transport}).
  17. %% API.
  18. start_link(Ref, Socket, Transport, Opts) ->
  19. proc_lib:start_link(?MODULE, init, [Ref, Socket, Transport, Opts]).
  20. %% gen_server.
  21. %% This function is never called. We only define it so that
  22. %% we can use the -behaviour(gen_server) attribute.
  23. init([]) -> {ok, undefined}.
  24. init(Ref, Socket, Transport, _Opts = []) ->
  25. ok = proc_lib:init_ack({ok, self()}),
  26. ok = ranch:accept_ack(Ref),
  27. ok = Transport:setopts(Socket, [{active, once}]),
  28. gen_server:enter_loop(?MODULE, [],
  29. #state{socket=Socket, transport=Transport},
  30. ?TIMEOUT).
  31. handle_info({tcp, Socket, Data}, State=#state{
  32. socket=Socket, transport=Transport}) ->
  33. Transport:setopts(Socket, [{active, once}]),
  34. Transport:send(Socket, reverse_binary(Data)),
  35. {noreply, State, ?TIMEOUT};
  36. handle_info({tcp_closed, _Socket}, State) ->
  37. {stop, normal, State};
  38. handle_info({tcp_error, _, Reason}, State) ->
  39. {stop, Reason, State};
  40. handle_info(timeout, State) ->
  41. {stop, normal, State};
  42. handle_info(_Info, State) ->
  43. {stop, normal, State}.
  44. handle_call(_Request, _From, State) ->
  45. {reply, ok, State}.
  46. handle_cast(_Msg, State) ->
  47. {noreply, State}.
  48. terminate(_Reason, _State) ->
  49. ok.
  50. code_change(_OldVsn, State, _Extra) ->
  51. {ok, State}.
  52. %% Internal.
  53. reverse_binary(B) when is_binary(B) ->
  54. [list_to_binary(lists:reverse(binary_to_list(
  55. binary:part(B, {0, byte_size(B)-2})
  56. ))), "\r\n"].