class Network():
	def __init__(self):
		self.c_manager = QueuedConnectionManager()
		self.c_listener = QueuedConnectionListener(self.c_manager, 0)
		self.c_reader = QueuedConnectionReader(self.c_manager, 0)
		self.c_writer = ConnectionWriter(self.c_manager,0)

		self.active_conns=[]

		self.port_address=9099 #No-other TCP/IP services are using this port
		self.backlog=1000 #If we ignore 1,000 connection attempts, something is wrong!

		#tcp_socket = c_manager.openTCPServerRendezvous(port_address,backlog)
		#self.tcp_socket = self.c_manager.openTCPServerRendezvous("0.0.0.0", 9099, 1000)
		#self.c_listener.addConnection(self.tcp_socket)

	def tsk_listener_pol(self, taskdata):
		if self.c_listener.newConnectionAvailable():

			rendezvous = PointerToConnection()
			netAddress = NetAddress()
			newConnection = PointerToConnection()

			if self.c_listener.getNewConnection(rendezvous,netAddress,newConnection):
				print("Connected: "+str(netAddress))
				newConnection = newConnection.p()
				self.active_conns.append(newConnection) # Remember connection
				self.c_reader.addConnection(newConnection)     # Begin reading connection
		return Task.cont

	def tsk_reader_pol(self, taskdata):
		if self.c_reader.dataAvailable():
			datagram=NetDatagram()  # catch the incoming data in this instance
			# Check the return value; if we were threaded, someone else could have
			# snagged this data before we did
			if self.c_reader.getData(datagram):
				self.data_process(datagram)
		return Task.cont

	def data_process(self, datagram):
			it = PyDatagramIterator(datagram)
			message = it.getString()
			print("Processed: "+message+" from: "+str(datagram.getAddress()))

	def listen(self):
		print("Now listening on all addresses on port 9099")
		self.tcp_socket = self.c_manager.openTCPServerRendezvous("0.0.0.0", 9099, 1000)
		self.c_listener.addConnection(self.tcp_socket)
		taskMgr.add(self.tsk_listener_pol, "Poll connection listener", -39)
		taskMgr.add(self.tsk_reader_pol, "Pol the connection reader", -40)

	def unlisten(self):
		print("Stopping listen")
		self.c_manager.closeConnection(self.tcp_socket)
class Server(ClientServerBase):
    def __init__(self, host="localhost", port=5001, name="server"):
        super().__init__(host=host, port=port, name=name)
        # self.setReaderCallback( sel.ProcessReaderData )

        backlog = 1000
        self.tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog)
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cListener.addConnection(self.tcpSocket)

        self.taskMgr.add(self.tskListenerPolling,
                         "Poll the connection listener", -39)

    def tskListenerPolling(self, taskdata):
        if self.cListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            if self.cListener.getNewConnection(rendezvous, netAddress,
                                               newConnection):
                newConnection = newConnection.p()
                self.connections.append(newConnection)  # Remember connection
                self.cReader.addConnection(
                    newConnection)  # Begin reading connection
                print("server: received new connection!")
        return Task.cont

    # TODO(victor): what happens when a connection drops away?

    def BroadcastMessage(self, datagram):
        # send the same message to all clients
        for con in self.connections:
            self.cWriter.send(datagram, con)

    # def ProcessReaderData( self, data ):
    #     # TODO(vicdie): overwrite in derived classes
    #     pass

    def Close(self):
        # remove all clients
        for con in self.connections:
            self.cReader.removeConnection(con)
        self.connections = []
        self.cManager.closeConnection(self.tcpSocket)
Beispiel #3
0
class TCP():
    def __init__(self, _core):
        print("TCP Protocol Startup...")
        self.core = _core
        self.config = self.core.server.config

    def start(self):
        self.setupTCP()
        self.startTCPTasks()

    def setupTCP(self):
        self.tcpManager = QueuedConnectionManager()
        self.tcpReader = QueuedConnectionReader(self.tcpManager, 0)
        self.tcpWriter = ConnectionWriter(self.tcpManager, 0)
        self.tcpListener = QueuedConnectionListener(self.tcpManager, 0)

        self.tcpSocket = self.tcpManager.openTCPServerRendezvous(
            self.config.TCPPORT, self.config.BACKLOG)
        self.tcpListener.addConnection(self.tcpSocket)
        print("Started Server on: ", self.config.HOSTNAME, self.config.TCPPORT)

    def startTCPTasks(self):
        taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0)
        print("TCP Listener Started")
        taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10)
        print("TCP Reader Started")
        taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler",
                    20)
        print("TCP Disconnection Handler Started")

    # TCP Listener Task
    def tcpListenerTask(self, task):
        """
        Accept new incoming connection from clients, related to TCP
        """
        # Handle new connection
        if self.tcpListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()

            if self.tcpListener.getNewConnection(rendezvous, netAddress,
                                                 newConnection):
                newConnection = newConnection.p()

                # Tell the reader about the new TCP connection
                self.tcpReader.addConnection(newConnection)

                # Handle the connection depending on persistent or not
                if self.core.server.isPersistent:
                    self.core.handleConnection(generateUUID(), newConnection,
                                               netAddress)
                else:
                    self.core.createPlayerObject(generateUUID(), newConnection,
                                                 netAddress)

                print("Server: New Connection from -",
                      str(netAddress.getIpString()))
            else:
                print("Server: Connection Failed from -",
                      str(netAddress.getIpString()))

        return Task.cont

    def tcpReaderTask(self, task):
        """
        Handle any data from clients by sending it to the Handlers.
        """
        while 1:
            (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader)
            if opcode is MSG_NONE:
                # Do nothing or use it as some 'keep_alive' thing.
                break
            else:
                # Handle it
                self.core.packetManager.handlePacket(opcode, data,
                                                     datagram.getAddress())

        return Task.cont

    # TCP NonBlockingRead??
    def tcpNonBlockingRead(self, qcr):
        """
        Return a datagram collection and type if data is available on
        the queued connection udpReader
        """
        if self.tcpReader.dataAvailable():
            datagram = NetDatagram()
            if self.tcpReader.getData(datagram):
                data = DatagramIterator(datagram)
                opcode = data.getUint8()

            else:
                data = None
                opcode = MSG_NONE

        else:
            datagram = None
            data = None
            opcode = MSG_NONE

        # Return the datagram to keep a handle on the data
        return (datagram, data, opcode)

    # TCP Disconnection Handler
    def tcpDisconnectionHandler(self, task):
        # Check for resets
        if self.tcpManager.resetConnectionAvailable():
            resetConnection = PointerToConnection()
            self.tcpManager.getResetConnection(resetConnection)

            for client in self.core.server.clients:
                if self.core.server.clients[
                        client].connection == resetConnection.p():
                    del self.core.server.clients[client]
                    self.tcpReader.removeConnection(resetConnection.p())
                    print("Removed Connection:", resetConnection.p())
                    print('Current Clients:', self.core.server.clients)
                    break

        return Task.cont

    def sendPacket(self, _pkt, _connection):
        self.tcpWriter.send(_pkt, _connection)

    def sendBroadcast(self, _pkt, _skipif=None):
        for client in self.serverManager.clients:
            if _skipif == client:
                pass
            else:
                conn = self.serverManager.clients[client].connection
                self.tcpWriter.send(_pkt, conn)
