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)
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)
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
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
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()