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; |
