Mercurial > prosody-modules
comparison mod_websocket/mod_websocket.lua @ 839:d297d76010d4
mod_websocket: Merge with current mod_c2s
author | Florian Zeitz <florob@babelmonkeys.de> |
---|---|
date | Thu, 04 Oct 2012 16:37:33 +0200 |
parents | 02fcb102b9aa |
children | f568661c9d39 |
comparison
equal
deleted
inserted
replaced
838:c9e2beec4ef6 | 839:d297d76010d4 |
---|---|
27 local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams"; | 27 local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams"; |
28 | 28 |
29 local log = module._log; | 29 local log = module._log; |
30 | 30 |
31 local c2s_timeout = module:get_option_number("c2s_timeout"); | 31 local c2s_timeout = module:get_option_number("c2s_timeout"); |
32 local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); | |
32 local opt_keepalives = module:get_option_boolean("tcp_keepalives", false); | 33 local opt_keepalives = module:get_option_boolean("tcp_keepalives", false); |
33 local self_closing_stream = module:get_option_boolean("websocket_self_closing_stream", true); | 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"); |
37 local core_process_stanza = prosody.core_process_stanza; | |
36 | 38 |
37 local stream_callbacks = { default_ns = "jabber:client", handlestanza = core_process_stanza }; | 39 local stream_callbacks = { default_ns = "jabber:client", handlestanza = core_process_stanza }; |
38 local listener = {}; | 40 local listener = {}; |
39 | 41 |
40 -- Websocket helpers | 42 -- Websocket helpers |
160 send(features); | 162 send(features); |
161 end | 163 end |
162 | 164 |
163 function stream_callbacks.streamclosed(session) | 165 function stream_callbacks.streamclosed(session) |
164 session.log("debug", "Received </stream:stream>"); | 166 session.log("debug", "Received </stream:stream>"); |
165 session:close(); | 167 session:close(false); |
166 end | 168 end |
167 | 169 |
168 function stream_callbacks.error(session, error, data) | 170 function stream_callbacks.error(session, error, data) |
169 if error == "no-stream" then | 171 if error == "no-stream" then |
170 session.log("debug", "Invalid opening stream header"); | 172 session.log("debug", "Invalid opening stream header"); |
210 session.send("<?xml version='1.0'?>"..tostring(st.stanza("stream:stream", default_stream_attr))); | 212 session.send("<?xml version='1.0'?>"..tostring(st.stanza("stream:stream", default_stream_attr))); |
211 else | 213 else |
212 session.send("<?xml version='1.0'?>"..st.stanza("stream:stream", default_stream_attr):top_tag()); | 214 session.send("<?xml version='1.0'?>"..st.stanza("stream:stream", default_stream_attr):top_tag()); |
213 end | 215 end |
214 end | 216 end |
215 if reason then | 217 if reason then -- nil == no err, initiated by us, false == initiated by client |
216 if type(reason) == "string" then -- assume stream error | 218 if type(reason) == "string" then -- assume stream error |
217 log("info", "Disconnecting client, <stream:error> is: %s", reason); | 219 log("debug", "Disconnecting client, <stream:error> is: %s", reason); |
218 session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' })); | 220 session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' })); |
219 elseif type(reason) == "table" then | 221 elseif type(reason) == "table" then |
220 if reason.condition then | 222 if reason.condition then |
221 local stanza = st.stanza("stream:error"):tag(reason.condition, stream_xmlns_attr):up(); | 223 local stanza = st.stanza("stream:error"):tag(reason.condition, stream_xmlns_attr):up(); |
222 if reason.text then | 224 if reason.text then |
223 stanza:tag("text", stream_xmlns_attr):text(reason.text):up(); | 225 stanza:tag("text", stream_xmlns_attr):text(reason.text):up(); |
224 end | 226 end |
225 if reason.extra then | 227 if reason.extra then |
226 stanza:add_child(reason.extra); | 228 stanza:add_child(reason.extra); |
227 end | 229 end |
228 log("info", "Disconnecting client, <stream:error> is: %s", tostring(stanza)); | 230 log("debug", "Disconnecting client, <stream:error> is: %s", tostring(stanza)); |
229 session.send(stanza); | 231 session.send(stanza); |
230 elseif reason.name then -- a stanza | 232 elseif reason.name then -- a stanza |
231 log("info", "Disconnecting client, <stream:error> is: %s", tostring(reason)); | 233 log("debug", "Disconnecting client, <stream:error> is: %s", tostring(reason)); |
232 session.send(reason); | 234 session.send(reason); |
233 end | 235 end |
234 end | 236 end |
235 end | 237 end |
236 session.send("</stream:stream>"); | 238 session.send("</stream:stream>"); |
237 session.conn:close(); | 239 function session.send() return false; end |
238 listener.ondisconnect(session.conn, (reason and (reason.text or reason.condition)) or reason or "session closed"); | 240 |
239 end | 241 local reason = (reason and (reason.text or reason.condition)) or reason; |
240 end | 242 session.log("info", "c2s stream for %s closed: %s", session.full_jid or ("<"..session.ip..">"), reason or "session closed"); |
243 | |
244 -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote | |
245 local conn = session.conn; | |
246 if reason == nil and not session.notopen and session.type == "c2s" then | |
247 -- Grace time to process data from authenticated cleanly-closed stream | |
248 add_task(stream_close_timeout, function () | |
249 if not session.destroyed then | |
250 session.log("warn", "Failed to receive a stream close response, closing connection anyway..."); | |
251 sm_destroy_session(session, reason); | |
252 conn:close(); | |
253 end | |
254 end); | |
255 else | |
256 sm_destroy_session(session, reason); | |
257 conn:close(); | |
258 end | |
259 end | |
260 end | |
261 | |
262 module:hook_global("user-deleted", function(event) | |
263 local username, host = event.username, event.host; | |
264 local user = hosts[host].sessions[username]; | |
265 if user and user.sessions then | |
266 for jid, session in pairs(user.sessions) do | |
267 session:close{ condition = "not-authorized", text = "Account deleted" }; | |
268 end | |
269 end | |
270 end, 200); | |
241 | 271 |
242 --- Port listener | 272 --- Port listener |
243 function listener.onconnect(conn) | 273 function listener.onconnect(conn) |
244 local session = sm_new_session(conn); | 274 local session = sm_new_session(conn); |
245 sessions[conn] = session; | 275 sessions[conn] = session; |
329 end | 359 end |
330 | 360 |
331 function listener.ondisconnect(conn, err) | 361 function listener.ondisconnect(conn, err) |
332 local session = sessions[conn]; | 362 local session = sessions[conn]; |
333 if session then | 363 if session then |
334 (session.log or log)("info", "Client disconnected: %s", err); | 364 (session.log or log)("info", "Client disconnected: %s", err or "connection closed"); |
335 sm_destroy_session(session, err); | 365 sm_destroy_session(session, err); |
336 sessions[conn] = nil; | 366 sessions[conn] = nil; |
337 session = nil; | |
338 end | 367 end |
339 end | 368 end |
340 | 369 |
341 function listener.associate_session(conn, session) | 370 function listener.associate_session(conn, session) |
342 sessions[conn] = session; | 371 sessions[conn] = session; |