示例#1
0
        internal void OnICMPError(RUDPOutgoingPacket packet)
        {
            int errorMTU = packet.Payload.Length + RUDPStack.UDPHeaderLength + RUDPStack.RUDPHeaderLength;
            int nextMTU  = (int)(errorMTU * 0.75);

            nextMTU = Math.Min(Math.Max(Math.Max(MinMTU, nextMTU), _rudp._mtu), MaxMTU);

            Trace("MTU:OnICMPError:" + errorMTU + " -> " + nextMTU);

            //---- We have a result for the packet
            _lastProbeTS         = -1;
            _mtuProbeResendCount = 0;

            //---- User packet : URGENT
            if (packet.Channel == RUDPPacketChannel.UserPacket)
            {
                _rudp._mtu = nextMTU;
                SendProbe(_rudp._mtu);
                return;
            }

            //---- MTU probe
            if (packet.Channel == RUDPPacketChannel.MTUTuning)
            {
                if (errorMTU > _rudp._mtu && nextMTU < _rudp._mtu)
                {
                    nextMTU = _rudp._mtu;
                }
                nextMTU = Math.Min(Math.Max(MinMTU, nextMTU), MaxMTU);
                SendDelayedProbe(nextMTU, DefaultProbeInterval);
                return;
            }
        }
示例#2
0
 /// <summary>
 /// Called when a packet is resended
 /// </summary>
 internal void OnTimeOut(RUDPOutgoingPacket packet)
 {
     //---- Congestion
     lock (this)
     {
         OnTimeOut_UpdateParameters(packet);
         OnTimeOut_UpdateWindow();
     }
 }
示例#3
0
        internal void OnTimeOut_UpdateParameters(RUDPOutgoingPacket packet)
        {
            // Karn's Algorithm : On successive retransmissions, set each timeout to twice the previous one.
            if (packet.Retransmission > 0)
            {
                //-- Calculate _rto
#if TRACE_MEMORY
                traces.Add("RTO x 2 : " + _rudp._rto + " new : " + _rudp._rto * 2);
#endif
                // Exponential RTO Backoff process
                _rudp.RTO = Math.Min(_rudp.RTO * 2, 60000000);

                //-- Calculate _sto
                _rudp.STO = (int)(15000000 + 4 * _rudp.RTT);
            }
        }
示例#4
0
        internal void OnACK_UpdateParameters(RUDPOutgoingPacket packet, double currentRTT)
        {
            //---- TCP - (RFC 2988) : http://www.faqs.org/rfcs/rfc2988.html
            if (packet.Retransmission > 0)
            {
                return;
            }

            double rudpRTT;
            double rudpDeltaRTT;

            //-- Calculate _rtt
            if (_rudp._rtt == 0)
            {
                rudpRTT      = currentRTT;
                rudpDeltaRTT = currentRTT / 2;
            }
            else
            {
                rudpRTT      = _rudp.RTT;
                rudpDeltaRTT = _rudp.DeltaRTT;

                // Jacobson's algorithm
                rudpRTT = (0.875 * rudpRTT + 0.125 * currentRTT);
                double error = currentRTT - rudpRTT;
                rudpDeltaRTT = (0.75 * rudpDeltaRTT + 0.25 * Math.Abs(error));
            }

            //-- Calculate _rto
#if TRACE_MEMORY
            traces.Add("RTO ACK : " + _rudp._rto + " new : " + _rudp._rtt + Math.Max(1, 4 * _rudp._deltaRtt) + "RTT=" + _rudp._rtt);
#endif
            double Rto = rudpRTT + Math.Max(4, 4 * rudpDeltaRTT);

            //if (_rudp._rto < 1000000)
            //    _rudp._rto = 1000000;
            if (Rto > 60000000)
            {
                Rto = 60000000;
            }

            //-- Calculate _sto
            long Sto = (long)(15000000 + 4 * rudpRTT);

            //-- Update parameters
            _rudp.SetRTT(rudpRTT, rudpDeltaRTT, Rto, Sto);
        }
示例#5
0
		abstract internal void OnACK_UpdateWindow(RUDPOutgoingPacket packet);
示例#6
0
		internal void OnACK_UpdateParameters(RUDPOutgoingPacket packet, double currentRTT)
		{
			//---- TCP - (RFC 2988) : http://www.faqs.org/rfcs/rfc2988.html
			if (packet.Retransmission > 0)
				return;

			double rudpRTT;
			double rudpDeltaRTT;

			//-- Calculate _rtt
			if (_rudp._rtt == 0)
			{
				rudpRTT = currentRTT;
				rudpDeltaRTT = currentRTT / 2;
			}
			else
			{
				rudpRTT = _rudp.RTT;
				rudpDeltaRTT = _rudp.DeltaRTT;

				// Jacobson's algorithm
				rudpRTT = (0.875 * rudpRTT + 0.125 * currentRTT);
				double error = currentRTT - rudpRTT;
				rudpDeltaRTT = (0.75 * rudpDeltaRTT + 0.25 * Math.Abs(error));
			}

			//-- Calculate _rto
#if TRACE_MEMORY
			traces.Add("RTO ACK : " + _rudp._rto + " new : " + _rudp._rtt + Math.Max(1, 4 * _rudp._deltaRtt) + "RTT=" + _rudp._rtt);
#endif
			double Rto = rudpRTT + Math.Max(4, 4 * rudpDeltaRTT);

			//if (_rudp._rto < 1000000)
			//    _rudp._rto = 1000000;
			if (Rto > 60000000)
				Rto = 60000000;

			//-- Calculate _sto
			long Sto = (long)(15000000 + 4 * rudpRTT);

			//-- Update parameters
			_rudp.SetRTT(rudpRTT, rudpDeltaRTT, Rto, Sto);
		}
示例#7
0
		internal void OnACK(RUDPOutgoingPacket packet, double currentRTT)
		{
			// Duplicated ACK
			if (packet == null)
				return;

			FlightSize -= packet.Payload.Length + RUDPStack.UDPHeaderLength;

			//---- Congestion
			lock (this)
			{
				OnACK_UpdateParameters(packet, currentRTT);
				OnACK_UpdateWindow(packet);
			}

			//---- Sliding
			int packetId = packet.PacketId;

			_sendSlotsLock.EnterWriteLock();

			SWSlot slot = null;
			try
			{
				for (int index = 0; index < _sendSlots.Count; index++)
				{
					slot = _sendSlots[index];

					// Delete this slot
					if (slot.EndPacketId < 0 && slot.StartPacketId == packetId)
					{
						_sendSlots.RemoveAt(index);
						return;
					}

					// Decrease the slot
					if (slot.EndPacketId > -1 && slot.StartPacketId == packetId)
					{
						slot.StartPacketId++;
						slot.StartByte += packet.Payload.Length;
						if (slot.StartPacketId == slot.EndPacketId)
							slot.EndPacketId = -1;
						return;
					}

					// Decrease the slot
					if (slot.EndPacketId > -1 && slot.EndPacketId == packetId)
					{
						slot.EndPacketId--;
						slot.EndByte -= packet.Payload.Length;
						if (slot.StartPacketId == slot.EndPacketId)
							slot.EndPacketId = -1;
						return;
					}

					// Split the slot
					if (slot.EndPacketId > -1 && slot.StartPacketId <= packetId && slot.EndPacketId >= packetId)
					{
						// Right slot
						SWSlot newSlot = new SWSlot(packetId + 1,
													slot.EndPacketId,
													packet.Sequence + packet.Payload.Length + 1,
													slot.EndByte);
						if (newSlot.StartPacketId == newSlot.EndPacketId)
							newSlot.EndPacketId = -1;
						_sendSlots.Insert(index + 1, newSlot);

						// Left slot
						slot.EndPacketId = packetId - 1;
						slot.EndByte = packet.Sequence - 1;
						if (slot.StartPacketId == slot.EndPacketId)
							slot.EndPacketId = -1;

						return;
					}
				}

			}
			finally
			{
				_sendSlotsLock.ExitWriteLock();
				ResumeTransmission();
			}
		}
