in http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/framing/FrameRenderer.scala [31:149]
def render(frame: FrameEvent): ByteString =
frame match {
case GoAwayFrame(lastStreamId, errorCode, debug) =>
Frame(
8 + debug.length,
Http2Protocol.FrameType.GOAWAY,
Http2Protocol.Flags.NO_FLAGS,
Http2Protocol.NoStreamId)
.putInt32(lastStreamId)
.putInt32(errorCode.id)
// appends debug data, if any
.put(debug)
.build()
case DataFrame(streamId, endStream, payload) =>
// TODO: should padding be emitted? In which cases?
Frame(
payload.length,
Http2Protocol.FrameType.DATA,
Http2Protocol.Flags.END_STREAM.ifSet(endStream),
streamId)
.put(payload)
.build()
case HeadersFrame(streamId, endStream, endHeaders, headerBlockFragment, prioInfo) =>
Frame(
(if (prioInfo.isDefined) 5 else 0) + headerBlockFragment.length,
Http2Protocol.FrameType.HEADERS,
Http2Protocol.Flags.END_STREAM.ifSet(endStream) |
Http2Protocol.Flags.END_HEADERS.ifSet(endHeaders) |
Http2Protocol.Flags.PRIORITY.ifSet(prioInfo.isDefined),
streamId)
.putPriorityInfo(prioInfo)
.put(headerBlockFragment)
.build()
case WindowUpdateFrame(streamId, windowSizeIncrement) =>
Frame(
4,
Http2Protocol.FrameType.WINDOW_UPDATE,
Http2Protocol.Flags.NO_FLAGS,
streamId)
.putInt32(windowSizeIncrement)
.build()
case ContinuationFrame(streamId, endHeaders, payload) =>
Frame(
payload.length,
Http2Protocol.FrameType.CONTINUATION,
Http2Protocol.Flags.END_HEADERS.ifSet(endHeaders),
streamId)
.put(payload)
.build()
case SettingsFrame(settings) =>
val b = Frame(
settings.length * 6,
Http2Protocol.FrameType.SETTINGS,
Http2Protocol.Flags.NO_FLAGS,
Http2Protocol.NoStreamId)
@tailrec def renderNext(remaining: Seq[Setting]): Unit =
remaining match {
case Setting(id, value) +: remaining =>
b.putInt16(id.id)
b.putInt32(value)
renderNext(remaining)
case Nil =>
}
renderNext(settings)
b.build()
case _: SettingsAckFrame =>
Frame(
0,
Http2Protocol.FrameType.SETTINGS,
Http2Protocol.Flags.ACK,
Http2Protocol.NoStreamId)
.build()
case PingFrame(ack, data) =>
Frame(
data.length,
Http2Protocol.FrameType.PING,
Http2Protocol.Flags.ACK.ifSet(ack),
Http2Protocol.NoStreamId)
.put(data)
.build()
case RstStreamFrame(streamId, errorCode) =>
Frame(
4,
Http2Protocol.FrameType.RST_STREAM,
Http2Protocol.Flags.NO_FLAGS,
streamId)
.putInt32(errorCode.id)
.build()
case PushPromiseFrame(streamId, endHeaders, promisedStreamId, headerBlockFragment) =>
Frame(
4 + headerBlockFragment.length,
Http2Protocol.FrameType.PUSH_PROMISE,
Http2Protocol.Flags.END_HEADERS.ifSet(endHeaders),
streamId)
.putInt32(promisedStreamId)
.put(headerBlockFragment)
.build()
case frame @ PriorityFrame(streamId, _, _, _) =>
Frame(
5,
Http2Protocol.FrameType.PRIORITY,
Http2Protocol.Flags.NO_FLAGS,
streamId)
.putPriorityInfo(frame)
.build()
case _ => throw new IllegalStateException(s"Unexpected frame type ${frame.frameTypeName}.")
}