mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
Experimental MIX (XEP-0369) support
This commit is contained in:
parent
6e40573c13
commit
b5121a346d
@ -157,3 +157,10 @@
|
|||||||
-define(NS_HTTP_UPLOAD_OLD, <<"eu:siacs:conversations:http:upload">>).
|
-define(NS_HTTP_UPLOAD_OLD, <<"eu:siacs:conversations:http:upload">>).
|
||||||
-define(NS_THUMBS_1, <<"urn:xmpp:thumbs:1">>).
|
-define(NS_THUMBS_1, <<"urn:xmpp:thumbs:1">>).
|
||||||
-define(NS_NICK, <<"http://jabber.org/protocol/nick">>).
|
-define(NS_NICK, <<"http://jabber.org/protocol/nick">>).
|
||||||
|
-define(NS_MIX_0, <<"urn:xmpp:mix:0">>).
|
||||||
|
-define(NS_MIX_SERVICEINFO_0, <<"urn:xmpp:mix:0#serviceinfo">>).
|
||||||
|
-define(NS_MIX_NODES_MESSAGES, <<"urn:xmpp:mix:nodes:messages">>).
|
||||||
|
-define(NS_MIX_NODES_PRESENCE, <<"urn:xmpp:mix:nodes:presence">>).
|
||||||
|
-define(NS_MIX_NODES_PARTICIPANTS, <<"urn:xmpp:mix:nodes:participants">>).
|
||||||
|
-define(NS_MIX_NODES_SUBJECT, <<"urn:xmpp:mix:nodes:subject">>).
|
||||||
|
-define(NS_MIX_NODES_CONFIG, <<"urn:xmpp:mix:nodes:config">>).
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
%% API
|
%% API
|
||||||
-export([start_link/0]).
|
-export([start_link/0]).
|
||||||
|
|
||||||
-export([route/3, route_iq/4, route_iq/5,
|
-export([route/3, route_iq/4, route_iq/5, process_iq/3,
|
||||||
process_iq_reply/3, register_iq_handler/4,
|
process_iq_reply/3, register_iq_handler/4,
|
||||||
register_iq_handler/5, register_iq_response_handler/4,
|
register_iq_handler/5, register_iq_response_handler/4,
|
||||||
register_iq_response_handler/5, unregister_iq_handler/2,
|
register_iq_response_handler/5, unregister_iq_handler/2,
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
-export([start/0,
|
-export([start/0,
|
||||||
start_link/0,
|
start_link/0,
|
||||||
route/3,
|
route/3,
|
||||||
|
process_iq/3,
|
||||||
open_session/5,
|
open_session/5,
|
||||||
open_session/6,
|
open_session/6,
|
||||||
close_session/4,
|
close_session/4,
|
||||||
|
329
src/mod_mix.erl
Normal file
329
src/mod_mix.erl
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||||
|
%%% @copyright (C) 2016, Evgeny Khramtsov
|
||||||
|
%%% @doc
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 2 Mar 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(mod_mix).
|
||||||
|
|
||||||
|
-behaviour(gen_server).
|
||||||
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([start_link/2, start/2, stop/1, process_iq/3,
|
||||||
|
disco_items/5, disco_identity/5, disco_info/5,
|
||||||
|
disco_features/5]).
|
||||||
|
|
||||||
|
%% gen_server callbacks
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
terminate/2, code_change/3]).
|
||||||
|
|
||||||
|
-include("logger.hrl").
|
||||||
|
-include("jlib.hrl").
|
||||||
|
-include("pubsub.hrl").
|
||||||
|
|
||||||
|
-define(PROCNAME, ejabberd_mod_mix).
|
||||||
|
-define(NODES, [?NS_MIX_NODES_MESSAGES,
|
||||||
|
?NS_MIX_NODES_PRESENCE,
|
||||||
|
?NS_MIX_NODES_PARTICIPANTS,
|
||||||
|
?NS_MIX_NODES_SUBJECT,
|
||||||
|
?NS_MIX_NODES_CONFIG]).
|
||||||
|
|
||||||
|
-record(state, {server_host :: binary(),
|
||||||
|
host :: binary()}).
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
%%% API
|
||||||
|
%%%===================================================================
|
||||||
|
start_link(Host, Opts) ->
|
||||||
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
|
gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []).
|
||||||
|
|
||||||
|
start(Host, Opts) ->
|
||||||
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
|
ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
|
||||||
|
temporary, 5000, worker, [?MODULE]},
|
||||||
|
supervisor:start_child(ejabberd_sup, ChildSpec).
|
||||||
|
|
||||||
|
stop(Host) ->
|
||||||
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
|
supervisor:terminate_child(ejabberd_sup, Proc),
|
||||||
|
supervisor:delete_child(ejabberd_sup, Proc),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
disco_features(_Acc, _From, _To, _Node, _Lang) ->
|
||||||
|
{result, [?NS_MIX_0]}.
|
||||||
|
|
||||||
|
disco_items(_Acc, _From, To, _Node, _Lang) when To#jid.luser /= <<"">> ->
|
||||||
|
To_s = jid:to_string(jid:remove_resource(To)),
|
||||||
|
{result, [#xmlel{name = <<"item">>,
|
||||||
|
attrs = [{<<"jid">>, To_s},
|
||||||
|
{<<"node">>, Node}]} || Node <- ?NODES]};
|
||||||
|
disco_items(_Acc, _From, _To, _Node, _Lang) ->
|
||||||
|
{result, []}.
|
||||||
|
|
||||||
|
disco_identity(Acc, _From, To, _Node, _Lang) when To#jid.luser == <<"">> ->
|
||||||
|
Acc ++ [#xmlel{name = <<"identity">>,
|
||||||
|
attrs =
|
||||||
|
[{<<"category">>, <<"conference">>},
|
||||||
|
{<<"name">>, <<"MIX service">>},
|
||||||
|
{<<"type">>, <<"text">>}]}];
|
||||||
|
disco_identity(Acc, _From, _To, _Node, _Lang) ->
|
||||||
|
Acc ++ [#xmlel{name = <<"identity">>,
|
||||||
|
attrs =
|
||||||
|
[{<<"category">>, <<"conference">>},
|
||||||
|
{<<"type">>, <<"mix">>}]}].
|
||||||
|
|
||||||
|
disco_info(_Acc, _From, To, _Node, _Lang) when is_atom(To) ->
|
||||||
|
[#xmlel{name = <<"x">>,
|
||||||
|
attrs = [{<<"xmlns">>, ?NS_XDATA},
|
||||||
|
{<<"type">>, <<"result">>}],
|
||||||
|
children = [#xmlel{name = <<"field">>,
|
||||||
|
attrs = [{<<"var">>, <<"FORM_TYPE">>},
|
||||||
|
{<<"type">>, <<"hidden">>}],
|
||||||
|
children = [#xmlel{name = <<"value">>,
|
||||||
|
children = [{xmlcdata,
|
||||||
|
?NS_MIX_SERVICEINFO_0}]}]}]}];
|
||||||
|
disco_info(Acc, _From, _To, _Node, _Lang) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
|
process_iq(From, To,
|
||||||
|
#iq{type = set, sub_el = #xmlel{name = <<"join">>} = SubEl} = IQ) ->
|
||||||
|
Nodes = lists:flatmap(
|
||||||
|
fun(#xmlel{name = <<"subscribe">>, attrs = Attrs}) ->
|
||||||
|
Node = fxml:get_attr_s(<<"node">>, Attrs),
|
||||||
|
case lists:member(Node, ?NODES) of
|
||||||
|
true -> [Node];
|
||||||
|
false -> []
|
||||||
|
end;
|
||||||
|
(_) ->
|
||||||
|
[]
|
||||||
|
end, SubEl#xmlel.children),
|
||||||
|
case subscribe_nodes(From, To, Nodes) of
|
||||||
|
{result, _} ->
|
||||||
|
case publish_participant(From, To) of
|
||||||
|
{result, _} ->
|
||||||
|
LFrom_s = jid:to_string(jid:tolower(jid:remove_resource(From))),
|
||||||
|
Subscribe = [#xmlel{name = <<"subscribe">>,
|
||||||
|
attrs = [{<<"node">>, Node}]} || Node <- Nodes],
|
||||||
|
IQ#iq{type = result,
|
||||||
|
sub_el = [#xmlel{name = <<"join">>,
|
||||||
|
attrs = [{<<"jid">>, LFrom_s},
|
||||||
|
{<<"xmlns">>, ?NS_MIX_0}],
|
||||||
|
children = Subscribe}]};
|
||||||
|
{error, Err} ->
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, Err]}
|
||||||
|
end;
|
||||||
|
{error, Err} ->
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, Err]}
|
||||||
|
end;
|
||||||
|
process_iq(From, To,
|
||||||
|
#iq{type = set, sub_el = #xmlel{name = <<"leave">>} = SubEl} = IQ) ->
|
||||||
|
case delete_participant(From, To) of
|
||||||
|
{result, _} ->
|
||||||
|
case unsubscribe_nodes(From, To, ?NODES) of
|
||||||
|
{result, _} ->
|
||||||
|
IQ#iq{type = result, sub_el = []};
|
||||||
|
{error, Err} ->
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, Err]}
|
||||||
|
end;
|
||||||
|
{error, Err} ->
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, Err]}
|
||||||
|
end;
|
||||||
|
process_iq(_From, _To, #iq{sub_el = SubEl} = IQ) ->
|
||||||
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}.
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
%%% gen_server callbacks
|
||||||
|
%%%===================================================================
|
||||||
|
init([ServerHost, Opts]) ->
|
||||||
|
Host = gen_mod:get_opt_host(ServerHost, Opts, <<"mix.@HOST@">>),
|
||||||
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
|
||||||
|
one_queue),
|
||||||
|
ConfigTab = gen_mod:get_module_proc(Host, config),
|
||||||
|
ets:new(ConfigTab, [named_table]),
|
||||||
|
ets:insert(ConfigTab, {plugins, [<<"mix">>]}),
|
||||||
|
ejabberd_hooks:add(disco_local_items, Host, ?MODULE, disco_items, 100),
|
||||||
|
ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 100),
|
||||||
|
ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, disco_identity, 100),
|
||||||
|
ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, disco_items, 100),
|
||||||
|
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, disco_features, 100),
|
||||||
|
ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, disco_identity, 100),
|
||||||
|
ejabberd_hooks:add(disco_info, Host, ?MODULE, disco_info, 100),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
|
?NS_DISCO_ITEMS, mod_disco,
|
||||||
|
process_local_iq_items, IQDisc),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
|
||||||
|
?NS_DISCO_INFO, mod_disco,
|
||||||
|
process_local_iq_info, IQDisc),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
||||||
|
?NS_DISCO_ITEMS, mod_disco,
|
||||||
|
process_local_iq_items, IQDisc),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
||||||
|
?NS_DISCO_INFO, mod_disco,
|
||||||
|
process_local_iq_info, IQDisc),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
||||||
|
?NS_PUBSUB, mod_pubsub, iq_sm, IQDisc),
|
||||||
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
|
||||||
|
?NS_MIX_0, ?MODULE, process_iq, IQDisc),
|
||||||
|
ejabberd_router:register_route(Host),
|
||||||
|
{ok, #state{server_host = ServerHost, host = Host}}.
|
||||||
|
|
||||||
|
handle_call(_Request, _From, State) ->
|
||||||
|
Reply = ok,
|
||||||
|
{reply, Reply, State}.
|
||||||
|
|
||||||
|
handle_cast(_Msg, State) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
handle_info({route, From, To, Packet}, State) ->
|
||||||
|
case catch do_route(State, From, To, Packet) of
|
||||||
|
{'EXIT', _} = Err ->
|
||||||
|
try
|
||||||
|
?ERROR_MSG("failed to route packet ~p from '~s' to '~s': ~p",
|
||||||
|
[Packet, jid:to_string(From), jid:to_string(To), Err]),
|
||||||
|
ErrPkt = jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR),
|
||||||
|
ejabberd_router:route_error(To, From, ErrPkt, Packet)
|
||||||
|
catch _:_ ->
|
||||||
|
ok
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
{noreply, State};
|
||||||
|
handle_info(_Info, State) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
terminate(_Reason, _State) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
|
{ok, State}.
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
%%% Internal functions
|
||||||
|
%%%===================================================================
|
||||||
|
do_route(_State, From, To, #xmlel{name = <<"iq">>} = Packet) ->
|
||||||
|
if To#jid.luser == <<"">> ->
|
||||||
|
ejabberd_local:process_iq(From, To, Packet);
|
||||||
|
true ->
|
||||||
|
ejabberd_sm:process_iq(From, To, Packet)
|
||||||
|
end;
|
||||||
|
do_route(_State, From, To, #xmlel{name = <<"presence">>} = Packet)
|
||||||
|
when To#jid.luser /= <<"">> ->
|
||||||
|
case fxml:get_tag_attr_s(<<"type">>, Packet) of
|
||||||
|
<<"unavailable">> ->
|
||||||
|
delete_presence(From, To);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end;
|
||||||
|
do_route(_State, _From, _To, _Packet) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
subscribe_nodes(From, To, Nodes) ->
|
||||||
|
LTo = jid:tolower(jid:remove_resource(To)),
|
||||||
|
LFrom = jid:tolower(jid:remove_resource(From)),
|
||||||
|
From_s = jid:to_string(LFrom),
|
||||||
|
lists:foldl(
|
||||||
|
fun(_Node, {error, _} = Err) ->
|
||||||
|
Err;
|
||||||
|
(Node, {result, _}) ->
|
||||||
|
case mod_pubsub:subscribe_node(LTo, Node, From, From_s, []) of
|
||||||
|
{error, _} = Err ->
|
||||||
|
case is_item_not_found(Err) of
|
||||||
|
true ->
|
||||||
|
case mod_pubsub:create_node(
|
||||||
|
LTo, To#jid.lserver, Node, LFrom, <<"mix">>) of
|
||||||
|
{result, _} ->
|
||||||
|
mod_pubsub:subscribe_node(LTo, Node, From, From_s, []);
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end;
|
||||||
|
false ->
|
||||||
|
Err
|
||||||
|
end;
|
||||||
|
{result, _} = Result ->
|
||||||
|
Result
|
||||||
|
end
|
||||||
|
end, {result, []}, Nodes).
|
||||||
|
|
||||||
|
unsubscribe_nodes(From, To, Nodes) ->
|
||||||
|
LTo = jid:tolower(jid:remove_resource(To)),
|
||||||
|
LFrom = jid:tolower(jid:remove_resource(From)),
|
||||||
|
From_s = jid:to_string(LFrom),
|
||||||
|
lists:foldl(
|
||||||
|
fun(_Node, {error, _} = Err) ->
|
||||||
|
Err;
|
||||||
|
(Node, {result, _} = Result) ->
|
||||||
|
case mod_pubsub:unsubscribe_node(LTo, Node, From, From_s, <<"">>) of
|
||||||
|
{error, _} = Err ->
|
||||||
|
case is_not_subscribed(Err) of
|
||||||
|
true -> Result;
|
||||||
|
_ -> Err
|
||||||
|
end;
|
||||||
|
{result, _} = Res ->
|
||||||
|
Res
|
||||||
|
end
|
||||||
|
end, {result, []}, Nodes).
|
||||||
|
|
||||||
|
publish_participant(From, To) ->
|
||||||
|
LFrom = jid:tolower(jid:remove_resource(From)),
|
||||||
|
LTo = jid:tolower(jid:remove_resource(To)),
|
||||||
|
Participant = #xmlel{name = <<"participant">>,
|
||||||
|
attrs = [{<<"xmlns">>, ?NS_MIX_0},
|
||||||
|
{<<"jid">>, jid:to_string(LFrom)}]},
|
||||||
|
ItemID = p1_sha:sha(jid:to_string(LFrom)),
|
||||||
|
mod_pubsub:publish_item(
|
||||||
|
LTo, To#jid.lserver, ?NS_MIX_NODES_PARTICIPANTS,
|
||||||
|
From, ItemID, [Participant]).
|
||||||
|
|
||||||
|
delete_presence(From, To) ->
|
||||||
|
LFrom = jid:tolower(From),
|
||||||
|
LTo = jid:tolower(jid:remove_resource(To)),
|
||||||
|
case mod_pubsub:get_items(LTo, ?NS_MIX_NODES_PRESENCE) of
|
||||||
|
Items when is_list(Items) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun(#pubsub_item{modification = {_, LJID},
|
||||||
|
itemid = {ItemID, _}}) when LJID == LFrom ->
|
||||||
|
delete_item(From, To, ?NS_MIX_NODES_PRESENCE, ItemID);
|
||||||
|
(_) ->
|
||||||
|
ok
|
||||||
|
end, Items);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
delete_participant(From, To) ->
|
||||||
|
LFrom = jid:tolower(jid:remove_resource(From)),
|
||||||
|
ItemID = p1_sha:sha(jid:to_string(LFrom)),
|
||||||
|
delete_presence(From, To),
|
||||||
|
delete_item(From, To, ?NS_MIX_NODES_PARTICIPANTS, ItemID).
|
||||||
|
|
||||||
|
delete_item(From, To, Node, ItemID) ->
|
||||||
|
LTo = jid:tolower(jid:remove_resource(To)),
|
||||||
|
case mod_pubsub:delete_item(
|
||||||
|
LTo, Node, From, ItemID, true) of
|
||||||
|
{result, _} = Res ->
|
||||||
|
Res;
|
||||||
|
{error, _} = Err ->
|
||||||
|
case is_item_not_found(Err) of
|
||||||
|
true -> {result, []};
|
||||||
|
false -> Err
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
is_item_not_found({error, ErrEl}) ->
|
||||||
|
case fxml:get_subtag_with_xmlns(
|
||||||
|
ErrEl, <<"item-not-found">>, ?NS_STANZAS) of
|
||||||
|
#xmlel{} -> true;
|
||||||
|
_ -> false
|
||||||
|
end.
|
||||||
|
|
||||||
|
is_not_subscribed({error, ErrEl}) ->
|
||||||
|
case fxml:get_subtag_with_xmlns(
|
||||||
|
ErrEl, <<"not-subscribed">>, ?NS_PUBSUB_ERRORS) of
|
||||||
|
#xmlel{} -> true;
|
||||||
|
_ -> false
|
||||||
|
end.
|
@ -63,7 +63,7 @@
|
|||||||
%% exports for console debug manual use
|
%% exports for console debug manual use
|
||||||
-export([create_node/5, create_node/7, delete_node/3,
|
-export([create_node/5, create_node/7, delete_node/3,
|
||||||
subscribe_node/5, unsubscribe_node/5, publish_item/6,
|
subscribe_node/5, unsubscribe_node/5, publish_item/6,
|
||||||
delete_item/4, send_items/7, get_items/2, get_item/3,
|
delete_item/4, delete_item/5, send_items/7, get_items/2, get_item/3,
|
||||||
get_cached_item/2, get_configure/5, set_configure/5,
|
get_cached_item/2, get_configure/5, set_configure/5,
|
||||||
tree_action/3, node_action/4, node_call/4]).
|
tree_action/3, node_action/4, node_call/4]).
|
||||||
|
|
||||||
|
167
src/node_mix.erl
Normal file
167
src/node_mix.erl
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||||
|
%%% @copyright (C) 2016, Evgeny Khramtsov
|
||||||
|
%%% @doc
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 8 Mar 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(node_mix).
|
||||||
|
|
||||||
|
-behaviour(gen_pubsub_node).
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([init/3, terminate/2, options/0, features/0,
|
||||||
|
create_node_permission/6, create_node/2, delete_node/1,
|
||||||
|
purge_node/2, subscribe_node/8, unsubscribe_node/4,
|
||||||
|
publish_item/6, delete_item/4, remove_extra_items/3,
|
||||||
|
get_entity_affiliations/2, get_node_affiliations/1,
|
||||||
|
get_affiliation/2, set_affiliation/3,
|
||||||
|
get_entity_subscriptions/2, get_node_subscriptions/1,
|
||||||
|
get_subscriptions/2, set_subscriptions/4,
|
||||||
|
get_pending_nodes/2, get_states/1, get_state/2,
|
||||||
|
set_state/1, get_items/7, get_items/3, get_item/7,
|
||||||
|
get_item/2, set_item/1, get_item_name/3, node_to_path/1,
|
||||||
|
path_to_node/1]).
|
||||||
|
|
||||||
|
-include("pubsub.hrl").
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
%%% API
|
||||||
|
%%%===================================================================
|
||||||
|
init(Host, ServerHost, Opts) ->
|
||||||
|
node_flat:init(Host, ServerHost, Opts).
|
||||||
|
|
||||||
|
terminate(Host, ServerHost) ->
|
||||||
|
node_flat:terminate(Host, ServerHost).
|
||||||
|
|
||||||
|
options() ->
|
||||||
|
[{deliver_payloads, true},
|
||||||
|
{notify_config, false},
|
||||||
|
{notify_delete, false},
|
||||||
|
{notify_retract, true},
|
||||||
|
{purge_offline, false},
|
||||||
|
{persist_items, true},
|
||||||
|
{max_items, ?MAXITEMS},
|
||||||
|
{subscribe, true},
|
||||||
|
{access_model, open},
|
||||||
|
{roster_groups_allowed, []},
|
||||||
|
{publish_model, open},
|
||||||
|
{notification_type, headline},
|
||||||
|
{max_payload_size, ?MAX_PAYLOAD_SIZE},
|
||||||
|
{send_last_published_item, never},
|
||||||
|
{deliver_notifications, true},
|
||||||
|
{broadcast_all_resources, true},
|
||||||
|
{presence_based_delivery, false}].
|
||||||
|
|
||||||
|
features() ->
|
||||||
|
[<<"create-nodes">>,
|
||||||
|
<<"delete-nodes">>,
|
||||||
|
<<"delete-items">>,
|
||||||
|
<<"instant-nodes">>,
|
||||||
|
<<"item-ids">>,
|
||||||
|
<<"outcast-affiliation">>,
|
||||||
|
<<"persistent-items">>,
|
||||||
|
<<"publish">>,
|
||||||
|
<<"purge-nodes">>,
|
||||||
|
<<"retract-items">>,
|
||||||
|
<<"retrieve-affiliations">>,
|
||||||
|
<<"retrieve-items">>,
|
||||||
|
<<"retrieve-subscriptions">>,
|
||||||
|
<<"subscribe">>,
|
||||||
|
<<"subscription-notifications">>].
|
||||||
|
|
||||||
|
create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
|
||||||
|
node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access).
|
||||||
|
|
||||||
|
create_node(Nidx, Owner) ->
|
||||||
|
node_flat:create_node(Nidx, Owner).
|
||||||
|
|
||||||
|
delete_node(Removed) ->
|
||||||
|
node_flat:delete_node(Removed).
|
||||||
|
|
||||||
|
subscribe_node(Nidx, Sender, Subscriber, AccessModel,
|
||||||
|
SendLast, PresenceSubscription, RosterGroup, Options) ->
|
||||||
|
node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast,
|
||||||
|
PresenceSubscription, RosterGroup, Options).
|
||||||
|
|
||||||
|
unsubscribe_node(Nidx, Sender, Subscriber, SubId) ->
|
||||||
|
node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId).
|
||||||
|
|
||||||
|
publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) ->
|
||||||
|
node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload).
|
||||||
|
|
||||||
|
remove_extra_items(Nidx, MaxItems, ItemIds) ->
|
||||||
|
node_flat:remove_extra_items(Nidx, MaxItems, ItemIds).
|
||||||
|
|
||||||
|
delete_item(Nidx, Publisher, PublishModel, ItemId) ->
|
||||||
|
node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId).
|
||||||
|
|
||||||
|
purge_node(Nidx, Owner) ->
|
||||||
|
node_flat:purge_node(Nidx, Owner).
|
||||||
|
|
||||||
|
get_entity_affiliations(Host, Owner) ->
|
||||||
|
node_flat:get_entity_affiliations(Host, Owner).
|
||||||
|
|
||||||
|
get_node_affiliations(Nidx) ->
|
||||||
|
node_flat:get_node_affiliations(Nidx).
|
||||||
|
|
||||||
|
get_affiliation(Nidx, Owner) ->
|
||||||
|
node_flat:get_affiliation(Nidx, Owner).
|
||||||
|
|
||||||
|
set_affiliation(Nidx, Owner, Affiliation) ->
|
||||||
|
node_flat:set_affiliation(Nidx, Owner, Affiliation).
|
||||||
|
|
||||||
|
get_entity_subscriptions(Host, Owner) ->
|
||||||
|
node_flat:get_entity_subscriptions(Host, Owner).
|
||||||
|
|
||||||
|
get_node_subscriptions(Nidx) ->
|
||||||
|
node_flat:get_node_subscriptions(Nidx).
|
||||||
|
|
||||||
|
get_subscriptions(Nidx, Owner) ->
|
||||||
|
node_flat:get_subscriptions(Nidx, Owner).
|
||||||
|
|
||||||
|
set_subscriptions(Nidx, Owner, Subscription, SubId) ->
|
||||||
|
node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId).
|
||||||
|
|
||||||
|
get_pending_nodes(Host, Owner) ->
|
||||||
|
node_flat:get_pending_nodes(Host, Owner).
|
||||||
|
|
||||||
|
get_states(Nidx) ->
|
||||||
|
node_flat:get_states(Nidx).
|
||||||
|
|
||||||
|
get_state(Nidx, JID) ->
|
||||||
|
node_flat:get_state(Nidx, JID).
|
||||||
|
|
||||||
|
set_state(State) ->
|
||||||
|
node_flat:set_state(State).
|
||||||
|
|
||||||
|
get_items(Nidx, From, RSM) ->
|
||||||
|
node_flat:get_items(Nidx, From, RSM).
|
||||||
|
|
||||||
|
get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) ->
|
||||||
|
node_flat:get_items(Nidx, JID, AccessModel,
|
||||||
|
PresenceSubscription, RosterGroup, SubId, RSM).
|
||||||
|
|
||||||
|
get_item(Nidx, ItemId) ->
|
||||||
|
node_flat:get_item(Nidx, ItemId).
|
||||||
|
|
||||||
|
get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
|
||||||
|
node_flat:get_item(Nidx, ItemId, JID, AccessModel,
|
||||||
|
PresenceSubscription, RosterGroup, SubId).
|
||||||
|
|
||||||
|
set_item(Item) ->
|
||||||
|
node_flat:set_item(Item).
|
||||||
|
|
||||||
|
get_item_name(Host, Node, Id) ->
|
||||||
|
node_flat:get_item_name(Host, Node, Id).
|
||||||
|
|
||||||
|
node_to_path(Node) ->
|
||||||
|
node_flat:node_to_path(Node).
|
||||||
|
|
||||||
|
path_to_node(Path) ->
|
||||||
|
node_flat:path_to_node(Path).
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
%%% Internal functions
|
||||||
|
%%%===================================================================
|
Loading…
Reference in New Issue
Block a user