Comparison

plugins/mod_c2s.lua @ 4964:c9b8ec3eb1e9

mod_c2s: Don't call ondisconnect manually on close, it is now called by net.server. Replace with inline code for destroying the session, and also waiting for a reply </stream:stream> if there is a chance of further data sent by the client. session.send() on a half-closed stream returns false (and does not deliver the data).
author Matthew Wild <mwild1@gmail.com>
date Sun, 22 Jul 2012 16:59:12 +0100
parent 4852:9cc934f49df0
child 4986:9da430b69f13
comparison
equal deleted inserted replaced
4963:54e2c83af127 4964:c9b8ec3eb1e9
22 local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams"; 22 local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams";
23 23
24 local log = module._log; 24 local log = module._log;
25 25
26 local c2s_timeout = module:get_option_number("c2s_timeout"); 26 local c2s_timeout = module:get_option_number("c2s_timeout");
27 local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5);
27 local opt_keepalives = module:get_option_boolean("tcp_keepalives", false); 28 local opt_keepalives = module:get_option_boolean("tcp_keepalives", false);
28 29
29 local sessions = module:shared("sessions"); 30 local sessions = module:shared("sessions");
30 31
31 local stream_callbacks = { default_ns = "jabber:client", handlestanza = core_process_stanza }; 32 local stream_callbacks = { default_ns = "jabber:client", handlestanza = core_process_stanza };
141 session.send(reason); 142 session.send(reason);
142 end 143 end
143 end 144 end
144 end 145 end
145 session.send("</stream:stream>"); 146 session.send("</stream:stream>");
146 session.conn:close(); 147
147 listener.ondisconnect(session.conn, (reason and (reason.text or reason.condition)) or reason or "session closed"); 148 function session.send() return false; end
149
150 local reason = (reason and (reason.text or reason.condition)) or reason or "session closed";
151 session.log("info", "c2s stream for %s closed: %s", session.full_jid or ("<"..session.ip..">"), reason);
152
153 -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote
154 local conn = session.conn;
155 if reason == "session closed" and not session.notopen and session.type == "c2s" then
156 -- Grace time to process data from authenticated cleanly-closed stream
157 add_task(stream_close_timeout, function ()
158 if not session.destroyed then
159 session.log("warn", "Failed to receive a stream close response, closing connection anyway...");
160 sm_destroy_session(session, reason);
161 conn:close();
162 end
163 end);
164 else
165 sm_destroy_session(session, reason);
166 conn:close();
167 end
148 end 168 end
149 end 169 end
150 170
151 --- Port listener 171 --- Port listener
152 function listener.onconnect(conn) 172 function listener.onconnect(conn)
206 end 226 end
207 227
208 function listener.ondisconnect(conn, err) 228 function listener.ondisconnect(conn, err)
209 local session = sessions[conn]; 229 local session = sessions[conn];
210 if session then 230 if session then
211 (session.log or log)("info", "Client disconnected: %s", err); 231 (session.log or log)("info", "Client disconnected: %s", err or "connection closed");
212 sm_destroy_session(session, err); 232 sm_destroy_session(session, err);
213 sessions[conn] = nil; 233 sessions[conn] = nil;
214 session = nil;
215 end 234 end
216 end 235 end
217 236
218 function listener.associate_session(conn, session) 237 function listener.associate_session(conn, session)
219 sessions[conn] = session; 238 sessions[conn] = session;