コード例 #1
0
        public Bytes ExtractHead(out uint startOffset, out uint length)
        {
            if (this.Empty)
            {
                startOffset = 0;
                length      = 0;
                return(null);
            }
            TcpVectorNode candidate = this.listHead.next;
            Bytes         data      = candidate.Unlink();

            count--;
            if (data != null)
            {
                size -= candidate.length;
            }
            else
            {
                DebugStub.WriteLine("Extracthead no data??\n");
                DebugStub.Break();
                VTable.Assert(false);
            }
            startOffset = candidate.startOffset;
            length      = candidate.length;
            return(data);
        }
コード例 #2
0
        public TcpVectorNode PopNextContiguousSegment(uint targetSeqNumber,
                                                      uint windowSize)
        {
            if (this.listHead == this.listTail)
            {
                return(null);
            }

            TcpVectorNode candidate = this.listHead.next;

            VTable.Assert(candidate.data != null);

            if (candidate.length > windowSize)
            {
                DebugPrint("Window full, can't pop waiting segment\n");
                return(null);
            }
            if (candidate.seqNumber == targetSeqNumber)
            {
                return(this.ExtractHead());
            }
            DebugPrint("PopNextContiguousSegment: None available.  target seq number {0} head of list seq number {1}\n",
                       targetSeqNumber, candidate.seqNumber);
            return(null);
        }
コード例 #3
0
 internal void LinkAsPrev(TcpVectorNode tcpVNode)
 {
     tcpVNode.prev      = this.prev;
     this.prev          = tcpVNode;
     tcpVNode.next      = this;
     tcpVNode.prev.next = tcpVNode;
 }
コード例 #4
0
 internal void LinkAsNext(TcpVectorNode tcpVNode)
 {
     tcpVNode.next      = this.next;
     this.next          = tcpVNode;
     tcpVNode.prev      = this;
     tcpVNode.next.prev = tcpVNode;
 }
コード例 #5
0
        public Bytes GetNextBuffer(out int start, out int length)
        {
            if (this.Empty)
            {
                start  = -1;
                length = -1;
                return(null);
            }

            if (this.currentTxBuff == null)
            {
                this.currentTxBuff         = this.listHead.next;
                this.currentTxTotalOffset  = 0;
                this.currentTxBufferOffset = this.currentTxBuff.startOffset;
            }
            else
            {
                this.currentTxBuff         = this.currentTxBuff.next;
                this.currentTxBufferOffset = this.currentTxBuff.startOffset;
                if (this.currentTxBuff == this.listTail)
                {
                    DebugStub.Print("GetBuffer: Empty list???\n");
                    DebugStub.Break();
                    start  = -1;
                    length = -1;
                    return(null);
                }
            }
            start  = (int)this.currentTxBuff.startOffset;
            length = (int)this.currentTxBuff.length;

            return(this.currentTxBuff.data);
        }
コード例 #6
0
 internal TcpVectorNode BoxedUnlink()
 {
     this.prev.next = this.next;
     this.next.prev = this.prev;
     this.next      = this;
     this.prev      = this;
     return(this);
 }
コード例 #7
0
 internal Bytes Unlink()
 {
     this.prev.next = this.next;
     this.next.prev = this.prev;
     this.next      = this;
     this.prev      = this;
     return(this.data);
 }
コード例 #8
0
            internal void LinkAsPrev(Bytes data, uint seqNumber, uint length)
            {
                TcpVectorNode prev = new TcpVectorNode(data, seqNumber, length);

                prev.prev      = this.prev;
                this.prev      = prev;
                prev.next      = this;
                prev.prev.next = prev;
            }
コード例 #9
0
            internal void LinkAsNext(Bytes data, uint seqNumber, uint length)
            {
                TcpVectorNode next = new TcpVectorNode(data, seqNumber, length);

                next.next      = this.next;
                this.next      = next;
                next.prev      = this;
                next.next.prev = next;
            }
コード例 #10
0
 internal TcpVectorNode(Bytes arg, uint seqNumber, uint length)
 {
     this.next        = this;
     this.prev        = this;
     this.data        = arg;
     this.seqNumber   = seqNumber;
     this.startOffset = 0;
     this.length      = length;
 }
コード例 #11
0
        public TcpVectorQueueByte()
        {
            size  = 0;
            count = 0;
            TcpVectorNode node = this.listHead = new TcpVectorNode();

            this.listTail         = node;
            currentTxBuff         = null;
            currentTxBufferOffset = 0;
            currentTxTotalOffset  = 0;
        }
コード例 #12
0
        public TcpVectorNode ExtractHead()
        {
            if (this.Empty)
            {
                return(null);
            }

            TcpVectorNode candidate = this.listHead.next;

            VTable.Assert(candidate.length != 0);
            size -= candidate.length;
            count--;
            return(candidate.BoxedUnlink());
        }
