Beispiel #1
0
        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);
        }
Beispiel #2
0
 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,
     });
 }
Beispiel #3
0
        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);
                }
            }
        }
Beispiel #4
0
 public TcpInputStream(TcpPcb pcb)
 {
     this.Pcb = pcb ?? throw new ArgumentNullException(nameof(pcb));
 }
Beispiel #5
0
        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);
                    }
                }
            }
        }
Beispiel #6
0
        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);
                        }
                    }
                }
            }
        }