private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEndPoint) { #if STATS_ENABLED Statistics.PacketsReceived++; Statistics.BytesReceived += (uint)count; #endif //Try read packet NetPacket packet = NetPacketPool.GetPacket(count, false); if (!packet.FromBytes(reusableBuffer, 0, count)) { NetPacketPool.Recycle(packet); NetUtils.DebugWriteError("[NM] DataReceived: bad!"); return; } //get peer //Check normal packets NetPeer netPeer; //old packets protection NetEvent netEvent; bool peerFound = _peers.TryGetValue(remoteEndPoint, out netPeer); //Check unconnected switch (packet.Property) { case PacketProperty.DiscoveryRequest: if (!DiscoveryEnabled) { break; } netEvent = CreateEvent(NetEventType.DiscoveryRequest); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count); EnqueueEvent(netEvent); break; case PacketProperty.DiscoveryResponse: netEvent = CreateEvent(NetEventType.DiscoveryResponse); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count); EnqueueEvent(netEvent); break; case PacketProperty.UnconnectedMessage: if (!UnconnectedMessagesEnabled) { break; } netEvent = CreateEvent(NetEventType.ReceiveUnconnected); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count); EnqueueEvent(netEvent); break; case PacketProperty.NatIntroduction: case PacketProperty.NatIntroductionRequest: case PacketProperty.NatPunchMessage: if (NatPunchEnabled) { NatPunchModule.ProcessMessage(remoteEndPoint, packet); } break; case PacketProperty.Disconnect: if (peerFound) { var disconnectResult = netPeer.ProcessDisconnect(packet); if (disconnectResult == DisconnectResult.None) { NetPacketPool.Recycle(packet); return; } if (disconnectResult == DisconnectResult.Disconnect) { _connectedPeersCount--; } netEvent = CreateEvent(NetEventType.Disconnect); netEvent.Peer = netPeer; netEvent.DataReader.SetSource(packet.RawData, 9, packet.Size); netEvent.DisconnectReason = disconnectResult == DisconnectResult.Disconnect ? DisconnectReason.RemoteConnectionClose : DisconnectReason.ConnectionRejected; EnqueueEvent(netEvent); } else { NetPacketPool.Recycle(packet); } //Send shutdown SendRaw(new[] { (byte)PacketProperty.ShutdownOk }, 0, 1, remoteEndPoint); break; case PacketProperty.ConnectAccept: var connAccept = NetConnectAcceptPacket.FromData(packet); if (connAccept != null && peerFound && netPeer.ProcessConnectAccept(connAccept)) { var connectEvent = CreateEvent(NetEventType.Connect); connectEvent.Peer = netPeer; EnqueueEvent(connectEvent); } break; case PacketProperty.ConnectRequest: var connRequest = NetConnectRequestPacket.FromData(packet); if (connRequest != null) { ProcessConnectRequest(remoteEndPoint, netPeer, connRequest); } break; default: if (peerFound) { netPeer.ProcessPacket(packet); } break; } }
//Process incoming packet internal void ProcessPacket(NetPacket packet) { _timeSinceLastPacket = 0; if (packet.ConnectionNumber != _connectNum && packet.Property != PacketProperty.ShutdownOk) //withou connectionNum { NetUtils.DebugWrite(ConsoleColor.Red, "[RR]Old packet"); _packetPool.Recycle(packet); return; } NetUtils.DebugWrite("[RR]PacketProperty: {0}", packet.Property); switch (packet.Property) { case PacketProperty.Merged: int pos = NetConstants.HeaderSize; while (pos < packet.Size) { ushort size = BitConverter.ToUInt16(packet.RawData, pos); pos += 2; NetPacket mergedPacket = _packetPool.GetPacket(size, false); if (!mergedPacket.FromBytes(packet.RawData, pos, size)) { _packetPool.Recycle(packet); break; } pos += size; ProcessPacket(mergedPacket); } break; //If we get ping, send pong case PacketProperty.Ping: if (NetUtils.RelativeSequenceNumber(packet.Sequence, _remotePingSequence) < 0) { _packetPool.Recycle(packet); break; } NetUtils.DebugWrite("[PP]Ping receive, send pong"); _remotePingSequence = packet.Sequence; _packetPool.Recycle(packet); //send _pongPacket.Sequence = _remotePingSequence; _netManager.SendRaw(_pongPacket, _remoteEndPoint); break; //If we get pong, calculate ping time and rtt case PacketProperty.Pong: if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pingSequence) < 0) { _packetPool.Recycle(packet); break; } _pingSequence = packet.Sequence; int rtt = (int)(DateTime.UtcNow - _pingTimeStart).TotalMilliseconds; UpdateRoundTripTime(rtt); NetUtils.DebugWrite("[PP]Ping: {0}", rtt); _packetPool.Recycle(packet); break; //Process ack case PacketProperty.AckReliable: _reliableUnorderedChannel.ProcessAck(packet); _packetPool.Recycle(packet); break; case PacketProperty.AckReliableOrdered: _reliableOrderedChannel.ProcessAck(packet); _packetPool.Recycle(packet); break; //Process in order packets case PacketProperty.Sequenced: _sequencedChannel.ProcessPacket(packet); break; case PacketProperty.ReliableUnordered: _reliableUnorderedChannel.ProcessPacket(packet); break; case PacketProperty.ReliableOrdered: _reliableOrderedChannel.ProcessPacket(packet); break; case PacketProperty.ReliableSequenced: _reliableSequencedChannel.ProcessPacket(packet); break; case PacketProperty.AckReliableSequenced: _reliableSequencedChannel.ProcessAck(packet); _packetPool.Recycle(packet); break; //Simple packet without acks case PacketProperty.Unreliable: AddIncomingPacket(packet); return; case PacketProperty.MtuCheck: case PacketProperty.MtuOk: ProcessMtuPacket(packet); break; case PacketProperty.ShutdownOk: if (_connectionState == ConnectionState.ShutdownRequested) { _connectionState = ConnectionState.Disconnected; } _packetPool.Recycle(packet); break; default: NetUtils.DebugWriteError("Error! Unexpected packet type: " + packet.Property); break; } }