2
votes

I am developing an SSL server application that is supposed to accept connections and respond in a simple fashion. I have created the skeleton of the application in a regular Erlang script which has been tested in the Erlang shell. This approach worked flawlessly, but when trying to implement it in Rebar the module stopped working.

My module looks like this (called api):

-define(SSL_OPTIONS, [{active, false}, {reuseaddr, true}, {certfile,"../priv/certificate.pem"}, {keyfile,"../priv/key.pem"}]).
start() ->
    try
        ssl:start(),
        Pid = listen(3000),
        {ok, Pid}
    catch
        _:_ -> error
    end.

listen(Port) ->
    {ok, LSocket} = ssl:listen(Port, ?SSL_OPTIONS),
    spawn(fun() -> accept(LSocket) end).

accept(LSocket) ->
    {ok, Socket} = ssl:transport_accept(LSocket),
    Pid = spawn(fun() -> communicator:loop(Socket) end),
    ssl:controlling_process(Socket, Pid),
    ?MODULE:accept(LSocket).

My implementation of the Rebar app looks like follows (called redirector_app):

-module(redirector_app).

-behaviour(application).

%% Application callbacks
-export([start/2, stop/1]).

%% ===================================================================
%% Application callbacks
%% ===================================================================

start(_StartType, _StartArgs) ->
    redirector_sup:start_link(),
    spawn(fun() -> init() end).

stop(_State) ->
    ok.

init() ->
    api:start(),
    ok.

I can start the api module by going into the ebin folder, where the .beam files are located and running the Erlang shell. Within the Erlang shell I run the command:

api:start().

However, when I try to run the Rebar app from the same folder and same shell with:

redirector_app:start([],[]).

I receive the following error:

Error in process <0.50.0> with exit value: {{badmatch,{error,einval}},[{ssl,transport_accept,2,[{file,"ssl.erl"},{line,197}]},{api,accept,1,[{file,"src/api.erl"},{line,25}]}]}

This doesn't change if I go to the root of the Rebar app and run the Erlang shell with:

$ erl -pa ebin/

I have narrowed the problem down to an issue with the connection. I think the connection actually closes before ssl:transport_accept(LSocket) is run.

1
your redirector_app:start/2 function should return {ok, pid()}. Ideally you should start a supervisor there and start other processes from that supervisor as children. I don't think this is going to solve your problem anyhow. Try changing your cert path from '../priv/....' to 'priv/...' and run from the root of your app with erl -pa ebin. I would read up on the links Dmitry listed. You should lists your dependencies in your .app file (.app.src and rebar will take care of rest) and make sure they are started before your app is started (in case your are not using a release).cashmere
oh and start your app by application:start(redirector) not redirector_app:start([],[])cashmere

1 Answers

1
votes

Rebar app is the rebar itself. And what you do is called Erlang application. You can check documentation right here: http://www.erlang.org/doc/design_principles/applications.html

Erlang applications start differently. You must use application:start(redirector). It also means you must have redirector.app file in your ebin (or other search path) which must have {mod, {redirector_app,[]}}. You must ensure that all applications that you depend on are started before your application, this may be done automatically if you use Erlang releases http://www.erlang.org/doc/design_principles/release_structure.html

I recommend you to read an article http://www.metabrew.com/article/erlang-rebar-tutorial-generating-releases-upgrades