Ejemplo n.º 1
0
        public void ConnectAsync()
        {
            if (TCPState == TCPSocketState.Closed || TCPState == TCPSocketState.Listen)
            {
                if (TCPState == TCPSocketState.Closed)
                {
                    CreateTCB();
                }

                TCPFrame tcpFrame = new TCPFrame();
                tcpFrame.SynchronizeFlagSet = true;
                tcpFrame.SequenceNumber     = tcb.ISS;
                tcpFrame.SourcePort         = this.LocalBinding;
                tcpFrame.DestinationPort    = this.RemoteBinding;
                tcpFrame.Window             = tcb.RCV_WND;
                tcpFrame.EncapsulatedFrame  = new RawDataFrame(new byte[0]);
                tcpFrame.Checksum           = tcpFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpFrame));

                TransmitAssured(tcpFrame);

                tcb.SND_UNA = tcb.ISS;
                tcb.SND_NXT = (tcb.ISS + 1) % uint.MaxValue;

                this.TCPState = TCPSocketState.SynSent;
            }
            else
            {
                throw new InvalidOperationException("Cannot call Connect() on a socket which is being used.");
            }
        }
Ejemplo n.º 2
0
        private void RespondWithAck()
        {
            TCPFrame tcpResponseFrame = new TCPFrame();

            tcpResponseFrame.AcknowledgementFlagSet = true;
            tcpResponseFrame.SequenceNumber         = tcb.SND_NXT;
            tcpResponseFrame.AcknowledgementNumber  = tcb.RCV_NXT;
            tcpResponseFrame.SourcePort             = this.LocalBinding;
            tcpResponseFrame.DestinationPort        = this.RemoteBinding;
            tcpResponseFrame.Window   = tcb.RCV_WND;
            tcpResponseFrame.Checksum = tcpResponseFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpResponseFrame));

            InvokeFrameEncapsulated(tcpResponseFrame);
        }
        /// <summary>
        /// Decapsulates the given TCP frame if the binding of this socket matches the frame and invokes the FrameDecapsulated event when finished.
        /// </summary>
        /// <param name="fFrame">The frame to process</param>
        /// <param name="bPush">The TCP Socket ignores this parameter, since TCP push flags can be set in the TCP frame directly.</param>
        /// <returns>A bool indicating whether the given frame is matching the binding of this socket</returns>
        public override bool PushUp(Frame fFrame, bool bPush)
        {
            if (fFrame.FrameType != FrameTypes.TCP)
            {
                fFrame = new TCPFrame(fFrame.FrameBytes);
            }

            TCPFrame tcpFrame = (TCPFrame)fFrame;

            //Is this socket the frame's destination?

            if (tcpFrame.DestinationPort != LocalBinding || tcpFrame.SourcePort != RemoteBinding)
            {
                return(false);
            }

            //Check the checksum

            byte[] bMyChecksum       = tcpFrame.CalculateChecksum(this.pseudoHeaderSource.GetPseudoHeader(tcpFrame));
            byte[] bReceivedChecksum = tcpFrame.Checksum;

            for (int iC1 = 0; iC1 < bMyChecksum.Length; iC1++)
            {
                if (bMyChecksum[iC1] != bReceivedChecksum[iC1])
                {
                    //If the checksum is different, return.
                    return(true);
                }
            }

            //Handle the frame

            switch (TCPState)
            {
            case TCPSocketState.Established:
                HandleEstablished(tcpFrame);
                break;

            case TCPSocketState.Listen:
                HandleListen(tcpFrame);
                break;

            case TCPSocketState.SynSent:
                HandleSynSent(tcpFrame);
                break;
            }

            return(true);
        }
