Пример #1
0
        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);
        }
Пример #2
0
        public TcpPcb(TcpFrame frame, ILayerLocator locator)
        {
            if (frame == null)
            {
                throw new ArgumentNullException(nameof(frame));
            }

            this.Locator              = locator ?? throw new ArgumentNullException(nameof(locator));
            this.AcknowledgeNo        = frame.AcknowledgeNo;
            this.SequenceNo           = frame.SequenceNo;
            this.AddressFamily        = frame.AddressFamily;
            this.Destination          = frame.Destination;
            this.Source               = frame.Source;
            this.Ttl                  = frame.Ttl;
            this.Aborted              = false;
            this.Estableshed          = false;
            this.SendBufferSize       = frame.WindowSize;
            this.ReceiveBufferSize    = frame.WindowSize;
            this.InputStream          = new TcpInputStream(this);
            this.InputStream.Receive += (sender, e) =>
            {
                uint ackNo = Convert.ToUInt32(e.SequenceNo + e.Payload.Length);
                uint seqNo = e.AcknowledgeNo;
                this.SequenceNo = ackNo;
                {
                    this.Post(TcpFlags.TCP_ACK, ackNo, seqNo, 0);
                }
                this.OnMessage(e.Payload);
            };
        }
Пример #3
0
        public virtual void Output(TcpFrame frame)
        {
            IPFrame ip = ToIPFrame(frame);

            if (ip != null)
            {
                Locator.IPv4.Output(ip);
            }
        }
Пример #4
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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        public virtual void Input(TcpFrame frame)
        {
            if (frame == null || frame.Payload == null)
            {
                return;
            }

            if (frame.Payload.Length <= 0)
            {
                return;
            }

            lock (this.Frames)
            {
                if (frame.SequenceNo == this.Pcb.SequenceNo)
                {
                    this.Pcb.SequenceNo = frame.SequenceNo + (uint)frame.Payload.Length;
                    OnReceive(frame);

                    var node = this.Frames.First;
                    while (node != null)
                    {
                        TcpFrame f       = node.Value;
                        var      current = node;
                        node = current.Next;

                        if (f.SequenceNo == this.Pcb.SequenceNo)
                        {
                            this.Frames.Remove(current);
                            this.Pcb.SequenceNo = f.SequenceNo + (uint)f.Payload.Length;

                            OnReceive(f);
                        }
                    }
                }
                else if (this.Frames.Count <= 0)
                {
                    this.Frames.AddLast(frame);
                }
                else
                {
                    var node = this.Frames.Last;
                    if (frame.SequenceNo == node.Value.SequenceNo)
                    {
                        return;
                    }
                    else if (frame.SequenceNo > node.Value.SequenceNo)
                    {
                        this.Frames.AddLast(frame);
                    }
                    else
                    {
                        node = this.Frames.Last;
                        while (node != null)
                        {
                            TcpFrame f = node.Value;
                            if (f.SequenceNo == frame.SequenceNo)
                            {
                                return;
                            }
                            if (f.SequenceNo < frame.SequenceNo)
                            {
                                this.Frames.AddAfter(node, frame);
                                break;
                            }
                            node = node.Previous;
                        }
                        if (node == null)
                        {
                            this.Frames.AddFirst(frame);
                        }
                    }
                }
            }
        }
Пример #7
0
 protected virtual void OnReceive(TcpFrame frame)
 {
     this.Receive?.Invoke(this, frame);
 }
