2024-02-18 10:42:21 +00:00
// Copyright 2014 The Go Authors. All rights reserved.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Use of this source code is governed by a BSD-style
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// license that can be found in the LICENSE file.
// TODO: turn off the serve goroutine when idle, so
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// an idle conn only has the readFrames goroutine active. (which could
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// also be optimized probably to pin less memory in crypto/tls). This
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// would involve tracking when the serve goroutine is active (atomic
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// int32 read/CAS probably?) and starting it up when frames arrive,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and shutting it down when all handlers exit. the occasional PING
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// packets could use time.AfterFunc to call sc.wakeStartServeLoop()
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (which is a no-op if already running) and then queue the PING write
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// as normal. The serve loop would then exit in most cases (if no
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Handlers running) and not be woken up again until the PING packet
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// returns.
// TODO (maybe): add a mechanism for Handlers to going into
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// half-closed-local mode (rw.(io.Closer) test?) but not exit their
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// handler, and continue to be able to read from the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Request.Body. This would be a somewhat semantic change from HTTP/1
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (or at least what we expose in net/http), so I'd probably want to
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// add it there too. For now, this package says that returning from
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the Handler ServeHTTP function means you're both done reading and
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// done writing, without a way to stop just one or the other.
package http2
import (
"bufio"
"bytes"
"context"
"crypto/tls"
"errors"
"fmt"
"io"
"log"
"math"
"net"
"net/http"
"net/textproto"
"net/url"
"os"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"time"
"golang.org/x/net/http/httpguts"
"golang.org/x/net/http2/hpack"
)
const (
2024-07-24 23:45:04 +00:00
prefaceTimeout = 10 * time . Second
firstSettingsTimeout = 2 * time . Second // should be in-flight with preface anyway
handlerChunkWriteSize = 4 << 10
defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
2024-02-18 10:42:21 +00:00
maxQueuedControlFrames = 10000
)
var (
errClientDisconnected = errors . New ( "client disconnected" )
2024-07-24 23:45:04 +00:00
errClosedBody = errors . New ( "body closed by handler" )
errHandlerComplete = errors . New ( "http2: request body closed due to handler exiting" )
errStreamClosed = errors . New ( "http2: stream closed" )
2024-02-18 10:42:21 +00:00
)
var responseWriterStatePool = sync . Pool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
New : func ( ) interface { } {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := & responseWriterState { }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . bw = bufio . NewWriterSize ( chunkWriter { rws } , handlerChunkWriteSize )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return rws
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} ,
}
// Test hooks.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var (
2024-07-24 23:45:04 +00:00
testHookOnConn func ( )
2024-02-18 10:42:21 +00:00
testHookGetServerConn func ( * serverConn )
2024-07-24 23:45:04 +00:00
testHookOnPanicMu * sync . Mutex // nil except in tests
testHookOnPanic func ( sc * serverConn , panicVal interface { } ) ( rePanic bool )
2024-02-18 10:42:21 +00:00
)
// Server is an HTTP/2 server.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type Server struct {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// MaxHandlers limits the number of http.Handler ServeHTTP goroutines
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// which may run at a time over all connections.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Negative or zero no limit.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: implement
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
MaxHandlers int
// MaxConcurrentStreams optionally specifies the number of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// concurrent streams that each client may have open at a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// time. This is unrelated to the number of http.Handler goroutines
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// which may be active globally, which is MaxHandlers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If zero, MaxConcurrentStreams defaults to at least 100, per
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the HTTP/2 spec's recommendations.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
MaxConcurrentStreams uint32
// MaxDecoderHeaderTableSize optionally specifies the http2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// SETTINGS_HEADER_TABLE_SIZE to send in the initial settings frame. It
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// informs the remote endpoint of the maximum size of the header compression
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// table used to decode header blocks, in octets. If zero, the default value
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// of 4096 is used.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
MaxDecoderHeaderTableSize uint32
// MaxEncoderHeaderTableSize optionally specifies an upper limit for the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// header compression table used for encoding request headers. Received
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// SETTINGS_HEADER_TABLE_SIZE settings are capped at this limit. If zero,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the default value of 4096 is used.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
MaxEncoderHeaderTableSize uint32
// MaxReadFrameSize optionally specifies the largest frame
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// this server is willing to read. A valid value is between
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 16k and 16M, inclusive. If zero or otherwise invalid, a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// default value is used.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
MaxReadFrameSize uint32
// PermitProhibitedCipherSuites, if true, permits the use of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// cipher suites prohibited by the HTTP/2 spec.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
PermitProhibitedCipherSuites bool
// IdleTimeout specifies how long until idle clients should be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// closed with a GOAWAY frame. PING frames are not considered
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// activity for the purposes of IdleTimeout.
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
// If zero or negative, there is no timeout.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
IdleTimeout time . Duration
// MaxUploadBufferPerConnection is the size of the initial flow
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// control window for each connections. The HTTP/2 spec does not
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// allow this to be smaller than 65535 or larger than 2^32-1.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If the value is outside this range, a default value will be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// used instead.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
MaxUploadBufferPerConnection int32
// MaxUploadBufferPerStream is the size of the initial flow control
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// window for each stream. The HTTP/2 spec does not allow this to
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// be larger than 2^32-1. If the value is zero or larger than the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// maximum, a default value will be used instead.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
MaxUploadBufferPerStream int32
// NewWriteScheduler constructs a write scheduler for a connection.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If nil, a default scheduler is chosen.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
NewWriteScheduler func ( ) WriteScheduler
// CountError, if non-nil, is called on HTTP/2 server errors.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// It's intended to increment a metric for monitoring, such
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// as an expvar or Prometheus metric.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The errType consists of only ASCII word characters.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
CountError func ( errType string )
// Internal state. This is a pointer (rather than embedded directly)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// so that we don't embed a Mutex in this struct, which will make the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// struct non-copyable, which might break some callers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
state * serverInternalState
}
func ( s * Server ) initialConnRecvWindowSize ( ) int32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if s . MaxUploadBufferPerConnection >= initialWindowSize {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return s . MaxUploadBufferPerConnection
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 1 << 20
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( s * Server ) initialStreamRecvWindowSize ( ) int32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if s . MaxUploadBufferPerStream > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return s . MaxUploadBufferPerStream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 1 << 20
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( s * Server ) maxReadFrameSize ( ) uint32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if v := s . MaxReadFrameSize ; v >= minMaxFrameSize && v <= maxFrameSize {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return v
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return defaultMaxReadFrameSize
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( s * Server ) maxConcurrentStreams ( ) uint32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if v := s . MaxConcurrentStreams ; v > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return v
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return defaultMaxStreams
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( s * Server ) maxDecoderHeaderTableSize ( ) uint32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if v := s . MaxDecoderHeaderTableSize ; v > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return v
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return initialHeaderTableSize
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( s * Server ) maxEncoderHeaderTableSize ( ) uint32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if v := s . MaxEncoderHeaderTableSize ; v > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return v
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return initialHeaderTableSize
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// maxQueuedControlFrames is the maximum number of control frames like
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// SETTINGS, PING and RST_STREAM that will be queued for writing before
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the connection is closed to prevent memory exhaustion attacks.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( s * Server ) maxQueuedControlFrames ( ) int {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: if anybody asks, add a Server field, and remember to define the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// behavior of negative values.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return maxQueuedControlFrames
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
type serverInternalState struct {
2024-07-24 23:45:04 +00:00
mu sync . Mutex
2024-02-18 10:42:21 +00:00
activeConns map [ * serverConn ] struct { }
}
func ( s * serverInternalState ) registerConn ( sc * serverConn ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if s == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return // if the Server was used without calling ConfigureServer
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . mu . Lock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . activeConns [ sc ] = struct { } { }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . mu . Unlock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( s * serverInternalState ) unregisterConn ( sc * serverConn ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if s == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return // if the Server was used without calling ConfigureServer
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . mu . Lock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
delete ( s . activeConns , sc )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . mu . Unlock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( s * serverInternalState ) startGracefulShutdown ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if s == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return // if the Server was used without calling ConfigureServer
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . mu . Lock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for sc := range s . activeConns {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startGracefulShutdown ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . mu . Unlock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// ConfigureServer adds HTTP/2 support to a net/http Server.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The configuration conf may be nil.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ConfigureServer must be called before s begins serving.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ConfigureServer ( s * http . Server , conf * Server ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if s == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "nil *http.Server" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if conf == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
conf = new ( Server )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
conf . state = & serverInternalState { activeConns : make ( map [ * serverConn ] struct { } ) }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if h1 , h2 := s , conf ; h2 . IdleTimeout == 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if h1 . IdleTimeout != 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h2 . IdleTimeout = h1 . IdleTimeout
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h2 . IdleTimeout = h1 . ReadTimeout
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . RegisterOnShutdown ( conf . state . startGracefulShutdown )
if s . TLSConfig == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . TLSConfig = new ( tls . Config )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else if s . TLSConfig . CipherSuites != nil && s . TLSConfig . MinVersion < tls . VersionTLS13 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If they already provided a TLS 1.0– 1.2 CipherSuite list, return an
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// error if it is missing ECDHE_RSA_WITH_AES_128_GCM_SHA256 or
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
haveRequired := false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , cs := range s . TLSConfig . CipherSuites {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch cs {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case tls . TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Alternative MTI cipher to not discourage ECDSA-only servers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// See http://golang.org/cl/30721 for further information.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
tls . TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
haveRequired = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! haveRequired {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return fmt . Errorf ( "http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Note: not setting MinVersion to tls.VersionTLS12,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// as we don't want to interfere with HTTP/1.1 traffic
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// on the user's server. We enforce TLS 1.2 later once
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// we accept a connection. Ideally this should be done
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// during next-proto selection, but using TLS <1.2 with
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// HTTP/2 is still the client's bug.
s . TLSConfig . PreferServerCipherSuites = true
if ! strSliceContains ( s . TLSConfig . NextProtos , NextProtoTLS ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . TLSConfig . NextProtos = append ( s . TLSConfig . NextProtos , NextProtoTLS )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! strSliceContains ( s . TLSConfig . NextProtos , "http/1.1" ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . TLSConfig . NextProtos = append ( s . TLSConfig . NextProtos , "http/1.1" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if s . TLSNextProto == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . TLSNextProto = map [ string ] func ( * http . Server , * tls . Conn , http . Handler ) { }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
protoHandler := func ( hs * http . Server , c * tls . Conn , h http . Handler ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if testHookOnConn != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
testHookOnConn ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The TLSNextProto interface predates contexts, so
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the net/http package passes down its per-connection
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// base context via an exported but unadvertised
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// method on the Handler. This is for internal
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// net/http<=>http2 use only.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var ctx context . Context
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type baseContexter interface {
BaseContext ( ) context . Context
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if bc , ok := h . ( baseContexter ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ctx = bc . BaseContext ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
conf . ServeConn ( c , & ServeConnOpts {
2024-07-24 23:45:04 +00:00
Context : ctx ,
Handler : h ,
2024-02-18 10:42:21 +00:00
BaseConfig : hs ,
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
s . TLSNextProto [ NextProtoTLS ] = protoHandler
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// ServeConnOpts are options for the Server.ServeConn method.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type ServeConnOpts struct {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Context is the base context to use.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If nil, context.Background is used.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
Context context . Context
// BaseConfig optionally sets the base configuration
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// for values. If nil, defaults are used.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
BaseConfig * http . Server
// Handler specifies which handler to use for processing
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// requests. If nil, BaseConfig.Handler is used. If BaseConfig
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// or BaseConfig.Handler is nil, http.DefaultServeMux is used.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
Handler http . Handler
// UpgradeRequest is an initial request received on a connection
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// undergoing an h2c upgrade. The request body must have been
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// completely read from the connection before calling ServeConn,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and the 101 Switching Protocols response written.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
UpgradeRequest * http . Request
// Settings is the decoded contents of the HTTP2-Settings header
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// in an h2c upgrade request.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
Settings [ ] byte
// SawClientPreface is set if the HTTP/2 connection preface
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// has already been read from the connection.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
SawClientPreface bool
}
func ( o * ServeConnOpts ) context ( ) context . Context {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if o != nil && o . Context != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return o . Context
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return context . Background ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( o * ServeConnOpts ) baseConfig ( ) * http . Server {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if o != nil && o . BaseConfig != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return o . BaseConfig
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return new ( http . Server )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( o * ServeConnOpts ) handler ( ) http . Handler {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if o != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if o . Handler != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return o . Handler
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if o . BaseConfig != nil && o . BaseConfig . Handler != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return o . BaseConfig . Handler
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return http . DefaultServeMux
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// ServeConn serves HTTP/2 requests on the provided connection and
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// blocks until the connection is no longer readable.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ServeConn starts speaking HTTP/2 assuming that c has not had any
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// reads or writes. It writes its initial settings frame and expects
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// to be able to read the preface and settings frame from the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// client. If c has a ConnectionState method like a *tls.Conn, the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ConnectionState is used to verify the TLS ciphersuite and to set
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the Request.TLS field in Handlers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ServeConn does not support h2c by itself. Any h2c support must be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// implemented in terms of providing a suitably-behaving net.Conn.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The opts parameter is optional. If nil, default values are used.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( s * Server ) ServeConn ( c net . Conn , opts * ServeConnOpts ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
baseCtx , cancel := serverConnBaseContext ( c , opts )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer cancel ( )
sc := & serverConn {
2024-07-24 23:45:04 +00:00
srv : s ,
hs : opts . baseConfig ( ) ,
conn : c ,
baseCtx : baseCtx ,
remoteAddrStr : c . RemoteAddr ( ) . String ( ) ,
bw : newBufferedWriter ( c ) ,
handler : opts . handler ( ) ,
streams : make ( map [ uint32 ] * stream ) ,
readFrameCh : make ( chan readFrameResult ) ,
wantWriteFrameCh : make ( chan FrameWriteRequest , 8 ) ,
serveMsgCh : make ( chan interface { } , 8 ) ,
wroteFrameCh : make ( chan frameWriteResult , 1 ) , // buffered; one send in writeFrameAsync
bodyReadCh : make ( chan bodyReadMsg ) , // buffering doesn't matter either way
doneServing : make ( chan struct { } ) ,
clientMaxStreams : math . MaxUint32 , // Section 6.5.2: "Initially, there is no limit to this value"
advMaxStreams : s . maxConcurrentStreams ( ) ,
2024-02-18 10:42:21 +00:00
initialStreamSendWindowSize : initialWindowSize ,
2024-07-24 23:45:04 +00:00
maxFrameSize : initialMaxFrameSize ,
serveG : newGoroutineLock ( ) ,
pushEnabled : true ,
sawClientPreface : opts . SawClientPreface ,
2024-02-18 10:42:21 +00:00
}
s . state . registerConn ( sc )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer s . state . unregisterConn ( sc )
// The net/http package sets the write deadline from the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http.Server.WriteTimeout during the TLS handshake, but then
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// passes the connection off to us with the deadline already set.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Write deadlines are set per stream in serverConn.newStream.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Disarm the net.Conn write deadline here.
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
if sc . hs . WriteTimeout > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . conn . SetWriteDeadline ( time . Time { } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if s . NewWriteScheduler != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeSched = s . NewWriteScheduler ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeSched = newRoundRobinWriteScheduler ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// These start at the RFC-specified defaults. If there is a higher
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// configured value for inflow, that will be updated when we send a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// WINDOW_UPDATE shortly after sending SETTINGS.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . flow . add ( initialWindowSize )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . inflow . init ( initialWindowSize )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . hpackEncoder = hpack . NewEncoder ( & sc . headerWriteBuf )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . hpackEncoder . SetMaxDynamicTableSizeLimit ( s . maxEncoderHeaderTableSize ( ) )
fr := NewFramer ( sc . bw , c )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if s . CountError != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
fr . countError = s . CountError
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
fr . ReadMetaHeaders = hpack . NewDecoder ( s . maxDecoderHeaderTableSize ( ) , nil )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
fr . MaxHeaderListSize = sc . maxHeaderListSize ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
fr . SetMaxReadFrameSize ( s . maxReadFrameSize ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . framer = fr
if tc , ok := c . ( connectionStater ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . tlsState = new ( tls . ConnectionState )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
* sc . tlsState = tc . ConnectionState ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 9.2 Use of TLS Features
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// An implementation of HTTP/2 over TLS MUST use TLS
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 1.2 or higher with the restrictions on feature set
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and cipher suite described in this section. Due to
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// implementation limitations, it might not be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// possible to fail TLS negotiation. An endpoint MUST
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// immediately terminate an HTTP/2 connection that
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// does not meet the TLS requirements described in
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// this section with a connection error (Section
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 5.4.1) of type INADEQUATE_SECURITY.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . tlsState . Version < tls . VersionTLS12 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . rejectConn ( ErrCodeInadequateSecurity , "TLS version too low" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if sc . tlsState . ServerName == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Client must use SNI, but we don't enforce that anymore,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// since it was causing problems when connecting to bare IP
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// addresses during development.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: optionally enforce? Or enforce at the time we receive
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// a new request, and verify the ServerName matches the :authority?
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// But that precludes proxy situations, perhaps.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// So for now, do nothing here again.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if ! s . PermitProhibitedCipherSuites && isBadCipher ( sc . tlsState . CipherSuite ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "Endpoints MAY choose to generate a connection error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (Section 5.4.1) of type INADEQUATE_SECURITY if one of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the prohibited cipher suites are negotiated."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// We choose that. In my opinion, the spec is weak
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// here. It also says both parties must support at least
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// excuses here. If we really must, we could allow an
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "AllowInsecureWeakCiphers" option on the server later.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Let's see how it plays out first.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . rejectConn ( ErrCodeInadequateSecurity , fmt . Sprintf ( "Prohibited TLS 1.2 Cipher Suite: %x" , sc . tlsState . CipherSuite ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if opts . Settings != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
fr := & SettingsFrame {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
FrameHeader : FrameHeader { valid : true } ,
2024-07-24 23:45:04 +00:00
p : opts . Settings ,
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := fr . ForeachSetting ( sc . processSetting ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . rejectConn ( ErrCodeProtocol , "invalid settings" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
opts . Settings = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if hook := testHookGetServerConn ; hook != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
hook ( sc )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if opts . UpgradeRequest != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . upgradeRequest ( opts . UpgradeRequest )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
opts . UpgradeRequest = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
sc . serve ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func serverConnBaseContext ( c net . Conn , opts * ServeConnOpts ) ( ctx context . Context , cancel func ( ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ctx , cancel = context . WithCancel ( opts . context ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ctx = context . WithValue ( ctx , http . LocalAddrContextKey , c . LocalAddr ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if hs := opts . baseConfig ( ) ; hs != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ctx = context . WithValue ( ctx , http . ServerContextKey , hs )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) rejectConn ( err ErrCode , debug string ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server rejecting conn: %v, %s" , err , debug )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ignoring errors. hanging up anyway.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . framer . WriteGoAway ( 0 , err , [ ] byte ( debug ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . bw . Flush ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . conn . Close ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
type serverConn struct {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Immutable:
2024-07-24 23:45:04 +00:00
srv * Server
hs * http . Server
conn net . Conn
bw * bufferedWriter // writing to conn
handler http . Handler
baseCtx context . Context
framer * Framer
doneServing chan struct { } // closed when serverConn.serve ends
readFrameCh chan readFrameResult // written by serverConn.readFrames
2024-02-18 10:42:21 +00:00
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
2024-07-24 23:45:04 +00:00
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
bodyReadCh chan bodyReadMsg // from handlers -> serve
serveMsgCh chan interface { } // misc messages & code to send to / run on the serve loop
flow outflow // conn-wide (not stream-specific) outbound flow control
inflow inflow // conn-wide inbound flow control
tlsState * tls . ConnectionState // shared by all handlers, like net/http
remoteAddrStr string
writeSched WriteScheduler
2024-02-18 10:42:21 +00:00
// Everything following is owned by the serve loop; use serveG.check():
2024-07-24 23:45:04 +00:00
serveG goroutineLock // used to verify funcs are on serve()
pushEnabled bool
sawClientPreface bool // preface has already been read, used in h2c upgrade
sawFirstSettings bool // got the initial SETTINGS frame after the preface
needToSendSettingsAck bool
unackedSettings int // how many SETTINGS have we sent without ACKs?
queuedControlFrames int // control frames in the writeSched queue
clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
curClientStreams uint32 // number of open streams initiated by the client
curPushedStreams uint32 // number of open streams initiated by server push
curHandlers uint32 // number of running handler goroutines
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
streams map [ uint32 ] * stream
unstartedHandlers [ ] unstartedHandler
2024-02-18 10:42:21 +00:00
initialStreamSendWindowSize int32
2024-07-24 23:45:04 +00:00
maxFrameSize int32
peerMaxHeaderListSize uint32 // zero means unknown (default)
canonHeader map [ string ] string // http2-lower-case -> Go-Canonical-Case
canonHeaderKeysSize int // canonHeader keys size in bytes
writingFrame bool // started writing a frame (on serve goroutine or separate)
writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
needsFrameFlush bool // last frame write wasn't a flush
inGoAway bool // we've started to or sent GOAWAY
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
needToSendGoAway bool // we need to schedule a GOAWAY frame write
goAwayCode ErrCode
shutdownTimer * time . Timer // nil until used
idleTimer * time . Timer // nil if unused
2024-02-18 10:42:21 +00:00
// Owned by the writeFrameAsync goroutine:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
headerWriteBuf bytes . Buffer
2024-07-24 23:45:04 +00:00
hpackEncoder * hpack . Encoder
2024-02-18 10:42:21 +00:00
// Used by startGracefulShutdown.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
shutdownOnce sync . Once
}
func ( sc * serverConn ) maxHeaderListSize ( ) uint32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
n := sc . hs . MaxHeaderBytes
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if n <= 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
n = http . DefaultMaxHeaderBytes
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http2's count is in a slightly different unit and includes 32 bytes per pair.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
const perFieldOverhead = 32 // per http2 spec
2024-07-24 23:45:04 +00:00
const typicalHeaders = 10 // conservative
2024-02-18 10:42:21 +00:00
return uint32 ( n + typicalHeaders * perFieldOverhead )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) curOpenStreams ( ) uint32 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . curClientStreams + sc . curPushedStreams
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// stream represents a stream. This is the minimal metadata needed by
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the serve goroutine. Most of the actual stream state is owned by
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the http.Handler's goroutine in the responseWriter. Because the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// responseWriter's responseWriterState is recycled at the end of a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// handler, this struct intentionally has no pointer to the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// *responseWriter{,State} itself, as the Handler ending nils out the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// responseWriter's state field.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type stream struct {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// immutable:
2024-07-24 23:45:04 +00:00
sc * serverConn
id uint32
body * pipe // non-nil if expecting DATA frames
cw closeWaiter // closed wait stream transitions to closed state
ctx context . Context
2024-02-18 10:42:21 +00:00
cancelCtx func ( )
// owned by serverConn's serve loop:
2024-07-24 23:45:04 +00:00
bodyBytes int64 // body bytes seen so far
declBodyBytes int64 // or -1 if undeclared
flow outflow // limits writing from Handler to client
inflow inflow // what the client is allowed to POST/etc to us
state streamState
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
gotTrailerHeader bool // HEADER frame for trailers was seen
wroteHeaders bool // whether we wrote headers (not status 100)
readDeadline * time . Timer // nil if unused
writeDeadline * time . Timer // nil if unused
closeErr error // set before cw is closed
trailer http . Header // accumulated trailers
2024-02-18 10:42:21 +00:00
reqTrailer http . Header // handler's Request.Trailer
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
func ( sc * serverConn ) Framer ( ) * Framer { return sc . framer }
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) CloseConn ( ) error { return sc . conn . Close ( ) }
2024-07-24 23:45:04 +00:00
func ( sc * serverConn ) Flush ( ) error { return sc . bw . Flush ( ) }
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) HeaderEncoder ( ) ( * hpack . Encoder , * bytes . Buffer ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . hpackEncoder , & sc . headerWriteBuf
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) state ( streamID uint32 ) ( streamState , * stream ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http://tools.ietf.org/html/rfc7540#section-5.1
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st , ok := sc . streams [ streamID ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return st . state , st
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "The first use of a new stream identifier implicitly closes all
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// streams in the "idle" state that might have been initiated by
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// that peer with a lower-valued stream identifier. For example, if
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// a client sends a HEADERS frame on stream 7 without ever sending a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// frame on stream 5, then stream 5 transitions to the "closed"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// state when the first frame for stream 7 is sent or received."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if streamID % 2 == 1 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if streamID <= sc . maxClientStreamID {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return stateClosed , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if streamID <= sc . maxPushPromiseID {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return stateClosed , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return stateIdle , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// setConnState calls the net/http ConnState hook for this connection, if configured.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Note that the net/http package does StateNew and StateClosed for us.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) setConnState ( state http . ConnState ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . hs . ConnState != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . hs . ConnState ( sc . conn , state )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) vlogf ( format string , args ... interface { } ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if VerboseLogs {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . logf ( format , args ... )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) logf ( format string , args ... interface { } ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if lg := sc . hs . ErrorLog ; lg != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
lg . Printf ( format , args ... )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
log . Printf ( format , args ... )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// errno returns v's underlying uintptr, else 0.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: remove this helper function once http2 can use build
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// tags. See comment in isClosedConnError.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func errno ( v error ) uintptr {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rv := reflect . ValueOf ( v ) ; rv . Kind ( ) == reflect . Uintptr {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return uintptr ( rv . Uint ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// isClosedConnError reports whether err is an error from use of a closed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// network connection.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func isClosedConnError ( err error ) bool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-05-14 13:07:09 +00:00
if errors . Is ( err , net . ErrClosed ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// TODO(bradfitz): x/tools/cmd/bundle doesn't really support
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// build tags, so I can't make an http2_windows.go file with
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Windows-specific stuff. Fix that and move this, once we
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// have a way to bundle this into std's net/http somehow.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if runtime . GOOS == "windows" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if oe , ok := err . ( * net . OpError ) ; ok && oe . Op == "read" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if se , ok := oe . Err . ( * os . SyscallError ) ; ok && se . Syscall == "wsarecv" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
const WSAECONNABORTED = 10053
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
const WSAECONNRESET = 10054
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if n := errno ( se . Err ) ; n == WSAECONNRESET || n == WSAECONNABORTED {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) condlogf ( err error , format string , args ... interface { } ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == io . EOF || err == io . ErrUnexpectedEOF || isClosedConnError ( err ) || err == errPrefaceTimeout {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Boring, expected errors.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( format , args ... )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . logf ( format , args ... )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// of the entries in the canonHeader cache.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This should be larger than the size of unique, uncommon header keys likely to
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// be sent by the peer, while not so high as to permit unreasonable memory usage
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// if the peer sends an unbounded number of unique header keys.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
const maxCachedCanonicalHeadersKeysSize = 2048
func ( sc * serverConn ) canonicalHeader ( v string ) string {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
buildCommonHeaderMapsOnce ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
cv , ok := commonCanonHeader [ v ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return cv
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
cv , ok = sc . canonHeader [ v ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return cv
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . canonHeader == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . canonHeader = make ( map [ string ] string )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
cv = http . CanonicalHeaderKey ( v )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
size := 100 + len ( v ) * 2 // 100 bytes of map overhead + key + value
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . canonHeaderKeysSize + size <= maxCachedCanonicalHeadersKeysSize {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . canonHeader [ v ] = cv
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . canonHeaderKeysSize += size
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return cv
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
type readFrameResult struct {
2024-07-24 23:45:04 +00:00
f Frame // valid until readMore is called
2024-02-18 10:42:21 +00:00
err error
// readMore should be called once the consumer no longer needs or
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// retains f. After readMore, f is invalid and more frames can be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// read.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
readMore func ( )
}
// readFrames is the loop that reads incoming frames.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// It takes care to only read one frame at a time, blocking until the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// consumer is done with the frame.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// It's run on its own goroutine.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) readFrames ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
gate := make ( gate )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
gateDone := gate . Done
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
f , err := sc . framer . ReadFrame ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case sc . readFrameCh <- readFrameResult { f , err , gateDone } :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- gate :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if terminalReadFrameError ( err ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type frameWriteResult struct {
2024-07-24 23:45:04 +00:00
_ incomparable
wr FrameWriteRequest // what was written (or attempted)
err error // result of the writeFrame call
2024-02-18 10:42:21 +00:00
}
// writeFrameAsync runs in its own goroutine and writes a single frame
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and then reports when it's done.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// At most one goroutine can be running writeFrameAsync at a time per
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// serverConn.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) writeFrameAsync ( wr FrameWriteRequest , wd * writeData ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var err error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wd == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = wr . write . writeFrame ( sc )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = sc . framer . endWrite ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . wroteFrameCh <- frameWriteResult { wr : wr , err : err }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) closeAllStreamsOnConnClose ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , st := range sc . streams {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . closeStream ( st , errClientDisconnected )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) stopShutdownTimer ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if t := sc . shutdownTimer ; t != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
t . Stop ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) notePanic ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Note: this is for serverConn.serve panicking, not http.Handler code.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if testHookOnPanicMu != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
testHookOnPanicMu . Lock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer testHookOnPanicMu . Unlock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if testHookOnPanic != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if e := recover ( ) ; e != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if testHookOnPanic ( sc , e ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( e )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) serve ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer sc . notePanic ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer sc . conn . Close ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer sc . closeAllStreamsOnConnClose ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer sc . stopShutdownTimer ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer close ( sc . doneServing ) // unblocks handlers trying to send
if VerboseLogs {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server connection from %v on %p" , sc . conn . RemoteAddr ( ) , sc . hs )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
sc . writeFrame ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
write : writeSettings {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
{ SettingMaxFrameSize , sc . srv . maxReadFrameSize ( ) } ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
{ SettingMaxConcurrentStreams , sc . advMaxStreams } ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
{ SettingMaxHeaderListSize , sc . maxHeaderListSize ( ) } ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
{ SettingHeaderTableSize , sc . srv . maxDecoderHeaderTableSize ( ) } ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
{ SettingInitialWindowSize , uint32 ( sc . srv . initialStreamRecvWindowSize ( ) ) } ,
} ,
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . unackedSettings ++
// Each connection starts with initialWindowSize inflow tokens.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If a higher value is configured, we add more tokens.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if diff := sc . srv . initialConnRecvWindowSize ( ) - initialWindowSize ; diff > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( nil , int ( diff ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if err := sc . readPreface ( ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . condlogf ( err , "http2: server: error reading preface from client %v: %v" , sc . conn . RemoteAddr ( ) , err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Now that we've got the preface, get us out of the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "StateNew" state. We can't go directly to idle, though.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Active means we read some data and anticipate a request. We'll
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// do another Active when we get a HEADERS frame.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . setConnState ( http . StateActive )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . setConnState ( http . StateIdle )
2024-05-14 13:07:09 +00:00
if sc . srv . IdleTimeout > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . idleTimer = time . AfterFunc ( sc . srv . IdleTimeout , sc . onIdleTimer )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer sc . idleTimer . Stop ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
go sc . readFrames ( ) // closed by defer sc.conn.Close above
settingsTimer := time . AfterFunc ( firstSettingsTimeout , sc . onSettingsTimer )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer settingsTimer . Stop ( )
loopNum := 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
loopNum ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case wr := <- sc . wantWriteFrameCh :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if se , ok := wr . write . ( StreamError ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . resetStream ( se )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
break
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeFrame ( wr )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case res := <- sc . wroteFrameCh :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . wroteFrame ( res )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case res := <- sc . readFrameCh :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Process any written frames before reading new frames from the client since a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// written frame could have triggered a new stream to be started.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . writingFrameAsync {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case wroteRes := <- sc . wroteFrameCh :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . wroteFrame ( wroteRes )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . processFrameFromReader ( res ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
res . readMore ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if settingsTimer != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
settingsTimer . Stop ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
settingsTimer = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case m := <- sc . bodyReadCh :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . noteBodyRead ( m . st , m . n )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case msg := <- sc . serveMsgCh :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch v := msg . ( type ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case func ( int ) :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
v ( loopNum ) // for testing
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * serverMessage :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch v {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case settingsTimerMsg :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . logf ( "timeout waiting for SETTINGS frames from %v" , sc . conn . RemoteAddr ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case idleTimerMsg :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "connection is idle" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . goAway ( ErrCodeNo )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case shutdownTimerMsg :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "GOAWAY close timer fired; closing conn from %v" , sc . conn . RemoteAddr ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case gracefulShutdownMsg :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startGracefulShutdownInternal ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case handlerDoneMsg :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . handlerDone ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "unknown timer" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * startPushRequest :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startPush ( v )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case func ( * serverConn ) :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
v ( sc )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( fmt . Sprintf ( "unexpected type %T" , v ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// If the peer is causing us to generate a lot of control frames,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// but not reading them from us, assume they are trying to make us
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// run out of memory.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . queuedControlFrames > sc . srv . maxQueuedControlFrames ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: too many control frames in send queue, closing connection" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// with no error code (graceful shutdown), don't start the timer until
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// all open streams have been completed.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sentGoAway := sc . inGoAway && ! sc . needToSendGoAway && ! sc . writingFrame
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
gracefulShutdownComplete := sc . goAwayCode == ErrCodeNo && sc . curOpenStreams ( ) == 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sentGoAway && sc . shutdownTimer == nil && ( sc . goAwayCode != ErrCodeNo || gracefulShutdownComplete ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . shutDownIn ( goAwayTimeout )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
type serverMessage int
// Message values sent to serveMsgCh.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var (
2024-07-24 23:45:04 +00:00
settingsTimerMsg = new ( serverMessage )
idleTimerMsg = new ( serverMessage )
shutdownTimerMsg = new ( serverMessage )
2024-02-18 10:42:21 +00:00
gracefulShutdownMsg = new ( serverMessage )
2024-07-24 23:45:04 +00:00
handlerDoneMsg = new ( serverMessage )
2024-02-18 10:42:21 +00:00
)
func ( sc * serverConn ) onSettingsTimer ( ) { sc . sendServeMsg ( settingsTimerMsg ) }
2024-07-24 23:45:04 +00:00
func ( sc * serverConn ) onIdleTimer ( ) { sc . sendServeMsg ( idleTimerMsg ) }
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) onShutdownTimer ( ) { sc . sendServeMsg ( shutdownTimerMsg ) }
func ( sc * serverConn ) sendServeMsg ( msg interface { } ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . checkNotOn ( ) // NOT
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case sc . serveMsgCh <- msg :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
var errPrefaceTimeout = errors . New ( "timeout waiting for client preface" )
// readPreface reads the ClientPreface greeting from the peer or
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// returns errPrefaceTimeout on timeout, or an error if the greeting
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// is invalid.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) readPreface ( ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . sawClientPreface {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errc := make ( chan error , 1 )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go func ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Read the client preface
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
buf := make ( [ ] byte , len ( ClientPreface ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if _ , err := io . ReadFull ( sc . conn , buf ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errc <- err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else if ! bytes . Equal ( buf , clientPreface ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errc <- fmt . Errorf ( "bogus greeting %q" , buf )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errc <- nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
timer := time . NewTimer ( prefaceTimeout ) // TODO: configurable on *Server?
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer timer . Stop ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- timer . C :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errPrefaceTimeout
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case err := <- errc :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if VerboseLogs {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server: client %v said hello" , sc . conn . RemoteAddr ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
var errChanPool = sync . Pool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
New : func ( ) interface { } { return make ( chan error , 1 ) } ,
}
var writeDataPool = sync . Pool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
New : func ( ) interface { } { return new ( writeData ) } ,
}
// writeDataFromHandler writes DATA response frames from a handler on
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the given stream.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) writeDataFromHandler ( stream * stream , data [ ] byte , endStream bool ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ch := errChanPool . Get ( ) . ( chan error )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
writeArg := writeDataPool . Get ( ) . ( * writeData )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
* writeArg = writeData { stream . id , data , endStream }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err := sc . writeFrameFromHandler ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
write : writeArg ,
2024-02-18 10:42:21 +00:00
stream : stream ,
2024-07-24 23:45:04 +00:00
done : ch ,
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var frameWriteDone bool // the frame write is done (successfully or not)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case err = <- ch :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
frameWriteDone = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errClientDisconnected
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- stream . cw :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If both ch and stream.cw were ready (as might
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// happen on the final Write after an http.Handler
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ends), prefer the write result. Otherwise this
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// might just be us successfully closing the stream.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The writeFrameAsync and serve goroutines guarantee
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// that the ch send will happen before the stream.cw
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// close.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case err = <- ch :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
frameWriteDone = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errStreamClosed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errChanPool . Put ( ch )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if frameWriteDone {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
writeDataPool . Put ( writeArg )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// if the connection has gone away.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This must not be run from the serve goroutine itself, else it might
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// deadlock writing to sc.wantWriteFrameCh (which is only mildly
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// buffered and is read by serve itself). If you're on the serve
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// goroutine, call writeFrame instead.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) writeFrameFromHandler ( wr FrameWriteRequest ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . checkNotOn ( ) // NOT
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case sc . wantWriteFrameCh <- wr :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Serve loop is gone.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Client has closed their connection to the server.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errClientDisconnected
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// writeFrame schedules a frame to write and sends it if there's nothing
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// already being written.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// There is no pushback here (the serve goroutine never blocks). It's
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the http.Handlers that block, waiting for their previous frames to
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// make it onto the wire
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If you're not on the serve goroutine, use writeFrameFromHandler instead.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) writeFrame ( wr FrameWriteRequest ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
// If true, wr will not be written and wr.done will not be signaled.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var ignoreWrite bool
// We are not allowed to write frames on closed streams. RFC 7540 Section
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// a closed stream." Our server never sends PRIORITY, so that exception
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// does not apply.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The serverConn might close an open stream while the stream's handler
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// is still running. For example, the server might close a stream when it
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// receives bad data from the client. If this happens, the handler might
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// attempt to write a frame after the stream has been closed (since the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// handler hasn't yet been notified of the close). In this case, we simply
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ignore the frame. The handler will notice that the stream is closed when
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// it waits for the frame to be written.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// As an exception to this rule, we allow sending RST_STREAM after close.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This allows us to immediately reject new streams without tracking any
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// state for those streams (except for the queued RST_STREAM frame). This
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// may result in duplicate RST_STREAMs in some cases, but the client should
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ignore those.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wr . StreamID ( ) != 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
_ , isReset := wr . write . ( StreamError )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if state , _ := sc . state ( wr . StreamID ( ) ) ; state == stateClosed && ! isReset {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ignoreWrite = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Don't send a 100-continue response if we've already sent headers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// See golang.org/issue/14030.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch wr . write . ( type ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * writeResHeaders :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
wr . stream . wroteHeaders = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case write100ContinueHeadersFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wr . stream . wroteHeaders {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// We do not need to notify wr.done because this frame is
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// never written with wr.done != nil.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wr . done != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "wr.done != nil for write100ContinueHeadersFrame" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ignoreWrite = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if ! ignoreWrite {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wr . isControl ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . queuedControlFrames ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// For extra safety, detect wraparounds, which should not happen,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and pull the plug.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . queuedControlFrames < 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . conn . Close ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeSched . Push ( wr )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . scheduleFrameWrite ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// startFrameWrite starts a goroutine to write wr (in a separate
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// goroutine since that might block on the network), and updates the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// serve goroutine's state about the world, updated from info in wr.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) startFrameWrite ( wr FrameWriteRequest ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . writingFrame {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "internal error: can only be writing one frame at a time" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
st := wr . stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch st . state {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case stateHalfClosedLocal :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch wr . write . ( type ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case StreamError , handlerPanicRST , writeWindowUpdate :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// in this state. (We never send PRIORITY from the server, so that is not checked.)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( fmt . Sprintf ( "internal error: attempt to send frame on a half-closed-local stream: %v" , wr ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case stateClosed :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( fmt . Sprintf ( "internal error: attempt to send frame on a closed stream: %v" , wr ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wpp , ok := wr . write . ( * writePushPromise ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var err error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
wpp . promisedID , err = wpp . allocatePromisedID ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writingFrameAsync = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
wr . replyToWriter ( err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
sc . writingFrame = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . needsFrameFlush = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wr . write . staysWithinBuffer ( sc . bw . Available ( ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writingFrameAsync = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err := wr . write . writeFrame ( sc )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . wroteFrame ( frameWriteResult { wr : wr , err : err } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else if wd , ok := wr . write . ( * writeData ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Encode the frame in the serve goroutine, to ensure we don't have
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// any lingering asynchronous references to data passed to Write.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// See https://go.dev/issue/58446.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . framer . startWriteDataPadded ( wd . streamID , wd . endStream , wd . p , nil )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writingFrameAsync = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go sc . writeFrameAsync ( wr , wd )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writingFrameAsync = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go sc . writeFrameAsync ( wr , nil )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// errHandlerPanicked is the error given to any callers blocked in a read from
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Request.Body when the main goroutine panics. Since most handlers read in the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// main ServeHTTP goroutine, this will show up rarely.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var errHandlerPanicked = errors . New ( "http2: handler panicked" )
// wroteFrame is called on the serve goroutine with the result of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// whatever happened on writeFrameAsync.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) wroteFrame ( res frameWriteResult ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . writingFrame {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "internal error: expected to be already writing a frame" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writingFrame = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writingFrameAsync = false
wr := res . wr
if writeEndsStream ( wr . write ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st := wr . stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "internal error: expecting non-nil stream" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch st . state {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case stateOpen :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Here we would go to stateHalfClosedLocal in
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// theory, but since our handler is done and
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the net/http package provides no mechanism
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// for closing a ResponseWriter while still
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// reading data (see possible TODO at top of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// this file), we go into closed state here
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// anyway, after telling the peer we're
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// hanging up on them. We'll transition to
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// stateClosed after the RST_STREAM frame is
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// written.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . state = stateHalfClosedLocal
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Section 8.1: a server MAY request that the client abort
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// transmission of a request without error by sending a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// RST_STREAM with an error code of NO_ERROR after sending
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// a complete response.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . resetStream ( streamError ( st . id , ErrCodeNo ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case stateHalfClosedRemote :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . closeStream ( st , errHandlerComplete )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch v := wr . write . ( type ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case StreamError :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// st may be unknown if the RST_STREAM was generated to reject bad input.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st , ok := sc . streams [ v . StreamID ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . closeStream ( st , v )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case handlerPanicRST :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . closeStream ( wr . stream , errHandlerPanicked )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Reply (if requested) to unblock the ServeHTTP goroutine.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
wr . replyToWriter ( res . err )
sc . scheduleFrameWrite ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// scheduleFrameWrite tickles the frame writing scheduler.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If a frame is already being written, nothing happens. This will be called again
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// when the frame is done being written.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If a frame isn't being written and we need to send one, the best frame
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// to send is selected by writeSched.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If a frame isn't being written and there's nothing else to send, we
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// flush the write buffer.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) scheduleFrameWrite ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . writingFrame || sc . inFrameScheduleLoop {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . inFrameScheduleLoop = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for ! sc . writingFrameAsync {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . needToSendGoAway {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . needToSendGoAway = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startFrameWrite ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
write : & writeGoAway {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
maxStreamID : sc . maxClientStreamID ,
2024-07-24 23:45:04 +00:00
code : sc . goAwayCode ,
2024-02-18 10:42:21 +00:00
} ,
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
continue
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . needToSendSettingsAck {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . needToSendSettingsAck = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startFrameWrite ( FrameWriteRequest { write : writeSettingsAck { } } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
continue
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . inGoAway || sc . goAwayCode == ErrCodeNo {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wr , ok := sc . writeSched . Pop ( ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wr . isControl ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . queuedControlFrames --
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startFrameWrite ( wr )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
continue
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . needsFrameFlush {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startFrameWrite ( FrameWriteRequest { write : flushFrameWriter { } } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . needsFrameFlush = false // after startFrameWrite, since it sets this true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
continue
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
break
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . inFrameScheduleLoop = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// startGracefulShutdown gracefully shuts down a connection. This
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// shutting down. The connection isn't closed until all current
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// streams are done.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// startGracefulShutdown returns immediately; it does not wait until
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the connection has shut down.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) startGracefulShutdown ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . checkNotOn ( ) // NOT
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . shutdownOnce . Do ( func ( ) { sc . sendServeMsg ( gracefulShutdownMsg ) } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// After sending GOAWAY with an error code (non-graceful shutdown), the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// connection will close after goAwayTimeout.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If we close the connection immediately after sending GOAWAY, there may
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// be unsent data in our kernel receive buffer, which will cause the kernel
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// to send a TCP RST on close() instead of a FIN. This RST will abort the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// connection immediately, whether or not the client had received the GOAWAY.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Ideally we should delay for at least 1 RTT + epsilon so the client has
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// a chance to read the GOAWAY and stop sending messages. Measuring RTT
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// is hard, so we approximate with 1 second. See golang.org/issue/18701.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This is a var so it can be shorter in tests, where all requests uses the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// loopback interface making the expected RTT very small.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: configurable?
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var goAwayTimeout = 1 * time . Second
func ( sc * serverConn ) startGracefulShutdownInternal ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . goAway ( ErrCodeNo )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) goAway ( code ErrCode ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . inGoAway {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . goAwayCode == ErrCodeNo {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . goAwayCode = code
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . inGoAway = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . needToSendGoAway = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . goAwayCode = code
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . scheduleFrameWrite ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) shutDownIn ( d time . Duration ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . shutdownTimer = time . AfterFunc ( d , sc . onShutdownTimer )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) resetStream ( se StreamError ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeFrame ( FrameWriteRequest { write : se } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st , ok := sc . streams [ se . StreamID ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . resetQueued = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// processFrameFromReader processes the serve loop's read from readFrameCh from the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// frame-reading goroutine.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// processFrameFromReader returns whether the connection should be kept open.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) processFrameFromReader ( res readFrameResult ) bool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err := res . err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == ErrFrameTooLarge {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . goAway ( ErrCodeFrameSize )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true // goAway will close the loop
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
clientGone := err == io . EOF || err == io . ErrUnexpectedEOF || isClosedConnError ( err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if clientGone {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: could we also get into this state if
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the peer does a half close
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (e.g. CloseWrite) because they're done
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// sending frames but they're still wanting
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// our open replies? Investigate.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: add CloseWrite to crypto/tls.Conn first
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// so we have a way to test this? I suppose
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// just for testing we could have a non-TLS mode.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
f := res . f
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if VerboseLogs {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server read frame %v" , summarizeFrame ( f ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = sc . processFrame ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
switch ev := err . ( type ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case StreamError :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . resetStream ( ev )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case goAwayFlowError :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . goAway ( ErrCodeFlowControl )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case ConnectionError :
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
if res . f != nil {
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
if id := res . f . Header ( ) . StreamID ; id > sc . maxClientStreamID {
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
sc . maxClientStreamID = id
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
}
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . logf ( "http2: server connection error from %v: %v" , sc . conn . RemoteAddr ( ) , ev )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . goAway ( ErrCode ( ev ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true // goAway will handle shutdown
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if res . err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server closing client connection; error reading frame from client %s: %v" , sc . conn . RemoteAddr ( ) , err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . logf ( "http2: server closing client connection: %v" , err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processFrame ( f Frame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
// First frame received must be SETTINGS.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . sawFirstSettings {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if _ , ok := f . ( * SettingsFrame ) ; ! ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "first_settings" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sawFirstSettings = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Discard frames for streams initiated after the identified last
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// stream sent in a GOAWAY, or all frames after sending an error.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// We still need to return connection-level flow control for DATA frames.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// RFC 9113 Section 6.8.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . inGoAway && ( sc . goAwayCode != ErrCodeNo || f . Header ( ) . StreamID > sc . maxClientStreamID ) {
if f , ok := f . ( * DataFrame ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . inflow . take ( f . Length ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "data_flow" , streamError ( f . Header ( ) . StreamID , ErrCodeFlowControl ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( nil , int ( f . Length ) ) // conn-level
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
switch f := f . ( type ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * SettingsFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processSettings ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * MetaHeadersFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processHeaders ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * WindowUpdateFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processWindowUpdate ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * PingFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processPing ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * DataFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processData ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * RSTStreamFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processResetStream ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * PriorityFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processPriority ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * GoAwayFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processGoAway ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case * PushPromiseFrame :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "push_promise" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server ignoring frame: %v" , f . Header ( ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processPing ( f * PingFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . IsAck ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 6.7 PING: " An endpoint MUST NOT respond to PING frames
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// containing this flag."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . StreamID != 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "PING frames are not associated with any individual
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// stream. If a PING frame is received with a stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// identifier field value other than 0x0, the recipient MUST
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// respond with a connection error (Section 5.4.1) of type
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// PROTOCOL_ERROR."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "ping_on_stream" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeFrame ( FrameWriteRequest { write : writePingAck { f } } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processWindowUpdate ( f * WindowUpdateFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case f . StreamID != 0 : // stream-level flow control
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
state , st := sc . state ( f . StreamID )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if state == stateIdle {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Section 5.1: "Receiving any frame other than HEADERS
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// or PRIORITY on a stream in this state MUST be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// treated as a connection error (Section 5.4.1) of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// type PROTOCOL_ERROR."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "stream_idle" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "WINDOW_UPDATE can be sent by a peer that has sent a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// frame bearing the END_STREAM flag. This means that a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// receiver could receive a WINDOW_UPDATE frame on a "half
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// closed (remote)" or "closed" stream. A receiver MUST
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// NOT treat this as an error, see Section 5.1."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! st . flow . add ( int32 ( f . Increment ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "bad_flow" , streamError ( f . StreamID , ErrCodeFlowControl ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default : // connection-level flow control
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . flow . add ( int32 ( f . Increment ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return goAwayFlowError { }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . scheduleFrameWrite ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processResetStream ( f * RSTStreamFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
state , st := sc . state ( f . StreamID )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if state == stateIdle {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 6.4 "RST_STREAM frames MUST NOT be sent for a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// stream in the "idle" state. If a RST_STREAM frame
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// identifying an idle stream is received, the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// recipient MUST treat this as a connection error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (Section 5.4.1) of type PROTOCOL_ERROR.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "reset_idle_stream" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . cancelCtx ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . closeStream ( st , streamError ( f . StreamID , f . ErrCode ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) closeStream ( st * stream , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . state == stateIdle || st . state == stateClosed {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( fmt . Sprintf ( "invariant; can't close stream in state %v" , st . state ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . state = stateClosed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . readDeadline != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . readDeadline . Stop ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . writeDeadline != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . writeDeadline . Stop ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . isPushed ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curPushedStreams --
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curClientStreams --
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
delete ( sc . streams , st . id )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if len ( sc . streams ) == 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . setConnState ( http . StateIdle )
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
if sc . srv . IdleTimeout > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . idleTimer . Reset ( sc . srv . IdleTimeout )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if h1ServerKeepAlivesDisabled ( sc . hs ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startGracefulShutdownInternal ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if p := st . body ; p != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Return any buffered unread bytes worth of conn-level flow control.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// See golang.org/issue/16481
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( nil , p . Len ( ) )
p . CloseWithError ( err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if e , ok := err . ( StreamError ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if e . Cause != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = e . Cause
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = errStreamClosed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . closeErr = err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . cw . Close ( ) // signals Handler's CloseNotifier, unblocks writes, etc
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeSched . CloseStream ( st . id )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processSettings ( f * SettingsFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . IsAck ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . unackedSettings --
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . unackedSettings < 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Why is the peer ACKing settings we never sent?
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The spec doesn't mention this case, but
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// hang up on them anyway.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "ack_mystery" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . NumSettings ( ) > 100 || f . HasDuplicates ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This isn't actually in the spec, but hang up on
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// suspiciously large settings frames or those with
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// duplicate entries.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "settings_big_or_dups" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := f . ForeachSetting ( sc . processSetting ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// acknowledged individually, even if multiple are received before the ACK.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . needToSendSettingsAck = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . scheduleFrameWrite ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processSetting ( s Setting ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := s . Valid ( ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if VerboseLogs {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server processing setting %v" , s )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch s . ID {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case SettingHeaderTableSize :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . hpackEncoder . SetMaxDynamicTableSize ( s . Val )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case SettingEnablePush :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . pushEnabled = s . Val != 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case SettingMaxConcurrentStreams :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . clientMaxStreams = s . Val
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case SettingInitialWindowSize :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . processSettingInitialWindowSize ( s . Val )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case SettingMaxFrameSize :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . maxFrameSize = int32 ( s . Val ) // the maximum valid s.Val is < 2^31
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case SettingMaxHeaderListSize :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . peerMaxHeaderListSize = s . Val
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Unknown setting: "An endpoint that receives a SETTINGS
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// frame with any unknown or unsupported identifier MUST
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ignore that setting."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if VerboseLogs {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: server ignoring unknown setting %v" , s )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processSettingInitialWindowSize ( val uint32 ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Note: val already validated to be within range by
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// processSetting's Valid call.
// "A SETTINGS frame can alter the initial flow control window
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// size for all current streams. When the value of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// adjust the size of all stream flow control windows that it
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// maintains by the difference between the new value and the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// old value."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
old := sc . initialStreamSendWindowSize
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . initialStreamSendWindowSize = int32 ( val )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
growth := int32 ( val ) - old // may be negative
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , st := range sc . streams {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! st . flow . add ( growth ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 6.9.2 Initial Flow Control Window Size
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "An endpoint MUST treat a change to
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// control window to exceed the maximum size as a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// connection error (Section 5.4.1) of type
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// FLOW_CONTROL_ERROR."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "setting_win_size" , ConnectionError ( ErrCodeFlowControl ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processData ( f * DataFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
id := f . Header ( ) . StreamID
data := f . Data ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
state , st := sc . state ( id )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if id == 0 || state == stateIdle {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Section 6.1: "DATA frames MUST be associated with a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// stream. If a DATA frame is received whose stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// identifier field is 0x0, the recipient MUST respond
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// with a connection error (Section 5.4.1) of type
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// PROTOCOL_ERROR."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Section 5.1: "Receiving any frame other than HEADERS
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// or PRIORITY on a stream in this state MUST be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// treated as a connection error (Section 5.4.1) of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// type PROTOCOL_ERROR."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "data_on_idle" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// "If a DATA frame is received whose stream is not in "open"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// or "half closed (local)" state, the recipient MUST respond
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// with a stream error (Section 5.4.2) of type STREAM_CLOSED."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st == nil || state != stateOpen || st . gotTrailerHeader || st . resetQueued {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This includes sending a RST_STREAM if the stream is
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// in stateHalfClosedLocal (which currently means that
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the http.Handler returned, so it's done reading &
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// done writing). Try to stop the client from sending
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// more DATA.
// But still enforce their connection-level flow control,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and return any flow control bytes since we're not going
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// to consume them.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . inflow . take ( f . Length ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "data_flow" , streamError ( id , ErrCodeFlowControl ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( nil , int ( f . Length ) ) // conn-level
if st != nil && st . resetQueued {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Already have a stream error in flight. Don't send another.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "closed" , streamError ( id , ErrCodeStreamClosed ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . body == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "internal error: should have a body in this state" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Sender sending more than they'd declared?
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . declBodyBytes != - 1 && st . bodyBytes + int64 ( len ( data ) ) > st . declBodyBytes {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . inflow . take ( f . Length ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "data_flow" , streamError ( id , ErrCodeFlowControl ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( nil , int ( f . Length ) ) // conn-level
st . body . CloseWithError ( fmt . Errorf ( "sender tried to send more than declared Content-Length of %d bytes" , st . declBodyBytes ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// value of a content-length header field does not equal the sum of the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// DATA frame payload lengths that form the body.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "send_too_much" , streamError ( id , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . Length > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Check whether the client has flow control quota.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! takeInflows ( & sc . inflow , & st . inflow , f . Length ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "flow_on_data_length" , streamError ( id , ErrCodeFlowControl ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if len ( data ) > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . bodyBytes += int64 ( len ( data ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
wrote , err := st . body . Write ( data )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The handler has closed the request body.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Return the connection-level flow control for the discarded data,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// but not the stream-level flow control.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( nil , int ( f . Length ) - wrote )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if wrote != len ( data ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "internal error: bad Writer" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Return any padded flow control now, since we won't
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// refund it later on body reads.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Call sendWindowUpdate even if there is no padding,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// to return buffered flow control credit if the sent
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// window has shrunk.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
pad := int32 ( f . Length ) - int32 ( len ( data ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate32 ( nil , pad )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate32 ( st , pad )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . StreamEnded ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . endStream ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processGoAway ( f * GoAwayFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . ErrCode != ErrCodeNo {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . logf ( "http2: received GOAWAY %+v, starting graceful shutdown" , f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . vlogf ( "http2: received GOAWAY %+v, starting graceful shutdown" , f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startGracefulShutdownInternal ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http://tools.ietf.org/html/rfc7540#section-6.8
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// We should not create any new streams, which means we should disable push.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . pushEnabled = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// isPushed reports whether the stream is server-initiated.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( st * stream ) isPushed ( ) bool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return st . id % 2 == 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// endStream closes a Request.Body's pipe. It is called when a DATA
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// frame says a request body is over (or after trailers).
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( st * stream ) endStream ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc := st . sc
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
if st . declBodyBytes != - 1 && st . declBodyBytes != st . bodyBytes {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . body . CloseWithError ( fmt . Errorf ( "request declared a Content-Length of %d but only wrote %d bytes" ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . declBodyBytes , st . bodyBytes ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . body . closeWithErrorAndCode ( io . EOF , st . copyTrailersToHandlerRequest )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . body . CloseWithError ( io . EOF )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . state = stateHalfClosedRemote
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// copyTrailersToHandlerRequest is run in the Handler's goroutine in
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// its Request.Body.Read just before it gets io.EOF.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( st * stream ) copyTrailersToHandlerRequest ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for k , vv := range st . trailer {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if _ , ok := st . reqTrailer [ k ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Only copy it over it was pre-declared.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . reqTrailer [ k ] = vv
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// onReadTimeout is run on its own goroutine (from time.AfterFunc)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// when the stream's ReadTimeout has fired.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( st * stream ) onReadTimeout ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . body != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Wrap the ErrDeadlineExceeded to avoid callers depending on us
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// returning the bare error.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . body . CloseWithError ( fmt . Errorf ( "%w" , os . ErrDeadlineExceeded ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// when the stream's WriteTimeout has fired.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( st * stream ) onWriteTimeout ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . sc . writeFrameFromHandler ( FrameWriteRequest { write : StreamError {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
StreamID : st . id ,
2024-07-24 23:45:04 +00:00
Code : ErrCodeInternal ,
Cause : os . ErrDeadlineExceeded ,
2024-02-18 10:42:21 +00:00
} } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processHeaders ( f * MetaHeadersFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
id := f . StreamID
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http://tools.ietf.org/html/rfc7540#section-5.1.1
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Streams initiated by a client MUST use odd-numbered stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// identifiers. [...] An endpoint that receives an unexpected
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// stream identifier MUST respond with a connection error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (Section 5.4.1) of type PROTOCOL_ERROR.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if id % 2 != 1 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "headers_even" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// A HEADERS frame can be used to create a new stream or
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// send a trailer for an open one. If we already have a stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// open, let it process its own HEADERS frame (trailers at this
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// point, if it's valid).
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st := sc . streams [ f . StreamID ] ; st != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . resetQueued {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// We're sending RST_STREAM to close the stream, so don't bother
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// processing this frame.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// RFC 7540, sec 5.1: If an endpoint receives additional frames, other than
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// this state, it MUST respond with a stream error (Section 5.4.2) of
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// type STREAM_CLOSED.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . state == stateHalfClosedRemote {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "headers_half_closed" , streamError ( id , ErrCodeStreamClosed ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return st . processTrailerHeaders ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// [...] The identifier of a newly established stream MUST be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// numerically greater than all streams that the initiating
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// endpoint has opened or reserved. [...] An endpoint that
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// receives an unexpected stream identifier MUST respond with
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if id <= sc . maxClientStreamID {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "stream_went_down" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . maxClientStreamID = id
if sc . idleTimer != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . idleTimer . Stop ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// http://tools.ietf.org/html/rfc7540#section-5.1.2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// [...] Endpoints MUST NOT exceed the limit set by their peer. An
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// endpoint that receives a HEADERS frame that causes their
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// advertised concurrent stream limit to be exceeded MUST treat
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// or REFUSED_STREAM.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . curClientStreams + 1 > sc . advMaxStreams {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . unackedSettings == 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// They should know better.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "over_max_streams" , streamError ( id , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Assume it's a network race, where they just haven't
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// received our last SETTINGS update. But actually
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// this can't happen yet, because we don't yet provide
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// a way for users to adjust server parameters at
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// runtime.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "over_max_streams_race" , streamError ( id , ErrCodeRefusedStream ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
initialState := stateOpen
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . StreamEnded ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
initialState = stateHalfClosedRemote
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st := sc . newStream ( id , 0 , initialState )
if f . HasPriority ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := sc . checkPriority ( f . StreamID , f . Priority ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeSched . AdjustStream ( st . id , f . Priority )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
rw , req , err := sc . newWriterAndRequest ( st , f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . reqTrailer = req . Trailer
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . reqTrailer != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . trailer = make ( http . Header )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . body = req . Body . ( * requestBody ) . pipe // may be nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . declBodyBytes = req . ContentLength
handler := sc . handler . ServeHTTP
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f . Truncated {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Their header list was too long. Send a 431 error.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
handler = handleHeaderListTooLong
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else if err := checkValidHTTP2RequestHeaders ( req . Header ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
handler = new400Handler ( err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// The net/http package sets the read deadline from the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http.Server.ReadTimeout during the TLS handshake, but then
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// passes the connection off to us with the deadline already
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// set. Disarm it here after the request headers are read,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// similar to how the http1 server works. Here it's
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// technically more like the http1 Server's ReadHeaderTimeout
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (in Go 1.8), though. That's a more sane option anyway.
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
if sc . hs . ReadTimeout > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . conn . SetReadDeadline ( time . Time { } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . readDeadline = time . AfterFunc ( sc . hs . ReadTimeout , st . onReadTimeout )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
return sc . scheduleHandler ( id , rw , req , handler )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) upgradeRequest ( req * http . Request ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
id := uint32 ( 1 )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . maxClientStreamID = id
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st := sc . newStream ( id , 0 , stateHalfClosedRemote )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . reqTrailer = req . Trailer
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . reqTrailer != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . trailer = make ( http . Header )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rw := sc . newResponseWriter ( st , req )
// Disable any read deadline set by the net/http package
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// prior to the upgrade.
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
if sc . hs . ReadTimeout > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . conn . SetReadDeadline ( time . Time { } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// This is the first request on the connection,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// so start the handler directly rather than going
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// through scheduleHandler.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curHandlers ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go sc . runHandler ( rw , req , sc . handler . ServeHTTP )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( st * stream ) processTrailerHeaders ( f * MetaHeadersFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc := st . sc
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . gotTrailerHeader {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "dup_trailers" , ConnectionError ( ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . gotTrailerHeader = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! f . StreamEnded ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "trailers_not_ended" , streamError ( st . id , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if len ( f . PseudoFields ( ) ) > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "trailers_pseudo" , streamError ( st . id , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . trailer != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , hf := range f . RegularFields ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
key := sc . canonicalHeader ( hf . Name )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! httpguts . ValidTrailerHeader ( key ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: send more details to the peer somehow. But http2 has
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// no way to send debug data at a stream level. Discuss with
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// HTTP folk.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "trailers_bogus" , streamError ( st . id , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . trailer [ key ] = append ( st . trailer [ key ] , hf . Value )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . endStream ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) checkPriority ( streamID uint32 , p PriorityParam ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if streamID == p . StreamDep {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Section 5.3.3 says that a stream can depend on one of its dependencies,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// so it's only self-dependencies that are forbidden.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "priority" , streamError ( streamID , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) processPriority ( f * PriorityFrame ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := sc . checkPriority ( f . StreamID , f . PriorityParam ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeSched . AdjustStream ( f . StreamID , f . PriorityParam )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) newStream ( id , pusherID uint32 , state streamState ) * stream {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if id == 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "internal error: cannot create stream with id 0" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
ctx , cancelCtx := context . WithCancel ( sc . baseCtx )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st := & stream {
2024-07-24 23:45:04 +00:00
sc : sc ,
id : id ,
state : state ,
ctx : ctx ,
2024-02-18 10:42:21 +00:00
cancelCtx : cancelCtx ,
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . cw . Init ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . flow . conn = & sc . flow // link to conn-level counter
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . flow . add ( sc . initialStreamSendWindowSize )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . inflow . init ( sc . srv . initialStreamRecvWindowSize ( ) )
2024-07-24 23:45:04 +00:00
2024-05-14 13:07:09 +00:00
if sc . hs . WriteTimeout > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . writeDeadline = time . AfterFunc ( sc . hs . WriteTimeout , st . onWriteTimeout )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
sc . streams [ id ] = st
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeSched . OpenStream ( st . id , OpenStreamOptions { PusherID : pusherID } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . isPushed ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curPushedStreams ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curClientStreams ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . curOpenStreams ( ) == 1 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . setConnState ( http . StateActive )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
return st
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) newWriterAndRequest ( st * stream , f * MetaHeadersFrame ) ( * responseWriter , * http . Request , error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
rp := requestParam {
2024-07-24 23:45:04 +00:00
method : f . PseudoValue ( "method" ) ,
scheme : f . PseudoValue ( "scheme" ) ,
2024-02-18 10:42:21 +00:00
authority : f . PseudoValue ( "authority" ) ,
2024-07-24 23:45:04 +00:00
path : f . PseudoValue ( "path" ) ,
2024-02-18 10:42:21 +00:00
}
isConnect := rp . method == "CONNECT"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if isConnect {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rp . path != "" || rp . scheme != "" || rp . authority == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil , nil , sc . countError ( "bad_connect" , streamError ( f . StreamID , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else if rp . method == "" || rp . path == "" || ( rp . scheme != "https" && rp . scheme != "http" ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// See 8.1.2.6 Malformed Requests and Responses:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Malformed requests or responses that are detected
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// MUST be treated as a stream error (Section 5.4.2)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// of type PROTOCOL_ERROR."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 8.1.2.3 Request Pseudo-Header Fields
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "All HTTP/2 requests MUST include exactly one valid
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// value for the :method, :scheme, and :path
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// pseudo-header fields"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil , nil , sc . countError ( "bad_path_method" , streamError ( f . StreamID , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
rp . header = make ( http . Header )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , hf := range f . RegularFields ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rp . header . Add ( sc . canonicalHeader ( hf . Name ) , hf . Value )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rp . authority == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rp . authority = rp . header . Get ( "Host" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
rw , req , err := sc . newWriterAndRequestNoBody ( st , rp )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil , nil , err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
bodyOpen := ! f . StreamEnded ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if bodyOpen {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if vv , ok := rp . header [ "Content-Length" ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if cl , err := strconv . ParseUint ( vv [ 0 ] , 10 , 63 ) ; err == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
req . ContentLength = int64 ( cl )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
req . ContentLength = 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
req . ContentLength = - 1
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
req . Body . ( * requestBody ) . pipe = & pipe {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
b : & dataBuffer { expected : req . ContentLength } ,
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return rw , req , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
type requestParam struct {
2024-07-24 23:45:04 +00:00
method string
2024-02-18 10:42:21 +00:00
scheme , authority , path string
2024-07-24 23:45:04 +00:00
header http . Header
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) newWriterAndRequestNoBody ( st * stream , rp requestParam ) ( * responseWriter , * http . Request , error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
var tlsState * tls . ConnectionState // nil if not scheme https
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rp . scheme == "https" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
tlsState = sc . tlsState
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
needsContinue := httpguts . HeaderValuesContainsToken ( rp . header [ "Expect" ] , "100-continue" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if needsContinue {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rp . header . Del ( "Expect" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Merge Cookie headers into one "; "-delimited value.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if cookies := rp . header [ "Cookie" ] ; len ( cookies ) > 1 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rp . header . Set ( "Cookie" , strings . Join ( cookies , "; " ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Setup Trailers
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var trailer http . Header
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , v := range rp . header [ "Trailer" ] {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , key := range strings . Split ( v , "," ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
key = http . CanonicalHeaderKey ( textproto . TrimString ( key ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch key {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case "Transfer-Encoding" , "Trailer" , "Content-Length" :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Bogus. (copy of http1 rules)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Ignore.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if trailer == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
trailer = make ( http . Header )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
trailer [ key ] = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
delete ( rp . header , "Trailer" )
var url_ * url . URL
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var requestURI string
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rp . method == "CONNECT" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
url_ = & url . URL { Host : rp . authority }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
requestURI = rp . authority // mimic HTTP/1 server behavior
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var err error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
url_ , err = url . ParseRequestURI ( rp . path )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil , nil , sc . countError ( "bad_path" , streamError ( st . id , ErrCodeProtocol ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
requestURI = rp . path
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
body := & requestBody {
2024-07-24 23:45:04 +00:00
conn : sc ,
stream : st ,
2024-02-18 10:42:21 +00:00
needsContinue : needsContinue ,
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
req := & http . Request {
2024-07-24 23:45:04 +00:00
Method : rp . method ,
URL : url_ ,
2024-02-18 10:42:21 +00:00
RemoteAddr : sc . remoteAddrStr ,
2024-07-24 23:45:04 +00:00
Header : rp . header ,
2024-02-18 10:42:21 +00:00
RequestURI : requestURI ,
2024-07-24 23:45:04 +00:00
Proto : "HTTP/2.0" ,
2024-02-18 10:42:21 +00:00
ProtoMajor : 2 ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ProtoMinor : 0 ,
2024-07-24 23:45:04 +00:00
TLS : tlsState ,
Host : rp . authority ,
Body : body ,
Trailer : trailer ,
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
req = req . WithContext ( st . ctx )
rw := sc . newResponseWriter ( st , req )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return rw , req , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) newResponseWriter ( st * stream , req * http . Request ) * responseWriter {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := responseWriterStatePool . Get ( ) . ( * responseWriterState )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
bwSave := rws . bw
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
* rws = responseWriterState { } // zero all the fields
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . conn = sc
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . bw = bwSave
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . bw . Reset ( chunkWriter { rws } )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . stream = st
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . req = req
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return & responseWriter { rws : rws }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
type unstartedHandler struct {
streamID uint32
2024-07-24 23:45:04 +00:00
rw * responseWriter
req * http . Request
handler func ( http . ResponseWriter , * http . Request )
2024-02-18 10:42:21 +00:00
}
// scheduleHandler starts a handler goroutine,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// or schedules one to start as soon as an existing handler finishes.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) scheduleHandler ( streamID uint32 , rw * responseWriter , req * http . Request , handler func ( http . ResponseWriter , * http . Request ) ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
maxHandlers := sc . advMaxStreams
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . curHandlers < maxHandlers {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curHandlers ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go sc . runHandler ( rw , req , handler )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if len ( sc . unstartedHandlers ) > int ( 4 * sc . advMaxStreams ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return sc . countError ( "too_many_early_resets" , ConnectionError ( ErrCodeEnhanceYourCalm ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . unstartedHandlers = append ( sc . unstartedHandlers , unstartedHandler {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
streamID : streamID ,
2024-07-24 23:45:04 +00:00
rw : rw ,
req : req ,
handler : handler ,
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) handlerDone ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curHandlers --
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
i := 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
maxHandlers := sc . advMaxStreams
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for ; i < len ( sc . unstartedHandlers ) ; i ++ {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
u := sc . unstartedHandlers [ i ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . streams [ u . streamID ] == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This stream was reset before its goroutine had a chance to start.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
continue
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . curHandlers >= maxHandlers {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
break
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . curHandlers ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go sc . runHandler ( u . rw , u . req , u . handler )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . unstartedHandlers [ i ] = unstartedHandler { } // don't retain references
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . unstartedHandlers = sc . unstartedHandlers [ i : ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if len ( sc . unstartedHandlers ) == 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . unstartedHandlers = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Run on its own goroutine.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) runHandler ( rw * responseWriter , req * http . Request , handler func ( http . ResponseWriter , * http . Request ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer sc . sendServeMsg ( handlerDoneMsg )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
didPanic := true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
defer func ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rw . rws . stream . cancelCtx ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if req . MultipartForm != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
req . MultipartForm . RemoveAll ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if didPanic {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
e := recover ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeFrameFromHandler ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
write : handlerPanicRST { rw . rws . stream . id } ,
2024-02-18 10:42:21 +00:00
stream : rw . rws . stream ,
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Same as net/http:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if e != nil && e != http . ErrAbortHandler {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
const size = 64 << 10
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
buf := make ( [ ] byte , size )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
buf = buf [ : runtime . Stack ( buf , false ) ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . logf ( "http2: panic serving %v: %v\n%s" , sc . conn . RemoteAddr ( ) , e , buf )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rw . handlerDone ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
handler ( rw , req )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
didPanic = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func handleHeaderListTooLong ( w http . ResponseWriter , r * http . Request ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// 10.5.1 Limits on Header Block Size:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// .. "A server that receives a larger header block than it is
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// willing to handle can send an HTTP 431 (Request Header Fields Too
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Large) status code"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
const statusRequestHeaderFieldsTooLarge = 431 // only in Go 1.6+
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
w . WriteHeader ( statusRequestHeaderFieldsTooLarge )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
io . WriteString ( w , "<h1>HTTP Error 431</h1><p>Request Header Field(s) Too Large</p>" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// called from handler goroutines.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// h may be nil.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) writeHeaders ( st * stream , headerData * writeResHeaders ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . checkNotOn ( ) // NOT on
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var errc chan error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if headerData . h != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If there's a header map (which we don't own), so we have to block on
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// waiting for this frame to be written, so an http.Flush mid-handler
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// writes out the correct value of keys, before a handler later potentially
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// mutates it.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errc = errChanPool . Get ( ) . ( chan error )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := sc . writeFrameFromHandler ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
write : headerData ,
2024-02-18 10:42:21 +00:00
stream : st ,
2024-07-24 23:45:04 +00:00
done : errc ,
2024-02-18 10:42:21 +00:00
} ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if errc != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case err := <- errc :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errChanPool . Put ( errc )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errClientDisconnected
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- st . cw :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errStreamClosed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// called from handler goroutines.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) write100ContinueHeaders ( st * stream ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeFrameFromHandler ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
write : write100ContinueHeadersFrame { st . id } ,
2024-02-18 10:42:21 +00:00
stream : st ,
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// A bodyReadMsg tells the server loop that the http.Handler read n
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// bytes of the DATA from the client on the given stream.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type bodyReadMsg struct {
st * stream
2024-07-24 23:45:04 +00:00
n int
2024-02-18 10:42:21 +00:00
}
// called from handler goroutines.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Notes that the handler for the given stream ID read n bytes of its body
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and schedules flow control tokens to be sent.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) noteBodyReadFromHandler ( st * stream , n int , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . checkNotOn ( ) // NOT on
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if n > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case sc . bodyReadCh <- bodyReadMsg { st , n } :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) noteBodyRead ( st * stream , n int ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( nil , n ) // conn-level
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . state != stateHalfClosedRemote && st . state != stateClosed {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Don't send this WINDOW_UPDATE if the stream is closed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// remotely.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( st , n )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// st may be nil for conn-level
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) sendWindowUpdate32 ( st * stream , n int32 ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . sendWindowUpdate ( st , int ( n ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// st may be nil for conn-level
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( sc * serverConn ) sendWindowUpdate ( st * stream , n int ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var streamID uint32
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var send int32
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
send = sc . inflow . add ( n )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
streamID = st . id
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
send = st . inflow . add ( n )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if send == 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . writeFrame ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
write : writeWindowUpdate { streamID : streamID , n : uint32 ( send ) } ,
2024-02-18 10:42:21 +00:00
stream : st ,
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// requestBody is the Handler's Request.Body type.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Read and Close may be called concurrently.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type requestBody struct {
2024-07-24 23:45:04 +00:00
_ incomparable
stream * stream
conn * serverConn
closeOnce sync . Once // for use by Close only
sawEOF bool // for use by Read only
pipe * pipe // non-nil if we have an HTTP entity message body
needsContinue bool // need to send a 100-continue
2024-02-18 10:42:21 +00:00
}
func ( b * requestBody ) Close ( ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
b . closeOnce . Do ( func ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if b . pipe != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
b . pipe . BreakWithError ( errClosedBody )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( b * requestBody ) Read ( p [ ] byte ) ( n int , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if b . needsContinue {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
b . needsContinue = false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
b . conn . write100ContinueHeaders ( b . stream )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if b . pipe == nil || b . sawEOF {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , io . EOF
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
n , err = b . pipe . Read ( p )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == io . EOF {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
b . sawEOF = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if b . conn == nil && inTests {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
b . conn . noteBodyReadFromHandler ( b . stream , n , err )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// responseWriter is the http.ResponseWriter implementation. It's
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// intentionally small (1 pointer wide) to minimize garbage. The
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// responseWriterState pointer inside is zeroed at the end of a
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// request (in handlerDone) and calls on the responseWriter thereafter
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// simply crash (caller's mistake), but the much larger responseWriterState
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and buffers are reused between multiple requests.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type responseWriter struct {
rws * responseWriterState
}
// Optional http.ResponseWriter interfaces implemented.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var (
_ http . CloseNotifier = ( * responseWriter ) ( nil )
2024-07-24 23:45:04 +00:00
_ http . Flusher = ( * responseWriter ) ( nil )
_ stringWriter = ( * responseWriter ) ( nil )
2024-02-18 10:42:21 +00:00
)
type responseWriterState struct {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// immutable within a request:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
stream * stream
2024-07-24 23:45:04 +00:00
req * http . Request
conn * serverConn
2024-02-18 10:42:21 +00:00
// TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
bw * bufio . Writer // writing to a chunkWriter{this *responseWriterState}
// mutated by http.Handler goroutine:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
handlerHeader http . Header // nil until called
2024-07-24 23:45:04 +00:00
snapHeader http . Header // snapshot of handlerHeader at WriteHeader time
trailers [ ] string // set in writeChunk
status int // status code passed to WriteHeader
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
sentHeader bool // have we sent the header frame?
handlerDone bool // handler has finished
2024-02-18 10:42:21 +00:00
sentContentLen int64 // non-zero if handler set a Content-Length header
2024-07-24 23:45:04 +00:00
wroteBytes int64
2024-02-18 10:42:21 +00:00
closeNotifierMu sync . Mutex // guards closeNotifierCh
2024-07-24 23:45:04 +00:00
closeNotifierCh chan bool // nil until first used
2024-02-18 10:42:21 +00:00
}
type chunkWriter struct { rws * responseWriterState }
func ( cw chunkWriter ) Write ( p [ ] byte ) ( n int , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
n , err = cw . rws . writeChunk ( p )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == errStreamClosed {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If writing failed because the stream has been closed,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// return the reason it was closed.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = cw . rws . stream . closeErr
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return n , err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( rws * responseWriterState ) hasTrailers ( ) bool { return len ( rws . trailers ) > 0 }
func ( rws * responseWriterState ) hasNonemptyTrailers ( ) bool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , trailer := range rws . trailers {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if _ , ok := rws . handlerHeader [ trailer ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// declareTrailer is called for each Trailer header when the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// response header is written. It notes that a header will need to be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// written in the trailers at the end of the response.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( rws * responseWriterState ) declareTrailer ( k string ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
k = http . CanonicalHeaderKey ( k )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! httpguts . ValidTrailerHeader ( k ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Forbidden by RFC 7230, section 4.1.2.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . conn . logf ( "ignoring invalid trailer %q" , k )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! strSliceContains ( rws . trailers , k ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . trailers = append ( rws . trailers , k )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// writeChunk writes chunks from the bufio.Writer. But because
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// bufio.Writer may bypass its chunking, sometimes p may be
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// arbitrarily large.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// writeChunk is also responsible (on the first chunk) for sending the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// HEADER response.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( rws * responseWriterState ) writeChunk ( p [ ] byte ) ( n int , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! rws . wroteHeader {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . writeHeader ( 200 )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if rws . handlerDone {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . promoteUndeclaredTrailers ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
isHeadResp := rws . req . Method == "HEAD"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! rws . sentHeader {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . sentHeader = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var ctype , clen string
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if clen = rws . snapHeader . Get ( "Content-Length" ) ; clen != "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . snapHeader . Del ( "Content-Length" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if cl , err := strconv . ParseUint ( clen , 10 , 63 ) ; err == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . sentContentLen = int64 ( cl )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
clen = ""
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
_ , hasContentLength := rws . snapHeader [ "Content-Length" ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! hasContentLength && clen == "" && rws . handlerDone && bodyAllowedForStatus ( rws . status ) && ( len ( p ) > 0 || ! isHeadResp ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
clen = strconv . Itoa ( len ( p ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
_ , hasContentType := rws . snapHeader [ "Content-Type" ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If the Content-Encoding is non-blank, we shouldn't
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// sniff the body. See Issue golang.org/issue/31753.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ce := rws . snapHeader . Get ( "Content-Encoding" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
hasCE := len ( ce ) > 0
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! hasCE && ! hasContentType && bodyAllowedForStatus ( rws . status ) && len ( p ) > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ctype = http . DetectContentType ( p )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var date string
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if _ , ok := rws . snapHeader [ "Date" ] ; ! ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO(bradfitz): be faster here, like net/http? measure.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
date = time . Now ( ) . UTC ( ) . Format ( http . TimeFormat )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
for _ , v := range rws . snapHeader [ "Trailer" ] {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
foreachHeaderElement ( v , rws . declareTrailer )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// "Connection" headers aren't allowed in HTTP/2 (RFC 7540, 8.1.2.2),
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// but respect "Connection" == "close" to mean sending a GOAWAY and tearing
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// down the TCP connection when idle, like we do for HTTP/1.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: remove more Connection-specific header fields here, in addition
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// to "Connection".
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if _ , ok := rws . snapHeader [ "Connection" ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
v := rws . snapHeader . Get ( "Connection" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
delete ( rws . snapHeader , "Connection" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if v == "close" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . conn . startGracefulShutdown ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
endStream := ( rws . handlerDone && ! rws . hasTrailers ( ) && len ( p ) == 0 ) || isHeadResp
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = rws . conn . writeHeaders ( rws . stream , & writeResHeaders {
2024-07-24 23:45:04 +00:00
streamID : rws . stream . id ,
httpResCode : rws . status ,
h : rws . snapHeader ,
endStream : endStream ,
contentType : ctype ,
2024-02-18 10:42:21 +00:00
contentLength : clen ,
2024-07-24 23:45:04 +00:00
date : date ,
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if endStream {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if isHeadResp {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return len ( p ) , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if len ( p ) == 0 && ! rws . handlerDone {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// only send trailers if they have actually been defined by the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// server handler.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
hasNonemptyTrailers := rws . hasNonemptyTrailers ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
endStream := rws . handlerDone && ! hasNonemptyTrailers
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if len ( p ) > 0 || endStream {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// only send a 0 byte DATA frame if we're ending the stream.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := rws . conn . writeDataFromHandler ( rws . stream , p , endStream ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if rws . handlerDone && hasNonemptyTrailers {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = rws . conn . writeHeaders ( rws . stream , & writeResHeaders {
2024-07-24 23:45:04 +00:00
streamID : rws . stream . id ,
h : rws . handlerHeader ,
trailers : rws . trailers ,
2024-02-18 10:42:21 +00:00
endStream : true ,
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return len ( p ) , err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return len ( p ) , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// that, if present, signals that the map entry is actually for
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the response trailers, and not the response headers. The prefix
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// is stripped after the ServeHTTP call finishes and the values are
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// sent in the trailers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This mechanism is intended only for trailers that are not known
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// prior to the headers being written. If the set of trailers is fixed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// or known before the header is written, the normal Go trailers mechanism
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// is preferred:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// https://golang.org/pkg/net/http/#ResponseWriter
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
const TrailerPrefix = "Trailer:"
// promoteUndeclaredTrailers permits http.Handlers to set trailers
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// after the header has already been flushed. Because the Go
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ResponseWriter interface has no way to set Trailers (only the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Header), and because we didn't want to expand the ResponseWriter
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// interface, and because nobody used trailers, and because RFC 7230
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// says you SHOULD (but not must) predeclare any trailers in the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// header, the official ResponseWriter rules said trailers in Go must
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// be predeclared, and then we reuse the same ResponseWriter.Header()
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// map to mean both Headers and Trailers. When it's time to write the
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Trailers, we pick out the fields of Headers that were declared as
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// trailers. That worked for a while, until we found the first major
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// user of Trailers in the wild: gRPC (using them only over http2),
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// and gRPC libraries permit setting trailers mid-stream without
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// predeclaring them. So: change of plans. We still permit the old
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// way, but we also permit this hack: if a Header() key begins with
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "Trailer:", the suffix of that key is a Trailer. Because ':' is an
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// invalid token byte anyway, there is no ambiguity. (And it's already
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// filtered out) It's mildly hacky, but not terrible.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// This method runs after the Handler is done and promotes any Header
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// fields to be trailers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( rws * responseWriterState ) promoteUndeclaredTrailers ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for k , vv := range rws . handlerHeader {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! strings . HasPrefix ( k , TrailerPrefix ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
continue
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
trailerKey := strings . TrimPrefix ( k , TrailerPrefix )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . declareTrailer ( trailerKey )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . handlerHeader [ http . CanonicalHeaderKey ( trailerKey ) ] = vv
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if len ( rws . trailers ) > 1 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sorter := sorterPool . Get ( ) . ( * sorter )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sorter . SortStrings ( rws . trailers )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sorterPool . Put ( sorter )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) SetReadDeadline ( deadline time . Time ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st := w . rws . stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! deadline . IsZero ( ) && deadline . Before ( time . Now ( ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If we're setting a deadline in the past, reset the stream immediately
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// so writes after SetWriteDeadline returns will fail.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . onReadTimeout ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
w . rws . conn . sendServeMsg ( func ( sc * serverConn ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . readDeadline != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! st . readDeadline . Stop ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Deadline already exceeded, or stream has been closed.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if deadline . IsZero ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . readDeadline = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else if st . readDeadline == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . readDeadline = time . AfterFunc ( deadline . Sub ( time . Now ( ) ) , st . onReadTimeout )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . readDeadline . Reset ( deadline . Sub ( time . Now ( ) ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) SetWriteDeadline ( deadline time . Time ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st := w . rws . stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! deadline . IsZero ( ) && deadline . Before ( time . Now ( ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// If we're setting a deadline in the past, reset the stream immediately
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// so writes after SetWriteDeadline returns will fail.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . onWriteTimeout ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
w . rws . conn . sendServeMsg ( func ( sc * serverConn ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . writeDeadline != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! st . writeDeadline . Stop ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Deadline already exceeded, or stream has been closed.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if deadline . IsZero ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . writeDeadline = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else if st . writeDeadline == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . writeDeadline = time . AfterFunc ( deadline . Sub ( time . Now ( ) ) , st . onWriteTimeout )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st . writeDeadline . Reset ( deadline . Sub ( time . Now ( ) ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) Flush ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
w . FlushError ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) FlushError ( ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := w . rws
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "Header called after Handler finished" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var err error
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws . bw . Buffered ( ) > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = rws . bw . Flush ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The bufio.Writer won't call chunkWriter.Write
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// (writeChunk with zero bytes), so we have to do it
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// ourselves to force the HTTP response header and/or
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// final DATA frame (with END_STREAM) to be sent.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
_ , err = chunkWriter { rws } . Write ( nil )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- rws . stream . cw :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
err = rws . stream . closeErr
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) CloseNotify ( ) <- chan bool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := w . rws
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "CloseNotify called after Handler finished" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . closeNotifierMu . Lock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ch := rws . closeNotifierCh
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ch == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ch = make ( chan bool , 1 )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . closeNotifierCh = ch
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
cw := rws . stream . cw
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go func ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
cw . Wait ( ) // wait for close
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
ch <- true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . closeNotifierMu . Unlock ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return ch
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) Header ( ) http . Header {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := w . rws
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "Header called after Handler finished" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws . handlerHeader == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . handlerHeader = make ( http . Header )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return rws . handlerHeader
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func checkWriteHeaderCode ( code int ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Issue 22880: require valid WriteHeader status codes.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// For now we only enforce that it's three digits.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// In the future we might block things over 599 (600 and above aren't defined
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// at http://httpwg.org/specs/rfc7231.html#status.codes).
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// But for now any three digits.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// no equivalent bogus thing we can realistically send in HTTP/2,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// so we'll consistently panic instead and help people find their bugs
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// early. (We can't return an error from WriteHeader even if we wanted to.)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if code < 100 || code > 999 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( fmt . Sprintf ( "invalid WriteHeader code %v" , code ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) WriteHeader ( code int ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := w . rws
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "WriteHeader called after Handler finished" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . writeHeader ( code )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( rws * responseWriterState ) writeHeader ( code int ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws . wroteHeader {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
checkWriteHeaderCode ( code )
// Handle informational headers
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if code >= 100 && code <= 199 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Per RFC 8297 we must not clear the current header map
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h := rws . handlerHeader
_ , cl := h [ "Content-Length" ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
_ , te := h [ "Transfer-Encoding" ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if cl || te {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h = h . Clone ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h . Del ( "Content-Length" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h . Del ( "Transfer-Encoding" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
rws . conn . writeHeaders ( rws . stream , & writeResHeaders {
2024-07-24 23:45:04 +00:00
streamID : rws . stream . id ,
2024-02-18 10:42:21 +00:00
httpResCode : code ,
2024-07-24 23:45:04 +00:00
h : h ,
endStream : rws . handlerDone && ! rws . hasTrailers ( ) ,
2024-02-18 10:42:21 +00:00
} )
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
rws . wroteHeader = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . status = code
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if len ( rws . handlerHeader ) > 0 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . snapHeader = cloneHeader ( rws . handlerHeader )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func cloneHeader ( h http . Header ) http . Header {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h2 := make ( http . Header , len ( h ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for k , vv := range h {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
vv2 := make ( [ ] string , len ( vv ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
copy ( vv2 , vv )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
h2 [ k ] = vv2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return h2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// The Life Of A Write is like this:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
//
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// * Handler calls w.Write or w.WriteString ->
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// * -> rws.bw (*bufio.Writer) ->
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// * (Handler might call Flush)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// * -> chunkWriter{rws}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// * -> responseWriterState.writeChunk(p []byte)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( w * responseWriter ) Write ( p [ ] byte ) ( n int , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return w . write ( len ( p ) , p , "" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) WriteString ( s string ) ( n int , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return w . write ( len ( s ) , nil , s )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// either dataB or dataS is non-zero.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func ( w * responseWriter ) write ( lenData int , dataB [ ] byte , dataS string ) ( n int , err error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := w . rws
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( "Write called after Handler finished" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! rws . wroteHeader {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
w . WriteHeader ( 200 )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! bodyAllowedForStatus ( rws . status ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , http . ErrBodyNotAllowed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . wroteBytes += int64 ( len ( dataB ) ) + int64 ( len ( dataS ) ) // only one can be set
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if rws . sentContentLen != 0 && rws . wroteBytes > rws . sentContentLen {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// TODO: send a RST_STREAM
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , errors . New ( "http2: handler wrote more than declared Content-Length" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if dataB != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return rws . bw . Write ( dataB )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return rws . bw . WriteString ( dataS )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( w * responseWriter ) handlerDone ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws := w . rws
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rws . handlerDone = true
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
w . Flush ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
w . rws = nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
responseWriterStatePool . Put ( rws )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Push errors.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var (
2024-07-24 23:45:04 +00:00
ErrRecursivePush = errors . New ( "http2: recursive push not allowed" )
2024-02-18 10:42:21 +00:00
ErrPushLimitReached = errors . New ( "http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS" )
)
var _ http . Pusher = ( * responseWriter ) ( nil )
func ( w * responseWriter ) Push ( target string , opts * http . PushOptions ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
st := w . rws . stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc := st . sc
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . checkNotOn ( )
// No recursive pushes: "PUSH_PROMISE frames MUST only be sent on a peer-initiated stream."
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http://tools.ietf.org/html/rfc7540#section-6.6
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if st . isPushed ( ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return ErrRecursivePush
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
if opts == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
opts = new ( http . PushOptions )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Default options.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if opts . Method == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
opts . Method = "GET"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if opts . Header == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
opts . Header = http . Header { }
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
wantScheme := "http"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if w . rws . req . TLS != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
wantScheme = "https"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// Validate the request.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
u , err := url . Parse ( target )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if u . Scheme == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! strings . HasPrefix ( target , "/" ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return fmt . Errorf ( "target must be an absolute URL or an absolute path: %q" , target )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
u . Scheme = wantScheme
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
u . Host = w . rws . req . Host
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
} else {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if u . Scheme != wantScheme {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return fmt . Errorf ( "cannot push URL with scheme %q from request with scheme %q" , u . Scheme , wantScheme )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if u . Host == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errors . New ( "URL must have a host" )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for k := range opts . Header {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if strings . HasPrefix ( k , ":" ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return fmt . Errorf ( "promised request headers cannot include pseudo header %q" , k )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// These headers are meaningful only if the request has a body,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// but PUSH_PROMISE requests cannot have a body.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http://tools.ietf.org/html/rfc7540#section-8.2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Also disallow Host, since the promised URL must be absolute.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if asciiEqualFold ( k , "content-length" ) ||
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
asciiEqualFold ( k , "content-encoding" ) ||
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
asciiEqualFold ( k , "trailer" ) ||
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
asciiEqualFold ( k , "te" ) ||
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
asciiEqualFold ( k , "expect" ) ||
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
asciiEqualFold ( k , "host" ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return fmt . Errorf ( "promised request headers cannot include %q" , k )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err := checkValidHTTP2RequestHeaders ( opts . Header ) ; err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// The RFC effectively limits promised requests to GET and HEAD:
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// "Promised requests MUST be cacheable [GET, HEAD, or POST], and MUST be safe [GET or HEAD]"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http://tools.ietf.org/html/rfc7540#section-8.2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if opts . Method != "GET" && opts . Method != "HEAD" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return fmt . Errorf ( "method %q must be GET or HEAD" , opts . Method )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
msg := & startPushRequest {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
parent : st ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
method : opts . Method ,
2024-07-24 23:45:04 +00:00
url : u ,
2024-02-18 10:42:21 +00:00
header : cloneHeader ( opts . Header ) ,
2024-07-24 23:45:04 +00:00
done : errChanPool . Get ( ) . ( chan error ) ,
2024-02-18 10:42:21 +00:00
}
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errClientDisconnected
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- st . cw :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errStreamClosed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case sc . serveMsgCh <- msg :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
select {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- sc . doneServing :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errClientDisconnected
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case <- st . cw :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errStreamClosed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case err := <- msg . done :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
errChanPool . Put ( msg . done )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
type startPushRequest struct {
parent * stream
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
method string
2024-07-24 23:45:04 +00:00
url * url . URL
2024-02-18 10:42:21 +00:00
header http . Header
2024-07-24 23:45:04 +00:00
done chan error
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) startPush ( msg * startPushRequest ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
// http://tools.ietf.org/html/rfc7540#section-6.6.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// is in either the "open" or "half-closed (remote)" state.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if msg . parent . state != stateOpen && msg . parent . state != stateHalfClosedRemote {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// responseWriter.Push checks that the stream is peer-initiated.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
msg . done <- errStreamClosed
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// http://tools.ietf.org/html/rfc7540#section-6.6.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . pushEnabled {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
msg . done <- http . ErrNotSupported
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// PUSH_PROMISE frames must be sent in increasing order by stream ID, so
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// we allocate an ID for the promised stream lazily, when the PUSH_PROMISE
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// is written. Once the ID is allocated, we start the request handler.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
allocatePromisedID := func ( ) ( uint32 , error ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . serveG . check ( )
// Check this again, just in case. Technically, we might have received
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// an updated SETTINGS by the time we got around to writing this frame.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! sc . pushEnabled {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , http . ErrNotSupported
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// http://tools.ietf.org/html/rfc7540#section-6.5.2.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . curPushedStreams + 1 > sc . clientMaxStreams {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , ErrPushLimitReached
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// http://tools.ietf.org/html/rfc7540#section-5.1.1.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Streams initiated by the server MUST use even-numbered identifiers.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// A server that is unable to establish a new stream identifier can send a GOAWAY
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// frame so that the client is forced to open a new connection for new streams.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc . maxPushPromiseID + 2 >= 1 << 31 {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . startGracefulShutdownInternal ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return 0 , ErrPushLimitReached
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
sc . maxPushPromiseID += 2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
promisedID := sc . maxPushPromiseID
// http://tools.ietf.org/html/rfc7540#section-8.2.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Strictly speaking, the new stream should start in "reserved (local)", then
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// transition to "half closed (remote)" after sending the initial HEADERS, but
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// we start in "half closed (remote)" for simplicity.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// See further comments at the definition of stateHalfClosedRemote.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
promised := sc . newStream ( promisedID , msg . parent . id , stateHalfClosedRemote )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
rw , req , err := sc . newWriterAndRequestNoBody ( promised , requestParam {
2024-07-24 23:45:04 +00:00
method : msg . method ,
scheme : msg . url . Scheme ,
2024-02-18 10:42:21 +00:00
authority : msg . url . Host ,
2024-07-24 23:45:04 +00:00
path : msg . url . RequestURI ( ) ,
header : cloneHeader ( msg . header ) , // clone since handler runs concurrently with writing the PUSH_PROMISE
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if err != nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// Should not happen, since we've already validated msg.url.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
panic ( fmt . Sprintf ( "newWriterAndRequestNoBody(%+v): %v" , msg . url , err ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
sc . curHandlers ++
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
go sc . runHandler ( rw , req , sc . handler . ServeHTTP )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return promisedID , nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
sc . writeFrame ( FrameWriteRequest {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
write : & writePushPromise {
2024-07-24 23:45:04 +00:00
streamID : msg . parent . id ,
method : msg . method ,
url : msg . url ,
h : msg . header ,
2024-02-18 10:42:21 +00:00
allocatePromisedID : allocatePromisedID ,
} ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
stream : msg . parent ,
2024-07-24 23:45:04 +00:00
done : msg . done ,
2024-02-18 10:42:21 +00:00
} )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// foreachHeaderElement splits v according to the "#rule" construction
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// in RFC 7230 section 7 and calls fn for each non-empty element.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func foreachHeaderElement ( v string , fn func ( string ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
v = textproto . TrimString ( v )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if v == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if ! strings . Contains ( v , "," ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
fn ( v )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , f := range strings . Split ( v , "," ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f = textproto . TrimString ( f ) ; f != "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
fn ( f )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var connHeaders = [ ] string {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
"Connection" ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
"Keep-Alive" ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
"Proxy-Connection" ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
"Transfer-Encoding" ,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
"Upgrade" ,
}
// checkValidHTTP2RequestHeaders checks whether h is a valid HTTP/2 request,
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// per RFC 7540 Section 8.1.2.2.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// The returned error is reported to users.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func checkValidHTTP2RequestHeaders ( h http . Header ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
for _ , k := range connHeaders {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if _ , ok := h [ k ] ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return fmt . Errorf ( "request header %q is not valid in HTTP/2" , k )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
te := h [ "Te" ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if len ( te ) > 0 && ( len ( te ) > 1 || ( te [ 0 ] != "trailers" && te [ 0 ] != "" ) ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return errors . New ( ` request header "TE" may only be "trailers" in HTTP/2 ` )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return nil
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func new400Handler ( err error ) http . HandlerFunc {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return func ( w http . ResponseWriter , r * http . Request ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
http . Error ( w , err . Error ( ) , http . StatusBadRequest )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// disabled. See comments on h1ServerShutdownChan above for why
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
// the code is written this way.
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
func h1ServerKeepAlivesDisabled ( hs * http . Server ) bool {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var x interface { } = hs
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
type I interface {
doKeepAlives ( ) bool
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if hs , ok := x . ( I ) ; ok {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return ! hs . doKeepAlives ( )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return false
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
func ( sc * serverConn ) countError ( name string , err error ) error {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if sc == nil || sc . srv == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
f := sc . srv . CountError
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if f == nil {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var typ string
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
var code ErrCode
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
switch e := err . ( type ) {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case ConnectionError :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
typ = "conn"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
code = ErrCode ( e )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
case StreamError :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
typ = "stream"
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
code = ErrCode ( e . Code )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
default :
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
codeStr := errCodeName [ code ]
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
if codeStr == "" {
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
codeStr = strconv . Itoa ( int ( code ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
f ( fmt . Sprintf ( "%s_%s_%s" , typ , codeStr , name ) )
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
return err
2024-07-24 23:45:04 +00:00
2024-02-18 10:42:21 +00:00
}