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;
}
}
}
}
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));
}
}
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;
}
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);
}
}
}
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);
}
}
Aggregations