Пример #1
0
        public void TrackingModuleTest()
        {
            RUDPDeliverTrackingModule trackingModule = new RUDPDeliverTrackingModule();

            ushort seed          = 65520;
            ushort payloadsCount = 0;

            trackingModule.Reset(65520);

            for (ushort i = seed; i != 20; i++)
            {
                RUDPPayload newPayload = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, 0);
                newPayload.Packet = this.emptyPacket;
                trackingModule.PrepareToDeliver(newPayload);
                payloadsCount++;
            }

            // 몇가지 Seq를 뺀 Ack를 만들어서 trackingModule에서 Ack를 처리하게 해야함
            // 그리고 결과를 처음 빠트린 Ack와 정상 ACk와 일치하는지 검증

            ushort halfPoint = seed;

            halfPoint += (ushort)(payloadsCount / 2);

            AckRange ackR = new AckRange(halfPoint, (ushort)(payloadsCount / 2));

            trackingModule.ProcessAckRange(ackR);

            ushort[] success = trackingModule.GetAndClearSuccessPayloadSeqNums();
            ushort[] fail    = trackingModule.GetAndClearLossPayloadSeqNums();

            Assert.IsTrue(ackR.AckCount == success.Length);
            Assert.IsTrue((payloadsCount - ackR.AckCount) == fail.Length);

            for (int i = 0; i < ackR.AckCount; i++)   //성공한 Ack
            {
                Assert.IsTrue((ackR.StartNum + i) == success[i]);
            }

            ushort start = seed;

            for (ushort i = 0; i < (payloadsCount - ackR.AckCount); i++)   //실패한 Ack
            {
                Assert.IsTrue((ushort)start == fail[i]);
                start++;
            }
        }
Пример #2
0
    private void OnReceivePayloads(Queue <RUDPPayload> payloads)
    {
        var iter = payloads.GetEnumerator();

        while (iter.MoveNext())
        {
            if (iter.Current.Packet != null)
            {
                switch (iter.Current.Tag)
                {
                case RUDPPayload.PAYLOAD_TAG.RAW: {
                    OnPacketReceive(iter.Current.Packet);
                    break;
                }

                case RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY: {
                    //Debug.Log(string.Format("DeliverNotify 패킷 받음 {0}", iter.Current.SequenceNumber));
                    if (this.deliverConfirmModule.JudgeIncomePayload(iter.Current))
                    {
                        OnPacketReceive(iter.Current.Packet);
                    }
                    break;
                }

                case RUDPPayload.PAYLOAD_TAG.ACK: {
                    AckRange currentAck = new AckRange(0, iter.Current.Packet.Pop_UInt16());
                    currentAck.StartNum = iter.Current.Packet.Pop_UInt16();
                    //Debug.Log(string.Format("Ack 받음 StartNum : {0}, Count : {1}", currentAck.StartNum, currentAck.AckCount));
                    deliverTrackingModule.ProcessAckRange(currentAck);
                    break;
                }

                case RUDPPayload.PAYLOAD_TAG.DISCONNECT: {
                    isDisable = true;
                    this.receiver.Disconnect();
                    this.sender.Disconnect(true, true);
                    OnDisconnect.Invoke();
                    break;
                }
                }
            }
        }
    }
