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