Search in sources :

Example 1 with EncapsulatedPacket

use of cn.nukkit.raknet.protocol.EncapsulatedPacket in project Nukkit by Nukkit.

the class Session method handlePacket.

public void handlePacket(Packet packet) throws Exception {
    this.isActive = true;
    this.lastUpdate = System.currentTimeMillis();
    if (this.state == STATE_CONNECTED || this.state == STATE_CONNECTING_2) {
        if (((packet.buffer[0] & 0xff) >= 0x80 || (packet.buffer[0] & 0xff) <= 0x8f) && packet instanceof DataPacket) {
            DataPacket dp = (DataPacket) packet;
            dp.decode();
            if (dp.seqNumber < this.windowStart || dp.seqNumber > this.windowEnd || this.receivedWindow.containsKey(dp.seqNumber)) {
                return;
            }
            int diff = dp.seqNumber - this.lastSeqNumber;
            this.NACKQueue.remove(dp.seqNumber);
            this.ACKQueue.put(dp.seqNumber, dp.seqNumber);
            this.receivedWindow.put(dp.seqNumber, dp.seqNumber);
            if (diff != 1) {
                for (int i = this.lastSeqNumber + 1; i < dp.seqNumber; i++) {
                    if (!this.receivedWindow.containsKey(i)) {
                        this.NACKQueue.put(i, i);
                    }
                }
            }
            if (diff >= 1) {
                this.lastSeqNumber = dp.seqNumber;
                this.windowStart += diff;
                this.windowEnd += diff;
            }
            for (Object pk : dp.packets) {
                if (pk instanceof EncapsulatedPacket) {
                    this.handleEncapsulatedPacket((EncapsulatedPacket) pk);
                }
            }
        } else {
            if (packet instanceof ACK) {
                packet.decode();
                for (int seq : new ArrayList<>(((ACK) packet).packets.values())) {
                    if (this.recoveryQueue.containsKey(seq)) {
                        for (Object pk : this.recoveryQueue.get(seq).packets) {
                            if (pk instanceof EncapsulatedPacket && ((EncapsulatedPacket) pk).needACK && ((EncapsulatedPacket) pk).messageIndex != null) {
                                if (this.needACK.containsKey(((EncapsulatedPacket) pk).identifierACK)) {
                                    this.needACK.get(((EncapsulatedPacket) pk).identifierACK).remove(((EncapsulatedPacket) pk).messageIndex);
                                }
                            }
                        }
                        this.recoveryQueue.remove(seq);
                    }
                }
            } else if (packet instanceof NACK) {
                packet.decode();
                for (int seq : new ArrayList<>(((NACK) packet).packets.values())) {
                    if (this.recoveryQueue.containsKey(seq)) {
                        DataPacket pk = this.recoveryQueue.get(seq);
                        pk.seqNumber = this.sendSeqNumber++;
                        this.packetToSend.add(pk);
                        this.recoveryQueue.remove(seq);
                    }
                }
            }
        }
    } else if ((packet.buffer[0] & 0xff) > 0x00 || (packet.buffer[0] & 0xff) < 0x80) {
        // Not Data packet :)
        packet.decode();
        if (packet instanceof OPEN_CONNECTION_REQUEST_1) {
            // TODO: check protocol number and refuse connections
            OPEN_CONNECTION_REPLY_1 pk = new OPEN_CONNECTION_REPLY_1();
            pk.mtuSize = ((OPEN_CONNECTION_REQUEST_1) packet).mtuSize;
            pk.serverID = sessionManager.getID();
            this.sendPacket(pk);
            this.state = STATE_CONNECTING_1;
        } else if (this.state == STATE_CONNECTING_1 && packet instanceof OPEN_CONNECTION_REQUEST_2) {
            this.id = ((OPEN_CONNECTION_REQUEST_2) packet).clientID;
            if (((OPEN_CONNECTION_REQUEST_2) packet).serverPort == this.sessionManager.getPort() || !this.sessionManager.portChecking) {
                // Max size, do not allow creating large buffers to fill server memory
                this.mtuSize = Math.min(Math.abs(((OPEN_CONNECTION_REQUEST_2) packet).mtuSize), 1464);
                OPEN_CONNECTION_REPLY_2 pk = new OPEN_CONNECTION_REPLY_2();
                pk.mtuSize = (short) this.mtuSize;
                pk.serverID = this.sessionManager.getID();
                pk.clientAddress = this.address;
                pk.clientPort = this.port;
                this.sendPacket(pk);
                this.state = STATE_CONNECTING_2;
            }
        }
    }
}
Also used : EncapsulatedPacket(cn.nukkit.raknet.protocol.EncapsulatedPacket) DataPacket(cn.nukkit.raknet.protocol.DataPacket)

