Пример #1
0
        //ProcessAck in packet
        public void ProcessAck(NetPacket packet)
        {
            ushort ackWindowStart = packet.Sequence;

            if (ackWindowStart >= NetConstants.MaxSequence)
            {
                NetUtils.DebugWrite("[PA]Bad window start");
                return;
            }

            byte[] acksData = packet.RawData;
            NetUtils.DebugWrite("[PA]AcksStart: {0}", ackWindowStart);
            //Monitor.Enter(_pendingPackets);

            for (int idx = 0; idx < packet.GetDataSize(); ++idx)
            {
                int currentByte = idx / BitsInByte;
                int currentBit  = idx % BitsInByte;
                if ((acksData[currentByte] & (1 << currentBit)) == 0)
                {
                    // Packet not ack, will be resent automaticaly as needed
                    continue;
                }

                // packet acknowledged = true
                int seqAck = NetUtils.IncrementSequenceNumber(ackWindowStart, idx);

                PendingPacket pendingPacket = _headPendingPacket;
                PendingPacket prevPacket    = null;
                while (pendingPacket != null)
                {
                    // Looking for the packet to acknowledge
                    if (pendingPacket.Packet.Sequence != seqAck)
                    {
                        prevPacket    = pendingPacket;
                        pendingPacket = pendingPacket.Next;
                        continue;
                    }

                    // Packet found, remove it from the list
                    if (pendingPacket == _headPendingPacket)
                    {
                        _headPendingPacket = pendingPacket.Next;
                    }

                    var packetToClear = pendingPacket;

                    //move forward
                    pendingPacket = pendingPacket.Next;
                    if (prevPacket != null)
                    {
                        prevPacket.Next = pendingPacket;
                    }

                    //clear acked packet
                    packetToClear.Packet.Recycle();
                    packetToClear.Clear();
                    NetUtils.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", seqAck);
                    break;
                }
            }
            //Monitor.Exit(_pendingPackets);
        }
Пример #2
0
        //Process incoming packet
        internal void ProcessPacket(NetPacket packet)
        {
            _timeSinceLastPacket = 0;

            NetUtils.DebugWrite("[RR]PacketProperty: {0}", packet.Property);
            switch (packet.Property)
            {
            case PacketProperty.ConnectRequest:
                //response with connect
                long newId = BitConverter.ToInt64(packet.RawData, NetConstants.RequestConnectIdIndex);

                NetUtils.DebugWrite("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}", _connectId, newId, _remoteEndPoint);
                if (newId > _connectId)
                {
                    _connectId = newId;
                }

                SendConnectAccept();
                packet.Recycle();
                break;

            case PacketProperty.Merged:
                int pos = 0;
                while (pos < packet.GetDataSize())
                {
                    ushort size = BitConverter.ToUInt16(packet.RawData, pos);
                    pos += sizeof(ushort);
                    NetPacket mergedPacket = _packetPool.GetAndRead(packet.RawData, pos, size);
                    if (mergedPacket == null)
                    {
                        packet.Recycle();
                        break;
                    }
                    pos += size;
                    ProcessPacket(mergedPacket);
                }
                break;

            //If we get ping, send pong
            case PacketProperty.Ping:
                if (NetUtils.RelativeSequenceNumber(packet.Sequence, _remotePingSequence) < 0)
                {
                    packet.Recycle();
                    break;
                }
                NetUtils.DebugWrite("[PP]Ping receive, send pong");
                _remotePingSequence = packet.Sequence;
                packet.Recycle();

                //send
                _pingMustSend = true;
                break;

            //If we get pong, calculate ping time and rtt
            case PacketProperty.Pong:
                if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pingSequence) < 0)
                {
                    packet.Recycle();
                    break;
                }
                _pingSequence = packet.Sequence;
                long rtt = NetTime.NowMs - _pingTimeStart;
                UpdateRoundTripTime(rtt);
                NetUtils.DebugWrite("[PP]Ping: {0}", rtt);
                packet.Recycle();
                break;

            //Process ack
            case PacketProperty.AckReliable:
                getReliableUnorderedChannel(packet.Channel).ProcessAck(packet);
                packet.Recycle();
                break;

            case PacketProperty.AckReliableOrdered:
                getReliableOrderedChannel(packet.Channel).ProcessAck(packet);
                packet.Recycle();
                break;

            //Process in order packets
            case PacketProperty.Sequenced:
                if (getSequencedChannel(packet.Channel).ProcessPacket(packet) == false)
                {
                    packet.Recycle();
                }
                break;

            case PacketProperty.ReliableUnordered:
                if (getReliableUnorderedChannel(packet.Channel).ProcessPacket(packet) == false)
                {
                    packet.Recycle();
                }
                break;

            case PacketProperty.ReliableOrdered:
                if (getReliableOrderedChannel(packet.Channel).ProcessPacket(packet) == false)
                {
                    packet.Recycle();
                }
                break;

            case PacketProperty.ReliableSequenced:
                getReliableSequencedChannel(packet.Channel).ProcessPacket(packet);
                break;

            //Simple packet without acks
            case PacketProperty.Unreliable:
                AddIncomingPacket(packet);
                return;

            case PacketProperty.MtuCheck:
            case PacketProperty.MtuOk:
                ProcessMtuPacket(packet);
                break;

            case PacketProperty.ShutdownOk:
                _connectionState = ConnectionState.Disconnected;
                break;

            default:
                NetUtils.DebugWriteError("Error! Unexpected packet type: " + packet.Property);
                break;
            }
        }
