Mercurial > prosody-hg
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 |
| parents | 9f9f69d67edb |
| children | 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 |
