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); }
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); }
internal void LinkAsPrev(TcpVectorNode tcpVNode) { tcpVNode.prev = this.prev; this.prev = tcpVNode; tcpVNode.next = this; tcpVNode.prev.next = tcpVNode; }
internal void LinkAsNext(TcpVectorNode tcpVNode) { tcpVNode.next = this.next; this.next = tcpVNode; tcpVNode.prev = this; tcpVNode.next.prev = tcpVNode; }
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); }
internal TcpVectorNode BoxedUnlink() { this.prev.next = this.next; this.next.prev = this.prev; this.next = this; this.prev = this; return(this); }
internal Bytes Unlink() { this.prev.next = this.next; this.next.prev = this.prev; this.next = this; this.prev = this; return(this.data); }
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; }
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; }
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; }
public TcpVectorQueueByte() { size = 0; count = 0; TcpVectorNode node = this.listHead = new TcpVectorNode(); this.listTail = node; currentTxBuff = null; currentTxBufferOffset = 0; currentTxTotalOffset = 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()); }
// 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(); }
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); }
public void AddHead(TcpVectorNode tcpVNode) { this.size += tcpVNode.length; this.count++; this.listHead.LinkAsNext(tcpVNode); }
internal TcpVectorNode() { this.next = this; this.prev = this; }
public void AddTail(TcpVectorNode tcpVNode) { this.size += tcpVNode.length; this.count++; this.listTail.LinkAsPrev(tcpVNode); }
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; } }
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); }
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); }