internal virtual void Post(TcpFlags flags, uint ackno, uint seqno, uint length = 0, int retransmission = 0, bool timeout = false) { SegmentsContext segments = null; lock (this) { lock (this.SegmentsContexts) { segments = new SegmentsContext() { AcknowledgeNo = ackno, SequenceNo = seqno, Flags = flags, Length = length, Stopwatch = new Stopwatch(), Retransmission = retransmission, Pcb = this, Timeout = timeout, }; if (retransmission > 0) { long nackNo = segments.SequenceNo + segments.Length; if (this.SegmentsContexts.TryAdd(nackNo, segments)) { segments.Stopwatch.Start(); } } } } TcpFrame frame = segments.CreateFrame(this); this.Locator.Tcp.Output(frame); }
public override bool Send(BufferSegment payload) { if (payload == null || payload.Length <= 0) { return(false); } bool sendto(BufferSegment buffer) { if (buffer == null || buffer.Length <= 0) { return(false); } SegmentsContext segments = null; lock (this) { lock (this.SegmentsContexts) { segments = new SegmentsContext() { AcknowledgeNo = this.SequenceNo, SequenceNo = this.AcknowledgeNo, Flags = TcpFlags.TCP_PSH | TcpFlags.TCP_ACK, Length = (uint)buffer.Length, Stopwatch = new Stopwatch(), Pcb = this, Retransmission = 5, Payload = payload, }; var ackNo = segments.SequenceNo + segments.Length; if (this.SegmentsContexts.TryAdd(ackNo, segments)) { segments.Stopwatch.Start(); this.AcknowledgeNo += segments.Length; } } } TcpFrame frame = segments.CreateFrame(this); this.Locator.Tcp.Output(frame); return(true); } foreach (BufferSegment buffer in Slices(payload)) { if (!sendto(buffer)) { return(false); } } return(true); }
internal virtual bool Ack(long ackno) { bool ack = false; SegmentsContext segments = null; lock (this.SegmentsContexts) { ack = this.SegmentsContexts.Remove(ackno, out segments); if (ack) { segments.Stopwatch.Stop(); UpdateAckTime(segments.Stopwatch.ElapsedMilliseconds); if (this.State == TcpState.SYN_RCVD) { this.State = TcpState.ESTABLISHED; this.OnOpen(EventArgs.Empty); } } if (this.SegmentsContexts.Count > 0 && ackno <= this.AcknowledgeNo) { var rapids = new List <long>(); foreach (var key in this.SegmentsContexts.Keys) { if (key > ackno) { break; } rapids.Add(key); } foreach (var key in rapids) { this.SegmentsContexts.Remove(key, out segments); } } } return(ack); }
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); } } } } }