server-failover
This commit is contained in:
parent
e29b86d38f
commit
2623dabc13
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue