コード例 #1
0
        private void SendAck(ITcpDataPacket packet, ITcpDataPacket lastDataPacket, bool firstSend)
        {
            StandardAckPacket outPacket = new StandardAckPacket(packet.Sequence)
            {
                ConnectionId   = ConnectionId,
                ResendCount    = packet.ResendCount,
                CurrentDataAck = lastDataPacket.Sequence
            };

            try
            {
                Transport.SendData(outPacket);

                if (firstSend)
                {
                    Stats.AcksSent++;
                }
                else
                {
                    Stats.AcksResent++;
                }
#if DEBUG
                Logger.Debug("Sent ack [" + outPacket + "]");
#endif
            }
            catch (Exception e)
            {
                Logger.Error("Failed to send ack to peer for packet " + packet.Sequence + " : " + e.Message, e);
            }
        }
コード例 #2
0
        private void SendAck(ITcpPacket packet, bool firstSend)
        {
            StandardAckPacket outPacket = new StandardAckPacket(packet.Sequence);

            outPacket.ConnectionId = ConnectionId;
            try
            {
                Transport.SendData(outPacket);
#if DEBUG
                Logger.Debug("Sent ack [" + outPacket + "]");
#endif

                if (firstSend)
                {
                    PacketCountTransmitAckFirst++;
                }
                else
                {
                    PacketCountTransmitAckResend++;
                }
            }
            catch (Exception e)
            {
                Logger.Error("Failed to send ack to peer for packet " + packet.Sequence + " : " + e.Message);
            }
        }
コード例 #3
0
        public override void ProcessAck(StandardAckPacket packet)
        {
            if (packet.Sequence == _sequenceOut)
            {
                PacketCountReceiveAckValid++;
                _ackEvent.Set();
            }
            else
            {
                PacketCountReceiveAckInvalid++;
#if DEBUG
                Logger.Debug("Dropping unexpected ack : " + packet);
#endif
            }
        }
コード例 #4
0
        public BasicTcpPacket getPacket(byte[] bytes)
        {
            BasicTcpPacket packet;

            switch (bytes[BasicTcpPacket.PKT_POS_TYPE])
            {
            case BasicTcpPacket.PKT_TYPE_DISCONNECT:
                packet = new StandardDisconnectPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_DISCONNECT_ACK:
                packet = new StandardDisconnectAckPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_DISCONNECT_RS:
                packet = new StandardDisconnectRsPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_CONNECT_RS_ACK:
                packet = new StandardConnectRsAckPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_CONNECT_NAME_RS:
                packet = new StandardNamedConnectRsPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_CONNECT_NAME_RQ:
                packet = new StandardNamedConnectRqPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_DATA:
                packet = new StandardTcpDataPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_ACK:
                packet = new StandardAckPacket();
                break;

            case BasicTcpPacket.PKT_TYPE_NOP:
                packet = new StandardTcpNopPacket();
                break;

            default:
                throw new UnknownPacketException("Failed to determine packet type");
            }
            packet.ProcessPacket(bytes);
            return(packet);
        }
コード例 #5
0
 private void ProcessAckPacket(StandardAckPacket packet)
 {
     try
     {
         TcpConnectionHolder conn = _tcpConnections.GetRemoteConnection(packet.ConnectionId);
         // Lock sending while we process this packet (we will still be able to receive)
         // Now TcpConnection doesn't have to be threadsafe, but each connection
         // can process acks independently at full speed.
         lock (conn.SendLock)
         {
             // now process the ackPacket;
             conn.Connection.ProcessAck(packet);
         }
     }
     catch (ConnectionException e)
     {
         Logger.Error("Dropping ack packet [" + packet + "], failed to get a connection : " + e.Message);
     }
 }
