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