コード例 #1
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
        internal RUDPSocketError BeginConnect(RUDPSocket rudp, int timeOut)
        {
            //---- Add it to our list of "connected" sockets
            RegisterConnectedSocket(rudp);

            return(RUDPStack.BeginConnect(rudp, timeOut));
        }
コード例 #2
0
ファイル: PhysicalSocket.cs プロジェクト: cheehwasun/ourmsg
		internal void Dispose()
		{
			_receiveBuffer = null;
			_connectedRDUPs.Clear();
			_acceptingRDUP = null;
			_socket = null;
		}
コード例 #3
0
ファイル: PMTUDiscovery.cs プロジェクト: xingchaoet/ourmsg
        internal PMTUDiscovery(RUDPSocket rudp)
        {
            _rudp = rudp;

            // Start with minimum MTU to insure correct communication
            _rudp._mtu = MinMTU;
        }
コード例 #4
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
 internal void Dispose()
 {
     _receiveBuffer = null;
     _connectedRDUPs.Clear();
     _acceptingRDUP = null;
     _socket        = null;
 }
コード例 #5
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
        internal RUDPSocket OnEndAccept(IPEndPoint remoteEndPoint, int packetId)
        {
            // Create the new socket
            RUDPSocket acceptSocket = new RUDPSocket();

            acceptSocket._physical       = this;
            acceptSocket._status         = RUDPSocketStatus.Connected;
            acceptSocket._remoteEndPoint = remoteEndPoint;
            acceptSocket._incomingPackets.CurrentPacketId = packetId;

            // Add it to our list of "connected" sockets
            RUDPStack.RegisterRUDPSocket(acceptSocket);
            RegisterConnectedSocket(acceptSocket);

            // Release it
            RUDPSocket previousAcceptingRDUP = _acceptingRDUP;

            _acceptingRDUPLock.EnterWriteLock();
            _acceptingRDUP = null;
            _acceptingRDUPLock.ExitWriteLock();

            // End the accept
            previousAcceptingRDUP.OnEndAccept(acceptSocket);

            return(acceptSocket);
        }
コード例 #6
0
ファイル: PMTUDiscovery.cs プロジェクト: cheehwasun/ourmsg
		internal PMTUDiscovery(RUDPSocket rudp)
		{
			_rudp = rudp;

			// Start with minimum MTU to insure correct communication
			_rudp._mtu = MinMTU;
		}
コード例 #7
0
        internal long TSReceived;         // Time Stamp : when message is received

        internal RUDPIngoingPacket(RUDPSocket rudp, int packetId, byte[] payload, RUDPPacketChannel channel, long tsReceived)
        {
            RUDP       = rudp;
            PacketId   = packetId;
            Channel    = channel;
            Payload    = payload;
            TSReceived = tsReceived;
        }
コード例 #8
0
ファイル: RUDPIngoingPacket.cs プロジェクト: iraychen/ourmsg
		internal long TSReceived; // Time Stamp : when message is received

		internal RUDPIngoingPacket(RUDPSocket rudp, int packetId, byte[] payload, RUDPPacketChannel channel, long tsReceived)
		{
			RUDP = rudp;
			PacketId = packetId;
			Channel = channel;
			Payload = payload;
			TSReceived = tsReceived;
		}
コード例 #9
0
		internal FragmentInformation(RUDPSocket rudpSocket, bool isReliable, byte[] payload, int offset, int size, RUDPSendIAsyncResult asyncResult)
		{
			rudp = rudpSocket;
			IsReliable = isReliable;
			Offset = offset;
			Size = size;
			Payload = payload;
			AsyncResult = asyncResult;
		}
コード例 #10
0
 internal FragmentInformation(RUDPSocket rudpSocket, bool isReliable, byte[] payload, int offset, int size, RUDPSendIAsyncResult asyncResult)
 {
     rudp        = rudpSocket;
     IsReliable  = isReliable;
     Offset      = offset;
     Size        = size;
     Payload     = payload;
     AsyncResult = asyncResult;
 }
コード例 #11
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
        internal void BeginAccept(RUDPSocket rudp, AsyncCallback callback, Object state)
        {
            rudp._status = RUDPSocketStatus.Accepting;

            //---- Only one socket accept on this port
            _acceptingRDUPLock.EnterWriteLock();
            _acceptingRDUP = rudp;
            _acceptingRDUPLock.ExitWriteLock();

            //---- Unregister for the stack
            RUDPStack.BeginAccept(rudp);
        }
コード例 #12
0
        internal void OnEndAccept(RUDPSocket acceptedSocket)
        {
            RUDPAcceptIAsyncResult result = null;

            Interlocked.Exchange <RUDPAcceptIAsyncResult>(ref result, _asyncResultAccept);
            if (result == null)
            {
                return;
            }

            Interlocked.Exchange <RUDPAcceptIAsyncResult>(ref _asyncResultAccept, null);

            result.AcceptedSocket = acceptedSocket;
            result.ForceAsyncCall = true;
            result.SetAsCompleted(RUDPSocketError.Success, false);
        }