Пример #8
0
        public static TcpFrame ParseFrame(IPFrame ip, bool checksum = true)
        {
            if (ip == null)
            {
                return(null);
            }

            TcpFrame      frame  = null;
            BufferSegment packet = ip.Payload;

            packet.UnsafeAddrOfPinnedArrayElement((p) =>
            {
                tcp_hdr *tcphdr = (tcp_hdr *)p;
                if (tcphdr == null)
                {
                    return;
                }

                int hdrlen_bytes = TCPH_HDRLEN_BYTES(tcphdr);
                if (hdrlen_bytes < TCP_HLEN || hdrlen_bytes > packet.Length) // 错误的数据报
                {
                    return;
                }

                int len = packet.Length - hdrlen_bytes;
                if (len < 0)
                {
                    return;
                }

                TcpFlags flags = (TcpFlags)TCPH_FLAGS(tcphdr);
                if (checksum && tcphdr->chksum != 0)
                {
                    uint pseudo_checksum = CheckSum.inet_chksum_pseudo((byte *)p.ToPointer(),
                                                                       (uint)ProtocolType.Tcp,
                                                                       (uint)packet.Length,
                                                                       ip.SourceAddressV4,
                                                                       ip.DestinationAddressV4);
                    if (pseudo_checksum != 0)
                    {
                        return;
                    }
                }

                long payload_offset = 0;
                fixed(byte *stream  = packet.Buffer)
                {
                    payload_offset = ((byte *)p + hdrlen_bytes) - stream;
                }

                BufferSegment message_data = new BufferSegment(packet.Buffer, unchecked ((int)payload_offset), len);
                BufferSegment options_data = null;
                int options_size           = hdrlen_bytes - sizeof(tcp_hdr);
                if (options_size <= 0)
                {
                    options_data = new BufferSegment(BufferSegment.Empty);
                }
                else
                {
                    options_data = new BufferSegment(packet.Buffer,
                                                     packet.Offset + sizeof(tcp_hdr), options_size);
                }
                frame = new TcpFrame(new IPEndPoint(ip.Source, CheckSum.ntohs(tcphdr->src)), new IPEndPoint(ip.Destination, CheckSum.ntohs(tcphdr->dest)), message_data)
                {
                    Ttl                   = ip.Ttl,
                    AcknowledgeNo         = CheckSum.ntohl(tcphdr->ackno),
                    SequenceNo            = CheckSum.ntohl(tcphdr->seqno),
                    WindowSize            = CheckSum.ntohs(tcphdr->wnd),
                    Flags                 = flags,
                    SourceMacAddress      = ip.SourceMacAddress,
                    DestinationMacAddress = ip.DestinationMacAddress,
                    Options               = options_data,
                    UrgentPointer         = CheckSum.ntohs(tcphdr->urgp)
                };
            });
            return(frame);
        }
Пример #9
0
        public static IPFrame ToIPFrame(TcpFrame frame)
        {
            if (frame == null)
            {
                throw new ArgumentNullException(nameof(frame));
            }

            if (frame.AddressFamily != AddressFamily.InterNetwork)
            {
                throw new ArgumentNullException("TCP frames of this address family type are not supported.");
            }

            BufferSegment options_data   = frame.Options;
            int           options_size   = options_data?.Length ?? 0;
            int           payload_offset = sizeof(tcp_hdr) + options_size;
            int           payload_size   = frame.Payload?.Length ?? 0;

            byte[] message = new byte[payload_offset + payload_size];
            fixed(byte *pinned = message)
            {
                tcp_hdr *tcphdr = (tcp_hdr *)pinned;

                tcphdr->dest  = CheckSum.htons((ushort)frame.Destination.Port);
                tcphdr->src   = CheckSum.htons((ushort)frame.Source.Port);
                tcphdr->seqno = CheckSum.htonl(frame.SequenceNo);
                tcphdr->ackno = CheckSum.htonl(frame.AcknowledgeNo);
                tcphdr->urgp  = CheckSum.htons(frame.UrgentPointer);
                tcphdr->wnd   = CheckSum.htons(frame.WindowSize);

                TCPH_HDRLEN_SET(tcphdr, payload_offset >> 2);
                TCPH_FLAGS_SET(tcphdr, (int)frame.Flags);

                if (options_size > 0)
                {
                    IntPtr destination_options = (IntPtr)(pinned + sizeof(tcp_hdr));
                    Marshal.Copy(options_data.Buffer, options_data.Offset, destination_options, options_size);
                }

                if (payload_size > 0)
                {
                    using (MemoryStream ms = new MemoryStream(message, payload_offset, payload_size))
                    {
                        ms.Write(frame.Payload.Buffer, frame.Payload.Offset, payload_size);
                    }
                }

                ushort pseudo_checksum = CheckSum.inet_chksum_pseudo(pinned, (uint)ProtocolType.Tcp, (uint)message.Length,
                                                                     IPFrame.GetAddressV4(frame.Source.Address),
                                                                     IPFrame.GetAddressV4(frame.Destination.Address));

                if (pseudo_checksum == 0)
                {
                    pseudo_checksum = 0xffff;
                }

                tcphdr->chksum = pseudo_checksum;
            }

            return(new IPFrame(ProtocolType.Tcp, frame.Source.Address, frame.Destination.Address, new BufferSegment(message))
            {
                Ttl = frame.Ttl,
                SourceMacAddress = frame.SourceMacAddress,
                DestinationMacAddress = frame.DestinationMacAddress,
            });
        }
Пример #10
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);
                    }
                }
            }
        }