Beispiel #4
0
class TCP():

    def __init__(self, _core):
        print ("TCP Protocol Startup...")
        self.core = _core
        self.config = self.core.server.config


    def start(self):
        self.setupTCP()
        self.startTCPTasks()


    def setupTCP(self):
        self.tcpManager = QueuedConnectionManager()
        self.tcpReader = QueuedConnectionReader(self.tcpManager, 0)
        self.tcpWriter = ConnectionWriter(self.tcpManager, 0)
        self.tcpListener = QueuedConnectionListener(self.tcpManager, 0)

        self.tcpSocket = self.tcpManager.openTCPServerRendezvous(self.config.TCPPORT, self.config.BACKLOG)
        self.tcpListener.addConnection(self.tcpSocket)
        print ("Started Server on: ", self.config.HOSTNAME, self.config.TCPPORT)


    def startTCPTasks(self):
        taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0)
        print ("TCP Listener Started")
        taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10)
        print ("TCP Reader Started")
        taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler", 20)
        print ("TCP Disconnection Handler Started")

    # TCP Listener Task
    def tcpListenerTask(self, task):
        """
        Accept new incoming connection from clients, related to TCP
        """
        # Handle new connection
        if self.tcpListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            
            if self.tcpListener.getNewConnection(rendezvous, netAddress, newConnection):
                newConnection = newConnection.p()
                
                # Tell the reader about the new TCP connection
                self.tcpReader.addConnection(newConnection)

                # Handle the connection depending on persistent or not
                if self.core.server.isPersistent:
                    self.core.handleConnection(generateUUID(), newConnection, netAddress)
                else:
                    self.core.createPlayerObject(generateUUID(),newConnection, netAddress)
                    
                print ("Server: New Connection from -", str(netAddress.getIpString()))
            else:
                print ("Server: Connection Failed from -", str(netAddress.getIpString()))    
                    
            
        return Task.cont


    def tcpReaderTask(self, task):
        """
        Handle any data from clients by sending it to the Handlers.
        """
        while 1:
            (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader)
            if opcode is MSG_NONE:
                # Do nothing or use it as some 'keep_alive' thing.
                break
            else:
                # Handle it
                self.core.packetManager.handlePacket(opcode, data, datagram.getAddress())
                
        return Task.cont


    # TCP NonBlockingRead??
    def tcpNonBlockingRead(self, qcr):
        """
        Return a datagram collection and type if data is available on
        the queued connection udpReader
        """
        if self.tcpReader.dataAvailable():
            datagram = NetDatagram()
            if self.tcpReader.getData(datagram):
                data = DatagramIterator(datagram)
                opcode = data.getUint8()

            else:
                data = None
                opcode = MSG_NONE

        else:
            datagram = None
            data = None
            opcode = MSG_NONE

        # Return the datagram to keep a handle on the data
        return (datagram, data, opcode)


    # TCP Disconnection Handler
    def tcpDisconnectionHandler(self, task):
        # Check for resets
        if self.tcpManager.resetConnectionAvailable():
            resetConnection = PointerToConnection()
            self.tcpManager.getResetConnection(resetConnection)
            
            for client in self.core.server.clients:
                if self.core.server.clients[client].connection == resetConnection.p():
                    del self.core.server.clients[client]
                    self.tcpReader.removeConnection(resetConnection.p())
                    print ("Removed Connection:", resetConnection.p())
                    print ('Current Clients:', self.core.server.clients)
                    break

        return Task.cont


    def sendPacket(self, _pkt, _connection):
        self.tcpWriter.send(_pkt, _connection)


    def sendBroadcast(self, _pkt, _skipif=None):
        for client in self.serverManager.clients:
            if _skipif == client:
                pass
            else:
                conn = self.serverManager.clients[client].connection
                self.tcpWriter.send(_pkt, conn)
Beispiel #5
0
class Server:
    def __init__(self):

        self.port = 5555
        self.addr = "127.0.0.1"
        self.backlog = 7
        self.active_connections = dict()
        self.start = False

        self.connect()

    def connect(self) -> None:
        # Handle connections and terminations
        self.manager = QueuedConnectionManager()
        # Wait for clients connection requests
        self.listener = QueuedConnectionListener(self.manager, 0)
        # Buffers incoming data from active connection
        self.reader = QueuedConnectionReader(self.manager, 0)
        # Transmit PyDatagrams to active connection
        self.writer = ConnectionWriter(self.manager, 0)
        # Open TCP Rendezvous to accept client connections with a limit
        self.socket = self.manager.openTCPServerRendezvous(
            self.port, self.backlog)
        self.listener.addConnection(self.socket)
        print("Server listening on port %s...." % str(self.port))
        # Listen for mew incoming connections
        taskMgr.add(self.handle_incoming_connections,
                    "Poll the connection listener", -39)
        # Listen for new datagrams
        taskMgr.add(self.handle_connection_data,
                    "Poll the connection reader", -40)
        # Listen for dropped connections
        taskMgr.add(self.handle_dropped_connections,
                    "Poll the dropped connection listener", -41)
        # See if game can be started
        taskMgr.add(self.start_game, "Start Game", -42)

    def start_game(self, task_data: Task) -> Task:
        if len(self.active_connections) == self.backlog:
            self.start = True
        return Task.cont

    def handle_incoming_connections(self, task_data: Task) -> Task:
        if self.listener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            net_addr = NetAddress()
            new_connection = PointerToConnection()
            if self.listener.getNewConnection(rendezvous, net_addr, new_connection):
                new_connection = new_connection.p()
                # Keep track of our active connections
                self.active_connections[str(
                    new_connection.this)] = new_connection
                # Start reading the new connection
                self.reader.addConnection(new_connection)
                print("%s just connected" % str(new_connection))
        return Task.cont

    def handle_connection_data(self, task_data: Task) -> Task:
        if self.reader.dataAvailable():
            # Catch the incoming data
            datagram = NetDatagram()
            if self.reader.getData(datagram):
                name = self.handle_client_message(datagram)
                broadcast = f"Everyone, welcome {name} to the game!"
                self.broadcast_message(broadcast)

        return Task.cont

    def handle_dropped_connections(self, task_data: Task) -> Task:
        if self.manager.resetConnectionAvailable():
            connection_pointer = PointerToConnection()
            self.manager.getResetConnection(connection_pointer)
            lost_connection = connection_pointer.p()
            print("% s disconnected from server" % str(lost_connection))
            del self.active_connections[str(lost_connection.this)]
            self.manager.closeConnection(lost_connection)
        return Task.cont

    def handle_client_message(self, message: str) -> str:
        iterator = PyDatagramIterator(message)
        return iterator.getString()

    def get_connections_count(self) -> int:
        return len(self.active_connections)

    def send_personal_message(self, message: str, client: PointerToConnection) -> None:
        datagram = self.create_new_datagram(message)
        self.writer.send(datagram, client)

    def broadcast_message(self, message: str) -> None:
        datagram = self.create_new_datagram(message)
        for client in self.active_connections:
            self.writer.send(datagram, self.active_connections[client])

    def create_new_datagram(self, message: str) -> PyDatagram:
        new_datagram = PyDatagram()
        new_datagram.addString(message)
        return new_datagram

    def terminate_all_clients(self) -> None:
        for client in self.active_connections:
            self.reader.removeConnection(client)
        self.active_connections = list()

    def terminate_specific_client(self, client: PointerToConnection) -> None:
        self.reader.removeConnection(client)
        del self.active_connections[str(client)]
