From 09e243d6f6b9efc4f164f5f14bf30edc8b620d31 Mon Sep 17 00:00:00 2001 From: benoitc Date: Sat, 20 Nov 2010 21:04:03 +0100 Subject: [PATCH] ipv6 support in gunicorn. fix ticket #107. --- gunicorn/sock.py | 13 ++++++++++++- gunicorn/util.py | 45 ++++++++++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/gunicorn/sock.py b/gunicorn/sock.py index 78b1abb9..b32cf3db 100644 --- a/gunicorn/sock.py +++ b/gunicorn/sock.py @@ -61,6 +61,14 @@ class TCPSocket(BaseSocket): sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) return super(TCPSocket, self).set_options(sock, bound=bound) +class TCP6Socket(TCPSocket): + + FAMILY = socket.AF_INET6 + + def __str__(self): + (host, port, fl, sc) = self.sock.getsockname() + return "http://[%s]:%d" % (host, port) + class UnixSocket(BaseSocket): FAMILY = socket.AF_UNIX @@ -97,7 +105,10 @@ def create_socket(conf): addr = conf.address if isinstance(addr, tuple): - sock_type = TCPSocket + if util.is_ipv6(addr[0]): + sock_type = TCP6Socket + else: + sock_type = TCPSocket elif isinstance(addr, basestring): sock_type = UnixSocket else: diff --git a/gunicorn/util.py b/gunicorn/util.py index 1c9e066b..8cba9f4f 100644 --- a/gunicorn/util.py +++ b/gunicorn/util.py @@ -99,20 +99,39 @@ def chown(path, uid, gid): os.chown(path, uid, gid) except OverflowError: os.chown(path, uid, -ctypes.c_int(-gid).value) + + +def is_ipv6(addr): + try: + socket.inet_pton(socket.AF_INET6, addr) + except socket.error: # not a valid address + return False + return True -def parse_address(host, port=None, default_port=8000): - if host.startswith("unix:"): - return host.split("unix:")[1] - - if not port: - if ':' in host: - host, port = host.split(':', 1) - if not port.isdigit(): - raise RuntimeError("%r is not a valid port number." % port) - port = int(port) - else: - port = default_port - return (host, int(port)) +def parse_address(netloc, default_port=8000): + if netloc.startswith("unix:"): + return netloc.split("unix:")[1] + + # get host + if '[' in netloc and ']' in netloc: + host = netloc.split(']')[0][1:].lower() + elif ':' in netloc: + host = netloc.split(':')[0].lower() + elif netloc == "": + host = "0.0.0.0" + else: + host = netloc.lower() + + #get port + netloc = netloc.split(']')[-1] + if ":" in netloc: + port = netloc.rsplit(':', 1)[1] + if not port.isdigit(): + raise RuntimeError("%r is not a valid port number." % port) + port = int(port) + else: + port = default_port + return (host, port) def get_maxfd(): maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]