deliverData method

void deliverData(
  1. int offset,
  2. Uint8List data
)

Delivers a chunk at its offset in the stream, releasing whatever has become contiguous.

Ordering is per stream, on these offsets. It used to happen at the socket, on the connection's packet sequence number, which meant a gap belonging to one stream stalled delivery on all of them.

Implementation

void deliverData(int offset, Uint8List data) {
  if (data.isEmpty) return;

  final end = offset + data.length;

  // Already delivered. A retransmission of bytes the application has seen
  // arrives here, and must not be handed over twice — that corrupts the byte
  // stream, and the Noise layer above fails its MAC rather than merely
  // reading duplicates.
  if (end <= _recvOffset) return;

  // Partly delivered: keep only the tail that is new.
  if (offset < _recvOffset) {
    data = Uint8List.sublistView(data, _recvOffset - offset);
    offset = _recvOffset;
  }

  if (offset > _recvOffset) {
    // Ahead of a gap. Hold it until the missing bytes arrive.
    //
    // Flow control is the real bound here; the backstop below only catches a
    // peer ignoring its limit, which is why it sits above the largest window
    // rather than at it. Discarding is never safe: the packet was
    // acknowledged on arrival, so the sender has already stopped tracking it
    // and will never send those bytes again, stranding the stream at this
    // offset for good. A backstop equal to the maximum window fires during
    // legitimate transfers, because a stream whose window has grown to the
    // maximum can have that whole window sitting out of order.
    if (_recvOOO.containsKey(offset)) return;
    if (_oooBytes + data.length > _maxOutOfOrderBytes) {
      addError(StreamResetError(2)); // flow control violation
      _close(isReset: true);
      return;
    }
    _recvOOO[offset] = Uint8List.fromList(data);
    _oooBytes += data.length;
    _accountReceived(data.length);
    return;
  }

  _emitContiguous(data);

  // Release anything that was waiting on the bytes just delivered.
  while (true) {
    final next = _recvOOO.remove(_recvOffset);
    if (next == null) break;
    _oooBytes -= next.length;
    _emitContiguous(next, alreadyAccounted: true);
  }

  _checkFinished();
}