Beispiel #6
0
class ConnectionManager:
    notify = DirectNotifyGlobal.directNotify.newCategory("ConnectionManager")

    def __init__(self):
        self.socket = None
        self.hostName = None
        self.port = None

        self.ourChannel = 100001

        self.cManager = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.cWriter = ConnectionWriter(self.cManager, 0)

    def start(self):
        self.hostName = base.configManager.getString('host-name', '127.0.0.1')
        self.port = base.configManager.getInt('port-number', 6667)

        self.socket = self.cManager.openTCPServerRendezvous(
            self.hostName, self.port, 1000)
        if self.socket:
            self.cListener.addConnection(self.socket)
            self._serverStarted(self.hostName, self.port)
            taskMgr.add(self._socketListener, 'Connection Listener')
            taskMgr.add(self._socketReader, 'Connection Reader')
        else:
            self.notify.warning(
                "Unable to start server on %s:%d - is the port in use?" %
                (self.hostName, self.port))
            base.logManager.writeServerEvent(
                'ServerBase',
                'Unable to start server on %s:%d - is the port in use?' %
                (self.hostName, self.port))
            sys.exit()

    def _serverStarted(self, host, port):
        self.notify.warning("Server started on %s:%d" % (host, port))
        base.logManager.writeServerEvent(
            'ServerBase', 'Server started on %s:%d' % (host, port))

    def _socketListener(self, task):
        if self.cListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()

            if self.cListener.getNewConnection(rendezvous, netAddress,
                                               newConnection):
                newConnection = newConnection.p()
                base.activeConnections[newConnection] = NetworkedClient()
                self.cReader.addConnection(newConnection)
                self.notify.warning("New Unauthed Client Connected: %s" %
                                    (netAddress))

        return Task.cont

    def _socketReader(self, task):
        if self.cReader.dataAvailable():
            datagram = NetDatagram()

            if self.cReader.getData(datagram):
                base.messageManager.handleMessage(datagram)

        return Task.cont
