4 server.lua based on lua/libevent by blastbeat
7 -- when using luaevent, never register 2 or more EV_READ at one socket, same for EV_WRITE
8 -- you can't even register a new EV_READ/EV_WRITE callback inside another one
9 -- to do some of the above, use timeout events or something what will called from outside
10 -- don't let garbagecollect eventcallbacks, as long they are running
11 -- when using luasec, there are 4 cases of timeout errors: wantread or wantwrite during reading or writing
14 -- luacheck: ignore 212/self 431/err 211/ret
16 local SCRIPT_NAME
= "server_event.lua"
17 local SCRIPT_VERSION
= "0.05"
18 local SCRIPT_AUTHOR
= "blastbeat"
19 local LAST_MODIFIED
= "2009/11/20"
22 MAX_CONNECTIONS
= 100000, -- max per server connections (use "ulimit -n" on *nix)
23 MAX_HANDSHAKE_ATTEMPTS
= 1000, -- attempts to finish ssl handshake
24 HANDSHAKE_TIMEOUT
= 60, -- timeout in seconds per handshake attempt
25 MAX_READ_LENGTH
= 1024 * 1024 * 1024 * 1024, -- max bytes allowed to read from sockets
26 MAX_SEND_LENGTH
= 1024 * 1024 * 1024 * 1024, -- max bytes size of write buffer (for writing on sockets)
27 ACCEPT_QUEUE
= 128, -- might influence the length of the pending sockets queue
28 ACCEPT_DELAY
= 10, -- seconds to wait until the next attempt of a full server to accept
29 READ_TIMEOUT
= 14 * 60, -- timeout in seconds for read data from socket
30 WRITE_TIMEOUT
= 180, -- timeout in seconds for write data on socket
31 CONNECT_TIMEOUT
= 20, -- timeout in seconds for connection attempts
32 CLEAR_DELAY
= 5, -- seconds to wait for clearing interface list (and calling ondisconnect listeners)
33 READ_RETRY_DELAY
= 1e-06, -- if, after reading, there is still data in buffer, wait this long and continue reading
34 DEBUG
= true, -- show debug messages
39 local require
= require
40 local tostring = tostring
41 local setmetatable
= setmetatable
43 local t_insert
= table.insert
44 local t_concat
= table.concat
45 local s_sub
= string.sub
47 local coroutine_wrap
= coroutine
.wrap
48 local coroutine_yield
= coroutine
.yield
50 local has_luasec
, ssl
= pcall ( require
, "ssl" )
51 local socket
= require
"socket"
52 local levent
= require
"luaevent.core"
53 local inet
= require
"util.net";
54 local inet_pton
= inet
.pton
;
56 local socket_gettime
= socket
.gettime
58 local log = require ("util.logger").init("socket")
60 local function debug(...)
61 return log("debug", ("%s "):rep(select('#', ...)), ...)
63 -- local vdebug = debug;
65 local bitor
= ( function( ) -- thx Rici Lake
66 local hasbit
= function( x
, p
)
67 return x
% ( p
+ p
) >= p
69 return function( x
, y
)
72 local limit
= x
> y
and x
or y
74 if hasbit( x
, p
) or hasbit( y
, p
) then
83 local base
= levent
.new( )
84 local addevent
= base
.addevent
85 local EV_READ
= levent
.EV_READ
86 local EV_WRITE
= levent
.EV_WRITE
87 local EV_TIMEOUT
= levent
.EV_TIMEOUT
88 local EV_SIGNAL
= levent
.EV_SIGNAL
90 local EV_READWRITE
= bitor( EV_READ
, EV_WRITE
)
92 local interfacelist
= { }
94 -- Client interface methods
95 local interface_mt
= {}; interface_mt
.__index
= interface_mt
;
98 function interface_mt
:_close()
99 return self
:_destroy();
102 function interface_mt
:_start_connection(plainssl
) -- called from wrapclient
103 local callback
= function( event
)
104 if EV_TIMEOUT
== event
then -- timeout during connection
105 self
.fatalerror
= "connection timeout"
106 self
:ontimeout() -- call timeout listener
108 debug( "new connection failed. id:", self
.id
, "error:", self
.fatalerror
)
110 if EV_READWRITE
== event
then
111 if self
.readcallback(event
) == -1 then
112 -- Fatal error occurred
116 if plainssl
and has_luasec
then -- start ssl session
117 self
:starttls(self
._sslctx
, true)
118 else -- normal connection
119 self
:_start_session(true)
121 debug( "new connection established. id:", self
.id
)
123 self
.eventconnect
= nil
126 self
.eventconnect
= addevent( base
, self
.conn
, EV_READWRITE
, callback
, cfg
.CONNECT_TIMEOUT
)
129 function interface_mt
:_start_session(call_onconnect
) -- new session, for example after startssl
130 if self
.type == "client" then
131 local callback
= function( )
132 self
:_lock( false, false, false )
133 --vdebug( "start listening on client socket with id:", self.id )
134 self
.eventread
= addevent( base
, self
.conn
, EV_READ
, self
.readcallback
, cfg
.READ_TIMEOUT
); -- register callback
135 if call_onconnect
then
138 self
.eventsession
= nil
141 self
.eventsession
= addevent( base
, nil, EV_TIMEOUT
, callback
, 0 )
144 --vdebug( "start listening on server socket with id:", self.id )
145 self
.eventread
= addevent( base
, self
.conn
, EV_READ
, self
.readcallback
) -- register callback
149 function interface_mt
:_start_ssl(call_onconnect
) -- old socket will be destroyed, therefore we have to close read/write events first
150 --vdebug( "starting ssl session with client id:", self.id )
152 _
= self
.eventread
and self
.eventread
:close( ) -- close events; this must be called outside of the event callbacks!
153 _
= self
.eventwrite
and self
.eventwrite
:close( )
154 self
.eventread
, self
.eventwrite
= nil, nil
156 self
.conn
, err
= ssl
.wrap( self
.conn
, self
._sslctx
)
158 self
.fatalerror
= err
159 self
.conn
= nil -- cannot be used anymore
160 if call_onconnect
then
161 self
.ondisconnect
= nil -- don't call this when client isn't really connected
164 debug( "fatal error while ssl wrapping:", err
)
168 if self
.conn
.sni
then
169 if self
.servername
then
170 self
.conn
:sni(self
.servername
);
171 elseif self
._server
and type(self
._server
.hosts
) == "table" and next(self
._server
.hosts
) ~= nil then
172 self
.conn
:sni(self
._server
.hosts
, true);
176 self
.conn
:settimeout( 0 ) -- set non blocking
177 local handshakecallback
= coroutine_wrap(function( event
)
180 local maxattempt
= cfg
.MAX_HANDSHAKE_ATTEMPTS
181 while attempt
< maxattempt
do -- no endless loop
182 attempt
= attempt
+ 1
183 debug( "ssl handshake of client with id:"..tostring(self
)..", attempt:"..attempt
)
184 if attempt
> maxattempt
then
185 self
.fatalerror
= "max handshake attempts exceeded"
186 elseif EV_TIMEOUT
== event
then
187 self
.fatalerror
= "timeout during handshake"
189 _
, err
= self
.conn
:dohandshake( )
191 self
:_lock( false, false, false ) -- unlock the interface; sending, closing etc allowed
192 self
.send
= self
.conn
.send
-- caching table lookups with new client object
193 self
.receive
= self
.conn
.receive
194 if not call_onconnect
then -- trigger listener
195 self
:onstatus("ssl-handshake-complete");
197 self
:_start_session( call_onconnect
)
198 debug( "ssl handshake done" )
199 self
.eventhandshake
= nil
202 if err
== "wantwrite" then
204 elseif err
== "wantread" then
207 debug( "ssl handshake error:", err
)
208 self
.fatalerror
= err
211 if self
.fatalerror
then
212 if call_onconnect
then
213 self
.ondisconnect
= nil -- don't call this when client isn't really connected
216 debug( "handshake failed because:", self
.fatalerror
)
217 self
.eventhandshake
= nil
220 event
= coroutine_yield( event
, cfg
.HANDSHAKE_TIMEOUT
) -- yield this monster...
224 debug
"starting handshake..."
225 self
:_lock( false, true, true ) -- unlock read/write events, but keep interface locked
226 self
.eventhandshake
= addevent( base
, self
.conn
, EV_READWRITE
, handshakecallback
, cfg
.HANDSHAKE_TIMEOUT
)
229 function interface_mt
:_destroy() -- close this interface + events and call last listener
230 debug( "closing client with id:", self
.id
, self
.fatalerror
)
231 self
:_lock( true, true, true ) -- first of all, lock the interface to avoid further actions
233 _
= self
.eventread
and self
.eventread
:close( )
234 if self
.type == "client" then
235 _
= self
.eventwrite
and self
.eventwrite
:close( )
236 _
= self
.eventhandshake
and self
.eventhandshake
:close( )
237 _
= self
.eventstarthandshake
and self
.eventstarthandshake
:close( )
238 _
= self
.eventconnect
and self
.eventconnect
:close( )
239 _
= self
.eventsession
and self
.eventsession
:close( )
240 _
= self
.eventwritetimeout
and self
.eventwritetimeout
:close( )
241 _
= self
.eventreadtimeout
and self
.eventreadtimeout
:close( )
242 -- call ondisconnect listener (won't be the case if handshake failed on connect)
243 _
= self
.ondisconnect
and self
:ondisconnect( self
.fatalerror
~= "client to close" and self
.fatalerror
)
244 _
= self
.conn
and self
.conn
:close( ) -- close connection
245 _
= self
._server
and self
._server
:counter(-1);
246 self
.eventread
, self
.eventwrite
= nil, nil
247 self
.eventstarthandshake
, self
.eventhandshake
, self
.eventclose
= nil, nil, nil
248 self
.readcallback
, self
.writecallback
= nil, nil
251 self
.eventread
, self
.eventclose
= nil, nil
252 self
.interface
, self
.readcallback
= nil, nil
254 interfacelist
[ self
] = nil
258 function interface_mt
:_lock(nointerface
, noreading
, nowriting
) -- lock or unlock this interface or events
259 self
.nointerface
, self
.noreading
, self
.nowriting
= nointerface
, noreading
, nowriting
260 return nointerface
, noreading
, nowriting
264 function interface_mt
:lock_read(switch
)
265 log("warn", ":lock_read is deprecated, use :pasue() and :resume()");
269 return self
:resume();
273 function interface_mt
:pause()
274 return self
:_lock(self
.nointerface
, true, self
.nowriting
);
277 function interface_mt
:resume()
278 self
:_lock(self
.nointerface
, false, self
.nowriting
);
279 if self
.readcallback
and not self
.eventread
then
280 self
.eventread
= addevent( base
, self
.conn
, EV_READ
, self
.readcallback
, cfg
.READ_TIMEOUT
); -- register callback
285 function interface_mt
:pause_writes()
286 return self
:_lock(self
.nointerface
, self
.noreading
, true);
289 function interface_mt
:resume_writes()
290 self
:_lock(self
.nointerface
, self
.noreading
, false);
291 if self
.writecallback
and not self
.eventwrite
then
292 self
.eventwrite
= addevent( base
, self
.conn
, EV_WRITE
, self
.writecallback
, cfg
.WRITE_TIMEOUT
); -- register callback
298 function interface_mt
:counter(c
)
300 self
._connections
= self
._connections
+ c
302 return self
._connections
306 function interface_mt
:write(data
)
307 if self
.nointerface
then return nil, "locked"; end
308 --vdebug( "try to send data to client, id/data:", self.id, data )
309 data
= tostring( data
)
311 local total
= len
+ self
.writebufferlen
312 if total
> cfg
.MAX_SEND_LENGTH
then -- check buffer length
313 local err
= "send buffer exceeded"
314 debug( "error:", err
) -- to much, check your app
317 t_insert(self
.writebuffer
, data
) -- new buffer
318 self
.writebufferlen
= total
319 if not self
.eventwrite
and not self
.nowriting
then -- register new write event
320 --vdebug( "register new write event" )
321 self
.eventwrite
= addevent( base
, self
.conn
, EV_WRITE
, self
.writecallback
, cfg
.WRITE_TIMEOUT
)
325 function interface_mt
:close()
326 if self
.nointerface
then return nil, "locked"; end
327 debug( "try to close client connection with id:", self
.id
)
328 if self
.type == "client" then
329 self
.fatalerror
= "client to close"
330 if self
.eventwrite
then -- wait for incomplete write request
331 self
:_lock( true, true, false )
332 debug
"closing delayed until writebuffer is empty"
333 return nil, "writebuffer not empty, waiting"
335 self
:_lock( true, true, true )
340 debug( "try to close server with id:", tostring(self
.id
))
341 self
.fatalerror
= "server to close"
348 function interface_mt
:socket()
352 function interface_mt
:server()
353 return self
._server
or self
;
356 function interface_mt
:port()
360 function interface_mt
:serverport()
361 return self
._serverport
364 function interface_mt
:ip()
368 function interface_mt
:ssl()
369 return self
._usingssl
371 interface_mt
.clientport
= interface_mt
.port
-- COMPAT server_select
373 function interface_mt
:type()
374 return self
._type
or "client"
377 function interface_mt
:connections()
378 return self
._connections
381 function interface_mt
:address()
385 function interface_mt
:set_sslctx(sslctx
)
386 self
._sslctx
= sslctx
;
388 self
.starttls
= nil; -- use starttls() of interface_mt
390 self
.starttls
= false; -- prevent starttls()
394 function interface_mt
:set_mode(pattern
)
396 self
._pattern
= pattern
;
398 return self
._pattern
;
401 function interface_mt
:set_send(new_send
) -- luacheck: ignore 212
402 -- No-op, we always use the underlying connection's send
405 function interface_mt
:starttls(sslctx
, call_onconnect
)
406 debug( "try to start ssl at client id:", self
.id
)
408 self
._sslctx
= sslctx
;
409 if self
._usingssl
then -- startssl was already called
410 err
= "ssl already active"
413 debug( "error:", err
)
416 self
._usingssl
= true
417 self
.startsslcallback
= function( ) -- we have to start the handshake outside of a read/write event
418 self
.startsslcallback
= nil
419 self
:_start_ssl(call_onconnect
);
420 self
.eventstarthandshake
= nil
423 if not self
.eventwrite
then
424 self
:_lock( true, true, true ) -- lock the interface, to not disturb the handshake
425 self
.eventstarthandshake
= addevent( base
, nil, EV_TIMEOUT
, self
.startsslcallback
, 0 ) -- add event to start handshake
427 -- wait until writebuffer is empty
428 self
:_lock( true, true, false )
429 debug
"ssl session delayed until writebuffer is empty..."
431 self
.starttls
= false;
435 function interface_mt
:setoption(option
, value
)
436 if self
.conn
.setoption
then
437 return self
.conn
:setoption(option
, value
);
439 return false, "setoption not implemented";
442 function interface_mt
:setlistener(listener
, data
)
443 self
:ondetach(); -- Notify listener that it is no longer responsible for this connection
444 self
.onconnect
= listener
.onconnect
;
445 self
.ondisconnect
= listener
.ondisconnect
;
446 self
.onincoming
= listener
.onincoming
;
447 self
.ontimeout
= listener
.ontimeout
;
448 self
.onreadtimeout
= listener
.onreadtimeout
;
449 self
.onstatus
= listener
.onstatus
;
450 self
.ondetach
= listener
.ondetach
;
451 self
.onattach
= listener
.onattach
;
452 self
.ondrain
= listener
.ondrain
;
457 function interface_mt
:onconnect()
459 function interface_mt
:onincoming()
461 function interface_mt
:ondisconnect()
463 function interface_mt
:ontimeout()
465 function interface_mt
:onreadtimeout()
466 self
.fatalerror
= "timeout during receiving"
467 debug( "connection failed:", self
.fatalerror
)
471 function interface_mt
:ondrain()
473 function interface_mt
:ondetach()
475 function interface_mt
:onattach()
477 function interface_mt
:onstatus()
480 -- End of client interface methods
482 local function handleclient( client
, ip
, port
, server
, pattern
, listener
, sslctx
, extra
) -- creates an client interface
483 --vdebug("creating client interfacce...")
487 currenttime
= socket_gettime( ); -- safe the origin
488 writebuffer
= {}; -- writebuffer
489 writebufferlen
= 0; -- length of writebuffer
490 send
= client
.send
; -- caching table lookups
491 receive
= client
.receive
;
492 onconnect
= listener
.onconnect
; -- will be called when client disconnects
493 ondisconnect
= listener
.ondisconnect
; -- will be called when client disconnects
494 onincoming
= listener
.onincoming
; -- will be called when client sends data
495 ontimeout
= listener
.ontimeout
; -- called when fatal socket timeout occurs
496 onreadtimeout
= listener
.onreadtimeout
; -- called when socket inactivity timeout occurs
497 ondrain
= listener
.ondrain
; -- called when writebuffer is empty
498 ondetach
= listener
.ondetach
; -- called when disassociating this listener from this connection
499 onstatus
= listener
.onstatus
; -- called for status changes (e.g. of SSL/TLS)
500 eventread
= false, eventwrite
= false, eventclose
= false,
501 eventhandshake
= false, eventstarthandshake
= false; -- event handler
502 eventconnect
= false, eventsession
= false; -- more event handler...
503 eventwritetimeout
= false; -- even more event handler...
504 eventreadtimeout
= false;
505 fatalerror
= false; -- error message
506 writecallback
= false; -- will be called on write events
507 readcallback
= false; -- will be called on read events
508 nointerface
= true; -- lock/unlock parameter of this interface
509 noreading
= false, nowriting
= false; -- locks of the read/writecallback
510 startsslcallback
= false; -- starting handshake callback
511 position
= false; -- position of client in interfacelist
514 _ip
= ip
, _port
= port
, _server
= server
, _pattern
= pattern
,
515 _serverport
= (server
and server
:port() or nil),
516 _sslctx
= sslctx
; -- parameters
517 _usingssl
= false; -- client is using ssl;
519 servername
= extra
and extra
.servername
;
521 if not has_luasec
then interface
.starttls
= false; end
522 interface
.id
= tostring(interface
):match("%x+$");
523 interface
.writecallback
= function( event
) -- called on write events
524 --vdebug( "new client write event, id/ip/port:", interface, ip, port )
525 if interface
.nowriting
or ( interface
.fatalerror
and ( "client to close" ~= interface
.fatalerror
) ) then -- leave this event
526 --vdebug( "leaving this event because:", interface.nowriting or interface.fatalerror )
527 interface
.eventwrite
= false
530 if EV_TIMEOUT
== event
then -- took too long to write some data to socket -> disconnect
531 interface
.fatalerror
= "timeout during writing"
532 debug( "writing failed:", interface
.fatalerror
)
534 interface
.eventwrite
= false
537 if interface
._usingssl
then -- handle luasec
538 if interface
.eventreadtimeout
then -- we have to read first
539 local ret
= interface
.readcallback( ) -- call readcallback
540 --vdebug( "tried to read in writecallback, result:", ret )
542 if interface
.eventwritetimeout
then -- luasec only
543 interface
.eventwritetimeout
:close( ) -- first we have to close timeout event which where regged after a wantread error
544 interface
.eventwritetimeout
= false
547 interface
.writebuffer
= { t_concat(interface
.writebuffer
) }
548 local succ
, err
, byte
= interface
.conn
:send( interface
.writebuffer
[1], 1, interface
.writebufferlen
)
549 --vdebug( "write data:", interface.writebuffer, "error:", err, "part:", byte )
550 if succ
then -- writing successful
551 interface
.writebuffer
[1] = nil
552 interface
.writebufferlen
= 0
554 if interface
.fatalerror
then
555 debug
"closing client after writing"
556 interface
:_close() -- close interface if needed
557 elseif interface
.startsslcallback
then -- start ssl connection if needed
558 debug
"starting ssl handshake after writing"
559 interface
.eventstarthandshake
= addevent( base
, nil, EV_TIMEOUT
, interface
.startsslcallback
, 0 )
560 elseif interface
.writebufferlen
~= 0 then
561 -- data possibly written from ondrain
562 return EV_WRITE
, cfg
.WRITE_TIMEOUT
563 elseif interface
.eventreadtimeout
then
564 return EV_WRITE
, cfg
.WRITE_TIMEOUT
566 interface
.eventwrite
= nil
568 elseif byte
and (err
== "timeout" or err
== "wantwrite") then -- want write again
569 --vdebug( "writebuffer is not empty:", err )
570 interface
.writebuffer
[1] = s_sub( interface
.writebuffer
[1], byte
+ 1, interface
.writebufferlen
) -- new buffer
571 interface
.writebufferlen
= interface
.writebufferlen
- byte
572 if "wantread" == err
then -- happens only with luasec
573 local callback
= function( )
575 interface
.eventwritetimeout
= nil
578 interface
.eventwritetimeout
= addevent( base
, nil, EV_TIMEOUT
, callback
, cfg
.WRITE_TIMEOUT
) -- reg a new timeout event
579 debug( "wantread during write attempt, reg it in readcallback but don't know what really happens next..." )
580 -- hopefully this works with luasec; its simply not possible to use 2 different write events on a socket in luaevent
583 return EV_WRITE
, cfg
.WRITE_TIMEOUT
584 else -- connection was closed during writing or fatal error
585 interface
.fatalerror
= err
or "fatal error"
586 debug( "connection failed in write event:", interface
.fatalerror
)
588 interface
.eventwrite
= nil
594 interface
.readcallback
= function( event
) -- called on read events
595 --vdebug( "new client read event, id/ip/port:", tostring(interface.id), tostring(ip), tostring(port) )
596 if interface
.noreading
or interface
.fatalerror
then -- leave this event
597 --vdebug( "leaving this event because:", tostring(interface.noreading or interface.fatalerror) )
598 interface
.eventread
= nil
601 if EV_TIMEOUT
== event
and not interface
.conn
:dirty() and interface
:onreadtimeout() ~= true then
602 interface
.fatalerror
= "timeout during receiving"
603 debug( "connection failed:", interface
.fatalerror
)
605 interface
.eventread
= nil
606 return -1 -- took too long to get some data from client -> disconnect
608 if interface
._usingssl
then -- handle luasec
609 if interface
.eventwritetimeout
then -- ok, in the past writecallback was regged
610 local ret
= interface
.writecallback( ) -- call it
611 --vdebug( "tried to write in readcallback, result:", tostring(ret) )
613 if interface
.eventreadtimeout
then
614 interface
.eventreadtimeout
:close( )
615 interface
.eventreadtimeout
= nil
618 local buffer
, err
, part
= interface
.conn
:receive( interface
._pattern
) -- receive buffer with "pattern"
619 --vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
620 buffer
= buffer
or part
621 if buffer
and #buffer
> cfg
.MAX_READ_LENGTH
then -- check buffer length
622 interface
.fatalerror
= "receive buffer exceeded"
623 debug( "fatal error:", interface
.fatalerror
)
625 interface
.eventread
= nil
628 if err
and ( err
~= "timeout" and err
~= "wantread" ) then
629 if "wantwrite" == err
then -- need to read on write event
630 if not interface
.eventwrite
then -- register new write event if needed
631 interface
.eventwrite
= addevent( base
, interface
.conn
, EV_WRITE
, interface
.writecallback
, cfg
.WRITE_TIMEOUT
)
633 interface
.eventreadtimeout
= addevent( base
, nil, EV_TIMEOUT
,
634 function( ) interface
:_close() end, cfg
.READ_TIMEOUT
)
635 debug( "wantwrite during read attempt, reg it in writecallback but don't know what really happens next..." )
636 -- to be honest i don't know what happens next, if it is allowed to first read, the write etc...
637 else -- connection was closed or fatal error
638 interface
.fatalerror
= err
639 debug( "connection failed in read event:", interface
.fatalerror
)
641 interface
.eventread
= nil
645 interface
.onincoming( interface
, buffer
, err
) -- send new data to listener
647 if interface
.noreading
then
648 interface
.eventread
= nil;
651 if interface
.conn
:dirty() then -- still data left in buffer
652 return EV_TIMEOUT
, cfg
.READ_RETRY_DELAY
;
654 return EV_READ
, cfg
.READ_TIMEOUT
657 client
:settimeout( 0 ) -- set non blocking
658 setmetatable(interface
, interface_mt
)
659 interfacelist
[ interface
] = true -- add to interfacelist
663 local function handleserver( server
, addr
, port
, pattern
, listener
, sslctx
, startssl
) -- creates a server interface
664 debug
"creating server interface..."
670 onconnect
= listener
.onconnect
; -- will be called when new client connected
671 eventread
= false; -- read event handler
672 eventclose
= false; -- close event handler
673 readcallback
= false; -- read event callback
674 fatalerror
= false; -- error message
675 nointerface
= true; -- lock/unlock parameter
677 _ip
= addr
, _port
= port
, _pattern
= pattern
,
681 interface
.id
= tostring(interface
):match("%x+$");
682 interface
.readcallback
= function( event
) -- server handler, called on incoming connections
683 --vdebug( "server can accept, id/addr/port:", interface, addr, port )
684 if interface
.fatalerror
then
685 --vdebug( "leaving this event because:", self.fatalerror )
686 interface
.eventread
= nil
689 local delay
= cfg
.ACCEPT_DELAY
690 if EV_TIMEOUT
== event
then
691 if interface
._connections
>= cfg
.MAX_CONNECTIONS
then -- check connection count
692 debug( "to many connections, seconds to wait for next accept:", delay
)
693 return EV_TIMEOUT
, delay
-- timeout...
695 return EV_READ
-- accept again
698 --vdebug("max connection check ok, accepting...")
699 local client
, err
= server
:accept() -- try to accept; TODO: check err
701 if interface
._connections
>= cfg
.MAX_CONNECTIONS
then
702 client
:close( ) -- refuse connection
703 debug( "maximal connections reached, refuse client connection; accept delay:", delay
)
704 return EV_TIMEOUT
, delay
-- delay for next accept attempt
706 local client_ip
, client_port
= client
:getpeername( )
707 interface
._connections
= interface
._connections
+ 1 -- increase connection count
708 local clientinterface
= handleclient( client
, client_ip
, client_port
, interface
, pattern
, listener
, sslctx
)
709 --vdebug( "client id:", clientinterface, "startssl:", startssl )
710 if has_luasec
and startssl
then
711 clientinterface
:starttls(sslctx
, true)
713 clientinterface
:_start_session( true )
715 debug( "accepted incoming client connection from:", client_ip
or "<unknown IP>", client_port
or "<unknown port>", "to", port
or "<unknown port>");
717 client
, err
= server
:accept() -- try to accept again
722 server
:settimeout( 0 )
723 setmetatable(interface
, interface_mt
)
724 interfacelist
[ interface
] = true
725 interface
:_start_session()
729 local function listen(addr
, port
, listener
, config
)
730 config
= config
or {}
731 if config
.sslctx
and not has_luasec
then
732 debug
"fatal error: luasec not found"
733 return nil, "luasec not found"
735 local server
, err
= socket
.bind( addr
, port
, cfg
.ACCEPT_QUEUE
) -- create server socket
737 debug( "creating server socket on "..addr
.." port "..port
.." failed:", err
)
740 local interface
= handleserver( server
, addr
, port
, config
.read_size
, listener
, config
.tls_ctx
, config
.tls_direct
) -- new server handler
741 debug( "new server created with id:", tostring(interface
))
745 local function addserver( addr
, port
, listener
, pattern
, sslctx
) -- TODO: check arguments
746 --vdebug( "creating new tcp server with following parameters:", addr or "nil", port or "nil", sslctx or "nil", startssl or "nil")
747 return listen( addr
, port
, listener
, {
750 tls_direct
= not not sslctx
,
754 local function wrapclient( client
, ip
, port
, listeners
, pattern
, sslctx
, extra
)
755 local interface
= handleclient( client
, ip
, port
, nil, pattern
, listeners
, sslctx
, extra
)
756 interface
:_start_connection(sslctx
)
757 return interface
, client
758 --function handleclient( client, ip, port, server, pattern, listener, _, sslctx ) -- creates an client interface
761 local function addclient( addr
, serverport
, listener
, pattern
, sslctx
, typ
, extra
)
762 if sslctx
and not has_luasec
then
763 debug
"need luasec, but not available"
764 return nil, "luasec not found"
767 local n
= inet_pton(addr
);
768 if not n
then return nil, "invalid-ip"; end
775 local create
= socket
[typ
];
776 if type( create
) ~= "function" then
777 return nil, "invalid socket type"
779 local client
, err
= create() -- creating new socket
781 debug( "cannot create socket:", err
)
784 client
:settimeout( 0 ) -- set nonblocking
785 local res
, err
= client
:setpeername( addr
, serverport
) -- connect
786 if res
or ( err
== "timeout" ) then
787 local ip
, port
= client
:getsockname( )
788 local interface
= wrapclient( client
, ip
, serverport
, listener
, pattern
, sslctx
, extra
)
789 debug( "new connection id:", interface
.id
)
790 return interface
, err
792 debug( "new connection failed:", err
)
797 local function loop( ) -- starts the event loop
802 local function newevent( ... )
803 return addevent( base
, ... )
806 local function closeallservers ( arg
)
807 for item
in pairs( interfacelist
) do
808 if item
.type == "server" then
814 local function setquitting(yes
)
817 if yes
~= "once" then
824 local function get_backend()
825 return "libevent " .. base
:method();
828 -- We need to hold onto the events to stop them
829 -- being garbage-collected
830 local signal_events
= {}; -- [signal_num] -> event object
831 local function hook_signal(signal_num
, handler
)
832 local function _handler()
833 local ret
= handler();
834 if ret
~= false then -- Continue handling this signal?
835 return EV_SIGNAL
; -- Yes
837 return -1; -- Close this event
839 signal_events
[signal_num
] = base
:addevent(signal_num
, EV_SIGNAL
, _handler
);
840 return signal_events
[signal_num
];
843 local function link(sender
, receiver
, buffersize
)
846 function receiver
:ondrain()
847 if sender_locked
then
853 function sender
:onincoming(data
)
854 receiver
:write(data
);
855 if receiver
.writebufferlen
>= buffersize
then
856 sender_locked
= true;
860 sender
:set_mode("*a");
863 local function add_task(delay
, callback
)
865 event_handle
= base
:addevent(nil, 0, function ()
866 local ret
= callback(socket_gettime());
869 elseif event_handle
then
877 local function watchfd(fd
, onreadable
, onwriteable
)
879 function handle
:setflags(r
,w
)
881 if r
and not self
.wantread
then
882 self
.wantread
= base
:addevent(fd
, EV_READ
, function ()
885 elseif not r
and self
.wantread
then
886 self
.wantread
:close();
891 if w
and not self
.wantwrite
then
892 self
.wantwrite
= base
:addevent(fd
, EV_WRITE
, function ()
895 elseif not r
and self
.wantread
then
896 self
.wantwrite
:close();
897 self
.wantwrite
= nil;
901 handle
:setflags(onreadable
, onwriteable
);
913 addserver
= addserver
,
915 addclient
= addclient
,
916 wrapclient
= wrapclient
,
917 setquitting
= setquitting
,
918 closeall
= closeallservers
,
919 get_backend
= get_backend
,
920 hook_signal
= hook_signal
,
924 __NAME
= SCRIPT_NAME
,
925 __DATE
= LAST_MODIFIED
,
926 __AUTHOR
= SCRIPT_AUTHOR
,
927 __VERSION
= SCRIPT_VERSION
,