コード例 #13
0
//        public void Release() {}
//        public void Acquire() {}
        public void Dispose()
        {
            TcpVectorNode current = this.listHead.next;

            while (current != this.listHead)
            {
                // temporary hack until we fix the upcast in receiver context
                Bytes data = current.data;
                if (data != null)
                {
                    //delete data;
                }
                current = current.next;
            }
            this.listTail = this.listHead = new TcpVectorNode();
        }
コード例 #14
0
        public Bytes ExtractTail(out uint startOffset, out uint length)
        {
            if (this.Empty)
            {
                startOffset = 0;
                length      = 0;
                return(null);
            }
            TcpVectorNode candidate = this.listTail.prev;

            Bytes data = candidate.Unlink();

            count--;
            if (data != null)
            {
                size -= candidate.length;
            }
            startOffset = candidate.startOffset;
            length      = candidate.length;
            return(data);
        }
コード例 #15
0
 public void AddHead(TcpVectorNode tcpVNode)
 {
     this.size += tcpVNode.length;
     this.count++;
     this.listHead.LinkAsNext(tcpVNode);
 }
コード例 #16
0
 internal TcpVectorNode()
 {
     this.next = this;
     this.prev = this;
 }
コード例 #17
0
 public void AddTail(TcpVectorNode tcpVNode)
 {
     this.size += tcpVNode.length;
     this.count++;
     this.listTail.LinkAsPrev(tcpVNode);
 }
コード例 #18
0
        public void AddInSeqOrder(Bytes data, uint seqNumber, uint length)
        {
            if (this.Empty)
            {
                this.AddHead(data, seqNumber);
                return;
            }
            TcpVectorNode current = this.listHead.next;
            TcpVectorNode prev    = null;

            while (current != this.listHead)
            {
                //see if we belong past the current node
                if (TcpHeader.SeqGreater(seqNumber, (current.seqNumber + current.length)))
                {
                    if (current.next == this.listHead.next)
                    {
                        AddTail(data, seqNumber);
                        break;
                    }
                    prev    = current;
                    current = current.next;
                    continue;
                }
                //so now we're either
                //a) independent of both the prev and next node (simple insertion)
                //b) overlap with part of the prev or next node (trim the buffer)
                //c) subsumed by packets already in the assembly queue (discard the packer)

                //subsumed by next segment
                if (TcpHeader.SeqGreater(seqNumber, current.seqNumber) &&
                    TcpHeader.SeqLess(seqNumber + length, current.seqNumber + current.length))
                {
                    DebugPrint("data completely subsumed by existing segment\n");
                    //delete data;
                    break;
                }
                //subsumed by prev segment
                if (prev != null &&
                    TcpHeader.SeqGEQ(seqNumber, prev.seqNumber) &&
                    TcpHeader.SeqLEQ(seqNumber + length, prev.seqNumber + prev.length))
                {
                    DebugPrint("data completely subsumed by existing segment\n");
                    //delete data;
                    break;
                }
                //subsumed because next and prev are contiguous
                if (prev != null &&
                    TcpHeader.SeqEQ(prev.seqNumber + length, current.seqNumber))
                {
                    DebugPrint("data completely subsumed by existing segment\n");
                    //delete data;
                    break;
                }
                //a)
                if (TcpHeader.SeqLess(seqNumber, current.seqNumber) &&
                    TcpHeader.SeqLEQ(seqNumber + length, current.seqNumber) &&
                    ((prev == null) || TcpHeader.SeqGEQ(seqNumber, (prev.seqNumber + prev.length))))
                {
                    DebugPrint("new segment fits between two existing segments\n");
                    current.LinkAsPrev(data, seqNumber, length);
                    break;
                }
                //b)
                int trimEnd = 0;
                if (TcpHeader.SeqLess(seqNumber, current.seqNumber) &&
                    TcpHeader.SeqGreater(seqNumber + length, current.seqNumber))
                {
                    //we could worry about this segment subsuming later segments...
                    //instead we trim to fit (since we aleady have the later data
                    trimEnd = (int)length - (int)(current.seqNumber - seqNumber);
                    DebugStub.Assert(trimEnd > 0);
                }
                if (prev == null)
                {
                    DebugStub.Assert(trimEnd > 0);
                    current.LinkAsPrev(data, seqNumber, length);
                    current.prev.TrimEnd((uint)trimEnd);
                    break;
                }
                int trimStart = 0;
                if (TcpHeader.SeqLess(seqNumber, prev.seqNumber + prev.length))
                {
                    //at this point we know there is some gap between prev and next
                    trimStart = (int)((prev.seqNumber + prev.length) - seqNumber);
                    DebugStub.Assert(trimStart > 0);
                    VTable.Assert(trimStart > 0);
                }
                current.LinkAsPrev(data, seqNumber, length);
                current.prev.TrimStart((uint)trimStart);
                current.prev.TrimEnd((uint)trimEnd);
                break;
            }
        }
