comparison mod_websocket/mod_websocket.lua @ 692:2de21fa40382

mod_websocket: Make sending a self-closing <stream:stream> tag configurable Due to limitations in browser's XML parsers most (all?) existing client implementations require the <stream:stream/> tag to be self-closing. This commit makes this behaviour configurable, to enable "proper" implementations.
author Florian Zeitz <florob@babelmonkeys.de>
date Mon, 28 May 2012 00:52:47 +0200
parents 04662cc35280
children 7d165cd6168c
comparison
equal deleted inserted replaced
691:04662cc35280 692:2de21fa40382
29 29
30 local log = module._log; 30 local log = module._log;
31 31
32 local c2s_timeout = module:get_option_number("c2s_timeout"); 32 local c2s_timeout = module:get_option_number("c2s_timeout");
33 local opt_keepalives = module:get_option_boolean("tcp_keepalives", false); 33 local opt_keepalives = module:get_option_boolean("tcp_keepalives", false);
34 local self_closing_stream = module:get_option_boolean("websocket_self_closing_stream", true);
34 35
35 local sessions = module:shared("sessions"); 36 local sessions = module:shared("sessions");
36 37
37 local stream_callbacks = { default_ns = "jabber:client", handlestanza = core_process_stanza }; 38 local stream_callbacks = { default_ns = "jabber:client", handlestanza = core_process_stanza };
38 local listener = {}; 39 local listener = {};
132 session:close{ condition = "host-unknown", text = "This server does not serve "..tostring(session.host)}; 133 session:close{ condition = "host-unknown", text = "This server does not serve "..tostring(session.host)};
133 return; 134 return;
134 end 135 end
135 136
136 -- COMPAT: Current client implementations need this to be self-closing 137 -- COMPAT: Current client implementations need this to be self-closing
137 send("<?xml version='1.0'?>"..(tostring(st.stanza("stream:stream", { 138 if self_closing_stream then
138 xmlns = 'jabber:client', ["xmlns:stream"] = 'http://etherx.jabber.org/streams'; 139 send("<?xml version='1.0'?>"..tostring(st.stanza("stream:stream", {
139 id = session.streamid, from = session.host, version = '1.0', ["xml:lang"] = 'en' }):top_tag()):gsub(">", "/>"))); 140 xmlns = 'jabber:client', ["xmlns:stream"] = 'http://etherx.jabber.org/streams';
141 id = session.streamid, from = session.host, version = '1.0', ["xml:lang"] = 'en' })));
142 else
143 send("<?xml version='1.0'?>"..st.stanza("stream:stream", {
144 xmlns = 'jabber:client', ["xmlns:stream"] = 'http://etherx.jabber.org/streams';
145 id = session.streamid, from = session.host, version = '1.0', ["xml:lang"] = 'en' }):top_tag());
146 end
140 147
141 (session.log or log)("debug", "Sent reply <stream:stream> to client"); 148 (session.log or log)("debug", "Sent reply <stream:stream> to client");
142 session.notopen = nil; 149 session.notopen = nil;
143 150
144 -- If session.secure is *false* (not nil) then it means we /were/ encrypting 151 -- If session.secure is *false* (not nil) then it means we /were/ encrypting
197 --- Session methods 204 --- Session methods
198 local function session_close(session, reason) 205 local function session_close(session, reason)
199 local log = session.log or log; 206 local log = session.log or log;
200 if session.conn then 207 if session.conn then
201 if session.notopen then 208 if session.notopen then
202 session.send("<?xml version='1.0'?>"); 209 -- COMPAT: Current client implementations need this to be self-closing
203 session.send(st.stanza("stream:stream", default_stream_attr):top_tag()); 210 if self_closing_stream then
211 session.send("<?xml version='1.0'?>"..tostring(st.stanza("stream:stream", default_stream_attr)));
212 else
213 session.send("<?xml version='1.0'?>"..st.stanza("stream:stream", default_stream_attr):top_tag());
214 end
204 end 215 end
205 if reason then 216 if reason then
206 if type(reason) == "string" then -- assume stream error 217 if type(reason) == "string" then -- assume stream error
207 log("info", "Disconnecting client, <stream:error> is: %s", reason); 218 log("info", "Disconnecting client, <stream:error> is: %s", reason);
208 session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' })); 219 session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }));
276 if frame.FIN then 287 if frame.FIN then
277 data = buffer; 288 data = buffer;
278 buffer = ""; 289 buffer = "";
279 290
280 -- COMPAT: Current client implementations send a self-closing <stream:stream> 291 -- COMPAT: Current client implementations send a self-closing <stream:stream>
281 data = data:gsub("/>$", ">"); 292 if self_closing_stream then
293 data = data:gsub("/>$", ">");
294 end
282 295
283 data = filter("bytes/in", data); 296 data = filter("bytes/in", data);
284 if data then 297 if data then
285 local ok, err = stream:feed(data); 298 local ok, err = stream:feed(data);
286 if ok then return; end 299 if ok then return; end