Comparison

plugins/mod_bosh.lua @ 7651:55f11a6806bc

mod_bosh: Correctly handle requests arriving out of order (thanks Jitsi folk!)
author Matthew Wild <mwild1@gmail.com>
date Fri, 02 Sep 2016 21:57:22 +0100
parent 7387:addd041342bd
child 7652:7cc3d6c764ce
comparison
equal deleted inserted replaced
7648:d91ef1e6afc2 7651:55f11a6806bc
347 end 347 end
348 348
349 if session.rid then 349 if session.rid then
350 local rid = tonumber(attr.rid); 350 local rid = tonumber(attr.rid);
351 local diff = rid - session.rid; 351 local diff = rid - session.rid;
352 if diff > 1 then 352 -- Diff should be 1 for a healthy request
353 session.log("warn", "rid too large (means a request was lost). Last rid: %d New rid: %s", session.rid, attr.rid); 353 if diff ~= 1 then
354 elseif diff <= 0 then 354 context.sid = sid;
355 -- Repeated, ignore
356 session.log("debug", "rid repeated, ignoring: %s (diff %d)", session.rid, diff);
357 context.notopen = nil; 355 context.notopen = nil;
356 if diff == 2 then
357 -- Hold request, but don't process it (ouch!)
358 session.log("debug", "rid skipped: %d, deferring this request", rid-1)
359 context.defer = true;
360 session.bosh_deferred = { context = context, sid = sid, rid = rid, terminate = attr.type == "terminate" };
361 return;
362 end
358 context.ignore = true; 363 context.ignore = true;
359 context.sid = sid; 364 if diff == 0 then
360 t_insert(session.requests, response); 365 -- Re-send previous response, ignore stanzas in this request
366 session.log("debug", "rid repeated, ignoring: %s (diff %d)", session.rid, diff);
367 response:send(session.bosh_last_response);
368 return;
369 end
370 -- Session broken, destroy it
371 session.log("debug", "rid out of range: %d (diff %d)", rid, diff);
372 response:send(tostring(st.stanza("body", { xmlns = xmlns_bosh, type = "terminate", condition = "item-not-found" })));
361 return; 373 return;
362 end 374 end
363 session.rid = rid; 375 session.rid = rid;
364 end 376 end
365 377
389 local session = sessions[context.sid]; 401 local session = sessions[context.sid];
390 if session then 402 if session then
391 if stanza.attr.xmlns == xmlns_bosh then 403 if stanza.attr.xmlns == xmlns_bosh then
392 stanza.attr.xmlns = nil; 404 stanza.attr.xmlns = nil;
393 end 405 end
394 stanza = session.filter("stanzas/in", stanza); 406 if context.defer and session.bosh_deferred then
395 if stanza then 407 log("debug", "Deferring this stanza");
396 return xpcall(function () return core_process_stanza(session, stanza) end, handleerr); 408 t_insert(session.bosh_deferred, stanza);
409 else
410 stanza = session.filter("stanzas/in", stanza);
411 if stanza then
412 return xpcall(function () return core_process_stanza(session, stanza) end, handleerr);
413 end
397 end 414 end
398 end 415 end
399 end 416 end
400 417
401 function stream_callbacks.streamclosed(context) 418 function stream_callbacks.streamclosed(context)
402 local session = sessions[context.sid]; 419 local session = sessions[context.sid];
403 if session then 420 if session then
421 if not context.defer and session.bosh_deferred then
422 -- Handle deferred stanzas now
423 local deferred_stanzas = session.bosh_deferred;
424 local context = deferred_stanzas.context;
425 session.bosh_deferred = nil;
426 log("debug", "Handling deferred stanzas from rid %d", deferred_stanzas.rid);
427 session.rid = deferred_stanzas.rid;
428 t_insert(session.requests, context.response);
429 for _, stanza in ipairs(deferred_stanzas) do
430 stream_callbacks.handlestanza(context, stanza);
431 end
432 if deferred_stanzas.terminate then
433 session.bosh_terminate = true;
434 end
435 end
404 session.bosh_processing = false; 436 session.bosh_processing = false;
405 if #session.send_buffer > 0 then 437 if #session.send_buffer > 0 then
406 session.send(""); 438 session.send("");
407 end 439 end
408 end 440 end