예제 #1
0
 def encodePayload(self):
     payload = b""
     records = 0
     self.packets.sort()
     if len(self.packets) > 0:
         pointer = 1
         start = self.packets[0]
         last = self.packets[0]
         while pointer < len(self.packets):
             current = self.packets[pointer]
             pointer += 1
             diff = current - last
             if diff == 1:
                 last = current
             elif diff > 1:
                 if start == last:
                     payload += Binary.writeByte(1)
                     payload += Binary.writeLTriad(start)
                     start = last = current
                 else:
                     payload += Binary.writeByte(0)
                     payload += Binary.writeLTriad(start)
                     payload += Binary.writeLTriad(last)
                     start = last = current
                 records += 1
         if start == last:
             payload += Binary.writeByte(1)
             payload += Binary.writeLTriad(start)
         else:
             payload += Binary.writeByte(0)
             payload += Binary.writeLTriad(start)
             payload += Binary.writeLTriad(last)
         records += 1
     self.putShort(records)
     self.put(payload)
예제 #2
0
 def handlePacket(self, packet):
     if packet.split:
         self.handleSplit(packet)
         return
     id = packet.buffer[0]
     dataPacket = None
     pk = None
     sendPacket = None
     if id < 0x80:
         if self.state == self.status["Connecting"]:
             if id == PacketIdentifiers.ConnectionRequest:
                 dataPacket = ConnectionRequest()
                 dataPacket.buffer = packet.buffer
                 dataPacket.decode()
                 pk = ConnectionRequestAccepted()
                 pk.clientAddress = self.address
                 pk.systemIndex = 0
                 pk.requestTime = dataPacket.time
                 pk.time = Binary.flipLongEndianness(int(timeNow(
                 ))) if Binary.ENDIANNESS == Binary.LITTLE_ENDIAN else int(
                     timeNow())
                 pk.encode()
                 sendPacket = EncapsulatedPacket()
                 sendPacket.reliability = 0
                 sendPacket.buffer = pk.buffer
                 self.addToQueue(sendPacket, self.priority["Immediate"])
             elif id == PacketIdentifiers.NewIncomingConnection:
                 dataPacket = NewIncomingConnection()
                 dataPacket.buffer = packet.buffer
                 dataPacket.decode()
                 serverPort = self.server.socket.address.port
                 if dataPacket.address.port == serverPort:
                     self.state = status["Connected"]
                     self.server.interface.onOpenConnection(self)
         elif id == PacketIdentifiers.DisconnectNotification:
             self.disconnect('client disconnect')
         elif id == PacketIdentifiers.ConnectedPing:
             dataPacket = ConnectedPing()
             dataPacket.buffer = packet.buffer
             dataPacket.decode()
             pk = ConnectedPong()
             pk.pingTime = dataPacket.time
             pk.pongTime = Binary.flipLongEndianness(int(timeNow(
             ))) if Binary.ENDIANNESS == Binary.LITTLE_ENDIAN else int(
                 timeNow())
             pk.encode()
             sendPacket = EncapsulatedPacket()
             sendPacket.reliability = 0
             sendPacket.buffer = pk.buffer
             self.addToQueue(sendPacket)
     elif self.state == self.status["Connected"]:
         self.interface.onEncapsulated(packet, self.address)
예제 #3
0
 def fromBinary(self, buffer):
     offset = 0
     packet = EncapsulatedPacket()
     header = buffer[offset]
     offset += 1
     packet.reliability = (header & 224) >> 5
     packet.split = (header & BitFlags.Split) > 0
     length = Binary.readShort(buffer[offset:offset + 2])
     length >>= 3
     offset += 2
     if length == 0:
         raise Exception("Got an empty encapsulated packet")
     if Reliability().isReliable(packet.reliability):
         packet.messageIndex = Binary.readLTriad(buffer[offset:offset + 3])
         offset += 3
     if Reliability().isSequenced(packet.reliability):
         packet.sequenceIndex = Binary.readLTriad(buffer[offset:offset + 3])
         offset += 3
     if Reliability().isSequencedOrOrdered(packet.reliability):
         packet.orderIndex = Binary.readLTriad(buffer[offset:offset + 3])
         offset += 3
         packet.orderChannel = Binary.readByte(buffer[offset:offset + 1])
         offset += 1
     if packet.split:
         packet.splitCount = Binary.readInt(buffer[offset:offset + 4])
         offset += 4
         packet.splitId = Binary.readShort(buffer[offset:offset + 2])
         offset += 2
         packet.splitIndex = Binary.readInt(buffer[offset:offset + 4])
         offset += 4
     packet.buffer = buffer[offset:offset + length]
     offset += length
     return packet
