X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=net%2Fserver_event.lua;h=43e70a0f7f135a0e1e7d4eb9915ad5ca7f18df2b;hb=9adde78703cd85056a59b5e4fe005d40428226dc;hp=3afc732ba1705aa19a9dd295187fa262f9ee3731;hpb=0704417ee5d698a465192984a851cbcd5b98e8c4;p=prosody.git diff --git a/net/server_event.lua b/net/server_event.lua index 3afc732b..43e70a0f 100644 --- a/net/server_event.lua +++ b/net/server_event.lua @@ -20,14 +20,14 @@ local LAST_MODIFIED = "2009/11/20" local cfg = { MAX_CONNECTIONS = 100000, -- max per server connections (use "ulimit -n" on *nix) - MAX_HANDSHAKE_ATTEMPS = 10, -- attemps to finish ssl handshake - HANDSHAKE_TIMEOUT = 1, -- timout in seconds per handshake attemp + MAX_HANDSHAKE_ATTEMPS = 1000, -- attempts to finish ssl handshake + HANDSHAKE_TIMEOUT = 60, -- timout in seconds per handshake attempt MAX_READ_LENGTH = 1024 * 1024 * 1024 * 1024, -- max bytes allowed to read from sockets MAX_SEND_LENGTH = 1024 * 1024 * 1024 * 1024, -- max bytes size of write buffer (for writing on sockets) - ACCEPT_DELAY = 10, -- seconds to wait until the next attemp of a full server to accept - READ_TIMEOUT = 60 * 30, -- timeout in seconds for read data from socket - WRITE_TIMEOUT = 30, -- timeout in seconds for write data on socket - CONNECT_TIMEOUT = 10, -- timeout in seconds for connection attemps + ACCEPT_DELAY = 10, -- seconds to wait until the next attempt of a full server to accept + READ_TIMEOUT = 60 * 60 * 6, -- timeout in seconds for read data from socket + WRITE_TIMEOUT = 180, -- timeout in seconds for write data on socket + CONNECT_TIMEOUT = 20, -- timeout in seconds for connection attempts CLEAR_DELAY = 5, -- seconds to wait for clearing interface list (and calling ondisconnect listeners) DEBUG = true, -- show debug messages } @@ -43,7 +43,7 @@ local tostring = use "tostring" local coroutine = use "coroutine" local setmetatable = use "setmetatable" -local ssl = use "ssl" or require "ssl" +local ssl = use "ssl" local socket = use "socket" or require "socket" local log = require ("util.logger").init("socket") @@ -142,7 +142,7 @@ do self:_close() debug( "new connection failed. id:", self.id, "error:", self.fatalerror ) else - if plainssl then -- start ssl session + if plainssl and ssl then -- start ssl session self:starttls() else -- normal connection self:_start_session( self.listener.onconnect ) @@ -160,7 +160,7 @@ do local callback = function( ) self:_lock( false, false, false ) --vdebug( "start listening on client socket with id:", self.id ) - self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT ) -- register callback + self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT ); -- register callback self:onconnect() self.eventsession = nil return -1 @@ -197,7 +197,7 @@ do local _, err local attempt = 0 local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPS - while attempt < 1000 do -- no endless loop + while attempt < maxattempt do -- no endless loop attempt = attempt + 1 debug( "ssl handshake of client with id:"..tostring(self).."attemp:"..attempt ) if attempt > maxattempt then @@ -262,7 +262,7 @@ do _ = self.eventsession and self.eventsession:close( ) _ = self.eventwritetimeout and self.eventwritetimeout:close( ) _ = self.eventreadtimeout and self.eventreadtimeout:close( ) - _ = self.ondisconnect and self:ondisconnect( self.fatalerror ) -- call ondisconnect listener (wont be the case if handshake failed on connect) + _ = self.ondisconnect and self:ondisconnect( self.fatalerror ~= "client to close" and self.fatalerror) -- call ondisconnect listener (wont be the case if handshake failed on connect) _ = self.conn and self.conn:close( ) -- close connection, must also be called outside of any socket registered events! _ = self._server and self._server:counter(-1); self.eventread, self.eventwrite = nil, nil @@ -281,6 +281,23 @@ do self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting return nointerface, noreading, nowriting end + + --TODO: Deprecate + function interface_mt:lock_read(switch) + if switch then + return self:pause(); + else + return self:resume(); + end + end + + function interface_mt:pause() + return self:_lock(self.nointerface, true, self.nowriting); + end + + function interface_mt:resume() + return self:_lock(self.nointerface, false, self.nowriting); + end function interface_mt:counter(c) if c then @@ -385,6 +402,13 @@ do self.starttls = false; -- prevent starttls() end end + + function interface_mt:set_mode(pattern) + if pattern then + self._pattern = pattern; + end + return self._pattern; + end function interface_mt:set_send(new_send) -- No-op, we always use the underlying connection's send @@ -433,6 +457,7 @@ do -- Stub handlers function interface_mt:onconnect() + return self:onincoming(nil); end function interface_mt:onincoming() end @@ -440,6 +465,8 @@ do end function interface_mt:ontimeout() end + function interface_mt:ondrain() + end function interface_mt:onstatus() debug("server.lua: Dummy onstatus()") end @@ -489,6 +516,7 @@ do _sslctx = sslctx; -- parameters _usingssl = false; -- client is using ssl; } + if not ssl then interface.starttls = false; end interface.id = tostring(interface):match("%x+$"); interface.writecallback = function( event ) -- called on write events --vdebug( "new client write event, id/ip/port:", interface, ip, port ) @@ -519,6 +547,7 @@ do if succ then -- writing succesful interface.writebuffer = "" interface.writebufferlen = 0 + interface:ondrain(); if interface.fatalerror then debug "closing client after writing" interface:_close() -- close interface if needed @@ -530,7 +559,7 @@ do end interface.eventwrite = nil return -1 - elseif byte then -- want write again + elseif byte and (err == "timeout" or err == "wantwrite") then -- want write again --vdebug( "writebuffer is not empty:", err ) interface.writebuffer = string_sub( interface.writebuffer, byte + 1, interface.writebufferlen ) -- new buffer interface.writebufferlen = interface.writebufferlen - byte @@ -538,7 +567,7 @@ do local callback = function( ) interface:_close() interface.eventwritetimeout = nil - return evreturn, evtimeout + return -1; end interface.eventwritetimeout = addevent( base, nil, EV_TIMEOUT, callback, cfg.WRITE_TIMEOUT ) -- reg a new timeout event debug( "wantread during write attemp, reg it in readcallback but dont know what really happens next..." ) @@ -580,7 +609,7 @@ do interface.eventreadtimeout = nil end end - local buffer, err, part = interface.conn:receive( pattern ) -- receive buffer with "pattern" + local buffer, err, part = interface.conn:receive( interface._pattern ) -- receive buffer with "pattern" --vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) ) buffer = buffer or part or "" local len = string_len( buffer ) @@ -666,16 +695,17 @@ do debug( "maximal connections reached, refuse client connection; accept delay:", delay ) return EV_TIMEOUT, delay -- delay for next accept attemp end - local ip, port = client:getpeername( ) + local client_ip, client_port = client:getpeername( ) interface._connections = interface._connections + 1 -- increase connection count - local clientinterface = handleclient( client, ip, port, interface, pattern, listener, nil, sslctx ) + local clientinterface = handleclient( client, client_ip, client_port, interface, pattern, listener, nil, sslctx ) --vdebug( "client id:", clientinterface, "startssl:", startssl ) - if sslctx then + if ssl and sslctx then clientinterface:starttls(sslctx) else clientinterface:_start_session( clientinterface.onconnect ) end - debug( "accepted incoming client connection from:", ip, port ) + debug( "accepted incoming client connection from:", client_ip or "", client_port or "", "to", port or ""); + client, err = server:accept() -- try to accept again end return EV_READ @@ -703,7 +733,7 @@ local addserver = ( function( ) debug "fatal error: luasec not found" return nil, "luasec not found" end - sslctx, err = ssl.newcontext( sslcfg ) + sslctx, err = sslcfg if err then debug( "error while creating new ssl context for server socket:", err ) return nil, err @@ -744,7 +774,7 @@ do debug "need luasec, but not available" return nil, "luasec not found" end - sslctx, err = ssl.newcontext( sslcfg ) + sslctx, err = sslcfg if err then debug( "cannot create new ssl context:", err ) return nil, err @@ -756,7 +786,7 @@ do local server = function( ) return nil, "this is a dummy server interface" end - local interface = wrapclient( client, ip, serverport, listeners, pattern, sslctx, startssl ) + local interface = wrapclient( client, ip, serverport, listener, pattern, sslctx, startssl ) interface:_start_connection( startssl ) debug( "new connection id:", interface.id ) return interface, err @@ -815,11 +845,32 @@ function hook_signal(signal_num, handler) return signal_events[signal_num]; end +local function link(sender, receiver, buffersize) + sender:set_mode(buffersize); + local sender_locked; + + function receiver:ondrain() + if sender_locked then + sender:resume(); + sender_locked = nil; + end + end + + function sender:onincoming(data) + receiver:write(data); + if receiver.writebufferlen >= buffersize then + sender_locked = true; + sender:pause(); + end + end +end + return { cfg = cfg, base = base, loop = loop, + link = link, event = event, event_base = base, addevent = newevent,