diff --git a/TODO b/TODO index e3f828c9f..a87f73c34 100644 --- a/TODO +++ b/TODO @@ -4,8 +4,8 @@ admin interface backup management S2S timeouts rewrite S2S key validation -iq:browse(?) +iq:browse (?) SRV DNS records karma SSL -JEP-62,63 \ No newline at end of file +JEP-62,63 (?) diff --git a/src/Makefile b/src/Makefile index 2cc96509c..8f3c17bce 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,7 +11,6 @@ ERLSHLIBS = expat_erl.so all: $(ERLSHLIBS) erl -s make all report -noinput -s erlang halt - etags *.erl $(ERLSHLIBS): %.so: %.c gcc -Wall $(INCLUDES) $(LIBDIRS) \ @@ -26,3 +25,7 @@ clean: Makefile.inc: ./configure + +TAGS: + etags *.erl + diff --git a/src/acl.erl b/src/acl.erl index 375f69490..2c8a8e7ca 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -14,13 +14,24 @@ -include("ejabberd.hrl"). +-record(acl, {aclname, aclspec}). + start() -> - ets:new(acls, [bag, named_table, public]), + %ets:new(acls, [bag, named_table, public]), + mnesia:create_table(acl, + [{disc_copies, [node()]}, + {type, bag}, + {attributes, record_info(fields, acl)}]), + mnesia:add_table_copy(acl, node(), ram_copies), ok. -add(ACLName, ACLData) -> - ets:insert(acls, {ACLName, ACLData}). +add(ACLName, ACLSpec) -> + F = fun() -> + mnesia:write(#acl{aclname = ACLName, aclspec = ACLSpec}) + end, + mnesia:transaction(F). + %ets:insert(acls, {ACLName, ACLData}). match_rule(Rule, JID) -> case ejabberd_config:get_global_option({access, Rule}) of @@ -42,7 +53,7 @@ match_acls([{Access, ACL} | ACLs], JID) -> match_acl(ACL, JID) -> {User, Server, Resource} = jlib:jid_tolower(JID), - lists:any(fun({_, Spec}) -> + lists:any(fun(#acl{aclspec = Spec}) -> case Spec of all -> true; @@ -53,4 +64,4 @@ match_acl(ACL, JID) -> {server, S} -> S == Server end - end, ets:lookup(acls, ACL)). + end, ets:lookup(acl, ACL)). diff --git a/src/ejabberd.cfg b/src/ejabberd.cfg index a949a7cf8..6d4f3551b 100644 --- a/src/ejabberd.cfg +++ b/src/ejabberd.cfg @@ -21,6 +21,9 @@ {8888, ejabberd_service, start, ["asd.e.localhost", "asdqwe"]} ]}. +% This value (5569) is only for debugging, must be 5269 +{outgoing_s2s_port, 5569}. + {modules, [ {mod_register, []}, {mod_roster, []}, diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index d280a4292..b977103c4 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -185,17 +185,11 @@ get_password_s(User) -> is_user_exists(User) -> LUser = jlib:tolower(User), - F = fun() -> - case mnesia:read({passwd, LUser}) of - [] -> - false; - [_] -> - true - end - end, - case mnesia:transaction(F) of - {atomic, Res} -> - Res; + case catch mnesia:dirty_read({passwd, LUser}) of + [] -> + false; + [_] -> + true; _ -> false end. diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index c1f7ebc5d..8c66d3262 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -286,12 +286,14 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> ?DEBUG("broadcast!!!!!!!!!!!~n~p~n", [Els]), NewSt = case Els of [{item, IJID, ISubscription}] -> - roster_change(IJID, ISubscription, - StateData); + {false, Attrs, + roster_change(IJID, ISubscription, + StateData)}; + [{exit, Reason}] -> + {exit, Attrs, Reason}; _ -> - StateData - end, - {false, Attrs, NewSt}; + {false, Attrs, StateData} + end; "iq" -> IQ = jlib:iq_query_info(Packet), case IQ of @@ -310,16 +312,19 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> _ -> {true, Attrs, StateData} end, - if Pass -> + if + Pass == exit -> + {stop, normal, StateData}; + Pass -> Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From), jlib:jid_to_string(To), NewAttrs), Text = xml:element_to_string({xmlelement, Name, Attrs2, Els}), - send_text(StateData#state.sender, Text); - true -> - ok - end, - {next_state, StateName, NewState}. + send_text(StateData#state.sender, Text), + {next_state, StateName, NewState}; + true -> + {next_state, StateName, NewState} + end. %%---------------------------------------------------------------------- %% Func: terminate/3 diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index c567cbfa6..e0415b0d2 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -13,7 +13,9 @@ -export([start/0, init/0]). -export([register_iq_handler/3, - register_iq_handler/4]). + register_iq_handler/4, + unregister_iq_handler/1 + ]). -include("ejabberd.hrl"). @@ -41,6 +43,18 @@ loop(State) -> {register_iq_handler, XMLNS, Module, Function, Opts} -> ets:insert(State#state.iqtable, {XMLNS, Module, Function, Opts}), mod_disco:register_feature(XMLNS), + loop(State); + {unregister_iq_handler, XMLNS} -> + case ets:lookup(State#state.iqtable, XMLNS) of + [{_, Module, Function, Opts}] -> + gen_iq_handler:stop_iq_handler(Module, Function, Opts); + _ -> + ok + end, + ets:delete(State#state.iqtable, XMLNS), + mod_disco:unregister_feature(XMLNS), + loop(State); + _ -> loop(State) end. @@ -117,3 +131,7 @@ register_iq_handler(XMLNS, Module, Fun) -> register_iq_handler(XMLNS, Module, Fun, Opts) -> ejabberd_local ! {register_iq_handler, XMLNS, Module, Fun, Opts}. + +unregister_iq_handler(XMLNS) -> + ejabberd_local ! {unregister_iq_handler, XMLNS}. + diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 799e9da41..aaa3356fd 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -97,7 +97,8 @@ init([From, Server, Type]) -> %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- open_socket(init, StateData) -> - case gen_tcp:connect(StateData#state.server, 5569, + case gen_tcp:connect(StateData#state.server, + ejabberd_config:get_local_option(outgoing_s2s_port), [binary, {packet, 0}]) of {ok, Socket} -> XMLStreamPid = xml_stream:start(self()), diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index a6c5efa0a..8860dcf5d 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -17,7 +17,9 @@ dirty_get_sessions_list/0, dirty_get_my_sessions_list/0, register_iq_handler/3, - register_iq_handler/4]). + register_iq_handler/4, + unregister_iq_handler/1 + ]). -include_lib("mnemosyne/include/mnemosyne.hrl"). -include("ejabberd.hrl"). @@ -77,6 +79,16 @@ loop() -> {register_iq_handler, XMLNS, Module, Function, Opts} -> ets:insert(sm_iqtable, {XMLNS, Module, Function, Opts}), loop(); + {unregister_iq_handler, XMLNS} -> + case ets:lookup(sm_iqtable, XMLNS) of + [{_, Module, Function, Opts}] -> + gen_iq_handler:stop_iq_handler(Module, Function, Opts); + _ -> + ok + end, + ets:delete(sm_iqtable, XMLNS), + mod_disco:unregister_feature(XMLNS), + loop(); _ -> loop() end. @@ -389,3 +401,6 @@ register_iq_handler(XMLNS, Module, Fun) -> register_iq_handler(XMLNS, Module, Fun, Opts) -> ejabberd_sm ! {register_iq_handler, XMLNS, Module, Fun, Opts}. +unregister_iq_handler(XMLNS) -> + ejabberd_sm ! {unregister_iq_handler, XMLNS}. + diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index 614061085..3bdeeee4c 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -12,6 +12,8 @@ -export([start/0, add_iq_handler/5, + remove_iq_handler/2, + stop_iq_handler/3, handle/6, process_iq/5, queue_init/2]). @@ -33,6 +35,17 @@ add_iq_handler(Component, NS, Module, Function, Type) -> Component:register_iq_handler(NS, Module, Function, parallel) end. +remove_iq_handler(Component, NS) -> + Component:unregister_iq_handler(NS). + +stop_iq_handler(Module, Function, Opts) -> + case Opts of + {one_queue, Pid} -> + exit(Pid, kill); + _ -> + ok + end. + handle(Module, Function, Opts, From, To, IQ) -> case Opts of no_queue -> diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 6e6b7f903..fe89a2ded 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -13,6 +13,7 @@ -behaviour(gen_mod). -export([start/1, + stop/0, process_local_iq/3, process_sm_iq/3]). @@ -28,6 +29,10 @@ start(Opts) -> ?MODULE, process_sm_iq, IQDisc), ok. +stop() -> + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_XDATA), + gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_XDATA). + process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> case acl:match_rule(configure, From) of @@ -240,7 +245,7 @@ get_form(["config", "acls"], Lang) -> end, string:tokens( lists:flatten(io_lib:format("~p", - [ets:tab2list(acls)])), + [ets:tab2list(acl)])), "\n")) %{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]} } @@ -379,6 +384,9 @@ set_form(["config", "remusers"], Lang, XData) -> fun({Var, Vals}) -> case Vals of ["1"] -> + ejabberd_sm ! {route, {"", "", ""}, {Var, "", ""}, + {xmlelement, "broadcast", [], + [{exit, "User removed"}]}}, catch ejabberd_auth:remove_user(Var), catch mod_roster:remove_user(Var), catch mod_offline:remove_user(Var), diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 705780a5c..474eb2ac8 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -13,11 +13,13 @@ -behaviour(gen_mod). -export([start/1, + stop/0, process_local_iq_items/3, process_local_iq_info/3, process_sm_iq_items/3, process_sm_iq_info/3, - register_feature/1]). + register_feature/1, + unregister_feature/1]). -include("ejabberd.hrl"). -include("namespaces.hrl"). @@ -41,10 +43,21 @@ start(Opts) -> register_feature("presence-invisible"), ok. +stop() -> + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_DISCO_ITEMS), + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_DISCO_INFO), + gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_DISCO_ITEMS), + gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_DISCO_INFO). + + register_feature(Feature) -> catch ets:new(disco_features, [named_table, ordered_set, public]), ets:insert(disco_features, {Feature}). +unregister_feature(Feature) -> + catch ets:new(disco_features, [named_table, ordered_set, public]), + ets:delete(disco_features, Feature). + process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) -> Lang = xml:get_tag_attr_s("xml:lang", SubEl), case Type of diff --git a/src/mod_offline.erl b/src/mod_offline.erl index b5e84cad0..63391cfc4 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -12,6 +12,7 @@ -behaviour(gen_mod). -export([start/1, + stop/0, store_packet/3, resend_offline_messages/1, remove_user/1]). @@ -27,6 +28,9 @@ start(_) -> {type, bag}, {attributes, record_info(fields, offline_msg)}]). +stop() -> + % TODO: maybe throw error that this module can't be removed? + ok. store_packet(From, To, Packet) -> case check_event(From, To, Packet) of diff --git a/src/mod_private.erl b/src/mod_private.erl index ef0bc21af..eb14f804c 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -13,6 +13,7 @@ -behaviour(gen_mod). -export([start/1, + stop/0, process_local_iq/3]). -include("ejabberd.hrl"). @@ -28,6 +29,9 @@ start(Opts) -> gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_PRIVATE, ?MODULE, process_local_iq, IQDisc). +stop() -> + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_PRIVATE). + process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> {User, Server, _} = From, diff --git a/src/mod_stats.erl b/src/mod_stats.erl index e0787ce11..ff5b65369 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -13,6 +13,7 @@ -behaviour(gen_mod). -export([start/1, + stop/0, process_local_iq/3]). -include("namespaces.hrl"). @@ -22,6 +23,9 @@ start(Opts) -> gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_STATS, ?MODULE, process_local_iq, IQDisc). +stop() -> + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_STATS). + process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> Lang = xml:get_tag_attr_s("xml:lang", SubEl), @@ -77,7 +81,11 @@ get_local_stats(["running nodes", _], []) -> {result, [?STAT("time/uptime"), ?STAT("time/cputime"), - ?STAT("users/online") + ?STAT("users/online"), + ?STAT("transactions/commited"), + ?STAT("transactions/aborted"), + ?STAT("transactions/restarted"), + ?STAT("transactions/logged") ]}; get_local_stats(["running nodes", ENode], Names) -> @@ -159,6 +167,39 @@ get_node_stat(Node, Name) when Name == "users/online" -> Users -> ?STATVAL(integer_to_list(length(Users)), "users") end; + +get_node_stat(Node, Name) when Name == "transactions/commited" -> + case catch rpc:call(Node, mnesia, system_info, [transaction_commits]) of + {badrpc, Reason} -> + ?STATERR("500", "Internal Server Error"); + Transactions -> + ?STATVAL(integer_to_list(Transactions), "transactions") + end; + +get_node_stat(Node, Name) when Name == "transactions/aborted" -> + case catch rpc:call(Node, mnesia, system_info, [transaction_failures]) of + {badrpc, Reason} -> + ?STATERR("500", "Internal Server Error"); + Transactions -> + ?STATVAL(integer_to_list(Transactions), "transactions") + end; + +get_node_stat(Node, Name) when Name == "transactions/restarted" -> + case catch rpc:call(Node, mnesia, system_info, [transaction_restarts]) of + {badrpc, Reason} -> + ?STATERR("500", "Internal Server Error"); + Transactions -> + ?STATVAL(integer_to_list(Transactions), "transactions") + end; + +get_node_stat(Node, Name) when Name == "transactions/logged" -> + case catch rpc:call(Node, mnesia, system_info, [transaction_log_writes]) of + {badrpc, Reason} -> + ?STATERR("500", "Internal Server Error"); + Transactions -> + ?STATVAL(integer_to_list(Transactions), "transactions") + end; + get_node_stat(_, Name) -> ?STATERR("404", "Not Found"). diff --git a/src/mod_time.erl b/src/mod_time.erl index 7837c83c3..a9959398f 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -13,6 +13,7 @@ -behaviour(gen_mod). -export([start/1, + stop/0, process_local_iq/3]). -include("ejabberd.hrl"). @@ -24,6 +25,8 @@ start(Opts) -> gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_TIME, ?MODULE, process_local_iq, IQDisc). +stop() -> + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_TIME). process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> case Type of diff --git a/src/mod_version.erl b/src/mod_version.erl index 0789c2954..a00d4a08a 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -13,6 +13,7 @@ -behaviour(gen_mod). -export([start/1, + stop/0, process_local_iq/3]). -include("ejabberd.hrl"). @@ -25,6 +26,8 @@ start(Opts) -> gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_VERSION, ?MODULE, process_local_iq, IQDisc). +stop() -> + gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_VERSION). process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->