Merge pull request #377 from weiss/new-timestamps

Add timestamps to stanzas resent from stream management queue
This commit is contained in:
Evgeny Khramtsov 2014-12-13 09:42:30 +03:00
commit df88d9f2e5
7 changed files with 167 additions and 163 deletions

View File

@ -2049,13 +2049,9 @@ process_presence_probe(From, To, StateData) ->
?SETS:is_element(LBFrom, StateData#state.pres_f)), ?SETS:is_element(LBFrom, StateData#state.pres_f)),
if if
Cond -> Cond ->
Timestamp = StateData#state.pres_timestamp, %% To is the one sending the presence (the probe target)
Packet = xml:append_subtags( Packet = jlib:add_delay_info(StateData#state.pres_last, To,
StateData#state.pres_last, StateData#state.pres_timestamp),
%% To is the one sending the presence (the target of the probe)
[jlib:timestamp_to_xml(Timestamp, utc, To, <<"">>),
%% TODO: Delete the next line once XEP-0091 is Obsolete
jlib:timestamp_to_xml(Timestamp)]),
case privacy_check_packet(StateData, To, From, Packet, out) of case privacy_check_packet(StateData, To, From, Packet, out) of
deny -> deny ->
ok; ok;
@ -2107,12 +2103,11 @@ presence_update(From, Packet, StateData) ->
OldPresence -> get_priority_from_presence(OldPresence) OldPresence -> get_priority_from_presence(OldPresence)
end, end,
NewPriority = get_priority_from_presence(Packet), NewPriority = get_priority_from_presence(Packet),
Timestamp = calendar:now_to_universal_time(now()),
update_priority(NewPriority, Packet, StateData), update_priority(NewPriority, Packet, StateData),
FromUnavail = (StateData#state.pres_last == undefined), FromUnavail = (StateData#state.pres_last == undefined),
?DEBUG("from unavail = ~p~n", [FromUnavail]), ?DEBUG("from unavail = ~p~n", [FromUnavail]),
NewStateData = StateData#state{pres_last = Packet, NewStateData = StateData#state{pres_last = Packet,
pres_timestamp = Timestamp}, pres_timestamp = now()},
NewState = if FromUnavail -> NewState = if FromUnavail ->
ejabberd_hooks:run(user_available_hook, ejabberd_hooks:run(user_available_hook,
NewStateData#state.server, NewStateData#state.server,
@ -2805,7 +2800,10 @@ handle_resume(StateData, Attrs) ->
{<<"h">>, AttrH}, {<<"h">>, AttrH},
{<<"previd">>, AttrId}], {<<"previd">>, AttrId}],
children = []}), children = []}),
SendFun = fun(_F, _T, El) -> send_element(NewState, El) end, SendFun = fun(_F, _T, El, Time) ->
NewEl = add_resent_delay_info(NewState, El, Time),
send_element(NewState, NewEl)
end,
handle_unacked_stanzas(NewState, SendFun), handle_unacked_stanzas(NewState, SendFun),
send_element(NewState, send_element(NewState,
#xmlel{name = <<"r">>, #xmlel{name = <<"r">>,
@ -2861,13 +2859,13 @@ mgmt_queue_add(StateData, El) ->
Num -> Num ->
Num + 1 Num + 1
end, end,
NewQueue = queue:in({NewNum, El}, StateData#state.mgmt_queue), NewQueue = queue:in({NewNum, now(), El}, StateData#state.mgmt_queue),
NewState = StateData#state{mgmt_queue = NewQueue, NewState = StateData#state{mgmt_queue = NewQueue,
mgmt_stanzas_out = NewNum}, mgmt_stanzas_out = NewNum},
check_queue_length(NewState). check_queue_length(NewState).
mgmt_queue_drop(StateData, NumHandled) -> mgmt_queue_drop(StateData, NumHandled) ->
NewQueue = jlib:queue_drop_while(fun({N, _Stanza}) -> N =< NumHandled end, NewQueue = jlib:queue_drop_while(fun({N, _T, _E}) -> N =< NumHandled end,
StateData#state.mgmt_queue), StateData#state.mgmt_queue),
StateData#state{mgmt_queue = NewQueue}. StateData#state{mgmt_queue = NewQueue}.
@ -2895,12 +2893,12 @@ handle_unacked_stanzas(StateData, F)
?INFO_MSG("~B stanzas were not acknowledged by ~s", ?INFO_MSG("~B stanzas were not acknowledged by ~s",
[N, jlib:jid_to_string(StateData#state.jid)]), [N, jlib:jid_to_string(StateData#state.jid)]),
lists:foreach( lists:foreach(
fun({_, #xmlel{attrs = Attrs} = El}) -> fun({_, Time, #xmlel{attrs = Attrs} = El}) ->
From_s = xml:get_attr_s(<<"from">>, Attrs), From_s = xml:get_attr_s(<<"from">>, Attrs),
From = jlib:string_to_jid(From_s), From = jlib:string_to_jid(From_s),
To_s = xml:get_attr_s(<<"to">>, Attrs), To_s = xml:get_attr_s(<<"to">>, Attrs),
To = jlib:string_to_jid(To_s), To = jlib:string_to_jid(To_s),
F(From, To, El) F(From, To, El, Time)
end, queue:to_list(Queue)) end, queue:to_list(Queue))
end; end;
handle_unacked_stanzas(_StateData, _F) -> handle_unacked_stanzas(_StateData, _F) ->
@ -2919,16 +2917,19 @@ handle_unacked_stanzas(StateData)
end, end,
ReRoute = case ResendOnTimeout of ReRoute = case ResendOnTimeout of
true -> true ->
fun ejabberd_router:route/3; fun(From, To, El, Time) ->
NewEl = add_resent_delay_info(StateData, El, Time),
ejabberd_router:route(From, To, NewEl)
end;
false -> false ->
fun(From, To, El) -> fun(From, To, El, _Time) ->
Err = Err =
jlib:make_error_reply(El, jlib:make_error_reply(El,
?ERR_SERVICE_UNAVAILABLE), ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err) ejabberd_router:route(To, From, Err)
end end
end, end,
F = fun(From, To, El) -> F = fun(From, To, El, Time) ->
%% We'll drop the stanza if it was <forwarded/> by some %% We'll drop the stanza if it was <forwarded/> by some
%% encapsulating protocol as per XEP-0297. One such protocol is %% encapsulating protocol as per XEP-0297. One such protocol is
%% XEP-0280, which says: "When a receiving server attempts to %% XEP-0280, which says: "When a receiving server attempts to
@ -2941,7 +2942,7 @@ handle_unacked_stanzas(StateData)
?DEBUG("Dropping forwarded stanza from ~s", ?DEBUG("Dropping forwarded stanza from ~s",
[xml:get_attr_s(<<"from">>, El#xmlel.attrs)]); [xml:get_attr_s(<<"from">>, El#xmlel.attrs)]);
false -> false ->
ReRoute(From, To, El) ReRoute(From, To, El, Time)
end end
end, end,
handle_unacked_stanzas(StateData, F); handle_unacked_stanzas(StateData, F);
@ -3032,6 +3033,9 @@ make_resume_id(StateData) ->
{Time, _} = StateData#state.sid, {Time, _} = StateData#state.sid,
jlib:term_to_base64({StateData#state.resource, Time}). jlib:term_to_base64({StateData#state.resource, Time}).
add_resent_delay_info(#state{server = From}, El, Time) ->
jlib:add_delay_info(El, From, Time, <<"Resent">>).
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% XEP-0352 %%% XEP-0352
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
@ -3054,37 +3058,36 @@ csi_filter_stanza(#state{csi_state = CsiState, jid = JID} = StateData,
StateData2#state{csi_state = CsiState} StateData2#state{csi_state = CsiState}
end. end.
csi_queue_add(#state{csi_queue = Queue, server = Host} = StateData, csi_queue_add(#state{csi_queue = Queue} = StateData, Stanza) ->
#xmlel{children = Els} = Stanza) ->
From = xml:get_tag_attr_s(<<"from">>, Stanza),
Time = calendar:now_to_universal_time(os:timestamp()),
DelayTag = [jlib:timestamp_to_xml(Time, utc,
jlib:make_jid(<<"">>, Host, <<"">>),
<<"Client Inactive">>)],
NewStanza = Stanza#xmlel{children = Els ++ DelayTag},
case length(StateData#state.csi_queue) >= csi_max_queue(StateData) of case length(StateData#state.csi_queue) >= csi_max_queue(StateData) of
true -> csi_queue_add(csi_queue_flush(StateData), NewStanza); true -> csi_queue_add(csi_queue_flush(StateData), Stanza);
false -> false ->
NewQueue = lists:keystore(From, 1, Queue, {From, NewStanza}), From = xml:get_tag_attr_s(<<"from">>, Stanza),
NewQueue = lists:keystore(From, 1, Queue, {From, now(), Stanza}),
StateData#state{csi_queue = NewQueue} StateData#state{csi_queue = NewQueue}
end. end.
csi_queue_send(#state{csi_queue = Queue, csi_state = CsiState} = StateData, csi_queue_send(#state{csi_queue = Queue, csi_state = CsiState, server = Host} =
From) -> StateData, From) ->
case lists:keytake(From, 1, Queue) of case lists:keytake(From, 1, Queue) of
{value, {From, Stanza}, NewQueue} -> {value, {From, Time, Stanza}, NewQueue} ->
NewStanza = jlib:add_delay_info(Stanza, Host, Time,
<<"Client Inactive">>),
NewStateData = send_stanza(StateData#state{csi_state = active}, NewStateData = send_stanza(StateData#state{csi_state = active},
Stanza), NewStanza),
NewStateData#state{csi_queue = NewQueue, csi_state = CsiState}; NewStateData#state{csi_queue = NewQueue, csi_state = CsiState};
false -> StateData false -> StateData
end. end.
csi_queue_flush(#state{csi_queue = Queue, csi_state = CsiState, jid = JID} = csi_queue_flush(#state{csi_queue = Queue, csi_state = CsiState, jid = JID,
StateData) -> server = Host} = StateData) ->
?DEBUG("Flushing CSI queue for ~s", [jlib:jid_to_string(JID)]), ?DEBUG("Flushing CSI queue for ~s", [jlib:jid_to_string(JID)]),
NewStateData = NewStateData =
lists:foldl(fun({_From, Stanza}, AccState) -> lists:foldl(fun({_From, Time, Stanza}, AccState) ->
send_stanza(AccState, Stanza) NewStanza =
jlib:add_delay_info(Stanza, Host, Time,
<<"Client Inactive">>),
send_stanza(AccState, NewStanza)
end, StateData#state{csi_state = active}, Queue), end, StateData#state{csi_state = active}, Queue),
NewStateData#state{csi_queue = [], csi_state = CsiState}. NewStateData#state{csi_queue = [], csi_state = CsiState}.

View File

@ -41,10 +41,11 @@
jid_remove_resource/1, jid_replace_resource/2, jid_remove_resource/1, jid_replace_resource/2,
get_iq_namespace/1, iq_query_info/1, get_iq_namespace/1, iq_query_info/1,
iq_query_or_response_info/1, is_iq_request_type/1, iq_query_or_response_info/1, is_iq_request_type/1,
iq_to_xml/1, parse_xdata_submit/1, timestamp_to_iso/1, iq_to_xml/1, parse_xdata_submit/1,
timestamp_to_iso/2, timestamp_to_xml/4, add_delay_info/3, add_delay_info/4,
timestamp_to_xml/1, now_to_utc_string/1, timestamp_to_iso/1, timestamp_to_iso/2,
now_to_local_string/1, datetime_string_to_timestamp/1, now_to_utc_string/1, now_to_local_string/1,
datetime_string_to_timestamp/1,
term_to_base64/1, base64_to_term/1, term_to_base64/1, base64_to_term/1,
decode_base64/1, encode_base64/1, ip_to_list/1, decode_base64/1, encode_base64/1, ip_to_list/1,
rsm_encode/1, rsm_encode/2, rsm_decode/1, rsm_encode/1, rsm_encode/2, rsm_decode/1,
@ -600,6 +601,77 @@ rsm_encode_count(Count, Arr) ->
children = [{xmlcdata, i2l(Count)}]} children = [{xmlcdata, i2l(Count)}]}
| Arr]. | Arr].
-spec add_delay_info(xmlel(), erlang:timestamp(), binary()) -> xmlel().
add_delay_info(El, From, Time) ->
add_delay_info(El, From, Time, <<"">>).
-spec add_delay_info(xmlel(), erlang:timestamp(), binary(),
binary()) -> xmlel().
add_delay_info(El, From, Time, Desc) ->
%% TODO: Remove support for <x/>, XEP-0091 is obsolete.
El1 = add_delay_info(El, From, Time, Desc, <<"delay">>, ?NS_DELAY),
El2 = add_delay_info(El1, From, Time, Desc, <<"x">>, ?NS_DELAY91),
El2.
-spec add_delay_info(xmlel(), erlang:timestamp(), binary(), binary(), binary(),
binary()) -> xmlel().
add_delay_info(El, From, Time, Desc, Name, XMLNS) ->
case xml:get_subtag_with_xmlns(El, Name, XMLNS) of
false ->
%% Add new tag
DelayTag = create_delay_tag(Time, From, Desc, XMLNS),
xml:append_subtags(El, [DelayTag]);
DelayTag ->
%% Update existing tag
NewDelayTag =
case {xml:get_tag_cdata(DelayTag), Desc} of
{<<"">>, <<"">>} ->
DelayTag;
{OldDesc, <<"">>} ->
DelayTag#xmlel{children = [{xmlcdata, OldDesc}]};
{<<"">>, NewDesc} ->
DelayTag#xmlel{children = [{xmlcdata, NewDesc}]};
{OldDesc, NewDesc} ->
case binary:match(OldDesc, NewDesc) of
nomatch ->
FinalDesc = <<OldDesc/binary, ", ", NewDesc/binary>>,
DelayTag#xmlel{children = [{xmlcdata, FinalDesc}]};
_ ->
DelayTag#xmlel{children = [{xmlcdata, OldDesc}]}
end
end,
NewEl = xml:remove_subtags(El, Name, {<<"xmlns">>, XMLNS}),
xml:append_subtags(NewEl, [NewDelayTag])
end.
-spec create_delay_tag(erlang:timestamp(), jid() | binary(), binary(),
binary()) -> xmlel() | error.
create_delay_tag(TimeStamp, FromJID, Desc, XMLNS) when is_tuple(FromJID) ->
From = jlib:jid_to_string(FromJID),
{Name, Stamp} = case XMLNS of
?NS_DELAY ->
{<<"delay">>, now_to_utc_string(TimeStamp, 3)};
?NS_DELAY91 ->
DateTime = calendar:now_to_universal_time(TimeStamp),
{<<"x">>, timestamp_to_iso(DateTime)}
end,
Children = case Desc of
<<"">> -> [];
_ -> [{xmlcdata, Desc}]
end,
#xmlel{name = Name,
attrs =
[{<<"xmlns">>, XMLNS}, {<<"from">>, From},
{<<"stamp">>, Stamp}],
children = Children};
create_delay_tag(DateTime, Host, Desc, XMLNS) when is_binary(Host) ->
FromJID = jlib:make_jid(<<"">>, Host, <<"">>),
create_delay_tag(DateTime, FromJID, Desc, XMLNS).
-type tz() :: {binary(), {integer(), integer()}} | {integer(), integer()} | utc. -type tz() :: {binary(), {integer(), integer()}} | {integer(), integer()} | utc.
%% Timezone = utc | {Sign::string(), {Hours, Minutes}} | {Hours, Minutes} %% Timezone = utc | {Sign::string(), {Hours, Minutes}} | {Hours, Minutes}
@ -611,18 +683,18 @@ timestamp_to_iso({{Year, Month, Day},
{Hour, Minute, Second}}, {Hour, Minute, Second}},
Timezone) -> Timezone) ->
Timestamp_string = Timestamp_string =
lists:flatten(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w", lists:flatten(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",
[Year, Month, Day, Hour, Minute, Second])), [Year, Month, Day, Hour, Minute, Second])),
Timezone_string = case Timezone of Timezone_string = case Timezone of
utc -> "Z"; utc -> "Z";
{Sign, {TZh, TZm}} -> {Sign, {TZh, TZm}} ->
io_lib:format("~s~2..0w:~2..0w", [Sign, TZh, TZm]); io_lib:format("~s~2..0B:~2..0B", [Sign, TZh, TZm]);
{TZh, TZm} -> {TZh, TZm} ->
Sign = case TZh >= 0 of Sign = case TZh >= 0 of
true -> "+"; true -> "+";
false -> "-" false -> "-"
end, end,
io_lib:format("~s~2..0w:~2..0w", io_lib:format("~s~2..0B:~2..0B",
[Sign, abs(TZh), TZm]) [Sign, abs(TZh), TZm])
end, end,
{iolist_to_binary(Timestamp_string), iolist_to_binary(Timezone_string)}. {iolist_to_binary(Timestamp_string), iolist_to_binary(Timezone_string)}.
@ -631,46 +703,25 @@ timestamp_to_iso({{Year, Month, Day},
timestamp_to_iso({{Year, Month, Day}, timestamp_to_iso({{Year, Month, Day},
{Hour, Minute, Second}}) -> {Hour, Minute, Second}}) ->
iolist_to_binary(io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w", iolist_to_binary(io_lib:format("~4..0B~2..0B~2..0BT~2..0B:~2..0B:~2..0B",
[Year, Month, Day, Hour, Minute, Second])). [Year, Month, Day, Hour, Minute, Second])).
-spec timestamp_to_xml(calendar:datetime(), tz(), jid(), binary()) -> xmlel().
timestamp_to_xml(DateTime, Timezone, FromJID, Desc) ->
{T_string, Tz_string} = timestamp_to_iso(DateTime,
Timezone),
Text = [{xmlcdata, Desc}],
From = jlib:jid_to_string(FromJID),
%% TODO: Remove this function once XEP-0091 is Obsolete
#xmlel{name = <<"delay">>,
attrs =
[{<<"xmlns">>, ?NS_DELAY}, {<<"from">>, From},
{<<"stamp">>, <<T_string/binary, Tz_string/binary>>}],
children = Text}.
-spec timestamp_to_xml(calendar:datetime()) -> xmlel().
timestamp_to_xml({{Year, Month, Day},
{Hour, Minute, Second}}) ->
#xmlel{name = <<"x">>,
attrs =
[{<<"xmlns">>, ?NS_DELAY91},
{<<"stamp">>,
iolist_to_binary(io_lib:format("~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w",
[Year, Month, Day, Hour, Minute,
Second]))}],
children = []}.
-spec now_to_utc_string(erlang:timestamp()) -> binary(). -spec now_to_utc_string(erlang:timestamp()) -> binary().
now_to_utc_string({MegaSecs, Secs, MicroSecs}) -> now_to_utc_string({MegaSecs, Secs, MicroSecs}) ->
now_to_utc_string({MegaSecs, Secs, MicroSecs}, 6).
-spec now_to_utc_string(erlang:timestamp(), 1..6) -> binary().
now_to_utc_string({MegaSecs, Secs, MicroSecs}, Precision) ->
{{Year, Month, Day}, {Hour, Minute, Second}} = {{Year, Month, Day}, {Hour, Minute, Second}} =
calendar:now_to_universal_time({MegaSecs, Secs, calendar:now_to_universal_time({MegaSecs, Secs,
MicroSecs}), MicroSecs}),
list_to_binary(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6." FracOfSec = round(MicroSecs / math:pow(10, 6 - Precision)),
".0wZ", list_to_binary(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B.~*."
".0BZ",
[Year, Month, Day, Hour, Minute, Second, [Year, Month, Day, Hour, Minute, Second,
MicroSecs])). Precision, FracOfSec])).
-spec now_to_local_string(erlang:timestamp()) -> binary(). -spec now_to_local_string(erlang:timestamp()) -> binary().
@ -688,8 +739,8 @@ now_to_local_string({MegaSecs, Secs, MicroSecs}) ->
end, end,
{{Year, Month, Day}, {Hour, Minute, Second}} = {{Year, Month, Day}, {Hour, Minute, Second}} =
LocalTime, LocalTime,
list_to_binary(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6." list_to_binary(io_lib:format("~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B.~6."
".0w~s~2..0w:~2..0w", ".0B~s~2..0B:~2..0B",
[Year, Month, Day, Hour, Minute, Second, [Year, Month, Day, Hour, Minute, Second,
MicroSecs, Sign, H, M])). MicroSecs, Sign, H, M])).