コード例 #13
0
        public IAsyncResult BeginAccept(AsyncCallback callback, Object state)
        {
            RUDPAcceptIAsyncResult asyncResult = new RUDPAcceptIAsyncResult(this, callback, state);

            Interlocked.Exchange <RUDPAcceptIAsyncResult>(ref _asyncResultAccept, asyncResult);

            //---- Check if we do not already have a socket
            if (_acceptedRUDPSockets.Count > 0)
            {
                RUDPSocket rudp = _acceptedRUDPSockets[0];
                lock (_acceptedRUDPSockets)
                    _acceptedRUDPSockets.RemoveAt(0);

                OnEndAccept(rudp);
            }
            else
            {
                //-- Request an accept
                _physical.BeginAccept(this, callback, state);
            }

            return(asyncResult);
        }
コード例 #14
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static void Shutdown(RUDPSocket rudp)
		{
			if (rudp._status == RUDPSocketStatus.Accepting)
			{
				rudp.Reset(RUDPSocketStatus.Closed);
				return;
			}

			if (rudp._status == RUDPSocketStatus.Closed ||
				rudp._isShutingDown)
				return;

			if (rudp._status == RUDPSocketStatus.Closing ||
				rudp._status == RUDPSocketStatus.ClosingACKed)
				return;

			if (rudp._status == RUDPSocketStatus.Connecting)
			{
				rudp.Reset(RUDPSocketStatus.Closed);
				return;
			}

			//---- Send the tear down message

			//-- Update the status
			rudp._isShutingDown = true;
			rudp._status = RUDPSocketStatus.Closing;

			//-- Wait for sending
			while (!rudp._controlWindow.CanSend(0))
			{
				if (rudp._status != RUDPSocketStatus.Closing)
					return;
				Thread.Sleep(100);
			}

			//-- Send the tear down message
			PushPacketToSend(rudp, true, RUDPPacketChannel.TearDown, null, 0, 0);

			//---- Currently closing the connection, wait for the end of the operation
			long startTime = HiResTimer.MicroSeconds;

			//-- Wait until closed
			// Wait until "ClosingACKed"
			// Wait until we have receive the "TearDown" message too and send the ACK
			// Wait until "Time out"
			while (rudp._status == RUDPSocketStatus.Closing &&
					rudp._outgoingPackets.Count > 0 &&
					(HiResTimer.MicroSeconds - startTime) < rudp._sto)
			{
				Thread.Sleep(100);
			}

			//---- Set the status as closed
			rudp.Reset(RUDPSocketStatus.Closed);

			//---- Notify
			rudp._physical.OnDisconnected(rudp, RUDPSocketError.Shutdown);
		}
コード例 #15
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		/// <summary>
		/// Close the socket. Send the tear down message.
		/// </summary>
		internal static void Close(RUDPSocket rudp)
		{
			if (rudp._status == RUDPSocketStatus.Closed)
				return;

			if (rudp._status == RUDPSocketStatus.Accepting)
			{
				rudp.Reset(RUDPSocketStatus.Closed);
				return;
			}

			AsyncShutdown(rudp);
		}
コード例 #16
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static RUDPSocketError BeginConnect(RUDPSocket rudp, int timeOut)
		{
			Trace("Connecting to :" + rudp._remoteEndPoint);

			if (rudp._status == RUDPSocketStatus.Connected)
				return RUDPSocketError.IsConnected;

			if (rudp._status == RUDPSocketStatus.Connecting)
				return RUDPSocketError.AlreadyInProgress;

			//---- Set the status
			rudp.Reset(RUDPSocketStatus.Connecting);

			//---- Register for the stack
			RUDPStack.RegisterRUDPSocket(rudp);

			//---- Send a ping
			if (rudp.IsRendezVousMode)
				PushPacketToSend(rudp, true, RUDPPacketChannel.PingRendezVous, null, 0, 0);
			else
				PushPacketToSend(rudp, true, RUDPPacketChannel.Ping, null, 0, 0);

			return RUDPSocketError.Success;
		}
コード例 #17
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static void RegisterRUDPSocket(RUDPSocket rudp)
		{
			int controlThreadId = -1;
			int count = Int32.MaxValue;
			for (int index = 0; index < _controlThreadInformations.Length; index++)
				if (_controlThreadInformations[index]._rudpSockets.Count < count)
				{
					controlThreadId = index;
					count = _controlThreadInformations[index]._rudpSockets.Count;
				}

			// Register the socket
			rudp._controlThreadId = controlThreadId;
			_controlThreadInformations[controlThreadId]._rudpSocketsLock.EnterWriteLock();
			if (!_controlThreadInformations[controlThreadId]._rudpSockets.Contains(rudp))
				_controlThreadInformations[controlThreadId]._rudpSockets.Add(rudp);
			_controlThreadInformations[controlThreadId]._rudpSocketsLock.ExitWriteLock();
		}