Ejemplo n.º 4
0
        public void BeginClose()
        {
            if (tcpState != TCPSocketState.TimeWait && tcpState != TCPSocketState.Closed)
            {
                if (rbSendBuffer.Length > 0)
                {
                    Flush();
                }
                if (tcpState == TCPSocketState.Established)
                {
                    TCPFrame tcpResponseFrame = new TCPFrame();
                    tcpResponseFrame.FinishFlagSet          = true;
                    tcpResponseFrame.AcknowledgementFlagSet = true;
                    tcpResponseFrame.SequenceNumber         = tcb.SND_NXT;
                    tcpResponseFrame.AcknowledgementNumber  = tcb.RCV_NXT;
                    tcpResponseFrame.SourcePort             = this.LocalBinding;
                    tcpResponseFrame.DestinationPort        = this.RemoteBinding;
                    tcpResponseFrame.Window   = tcb.RCV_WND;
                    tcpResponseFrame.Checksum = tcpResponseFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpResponseFrame));

                    tcb.SND_NXT = tcb.SND_NXT + 1;

                    TransmitAssured(tcpResponseFrame);
                    this.TCPState = TCPSocketState.FinWait1;
                }
                else if (tcpState == TCPSocketState.Listen)
                {
                    ClearBuffers();
                    this.TCPState = TCPSocketState.Closed;
                }
                else
                {
                    this.TCPState = TCPSocketState.TimeWait;
                }
            }
            else
            {
                throw new InvalidOperationException("Cannot close a socket which has no connection established.");
            }
        }
Ejemplo n.º 5
0
        private void SegmentAndSend()
        {
            lock (oTCBLock)
            {
                if (tcpState != TCPSocketState.Established)
                {
                    bFlushWhenEstablished = true;
                    return;
                }

                byte[] bSegment = new byte[Math.Min(rbSendBuffer.Count, (tcb.SND_UNA + tcb.SND_WND - tcb.SND_NXT))];
                rbSendBuffer.Read(bSegment, 0, bSegment.Length);

                for (int iC1 = 0; iC1 < bSegment.Length; iC1 += MaximumSegmentSize)
                {
                    byte[] bSegmentedSegment = new byte[Math.Min(bSegment.Length - iC1, MaximumSegmentSize)];

                    for (int iC2 = 0; iC2 < bSegmentedSegment.Length; iC2++)
                    {
                        bSegmentedSegment[iC2] = bSegment[iC2 + (iC1)];
                    }

                    TCPFrame tcpFrame = new TCPFrame();

                    tcpFrame.SequenceNumber        = tcb.SND_NXT;
                    tcpFrame.AcknowledgementNumber = tcb.RCV_NXT;
                    tcpFrame.Window = tcb.RCV_WND;
                    tcpFrame.AcknowledgementFlagSet = true;
                    tcpFrame.SourcePort             = this.LocalBinding;
                    tcpFrame.DestinationPort        = this.RemoteBinding;
                    tcpFrame.EncapsulatedFrame      = new RawDataFrame(bSegmentedSegment);
                    tcpFrame.PushFlagSet            = true;
                    tcb.SND_NXT      += (uint)bSegmentedSegment.Length;
                    tcpFrame.Checksum = tcpFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpFrame));

                    TransmitAssured(tcpFrame);
                }
            }
        }
Ejemplo n.º 6
0
        private void RespondWithReset(TCPFrame tcpFrame)
        {
            if (!tcpFrame.ResetFlagSet)
            {
                TCPFrame tcpResponseFrame = new TCPFrame();
                tcpResponseFrame.SourcePort      = LocalBinding;
                tcpResponseFrame.DestinationPort = RemoteBinding;
                tcpResponseFrame.ResetFlagSet    = true;
                if (!tcpFrame.AcknowledgementFlagSet)
                {
                    tcpResponseFrame.AcknowledgementFlagSet = true;
                    tcpResponseFrame.AcknowledgementNumber  = tcpFrame.SequenceNumber + (uint)tcpFrame.Length;
                    tcpResponseFrame.SequenceNumber         = 0;
                }
                else
                {
                    tcpResponseFrame.SequenceNumber = tcpFrame.AcknowledgementNumber;
                }
                tcpResponseFrame.Checksum = tcpResponseFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpResponseFrame));

                Transmit(tcpResponseFrame);
            }
        }