View File

@ -2438,24 +2438,21 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) ->
false -> false; false -> false;
_ -> true _ -> true
end, end,
TimeStamp = calendar:now_to_universal_time(now()), TimeStamp = now(),
SenderJid = case SenderJid = case
(StateData#state.config)#config.anonymous (StateData#state.config)#config.anonymous
of of
true -> StateData#state.jid; true -> StateData#state.jid;
false -> FromJID false -> FromJID
end, end,
TSPacket = xml:append_subtags(Packet, TSPacket = jlib:add_delay_info(Packet, SenderJid, TimeStamp),
[jlib:timestamp_to_xml(TimeStamp, utc,
SenderJid, <<"">>),
jlib:timestamp_to_xml(TimeStamp)]),
SPacket = SPacket =
jlib:replace_from_to(jlib:jid_replace_resource(StateData#state.jid, jlib:replace_from_to(jlib:jid_replace_resource(StateData#state.jid,
FromNick), FromNick),
StateData#state.jid, TSPacket), StateData#state.jid, TSPacket),
Size = element_size(SPacket), Size = element_size(SPacket),
Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, Q1 = lqueue_in({FromNick, TSPacket, HaveSubject,
TimeStamp, Size}, calendar:now_to_universal_time(TimeStamp), Size},
StateData#state.history), StateData#state.history),
add_to_log(text, {FromNick, Packet}, StateData), add_to_log(text, {FromNick, Packet}, StateData),
StateData#state{history = Q1}. StateData#state{history = Q1}.

View File

@ -215,26 +215,15 @@ store_offline_msg(Host, {User, _Server}, Msgs, Len, MaxOfflineMsgs, odbc) ->
ejabberd_odbc:escape((M#offline_msg.to)#jid.luser), ejabberd_odbc:escape((M#offline_msg.to)#jid.luser),
From = M#offline_msg.from, From = M#offline_msg.from,
To = M#offline_msg.to, To = M#offline_msg.to,
#xmlel{name = Name, attrs = Attrs, Packet =
children = Els} = jlib:replace_from_to(From, To,
M#offline_msg.packet, M#offline_msg.packet),
Attrs2 = NewPacket =
jlib:replace_from_to_attrs(jlib:jid_to_string(From), jlib:add_delay_info(Packet, Host,
jlib:jid_to_string(To), M#offline_msg.timestamp,
Attrs), <<"Offline Storage">>),
Packet = #xmlel{name = Name,
attrs = Attrs2,
children =
Els ++
[jlib:timestamp_to_xml(calendar:now_to_universal_time(M#offline_msg.timestamp),
utc,
jlib:make_jid(<<"">>,
Host,
<<"">>),
<<"Offline Storage">>),
jlib:timestamp_to_xml(calendar:now_to_universal_time(M#offline_msg.timestamp))]},
XML = XML =
ejabberd_odbc:escape(xml:element_to_binary(Packet)), ejabberd_odbc:escape(xml:element_to_binary(NewPacket)),
odbc_queries:add_spool_sql(Username, XML) odbc_queries:add_spool_sql(Username, XML)
end, end,
Msgs), Msgs),
@ -432,15 +421,12 @@ resend_offline_messages(User, Server) ->
case mnesia:transaction(F) of case mnesia:transaction(F) of
{atomic, Rs} -> {atomic, Rs} ->
lists:foreach(fun (R) -> lists:foreach(fun (R) ->
#xmlel{name = Name, attrs = Attrs,
children = Els} =
R#offline_msg.packet,
ejabberd_sm ! ejabberd_sm !
{route, R#offline_msg.from, R#offline_msg.to, {route, R#offline_msg.from, R#offline_msg.to,
#xmlel{name = Name, attrs = Attrs, jlib:add_delay_info(R#offline_msg.packet,
children = LServer,
Els ++ R#offline_msg.timestamp,
[jlib:timestamp_to_xml(calendar:now_to_universal_time(R#offline_msg.timestamp))]}} <<"Offline Storage">>)}
end, end,
lists:keysort(#offline_msg.timestamp, Rs)); lists:keysort(#offline_msg.timestamp, Rs));
_ -> ok _ -> ok
@ -686,19 +672,9 @@ get_offline_els(LUser, LServer, odbc) ->
end. end.
offline_msg_to_route(LServer, #offline_msg{} = R) -> offline_msg_to_route(LServer, #offline_msg{} = R) ->
El = #xmlel{children = Els} = R#offline_msg.packet,
{route, R#offline_msg.from, R#offline_msg.to, {route, R#offline_msg.from, R#offline_msg.to,
El#xmlel{children = jlib:add_delay_info(R#offline_msg.packet, LServer, R#offline_msg.timestamp,
Els ++ <<"Offline Storage">>)};
[jlib:timestamp_to_xml(
calendar:now_to_universal_time(
R#offline_msg.timestamp),
utc,
jlib:make_jid(<<"">>, LServer, <<"">>),
<<"Offline Storage">>),
jlib:timestamp_to_xml(
calendar:now_to_universal_time(
R#offline_msg.timestamp))]}};
offline_msg_to_route(_LServer, #xmlel{} = El) -> offline_msg_to_route(_LServer, #xmlel{} = El) ->
To = jlib:string_to_jid(xml:get_tag_attr_s(<<"to">>, El)), To = jlib:string_to_jid(xml:get_tag_attr_s(<<"to">>, El)),
From = jlib:string_to_jid(xml:get_tag_attr_s(<<"from">>, El)), From = jlib:string_to_jid(xml:get_tag_attr_s(<<"from">>, El)),
@ -1109,26 +1085,14 @@ export(_Server) ->
packet = Packet}) packet = Packet})
when LServer == Host -> when LServer == Host ->
Username = ejabberd_odbc:escape(LUser), Username = ejabberd_odbc:escape(LUser),
#xmlel{name = Name, attrs = Attrs, children = Els} = Packet1 =
Packet, jlib:replace_from_to(jlib:jid_to_string(From),
Attrs2 = jlib:jid_to_string(To), Packet),
jlib:replace_from_to_attrs(jlib:jid_to_string(From), Packet2 =
jlib:jid_to_string(To), jlib:add_delay_info(Packet1, LServer, TimeStamp,
Attrs), <<"Offline Storage">>),
NewPacket = #xmlel{name = Name, attrs = Attrs2,
children =
Els ++
[jlib:timestamp_to_xml(
calendar:now_to_universal_time(TimeStamp),
utc,
jlib:make_jid(<<"">>,
LServer,
<<"">>),
<<"Offline Storage">>),
jlib:timestamp_to_xml(
calendar:now_to_universal_time(TimeStamp))]},
XML = XML =
ejabberd_odbc:escape(xml:element_to_binary(NewPacket)), ejabberd_odbc:escape(xml:element_to_binary(Packet2)),
[[<<"delete from spool where username='">>, Username, <<"';">>], [[<<"delete from spool where username='">>, Username, <<"';">>],
[<<"insert into spool(username, xml) values ('">>, [<<"insert into spool(username, xml) values ('">>,
Username, <<"', '">>, XML, <<"');">>]]; Username, <<"', '">>, XML, <<"');">>]];

View File

@ -4275,21 +4275,15 @@ payload_xmlelements([_ | Tail], Count) ->
%% @spec (Els) -> stanza() %% @spec (Els) -> stanza()
%% Els = [xmlelement()] %% Els = [xmlelement()]
%% @doc <p>Build pubsub event stanza</p> %% @doc <p>Build pubsub event stanza</p>
event_stanza(Els) -> event_stanza_withmoreels(Els, []). event_stanza(Els) ->
event_stanza_with_delay(Els, ModifNow, ModifUSR) ->
DateTime = calendar:now_to_datetime(ModifNow),
MoreEls = [jlib:timestamp_to_xml(DateTime, utc,
ModifUSR, <<"">>)],
event_stanza_withmoreels(Els, MoreEls).
event_stanza_withmoreels(Els, MoreEls) ->
#xmlel{name = <<"message">>, attrs = [], #xmlel{name = <<"message">>, attrs = [],
children = children =
[#xmlel{name = <<"event">>, [#xmlel{name = <<"event">>,
attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}], attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}],
children = Els} children = Els}]}.
| MoreEls]}.
event_stanza_with_delay(Els, ModifNow, ModifUSR) ->
jlib:add_delay_info(event_stanza(Els), ModifUSR, ModifNow).
%%%%%% broadcast functions %%%%%% broadcast functions

View File

@ -3925,21 +3925,15 @@ payload_xmlelements([_ | Tail], Count) ->
%% @spec (Els) -> stanza() %% @spec (Els) -> stanza()
%% Els = [xmlelement()] %% Els = [xmlelement()]
%% @doc <p>Build pubsub event stanza</p> %% @doc <p>Build pubsub event stanza</p>
event_stanza(Els) -> event_stanza_withmoreels(Els, []). event_stanza(Els) ->
event_stanza_with_delay(Els, ModifNow, ModifUSR) ->
DateTime = calendar:now_to_datetime(ModifNow),
MoreEls = [jlib:timestamp_to_xml(DateTime, utc,
ModifUSR, <<"">>)],
event_stanza_withmoreels(Els, MoreEls).
event_stanza_withmoreels(Els, MoreEls) ->
#xmlel{name = <<"message">>, attrs = [], #xmlel{name = <<"message">>, attrs = [],
children = children =
[#xmlel{name = <<"event">>, [#xmlel{name = <<"event">>,
attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}], attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}],
children = Els} children = Els}]}.
| MoreEls]}.
event_stanza_with_delay(Els, ModifNow, ModifUSR) ->
jlib:add_delay_info(event_stanza(Els), ModifUSR, ModifNow).
%%%%%% broadcast functions %%%%%% broadcast functions

