4e5ec366c11cf901268d851dd101645707e0a606
[prosody.git] / net / server.lua
1 --[[
2
3                 server.lua by blastbeat of the luadch project
4                 
5                 re-used here under the MIT/X Consortium License
6                 
7                 Modifications (C) 2008 Matthew Wild, Waqas Hussain
8 ]]--
9
10 ----------------------------------// DECLARATION //--
11
12 --// constants //--
13
14 local STAT_UNIT = 1 / ( 1024 * 1024 )    -- mb
15
16 --// lua functions //--
17
18 local function use( what ) return _G[ what ] end
19
20 local type = use "type"
21 local pairs = use "pairs"
22 local ipairs = use "ipairs"
23 local tostring = use "tostring"
24 local collectgarbage = use "collectgarbage"
25
26 --// lua libs //--
27
28 local table = use "table"
29 local coroutine = use "coroutine"
30
31 --// lua lib methods //--
32
33 local table_concat = table.concat
34 local table_remove = table.remove
35 local string_sub = use'string'.sub
36 local coroutine_wrap = coroutine.wrap
37 local coroutine_yield = coroutine.yield
38 local print = print;
39 local out_put = function () end --print;
40 local out_error = print;
41
42 --// extern libs //--
43
44 local luasec = select(2, pcall(require, "ssl"))
45 local luasocket = require "socket"
46
47 --// extern lib methods //--
48
49 local ssl_wrap = ( luasec and luasec.wrap )
50 local socket_bind = luasocket.bind
51 local socket_select = luasocket.select
52 local ssl_newcontext = ( luasec and luasec.newcontext )
53
54 --// functions //--
55
56 local loop
57 local stats
58 local addtimer
59 local closeall
60 local addserver
61 local firetimer
62 local closesocket
63 local removesocket
64 local wrapserver
65 local wraptcpclient
66 local wrapsslclient
67
68 --// tables //--
69
70 local listener
71 local readlist
72 local writelist
73 local socketlist
74 local timelistener
75
76 --// simple data types //--
77
78 local _
79 local readlen = 0    -- length of readlist
80 local writelen = 0    -- lenght of writelist
81
82 local sendstat= 0
83 local receivestat = 0
84
85 ----------------------------------// DEFINITION //--
86
87 listener = { }    -- key = port, value = table
88 readlist = { }    -- array with sockets to read from
89 writelist = { }    -- arrary with sockets to write to
90 socketlist = { }    -- key = socket, value = wrapped socket
91 timelistener = { }
92
93 stats = function( )
94         return receivestat, sendstat
95 end
96
97 wrapserver = function( listener, socket, ip, serverport, mode, sslctx )    -- this function wraps a server
98
99         local dispatch, disconnect = listener.listener, listener.disconnect    -- dangerous
100
101         local wrapclient, err
102
103         if sslctx then
104                 if not ssl_newcontext then
105                         return nil, "luasec not found"
106                 end
107                 if type( sslctx ) ~= "table" then
108                         out_error "server.lua: wrong server sslctx"
109                         return nil, "wrong server sslctx"
110                 end
111                 sslctx, err = ssl_newcontext( sslctx )
112                 if not sslctx then
113                         err = err or "wrong sslctx parameters"
114                         out_error( "server.lua: ", err )
115                         return nil, err
116                 end
117                 wrapclient = wrapsslclient
118                 wrapclient = wraptlsclient
119         else
120                 wrapclient = wraptcpclient
121         end
122
123         local accept = socket.accept
124         local close = socket.close
125
126         --// public methods of the object //--    
127
128         local handler = { }
129
130         handler.shutdown = function( ) end
131
132         --[[handler.listener = function( data, err )
133                 return ondata( handler, data, err )
134         end]]
135         handler.ssl = function( )
136                 return sslctx and true or false
137         end
138         handler.close = function( closed )
139                 _ = not closed and close( socket )
140                 writelen = removesocket( writelist, socket, writelen )
141                 readlen = removesocket( readlist, socket, readlen )
142                 socketlist[ socket ] = nil
143                 handler = nil
144         end
145         handler.ip = function( )
146                 return ip
147         end
148         handler.serverport = function( )
149                 return serverport
150         end
151         handler.socket = function( )
152                 return socket
153         end
154         handler.receivedata = function( )
155                 local client, err = accept( socket )    -- try to accept
156                 if client then
157                         local ip, clientport = client:getpeername( )
158                         client:settimeout( 0 )
159                         local handler, client, err = wrapclient( listener, client, ip, serverport, clientport, mode, sslctx )    -- wrap new client socket
160                         if err then    -- error while wrapping ssl socket
161                                 return false
162                         end
163                         out_put( "server.lua: accepted new client connection from ", ip, ":", clientport )
164                         return dispatch( handler )
165                 elseif err then    -- maybe timeout or something else
166                         out_put( "server.lua: error with new client connection: ", err )
167                         return false
168                 end
169         end
170         return handler
171 end
172
173 wrapsslclient = function( listener, socket, ip, serverport, clientport, mode, sslctx )    -- this function wraps a ssl cleint
174
175         local dispatch, disconnect = listener.listener, listener.disconnect
176
177         --// transform socket to ssl object //--
178
179         local err
180         socket, err = ssl_wrap( socket, sslctx )    -- wrap socket
181         if err then
182                 out_put( "server.lua: ssl error: ", err )
183                 return nil, nil, err    -- fatal error
184         end
185         socket:settimeout( 0 )
186
187         --// private closures of the object //--
188
189         local writequeue = { }    -- buffer for messages to send
190
191         local eol, fatal_send_error   -- end of buffer
192
193         local sstat, rstat = 0, 0
194
195         --// local import of socket methods //--
196
197         local send = socket.send
198         local receive = socket.receive
199         local close = socket.close
200         --local shutdown = socket.shutdown
201
202         --// public methods of the object //--
203
204         local handler = { }
205
206         handler.getstats = function( )
207                 return rstat, sstat
208         end
209
210         handler.listener = function( data, err )
211                 return listener( handler, data, err )
212         end
213         handler.ssl = function( )
214                 return true
215         end
216         handler.send = function( _, data, i, j )
217                         return send( socket, data, i, j )
218         end
219         handler.receive = function( pattern, prefix )
220                         return receive( socket, pattern, prefix )
221         end
222         handler.shutdown = function( pattern )
223                 --return shutdown( socket, pattern )
224         end
225         handler.close = function( closed )
226                 if eol and not fatal_send_error then handler._dispatchdata(); end
227                 close( socket )
228                 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen
229                 readlen = removesocket( readlist, socket, readlen )
230                 socketlist[ socket ] = nil
231                 out_put "server.lua: closed handler and removed socket from list"
232         end
233         handler.ip = function( )
234                 return ip
235         end
236         handler.serverport = function( )
237                 return serverport
238         end
239         handler.clientport = function( ) 
240                 return clientport
241         end
242
243         handler.write = function( data )
244                 if not eol then
245                         writelen = writelen + 1
246                         writelist[ writelen ] = socket
247                         eol = 0
248                 end
249                 eol = eol + 1
250                 writequeue[ eol ] = data
251         end
252         handler.writequeue = function( )
253                 return writequeue
254         end
255         handler.socket = function( )
256                 return socket
257         end
258         handler.mode = function( )
259                 return mode
260         end
261         handler._receivedata = function( )
262                 local data, err, part = receive( socket, mode )    -- receive data in "mode"
263                 if not err or ( err == "timeout" or err == "wantread" ) then    -- received something
264                         local data = data or part or ""
265                         local count = #data * STAT_UNIT
266                         rstat = rstat + count
267                         receivestat = receivestat + count
268                         --out_put( "server.lua: read data '", data, "', error: ", err )
269                         return dispatch( handler, data, err )
270                 else    -- connections was closed or fatal error
271                         out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
272                         handler.close( )
273                         disconnect( handler, err )
274                         writequeue = nil
275                         handler = nil
276                         return false
277                 end
278         end
279         handler._dispatchdata = function( )    -- this function writes data to handlers
280                 local buffer = table_concat( writequeue, "", 1, eol )
281                 local succ, err, byte = send( socket, buffer )
282                 local count = ( succ or 0 ) * STAT_UNIT
283                 sstat = sstat + count
284                 sendstat = sendstat + count
285                 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport )
286                 if succ then    -- sending succesful
287                         --writequeue = { }
288                         eol = nil
289                         writelen = removesocket( writelist, socket, writelen )    -- delete socket from writelist
290                         return true
291                 elseif byte and ( err == "timeout" or err == "wantwrite" ) then    -- want write
292                         buffer = string_sub( buffer, byte + 1, -1 )    -- new buffer
293                         writequeue[ 1 ] = buffer    -- insert new buffer in queue
294                         eol = 1
295                         return true
296                 else    -- connection was closed during sending or fatal error
297                         fatal_send_error = true;
298                         out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
299                         handler.close( )
300                         disconnect( handler, err )
301                         writequeue = nil
302                         handler = nil
303                         return false
304                 end
305         end
306
307         -- // COMPAT // --
308
309         handler.getIp = handler.ip
310         handler.getPort = handler.clientport
311
312         --// handshake //--
313
314         local wrote
315
316         handler.handshake = coroutine_wrap( function( client )
317                         local err
318                         for i = 1, 10 do    -- 10 handshake attemps
319                                 _, err = client:dohandshake( )
320                                 if not err then
321                                         out_put( "server.lua: ssl handshake done" )
322                                         writelen = ( wrote and removesocket( writelist, socket, writelen ) ) or writelen
323                                         handler.receivedata = handler._receivedata    -- when handshake is done, replace the handshake function with regular functions
324                                         handler.dispatchdata = handler._dispatchdata
325                                         return dispatch( handler )
326                                 else
327                                         out_put( "server.lua: error during ssl handshake: ", err )
328                                         if err == "wantwrite" then
329                                                 if wrote == nil then
330                                                         writelen = writelen + 1
331                                                         writelist[ writelen ] = client
332                                                         wrote = true
333                                                 end
334                                         end
335                                         coroutine_yield( handler, nil, err )    -- handshake not finished
336                                 end
337                         end
338                         _ = err ~= "closed" and close( socket )
339                         handler.close( )
340                         disconnect( handler, err )
341                         writequeue = nil
342                         handler = nil
343                         return false    -- handshake failed
344                 end
345         )
346         handler.receivedata = handler.handshake
347         handler.dispatchdata = handler.handshake
348
349         handler.handshake( socket )    -- do handshake
350
351         socketlist[ socket ] = handler
352         readlen = readlen + 1
353         readlist[ readlen ] = socket
354
355         return handler, socket
356 end
357
358 wraptlsclient = function( listener, socket, ip, serverport, clientport, mode, sslctx )    -- this function wraps a tls cleint
359
360         local dispatch, disconnect = listener.listener, listener.disconnect
361
362         --// transform socket to ssl object //--
363
364         local err
365
366         socket:settimeout( 0 )
367         --// private closures of the object //--
368
369         local writequeue = { }    -- buffer for messages to send
370
371         local eol, fatal_send_error   -- end of buffer
372
373         local sstat, rstat = 0, 0
374
375         --// local import of socket methods //--
376
377         local send = socket.send
378         local receive = socket.receive
379         local close = socket.close
380         --local shutdown = socket.shutdown
381
382         --// public methods of the object //--
383
384         local handler = { }
385
386         handler.getstats = function( )
387                 return rstat, sstat
388         end
389
390         handler.listener = function( data, err )
391                 return listener( handler, data, err )
392         end
393         handler.ssl = function( )
394                 return false
395         end
396         handler.send = function( _, data, i, j )
397                         return send( socket, data, i, j )
398         end
399         handler.receive = function( pattern, prefix )
400                         return receive( socket, pattern, prefix )
401         end
402         handler.shutdown = function( pattern )
403                 --return shutdown( socket, pattern )
404         end
405         handler.close = function( closed )
406                 if eol and not fatal_send_error then handler._dispatchdata(); end
407                 close( socket )
408                 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen
409                 readlen = removesocket( readlist, socket, readlen )
410                 socketlist[ socket ] = nil
411                 out_put "server.lua: closed handler and removed socket from list"
412         end
413         handler.ip = function( )
414                 return ip
415         end
416         handler.serverport = function( )
417                 return serverport
418         end
419         handler.clientport = function( ) 
420                 return clientport
421         end
422
423         handler.write = function( data )
424                 if not eol then
425                         writelen = writelen + 1
426                         writelist[ writelen ] = socket
427                         eol = 0
428                 end
429                 eol = eol + 1
430                 writequeue[ eol ] = data
431         end
432         handler.writequeue = function( )
433                 return writequeue
434         end
435         handler.socket = function( )
436                 return socket
437         end
438         handler.mode = function( )
439                 return mode
440         end
441         handler._receivedata = function( )
442                 local data, err, part = receive( socket, mode )    -- receive data in "mode"
443                 if not err or ( err == "timeout" or err == "wantread" ) then    -- received something
444                         local data = data or part or ""
445                         local count = #data * STAT_UNIT
446                         rstat = rstat + count
447                         receivestat = receivestat + count
448                         --out_put( "server.lua: read data '", data, "', error: ", err )
449                         return dispatch( handler, data, err )
450                 else    -- connections was closed or fatal error
451                         out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
452                         handler.close( )
453                         disconnect( handler, err )
454                         writequeue = nil
455                         handler = nil
456                         return false
457                 end
458         end
459         handler._dispatchdata = function( )    -- this function writes data to handlers
460                 local buffer = table_concat( writequeue, "", 1, eol )
461                 local succ, err, byte = send( socket, buffer )
462                 local count = ( succ or 0 ) * STAT_UNIT
463                 sstat = sstat + count
464                 sendstat = sendstat + count
465                 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport )
466                 if succ then    -- sending succesful
467                         --writequeue = { }
468                         eol = nil
469                         writelen = removesocket( writelist, socket, writelen )    -- delete socket from writelist
470                         if handler.need_tls then
471                                 out_put("server.lua: connection is ready for tls handshake");
472                                 handler.starttls(true);
473                         end
474                         return true
475                 elseif byte and ( err == "timeout" or err == "wantwrite" ) then    -- want write
476                         buffer = string_sub( buffer, byte + 1, -1 )    -- new buffer
477                         writequeue[ 1 ] = buffer    -- insert new buffer in queue
478                         eol = 1
479                         return true
480                 else    -- connection was closed during sending or fatal error
481                         fatal_send_error = true; -- :(
482                         out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
483                         handler.close( )
484                         disconnect( handler, err )
485                         writequeue = nil
486                         handler = nil
487                         return false
488                 end
489         end
490
491         handler.receivedata, handler.dispatchdata = handler._receivedata, handler._dispatchdata;
492         -- // COMPAT // --
493
494         handler.getIp = handler.ip
495         handler.getPort = handler.clientport
496
497         --// handshake //--
498
499         local wrote, read
500         
501         handler.starttls = function (now)
502                 if not now then out_put("server.lua: we need to do tls, but delaying until later"); handler.need_tls = true; return; end
503                 out_put( "server.lua: attempting to start tls on "..tostring(socket) )
504                 local oldsocket = socket;
505                 socket, err = ssl_wrap( socket, sslctx )    -- wrap socket
506                 out_put("sslwrapped socket is "..tostring(socket));
507                 if err then
508                         out_put( "server.lua: ssl error: ", err )
509                         return nil, nil, err    -- fatal error
510                 end
511                 socket:settimeout(0);
512                 
513                 -- Add the new socket to our system
514                 socketlist[ socket ] = handler
515                 readlen = readlen + 1
516                 readlist[ readlen ] = socket
517                 
518                 -- Remove traces of the old socket
519                 readlen = removesocket( readlist, oldsocket, readlen )
520                 socketlist [ oldsocket ] = nil;
521                 
522                 send = socket.send
523                 receive = socket.receive
524                 close = socket.close
525                 handler.ssl = function( )
526                         return true
527                 end
528                 handler.send = function( _, data, i, j )
529                         return send( socket, data, i, j )
530                 end
531                 handler.receive = function( pattern, prefix )
532                         return receive( socket, pattern, prefix )
533                 end
534                 
535                 handler.starttls = nil;
536                 handler.need_tls = nil
537                 
538                         handler.handshake = coroutine_wrap( function( client )
539                                         local err
540                                         for i = 1, 10 do    -- 10 handshake attemps
541                                                 _, err = client:dohandshake( )
542                                                 if not err then
543                                                         out_put( "server.lua: ssl handshake done" )
544                                                         writelen = ( wrote and removesocket( writelist, socket, writelen ) ) or writelen
545                                                         handler.receivedata = handler._receivedata    -- when handshake is done, replace the handshake function with regular functions
546                                                         handler.dispatchdata = handler._dispatchdata;
547                                                         return true;
548                                                 else
549                                                         out_put( "server.lua: error during ssl handshake: ", err )
550                                                         if err == "wantwrite" then
551                                                                 if wrote == nil then
552                                                                         writelen = writelen + 1
553                                                                         writelist[ writelen ] = client
554                                                                         wrote = true
555                                                                 end
556                                                         end
557                                                         coroutine_yield( handler, nil, err )    -- handshake not finished
558                                                 end
559                                         end
560                                         _ = err ~= "closed" and close( socket )
561                                         handler.close( )
562                                         disconnect( handler, err )
563                                         writequeue = nil
564                                         handler = nil
565                                         return false    -- handshake failed
566                                 end
567                         )
568                         handler.receivedata = handler.handshake
569                         handler.dispatchdata = handler.handshake
570                         
571                         handler.handshake( socket )    -- do handshake
572                 end
573         socketlist[ socket ] = handler
574         readlen = readlen + 1
575         readlist[ readlen ] = socket
576
577         return handler, socket
578 end
579
580 wraptcpclient = function( listener, socket, ip, serverport, clientport, mode )    -- this function wraps a socket
581
582         local dispatch, disconnect = listener.listener, listener.disconnect
583
584         --// private closures of the object //--
585
586         local writequeue = { }    -- list for messages to send
587
588         local eol, fatal_send_error
589
590         socket:settimeout(0);
591         
592         local rstat, sstat = 0, 0
593
594         --// local import of socket methods //--
595
596         local send = socket.send
597         local receive = socket.receive
598         local close = socket.close
599         local shutdown = socket.shutdown
600
601         --// public methods of the object //--
602
603         local handler = { }
604
605         handler.getstats = function( )
606                 return rstat, sstat
607         end
608
609         handler.listener = function( data, err )
610                 return listener( handler, data, err )
611         end
612         handler.ssl = function( )
613                 return false
614         end
615         handler.send = function( _, data, i, j )
616                         return send( socket, data, i, j )
617         end
618         handler.receive = function( pattern, prefix )
619                         return receive( socket, pattern, prefix )
620         end
621         handler.shutdown = function( pattern )
622                 return shutdown( socket, pattern )
623         end
624         handler.close = function( closed )
625                 if eol and not fatal_send_error then handler.dispatchdata(); end
626                 _ = not closed and shutdown( socket )
627                 _ = not closed and close( socket )
628                 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen
629                 readlen = removesocket( readlist, socket, readlen )
630                 socketlist[ socket ] = nil
631                 out_put "server.lua: closed handler and removed socket from list"
632         end
633         handler.ip = function( )
634                 return ip
635         end
636         handler.serverport = function( )
637                 return serverport
638         end
639         handler.clientport = function( ) 
640                 return clientport
641         end
642         handler.write = function( data )
643                 if not eol then
644                         writelen = writelen + 1
645                         writelist[ writelen ] = socket
646                         eol = 0
647                 end
648                 eol = eol + 1
649                 writequeue[ eol ] = data
650         end
651         handler.writequeue = function( )
652                 return writequeue
653         end
654         handler.socket = function( )
655                 return socket
656         end
657         handler.mode = function( )
658                 return mode
659         end
660         
661         handler.receivedata = function( )
662                 local data, err, part = receive( socket, mode )    -- receive data in "mode"
663                 if not err or ( err == "timeout" or err == "wantread" ) then    -- received something
664                         local data = data or part or ""
665                         local count = #data * STAT_UNIT
666                         rstat = rstat + count
667                         receivestat = receivestat + count
668                         --out_put( "server.lua: read data '", data, "', error: ", err )
669                         return dispatch( handler, data, err )
670                 else    -- connections was closed or fatal error
671                         out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
672                         handler.close( )
673                         disconnect( handler, err )
674                         writequeue = nil
675                         handler = nil
676                         return false
677                 end
678         end
679         
680         handler.dispatchdata = function( )    -- this function writes data to handlers
681                 local buffer = table_concat( writequeue, "", 1, eol )
682                 local succ, err, byte = send( socket, buffer )
683                 local count = ( succ or 0 ) * STAT_UNIT
684                 sstat = sstat + count
685                 sendstat = sendstat + count
686                 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport )
687                 if succ then    -- sending succesful
688                         --writequeue = { }
689                         eol = nil
690                         writelen = removesocket( writelist, socket, writelen )    -- delete socket from writelist
691                         return true
692                 elseif byte and ( err == "timeout" or err == "wantwrite" ) then    -- want write
693                         buffer = string_sub( buffer, byte + 1, -1 )    -- new buffer
694                         writequeue[ 1 ] = buffer    -- insert new buffer in queue
695                         eol = 1
696                         return true
697                 else    -- connection was closed during sending or fatal error
698                         fatal_send_error = true; -- :'-(
699                         out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
700                         handler.close( )
701                         disconnect( handler, err )
702                         writequeue = nil
703                         handler = nil
704                         return false
705                 end
706         end
707
708         -- // COMPAT // --
709
710         handler.getIp = handler.ip
711         handler.getPort = handler.clientport
712
713         socketlist[ socket ] = handler
714         readlen = readlen + 1
715         readlist[ readlen ] = socket
716
717         return handler, socket
718 end
719
720 addtimer = function( listener )
721         timelistener[ #timelistener + 1 ] = listener
722 end
723
724 firetimer = function( listener )
725         for i, listener in ipairs( timelistener ) do
726                 listener( )
727         end
728 end
729
730 addserver = function( listeners, port, addr, mode, sslctx )    -- this function provides a way for other scripts to reg a server
731         local err
732         if type( listeners ) ~= "table" then
733                 err = "invalid listener table"
734         else
735                 for name, func in pairs( listeners ) do
736                         if type( func ) ~= "function" then
737                                 --err = "invalid listener function"
738                                 break
739                         end
740                 end
741         end
742         if not type( port ) == "number" or not ( port >= 0 and port <= 65535 ) then
743                 err = "invalid port"
744         elseif listener[ port ] then
745                 err=  "listeners on port '" .. port .. "' already exist"
746         elseif sslctx and not luasec then
747                 err = "luasec not found"
748         end
749         if err then
750                 out_error( "server.lua: ", err )
751                 return nil, err
752         end
753         addr = addr or "*"
754         local server, err = socket_bind( addr, port )
755         if err then
756                 out_error( "server.lua: ", err )
757                 return nil, err
758         end
759         local handler, err = wrapserver( listeners, server, addr, port, mode, sslctx )    -- wrap new server socket
760         if not handler then
761                 server:close( )
762                 return nil, err
763         end
764         server:settimeout( 0 )
765         readlen = readlen + 1
766         readlist[ readlen ] = server
767         listener[ port ] = listeners
768         socketlist[ server ] = handler
769         out_put( "server.lua: new server listener on ", addr, ":", port )
770         return true
771 end
772
773 removesocket = function( tbl, socket, len )    -- this function removes sockets from a list
774         for i, target in ipairs( tbl ) do
775                 if target == socket then
776                         len = len - 1
777                         table_remove( tbl, i )
778                         return len
779                 end
780         end
781         return len
782 end
783
784 closeall = function( )
785         for sock, handler in pairs( socketlist ) do
786                 handler.shutdown( )
787                 handler.close( )
788                 socketlist[ sock ] = nil
789         end
790         writelist, readlist, socketlist = { }, { }, { }
791 end
792
793 closesocket = function( socket )
794         writelen = removesocket( writelist, socket, writelen )
795         readlen = removesocket( readlist, socket, readlen )
796         socketlist[ socket ] = nil
797         socket:close( )
798 end
799
800 loop = function( )    -- this is the main loop of the program
801         --signal_set( "hub", "run" )
802         repeat
803                 local read, write, err = socket_select( readlist, writelist, 1 )    -- 1 sec timeout, nice for timers
804                 for i, socket in ipairs( write ) do    -- send data waiting in writequeues
805                         local handler = socketlist[ socket ]
806                         if handler then
807                                 handler.dispatchdata( )
808                         else
809                                 closesocket( socket )
810                                 out_put "server.lua: found no handler and closed socket (writelist)"    -- this should not happen
811                         end
812                 end
813                 for i, socket in ipairs( read ) do    -- receive data
814                         local handler = socketlist[ socket ]
815                         if handler then
816                                 handler.receivedata( )
817                         else
818                                 closesocket( socket )
819                                 out_put "server.lua: found no handler and closed socket (readlist)"    -- this can happen
820                         end
821                 end
822                 firetimer( )
823         until false
824         return
825 end
826
827 ----------------------------------// BEGIN //--
828
829 ----------------------------------// PUBLIC INTERFACE //--
830
831 return {
832
833         add = addserver,
834         loop = loop,
835         stats = stats,
836         closeall = closeall,
837         addtimer = addtimer,
838         wraptcpclient = wraptcpclient,
839         wraptlsclient = wraptlsclient,
840 }