mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Merge pull request #377 from weiss/new-timestamps
Add timestamps to stanzas resent from stream management queue
This commit is contained in:
commit
df88d9f2e5
@ -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}.
|
||||||
|
|
||||||
|
131
src/jlib.erl
131
src/jlib.erl
@ -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])).
|
||||||
|
|
||||||
|
@ -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}.
|
||||||
|
@ -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, <<"');">>]];
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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).
|
||||||
|
Loading…
Reference in New Issue
Block a user