class NetworkHost ():
    """
        Handles networking with one or more clients. This class is essentially
         a server that handles the communication of GameManager's game logic.
        One player will have a NetworkHost and the rest of players will have
         NetworkClients.
    """
    def __init__ (self, gameManager):
        self._connManager = QueuedConnectionManager()
        self._loadConfig()
        self._activeConns = [] # Active connections list.
        self._isActive = False
        self._backlog = HOST_MAX_BACKLOG
        self._gameManager = gameManager
        self._playerInfo = dict() # connections by connectionID (cID)
        self._creatures = dict() # Creatures by cID.
        self._localPlayerCID = None
        self._creatureIDCount = 0

    def _initListener (self):
        """
            Initializes this NetworkHost's connection listener.
        """
        self._connListener = QueuedConnectionListener(self._connManager, 0)
        self._tcpSocket = connManager.openTCPServerRendezvous(self._portAddress,
                                                              self._backlog)
        self._connListener.addConnection(self._tcpSocket)

    def _loadConfig (self):
        """
            Loads network configuration defaults.
        """
        self._portAddress = ConfigVariableInt("default-port",
                                              DEFAULT_PORT).getValue()

    def startHost (self):
        """
            Finishes initialization and begins listening.
        """
        # Initialize Reader and Writer:
        self._connReader = QueuedConnectionReader(self._connManager, 0)
        self._connWriter = ConnectionWriter(self._connManager, 0)
        # Initialize Listener:
        self._connListener = QueuedConnectionListener(self._connManager, 0)
        self._tcpSocket = self._connManager.openTCPServerRendezvous(
                                            self._portAddress, self._backlog)
        self._connListener.addConnection(self._tcpSocket)
        # Begin handling messages (start listening):
        taskMgr.add(self._onListenerPoll,"Poll the connection listener",-39)
        taskMgr.add(self._onReaderPoll,"Poll the connection reader",-40)
        self._isActive = True
        print ("[Host Started at %s]" % socket.gethostbyname(
                                            socket.gethostname()))

        self._gameManager.onHostInitialized()

    def _onListenerPoll(self, taskdata):
        """
            Updates list of connections based on the listener's current
             findings.
            Does not read messages. See onReaderPoll().
            (Assumes self._connListener has been initialized)
        """
        # Check for new connections:
        if self._connListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            # If we have a new connection, add it to our list:
            if self._connListener.getNewConnection(rendezvous,netAddress,
                                                   newConnection):
                newConnection = newConnection.p()
                print ("[Host Received New Connection: %s]" % netAddress)
                self._activeConns.append(newConnection)
                # Begin reading messages from this new connection:
                self._connReader.addConnection(newConnection)
                # activate the onClientConnected functionalities:
                self.onClientConnected(newConnection)
        return Task.cont # Repeat this call on an interval

    def _onReaderPoll (self, taskdata):
        """
            Called on an interval to interpret messages from the reader.
        """
        if self._connReader.dataAvailable():
            newDatagram = NetDatagram()
            # Double check to make sure (Multithreading safety):
            if self._connReader.getData(newDatagram):
                self._interpretDatagram(newDatagram)
        return Task.cont # Repeat this call on an interval

    def sendToClient (self, newMsg, conn, msgType):
        """
            Sends a new message to a client at the other end of conn.
        """
        print("[Server Sending %s message type %s]"%(str(conn), str(msgType)))
        self._connWriter.send(newMsg, conn)

    def sendToAll (self, newMsg, msgType):
        """
            Writes and sends a new message to all connected clients.
        """
        for conn in self._activeConns:
            self.sendToClient(newMsg, conn, msgType)

    def _interpretDatagram (self, datagram):
        """
            Interprets a received datagram and performs actions based on its
             values.
        """
        msg = PyDatagramIterator(datagram)
        msgType = msg.getUint8()
        if msgType == DEBUG_MESSAGE:
            print (msg.getString())
        elif msgType == UPDATE_PLAYER_INFO:
            data = msg.getString()
            self._updatePlayerInfoHandler(datagram.getConnection().this, data)
        elif msgType == SPAWN_CHARACTER:
            data = msg.getString()
            dataDict = json.loads(data)
            self._onSpawnHandler(dataDict)
        elif msgType == SYNC_ACTION:
            data = msg.getString()
            dataDict = json.loads(data)
            self._onActionSyncHandler(dataDict, datagram.getConnection())
        elif msgType == SYNC_RESPAWN:
            data = msg.getString()
            dataDict = json.loads(data)
            self._onRespawnRequestReceived(dataDict)
        elif msgType == WIN_STATE:
            data = msg.getString()
            self._onGameWon(data)

    def isHosting (self):
        """
            Returns whether this NetworkHost is actively hosting.
        """
        return self._isActive

    def getMyCID (self):
        return self._localPlayerCID

    def registerNewCID (self):
        newCID = "host" + str(self._creatureIDCount)
        self._creatureIDCount += 1
        return newCID

    def registerLocalCID (self):
        newCID = self.registerNewCID()
        self._localPlayerCID = newCID

    # === [Local Client to Network] ===
    def onCreatureDeath (self, creature):
        """
            Sends a creature death message to all connected clients.
        """
        msg = createSyncDeathMessage(creature.getCID())
        self.sendToAll(msg, SYNC_DEATH)

    def onLocalPlayerRespawn (self, creature, newLocation):
        """
            Respawns the local player and sends a sync message to all remotes.
        """
        # Fulfill local player request to respawn:
        creature.respawn(newLocation)
        # Refill the creature's HP (Automatically syncs!):
        creature.takeDamage(-1*creature.getMaxHealth())
        # Spawn on all connected clients:
        msg = createRespawnMessage(creature.getCID(), newLocation)
        self.sendToAll(msg, SYNC_RESPAWN)

    def localPlayerWins (self):
        """
            End the game display the
             win screen.
        """
        self._gameManager.onWinStateAchieved(self._playerInfo[self.getMyCID()])
        msg = createWinMessage(self._playerInfo[self.getMyCID()])
        self.sendToAll(msg, WIN_STATE)

    def updateLocalPlayerInfo (self, info=None):
        """
            Updates info for this local player and sends it to all
             connected clients.
        """
        if not info:
            self._playerInfo[self.getMyCID()] = PlayerInfo(cID=self.getMyCID())
        else: # If info == None, we are just initializing.
            self._playerInfo[self.getMyCID()] = info
            infoMsg = createPlayerInfoMessage(info)
            self.sendToAll(infoMsg, UPDATE_PLAYER_INFO)
    # === ===

    # === [Gameplay specific] ===
    def _onGameWon (self, data):
        """
            Boo. A remote client won.
            Oh well. Still have to sync that win across all other clients.
        """
        # Show winner locally:
        winnerData = PlayerInfo(fromJson=data)
        self._gameManager.onWinStateAchieved(winnerData)
        msg = createWinMessage(winnerData)
        self.sendToAll(msg, WIN_STATE)

    def syncAction (self, cID, actionID, **kwargs):
        """
            The local player has performed an action that must be synced across
             the network. Send a message to all clients telling them to perform
             a related action on that character.
        """
        msg = createSyncActionMessage(cID, actionID, **kwargs)
        self.sendToAll(msg, SYNC_ACTION)

    def spawnGameObject (self, gameObject):
        """
            Tracks the given gameObject and sends it to all clients.
        """
        # First, track it locally:
        self._creatures[gameObject.getCID()] = gameObject
        # Send to all clients:
        msg = createSpawnCharacterMessage(gameObject, gameObject.getCID())
        self.sendToAll(msg, SPAWN_CHARACTER)

    def dropItem (self, itemEnum, pos):
        """
            Spawn a new item locally and sync!
        """
        itemID = self.registerNewCID()
        # Create item locally:
        newItem = ITEM_ID_DICT[itemEnum](self._gameManager, itemID, coords=pos)
        self._gameManager.getTileMap().spawnItem(newItem, pos)
        # Track new item:
        self._creatures[itemID] = newItem
        msg = createSpawnItemMessage(newItem)
        self.sendToAll(msg, SPAWN_ITEM)

    def _onSpawnHandler (self, dataDict):
        """ Handles networking spawning characters """
        # Spawn object locally if the object at cID doesn't already exist.
        if not dataDict['objID'] in self._creatures.keys():
            # Spawn object of charType at pos
            objectType = getCharacterTypeAsClass(dataDict['charType'])
            newPos = Point2D(dataDict['pos'][0], dataDict['pos'][1])
            newChar = objectType(parentCtrlr=None, cID=dataDict['objID'],
                                 gameManager=self._gameManager, coords=newPos)
            self._creatures[dataDict['objID']] = newChar
            self._gameManager.getTileMap().spawnObject(newChar, newPos)
            print("[Server Spawned %s]" % dataDict['objID'])
            # If we have a player info for this player, use their name for the
            #  displayName:
            if dataDict['objID'] in self._playerInfo:
                newName = self._playerInfo[dataDict['objID']].cName
                newChar.setNameDisplay(newName)
        else:
            # Ignore Overwrite
            pass
        # Tell all other clients to spawn objects:
        newMsg = createSpawnCharacterMessage(self._creatures[dataDict['objID']],
                                             dataDict['objID'])
        self.sendToAll(newMsg, SPAWN_CHARACTER)

    def _onActionSyncHandler (self, dataDict, msgConn):
        """
            Attempts to queue an action for execution on a target denoted by
             dataDict['objID']
        """
        copyMsg = createSyncActionMessage(**dataDict)

        syncedAction = ACTION_NETWORKING_DICT[dataDict['actionID']]
        # Add a few local variables to dataDict:
        targetObj = self._creatures[dataDict['objID']] # TODO Maybe make this part of dataDict!
        dataDict['tileMap'] = self._gameManager.getTileMap()
        if 'targetCID' in dataDict: # If there is another target:
            # Assign the target:
            dataDict['target'] = self._creatures[dataDict['targetCID']]
        dataDict['isServer'] = True # Let sync function know we are server

        # Create the newAction
        newAction = syncedAction(targetObj, **dataDict)
        targetObj.startAction(newAction) # queue or start the new action
        # Send action to all clients except the client that sent the sync msg:
        for client in self.getAllClientsExcept(msgConn):
            self.sendToClient(copyMsg, client, SYNC_ACTION)

    def _onRespawnRequestReceived (self, dataDict):
        """
            Respawns the remote clients character in a new position and then
             syncs to all clients (including the one who requested).
        """
        newPos = self._gameManager.getTileMap().getRandomEmptyFloor()
        targetObj = self._creatures[dataDict['objID']]
        # Set the target's HP to full and sync that:
        targetObj.takeDamage(-1*targetObj.getMaxHealth())
        targetObj.respawn(newPos)
        # Sync the respawn to all clients:
        newMsg = createRespawnMessage(targetObj.getCID(), newPos)
        self.sendToAll(newMsg, SYNC_RESPAWN)

    def getAllClientsExcept (self, exceptConn):
        clientList = list()
        for conn in self._activeConns:
            if conn != exceptConn:
                clientList.append(conn)
        return clientList

    def onClientConnected (self, clientConn):
        """
            If we have a map and/or any positional data, give it to this client.
            Also signal to the GameManager and all remote clients that a new
             player connected!
        """
        connID = clientConn.this
        tileMap = self._gameManager.getTileMap()
        if tileMap != None:
            data = tileMap.getTileMapStr()
            msg = createMapMessage(data)
            self.sendToClient(msg, clientConn, MAP_MESSAGE)
        # Send player info to the new client:
        for player in self._playerInfo:
            # Don't send an info message about the player to the same player!
            if player != connID:
                newInfoMsg = createPlayerInfoMessage(self._playerInfo[player])
                self.sendToClient(newInfoMsg, clientConn,
                                  UPDATE_PLAYER_INFO)
        # Send all creatures to the new client:
        for creatureID in self._creatures:
            newMsg = createSpawnCharacterMessage(self._creatures[creatureID],
                                                 creatureID)
            self.sendToClient(newMsg, clientConn, SPAWN_CHARACTER)

    def _updatePlayerInfoHandler (self, connID, data=None):
        """
            Adds data to self._playerInfo.
            If info doesn't exist, creates a new one for clientConn.
        """
        if data != None:
            newPlayerData = PlayerInfo(fromJson=data)
        else:
            newPlayerData = PlayerInfo(cID=connID)
        # Update the playerInfo dict with the new data:
        self._playerInfo[newPlayerData.cID] = newPlayerData
        self._gameManager.updatePartyInfo(self._playerInfo, self.getMyCID())
        # Send player info to every client:
        for player in self._playerInfo:
            newInfoMsg = createPlayerInfoMessage(self._playerInfo[player])
            #Send every player to every client:
            self.sendToAll(newInfoMsg, UPDATE_PLAYER_INFO)
        # Update the creature's floating display name locally:
        if newPlayerData.cID in self._creatures:
            self._creatures[newPlayerData.cID]\
                .setNameDisplay(newPlayerData.cName)

    def syncHealthChange (self, creatureID, newHealth):
        """
            Called after the host runs a damage/healing action on a creature.
            Lets all clients know to update to a new value.
        """
        data = createSyncHealthMessage(creatureID, newHealth)
        self.sendToAll(data, SYNC_HEALTH)