コード例 #18
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		/// <summary>
		/// Called when we have an error on a socket.
		/// </summary>
		static internal void OnSocketUnhandledError(RUDPSocket rudp, RUDPSocketError error, RUDPSendIAsyncResult sendAsyncResult)
		{
			//---- Disconnect the socket
			OnDisconnected(rudp, DisconnectionReason.SocketError);

			//---- Handle the error and forward it to the socket
			if (rudp._status == RUDPSocketStatus.Connecting)
				rudp.OnEndConnect(error);
			else
			{
				// On Send Error
				if (sendAsyncResult != null)
					rudp.OnEndSend(error, sendAsyncResult);

				// ELSE ... HOW TO GET sendAsyncResult when NULL ?????

				// On Receive Error
				RUDPReceiveIAsyncResult receiveAsyncResult = null;
				Interlocked.Exchange<RUDPReceiveIAsyncResult>(ref receiveAsyncResult, rudp._asyncResultReceive);
				if (receiveAsyncResult != null)
				{
					Interlocked.Exchange<RUDPReceiveIAsyncResult>(ref rudp._asyncResultReceive, null);

					rudp.OnEndReceive(error, null, true, receiveAsyncResult);
				}
			}
		}
コード例 #19
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static void KeepAliveTimer(RUDPSocket rudp, long now)
		{
			long lastSendTS = Math.Max(rudp._lastSendTS, rudp._lastACKSendTS);

			//---- Send a keep alive (if possible)
			if (rudp._status == RUDPSocketStatus.Connected &&
				(now - lastSendTS) > RUDPStack.KeepAliveInterval &&
				rudp._controlWindow.CanSend(0))
			{
				PushPacketToSend(rudp, true, RUDPPacketChannel.KeepAlive, new byte[0], 0, 0);
			}
		}
コード例 #20
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
 internal void OnEndSend(RUDPSocket rudp, RUDPSendIAsyncResult asyncResult)
 {
     rudp.OnEndSend(RUDPSocketError.Success, asyncResult);
 }
コード例 #21
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
 internal void Close(RUDPSocket rudp)
 {
     RUDPStack.Close(rudp);
 }
コード例 #22
0
 internal RUDPSocketNetworkInformation(RUDPSocket rudp)
 {
     _rudp = rudp;
 }
コード例 #23
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
 internal void Shutdown(RUDPSocket rudp)
 {
     RUDPStack.Shutdown(rudp);
 }
コード例 #24
0
 internal RUDPSendIAsyncResult(RUDPSocket rudp, AsyncCallback callback, Object state, int size)
     : base(rudp, callback, state)
 {
     _size = size;
 }
コード例 #25
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static bool PushPacketToSend(RUDPSocket rudp,
											bool reliablePacket,
											RUDPPacketChannel channel,
											byte[] payload,
											int offset,
											int payloadLength)
		{
			int packetId = -1;
			if (reliablePacket)
				packetId = Interlocked.Increment(ref rudp._ougoingPacketId);

			//---- Get the SACKs
			SACKSlot slot1 = null;
			SACKSlot slot2 = null;
			SACKSlot slot3 = null;
			SACKSlot slot4 = null;
			rudp._sackWindow.GetSLACKSlots(out slot1, out slot2, out slot3, out slot4);

			//---- Copy the payload to send
			byte[] rudpPayload = MakePacketPayload(rudp, packetId, channel, slot1, slot2, slot3, slot4, payload, offset, payloadLength);

			//---- Create a packet
			RUDPOutgoingPacket packet = NewOutgoingPacket(packetId, rudp._sequence, rudpPayload, channel);
			packet.CurrentCwnd = rudp._controlWindow.CWND;

			if (reliablePacket)
			{
				//---- Notify the control window
				rudp._controlWindow.OnSend(packetId, rudp._sequence, payloadLength);

				//---- Increment sequence number
				Interlocked.Exchange(ref rudp._sequence, rudp._sequence + payloadLength);
			}

			//---- In the "resend list"
			if (reliablePacket)
			{
				rudp._outgoingPacketsLock.EnterWriteLock();
				rudp._outgoingPackets.Add(packet);
				rudp._outgoingPacketsLock.ExitWriteLock();
			}

			//---- Send the packet
			packet.TSFirstSend = HiResTimer.MicroSeconds;
			if (!SocketSendPacket(rudp, packet, packet.Payload, packet.TSFirstSend))
			{
				// Nothing to do... socket is closed and reseted !
				return false;
			}

			return true;
		}
