Lobby utility library:

* Create another custom context manager (can be used in with-statement) for creating a connection to a given (host, port): "connection"
  - Perform manual name-resolution, using each returned entry until one can be succesfully connected to (allows IPv4 + IPv6 through the same function)
 * Use this context manager instead of connecting manually

git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@7305 4a71c877-e1ca-e34f-864e-861f7616d084
master
Giel van Schijndel 2009-05-03 18:28:35 +00:00 committed by Git SVN Gateway
parent 24cc8fda66
commit 7c49ed6628
2 changed files with 29 additions and 17 deletions

View File

@ -40,6 +40,25 @@ def _socket(family = socket.AF_INET, type = socket.SOCK_STREAM, proto = 0):
finally: finally:
s.close() s.close()
@contextmanager
def connection(host, port, family = socket.AF_UNSPEC, socktype = socket.SOCK_STREAM):
addrs = socket.getaddrinfo(host, port, family, socktype)
for i in xrange(len(addrs)):
(family, socktype, proto, canonname, sockaddr) = addrs[i]
with _socket(family, socktype, proto) as s:
timeout = s.gettimeout()
s.settimeout(10.0)
try:
s.connect(sockaddr)
except socket.timeout:
if i == (len(addrs) - 1):
raise
continue
s.settimeout(timeout)
yield s
return
def _encodeCString(string, buf_len): def _encodeCString(string, buf_len):
# If we haven't got a string return an empty one # If we haven't got a string return an empty one
if not string: if not string:
@ -118,22 +137,17 @@ 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(socket.AF_INET6) as s: try:
try: logging.debug("Checking %s's vitality..." % game.host)
logging.debug("Checking %s's vitality..." % game.host) with connection(game.host, self.gamePort) as s:
s.settimeout(10.0)
s.connect((game.host, self.gamePort))
return True return True
except (socket.error, socket.herror, socket.gaierror, socket.timeout), e: except (socket.error, socket.herror, socket.gaierror, socket.timeout), e:
logging.debug("%s did not respond: %s" % (game.host, e)) logging.debug("%s did not respond: %s" % (game.host, e))
return False return False
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(socket.AF_INET6) as s: with connection(host, self.lobbyPort) as s:
s.settimeout(10.0)
s.connect((host, self.lobbyPort))
s.send("list\0") s.send("list\0")
for game in self.decodeMultiple(s): for game in self.decodeMultiple(s):
yield game yield game

View File

@ -40,7 +40,7 @@ import time
import struct import struct
from game import * from game import *
from protocol import * from protocol import *
from protocol import _socket as socket from protocol import connection
server="lobby.wz2100.net" server="lobby.wz2100.net"
protocol = Protocol() protocol = Protocol()
@ -84,10 +84,8 @@ def doAddGame():
g.future3 = 0 g.future3 = 0
g.future4 = 0 g.future4 = 0
with socket() as s: logging.debug("connect to lobby")
logging.debug("connect to lobby") with connection(server, protocol.lobbyPort) as s:
s.settimeout(10.0)
s.connect((server, protocol.lobbyPort))
s.send("addg\0") s.send("addg\0")
protocol.encodeSingle(g, s) protocol.encodeSingle(g, s)
#hold the game open for 10 seconds #hold the game open for 10 seconds