Пример #3
0
        private void DataReceived(byte[] reusableBuffer, int count, NetEndPoint remoteEndPoint)
        {
#if STATS_ENABLED
            Statistics.PacketsReceived++;
            Statistics.BytesReceived += (uint)count;
#endif

            //Try read packet
            NetPacket packet = NetPacketPool.GetAndRead(reusableBuffer, 0, count);
            if (packet == null)
            {
                NetUtils.DebugWriteError("[NM] DataReceived: bad!");
                return;
            }

            //Check unconnected
            switch (packet.Property)
            {
            case PacketProperty.DiscoveryRequest:
                if (DiscoveryEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.DiscoveryRequest);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.DiscoveryResponse:
            {
                var netEvent = CreateEvent(NetEventType.DiscoveryResponse);
                netEvent.RemoteEndPoint = remoteEndPoint;
                netEvent.DataReader.SetSource(packet);
                EnqueueEvent(netEvent);
            }
                return;

            case PacketProperty.UnconnectedMessage:
                if (UnconnectedMessagesEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.ReceiveUnconnected);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.NatIntroduction:
            case PacketProperty.NatIntroductionRequest:
            case PacketProperty.NatPunchMessage:
            {
                if (NatPunchEnabled)
                {
                    NatPunchModule.ProcessMessage(remoteEndPoint, packet);
                }
                return;
            }
            }

            //Check normal packets
            NetPeer netPeer;
            lock (_peers)
            {
                _peers.TryGetValue(remoteEndPoint, out netPeer);
            }
            if (netPeer != null &&
                netPeer.ConnectionState != ConnectionState.Disconnected)
            {
                switch (packet.Property)
                {
                case PacketProperty.Disconnect:
                    if (netPeer.ConnectionState == ConnectionState.InProgress ||
                        netPeer.ConnectionState == ConnectionState.Connected)
                    {
                        if (BitConverter.ToInt64(packet.RawData, 0) != netPeer.ConnectId)
                        {
                            //Old or incorrect disconnect
                            packet.Recycle();
                            return;
                        }

                        var netEvent = CreateEvent(NetEventType.Disconnect);
                        netEvent.Peer = netPeer;
                        netEvent.DataReader.SetSource(packet.RawData, sizeof(long), packet.GetDataSize() - sizeof(long));
                        netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose;
                        EnqueueEvent(netEvent);
                    }
                    break;

                case PacketProperty.ShutdownOk:
                    if (netPeer.ConnectionState != ConnectionState.ShutdownRequested)
                    {
                        return;
                    }
                    netPeer.ProcessPacket(packet);
                    NetUtils.DebugWriteForce(ConsoleColor.Cyan, "[NM] ShutdownOK!");
                    break;

                case PacketProperty.ConnectAccept:
                    if (netPeer.ProcessConnectAccept(packet))
                    {
                        var connectEvent = CreateEvent(NetEventType.Connect);
                        connectEvent.Peer = netPeer;
                        EnqueueEvent(connectEvent);
                    }
                    packet.Recycle();
                    return;

                default:
                    netPeer.ProcessPacket(packet);
                    return;
                }
                return;
            }

            //Unacked shutdown
            if (packet.Property == PacketProperty.Disconnect)
            {
                byte[] data = { (byte)PacketProperty.ShutdownOk };
                SendRaw(data, 0, 1, remoteEndPoint);
                return;
            }

            if (packet.Property == PacketProperty.ConnectRequest && packet.Size >= 12)
            {
                lock (_connectingPeers)
                {
                    if (_connectingPeers.Contains(remoteEndPoint))
                    {
                        return;
                    }
                }
                int peersCount = GetPeersCount(ConnectionState.Connected | ConnectionState.InProgress);
                if (peersCount < _maxConnections)
                {
                    int protoId = BitConverter.ToInt32(packet.RawData, 0);
                    if (protoId != NetConstants.ProtocolId)
                    {
                        NetUtils.DebugWrite(ConsoleColor.Cyan,
                                            "[NM] Peer connect reject. Invalid protocol ID: " + protoId);
                        return;
                    }

                    //Getting new id for peer
                    long connectionId = BitConverter.ToInt64(packet.RawData, sizeof(int));

                    // Read data and create request
                    var reader = new NetDataReader(null, 0, 0);
                    if (packet.GetDataSize() > sizeof(int) + sizeof(long))
                    {
                        reader.SetSource(packet.RawData, sizeof(int) + sizeof(long), packet.GetDataSize() - sizeof(int) - sizeof(long));
                    }

                    lock (_connectingPeers)
                    {
                        _connectingPeers.Add(remoteEndPoint);
                    }

                    var netEvent = CreateEvent(NetEventType.ConnectionRequest);
                    netEvent.ConnectionRequest =
                        new ConnectionRequest(connectionId, remoteEndPoint, reader, OnConnectionSolved);
                    if (String.IsNullOrEmpty(PasscodeKey) == true)
                    {
                        EnqueueEvent(netEvent);
                    }
                    else
                    {
                        netEvent.ConnectionRequest.AcceptIfKey(PasscodeKey);
                        OnConnectionSolved(netEvent.ConnectionRequest);
                    }
                }
            }
        }
