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