コード例 #6
0
        // received this ack
        public override void ProcessAck(StandardAckPacket packet)
        {
            Stats.AcksReceived++;
            lock (_ackWaitingLock)
            {
                // update the rtt based on this packet if its a fresh ack and there is something in the window
                if (packet.ResendCount == 0 && _sendWindow[_oldestUnackedPacket] != null)
                {
                    // Is this packets seq ahead of the ones we are expecting
                    int seqDiff = BasicTcpPacket.CompareSequences(_sendWindow[_oldestUnackedPacket].Sequence,
                                                                  packet.Sequence);
                    if (seqDiff <= 0)
                    {
                        int distance = DifferenceInSequences(_sendWindow[_oldestUnackedPacket].Sequence,
                                                             packet.Sequence);
                        if (distance < WindowSize)
                        {
                            var matchingDataPacket = _sendWindow[(_oldestUnackedPacket + distance) % WindowSize];
                            if (matchingDataPacket != null && matchingDataPacket.Sequence == packet.Sequence)
                            {
                                long rtt = Environment.TickCount - matchingDataPacket.Timestamp;
                                AdjustRetryInterval(rtt);
#if DEBUG
                                Logger.Debug("RTT of " + matchingDataPacket + " is " + rtt + ", srtt=" + _srtt +
                                             ", deviation=" + _deviation + ", retryInterval=" + _retryInterval);
#endif
                            }
                            else
                            {
                                Logger.Error("Got an ack " + packet + " but can't find matching data packet, oldest unacked is "
                                             + _sendWindow[_oldestUnackedPacket] + ", nextSeqOut=" + _nextDataSeqOut + ", nextSeqIn=" + _nextDataSeqIn + ", lastAckPaket=" + _lastAckPacket);
                            }
                        }
                        else
                        {
                            Logger.Error("Got an ack for a message too far in the future [distance=" + distance + "]");
                        }
                    }
                    else
                    {
#if DEBUG
                        Logger.Debug("Got an ack from the past, cannot use it to calculate RTT");
#endif
                    }
                }

                // loop through expected acks clearing them until we are in sync with incoming ack packet
                while (_sendWindow[_oldestUnackedPacket] != null)
                {
                    // current data packet in the window
                    var currentDataPacket = _sendWindow[_oldestUnackedPacket];
                    int seqDiff           = BasicTcpPacket.CompareSequences(currentDataPacket.Sequence,
                                                                            packet.CurrentDataAck);
                    // If this incoming packet's currentDataAck is the one we are expecting (==) or one ahead of our current
                    // expected ack < (indicating receiver has all those up until this one)
                    if (seqDiff <= 0)
                    {
                        // null the packet (its acked)
                        _sendWindow[_oldestUnackedPacket] = null;
                        // oldestUnackedPaket is now the next one
                        _oldestUnackedPacket = (byte)((_oldestUnackedPacket + 1) % WindowSize);
#if DEBUG
                        Logger.Debug("Cleared old packet " + currentDataPacket.Sequence + ", oldestUnackedPacket=" +
                                     _oldestUnackedPacket);
#endif

                        // save the last ack we received (and the count)
                        _lastAckPacketSeq = currentDataPacket.Sequence;
                        // and we have received it once
                        _lastAckPacketCount = 1;
                        // if the current pack is the exact one we received an ack for
                        // then lets reset the timer and leave the loop
                        if (seqDiff == 0)
                        {
                            lock (_retryTimer)
                            {
                                // reset the time against the next unacked packet
                                long timeLeft = _retryInterval - (Environment.TickCount - currentDataPacket.Timestamp);
                                if (timeLeft <= 0)
                                {
                                    timeLeft = 1;
                                }
                                if (_retryTimer.Enabled)
                                {
                                    _retryTimer.Stop();
                                }
                                _retryTimer.Interval = timeLeft;
#if DEBUG
                                Logger.Debug("Setup retransmit timeout for " + currentDataPacket.Sequence + " to " +
                                             timeLeft + "ms.");
#endif
                                _retryTimer.Start();
                            }
                            break;
                        }
                    }
                    else
                    {
                        if (packet.CurrentDataAck == _lastAckPacketSeq)
                        {
                            // this is an old ack, if we get 3, we retrasmit the next one
                            _lastAckPacketCount++;
#if DEBUG
                            Logger.Debug("Discarding the repeated ack " + packet + "[" + _lastAckPacketCount + " times], checking for retransmit");
#endif
                            // we only resend via fast transmit if it is a count of 3 and it hasn't been resent before
                            if (_lastAckPacketCount == 3)
                            {
                                RunFastRetransmit(currentDataPacket);
                            }
                        }
                        else
                        {
                            // old ack too far back to care
#if DEBUG
                            Logger.Debug("Discarding old ack " + packet);
#endif
                            Stats.OldAcksReceived++;
                        }
                        break;
                    }
                }
#if DEBUG
                Logger.Debug("Finished processing ack " + packet.Sequence + ", expecting next ack to be " +
                             (_sendWindow[_oldestUnackedPacket] == null
                                  ? "none"
                                  : _sendWindow[_oldestUnackedPacket].Sequence.ToString()));
#endif
                Monitor.PulseAll(_ackWaitingLock);
            }
        }
コード例 #7
0
 public abstract void ProcessAck(StandardAckPacket packet);