示例#8
0
		internal void OnTimeOut_UpdateParameters(RUDPOutgoingPacket packet)
		{
			// Karn's Algorithm : On successive retransmissions, set each timeout to twice the previous one.
			if (packet.Retransmission > 0)
			{
				//-- Calculate _rto
#if TRACE_MEMORY
				traces.Add("RTO x 2 : " + _rudp._rto + " new : " + _rudp._rto * 2);
#endif
				// Exponential RTO Backoff process
				_rudp.RTO = Math.Min(_rudp.RTO * 2, 60000000);

				//-- Calculate _sto
				_rudp.STO = (int)(15000000 + 4 * _rudp.RTT);
			}
		}
示例#9
0
		/// <summary>
		/// Called when a packet is resended
		/// </summary>
		internal void OnTimeOut(RUDPOutgoingPacket packet)
		{
			//---- Congestion
			lock (this)
			{
				OnTimeOut_UpdateParameters(packet);
				OnTimeOut_UpdateWindow();
			}
		}
示例#10
0
		internal void OnICMPError(RUDPOutgoingPacket packet)
		{
			int errorMTU = packet.Payload.Length + RUDPStack.UDPHeaderLength + RUDPStack.RUDPHeaderLength;
			int nextMTU = (int)(errorMTU * 0.75);
			nextMTU = Math.Min(Math.Max(Math.Max(MinMTU, nextMTU),_rudp._mtu), MaxMTU);

			Trace("MTU:OnICMPError:" + errorMTU + " -> " + nextMTU);

			//---- We have a result for the packet
			_lastProbeTS = -1;
			_mtuProbeResendCount = 0;

			//---- User packet : URGENT
			if (packet.Channel == RUDPPacketChannel.UserPacket)
			{
				_rudp._mtu = nextMTU;
				SendProbe(_rudp._mtu);
				return;
			}

			//---- MTU probe
			if (packet.Channel == RUDPPacketChannel.MTUTuning)
			{
				if (errorMTU > _rudp._mtu && nextMTU < _rudp._mtu)
					nextMTU = _rudp._mtu;
				nextMTU = Math.Min(Math.Max(MinMTU, nextMTU), MaxMTU);
				SendDelayedProbe(nextMTU, DefaultProbeInterval);
				return;
			}
		}
示例#11
0
		private static bool SocketSendPacket(RUDPSocket rudp, RUDPOutgoingPacket packet, byte[] rudpPayload, long now)
		{
			//---- Send the request
			try
			{
				rudp._physical._socket.SendTo(rudpPayload, rudp._remoteEndPoint);
				//rudp._physical._socket.BeginSendTo(rudpPayload, 0, rudpPayload.Length, SocketFlags.None, rudp._remoteEndPoint, null, null);
			}
			catch (SocketException exception)
			{
				if (exception.ErrorCode == (int)SocketError.MessageSize && packet.Channel == RUDPPacketChannel.MTUTuning)
				{
					// ICMP type 3 subtype 4
					// ICMP message, tell that this packet is too big
					rudp._pmtuDiscovery.OnICMPError(packet);
					return true;
				}

				OnSocketUnhandledError(rudp, SocketErrorToRUDPSocketError(exception.SocketErrorCode), null);
				return false;
			}

			rudp._lastSendTS = now;
			packet.TSLastSend = now;

			return true;
		}
示例#12
0
		internal static void ReleaseOutgoingPacket(RUDPOutgoingPacket packet)
		{
			//return;
			_outgoingPacketsPools.Enqueue(packet);
			PayloadManager.Deallocate(packet.Channel, packet.Payload);
			packet.Payload = null;
		}
