diff --git a/direct/src/distributed/ServerRepository.py b/direct/src/distributed/ServerRepository.py index 9a39da0142..a05a0e674d 100644 --- a/direct/src/distributed/ServerRepository.py +++ b/direct/src/distributed/ServerRepository.py @@ -32,22 +32,22 @@ class ServerRepository: self.qcl.addConnection(self.tcpRendezvous) taskMgr.add(self.listenerPoll, "serverListenerPollTask") taskMgr.add(self.readerPollUntilEmpty, "serverReaderPollTask") - taskMgr.add(self.clientHardDisconnectTask, "clientHardDisconnect") - self.ClientIP = {} - self.ClientZones = {} - self.ClientDOIDbase = {} - self.ClientObjects = {} - self.DOIDnext = 1 - self.DOIDrange = 1000000 - self.DOIDtoClients = {} - self.DOIDtoZones = {} - self.DOIDtoDClass = {} - self.ZonesToClients = {} - self.ZonetoDOIDs = {} - self.RemovedDOIDs = [] - self.dcFile = DCFile() - self.dcSuffix = '' - self.readDCFile() + taskMgr.add(self.clientHardDisconnectTask, "clientHardDisconnect") + self.ClientIP = {} + self.ClientZones = {} + self.ClientDOIDbase = {} + self.ClientObjects = {} + self.DOIDnext = 1 + self.DOIDrange = 1000000 + self.DOIDtoClients = {} + self.DOIDtoZones = {} + self.DOIDtoDClass = {} + self.ZonesToClients = {} + self.ZonetoDOIDs = {} + self.RemovedDOIDs = [] + self.dcFile = DCFile() + self.dcSuffix = '' + self.readDCFile() def importModule(self, dcImports, moduleName, importSymbols): """ Imports the indicated moduleName and all of its symbols @@ -172,12 +172,12 @@ class ServerRepository: # Crazy dereferencing newConnection=newConnection.p() self.qcr.addConnection(newConnection) - # Add clients infomation to dictionary - self.ClientIP[newConnection] = netAddress.getIpString() - self.ClientZones[newConnection] = [] - self.ClientObjects[newConnection] = [] + # Add clients infomation to dictionary + self.ClientIP[newConnection] = netAddress.getIpString() + self.ClientZones[newConnection] = [] + self.ClientObjects[newConnection] = [] self.lastConnection = newConnection - self.sendDOIDrange(self.lastConnection) + self.sendDOIDrange(self.lastConnection) else: self.notify.warning( "getNewConnection returned false") @@ -187,7 +187,7 @@ class ServerRepository: def readerPollUntilEmpty(self, task): while self.readerPollOnce(): - pass + pass return Task.cont # checks for available messages to the server @@ -198,7 +198,7 @@ class ServerRepository: datagram = NetDatagram() readRetVal = self.qcr.getData(datagram) if readRetVal: - # need to send to message processing unit + # need to send to message processing unit self.handleDatagram(datagram) else: self.notify.warning("getData returned false") @@ -207,97 +207,97 @@ class ServerRepository: # switching station for messages def handleDatagram(self, datagram): - dgi = DatagramIterator.DatagramIterator(datagram) - type = dgi.getUint16() + dgi = DatagramIterator.DatagramIterator(datagram) + type = dgi.getUint16() - if type == CLIENT_DISCONNECT: - self.handleClientDisconnect(datagram.getConnection()) - elif type == CLIENT_SET_ZONE: - self.handleSetZone(dgi, datagram.getConnection()) - elif type == CLIENT_REMOVE_ZONE: - self.handleRemoveZone(dgi, datagram.getConnection()) - elif type == CLIENT_CREATE_OBJECT_REQUIRED: - self.handleClientCreateObjectRequired(datagram, dgi) - elif type == CLIENT_OBJECT_UPDATE_FIELD: - self.handleClientUpdateField(datagram, dgi) - elif type == CLIENT_OBJECT_DELETE: - self.handleClientDeleteObject(datagram, dgi.getUint32()) - elif type == CLIENT_OBJECT_DISABLE: - self.handleClientDisable(datagram, dgi.getUint32()) - else: + if type == CLIENT_DISCONNECT: + self.handleClientDisconnect(datagram.getConnection()) + elif type == CLIENT_SET_ZONE: + self.handleSetZone(dgi, datagram.getConnection()) + elif type == CLIENT_REMOVE_ZONE: + self.handleRemoveZone(dgi, datagram.getConnection()) + elif type == CLIENT_CREATE_OBJECT_REQUIRED: + self.handleClientCreateObjectRequired(datagram, dgi) + elif type == CLIENT_OBJECT_UPDATE_FIELD: + self.handleClientUpdateField(datagram, dgi) + elif type == CLIENT_OBJECT_DELETE: + self.handleClientDeleteObject(datagram, dgi.getUint32()) + elif type == CLIENT_OBJECT_DISABLE: + self.handleClientDisable(datagram, dgi.getUint32()) + else: self.notify.error("unrecognized message") # client wants to create an object, so we store appropriate data, # and then pass message along to corresponding zones def handleClientCreateObjectRequired(self, datagram, dgi): - connection = datagram.getConnection() + connection = datagram.getConnection() # no need to create a new message, just forward the received - # message as it has the same msg type number - zone = dgi.getUint32() - classid = dgi.getUint16() - doid = dgi.getUint32() - rest = dgi.getRemainingBytes() - datagram = NetDatagram() - datagram.addUint16(CLIENT_CREATE_OBJECT_REQUIRED) - datagram.addUint16(classid) - datagram.addUint32(doid) - datagram.appendData(rest) - dclass = self.dclassesByNumber[classid] - if self.ClientObjects[connection].count(doid) == 0: - self.ClientObjects[connection].append(doid) - self.DOIDtoZones[doid] = zone - self.DOIDtoDClass[doid] = dclass - if zone in self.ZonetoDOIDs: - if self.ZonetoDOIDs[zone].count(doid)==0: - self.ZonetoDOIDs[zone].append(doid) - else: - self.ZonetoDOIDs[zone] = [doid] - self.sendToZoneExcept(zone, datagram, connection) - return None + # message as it has the same msg type number + zone = dgi.getUint32() + classid = dgi.getUint16() + doid = dgi.getUint32() + rest = dgi.getRemainingBytes() + datagram = NetDatagram() + datagram.addUint16(CLIENT_CREATE_OBJECT_REQUIRED) + datagram.addUint16(classid) + datagram.addUint32(doid) + datagram.appendData(rest) + dclass = self.dclassesByNumber[classid] + if self.ClientObjects[connection].count(doid) == 0: + self.ClientObjects[connection].append(doid) + self.DOIDtoZones[doid] = zone + self.DOIDtoDClass[doid] = dclass + if zone in self.ZonetoDOIDs: + if self.ZonetoDOIDs[zone].count(doid)==0: + self.ZonetoDOIDs[zone].append(doid) + else: + self.ZonetoDOIDs[zone] = [doid] + self.sendToZoneExcept(zone, datagram, connection) + return None # client wants to update an object, forward message along # to corresponding zone - def handleClientUpdateField(self, datagram, dgi): - connection = datagram.getConnection() - doid = dgi.getUint32() - fieldid = dgi.getUint16() - dclass = self.DOIDtoDClass[doid] - dcfield = dclass.getField(fieldid) + def handleClientUpdateField(self, datagram, dgi): + connection = datagram.getConnection() + doid = dgi.getUint32() + fieldid = dgi.getUint16() + dclass = self.DOIDtoDClass[doid] + dcfield = dclass.getField(fieldid) if (dcfield.isBroadcast()): - if (dcfield.isP2p()): - self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0) - else: - self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, connection) - elif (dcfield.isP2p()): - self.cw.send(datagram, self.DOIDtoClients[doid]) - else: + if (dcfield.isP2p()): + self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0) + else: + self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, connection) + elif (dcfield.isP2p()): + self.cw.send(datagram, self.DOIDtoClients[doid]) + else: self.notify.warning( - "Message is not broadcast, p2p, or broadcast+p2p") - return None + "Message is not broadcast, p2p, or broadcast+p2p") + return None # client disables an object, let everyone know who is in # that zone know about it def handleClientDisable(self, datagram, doid): - # now send disable message to all clients that need to know - if doid in self.DOIDtoZones: - self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0) - return None + # now send disable message to all clients that need to know + if doid in self.DOIDtoZones: + self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0) + return None # client deletes an object, let everyone who is in zone with # object know about it def handleClientDeleteObject(self, datagram, doid): - if doid in self.DOIDtoZones: - self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0) - self.ClientObjects[datagram.getConnection()].remove(doid) - self.ZonetoDOIDs[self.DOIDtoZones[doid]].remove(doid) - del self.DOIDtoZones[doid] - del self.DOIDtoDClass[doid] - return None + if doid in self.DOIDtoZones: + self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0) + self.ClientObjects[datagram.getConnection()].remove(doid) + self.ZonetoDOIDs[self.DOIDtoZones[doid]].remove(doid) + del self.DOIDtoZones[doid] + del self.DOIDtoDClass[doid] + return None def sendAvatarGenerate(self): datagram = PyDatagram() @@ -314,104 +314,104 @@ class ServerRepository: # sends the client the range of doid's that the client can use def sendDOIDrange(self, connection): - # reuse DOID assignments if we can - if len(self.RemovedDOIDs) > 0: - id = self.RemovedDOIDs[0] - self.RemovedDOIDs.remove(id) - else: - id = self.DOIDnext + self.DOIDrange - self.DOIDnext = self.DOIDnext + self.DOIDrange - self.DOIDtoClients[id] = connection - self.ClientDOIDbase[connection] = id - datagram = NetDatagram() - datagram.addUint16(CLIENT_SET_DOID_RANGE) - datagram.addUint32(id) - datagram.addUint32(self.DOIDrange) - print "Sending DOID range: ",id,self.DOIDrange - self.cw.send(datagram, connection) - return None + # reuse DOID assignments if we can + if len(self.RemovedDOIDs) > 0: + id = self.RemovedDOIDs[0] + self.RemovedDOIDs.remove(id) + else: + id = self.DOIDnext + self.DOIDrange + self.DOIDnext = self.DOIDnext + self.DOIDrange + self.DOIDtoClients[id] = connection + self.ClientDOIDbase[connection] = id + datagram = NetDatagram() + datagram.addUint16(CLIENT_SET_DOID_RANGE) + datagram.addUint32(id) + datagram.addUint32(self.DOIDrange) + print "Sending DOID range: ",id,self.DOIDrange + self.cw.send(datagram, connection) + return None # a client disconnected from us, we need to update our data, also tell other clients to remove # the disconnected clients objects def handleClientDisconnect(self, connection): - if (self.ClientIP.has_key(connection)): - self.RemovedDOIDs.append(self.ClientDOIDbase[connection]) - del self.DOIDtoClients[self.ClientDOIDbase[connection]] - for zone in self.ClientZones[connection]: - if len(self.ZonesToClients[zone]) == 1: - del self.ZonesToClients[zone] - else: - self.ZonesToClients[zone].remove(connection) - for obj in self.ClientObjects[connection]: - #create and send delete message - datagram = NetDatagram() - datagram.addUint16(CLIENT_OBJECT_DELETE_RESP) - datagram.addUint32(obj) - self.sendToZoneExcept(self.DOIDtoZones[obj], datagram, 0) - self.ZonetoDOIDs[self.DOIDtoZones[obj]].remove(obj) - del self.DOIDtoZones[obj] - del self.DOIDtoDClass[obj] - del self.ClientIP[connection] - del self.ClientZones[connection] - del self.ClientDOIDbase[connection] - del self.ClientObjects[connection] - self.RemovedDOIDs.sort() - return None + if (self.ClientIP.has_key(connection)): + self.RemovedDOIDs.append(self.ClientDOIDbase[connection]) + del self.DOIDtoClients[self.ClientDOIDbase[connection]] + for zone in self.ClientZones[connection]: + if len(self.ZonesToClients[zone]) == 1: + del self.ZonesToClients[zone] + else: + self.ZonesToClients[zone].remove(connection) + for obj in self.ClientObjects[connection]: + #create and send delete message + datagram = NetDatagram() + datagram.addUint16(CLIENT_OBJECT_DELETE_RESP) + datagram.addUint32(obj) + self.sendToZoneExcept(self.DOIDtoZones[obj], datagram, 0) + self.ZonetoDOIDs[self.DOIDtoZones[obj]].remove(obj) + del self.DOIDtoZones[obj] + del self.DOIDtoDClass[obj] + del self.ClientIP[connection] + del self.ClientZones[connection] + del self.ClientDOIDbase[connection] + del self.ClientObjects[connection] + self.RemovedDOIDs.sort() + return None # client told us it's zone(s), store information def handleSetZone(self, dgi, connection): - while dgi.getRemainingSize() > 0: - ZoneID = dgi.getUint32() - if self.ClientZones[connection].count(ZoneID) == 0: - self.ClientZones[connection].append(ZoneID) - if ZoneID in self.ZonesToClients: - if self.ZonesToClients[ZoneID].count(connection) == 0: - self.ZonesToClients[ZoneID].append(connection) - else: - self.ZonesToClients[ZoneID] = [connection] + while dgi.getRemainingSize() > 0: + ZoneID = dgi.getUint32() + if self.ClientZones[connection].count(ZoneID) == 0: + self.ClientZones[connection].append(ZoneID) + if ZoneID in self.ZonesToClients: + if self.ZonesToClients[ZoneID].count(connection) == 0: + self.ZonesToClients[ZoneID].append(connection) + else: + self.ZonesToClients[ZoneID] = [connection] - # We have a new member, need to get all of the data from clients who may have objects in this zone - datagram = NetDatagram() - datagram.addUint16(CLIENT_REQUEST_GENERATES) - datagram.addUint32(ZoneID) - self.sendToAll(datagram) - print "SENDING REQUEST GENERATES (",ZoneID,") TO ALL" - return None + # We have a new member, need to get all of the data from clients who may have objects in this zone + datagram = NetDatagram() + datagram.addUint16(CLIENT_REQUEST_GENERATES) + datagram.addUint32(ZoneID) + self.sendToAll(datagram) + print "SENDING REQUEST GENERATES (",ZoneID,") TO ALL" + return None # client has moved zones, need to update them def handleRemoveZone(self, dgi, connection): - while dgi.getRemainingSize() > 0: - ZoneID = dgi.getUint32() - if self.ClientZones[connection].count(ZoneID) == 1: - self.ClientZones[connection].remove(ZoneID) - if ZoneID in self.ZonesToClients: - if self.ZonesToClients[ZoneID].count(connection) == 1: - self.ZonesToClients[ZoneID].remove(connection) - for i in self.ZonetoDOIDs[ZoneID]: - datagram = NetDatagram() - datagram.addUint16(CLIENT_OBJECT_DELETE) - datagram.addUint32(i) - self.cw.send(datagram, connection) - return None + while dgi.getRemainingSize() > 0: + ZoneID = dgi.getUint32() + if self.ClientZones[connection].count(ZoneID) == 1: + self.ClientZones[connection].remove(ZoneID) + if ZoneID in self.ZonesToClients: + if self.ZonesToClients[ZoneID].count(connection) == 1: + self.ZonesToClients[ZoneID].remove(connection) + for i in self.ZonetoDOIDs[ZoneID]: + datagram = NetDatagram() + datagram.addUint16(CLIENT_OBJECT_DELETE) + datagram.addUint32(i) + self.cw.send(datagram, connection) + return None # client did not tell us he was leaving but we lost connection to him, so we need to update our data and tell others def clientHardDisconnectTask(self, task): - for i in self.ClientIP.keys(): - if (not self.qcr.isConnectionOk(i)): - self.handleClientDisconnect(i) - return Task.cont + for i in self.ClientIP.keys(): + if (not self.qcr.isConnectionOk(i)): + self.handleClientDisconnect(i) + return Task.cont - # sends a message to everyone who is in the zone - def sendToZoneExcept(self, ZoneID, datagram, connection): - if ZoneID in self.ZonesToClients: - for conn in self.ZonesToClients[ZoneID]: - if (conn != connection): self.cw.send(datagram, conn) - return None + # sends a message to everyone who is in the zone + def sendToZoneExcept(self, ZoneID, datagram, connection): + if ZoneID in self.ZonesToClients: + for conn in self.ZonesToClients[ZoneID]: + if (conn != connection): self.cw.send(datagram, conn) + return None # sends a message to all connected clients def sendToAll(self, datagram): - for client in self.ClientIP.keys(): + for client in self.ClientIP.keys(): self.cw.send(datagram, client) - return None + return None