aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_c2s.erl24
-rw-r--r--src/ejabberd_odbc.erl2
-rw-r--r--src/mod_sip.erl21
-rw-r--r--src/mod_sip_proxy.erl54
-rw-r--r--src/mod_sip_registrar.erl7
5 files changed, 78 insertions, 30 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 1076eb895..6aebefdd6 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -1170,8 +1170,7 @@ session_established({xmlstreamerror, _}, StateData) ->
{stop, normal, StateData};
session_established(closed, StateData)
when StateData#state.mgmt_timeout > 0,
- StateData#state.mgmt_state == active orelse
- StateData#state.mgmt_state == pending ->
+ StateData#state.mgmt_state == active ->
log_pending_state(StateData),
fsm_next_state(wait_for_resume, StateData#state{mgmt_state = pending});
session_established(closed, StateData) ->
@@ -1312,8 +1311,8 @@ handle_sync_event(get_subscribed, _From, StateName,
StateData) ->
Subscribed = (?SETS):to_list(StateData#state.pres_f),
{reply, Subscribed, StateName, StateData};
-handle_sync_event(resume_session, _From, _StateName,
- StateData) ->
+handle_sync_event({resume_session, Time}, _From, _StateName,
+ StateData) when element(1, StateData#state.sid) == Time ->
%% The old session should be closed before the new one is opened, so we do
%% this here instead of leaving it to the terminate callback
ejabberd_sm:close_session(StateData#state.sid,
@@ -1321,6 +1320,9 @@ handle_sync_event(resume_session, _From, _StateName,
StateData#state.server,
StateData#state.resource),
{stop, normal, {ok, StateData}, StateData#state{mgmt_state = resumed}};
+handle_sync_event({resume_session, _Time}, _From, StateName,
+ StateData) ->
+ {reply, {error, <<"Previous session not found">>}, StateName, StateData};
handle_sync_event(_Event, _From, StateName,
StateData) ->
Reply = ok, fsm_reply(Reply, StateName, StateData).
@@ -1373,7 +1375,6 @@ handle_info({route, _From, _To, {broadcast, Data}},
fsm_next_state(StateName, StateData);
NewPL ->
PrivPushIQ = #iq{type = set,
- xmlns = ?NS_PRIVACY,
id = <<"push",
(randoms:get_string())/binary>>,
sub_el =
@@ -2549,8 +2550,7 @@ route_blocking(What, StateData) ->
#xmlel{name = <<"unblock">>,
attrs = [{<<"xmlns">>, ?NS_BLOCKING}], children = []}
end,
- PrivPushIQ = #iq{type = set, xmlns = ?NS_BLOCKING,
- id = <<"push">>, sub_el = [SubEl]},
+ PrivPushIQ = #iq{type = set, id = <<"push">>, sub_el = [SubEl]},
PrivPushEl =
jlib:replace_from_to(jlib:jid_remove_resource(StateData#state.jid),
StateData#state.jid, jlib:iq_to_xml(PrivPushIQ)),
@@ -2902,8 +2902,8 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) ->
{error, <<"Previous session PID not found">>};
OldPID ->
OldSID = {Time, OldPID},
- case catch resume_session(OldPID) of
- {ok, #state{sid = OldSID} = OldStateData} ->
+ case catch resume_session(OldSID) of
+ {ok, OldStateData} ->
NewSID = {Time, self()}, % Old time, new PID
Priority = case OldStateData#state.pres_last of
undefined ->
@@ -2935,6 +2935,8 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) ->
mgmt_stanzas_in = OldStateData#state.mgmt_stanzas_in,
mgmt_stanzas_out = OldStateData#state.mgmt_stanzas_out,
mgmt_state = active}};
+ {error, Msg} ->
+ {error, Msg};
_ ->
{error, <<"Cannot grab session state">>}
end
@@ -2943,8 +2945,8 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) ->
{error, <<"Invalid 'previd' value">>}
end.
-resume_session(FsmRef) ->
- (?GEN_FSM):sync_send_all_state_event(FsmRef, resume_session, 3000).
+resume_session({Time, PID}) ->
+ (?GEN_FSM):sync_send_all_state_event(PID, {resume_session, Time}, 3000).
make_resume_id(StateData) ->
{Time, _} = StateData#state.sid,
diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl
index 2b852bfaa..49a4f30b4 100644
--- a/src/ejabberd_odbc.erl
+++ b/src/ejabberd_odbc.erl
@@ -588,7 +588,7 @@ db_opts(Host) ->
[odbc, Server];
_ ->
Port = ejabberd_config:get_option(
- {port, Host},
+ {odbc_port, Host},
fun(P) when is_integer(P), P > 0, P < 65536 -> P end,
case Type of
mysql -> ?MYSQL_PORT;
diff --git a/src/mod_sip.erl b/src/mod_sip.erl
index 8ed4ed8cf..4b733c623 100644
--- a/src/mod_sip.erl
+++ b/src/mod_sip.erl
@@ -12,7 +12,7 @@
-behaviour(esip).
%% API
--export([start/2, stop/1, prepare_request/1, make_response/2, at_my_host/1]).
+-export([start/2, stop/1, make_response/2, is_my_host/1, at_my_host/1]).
%% esip_callbacks
-export([data_in/2, data_out/2, message_in/2, message_out/2,
@@ -77,6 +77,13 @@ message_out(_, _) ->
response(_Resp, _SIPSock) ->
ok.
+request(#sip{method = <<"ACK">>} = Req, SIPSock) ->
+ case action(Req, SIPSock) of
+ {relay, LServer} ->
+ mod_sip_proxy:route(Req, LServer, []);
+ _ ->
+ error
+ end;
request(_Req, _SIPSock) ->
error.
@@ -251,18 +258,6 @@ process(Req, _) ->
make_response(Req, #sip{type = response, status = 405,
hdrs = [{'allow', allow()}]}).
-prepare_request(#sip{hdrs = Hdrs1} = Req) ->
- MF = esip:get_hdr('max-forwards', Hdrs1),
- Hdrs2 = esip:set_hdr('max-forwards', MF-1, Hdrs1),
- Hdrs3 = lists:filter(
- fun({'proxy-authorization', {_, Params}}) ->
- Realm = esip:unquote(esip:get_param(<<"realm">>, Params)),
- not is_my_host(jlib:nameprep(Realm));
- (_) ->
- true
- end, Hdrs2),
- Req#sip{hdrs = Hdrs3}.
-
make_auth_hdr(LServer) ->
Realm = jlib:nameprep(LServer),
{<<"Digest">>, [{<<"realm">>, esip:quote(Realm)},
diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl
index cae75bff8..b05c49061 100644
--- a/src/mod_sip_proxy.erl
+++ b/src/mod_sip_proxy.erl
@@ -12,7 +12,7 @@
-behaviour(?GEN_FSM).
%% API
--export([start/2, start_link/2, route/4]).
+-export([start/2, start_link/2, route/3, route/4]).
%% gen_fsm callbacks
-export([init/1, wait_for_request/2, wait_for_response/2,
@@ -42,6 +42,19 @@ start_link(LServer, Opts) ->
route(SIPMsg, _SIPSock, TrID, Pid) ->
?GEN_FSM:send_event(Pid, {SIPMsg, TrID}).
+route(Req, LServer, Opts) ->
+ Req1 = prepare_request(LServer, Req),
+ case connect(Req1, add_certfile(LServer, Opts)) of
+ {ok, SIPSockets} ->
+ lists:foreach(
+ fun(SIPSocket) ->
+ Req2 = add_via(SIPSocket, LServer, Req1),
+ esip:send(SIPSocket, Req2)
+ end, SIPSockets);
+ _ ->
+ error
+ end.
+
%%%===================================================================
%%% gen_fsm callbacks
%%%===================================================================
@@ -51,7 +64,7 @@ init([Host, Opts]) ->
wait_for_request({#sip{type = request} = Req, TrID}, State) ->
Opts = State#state.opts,
- Req1 = mod_sip:prepare_request(Req),
+ Req1 = prepare_request(State#state.host, Req),
case connect(Req1, Opts) of
{ok, SIPSockets} ->
NewState =
@@ -59,8 +72,9 @@ wait_for_request({#sip{type = request} = Req, TrID}, State) ->
fun(_SIPSocket, {error, _} = Err) ->
Err;
(SIPSocket, #state{tr_ids = TrIDs} = AccState) ->
- Req2 = add_via(SIPSocket, State#state.host, Req1),
- case esip:request(SIPSocket, Req2,
+ Req2 = add_record_route(SIPSocket, State#state.host, Req1),
+ Req3 = add_via(SIPSocket, State#state.host, Req2),
+ case esip:request(SIPSocket, Req3,
{?MODULE, route, [self()]}) of
{ok, ClientTrID} ->
NewTrIDs = [ClientTrID|TrIDs],
@@ -234,6 +248,11 @@ add_via(#sip_socket{type = Transport}, LServer, #sip{hdrs = Hdrs} = Req) ->
{<<"rport">>, <<"">>}]},
Req#sip{hdrs = [{'via', [Via]}|Hdrs]}.
+add_record_route(_SIPSocket, LServer, #sip{hdrs = Hdrs} = Req) ->
+ URI = #uri{host = LServer, params = [{<<"lr">>, <<"">>}]},
+ Hdrs1 = [{'record-route', [{<<>>, URI, []}]}|Hdrs],
+ Req#sip{hdrs = Hdrs1}.
+
get_configured_vias(LServer) ->
gen_mod:get_module_opt(
LServer, ?MODULE, via,
@@ -275,3 +294,30 @@ choose_best_response(#state{responses = Responses} = State) ->
ok
end
end.
+
+prepare_request(Host, #sip{hdrs = Hdrs} = Req) ->
+ Hdrs1 = lists:flatmap(
+ fun({Hdr, HdrList}) when Hdr == 'route';
+ Hdr == 'record-route' ->
+ case lists:filter(
+ fun({_, #uri{user = <<"">>, host = Host1}, _}) ->
+ Host1 /= Host
+ end, HdrList) of
+ [] ->
+ [];
+ HdrList1 ->
+ [{Hdr, HdrList1}]
+ end;
+ (Hdr) ->
+ [Hdr]
+ end, Hdrs),
+ MF = esip:get_hdr('max-forwards', Hdrs1),
+ Hdrs2 = esip:set_hdr('max-forwards', MF-1, Hdrs1),
+ Hdrs3 = lists:filter(
+ fun({'proxy-authorization', {_, Params}}) ->
+ Realm = esip:unquote(esip:get_param(<<"realm">>, Params)),
+ not mod_sip:is_my_host(jlib:nameprep(Realm));
+ (_) ->
+ true
+ end, Hdrs2),
+ Req#sip{hdrs = Hdrs3}.
diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl
index 57c55be08..689efe48e 100644
--- a/src/mod_sip_registrar.erl
+++ b/src/mod_sip_registrar.erl
@@ -57,8 +57,13 @@ request(#sip{hdrs = Hdrs} = Req, SIPSock) ->
ok ->
?INFO_MSG("unregister SIP session for user ~s@~s from ~s",
[LUser, LServer, inet_parse:ntoa(PeerIP)]),
+ Contact = {<<"">>, #uri{user = LUser, host = LServer},
+ [{<<"expires">>, <<"0">>}]},
mod_sip:make_response(
- Req, #sip{type = response, status = 200});
+ Req,
+ #sip{type = response,
+ status = 200,
+ hdrs = [{'contact', [Contact]}]});
{error, Why} ->
{Status, Reason} = make_status(Why),
mod_sip:make_response(