private void RST(TcpPcb pcb, TcpFrame frame) { uint seqno = frame.AcknowledgeNo; uint ackno = frame.SequenceNo + 1; pcb.State = TcpState.LAST_ACK; pcb.Post(TcpFlags.TCP_RST, ackno, seqno); ClosePCB(pcb, TcpState.CLOSED); }
public TcpFrame CreateFrame(TcpPcb pcb) { return(new TcpFrame(pcb.Destination, pcb.Source, this.Payload) { AcknowledgeNo = this.AcknowledgeNo, SequenceNo = this.SequenceNo, Flags = this.Flags, Ttl = pcb.Ttl, WindowSize = (ushort)pcb.ReceiveBufferSize, }); }
private void ClosePCB(TcpPcb pcb, TcpState state) { if (pcb == null) { return; } string pcbKey = GetPcbKey(pcb.Source, pcb.Destination); lock (_pcbTable) { _pcbTable.TryRemove(pcbKey, out TcpPcb pcbx); } lock (pcb) { pcb.State = state; if (!pcb.Aborted) { pcb.Aborted = true; pcb.OnAbort(EventArgs.Empty); } } }
public TcpInputStream(TcpPcb pcb) { this.Pcb = pcb ?? throw new ArgumentNullException(nameof(pcb)); }
public virtual void Input(TcpFrame frame) { string pcbKey = GetPcbKey(frame.Source, frame.Destination); TcpPcb pcb = null; lock (_pcbTable) { _pcbTable.TryGetValue(pcbKey, out pcb); if (pcb == null) { pcb = new TcpPcb(frame, this.Locator) { State = TcpState.SYN_RCVD }; if (0 == (frame.Flags & TcpFlags.TCP_SYN) || // 不接受此套接字则积极拒绝 !this.Locator.Sockets.BeginAccept(pcb)) { RST(pcb, frame); return; } _pcbTable.TryAdd(pcbKey, pcb); pcb.Open += (sender, e) => { if (!pcb.Estableshed) { pcb.Estableshed = true; var socket = this.Locator.Sockets.EndAccept(pcb); if (socket == null) { pcb.Close(); } else { pcb.OnOpen(e); } } }; pcb.Abort += (sender, e) => ClosePCB(sender as TcpPcb, TcpState.CLOSED); } } lock (pcb) { if (0 != (frame.Flags & TcpFlags.TCP_SYN)) { uint seqno = pcb.AcknowledgeNo++; uint ackno = ++pcb.SequenceNo; pcb.Post(TcpFlags.TCP_SYN | TcpFlags.TCP_ACK, ackno, seqno, 1, 3); } else if (0 != (frame.Flags & TcpFlags.TCP_RST) || 0 != (frame.Flags & (TcpFlags.TCP_CWR | TcpFlags.TCP_ECE | TcpFlags.TCP_UGR))) { RST(pcb, frame); } else { pcb.SendBufferSize = frame.WindowSize; if (0 != (frame.Flags & TcpFlags.TCP_ACK)) { pcb.Ack(frame.AcknowledgeNo); } if (0 != (frame.Flags & TcpFlags.TCP_PSH)) { uint pylen = (uint)frame.Payload.Length; uint seqno = frame.AcknowledgeNo; uint ackno = frame.SequenceNo + pylen; if (ackno >= pcb.SequenceNo) { pcb.InputStream.Input(frame); } else { pcb.Post(TcpFlags.TCP_ACK, ackno, seqno, 0); } } else if (0 != (frame.Flags & TcpFlags.TCP_FIN)) { uint seqno = frame.AcknowledgeNo; uint ackno = frame.SequenceNo + 1; pcb.Post(TcpFlags.TCP_ACK, ackno, seqno, 0); ClosePCB(pcb, TcpState.CLOSED); } } } }
private void WorkThread(object state) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (!this._disposed) { if (stopwatch.ElapsedTicks < TcpPcb.MIN_RTO) { Thread.Sleep(1); continue; } else { stopwatch.Restart(); } foreach (var pair in _pcbTable) { TcpPcb pcb = pair.Value; if (pcb == null) { continue; } SortedDictionary <long, SegmentsContext> segments = pcb.SegmentsContexts; if (segments == null) { continue; } lock (segments) { var remove_segments_keys = new List <long>(); foreach (var segments_pair in segments) { SegmentsContext segments_context = segments_pair.Value; if (segments_context == null) { continue; } double rto_radix = Math.Pow(1.5, Math.Min(segments_context.Retransmission, (1 + segments_context.Counter))); if (segments_context.Stopwatch.ElapsedMilliseconds >= (Math.Max(pcb.RTO, TcpPcb.MIN_RTO) * rto_radix)) { if (segments_context.Counter++ < segments_context.Retransmission) { segments_context.Stopwatch.Restart(); this.Output(segments_context.CreateFrame(pcb)); } else { remove_segments_keys.Add(segments_pair.Key); } } } foreach (var segments_key in remove_segments_keys) { pcb.SegmentsContexts.Remove(segments_key, out SegmentsContext segments_x); } } } } }