aboutsummaryrefslogtreecommitdiff
path: root/src/mod_multicast.erl
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2015-08-05 19:17:58 +0300
committerAlexey Shchepin <alexey@process-one.net>2015-08-05 19:21:28 +0300
commit4125dfd166067b4c613bd8d49eef5f876fdb1b94 (patch)
tree600de3b244e155e15f188042c6b2f8a8a99a957e /src/mod_multicast.erl
parentUse websocket pings also on old style connections (diff)
mod_multicast changes:
- catch exceptions - do ets:give_away for multicastp table on init - don't send multicasts to itself - don't check user@server for multicast support - handle empty disco items - ignore cdata in <addresses/> - properly check for subdomains
Diffstat (limited to 'src/mod_multicast.erl')
-rw-r--r--src/mod_multicast.erl122
1 files changed, 81 insertions, 41 deletions
diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl
index b39a391be..0abf4215c 100644
--- a/src/mod_multicast.erl
+++ b/src/mod_multicast.erl
@@ -153,24 +153,11 @@ handle_cast(_Msg, State) -> {noreply, State}.
handle_info({route, From, To,
#xmlel{name = <<"iq">>, attrs = Attrs} = Packet},
State) ->
- IQ = jlib:iq_query_info(Packet),
- case catch process_iq(From, IQ, State) of
- Result when is_record(Result, iq) ->
- ejabberd_router:route(To, From, jlib:iq_to_xml(Result));
- {'EXIT', Reason} ->
- ?ERROR_MSG("Error when processing IQ stanza: ~p",
- [Reason]),
- Err = jlib:make_error_reply(Packet,
- ?ERR_INTERNAL_SERVER_ERROR),
- ejabberd_router:route(To, From, Err);
- reply ->
- LServiceS = jts(To),
- case xml:get_attr_s(<<"type">>, Attrs) of
- <<"result">> ->
- process_iqreply_result(From, LServiceS, Packet, State);
- <<"error">> ->
- process_iqreply_error(From, LServiceS, Packet)
- end
+ case catch handle_iq(From, To, #xmlel{attrs = Attrs} = Packet, State) of
+ {'EXIT', Reason} ->
+ ?ERROR_MSG("Error when processing IQ stanza: ~p",
+ [Reason]);
+ _ -> ok
end,
{noreply, State};
%% XEP33 allows only 'message' and 'presence' stanza type
@@ -188,11 +175,16 @@ handle_info({route, From, To,
handle_info({route_trusted, From, Destinations, Packet},
#state{lservice = LServiceS, lserver = LServerS} =
State) ->
- route_trusted(LServiceS, LServerS, From, Destinations,
- Packet),
+ case catch route_trusted(LServiceS, LServerS, From, Destinations,
+ Packet) of
+ {'EXIT', Reason} ->
+ ?ERROR_MSG("Error in route_trusted: ~p", [Reason]);
+ _ -> ok
+ end,
{noreply, State};
handle_info({get_host, Pid}, State) ->
- Pid ! {my_host, State#state.lservice}, {noreply, State};
+ Pid ! {my_host, State#state.lservice},
+ {noreply, State};
handle_info(_Info, State) -> {noreply, State}.
terminate(_Reason, State) ->
@@ -210,6 +202,28 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
%%% IQ Request Processing
%%%------------------------
+handle_iq(From, To, #xmlel{attrs = Attrs} = Packet, State) ->
+ IQ = jlib:iq_query_info(Packet),
+ case catch process_iq(From, IQ, State) of
+ Result when is_record(Result, iq) ->
+ ejabberd_router:route(To, From, jlib:iq_to_xml(Result));
+ {'EXIT', Reason} ->
+ ?ERROR_MSG("Error when processing IQ stanza: ~p",
+ [Reason]),
+ Err = jlib:make_error_reply(Packet,
+ ?ERR_INTERNAL_SERVER_ERROR),
+ ejabberd_router:route(To, From, Err);
+ reply ->
+ LServiceS = jts(To),
+ case xml:get_attr_s(<<"type">>, Attrs) of
+ <<"result">> ->
+ process_iqreply_result(From, LServiceS, Packet, State);
+ <<"error">> ->
+ process_iqreply_error(From, LServiceS, Packet)
+ end;
+ ok -> ok
+ end.
+
process_iq(From,
#iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} =
IQ,
@@ -377,6 +391,9 @@ perform(From, Packet, AAttrs, LServiceS,
group = Group, renewal = true, sender = From,
packet = Packet, aattrs = AAttrs,
addresses = Group#group.addresses});
+perform(_From, _Packet, _AAttrs, LServiceS,
+ {{ask, LServiceS, _}, _Group}) ->
+ ok;
perform(From, Packet, AAttrs, LServiceS,
{{ask, Server, not_renewal}, Group}) ->
send_query_info(Server, LServiceS),
@@ -411,7 +428,7 @@ strip_addresses_element(Packet) ->
Els_stripped = lists:keydelete(<<"addresses">>, 2, Els),
Packet_stripped = #xmlel{name = Name, attrs = Attrs,
children = Els_stripped},
- {ok, Packet_stripped, AAttrs, Addresses};
+ {ok, Packet_stripped, AAttrs, xml:remove_cdata(Addresses)};
_ -> throw(ewxmlns)
end;
_ -> throw(eadsele)
@@ -646,7 +663,8 @@ check_relay(RS, LS, Gs) ->
end.
check_relay_required(RServer, LServerS, Groups) ->
- case str:str(RServer, LServerS) > 0 of
+ case lists:suffix(str:tokens(LServerS, <<".">>),
+ str:tokens(RServer, <<".">>)) of
true -> false;
false -> check_relay_required(LServerS, Groups)
end.
@@ -830,29 +848,44 @@ get_limits_values(Values) ->
%%%-------------------------
process_discoitems_result(From, LServiceS, Els) ->
- List = lists:foldl(fun (XML, Res) ->
- case XML of
- #xmlel{name = <<"item">>, attrs = Attrs} ->
- Res ++ [xml:get_attr_s(<<"jid">>, Attrs)];
- _ -> Res
- end
- end,
- [], Els),
- [send_query_info(Item, LServiceS) || Item <- List],
FromS = jts(From),
- {found_waiter, Waiter} = search_waiter(FromS, LServiceS,
- items),
- delo_waiter(Waiter),
- add_waiter(Waiter#waiter{awaiting =
- {List, LServiceS, info},
- renewal = false}).
+ case search_waiter(FromS, LServiceS, items) of
+ {found_waiter, Waiter} ->
+ List = lists:foldl(
+ fun(XML, Res) ->
+ case XML of
+ #xmlel{name = <<"item">>, attrs = Attrs} ->
+ SJID = xml:get_attr_s(<<"jid">>, Attrs),
+ case jlib:string_to_jid(SJID) of
+ #jid{luser = <<"">>,
+ lresource = <<"">>} ->
+ [SJID | Res];
+ _ -> Res
+ end;
+ _ -> Res
+ end
+ end,
+ [], Els),
+ case List of
+ [] ->
+ received_awaiter(FromS, Waiter, LServiceS);
+ _ ->
+ [send_query_info(Item, LServiceS) || Item <- List],
+ delo_waiter(Waiter),
+ add_waiter(Waiter#waiter{awaiting =
+ {List, LServiceS, info},
+ renewal = false})
+ end;
+ _ ->
+ ok
+ end.
%%%-------------------------
%%% Check protocol support: Receive response: Received awaiter
%%%-------------------------
received_awaiter(JID, Waiter, LServiceS) ->
- {JIDs, LServiceS, info} = Waiter#waiter.awaiting,
+ {JIDs, LServiceS, _} = Waiter#waiter.awaiting,
delo_waiter(Waiter),
Group = Waiter#waiter.group,
RServer = Group#group.server,
@@ -984,8 +1017,12 @@ purge_loop(NM) ->
%%%-------------------------
create_pool() ->
- catch ets:new(multicastp,
- [duplicate_bag, public, named_table, {keypos, 2}]).
+ catch
+ begin
+ ets:new(multicastp,
+ [duplicate_bag, public, named_table, {keypos, 2}]),
+ ets:give_away(multicastp, whereis(ejabberd), ok)
+ end.
add_waiter(Waiter) ->
true = ets:insert(multicastp, Waiter).
@@ -993,6 +1030,9 @@ add_waiter(Waiter) ->
delo_waiter(Waiter) ->
true = ets:delete_object(multicastp, Waiter).
+-spec search_waiter(binary(), binary(), info | items) ->
+ {found_waiter, #waiter{}} | waiter_not_found.
+
search_waiter(JID, LServiceS, Type) ->
Rs = ets:foldl(fun (W, Res) ->
{JIDs, LServiceS1, Type1} = W#waiter.awaiting,