diff options
author | tmallard <tmallard@null> | 2005-04-17 18:08:34 +0000 |
---|---|---|
committer | tmallard <tmallard@null> | 2005-04-17 18:08:34 +0000 |
commit | 374446f8471747c878cdaf760c4bb37d17493ab7 (patch) | |
tree | e91bac5669555dcf33627e4745b04236f743126d /src/mod_muc | |
parent | * src/ejabberd_c2s.erl: Send new id for each new stream inside one (diff) |
Merged the Process One contributions ( Virtual Hosting )
SVN Revision: 307
Diffstat (limited to 'src/mod_muc')
-rw-r--r-- | src/mod_muc/mod_muc.erl | 250 | ||||
-rw-r--r-- | src/mod_muc/mod_muc_room.erl | 21 |
2 files changed, 189 insertions, 82 deletions
diff --git a/src/mod_muc/mod_muc.erl b/src/mod_muc/mod_muc.erl index b7f5862b..e7ffe42d 100644 --- a/src/mod_muc/mod_muc.erl +++ b/src/mod_muc/mod_muc.erl @@ -15,20 +15,20 @@ -export([start/1, init/2, stop/0, - room_destroyed/1, - store_room/2, - restore_room/1, - forget_room/1, + room_destroyed/2, + store_room/3, + restore_room/2, + forget_room/2, process_iq_disco_items/4, - can_use_nick/2]). + can_use_nick/3]). -include("ejabberd.hrl"). -include("jlib.hrl"). --record(muc_room, {name, opts}). --record(muc_online_room, {name, pid}). --record(muc_registered, {user, nick}). +-record(muc_room, {name_host, opts}). +-record(muc_online_room, {name_host, pid}). +-record(muc_registered, {us_host, nick}). start(Opts) -> @@ -38,43 +38,45 @@ start(Opts) -> mnesia:create_table(muc_registered, [{disc_copies, [node()]}, {attributes, record_info(fields, muc_registered)}]), + Hosts = gen_mod:get_hosts(Opts, "conference."), + Host = hd(Hosts), + update_tables(Host), mnesia:add_table_index(muc_registered, nick), - Host = gen_mod:get_opt(host, Opts, "conference." ++ ?MYNAME), Access = gen_mod:get_opt(access, Opts, all), AccessCreate = gen_mod:get_opt(access_create, Opts, all), AccessAdmin = gen_mod:get_opt(access_admin, Opts, none), register(ejabberd_mod_muc, - spawn(?MODULE, init, [Host, {Access, AccessCreate, AccessAdmin}])). + spawn(?MODULE, init, + [Hosts, {Access, AccessCreate, AccessAdmin}])). -init(Host, Access) -> +init(Hosts, Access) -> catch ets:new(muc_online_room, [named_table, public, - {keypos, #muc_online_room.name}]), - ejabberd_router:register_route(Host), - load_permanent_rooms(Host, Access), - loop(Host, Access). + {keypos, #muc_online_room.name_host}]), + ejabberd_router:register_routes(Hosts), + load_permanent_rooms(Access), + loop(Hosts, Access). -loop(Host, Access) -> +loop(Hosts, Access) -> receive {route, From, To, Packet} -> - case catch do_route(Host, Access, From, To, Packet) of + case catch do_route(To#jid.lserver, Access, From, To, Packet) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); _ -> ok end, - loop(Host, Access); - {room_destroyed, Room} -> - ets:delete(muc_online_room, Room), - loop(Host, Access); + loop(Hosts, Access); + {room_destroyed, RoomHost} -> + ets:delete(muc_online_room, RoomHost), + loop(Hosts, Access); stop -> - % TODO - ejabberd_router:unregister_global_route(Host), + ejabberd_router:unregister_routes(Hosts), ok; _ -> - loop(Host, Access) + loop(Hosts, Access) end. @@ -127,7 +129,7 @@ do_route1(Host, Access, From, To, Packet) -> [{xmlelement, "query", [{"xmlns", XMLNS}], iq_get_register_info( - From, Host, Lang)}]}, + Host, From, Lang)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); @@ -135,7 +137,7 @@ do_route1(Host, Access, From, To, Packet) -> xmlns = ?NS_REGISTER = XMLNS, lang = Lang, sub_el = SubEl} = IQ -> - case process_iq_register_set(From, SubEl, Lang) of + case process_iq_register_set(Host, From, SubEl, Lang) of {result, IQRes} -> Res = IQ#iq{type = result, sub_el = @@ -180,7 +182,7 @@ do_route1(Host, Access, From, To, Packet) -> Msg = xml:get_path_s( Packet, [{elem, "body"}, cdata]), - broadcast_service_message(Msg); + broadcast_service_message(Host, Msg); _ -> Lang = xml:get_attr_s("xml:lang", Attrs), ErrText = "Only service administrators " @@ -208,7 +210,7 @@ do_route1(Host, Access, From, To, Packet) -> end end; _ -> - case ets:lookup(muc_online_room, Room) of + case ets:lookup(muc_online_room, {Room, Host}) of [] -> Type = xml:get_attr_s("type", Attrs), case {Name, Type} of @@ -220,7 +222,8 @@ do_route1(Host, Access, From, To, Packet) -> Host, Access, Room, From, Nick), ets:insert( muc_online_room, - #muc_online_room{name = Room, pid = Pid}), + #muc_online_room{name_host = {Room, Host}, + pid = Pid}), mod_muc_room:route(Pid, From, Nick, Packet), ok; _ -> @@ -248,8 +251,8 @@ do_route1(Host, Access, From, To, Packet) -> -room_destroyed(Room) -> - ejabberd_mod_muc ! {room_destroyed, Room}, +room_destroyed(Host, Room) -> + ejabberd_mod_muc ! {room_destroyed, {Room, Host}}, ok. stop() -> @@ -257,15 +260,15 @@ stop() -> ok. -store_room(Name, Opts) -> +store_room(Host, Name, Opts) -> F = fun() -> - mnesia:write(#muc_room{name = Name, + mnesia:write(#muc_room{name_host = {Name, Host}, opts = Opts}) end, mnesia:transaction(F). -restore_room(Name) -> - case catch mnesia:dirty_read(muc_room, Name) of +restore_room(Host, Name) -> + case catch mnesia:dirty_read(muc_room, {Name, Host}) of [#muc_room{opts = Opts}] -> Opts; _ -> @@ -273,21 +276,21 @@ restore_room(Name) -> end. -forget_room(Name) -> +forget_room(Host, Name) -> F = fun() -> - mnesia:delete({muc_room, Name}) + mnesia:delete({muc_room, {Name, Host}}) end, mnesia:transaction(F). -load_permanent_rooms(Host, Access) -> +load_permanent_rooms(Access) -> case catch mnesia:dirty_select(muc_room, [{'_', [], ['$_']}]) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), ok; Rs -> lists:foreach(fun(R) -> - Room = R#muc_room.name, + {Room, Host} = R#muc_room.name_host, {ok, Pid} = mod_muc_room:start( Host, Access, @@ -295,7 +298,8 @@ load_permanent_rooms(Host, Access) -> R#muc_room.opts), ets:insert( muc_online_room, - #muc_online_room{name = Room, pid = Pid}) + #muc_online_room{name_host = {Room, Host}, + pid = Pid}) end, Rs) end. @@ -320,7 +324,7 @@ process_iq_disco_items(Host, From, To, #iq{lang = Lang} = IQ) -> jlib:iq_to_xml(Res)). iq_disco_items(Host, From, Lang) -> - lists:zf(fun(#muc_online_room{name = Name, pid = Pid}) -> + lists:zf(fun(#muc_online_room{name_host = {Name, _Host}, pid = Pid}) -> case catch gen_fsm:sync_send_all_state_event( Pid, {get_disco_item, From, Lang}, 100) of {item, Desc} -> @@ -331,7 +335,7 @@ iq_disco_items(Host, From, Lang) -> _ -> false end - end, ets:tab2list(muc_online_room)). + end, get_vh_rooms(Host)). -define(XFIELD(Type, Label, Var, Val), @@ -340,17 +344,18 @@ iq_disco_items(Host, From, Lang) -> {"var", Var}], [{xmlelement, "value", [], [{xmlcdata, Val}]}]}). -iq_get_register_info(From, Host, Lang) -> +iq_get_register_info(Host, From, Lang) -> {LUser, LServer, _} = jlib:jid_tolower(From), LUS = {LUser, LServer}, - {Nick, Registered} = case catch mnesia:dirty_read(muc_registered, LUS) of - {'EXIT', _Reason} -> - {"", []}; - [] -> - {"", []}; - [#muc_registered{nick = N}] -> - {N, [{xmlelement, "registered", [], []}]} - end, + {Nick, Registered} = + case catch mnesia:dirty_read(muc_registered, {LUS, Host}) of + {'EXIT', _Reason} -> + {"", []}; + [] -> + {"", []}; + [#muc_registered{nick = N}] -> + {N, [{xmlelement, "registered", [], []}]} + end, Registered ++ [{xmlelement, "instructions", [], [{xmlcdata, @@ -368,7 +373,7 @@ iq_get_register_info(From, Host, Lang) -> Lang, "Enter nickname you want to register")}]}, ?XFIELD("text-single", "Nickname", "nick", Nick)]}]. -iq_set_register_info(From, XData, Lang) -> +iq_set_register_info(Host, From, XData, Lang) -> {LUser, LServer, _} = jlib:jid_tolower(From), LUS = {LUser, LServer}, case lists:keysearch("nick", 1, XData) of @@ -379,22 +384,26 @@ iq_set_register_info(From, XData, Lang) -> F = fun() -> case Nick of "" -> - mnesia:delete({muc_registered, LUS}), + mnesia:delete({muc_registered, {LUS, Host}}), ok; _ -> - Allow = case mnesia:index_read( - muc_registered, - Nick, - #muc_registered.nick) of - [] -> - true; - [#muc_registered{user = U}] -> - U == LUS - end, + Allow = + case mnesia:select( + muc_registered, + [{#muc_registered{us_host = '$1', + nick = Nick, + _ = '_'}, + [{'==', {element, 2, '$1'}, Host}], + ['$_']}]) of + [] -> + true; + [#muc_registered{us_host = {U, _Host}}] -> + U == LUS + end, if Allow -> mnesia:write( - #muc_registered{user = LUS, + #muc_registered{us_host = {LUS, Host}, nick = Nick}), ok; true -> @@ -413,7 +422,7 @@ iq_set_register_info(From, XData, Lang) -> end end. -process_iq_register_set(From, SubEl, Lang) -> +process_iq_register_set(Host, From, SubEl, Lang) -> {xmlelement, _Name, _Attrs, Els} = SubEl, case xml:remove_cdata(Els) of [{xmlelement, "x", _Attrs1, _Els1} = XEl] -> @@ -427,7 +436,7 @@ process_iq_register_set(From, SubEl, Lang) -> invalid -> {error, ?ERR_BAD_REQUEST}; _ -> - iq_set_register_info(From, XData, Lang) + iq_set_register_info(Host, From, XData, Lang) end; _ -> {error, ?ERR_BAD_REQUEST} @@ -447,30 +456,125 @@ iq_get_vcard(Lang) -> "Copyright (c) 2003-2005 Alexey Shchepin")}]}]. -broadcast_service_message(Msg) -> +broadcast_service_message(Host, Msg) -> lists:foreach( fun(#muc_online_room{pid = Pid}) -> gen_fsm:send_all_state_event( Pid, {service_message, Msg}) - end, ets:tab2list(muc_online_room)). + end, get_vh_rooms(Host)). +get_vh_rooms(Host) -> + ets:select(muc_online_room, + [{#muc_online_room{name_host = '$1', _ = '_'}, + [{'==', {element, 2, '$1'}, Host}], + ['$_']}]). -can_use_nick(_JID, "") -> +can_use_nick(_Host, _JID, "") -> false; -can_use_nick(JID, Nick) -> +can_use_nick(Host, JID, Nick) -> {LUser, LServer, _} = jlib:jid_tolower(JID), LUS = {LUser, LServer}, - case catch mnesia:dirty_index_read(muc_registered, - Nick, - #muc_registered.nick) of + case catch mnesia:dirty_select( + muc_registered, + [{#muc_registered{us_host = '$1', + nick = Nick, + _ = '_'}, + [{'==', {element, 2, '$1'}, Host}], + ['$_']}]) of {'EXIT', _Reason} -> true; [] -> true; - [#muc_registered{user = U}] -> + [#muc_registered{us_host = {U, _Host}}] -> U == LUS end. +update_tables(Host) -> + update_muc_room_table(Host), + update_muc_registered_table(Host). + +update_muc_room_table(Host) -> + Fields = record_info(fields, muc_room), + case mnesia:table_info(muc_room, attributes) of + Fields -> + ok; + [name, opts] -> + ?INFO_MSG("Converting muc_room table from " + "{name, opts} format", []), + {atomic, ok} = mnesia:create_table( + mod_muc_tmp_table, + [{disc_only_copies, [node()]}, + {type, bag}, + {local_content, true}, + {record_name, muc_room}, + {attributes, record_info(fields, muc_room)}]), + mnesia:transform_table(muc_room, ignore, Fields), + F1 = fun() -> + mnesia:write_lock_table(mod_muc_tmp_table), + mnesia:foldl( + fun(#muc_room{name_host = Name} = R, _) -> + mnesia:dirty_write( + mod_muc_tmp_table, + R#muc_room{name_host = {Name, Host}}) + end, ok, muc_room) + end, + mnesia:transaction(F1), + mnesia:clear_table(muc_room), + F2 = fun() -> + mnesia:write_lock_table(muc_room), + mnesia:foldl( + fun(R, _) -> + mnesia:dirty_write(R) + end, ok, mod_muc_tmp_table) + end, + mnesia:transaction(F2), + mnesia:delete_table(mod_muc_tmp_table); + _ -> + ?INFO_MSG("Recreating muc_room table", []), + mnesia:transform_table(muc_room, ignore, Fields) + end. + +update_muc_registered_table(Host) -> + Fields = record_info(fields, muc_registered), + case mnesia:table_info(muc_registered, attributes) of + Fields -> + ok; + [user, nick] -> + ?INFO_MSG("Converting muc_registered table from " + "{user, nick} format", []), + {atomic, ok} = mnesia:create_table( + mod_muc_tmp_table, + [{disc_only_copies, [node()]}, + {type, bag}, + {local_content, true}, + {record_name, muc_registered}, + {attributes, record_info(fields, muc_registered)}]), + mnesia:del_table_index(muc_registered, nick), + mnesia:transform_table(muc_registered, ignore, Fields), + F1 = fun() -> + mnesia:write_lock_table(mod_muc_tmp_table), + mnesia:foldl( + fun(#muc_registered{us_host = US} = R, _) -> + mnesia:dirty_write( + mod_muc_tmp_table, + R#muc_registered{us_host = {US, Host}}) + end, ok, muc_registered) + end, + mnesia:transaction(F1), + mnesia:clear_table(muc_registered), + F2 = fun() -> + mnesia:write_lock_table(muc_registered), + mnesia:foldl( + fun(R, _) -> + mnesia:dirty_write(R) + end, ok, mod_muc_tmp_table) + end, + mnesia:transaction(F2), + mnesia:delete_table(mod_muc_tmp_table); + _ -> + ?INFO_MSG("Recreating muc_registered table", []), + mnesia:transform_table(muc_registered, ignore, Fields) + end. diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 298fe076..0a90faf3 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -149,6 +149,7 @@ normal_state({route, From, "", case (NSD#state.config)#config.persistent of true -> mod_muc:store_room( + NSD#state.host, NSD#state.room, make_opts(NSD)); _ -> @@ -364,7 +365,8 @@ normal_state({route, From, Nick, case is_nick_change(From, Nick, StateData) of true -> case {is_nick_exists(Nick, StateData), - mod_muc:can_use_nick(From, Nick)} of + mod_muc:can_use_nick( + StateData#state.host, From, Nick)} of {true, _} -> Lang = xml:get_attr_s("xml:lang", Attrs), ErrText = "Nickname is already in use by another occupant", @@ -639,7 +641,7 @@ handle_info(_Info, StateName, StateData) -> %% Returns: any %%---------------------------------------------------------------------- terminate(_Reason, _StateName, StateData) -> - mod_muc:room_destroyed(StateData#state.room), + mod_muc:room_destroyed(StateData#state.host, StateData#state.room), ok. %%%---------------------------------------------------------------------- @@ -806,8 +808,8 @@ filter_presence({xmlelement, "presence", Attrs, Els}) -> case El of {xmlcdata, _} -> false; - {xmlelement, Name1, Attrs1, _Els1} -> - XMLNS = xml:get_attr_s("xmlns", Attrs1), + {xmlelement, Name1, _Attrs1, _Els1} -> + XMLNS = xml:get_attr_s("xmlns", Attrs), case {Name1, XMLNS} of {"show", ""} -> true; @@ -872,7 +874,7 @@ is_nick_change(JID, Nick, StateData) -> add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) -> Lang = xml:get_attr_s("xml:lang", Attrs), case {is_nick_exists(Nick, StateData), - mod_muc:can_use_nick(From, Nick)} of + mod_muc:can_use_nick(StateData#state.host, From, Nick)} of {true, _} -> ErrText = "Nickname is already in use by another occupant", Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)), @@ -1517,7 +1519,8 @@ process_admin_items_set(UJID, Items, Lang, StateData) -> io:format("MUC SET: ~p~n", [Res]), case (NSD#state.config)#config.persistent of true -> - mod_muc:store_room(NSD#state.room, make_opts(NSD)); + mod_muc:store_room(NSD#state.host, NSD#state.room, + make_opts(NSD)); _ -> ok end, @@ -2043,9 +2046,9 @@ change_config(Config, StateData) -> case {(StateData#state.config)#config.persistent, Config#config.persistent} of {_, true} -> - mod_muc:store_room(NSD#state.room, make_opts(NSD)); + mod_muc:store_room(NSD#state.host, NSD#state.room, make_opts(NSD)); {true, false} -> - mod_muc:forget_room(NSD#state.room); + mod_muc:forget_room(NSD#state.host, NSD#state.room); {false, false} -> ok end, @@ -2130,7 +2133,7 @@ destroy_room(DEls, StateData) -> end, ?DICT:to_list(StateData#state.users)), case (StateData#state.config)#config.persistent of true -> - mod_muc:forget_room(StateData#state.room); + mod_muc:forget_room(StateData#state.host, StateData#state.room); false -> ok end, |