Package-Level Type Names (total 124, in which 48 are exported)
/* sort exporteds by: | */
ClientConn is the state of a single HTTP/2 client connection to an
HTTP/2 server. // whether conn is being reused; atomicbr*bufio.Readerbw*bufio.Writerclosedbool // true if conn was closed for idlenessclosingbool // hold mu; broadcast on flow/closed changes // whether conn is marked to not be reused for any future requestsextendedConnectAllowedbool // our conn-level flow control quota (cs.outflow is per stream)fr*Framer // used by clientConnPool // if non-nil, the GoAwayFrame we received // goAway frame's debug data, retained as a string // HPACK encoder writes into thishenc*hpack.Encoder // or 0 for neveridleTimer*time.Timer // peer's conn-level flow controlinitialStreamRecvWindowSizeint32 internalStateHook reports state changes back to the net/http.ClientConn.
Note that this is different from the user state hook registered by
net/http.ClientConn.SetStateHook: The internal hook calls ClientConn,
which calls the user hook.lastActivetime.Time // time last idlemaxConcurrentStreamsuint32 Settings from peer: (also guarded by wmu) // guards followingnextStreamIDuint32peerMaxHeaderListSizeuint64peerMaxHeaderTableSizeuint32 // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams pendingResets is the number of RST_STREAM frames we have sent to the peer,
without confirming that the peer has received them. When we send a RST_STREAM,
we bundle it with a PING frame, unless a PING is already in flight. We count
the reset stream against the connection's concurrency limit until we get
a PING response. This limits the number of requests we'll try to send to a
completely unresponsive connection.pingTimeouttime.Duration // in flight ping data to notification channel readBeforeStreamID is the smallest stream ID that has not been followed by
a frame read from the peer. We use this to determine when a request may
have been sent to a completely unresponsive connection:
If the request ID is less than readBeforeStreamID, then we have had some
indication of life on the connection since sending the request.readIdleTimeouttime.Duration readLoop goroutine fields: // closed on error // set before readerDone is closed reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests.
Write to reqHeaderMu to lock it, read from it to unlock.
Lock reqmu BEFORE mu or wmu. rstStreamPingsBlocked works around an unfortunate gRPC behavior.
gRPC strictly limits the number of PING frames that it will receive.
The default is two pings per two hours, but the limit resets every time
the gRPC endpoint sends a HEADERS or DATA frame. See golang/go#70575.
rstStreamPingsBlocked is set after receiving a response to a PING frame
bundled with an RST_STREAM (see pendingResets below), and cleared after
receiving a HEADERS or DATA frame. // true if we've seen a settings frame, false otherwise // closed when seenSettings is true or frame reading fails // whether being used for a single http.Request // client-initiated // incr by ReserveNewRequest; decr on RoundTripstrictMaxConcurrentStreamsboolt*Transport // usually *tls.Conn, except specialized impls // nil only for specialized impls // we sent a SETTINGS frame and haven't heard back // first write error that has occurred wmu is held while writing.
Acquire BEFORE mu when holding both, to avoid blocking mu on network writes.
Only acquire both at the same time when changing peer settings. CanTakeNewRequest reports whether the connection can take a new request,
meaning it has not been closed or received or sent a GOAWAY.
If the caller is going to immediately make a new request on this
connection, use ReserveNewRequest instead. Close closes the client connection immediately.
In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead. Ping sends a PING frame to the server and waits for the ack. ReserveNewRequest is like CanTakeNewRequest but also reserves a
concurrent stream in cc. The reservation is decremented on the
next call to RoundTrip.(*ClientConn) RoundTrip(req *ClientRequest) (*ClientResponse, error) SetDoNotReuse marks cc as not reusable for future HTTP requests. Shutdown gracefully closes the client connection, waiting for running streams to complete. State returns a snapshot of cc's state. requires cc.mu be held. availableLocked reports the number of concurrency slots available. awaitOpenSlotForStreamLocked waits until len(streams) < maxConcurrentStreams.
Must hold cc.mu. canReserveLocked reports whether a net/http.ClientConn can reserve a slot on this conn.
This follows slightly different rules than clientConnIdleState.canTakeNewRequest.
We only permit reservations up to the conn's concurrency limit.
This differs from ClientConn.ReserveNewRequest, which permits reservations
past the limit when StrictMaxConcurrentStreams is set.(*ClientConn) canTakeNewRequestLocked() bool(*ClientConn) closeConn() closes the client connection immediately. In-flight requests are interrupted.
err is sent to streams. closes the client connection immediately. In-flight requests are interrupted.(*ClientConn) closeIfIdle() countReadFrameError calls ClientConn.fr.countError with a string
representing err. currentRequestCountLocked reports the number of concurrency slots currently in use,
including active streams, reserved slots, and reset streams waiting for acknowledgement.(*ClientConn) decrStreamReservations()(*ClientConn) decrStreamReservationsLocked() requires cc.wmu be held. A tls.Conn.Close can hang for a long time if the peer is unresponsive.
Try to shut it down more aggressively.(*ClientConn) forgetStreamID(id uint32)(*ClientConn) goAwayAndClose(code ErrCode)(*ClientConn) healthCheck()(*ClientConn) idleState() clientConnIdleState(*ClientConn) idleStateLocked() (st clientConnIdleState)(*ClientConn) isDoNotReuseAndIdle() bool(*ClientConn) isUsableLocked() bool(*ClientConn) logf(format string, args ...any)(*ClientConn) maybeCallStateHook() onIdleTimeout is called from a time.AfterFunc goroutine. It will
only be called when we're idle, but because we're coming from a new
goroutine, there could be a new request coming in at the same time,
so this simply calls the synchronized closeIfIdle to shut down this
connection. The timer could just call closeIfIdle, but this is more
clear. readLoop runs in its own goroutine and reads and dispatches frames.(*ClientConn) responseHeaderTimeout() time.Duration(*ClientConn) roundTrip(req *ClientRequest, streamf func(*clientStream)) (*ClientResponse, error)(*ClientConn) sendGoAway() error tooIdleLocked reports whether this connection has been been sitting idle
for too much wall time.(*ClientConn) vlogf(format string, args ...any)(*ClientConn) writeHeader(name, value string) requires cc.wmu be held writeStreamReset sends a RST_STREAM frame.
When ping is true, it also sends a PING frame with a random payload.
*ClientConn : database/sql/driver.Pinger
*ClientConn : io.Closer
func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn
func (*Transport).dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error)
func (*Transport).newClientConn(c net.Conn, singleUse bool, internalStateHook func()) (*ClientConn, error)
func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn
func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn
func traceGotConn(req *ClientRequest, cc *ClientConn, reused bool)
ClientConnState describes the state of a ClientConn. Closed is whether the connection is closed. Closing is whether the connection is in the process of
closing. It may be closing due to shutdown, being a
single-use connection, being marked as DoNotReuse, or
having received a GOAWAY frame. LastIdle, if non-zero, is when the connection last
transitioned to idle state. MaxConcurrentStreams is how many concurrent streams the
peer advertised as acceptable. Zero means no SETTINGS
frame has been received yet. StreamsActive is how many streams are active. StreamsPending is how many requests have been sent in excess
of the peer's advertised MaxConcurrentStreams setting and
are waiting for other streams to complete. StreamsReserved is how many streams have been reserved via
ClientConn.ReserveNewRequest.
func (*ClientConn).State() ClientConnState
A ContinuationFrame is used to continue a sequence of header block fragments.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.10FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). // caller can access []byte fields in the FrameheaderFragBuf[]byte Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.(*ContinuationFrame) HeaderBlockFragment() []byte(*ContinuationFrame) HeadersEnded() bool( ContinuationFrame) String() string(*ContinuationFrame) checkValid()(*ContinuationFrame) invalidate()( ContinuationFrame) writeDebug(buf *bytes.Buffer)
*ContinuationFrame : Frame
ContinuationFrame : expvar.Var
ContinuationFrame : fmt.Stringer
*ContinuationFrame : headersEnder
*ContinuationFrame : headersOrContinuation
ContinuationFrame : context.stringer
*ContinuationFrame : golang.org/x/net/http2.headersEnder
*ContinuationFrame : golang.org/x/net/http2.headersOrContinuation
ContinuationFrame : runtime.stringer
A DataFrame conveys arbitrary, variable-length sequences of octets
associated with a stream.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.1FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame).data[]byte // caller can access []byte fields in the Frame Data returns the frame's data octets, not including any padding
size byte or padding suffix bytes.
The caller must not retain the returned memory past the next
call to ReadFrame. Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.(*DataFrame) StreamEnded() bool( DataFrame) String() string(*DataFrame) checkValid()(*DataFrame) invalidate()( DataFrame) writeDebug(buf *bytes.Buffer)
*DataFrame : Frame
DataFrame : expvar.Var
DataFrame : fmt.Stringer
*DataFrame : streamEnder
DataFrame : context.stringer
*DataFrame : golang.org/x/net/http2.streamEnder
DataFrame : runtime.stringer
A Framer reads and writes Frames. AllowIllegalReads permits the Framer's ReadFrame method
to return non-compliant frames or frame orders.
This is for testing and permits using the Framer to test
other HTTP/2 implementations' conformance to the spec.
It is not compatible with ReadMetaHeaders. AllowIllegalWrites permits the Framer's Write methods to
write frames that do not conform to the HTTP/2 spec. This
permits using the Framer to test other HTTP/2
implementations' conformance to the spec.
If false, the Write methods will prefer to return an error
rather than comply. MaxHeaderListSize is the http2 MAX_HEADER_LIST_SIZE.
It's used only if ReadMetaHeaders is set; 0 means a sane default
(currently 16MB)
If the limit is hit, MetaHeadersFrame.Truncated is set true. MaxHeaderValueCount is the maximum permitted number of
header values.
It's used only if ReadMetaHeaders is set; 0 means no limit.
If the limit is hit, MetaHeadersFrame.Truncated is set true. ReadMetaHeaders if non-nil causes ReadFrame to merge
HEADERS and CONTINUATION frames together and return
MetaHeadersFrame instead. countError is a non-nil func that's called on a frame parse
error with some unique error path token. It's initialized
from Transport.CountError or Server.CountError. // only use for logging written writesdebugFramerBuf*bytes.BufferdebugReadLoggerffunc(string, ...any)debugWriteLoggerffunc(string, ...any)errDetailerror // nil if frames aren't reused (default) TODO: let getReadBuf be configurable, and use a less memory-pinning
allocator in server.go to minimize memory pinned for many idle conns.
Will probably also need to make frame invalidation have a hook too.headerBuf[9]bytelastFrameFrame lastFrameType holds the type of the last frame for verifying frame order. lastHeaderStream is non-zero if the last frame was an
unfinished HEADERS/CONTINUATION.logReadsboollogWritesboolmaxReadSizeuint32 // zero means unlimited; TODO: implementrio.Reader // cache for default getReadBufwio.Writerwbuf[]byte ErrorDetail returns a more detailed error of the last error
returned by Framer.ReadFrame. For instance, if ReadFrame
returns a StreamError with code PROTOCOL_ERROR, ErrorDetail
will say exactly what was invalid. ErrorDetail is not guaranteed
to return a non-nil value and like the rest of the http2 package,
its return value is not protected by an API compatibility promise.
ErrorDetail is reset after the next call to ReadFrame. ReadFrame reads a single frame. The returned Frame is only valid
until the next call to ReadFrame or ReadFrameBodyForHeader.
If the frame is larger than previously set with SetMaxReadFrameSize, the
returned error is ErrFrameTooLarge. Other errors may be of type
ConnectionError, StreamError, or anything else from the underlying
reader.
If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID
indicates the stream responsible for the error. ReadFrameForHeader reads the payload for the frame with the given FrameHeader.
It behaves identically to ReadFrame, other than not checking the maximum
frame size. ReadFrameHeader reads the header of the next frame.
It reads the 9-byte fixed frame header, and does not read any portion of the
frame payload. The caller is responsible for consuming the payload, either
with ReadFrameForHeader or directly from the Framer's io.Reader.
If the frame is larger than previously set with SetMaxReadFrameSize, it
returns the frame header and ErrFrameTooLarge.
If the returned FrameHeader.StreamID is non-zero, it indicates the stream
responsible for the error. SetMaxReadFrameSize sets the maximum size of a frame
that will be read by a subsequent call to ReadFrame.
It is the caller's responsibility to advertise this
limit with a SETTINGS frame. SetReuseFrames allows the Framer to reuse Frames.
If called on a Framer, Frames returned by calls to ReadFrame are only
valid until the next call to ReadFrame. WriteContinuation writes a CONTINUATION frame.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently. WriteData writes a DATA frame.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility not to violate the maximum frame size
and to not call other Write methods concurrently. WriteDataPadded writes a DATA frame with optional padding.
If pad is nil, the padding bit is not sent.
The length of pad must not exceed 255 bytes.
The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility not to violate the maximum frame size
and to not call other Write methods concurrently.(*Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error WriteHeaders writes a single HEADERS frame.
This is a low-level header writing method. Encoding headers and
splitting them into any necessary CONTINUATION frames is handled
elsewhere.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently.(*Framer) WritePing(ack bool, data [8]byte) error WritePriority writes a PRIORITY frame.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently. WritePriorityUpdate writes a PRIORITY_UPDATE frame.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently. WritePushPromise writes a single PushPromise Frame.
As with Header Frames, This is the low level call for writing
individual frames. Continuation frames are handled elsewhere.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently. WriteRSTStream writes a RST_STREAM frame.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently. WriteRawFrame writes a raw frame. This can be used to write
extension frames unknown to this package. WriteSettings writes a SETTINGS frame with zero or more settings
specified and the ACK bit not set.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently. WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
It will perform exactly one Write to the underlying Writer.
It is the caller's responsibility to not call other Write methods concurrently. WriteWindowUpdate writes a WINDOW_UPDATE frame.
The increment value must be between 1 and 2,147,483,647, inclusive.
If the Stream ID is zero, the window update applies to the
connection as a whole. checkFrameOrder reports an error if f is an invalid frame to return
next from ReadFrame. Mostly it checks whether HEADERS and
CONTINUATION frames are contiguous. connError returns ConnectionError(code) but first
stashes away a public reason to the caller can optionally relay it
to the peer before hanging up on them. This might help others debug
their implementations.(*Framer) endWrite() error(*Framer) logWrite()(*Framer) maxHeaderListSize() uint32(*Framer) maxHeaderStringLen() int(*Framer) maxHeaderValueCount() int readMetaFrame returns 0 or more CONTINUATION frames from fr and
merge them into the provided hf and returns a MetaHeadersFrame
with the decoded hpack values.(*Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) startWriteDataPadded is WriteDataPadded, but only writes the frame to the Framer's internal buffer.
The caller should call endWrite to flush the frame to the underlying writer.(*Framer) writeByte(v byte)(*Framer) writeBytes(v []byte)(*Framer) writeUint16(v uint16)(*Framer) writeUint32(v uint32)
func NewFramer(w io.Writer, r io.Reader) *Framer
FrameWriteRequest is a request to write a frame. done, if non-nil, must be a buffered channel with space for
1 message and is sent the return value from write (or an
earlier error) when the frame has been written. stream is the stream on which this frame will be written.
nil for non-stream frames like PING and SETTINGS.
nil for RST_STREAM streams, which use the StreamError.StreamID field instead. write is the interface value that does the writing, once the
WriteScheduler has selected this frame to write. The write
functions are all defined in write.go. Consume consumes min(n, available) bytes from this frame, where available
is the number of flow control bytes available on the stream. Consume returns
0, 1, or 2 frames, where the integer return value gives the number of frames
returned.
If flow control prevents consuming any bytes, this returns (_, _, 0). If
the entire frame was consumed, this returns (wr, _, 1). Otherwise, this
returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and
'rest' contains the remaining bytes. The consumed bytes are deducted from the
underlying stream's flow control budget. DataSize returns the number of flow control bytes that must be consumed
to write this entire frame. This is 0 for non-DATA frames. StreamID returns the id of the stream this frame will be written to.
0 is used for non-stream frames such as PING and SETTINGS. String is for debugging only. isControl reports whether wr is a control frame for MaxQueuedControlFrames
purposes. That includes non-stream frames and RST_STREAM frames. replyToWriter sends err to wr.done and panics if the send must block
This does nothing if wr.done is nil.
FrameWriteRequest : expvar.Var
FrameWriteRequest : fmt.Stringer
FrameWriteRequest : context.stringer
FrameWriteRequest : runtime.stringer
func FrameWriteRequest.Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int)
func FrameWriteRequest.Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int)
func WriteScheduler.Pop() (wr FrameWriteRequest, ok bool)
func WriteScheduler.Push(wr FrameWriteRequest)
A GoAwayFrame informs the remote peer to stop creating streams on this connection.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.8ErrCodeErrCodeFrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame).LastStreamIDuint32debugData[]byte // caller can access []byte fields in the Frame DebugData returns any debug data in the GOAWAY frame. Its contents
are not defined.
The caller must not retain the returned memory past the next
call to ReadFrame. Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.( GoAwayFrame) String() string(*GoAwayFrame) checkValid()(*GoAwayFrame) invalidate()( GoAwayFrame) writeDebug(buf *bytes.Buffer)
*GoAwayFrame : Frame
GoAwayFrame : expvar.Var
GoAwayFrame : fmt.Stringer
GoAwayFrame : context.stringer
GoAwayFrame : runtime.stringer
A HeadersFrame is used to open a stream and additionally carries a
header block fragment.FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). Priority is set if FlagHeadersPriority is set in the FrameHeader. // caller can access []byte fields in the Frame // not owned(*HeadersFrame) HasPriority() bool Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.(*HeadersFrame) HeaderBlockFragment() []byte(*HeadersFrame) HeadersEnded() bool(*HeadersFrame) StreamEnded() bool( HeadersFrame) String() string(*HeadersFrame) checkValid()(*HeadersFrame) invalidate()( HeadersFrame) writeDebug(buf *bytes.Buffer)
*HeadersFrame : Frame
HeadersFrame : expvar.Var
HeadersFrame : fmt.Stringer
*HeadersFrame : headersEnder
*HeadersFrame : headersOrContinuation
*HeadersFrame : streamEnder
HeadersFrame : context.stringer
*HeadersFrame : golang.org/x/net/http2.headersEnder
*HeadersFrame : golang.org/x/net/http2.headersOrContinuation
*HeadersFrame : golang.org/x/net/http2.streamEnder
HeadersFrame : runtime.stringer
func (*Framer).readMetaFrame(hf *HeadersFrame) (Frame, error)
HeadersFrameParam are the parameters for writing a HEADERS frame. BlockFragment is part (or all) of a Header Block. EndHeaders indicates that this frame contains an entire
header block and is not followed by any
CONTINUATION frames. EndStream indicates that the header block is the last that
the endpoint will send for the identified stream. Setting
this flag causes the stream to enter one of "half closed"
states. PadLength is the optional number of bytes of zeros to add
to this frame. Priority, if non-zero, includes stream priority information
in the HEADER frame. StreamID is the required Stream ID to initiate.
func (*Framer).WriteHeaders(p HeadersFrameParam) error
A MetaHeadersFrame is the representation of one HEADERS frame and
zero or more contiguous CONTINUATION frames and the decoding of
their HPACK-encoded contents.
This type of frame does not appear on the wire and is only returned
by the Framer when Framer.ReadMetaHeaders is set. Fields are the fields contained in the HEADERS and
CONTINUATION frames. The underlying slice is owned by the
Framer and must not be retained after the next call to
ReadFrame.
Fields are guaranteed to be in the correct http2 order and
not have unknown pseudo header fields or invalid header
field names or values. Required pseudo header fields may be
missing, however. Use the MetaHeadersFrame.Pseudo accessor
method access pseudo headers.HeadersFrame*HeadersFrameHeadersFrame.FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). Priority is set if FlagHeadersPriority is set in the FrameHeader. Truncated is whether the max header list size limit was hit
and Fields is incomplete. The hpack decoder state is still
valid, however. // caller can access []byte fields in the Frame // not owned( MetaHeadersFrame) HasPriority() bool Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.( MetaHeadersFrame) HeaderBlockFragment() []byte( MetaHeadersFrame) HeadersEnded() bool PseudoFields returns the pseudo header fields of mh.
The caller does not own the returned slice. PseudoValue returns the given pseudo header field's value.
The provided pseudo field should not contain the leading colon. RegularFields returns the regular (non-pseudo) header fields of mh.
The caller does not own the returned slice.( MetaHeadersFrame) StreamEnded() bool( MetaHeadersFrame) String() string(*MetaHeadersFrame) checkPseudos() error( MetaHeadersFrame) checkValid()( MetaHeadersFrame) invalidate()(*MetaHeadersFrame) rfc9218Priority(priorityAware bool) (p PriorityParam, priorityAwareAfter, hasIntermediary bool)( MetaHeadersFrame) writeDebug(buf *bytes.Buffer)
MetaHeadersFrame : Frame
MetaHeadersFrame : expvar.Var
MetaHeadersFrame : fmt.Stringer
MetaHeadersFrame : headersEnder
MetaHeadersFrame : headersOrContinuation
MetaHeadersFrame : streamEnder
MetaHeadersFrame : context.stringer
MetaHeadersFrame : golang.org/x/net/http2.headersEnder
MetaHeadersFrame : golang.org/x/net/http2.headersOrContinuation
MetaHeadersFrame : golang.org/x/net/http2.streamEnder
MetaHeadersFrame : runtime.stringer
OpenStreamOptions specifies extra options for WriteScheduler.OpenStream. PusherID is zero if the stream was initiated by the client. Otherwise,
PusherID names the stream that pushed the newly opened stream. priority is used to set the priority of the newly opened stream.
func WriteScheduler.OpenStream(streamID uint32, options OpenStreamOptions)
A PingFrame is a mechanism for measuring a minimal round trip time
from the sender, as well as determining whether an idle connection
is still functional.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.7Data[8]byteFrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). // caller can access []byte fields in the Frame Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.(*PingFrame) IsAck() bool( PingFrame) String() string(*PingFrame) checkValid()(*PingFrame) invalidate()( PingFrame) writeDebug(buf *bytes.Buffer)
*PingFrame : Frame
PingFrame : expvar.Var
PingFrame : fmt.Stringer
PingFrame : context.stringer
PingFrame : runtime.stringer
A PriorityFrame specifies the sender-advised priority of a stream.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.3FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame).PriorityParamPriorityParam Exclusive is whether the dependency is exclusive. StreamDep is a 31-bit stream identifier for the
stream that this stream depends on. Zero means no
dependency. Weight is the stream's zero-indexed weight. It should be
set together with StreamDep, or neither should be set. Per
the spec, "Add one to the value to obtain a weight between
1 and 256." // caller can access []byte fields in the Frame "The incremental (i) parameter value is Boolean (see Section 3.3.6 of
[STRUCTURED-FIELDS]). It indicates if an HTTP response can be processed
incrementally, i.e., provide some meaningful output as chunks of the
response arrive."
We use uint8 (i.e. 0 is false, 1 is true) instead of bool so we can
avoid unnecessary type conversions and because either type takes 1 byte. "The urgency (u) parameter value is Integer (see Section 3.3.1 of
[STRUCTURED-FIELDS]), between 0 and 7 inclusive, in descending order of
priority. The default is 3." Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.( PriorityFrame) IsZero() bool( PriorityFrame) String() string(*PriorityFrame) checkValid()(*PriorityFrame) invalidate()( PriorityFrame) writeDebug(buf *bytes.Buffer)
*PriorityFrame : Frame
PriorityFrame : expvar.Var
PriorityFrame : fmt.Stringer
PriorityFrame : context.stringer
PriorityFrame : encoding/json/v2.isZeroer
PriorityFrame : runtime.stringer
PriorityParam are the stream prioritization parameters. Exclusive is whether the dependency is exclusive. StreamDep is a 31-bit stream identifier for the
stream that this stream depends on. Zero means no
dependency. Weight is the stream's zero-indexed weight. It should be
set together with StreamDep, or neither should be set. Per
the spec, "Add one to the value to obtain a weight between
1 and 256." "The incremental (i) parameter value is Boolean (see Section 3.3.6 of
[STRUCTURED-FIELDS]). It indicates if an HTTP response can be processed
incrementally, i.e., provide some meaningful output as chunks of the
response arrive."
We use uint8 (i.e. 0 is false, 1 is true) instead of bool so we can
avoid unnecessary type conversions and because either type takes 1 byte. "The urgency (u) parameter value is Integer (see Section 3.3.1 of
[STRUCTURED-FIELDS]), between 0 and 7 inclusive, in descending order of
priority. The default is 3."( PriorityParam) IsZero() bool
PriorityParam : encoding/json/v2.isZeroer
func defaultRFC9218Priority(canUseDefault bool) PriorityParam
func parseRFC9218Priority(s string, canUseDefault bool) (p PriorityParam, ok bool)
func (*MetaHeadersFrame).rfc9218Priority(priorityAware bool) (p PriorityParam, priorityAwareAfter, hasIntermediary bool)
func (*Framer).WritePriority(streamID uint32, p PriorityParam) error
func WriteScheduler.AdjustStream(streamID uint32, priority PriorityParam)
PriorityUpdateFrame is a PRIORITY_UPDATE frame as described in
https://www.rfc-editor.org/rfc/rfc9218.html#name-the-priority_update-frame.FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame).PrioritizedStreamIDuint32Prioritystring // caller can access []byte fields in the Frame Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.( PriorityUpdateFrame) String() string(*PriorityUpdateFrame) checkValid()(*PriorityUpdateFrame) invalidate()( PriorityUpdateFrame) writeDebug(buf *bytes.Buffer)
*PriorityUpdateFrame : Frame
PriorityUpdateFrame : expvar.Var
PriorityUpdateFrame : fmt.Stringer
PriorityUpdateFrame : context.stringer
PriorityUpdateFrame : runtime.stringer
A PushPromiseFrame is used to initiate a server stream.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.6FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame).PromiseIDuint32 // caller can access []byte fields in the Frame // not owned Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.(*PushPromiseFrame) HeaderBlockFragment() []byte(*PushPromiseFrame) HeadersEnded() bool( PushPromiseFrame) String() string(*PushPromiseFrame) checkValid()(*PushPromiseFrame) invalidate()( PushPromiseFrame) writeDebug(buf *bytes.Buffer)
*PushPromiseFrame : Frame
PushPromiseFrame : expvar.Var
PushPromiseFrame : fmt.Stringer
*PushPromiseFrame : headersEnder
*PushPromiseFrame : headersOrContinuation
PushPromiseFrame : context.stringer
*PushPromiseFrame : golang.org/x/net/http2.headersEnder
*PushPromiseFrame : golang.org/x/net/http2.headersOrContinuation
PushPromiseFrame : runtime.stringer
PushPromiseParam are the parameters for writing a PUSH_PROMISE frame. BlockFragment is part (or all) of a Header Block. EndHeaders indicates that this frame contains an entire
header block and is not followed by any
CONTINUATION frames. PadLength is the optional number of bytes of zeros to add
to this frame. PromiseID is the required Stream ID which this
Push Promises StreamID is the required Stream ID to initiate.
func (*Framer).WritePushPromise(p PushPromiseParam) error
RoundTripOpt are options for the Transport.RoundTripOpt method. OnlyCachedConn controls whether RoundTripOpt may
create a new TCP connection. If set true and
no cached connection is available, RoundTripOpt
will return ErrNoCachedConn.
func (*Transport).RoundTripOpt(req *ClientRequest, opt RoundTripOpt) (*ClientResponse, error)
A RSTStreamFrame allows for abnormal termination of a stream.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.4ErrCodeErrCodeFrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). // caller can access []byte fields in the Frame Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.( RSTStreamFrame) String() string(*RSTStreamFrame) checkValid()(*RSTStreamFrame) invalidate()( RSTStreamFrame) writeDebug(buf *bytes.Buffer)
*RSTStreamFrame : Frame
RSTStreamFrame : expvar.Var
RSTStreamFrame : fmt.Stringer
RSTStreamFrame : context.stringer
RSTStreamFrame : runtime.stringer
ServeConnOpts are options for the Server.ServeConn method. BaseConfig optionally sets the base configuration
for values. If nil, defaults are used. Context is the base context to use.
If nil, context.Background is used. Handler specifies which handler to use for processing
requests. If nil, BaseConfig.Handler is used. If BaseConfig
or BaseConfig.Handler is nil, http.DefaultServeMux is used. SawClientPreface is set if the HTTP/2 connection preface
has already been read from the connection. Settings is the decoded contents of the HTTP2-Settings header
in an h2c upgrade request.UpgradeRequest*ServerRequest(*ServeConnOpts) context() context.Context
func (*Server).ServeConn(c net.Conn, opts *ServeConnOpts)
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func())
func (*Server).serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverConn))
Server is an HTTP/2 server.activeConnsmap[*serverConn]struct{} Pool of error channels. This is per-Server rather than global
because channels can't be reused across synctest bubbles.musync.Mutex(*Server) Configure(conf ServerConfig, tcfg *tls.Config) error(*Server) GracefulShutdown() ServeConn serves HTTP/2 requests on the provided connection and
blocks until the connection is no longer readable.
ServeConn starts speaking HTTP/2 assuming that c has not had any
reads or writes. It writes its initial settings frame and expects
to be able to read the preface and settings frame from the
client. If c has a ConnectionState method like a *tls.Conn, the
ConnectionState is used to verify the TLS ciphersuite and to set
the Request.TLS field in Handlers.
ServeConn does not support h2c by itself. Any h2c support must be
implemented in terms of providing a suitably-behaving net.Conn.
The opts parameter is optional. If nil, default values are used.(*Server) getErrChan() chan error(*Server) putErrChan(ch chan error)(*Server) registerConn(sc *serverConn)(*Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverConn))(*Server) startGracefulShutdown()(*Server) unregisterConn(sc *serverConn)
Setting is a setting parameter: which setting it is, and its value. ID is which setting is being set.
See https://httpwg.org/specs/rfc7540.html#SettingFormat Val is the value.( Setting) String() string Valid reports whether the setting is valid.
Setting : expvar.Var
Setting : fmt.Stringer
Setting : context.stringer
Setting : runtime.stringer
func (*SettingsFrame).Setting(i int) Setting
func (*Framer).WriteSettings(settings ...Setting) error
A SettingsFrame conveys configuration parameters that affect how
endpoints communicate, such as preferences and constraints on peer
behavior.
See https://httpwg.org/specs/rfc7540.html#SETTINGSFrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). // caller can access []byte fields in the Framep[]byte ForeachSetting runs fn for each setting.
It stops and returns the first error. HasDuplicates reports whether f contains any duplicate setting IDs. Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.(*SettingsFrame) IsAck() bool(*SettingsFrame) NumSettings() int Setting returns the setting from the frame at the given 0-based index.
The index must be >= 0 and less than f.NumSettings().( SettingsFrame) String() string(*SettingsFrame) Value(id SettingID) (v uint32, ok bool)(*SettingsFrame) checkValid()(*SettingsFrame) invalidate()( SettingsFrame) writeDebug(buf *bytes.Buffer)
*SettingsFrame : Frame
SettingsFrame : expvar.Var
SettingsFrame : fmt.Stringer
SettingsFrame : context.stringer
SettingsFrame : runtime.stringer
An UnknownFrame is the frame type returned when the frame type is unknown
or no specific frame type parser exists.FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). // caller can access []byte fields in the Framep[]byte Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface. Payload returns the frame's payload (after the header). It is not
valid to call this method after a subsequent call to
Framer.ReadFrame, nor is it valid to retain the returned slice.
The memory is owned by the Framer and is invalidated when the next
frame is read.( UnknownFrame) String() string(*UnknownFrame) checkValid()(*UnknownFrame) invalidate()( UnknownFrame) writeDebug(buf *bytes.Buffer)
*UnknownFrame : Frame
UnknownFrame : expvar.Var
UnknownFrame : fmt.Stringer
UnknownFrame : context.stringer
UnknownFrame : runtime.stringer
A WindowUpdateFrame is used to implement flow control.
See https://httpwg.org/specs/rfc7540.html#rfc.section.6.9FrameHeaderFrameHeader Flags are the 1 byte of 8 potential bit flags per frame.
They are specific to the frame type. Length is the length of the frame, not including the 9 byte header.
The maximum size is one byte less than 16MB (uint24), but only
frames up to 16KB are allowed without peer agreement. StreamID is which stream this frame is for. Certain frames
are not stream-specific, in which case this field is 0. Type is the 1 byte frame type. There are ten standard frame
types, but extension frame types may be written by WriteRawFrame
and will be returned by ReadFrame (as UnknownFrame). // never read with high bit set // caller can access []byte fields in the Frame Header returns h. It exists so FrameHeaders can be embedded in other
specific frame types and implement the Frame interface.( WindowUpdateFrame) String() string(*WindowUpdateFrame) checkValid()(*WindowUpdateFrame) invalidate()( WindowUpdateFrame) writeDebug(buf *bytes.Buffer)
*WindowUpdateFrame : Frame
WindowUpdateFrame : expvar.Var
WindowUpdateFrame : fmt.Stringer
WindowUpdateFrame : context.stringer
WindowUpdateFrame : runtime.stringer
WriteScheduler is the interface implemented by HTTP/2 write schedulers.
Methods are never called concurrently. AdjustStream adjusts the priority of the given stream. This may be called
on a stream that has not yet been opened or has been closed. Note that
RFC 7540 allows PRIORITY frames to be sent on streams in any state. See:
https://tools.ietf.org/html/rfc7540#section-5.1 CloseStream closes a stream in the write scheduler. Any frames queued on
this stream should be discarded. It is illegal to call this on a stream
that is not open -- the call may panic. OpenStream opens a new stream in the write scheduler.
It is illegal to call this with streamID=0 or with a streamID that is
already open -- the call may panic. Pop dequeues the next frame to write. Returns false if no frames can
be written. Frames with a given wr.StreamID() are Pop'd in the same
order they are Push'd, except RST_STREAM frames. No frames should be
discarded except by CloseStream. Push queues a frame in the scheduler. In most cases, this will not be
called with wr.StreamID()!=0 unless that stream is currently open. The one
exception is RST_STREAM frames, which may be sent on idle or closed streams.
*priorityWriteSchedulerRFC9218
*roundRobinWriteScheduler
func newPriorityWriteSchedulerRFC9218() WriteScheduler
func newRoundRobinWriteScheduler() WriteScheduler
A bodyReadMsg tells the server loop that the http.Handler read n
bytes of the DATA from the client on the given stream.nintst*stream
bufferedWriter is a buffered writer that writes to w.
Its buffered writer is lazily allocated as needed, to minimize
idle memory usage with many connections. // non-nil when data is buffered // immutable, WriteByteTimeout // immutablewerrerror(*bufferedWriter) Available() int(*bufferedWriter) Flush() error(*bufferedWriter) Write(p []byte) (n int, err error)
*bufferedWriter : internal/bisect.Writer
*bufferedWriter : io.Writer
*bufferedWriter : crypto/tls.transcriptHash
func newBufferedWriter(conn net.Conn, timeout time.Duration) *bufferedWriter
// non-nil when data is buffered // immutable, WriteByteTimeout // immutablewerrerror(*bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error)
*bufferedWriterTimeoutWriter : internal/bisect.Writer
*bufferedWriterTimeoutWriter : io.Writer
*bufferedWriterTimeoutWriter : crypto/tls.transcriptHash
TODO: use singleflight for dialing and addConnCalls? // in-flight addConnIfNeeded calls TODO: add support for sharing conns based on cert names
(e.g. share conn for googleapis.com and appspot.com) // key is host:port // currently in-flight dialskeysmap[*ClientConn][]string // TODO: maybe switch to RWMutext*Transport(*clientConnPool) GetClientConn(req *ClientRequest, addr string) (*ClientConn, error)(*clientConnPool) MarkDead(cc *ClientConn) addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
already exist. It coalesces concurrent calls with the same key.
This is used by the http1 Transport code when it creates a new connection. Because
the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
the protocol), it can get into a situation where it has multiple TLS connections.
This code decides which ones live or die.
The return value used is whether c was used.
c is never closed. p.mu must be held(*clientConnPool) closeIdleConnections()(*clientConnPool) getClientConn(req *ClientRequest, addr string, dialOnMiss bool) (*ClientConn, error) requires p.mu is held.
clientStream is the state for a single HTTP/2 stream. One of these
is created for each Transport.RoundTrip call.IDuint32 // closed to signal stream should end immediately // set if abort is closedabortOncesync.Once // buffered pipe with the flow-controlled response payload // -1 means unknown; owned by transportResponseBody.Readcc*ClientConn Fields of Request that we may access even after the response body is closed. // closed after the stream is in the closed state owned by clientConnReadLoop: // got the first response byte // guarded by cc.mu // guarded by cc.muisHeadbool // buffered; written to if a 100 is received // got first MetaHeadersFrame (actual headers) // got optional second MetaHeadersFrame (trailers) // closed when the peer sends an END_STREAM flag // read loop reset the stream // peer sent an END_STREAM flag // sticky read error; owned by transportResponseBody.ReadreqBodyio.ReadCloser // guarded by cc.mu; non-nil on Close, closed when done // -1 means unknownreqCancel<-chan struct{}requestedGzipbool // set if respHeaderRecv is closed // client's Response.Trailer // closed when headers are received owned by writeRequest: // sent an END_STREAM flag to the peersentHeadersboolstaticRespClientResponse // total size of 1xx headers seen // or nil // accumulated trailers(*clientStream) abortRequestBodyWrite()(*clientStream) abortStream(err error)(*clientStream) abortStreamLocked(err error) awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow
control tokens from the server.
It returns either the non-zero number of tokens taken or an error
if the stream is dead. cleanupWriteRequest performs post-request tasks.
If err (the result of writeRequest) is non-nil and the stream is not closed,
cleanupWriteRequest will send a reset to the peer.(*clientStream) closeReqBodyLocked()(*clientStream) copyTrailers() doRequest runs for the duration of the request lifetime.
It sends the request and performs post-request cleanup (closing Request.Body, etc.).(*clientStream) encodeAndWriteHeaders(req *ClientRequest) error frameScratchBufferLen returns the length of a buffer to use for
outgoing request bodies to read/write to/from.
It returns max(1, min(peer's advertised max frame size,
Request.ContentLength+1, 512KB)). get1xxTraceFunc returns the value of request's httptrace.ClientTrace.Got1xxResponse func,
if any. It returns nil if not set or if the Go version is too old. writeRequest sends a request.
It returns nil after the request is written, the response read,
and the request stream is half-closed by the peer.
It returns non-nil if the request ends otherwise.
If the returned error is StreamError, the error Code may be used in resetting the stream.(*clientStream) writeRequestBody(req *ClientRequest) (err error)
func (*ClientConn).addStreamLocked(cs *clientStream)
func (*ClientConn).awaitOpenSlotForStreamLocked(cs *clientStream) error
A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed). Close marks the closeWaiter as closed and unblocks any waiters. Init makes a closeWaiter usable.
It exists because so a closeWaiter value can be placed inside a
larger struct and have the Mutex and Cond's memory in the same
allocation. Wait waits for the closeWaiter to become closed.
connError represents an HTTP/2 ConnectionError error code, along
with a string (for debugging) explaining why.
Errors of this type are only returned by the frame parser functions
and converted into ConnectionError(Code), after stashing away
the Reason into the Framer's errDetail field, accessible via
the (*Framer).ErrorDetail method. // the ConnectionError error code // additional reason( connError) Error() string
connError : error
connOutflow is connection-level outbound flow control. // set when a flow control error is encountered // SETTINGS_INITIAL_WINDOW_SIZE, changes with settings updates // connection-level flow control window(*connOutflow) add(n int32) bool(*connOutflow) changeInitialWindowSize(size int64) bool(*connOutflow) init()
dataBuffer is an io.ReadWriter backed by a list of data chunks.
Each dataBuffer is used to read DATA frames on a single stream.
The buffer is divided into chunks so the server can limit the
total memory used by a single connection without limiting the
request body size on any single stream.chunks[][]byte // we expect at least this many bytes in future Write calls (ignored if <= 0) // next byte to read is chunks[0][r] // total buffered bytes // next byte to write is chunks[len(chunks)-1][w] Len returns the number of bytes of the unread portion of the buffer. Read copies bytes from the buffer into p.
It is an error to read when no data is available. Write appends p to the buffer.(*dataBuffer) bytesFromFirstChunk() []byte(*dataBuffer) lastChunkOrAlloc(want int64) []byte
*dataBuffer : internal/bisect.Writer
*dataBuffer : io.Reader
*dataBuffer : io.ReadWriter
*dataBuffer : io.Writer
*dataBuffer : pipeBuffer
*dataBuffer : crypto/tls.transcriptHash
*dataBuffer : golang.org/x/net/http2.pipeBuffer
dialCall is an in-flight Transport dial call to a host. the context associated with the request
that created this dialCall // closed when done // valid after done is closedp*clientConnPool // valid after done is closed run in its own goroutine.
func shouldRetryDial(call *dialCall, req *ClientRequest) bool
a frameParser parses a frame given its FrameHeader and payload
bytes. The length of payload will always equal fh.Length (which
might be 0).
func typeFrameParser(t FrameType) frameParser
frameWriteResult is the message passed from writeFrameAsync to the serve goroutine. // result of the writeFrame call // what was written (or attempted)
6.9.1 The Flow Control Window
"If a sender receives a WINDOW_UPDATE that causes a flow control
window to exceed this maximum it MUST terminate either the stream
or the connection, as appropriate. For streams, [...]; for the
connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."( goAwayFlowError) Error() string
goAwayFlowError : error
gzipReader wraps a response body so it can lazily
get gzip.Reader from the pool on the first call to Read.
After Close is called it puts gzip.Reader to the pool immediately
if there is no Read in progress or later when Read completes. // underlying Response.Body // guards zr and zerr // sticky gzip reader init error or sentinel value to detect concurrent read and read after close // stores gzip reader from the pool between reads(*gzipReader) Close() error(*gzipReader) Read(p []byte) (n int, err error) acquire returns a gzip.Reader for reading response body.
The reader must be released after use. close returns the gzip.Reader to the pool immediately or
signals release to do so after Read completes. release returns the gzip.Reader to the pool if Close was called during Read.
*gzipReader : io.Closer
*gzipReader : io.ReadCloser
*gzipReader : io.Reader
incomparable is a zero-width, non-comparable type. Adding it to a struct
makes that struct also non-comparable, and generally doesn't add
any size (as long as it's first).
inflow accounts for an inbound flow control window.
It tracks both the latest window sent to the peer (used for enforcement)
and the accumulated unsent window.availint32unsentint32 add adds n bytes to the window, with a maximum window size of max,
indicating that the peer can now send us more data.
For example, the user read from a {Request,Response} body and consumed
some of the buffered data, so the peer can now send more.
It returns the number of bytes to send in a WINDOW_UPDATE frame to the peer.
Window updates are accumulated and sent when the unsent capacity
is at least inflowMinRefresh or will at least double the peer's available window. init sets the initial window. take attempts to take n bytes from the peer's flow control window.
It reports whether the window has available capacity.
func takeInflows(f1, f2 *inflow, n uint32) bool
noCachedConnError is the concrete type of ErrNoCachedConn, which
needs to be detected by net/http regardless of whether it's its
bundled version (in h2_bundle.go with a rewritten type name) or
from a user's x/net/http2. As such, as it has a unique method name
(IsHTTP2NoCachedConnError) that net/http sniffs for via func
isNoCachedConnError.( noCachedConnError) Error() string( noCachedConnError) IsHTTP2NoCachedConnError()
noCachedConnError : error
noDialClientConnPool is an implementation of http2.ClientConnPool
which never dials. We let the HTTP/1.1 client dial and use its TLS
connection instead.clientConnPool*clientConnPool // in-flight addConnIfNeeded calls TODO: add support for sharing conns based on cert names
(e.g. share conn for googleapis.com and appspot.com) // key is host:port // currently in-flight dialsclientConnPool.keysmap[*ClientConn][]string // TODO: maybe switch to RWMutexclientConnPool.t*Transport( noDialClientConnPool) GetClientConn(req *ClientRequest, addr string) (*ClientConn, error)( noDialClientConnPool) MarkDead(cc *ClientConn) addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
already exist. It coalesces concurrent calls with the same key.
This is used by the http1 Transport code when it creates a new connection. Because
the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
the protocol), it can get into a situation where it has multiple TLS connections.
This code decides which ones live or die.
The return value used is whether c was used.
c is never closed. p.mu must be held( noDialClientConnPool) closeIdleConnections()( noDialClientConnPool) getClientConn(req *ClientRequest, addr string, dialOnMiss bool) (*ClientConn, error) requires p.mu is held.
outflow is the stream-level outbound flow control window's size. conn points to the shared connection-level outflow that is
shared by all streams on that conn. delta is the difference between the stream's flow control window and
the connection's initial window size (conn.initial).
Another view is that delta is the number of flow control bytes provided to this
stream in WINDOW_UPDATE frames, less the number of bytes sent on the stream. add adds n bytes (positive or negative) to the flow control window.
It returns false if the sum would exceed 2^31-1.(*outflow) available() (int32, bool)(*outflow) take(n int32)
pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
io.Pipe except there are no PipeReader/PipeWriter halves, and the
underlying buffer is an interface. (io.Pipe is always unbuffered) // nil when done reading // immediate read error (caller doesn't see rest of b) // c.L lazily initialized to &p.mu // closed on error // read error once empty. non-nil means closed.musync.Mutex // optional code to run in Read before error // bytes unread when done BreakWithError causes the next Read (waking up a current blocked
Read if needed) to return the provided err immediately, without
waiting for unread data. CloseWithError causes the next Read (waking up a current blocked
Read if needed) to return the provided err after all data has been
read.
The error must be non-nil. Done returns a channel which is closed if and when this pipe is closed
with CloseWithError. Err returns the error (if any) first set by BreakWithError or CloseWithError.(*pipe) Len() int Read waits until data is available and copies bytes
from the buffer into p. Write copies bytes from p into the buffer and wakes a reader.
It is an error to write more data than the buffer can hold. requires p.mu be held.(*pipe) closeWithError(dst *error, err error, fn func()) closeWithErrorAndCode is like CloseWithError but also sets some code to run
in the caller's goroutine before returning the error. setBuffer initializes the pipe buffer.
It has no effect if the pipe is already closed.
*pipe : internal/bisect.Writer
*pipe : io.Reader
*pipe : io.ReadWriter
*pipe : io.Writer
*pipe : pipeBuffer
*pipe : crypto/tls.transcriptHash
*pipe : golang.org/x/net/http2.pipeBuffer
control contains control frames (SETTINGS, PING, etc.). heads contain the head of a circular list of streams.
We put these heads within a nested array that represents urgency and
incremental, as defined in
https://www.rfc-editor.org/rfc/rfc9218.html#name-priority-parameters.
8 represents u=0 up to u=7, and 2 represents i=false and i=true. prioritizeIncremental is used to determine whether we should prioritize
incremental streams or not, when urgency is the same in a given Pop()
call. priorityUpdateBuf is used to buffer the most recent PRIORITY_UPDATE we
receive per https://www.rfc-editor.org/rfc/rfc9218.html#name-the-priority_update-frame. queuePool are empty queues for reuse. streams contains a mapping between each stream ID and their metadata, so
we can quickly locate them when needing to, for example, adjust their
priority.(*priorityWriteSchedulerRFC9218) AdjustStream(streamID uint32, priority PriorityParam)(*priorityWriteSchedulerRFC9218) CloseStream(streamID uint32)(*priorityWriteSchedulerRFC9218) OpenStream(streamID uint32, opt OpenStreamOptions)(*priorityWriteSchedulerRFC9218) Pop() (FrameWriteRequest, bool)(*priorityWriteSchedulerRFC9218) Push(wr FrameWriteRequest)
*priorityWriteSchedulerRFC9218 : WriteScheduler
errerror // valid until readMore is called readMore should be called once the consumer no longer needs or
retains f. After readMore, f is invalid and more frames can be
read.
requestBody is the Handler's Request.Body type.
Read and Close may be called concurrently. // for use by Close onlyconn*serverConn // need to send a 100-continue // non-nil if we have an HTTP entity message body // for use by Read onlystream*stream(*requestBody) Close() error(*requestBody) Read(p []byte) (n int, err error)
*requestBody : io.Closer
*requestBody : io.ReadCloser
*requestBody : io.Reader
responseWriter is the http.ResponseWriter implementation. It's
intentionally small (1 pointer wide) to minimize garbage. The
responseWriterState pointer inside is zeroed at the end of a
request (in handlerDone) and calls on the responseWriter thereafter
simply crash (caller's mistake), but the much larger responseWriterState
and buffers are reused between multiple requests.rws*responseWriterState(*responseWriter) CloseNotify() <-chan bool(*responseWriter) EnableFullDuplex() error(*responseWriter) Flush()(*responseWriter) FlushError() error(*responseWriter) Header() Header(*responseWriter) Push(target, method string, header Header) error(*responseWriter) SetReadDeadline(deadline time.Time) error(*responseWriter) SetWriteDeadline(deadline time.Time) error The Life Of A Write is like this:
* Handler calls w.Write or w.WriteString ->
* -> rws.bw (*bufio.Writer) ->
* (Handler might call Flush)
* -> chunkWriter{rws}
* -> responseWriterState.writeChunk(p []byte)
* -> responseWriterState.writeChunk (most of the magic; see comment there)(*responseWriter) WriteHeader(code int)(*responseWriter) WriteString(s string) (n int, err error)(*responseWriter) handlerDone() either dataB or dataS is non-zero.
*responseWriter : net/http.CloseNotifier
*responseWriter : net/http.Flusher
*responseWriter : internal/bisect.Writer
*responseWriter : io.StringWriter
*responseWriter : io.Writer
*responseWriter : crypto/tls.transcriptHash
*responseWriter : golang.org/x/net/http2.stringWriter
*responseWriter : testing.stringWriter
TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc // writing to a chunkWriter{this *responseWriterState} // nil until first used // guards closeNotifierChconn*serverConn // handler has finished mutated by http.Handler goroutine: // nil until calledreqServerRequest // non-zero if handler set a Content-Length header // have we sent the header frame? // snapshot of handlerHeader at WriteHeader time // status code passed to WriteHeader immutable within a request: // set in writeChunkwroteBytesint64 // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet. declareTrailer is called for each Trailer header when the
response header is written. It notes that a header will need to be
written in the trailers at the end of the response.(*responseWriterState) hasNonemptyTrailers() bool(*responseWriterState) hasTrailers() bool promoteUndeclaredTrailers permits http.Handlers to set trailers
after the header has already been flushed. Because the Go
ResponseWriter interface has no way to set Trailers (only the
Header), and because we didn't want to expand the ResponseWriter
interface, and because nobody used trailers, and because RFC 7230
says you SHOULD (but not must) predeclare any trailers in the
header, the official ResponseWriter rules said trailers in Go must
be predeclared, and then we reuse the same ResponseWriter.Header()
map to mean both Headers and Trailers. When it's time to write the
Trailers, we pick out the fields of Headers that were declared as
trailers. That worked for a while, until we found the first major
user of Trailers in the wild: gRPC (using them only over http2),
and gRPC libraries permit setting trailers mid-stream without
predeclaring them. So: change of plans. We still permit the old
way, but we also permit this hack: if a Header() key begins with
"Trailer:", the suffix of that key is a Trailer. Because ':' is an
invalid token byte anyway, there is no ambiguity. (And it's already
filtered out) It's mildly hacky, but not terrible.
This method runs after the Handler is done and promotes any Header
fields to be trailers. writeChunk writes chunks from the bufio.Writer. But because
bufio.Writer may bypass its chunking, sometimes p may be
arbitrarily large.
writeChunk is also responsible (on the first chunk) for sending the
HEADER response.(*responseWriterState) writeHeader(code int)
control contains control frames (SETTINGS, PING, etc.). stream queues are stored in a circular linked list.
head is the next stream to write, or nil if there are no streams open. pool of empty queues for reuse. streams maps stream ID to a queue.(*roundRobinWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam)(*roundRobinWriteScheduler) CloseStream(streamID uint32)(*roundRobinWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions)(*roundRobinWriteScheduler) Pop() (FrameWriteRequest, bool)(*roundRobinWriteScheduler) Push(wr FrameWriteRequest)
*roundRobinWriteScheduler : WriteScheduler
// our SETTINGS_MAX_CONCURRENT_STREAMS advertised the clientbaseCtxcontext.Context // from handlers -> serve // writing to conn // http2-lower-case -> Go-Canonical-Case // canonHeader keys size in bytes // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)connnet.ConncountErrorFuncfunc(errType string) // number of open streams initiated by the client // number of running handler goroutines // number of open streams initiated by server push // closed when serverConn.serve ends // latest SETTINGS_HEADER_TABLE_SIZE // smallest SETTINGS_HEADER_TABLE_SIZE since the last apply // conn-wide (not stream-specific) outbound flow controlframer*FramergoAwayCodeErrCodehandlerHandler Used for RFC 9218 prioritization. // connection is done via an intermediary / proxy Owned by the writeFrameAsync goroutine:hpackEncoder*hpack.EncoderhsServerConfig // nil if unused // whether we're in the scheduleFrameWrite loop // we've started to or sent GOAWAY // conn-wide inbound flow controlinitialStreamRecvWindowSizeint32 // max ever seen from client (odd), or 0 if there have been no client requestsmaxFrameSizeint32 // ID of the last push promise (even), or 0 if there have been no pushes // we need to schedule a GOAWAY frame writeneedToSendSettingsAckbool // last frame write wasn't a flush // zero means unknown (default) // peer changed SETTINGS_HEADER_TABLE_SIZE; apply to hpackEncoder before the next frame writepingSentboolpingTimeouttime.Duration // the client has sent priority signal, meaning that it is aware of it.pushEnabledbool // control frames in the writeSched queue // written by serverConn.readFramesreadIdleTimeouttime.Duration // nil if unusedremoteAddrStrstring // preface has already been read, used in h2c upgrade // got the initial SETTINGS frame after the prefacesentPingData[8]byte Everything following is owned by the serve loop; use serveG.check(): // used to verify funcs are on serve() // misc messages & code to send to / run on the serve loop Used by startGracefulShutdown. // nil until used Immutable:streamsmap[uint32]*stream // shared by all handlers, like net/http // how many SETTINGS have we sent without ACKs?unstartedHandlers[]unstartedHandler // from handlers -> servewriteSchedWriteScheduler // started writing a frame (on serve goroutine or separate) // started a frame on its own goroutine but haven't heard back on wroteFrameCh // from writeFrameAsync -> serve, tickles more frame writes(*serverConn) CloseConn() error(*serverConn) Flush() error(*serverConn) Framer() *Framer(*serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)(*serverConn) canonicalHeader(v string) string(*serverConn) checkPriority(streamID uint32, p PriorityParam) error(*serverConn) closeAllStreamsOnConnClose()(*serverConn) closeStream(st *stream, err error)(*serverConn) condlogf(err error, format string, args ...any)(*serverConn) countError(name string, err error) error(*serverConn) curOpenStreams() uint32(*serverConn) goAway(code ErrCode)(*serverConn) handlePingTimer(lastFrameReadTime time.Time)(*serverConn) handlerDone()(*serverConn) logf(format string, args ...any)(*serverConn) maxHeaderListSize() uint32(*serverConn) newResponseWriter(st *stream) *responseWriter(*serverConn) newStream(id, pusherID uint32, state streamState, priority PriorityParam) *stream(*serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *ServerRequest, error)(*serverConn) newWriterAndRequestNoBody(st *stream, rp httpcommon.ServerRequestParam) (*responseWriter, *ServerRequest, error)(*serverConn) noteBodyRead(st *stream, n int) called from handler goroutines.
Notes that the handler for the given stream ID read n bytes of its body
and schedules flow control tokens to be sent.(*serverConn) notePanic()(*serverConn) onIdleTimer()(*serverConn) onReadIdleTimer()(*serverConn) onSettingsTimer()(*serverConn) onShutdownTimer()(*serverConn) processData(f *DataFrame) error(*serverConn) processFrame(f Frame) error processFrameFromReader processes the serve loop's read from readFrameCh from the
frame-reading goroutine.
processFrameFromReader returns whether the connection should be kept open.(*serverConn) processGoAway(f *GoAwayFrame) error(*serverConn) processHeaders(f *MetaHeadersFrame) error(*serverConn) processPing(f *PingFrame) error(*serverConn) processPriority(f *PriorityFrame) error(*serverConn) processPriorityUpdate(f *PriorityUpdateFrame) error(*serverConn) processResetStream(f *RSTStreamFrame) error(*serverConn) processSetting(s Setting) error(*serverConn) processSettingInitialWindowSize(val uint32) error(*serverConn) processSettings(f *SettingsFrame) error(*serverConn) processWindowUpdate(f *WindowUpdateFrame) error readFrames is the loop that reads incoming frames.
It takes care to only read one frame at a time, blocking until the
consumer is done with the frame.
It's run on its own goroutine. readPreface reads the ClientPreface greeting from the peer or
returns errPrefaceTimeout on timeout, or an error if the greeting
is invalid.(*serverConn) rejectConn(err ErrCode, debug string)(*serverConn) resetStream(se StreamError) Run on its own goroutine. scheduleFrameWrite tickles the frame writing scheduler.
If a frame is already being written, nothing happens. This will be called again
when the frame is done being written.
If a frame isn't being written and we need to send one, the best frame
to send is selected by writeSched.
If a frame isn't being written and there's nothing else to send, we
flush the write buffer. scheduleHandler starts a handler goroutine,
or schedules one to start as soon as an existing handler finishes.(*serverConn) sendServeMsg(msg any) st may be nil for conn-level st may be nil for conn-level(*serverConn) serve(conf Config) setConnState calls the net/http ConnState hook for this connection, if configured.
Note that the net/http package does StateNew and StateClosed for us.
There is currently no plan for StateHijacked or hijacking HTTP/2 connections.(*serverConn) shutDownIn(d time.Duration) startFrameWrite starts a goroutine to write wr (in a separate
goroutine since that might block on the network), and updates the
serve goroutine's state about the world, updated from info in wr. startGracefulShutdown gracefully shuts down a connection. This
sends GOAWAY with ErrCodeNo to tell the client we're gracefully
shutting down. The connection isn't closed until all current
streams are done.
startGracefulShutdown returns immediately; it does not wait until
the connection has shut down.(*serverConn) startGracefulShutdownInternal()(*serverConn) startPush(msg *startPushRequest)(*serverConn) state(streamID uint32) (streamState, *stream)(*serverConn) stopShutdownTimer()(*serverConn) upgradeRequest(req *ServerRequest)(*serverConn) vlogf(format string, args ...any) called from handler goroutines. writeDataFromHandler writes DATA response frames from a handler on
the given stream. writeFrame schedules a frame to write and sends it if there's nothing
already being written.
There is no pushback here (the serve goroutine never blocks). It's
the http.Handlers that block, waiting for their previous frames to
make it onto the wire
If you're not on the serve goroutine, use writeFrameFromHandler instead. writeFrameAsync runs in its own goroutine and writes a single frame
and then reports when it's done.
At most one goroutine can be running writeFrameAsync at a time per
serverConn. writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
if the connection has gone away.
This must not be run from the serve goroutine itself, else it might
deadlock writing to sc.wantWriteFrameCh (which is only mildly
buffered and is read by serve itself). If you're on the serve
goroutine, call writeFrame instead. called from handler goroutines.
h may be nil.(*serverConn) writeSchedIgnoresRFC7540() bool wroteFrame is called on the serve goroutine with the result of
whatever happened on writeFrameAsync.
*serverConn : writeContext
func (*Server).registerConn(sc *serverConn)
func (*Server).unregisterConn(sc *serverConn)
stream represents a stream. This is the minimal metadata needed by
the serve goroutine. Most of the actual stream state is owned by
the http.Handler's goroutine in the responseWriter. Because the
responseWriter's responseWriterState is recycled at the end of a
handler, this struct intentionally has no pointer to the
*responseWriter{,State} itself, as the Handler ending nils out the
responseWriter's state field. // non-nil if expecting DATA frames owned by serverConn's serve loop: // body bytes seen so farcancelCtxfunc() // set before cw is closedctxcontext.Context // closed wait stream transitions to closed state // or -1 if undeclared // limits writing from Handler to client // HEADER frame for trailers was seeniduint32 // what the client is allowed to POST/etc to us // nil if unusedreqBody*requestBody // handler's Request.Trailer // RST_STREAM queued for write; set by sc.resetStream immutable:statestreamState // accumulated trailers // nil if unused // whether we wrote headers (not status 100) copyTrailersToHandlerRequest is run in the Handler's goroutine in
its Request.Body.Read just before it gets io.EOF. endStream closes a Request.Body's pipe. It is called when a DATA
frame says a request body is over (or after trailers). isPushed reports whether the stream is server-initiated. onReadTimeout is run on its own goroutine (from time.AfterFunc)
when the stream's ReadTimeout has fired. onWriteTimeout is run on its own goroutine (from time.AfterFunc)
when the stream's WriteTimeout has fired.(*stream) processTrailerHeaders(f *MetaHeadersFrame) error
transportResponseBody is the concrete type of Transport.RoundTrip's
Response.Body. It is an io.ReadCloser.cs*clientStream( transportResponseBody) Close() error( transportResponseBody) Read(p []byte) (n int, err error)
transportResponseBody : io.Closer
transportResponseBody : io.ReadCloser
transportResponseBody : io.Reader
writeContext is the interface needed by the various frame writer
types below. All the writeFrame methods below are scheduled via the
frame writing scheduler (see writeScheduler in writesched.go).
This interface is implemented by *serverConn.
TODO: decide whether to a) use this in the client code (which didn't
end up using this yet, because it has a simpler design, not
currently implementing priorities), or b) delete this and
make the server code a bit more concrete.( writeContext) CloseConn() error( writeContext) Flush() error( writeContext) Framer() *Framer HeaderEncoder returns an HPACK encoder that writes to the
returned buffer.
*serverConn
func splitHeaderBlock(ctx writeContext, headerBlock []byte, fn func(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error) error
func StreamError.writeFrame(ctx writeContext) error
writePushPromise is a request to write a PUSH_PROMISE and 0+ CONTINUATION frames. Creates an ID for a pushed stream. This runs on serveG just before
the frame is written. The returned ID is copied to promisedID.hHeader // for :methodpromisedIDuint32 // pusher stream // for :scheme, :authority, :path(*writePushPromise) staysWithinBuffer(max int) bool(*writePushPromise) writeFrame(ctx writeContext) error(*writePushPromise) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error
*writePushPromise : writeFramer
writeQueue is used by implementations of WriteScheduler.
Each writeQueue contains a queue of FrameWriteRequests, meant to store all
FrameWriteRequests associated with a given stream. This is implemented as a
two-stage queue: currQueue[currPos:] and nextQueue. Removing an item is done
by incrementing currPos of currQueue. Adding an item is done by appending it
to the nextQueue. If currQueue is empty when trying to remove an item, we
can swap currQueue and nextQueue to remedy the situation.
This two-stage queue is analogous to the use of two lists in Okasaki's
purely functional queue but without the overhead of reversing the list when
swapping stages.
writeQueue also contains prev and next, this can be used by implementations
of WriteScheduler to construct data structures that represent the order of
writing between different streams (e.g. circular linked list).currPosintcurrQueue[]FrameWriteRequestnext*writeQueuenextQueue[]FrameWriteRequestprev*writeQueue consume consumes up to n bytes from q.s[0]. If the frame is
entirely consumed, it is removed from the queue. If the frame
is partially consumed, the frame is kept with the consumed
bytes removed. Returns true iff any bytes were consumed.(*writeQueue) empty() bool(*writeQueue) peek() *FrameWriteRequest(*writeQueue) push(wr FrameWriteRequest)(*writeQueue) shift() FrameWriteRequest
get returns an empty writeQueue. put inserts an unused writeQueue into the pool.
Return the first number n such that n*base >= 1<<64.
defaultRFC9218Priority determines what priority we should use as the default
value.
According to RFC 9218, by default, streams should be given an urgency of 3
and should be non-incremental. However, making streams non-incremental by
default would be a huge change to our historical behavior where we would
round-robin writes across streams. When streams are non-incremental, we
would process streams of the same urgency one-by-one to completion instead.
To avoid such a sudden change which might break some HTTP/2 users, this
function allows the caller to specify whether they can actually use the
default value as specified in RFC 9218. If not, this function will return a
priority value where streams are incremental by default instead: effectively
a round-robin between stream of the same urgency.
As an example, a server might not be able to use the RFC 9218 default value
when it's not sure that the client it is serving is aware of RFC 9218.
gzipPoolGet gets a gzip.Reader from the pool and resets it to read from r.
gzipPoolPut puts a gzip.Reader back into the pool.
h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
disabled. See comments on h1ServerShutdownChan above for why
the code is written this way.
isASCIIPrint returns whether s is ASCII and printable according to
https://tools.ietf.org/html/rfc20#section-4.2.
isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
References:
https://tools.ietf.org/html/rfc7540#appendix-A
Reject cipher suites from Appendix A.
"This list includes those cipher suites that do not
offer an ephemeral key exchange and those that are
based on the TLS null, stream or block cipher type"
isClosedConnError reports whether err is an error from use of a closed
network connection.
isConnectionCloseRequest reports whether req should use its own
connection for a single request and then close the connection.
isNoCachedConnError reports whether err is of type noCachedConnError
or its equivalent renamed type in net/http2's h2_bundle.go. Both types
may coexist in the same running program.
newRoundRobinWriteScheduler constructs a new write scheduler.
The round robin scheduler prioritizes control frames
like SETTINGS and PING over DATA frames.
When there are no control frames to send, it performs a round-robin
selection from the ready streams.
shouldRetryDial reports whether the current request should
retry dialing after the call finished unsuccessfully, for example
if the dial was canceled because of a context cancellation or
deadline expiry.
shouldRetryRequest is called by RoundTrip when a request fails to get
response headers. It is always called with a non-nil error.
It returns either a request to retry or an error if the request can't be replayed.
If the request is retried, it always clones the request (since requests
contain an unreusable clientStream).
splitHeaderBlock splits headerBlock into fragments so that each fragment fits
in a single frame, then calls fn for each fragment. firstFrag/lastFrag are true
for the first/last fragment, respectively.
takeInflows attempts to take n bytes from two inflows,
typically connection-level and stream-level flows.
It reports whether both windows have available capacity.
terminalReadFrameError reports whether err is an unrecoverable
error from ReadFrame and no other frames should be read.
validWireHeaderFieldName reports whether v is a valid header field
name (key). See httpguts.ValidHeaderName for the base rules.
Further, http2 says:
"Just as in HTTP/1.x, header field names are strings of ASCII
characters that are compared in a case-insensitive
fashion. However, header field names MUST be converted to
lowercase prior to their encoding in HTTP/2. "
writeEndsStream reports whether w writes a frame that will transition
the stream to a half-closed local state. This returns false for RST_STREAM,
which closes the entire stream (not just the local half).
writeWithByteTimeout writes to conn.
If more than timeout passes without any bytes being written to the connection,
the write fails.
Package-Level Variables (total 83, in which 14 are exported)
Variables defined in net/http and initialized by an init func in that package.
NoBody and LocalAddrContextKey have concrete types in net/http,
and therefore can't be moved into a common package without introducing
a dependency cycle.
Variables defined in net/http and initialized by an init func in that package.
NoBody and LocalAddrContextKey have concrete types in net/http,
and therefore can't be moved into a common package without introducing
a dependency cycle.
Seven bufPools manage different frame sizes. This helps to avoid scenarios where long-running
streaming requests using small frame sizes occupy large buffers initially allocated for prior
requests needing big buffers. The size ranges are as follows:
{0 KB, 16 KB], {16 KB, 32 KB], {32 KB, 64 KB], {64 KB, 128 KB], {128 KB, 256 KB],
{256 KB, 512 KB], {512 KB, infinity}
In practice, the maximum scratch buffer size should not exceed 512 KB due to
frameScratchBufferLen(maxFrameSize), thus the "infinity pool" should never be used.
It exists mainly as a safety measure, for potential future increases in max buffer size.
From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
Buffer chunks are allocated from a pool to reduce pressure on GC.
The maximum wasted space per dataBuffer is 2x the largest size class,
which happens when the dataBuffer has multiple chunks and there is
one unread byte in both the first and last chunks. We use a few size
classes to minimize overheads for servers that typically receive very
small request bodies.
TODO: Benchmark to determine if the pools are necessary. The GC may have
improved enough that we can instead allocate chunks like this:
make([]byte, max(16<<10, expectedBytesRemaining))
Setting DebugGoroutines to false during a test to disable goroutine debugging
results in race detector complaints when a test leaves goroutines running before
returning. Tests shouldn't do this, of course, but when they do it generally shows
up as infrequent, hard-to-debug flakes. (See #66519.)
Disable goroutine debugging during individual tests with an atomic bool.
(Note that it's safe to enable/disable debugging mid-test, so the actual race condition
here is harmless.)
Enabling extended CONNECT by causes browsers to attempt to use
WebSockets-over-HTTP/2. This results in problems when the server's websocket
package doesn't support extended CONNECT.
Disable extended CONNECT by default for now.
Issue #71128.
Global error channel pool used for uninitialized Servers.
We use a per-Server pool when possible to avoid using channels across synctest bubbles.
errFromPeer is a sentinel error value for StreamError.Cause to
indicate that the StreamError was sent from the peer over the wire
and wasn't locally generated in the Transport.
errHandlerPanicked is the error given to any callers blocked in a read from
Request.Body when the main goroutine panics. Since most handlers read in the
main ServeHTTP goroutine, this will show up rarely.
After sending GOAWAY with an error code (non-graceful shutdown), the
connection will close after goAwayTimeout.
If we close the connection immediately after sending GOAWAY, there may
be unsent data in our kernel receive buffer, which will cause the kernel
to send a TCP RST on close() instead of a FIN. This RST will abort the
connection immediately, whether or not the client had received the GOAWAY.
Ideally we should delay for at least 1 RTT + epsilon so the client has
a chance to read the GOAWAY and stop sending messages. Measuring RTT
is hard, so we approximate with 1 second. See golang.org/issue/18701.
This is a var so it can be shorter in tests, where all requests uses the
loopback interface making the expected RTT very small.
TODO: configurable?
constTimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT" // keep in sync with net/http
TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
that, if present, signals that the map entry is actually for
the response trailers, and not the response headers. The prefix
is stripped after the ServeHTTP call finishes and the values are
sent in the trailers.
This mechanism is intended only for trailers that are not known
prior to the headers being written. If the set of trailers is fixed
or known before the header is written, the normal Go trailers mechanism
is preferred:
https://golang.org/pkg/net/http/#ResponseWriter
https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
bufWriterPoolBufferSize is the size of bufio.Writer's
buffers created using bufWriterPool.
TODO: pick a less arbitrary value? this is a bit under
(3 x typical 1500 byte MTU) at least. Other than that,
not much thought went into it.
initialMaxConcurrentStreams is a connections maxConcurrentStreams until
it's received servers initial SETTINGS frame, which corresponds with the
spec's minimum recommended value.
maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
of the entries in the canonHeader cache.
This should be larger than the size of unique, uncommon header keys likely to
be sent by the peer, while not so high as to permit unreasonable memory usage
if the peer sends an unbounded number of unique header keys.
maxFlowWindow is the maximum size of a flow control window.
maxQueuedControlFrames is the maximum number of control frames like
SETTINGS, PING and RST_STREAM that will be queued for writing before
the connection is closed to prevent memory exhaustion attacks.
HTTP/2 stream states.
See http://tools.ietf.org/html/rfc7540#section-5.1.
For simplicity, the server code merges "reserved (local)" into
"half-closed (remote)". This is one less state transition to track.
The only downside is that we send PUSH_PROMISEs slightly less
liberally than allowable. More discussion here:
https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
"reserved (remote)" is omitted since the client code does not
support server push.
HTTP/2 stream states.
See http://tools.ietf.org/html/rfc7540#section-5.1.
For simplicity, the server code merges "reserved (local)" into
"half-closed (remote)". This is one less state transition to track.
The only downside is that we send PUSH_PROMISEs slightly less
liberally than allowable. More discussion here:
https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
"reserved (remote)" is omitted since the client code does not
support server push.
HTTP/2 stream states.
See http://tools.ietf.org/html/rfc7540#section-5.1.
For simplicity, the server code merges "reserved (local)" into
"half-closed (remote)". This is one less state transition to track.
The only downside is that we send PUSH_PROMISEs slightly less
liberally than allowable. More discussion here:
https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
"reserved (remote)" is omitted since the client code does not
support server push.
HTTP/2 stream states.
See http://tools.ietf.org/html/rfc7540#section-5.1.
For simplicity, the server code merges "reserved (local)" into
"half-closed (remote)". This is one less state transition to track.
The only downside is that we send PUSH_PROMISEs slightly less
liberally than allowable. More discussion here:
https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
"reserved (remote)" is omitted since the client code does not
support server push.
HTTP/2 stream states.
See http://tools.ietf.org/html/rfc7540#section-5.1.
For simplicity, the server code merges "reserved (local)" into
"half-closed (remote)". This is one less state transition to track.
The only downside is that we send PUSH_PROMISEs slightly less
liberally than allowable. More discussion here:
https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
"reserved (remote)" is omitted since the client code does not
support server push.
transportDefaultConnFlow is how many connection-level flow control
tokens we give the server at start-up, past the default 64k.
transportDefaultStreamFlow is how many stream-level flow
control tokens we announce to the peer, and how many bytes
we buffer per stream.
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)