aboutsummaryrefslogtreecommitdiff
path: root/src/mod_irc
diff options
context:
space:
mode:
authortmallard <tmallard@null>2005-04-17 18:08:34 +0000
committertmallard <tmallard@null>2005-04-17 18:08:34 +0000
commit374446f8471747c878cdaf760c4bb37d17493ab7 (patch)
treee91bac5669555dcf33627e4745b04236f743126d /src/mod_irc
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_irc')
-rw-r--r--src/mod_irc/mod_irc.erl123
-rw-r--r--src/mod_irc/mod_irc_connection.erl53
2 files changed, 112 insertions, 64 deletions
diff --git a/src/mod_irc/mod_irc.erl b/src/mod_irc/mod_irc.erl
index 1a9d78ce2..337d9761b 100644
--- a/src/mod_irc/mod_irc.erl
+++ b/src/mod_irc/mod_irc.erl
@@ -12,48 +12,51 @@
-behaviour(gen_mod).
--export([start/1, init/2, stop/0, closed_conection/2,
- get_user_and_encoding/2]).
+-export([start/1, init/2, stop/0,
+ closed_connection/3,
+ get_user_and_encoding/3]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(DEFAULT_IRC_ENCODING, "koi8-r").
--record(irc_connection, {userserver, pid}).
--record(irc_custom, {userserver, data}).
+-record(irc_connection, {jid_server_host, pid}).
+-record(irc_custom, {us_host, data}).
start(Opts) ->
iconv:start(),
mnesia:create_table(irc_custom,
[{disc_copies, [node()]},
{attributes, record_info(fields, irc_custom)}]),
- Host = gen_mod:get_opt(host, Opts, "irc." ++ ?MYNAME),
+ Hosts = gen_mod:get_hosts(Opts, "irc."),
+ Host = hd(Hosts),
+ update_table(Host),
Access = gen_mod:get_opt(access, Opts, all),
- register(ejabberd_mod_irc, spawn(?MODULE, init, [Host, Access])).
+ register(ejabberd_mod_irc, spawn(?MODULE, init, [Hosts, Access])).
-init(Host, Access) ->
+init(Hosts, Access) ->
catch ets:new(irc_connection, [named_table,
public,
- {keypos, #irc_connection.userserver}]),
- ejabberd_router:register_route(Host),
- loop(Host, Access).
+ {keypos, #irc_connection.jid_server_host}]),
+ ejabberd_router:register_routes(Hosts),
+ 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);
+ loop(Hosts, Access);
stop ->
- ejabberd_router:unregister_global_route(Host),
+ ejabberd_router:unregister_routes(Hosts),
ok;
_ ->
- loop(Host, Access)
+ loop(Hosts, Access)
end.
@@ -96,7 +99,7 @@ do_route1(Host, From, To, Packet) ->
From,
jlib:iq_to_xml(Res));
#iq{xmlns = ?NS_REGISTER} = IQ ->
- process_register(From, To, IQ);
+ process_register(Host, From, To, IQ);
#iq{type = get, xmlns = ?NS_VCARD = XMLNS,
lang = Lang} = IQ ->
Res = IQ#iq{type = result,
@@ -121,17 +124,17 @@ do_route1(Host, From, To, Packet) ->
_ ->
case string:tokens(ChanServ, "%") of
[[_ | _] = Channel, [_ | _] = Server] ->
- case ets:lookup(irc_connection, {From, Server}) of
+ case ets:lookup(irc_connection, {From, Server, Host}) of
[] ->
io:format("open new connection~n"),
{Username, Encoding} = get_user_and_encoding(
- From, Server),
+ Host, From, Server),
{ok, Pid} = mod_irc_connection:start(
From, Host, Server,
Username, Encoding),
ets:insert(
irc_connection,
- #irc_connection{userserver = {From, Server},
+ #irc_connection{jid_server_host = {From, Server, Host},
pid = Pid}),
mod_irc_connection:route_chan(
Pid, Channel, Resource, Packet),
@@ -147,7 +150,7 @@ do_route1(Host, From, To, Packet) ->
_ ->
case string:tokens(ChanServ, "!") of
[[_ | _] = Nick, [_ | _] = Server] ->
- case ets:lookup(irc_connection, {From, Server}) of
+ case ets:lookup(irc_connection, {From, Server, Host}) of
[] ->
Err = jlib:make_error_reply(
Packet, ?ERR_SERVICE_UNAVAILABLE),
@@ -175,8 +178,8 @@ stop() ->
ejabberd_mod_irc ! stop,
ok.
-closed_conection(From, Server) ->
- ets:delete(irc_connection, {From, Server}).
+closed_connection(Host, From, Server) ->
+ ets:delete(irc_connection, {From, Server, Host}).
iq_disco() ->
@@ -201,8 +204,8 @@ iq_get_vcard(Lang) ->
[{xmlcdata, translate:translate(Lang, "ejabberd IRC module\n"
"Copyright (c) 2003-2005 Alexey Shchepin")}]}].
-process_register(From, To, #iq{} = IQ) ->
- case catch process_irc_register(From, To, IQ) of
+process_register(Host, From, To, #iq{} = IQ) ->
+ case catch process_irc_register(Host, From, To, IQ) of
{'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]);
ResIQ ->
@@ -232,7 +235,7 @@ find_xdata_el1([{xmlelement, Name, Attrs, SubEls} | Els]) ->
find_xdata_el1([_ | Els]) ->
find_xdata_el1(Els).
-process_irc_register(From, To,
+process_irc_register(Host, From, To,
#iq{type = Type, xmlns = XMLNS,
lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
@@ -257,7 +260,8 @@ process_irc_register(From, To,
Node = string:tokens(
xml:get_tag_attr_s("node", SubEl),
"/"),
- case set_form(From, Node, Lang, XData) of
+ case set_form(
+ Host, From, Node, Lang, XData) of
{result, Res} ->
IQ#iq{type = result,
sub_el = [{xmlelement, "query",
@@ -277,7 +281,7 @@ process_irc_register(From, To,
get ->
Node =
string:tokens(xml:get_tag_attr_s("node", SubEl), "/"),
- case get_form(From, Node, Lang) of
+ case get_form(Host, From, Node, Lang) of
{result, Res} ->
IQ#iq{type = result,
sub_el = [{xmlelement, "query",
@@ -292,11 +296,12 @@ process_irc_register(From, To,
-get_form(From, [], Lang) ->
+get_form(Host, From, [], Lang) ->
#jid{user = User, server = Server,
luser = LUser, lserver = LServer} = From,
+ US = {LUser, LServer},
Customs =
- case catch mnesia:dirty_read({irc_custom, {LUser, LServer}}) of
+ case catch mnesia:dirty_read({irc_custom, {US, Host}}) of
{'EXIT', Reason} ->
{error, ?ERR_INTERNAL_SERVER_ERROR};
[] ->
@@ -306,7 +311,7 @@ get_form(From, [], Lang) ->
xml:get_attr_s(encodings, Data)}
end,
case Customs of
- {error, _, _} ->
+ {error, _Error} ->
Customs;
{Username, Encodings} ->
{result,
@@ -370,15 +375,15 @@ get_form(From, [], Lang) ->
]}]}
end;
-
-get_form(_, _, Lang) ->
+get_form(_Host, _, _, Lang) ->
{error, ?ERR_SERVICE_UNAVAILABLE}.
-set_form(From, [], Lang, XData) ->
+set_form(Host, From, [], Lang, XData) ->
{LUser, LServer, _} = jlib:jid_tolower(From),
+ US = {LUser, LServer},
case {lists:keysearch("username", 1, XData),
lists:keysearch("encodings", 1, XData)} of
{{value, {_, [Username]}}, {value, {_, Strings}}} ->
@@ -392,8 +397,8 @@ set_form(From, [], Lang, XData) ->
case mnesia:transaction(
fun() ->
mnesia:write(
- #irc_custom{userserver =
- {LUser, LServer},
+ #irc_custom{us_host =
+ {US, Host},
data =
[{username,
Username},
@@ -416,14 +421,15 @@ set_form(From, [], Lang, XData) ->
end;
-set_form(_, _, Lang, XData) ->
+set_form(_Host, _, _, Lang, XData) ->
{error, ?ERR_SERVICE_UNAVAILABLE}.
-get_user_and_encoding(From, IRCServer) ->
+get_user_and_encoding(Host, From, IRCServer) ->
#jid{user = User, server = Server,
luser = LUser, lserver = LServer} = From,
- case catch mnesia:dirty_read({irc_custom, {LUser, LServer}}) of
+ US = {LUser, LServer},
+ case catch mnesia:dirty_read({irc_custom, {US, Host}}) of
{'EXIT', Reason} ->
{User, ?DEFAULT_IRC_ENCODING};
[] ->
@@ -436,3 +442,44 @@ get_user_and_encoding(From, IRCServer) ->
end}
end.
+
+update_table(Host) ->
+ Fields = record_info(fields, irc_custom),
+ case mnesia:table_info(irc_custom, attributes) of
+ Fields ->
+ ok;
+ [userserver, data] ->
+ ?INFO_MSG("Converting irc_custom table from "
+ "{userserver, data} format", []),
+ {atomic, ok} = mnesia:create_table(
+ mod_irc_tmp_table,
+ [{disc_only_copies, [node()]},
+ {type, bag},
+ {local_content, true},
+ {record_name, irc_custom},
+ {attributes, record_info(fields, irc_custom)}]),
+ mnesia:transform_table(irc_custom, ignore, Fields),
+ F1 = fun() ->
+ mnesia:write_lock_table(mod_irc_tmp_table),
+ mnesia:foldl(
+ fun(#irc_custom{us_host = US} = R, _) ->
+ mnesia:dirty_write(
+ mod_irc_tmp_table,
+ R#irc_custom{us_host = {US, Host}})
+ end, ok, irc_custom)
+ end,
+ mnesia:transaction(F1),
+ mnesia:clear_table(irc_custom),
+ F2 = fun() ->
+ mnesia:write_lock_table(irc_custom),
+ mnesia:foldl(
+ fun(R, _) ->
+ mnesia:dirty_write(R)
+ end, ok, mod_irc_tmp_table)
+ end,
+ mnesia:transaction(F2),
+ mnesia:delete_table(mod_irc_tmp_table);
+ _ ->
+ ?INFO_MSG("Recreating irc_custom table", []),
+ mnesia:transform_table(irc_custom, ignore, Fields)
+ end.
diff --git a/src/mod_irc/mod_irc_connection.erl b/src/mod_irc/mod_irc_connection.erl
index fff4fedf8..11a172914 100644
--- a/src/mod_irc/mod_irc_connection.erl
+++ b/src/mod_irc/mod_irc_connection.erl
@@ -32,7 +32,7 @@
-define(SETS, gb_sets).
-record(state, {socket, encoding, receiver, queue,
- user, myname, server, nick,
+ user, host, server, nick,
channels = dict:new(),
inbuf = "", outbuf = ""}).
@@ -67,7 +67,7 @@ init([From, Host, Server, Username, Encoding]) ->
encoding = Encoding,
user = From,
nick = Username,
- myname = Host,
+ host = Host,
server = Server}}.
%%----------------------------------------------------------------------
@@ -90,7 +90,7 @@ open_socket(init, StateData) ->
"USER ~s ~s ~s :~s\r\n",
[StateData#state.nick,
StateData#state.nick,
- StateData#state.myname,
+ StateData#state.host,
StateData#state.nick])),
send_text(NewStateData,
io_lib:format("CODEPAGE ~s\r\n", [StateData#state.encoding])),
@@ -231,7 +231,7 @@ handle_info({route_chan, Channel, Resource,
jlib:make_jid(
lists:concat(
[Channel, "%", StateData#state.server]),
- StateData#state.myname, StateData#state.nick),
+ StateData#state.host, StateData#state.nick),
StateData#state.user, El),
Body = xml:get_path_s(El, [{elem, "body"}, cdata]),
case Body of
@@ -304,7 +304,7 @@ handle_info({route_chan, Channel, Resource,
StateName, StateData) ->
From = StateData#state.user,
To = jlib:make_jid(lists:concat([Channel, "%", StateData#state.server]),
- StateData#state.myname, StateData#state.nick),
+ StateData#state.host, StateData#state.nick),
case jlib:iq_query_info(El) of
#iq{xmlns = ?NS_MUC_ADMIN} = IQ ->
iq_admin(StateData, Channel, From, To, IQ);
@@ -474,15 +474,16 @@ handle_info({tcp_error, Socket, Reason}, StateName, StateData) ->
%% Returns: any
%%----------------------------------------------------------------------
terminate(Reason, StateName, StateData) ->
- mod_irc:closed_conection(StateData#state.user,
- StateData#state.server),
+ mod_irc:closed_connection(StateData#state.host,
+ StateData#state.user,
+ StateData#state.server),
bounce_messages("Server Connect Failed"),
lists:foreach(
fun(Chan) ->
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, StateData#state.nick),
+ StateData#state.host, StateData#state.nick),
StateData#state.user,
{xmlelement, "presence", [{"type", "error"}],
[{xmlelement, "error", [{"code", "502"}],
@@ -592,7 +593,7 @@ process_channel_list_user(StateData, Chan, User) ->
end,
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, User2),
+ StateData#state.host, User2),
StateData#state.user,
{xmlelement, "presence", [],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -618,7 +619,7 @@ process_channel_topic(StateData, Chan, String) ->
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
[{xmlelement, "subject", [], [{xmlcdata, Msg1}]}]}).
@@ -636,7 +637,7 @@ process_chanprivmsg(StateData, Chan, From, String) ->
Msg2 = filter_message(Msg1),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
@@ -655,7 +656,7 @@ process_channotice(StateData, Chan, From, String) ->
Msg2 = filter_message(Msg1),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
[{xmlelement, "body", [], [{xmlcdata, "NOTICE: " ++ Msg2}]}]}).
@@ -675,7 +676,7 @@ process_privmsg(StateData, Nick, From, String) ->
Msg2 = filter_message(Msg1),
ejabberd_router:route(
jlib:make_jid(lists:concat([FromUser, "!", StateData#state.server]),
- StateData#state.myname, ""),
+ StateData#state.host, ""),
StateData#state.user,
{xmlelement, "message", [{"type", "chat"}],
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
@@ -693,7 +694,7 @@ process_notice(StateData, Nick, From, String) ->
Msg2 = filter_message(Msg1),
ejabberd_router:route(
jlib:make_jid(lists:concat([FromUser, "!", StateData#state.server]),
- StateData#state.myname, ""),
+ StateData#state.host, ""),
StateData#state.user,
{xmlelement, "message", [{"type", "chat"}],
[{xmlelement, "body", [], [{xmlcdata, "NOTICE: " ++ Msg2}]}]}).
@@ -719,7 +720,7 @@ process_topic(StateData, Chan, From, String) ->
Msg1 = filter_message(Msg),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
[{xmlelement, "subject", [], [{xmlcdata, Msg1}]},
@@ -733,7 +734,7 @@ process_part(StateData, Chan, From, String) ->
Msg1 = filter_message(Msg),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
[{xmlelement, "body", [],
@@ -742,7 +743,7 @@ process_part(StateData, Chan, From, String) ->
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -777,7 +778,7 @@ process_quit(StateData, From, String) ->
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
[{xmlelement, "body", [],
@@ -787,7 +788,7 @@ process_quit(StateData, From, String) ->
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -811,7 +812,7 @@ process_join(StateData, Channel, From, String) ->
Chan = lists:subtract(Channel, ":#"),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "presence", [],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -825,7 +826,7 @@ process_join(StateData, Channel, From, String) ->
Msg1 = filter_message(Msg),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
[{xmlelement, "body", [],
@@ -848,7 +849,7 @@ process_mode_o(StateData, Chan, From, Nick, Affiliation, Role) ->
%Msg = lists:last(string:tokens(String, ":")),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, Nick),
+ StateData#state.host, Nick),
StateData#state.user,
{xmlelement, "presence", [],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -861,7 +862,7 @@ process_kick(StateData, Chan, From, Nick) ->
%Msg = lists:last(string:tokens(String, ":")),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, Nick),
+ StateData#state.host, Nick),
StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -883,7 +884,7 @@ process_nick(StateData, From, NewNick) ->
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, FromUser),
+ StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -897,7 +898,7 @@ process_nick(StateData, From, NewNick) ->
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, Nick),
+ StateData#state.host, Nick),
StateData#state.user,
{xmlelement, "presence", [],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
@@ -921,7 +922,7 @@ process_error(StateData, String) ->
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.myname, StateData#state.nick),
+ StateData#state.host, StateData#state.nick),
StateData#state.user,
{xmlelement, "presence", [{"type", "error"}],
[{xmlelement, "error", [{"code", "502"}],