server_select: Add logging of when servers are paused and resumed
[prosody.git] / net / server_event.lua
index 5316866ecccb95ff68c774b9b05b92292804c2e9..45938a13b46c94f718c3fcf8c6259dd3d1e31220 100644 (file)
@@ -23,6 +23,7 @@ local cfg = {
        HANDSHAKE_TIMEOUT     = 60,  -- timeout 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_QUEUE          = 128,  -- might influence the length of the pending sockets queue
        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
@@ -40,6 +41,9 @@ local tostring = use "tostring"
 local coroutine = use "coroutine"
 local setmetatable = use "setmetatable"
 
+local t_insert = table.insert
+local t_concat = table.concat
+
 local ssl = use "ssl"
 local socket = use "socket" or require "socket"
 
@@ -120,14 +124,8 @@ do
                        self.position = new_position or self.position
                        return self.position;
        end
-       function interface_mt:_close() -- regs event to start self:_destroy()
-                       local callback = function( )
-                               self:_destroy();
-                               self.eventclose = nil
-                               return -1
-                       end
-                       self.eventclose = addevent( base, nil, EV_TIMEOUT, callback, 0 )
-                       return true
+       function interface_mt:_close()
+               return self:_destroy();
        end
        
        function interface_mt:_start_connection(plainssl) -- should be called from addclient
@@ -315,7 +313,7 @@ do
                        debug( "error:", err )  -- to much, check your app
                        return nil, err
                end
-               self.writebuffer = self.writebuffer .. data -- new buffer
+               t_insert(self.writebuffer, data) -- new buffer
                self.writebufferlen = total
                if not self.eventwrite then  -- register new write event
                        --vdebug( "register new write event" )
@@ -369,6 +367,7 @@ do
        function interface_mt:ssl()
                return self._usingssl
        end
+       interface_mt.clientport = interface_mt.port -- COMPAT server_select
 
        function interface_mt:type()
                return self._type or "client"
@@ -439,8 +438,11 @@ do
        end
        
        function interface_mt:setlistener(listener)
-               self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onstatus
-                       = listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout, listener.onstatus;
+               self:ondetach(); -- Notify listener that it is no longer responsible for this connection
+               self.onconnect, self.ondisconnect, self.onincoming,
+               self.ontimeout, self.onstatus, self.ondetach
+                       = listener.onconnect, listener.ondisconnect, listener.onincoming,
+                       listener.ontimeout, listener.onstatus, listener.ondetach;
        end
        
        -- Stub handlers
@@ -454,6 +456,8 @@ do
        end
        function interface_mt:ondrain()
        end
+       function interface_mt:ondetach()
+       end
        function interface_mt:onstatus()
        end
 end
@@ -463,7 +467,6 @@ end
 local handleclient;
 do
        local string_sub = string.sub  -- caching table lookups
-       local string_len = string.len
        local addevent = base.addevent
        local socket_gettime = socket.gettime
        function handleclient( client, ip, port, server, pattern, listener, sslctx )  -- creates an client interface
@@ -472,7 +475,7 @@ do
                        type = "client";
                        conn = client;
                        currenttime = socket_gettime( );  -- safe the origin
-                       writebuffer = "";  -- writebuffer
+                       writebuffer = {};  -- writebuffer
                        writebufferlen = 0;  -- length of writebuffer
                        send = client.send;  -- caching table lookups
                        receive = client.receive;
@@ -480,6 +483,8 @@ 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
+                       ondrain = listener.ondrain; -- called when writebuffer is empty
+                       ondetach = listener.ondetach; -- called when disassociating this listener from this connection
                        onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS)
                        eventread = false, eventwrite = false, eventclose = false,
                        eventhandshake = false, eventstarthandshake = false;  -- event handler
@@ -526,10 +531,11 @@ do
                                                interface.eventwritetimeout = false
                                        end
                                end
-                               local succ, err, byte = interface.conn:send( interface.writebuffer, 1, interface.writebufferlen )
+                               interface.writebuffer = { t_concat(interface.writebuffer) }
+                               local succ, err, byte = interface.conn:send( interface.writebuffer[1], 1, interface.writebufferlen )
                                --vdebug( "write data:", interface.writebuffer, "error:", err, "part:", byte )
                                if succ then  -- writing succesful
-                                       interface.writebuffer = ""
+                                       interface.writebuffer[1] = nil
                                        interface.writebufferlen = 0
                                        interface:ondrain();
                                        if interface.fatalerror then
@@ -545,7 +551,7 @@ do
                                        return -1
                                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.writebuffer[1] = string_sub( interface.writebuffer[1], byte + 1, interface.writebufferlen )  -- new buffer
                                        interface.writebufferlen = interface.writebufferlen - byte
                                        if "wantread" == err then  -- happens only with luasec
                                                local callback = function( )
@@ -847,6 +853,7 @@ local function link(sender, receiver, buffersize)
                        sender:pause();
                end
        end
+       sender:set_mode("*a");
 end
 
 return {