/net/server_select.lua
Lua | 935 lines | 781 code | 110 blank | 44 comment | 87 complexity | 7a52c2dd838a51e34d5b00f2f86f8391 MD5 | raw file
1-- 2-- server.lua by blastbeat of the luadch project 3-- Re-used here under the MIT/X Consortium License 4-- 5-- Modifications (C) 2008-2010 Matthew Wild, Waqas Hussain 6-- 7 8-- // wrapping luadch stuff // -- 9 10local use = function( what ) 11 return _G[ what ] 12end 13local clean = function( tbl ) 14 for i, k in pairs( tbl ) do 15 tbl[ i ] = nil 16 end 17end 18 19local log, table_concat = require ("util.logger").init("socket"), table.concat; 20local out_put = function (...) return log("debug", table_concat{...}); end 21local out_error = function (...) return log("warn", table_concat{...}); end 22local mem_free = collectgarbage 23 24----------------------------------// DECLARATION //-- 25 26--// constants //-- 27 28local STAT_UNIT = 1 -- byte 29 30--// lua functions //-- 31 32local type = use "type" 33local pairs = use "pairs" 34local ipairs = use "ipairs" 35local tostring = use "tostring" 36local collectgarbage = use "collectgarbage" 37 38--// lua libs //-- 39 40local os = use "os" 41local table = use "table" 42local string = use "string" 43local coroutine = use "coroutine" 44 45--// lua lib methods //-- 46 47local os_time = os.time 48local os_difftime = os.difftime 49local table_concat = table.concat 50local table_remove = table.remove 51local string_len = string.len 52local string_sub = string.sub 53local coroutine_wrap = coroutine.wrap 54local coroutine_yield = coroutine.yield 55 56--// extern libs //-- 57 58local luasec = use "ssl" 59local luasocket = use "socket" or require "socket" 60 61--// extern lib methods //-- 62 63local ssl_wrap = ( luasec and luasec.wrap ) 64local socket_bind = luasocket.bind 65local socket_sleep = luasocket.sleep 66local socket_select = luasocket.select 67local ssl_newcontext = ( luasec and luasec.newcontext ) 68 69--// functions //-- 70 71local id 72local loop 73local stats 74local idfalse 75local addtimer 76local closeall 77local addserver 78local getserver 79local wrapserver 80local getsettings 81local closesocket 82local removesocket 83local removeserver 84local changetimeout 85local wrapconnection 86local changesettings 87 88--// tables //-- 89 90local _server 91local _readlist 92local _timerlist 93local _sendlist 94local _socketlist 95local _closelist 96local _readtimes 97local _writetimes 98 99--// simple data types //-- 100 101local _ 102local _readlistlen 103local _sendlistlen 104local _timerlistlen 105 106local _sendtraffic 107local _readtraffic 108 109local _selecttimeout 110local _sleeptime 111 112local _starttime 113local _currenttime 114 115local _maxsendlen 116local _maxreadlen 117 118local _checkinterval 119local _sendtimeout 120local _readtimeout 121 122local _cleanqueue 123 124local _timer 125 126local _maxclientsperserver 127 128----------------------------------// DEFINITION //-- 129 130_server = { } -- key = port, value = table; list of listening servers 131_readlist = { } -- array with sockets to read from 132_sendlist = { } -- arrary with sockets to write to 133_timerlist = { } -- array of timer functions 134_socketlist = { } -- key = socket, value = wrapped socket (handlers) 135_readtimes = { } -- key = handler, value = timestamp of last data reading 136_writetimes = { } -- key = handler, value = timestamp of last data writing/sending 137_closelist = { } -- handlers to close 138 139_readlistlen = 0 -- length of readlist 140_sendlistlen = 0 -- length of sendlist 141_timerlistlen = 0 -- lenght of timerlist 142 143_sendtraffic = 0 -- some stats 144_readtraffic = 0 145 146_selecttimeout = 1 -- timeout of socket.select 147_sleeptime = 0 -- time to wait at the end of every loop 148 149_maxsendlen = 51000 * 1024 -- max len of send buffer 150_maxreadlen = 25000 * 1024 -- max len of read buffer 151 152_checkinterval = 1200000 -- interval in secs to check idle clients 153_sendtimeout = 60000 -- allowed send idle time in secs 154_readtimeout = 6 * 60 * 60 -- allowed read idle time in secs 155 156_cleanqueue = false -- clean bufferqueue after using 157 158_maxclientsperserver = 1000 159 160_maxsslhandshake = 30 -- max handshake round-trips 161 162----------------------------------// PRIVATE //-- 163 164wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxconnections ) -- this function wraps a server 165 166 maxconnections = maxconnections or _maxclientsperserver 167 168 local connections = 0 169 170 local dispatch, disconnect = listeners.onincoming, listeners.ondisconnect 171 172 local accept = socket.accept 173 174 --// public methods of the object //-- 175 176 local handler = { } 177 178 handler.shutdown = function( ) end 179 180 handler.ssl = function( ) 181 return sslctx ~= nil 182 end 183 handler.sslctx = function( ) 184 return sslctx 185 end 186 handler.remove = function( ) 187 connections = connections - 1 188 end 189 handler.close = function( ) 190 for _, handler in pairs( _socketlist ) do 191 if handler.serverport == serverport then 192 handler.disconnect( handler, "server closed" ) 193 handler:close( true ) 194 end 195 end 196 socket:close( ) 197 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 198 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 199 _socketlist[ socket ] = nil 200 handler = nil 201 socket = nil 202 --mem_free( ) 203 out_put "server.lua: closed server handler and removed sockets from list" 204 end 205 handler.ip = function( ) 206 return ip 207 end 208 handler.serverport = function( ) 209 return serverport 210 end 211 handler.socket = function( ) 212 return socket 213 end 214 handler.readbuffer = function( ) 215 if connections > maxconnections then 216 out_put( "server.lua: refused new client connection: server full" ) 217 return false 218 end 219 local client, err = accept( socket ) -- try to accept 220 if client then 221 local ip, clientport = client:getpeername( ) 222 client:settimeout( 0 ) 223 local handler, client, err = wrapconnection( handler, listeners, client, ip, serverport, clientport, pattern, sslctx ) -- wrap new client socket 224 if err then -- error while wrapping ssl socket 225 return false 226 end 227 connections = connections + 1 228 out_put( "server.lua: accepted new client connection from ", tostring(ip), ":", tostring(clientport), " to ", tostring(serverport)) 229 return dispatch( handler ) 230 elseif err then -- maybe timeout or something else 231 out_put( "server.lua: error with new client connection: ", tostring(err) ) 232 return false 233 end 234 end 235 return handler 236end 237 238wrapconnection = function( server, listeners, socket, ip, serverport, clientport, pattern, sslctx ) -- this function wraps a client to a handler object 239 240 socket:settimeout( 0 ) 241 242 --// local import of socket methods //-- 243 244 local send 245 local receive 246 local shutdown 247 248 --// private closures of the object //-- 249 250 local ssl 251 252 local dispatch = listeners.onincoming 253 local status = listeners.onstatus 254 local disconnect = listeners.ondisconnect 255 local drain = listeners.ondrain 256 257 local bufferqueue = { } -- buffer array 258 local bufferqueuelen = 0 -- end of buffer array 259 260 local toclose 261 local fatalerror 262 local needtls 263 264 local bufferlen = 0 265 266 local noread = false 267 local nosend = false 268 269 local sendtraffic, readtraffic = 0, 0 270 271 local maxsendlen = _maxsendlen 272 local maxreadlen = _maxreadlen 273 274 --// public methods of the object //-- 275 276 local handler = bufferqueue -- saves a table ^_^ 277 278 handler.dispatch = function( ) 279 return dispatch 280 end 281 handler.disconnect = function( ) 282 return disconnect 283 end 284 handler.setlistener = function( self, listeners ) 285 dispatch = listeners.onincoming 286 disconnect = listeners.ondisconnect 287 status = listeners.onstatus 288 drain = listeners.ondrain 289 end 290 handler.getstats = function( ) 291 return readtraffic, sendtraffic 292 end 293 handler.ssl = function( ) 294 return ssl 295 end 296 handler.sslctx = function ( ) 297 return sslctx 298 end 299 handler.send = function( _, data, i, j ) 300 return send( socket, data, i, j ) 301 end 302 handler.receive = function( pattern, prefix ) 303 return receive( socket, pattern, prefix ) 304 end 305 handler.shutdown = function( pattern ) 306 return shutdown( socket, pattern ) 307 end 308 handler.setoption = function (self, option, value) 309 if socket.setoption then 310 return socket:setoption(option, value); 311 end 312 return false, "setoption not implemented"; 313 end 314 handler.close = function( self, forced ) 315 if not handler then return true; end 316 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 317 _readtimes[ handler ] = nil 318 if bufferqueuelen ~= 0 then 319 if not ( forced or fatalerror ) then 320 handler.sendbuffer( ) 321 if bufferqueuelen ~= 0 then -- try again... 322 if handler then 323 handler.write = nil -- ... but no further writing allowed 324 end 325 toclose = true 326 return false 327 end 328 else 329 send( socket, table_concat( bufferqueue, "", 1, bufferqueuelen ), 1, bufferlen ) -- forced send 330 end 331 end 332 if socket then 333 _ = shutdown and shutdown( socket ) 334 socket:close( ) 335 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 336 _socketlist[ socket ] = nil 337 socket = nil 338 else 339 out_put "server.lua: socket already closed" 340 end 341 if handler then 342 _writetimes[ handler ] = nil 343 _closelist[ handler ] = nil 344 handler = nil 345 end 346 if server then 347 server.remove( ) 348 end 349 out_put "server.lua: closed client handler and removed socket from list" 350 return true 351 end 352 handler.ip = function( ) 353 return ip 354 end 355 handler.serverport = function( ) 356 return serverport 357 end 358 handler.clientport = function( ) 359 return clientport 360 end 361 local write = function( self, data ) 362 bufferlen = bufferlen + string_len( data ) 363 if bufferlen > maxsendlen then 364 _closelist[ handler ] = "send buffer exceeded" -- cannot close the client at the moment, have to wait to the end of the cycle 365 handler.write = idfalse -- dont write anymore 366 return false 367 elseif socket and not _sendlist[ socket ] then 368 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen) 369 end 370 bufferqueuelen = bufferqueuelen + 1 371 bufferqueue[ bufferqueuelen ] = data 372 if handler then 373 _writetimes[ handler ] = _writetimes[ handler ] or _currenttime 374 end 375 return true 376 end 377 handler.write = write 378 handler.bufferqueue = function( self ) 379 return bufferqueue 380 end 381 handler.socket = function( self ) 382 return socket 383 end 384 handler.set_mode = function( self, new ) 385 pattern = new or pattern 386 return pattern 387 end 388 handler.set_send = function ( self, newsend ) 389 send = newsend or send 390 return send 391 end 392 handler.bufferlen = function( self, readlen, sendlen ) 393 maxsendlen = sendlen or maxsendlen 394 maxreadlen = readlen or maxreadlen 395 return bufferlen, maxreadlen, maxsendlen 396 end 397 --TODO: Deprecate 398 handler.lock_read = function (self, switch) 399 if switch == true then 400 local tmp = _readlistlen 401 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 402 _readtimes[ handler ] = nil 403 if _readlistlen ~= tmp then 404 noread = true 405 end 406 elseif switch == false then 407 if noread then 408 noread = false 409 _readlistlen = addsocket(_readlist, socket, _readlistlen) 410 _readtimes[ handler ] = _currenttime 411 end 412 end 413 return noread 414 end 415 handler.pause = function (self) 416 return self:lock_read(true); 417 end 418 handler.resume = function (self) 419 return self:lock_read(false); 420 end 421 handler.lock = function( self, switch ) 422 handler.lock_read (switch) 423 if switch == true then 424 handler.write = idfalse 425 local tmp = _sendlistlen 426 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 427 _writetimes[ handler ] = nil 428 if _sendlistlen ~= tmp then 429 nosend = true 430 end 431 elseif switch == false then 432 handler.write = write 433 if nosend then 434 nosend = false 435 write( "" ) 436 end 437 end 438 return noread, nosend 439 end 440 local _readbuffer = function( ) -- this function reads data 441 local buffer, err, part = receive( socket, pattern ) -- receive buffer with "pattern" 442 if not err or (err == "wantread" or err == "timeout") then -- received something 443 local buffer = buffer or part or "" 444 local len = string_len( buffer ) 445 if len > maxreadlen then 446 disconnect( handler, "receive buffer exceeded" ) 447 handler:close( true ) 448 return false 449 end 450 local count = len * STAT_UNIT 451 readtraffic = readtraffic + count 452 _readtraffic = _readtraffic + count 453 _readtimes[ handler ] = _currenttime 454 --out_put( "server.lua: read data '", buffer:gsub("[^%w%p ]", "."), "', error: ", err ) 455 return dispatch( handler, buffer, err ) 456 else -- connections was closed or fatal error 457 out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) ) 458 fatalerror = true 459 disconnect( handler, err ) 460 _ = handler and handler:close( ) 461 return false 462 end 463 end 464 local _sendbuffer = function( ) -- this function sends data 465 local succ, err, byte, buffer, count; 466 local count; 467 if socket then 468 buffer = table_concat( bufferqueue, "", 1, bufferqueuelen ) 469 succ, err, byte = send( socket, buffer, 1, bufferlen ) 470 count = ( succ or byte or 0 ) * STAT_UNIT 471 sendtraffic = sendtraffic + count 472 _sendtraffic = _sendtraffic + count 473 _ = _cleanqueue and clean( bufferqueue ) 474 --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) ) 475 else 476 succ, err, count = false, "closed", 0; 477 end 478 if succ then -- sending succesful 479 bufferqueuelen = 0 480 bufferlen = 0 481 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) -- delete socket from writelist 482 _ = needtls and handler:starttls(nil, true) 483 _writetimes[ handler ] = nil 484 if drain then 485 drain(handler) 486 end 487 _ = toclose and handler:close( ) 488 return true 489 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write 490 buffer = string_sub( buffer, byte + 1, bufferlen ) -- new buffer 491 bufferqueue[ 1 ] = buffer -- insert new buffer in queue 492 bufferqueuelen = 1 493 bufferlen = bufferlen - byte 494 _writetimes[ handler ] = _currenttime 495 return true 496 else -- connection was closed during sending or fatal error 497 out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) ) 498 fatalerror = true 499 disconnect( handler, err ) 500 _ = handler and handler:close( ) 501 return false 502 end 503 end 504 505 -- Set the sslctx 506 local handshake; 507 function handler.set_sslctx(self, new_sslctx) 508 ssl = true 509 sslctx = new_sslctx; 510 local wrote 511 local read 512 handshake = coroutine_wrap( function( client ) -- create handshake coroutine 513 local err 514 for i = 1, _maxsslhandshake do 515 _sendlistlen = ( wrote and removesocket( _sendlist, client, _sendlistlen ) ) or _sendlistlen 516 _readlistlen = ( read and removesocket( _readlist, client, _readlistlen ) ) or _readlistlen 517 read, wrote = nil, nil 518 _, err = client:dohandshake( ) 519 if not err then 520 out_put( "server.lua: ssl handshake done" ) 521 handler.readbuffer = _readbuffer -- when handshake is done, replace the handshake function with regular functions 522 handler.sendbuffer = _sendbuffer 523 _ = status and status( handler, "ssl-handshake-complete" ) 524 _readlistlen = addsocket(_readlist, client, _readlistlen) 525 return true 526 else 527 out_put( "server.lua: error during ssl handshake: ", tostring(err) ) 528 if err == "wantwrite" and not wrote then 529 _sendlistlen = addsocket(_sendlist, client, _sendlistlen) 530 wrote = true 531 elseif err == "wantread" and not read then 532 _readlistlen = addsocket(_readlist, client, _readlistlen) 533 read = true 534 else 535 break; 536 end 537 --coroutine_yield( handler, nil, err ) -- handshake not finished 538 coroutine_yield( ) 539 end 540 end 541 disconnect( handler, "ssl handshake failed" ) 542 _ = handler and handler:close( true ) -- forced disconnect 543 return false -- handshake failed 544 end 545 ) 546 end 547 if luasec then 548 if sslctx then -- ssl? 549 handler:set_sslctx(sslctx); 550 out_put("server.lua: ", "starting ssl handshake") 551 local err 552 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket 553 if err then 554 out_put( "server.lua: ssl error: ", tostring(err) ) 555 --mem_free( ) 556 return nil, nil, err -- fatal error 557 end 558 socket:settimeout( 0 ) 559 handler.readbuffer = handshake 560 handler.sendbuffer = handshake 561 handshake( socket ) -- do handshake 562 if not socket then 563 return nil, nil, "ssl handshake failed"; 564 end 565 else 566 local sslctx; 567 handler.starttls = function( self, _sslctx, now ) 568 if _sslctx then 569 sslctx = _sslctx; 570 handler:set_sslctx(sslctx); 571 end 572 if not now then 573 out_put "server.lua: we need to do tls, but delaying until later" 574 needtls = true 575 return 576 end 577 out_put( "server.lua: attempting to start tls on " .. tostring( socket ) ) 578 local oldsocket, err = socket 579 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket 580 --out_put( "server.lua: sslwrapped socket is " .. tostring( socket ) ) 581 if err then 582 out_put( "server.lua: error while starting tls on client: ", tostring(err) ) 583 return nil, err -- fatal error 584 end 585 586 socket:settimeout( 0 ) 587 588 -- add the new socket to our system 589 590 send = socket.send 591 receive = socket.receive 592 shutdown = id 593 594 _socketlist[ socket ] = handler 595 _readlistlen = addsocket(_readlist, socket, _readlistlen) 596 597 -- remove traces of the old socket 598 599 _readlistlen = removesocket( _readlist, oldsocket, _readlistlen ) 600 _sendlistlen = removesocket( _sendlist, oldsocket, _sendlistlen ) 601 _socketlist[ oldsocket ] = nil 602 603 handler.starttls = nil 604 needtls = nil 605 606 -- Secure now 607 ssl = true 608 609 handler.readbuffer = handshake 610 handler.sendbuffer = handshake 611 handshake( socket ) -- do handshake 612 end 613 handler.readbuffer = _readbuffer 614 handler.sendbuffer = _sendbuffer 615 end 616 else 617 handler.readbuffer = _readbuffer 618 handler.sendbuffer = _sendbuffer 619 end 620 send = socket.send 621 receive = socket.receive 622 shutdown = ( ssl and id ) or socket.shutdown 623 624 _socketlist[ socket ] = handler 625 _readlistlen = addsocket(_readlist, socket, _readlistlen) 626 if listeners.onconnect then 627 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen) 628 handler.sendbuffer = function () 629 listeners.onconnect(handler); 630 handler.sendbuffer = _sendbuffer; 631 if bufferqueuelen > 0 then 632 return _sendbuffer(); 633 end 634 end 635 end 636 return handler, socket 637end 638 639id = function( ) 640end 641 642idfalse = function( ) 643 return false 644end 645 646addsocket = function( list, socket, len ) 647 if not list[ socket ] then 648 len = len + 1 649 list[ len ] = socket 650 list[ socket ] = len 651 end 652 return len; 653end 654 655removesocket = function( list, socket, len ) -- this function removes sockets from a list ( copied from copas ) 656 local pos = list[ socket ] 657 if pos then 658 list[ socket ] = nil 659 local last = list[ len ] 660 list[ len ] = nil 661 if last ~= socket then 662 list[ last ] = pos 663 list[ pos ] = last 664 end 665 return len - 1 666 end 667 return len 668end 669 670closesocket = function( socket ) 671 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 672 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 673 _socketlist[ socket ] = nil 674 socket:close( ) 675 --mem_free( ) 676end 677 678local function link(sender, receiver, buffersize) 679 sender:set_mode(buffersize); 680 local sender_locked; 681 local _sendbuffer = receiver.sendbuffer; 682 function receiver.sendbuffer() 683 _sendbuffer(); 684 if sender_locked and receiver.bufferlen() < buffersize then 685 sender:lock_read(false); -- Unlock now 686 sender_locked = nil; 687 end 688 end 689 690 local _readbuffer = sender.readbuffer; 691 function sender.readbuffer() 692 _readbuffer(); 693 if not sender_locked and receiver.bufferlen() >= buffersize then 694 sender_locked = true; 695 sender:lock_read(true); 696 end 697 end 698end 699 700----------------------------------// PUBLIC //-- 701 702addserver = function( addr, port, listeners, pattern, sslctx ) -- this function provides a way for other scripts to reg a server 703 local err 704 if type( listeners ) ~= "table" then 705 err = "invalid listener table" 706 end 707 if type( port ) ~= "number" or not ( port >= 0 and port <= 65535 ) then 708 err = "invalid port" 709 elseif _server[ port ] then 710 err = "listeners on port '" .. port .. "' already exist" 711 elseif sslctx and not luasec then 712 err = "luasec not found" 713 end 714 if err then 715 out_error( "server.lua, port ", port, ": ", err ) 716 return nil, err 717 end 718 addr = addr or "*" 719 local server, err = socket_bind( addr, port ) 720 if err then 721 out_error( "server.lua, port ", port, ": ", err ) 722 return nil, err 723 end 724 local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, _maxclientsperserver ) -- wrap new server socket 725 if not handler then 726 server:close( ) 727 return nil, err 728 end 729 server:settimeout( 0 ) 730 _readlistlen = addsocket(_readlist, server, _readlistlen) 731 _server[ port ] = handler 732 _socketlist[ server ] = handler 733 out_put( "server.lua: new "..(sslctx and "ssl " or "").."server listener on '", addr, ":", port, "'" ) 734 return handler 735end 736 737getserver = function ( port ) 738 return _server[ port ]; 739end 740 741removeserver = function( port ) 742 local handler = _server[ port ] 743 if not handler then 744 return nil, "no server found on port '" .. tostring( port ) .. "'" 745 end 746 handler:close( ) 747 _server[ port ] = nil 748 return true 749end 750 751closeall = function( ) 752 for _, handler in pairs( _socketlist ) do 753 handler:close( ) 754 _socketlist[ _ ] = nil 755 end 756 _readlistlen = 0 757 _sendlistlen = 0 758 _timerlistlen = 0 759 _server = { } 760 _readlist = { } 761 _sendlist = { } 762 _timerlist = { } 763 _socketlist = { } 764 --mem_free( ) 765end 766 767getsettings = function( ) 768 return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver, _maxsslhandshake 769end 770 771changesettings = function( new ) 772 if type( new ) ~= "table" then 773 return nil, "invalid settings table" 774 end 775 _selecttimeout = tonumber( new.timeout ) or _selecttimeout 776 _sleeptime = tonumber( new.sleeptime ) or _sleeptime 777 _maxsendlen = tonumber( new.maxsendlen ) or _maxsendlen 778 _maxreadlen = tonumber( new.maxreadlen ) or _maxreadlen 779 _checkinterval = tonumber( new.checkinterval ) or _checkinterval 780 _sendtimeout = tonumber( new.sendtimeout ) or _sendtimeout 781 _readtimeout = tonumber( new.readtimeout ) or _readtimeout 782 _cleanqueue = new.cleanqueue 783 _maxclientsperserver = new._maxclientsperserver or _maxclientsperserver 784 _maxsslhandshake = new._maxsslhandshake or _maxsslhandshake 785 return true 786end 787 788addtimer = function( listener ) 789 if type( listener ) ~= "function" then 790 return nil, "invalid listener function" 791 end 792 _timerlistlen = _timerlistlen + 1 793 _timerlist[ _timerlistlen ] = listener 794 return true 795end 796 797stats = function( ) 798 return _readtraffic, _sendtraffic, _readlistlen, _sendlistlen, _timerlistlen 799end 800 801local dontstop = true; -- thinking about tomorrow, ... 802 803setquitting = function (quit) 804 dontstop = not quit; 805 return; 806end 807 808loop = function( ) -- this is the main loop of the program 809 while dontstop do 810 local read, write, err = socket_select( _readlist, _sendlist, _selecttimeout ) 811 for i, socket in ipairs( write ) do -- send data waiting in writequeues 812 local handler = _socketlist[ socket ] 813 if handler then 814 handler.sendbuffer( ) 815 else 816 closesocket( socket ) 817 out_put "server.lua: found no handler and closed socket (writelist)" -- this should not happen 818 end 819 end 820 for i, socket in ipairs( read ) do -- receive data 821 local handler = _socketlist[ socket ] 822 if handler then 823 handler.readbuffer( ) 824 else 825 closesocket( socket ) 826 out_put "server.lua: found no handler and closed socket (readlist)" -- this can happen 827 end 828 end 829 for handler, err in pairs( _closelist ) do 830 handler.disconnect( )( handler, err ) 831 handler:close( true ) -- forced disconnect 832 end 833 clean( _closelist ) 834 _currenttime = os_time( ) 835 if os_difftime( _currenttime - _timer ) >= 1 then 836 for i = 1, _timerlistlen do 837 _timerlist[ i ]( _currenttime ) -- fire timers 838 end 839 _timer = _currenttime 840 end 841 socket_sleep( _sleeptime ) -- wait some time 842 --collectgarbage( ) 843 end 844 return "quitting" 845end 846 847local function get_backend() 848 return "select"; 849end 850 851--// EXPERIMENTAL //-- 852 853local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx ) 854 local handler = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx ) 855 _socketlist[ socket ] = handler 856 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen) 857 return handler, socket 858end 859 860local addclient = function( address, port, listeners, pattern, sslctx ) 861 local client, err = luasocket.tcp( ) 862 if err then 863 return nil, err 864 end 865 client:settimeout( 0 ) 866 _, err = client:connect( address, port ) 867 if err then -- try again 868 local handler = wrapclient( client, address, port, listeners ) 869 else 870 wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx ) 871 end 872end 873 874--// EXPERIMENTAL //-- 875 876----------------------------------// BEGIN //-- 877 878use "setmetatable" ( _socketlist, { __mode = "k" } ) 879use "setmetatable" ( _readtimes, { __mode = "k" } ) 880use "setmetatable" ( _writetimes, { __mode = "k" } ) 881 882_timer = os_time( ) 883_starttime = os_time( ) 884 885addtimer( function( ) 886 local difftime = os_difftime( _currenttime - _starttime ) 887 if difftime > _checkinterval then 888 _starttime = _currenttime 889 for handler, timestamp in pairs( _writetimes ) do 890 if os_difftime( _currenttime - timestamp ) > _sendtimeout then 891 --_writetimes[ handler ] = nil 892 handler.disconnect( )( handler, "send timeout" ) 893 handler:close( true ) -- forced disconnect 894 end 895 end 896 for handler, timestamp in pairs( _readtimes ) do 897 if os_difftime( _currenttime - timestamp ) > _readtimeout then 898 --_readtimes[ handler ] = nil 899 handler.disconnect( )( handler, "read timeout" ) 900 handler:close( ) -- forced disconnect? 901 end 902 end 903 end 904 end 905) 906 907local function setlogger(new_logger) 908 local old_logger = log; 909 if new_logger then 910 log = new_logger; 911 end 912 return old_logger; 913end 914 915----------------------------------// PUBLIC INTERFACE //-- 916 917return { 918 919 addclient = addclient, 920 wrapclient = wrapclient, 921 922 loop = loop, 923 link = link, 924 stats = stats, 925 closeall = closeall, 926 addtimer = addtimer, 927 addserver = addserver, 928 getserver = getserver, 929 setlogger = setlogger, 930 getsettings = getsettings, 931 setquitting = setquitting, 932 removeserver = removeserver, 933 get_backend = get_backend, 934 changesettings = changesettings, 935}