aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ejabberd_s2s_out.erl39
1 files changed, 37 insertions, 2 deletions
diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl
index 7cfb68d7a..907bdd65a 100644
--- a/src/ejabberd_s2s_out.erl
+++ b/src/ejabberd_s2s_out.erl
@@ -44,6 +44,7 @@
wait_for_features/2,
wait_for_auth_result/2,
wait_for_starttls_proceed/2,
+ relay_to_bridge/2,
reopen_socket/2,
wait_before_retry/2,
stream_established/2,
@@ -72,6 +73,7 @@
myname, server, queue,
delay_to_retry = undefined_delay,
new = false, verify = false,
+ bridge,
timer}).
%%-define(DBGFSM, true).
@@ -228,8 +230,19 @@ open_socket(init, StateData) ->
{error, _Reason} ->
?INFO_MSG("s2s connection: ~s -> ~s (remote server not found)",
[StateData#state.myname, StateData#state.server]),
- wait_before_reconnect(StateData)
- %%{stop, normal, StateData}
+ case ejabberd_hooks:run_fold(find_s2s_bridge,
+ undefined,
+ [StateData#state.myname,
+ StateData#state.server]) of
+ {Mod, Fun, Type} ->
+ ?INFO_MSG("found a bridge to ~s for: ~s -> ~s",
+ [Type, StateData#state.myname,
+ StateData#state.server]),
+ NewStateData = StateData#state{bridge={Mod, Fun}},
+ {next_state, relay_to_bridge, NewStateData};
+ _ ->
+ wait_before_reconnect(StateData)
+ end
end;
open_socket(stop, StateData) ->
?INFO_MSG("s2s connection: ~s -> ~s (stopped in open socket)",
@@ -677,6 +690,15 @@ reopen_socket(closed, StateData) ->
wait_before_retry(_Event, StateData) ->
{next_state, wait_before_retry, StateData, ?FSMTIMEOUT}.
+relay_to_bridge(stop, StateData) ->
+ wait_before_reconnect(StateData);
+relay_to_bridge(closed, StateData) ->
+ ?INFO_MSG("relay to bridge: ~s -> ~s (closed)",
+ [StateData#state.myname, StateData#state.server]),
+ {stop, normal, StateData};
+relay_to_bridge(_Event, StateData) ->
+ {next_state, relay_to_bridge, StateData}.
+
stream_established({xmlstreamelement, El}, StateData) ->
?DEBUG("s2S stream established", []),
case is_verify_res(El) of
@@ -827,6 +849,19 @@ handle_info({send_element, El}, StateName, StateData) ->
wait_before_retry ->
bounce_element(El, ?ERR_REMOTE_SERVER_NOT_FOUND),
{next_state, StateName, StateData};
+ relay_to_bridge ->
+ %% In this state we relay all outbound messages
+ %% to a foreign protocol bridge such as SMTP, SIP, etc.
+ {Mod, Fun} = StateData#state.bridge,
+ ?DEBUG("relaying stanza via ~p:~p/1", [Mod, Fun]),
+ case catch Mod:Fun(El) of
+ {'EXIT', Reason} ->
+ ?ERROR_MSG("Error while relaying to bridge: ~p", [Reason]),
+ bounce_element(El, ?ERR_INTERNAL_SERVER_ERROR),
+ wait_before_reconnect(StateData);
+ _ ->
+ {next_state, StateName, StateData}
+ end;
_ ->
Q = queue:in(El, StateData#state.queue),
{next_state, StateName, StateData#state{queue = Q},