View File

@ -801,7 +801,7 @@ pubsub(Config) ->
node = Node, node = Node,
jid = my_jid(Config)}}]}), jid = my_jid(Config)}}]}),
?recv2( ?recv2(
#message{sub_els = [#pubsub_event{}, #delay{}]}, #message{sub_els = [#pubsub_event{}, #delay{}, #legacy_delay{}]},
#iq{type = result, id = I1}), #iq{type = result, id = I1}),
%% Get subscriptions %% Get subscriptions
true = lists:member(?PUBSUB("retrieve-subscriptions"), Features), true = lists:member(?PUBSUB("retrieve-subscriptions"), Features),
@ -1588,7 +1588,8 @@ client_state_slave(Config) ->
body = [#text{data = <<"body">>}]} = recv(), body = [#text{data = <<"body">>}]} = recv(),
wait_for_master(Config), wait_for_master(Config),
send(Config, #csi{type = active}), send(Config, #csi{type = active}),
?recv2(#presence{from = Peer, type = unavailable, sub_els = [#delay{}]}, ?recv2(#presence{from = Peer, type = unavailable,
sub_els = [#delay{}, #legacy_delay{}]},
#message{from = Peer, thread = <<"1">>, #message{from = Peer, thread = <<"1">>,
sub_els = [#chatstate{type = active}]}), sub_els = [#chatstate{type = active}]}),
disconnect(Config). disconnect(Config).