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