412d03c050b949205e3992fb4d59f798261982bc
[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, 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                         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                 handler.readbuffer = _readbuffer
600                 handler.sendbuffer = _sendbuffer
601                 
602                 if sslctx then
603                         out_put "server.lua: auto-starting ssl negotiation..."
604                         handler.autostart_ssl = true;
605                         handler:starttls(sslctx);
606                 end
607
608         else
609                 handler.readbuffer = _readbuffer
610                 handler.sendbuffer = _sendbuffer
611         end
612         send = socket.send
613         receive = socket.receive
614         shutdown = ( ssl and id ) or socket.shutdown
615
616         _socketlist[ socket ] = handler
617         _readlistlen = addsocket(_readlist, socket, _readlistlen)
618         return handler, socket
619 end
620
621 id = function( )
622 end
623
624 idfalse = function( )
625         return false
626 end
627
628 addsocket = function( list, socket, len )
629         if not list[ socket ] then
630                 len = len + 1
631                 list[ len ] = socket
632                 list[ socket ] = len
633         end
634         return len;
635 end
636
637 removesocket = function( list, socket, len )    -- this function removes sockets from a list ( copied from copas )
638         local pos = list[ socket ]
639         if pos then
640                 list[ socket ] = nil
641                 local last = list[ len ]
642                 list[ len ] = nil
643                 if last ~= socket then
644                         list[ last ] = pos
645                         list[ pos ] = last
646                 end
647                 return len - 1
648         end
649         return len
650 end
651
652 closesocket = function( socket )
653         _sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
654         _readlistlen = removesocket( _readlist, socket, _readlistlen )
655         _socketlist[ socket ] = nil
656         socket:close( )
657         --mem_free( )
658 end
659
660 local function link(sender, receiver, buffersize)
661         local sender_locked;
662         local _sendbuffer = receiver.sendbuffer;
663         function receiver.sendbuffer()
664                 _sendbuffer();
665                 if sender_locked and receiver.bufferlen() < buffersize then
666                         sender:lock_read(false); -- Unlock now
667                         sender_locked = nil;
668                 end
669         end
670         
671         local _readbuffer = sender.readbuffer;
672         function sender.readbuffer()
673                 _readbuffer();
674                 if not sender_locked and receiver.bufferlen() >= buffersize then
675                         sender_locked = true;
676                         sender:lock_read(true);
677                 end
678         end
679 end
680
681 ----------------------------------// PUBLIC //--
682
683 addserver = function( addr, port, listeners, pattern, sslctx ) -- this function provides a way for other scripts to reg a server
684         local err
685         if type( listeners ) ~= "table" then
686                 err = "invalid listener table"
687         end
688         if type( port ) ~= "number" or not ( port >= 0 and port <= 65535 ) then
689                 err = "invalid port"
690         elseif _server[ addr..":"..port ] then
691                 err = "listeners on '[" .. addr .. "]:" .. port .. "' already exist"
692         elseif sslctx and not luasec then
693                 err = "luasec not found"
694         end
695         if err then
696                 out_error( "server.lua, [", addr, "]:", port, ": ", err )
697                 return nil, err
698         end
699         addr = addr or "*"
700         local server, err = socket_bind( addr, port )
701         if err then
702                 out_error( "server.lua, [", addr, "]:", port, ": ", err )
703                 return nil, err
704         end
705         local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, _maxclientsperserver ) -- wrap new server socket
706         if not handler then
707                 server:close( )
708                 return nil, err
709         end
710         server:settimeout( 0 )
711         _readlistlen = addsocket(_readlist, server, _readlistlen)
712         _server[ addr..":"..port ] = handler
713         _socketlist[ server ] = handler
714         out_put( "server.lua: new "..(sslctx and "ssl " or "").."server listener on '[", addr, "]:", port, "'" )
715         return handler
716 end
717
718 getserver = function ( addr, port )
719         return _server[ addr..":"..port ];
720 end
721
722 removeserver = function( addr, port )
723         local handler = _server[ addr..":"..port ]
724         if not handler then
725                 return nil, "no server found on '[" .. addr .. "]:" .. tostring( port ) .. "'"
726         end
727         handler:close( )
728         _server[ addr..":"..port ] = nil
729         return true
730 end
731
732 closeall = function( )
733         for _, handler in pairs( _socketlist ) do
734                 handler:close( )
735                 _socketlist[ _ ] = nil
736         end
737         _readlistlen = 0
738         _sendlistlen = 0
739         _timerlistlen = 0
740         _server = { }
741         _readlist = { }
742         _sendlist = { }
743         _timerlist = { }
744         _socketlist = { }
745         --mem_free( )
746 end
747
748 getsettings = function( )
749         return  _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver, _maxsslhandshake
750 end
751
752 changesettings = function( new )
753         if type( new ) ~= "table" then
754                 return nil, "invalid settings table"
755         end
756         _selecttimeout = tonumber( new.timeout ) or _selecttimeout
757         _sleeptime = tonumber( new.sleeptime ) or _sleeptime
758         _maxsendlen = tonumber( new.maxsendlen ) or _maxsendlen
759         _maxreadlen = tonumber( new.maxreadlen ) or _maxreadlen
760         _checkinterval = tonumber( new.checkinterval ) or _checkinterval
761         _sendtimeout = tonumber( new.sendtimeout ) or _sendtimeout
762         _readtimeout = tonumber( new.readtimeout ) or _readtimeout
763         _cleanqueue = new.cleanqueue
764         _maxclientsperserver = new._maxclientsperserver or _maxclientsperserver
765         _maxsslhandshake = new._maxsslhandshake or _maxsslhandshake
766         return true
767 end
768
769 addtimer = function( listener )
770         if type( listener ) ~= "function" then
771                 return nil, "invalid listener function"
772         end
773         _timerlistlen = _timerlistlen + 1
774         _timerlist[ _timerlistlen ] = listener
775         return true
776 end
777
778 stats = function( )
779         return _readtraffic, _sendtraffic, _readlistlen, _sendlistlen, _timerlistlen
780 end
781
782 local quitting;
783
784 local function setquitting(quit)
785         quitting = not not quit;
786 end
787
788 loop = function(once) -- this is the main loop of the program
789         if quitting then return "quitting"; end
790         if once then quitting = "once"; end
791         local next_timer_time = math_huge;
792         repeat
793                 local read, write, err = socket_select( _readlist, _sendlist, math_min(_selecttimeout, next_timer_time) )
794                 for i, socket in ipairs( write ) do -- send data waiting in writequeues
795                         local handler = _socketlist[ socket ]
796                         if handler then
797                                 handler.sendbuffer( )
798                         else
799                                 closesocket( socket )
800                                 out_put "server.lua: found no handler and closed socket (writelist)"    -- this should not happen
801                         end
802                 end
803                 for i, socket in ipairs( read ) do -- receive data
804                         local handler = _socketlist[ socket ]
805                         if handler then
806                                 handler.readbuffer( )
807                         else
808                                 closesocket( socket )
809                                 out_put "server.lua: found no handler and closed socket (readlist)" -- this can happen
810                         end
811                 end
812                 for handler, err in pairs( _closelist ) do
813                         handler.disconnect( )( handler, err )
814                         handler:close( true )    -- forced disconnect
815                 end
816                 clean( _closelist )
817                 _currenttime = luasocket_gettime( )
818                 if _currenttime - _timer >= math_min(next_timer_time, 1) then
819                         next_timer_time = math_huge;
820                         for i = 1, _timerlistlen do
821                                 local t = _timerlist[ i ]( _currenttime ) -- fire timers
822                                 if t then next_timer_time = math_min(next_timer_time, t); end
823                         end
824                         _timer = _currenttime
825                 else
826                         next_timer_time = next_timer_time - (_currenttime - _timer);
827                 end
828                 socket_sleep( _sleeptime ) -- wait some time
829                 --collectgarbage( )
830         until quitting;
831         if once and quitting == "once" then quitting = nil; return; end
832         return "quitting"
833 end
834
835 local function step()
836         return loop(true);
837 end
838
839 local function get_backend()
840         return "select";
841 end
842
843 --// EXPERIMENTAL //--
844
845 local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx )
846         local handler = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx )
847         _socketlist[ socket ] = handler
848         if not sslctx then
849                 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen)
850                 if listeners.onconnect then
851                         -- When socket is writeable, call onconnect
852                         local _sendbuffer = handler.sendbuffer;
853                         handler.sendbuffer = function ()
854                                 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen );
855                                 handler.sendbuffer = _sendbuffer;
856                                 listeners.onconnect(handler);
857                                 -- If there was data with the incoming packet, handle it now.
858                                 if #handler:bufferqueue() > 0 then
859                                         return _sendbuffer();
860                                 end
861                         end
862                 end
863         end
864         return handler, socket
865 end
866
867 local addclient = function( address, port, listeners, pattern, sslctx )
868         local client, err = luasocket.tcp( )
869         if err then
870                 return nil, err
871         end
872         client:settimeout( 0 )
873         _, err = client:connect( address, port )
874         if err then -- try again
875                 local handler = wrapclient( client, address, port, listeners )
876         else
877                 wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx )
878         end
879 end
880
881 --// EXPERIMENTAL //--
882
883 ----------------------------------// BEGIN //--
884
885 use "setmetatable" ( _socketlist, { __mode = "k" } )
886 use "setmetatable" ( _readtimes, { __mode = "k" } )
887 use "setmetatable" ( _writetimes, { __mode = "k" } )
888
889 _timer = luasocket_gettime( )
890 _starttime = luasocket_gettime( )
891
892 addtimer( function( )
893                 local difftime = os_difftime( _currenttime - _starttime )
894                 if difftime > _checkinterval then
895                         _starttime = _currenttime
896                         for handler, timestamp in pairs( _writetimes ) do
897                                 if os_difftime( _currenttime - timestamp ) > _sendtimeout then
898                                         --_writetimes[ handler ] = nil
899                                         handler.disconnect( )( handler, "send timeout" )
900                                         handler:close( true )    -- forced disconnect
901                                 end
902                         end
903                         for handler, timestamp in pairs( _readtimes ) do
904                                 if os_difftime( _currenttime - timestamp ) > _readtimeout then
905                                         --_readtimes[ handler ] = nil
906                                         handler.disconnect( )( handler, "read timeout" )
907                                         handler:close( )        -- forced disconnect?
908                                 end
909                         end
910                 end
911         end
912 )
913
914 local function setlogger(new_logger)
915         local old_logger = log;
916         if new_logger then
917                 log = new_logger;
918         end
919         return old_logger;
920 end
921
922 ----------------------------------// PUBLIC INTERFACE //--
923
924 return {
925
926         addclient = addclient,
927         wrapclient = wrapclient,
928         
929         loop = loop,
930         link = link,
931         step = step,
932         stats = stats,
933         closeall = closeall,
934         addtimer = addtimer,
935         addserver = addserver,
936         getserver = getserver,
937         setlogger = setlogger,
938         getsettings = getsettings,
939         setquitting = setquitting,
940         removeserver = removeserver,
941         get_backend = get_backend,
942         changesettings = changesettings,
943 }