Beispiel #8
0
class NetworkManager:
    def __init__(self):
        print "Network Manager Started"

    def connection_open(self):
        self.cManager = QueuedConnectionManager()
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.cWriter = ConnectionWriter(self.cManager,0)

        self.activeConnections=[] # We'll want to keep track of these later

        self.cListener = QueuedConnectionListener(self.cManager, 0)
        port_address=9099 #No-other TCP/IP services are using this port
        backlog=1000 #If we ignore 1,000 connection attempts, something is wrong!
        self.tcpSocket = self.cManager.openTCPServerRendezvous(port_address,backlog)
        self.cListener.addConnection(self.tcpSocket)
        print "Network Connection Opened"
        taskMgr.add(self.tskListenerPolling,"Poll the connection listener",-39)
        taskMgr.add(self.tskReaderPolling,"Poll the connection reader",-40)

    def connection_close(self):
        for aClient in self.activeConnections:
            self.cReader.removeConnection(aClient)
        self.activeConnections=[]

         # close down our listener
        self.cManager.closeConnection(self.tcpSocket)
        print "Network Connection Closed"

    def tskListenerPolling(self, taskdata):
        if self.cListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            if self.cListener.getNewConnection(rendezvous,netAddress,newConnection):
                newConnection = newConnection.p()
                self.activeConnections.append(newConnection) # Remember connection
                self.cReader.addConnection(newConnection)     # Begin reading connection
        return Task.cont

    def tskReaderPolling(self, taskdata):
        if self.cReader.dataAvailable():
            datagram=NetDatagram()  # catch the incoming data in this instance
    # Check the return value; if we were threaded, someone else could have
    # snagged this data before we did
            if self.cReader.getData(datagram):
                if base.client == True:
                    self.client_processing(datagram)
                else:
                    self.server_processing(datagram)
        return Task.cont

    def server_messager(self,msg,args=[]):
        if msg == "map_set":
            order = PyDatagram()
            order.addUint16(MAP_SET)
            order.addInt32(args[0])
            self.send_package(order)
        elif msg == "client_update":
            order = PyDatagram()
            order.addUint16(CLIENT_INIT_UPDATE)
            order.addString(args[0])
            order.addString(args[1])
            order.addInt32(args[2])
            order.addInt32(args[3])
            self.send_package(order)
        elif msg == "chat_send":
            r = args[0][0]
            g = args[0][1]
            b = args[0][2]
            order = PyDatagram()
            order.addUint16(SERVER_CHAT)
            order.addInt32(r)
            order.addInt32(g)
            order.addInt32(b)
            order.addString(args[1])
            self.send_package(order)
            base.menu_manager.menus["mp-game"].chat_add((r,g,b,1),args[1])
        elif msg == "ready_button":
            order = PyDatagram()
            order.addUint16(SERVER_READY)
            order.addInt32(args[0])
            order.addInt32(args[1])
            self.send_package(order)
            base.menu_manager.menus["mp-game"].obj_list[args[0]]["indicatorValue"]=args[1]
            base.menu_manager.menus["mp-game"].start_game_check()
        elif msg == "server_loaded":
            order = PyDatagram()
            order.addUint16(SERVER_LOADED)
            self.send_package(order)
        elif msg == "all_loaded":
            order = PyDatagram()
            order.addUint16(ALL_LOADED)
            self.send_package(order)
        elif msg == "game_start":
            order = PyDatagram()
            order.addUint16(GAME_START)
            self.send_package(order)
        elif msg == "army_kill":
            order = PyDatagram()
            order.addUint16(ARMY_KILL)
            order.addInt32(args[0])
            self.send_package(order)
        elif msg == "build_start":
            order = PyDatagram()
            order.addUint16(BUILD_START)
            order.addInt32(args[0])
            order.addInt8(args[1])
            order.addString(args[2])
            self.send_package(order)
        elif msg == "tower_capture":
            order = PyDatagram()
            order.addUint16(TOWER_CAPTURE)
            order.addInt32(args[0])
            order.addInt8(args[1])
            self.send_package(order)
        elif msg == "build_complete":
            order = PyDatagram()
            order.addUint16(BUILD_COMPLETE)
            order.addInt32(args[0])
            order.addInt8(args[1])
            order.addString(args[2])
            self.send_package(order)
        elif msg == "build_cancel":
            order = PyDatagram()
            order.addUint16(BUILD_CANCEL)
            order.addInt32(args[0])
            self.send_package(order)
        elif msg == "battle_start":
            order = PyDatagram()
            order.addUint16(BATTLE_START)
            order.addInt32(args[0])
            order.addFloat32(args[1])
            order.addFloat32(args[2])
            order.addInt32(args[3])
            order.addFloat32(args[4])
            order.addFloat32(args[5])
            order.addInt32(args[6])
            self.send_package(order)
        elif msg == "battle_clash":
            order = PyDatagram()
            order.addUint16(BATTLE_CLASH)
            order.addInt32(args[0])
            order.addInt32(args[1])
            order.addInt32(args[2])
            order.addString(args[3])
            order.addInt8(args[4])
            self.send_package(order)
        elif msg == "battle_turn":
            order = PyDatagram()
            order.addUint16(BATTLE_TURN)
            order.addInt32(args[0])
            order.addInt32(args[1])
            self.send_package(order)
        elif msg == "battle_end":
            order = PyDatagram()
            order.addUint16(BATTLE_END)
            order.addInt32(args[0])
            self.send_package(order)
        elif msg == "battle_armyadd":
            order = PyDatagram()
            order.addUint16(BATTLE_ARMYADD)
            order.addInt32(args[0])
            order.addInt32(args[1])
            order.addFloat32(args[2])
            order.addFloat32(args[3])
            self.send_package(order)


    def client_messager(self,msg,args=[]):
        if msg == "chat_send":
            order = PyDatagram()
            order.addUint16(CLIENT_CHAT)
            order.addInt32(args[0][0])
            order.addInt32(args[0][1])
            order.addInt32(args[0][2])
            order.addString(args[1])
            self.send_package(order)
        elif msg == "ready_button":
            order = PyDatagram()
            order.addUint16(CLIENT_READY)
            order.addInt32(args[0])
            order.addInt32(args[1])
            self.send_package(order)
        elif msg == "client_loaded":
            order = PyDatagram()
            order.addUint16(CLIENT_LOADED)
            self.send_package(order)
        elif msg == "game_init_request":
            order = PyDatagram()
            order.addUint16(CLIENT_INIT_REQUEST)
            order.addString(args[0])
            order.addString(args[1])
            self.send_package(order)
        elif msg == "build_start_request":
            order = PyDatagram()
            order.addUint16(BUILD_START_REQUEST)
            order.addInt32(args[0])
            order.addInt32(args[1])
            order.addString(args[2])
            self.send_package(order)
        elif msg == "build_cancel_request":
            order = PyDatagram()
            order.addUint16(BUILD_CANCEL_REQUEST)
            order.addInt32(args[0])
            self.send_package(order)

    def client_processing(self,datagram):
        data_iter = PyDatagramIterator(datagram)
        msgID = data_iter.getUint16()
        if msgID == PRINT_MESSAGE:
            messageToPrint = data_iter.getString()
            print messageToPrint
        if msgID == ARMY_MOVE:
            army_id = data_iter.getInt16()
            ax = data_iter.getFloat64()
            ay = data_iter.getFloat64()
            tx = data_iter.getFloat64()
            ty = data_iter.getFloat64()
            base.armies[army_id].node_path.setX(ax)
            base.armies[army_id].node_path.setY(ay)
            base.armies[army_id].move_to_point(tx,ty)
        if msgID == CLIENT_INIT_UPDATE:
            p1_name = data_iter.getString()
            p1_kingdom = data_iter.getString()
            p1_ready = data_iter.getInt32()
            game_map = data_iter.getInt32()
            base.menu_manager.menus["mp-game"].client_update(p1_name,p1_kingdom,p1_ready,game_map)
        if msgID == SERVER_CHAT:
            r = data_iter.getInt32()
            g = data_iter.getInt32()
            b = data_iter.getInt32()
            text = data_iter.getString()
            base.menu_manager.menus["mp-game"].chat_add((r,g,b),text)
        if msgID == SERVER_READY:
            but_id = data_iter.getInt32()
            state = data_iter.getInt32()
            base.menu_manager.menus["mp-game"].obj_list[but_id]["indicatorValue"]=state
            base.menu_manager.menus["mp-game"].start_game_check()
        if msgID == SERVER_LOADED:
            base.menu_manager.menus["mp-load"].load()
        if msgID == ALL_LOADED:
            base.menu_manager.menus["mp-load"].load_complete()
        if msgID == GAME_START:
            base.menu_manager.menu_goto("mp-load")
        if msgID == MAP_SET:
            map = data_iter.getInt32()
            base.menu_manager.menus["mp-game"].map_selected = map
            mapname = base.menu_manager.menus["mp-game"].maplist[map]["fullname"]
            mapimage = base.menu_manager.menus["mp-game"].maplist[map]["preview"]
            base.menu_manager.menus["mp-game"].obj_list[11]["text"]=mapname
            base.menu_manager.menus["mp-game"].obj_list[10].setImage(mapimage)
        if msgID == BATTLE_TURN:
            bat = data_iter.getInt32()
            turn = data_iter.getInt32()
            base.battles[bat].turn_change(turn)
        if msgID == BATTLE_START:
            a1 = data_iter.getInt32()
            a1_x = data_iter.getFloat32()
            a1_y = data_iter.getFloat32()
            a2 = data_iter.getInt32()
            a2_x = data_iter.getFloat32()
            a2_y = data_iter.getFloat32()
            army_start = data_iter.getInt32()
            base.armies[a1].stop()
            base.armies[a2].stop()
            base.armies[a1].node_path.setPos(a1_x,a1_y,0)
            base.armies[a2].node_path.setPos(a2_x,a2_y,0)
            base.battles.append(TimObjects.Battle([base.armies[a1],base.armies[a2]],army_start))
        if msgID == BATTLE_CLASH:
            battle = data_iter.getInt32()
            a1 = data_iter.getInt32()
            a2 = data_iter.getInt32()
            result = data_iter.getString()
            buff = data_iter.getInt8()
            base.battles[battle].clash(base.armies[a1],base.armies[a2],result,buff)
        if msgID == BATTLE_ARMYADD:
            bat = data_iter.getInt32()
            army = data_iter.getInt32()
            a_x = data_iter.getFloat32()
            a_y = data_iter.getFloat32()
            base.battles[bat].add_army(base.armies[army])
            base.armies[army].node_path.setPos(a_x,a_y,0)
        if msgID == BATTLE_END:
            bat = data_iter.getInt32()
            base.battles[bat].end()
        if msgID == BUILD_START:
            t_id = data_iter.getInt32()
            player = data_iter.getInt8()
            type = data_iter.getString()
            base.towers[t_id].build_start()
        if msgID == TOWER_CAPTURE:
            t_id = data_iter.getInt32()
            player = data_iter.getInt8()
            base.towers[t_id].change_owner(player)
        if msgID == BUILD_CANCEL:
            t_id = data_iter.getInt32()
            base.towers[t_id].build_cancel()
        if msgID == BUILD_COMPLETE:
            t_id = data_iter.getInt32()
            player = data_iter.getInt8()
            type = data_iter.getString()
            base.towers[t_id].create_counter()

    def server_processing(self,datagram):
        data_iter = PyDatagramIterator(datagram)
        msgID = data_iter.getUint16()
        if msgID == PRINT_MESSAGE:
            messageToPrint = data_iter.getString()
            print messageToPrint
        if msgID == ARMY_MOVE_REQUEST:
            army_id = data_iter.getInt16()
            ax = data_iter.getFloat64()
            ay = data_iter.getFloat64()
            tx = data_iter.getFloat64()
            ty = data_iter.getFloat64()
            base.armies[army_id].set_target(False,tx,ty)
        if msgID == CLIENT_CHAT:
            r = data_iter.getInt32()
            g = data_iter.getInt32()
            b = data_iter.getInt32()
            text = data_iter.getString()
            self.server_messager("chat_send",[(r,g,b),text])
            #base.main_menu.chat_add((r,g,b,1),text)
        if msgID == CLIENT_READY:
            but_id = data_iter.getInt32()
            state = data_iter.getInt32()
            self.server_messager("ready_button",[but_id,state])
            #base.main_menu.chat_add((r,g,b,1),text)
        if msgID == CLIENT_LOADED:
            self.server_messager("all_loaded",[])
            base.menu_manager.menus["mp-load"].load_complete()
        if msgID == CLIENT_INIT_REQUEST:
            pn = data_iter.getString()
            pk = data_iter.getString()
            base.menu_manager.menus["mp-game"].obj_list[6]["text"] = pn
            base.menu_manager.menus["mp-game"].obj_list[7]["text"] = pk
            self.server_messager("client_update",[base.menu_manager.menus["mp-game"].obj_list[4]["text"],
                                                 base.menu_manager.menus["mp-game"].obj_list[5]["text"],
                                                 base.menu_manager.menus["mp-game"].obj_list[8]["indicatorValue"],
                                                 base.menu_manager.menus["mp-game"].map_selected])
        if msgID == BUILD_START_REQUEST:
            t_id = data_iter.getInt32()
            player = data_iter.getInt32()
            type = data_iter.getString()
            base.towers[t_id].build_start()
        if msgID == BUILD_CANCEL_REQUEST:
            t_id = data_iter.getInt32()
            player = data_iter.getInt32()
            type = data_iter.getString()
            base.towers[t_id].build_cancel()

    def msgAllClients(self):
        myPyDatagram=self.myNewPyDatagram()  # build a datagram to send
        for aClient in self.activeConnections:
            self.cWriter.send(myPyDatagram,aClient)

    def send_package(self,package):