示例#13
0
		private static void SetPacketACKed(RUDPSocket rudp, RUDPOutgoingPacket packet, double currentRTT)
		{
			lock (packet)
			{
				if (packet.IsACKed)
					return;

				rudp._controlWindow.OnACK(packet, currentRTT);

				// Mark as ACKed
				packet.IsACKed = true;
			}

			Trace("Packet ACKed(" + rudp.Handle + "): " + packet.PacketId + " " + packet.Channel);

			//---- Ping ACK
			if ((packet.Channel == RUDPPacketChannel.Ping || packet.Channel == RUDPPacketChannel.PingRendezVous) &&
				rudp._status == RUDPSocketStatus.Connecting)
			{
				rudp._status = RUDPSocketStatus.Connected;

				// MTU tuning
				if (rudp._usePMTUDiscovery)
					rudp._pmtuDiscovery.StartTuning();

				// connection done
				rudp.OnEndConnect(RUDPSocketError.Success);

				return;
			}

			//---- Tear Down ACK : It was a tear down message, it has been received, we can close
			if (packet.Channel == RUDPPacketChannel.TearDown &&
				rudp._status == RUDPSocketStatus.Closing)
			{
				rudp._status = RUDPSocketStatus.ClosingACKed;

				// Remove it to our list of "connected" sockets
				if (rudp._remoteEndPoint != null)
				{
					// Unregister for the stack
					UnregisterRUDPSocket(rudp);
					rudp._physical.UnregisterConnectedSocket(rudp);
				}
			}
		}
示例#14
0
 abstract internal void OnACK_UpdateWindow(RUDPOutgoingPacket packet);
示例#15
0
        internal void OnACK(RUDPOutgoingPacket packet, double currentRTT)
        {
            // Duplicated ACK
            if (packet == null)
            {
                return;
            }

            FlightSize -= packet.Payload.Length + RUDPStack.UDPHeaderLength;

            //---- Congestion
            lock (this)
            {
                OnACK_UpdateParameters(packet, currentRTT);
                OnACK_UpdateWindow(packet);
            }

            //---- Sliding
            int packetId = packet.PacketId;

            _sendSlotsLock.EnterWriteLock();

            SWSlot slot = null;

            try
            {
                for (int index = 0; index < _sendSlots.Count; index++)
                {
                    slot = _sendSlots[index];

                    // Delete this slot
                    if (slot.EndPacketId < 0 && slot.StartPacketId == packetId)
                    {
                        _sendSlots.RemoveAt(index);
                        return;
                    }

                    // Decrease the slot
                    if (slot.EndPacketId > -1 && slot.StartPacketId == packetId)
                    {
                        slot.StartPacketId++;
                        slot.StartByte += packet.Payload.Length;
                        if (slot.StartPacketId == slot.EndPacketId)
                        {
                            slot.EndPacketId = -1;
                        }
                        return;
                    }

                    // Decrease the slot
                    if (slot.EndPacketId > -1 && slot.EndPacketId == packetId)
                    {
                        slot.EndPacketId--;
                        slot.EndByte -= packet.Payload.Length;
                        if (slot.StartPacketId == slot.EndPacketId)
                        {
                            slot.EndPacketId = -1;
                        }
                        return;
                    }

                    // Split the slot
                    if (slot.EndPacketId > -1 && slot.StartPacketId <= packetId && slot.EndPacketId >= packetId)
                    {
                        // Right slot
                        SWSlot newSlot = new SWSlot(packetId + 1,
                                                    slot.EndPacketId,
                                                    packet.Sequence + packet.Payload.Length + 1,
                                                    slot.EndByte);
                        if (newSlot.StartPacketId == newSlot.EndPacketId)
                        {
                            newSlot.EndPacketId = -1;
                        }
                        _sendSlots.Insert(index + 1, newSlot);

                        // Left slot
                        slot.EndPacketId = packetId - 1;
                        slot.EndByte     = packet.Sequence - 1;
                        if (slot.StartPacketId == slot.EndPacketId)
                        {
                            slot.EndPacketId = -1;
                        }

                        return;
                    }
                }
            }
            finally
            {
                _sendSlotsLock.ExitWriteLock();
                ResumeTransmission();
            }
        }