net/server.lua

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

mercurial