コード例 #26
0
ファイル: AbstractWindow.cs プロジェクト: xingchaoet/ourmsg
 internal AbstractWindow(RUDPSocket rudp)
 {
     _rudp = rudp;
 }
コード例 #27
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static bool SocketSendACK(RUDPSocket rudp,
											PhysicalSocket physical,
											IPEndPoint remoteEndPoint,
											byte[] rudpPayload)
		{
			try
			{
				physical._socket.SendTo(rudpPayload, remoteEndPoint);
				//physical._socket.BeginSendTo(rudpPayload, 0, rudpPayload.Length, SocketFlags.None, rudp._remoteEndPoint, null, null);
			}
			catch (SocketException exception)
			{
				if (rudp != null)
					OnSocketUnhandledError(rudp, SocketErrorToRUDPSocketError(exception.SocketErrorCode), null);

				return false;
			}

			if (rudp != null)
				rudp._lastACKSendTS = HiResTimer.MicroSeconds;

			return true;
		}
コード例 #28
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
 internal void UnregisterConnectedSocket(RUDPSocket rudp)
 {
     _connectedRDUPsLock.EnterWriteLock();
     _connectedRDUPs.Remove(rudp._remoteEndPoint);
     _connectedRDUPsLock.ExitWriteLock();
 }
コード例 #29
0
 internal RUDPAsyncResult(RUDPSocket rudp, AsyncCallback callback, Object state)
 {
     _rudp          = rudp;
     _asyncCallback = callback;
     _asyncState    = state;
 }
コード例 #30
0
ファイル: PhysicalSocket.cs プロジェクト: cheehwasun/ourmsg
		internal void Close(RUDPSocket rudp)
		{
			RUDPStack.Close(rudp);
		}
コード例 #31
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static void BandwidthTimer(RUDPSocket rudp, long now)
		{
			//---- Send 2 packets
			if (rudp._status == RUDPSocketStatus.Connected &&
				(now - rudp._lastBandwidthTS) > RUDPStack.BandwidthInterval)
			{
				// Too small packet size can lead to overestimation
				byte[] fullMSSPacket = new byte[rudp._mtu - UDPHeaderLength - RUDPHeaderLength];
				BinaryHelper.WriteLong(now, fullMSSPacket, 0);

				PushPacketToSend(rudp, false, RUDPPacketChannel.Bandwidth01, fullMSSPacket, 0, fullMSSPacket.Length);
				PushPacketToSend(rudp, false, RUDPPacketChannel.Bandwidth02, fullMSSPacket, 0, fullMSSPacket.Length);
				rudp._lastBandwidthTS = now;
			}
		}
コード例 #32
0
ファイル: PhysicalSocket.cs プロジェクト: cheehwasun/ourmsg
		internal void Shutdown(RUDPSocket rudp)
		{
			RUDPStack.Shutdown(rudp);
		}
コード例 #33
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static FragmentInformation NewFragmentInformation(RUDPSocket rudpSocket, bool isReliable, byte[] payload, int offset, int size, RUDPSendIAsyncResult asyncResult)
		{
			//return new FragmentInformation(rudpSocket, isReliable, payload, offset, size, asyncResult);

			FragmentInformation fragment;

			if (!_fragmentsPools.TryDequeue(out fragment))
			{
				for (int index = 0; index < 100; index++)
					_fragmentsPools.Enqueue(new FragmentInformation(null, false, null, -1, -1, null));
				return new FragmentInformation(rudpSocket, isReliable, payload, offset, size, asyncResult);
			}

			fragment.rudp = rudpSocket;
			fragment.IsReliable = isReliable;
			fragment.Offset = offset;
			fragment.Size = size;
			fragment.Payload = payload;
			fragment.AsyncResult = asyncResult;

			return fragment;
		}
コード例 #34
0
ファイル: PhysicalSocket.cs プロジェクト: cheehwasun/ourmsg
		internal RUDPSocketError BeginConnect(RUDPSocket rudp, int timeOut)
		{
			//---- Add it to our list of "connected" sockets
			RegisterConnectedSocket(rudp);

			return RUDPStack.BeginConnect(rudp, timeOut);
		}
コード例 #35
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static void UnregisterRUDPSocket(RUDPSocket rudp)
		{
			if (rudp._controlThreadId > -1)
			{
				int controlThreadId = rudp._controlThreadId;
				_controlThreadInformations[controlThreadId]._rudpSocketsLock.EnterWriteLock();
				_controlThreadInformations[controlThreadId]._rudpSockets.Remove(rudp);
				rudp._controlThreadId = -1;
				_controlThreadInformations[controlThreadId]._rudpSocketsLock.ExitWriteLock();
			}
		}
