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-861f7616d084master
parent
66b09c68ec
commit
ebd93276a6
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue