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