コード例 #36
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
 internal void RegisterConnectedSocket(RUDPSocket rudp)
 {
     _connectedRDUPsLock.EnterWriteLock();
     _connectedRDUPs.Add(rudp._remoteEndPoint, rudp);
     _connectedRDUPsLock.ExitWriteLock();
 }
コード例 #37
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static bool BeginAccept(RUDPSocket rudp)
		{
			Trace("Accepting at :" + rudp._remoteEndPoint);

			if (rudp._status != RUDPSocketStatus.Accepting)
				return false;

			//---- Register for the stack
			RUDPStack.RegisterRUDPSocket(rudp);

			return true;
		}
コード例 #38
0
ファイル: PhysicalSocket.cs プロジェクト: xingchaoet/ourmsg
 internal void OnDisconnected(RUDPSocket rudp, RUDPSocketError error)
 {
     UnregisterConnectedSocket(rudp);
     rudp.OnDisconnected(error);
 }
コード例 #39
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static void AsyncShutdown(RUDPSocket rudp)
		{
			ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncShutdownCB), rudp);
		}
コード例 #40
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static void OnDisconnected(RUDPSocket rudp, DisconnectionReason reason)
		{
			if (rudp._status == RUDPSocketStatus.Closed)
				return;

			//---- Reset
			rudp._outgoingPacketsLock.EnterWriteLock();
			rudp._outgoingPackets.Clear();
			rudp._outgoingPacketsLock.ExitWriteLock();
			rudp.Reset(RUDPSocketStatus.Closed);

			//---- Notify
			if (reason != DisconnectionReason.ConnectionClosed)
			{
				RUDPSocketError error = RUDPSocketError.ConnectionReset;
				if (reason == DisconnectionReason.SocketError)
					error = RUDPSocketError.SocketError;
				if (reason == DisconnectionReason.TimeOut)
					error = RUDPSocketError.ConnectionReset;

				rudp._physical.OnDisconnected(rudp, error);
			}
		}
コード例 #41
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		internal static RUDPSocketError SendPayload(RUDPSocket rudp, byte[] payload, int offset, int payloadLength, bool reliable, RUDPSendIAsyncResult asyncResult)
		{
			// We are no longer active
			if (!_isStackRunning)
				return RUDPSocketError.SystemNotReady;

			//---- Only when connected
			if (rudp._status != RUDPSocketStatus.Connected)
				return RUDPSocketError.NotConnected;

			//---- Fragmentation
			asyncResult.ForceAsyncCall = true;
			FragmentInformation fragments = NewFragmentInformation(rudp, reliable, payload, offset, payloadLength, asyncResult);

			//----- Async send
			rudp._fragmentsLock.EnterWriteLock();
			rudp._fragments.AddFirst(fragments);
			rudp._fragmentsLock.ExitWriteLock();

			ForceFragmentsSending(rudp._controlThreadId);

			//---- If possible send Sync... otherwise relate to control thread
			/*
			if (!SendFragments(fragments))
			{
				rudp._fragmentsLock.EnterWriteLock();
				rudp._fragments.AddFirst(fragments);
				rudp._fragmentsLock.ExitWriteLock();

				_protocolControlEvent.Set();
			}
			*/

			//---- Synchrone send
			/*
			while (!SendFragments(fragments))
				fragments.rudp._controlWindow.WaitObject.WaitOne();
			*/
			return fragments.Error;
		}
コード例 #42
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static bool TransmissionTimer(RUDPSocket rudp, ControlThreadInformation controlInformation)
		{
			if (rudp._fragments.Count < 1)
				return true;

			rudp._fragmentsLock.EnterReadLock();
			FragmentInformation fragments = rudp._fragments.Last.Value;
			rudp._fragmentsLock.ExitReadLock();

			if (SendFragments(fragments, controlInformation))
			{
				rudp._fragmentsLock.EnterWriteLock();
				rudp._fragments.RemoveLast();
				rudp._fragmentsLock.ExitWriteLock();
				ReleaseFragmentInformation(fragments);
				return true;
			}

			// Else continue for other socket
			// will try to send packet during next loop
			ForceFragmentsSending(controlInformation.ControlThreadId);

			return false;
		}