예제 #4
0
 def toBinary(self):
     buffer = b""
     header = self.reliability << 5
     if self.split:
         header |= BitFlags.Split
     buffer += Binary.writeByte(header)
     buffer += Binary.writeShort(len(self.buffer) << 3)
     if Reliability().isReliable(self.reliability):
         buffer += Binary.writeLTriad(self.messageIndex)
     if Reliability().isSequenced(self.reliability):
         buffer += Binary.writeLTriad(self.sequenceIndex)
     if Reliability().isSequencedOrOrdered(self.reliability):
         buffer += Binary.writeLTriad(self.orderIndex)
         buffer += Binary.writeByte(self.orderChannel)
     if self.split:
         buffer += Binary.writeInt(self.splitCount)
         buffer += Binary.writeShort(self.splitId)
         buffer += Binary.writeInt(self.splitIndex)
     return buffer + self.buffer
예제 #5
0
class Server(Thread):
    protocol = 10
    raknetTps = 100
    raknetTickLength = 1 / raknetTps

    id = Binary.readLong(os.urandom(8))
    name = None
    socket = None
    interface = None
    connections = {}
    shutdown = False

    def __init__(self, address, interface=None):
        super().__init__()
        self.socket = ServerSocket(address)
        if interface is not None:
            self.interface = interface
        else:
            self.interface = ServerInterface()
        self.start()

    def handleUnconnectedPing(self, data):
        decodedPacket = UnconnectedPing()
        decodedPacket.buffer = data
        decodedPacket.decode()
        if not decodedPacket.isValid:
            raise Exception("Invalid offline message")
        packet = UnconnectedPong()
        packet.time = decodedPacket.time
        packet.serverId = self.id
        packet.serverName = self.name
        packet.encode()
        return packet.buffer

    def handleOpenConnectionRequest1(self, data):
        decodedPacket = OpenConnectionRequest1()
        decodedPacket.buffer = data
        decodedPacket.decode()
        if not decodedPacket.isValid:
            raise Exception("Invalid offline message")
        if decodedPacket.protocolVersion != self.protocol:
            packet = IncompatibleProtocol()
            packet.protocol = self.protocol
            packet.serverId = self.id
            packet.encode()
            return packet.buffer
        packet = OpenConnectionReply1()
        packet.serverId = self.id
        packet.mtu = decodedPacket.mtu
        packet.encode()
        return packet.buffer

    def handleOpenConnectionRequest2(self, data, address):
        decodedPacket = OpenConnectionRequest2()
        decodedPacket.buffer = data
        decodedPacket.decode()
        if not decodedPacket.isValid:
            raise Exception("Invalid offline message")
        packet = OpenConnectionReply2()
        packet.serverId = self.id
        packet.mtu = decodedPacket.mtu
        packet.clientAddress = address
        packet.encode()
        token = str(address.getAddress()) + ":" + str(address.getPort())
        connection = Connection(self, decodedPacket.mtu, address)
        self.connections[token] = connection
        return packet.buffer

    def handle(self, data, address):
        header = data[0]
        token = str(address.getAddress()) + ":" + str(address.getPort())
        if token in self.connections:
            connection = self.connections[token]
            connection.receive(data)
        else:
            if header == PacketIdentifiers.UnconnectedPing:
                self.socket.sendBuffer(
                    self.handleUnconnectedPing(data),
                    (address.getAddress(), address.getPort()))
            elif header == PacketIdentifiers.OpenConnectionRequest1:
                self.socket.sendBuffer(
                    self.handleOpenConnectionRequest1(data),
                    (address.getAddress(), address.getPort()))
            elif header == PacketIdentifiers.OpenConnectionRequest2:
                self.socket.sendBuffer(
                    self.handleOpenConnectionRequest2(data, address),
                    (address.getAddress(), address.getPort()))

    def removeConnection(self, connection, reason):
        address = connection.address
        token = f"{address.getAddress}:{address.getPort}"
        if token in self.connections:
            self.connections[token].close()
            del self.connections[token]
        self.interface.onCloseConnection(connection.address, reason)

    def tick(self):
        if not self.shutdown:
            for token, connection in self.connections.items():
                connection.update(timeNow())
        else:
            return
        sleep(self.raknetTickLength)

    def run(self):
        while True:
            buffer = self.socket.receiveBuffer()
            if buffer is not None:
                data, address = buffer
                self.handle(data, InternetAddress(address[0], address[1]))
                self.tick()