#        print "packaged"
        for aClient in self.activeConnections:
            print "Package",package,"sent"
            self.cWriter.send(package,aClient)

    def army_move(self,army_id,tx,ty):
        order = PyDatagram()
        if base.client == True:
            order.addUint16(ARMY_MOVE_REQUEST)
        else:
            order.addUint16(ARMY_MOVE)
        ax = base.armies[army_id].node_path.getX()
        ay = base.armies[army_id].node_path.getY()
        order.addInt16(army_id)
        order.addFloat64(ax)
        order.addFloat64(ay)
        order.addFloat64(tx)
        order.addFloat64(ty)
        if base.client == True:
            self.cWriter.send(order,base.server_connection)
        else:
            self.send_package(order)
            base.armies[army_id].move_to_point(tx,ty)

    def tower_train(self,tower_id,build_object):
        order = PyDatagram()
        if base.client == True:
            order.addUint16(REQUEST_TOWER_TRAIN)
        else:
            order.addUint16(TOWER_TRAIN)
        order.addInt16(army_id)
        order.addFloat64(tx)
        order.addFloat64(ty)
        if base.client == True:
            self.cWriter.send(order,base.server_connection)
        else:
            self.send_package(order)
            base.towers[tower_id].train_counter()

#    def request_army_move(self,army_id,tx,ty):
#        order = PyDatagram()
#        order.addUint16(REQUEST_MOVE_COUNTER)
#        order.addInt16(army_id)
#        order.addFloat64(tx)
#        order.addFloat64(ty)
#        self.cWriter.send(order,base.server_connection)

    def myNewPyDatagram(self):
        # Send a test message
        myPyDatagram = PyDatagram()
        myPyDatagram.addUint16(PRINT_MESSAGE)
        myPyDatagram.addString("You got ze message!")
        return myPyDatagram

    def client_connect(self,ip):
        port_address=9099  # same for client and server

         # a valid server URL. You can also use a DNS name
         # if the server has one, such as "localhost" or "panda3d.org"
        ip_address=ip

         # how long until we give up trying to reach the server?
        timeout_in_miliseconds=3000  # 3 seconds

        base.server_connection=self.cManager.openTCPClientConnection(ip_address,port_address,timeout_in_miliseconds)

        if base.server_connection:
            self.cReader.addConnection(base.server_connection)  # receive messages from server
            self.activeConnections.append(base.server_connection)
            print "Connected to server",ip
            return True
        print "Connection failed"
        return False
