Merge with 0.7
[prosody.git] / net / server_event.lua
index 31e5b034f0477ccba57fbefe66e99fc1fdb5ccee..d041ae4381527d909ae2b3d2cce63ec420031e4a 100644 (file)
@@ -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,  -- attemps to finish ssl handshake
+       HANDSHAKE_TIMEOUT     = 30,  -- timout in seconds per handshake attemp
        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
+       CONNECT_TIMEOUT       = 20,  -- timeout in seconds for connection attemps
        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 )
@@ -161,7 +161,7 @@ do
                                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:onconnect()
+                               self:onincoming()
                                self.eventsession = nil
                                return -1
                        end
@@ -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
@@ -218,6 +218,7 @@ do
                                                                end
                                                                self:_start_session( onsomething )
                                                                debug( "ssl handshake done" )
+                                                               self:onstatus("ssl-handshake-complete");
                                                                self.eventhandshake = nil
                                                                return -1
                                                        end
@@ -261,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
@@ -280,6 +281,10 @@ do
                        self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting
                        return nointerface, noreading, nowriting
        end
+       
+       function interface_mt:lock_read(switch)
+               return self:_lock(self.nointerface, switch, self.nowriting);
+       end
 
        function interface_mt:counter(c)
                if c then
@@ -389,12 +394,11 @@ do
                -- No-op, we always use the underlying connection's send
        end
        
-       function interface_mt:starttls()
+       function interface_mt:starttls(sslctx)
                debug( "try to start ssl at client id:", self.id )
                local err
-               if not self._sslctx then  -- no ssl available
-                       err = "no ssl context available"
-               elseif self._usingssl then  -- startssl was already called
+               self._sslctx = sslctx;
+               if self._usingssl then  -- startssl was already called
                        err = "ssl already active"
                end
                if err then
@@ -427,8 +431,8 @@ do
        end
        
        function interface_mt:setlistener(listener)
-               self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout
-                       = listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout;
+               self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onstatus
+                       = listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout, listener.onstatus;
        end
        
        -- Stub handlers
@@ -440,6 +444,9 @@ do
        end
        function interface_mt:ontimeout()
        end
+       function interface_mt:onstatus()
+               debug("server.lua: Dummy onstatus()")
+       end
 end
 
 -- End of client interface methods
@@ -466,6 +473,7 @@ do
                        ondisconnect = listener.ondisconnect;  -- will be called when client disconnects
                        onincoming = listener.onincoming;  -- will be called when client sends data
                        ontimeout = listener.ontimeout; -- called when fatal socket timeout occurs
+                       onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS)
                        eventread = false, eventwrite = false, eventclose = false,
                        eventhandshake = false, eventstarthandshake = false;  -- event handler
                        eventconnect = false, eventsession = false;  -- more event handler...
@@ -485,9 +493,7 @@ do
                        _sslctx = sslctx; -- parameters
                        _usingssl = false;  -- client is using ssl;
                }
-               if not sslctx then
-                       interface.starttls = false -- don't allow TLS
-               end
+               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 )
@@ -624,7 +630,7 @@ end
 
 local handleserver
 do
-       function handleserver( server, addr, port, pattern, listener, sslctx, startssl )  -- creates an server interface
+       function handleserver( server, addr, port, pattern, listener, sslctx )  -- creates an server interface
                debug "creating server interface..."
                local interface = {
                        _connections = 0;
@@ -669,12 +675,13 @@ do
                                interface._connections = interface._connections + 1  -- increase connection count
                                local clientinterface = handleclient( client, ip, port, interface, pattern, listener, nil, sslctx )
                                --vdebug( "client id:", clientinterface, "startssl:", startssl )
-                               if startssl then
-                                       clientinterface:starttls()
+                               if ssl and sslctx then
+                                       clientinterface:starttls(sslctx)
                                else
                                        clientinterface:_start_session( clientinterface.onconnect )
                                end
                                debug( "accepted incoming client connection from:", ip, port )
+                               
                                client, err = server:accept()    -- try to accept again
                        end
                        return EV_READ
@@ -702,7 +709,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
@@ -743,7 +750,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