-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathserver_wrap.go
More file actions
201 lines (177 loc) · 6.55 KB
/
Copy pathserver_wrap.go
File metadata and controls
201 lines (177 loc) · 6.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.27 && !http2legacy
// Server wrapping a net/http.Server.
package http2
import (
"context"
"errors"
"net"
"net/http"
"sync"
"time"
)
type serverInternalState struct {
s1 *http.Server
initOnce sync.Once
serveConnFunc func(context.Context, net.Conn, http.Handler, bool, *http.Request, []byte)
}
func configureServer(s *http.Server, conf *Server) error {
if s == nil {
panic("nil *http.Server")
}
if conf == nil {
conf = new(Server)
}
if conf.state != nil {
// This isn't a panic in the pre-wrapping implementation,
// but calling ConfigureServer twice with the same http2.Server
// overwrites internal state on the server.
// Make the error explicit and early here.
panic("ConfigureServer may be called only once per Server")
}
if h1, h2 := s, conf; h2.IdleTimeout == 0 {
if h1.IdleTimeout != 0 {
h2.IdleTimeout = h1.IdleTimeout
} else {
h2.IdleTimeout = h1.ReadTimeout
}
}
conf.state = &serverInternalState{
s1: s,
}
sconfig := &serverConfig{s: conf}
if err := s.Serve(sconfig); err != nil || sconfig.serveConnFunc == nil {
panic("http2: net/http does not support this version of x/net/http2")
}
conf.state.serveConnFunc = sconfig.serveConnFunc
return nil
}
type serverConfig struct {
s *Server
serveConnFunc func(context.Context, net.Conn, http.Handler, bool, *http.Request, []byte)
}
func (*serverConfig) Accept() (net.Conn, error) {
return nil, errors.New("unexpected call to Accept")
}
func (*serverConfig) Close() error {
return nil
}
func (*serverConfig) Addr() net.Addr {
return nil
}
func (s *serverConfig) ServeConnFunc(f func(context.Context, net.Conn, http.Handler, bool, *http.Request, []byte)) {
s.serveConnFunc = f
}
func (s *serverConfig) HTTP2Config() http.HTTP2Config {
return http.HTTP2Config{
MaxConcurrentStreams: int(s.s.MaxConcurrentStreams),
MaxDecoderHeaderTableSize: int(s.s.MaxDecoderHeaderTableSize),
MaxEncoderHeaderTableSize: int(s.s.MaxEncoderHeaderTableSize),
MaxReadFrameSize: int(s.s.MaxReadFrameSize),
PermitProhibitedCipherSuites: s.s.PermitProhibitedCipherSuites,
MaxReceiveBufferPerConnection: int(s.s.MaxUploadBufferPerConnection),
MaxReceiveBufferPerStream: int(s.s.MaxUploadBufferPerStream),
SendPingTimeout: s.s.ReadIdleTimeout,
PingTimeout: s.s.PingTimeout,
WriteByteTimeout: s.s.WriteByteTimeout,
CountError: s.s.CountError,
}
}
func (s *serverConfig) IdleTimeout() time.Duration {
return s.s.IdleTimeout
}
type serverConn struct{}
func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, _ func(*serverConn)) {
var serveConnFunc func(context.Context, net.Conn, http.Handler, bool, *http.Request, []byte)
switch {
case opts.BaseConfig != nil:
// The user has provided us with an http.Server to take configuration from.
//
// We can't send our request to opts.BaseConfig, because an http.Server can
// only be associated with a single http2.Server and the user might
// use this one with several http.Servers.
//
// We can't send our request to s.state.s1, because it doesn't contain
// the right configuration.
//
// So create a one-off copy of opts.BaseConfig and use it.
h1 := &http.Server{
TLSConfig: opts.BaseConfig.TLSConfig,
ReadTimeout: opts.BaseConfig.ReadTimeout,
ReadHeaderTimeout: opts.BaseConfig.ReadHeaderTimeout,
WriteTimeout: opts.BaseConfig.WriteTimeout,
IdleTimeout: opts.BaseConfig.IdleTimeout,
MaxHeaderBytes: opts.BaseConfig.MaxHeaderBytes,
ConnState: opts.BaseConfig.ConnState,
ErrorLog: opts.BaseConfig.ErrorLog,
BaseContext: opts.BaseConfig.BaseContext,
ConnContext: opts.BaseConfig.ConnContext,
HTTP2: opts.BaseConfig.HTTP2,
}
sconfig := &serverConfig{s: s}
if err := h1.Serve(sconfig); err != nil || sconfig.serveConnFunc == nil {
panic("http2: net/http does not support this version of x/net/http2")
}
serveConnFunc = sconfig.serveConnFunc
case s.state != nil:
serveConnFunc = s.state.serveConnFunc
default:
// Strange-but-true: Server has no concurrency-safe way to initialize
// its internal state, so historically ServeConn just doesn't use any
// persistent state if you don't call ConfigureServer first.
//
// If ConfigureServer hasn't been called, create a one-off http.Server
// for the connection, since we don't have any way to keep one around for reuse.
h1 := &http.Server{}
sconfig := &serverConfig{s: s}
if err := h1.Serve(sconfig); err != nil || sconfig.serveConnFunc == nil {
panic("http2: net/http does not support this version of x/net/http2")
}
serveConnFunc = sconfig.serveConnFunc
}
ctx, cancel := serverConnBaseContext(c, opts)
defer cancel()
serveConnFunc(ctx, c, opts.handler(), opts.SawClientPreface, opts.UpgradeRequest, opts.Settings)
}
// FrameWriteRequest is a request to write a frame.
//
// Deprecated: User-provided write schedulers are deprecated.
type FrameWriteRequest struct {
// Ideally we'd define this in writesched_common.go,
// to avoid duplicating an exported symbol across two files,
// but the changes required to make this work are fairly large.
}
func (wr FrameWriteRequest) StreamID() uint32 {
return 0
}
func (wr FrameWriteRequest) DataSize() int {
return 0
}
func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int) {
return FrameWriteRequest{}, FrameWriteRequest{}, 0
}
func (wr FrameWriteRequest) String() string {
return ""
}
// NewPriorityWriteScheduler is deprecated.
//
// Deprecated: User-provided write schedulers are deprecated.
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
return unsupportedWriteScheduler{}
}
// NewRandomWriteScheduler is deprecated.
//
// Deprecated: User-provided write schedulers are deprecated.
func NewRandomWriteScheduler() WriteScheduler {
return unsupportedWriteScheduler{}
}
type unsupportedWriteScheduler struct{}
func (unsupportedWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {}
func (unsupportedWriteScheduler) CloseStream(streamID uint32) {}
func (unsupportedWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {}
func (unsupportedWriteScheduler) Push(wr FrameWriteRequest) {}
func (unsupportedWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
return FrameWriteRequest{}, false
}