Search code examples
sslasynchronouserlangejabberdgen-server

erlang: receive response from ssl


I added a new module (-behavior(gen_mod)) inside ejabberd and I was able to open a ssl connection to a server and send a message directly using the ssl connection(ssl:send() function). However, I am unable to receive response after this.

  • I tried using the receive option in erlang to catch messages, and still no luck.
  • I tried changing the module to be a stateful module by using the gen_server behavior and I still don't observe any handle_info calls with any message.
  • I could not get any response using ssl:recv/2 either.

Am I missing something? How do I asynchronously receive the response from the ssl socket in erlang?

Any pointers would be really appreciated. Thank you!

code: Adding only relevant parts of the code.

sendPacketToServer() ->
 case ssl:connect(Gateway, Port, Options, ?SSL_TIMEOUT) of
        {ok, Socket} ->
            ssl:controlling_process(Socket, self()),
            Packet = .....,
            Result = ssl:send(Socket, Packet),
            receiveMessage(),
            ssl:close(Socket),
            ?INFO_MSG("~n~n~n~n Successfully sent payload to the server, result: ~p for the user: ~p", [Result, Username]);
        {error, Reason} = Err ->
            ?ERROR_MSG("Unable to connect to the server: ~s for the user: ~p", [ssl:format_error(Reason), Username]),
            Err
 end
...
....
receiveMessage() ->
  receive ->
      {ssl, Msg, Data} ->  % incoming msg from SSL, send it to process
      ......
    {ssl_closed, Msg} ->  % incoming msg from SSL, send it to process
      .....
    {ssl_error, Msg} ->  % incoming msg from SSL, send it to process
      .....
    {ssl_passive, Msg} ->  % incoming msg from SSL, send it to process
      ....
  end.

Added the following code for gen_server: (when doing the following, i do not close the socket immediately, but it still does not work).

start(Host, Opts) ->
        gen_mod:start_child(?MODULE, Host, Opts).
stop(Host) ->
        gen_mod:stop_child(?MODULE, Host).
init([ServerHost|_]) ->
    Opts = gen_mod:get_module_opts(ServerHost, ?MODULE),
    start(ServerHost, Opts),
    {ok, #state{host = ServerHost}}.

handle_call(Request, From, State) ->
    ?WARNING_MSG("Unexpected call from ~p: ~p", [From, Request]),
    {noreply, State}.
handle_cast(Msg, State) ->
    ?WARNING_MSG("Unexpected cast: ~p", [Msg]),
    {noreply, State}.
handle_info(Info, State) ->
    ?WARNING_MSG("Unexpected info: ~p", [Info]),
    {noreply, State}.
terminate(_Reason, State) ->
    ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.

Solution

  • I was able to overcome the problem by using a gen_server module, since it has explicit callbacks for any messages.