diff options
Diffstat (limited to 'src/web/ejabberd_http_bind.erl')
-rw-r--r-- | src/web/ejabberd_http_bind.erl | 177 |
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). |