Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation on usage of ranch with gen_server as protocol handler #104

Closed
josemic opened this issue Feb 12, 2015 · 3 comments
Closed

Comments

@josemic
Copy link

josemic commented Feb 12, 2015

Here is an improved example for the documentation in the file protocols.md:

%% Feel free to use, reuse and abuse the code in this file.

-module(my_echo_protocol).
-behaviour(ranch_protocol).
-behaviour(gen_server).

-export([start_link/4]).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
     terminate/2, code_change/3]).

-record(state, {ref, socket, transport, opts}).

-define(SERVER, ?MODULE).

start_link(Ref, Socket, Transport, Opts) ->
    gen_server:start_link(?MODULE, [Ref, Socket, Transport, Opts], []).

%% Alternative A: 
init([Ref, Socket, Transport, Opts]) ->
    %% the 0 at the follwing line sets the timeout to 0, thus the 
    %%
    {ok, #state{ref=Ref, socket=Socket, transport=Transport, opts= Opts}, 0}.

% Alternative B: Uncomment this and comment alternative A    
%init([Ref, Socket, Transport, Opts=[]]) ->
%    ok = proc_lib:init_ack({ok, self()}),
%    %% Perform any required state initialization here.
%    ok = ranch:accept_ack(Ref),
%    ok = Transport:setopts(Socket, [{active, once}]),
%    gen_server:enter_loop(?MODULE, [], #state{ref=Ref, socket=Socket, transport=Transport, opts= Opts}).

handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

%% The following timeout handling is only used in conjunction with alternative A
handle_info(timeout, State=#state{ref=Ref, socket=Socket, transport=Transport}) ->
    ok = ranch:accept_ack(Ref),
    ok = Transport:setopts(Socket, [{active, once}]),
    {noreply, State};

handle_info({tcp, Socket, Data}, State=#state{socket=Socket, transport=Transport}) ->
    Transport:setopts(Socket, [{active, once}]),
    Transport:send(Socket, reverse_binary(Data)),
    {noreply, State};
handle_info({tcp_closed, Socket}, State) ->
    {stop, normal, State};
handle_info({tcp_error, Socket, Reason}, State) ->
    {stop, Reason, State}.    
handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.


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"].
@essen
Copy link
Member

essen commented Mar 6, 2015

Hey, any chance you can submit a PR editing the file? Both ways to do it need to be separate.

@essen
Copy link
Member

essen commented Aug 21, 2015

After reviewing this, here's what I want (no worries, I will do it):

  • Remove the example with the timeout, it's terrible
  • Update the remaining example by having a init/1 instead of init/4 (so we don't get a behavior related warning)
  • Make an actual example out of this
  • Make another example with gen_fsm

@josemic
Copy link
Author

josemic commented Aug 21, 2015

I agree. These are appreciated improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants