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