Ejemplo n.º 7
0
        private void HandleListen(TCPFrame tcpFrame)
        {
            if (tcpFrame.AcknowledgementFlagSet)
            {
                RespondWithReset(tcpFrame);
            }
            if (tcpFrame.SynchronizeFlagSet)
            {
                TCPState = TCPSocketState.SynReceived;

                tcb.RCV_NXT = tcpFrame.SequenceNumber + 1;

                tcb.IRS     = tcpFrame.SequenceNumber;
                tcb.SND_WND = tcpFrame.Window;

                if (tcpFrame.EncapsulatedFrame != null && tcpFrame.EncapsulatedFrame.Length > 0)
                {
                    ProcessFramePayload(tcpFrame);
                }

                TCPFrame tcpResponseFrame = new TCPFrame();
                tcpResponseFrame.SynchronizeFlagSet     = true;
                tcpResponseFrame.AcknowledgementFlagSet = true;
                tcpResponseFrame.SourcePort             = this.LocalBinding;
                tcpResponseFrame.DestinationPort        = this.RemoteBinding;
                tcpResponseFrame.SequenceNumber         = tcb.ISS;
                tcpResponseFrame.AcknowledgementNumber  = tcb.RCV_NXT;
                tcpResponseFrame.Window   = tcb.RCV_WND;
                tcpResponseFrame.Checksum = tcpResponseFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpResponseFrame));

                TransmitAssured(tcpResponseFrame);

                tcb.SND_NXT = tcb.ISS + 1;
                tcb.SND_UNA = tcb.ISS;
            }
        }
Ejemplo n.º 8
0
        private void HandleSynSent(TCPFrame tcpFrame)
        {
            if (tcpFrame.AcknowledgementFlagSet)
            {
                if (tcpFrame.AcknowledgementNumber <= tcb.ISS || tcpFrame.AcknowledgementNumber > tcb.SND_NXT)
                {
                    RespondWithReset(tcpFrame);
                    return;
                }
                if (!(tcb.SND_UNA <= tcpFrame.AcknowledgementNumber && tcpFrame.AcknowledgementNumber <= tcb.SND_NXT))
                {
                    return;
                }
            }
            if (tcpFrame.ResetFlagSet)
            {
                TCPState = TCPSocketState.Closed;
                return;
            }
            if (tcpFrame.SynchronizeFlagSet)
            {
                tcb.RCV_NXT = tcpFrame.SequenceNumber + 1;

                tcb.IRS     = tcpFrame.SequenceNumber;
                tcb.SND_WND = tcpFrame.Window;

                if (tcpFrame.AcknowledgementFlagSet)
                {
                    tcb.SND_UNA = tcpFrame.AcknowledgementNumber;
                    tcpRetransmissionQueue.Acknowledge(tcb.SND_UNA);
                }

                if (tcb.SND_UNA > tcb.ISS)
                {
                    TCPState = TCPSocketState.Established;

                    TCPFrame tcpResponseFrame = new TCPFrame();
                    tcpResponseFrame.SynchronizeFlagSet     = false;
                    tcpResponseFrame.AcknowledgementFlagSet = true;
                    tcpResponseFrame.SequenceNumber         = tcb.SND_NXT;
                    tcpResponseFrame.SourcePort             = this.LocalBinding;
                    tcpResponseFrame.DestinationPort        = this.RemoteBinding;
                    tcpResponseFrame.AcknowledgementNumber  = tcb.RCV_NXT;
                    tcpResponseFrame.Window   = tcb.RCV_WND;
                    tcpResponseFrame.Checksum = tcpResponseFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpResponseFrame));

                    Transmit(tcpResponseFrame);
                }
                else
                {
                    TCPState = TCPSocketState.SynReceived;

                    TCPFrame tcpResponseFrame = new TCPFrame();
                    tcpResponseFrame.SynchronizeFlagSet     = true;
                    tcpResponseFrame.AcknowledgementFlagSet = true;
                    tcpResponseFrame.SequenceNumber         = tcb.ISS;
                    tcpResponseFrame.SourcePort             = this.LocalBinding;
                    tcpResponseFrame.DestinationPort        = this.RemoteBinding;
                    tcpResponseFrame.AcknowledgementNumber  = tcb.RCV_NXT;
                    tcpResponseFrame.Window   = tcb.RCV_WND;
                    tcpResponseFrame.Checksum = tcpResponseFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpResponseFrame));

                    TransmitAssured(tcpFrame);
                }
            }
        }
