connlistener, server_select, prosody: Add support for binding to multiple addresses
authorFlorian Zeitz <florob@babelmonkeys.de>
Wed, 15 Jun 2011 21:44:18 +0000 (23:44 +0200)
committerFlorian Zeitz <florob@babelmonkeys.de>
Wed, 15 Jun 2011 21:44:18 +0000 (23:44 +0200)
net/connlisteners.lua
net/server_select.lua
prosody

index 7da25c62df3e4d52c7824d71432c516ff16650e1..6a227c9dc576115af0675c55ed5e359ab238dfdf 100644 (file)
@@ -12,6 +12,8 @@ local listeners_dir = (CFG_SOURCEDIR or ".").."/net/";
 local server = require "net.server";
 local log = require "util.logger".init("connlisteners");
 local tostring = tostring;
+local type = type
+local ipairs = ipairs
 
 local dofile, xpcall, error =
       dofile, xpcall, error
@@ -55,7 +57,8 @@ function start(name, udata)
                error("No such connection module: "..name.. (err and (" ("..err..")") or ""), 0);
        end
        
-       local interface = (udata and udata.interface) or h.default_interface or "*";
+       local interfaces = (udata and udata.interface) or h.default_interface or "*";
+       if type(interfaces) == "string" then interfaces = {interfaces}; end
        local port = (udata and udata.port) or h.default_port or error("Can't start listener "..name.." because no port was specified, and it has no default port", 0);
        local mode = (udata and udata.mode) or h.default_mode or 1;
        local ssl = (udata and udata.ssl) or nil;
@@ -64,8 +67,15 @@ function start(name, udata)
        if autossl and not ssl then
                return nil, "no ssl context";
        end
-       
-       return server.addserver(interface, port, h, mode, autossl and ssl or nil);
+
+       ok, err = true, {};
+       for _, interface in ipairs(interfaces) do
+               local handler
+               handler, err[interface] = server.addserver(interface, port, h, mode, autossl and ssl or nil);
+               ok = ok and handler;
+       end
+
+       return ok, err;
 end
 
 return _M;
index 13a910f8b4ce52a963b4d54f3067d621415c3c56..4a22d2ed04a5947fddc03c05b65d2a1455f703fb 100644 (file)
@@ -701,19 +701,19 @@ addserver = function( addr, port, listeners, pattern, sslctx ) -- this function
        end
        if type( port ) ~= "number" or not ( port >= 0 and port <= 65535 ) then
                err = "invalid port"
-       elseif _server[ port ] then
-               err = "listeners on port '" .. port .. "' already exist"
+       elseif _server[ addr..":"..port ] then
+               err = "listeners on '[" .. addr .. "]:" .. port .. "' already exist"
        elseif sslctx and not luasec then
                err = "luasec not found"
        end
        if err then
-               out_error( "server.lua, port ", port, ": ", err )
+               out_error( "server.lua, [", addr, "]:", port, ": ", err )
                return nil, err
        end
        addr = addr or "*"
        local server, err = socket_bind( addr, port )
        if err then
-               out_error( "server.lua, port ", port, ": ", err )
+               out_error( "server.lua, [", addr, "]:", port, ": ", err )
                return nil, err
        end
        local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, _maxclientsperserver ) -- wrap new server socket
@@ -723,23 +723,23 @@ addserver = function( addr, port, listeners, pattern, sslctx ) -- this function
        end
        server:settimeout( 0 )
        _readlistlen = addsocket(_readlist, server, _readlistlen)
-       _server[ port ] = handler
+       _server[ addr..":"..port ] = handler
        _socketlist[ server ] = handler
-       out_put( "server.lua: new "..(sslctx and "ssl " or "").."server listener on '", addr, ":", port, "'" )
+       out_put( "server.lua: new "..(sslctx and "ssl " or "").."server listener on '[", addr, "]:", port, "'" )
        return handler
 end
 
