2 -- server.lua by blastbeat of the luadch project
3 -- Re-used here under the MIT/X Consortium License
5 -- Modifications (C) 2008-2010 Matthew Wild, Waqas Hussain
8 -- // wrapping luadch stuff // --
10 local use
= function( what
)
14 local log, table_concat
= require ("util.logger").init("socket"), table.concat
;
15 local out_put
= function (...) return log("debug", table_concat
{...}); end
16 local out_error
= function (...) return log("warn", table_concat
{...}); end
18 ----------------------------------// DECLARATION //--
22 local STAT_UNIT
= 1 -- byte
24 --// lua functions //--
26 local type = use
"type"
27 local pairs
= use
"pairs"
28 local ipairs
= use
"ipairs"
29 local tonumber = use
"tonumber"
30 local tostring = use
"tostring"
34 local table = use
"table"
35 local string = use
"string"
36 local coroutine
= use
"coroutine"
38 --// lua lib methods //--
40 local math_min
= math
.min
41 local math_huge
= math
.huge
42 local table_concat
= table.concat
43 local table_insert
= table.insert
44 local string_sub
= string.sub
45 local coroutine_wrap
= coroutine
.wrap
46 local coroutine_yield
= coroutine
.yield
50 local has_luasec
, luasec
= pcall ( require
, "ssl" )
51 local luasocket
= use
"socket" or require
"socket"
52 local luasocket_gettime
= luasocket
.gettime
53 local inet
= require
"util.net";
54 local inet_pton
= inet
.pton
;
56 --// extern lib methods //--
58 local ssl_wrap
= ( has_luasec
and luasec
.wrap
)
59 local socket_bind
= luasocket
.bind
60 local socket_select
= luasocket
.select
94 --// simple data types //--
121 local _maxsslhandshake
123 ----------------------------------// DEFINITION //--
125 _server
= { } -- key = port, value = table; list of listening servers
126 _readlist
= { } -- array with sockets to read from
127 _sendlist
= { } -- array with sockets to write to
128 _timerlist
= { } -- array of timer functions
129 _socketlist
= { } -- key = socket, value = wrapped socket (handlers)
130 _readtimes
= { } -- key = handler, value = timestamp of last data reading
131 _writetimes
= { } -- key = handler, value = timestamp of last data writing/sending
132 _closelist
= { } -- handlers to close
133 _fullservers
= { } -- servers in a paused state while there are too many clients
135 _readlistlen
= 0 -- length of readlist
136 _sendlistlen
= 0 -- length of sendlist
137 _timerlistlen
= 0 -- length of timerlist
139 _sendtraffic
= 0 -- some stats
142 _selecttimeout
= 1 -- timeout of socket.select
143 _tcpbacklog
= 128 -- some kind of hint to the OS
144 _accepretry
= 10 -- seconds to wait until the next attempt of a full server to accept
146 _maxsendlen
= 51000 * 1024 -- max len of send buffer
147 _maxreadlen
= 25000 * 1024 -- max len of read buffer
149 _checkinterval
= 30 -- interval in secs to check idle clients
150 _sendtimeout
= 60000 -- allowed send idle time in secs
151 _readtimeout
= 14 * 60 -- allowed read idle time in secs
153 local is_windows
= package
.config
:sub(1,1) == "\\" -- check the directory separator, to determine whether this is Windows
154 _maxfd
= (is_windows
and math
.huge
) or luasocket
._SETSIZE
or 1024 -- max fd number, limit to 1024 by default to prevent glibc buffer overflow, but not on Windows
155 _maxselectlen
= luasocket
._SETSIZE
or 1024 -- But this still applies on Windows
157 _maxsslhandshake
= 30 -- max handshake round-trips
159 ----------------------------------// PRIVATE //--
161 wrapserver
= function( listeners
, socket
, ip
, serverport
, pattern
, sslctx
, ssldirect
) -- this function wraps a server -- FIXME Make sure FD < _maxfd
163 if socket
:getfd() >= _maxfd
then
164 out_error("server.lua: Disallowed FD number: "..socket
:getfd())
166 return nil, "fd-too-large"
169 local connections
= 0
171 local dispatch
, disconnect
= listeners
.onconnect
, listeners
.ondisconnect
173 local accept
= socket
.accept
175 --// public methods of the object //--
179 handler
.shutdown
= function( ) end
181 handler
.ssl
= function( )
184 handler
.sslctx
= function( )
187 handler
.hosts
= {} -- sni
188 handler
.remove = function( )
189 connections
= connections
- 1
194 handler
.close
= function()
196 _sendlistlen
= removesocket( _sendlist
, socket
, _sendlistlen
)
197 _readlistlen
= removesocket( _readlist
, socket
, _readlistlen
)
198 _server
[ip
..":"..serverport
] = nil;
199 _socketlist
[ socket
] = nil
203 out_put
"server.lua: closed server handler and removed sockets from list"
205 handler
.pause
= function( hard
)
206 if not handler
.paused
then
207 _readlistlen
= removesocket( _readlist
, socket
, _readlistlen
)
209 _socketlist
[ socket
] = nil
213 handler
.paused
= true;
214 out_put("server.lua: server [", ip
, "]:", serverport
, " paused")
217 handler
.resume
= function( )
218 if handler
.paused
then
220 socket
= socket_bind( ip
, serverport
, _tcpbacklog
);
221 socket
:settimeout( 0 )
223 _readlistlen
= addsocket(_readlist
, socket
, _readlistlen
)
224 _socketlist
[ socket
] = handler
225 _fullservers
[ handler
] = nil
226 handler
.paused
= false;
227 out_put("server.lua: server [", ip
, "]:", serverport
, " resumed")
230 handler
.ip
= function( )
233 handler
.serverport
= function( )
236 handler
.socket
= function( )
239 handler
.readbuffer
= function( )
240 if _readlistlen
>= _maxselectlen
or _sendlistlen
>= _maxselectlen
then
242 _fullservers
[ handler
] = _currenttime
243 out_put( "server.lua: refused new client connection: server full" )
246 local client
, err
= accept( socket
) -- try to accept
248 local ip
, clientport
= client
:getpeername( )
249 local handler
, client
, err
= wrapconnection( handler
, listeners
, client
, ip
, serverport
, clientport
, pattern
, sslctx
, ssldirect
) -- wrap new client socket
250 if err
then -- error while wrapping ssl socket
253 connections
= connections
+ 1
254 out_put( "server.lua: accepted new client connection from ", tostring(ip
), ":", tostring(clientport
), " to ", tostring(serverport
))
255 if dispatch
and not ssldirect
then -- SSL connections will notify onconnect when handshake completes
256 return dispatch( handler
);
259 elseif err
then -- maybe timeout or something else
260 out_put( "server.lua: error with new client connection: ", tostring(err
) )
262 _fullservers
[ handler
] = _currenttime
269 wrapconnection
= function( server
, listeners
, socket
, ip
, serverport
, clientport
, pattern
, sslctx
, ssldirect
, extra
) -- this function wraps a client to a handler object
271 if socket
:getfd() >= _maxfd
then
272 out_error("server.lua: Disallowed FD number: "..socket
:getfd()) -- PROTIP: Switch to libevent
273 socket
:close( ) -- Should we send some kind of error here?
275 _fullservers
[ server
] = _currenttime
278 return nil, nil, "fd-too-large"
280 socket
:settimeout( 0 )
282 --// local import of socket methods //--
288 --// private closures of the object //--
292 local dispatch
= listeners
.onincoming
293 local status
= listeners
.onstatus
294 local disconnect
= listeners
.ondisconnect
295 local drain
= listeners
.ondrain
296 local onreadtimeout
= listeners
.onreadtimeout
;
297 local detach
= listeners
.ondetach
299 local bufferqueue
= { } -- buffer array
300 local bufferqueuelen
= 0 -- end of buffer array
310 local sendtraffic
, readtraffic
= 0, 0
312 local maxsendlen
= _maxsendlen
313 local maxreadlen
= _maxreadlen
315 --// public methods of the object //--
317 local handler
= bufferqueue
-- saves a table ^_^
319 handler
.extra
= extra
321 handler
.servername
= extra
.servername
324 handler
.dispatch
= function( )
327 handler
.disconnect
= function( )
330 handler
.onreadtimeout
= onreadtimeout
;
332 handler
.setlistener
= function( self
, listeners
, data
)
334 detach(self
) -- Notify listener that it is no longer responsible for this connection
336 dispatch
= listeners
.onincoming
337 disconnect
= listeners
.ondisconnect
338 status
= listeners
.onstatus
339 drain
= listeners
.ondrain
340 handler
.onreadtimeout
= listeners
.onreadtimeout
341 detach
= listeners
.ondetach
342 if listeners
.onattach
then
343 listeners
.onattach(self
, data
)
346 handler
.getstats
= function( )
347 return readtraffic
, sendtraffic
349 handler
.ssl
= function( )
352 handler
.sslctx
= function ( )
355 handler
.send
= function( _
, data
, i
, j
)
356 return send( socket
, data
, i
, j
)
358 handler
.receive
= function( pattern
, prefix
)
359 return receive( socket
, pattern
, prefix
)
361 handler
.shutdown
= function( pattern
)
362 return shutdown( socket
, pattern
)
364 handler
.setoption
= function (self
, option
, value
)
365 if socket
.setoption
then
366 return socket
:setoption(option
, value
);
368 return false, "setoption not implemented";
370 handler
.force_close
= function ( self
, err
)
371 if bufferqueuelen
~= 0 then
372 out_put("server.lua: discarding unwritten data for ", tostring(ip
), ":", tostring(clientport
))
375 return self
:close(err
);
377 handler
.close
= function( self
, err
)
378 if not handler
then return true; end
379 _readlistlen
= removesocket( _readlist
, socket
, _readlistlen
)
380 _readtimes
[ handler
] = nil
381 if bufferqueuelen
~= 0 then
382 handler
.sendbuffer() -- Try now to send any outstanding data
383 if bufferqueuelen
~= 0 then -- Still not empty, so we'll try again later
385 handler
.write = nil -- ... but no further writing allowed
392 _
= shutdown
and shutdown( socket
)
394 _sendlistlen
= removesocket( _sendlist
, socket
, _sendlistlen
)
395 _socketlist
[ socket
] = nil
398 out_put
"server.lua: socket already closed"
401 _writetimes
[ handler
] = nil
402 _closelist
[ handler
] = nil
403 local _handler
= handler
;
406 disconnect(_handler
, err
or false);
413 out_put
"server.lua: closed client handler and removed socket from list"
416 handler
.server
= function ( )
419 handler
.ip
= function( )
422 handler
.serverport
= function( )
425 handler
.clientport
= function( )
428 handler
.port
= handler
.clientport
-- COMPAT server_event
429 local write = function( self
, data
)
430 if not handler
then return false end
431 bufferlen
= bufferlen
+ #data
432 if bufferlen
> maxsendlen
then
433 _closelist
[ handler
] = "send buffer exceeded" -- cannot close the client at the moment, have to wait to the end of the cycle
435 elseif not nosend
and socket
and not _sendlist
[ socket
] then
436 _sendlistlen
= addsocket(_sendlist
, socket
, _sendlistlen
)
438 bufferqueuelen
= bufferqueuelen
+ 1
439 bufferqueue
[ bufferqueuelen
] = data
441 _writetimes
[ handler
] = _writetimes
[ handler
] or _currenttime
445 handler
.write = write
446 handler
.bufferqueue
= function( self
)
449 handler
.socket
= function( self
)
452 handler
.set_mode
= function( self
, new
)
453 pattern
= new
or pattern
456 handler
.set_send
= function ( self
, newsend
)
457 send
= newsend
or send
460 handler
.bufferlen
= function( self
, readlen
, sendlen
)
461 maxsendlen
= sendlen
or maxsendlen
462 maxreadlen
= readlen
or maxreadlen
463 return bufferlen
, maxreadlen
, maxsendlen
465 handler
.lock_read
= function (self
, switch
)
466 out_error( "server.lua, lock_read() is deprecated, use pause() and resume()" )
467 if switch
== true then
469 elseif switch
== false then
474 handler
.pause
= function (self
)
475 local tmp
= _readlistlen
476 _readlistlen
= removesocket( _readlist
, socket
, _readlistlen
)
477 _readtimes
[ handler
] = nil
478 if _readlistlen
~= tmp
then
483 handler
.resume
= function (self
)
486 _readlistlen
= addsocket(_readlist
, socket
, _readlistlen
)
487 _readtimes
[ handler
] = _currenttime
491 handler
.lock
= function( self
, switch
)
492 out_error( "server.lua, lock() is deprecated" )
493 handler
.lock_read (self
, switch
)
494 if switch
== true then
495 handler
.pause_writes (self
)
496 elseif switch
== false then
497 handler
.resume_writes (self
)
499 return noread
, nosend
501 handler
.pause_writes
= function (self
)
502 local tmp
= _sendlistlen
503 _sendlistlen
= removesocket( _sendlist
, socket
, _sendlistlen
)
504 _writetimes
[ handler
] = nil
507 handler
.resume_writes
= function (self
)
509 if bufferlen
> 0 then
510 _sendlistlen
= addsocket(_sendlist
, socket
, _sendlistlen
)
514 local _readbuffer
= function( ) -- this function reads data
515 local buffer
, err
, part
= receive( socket
, pattern
) -- receive buffer with "pattern"
516 if not err
or (err
== "wantread" or err
== "timeout") then -- received something
517 local buffer
= buffer
or part
or ""
519 if len
> maxreadlen
then
520 handler
:close( "receive buffer exceeded" )
523 local count
= len
* STAT_UNIT
524 readtraffic
= readtraffic
+ count
525 _readtraffic
= _readtraffic
+ count
526 _readtimes
[ handler
] = _currenttime
527 --out_put( "server.lua: read data '", buffer:gsub("[^%w%p ]", "."), "', error: ", err )
528 return dispatch( handler
, buffer
, err
)
529 else -- connections was closed or fatal error
530 out_put( "server.lua: client ", tostring(ip
), ":", tostring(clientport
), " read error: ", tostring(err
) )
531 _
= handler
and handler
:force_close( err
)
535 local _sendbuffer
= function( ) -- this function sends data
536 local succ
, err
, byte
, buffer
, count
;
538 buffer
= table_concat( bufferqueue
, "", 1, bufferqueuelen
)
539 succ
, err
, byte
= send( socket
, buffer
, 1, bufferlen
)
540 count
= ( succ
or byte
or 0 ) * STAT_UNIT
541 sendtraffic
= sendtraffic
+ count
542 _sendtraffic
= _sendtraffic
+ count
543 for i
= bufferqueuelen
,1,-1 do
544 bufferqueue
[ i
] = nil
546 --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) )
548 succ
, err
, count
= false, "unexpected close", 0;
550 if succ
then -- sending successful
553 _sendlistlen
= removesocket( _sendlist
, socket
, _sendlistlen
) -- delete socket from writelist
554 _writetimes
[ handler
] = nil
558 _
= needtls
and handler
:starttls(nil)
559 _
= toclose
and handler
:force_close( )
561 elseif byte
and ( err
== "timeout" or err
== "wantwrite" ) then -- want write
562 buffer
= string_sub( buffer
, byte
+ 1, bufferlen
) -- new buffer
563 bufferqueue
[ 1 ] = buffer
-- insert new buffer in queue
565 bufferlen
= bufferlen
- byte
566 _writetimes
[ handler
] = _currenttime
568 else -- connection was closed during sending or fatal error
569 out_put( "server.lua: client ", tostring(ip
), ":", tostring(clientport
), " write error: ", tostring(err
) )
570 _
= handler
and handler
:force_close( err
)
577 function handler
.set_sslctx(self
, new_sslctx
)
580 handshake
= coroutine_wrap( function( client
) -- create handshake coroutine
582 for _
= 1, _maxsslhandshake
do
583 _sendlistlen
= ( wrote
and removesocket( _sendlist
, client
, _sendlistlen
) ) or _sendlistlen
584 _readlistlen
= ( read and removesocket( _readlist
, client
, _readlistlen
) ) or _readlistlen
585 read, wrote
= nil, nil
586 _
, err
= client
:dohandshake( )
588 out_put( "server.lua: ssl handshake done" )
589 handler
.readbuffer
= _readbuffer
-- when handshake is done, replace the handshake function with regular functions
590 handler
.sendbuffer
= _sendbuffer
591 _
= status
and status( handler
, "ssl-handshake-complete" )
592 if self
.autostart_ssl
and listeners
.onconnect
then
593 listeners
.onconnect(self
);
594 if bufferqueuelen
~= 0 then
595 _sendlistlen
= addsocket(_sendlist
, client
, _sendlistlen
)
598 _readlistlen
= addsocket(_readlist
, client
, _readlistlen
)
601 if err
== "wantwrite" then
602 _sendlistlen
= addsocket(_sendlist
, client
, _sendlistlen
)
604 elseif err
== "wantread" then
605 _readlistlen
= addsocket(_readlist
, client
, _readlistlen
)
611 coroutine_yield( ) -- handshake not finished
614 err
= "ssl handshake error: " .. ( err
or "handshake too long" );
615 out_put( "server.lua: ", err
);
616 _
= handler
and handler
:force_close(err
)
617 return false, err
-- handshake failed
622 handler
.starttls
= function( self
, _sslctx
)
624 handler
:set_sslctx(_sslctx
);
626 if bufferqueuelen
> 0 then
627 out_put
"server.lua: we need to do tls, but delaying until send buffer empty"
631 out_put( "server.lua: attempting to start tls on " .. tostring( socket
) )
632 local oldsocket
, err
= socket
633 socket
, err
= ssl_wrap( socket
, sslctx
) -- wrap socket
636 out_put( "server.lua: error while starting tls on client: ", tostring(err
or "unknown error") )
637 return nil, err
-- fatal error
641 if self
.servername
then
642 socket
:sni(self
.servername
);
643 elseif self
._server
and type(self
._server
.hosts
) == "table" and next(self
._server
.hosts
) ~= nil then
644 socket
:sni(self
.server().hosts
, true);
648 socket
:settimeout( 0 )
650 -- add the new socket to our system
652 receive
= socket
.receive
654 _socketlist
[ socket
] = handler
655 _readlistlen
= addsocket(_readlist
, socket
, _readlistlen
)
657 -- remove traces of the old socket
658 _readlistlen
= removesocket( _readlist
, oldsocket
, _readlistlen
)
659 _sendlistlen
= removesocket( _sendlist
, oldsocket
, _sendlistlen
)
660 _socketlist
[ oldsocket
] = nil
662 handler
.starttls
= nil
665 -- Secure now (if handshake fails connection will close)
668 handler
.readbuffer
= handshake
669 handler
.sendbuffer
= handshake
670 return handshake( socket
) -- do handshake
674 handler
.readbuffer
= _readbuffer
675 handler
.sendbuffer
= _sendbuffer
677 receive
= socket
.receive
678 shutdown
= ( ssl
and id
) or socket
.shutdown
680 _socketlist
[ socket
] = handler
681 _readlistlen
= addsocket(_readlist
, socket
, _readlistlen
)
683 if sslctx
and ssldirect
and has_luasec
then
684 out_put
"server.lua: auto-starting ssl negotiation..."
685 handler
.autostart_ssl
= true;
686 local ok
, err
= handler
:starttls(sslctx
);
692 return handler
, socket
698 idfalse
= function( )
702 addsocket
= function( list
, socket
, len
)
703 if not list
[ socket
] then
711 removesocket
= function( list
, socket
, len
) -- this function removes sockets from a list ( copied from copas )
712 local pos
= list
[ socket
]
715 local last
= list
[ len
]
717 if last
~= socket
then
726 closesocket
= function( socket
)
727 _sendlistlen
= removesocket( _sendlist
, socket
, _sendlistlen
)
728 _readlistlen
= removesocket( _readlist
, socket
, _readlistlen
)
729 _socketlist
[ socket
] = nil
734 local function link(sender
, receiver
, buffersize
)
736 local _sendbuffer
= receiver
.sendbuffer
;
737 function receiver
.sendbuffer()
739 if sender_locked
and receiver
.bufferlen() < buffersize
then
740 sender
:lock_read(false); -- Unlock now
745 local _readbuffer
= sender
.readbuffer
;
746 function sender
.readbuffer()
748 if not sender_locked
and receiver
.bufferlen() >= buffersize
then
749 sender_locked
= true;
750 sender
:lock_read(true);
753 sender
:set_mode("*a");
756 ----------------------------------// PUBLIC //--
758 listen
= function ( addr
, port
, listeners
, config
)
760 config
= config
or {}
762 local sslctx
= config
.tls_ctx
;
763 local ssldirect
= config
.tls_direct
;
764 local pattern
= config
.read_size
;
765 if type( listeners
) ~= "table" then
766 err
= "invalid listener table"
767 elseif type ( addr
) ~= "string" then
768 err
= "invalid address"
769 elseif type( port
) ~= "number" or not ( port
>= 0 and port
<= 65535 ) then
771 elseif _server
[ addr
..":"..port
] then
772 err
= "listeners on '[" .. addr
.. "]:" .. port
.. "' already exist"
773 elseif sslctx
and not has_luasec
then
774 err
= "luasec not found"
777 out_error( "server.lua, [", addr
, "]:", port
, ": ", err
)
780 local server
, err
= socket_bind( addr
, port
, _tcpbacklog
)
782 out_error( "server.lua, [", addr
, "]:", port
, ": ", err
)
785 local handler
, err
= wrapserver( listeners
, server
, addr
, port
, pattern
, sslctx
, ssldirect
) -- wrap new server socket
790 server
:settimeout( 0 )
791 _readlistlen
= addsocket(_readlist
, server
, _readlistlen
)
792 _server
[ addr
..":"..port
] = handler
793 _socketlist
[ server
] = handler
794 out_put( "server.lua: new "..(sslctx
and "ssl " or "").."server listener on '[", addr
, "]:", port
, "'" )
798 addserver
= function( addr
, port
, listeners
, pattern
, sslctx
) -- this function provides a way for other scripts to reg a server
799 return listen(addr
, port
, listeners
, {
802 tls_direct
= sslctx
and true or false;
806 getserver
= function ( addr
, port
)
807 return _server
[ addr
..":"..port
];
810 removeserver
= function( addr
, port
)
811 local handler
= _server
[ addr
..":"..port
]
813 return nil, "no server found on '[" .. addr
.. "]:" .. tostring( port
) .. "'"
816 _server
[ addr
..":"..port
] = nil
820 closeall
= function( )
821 for _
, handler
in pairs( _socketlist
) do
823 _socketlist
[ _
] = nil
836 getsettings
= function( )
838 select_timeout
= _selecttimeout
;
839 tcp_backlog
= _tcpbacklog
;
840 max_send_buffer_size
= _maxsendlen
;
841 max_receive_buffer_size
= _maxreadlen
;
842 select_idle_check_interval
= _checkinterval
;
843 send_timeout
= _sendtimeout
;
844 read_timeout
= _readtimeout
;
845 max_connections
= _maxselectlen
;
846 max_ssl_handshake_roundtrips
= _maxsslhandshake
;
847 highest_allowed_fd
= _maxfd
;
848 accept_retry_interval
= _accepretry
;
852 changesettings
= function( new
)
853 if type( new
) ~= "table" then
854 return nil, "invalid settings table"
856 _selecttimeout
= tonumber( new
.select_timeout
) or _selecttimeout
857 _maxsendlen
= tonumber( new
.max_send_buffer_size
) or _maxsendlen
858 _maxreadlen
= tonumber( new
.max_receive_buffer_size
) or _maxreadlen
859 _checkinterval
= tonumber( new
.select_idle_check_interval
) or _checkinterval
860 _tcpbacklog
= tonumber( new
.tcp_backlog
) or _tcpbacklog
861 _sendtimeout
= tonumber( new
.send_timeout
) or _sendtimeout
862 _readtimeout
= tonumber( new
.read_timeout
) or _readtimeout
863 _accepretry
= tonumber( new
.accept_retry_interval
) or _accepretry
864 _maxselectlen
= new
.max_connections
or _maxselectlen
865 _maxsslhandshake
= new
.max_ssl_handshake_roundtrips
or _maxsslhandshake
866 _maxfd
= new
.highest_allowed_fd
or _maxfd
870 addtimer
= function( listener
)
871 if type( listener
) ~= "function" then
872 return nil, "invalid listener function"
874 _timerlistlen
= _timerlistlen
+ 1
875 _timerlist
[ _timerlistlen
] = listener
883 function add_task(delay
, callback
)
884 local current_time
= luasocket_gettime();
885 delay
= delay
+ current_time
;
886 if delay
>= current_time
then
887 table_insert(new_data
, {delay
, callback
});
889 local r
= callback(current_time
);
890 if r
and type(r
) == "number" then
891 return add_task(r
, callback
);
896 addtimer(function(current_time
)
897 if #new_data
> 0 then
898 for _
, d
in pairs(new_data
) do
899 table_insert(data
, d
);
904 local next_time
= math_huge
;
905 for i
, d
in pairs(data
) do
906 local t
, callback
= d
[1], d
[2];
907 if t
<= current_time
then
909 local r
= callback(current_time
);
910 if type(r
) == "number" then
911 add_task(r
, callback
);
912 next_time
= math_min(next_time
, r
);
915 next_time
= math_min(next_time
, t
- current_time
);
923 return _readtraffic
, _sendtraffic
, _readlistlen
, _sendlistlen
, _timerlistlen
928 local function setquitting(quit
)
932 loop
= function(once
) -- this is the main loop of the program
933 if quitting
then return "quitting"; end
934 if once
then quitting
= "once"; end
935 _currenttime
= luasocket_gettime( )
938 local next_timer_time
= math_huge
;
939 for i
= 1, _timerlistlen
do
940 local t
= _timerlist
[ i
]( _currenttime
) -- fire timers
941 if t
then next_timer_time
= math_min(next_timer_time
, t
); end
944 local read, write, err
= socket_select( _readlist
, _sendlist
, math_min(_selecttimeout
, next_timer_time
) )
945 for _
, socket
in ipairs( read ) do -- receive data
946 local handler
= _socketlist
[ socket
]
948 handler
.readbuffer( )
950 closesocket( socket
)
951 out_put
"server.lua: found no handler and closed socket (readlist)" -- this can happen
954 for _
, socket
in ipairs( write ) do -- send data waiting in writequeues
955 local handler
= _socketlist
[ socket
]
957 handler
.sendbuffer( )
959 closesocket( socket
)
960 out_put
"server.lua: found no handler and closed socket (writelist)" -- this should not happen
963 for handler
, err
in pairs( _closelist
) do
964 handler
.disconnect( )( handler
, err
)
965 handler
:force_close() -- forced disconnect
966 _closelist
[ handler
] = nil;
968 _currenttime
= luasocket_gettime( )
970 -- Check for socket timeouts
971 if _currenttime
- _starttime
> _checkinterval
then
972 _starttime
= _currenttime
973 for handler
, timestamp
in pairs( _writetimes
) do
974 if _currenttime
- timestamp
> _sendtimeout
then
975 handler
.disconnect( )( handler
, "send timeout" )
976 handler
:force_close() -- forced disconnect
979 for handler
, timestamp
in pairs( _readtimes
) do
980 if _currenttime
- timestamp
> _readtimeout
then
981 if not(handler
.onreadtimeout
) or handler
:onreadtimeout() ~= true then
982 handler
.disconnect( )( handler
, "read timeout" )
983 handler
:close( ) -- forced disconnect?
985 _readtimes
[ handler
] = _currenttime
-- reset timer
991 for server
, paused_time
in pairs( _fullservers
) do
992 if _currenttime
- paused_time
> _accepretry
then
993 _fullservers
[ server
] = nil;
998 if quitting
== "once" then quitting
= nil; return; end
1003 local function step()
1007 local function get_backend()
1011 --// EXPERIMENTAL //--
1013 local wrapclient
= function( socket
, ip
, serverport
, listeners
, pattern
, sslctx
, extra
)
1014 local handler
, socket
, err
= wrapconnection( nil, listeners
, socket
, ip
, serverport
, "clientport", pattern
, sslctx
, sslctx
, extra
)
1015 if not handler
then return nil, err
end
1016 _socketlist
[ socket
] = handler
1018 _readlistlen
= addsocket(_readlist
, socket
, _readlistlen
)
1019 _sendlistlen
= addsocket(_sendlist
, socket
, _sendlistlen
)
1020 if listeners
.onconnect
then
1021 -- When socket is writeable, call onconnect
1022 local _sendbuffer
= handler
.sendbuffer
;
1023 handler
.sendbuffer
= function ()
1024 handler
.sendbuffer
= _sendbuffer
;
1025 listeners
.onconnect(handler
);
1026 return _sendbuffer(); -- Send any queued outgoing data
1030 return handler
, socket
1033 local addclient
= function( address
, port
, listeners
, pattern
, sslctx
, typ
, extra
)
1035 if type( listeners
) ~= "table" then
1036 err
= "invalid listener table"
1037 elseif type ( address
) ~= "string" then
1038 err
= "invalid address"
1039 elseif type( port
) ~= "number" or not ( port
>= 0 and port
<= 65535 ) then
1040 err
= "invalid port"
1041 elseif sslctx
and not has_luasec
then
1042 err
= "luasec not found"
1045 local n
= inet_pton(address
);
1046 if not n
then return nil, "invalid-ip"; end
1053 local create
= luasocket
[typ
];
1054 if type( create
) ~= "function" then
1055 err
= "invalid socket type"
1059 out_error( "server.lua, addclient: ", err
)
1063 local client
, err
= create( )
1067 client
:settimeout( 0 )
1068 local ok
, err
= client
:setpeername( address
, port
)
1069 if ok
or err
== "timeout" or err
== "Operation already in progress" then
1070 return wrapclient( client
, address
, port
, listeners
, pattern
, sslctx
, extra
)
1076 local closewatcher
= function (handler
)
1077 local socket
= handler
.conn
;
1078 _sendlistlen
= removesocket( _sendlist
, socket
, _sendlistlen
)
1079 _readlistlen
= removesocket( _readlist
, socket
, _readlistlen
)
1080 _socketlist
[ socket
] = nil
1083 local addremove
= function (handler
, read, send
)
1084 local socket
= handler
.conn
1085 _socketlist
[ socket
] = handler
1088 _readlistlen
= addsocket( _readlist
, socket
, _readlistlen
)
1090 _sendlistlen
= removesocket( _sendlist
, socket
, _sendlistlen
)
1095 _sendlistlen
= addsocket( _sendlist
, socket
, _sendlistlen
)
1097 _readlistlen
= removesocket( _readlist
, socket
, _readlistlen
)
1102 local watchfd
= function ( fd
, onreadable
, onwriteable
)
1104 if type(fd
) == "number" then
1105 socket
= { getfd
= function () return fd
; end }
1109 readbuffer
= onreadable
or id
;
1110 sendbuffer
= onwriteable
or id
;
1111 close
= closewatcher
;
1112 setflags
= addremove
;
1114 addremove( handler
, onreadable
, onwriteable
)
1118 ----------------------------------// BEGIN //--
1120 use
"setmetatable" ( _socketlist
, { __mode
= "k" } )
1121 use
"setmetatable" ( _readtimes
, { __mode
= "k" } )
1122 use
"setmetatable" ( _writetimes
, { __mode
= "k" } )
1124 _starttime
= luasocket_gettime( )
1126 local function setlogger(new_logger
)
1127 local old_logger
= log;
1134 ----------------------------------// PUBLIC INTERFACE //--
1137 _addtimer
= addtimer
,
1138 add_task
= add_task
;
1140 addclient
= addclient
,
1141 wrapclient
= wrapclient
,
1148 closeall
= closeall
,
1149 addserver
= addserver
,
1151 getserver
= getserver
,
1152 setlogger
= setlogger
,
1153 getsettings
= getsettings
,
1154 setquitting
= setquitting
,
1155 removeserver
= removeserver
,
1156 get_backend
= get_backend
,
1157 changesettings
= changesettings
,