Beispiel #9
0
class Server:

    def __init__(self):

        self.activeConnections = [] # lists all connections
        self.players = {} # keys are the players logins, values are the players datagram connections
        self.parties = {} # keys are the parties names, values are dicts representing parties data
        self.sessions = {} # keys are the datagram connections, values are dicts storing the characters of the player and its party
        self.playersinlobby = [] # lists players in the party screen
        self.charid = 0 # used for random team generation
        self.chars = [] # lists of dicts representing characters data

        self.cManager  = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader   = QueuedConnectionReader(self.cManager, 0)
        self.cReader.setTcpHeaderSize(4)
        self.send = Send(self.cManager)

        port = 3001
        if len(sys.argv) > 1:
            port = sys.argv[1]

        self.tcpSocket = self.cManager.openTCPServerRendezvous(port, 10)
        self.cListener.addConnection(self.tcpSocket)
        print("Server listening on port", port)

        taskMgr.add(self.tskListenerPolling, "Poll the connection listener", -39)
        taskMgr.add(self.tskReaderPolling, "Poll the connection reader", -40)

    def processData(self, datagram):
        iterator = PyDatagramIterator(datagram)
        source = datagram.getConnection()
        callback = iterator.getString()
        getattr(globals()[callback], 'execute')(self, iterator, source)

    def updateAllPartyLists(self):
        parties = deepcopy(self.parties)
        for party in list(parties.values()):
            del party['map']['tiles']

        for player in self.playersinlobby:
            self.send.UPDATE_PARTY_LIST(parties, player)

    def tskListenerPolling(self, taskdata):
        if self.cListener.newConnectionAvailable():

            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
     
            if self.cListener.getNewConnection(rendezvous, netAddress, newConnection):
                newConnection = newConnection.p()
                self.activeConnections.append(newConnection)
                self.cReader.addConnection(newConnection)
                print('A new client is connected', newConnection)
        return Task.cont

    def tskReaderPolling(self, taskdata):
        if self.cReader.dataAvailable():
            datagram=NetDatagram()
            if self.cReader.getData(datagram):
                self.processData(datagram)
        return Task.cont
Beispiel #10
0
class Server(DirectObject):
    # TODO: Perhaps a better way to do this?
    handleNewConnection = None
    handleLostConnection = None

    def __init__(self, port, backlog=1000, compress=False):
        DirectObject.__init__(self)

        self.port = port
        self.compress = compress

        self.cManager = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.cWriter = ConnectionWriter(self.cManager, 0)

        self.passedData = []

        self.connect(port, backlog)
        self.startPolling()

    def connect(self, port, backlog):
        # Bind to our socket
        tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog)
        self.cListener.addConnection(tcpSocket)

    def startPolling(self):
        self.addTask(self.tskListenerPolling, "serverListenTask", -40)
        self.addTask(self.tskDisconnectPolling, "serverDisconnectTask", -39)

    def tskListenerPolling(self, task):
        if self.cListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()

            if self.cListener.getNewConnection(rendezvous, netAddress,
                                               newConnection):
                newConnection = newConnection.p()
                newConnection.setNoDelay(True)
                newConnection.setKeepAlive(True)
                if self.handleNewConnection:
                    self.handleNewConnection(newConnection)
                self.cReader.addConnection(
                    newConnection)  # Begin reading connection
        return Task.cont

    def tskDisconnectPolling(self, task):
        while self.cManager.resetConnectionAvailable():
            connPointer = PointerToConnection()
            self.cManager.getResetConnection(connPointer)
            connection = connPointer.p()

            # Remove the connection we just found to be "reset" or "disconnected"
            self.cReader.removeConnection(connection)

            if self.handleLostConnection:
                self.handleLostConnection(connection)

        return Task.cont

    def processData(self, netDatagram):
        myIterator = PyDatagramIterator(netDatagram)
        return self.decode(myIterator.getString())

    def encode(self, data, compress=False):
        # encode(and possibly compress) the data with rencode
        return rencode.dumps(data, compress)

    def decode(self, data):
        # decode(and possibly decompress) the data with rencode
        return rencode.loads(data)

    def sendData(self, data, con):
        myPyDatagram = PyDatagram()
        myPyDatagram.addString(self.encode(data, self.compress))
        self.cWriter.send(myPyDatagram, con)

    def passData(self, data, connection):
        self.passedData.append((data, connection))

    def getData(self):
        data = self.passedData
        self.passedData = []
        while self.cReader.dataAvailable():
            datagram = NetDatagram()
            if self.cReader.getData(datagram):
                data.append(
                    (datagram.getConnection(), self.processData(datagram)))
        return data