-getserver = function ( port )
-       return _server[ port ];
+getserver = function ( addr, port )
+       return _server[ addr..":"..port ];
 end
 
-removeserver = function( port )
-       local handler = _server[ port ]
+removeserver = function( addr, port )
+       local handler = _server[ addr..":"..port ]
        if not handler then
-               return nil, "no server found on port '" .. tostring( port ) .. "'"
+               return nil, "no server found on '[" .. addr .. "]:" .. tostring( port ) .. "'"
        end
        handler:close( )
-       _server[ port ] = nil
+       _server[ addr..":"..port ] = nil
        return true
 end
 
diff --git a/prosody b/prosody
index 1a58fd33fc0228a4f661888966b2ed57ceedc7c7..3f3284335a39aa789c079fe9f97d2a4343d3a830 100755 (executable)
--- a/prosody
+++ b/prosody
@@ -270,7 +270,7 @@ function init_global_state()
                                if type(port) ~= "number" then
                                        log("error", "Non-numeric "..ports_option..": "..tostring(port));
                                else
-                                       local ok, err = cl.start(listener, {
+                                       local ok, errors = cl.start(listener, {
                                                ssl = conntype == "ssl" and global_ssl_ctx,
                                                port = port,
                                                interface = (option and config.get("*", "core", option.."_interface"))
@@ -279,31 +279,33 @@ function init_global_state()
                                                type = conntype
                                        });
                                        if not ok then
-                                               local friendly_message = err;
-                                               if err:match(" in use") then
-                                                       if port == 5222 or port == 5223 or port == 5269 then
-                                                               friendly_message = "check that Prosody or another XMPP server is "
-                                                                       .."not already running and using this port";
-                                                       elseif port == 80 or port == 81 then
-                                                               friendly_message = "check that a HTTP server is not already using "
-                                                                       .."this port";
-                                                       elseif port == 5280 then
-                                                               friendly_message = "check that Prosody or a BOSH connection manager "
-                                                                       .."is not already running";
-                                                       else
-                                                               friendly_message = "this port is in use by another application";
-                                                       end
-                                               elseif err:match("permission") then
-                                                       friendly_message = "Prosody does not have sufficient privileges to use this port";
-                                               elseif err == "no ssl context" then
-                                                       if not config.get("*", "core", "ssl") then
-                                                               friendly_message = "there is no 'ssl' config under Host \"*\" which is "
-                                                                       .."require for legacy SSL ports";
-                                                       else
-                                                               friendly_message = "initializing SSL support failed, see previous log entries";
+                                               for addr, err in pairs(errors) do
+                                                       local friendly_message = err;
+                                                       if err:match(" in use") then
+                                                               if port == 5222 or port == 5223 or port == 5269 then
+                                                                       friendly_message = "check that Prosody or another XMPP server is "
+                                                                               .."not already running and using this port";
+                                                               elseif port == 80 or port == 81 then
+                                                                       friendly_message = "check that a HTTP server is not already using "
+                                                                               .."this port";
+                                                               elseif port == 5280 then
+                                                                       friendly_message = "check that Prosody or a BOSH connection manager "
+                                                                               .."is not already running";
+                                                               else
+                                                                       friendly_message = "this port is in use by another application";
+                                                               end
+                                                       elseif err:match("permission") then
+                                                               friendly_message = "Prosody does not have sufficient privileges to use this port";
+                                                       elseif err == "no ssl context" then
+                                                               if not config.get("*", "core", "ssl") then
+                                                                       friendly_message = "there is no 'ssl' config under Host \"*\" which is "
+                                                                               .."require for legacy SSL ports";
+                                                               else
+                                                                       friendly_message = "initializing SSL support failed, see previous log entries";
+                                                               end
                                                        end
+                                                       log("error", "Failed to open server port %d on %s, %s", port, addr, friendly_message);
                                                end
-                                               log("error", "Failed to open server port %d, %s", port, friendly_message);
                                        end
                                end
                        end