Changeset

4322:aff627b1ce95

connlistener, server_select, prosody: Add support for binding to multiple addresses
author Florian Zeitz <florob@babelmonkeys.de>
date Wed, 15 Jun 2011 23:44:18 +0200
parents 4321:4dcdba6900f2
children 4323:53f3c3001499
files net/connlisteners.lua net/server_select.lua prosody
diffstat 3 files changed, 51 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/net/connlisteners.lua	Sun Jun 12 22:21:10 2011 +0100
+++ b/net/connlisteners.lua	Wed Jun 15 23:44:18 2011 +0200
@@ -12,6 +12,8 @@
 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 @@
 		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 @@
 	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;
--- a/net/server_select.lua	Sun Jun 12 22:21:10 2011 +0100
+++ b/net/server_select.lua	Wed Jun 15 23:44:18 2011 +0200
@@ -701,19 +701,19 @@
 	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 @@
 	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
 
--- a/prosody	Sun Jun 12 22:21:10 2011 +0100
+++ b/prosody	Wed Jun 15 23:44:18 2011 +0200
@@ -270,7 +270,7 @@
 				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 @@
 						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";
+						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
-						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
+							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