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