support connectHttp

This commit is contained in:
David Rose 2002-10-21 14:50:53 +00:00
parent 5f859b3901
commit ebc6b3f7d0

View File

@ -8,7 +8,6 @@ import Task
import DirectNotifyGlobal import DirectNotifyGlobal
import ClientDistClass import ClientDistClass
import CRCache import CRCache
import Datagram
# The repository must import all known types of Distributed Objects # The repository must import all known types of Distributed Objects
#import DistributedObject #import DistributedObject
#import DistributedToon #import DistributedToon
@ -26,6 +25,23 @@ class ClientRepository(DirectObject.DirectObject):
self.doId2cdc={} self.doId2cdc={}
self.parseDcFile(dcFileName) self.parseDcFile(dcFileName)
self.cache=CRCache.CRCache() self.cache=CRCache.CRCache()
# Set this true to establish a connection to the server using
# the HTTPClient interface, which ultimately uses the OpenSSL
# socket library (even though SSL is not involved). This is
# not as robust a socket library as NSPR's, but the HTTPClient
# interface does a good job of negotiating the connection over
# an HTTP proxy if one is in use.
# Set it false to use Panda's net interface
# (e.g. QueuedConnectionManager, etc.) to establish the
# connection, which ultimately uses the NSPR socket library.
# This is a much better socket library, but it may be more
# than you need for most applications; and the Panda net
# interface doesn't support proxies at all.
self.connectHttp = base.config.GetBool('connect-http', 1)
self.tcpConn = None
return None return None
def parseDcFile(self, dcFileName): def parseDcFile(self, dcFileName):
@ -47,66 +63,64 @@ class ClientRepository(DirectObject.DirectObject):
self.name2cdc[dcClass.getName()]=clientDistClass self.name2cdc[dcClass.getName()]=clientDistClass
return None return None
def connect(self, serverName, serverPort): def connect(self, serverURL,
self.qcm=QueuedConnectionManager() successCallback = None, successArgs = [],
gameServerTimeoutMs = base.config.GetInt("game-server-timeout-ms", failureCallback = None, failureArgs = []):
20000) """
# A big old 20 second timeout. Attempts to establish a connection to the server. May return
self.tcpConn = self.qcm.openTCPClientConnection( before the connection is established. The two callbacks
serverName, serverPort, gameServerTimeoutMs) represent the two functions to call (and their arguments) on
# Test for bad connection success or failure, respectively. The failure callback also
if self.tcpConn == None: gets one additional parameter, which will be passed in first:
return None the return status code giving reason for failure, if it is
known.
"""
if self.connectHttp:
ch = self.http.makeChannel(0)
ch.beginConnectTo(serverURL)
ch.spawnTask(name = 'connect-to-server',
callback = self.httpConnectCallback,
extraArgs = [ch, successCallback, successArgs,
failureCallback, failureArgs])
else: else:
self.tcpConn.setNoDelay(1) self.qcm = QueuedConnectionManager()
self.qcr=QueuedConnectionReader(self.qcm, 0) gameServerTimeoutMs = base.config.GetInt("game-server-timeout-ms",
self.qcr.addConnection(self.tcpConn) 20000)
self.cw=ConnectionWriter(self.qcm, 0) # A big old 20 second timeout.
self.startReaderPollTask() self.tcpConn = self.qcm.openTCPClientConnection(
return self.tcpConn serverURL.getServer(), serverURL.getPort(),
gameServerTimeoutMs)
def startRawReaderPollTask(self): if self.tcpConn:
# Stop any tasks we are running now self.tcpConn.setNoDelay(1)
self.stopRawReaderPollTask() self.qcr=QueuedConnectionReader(self.qcm, 0)
self.stopReaderPollTask() self.qcr.addConnection(self.tcpConn)
task = Task.Task(self.rawReaderPollUntilEmpty) self.cw=ConnectionWriter(self.qcm, 0)
# Start with empty string self.startReaderPollTask()
task.currentRawString = "" if successCallback:
taskMgr.add(task, "rawReaderPollTask", priority=self.TASK_PRIORITY) successCallback(*successArgs)
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: else:
ClientRepository.notify.warning("getData returned false") # Failed to connect.
return availGetVal if failureCallback:
failureCallback(0, *failureArgs)
def handleRawString(self, str): def httpConnectCallback(self, ch, successCallback, successArgs,
# This method is meant to be pure virtual, and any classes that failureCallback, failureArgs):
# inherit from it need to make their own handleRawString method if ch.isConnectionReady():
pass self.tcpConn = ch.getConnection()
self.tcpConn.userManagesMemory = 1
self.startReaderPollTask()
if successCallback:
successCallback(*successArgs)
else:
# Failed to connect.
if failureCallback:
failureCallback(ch.getStatusCode(), *failureArgs)
def startReaderPollTask(self): def startReaderPollTask(self):
# Stop any tasks we are running now # Stop any tasks we are running now
self.stopRawReaderPollTask()
self.stopReaderPollTask() self.stopReaderPollTask()
taskMgr.add(self.readerPollUntilEmpty, "readerPollTask", taskMgr.add(self.readerPollUntilEmpty, "readerPollTask",
priority=self.TASK_PRIORITY) priority=self.TASK_PRIORITY)
@ -122,25 +136,42 @@ class ClientRepository(DirectObject.DirectObject):
return Task.cont return Task.cont
def readerPollOnce(self): def readerPollOnce(self):
self.ensureValidConnection() if self.connectHttp:
availGetVal = self.qcr.dataAvailable() datagram = Datagram()
if availGetVal: if self.tcpConn.receiveDatagram(datagram):
# print "Client: Incoming message!"
datagram = NetDatagram()
readRetVal = self.qcr.getData(datagram)
if readRetVal:
self.handleDatagram(datagram) self.handleDatagram(datagram)
else: return 1
ClientRepository.notify.warning("getData returned false")
return availGetVal # Unable to receive a datagram: did we lose the connection?
if self.tcpConn.isClosed():
self.tcpConn = None
self.loginFSM.request("noConnection")
return 0
else:
self.ensureValidConnection()
if self.qcr.dataAvailable():
datagram = NetDatagram()
if self.qcr.getData(datagram):
self.handleDatagram(datagram)
return 1
return 0
def ensureValidConnection(self): def ensureValidConnection(self):
# Was the connection reset? # Was the connection reset?
if self.qcm.resetConnectionAvailable(): if self.connectHttp:
resetConnectionPointer = PointerToConnection() pass
if self.qcm.getResetConnection(resetConnectionPointer): else:
self.qcm.closeConnection(resetConnectionPointer.p()) if self.qcm.resetConnectionAvailable():
self.loginFSM.request("noConnection") resetConnectionPointer = PointerToConnection()
if self.qcm.getResetConnection(resetConnectionPointer):
resetConn = resetConnectionPointer.p()
self.qcm.closeConnection(resetConn)
if self.tcpConn.this == resetConn.this:
self.tcpConn = None
self.loginFSM.request("noConnection")
else:
self.notify.warning("Lost unknown connection.")
return None return None
def handleDatagram(self, datagram): def handleDatagram(self, datagram):
@ -386,7 +417,7 @@ class ClientRepository(DirectObject.DirectObject):
return None return None
def sendSetShardMsg(self, shardId): def sendSetShardMsg(self, shardId):
datagram = Datagram.Datagram() datagram = Datagram()
# Add message type # Add message type
datagram.addUint16(CLIENT_SET_SHARD) datagram.addUint16(CLIENT_SET_SHARD)
# Add shard id # Add shard id
@ -396,7 +427,7 @@ class ClientRepository(DirectObject.DirectObject):
return None return None
def sendSetZoneMsg(self, zoneId): def sendSetZoneMsg(self, zoneId):
datagram = Datagram.Datagram() datagram = Datagram()
# Add message type # Add message type
datagram.addUint16(CLIENT_SET_ZONE) datagram.addUint16(CLIENT_SET_ZONE)
# Add zone id # Add zone id
@ -420,7 +451,15 @@ class ClientRepository(DirectObject.DirectObject):
print "ClientRepository sending datagram:" print "ClientRepository sending datagram:"
datagram.dumpHex(ostream) datagram.dumpHex(ostream)
self.cw.send(datagram, self.tcpConn) if not self.tcpConn:
self.notify.warning("Unable to send message after connection is closed.")
return
if self.connectHttp:
if not self.tcpConn.sendDatagram(datagram):
self.notify.warning("Could not send datagram.")
else:
self.cw.send(datagram, self.tcpConn)
return None return None
def replaceMethod(self, oldMethod, newFunction): def replaceMethod(self, oldMethod, newFunction):