in lib/src/frames/frame_reader.dart [156:274]
Frame _readFrame(FrameHeader header, List<int> bytes, int frameOffset) {
var frameEnd = frameOffset + header.length;
var offset = frameOffset;
switch (header.type) {
case FrameType.DATA:
var padLength = 0;
if (_isFlagSet(header.flags, DataFrame.FLAG_PADDED)) {
_checkFrameLengthCondition((frameEnd - offset) >= 1);
padLength = bytes[offset++];
}
var dataLen = frameEnd - offset - padLength;
_checkFrameLengthCondition(dataLen >= 0);
var dataBytes = viewOrSublist(bytes, offset, dataLen);
return DataFrame(header, padLength, dataBytes);
case FrameType.HEADERS:
var padLength = 0;
if (_isFlagSet(header.flags, HeadersFrame.FLAG_PADDED)) {
_checkFrameLengthCondition((frameEnd - offset) >= 1);
padLength = bytes[offset++];
}
int? streamDependency;
var exclusiveDependency = false;
int? weight;
if (_isFlagSet(header.flags, HeadersFrame.FLAG_PRIORITY)) {
_checkFrameLengthCondition((frameEnd - offset) >= 5);
exclusiveDependency = (bytes[offset] & 0x80) == 0x80;
streamDependency = readInt32(bytes, offset) & 0x7fffffff;
offset += 4;
weight = bytes[offset++];
}
var headerBlockLen = frameEnd - offset - padLength;
_checkFrameLengthCondition(headerBlockLen >= 0);
var headerBlockFragment = viewOrSublist(bytes, offset, headerBlockLen);
return HeadersFrame(header, padLength, exclusiveDependency,
streamDependency, weight, headerBlockFragment);
case FrameType.PRIORITY:
_checkFrameLengthCondition(
(frameEnd - offset) == PriorityFrame.FIXED_FRAME_LENGTH,
message: 'Priority frame length must be exactly 5 bytes.');
var exclusiveDependency = (bytes[offset] & 0x80) == 0x80;
var streamDependency = readInt32(bytes, offset) & 0x7fffffff;
var weight = bytes[offset + 4];
return PriorityFrame(
header, exclusiveDependency, streamDependency, weight);
case FrameType.RST_STREAM:
_checkFrameLengthCondition(
(frameEnd - offset) == RstStreamFrame.FIXED_FRAME_LENGTH,
message: 'Rst frames must have a length of 4.');
var errorCode = readInt32(bytes, offset);
return RstStreamFrame(header, errorCode);
case FrameType.SETTINGS:
_checkFrameLengthCondition((header.length % 6) == 0,
message: 'Settings frame length must be a multiple of 6 bytes.');
var count = header.length ~/ 6;
var settings = <Setting>[];
for (var i = 0; i < count; i++) {
var identifier = readInt16(bytes, offset + 6 * i);
var value = readInt32(bytes, offset + 6 * i + 2);
settings.add(Setting(identifier, value));
}
var frame = SettingsFrame(header, settings);
if (frame.hasAckFlag) {
_checkFrameLengthCondition(header.length == 0,
message: 'Settings frame length must 0 for ACKs.');
}
return frame;
case FrameType.PUSH_PROMISE:
var padLength = 0;
if (_isFlagSet(header.flags, PushPromiseFrame.FLAG_PADDED)) {
_checkFrameLengthCondition((frameEnd - offset) >= 1);
padLength = bytes[offset++];
}
var promisedStreamId = readInt32(bytes, offset) & 0x7fffffff;
offset += 4;
var headerBlockLen = frameEnd - offset - padLength;
_checkFrameLengthCondition(headerBlockLen >= 0);
var headerBlockFragment = viewOrSublist(bytes, offset, headerBlockLen);
return PushPromiseFrame(
header, padLength, promisedStreamId, headerBlockFragment);
case FrameType.PING:
_checkFrameLengthCondition(
(frameEnd - offset) == PingFrame.FIXED_FRAME_LENGTH,
message: 'Ping frames must have a length of 8.');
var opaqueData = readInt64(bytes, offset);
return PingFrame(header, opaqueData);
case FrameType.GOAWAY:
_checkFrameLengthCondition((frameEnd - offset) >= 8);
var lastStreamId = readInt32(bytes, offset);
var errorCode = readInt32(bytes, offset + 4);
var debugData = viewOrSublist(bytes, offset + 8, header.length - 8);
return GoawayFrame(header, lastStreamId, errorCode, debugData);
case FrameType.WINDOW_UPDATE:
_checkFrameLengthCondition(
(frameEnd - offset) == WindowUpdateFrame.FIXED_FRAME_LENGTH,
message: 'Window update frames must have a length of 4.');
var windowSizeIncrement = readInt32(bytes, offset) & 0x7fffffff;
return WindowUpdateFrame(header, windowSizeIncrement);
case FrameType.CONTINUATION:
var headerBlockFragment =
viewOrSublist(bytes, offset, frameEnd - offset);
return ContinuationFrame(header, headerBlockFragment);
default:
// Unknown frames should be ignored according to spec.
return UnknownFrame(
header, viewOrSublist(bytes, offset, frameEnd - offset));
}
}