Ejemplo n.º 9
0
        private void HandleEstablished(TCPFrame tcpFrame)
        {
            if (CheckSequenceNumber(tcpFrame))
            {
                if (tcpFrame.ResetFlagSet)
                {
                    ClearBuffers();
                    TCPState = TCPSocketState.Closed;
                }
                else
                {
                    if (tcpFrame.SynchronizeFlagSet)
                    {
                        RespondWithReset(tcpFrame);
                        ClearBuffers();
                        TCPState = TCPSocketState.Closed;
                    }
                    else
                    {
                        if (tcpFrame.AcknowledgementFlagSet)
                        {
                            if (tcb.SND_UNA < tcpFrame.AcknowledgementNumber && tcpFrame.AcknowledgementNumber <= tcb.SND_NXT)
                            {
                                tcb.SND_UNA = tcpFrame.AcknowledgementNumber;
                                SendAndUpdateRetransmissionQueue();
                            }
                            if (tcb.SND_NXT < tcpFrame.AcknowledgementNumber && tcpFrame.Length != 0)
                            {
                                RespondWithAck();
                                return;
                            }
                            if (tcb.SND_UNA <= tcpFrame.AcknowledgementNumber && tcpFrame.AcknowledgementNumber <= tcb.SND_NXT)
                            {
                                //Upadate send window
                                if (tcb.SND_WL1 < tcpFrame.SequenceNumber || (tcb.SND_WL1 == tcpFrame.SequenceNumber && tcb.SND_WL2 <= tcpFrame.AcknowledgementNumber))
                                {
                                    tcb.SND_WND = tcpFrame.Window;
                                    tcb.SND_WL2 = tcpFrame.AcknowledgementNumber;
                                    tcb.SND_WL1 = tcpFrame.SequenceNumber;
                                }
                            }
                        }

                        ProcessFramePayload(tcpFrame);

                        if (tcpFrame.FinishFlagSet)
                        {
                            HandleCommonFin(tcpFrame);
                            TCPState = TCPSocketState.CloseWait;

                            TCPFrame tcpResponseFrame = new TCPFrame();
                            tcpResponseFrame.FinishFlagSet          = true;
                            tcpResponseFrame.AcknowledgementFlagSet = true;
                            tcpResponseFrame.SequenceNumber         = tcb.SND_NXT;
                            tcpResponseFrame.AcknowledgementNumber  = tcb.RCV_NXT;
                            tcpResponseFrame.SourcePort             = this.LocalBinding;
                            tcpResponseFrame.DestinationPort        = this.RemoteBinding;
                            tcpResponseFrame.Window   = tcb.RCV_WND;
                            tcpResponseFrame.Checksum = tcpResponseFrame.CalculateChecksum(pseudoHeaderSource.GetPseudoHeader(tcpResponseFrame));

                            TransmitAssured(tcpResponseFrame);

                            TCPState = TCPSocketState.LastAck;
                        }
                        else
                        {
                            if (tcpFrame.EncapsulatedFrame != null && tcpFrame.EncapsulatedFrame.Length > 0)
                            {
                                RespondWithAck();
                            }
                        }
                    }
                }
            }
            else
            {
                RespondWithAck();
            }
        }