* src/ejabberd_s2s_in.erl: Changed timeout processing, bugfix

* src/ejabberd_s2s_out.erl: Changed timeout processing

* src/msgs/ru.msg: Updated (thanks to Sergei Golovan)

* src/mod_muc/mod_muc.erl: Better i18n support, added support for
<registered/> field in iq:register replies (thanks to Sergei
Golovan)

* src/mod_register.erl: More i18n support (thanks to Sergei
Golovan)

SVN Revision: 181
This commit is contained in:
Alexey Shchepin 2003-12-06 19:58:49 +00:00
parent 83a0be1009
commit 6f9a3922ef
6 changed files with 137 additions and 56 deletions

View File

@ -1,3 +1,18 @@
2003-12-06 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_s2s_in.erl: Changed timeout processing, bugfix
* src/ejabberd_s2s_out.erl: Changed timeout processing
* src/msgs/ru.msg: Updated (thanks to Sergei Golovan)
* src/mod_muc/mod_muc.erl: Better i18n support, added support for
<registered/> field in iq:register replies (thanks to Sergei
Golovan)
* src/mod_register.erl: More i18n support (thanks to Sergei
Golovan)
2003-12-02 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_c2s.erl: Bugfix in processing of connection

View File

@ -37,7 +37,8 @@
receiver,
streamid,
shaper,
connections = ?DICT:new()}).
connections = ?DICT:new(),
timer}).
%-define(DBGFSM, true).
@ -95,12 +96,13 @@ init([{SockMod, Socket}, Opts]) ->
{value, {_, S}} -> S;
_ -> none
end,
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
{ok, wait_for_stream,
#state{socket = Socket,
receiver = ReceiverPid,
streamid = new_id(),
shaper = Shaper},
?S2STIMEOUT}.
shaper = Shaper,
timer = Timer}}.
%%----------------------------------------------------------------------
%% Func: StateName/2
@ -114,7 +116,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
case {xml:get_attr_s("xmlns", Attrs), xml:get_attr_s("xmlns:db", Attrs)} of
{"jabber:server", "jabber:server:dialback"} ->
send_text(StateData#state.socket, ?STREAM_HEADER),
{next_state, stream_established, StateData#state{}, ?S2STIMEOUT};
{next_state, stream_established, StateData#state{}};
_ ->
send_text(StateData#state.socket, ?INVALID_NAMESPACE_ERR),
{stop, normal, StateData}
@ -132,6 +134,8 @@ wait_for_stream(closed, StateData) ->
{stop, normal, StateData}.
stream_established({xmlstreamelement, El}, StateData) ->
cancel_timer(StateData#state.timer),
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
case is_key_packet(El) of
{key, To, From, Id, Key} ->
?INFO_MSG("GET KEY: ~p", [{To, From, Id, Key}]),
@ -147,8 +151,8 @@ stream_established({xmlstreamelement, El}, StateData) ->
change_shaper(StateData, jlib:make_jid("", LFrom, "")),
{next_state,
stream_established,
StateData#state{connections = Conns},
?S2STIMEOUT};
StateData#state{connections = Conns,
timer = Timer}};
_ ->
send_text(StateData#state.socket, ?HOST_UNKNOWN_ERR),
{stop, normal, StateData}
@ -169,7 +173,7 @@ stream_established({xmlstreamelement, El}, StateData) ->
{"id", Id},
{"type", Type}],
[]}),
{next_state, wait_for_key, StateData, ?S2STIMEOUT};
{next_state, stream_established, StateData#state{timer = Timer}};
_ ->
{xmlelement, Name, Attrs, _Els} = El,
From_s = xml:get_attr_s("from", Attrs),
@ -195,9 +199,9 @@ stream_established({xmlstreamelement, El}, StateData) ->
end;
true ->
error
end
end,
{next_state, stream_established, StateData, ?S2STIMEOUT};
end,
{next_state, stream_established, StateData#state{timer = Timer}}
end;
stream_established({valid, From, To}, StateData) ->
send_element(StateData#state.socket,
@ -212,7 +216,7 @@ stream_established({valid, From, To}, StateData) ->
NSD = StateData#state{
connections = ?DICT:store({LFrom, LTo}, established,
StateData#state.connections)},
{next_state, stream_established, NSD, ?S2STIMEOUT};
{next_state, stream_established, NSD};
stream_established({invalid, From, To}, StateData) ->
send_element(StateData#state.socket,
@ -225,9 +229,9 @@ stream_established({invalid, From, To}, StateData) ->
LFrom = jlib:nameprep(From),
LTo = jlib:nameprep(To),
NSD = StateData#state{
connections = ?DICT:store({LFrom, LTo}, established,
connections = ?DICT:erase({LFrom, LTo},
StateData#state.connections)},
{next_state, stream_established, NSD, ?S2STIMEOUT};
{next_state, stream_established, NSD};
stream_established({xmlstreamend, _Name}, StateData) ->
{stop, normal, StateData};
@ -265,7 +269,7 @@ stream_established(closed, StateData) ->
%% {stop, Reason, NewStateData}
%%----------------------------------------------------------------------
handle_event(_Event, StateName, StateData) ->
{next_state, StateName, StateData, ?S2STIMEOUT}.
{next_state, StateName, StateData}.
%%----------------------------------------------------------------------
%% Func: handle_sync_event/4
@ -292,6 +296,11 @@ code_change(_OldVsn, StateName, StateData, _Extra) ->
handle_info({send_text, Text}, StateName, StateData) ->
send_text(StateData#state.socket, Text),
{next_state, StateName, StateData};
handle_info({timeout, Timer, _}, StateName,
#state{timer = Timer} = StateData) ->
{stop, normal, StateData};
handle_info(_, StateName, StateData) ->
{next_state, StateName, StateData}.
@ -333,6 +342,15 @@ change_shaper(StateData, JID) ->
new_id() ->
randoms:get_string().
cancel_timer(Timer) ->
erlang:cancel_timer(Timer),
receive
{timeout, Timer, _} ->
ok
after 0 ->
ok
end.
is_key_packet({xmlelement, Name, Attrs, Els}) when Name == "db:result" ->
{key,

View File

@ -32,7 +32,8 @@
-record(state, {socket, receiver, streamid,
myname, server, xmlpid, queue,
new = false, verify = false}).
new = false, verify = false,
timer}).
%-define(DBGFSM, true).
@ -91,12 +92,13 @@ init([From, Server, Type]) ->
{verify, Pid, Key, SID} ->
{false, {Pid, Key, SID}}
end,
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
{ok, open_socket, #state{queue = queue:new(),
myname = From,
server = Server,
new = New,
verify = Verify},
?S2STIMEOUT}.
verify = Verify,
timer = Timer}}.
%%----------------------------------------------------------------------
%% Func: StateName/2
@ -123,8 +125,7 @@ open_socket(init, StateData) ->
{next_state, wait_for_stream,
StateData#state{socket = Socket,
xmlpid = XMLStreamPid,
streamid = new_id()},
?S2STIMEOUT};
streamid = new_id()}};
{error, Reason} ->
?DEBUG("s2s_out: inet6 connect return ~p~n", [Reason]),
Error = ?ERR_REMOTE_SERVER_NOT_FOUND,
@ -174,8 +175,7 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
{"id", SID}],
[{xmlcdata, Key2}]})
end,
{next_state, wait_for_validation,
StateData#state{new = New}, ?S2STIMEOUT};
{next_state, wait_for_validation, StateData#state{new = New}};
_ ->
send_text(StateData#state.socket, ?INVALID_NAMESPACE_ERR),
{stop, normal, StateData}
@ -201,7 +201,7 @@ wait_for_validation({xmlstreamelement, El}, StateData) ->
case Type of
"valid" ->
send_queue(StateData#state.socket, StateData#state.queue),
{next_state, stream_established, StateData, ?S2STIMEOUT};
{next_state, stream_established, StateData};
_ ->
% TODO: bounce packets
{stop, normal, StateData}
@ -210,7 +210,7 @@ wait_for_validation({xmlstreamelement, El}, StateData) ->
?INFO_MSG("recv verify: ~p", [{From, To, Id, Type}]),
case StateData#state.verify of
false ->
{next_state, wait_for_validation, StateData, ?S2STIMEOUT};
{next_state, wait_for_validation, StateData};
{Pid, _Key, _SID} ->
case Type of
"valid" ->
@ -227,7 +227,7 @@ wait_for_validation({xmlstreamelement, El}, StateData) ->
{stop, normal, StateData}
end;
_ ->
{next_state, wait_for_validation, StateData, ?S2STIMEOUT}
{next_state, wait_for_validation, StateData}
end;
wait_for_validation({xmlstreamend, Name}, StateData) ->
@ -270,7 +270,7 @@ stream_established({xmlstreamelement, El}, StateData) ->
_ ->
ok
end,
{next_state, stream_established, StateData, ?S2STIMEOUT};
{next_state, stream_established, StateData};
stream_established({xmlstreamend, Name}, StateData) ->
{stop, normal, StateData};
@ -334,24 +334,40 @@ code_change(OldVsn, StateName, StateData, Extra) ->
%%----------------------------------------------------------------------
handle_info({send_text, Text}, StateName, StateData) ->
send_text(StateData#state.socket, Text),
{next_state, StateName, StateData};
cancel_timer(StateData#state.timer),
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
{next_state, StateName, StateData#state{timer = Timer}};
handle_info({send_element, El}, StateName, StateData) ->
cancel_timer(StateData#state.timer),
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
case StateName of
stream_established ->
send_element(StateData#state.socket, El),
{next_state, StateName, StateData};
{next_state, StateName, StateData#state{timer = Timer}};
_ ->
Q = queue:in(El, StateData#state.queue),
{next_state, StateName, StateData#state{queue = Q}}
{next_state, StateName, StateData#state{queue = Q,
timer = Timer}}
end;
handle_info({tcp, Socket, Data}, StateName, StateData) ->
xml_stream:send_text(StateData#state.xmlpid, Data),
{next_state, StateName, StateData};
handle_info({tcp_closed, Socket}, StateName, StateData) ->
gen_fsm:send_event(self(), closed),
{next_state, StateName, StateData};
handle_info({tcp_error, Socket, Reason}, StateName, StateData) ->
gen_fsm:send_event(self(), closed),
{next_state, StateName, StateData};
handle_info({timeout, Timer, _}, StateName,
#state{timer = Timer} = StateData) ->
{stop, normal, StateData};
handle_info(_, StateName, StateData) ->
{next_state, StateName, StateData}.
%%----------------------------------------------------------------------
@ -361,6 +377,8 @@ handle_info({tcp_error, Socket, Reason}, StateName, StateData) ->
%%----------------------------------------------------------------------
terminate(Reason, StateName, StateData) ->
?INFO_MSG("terminated: ~p", [Reason]),
Error = ?ERR_REMOTE_SERVER_NOT_FOUND,
bounce_queue(StateData#state.queue, Error),
case StateData#state.new of
false ->
ok;
@ -396,13 +414,34 @@ send_queue(Socket, Q) ->
ok
end.
bounce_queue(Q, Error) ->
case queue:out(Q) of
{{value, El}, Q1} ->
Err = jlib:make_error_reply(El, Error),
From = jlib:string_to_jid(xml:get_tag_attr_s("from", El)),
To = jlib:string_to_jid(xml:get_tag_attr_s("to", El)),
ejabberd_router:route(To, From, Err),
bounce_queue(Q1, Error);
{empty, Q1} ->
ok
end.
new_id() ->
randoms:get_string().
cancel_timer(Timer) ->
erlang:cancel_timer(Timer),
receive
{timeout, Timer, _} ->
ok
after 0 ->
ok
end.
bounce_messages(Error) ->
receive
{send_element, El} ->
{xmlelement, Name, Attrs, SubTags} = El,
{xmlelement, _Name, Attrs, _SubTags} = El,
case xml:get_attr_s("type", Attrs) of
"error" ->
ok;
@ -410,7 +449,7 @@ bounce_messages(Error) ->
Err = jlib:make_error_reply(El, Error),
From = jlib:string_to_jid(xml:get_attr_s("from", Attrs)),
To = jlib:string_to_jid(xml:get_attr_s("to", Attrs)),
ejabberd_router ! {route, To, From, Err}
ejabberd_router:route(To, From, Err)
end,
bounce_messages(Error)
after 0 ->

View File

@ -298,28 +298,30 @@ iq_disco_items(Host, From) ->
iq_get_register_info(From, Lang) ->
{LUser, LServer, _} = jlib:jid_tolower(From),
LUS = {LUser, LServer},
Nick = case catch mnesia:dirty_read(muc_registered, LUS) of
{Nick, Registered} = case catch mnesia:dirty_read(muc_registered, LUS) of
{'EXIT', Reason} ->
"";
{"", []};
[] ->
"";
{"", []};
[#muc_registered{nick = N}] ->
N
{N, [{xmlelement, "registered", [], []}]}
end,
[{xmlelement, "instructions", [],
[{xmlcdata, translate:translate(
Lang, "You need a x:data capable client to register.")}]},
{xmlelement, "x",
[{"xmlns", ?NS_XDATA}],
[{xmlelement, "title", [],
[{xmlcdata,
translate:translate(
Lang, "Nick Registration")}]},
{xmlelement, "instructions", [],
[{xmlcdata,
translate:translate(
Lang, "Enter nick you want to register.")}]},
?XFIELD("text-single", "Nick", "nick", Nick)]}].
Registered ++
[{xmlelement, "instructions", [],
[{xmlcdata,
translate:translate(
Lang, "You need a x:data capable client to register.")}]},
{xmlelement, "x",
[{"xmlns", ?NS_XDATA}],
[{xmlelement, "title", [],
[{xmlcdata,
translate:translate(
Lang, "Nickname Registration")}]},
{xmlelement, "instructions", [],
[{xmlcdata,
translate:translate(
Lang, "Enter nickname you want to register.")}]},
?XFIELD("text-single", "Nickname", "nick", Nick)]}].
iq_set_register_info(From, XData) ->
{LUser, LServer, _} = jlib:jid_tolower(From),
@ -358,7 +360,7 @@ iq_set_register_info(From, XData) ->
{atomic, ok} ->
{result, []};
{atomic, false} ->
{error, ?ERR_NOT_ALLOWED};
{error, ?ERR_CONFLICT};
_ ->
{error, ?ERR_INTERNAL_SERVER_ERROR}
end
@ -394,8 +396,8 @@ iq_get_vcard(Lang) ->
[{xmlcdata,
"http://ejabberd.jabberstudio.org/"}]},
{xmlelement, "DESC", [],
[{xmlcdata, "ejabberd MUC module\n"
"Copyright (c) 2003 Alexey Shchepin"}]}].
[{xmlcdata, translate:translate(Lang, "ejabberd MUC module\n"
"Copyright (c) 2003 Alexey Shchepin")}]}].
broadcast_service_message(Msg) ->

View File

@ -99,13 +99,15 @@ process_iq(From, _To, {iq, ID, Type, XMLNS, SubEl}) ->
[SubEl, ?ERR_BAD_REQUEST]}
end;
get ->
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
{iq, ID, result, XMLNS, [{xmlelement,
"query",
[{"xmlns", "jabber:iq:register"}],
[{xmlelement, "instructions", [],
[{xmlcdata,
"Choose a username and password "
"to register with this server."}]},
translate:translate(Lang,
"Choose a username and password "
"to register with this server.")}]},
{xmlelement, "username", [], []},
{xmlelement, "password", [], []}]}]}
end.

View File

@ -38,8 +38,9 @@
{"Start Modules", "Запуск модулей"}.
{"Stop Modules", "Остановка модулей"}.
% mod_register.erl
{"Choose a username and password to register with this server.",
"Выберите идентификатор пользователя и пароль для регистрации на этом сервере."}.
% mod_vcard.erl
{"You need a x:data capable client to search",
@ -62,9 +63,13 @@
{"Organization Name", "Название организации"}.
{"Organization Unit", "Отдел организации"}.
% mod_muc/mod_muc.erl
{"Nickname Registration", "Регистрация псевдонима"}.
{"Enter nickname you want to register.", "Введите псевдоним, который вы хотели бы зарегистрировать"}.
{"ejabberd MUC module\nCopyright (c) 2003 Alexey Shchepin",
"ejabberd MUC модуль\nCopyright (c) 2003 Алексей Щепин"}.
% mod_muc/mod_muc_room.erl
{"Room title", "Название комнаты"}.
{"Allow users to change subject?", "Разрешить пользователям изменять тему?"}.
{"Allow users to query other users?",