Example 2 with EncapsulatedPacket

use of cn.nukkit.raknet.protocol.EncapsulatedPacket in project Nukkit by Nukkit.

the class Session method handleEncapsulatedPacketRoute.

private void handleEncapsulatedPacketRoute(EncapsulatedPacket packet) throws Exception {
    if (this.sessionManager == null) {
        return;
    }
    if (packet.hasSplit) {
        if (this.state == STATE_CONNECTED) {
            this.handleSplit(packet);
        }
        return;
    }
    byte id = packet.buffer[0];
    if ((id & 0xff) < 0x80) {
        // internal data packet
        if (state == STATE_CONNECTING_2) {
            if (id == CLIENT_CONNECT_DataPacket.ID) {
                CLIENT_CONNECT_DataPacket dataPacket = new CLIENT_CONNECT_DataPacket();
                dataPacket.buffer = packet.buffer;
                dataPacket.decode();
                SERVER_HANDSHAKE_DataPacket pk = new SERVER_HANDSHAKE_DataPacket();
                pk.address = this.address;
                pk.port = this.port;
                pk.sendPing = dataPacket.sendPing;
                pk.sendPong = dataPacket.sendPing + 1000L;
                pk.encode();
                EncapsulatedPacket sendPacket = new EncapsulatedPacket();
                sendPacket.reliability = 0;
                sendPacket.buffer = pk.buffer;
                this.addToQueue(sendPacket, RakNet.PRIORITY_IMMEDIATE);
            } else if (id == CLIENT_HANDSHAKE_DataPacket.ID) {
                CLIENT_HANDSHAKE_DataPacket dataPacket = new CLIENT_HANDSHAKE_DataPacket();
                dataPacket.buffer = packet.buffer;
                dataPacket.decode();
                if (dataPacket.port == this.sessionManager.getPort() || !this.sessionManager.portChecking) {
                    // FINALLY!
                    this.state = STATE_CONNECTED;
                    this.isTemporal = false;
                    this.sessionManager.openSession(this);
                }
            }
        } else if (id == CLIENT_DISCONNECT_DataPacket.ID) {
            disconnect("client disconnect");
        } else if (id == PING_DataPacket.ID) {
            PING_DataPacket dataPacket = new PING_DataPacket();
            dataPacket.buffer = packet.buffer;
            dataPacket.decode();
            PONG_DataPacket pk = new PONG_DataPacket();
            pk.pingID = dataPacket.pingID;
            pk.encode();
            EncapsulatedPacket sendPacket = new EncapsulatedPacket();
            sendPacket.reliability = 0;
            sendPacket.buffer = pk.buffer;
            this.addToQueue(sendPacket);
            // Latency measurement
            PING_DataPacket pingPacket = new PING_DataPacket();
            pingPacket.pingID = System.currentTimeMillis();
            pingPacket.encode();
            sendPacket = new EncapsulatedPacket();
            sendPacket.reliability = 0;
            sendPacket.buffer = pingPacket.buffer;
            this.addToQueue(sendPacket);
        } else if (id == PONG_DataPacket.ID) {
            if (state == STATE_CONNECTED) {
                PONG_DataPacket dataPacket = new PONG_DataPacket();
                dataPacket.buffer = packet.buffer;
                dataPacket.decode();
                if (state == STATE_CONNECTED) {
                    PING_DataPacket pingPacket = new PING_DataPacket();
                    pingPacket.pingID = (System.currentTimeMillis() - dataPacket.pingID) / 10;
                    pingPacket.encode();
                    packet.buffer = pingPacket.buffer;
                    this.sessionManager.streamEncapsulated(this, packet);
                }
            }
        }
    } else if (state == STATE_CONNECTED) {
        this.sessionManager.streamEncapsulated(this, packet);
    } else {
    // this.sessionManager.getLogger().notice("Received packet before connection: "+Binary.bytesToHexString(packet.buffer));
    }
}
Also used : EncapsulatedPacket(cn.nukkit.raknet.protocol.EncapsulatedPacket)

