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