コード例 #43
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		/// <summary>
		/// Create the RUDP packet : HEADER + payload
		/// </summary>
		internal static byte[] MakePacketPayload(RUDPSocket rudp,
												int packetId,
												RUDPPacketChannel channel,
												SACKSlot slot1, SACKSlot slot2, SACKSlot slot3, SACKSlot slot4,
												byte[] payload,
												int offset,
												int payloadLength)
		{
			//---- Here we make the payload while we will send:
			/**
			 * We create a header
			 * The format is:
			 * --------------
			 * - 1 byte : protocol version
			 * - 1 byte : header information
			 * - 1 byte : channel
			 * - 4 bytes : message ID
			 * - 4 bytes : advertized congestion window size
			 * - 4 bytes : payloadLength
			 * - 4 X (4 + 4) : 32 bytes for 4 SACK slots
			 * - the payload bytes
			 */
			int headerOffset = 0;
			byte[] packetPayload = PayloadManager.Allocate(channel, RUDPHeaderLength + payloadLength);

			//---- Protocol version
			packetPayload[headerOffset] = (byte)1;
			headerOffset++;

			//---- Header information
			// 3 bits : number of ACK slots

			// sack slot (3 bits)
			byte sacksSlotCount = 0;
			if (slot1 != null)
				sacksSlotCount++;
			if (slot2 != null)
				sacksSlotCount++;
			if (slot3 != null)
				sacksSlotCount++;
			if (slot4 != null)
				sacksSlotCount++;

			packetPayload[headerOffset] = 0; // Reset (Because buffer reused)
			packetPayload[headerOffset] |= sacksSlotCount;
			headerOffset++;

			//---- Channel
			packetPayload[headerOffset] = (byte)channel;
			headerOffset++;

			//---- Message Id
			BinaryHelper.WriteInt(packetId, packetPayload, headerOffset);
			headerOffset += 4;

			//---- Control information : Advertised window
			if (rudp == null)
				BinaryHelper.WriteInt(-1, packetPayload, headerOffset);
			else
				BinaryHelper.WriteInt((int)rudp._controlWindow.AdvertisedWindow, packetPayload, headerOffset);
			headerOffset += 4;

			//---- Payload length
			BinaryHelper.WriteInt(payloadLength, packetPayload, headerOffset);
			headerOffset += 4;

			//---- SACK Slots
			if (slot1 != null)
			{
				BinaryHelper.WriteInt(slot1.StartPacketId, packetPayload, headerOffset);
				headerOffset += 4;
				BinaryHelper.WriteInt(slot1.EndPacketId, packetPayload, headerOffset);
				headerOffset += 4;
			}
			else
			{
				// Reset (Because buffer reused)
				Buffer.BlockCopy(Clean8Bytes, 0, packetPayload, headerOffset, 8);
				headerOffset += 8;
			}
			if (slot2 != null)
			{
				BinaryHelper.WriteInt(slot2.StartPacketId, packetPayload, headerOffset);
				headerOffset += 4;
				BinaryHelper.WriteInt(slot2.EndPacketId, packetPayload, headerOffset);
				headerOffset += 4;
			}
			else
			{
				// Reset (Because buffer reused)
				Buffer.BlockCopy(Clean8Bytes, 0, packetPayload, headerOffset, 8);
				headerOffset += 8;
			}
			if (slot3 != null)
			{
				BinaryHelper.WriteInt(slot3.StartPacketId, packetPayload, headerOffset);
				headerOffset += 4;
				BinaryHelper.WriteInt(slot3.EndPacketId, packetPayload, headerOffset);
				headerOffset += 4;
			}
			else
			{
				// Reset (Because buffer reused)
				Buffer.BlockCopy(Clean8Bytes, 0, packetPayload, headerOffset, 8);
				headerOffset += 8;
			}
			if (slot4 != null)
			{
				BinaryHelper.WriteInt(slot4.StartPacketId, packetPayload, headerOffset);
				headerOffset += 4;
				BinaryHelper.WriteInt(slot4.EndPacketId, packetPayload, headerOffset);
				headerOffset += 4;
			}
			else
			{
				// Reset (Because buffer reused)
				Buffer.BlockCopy(Clean8Bytes, 0, packetPayload, headerOffset, 8);
				headerOffset += 8;
			}

			if (payload == null)
				return packetPayload;

			//---- Payload
			Buffer.BlockCopy(payload, offset, packetPayload, headerOffset, payloadLength);

			return packetPayload;
		}
