/// <summary> /// Adds the current chunk to the terminal and starts a new chunk. /// </summary> private void _NextChunk() { this._Terminal._Push(this._Current); this._Current = new _Chunk() { Data = new byte[this._ChunkSize] }; }
public _SendStream(int ChunkSize, OutTerminal Terminal) { this._ChunkSize = ChunkSize; this._Terminal = Terminal; this._Current = new _Chunk { Data = new byte[ChunkSize], Initial = true }; }
/// <summary> /// Appends a new chunk to this terminal. /// </summary> private void _Push(_Chunk Chunk) { lock (this) { LinkedListNode<_Chunk> node = this._Chunks.AddLast(Chunk); if (this._SendNode == null) { this._SendNode = node; this._SendNumber = this._SequenceNumber; } this._SequenceNumber++; } }
/// <summary> /// Advances to the next chunk. /// </summary> private void _Continue() { if (this._Current.Final) { throw new StreamUnderflowException(); } if (this._Remove) { this._Chunks.Remove(this._SequenceNumber); } else { this._Current.Data = null; } this._Offset = 0; this._Current = this._Chunks[++this._SequenceNumber]; }
public _ReceiveStream(int SequenceNumber, bool Remove, InTerminal Terminal) { this._Remove = Remove; this._Chunks = Terminal._Chunks; this._SequenceNumber = SequenceNumber; this._Current = this._Chunks[SequenceNumber]; }
/// <summary> /// Processes the receipt of a chunk. Returns true and sets the message stream if a full message has been received. /// </summary> /// <param name="SequenceNumber">The sequence number for the received chunk.</param> /// <param name="Acknowledged">Indicates wether the receipt of this chunk has changed the acknowledgement number.</param> public bool Process(int SequenceNumber, byte[] Data, bool Initial, bool Final, out bool Acknowledged, ref Disposable<InStream> Message) { _Chunk chunk; // Make sure we need this chunk if (this._Chunks.ContainsKey(SequenceNumber) || this._AcknowledgementNumber - SequenceNumber > 0) { Acknowledged = false; return false; } // Update acknowledgement number if (Acknowledged = this._AcknowledgementNumber == SequenceNumber) { while (this._Chunks.TryGetValue(++this._AcknowledgementNumber, out chunk)) { // If the chunk has already been read in a message, remove it if (chunk.Data == null) { this._Chunks.Remove(this._AcknowledgementNumber); } } } // Add chunk chunk = new _Chunk { Data = Data, Initial = Initial, Final = Final }; // Find "First" chunk _Chunk first; int firstsq = SequenceNumber - 1; if (!Initial && this._Chunks.TryGetValue(firstsq, out first)) { firstsq = first.First; first = this._Chunks[firstsq]; chunk.First = firstsq; } else { chunk.First = firstsq = SequenceNumber; first = chunk; } // Find "Last" chunk _Chunk last; int lastsq = SequenceNumber + 1; if (!Final && this._Chunks.TryGetValue(lastsq, out last)) { lastsq = last.Last; last = this._Chunks[lastsq]; chunk.Last = lastsq; } else { chunk.Last = lastsq = SequenceNumber; last = chunk; } // Check if a full message can be formed this._Chunks[SequenceNumber] = chunk; if (first.Initial && last.Final) { Message = new _ReceiveStream(firstsq, Acknowledged, this); return true; } else { first.Last = lastsq; last.First = firstsq; return false; } }