Beispiel #11
0
class SocketTCP(ShowBase):

    def __init__(self, _parent=None):
        ShowBase.__init__(self, windowType = 'none')
        print ("TCP Protocol Startup...")
        #self.parent = _parent

        #self.config = self.parent.server.config
        # tmp config
        self.tcpport = 6000
        self.backlog = 10
        self.hostname = '127.0.0.1'

        self.sendPacketQueue = None


    def startAll(self):
        self.setupTCP()
        self.startTCPTasks()


    def setupTCP(self):
        self.tcpManager = QueuedConnectionManager()
        self.tcpReader = QueuedConnectionReader(self.tcpManager, 0)
        self.tcpWriter = ConnectionWriter(self.tcpManager, 0)
        self.tcpListener = QueuedConnectionListener(self.tcpManager, 0)

        self.tcpSocket = self.tcpManager.openTCPServerRendezvous(self.tcpport, self.backlog)
        self.tcpListener.addConnection(self.tcpSocket)
        print ("Started Server on: ", self.hostname, self.tcpport)


    def startTCPTasks(self):
        taskMgr.add(self.tcpListenerTask, "tcpListenerTask", 0)
        print ("TCP Listener Started")
        taskMgr.add(self.tcpReaderTask, "tcpReaderTask", -10)
        print ("TCP Reader Started")
        taskMgr.add(self.tcpDisconnectionHandler, "tcpDisconnectionHandler", 20)
        print ("TCP Disconnection Handler Started")
        taskMgr.add(self.tcpQueuedSendHandlerTask, "tcpQueuedSendhandlerTask", -11)
        print ("TCP Queued Send Handler Started")

    # TCP Listener Task
    def tcpListenerTask(self, task):
        """
        Accept new incoming connection from clients, related to TCP
        """
        # Handle new connection
        if self.tcpListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            
            if self.tcpListener.getNewConnection(rendezvous, netAddress, newConnection):
                newConnection = newConnection.p()
                
                # Tell the reader about the new TCP connection
                self.tcpReader.addConnection(newConnection)

                #self.core.createPlayerObject(generateUUID(),newConnection, netAddress)
                    
                print ("Server: " + str(generateUUID), str(netAddress.getIpString()))
            else:
                print ("Server: Connection Failed from -", str(netAddress.getIpString()))    
                    
            
        return Task.cont


    def tcpReaderTask(self, task):
        """
        Handle any data from clients by sending it to the Handlers.
        """
        while 1:
            (datagram, data, opcode) = self.tcpNonBlockingRead(self.tcpReader)
            if opcode is MSG_NONE:
                # Do nothing or use it as some 'keep_alive' thing.
                break
            else:
                # Handle it
                #self.core.packetManager.handlePacket(opcode, data, datagram.getAddress())
                print("Set Packet Handler to handle packets!")
                
        return Task.cont


    # TCP NonBlockingRead??
    def tcpNonBlockingRead(self, qcr):
        """
        Return a datagram collection and type if data is available on
        the queued connection udpReader
        """
        if self.tcpReader.dataAvailable():
            datagram = NetDatagram()
            if self.tcpReader.getData(datagram):
                data = DatagramIterator(datagram)
                opcode = data.getUint8()

            else:
                data = None
                opcode = MSG_NONE

        else:
            datagram = None
            data = None
            opcode = MSG_NONE

        # Return the datagram to keep a handle on the data
        return (datagram, data, opcode)


    # TCP Disconnection Handler
    def tcpDisconnectionHandler(self, task):
        # Check for resets
        if self.tcpManager.resetConnectionAvailable():
            resetConnection = PointerToConnection()
            self.tcpManager.getResetConnection(resetConnection)
            print(str(resetConnection.p()))
            #for client in self.core.server.clients:
            #    if self.core.server.clients[client].connection == resetConnection.p():
            #        del self.core.server.clients[client]
            #        self.tcpReader.removeConnection(resetConnection.p())
            #        print ("Removed Connection:", resetConnection.p())
            #        print ('Current Clients:', self.core.server.clients)
            #        break

        return Task.cont


    def sendPacket(self, _pkt, _connection):
        self.tcpWriter.send(_pkt, _connection)


    def sendBroadcast(self, _pkt, _skipif=None):
        for client in self.serverManager.clients:
            if _skipif == client:
                pass
            else:
                conn = self.serverManager.clients[client].connection
                self.tcpWriter.send(_pkt, conn)

    def addPacketToSendQueue(self, _data):
        # _data should contain packet and connection
        pass

    def addPacketToBroadcastQueue(self, _pkt, _connectionList):
        # _data should contain the pkt data and _connectionList should be the valid connections for that broadcast
        # Could have a grouping system that put clients together and broadcasts go per group
        pass

    def tcpQueuedSendHandlerTask(self, task):
        
        if not self.sendPacketQueue.isEmpty():
            self.addPacketToSendQueue(self.sendPacketQueue.removeFromQue())
        
        return Task.cont
Beispiel #12
0
class Server(net.NetCommon):
    """
    """

    def __init__(self, protocol):
        """
        """
        net.NetCommon.__init__(self, protocol)
        self.listener = QueuedConnectionListener(self.manager, 0)
        self.connections = []
        self.players = []
        self.protocol.setServer(self)
        self.active = False
        self.controller = None
        self.packetHelper = packet.ServerPacketHelper(self)

    def start(self, port):
        socket = self.manager.openTCPServerRendezvous(port, 100)
        self.listener.addConnection(socket)
        taskMgr.add(self.updateListener, "update_listener")

    def stop(self):
        del self.connections[:]
        del self.players[:]
        self.listener = None
        taskMgr.remove("update_listener")

    def updateListener(self, task):
        """
        """
        if self.listener.newConnectionAvailable():
            connection = PointerToConnection()
            if self.listener.getNewConnection(connection):
                connection = connection.p()
                self.connections.append(connection)
                self.reader.addConnection(connection)
                logging.info("New connection established")
                self.players.append(Player(connection))

        for conn in self.connections[:]:
            if not self.reader.isConnectionOk(conn):
                logging.warning("Non-ok connection detected")
                for player in self.players:
                    if player.connection == conn:
                        self.players.remove(player)
                        nick = player.nick
                        logging.info("Removed player with non-ok connection")
                        messenger.send("player_disconnected", sentArgs=[nick])
                self.connections.remove(conn)
        return task.cont

    def startGame(self):
        self.controller = controller.ServerController(self.players[0], self.players[1])
        messenger.send("send_start_game", [self.players])
        taskMgr.doMethodLater(1, self.controller.begin_game, "begin_game")

    def broadcast(self, datagram):
        for conn in self.connections:
            self.writer.send(datagram, conn)

    def sendToSelectedPlayers(self, datagram, players):
        for p in players:
            conn = p.connection
            self.writer.send(datagram, conn)

    def destroy(self):
        """
        """
        net.NetCommon.destroy(self)
        taskMgr.remove("update_listener")
Beispiel #13
0
class Server(object):

    # https://www.panda3d.org/manual/index.php/Client-Server_Connection

    def __init__(self, host="localhost", port=5001):
        taskMgr = Task.TaskManager()

        self.cManager = QueuedConnectionManager()
        self.cListener = QueuedConnectionListener(self.cManager, 0)
        self.cReader = QueuedConnectionReader(self.cManager, 0)
        self.cWriter = ConnectionWriter(self.cManager, 0)
        self.activeConnections = []  # We'll want to keep track of these later
        self.readerCallbacks = []

        backlog = 1000  #If we ignore 1,000 connection attempts, something is wrong!
        self.tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog)
        self.cListener.addConnection(self.tcpSocket)

        taskMgr.add(self.tskListenerPolling, "Poll the connection listener",
                    -39)
        taskMgr.add(self.tskReaderPolling, "Poll the connection reader", -40)
        print("started server! ({} at {})".format(port, host))

    def Start(self):
        # derived servers can overwrite this function if needed
        pass

    def tskListenerPolling(self, taskdata):
        # listen for new connections
        # TODO(victor): what happens if a client shuts down?
        # print("server.tskListenerPolling()")
        if self.cListener.newConnectionAvailable():
            rendezvous = PointerToConnection()
            netAddress = NetAddress()
            newConnection = PointerToConnection()
            if self.cListener.getNewConnection(rendezvous, netAddress,
                                               newConnection):
                newConnection = newConnection.p()
                self.activeConnections.append(
                    newConnection)  # Remember connection
                self.cReader.addConnection(
                    newConnection)  # Begin reading connection
                print("server: received new connection!")
        return Task.cont

    def tskReaderPolling(self, taskdata):
        # reader callback
        if not self.cReader.dataAvailable():
            return Task.cont

        # catch the incoming data in this instance
        # Check the return value; if we were threaded, someone else could have
        # snagged this data before we did
        datagram = NetDatagram()
        if not self.cReader.getData(datagram):
            return Task.cont

        for callback in self.readerCallbacks:
            callback(datagram)

        return Task.cont

    def addReaderCallback(self, callbackFunction):
        self.readerCallbacks.append(callbackFunction)

    def BroadcastMessage(self, datagram):
        # send the same message to all clients
        for client in self.activeConnections:
            self.cWriter.send(datagram, client)

    def Close(self):
        # remove all clients
        for client in self.activeConnections:
            self.cReader.removeConnection(client)
            self.activeConnections = []

        # close down our listener
        self.cManager.closeConnection(self.tcpSocket)