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