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