コード例 #19
0
        public bool ReleaseDataFromTxBuffer(uint bytes)
        {
            uint totalBytes = bytes;

            if (this.Empty)
            {
                DebugStub.Print("Attempting to release {0} bytes on an empty list? size {1}\n",
                                DebugStub.ArgList(bytes, this.size));
                DebugStub.Break();
                return(false);
            }
            else if (bytes > this.size)
            {
                DebugStub.Print("Ack! attempting to release {0} bytes size {1} bytes\n", DebugStub.ArgList(bytes, this.size));
                bytes = this.size;
            }
            if (bytes > this.currentTxTotalOffset)
            {
                DebugStub.Print("ack! trying to release more than total offset??\n");
                DebugStub.Break();
            }

            TcpVectorNode candidate = this.listHead.next;

            while (bytes != 0)
            {
                if (candidate.length <= bytes)
                {
                    TcpVectorNode toFree = candidate;
                    candidate  = candidate.next;
                    bytes      = bytes - toFree.length;
                    this.size -= toFree.length;
                    if (this.currentTxBuff == toFree)
                    {
                        this.currentTxBuff         = null;
                        this.currentTxBufferOffset = 0;
                    }
                    Bytes data = toFree.Unlink();
                    this.count--;
                    if (data != null)
                    {
                        //delete data;
                    }
                }
                else
                {
                    candidate.TrimStart(bytes);
                    //this happens when some packets being retransmitted are
                    //acknowledged during retransmission.
                    if ((candidate == this.currentTxBuff) &&
                        (candidate.startOffset > this.currentTxBufferOffset))
                    {
                        DebugStub.WriteLine("startoffset was {0} now {1} current offset {2} totalBytes to Free {3}\n",
                                            DebugStub.ArgList((candidate.startOffset - bytes), candidate.startOffset,
                                                              this.currentTxBufferOffset, totalBytes));
                        this.currentTxBufferOffset = candidate.startOffset;
                    }

                    this.size -= bytes;
                    bytes      = 0;
                }
            }
            if (this.Empty)
            {
                return(false);
            }
            return(true);
        }
コード例 #20
0
        public Bytes GetCurrentBuffer(out int start,
                                      out int length,
                                      out int bufferOffset,
                                      int totalOffset)
        {
            DebugPrint("GetCurrentBuffer: totalOffset{0} currentTxTotalOffset {1} currentTxBufferOffset {2}\n",
                       totalOffset, currentTxTotalOffset, currentTxBufferOffset);

            if (this.currentTxBuff != null && totalOffset == this.currentTxTotalOffset)
            {
                DebugPrint("GetCurrentBuff: fast path \n");
                start        = (int)this.currentTxBuff.startOffset;
                length       = (int)this.currentTxBuff.length;
                bufferOffset = (int)this.currentTxBufferOffset;
                return(this.currentTxBuff.data);
            }
            DebugPrint("GetCurrentBuff...slowpath\n");
            TcpVectorNode candidate = this.listHead.next;

            uint amt = (uint)totalOffset;

            if (amt == 0)
            {
                this.currentTxBuff         = this.listHead.next;
                this.currentTxTotalOffset  = 0;
                this.currentTxBufferOffset = this.currentTxBuff.startOffset;
                start        = (int)this.currentTxBuff.startOffset;
                length       = (int)this.currentTxBuff.length;
                bufferOffset = (int)this.currentTxBuff.startOffset;

                return(this.currentTxBuff.data);
            }

            while (amt > 0)
            {
                if (amt > candidate.length)
                {
                    amt -= candidate.length;
                    VTable.Assert(candidate.next != this.listTail);
                    candidate = candidate.next;
                    DebugStub.Assert(amt > 0);
                }
                else if (amt == candidate.length)
                {
                    DebugStub.Assert(amt >= 0);
                    amt -= candidate.length;
                    DebugStub.Assert(candidate.next != this.listTail);
                    VTable.Assert(candidate.next != this.listTail);
                    candidate                  = candidate.next;
                    start                      = (int)candidate.startOffset;
                    length                     = (int)candidate.length;
                    bufferOffset               = (int)candidate.startOffset;
                    this.currentTxBuff         = candidate;
                    this.currentTxTotalOffset  = (uint)totalOffset;
                    this.currentTxBufferOffset = candidate.startOffset;
                    return(candidate.data);
                }
                else
                {
                    DebugStub.Assert(amt >= 0);
                    bufferOffset               = (int)(amt + candidate.startOffset);
                    start                      = (int)candidate.startOffset;
                    length                     = (int)candidate.length;
                    this.currentTxBuff         = candidate;
                    this.currentTxTotalOffset  = (uint)totalOffset;
                    this.currentTxBufferOffset = amt + candidate.startOffset;
                    return(candidate.data);
                }
            }
            DebugStub.Print("ack! no buffer found!!!!\n");
            start        = -1;
            length       = -1;
            bufferOffset = -1;
            DebugStub.Assert(false);
            return(null);
        }