plugins/mod_muc_unique: Fix undefined global access (thanks Lance)
[prosody.git] / net / server_event.lua
index 81dc45122858d2f95b9c439a77c7ba919b47babc..480d876d4550c0c6eed9f0fddfd69f02cc9238dc 100644 (file)
@@ -46,6 +46,7 @@ local t_concat = table.concat
 
 local has_luasec, ssl = pcall ( require , "ssl" )
 local socket = use "socket" or require "socket"
+local getaddrinfo = socket.dns.getaddrinfo
 
 local log = require ("util.logger").init("socket")
 
@@ -367,6 +368,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"
@@ -437,9 +439,11 @@ do
        end
 
        function interface_mt:setlistener(listener)
-               self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onreadtimeout, self.onstatus
-                       = listener.onconnect, listener.ondisconnect, listener.onincoming,
-                         listener.ontimeout, listener.onreadtimeout, listener.onstatus;
+               self:ondetach(); -- Notify listener that it is no longer responsible for this connection
+               self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout,
+               self.onreadtimeout, self.onstatus, self.ondetach
+                       = listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout,
+                         listener.onreadtimeout, listener.onstatus, listener.ondetach;
        end
 
        -- Stub handlers
@@ -459,6 +463,8 @@ do
        end
        function interface_mt:ondrain()
        end
+       function interface_mt:ondetach()
+       end
        function interface_mt:onstatus()
        end
 end
@@ -486,6 +492,7 @@ do
                        ontimeout = listener.ontimeout; -- called when fatal socket timeout occurs
                        onreadtimeout = listener.onreadtimeout; -- called when socket inactivity 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
@@ -736,21 +743,34 @@ do
                --function handleclient( client, ip, port, server, pattern, listener, _, sslctx )  -- creates an client interface
        end
 
-       function addclient( addr, serverport, listener, pattern, sslctx )
+       function addclient( addr, serverport, listener, pattern, sslctx, typ )
                if sslctx and not has_luasec then
                        debug "need luasec, but not available"
                        return nil, "luasec not found"
                end
-               local client, err = socket.tcp()  -- creating new socket
+               if getaddrinfo and not typ then
+                       local addrinfo, err = getaddrinfo(addr)
+                       if not addrinfo then return nil, err end
+                       if addrinfo[1] and addrinfo[1].family == "inet6" then
+                               typ = "tcp6"
+                       end
+               end
+               local create = socket[typ or "tcp"]
+               if type( create ) ~= "function"  then
+                       return nil, "invalid socket type"
+               end
+               local client, err = create()  -- creating new socket
                if not client then
                        debug( "cannot create socket:", err )
                        return nil, err
                end
                client:settimeout( 0 )  -- set nonblocking
                local res, err = client:connect( addr, serverport )  -- connect
-               if res or ( err == "timeout" ) then
-                       local ip, port = client:getsockname( )
-                       local interface = wrapclient( client, ip, serverport, listener, pattern, sslctx )
+               if res or ( err == "timeout" or err == "Operation already in progress" ) then
+                       if client.getsockname then
+                               addr = client:getsockname( )
+                       end
+                       local interface = wrapclient( client, addr, serverport, listener, pattern, sslctx )
                        debug( "new connection id:", interface.id )
                        return interface, err
                else
@@ -825,6 +845,7 @@ local function link(sender, receiver, buffersize)
                        sender:pause();
                end
        end
+       sender:set_mode("*a");
 end
 
 return {