コード例 #44
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static bool RetransmissionTimer(RUDPSocket rudp, long now, ControlThreadInformation controlInformation)
		{
			int count = rudp._outgoingPackets.Count;
			bool hasDoFastRetransmit = false;

			controlInformation._chargeCheckStopWatch.Reset();
			controlInformation._chargeCheckStopWatch.Start();
			for (int index = 0; index < count; index++)
			{
				rudp._outgoingPacketsLock.EnterReadLock();
				RUDPOutgoingPacket packet = rudp._outgoingPackets[index];
				rudp._outgoingPacketsLock.ExitReadLock();

				//---- Not yet sended
				if (packet.TSLastSend < 0)
					continue;

				//---- It is ACKed
				if (packet.IsACKed)
				{
					rudp._outgoingPacketsLock.EnterWriteLock();
					rudp._outgoingPackets.RemoveAt(index);
					rudp._outgoingPacketsLock.ExitWriteLock();

					ReleaseOutgoingPacket(packet);

					index--;
					count--;
					continue;
				}

				//---- Check for time out
				if (packet.TSFirstSend > -1 && (now - packet.TSFirstSend) > rudp._sto)
				{
					//-- Normal time out
					// Send connection Reset with ACK
					OnDisconnected(rudp, DisconnectionReason.TimeOut);
					return true;
				}

				//---- Retransmission or not ?
				bool fastRetransmit = (packet.PacketId >= rudp._fastRetransmitStartPacketId && packet.PacketId <= rudp._fastRetransmitEndPacketId);
				if (!fastRetransmit && (now - packet.TSLastSend) < rudp._rto)
					continue;

				hasDoFastRetransmit = hasDoFastRetransmit | fastRetransmit;

				//---- Get the SACK slots to send with
				SACKSlot slot1 = null, slot2 = null, slot3 = null, slot4 = null;
				rudp._sackWindow.GetSLACKSlots(out slot1, out slot2, out slot3, out slot4);

				// Update the payload for the SACK slots
				UpdatePacketPayload(packet.Payload, slot1, slot2, slot3, slot4);

#if CONSOLE_TRACE
				string acksList = "";
				if (slot1 != null)
					acksList += " [" + slot1.StartPacketId + " <-> " + slot1.EndPacketId + "]";
				if (slot2 != null)
					acksList += " [" + slot2.StartPacketId + " <-> " + slot2.EndPacketId + "]";
				if (slot3 != null)
					acksList += " [" + slot3.StartPacketId + " <-> " + slot3.EndPacketId + "]";
				if (slot4 != null)
					acksList += " [" + slot4.StartPacketId + " <-> " + slot4.EndPacketId + "]";
#endif

				// Send
#if CONSOLE_TRACE
				Trace("Resend packet(" + rudp.Handle + "): " + packet.PacketId + " RTO=" + rudp._rto + "RTT=" + rudp._rtt + " ACKs:" + acksList);
#endif
				if (SocketSendPacket(rudp, packet, packet.Payload, now))
				{
					rudp._controlWindow.OnTimeOut(packet);

					// Update
					packet.Retransmission++;
				}

				if (controlInformation._chargeCheckStopWatch.ElapsedMilliseconds > 0)
					return false;
			}

			//---- Reset fast retransmit
			if (hasDoFastRetransmit)
				rudp.OnEndFastRetransmit();

			return true;
		}
コード例 #45
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		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;
		}
コード例 #46
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static void ACKTimer(RUDPSocket rudp, long now)
		{
			int acksCount = rudp._sackWindow.ACKCount;
			if (acksCount < 1)
				return;

			//now = HiResTimer.MicroSeconds;
			//---- Delayed ACKs
			if (acksCount < 2)
				if (rudp._lastACKSendTS > -1 && (now - rudp._lastACKSendTS) < DelayACKTime)
					return;

			/*
			bool sendACKDueToTimeOut = (acksCount < 2 && rudp._lastACKSendTS > -1 && (now - rudp._lastACKSendTS) >= DelayACKTime);
			long delayedACKTS = 0;
			if (sendACKDueToTimeOut)
			{
				delayedACKTS = now - rudp._lastACKSendTS;
			}
			*/

			rudp._lastACKSendTS = HiResTimer.MicroSeconds;

			//---- Prepare the SACKs list
			List<SACKSlot> sackSlots = rudp._sackWindow.PrepareACKList();

			for (int index = 0; index < sackSlots.Count; index++)
			{
				//---- Get the SACK slots to send with
				SACKSlot slot1 = null, slot2 = null, slot3 = null, slot4 = null;
				if (sackSlots.Count > 0)
				{
					slot1 = sackSlots[0];
					sackSlots.RemoveAt(0);
				}
				if (sackSlots.Count > 0)
				{
					slot2 = sackSlots[0];
					sackSlots.RemoveAt(0);
				}
				if (sackSlots.Count > 0)
				{
					slot3 = sackSlots[0];
					sackSlots.RemoveAt(0);
				}
				if (sackSlots.Count > 0)
				{
					slot4 = sackSlots[0];
					sackSlots.RemoveAt(0);
				}

#if CONSOLE_TRACE
				if (slot1 != null)
					Trace("Send ACK(" + rudp.Handle + "): " + slot1.StartPacketId + " <-> " + slot1.EndPacketId);
				if (slot2 != null)
					Trace("Send ACK(" + rudp.Handle + "): " + slot2.StartPacketId + " <-> " + slot2.EndPacketId);
				if (slot3 != null)
					Trace("Send ACK(" + rudp.Handle + "): " + slot3.StartPacketId + " <-> " + slot3.EndPacketId);
				if (slot4 != null)
					Trace("Send ACK(" + rudp.Handle + "): " + slot4.StartPacketId + " <-> " + slot4.EndPacketId);
#endif

				byte[] packetPayload = MakePacketPayload(rudp, -1, RUDPPacketChannel.ACK, slot1, slot2, slot3, slot4, null, 0, 0);
				SocketSendACK(rudp, rudp._physical, rudp._remoteEndPoint, packetPayload);
				PayloadManager.Deallocate(RUDPPacketChannel.ACK, packetPayload);
			}
		}
