server-failover

This commit is contained in:
David Rose 2003-03-13 00:48:08 +00:00
parent e29b86d38f
commit 2623dabc13
1 changed files with 48 additions and 116 deletions

View File

@ -89,7 +89,7 @@ class ClientRepository(DirectObject.DirectObject):
self.name2cdc[dcClass.getName()]=clientDistClass
return None
def connect(self, serverURL,
def connect(self, serverList,
successCallback = None, successArgs = [],
failureCallback = None, failureArgs = []):
"""
@ -113,77 +113,56 @@ class ClientRepository(DirectObject.DirectObject):
self.connectHttp = 0
else:
self.connectHttp = self.hasProxy
self.bootedIndex = None
self.bootedText = None
if self.connectHttp:
self.notify.info("Connecting via HTTP interface.")
# In the HTTP case, we can't just iterate through the list
# of servers, because each server attempt requires
# spawning a request and then coming back later to check
# the success or failure. Instead, we start the ball
# rolling by calling the connect callback, which will call
# itself repeatedly until we establish a connection (or
# run out of servers).
ch = self.http.makeChannel(0)
ch.beginConnectTo(DocumentSpec(serverURL))
ch.spawnTask(name = 'connect-to-server',
callback = self.httpConnectCallback,
extraArgs = [ch, successCallback, successArgs,
failureCallback, failureArgs])
self.httpConnectCallback(ch, serverList, 0,
successCallback, successArgs,
failureCallback, failureArgs)
else:
self.notify.info("Connecting via NSPR interface.")
self.qcm = QueuedConnectionManager()
# A big old 20 second timeout.
gameServerTimeoutMs = base.config.GetInt("game-server-timeout-ms",
20000)
if self.hasProxy:
url = self.proxy
else:
url = serverURL
self.tcpConn = self.qcm.openTCPClientConnection(
url.getServer(), url.getPort(),
gameServerTimeoutMs)
if self.tcpConn:
self.tcpConn.setNoDelay(1)
self.qcr=QueuedConnectionReader(self.qcm, 0)
self.qcr.addConnection(self.tcpConn)
minLag = config.GetFloat('min-lag', 0.)
maxLag = config.GetFloat('max-lag', 0.)
if minLag or maxLag:
self.qcr.startDelay(minLag, maxLag)
self.cw=ConnectionWriter(self.qcm, 0)
if self.hasProxy:
# Now we send an http CONNECT message on that
# connection to initiate a connection to the real
# game server
realGameServer = (serverURL.getServer() + ":" + str(serverURL.getPort()))
connectString = "CONNECT " + realGameServer + " HTTP/1.0\012\012"
datagram = Datagram()
# Use appendData and sendRaw so we do not send the length of the string
datagram.appendData(connectString)
self.notify.info("Sending CONNECT string: " + connectString)
self.cw.setRawMode(1)
self.qcr.setRawMode(1)
self.notify.info("done set raw mode")
self.send(datagram)
self.notify.info("done send datagram")
# Find the end of the http response, then call callback
self.findRawString(["\015\012", "\015\015"],
self.proxyConnectCallback, [successCallback, successArgs])
self.notify.info("done find raw string")
# Now start the raw reader poll task and look for
# the HTTP response When this is finished, it will
# call the connect callback just like the non
# proxy case
self.startRawReaderPollTask()
self.notify.info("done start raw reader poll task")
# Try each of the servers in turn.
for url in serverList:
self.notify.info("Connecting to %s via NSPR interface." % (url.cStr()))
self.tcpConn = self.qcm.openTCPClientConnection(
url.getServer(), url.getPort(),
gameServerTimeoutMs)
else:
# no proxy. We're done connecting.
if self.tcpConn:
self.tcpConn.setNoDelay(1)
self.qcr=QueuedConnectionReader(self.qcm, 0)
self.qcr.addConnection(self.tcpConn)
minLag = config.GetFloat('min-lag', 0.)
maxLag = config.GetFloat('max-lag', 0.)
if minLag or maxLag:
self.qcr.startDelay(minLag, maxLag)
self.cw=ConnectionWriter(self.qcm, 0)
self.startReaderPollTask()
if successCallback:
successCallback(*successArgs)
else:
# Failed to connect.
if failureCallback:
failureCallback(0, *failureArgs)
return
def httpConnectCallback(self, ch, successCallback, successArgs,
# Failed to connect.
if failureCallback:
failureCallback(0, *failureArgs)
def httpConnectCallback(self, ch, serverList, serverIndex,
successCallback, successArgs,
failureCallback, failureArgs):
if ch.isConnectionReady():
self.tcpConn = ch.getConnection()
@ -192,68 +171,21 @@ class ClientRepository(DirectObject.DirectObject):
if successCallback:
successCallback(*successArgs)
elif serverIndex < len(serverList):
# No connection yet, but keep trying.
url = serverList[serverIndex]
self.notify.info("Connecting to %s via HTTP interface." % (url.cStr()))
ch.beginConnectTo(DocumentSpec(url))
ch.spawnTask(name = 'connect-to-server',
callback = self.httpConnectCallback,
extraArgs = [ch, serverList, serverIndex + 1,
successCallback, successArgs,
failureCallback, failureArgs])
else:
# Failed to connect.
# No more servers to try; we have to give up now.
if failureCallback:
failureCallback(ch.getStatusCode(), *failureArgs)
def proxyConnectCallback(self, successCallback, successArgs):
# Make sure we are not in raw mode anymore
self.cw.setRawMode(0)
self.qcr.setRawMode(0)
self.stopRawReaderPollTask()
if successCallback:
successCallback(*successArgs)
def startRawReaderPollTask(self):
# Stop any tasks we are running now
self.stopRawReaderPollTask()
self.stopReaderPollTask()
task = Task.Task(self.rawReaderPollUntilEmpty)
# Start with empty string
task.currentRawString = ""
taskMgr.add(task, "rawReaderPollTask", priority=self.TASK_PRIORITY)
return None
def stopRawReaderPollTask(self):
taskMgr.remove("rawReaderPollTask")
return None
def rawReaderPollUntilEmpty(self, task):
while self.rawReaderPollOnce():
pass
return Task.cont
def rawReaderPollOnce(self):
self.notify.debug("rawReaderPollOnce")
self.ensureValidConnection()
availGetVal = self.qcr.dataAvailable()
if availGetVal:
datagram = NetDatagram()
readRetVal = self.qcr.getData(datagram)
if readRetVal:
str = datagram.getMessage()
self.notify.debug("rawReaderPollOnce: found str: " + str)
self.handleRawString(str)
else:
ClientRepository.notify.warning("getData returned false")
return availGetVal
def handleRawString(self, str):
self.notify.info("handleRawString: str = <%s>" % (str))
self.currentRawString += str
self.notify.info("currentRawString = <%s>" % (self.currentRawString))
# Look in all the match strings to see if we got it yet
for matchString in self.rawStringMatchList:
if (self.currentRawString.find(matchString) >= 0):
self.rawStringCallback(*self.rawStringExtraArgs)
return
def findRawString(self, matchList, callback, extraArgs = []):
self.currentRawString = ""
self.rawStringMatchList = matchList
self.rawStringCallback = callback
self.rawStringExtraArgs = extraArgs
def startReaderPollTask(self):
# Stop any tasks we are running now