Search in sources :

Example 1 with DataPacket

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

the class Session method addToQueue.

private void addToQueue(EncapsulatedPacket pk, int flags) throws Exception {
    int priority = flags & 0b0000111;
    if (pk.needACK && pk.messageIndex != null) {
        if (!this.needACK.containsKey(pk.identifierACK)) {
            this.needACK.put(pk.identifierACK, new HashMap<>());
        }
        this.needACK.get(pk.identifierACK).put(pk.messageIndex, pk.messageIndex);
    }
    if (priority == RakNet.PRIORITY_IMMEDIATE) {
        // Skip queues
        DataPacket packet = new DATA_PACKET_0();
        packet.seqNumber = this.sendSeqNumber++;
        if (pk.needACK) {
            packet.packets.add(pk.clone());
            pk.needACK = false;
        } else {
            packet.packets.add(pk.toBinary());
        }
        this.sendPacket(packet);
        packet.sendTime = System.currentTimeMillis();
        this.recoveryQueue.put(packet.seqNumber, packet);
        return;
    }
    int length = this.sendQueue.length();
    if (length + pk.getTotalLength() > this.mtuSize) {
        this.sendQueue();
    }
    if (pk.needACK) {
        this.sendQueue.packets.add(pk.clone());
        pk.needACK = false;
    } else {
        this.sendQueue.packets.add(pk.toBinary());
    }
}
Also used : DataPacket(cn.nukkit.raknet.protocol.DataPacket)

Example 2 with DataPacket

use of cn.nukkit.raknet.protocol.DataPacket 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 3 with DataPacket

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

the class Session method update.

public void update(long time) throws Exception {
    if (!this.isActive && (this.lastUpdate + 10000) < time) {
        // 10 second timeout
        this.disconnect("timeout");
        return;
    }
    this.isActive = false;
    if (!this.ACKQueue.isEmpty()) {
        ACK pk = new ACK();
        pk.packets = new TreeMap<>(this.ACKQueue);
        this.sendPacket(pk);
        this.ACKQueue = new HashMap<>();
    }
    if (!this.NACKQueue.isEmpty()) {
        NACK pk = new NACK();
        pk.packets = new TreeMap<>(this.NACKQueue);
        this.sendPacket(pk);
        this.NACKQueue = new HashMap<>();
    }
    if (!this.packetToSend.isEmpty()) {
        int limit = 16;
        for (int i = 0; i < this.packetToSend.size(); i++) {
            DataPacket pk = this.packetToSend.get(i);
            pk.sendTime = time;
            pk.encode();
            this.recoveryQueue.put(pk.seqNumber, pk);
            this.packetToSend.remove(pk);
            this.sendPacket(pk);
            if (limit-- <= 0) {
                break;
            }
        }
    }
    if (this.packetToSend.size() > WINDOW_SIZE) {
        this.packetToSend.clear();
    }
    if (!this.needACK.isEmpty()) {
        for (int identifierACK : new ArrayList<>(this.needACK.keySet())) {
            Map<Integer, Integer> indexes = this.needACK.get(identifierACK);
            if (indexes.isEmpty()) {
                this.needACK.remove(identifierACK);
                this.sessionManager.notifyACK(this, identifierACK);
            }
        }
    }
    for (int seq : new ArrayList<>(this.recoveryQueue.keySet())) {
        DataPacket pk = this.recoveryQueue.get(seq);
        if (pk.sendTime < System.currentTimeMillis() - 8000) {
            this.packetToSend.add(pk);
            this.recoveryQueue.remove(seq);
        } else {
            break;
        }
    }
    for (int seq : new ArrayList<>(this.receivedWindow.keySet())) {
        if (seq < this.windowStart) {
            this.receivedWindow.remove(seq);
        } else {
            break;
        }
    }
    this.sendQueue();
}
Also used : DataPacket(cn.nukkit.raknet.protocol.DataPacket)

Aggregations

DataPacket (cn.nukkit.raknet.protocol.DataPacket)3 EncapsulatedPacket (cn.nukkit.raknet.protocol.EncapsulatedPacket)1