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."); } }
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); }
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."); } }
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); } } }
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); } }
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; } }
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); } } }
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(); } }