Пример #3
0
    // AckRange 만큼의 Ack신호를 처리함. 주의점 : 절대로 타임아웃 패킷 정리와 동시에 수행되어서는 안됨.
    public void ProcessAckRange(AckRange range)
    {
        ushort currentInflightSeqNum = 0;
        int    distance = 0;

        lock (inflightPayloadsLock)
        {
            currentInflightSeqNum = this.inflightPayloads.Peek().Payload.SequenceNumber;
            distance = currentInflightSeqNum - range.StartNum;
        }


        if (distance == 0)   // 0이면 현재 inflight와 ack가 일치하는것임
        {
            for (int i = 0; i < range.AckCount; i++)
            {
                ushort seq = 0;
                lock (inflightPayloadsLock)
                {
                    seq = inflightPayloads.Dequeue().Payload.SequenceNumber;
                }
                statistics.SuccessPayloadCount++;
                lock (this.successPayloadSeqNumsLock)
                {
                    this.successPayloadSeqNums.Enqueue(seq);
                }
            }
        }
        else if (distance > 0 || distance < -InFlightPayload.benchmark)
        {     // Ack가 현재 Inflight보다 작음. 처리하지 않음
            if (distance > InFlightPayload.benchmark)
            { // 오버플로우 구간인지 검사하고 오버플로우 구간이면 처리하도록 함.
               // ack값이 기대보다 큼 중간에 패킷이 손실된것으로 판단, ack값 이전까지의 패킷을 손실로 처리
                ushort currentSeq = 0;
                lock (this.inflightPayloadsLock)
                {
                    currentSeq = this.inflightPayloads.Peek().Payload.SequenceNumber;
                }

                while (currentSeq != range.StartNum)
                {
                    lock (inflightPayloadsLock)
                    {
                        lock (this.lossPayloadSeqNumsLock)
                        {
                            this.lossPayloadSeqNums.Enqueue(inflightPayloads.Dequeue().Payload.SequenceNumber);
                        }
                    }
                    statistics.FailedPayloadCount++;
                    currentSeq++;
                }

                // ack에 해당하는 패킷들을 전송 성공처리 시켜줘야함.
                for (int i = 0; i < range.AckCount; i++)
                {
                    ushort seq = 0;
                    lock (inflightPayloadsLock)
                    {
                        seq = inflightPayloads.Dequeue().Payload.SequenceNumber;
                    }
                    statistics.SuccessPayloadCount++;
                    lock (this.successPayloadSeqNumsLock)
                    {
                        this.successPayloadSeqNums.Enqueue(seq);
                    }
                }
            }
            else   //오버플로우도 아니니까 현재 Inflight보다 작은 것으로 판단됨, 처리하지않도록함.
                   // ack신호를 무시하되, range 내에 무시해선 안될 ack가있는지 확인
            {
                ushort end = range.StartNum;
                end += range.AckCount;
                for (ushort currentAck = range.StartNum; currentAck != end; currentAck++)
                {
                    lock (inflightPayloadsLock)
                    {
                        if (currentAck == this.inflightPayloads.Peek().Payload.SequenceNumber)
                        {
                            lock (this.successPayloadSeqNumsLock)
                            {
                                this.successPayloadSeqNums.Enqueue(this.inflightPayloads.Dequeue().Payload.SequenceNumber);
                            }
                            statistics.SuccessPayloadCount++;
                        }
                    }
                }
            }
        }
        else
        {
            // ack값이 기대보다 큼 중간에 패킷이 손실된것으로 판단, ack값 이전까지의 패킷을 손실로 처리
            ushort currentSeq = 0;
            lock (this.inflightPayloadsLock) {
                currentSeq = this.inflightPayloads.Peek().Payload.SequenceNumber;
            }

            while (currentSeq != range.StartNum)
            {
                lock (inflightPayloadsLock) {
                    lock (this.lossPayloadSeqNumsLock) {
                        this.lossPayloadSeqNums.Enqueue(inflightPayloads.Dequeue().Payload.SequenceNumber);
                    }
                }
                statistics.FailedPayloadCount++;
                currentSeq++;
            }

            // ack에 해당하는 패킷들을 전송 성공처리 시켜줘야함.
            for (int i = 0; i < range.AckCount; i++)
            {
                ushort seq = 0;
                lock (inflightPayloadsLock)
                {
                    seq = inflightPayloads.Dequeue().Payload.SequenceNumber;
                }
                statistics.SuccessPayloadCount++;
                lock (this.successPayloadSeqNumsLock)
                {
                    this.successPayloadSeqNums.Enqueue(seq);
                }
            }
        }
    }
Пример #4
0
        public void ConfirmModuleTest()
        {
            RUDPDeliverConfirmModule confirmModule = new RUDPDeliverConfirmModule();

            confirmModule.Reset(ushort.MaxValue - 3); // 시퀀스 번호 최대값에 근접시키기(오버플로우 테스트 위해)

            // 시퀀스 번호가 낮을때 False Return
            RUDPPayload payload1 = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, ushort.MaxValue - 4);

            payload1.Packet = emptyPacket;

            bool result = confirmModule.JudgeIncomePayload(payload1);

            Assert.IsTrue(result == false);

            // 시퀀스 번호가 같을때 True Return
            RUDPPayload payload2 = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, ushort.MaxValue - 3);

            payload2.Packet = emptyPacket;

            bool result2 = confirmModule.JudgeIncomePayload(payload2);

            Assert.IsTrue(result2 == true);

            //시퀀스 번호가 높을때 (위에 테스트때문에 현재 ConfirmModule의 다음예상시퀀스는 ushort.MaxValue-2 임
            RUDPPayload payload3 = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, ushort.MaxValue - 1);

            payload3.Packet = emptyPacket;

            bool result3 = confirmModule.JudgeIncomePayload(payload3);

            Assert.IsTrue(result3 == true);

            //시퀀스 번호 오버플로우 구간일때(true 리턴해야함)
            RUDPPayload payload4 = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, 200);
            RUDPPayload payload5 = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, 201);
            RUDPPayload payload6 = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, 202);
            RUDPPayload payload7 = new RUDPPayload(RUDPPayload.PAYLOAD_TAG.DELIVERY_NOFIFY, 203);

            payload4.Packet = emptyPacket;
            payload5.Packet = emptyPacket;
            payload6.Packet = emptyPacket;
            payload7.Packet = emptyPacket;

            bool result4 = confirmModule.JudgeIncomePayload(payload4);

            Assert.IsTrue(result4 == true);

            // 밑에 AckRange검사용
            confirmModule.JudgeIncomePayload(payload5);
            confirmModule.JudgeIncomePayload(payload6);
            confirmModule.JudgeIncomePayload(payload7);


            //AckRange 가 잘 나오는지 검사
            Queue <AckRange> acks = confirmModule.PopPendingAckRanges();

            AckRange ack1 = acks.Dequeue();

            Assert.IsTrue(ack1.StartNum == (ushort.MaxValue - 3) && ack1.AckCount == 1);

            AckRange ack2 = acks.Dequeue();

            Assert.IsTrue(ack2.StartNum == (ushort.MaxValue - 1) && ack2.AckCount == 1);

            AckRange ack3 = acks.Dequeue();

            Assert.IsTrue(ack3.StartNum == 200 && ack3.AckCount == 4);
        }