Пример #4
0
        internal void AddIncomingPacket(NetPacket p)
        {
            if (p.IsFragmented)
            {
                NetUtils.DebugWrite("Fragment. Id: {0}, Part: {1}, Total: {2}", p.FragmentId, p.FragmentPart, p.FragmentsTotal);
                //Get needed array from dictionary
                ushort            packetFragId = p.FragmentId;
                IncomingFragments incomingFragments;
                if (!_holdedFragments.TryGetValue(packetFragId, out incomingFragments))
                {
                    incomingFragments = new IncomingFragments
                    {
                        Fragments = new NetPacket[p.FragmentsTotal]
                    };
                    _holdedFragments.Add(packetFragId, incomingFragments);
                }

                //Cache
                var fragments = incomingFragments.Fragments;

                //Error check
                if (p.FragmentPart >= fragments.Length || fragments[p.FragmentPart] != null)
                {
                    p.Recycle();
                    NetUtils.DebugWriteError("Invalid fragment packet");
                    return;
                }
                //Fill array
                fragments[p.FragmentPart] = p;

                //Increase received fragments count
                incomingFragments.ReceivedCount++;

                //Increase total size
                incomingFragments.TotalSize += p.GetDataSize();

                //Check for finish
                if (incomingFragments.ReceivedCount != fragments.Length)
                {
                    return;
                }

                NetUtils.DebugWrite("Received all fragments!");
                NetPacket resultingPacket = _packetPool.Get(p.Property, 0, incomingFragments.TotalSize);

                int resultingPacketOffset = 0;
                int firstFragmentSize     = fragments[0].GetDataSize();
                for (int i = 0; i < incomingFragments.ReceivedCount; i++)
                {
                    //Create resulting big packet
                    int fragmentSize = fragments[i].GetDataSize();
                    Buffer.BlockCopy(
                        fragments[i].RawData,
                        0,
                        resultingPacket.RawData,
                        resultingPacketOffset + firstFragmentSize * i,
                        fragmentSize);

                    //Free memory
                    fragments[i].Recycle();
                    fragments[i] = null;
                }

                //Send to process
                _netManager.ReceiveFromPeer(resultingPacket, _remoteEndPoint);

                //Clear memory
                //_packetPool.Recycle(resultingPacket);
                _holdedFragments.Remove(packetFragId);
            }
            else //Just simple packet
            {
                _netManager.ReceiveFromPeer(p, _remoteEndPoint);
                //_packetPool.Recycle(p);
            }
        }