}
@Override
protected void PacketReceived(UDPPacketBuffer buffer)
{
Packet packet = null;
// Check if this packet came from the server we expected it to come from
if (!remoteEndPoint.getAddress().equals(((InetSocketAddress)buffer.getRemoteEndPoint()).getAddress()))
{
JLogger.warn("Received " + buffer.getDataLength() + " bytes of data from unrecognized source " +
((InetSocketAddress)buffer.getRemoteEndPoint()).toString());
return;
}
// Update the disconnect flag so this sim doesn't time out
DisconnectCandidate = false;
//region Packet Decoding
int[] packetEnd = new int[]{buffer.getDataLength() - 1};
try
{
packet = Packet.BuildPacket(buffer.getData(), packetEnd,
// Only allocate a buffer for zerodecoding if the packet is zerocoded
((buffer.getData()[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[8192] : null);
}
catch (MalformedDataException e)
{
JLogger.error(String.format("Malformed data, cannot parse packet:\n%s\nException: %s",
Utils.bytesToHexDebugString(buffer.getData(), buffer.getDataLength(), null),
Utils.getExceptionStackTraceAsString(e)));
}
// Fail-safe check
if (packet == null)
{
JLogger.warn("Couldn't build a message from the incoming data");
return;
}
// Interlocked.Add(ref Stats.RecvBytes, buffer.DataLength);
// Interlocked.Increment(ref Stats.RecvPackets);
Stats.RecvBytes.addAndGet(buffer.getDataLength());
Stats.RecvPackets.incrementAndGet();
//endregion Packet Decoding
if (packet.header.Resent)
// Interlocked.Increment(ref Stats.ReceivedResends);
Stats.ReceivedResends.incrementAndGet();
//region ACK Receiving
// Handle appended ACKs
if (packet.header.AppendedAcks && packet.header.AckList != null)
{
synchronized (NeedAck)
{
for (int i = 0; i < packet.header.AckList.length; i++)
{
if (NeedAck.containsKey(packet.header.AckList[i])
&& NeedAck.get(packet.header.AckList[i]).Type.equals(PacketType.UseCircuitCode))
{
GotUseCircuitCodeAck.set();
}
NeedAck.remove(packet.header.AckList[i]);
}
}
}
// Handle PacketAck packets
if (packet.Type == PacketType.PacketAck)
{
PacketAckPacket ackPacket = (PacketAckPacket)packet;
synchronized (NeedAck)
{
for (int i = 0; i < ackPacket.Packets.length; i++)
{
if (NeedAck.containsKey(ackPacket.Packets[i].ID)
&& NeedAck.get(ackPacket.Packets[i].ID).Type.equals(PacketType.UseCircuitCode))
{
GotUseCircuitCodeAck.set();
}
NeedAck.remove(ackPacket.Packets[i].ID);
}
}
}
//endregion ACK Receiving
if (packet.header.Reliable)
{
//region ACK Sending
// Add this packet to the list of ACKs that need to be sent out
//uint
long sequence = (long)packet.header.Sequence;
PendingAcks.offer(sequence);
// Send out ACKs if we have a lot of them
if (PendingAcks.size() >= Client.settings.MAX_PENDING_ACKS)
SendAcks();
//endregion ACK Sending
// Check the archive of received packet IDs to see whether we already received this packet
if (!PacketArchive.offer(packet.header.Sequence))
{
if (packet.header.Resent)
JLogger.debug("Received a resend of already processed packet #" + packet.header.Sequence + ", type: " + packet.Type);
else
JLogger.warn("Received a duplicate (not marked as resend) of packet #" + packet.header.Sequence + ", type: " + packet.Type);
// Avoid firing a callback twice for the same packet
return;
}
}
//region Inbox Insertion
NetworkManager.IncomingPacket incomingPacket = new NetworkManager.IncomingPacket();
incomingPacket.simulator = this;
incomingPacket.packet = packet;
Network.PacketInbox.offer(incomingPacket);
//endregion Inbox Insertion
//region Stats Tracking
if (Client.settings.TRACK_UTILIZATION)
{
Client.stats.Update(packet.Type.toString(),
UtilizationStatistics.Type.Packet, 0, packet.getLength());
}
//endregion
}