Example 3 with EncapsulatedPacket

use of cn.nukkit.raknet.protocol.EncapsulatedPacket in project Nukkit by Nukkit.

the class RakNetInterface method putPacket.

@Override
public Integer putPacket(Player player, DataPacket packet, boolean needACK, boolean immediate) {
    if (this.identifiers.containsKey(player.rawHashCode())) {
        byte[] buffer;
        if (packet.pid() == ProtocolInfo.BATCH_PACKET) {
            buffer = ((BatchPacket) packet).payload;
        } else if (!needACK) {
            this.server.batchPackets(new Player[] { player }, new DataPacket[] { packet }, true);
            return null;
        } else {
            if (!packet.isEncoded) {
                packet.encode();
                packet.isEncoded = true;
            }
            buffer = packet.getBuffer();
            try {
                buffer = Zlib.deflate(Binary.appendBytes(Binary.writeUnsignedVarInt(buffer.length), buffer), Server.getInstance().networkCompressionLevel);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        String identifier = this.identifiers.get(player.rawHashCode());
        EncapsulatedPacket pk = null;
        if (!needACK) {
            if (packet.encapsulatedPacket == null) {
                packet.encapsulatedPacket = new CacheEncapsulatedPacket();
                packet.encapsulatedPacket.identifierACK = null;
                packet.encapsulatedPacket.buffer = Binary.appendBytes((byte) 0xfe, buffer);
                if (packet.getChannel() != 0) {
                    packet.encapsulatedPacket.reliability = 3;
                    packet.encapsulatedPacket.orderChannel = packet.getChannel();
                    packet.encapsulatedPacket.orderIndex = 0;
                } else {
                    packet.encapsulatedPacket.reliability = 2;
                }
            }
            pk = packet.encapsulatedPacket;
        }
        if (pk == null) {
            pk = new EncapsulatedPacket();
            pk.buffer = Binary.appendBytes((byte) 0xfe, buffer);
            if (packet.getChannel() != 0) {
                packet.reliability = 3;
                packet.orderChannel = packet.getChannel();
                packet.orderIndex = 0;
            } else {
                packet.reliability = 2;
            }
            if (needACK) {
                int iACK = this.identifiersACK.get(identifier);
                iACK++;
                pk.identifierACK = iACK;
                this.identifiersACK.put(identifier, iACK);
            }
        }
        this.handler.sendEncapsulated(identifier, pk, (needACK ? RakNet.FLAG_NEED_ACK : 0) | (immediate ? RakNet.PRIORITY_IMMEDIATE : RakNet.PRIORITY_NORMAL));
        return pk.identifierACK;
    }
    return null;
}
Also used : Player(cn.nukkit.Player) EncapsulatedPacket(cn.nukkit.raknet.protocol.EncapsulatedPacket) PING_DataPacket(cn.nukkit.raknet.protocol.packet.PING_DataPacket) DataPacket(cn.nukkit.network.protocol.DataPacket) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Example 4 with EncapsulatedPacket

use of cn.nukkit.raknet.protocol.EncapsulatedPacket in project Nukkit by Nukkit.

the class Session method handleEncapsulatedPacket.

private void handleEncapsulatedPacket(EncapsulatedPacket packet) throws Exception {
    if (packet.messageIndex == null) {
        this.handleEncapsulatedPacketRoute(packet);
    } else {
        if (packet.messageIndex < this.reliableWindowStart || packet.messageIndex > this.reliableWindowEnd) {
            return;
        }
        if ((packet.messageIndex - this.lastReliableIndex) == 1) {
            this.lastReliableIndex++;
            this.reliableWindowStart++;
            this.reliableWindowEnd++;
            this.handleEncapsulatedPacketRoute(packet);
            if (!this.reliableWindow.isEmpty()) {
                TreeMap<Integer, EncapsulatedPacket> sortedMap = new TreeMap<>(this.reliableWindow);
                for (int index : sortedMap.keySet()) {
                    EncapsulatedPacket pk = this.reliableWindow.get(index);
                    if ((index - this.lastReliableIndex) != 1) {
                        break;
                    }
                    this.lastReliableIndex++;
                    this.reliableWindowStart++;
                    this.reliableWindowEnd++;
                    this.handleEncapsulatedPacketRoute(pk);
                    this.reliableWindow.remove(index);
                }
            }
        } else {
            this.reliableWindow.put(packet.messageIndex, packet);
        }
    }
}
Also used : EncapsulatedPacket(cn.nukkit.raknet.protocol.EncapsulatedPacket)

Example 5 with EncapsulatedPacket

use of cn.nukkit.raknet.protocol.EncapsulatedPacket in project Nukkit by Nukkit.

the class Session method addEncapsulatedToQueue.

public void addEncapsulatedToQueue(EncapsulatedPacket packet, int flags) throws Exception {
    if ((packet.needACK = (flags & RakNet.FLAG_NEED_ACK) > 0)) {
        this.needACK.put(packet.identifierACK, new HashMap<>());
    }
    if (packet.reliability == 2 || packet.reliability == 3 || packet.reliability == 4 || packet.reliability == 6 || packet.reliability == 7) {
        packet.messageIndex = this.messageIndex++;
        if (packet.reliability == 3) {
            int index = this.channelIndex.get(packet.orderChannel) + 1;
            packet.orderIndex = index;
            channelIndex.put(packet.orderChannel, index);
        }
    }
    if (packet.getTotalLength() + 4 > this.mtuSize) {
        byte[][] buffers = Binary.splitBytes(packet.buffer, this.mtuSize - 34);
        int splitID = ++this.splitID % 65536;
        for (int count = 0; count < buffers.length; count++) {
            byte[] buffer = buffers[count];
            EncapsulatedPacket pk = new EncapsulatedPacket();
            pk.splitID = splitID;
            pk.hasSplit = true;
            pk.splitCount = buffers.length;
            pk.reliability = packet.reliability;
            pk.splitIndex = count;
            pk.buffer = buffer;
            if (count > 0) {
                pk.messageIndex = this.messageIndex++;
            } else {
                pk.messageIndex = packet.messageIndex;
            }
            if (pk.reliability == 3) {
                pk.orderChannel = packet.orderChannel;
                pk.orderIndex = packet.orderIndex;
            }
            this.addToQueue(pk, flags | RakNet.PRIORITY_IMMEDIATE);
        }
    } else {
        this.addToQueue(packet, flags);
    }
}
Also used : EncapsulatedPacket(cn.nukkit.raknet.protocol.EncapsulatedPacket)

Aggregations

EncapsulatedPacket (cn.nukkit.raknet.protocol.EncapsulatedPacket)6 Player (cn.nukkit.Player)1 DataPacket (cn.nukkit.network.protocol.DataPacket)1 DataPacket (cn.nukkit.raknet.protocol.DataPacket)1 PING_DataPacket (cn.nukkit.raknet.protocol.packet.PING_DataPacket)1 BinaryStream (cn.nukkit.utils.BinaryStream)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1