Software /
code /
prosody
Comparison
net/server.lua @ 630:e9336adb66e5
Fix data loss when closing connection with a large write queue. Thanks albert :)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Thu, 18 Dec 2008 20:01:09 +0000 |
parent | 620:9f9f69d67edb |
child | 657:7f1946174d4b |
comparison
equal
deleted
inserted
replaced
629:6f9052edb18d | 630:e9336adb66e5 |
---|---|
35 local string_sub = use'string'.sub | 35 local string_sub = use'string'.sub |
36 local coroutine_wrap = coroutine.wrap | 36 local coroutine_wrap = coroutine.wrap |
37 local coroutine_yield = coroutine.yield | 37 local coroutine_yield = coroutine.yield |
38 local print = print; | 38 local print = print; |
39 local out_put = function () end --print; | 39 local out_put = function () end --print; |
40 local out_put = print; | |
40 local out_error = print; | 41 local out_error = print; |
41 | 42 |
42 --// extern libs //-- | 43 --// extern libs //-- |
43 | 44 |
44 local luasec = select(2, pcall(require, "ssl")) | 45 local luasec = select(2, pcall(require, "ssl")) |
98 | 99 |
99 local dispatch, disconnect = listener.listener, listener.disconnect -- dangerous | 100 local dispatch, disconnect = listener.listener, listener.disconnect -- dangerous |
100 | 101 |
101 local wrapclient, err | 102 local wrapclient, err |
102 | 103 |
104 out_put("Starting a new server on "..tostring(serverport).." with ssl: "..tostring(sslctx)); | |
105 | |
103 if sslctx then | 106 if sslctx then |
104 if not ssl_newcontext then | 107 if not ssl_newcontext then |
105 return nil, "luasec not found" | 108 return nil, "luasec not found" |
106 end | 109 end |
107 if type( sslctx ) ~= "table" then | 110 if type( sslctx ) ~= "table" then |
186 | 189 |
187 --// private closures of the object //-- | 190 --// private closures of the object //-- |
188 | 191 |
189 local writequeue = { } -- buffer for messages to send | 192 local writequeue = { } -- buffer for messages to send |
190 | 193 |
191 local eol, fatal_send_error -- end of buffer | 194 local eol, fatal_send_error, wants_closing |
192 | 195 |
193 local sstat, rstat = 0, 0 | 196 local sstat, rstat = 0, 0 |
194 | 197 |
195 --// local import of socket methods //-- | 198 --// local import of socket methods //-- |
196 | 199 |
221 end | 224 end |
222 handler.shutdown = function( pattern ) | 225 handler.shutdown = function( pattern ) |
223 --return shutdown( socket, pattern ) | 226 --return shutdown( socket, pattern ) |
224 end | 227 end |
225 handler.close = function( closed ) | 228 handler.close = function( closed ) |
226 if eol and not fatal_send_error then handler._dispatchdata(); end | 229 if eol and not fatal_send_error then |
230 -- There is data in the buffer, and we haven't experienced | |
231 -- an error trying to send yet, so we'll flush the buffer now | |
232 handler._dispatchdata(); | |
233 if eol then | |
234 -- and there is *still* data in the buffer | |
235 -- we'll give up for now, and close later | |
236 wants_closing = true; | |
237 return; | |
238 end | |
239 end | |
227 close( socket ) | 240 close( socket ) |
228 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen | 241 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen |
229 readlen = removesocket( readlist, socket, readlen ) | 242 readlen = removesocket( readlist, socket, readlen ) |
230 socketlist[ socket ] = nil | 243 socketlist[ socket ] = nil |
231 out_put "server.lua: closed handler and removed socket from list" | 244 out_put "server.lua: closed handler and removed socket from list" |
285 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport ) | 298 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport ) |
286 if succ then -- sending succesful | 299 if succ then -- sending succesful |
287 --writequeue = { } | 300 --writequeue = { } |
288 eol = nil | 301 eol = nil |
289 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist | 302 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist |
303 if wants_closing then | |
304 handler.close(); | |
305 end | |
290 return true | 306 return true |
291 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write | 307 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write |
292 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer | 308 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer |
293 writequeue[ 1 ] = buffer -- insert new buffer in queue | 309 writequeue[ 1 ] = buffer -- insert new buffer in queue |
294 eol = 1 | 310 eol = 1 |
366 socket:settimeout( 0 ) | 382 socket:settimeout( 0 ) |
367 --// private closures of the object //-- | 383 --// private closures of the object //-- |
368 | 384 |
369 local writequeue = { } -- buffer for messages to send | 385 local writequeue = { } -- buffer for messages to send |
370 | 386 |
371 local eol, fatal_send_error -- end of buffer | 387 local eol, fatal_send_error, wants_closing |
372 | 388 |
373 local sstat, rstat = 0, 0 | 389 local sstat, rstat = 0, 0 |
374 | 390 |
375 --// local import of socket methods //-- | 391 --// local import of socket methods //-- |
376 | 392 |
401 end | 417 end |
402 handler.shutdown = function( pattern ) | 418 handler.shutdown = function( pattern ) |
403 --return shutdown( socket, pattern ) | 419 --return shutdown( socket, pattern ) |
404 end | 420 end |
405 handler.close = function( closed ) | 421 handler.close = function( closed ) |
406 if eol and not fatal_send_error then handler._dispatchdata(); end | 422 if eol and not fatal_send_error then |
423 -- There is data in the buffer, and we haven't experienced | |
424 -- an error trying to send yet, so we'll flush the buffer now | |
425 handler._dispatchdata(); | |
426 if eol then | |
427 -- and there is *still* data in the buffer | |
428 -- we'll give up for now, and close later | |
429 wants_closing = true; | |
430 return; | |
431 end | |
432 end | |
407 close( socket ) | 433 close( socket ) |
408 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen | 434 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen |
409 readlen = removesocket( readlist, socket, readlen ) | 435 readlen = removesocket( readlist, socket, readlen ) |
410 socketlist[ socket ] = nil | 436 socketlist[ socket ] = nil |
411 out_put "server.lua: closed handler and removed socket from list" | 437 out_put "server.lua: closed handler and removed socket from list" |
468 eol = nil | 494 eol = nil |
469 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist | 495 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist |
470 if handler.need_tls then | 496 if handler.need_tls then |
471 out_put("server.lua: connection is ready for tls handshake"); | 497 out_put("server.lua: connection is ready for tls handshake"); |
472 handler.starttls(true); | 498 handler.starttls(true); |
499 end | |
500 if wants_closing then | |
501 handler.close(); | |
473 end | 502 end |
474 return true | 503 return true |
475 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write | 504 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write |
476 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer | 505 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer |
477 writequeue[ 1 ] = buffer -- insert new buffer in queue | 506 writequeue[ 1 ] = buffer -- insert new buffer in queue |
583 | 612 |
584 --// private closures of the object //-- | 613 --// private closures of the object //-- |
585 | 614 |
586 local writequeue = { } -- list for messages to send | 615 local writequeue = { } -- list for messages to send |
587 | 616 |
588 local eol, fatal_send_error | 617 local eol, fatal_send_error, wants_closing |
589 | 618 |
590 socket:settimeout(0); | 619 socket:settimeout(0); |
591 | 620 |
592 local rstat, sstat = 0, 0 | 621 local rstat, sstat = 0, 0 |
593 | 622 |
620 end | 649 end |
621 handler.shutdown = function( pattern ) | 650 handler.shutdown = function( pattern ) |
622 return shutdown( socket, pattern ) | 651 return shutdown( socket, pattern ) |
623 end | 652 end |
624 handler.close = function( closed ) | 653 handler.close = function( closed ) |
625 if eol and not fatal_send_error then handler.dispatchdata(); end | 654 if eol and not fatal_send_error then |
655 -- There is data in the buffer, and we haven't experienced | |
656 -- an error trying to send yet, so we'll flush the buffer now | |
657 handler.dispatchdata(); | |
658 if eol then | |
659 -- and there is *still* data in the buffer | |
660 -- we'll give up for now, and close later | |
661 wants_closing = true; | |
662 return; | |
663 end | |
664 end | |
626 _ = not closed and shutdown( socket ) | 665 _ = not closed and shutdown( socket ) |
627 _ = not closed and close( socket ) | 666 _ = not closed and close( socket ) |
628 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen | 667 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen |
629 readlen = removesocket( readlist, socket, readlen ) | 668 readlen = removesocket( readlist, socket, readlen ) |
630 socketlist[ socket ] = nil | 669 socketlist[ socket ] = nil |
686 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport ) | 725 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport ) |
687 if succ then -- sending succesful | 726 if succ then -- sending succesful |
688 --writequeue = { } | 727 --writequeue = { } |
689 eol = nil | 728 eol = nil |
690 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist | 729 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist |
730 if wants_closing then | |
731 handler.close(); | |
732 end | |
691 return true | 733 return true |
692 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write | 734 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write |
693 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer | 735 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer |
694 writequeue[ 1 ] = buffer -- insert new buffer in queue | 736 writequeue[ 1 ] = buffer -- insert new buffer in queue |
695 eol = 1 | 737 eol = 1 |