diff options
author | Alexey Shchepin <alexey@process-one.net> | 2004-08-08 19:07:55 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2004-08-08 19:07:55 +0000 |
commit | 357554265e4c86c5cd0dc3b6ae2f69f20c85786b (patch) | |
tree | 41219e7fbcccd2f24ca040c8fad8237bdc6e2e8b /src | |
parent | * src/aclocal.m4: Updated to check for openssl library (thanks to (diff) |
* src/ejabberd_c2s.erl: Use resend_offline_messages_hook to fetch
offline messages
* src/mod_offline.erl: Likewise
* src/mod_offline.erl: Added table locking in
remove_old_messages/1
* src/ejabberd_sm.erl: Use offline_message_hook to store offline
messages
* src/mod_offline.erl: Likewise
* src/ejabberd_hooks.erl: Hooks support
* src/ejabberd_sup.erl: Added ejabberd_hooks
* doc/guide.tex: Updated
* src/ejabberd.cfg.example: Updated
* src/ejabberd_c2s.erl: Changed TLS options (thanks to Sergei
Golovan)
SVN Revision: 255
Diffstat (limited to 'src')
-rw-r--r-- | src/ejabberd.cfg.example | 9 | ||||
-rw-r--r-- | src/ejabberd_c2s.erl | 12 | ||||
-rw-r--r-- | src/ejabberd_hooks.erl | 183 | ||||
-rw-r--r-- | src/ejabberd_sm.erl | 20 | ||||
-rw-r--r-- | src/ejabberd_sup.erl | 78 | ||||
-rw-r--r-- | src/mod_offline.erl | 43 |
6 files changed, 280 insertions, 65 deletions
diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example index 405f4a2b2..82e1cc43c 100644 --- a/src/ejabberd.cfg.example +++ b/src/ejabberd.cfg.example @@ -91,8 +91,13 @@ % Listened ports: {listen, - [{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]}, - {5223, ejabberd_c2s, [{access, c2s}, ssl, {certfile, "./ssl.pem"}]}, + [{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}, + starttls, {certfile, "./ssl.pem"}]}, + {5223, ejabberd_c2s, [{access, c2s}, + tls, {certfile, "./ssl.pem"}]}, + % Use these two lines instead if TLS support is not compiled + %{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]}, + %{5223, ejabberd_c2s, [{access, c2s}, ssl, {certfile, "./ssl.pem"}]}, {5269, ejabberd_s2s_in, [{shaper, s2s_shaper}]}, {5280, ejabberd_http, [http_poll, web_admin]}, {8888, ejabberd_service, [{access, all}, diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index b5b3128da..844e7bcfb 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -80,8 +80,6 @@ -define(INVALID_NS_ERR, xml:element_to_string(?SERR_INVALID_NAMESPACE)). -%-define(INVALID_XML_ERR, -% "<stream:error code='400'>Invalid XML</stream:error>"). -define(INVALID_XML_ERR, xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)). @@ -118,8 +116,9 @@ init([{SockMod, Socket}, Opts]) -> {value, {_, S}} -> S; _ -> none end, - TLS = lists:member(tls, Opts), - TLSEnabled = lists:member(tls_from_start, Opts), + StartTLS = lists:member(starttls, Opts), + TLSEnabled = lists:member(tls, Opts), + TLS = StartTLS orelse TLSEnabled, TLSOpts = lists:filter(fun({certfile, _}) -> true; (_) -> false end, Opts), @@ -1387,9 +1386,8 @@ process_privacy_iq(From, To, resend_offline_messages(StateData) -> - case catch mod_offline:pop_offline_messages(StateData#state.user) of - {'EXIT', _Reason} -> - ok; + case ejabberd_hooks:run_fold(resend_offline_messages_hook, [], + [StateData#state.user]) of Rs when list(Rs) -> lists:foreach( fun({route, From, To, {xmlelement, Name, Attrs, Els}}) -> diff --git a/src/ejabberd_hooks.erl b/src/ejabberd_hooks.erl new file mode 100644 index 000000000..c00035b41 --- /dev/null +++ b/src/ejabberd_hooks.erl @@ -0,0 +1,183 @@ +%%%---------------------------------------------------------------------- +%%% File : ejabberd_hooks.erl +%%% Author : Alexey Shchepin <alexey@sevcom.net> +%%% Purpose : Manage hooks +%%% Created : 8 Aug 2004 by Alexey Shchepin <alexey@sevcom.net> +%%% Id : $Id$ +%%%---------------------------------------------------------------------- + +-module(ejabberd_hooks). +-author('alexey@sevcom.net'). + +-behaviour(gen_server). + +%% External exports +-export([start_link/0, + add/4, + delete/4, + run/2, + run_fold/3]). + +%% gen_server callbacks +-export([init/1, + handle_call/3, + handle_cast/2, + code_change/3, + handle_info/2, + terminate/2]). + +-include("ejabberd.hrl"). + +-record(state, {}). + +%%%---------------------------------------------------------------------- +%%% API +%%%---------------------------------------------------------------------- +start_link() -> + gen_server:start_link({local, ejabberd_hooks}, ejabberd_hooks, [], []). + +add(Hook, Module, Function, Seq) -> + gen_server:call(ejabberd_hooks, {add, Hook, Module, Function, Seq}). + +delete(Hook, Module, Function, Seq) -> + gen_server:call(ejabberd_hooks, {delete, Hook, Module, Function, Seq}). + +run(Hook, Args) -> + case ets:lookup(hooks, Hook) of + [{_, Ls}] -> + run1(Ls, Hook, Args); + [] -> + ok + end. + +run_fold(Hook, Val, Args) -> + case ets:lookup(hooks, Hook) of + [{_, Ls}] -> + run_fold1(Ls, Hook, Val, Args); + [] -> + ok + end. + +%%%---------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%---------------------------------------------------------------------- +init([]) -> + ets:new(hooks, [named_table]), + {ok, #state{}}. + +%%---------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%---------------------------------------------------------------------- +handle_call({add, Hook, Module, Function, Seq}, From, State) -> + Reply = case ets:lookup(hooks, Hook) of + [{_, Ls}] -> + El = {Seq, Module, Function}, + case lists:member(El, Ls) of + true -> + ok; + false -> + NewLs = lists:merge(Ls, [El]), + ets:insert(hooks, {Hook, NewLs}), + ok + end; + [] -> + NewLs = [{Seq, Module, Function}], + ets:insert(hooks, {Hook, NewLs}), + ok + end, + {reply, Reply, State}; +handle_call({delete, Hook, Module, Function, Seq}, From, State) -> + Reply = case ets:lookup(hooks, Hook) of + [{_, Ls}] -> + NewLs = lists:delete({Seq, Module, Function}, Ls), + ets:insert(hooks, {Hook, NewLs}), + ok; + [] -> + ok + end, + {reply, Reply, State}; +handle_call(Request, From, State) -> + Reply = ok, + {reply, Reply, State}. + +%%---------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%---------------------------------------------------------------------- +handle_cast(Msg, State) -> + {noreply, State}. + +%%---------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%---------------------------------------------------------------------- +handle_info(Info, State) -> + {noreply, State}. + +%%---------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%---------------------------------------------------------------------- +terminate(Reason, State) -> + ok. + + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%%---------------------------------------------------------------------- +%%% Internal functions +%%%---------------------------------------------------------------------- + +run1([], Hook, Args) -> + ok; +run1([{_Seq, Module, Function} | Ls], Hook, Args) -> + case catch apply(Module, Function, Args) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p~nrunning hook: ~p", + [Reason, {Hook, Args}]), + run1(Ls, Hook, Args); + stop -> + ok; + _ -> + run1(Ls, Hook, Args) + end. + + +run_fold1([], Hook, Val, Args) -> + Val; +run_fold1([{_Seq, Module, Function} | Ls], Hook, Val, Args) -> + case catch apply(Module, Function, [Val | Args]) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p~nrunning hook: ~p", + [Reason, {Hook, Args}]), + run_fold1(Ls, Hook, Val, Args); + stop -> + stopped; + {stop, NewVal} -> + NewVal; + NewVal -> + run_fold1(Ls, Hook, NewVal, Args) + end. + + + diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 882c61e0e..d4a972518 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -11,6 +11,7 @@ -vsn('$Revision$ '). -export([start_link/0, init/0, open_session/2, close_session/2, + bounce_offline_message/3, get_user_resources/1, set_presence/3, unset_presence/3, @@ -44,6 +45,8 @@ init() -> mnesia:add_table_index(presence, user), mnesia:subscribe(system), ets:new(sm_iqtable, [named_table]), + ejabberd_hooks:add(offline_message_hook, + ejabberd_sm, bounce_offline_message, 100), loop(). loop() -> @@ -263,18 +266,11 @@ route_message(From, To, Packet) -> _ -> case ejabberd_auth:is_user_exists(LUser) of true -> - case catch mod_offline:store_packet( - From, To, Packet) of - {'EXIT', _} -> - Err = jlib:make_error_reply( - Packet, ?ERR_SERVICE_UNAVAILABLE), - ejabberd_router:route(To, From, Err); - _ -> - ok - end; + ejabberd_hooks:run(offline_message_hook, + [From, To, Packet]); _ -> Err = jlib:make_error_reply( - Packet, ?ERR_ITEM_NOT_FOUND), + Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err) end end; @@ -291,6 +287,10 @@ route_message(From, To, Packet) -> end end. +bounce_offline_message(From, To, Packet) -> + Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), + ejabberd_router:route(To, From, Err), + stop. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index bda9b79a1..9a2cc74d5 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -19,36 +19,48 @@ start_link() -> init([]) -> - Router = {ejabberd_router, - {ejabberd_router, start_link, []}, - permanent, - brutal_kill, - worker, - [ejabberd_router]}, - SM = {ejabberd_sm, - {ejabberd_sm, start_link, []}, - permanent, - brutal_kill, - worker, - [ejabberd_sm]}, - S2S = {ejabberd_s2s, - {ejabberd_s2s, start_link, []}, - permanent, - brutal_kill, - worker, - [ejabberd_s2s]}, - Local = {ejabberd_local, - {ejabberd_local, start_link, []}, - permanent, - brutal_kill, - worker, - [ejabberd_local]}, - Listener = {ejabberd_listener, - {ejabberd_listener, start_link, []}, - permanent, - infinity, - supervisor, - [ejabberd_listener]}, + Hooks = + {ejabberd_hooks, + {ejabberd_hooks, start_link, []}, + permanent, + brutal_kill, + worker, + [ejabberd_hooks]}, + Router = + {ejabberd_router, + {ejabberd_router, start_link, []}, + permanent, + brutal_kill, + worker, + [ejabberd_router]}, + SM = + {ejabberd_sm, + {ejabberd_sm, start_link, []}, + permanent, + brutal_kill, + worker, + [ejabberd_sm]}, + S2S = + {ejabberd_s2s, + {ejabberd_s2s, start_link, []}, + permanent, + brutal_kill, + worker, + [ejabberd_s2s]}, + Local = + {ejabberd_local, + {ejabberd_local, start_link, []}, + permanent, + brutal_kill, + worker, + [ejabberd_local]}, + Listener = + {ejabberd_listener, + {ejabberd_listener, start_link, []}, + permanent, + infinity, + supervisor, + [ejabberd_listener]}, StringPrep = {stringprep, {stringprep, start_link, []}, @@ -112,7 +124,11 @@ init([]) -> supervisor, [ejabberd_tmp_sup]}, {ok, {{one_for_one, 10, 1}, - [Router, SM, S2S, Local, + [Hooks, + Router, + SM, + S2S, + Local, StringPrep, C2SSupervisor, S2SInSupervisor, diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 7af72442b..22e9b85ee 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -16,7 +16,7 @@ stop/0, store_packet/3, resend_offline_messages/1, - pop_offline_messages/1, + pop_offline_messages/2, remove_old_messages/1, remove_user/1]). @@ -31,6 +31,10 @@ start(_) -> [{disc_only_copies, [node()]}, {type, bag}, {attributes, record_info(fields, offline_msg)}]), + ejabberd_hooks:add(offline_message_hook, + ?MODULE, store_packet, 50), + ejabberd_hooks:add(resend_offline_messages_hook, + ?MODULE, pop_offline_messages, 50), register(?PROCNAME, spawn(?MODULE, init, [])). init() -> @@ -61,23 +65,31 @@ receive_all(Msgs) -> stop() -> + ejabberd_hooks:delete(offline_message_hook, + ?MODULE, store_packet, 50), + ejabberd_hooks:delete(resend_offline_messages_hook, + ?MODULE, pop_offline_messages, 50), exit(whereis(?PROCNAME), stop), ok. store_packet(From, To, Packet) -> - true = is_process_alive(whereis(?PROCNAME)), Type = xml:get_tag_attr_s("type", Packet), - true = Type /= "error" andalso Type /= "groupchat", - case check_event(From, To, Packet) of + if + (Type /= "error") and (Type /= "groupchat") -> + case check_event(From, To, Packet) of + true -> + #jid{luser = LUser} = To, + TimeStamp = now(), + ?PROCNAME ! #offline_msg{user = LUser, + timestamp = TimeStamp, + from = From, + to = To, + packet = Packet}, + stop; + _ -> + ok + end; true -> - #jid{luser = LUser} = To, - TimeStamp = now(), - ?PROCNAME ! #offline_msg{user = LUser, - timestamp = TimeStamp, - from = From, - to = To, - packet = Packet}; - _ -> ok end. @@ -154,7 +166,7 @@ resend_offline_messages(User) -> ok end. -pop_offline_messages(User) -> +pop_offline_messages(Ls, User) -> LUser = jlib:nodeprep(User), F = fun() -> Rs = mnesia:wread({offline_msg, LUser}), @@ -175,9 +187,9 @@ pop_offline_messages(User) -> calendar:now_to_universal_time( R#offline_msg.timestamp))]}} end, - lists:keysort(#offline_msg.timestamp, Rs)); + Ls ++ lists:keysort(#offline_msg.timestamp, Rs)); _ -> - [] + Ls end. remove_old_messages(Days) -> @@ -187,6 +199,7 @@ remove_old_messages(Days) -> Secs1 = S rem 1000000, TimeStamp = {MegaSecs1, Secs1, 0}, F = fun() -> + mnesia:write_lock_table(offline_msg), mnesia:foldl( fun(#offline_msg{timestamp = TS} = Rec, _Acc) when TS < TimeStamp -> |