Make the lobby server listen and operate on IPv6

* Also disable IPV6_V6ONLY to make sure that (on systems that support the option) IPv4 is still supported, using the same socket
  - This option works on Linux from 2.4.21 and 2.6 (according to "man ipv6")
  - On FreeBSD this works from version 6 onward (lower versions might work, I only tested on 6 and 7 and didn't find any note in the manual)
  - Furthermore, according to
    http://en.wikipedia.org/wiki/IPv4_mapped_address:
   * This works on Windows from Vista onward
   * This works on NetBSD (version unspecified)
   * This doesn't work on OpenBSD (as a design decision for security)

git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@7225 4a71c877-e1ca-e34f-864e-861f7616d084
master
Giel van Schijndel 2009-04-28 15:36:28 +00:00 committed by Git SVN Gateway
parent 66b09c68ec
commit ebd93276a6
2 changed files with 23 additions and 4 deletions

View File

@ -33,6 +33,9 @@ __all__ = ['Protocol']
def _socket(family = socket.AF_INET, type = socket.SOCK_STREAM, proto = 0): def _socket(family = socket.AF_INET, type = socket.SOCK_STREAM, proto = 0):
s = socket.socket(family, type, proto) s = socket.socket(family, type, proto)
try: try:
if family == socket.AF_INET6:
# Ensure that connecting to IPv6-mapped IPv4 addresses works as well
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
yield s yield s
finally: finally:
s.close() s.close()
@ -115,7 +118,7 @@ class BaseProtocol(object):
def check(self, game): def check(self, game):
"""Check we can connect to the game's host.""" """Check we can connect to the game's host."""
with _socket() as s: with _socket(socket.AF_INET6) as s:
try: try:
logging.debug("Checking %s's vitality..." % game.host) logging.debug("Checking %s's vitality..." % game.host)
s.settimeout(10.0) s.settimeout(10.0)
@ -127,7 +130,7 @@ class BaseProtocol(object):
def list(self, host): def list(self, host):
"""Retrieve a list of games from the lobby server.""" """Retrieve a list of games from the lobby server."""
with _socket() as s: with _socket(socket.AF_INET6) as s:
s.settimeout(10.0) s.settimeout(10.0)
s.connect((host, self.lobbyPort)) s.connect((host, self.lobbyPort))

View File

@ -216,6 +216,22 @@ class RequestHandler(SocketServer.ThreadingMixIn, SocketServer.StreamRequestHand
else: else:
raise Exception("(%s) Recieved a unknown command: %s" % (gameHost, netCommand)) raise Exception("(%s) Recieved a unknown command: %s" % (gameHost, netCommand))
class TCP46Server(SocketServer.TCPServer):
"""Class to enable listening on both IPv4 and IPv6 addresses."""
address_family = socket.AF_INET6
def server_bind(self):
"""Called by constructor to bind the socket.
Overridden to disable IPV6_V6ONLY.
"""
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
SocketServer.TCPServer.server_bind(self)
class ThreadingTCP46Server(SocketServer.ThreadingMixIn, TCP46Server): pass
# #
################################################################################ ################################################################################
# The legendary Main. # The legendary Main.
@ -232,8 +248,8 @@ if __name__ == '__main__':
gamedb = GameDB() gamedb = GameDB()
SocketServer.ThreadingTCPServer.allow_reuse_address = True ThreadingTCP46Server.allow_reuse_address = True
tcpserver = SocketServer.ThreadingTCPServer(('0.0.0.0', protocol.lobbyPort), RequestHandler) tcpserver = ThreadingTCP46Server(('::', protocol.lobbyPort), RequestHandler)
try: try:
while True: while True:
tcpserver.handle_request() tcpserver.handle_request()