summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/web/ejabberd_http_bind.erl177
1 files changed, 95 insertions, 82 deletions
diff --git a/src/web/ejabberd_http_bind.erl b/src/web/ejabberd_http_bind.erl
index ef3046fe..6f15703e 100644
--- a/src/web/ejabberd_http_bind.erl
+++ b/src/web/ejabberd_http_bind.erl
@@ -102,7 +102,7 @@
-define(MIN_POLLING, 2000000). % don't poll faster than that or we will
% shoot you (time in microsec)
-define(MAX_WAIT, 3600). % max num of secs to keep a request on hold
--define(MAX_INACTIVITY, 120000). % msecs to wait before terminating
+-define(MAX_INACTIVITY, 30000). % msecs to wait before terminating
% idle sessions
-define(MAX_PAUSE, 120). % may num of sec a client is allowed to pause
% the session
@@ -781,7 +781,7 @@ handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP) ->
{buffered, _Sess} ->
{200, ?HEADER, "<body xmlns='"++?NS_HTTP_BIND++"'/>"};
{ok, Sess} ->
- prepare_response(Sess, Rid, Attrs, StreamStart)
+ prepare_response(Sess, Rid, [], StreamStart)
end.
http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP) ->
@@ -883,9 +883,7 @@ update_shaper(ShaperState, PayloadSize) ->
{NewShaperState, undefined}
end.
-prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess,
- Rid, _, StreamStart) ->
- receive after 100 -> ok end, %% TODO: Why is this needed. Argh. Bad programming practice.
+prepare_response(Sess, Rid, OutputEls, StreamStart) ->
case catch http_get(Sess, Rid) of
{ok, cancel} ->
%% actually it would be better if we could completely
@@ -898,89 +896,104 @@ prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess,
{200, ?HEADER, "<body type='terminate' xmlns='"++?NS_HTTP_BIND++"'/>"};
{ok, ROutPacket} ->
OutPacket = lists:reverse(ROutPacket),
- ?DEBUG("OutPacket: ~p", [OutPacket]),
- case StreamStart of
- false ->
- case catch send_outpacket(Sess, OutPacket) of
- {'EXIT', _Reason} ->
- {200, ?HEADER,
- "<body type='terminate' xmlns='"++
- ?NS_HTTP_BIND++"'/>"};
- SendRes ->
- SendRes
- end;
- true ->
- case OutPacket of
- [{xmlstreamstart, _, OutAttrs} | Els] ->
- AuthID = xml:get_attr_s("id", OutAttrs),
- From = xml:get_attr_s("from", OutAttrs),
- Version = xml:get_attr_s("version", OutAttrs),
- OutEls =
- case Els of
- [] ->
- [];
- [{xmlstreamelement,
- {xmlelement, "stream:features",
- StreamAttribs, StreamEls}}
- | StreamTail] ->
- TypedTail =
- [check_default_xmlns(OEl) ||
- {xmlstreamelement, OEl} <-
- StreamTail],
- [{xmlelement, "stream:features",
- [{"xmlns:stream",
- ?NS_STREAM}] ++
- StreamAttribs, StreamEls}] ++
- TypedTail;
- StreamTail ->
- [check_default_xmlns(OEl) ||
- {xmlstreamelement, OEl} <-
- StreamTail]
- end,
- BOSH_attribs =
- [{"authid", AuthID},
- {"xmlns:xmpp", ?NS_BOSH},
- {"xmlns:stream", ?NS_STREAM}] ++
- case OutEls of
- [] ->
- [];
- _ ->
- [{"xmpp:version", Version}]
- end,
- MaxInactivity = get_max_inactivity(To, ?MAX_INACTIVITY),
- MaxPause = get_max_pause(To),
- {200, ?HEADER,
- xml:element_to_string(
- {xmlelement,"body",
- [{"xmlns",
- ?NS_HTTP_BIND},
- {"sid", Sid},
- {"wait", integer_to_list(Wait)},
- {"requests", integer_to_list(Hold+1)},
- {"inactivity",
- integer_to_list(
- trunc(MaxInactivity/1000))},
- {"maxpause",
- integer_to_list(MaxPause)},
- {"polling",
- integer_to_list(
- trunc(?MIN_POLLING/1000000))},
- {"ver", ?BOSH_VERSION},
- {"from", From},
- {"secure", "true"} %% we're always being secure
- ] ++ BOSH_attribs,OutEls})};
- {error, _} ->
- {200, ?HEADER, "<body type='terminate' "
- "condition='host-unknown' "
- "xmlns='"++?NS_HTTP_BIND++"'/>"}
- end
- end;
+ ?DEBUG("OutPacket: ~p", [OutputEls++OutPacket]),
+ prepare_outpacket_response(Sess, Rid, OutputEls++OutPacket, StreamStart);
{'EXIT', {shutdown, _}} ->
{200, ?HEADER, "<body type='terminate' condition='system-shutdown' xmlns='"++?NS_HTTP_BIND++"'/>"};
{'EXIT', _Reason} ->
{200, ?HEADER, "<body type='terminate' xmlns='"++?NS_HTTP_BIND++"'/>"}
end.
+%% Send output payloads on establised sessions
+prepare_outpacket_response(Sess, _Rid, OutPacket, false) ->
+ case catch send_outpacket(Sess, OutPacket) of
+ {'EXIT', _Reason} ->
+ {200, ?HEADER,
+ "<body type='terminate' xmlns='"++
+ ?NS_HTTP_BIND++"'/>"};
+ SendRes ->
+ SendRes
+ end;
+%% Handle a new session along with its output payload
+prepare_outpacket_response(#http_bind{id=Sid, wait=Wait,
+ hold=Hold, to=To}=Sess,
+ Rid, OutPacket, true) ->
+ case OutPacket of
+ [{xmlstreamstart, _, OutAttrs} | Els] ->
+ AuthID = xml:get_attr_s("id", OutAttrs),
+ From = xml:get_attr_s("from", OutAttrs),
+ Version = xml:get_attr_s("version", OutAttrs),
+ OutEls =
+ case Els of
+ [] ->
+ [];
+ [{xmlstreamelement,
+ {xmlelement, "stream:features",
+ StreamAttribs, StreamEls}}
+ | StreamTail] ->
+ TypedTail =
+ [check_default_xmlns(OEl) ||
+ {xmlstreamelement, OEl} <-
+ StreamTail],
+ [{xmlelement, "stream:features",
+ [{"xmlns:stream",
+ ?NS_STREAM}] ++
+ StreamAttribs, StreamEls}] ++
+ TypedTail;
+ StreamTail ->
+ [check_default_xmlns(OEl) ||
+ {xmlstreamelement, OEl} <-
+ StreamTail]
+ end,
+ case OutEls of
+ [] ->
+ prepare_response(Sess, Rid, OutPacket, true);
+ [{xmlelement,
+ "stream:error",_,_}] ->
+ {200, ?HEADER, "<body type='terminate' "
+ "condition='host-unknown' "
+ "xmlns='"++?NS_HTTP_BIND++"'/>"};
+ _ ->
+ BOSH_attribs =
+ [{"authid", AuthID},
+ {"xmlns:xmpp", ?NS_BOSH},
+ {"xmlns:stream", ?NS_STREAM}] ++
+ case OutEls of
+ [] ->
+ [];
+ _ ->
+ [{"xmpp:version", Version}]
+ end,
+ MaxInactivity = get_max_inactivity(To, ?MAX_INACTIVITY),
+ MaxPause = get_max_pause(To),
+ {200, ?HEADER,
+ xml:element_to_string(
+ {xmlelement,"body",
+ [{"xmlns",
+ ?NS_HTTP_BIND},
+ {"sid", Sid},
+ {"wait", integer_to_list(Wait)},
+ {"requests", integer_to_list(Hold+1)},
+ {"inactivity",
+ integer_to_list(
+ trunc(MaxInactivity/1000))},
+ {"maxpause",
+ integer_to_list(MaxPause)},
+ {"polling",
+ integer_to_list(
+ trunc(?MIN_POLLING/1000000))},
+ {"ver", ?BOSH_VERSION},
+ {"from", From},
+ {"secure", "true"} %% we're always being secure
+ ] ++ BOSH_attribs,OutEls})}
+ end;
+ _ ->
+ {200, ?HEADER, "<body type='terminate' "
+ "condition='internal-server-error' "
+ "xmlns='"++?NS_HTTP_BIND++"'/>"}
+ end.
+
+
http_get(#http_bind{pid = FsmRef, wait = Wait, hold = Hold}, Rid) ->
gen_fsm:sync_send_all_state_event(
FsmRef, {http_get, Rid, Wait, Hold}, 2 * ?MAX_WAIT * 1000).