コード例 #47
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		private static void HandleACKs(RUDPSocket rudp,
										SACKSlot slot1,
										SACKSlot slot2,
										SACKSlot slot3,
										SACKSlot slot4)
		{
			// No ack
			if (slot1 == null)
				return;

			int maxId = slot1.EndPacketId;
			if (slot4 != null)
				maxId = slot4.EndPacketId;
			else if (slot3 != null)
				maxId = slot3.EndPacketId;
			else if (slot2 != null)
				maxId = slot2.EndPacketId;

#if CONSOLE_TRACE
			if (slot1 != null)
				Trace("Handle ACK[1](" + rudp.Handle + "): " + slot1.StartPacketId + " <-> " + slot1.EndPacketId);
			if (slot2 != null)
				Trace("Handle ACK[2](" + rudp.Handle + "): " + slot2.StartPacketId + " <-> " + slot2.EndPacketId);
			if (slot3 != null)
				Trace("Handle ACK[3](" + rudp.Handle + "): " + slot3.StartPacketId + " <-> " + slot3.EndPacketId);
			if (slot4 != null)
				Trace("Handle ACK[4](" + rudp.Handle + "): " + slot4.StartPacketId + " <-> " + slot4.EndPacketId);
#endif

			//---- Prepare the list of packets
			List<RUDPOutgoingPacket> toACKPackets = new List<RUDPOutgoingPacket>();

			RUDPOutgoingPacket lastPacket = null;
			double currentRTT = Double.MaxValue;
			rudp._outgoingPacketsLock.EnterReadLock();

			try
			{
				for (int index = 0; index < rudp._outgoingPackets.Count; index++)
				{
					RUDPOutgoingPacket packet = rudp._outgoingPackets[index];

					if (packet.PacketId > maxId)
						break;

					if (packet.IsACKed)
						continue;

					if (slot4 != null)
						if (packet.PacketId >= slot4.StartPacketId && packet.PacketId <= slot4.EndPacketId)
						{
							if (packet.Retransmission < 1)
							{
								lastPacket = packet;
								currentRTT = Math.Min(currentRTT, HiResTimer.MicroSeconds - lastPacket.TSFirstSend);
							}
							toACKPackets.Add(packet);
							continue;
						}

					if (slot3 != null)
						if (packet.PacketId >= slot3.StartPacketId && packet.PacketId <= slot3.EndPacketId)
						{
							if (packet.Retransmission < 1)
							{
								lastPacket = packet;
								currentRTT = Math.Min(currentRTT, HiResTimer.MicroSeconds - lastPacket.TSFirstSend);
							}
							toACKPackets.Add(packet);
							continue;
						}

					if (slot2 != null)
						if (packet.PacketId >= slot2.StartPacketId && packet.PacketId <= slot2.EndPacketId)
						{
							if (packet.Retransmission < 1)
							{
								lastPacket = packet;
								currentRTT = Math.Min(currentRTT, HiResTimer.MicroSeconds - lastPacket.TSFirstSend);
							}
							toACKPackets.Add(packet);
							continue;
						}

					if (packet.PacketId >= slot1.StartPacketId && packet.PacketId <= slot1.EndPacketId)
					{
						if (packet.Retransmission < 1)
						{
							lastPacket = packet;
							currentRTT = Math.Min(currentRTT, HiResTimer.MicroSeconds - lastPacket.TSFirstSend);
						}
						toACKPackets.Add(packet);
					}
				}
			}
			finally
			{
				rudp._outgoingPacketsLock.ExitReadLock();
			}

			//---- If no good packet, use current RTT
			if (lastPacket == null)
				currentRTT = rudp.RTT;

			if (currentRTT < 1)
				currentRTT = 1;

			//---- Set the ACK for all the packets
			for (int index = 0; index < toACKPackets.Count; index++)
			{
				RUDPOutgoingPacket packet = toACKPackets[index];
				SetPacketACKed(rudp, packet, currentRTT);
			}
		}
コード例 #48
0
 internal RUDPReceiveIAsyncResult(RUDPSocket rudp, AsyncCallback callback, Object state)
     : base(rudp, callback, state)
 {
 }
コード例 #49
0
ファイル: AbstractWindow.cs プロジェクト: iraychen/ourmsg
		internal AbstractWindow(RUDPSocket rudp)
		{
			_rudp = rudp;
		}
コード例 #50
0
ファイル: RUDPStack.cs プロジェクト: cheehwasun/ourmsg
		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);
				}
			}
		}