blob: 94d354d6cafef60c8d85d299ab49186984e84b82 [file] [log] [blame]
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
5// Licensed under the same terms as Go itself:
6// https://code.google.com/p/go/source/browse/LICENSE
7
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08008// TODO: replace all <-sc.doneServing with reads from the stream's cw
9// instead, and make sure that on close we close all open
10// streams. then remove doneServing?
11
Brad Fitzpatrickb331b812014-11-13 11:51:54 -080012package http2
13
14import (
Brad Fitzpatrick390047e2014-11-14 20:37:08 -080015 "bufio"
Brad Fitzpatrickb331b812014-11-13 11:51:54 -080016 "bytes"
17 "crypto/tls"
18 "errors"
19 "fmt"
20 "io"
21 "log"
22 "net"
23 "net/http"
24 "net/url"
25 "strconv"
26 "strings"
Brad Fitzpatrick729bd722014-11-13 14:09:36 -080027 "sync"
Brad Fitzpatrick95842032014-11-15 09:47:42 -080028 "time"
Brad Fitzpatrickb331b812014-11-13 11:51:54 -080029
30 "github.com/bradfitz/http2/hpack"
31)
32
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -080033const (
Brad Fitzpatrick9581fe12014-11-28 13:51:46 -080034 prefaceTimeout = 10 * time.Second
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -080035 firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
36 handlerChunkWriteSize = 4 << 10
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -080037 defaultMaxStreams = 250
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -080038)
39
40var (
41 errClientDisconnected = errors.New("client disconnected")
42 errClosedBody = errors.New("body closed by handler")
Brad Fitzpatrick4c687c62014-11-23 00:07:43 -080043 errStreamBroken = errors.New("http2: stream broken")
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -080044)
45
46var responseWriterStatePool = sync.Pool{
47 New: func() interface{} {
48 rws := &responseWriterState{}
49 rws.bw = bufio.NewWriterSize(chunkWriter{rws}, handlerChunkWriteSize)
50 return rws
51 },
52}
53
54// Test hooks.
55var (
56 testHookOnConn func()
57 testHookGetServerConn func(*serverConn)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -080058)
59
60// TODO: finish GOAWAY support. Consider each incoming frame type and
61// whether it should be ignored during a shutdown race.
62
63// TODO: (edge case?) if peer sends a SETTINGS frame with e.g. a
64// SETTINGS_MAX_FRAME_SIZE that's lower than what we had before,
65// before we ACK it we have to make sure all currently-active streams
66// know about that and don't have existing too-large frames in flight?
67// Perhaps the settings processing should just wait for new frame to
68// be in-flight and then the frame scheduler in the serve goroutine
69// will be responsible for splitting things.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -080070
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -080071// TODO: send PING frames to idle clients and disconnect them if no
72// reply
73
Brad Fitzpatrick165c0982014-11-26 08:53:01 -080074// TODO: for bonus points: turn off the serve goroutine when idle, so
75// an idle conn only has the readFrames goroutine active. (which could
76// also be optimized probably to pin less memory in crypto/tls). This
77// would involve tracking when the serve goroutine is active (atomic
78// int32 read/CAS probably?) and starting it up when frames arrive,
79// and shutting it down when all handlers exit. the occasional PING
80// packets could use time.AfterFunc to call sc.wakeStartServeLoop()
81// (which is a no-op if already running) and then queue the PING write
82// as normal. The serve loop would then exit in most cases (if no
83// Handlers running) and not be woken up again until the PING packet
84// returns.
Brad Fitzpatrickfef99e62014-11-20 18:14:02 -080085
Brad Fitzpatrickb331b812014-11-13 11:51:54 -080086// Server is an HTTP/2 server.
87type Server struct {
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -080088 // MaxHandlers limits the number of http.Handler ServeHTTP goroutines
89 // which may run at a time over all connections.
90 // Negative or zero no limit.
91 // TODO: implement
92 MaxHandlers int
93
94 // MaxConcurrentStreams optionally specifies the number of
95 // concurrent streams that each client may have open at a
96 // time. This is unrelated to the number of http.Handler goroutines
97 // which may be active globally, which is MaxHandlers.
98 // If zero, MaxConcurrentStreams defaults to at least 100, per
99 // the HTTP/2 spec's recommendations.
100 MaxConcurrentStreams uint32
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800101
102 // MaxReadFrameSize optionally specifies the largest frame
103 // this server is willing to read. A valid value is between
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800104 // 16k and 16M, inclusive. If zero or otherwise invalid, a
105 // default value is used.
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800106 MaxReadFrameSize uint32
107}
108
109func (s *Server) maxReadFrameSize() uint32 {
110 if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
111 return v
112 }
113 return defaultMaxReadFrameSize
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800114}
115
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800116func (s *Server) maxConcurrentStreams() uint32 {
117 if v := s.MaxConcurrentStreams; v > 0 {
118 return v
119 }
120 return defaultMaxStreams
121}
122
Brad Fitzpatrickb5469d22014-11-13 12:17:52 -0800123// ConfigureServer adds HTTP/2 support to a net/http Server.
124//
125// The configuration conf may be nil.
126//
127// ConfigureServer must be called before s begins serving.
128func ConfigureServer(s *http.Server, conf *Server) {
129 if conf == nil {
130 conf = new(Server)
131 }
132 if s.TLSConfig == nil {
133 s.TLSConfig = new(tls.Config)
134 }
135 haveNPN := false
136 for _, p := range s.TLSConfig.NextProtos {
Brad Fitzpatrick36d9a672014-11-26 07:40:15 -0800137 if p == NextProtoTLS {
Brad Fitzpatrickb5469d22014-11-13 12:17:52 -0800138 haveNPN = true
139 break
140 }
141 }
142 if !haveNPN {
Brad Fitzpatrick36d9a672014-11-26 07:40:15 -0800143 s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
Brad Fitzpatrickb5469d22014-11-13 12:17:52 -0800144 }
145
146 if s.TLSNextProto == nil {
147 s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
148 }
Brad Fitzpatrick36d9a672014-11-26 07:40:15 -0800149 s.TLSNextProto[NextProtoTLS] = func(hs *http.Server, c *tls.Conn, h http.Handler) {
Brad Fitzpatrickb5469d22014-11-13 12:17:52 -0800150 if testHookOnConn != nil {
151 testHookOnConn()
152 }
153 conf.handleConn(hs, c, h)
154 }
155}
156
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800157func (srv *Server) handleConn(hs *http.Server, c net.Conn, h http.Handler) {
158 sc := &serverConn{
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800159 srv: srv,
160 hs: hs,
161 conn: c,
162 bw: newBufferedWriter(c),
163 handler: h,
164 streams: make(map[uint32]*stream),
165 readFrameCh: make(chan frameAndGate),
166 readFrameErrCh: make(chan error, 1), // must be buffered for 1
167 wantWriteFrameCh: make(chan frameWriteMsg, 8),
168 wroteFrameCh: make(chan struct{}, 1), // buffered; one send in reading goroutine
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -0800169 bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800170 doneServing: make(chan struct{}),
171 advMaxStreams: srv.maxConcurrentStreams(),
172 writeSched: writeScheduler{
173 maxFrameSize: initialMaxFrameSize,
174 },
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800175 initialWindowSize: initialWindowSize,
176 headerTableSize: initialHeaderTableSize,
177 serveG: newGoroutineLock(),
178 pushEnabled: true,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800179 }
Brad Fitzpatrick98766182014-12-02 10:30:08 -0800180 sc.flow.add(initialWindowSize)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800181 sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
182 sc.hpackDecoder = hpack.NewDecoder(initialHeaderTableSize, sc.onNewHeaderField)
Brad Fitzpatrick5e4e2dc2014-11-19 16:49:43 -0800183
184 fr := NewFramer(sc.bw, c)
185 fr.SetMaxReadFrameSize(srv.maxReadFrameSize())
186 sc.framer = fr
187
Brad Fitzpatrick0db6d652014-11-15 15:49:19 -0800188 if hook := testHookGetServerConn; hook != nil {
189 hook(sc)
190 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800191 sc.serve()
192}
193
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800194// frameAndGates coordinates the readFrames and serve
195// goroutines. Because the Framer interface only permits the most
196// recently-read Frame from being accessed, the readFrames goroutine
197// blocks until it has a frame, passes it to serve, and then waits for
198// serve to be done with it before reading the next one.
199type frameAndGate struct {
200 f Frame
201 g gate
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800202}
203
204type serverConn struct {
205 // Immutable:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800206 srv *Server
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800207 hs *http.Server
208 conn net.Conn
Brad Fitzpatrick5e4e2dc2014-11-19 16:49:43 -0800209 bw *bufferedWriter // writing to conn
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800210 handler http.Handler
211 framer *Framer
212 hpackDecoder *hpack.Decoder
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800213 doneServing chan struct{} // closed when serverConn.serve ends
214 readFrameCh chan frameAndGate // written by serverConn.readFrames
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800215 readFrameErrCh chan error
216 wantWriteFrameCh chan frameWriteMsg // from handlers -> serve
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800217 wroteFrameCh chan struct{} // from writeFrameAsync -> serve, tickles more frame writes
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -0800218 bodyReadCh chan bodyReadMsg // from handlers -> serve
Brad Fitzpatrick0db6d652014-11-15 15:49:19 -0800219 testHookCh chan func() // code to run on the serve loop
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800220 flow flow // connection-wide (not stream-specific) flow control
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800221
222 // Everything following is owned by the serve loop; use serveG.check():
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800223 serveG goroutineLock // used to verify funcs are on serve()
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800224 pushEnabled bool
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800225 sawFirstSettings bool // got the initial SETTINGS frame after the preface
226 needToSendSettingsAck bool
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -0800227 unackedSettings int // how many SETTINGS have we sent without ACKs?
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800228 clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
229 advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
230 curOpenStreams uint32 // client's number of open streams
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800231 maxStreamID uint32 // max ever seen
232 streams map[uint32]*stream
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800233 initialWindowSize int32
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800234 headerTableSize uint32
235 maxHeaderListSize uint32 // zero means unknown (default)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800236 canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800237 req requestParam // non-zero while reading request headers
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800238 writingFrame bool // started write goroutine but haven't heard back on wroteFrameCh
239 needsFrameFlush bool // last frame write wasn't a flush
Brad Fitzpatricka13c4a42014-11-27 17:47:29 -0800240 writeSched writeScheduler
241 inGoAway bool // we've started to or sent GOAWAY
242 needToSendGoAway bool // we need to schedule a GOAWAY frame write
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800243 goAwayCode ErrCode
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800244 shutdownTimerCh <-chan time.Time // nil until used
245 shutdownTimer *time.Timer // nil until used
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800246
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800247 // Owned by the writeFrameAsync goroutine:
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800248 headerWriteBuf bytes.Buffer
249 hpackEncoder *hpack.Encoder
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800250}
251
252// requestParam is the state of the next request, initialized over
253// potentially several frames HEADERS + zero or more CONTINUATION
254// frames.
255type requestParam struct {
256 // stream is non-nil if we're reading (HEADER or CONTINUATION)
257 // frames for a request (but not DATA).
258 stream *stream
259 header http.Header
260 method, path string
261 scheme, authority string
262 sawRegularHeader bool // saw a non-pseudo header already
263 invalidHeader bool // an invalid header was seen
264}
265
Gabriel Aszalos1aa5b312014-11-19 16:56:22 +0000266// stream represents a stream. This is the minimal metadata needed by
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800267// the serve goroutine. Most of the actual stream state is owned by
268// the http.Handler's goroutine in the responseWriter. Because the
269// responseWriter's responseWriterState is recycled at the end of a
270// handler, this struct intentionally has no pointer to the
271// *responseWriter{,State} itself, as the Handler ending nils out the
272// responseWriter's state field.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800273type stream struct {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800274 // immutable:
275 id uint32
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800276 flow flow // limits writing from Handler to client
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800277 body *pipe // non-nil if expecting DATA frames
278 cw closeWaiter // closed wait stream transitions to closed state
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800279
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800280 // owned by serverConn's serve loop:
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -0800281 parent *stream // or nil
282 weight uint8
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800283 state streamState
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800284 bodyBytes int64 // body bytes seen so far
285 declBodyBytes int64 // or -1 if undeclared
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800286 sentReset bool // only true once detached from streams map
287 gotReset bool // only true once detacted from streams map
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800288}
289
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800290func (sc *serverConn) Framer() *Framer { return sc.framer }
291func (sc *serverConn) CloseConn() error { return sc.conn.Close() }
292func (sc *serverConn) Flush() error { return sc.bw.Flush() }
293func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
294 return sc.hpackEncoder, &sc.headerWriteBuf
295}
296
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800297func (sc *serverConn) state(streamID uint32) streamState {
298 sc.serveG.check()
299 // http://http2.github.io/http2-spec/#rfc.section.5.1
300 if st, ok := sc.streams[streamID]; ok {
301 return st.state
302 }
303 // "The first use of a new stream identifier implicitly closes all
304 // streams in the "idle" state that might have been initiated by
305 // that peer with a lower-valued stream identifier. For example, if
306 // a client sends a HEADERS frame on stream 7 without ever sending a
307 // frame on stream 5, then stream 5 transitions to the "closed"
308 // state when the first frame for stream 7 is sent or received."
309 if streamID <= sc.maxStreamID {
310 return stateClosed
311 }
312 return stateIdle
313}
314
315func (sc *serverConn) vlogf(format string, args ...interface{}) {
316 if VerboseLogs {
317 sc.logf(format, args...)
318 }
319}
320
321func (sc *serverConn) logf(format string, args ...interface{}) {
322 if lg := sc.hs.ErrorLog; lg != nil {
323 lg.Printf(format, args...)
324 } else {
325 log.Printf(format, args...)
326 }
327}
328
329func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
330 if err == nil {
331 return
332 }
333 str := err.Error()
Brad Fitzpatrick95842032014-11-15 09:47:42 -0800334 if err == io.EOF || strings.Contains(str, "use of closed network connection") {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800335 // Boring, expected errors.
336 sc.vlogf(format, args...)
337 } else {
338 sc.logf(format, args...)
339 }
340}
341
342func (sc *serverConn) onNewHeaderField(f hpack.HeaderField) {
343 sc.serveG.check()
344 switch {
345 case !validHeader(f.Name):
346 sc.req.invalidHeader = true
347 case strings.HasPrefix(f.Name, ":"):
348 if sc.req.sawRegularHeader {
349 sc.logf("pseudo-header after regular header")
350 sc.req.invalidHeader = true
351 return
352 }
353 var dst *string
354 switch f.Name {
355 case ":method":
356 dst = &sc.req.method
357 case ":path":
358 dst = &sc.req.path
359 case ":scheme":
360 dst = &sc.req.scheme
361 case ":authority":
362 dst = &sc.req.authority
363 default:
364 // 8.1.2.1 Pseudo-Header Fields
365 // "Endpoints MUST treat a request or response
366 // that contains undefined or invalid
367 // pseudo-header fields as malformed (Section
368 // 8.1.2.6)."
369 sc.logf("invalid pseudo-header %q", f.Name)
370 sc.req.invalidHeader = true
371 return
372 }
373 if *dst != "" {
374 sc.logf("duplicate pseudo-header %q sent", f.Name)
375 sc.req.invalidHeader = true
376 return
377 }
378 *dst = f.Value
379 case f.Name == "cookie":
380 sc.req.sawRegularHeader = true
381 if s, ok := sc.req.header["Cookie"]; ok && len(s) == 1 {
382 s[0] = s[0] + "; " + f.Value
383 } else {
384 sc.req.header.Add("Cookie", f.Value)
385 }
386 default:
387 sc.req.sawRegularHeader = true
388 sc.req.header.Add(sc.canonicalHeader(f.Name), f.Value)
389 }
390}
391
392func (sc *serverConn) canonicalHeader(v string) string {
393 sc.serveG.check()
Brad Fitzpatrick6520e262014-11-15 09:36:47 -0800394 cv, ok := commonCanonHeader[v]
395 if ok {
396 return cv
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800397 }
Brad Fitzpatrick6520e262014-11-15 09:36:47 -0800398 cv, ok = sc.canonHeader[v]
399 if ok {
400 return cv
401 }
402 if sc.canonHeader == nil {
403 sc.canonHeader = make(map[string]string)
404 }
405 cv = http.CanonicalHeaderKey(v)
406 sc.canonHeader[v] = cv
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800407 return cv
408}
409
410// readFrames is the loop that reads incoming frames.
411// It's run on its own goroutine.
412func (sc *serverConn) readFrames() {
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800413 g := make(gate, 1)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800414 for {
415 f, err := sc.framer.ReadFrame()
416 if err != nil {
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800417 sc.readFrameErrCh <- err
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800418 close(sc.readFrameCh)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800419 return
420 }
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800421 sc.readFrameCh <- frameAndGate{f, g}
Brad Fitzpatrickb0a06c82014-11-26 09:21:28 -0800422 // We can't read another frame until this one is
423 // processed, as the ReadFrame interface doesn't copy
424 // memory. The Frame accessor methods access the last
425 // frame's (shared) buffer. So we wait for the
426 // serve goroutine to tell us it's done:
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800427 g.Wait()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800428 }
429}
430
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800431// writeFrameAsync runs in its own goroutine and writes a single frame
432// and then reports when it's done.
433// At most one goroutine can be running writeFrameAsync at a time per
434// serverConn.
435func (sc *serverConn) writeFrameAsync(wm frameWriteMsg) {
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800436 err := wm.write.writeFrame(sc)
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800437 if ch := wm.done; ch != nil {
438 select {
439 case ch <- err:
440 default:
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800441 panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.write))
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800442 }
443 }
444 sc.wroteFrameCh <- struct{}{} // tickle frame selection scheduler
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800445}
446
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -0800447func (sc *serverConn) closeAllStreamsOnConnClose() {
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800448 sc.serveG.check()
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800449 for _, st := range sc.streams {
450 sc.closeStream(st, errClientDisconnected)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800451 }
452}
453
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800454func (sc *serverConn) stopShutdownTimer() {
455 sc.serveG.check()
456 if t := sc.shutdownTimer; t != nil {
457 t.Stop()
458 }
459}
460
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800461func (sc *serverConn) serve() {
462 sc.serveG.check()
463 defer sc.conn.Close()
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -0800464 defer sc.closeAllStreamsOnConnClose()
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800465 defer sc.stopShutdownTimer()
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800466 defer close(sc.doneServing) // unblocks handlers trying to send
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800467
468 sc.vlogf("HTTP/2 connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
469
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800470 sc.writeFrame(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800471 write: writeSettings{
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800472 {SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
473 {SettingMaxConcurrentStreams, sc.advMaxStreams},
Brad Fitzpatrick953b5112014-12-06 17:59:01 -0800474
475 // TODO: more actual settings, notably
476 // SettingInitialWindowSize, but then we also
477 // want to bump up the conn window size the
478 // same amount here right after the settings
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800479 },
480 })
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -0800481 sc.unackedSettings++
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800482
483 if err := sc.readPreface(); err != nil {
gbbrd90e0982014-11-20 22:19:20 +0000484 sc.condlogf(err, "error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800485 return
486 }
487
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800488 go sc.readFrames() // closed by defer sc.conn.Close above
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800489
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800490 settingsTimer := time.NewTimer(firstSettingsTimeout)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800491 for {
492 select {
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800493 case wm := <-sc.wantWriteFrameCh:
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800494 sc.writeFrame(wm)
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800495 case <-sc.wroteFrameCh:
496 sc.writingFrame = false
497 sc.scheduleFrameWrite()
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800498 case fg, ok := <-sc.readFrameCh:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800499 if !ok {
500 sc.readFrameCh = nil
501 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800502 if !sc.processFrameFromReader(fg, ok) {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800503 return
504 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800505 if settingsTimer.C != nil {
506 settingsTimer.Stop()
507 settingsTimer.C = nil
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800508 }
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -0800509 case m := <-sc.bodyReadCh:
510 sc.noteBodyRead(m.st, m.n)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800511 case <-settingsTimer.C:
512 sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
513 return
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800514 case <-sc.shutdownTimerCh:
515 sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
516 return
Brad Fitzpatrick0db6d652014-11-15 15:49:19 -0800517 case fn := <-sc.testHookCh:
518 fn()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800519 }
520 }
521}
522
Brad Fitzpatrick95842032014-11-15 09:47:42 -0800523// readPreface reads the ClientPreface greeting from the peer
524// or returns an error on timeout or an invalid greeting.
525func (sc *serverConn) readPreface() error {
526 errc := make(chan error, 1)
527 go func() {
528 // Read the client preface
529 buf := make([]byte, len(ClientPreface))
Brad Fitzpatrick95842032014-11-15 09:47:42 -0800530 if _, err := io.ReadFull(sc.conn, buf); err != nil {
531 errc <- err
532 } else if !bytes.Equal(buf, clientPreface) {
533 errc <- fmt.Errorf("bogus greeting %q", buf)
534 } else {
535 errc <- nil
536 }
537 }()
538 timer := time.NewTimer(5 * time.Second) // TODO: configurable on *Server?
539 defer timer.Stop()
540 select {
541 case <-timer.C:
542 return errors.New("timeout waiting for client preface")
543 case err := <-errc:
544 if err == nil {
545 sc.vlogf("client %v said hello", sc.conn.RemoteAddr())
546 }
547 return err
548 }
549}
550
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800551// writeDataFromHandler writes the data described in req to stream.id.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800552//
553// The provided ch is used to avoid allocating new channels for each
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800554// write operation. It's expected that the caller reuses writeData and ch
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800555// over time.
Brad Fitzpatrick1797e702014-11-26 10:43:20 -0800556//
557// The flow control currently happens in the Handler where it waits
558// for 1 or more bytes to be available to then write here. So at this
559// point we know that we have flow control. But this might have to
560// change when priority is implemented, so the serve goroutine knows
561// the total amount of bytes waiting to be sent and can can have more
562// scheduling decisions available.
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800563func (sc *serverConn) writeDataFromHandler(stream *stream, writeData *writeData, ch chan error) error {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800564 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800565 write: writeData,
566 stream: stream,
567 done: ch,
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800568 })
569 select {
570 case err := <-ch:
571 return err
572 case <-sc.doneServing:
573 return errClientDisconnected
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800574 case <-stream.cw:
575 return errStreamBroken
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800576 }
577}
578
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800579// writeFrameFromHandler sends wm to sc.wantWriteFrameCh, but aborts
580// if the connection has gone away.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800581//
582// This must not be run from the serve goroutine itself, else it might
583// deadlock writing to sc.wantWriteFrameCh (which is only mildly
584// buffered and is read by serve itself). If you're on the serve
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800585// goroutine, call writeFrame instead.
586func (sc *serverConn) writeFrameFromHandler(wm frameWriteMsg) {
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -0800587 sc.serveG.checkNotOn() // NOT
588 select {
589 case sc.wantWriteFrameCh <- wm:
590 case <-sc.doneServing:
591 // Client has closed their connection to the server.
592 }
Brad Fitzpatricka29a3232014-11-15 11:18:25 -0800593}
594
Brad Fitzpatricka92fa952014-12-02 10:31:34 -0800595// writeFrame schedules a frame to write and sends it if there's nothing
596// already being written.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800597//
Brad Fitzpatricka92fa952014-12-02 10:31:34 -0800598// There is no pushback here (the serve goroutine never blocks). It's
599// the http.Handlers that block, waiting for their previous frames to
600// make it onto the wire
601//
602// If you're not on the serve goroutine, use writeFrameFromHandler instead.
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800603func (sc *serverConn) writeFrame(wm frameWriteMsg) {
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800604 sc.serveG.check()
Brad Fitzpatricka13c4a42014-11-27 17:47:29 -0800605 sc.writeSched.add(wm)
Tatsuhiro Tsujikawacc1e1da2014-12-02 20:04:27 +0900606 sc.scheduleFrameWrite()
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800607}
608
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800609// startFrameWrite starts a goroutine to write wm (in a separate
610// goroutine since that might block on the network), and updates the
611// serve goroutine's state about the world, updated from info in wm.
612func (sc *serverConn) startFrameWrite(wm frameWriteMsg) {
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800613 sc.serveG.check()
614 if sc.writingFrame {
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800615 panic("internal error: can only be writing one frame at a time")
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800616 }
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800617
618 st := wm.stream
619 if st != nil {
620 switch st.state {
621 case stateHalfClosedLocal:
622 panic("internal error: attempt to send frame on half-closed-local stream")
623 case stateClosed:
624 if st.sentReset || st.gotReset {
625 // Skip this frame. But fake the frame write to reschedule:
626 sc.wroteFrameCh <- struct{}{}
627 return
628 }
Brad Fitzpatricka92fa952014-12-02 10:31:34 -0800629 panic(fmt.Sprintf("internal error: attempt to send a write %v on a closed stream", wm))
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800630 }
631 }
632
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800633 sc.writingFrame = true
Brad Fitzpatrick5e4e2dc2014-11-19 16:49:43 -0800634 sc.needsFrameFlush = true
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800635 if endsStream(wm.write) {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800636 if st == nil {
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800637 panic("internal error: expecting non-nil stream")
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800638 }
639 switch st.state {
640 case stateOpen:
641 st.state = stateHalfClosedLocal
642 case stateHalfClosedRemote:
643 sc.closeStream(st, nil)
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800644 }
645 }
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800646 go sc.writeFrameAsync(wm)
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800647}
648
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800649// scheduleFrameWrite tickles the frame writing scheduler.
650//
651// If a frame is already being written, nothing happens. This will be called again
652// when the frame is done being written.
653//
654// If a frame isn't being written we need to send one, the best frame
655// to send is selected, preferring first things that aren't
656// stream-specific (e.g. ACKing settings), and then finding the
657// highest priority stream.
658//
659// If a frame isn't being written and there's nothing else to send, we
660// flush the write buffer.
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800661func (sc *serverConn) scheduleFrameWrite() {
662 sc.serveG.check()
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800663 if sc.writingFrame {
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800664 return
665 }
666 if sc.needToSendGoAway {
667 sc.needToSendGoAway = false
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800668 sc.startFrameWrite(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800669 write: &writeGoAway{
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800670 maxStreamID: sc.maxStreamID,
671 code: sc.goAwayCode,
672 },
673 })
674 return
675 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800676 if sc.needToSendSettingsAck {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800677 sc.needToSendSettingsAck = false
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800678 sc.startFrameWrite(frameWriteMsg{write: writeSettingsAck{}})
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800679 return
680 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800681 if !sc.inGoAway {
682 if wm, ok := sc.writeSched.take(); ok {
683 sc.startFrameWrite(wm)
684 return
685 }
686 }
687 if sc.needsFrameFlush {
688 sc.startFrameWrite(frameWriteMsg{write: flushFrameWriter{}})
689 sc.needsFrameFlush = false // after startFrameWrite, since it sets this true
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800690 return
691 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800692}
693
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800694func (sc *serverConn) goAway(code ErrCode) {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800695 sc.serveG.check()
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800696 if sc.inGoAway {
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800697 return
698 }
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800699 if code != ErrCodeNo {
700 sc.shutDownIn(250 * time.Millisecond)
701 } else {
702 // TODO: configurable
703 sc.shutDownIn(1 * time.Second)
704 }
705 sc.inGoAway = true
706 sc.needToSendGoAway = true
707 sc.goAwayCode = code
708 sc.scheduleFrameWrite()
709}
710
711func (sc *serverConn) shutDownIn(d time.Duration) {
712 sc.serveG.check()
713 sc.shutdownTimer = time.NewTimer(d)
714 sc.shutdownTimerCh = sc.shutdownTimer.C
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800715}
716
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800717func (sc *serverConn) resetStream(se StreamError) {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800718 sc.serveG.check()
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -0800719 st, ok := sc.streams[se.StreamID]
720 if !ok {
721 panic("internal package error; resetStream called on non-existent stream")
722 }
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800723 sc.writeFrame(frameWriteMsg{write: se})
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -0800724 st.sentReset = true
725 sc.closeStream(st, se)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800726}
727
Brad Fitzpatrickb0a06c82014-11-26 09:21:28 -0800728// curHeaderStreamID returns the stream ID of the header block we're
729// currently in the middle of reading. If this returns non-zero, the
730// next frame must be a CONTINUATION with this stream id.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800731func (sc *serverConn) curHeaderStreamID() uint32 {
732 sc.serveG.check()
733 st := sc.req.stream
734 if st == nil {
735 return 0
736 }
737 return st.id
738}
739
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800740// processFrameFromReader processes the serve loop's read from readFrameCh from the
741// frame-reading goroutine.
742// processFrameFromReader returns whether the connection should be kept open.
743func (sc *serverConn) processFrameFromReader(fg frameAndGate, fgValid bool) bool {
744 sc.serveG.check()
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800745 var clientGone bool
746 var err error
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800747 if !fgValid {
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800748 err = <-sc.readFrameErrCh
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800749 if err == ErrFrameTooLarge {
750 sc.goAway(ErrCodeFrameSize)
751 return true // goAway will close the loop
752 }
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800753 clientGone = err == io.EOF || strings.Contains(err.Error(), "use of closed network connection")
754 if clientGone {
755 // TODO: could we also get into this state if
756 // the peer does a half close
757 // (e.g. CloseWrite) because they're done
758 // sending frames but they're still wanting
759 // our open replies? Investigate.
760 return false
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800761 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800762 }
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800763
764 if fgValid {
765 f := fg.f
766 sc.vlogf("got %v: %#v", f.Header(), f)
767 err = sc.processFrame(f)
768 fg.g.Done() // unblock the readFrames goroutine
769 if err == nil {
770 return true
771 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800772 }
773
774 switch ev := err.(type) {
775 case StreamError:
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800776 sc.resetStream(ev)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800777 return true
778 case goAwayFlowError:
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800779 sc.goAway(ErrCodeFlowControl)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800780 return true
781 case ConnectionError:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800782 sc.logf("%v: %v", sc.conn.RemoteAddr(), ev)
783 sc.goAway(ErrCode(ev))
784 return true // goAway will handle shutdown
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800785 default:
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800786 if !fgValid {
787 sc.logf("disconnecting; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)
788 } else {
789 sc.logf("disconnection due to other error: %v", err)
790 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800791 }
792 return false
793}
794
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800795func (sc *serverConn) processFrame(f Frame) error {
796 sc.serveG.check()
797
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800798 // First frame received must be SETTINGS.
799 if !sc.sawFirstSettings {
800 if _, ok := f.(*SettingsFrame); !ok {
801 return ConnectionError(ErrCodeProtocol)
802 }
803 sc.sawFirstSettings = true
804 }
805
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800806 if s := sc.curHeaderStreamID(); s != 0 {
807 if cf, ok := f.(*ContinuationFrame); !ok {
808 return ConnectionError(ErrCodeProtocol)
809 } else if cf.Header().StreamID != s {
810 return ConnectionError(ErrCodeProtocol)
811 }
812 }
813
814 switch f := f.(type) {
815 case *SettingsFrame:
816 return sc.processSettings(f)
817 case *HeadersFrame:
818 return sc.processHeaders(f)
819 case *ContinuationFrame:
820 return sc.processContinuation(f)
821 case *WindowUpdateFrame:
822 return sc.processWindowUpdate(f)
823 case *PingFrame:
824 return sc.processPing(f)
825 case *DataFrame:
826 return sc.processData(f)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800827 case *RSTStreamFrame:
828 return sc.processResetStream(f)
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -0800829 case *PriorityFrame:
830 return sc.processPriority(f)
Daniel Morsing9f251692014-12-05 18:17:30 +0000831 case *PushPromiseFrame:
832 // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
833 // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
834 return ConnectionError(ErrCodeProtocol)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800835 default:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800836 log.Printf("Ignoring frame: %v", f.Header())
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800837 return nil
838 }
839}
840
841func (sc *serverConn) processPing(f *PingFrame) error {
842 sc.serveG.check()
843 if f.Flags.Has(FlagSettingsAck) {
844 // 6.7 PING: " An endpoint MUST NOT respond to PING frames
845 // containing this flag."
846 return nil
847 }
848 if f.StreamID != 0 {
849 // "PING frames are not associated with any individual
850 // stream. If a PING frame is received with a stream
851 // identifier field value other than 0x0, the recipient MUST
852 // respond with a connection error (Section 5.4.1) of type
853 // PROTOCOL_ERROR."
854 return ConnectionError(ErrCodeProtocol)
855 }
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800856 sc.writeFrame(frameWriteMsg{write: writePingAck{f}})
Brad Fitzpatrick9e0eccc2014-11-15 09:14:49 -0800857 return nil
858}
859
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800860func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
861 sc.serveG.check()
862 switch {
863 case f.StreamID != 0: // stream-level flow control
864 st := sc.streams[f.StreamID]
865 if st == nil {
866 // "WINDOW_UPDATE can be sent by a peer that has sent a
867 // frame bearing the END_STREAM flag. This means that a
868 // receiver could receive a WINDOW_UPDATE frame on a "half
869 // closed (remote)" or "closed" stream. A receiver MUST
870 // NOT treat this as an error, see Section 5.1."
871 return nil
872 }
873 if !st.flow.add(int32(f.Increment)) {
874 return StreamError{f.StreamID, ErrCodeFlowControl}
875 }
876 default: // connection-level flow control
877 if !sc.flow.add(int32(f.Increment)) {
878 return goAwayFlowError{}
879 }
880 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800881 sc.scheduleFrameWrite()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800882 return nil
883}
884
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800885func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
886 sc.serveG.check()
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800887 if sc.state(f.StreamID) == stateIdle {
888 // 6.4 "RST_STREAM frames MUST NOT be sent for a
889 // stream in the "idle" state. If a RST_STREAM frame
890 // identifying an idle stream is received, the
891 // recipient MUST treat this as a connection error
892 // (Section 5.4.1) of type PROTOCOL_ERROR.
893 return ConnectionError(ErrCodeProtocol)
894 }
895 st, ok := sc.streams[f.StreamID]
896 if ok {
897 st.gotReset = true
898 sc.closeStream(st, StreamError{f.StreamID, f.ErrCode})
899 }
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800900 return nil
901}
902
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800903func (sc *serverConn) closeStream(st *stream, err error) {
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800904 sc.serveG.check()
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800905 if st.state == stateIdle || st.state == stateClosed {
906 panic("invariant")
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800907 }
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800908 st.state = stateClosed
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800909 sc.curOpenStreams--
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800910 delete(sc.streams, st.id)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800911 if p := st.body; p != nil {
912 p.Close(err)
913 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800914 st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
Brad Fitzpatrick5b95eb32014-12-02 10:52:56 -0800915 sc.writeSched.forgetStream(st.id)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800916}
917
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800918func (sc *serverConn) processSettings(f *SettingsFrame) error {
919 sc.serveG.check()
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800920 if f.IsAck() {
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -0800921 sc.unackedSettings--
922 if sc.unackedSettings < 0 {
923 // Why is the peer ACKing settings we never sent?
924 // The spec doesn't mention this case, but
925 // hang up on them anyway.
926 return ConnectionError(ErrCodeProtocol)
927 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800928 return nil
929 }
930 if err := f.ForeachSetting(sc.processSetting); err != nil {
931 return err
932 }
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800933 sc.needToSendSettingsAck = true
934 sc.scheduleFrameWrite()
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800935 return nil
936}
937
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800938func (sc *serverConn) processSetting(s Setting) error {
939 sc.serveG.check()
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800940 if err := s.Valid(); err != nil {
941 return err
942 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800943 sc.vlogf("processing setting %v", s)
944 switch s.ID {
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800945 case SettingHeaderTableSize:
946 sc.headerTableSize = s.Val
Tatsuhiro Tsujikawac7d67a52014-11-20 01:01:39 +0900947 sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800948 case SettingEnablePush:
949 sc.pushEnabled = s.Val != 0
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800950 case SettingMaxConcurrentStreams:
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800951 sc.clientMaxStreams = s.Val
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800952 case SettingInitialWindowSize:
953 return sc.processSettingInitialWindowSize(s.Val)
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800954 case SettingMaxFrameSize:
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800955 sc.writeSched.maxFrameSize = s.Val
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800956 case SettingMaxHeaderListSize:
957 sc.maxHeaderListSize = s.Val
gbbr0b3b5742014-11-23 00:44:48 +0000958 default:
959 // Unknown setting: "An endpoint that receives a SETTINGS
960 // frame with any unknown or unsupported identifier MUST
961 // ignore that setting."
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800962 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800963 return nil
964}
965
966func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
967 sc.serveG.check()
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800968 // Note: val already validated to be within range by
969 // processSetting's Valid call.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800970
971 // "A SETTINGS frame can alter the initial flow control window
972 // size for all current streams. When the value of
973 // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
974 // adjust the size of all stream flow control windows that it
975 // maintains by the difference between the new value and the
976 // old value."
977 old := sc.initialWindowSize
978 sc.initialWindowSize = int32(val)
979 growth := sc.initialWindowSize - old // may be negative
980 for _, st := range sc.streams {
981 if !st.flow.add(growth) {
982 // 6.9.2 Initial Flow Control Window Size
983 // "An endpoint MUST treat a change to
984 // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
985 // control window to exceed the maximum size as a
986 // connection error (Section 5.4.1) of type
987 // FLOW_CONTROL_ERROR."
988 return ConnectionError(ErrCodeFlowControl)
989 }
990 }
991 return nil
992}
993
994func (sc *serverConn) processData(f *DataFrame) error {
995 sc.serveG.check()
996 // "If a DATA frame is received whose stream is not in "open"
997 // or "half closed (local)" state, the recipient MUST respond
998 // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
999 id := f.Header().StreamID
1000 st, ok := sc.streams[id]
1001 if !ok || (st.state != stateOpen && st.state != stateHalfClosedLocal) {
1002 return StreamError{id, ErrCodeStreamClosed}
1003 }
1004 if st.body == nil {
Brad Fitzpatrickb0a06c82014-11-26 09:21:28 -08001005 panic("internal error: should have a body in this state")
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001006 }
1007 data := f.Data()
1008
1009 // Sender sending more than they'd declared?
1010 if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
gbbrd90e0982014-11-20 22:19:20 +00001011 st.body.Close(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001012 return StreamError{id, ErrCodeStreamClosed}
1013 }
1014 if len(data) > 0 {
Brad Fitzpatrickc57de9f2014-12-07 19:03:45 -08001015 // TODO: verify they're allowed to write with the flow
1016 // control window we'd advertised to them. (currently
1017 // this is fails elsewhere, in that the body buffer is
1018 // always 65k, the default initial window size, but
1019 // once that's fixed to grow and shrink on demand,
1020 // we'll need to be stricter before that, or in the
1021 // buffer code)
Brad Fitzpatrick0218ba62014-11-26 09:36:05 -08001022 wrote, err := st.body.Write(data)
1023 if err != nil {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001024 return StreamError{id, ErrCodeStreamClosed}
1025 }
Brad Fitzpatrick0218ba62014-11-26 09:36:05 -08001026 if wrote != len(data) {
1027 panic("internal error: bad Writer")
1028 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001029 st.bodyBytes += int64(len(data))
1030 }
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001031 if f.StreamEnded() {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001032 if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
gbbrd90e0982014-11-20 22:19:20 +00001033 st.body.Close(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001034 st.declBodyBytes, st.bodyBytes))
1035 } else {
1036 st.body.Close(io.EOF)
1037 }
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001038 switch st.state {
1039 case stateOpen:
1040 st.state = stateHalfClosedRemote
1041 case stateHalfClosedLocal:
Brad Fitzpatrick7189a052014-12-07 19:05:01 -08001042 // TODO: this causes a known crash (currently skipped
1043 // test in server_test.go). We shouldn't leave
1044 // streams in the map in stateClosed.
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001045 st.state = stateClosed
1046 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001047 }
1048 return nil
1049}
1050
1051func (sc *serverConn) processHeaders(f *HeadersFrame) error {
1052 sc.serveG.check()
1053 id := f.Header().StreamID
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -08001054 if sc.inGoAway {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001055 // Ignore.
1056 return nil
1057 }
1058 // http://http2.github.io/http2-spec/#rfc.section.5.1.1
1059 if id%2 != 1 || id <= sc.maxStreamID || sc.req.stream != nil {
1060 // Streams initiated by a client MUST use odd-numbered
1061 // stream identifiers. [...] The identifier of a newly
1062 // established stream MUST be numerically greater than all
1063 // streams that the initiating endpoint has opened or
1064 // reserved. [...] An endpoint that receives an unexpected
1065 // stream identifier MUST respond with a connection error
1066 // (Section 5.4.1) of type PROTOCOL_ERROR.
1067 return ConnectionError(ErrCodeProtocol)
1068 }
1069 if id > sc.maxStreamID {
1070 sc.maxStreamID = id
1071 }
1072 st := &stream{
1073 id: id,
1074 state: stateOpen,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001075 }
Tatsuhiro Tsujikawacc1e1da2014-12-02 20:04:27 +09001076 // connection-level flow control is shared by all streams.
1077 st.flow.conn = &sc.flow
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001078 st.flow.add(sc.initialWindowSize)
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001079 st.cw.Init() // make Cond use its Mutex, without heap-promoting them separately
1080 if f.StreamEnded() {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001081 st.state = stateHalfClosedRemote
1082 }
1083 sc.streams[id] = st
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -08001084 if f.HasPriority() {
1085 sc.adjustStreamPriority(st.id, f.Priority)
1086 }
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001087 sc.curOpenStreams++
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001088 sc.req = requestParam{
1089 stream: st,
1090 header: make(http.Header),
1091 }
1092 return sc.processHeaderBlockFragment(st, f.HeaderBlockFragment(), f.HeadersEnded())
1093}
1094
1095func (sc *serverConn) processContinuation(f *ContinuationFrame) error {
1096 sc.serveG.check()
1097 st := sc.streams[f.Header().StreamID]
1098 if st == nil || sc.curHeaderStreamID() != st.id {
1099 return ConnectionError(ErrCodeProtocol)
1100 }
1101 return sc.processHeaderBlockFragment(st, f.HeaderBlockFragment(), f.HeadersEnded())
1102}
1103
1104func (sc *serverConn) processHeaderBlockFragment(st *stream, frag []byte, end bool) error {
1105 sc.serveG.check()
1106 if _, err := sc.hpackDecoder.Write(frag); err != nil {
1107 // TODO: convert to stream error I assume?
1108 return err
1109 }
1110 if !end {
1111 return nil
1112 }
1113 if err := sc.hpackDecoder.Close(); err != nil {
1114 // TODO: convert to stream error I assume?
1115 return err
1116 }
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001117 defer sc.resetPendingRequest()
1118 if sc.curOpenStreams > sc.advMaxStreams {
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -08001119 // "Endpoints MUST NOT exceed the limit set by their
1120 // peer. An endpoint that receives a HEADERS frame
1121 // that causes their advertised concurrent stream
1122 // limit to be exceeded MUST treat this as a stream
1123 // error (Section 5.4.2) of type PROTOCOL_ERROR or
1124 // REFUSED_STREAM."
1125 if sc.unackedSettings == 0 {
1126 // They should know better.
1127 return StreamError{st.id, ErrCodeProtocol}
1128 }
1129 // Assume it's a network race, where they just haven't
1130 // received our last SETTINGS update. But actually
1131 // this can't happen yet, because we don't yet provide
1132 // a way for users to adjust server parameters at
1133 // runtime.
1134 return StreamError{st.id, ErrCodeRefusedStream}
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001135 }
1136
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001137 rw, req, err := sc.newWriterAndRequest()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001138 if err != nil {
1139 return err
1140 }
1141 st.body = req.Body.(*requestBody).pipe // may be nil
1142 st.declBodyBytes = req.ContentLength
1143 go sc.runHandler(rw, req)
1144 return nil
1145}
1146
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -08001147func (sc *serverConn) processPriority(f *PriorityFrame) error {
1148 sc.adjustStreamPriority(f.StreamID, f.PriorityParam)
1149 return nil
1150}
1151
1152func (sc *serverConn) adjustStreamPriority(streamID uint32, priority PriorityParam) {
1153 // TODO: untested
1154 st, ok := sc.streams[streamID]
1155 if !ok {
1156 // TODO: not quite correct (this streamID might
1157 // already exist in the dep tree, but be closed), but
1158 // close enough for now.
1159 return
1160 }
1161 st.weight = priority.Weight
1162 st.parent = sc.streams[priority.StreamDep] // might be nil
1163 if priority.Exclusive && st.parent != nil {
1164 for _, openStream := range sc.streams {
1165 if openStream.parent == st.parent {
1166 openStream.parent = st
1167 }
1168 }
1169 }
1170}
1171
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001172// resetPendingRequest zeros out all state related to a HEADERS frame
1173// and its zero or more CONTINUATION frames sent to start a new
1174// request.
1175func (sc *serverConn) resetPendingRequest() {
1176 sc.serveG.check()
1177 sc.req = requestParam{}
1178}
1179
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001180func (sc *serverConn) newWriterAndRequest() (*responseWriter, *http.Request, error) {
1181 sc.serveG.check()
1182 rp := &sc.req
1183 if rp.invalidHeader || rp.method == "" || rp.path == "" ||
1184 (rp.scheme != "https" && rp.scheme != "http") {
1185 // See 8.1.2.6 Malformed Requests and Responses:
1186 //
1187 // Malformed requests or responses that are detected
1188 // MUST be treated as a stream error (Section 5.4.2)
1189 // of type PROTOCOL_ERROR."
1190 //
1191 // 8.1.2.3 Request Pseudo-Header Fields
1192 // "All HTTP/2 requests MUST include exactly one valid
1193 // value for the :method, :scheme, and :path
1194 // pseudo-header fields"
1195 return nil, nil, StreamError{rp.stream.id, ErrCodeProtocol}
1196 }
1197 var tlsState *tls.ConnectionState // make this non-nil if https
1198 if rp.scheme == "https" {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001199 tlsState = &tls.ConnectionState{}
Brad Fitzpatrick7482ed02014-11-18 15:45:54 -08001200 if tc, ok := sc.conn.(*tls.Conn); ok {
1201 *tlsState = tc.ConnectionState()
1202 if tlsState.Version < tls.VersionTLS12 {
1203 // 9.2 Use of TLS Features
1204 // An implementation of HTTP/2 over TLS MUST use TLS
1205 // 1.2 or higher with the restrictions on feature set
1206 // and cipher suite described in this section. Due to
1207 // implementation limitations, it might not be
1208 // possible to fail TLS negotiation. An endpoint MUST
1209 // immediately terminate an HTTP/2 connection that
1210 // does not meet the TLS requirements described in
1211 // this section with a connection error (Section
1212 // 5.4.1) of type INADEQUATE_SECURITY.
1213 return nil, nil, ConnectionError(ErrCodeInadequateSecurity)
1214 }
1215 // TODO: verify cipher suites. (9.2.1, 9.2.2)
1216 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001217 }
1218 authority := rp.authority
1219 if authority == "" {
1220 authority = rp.header.Get("Host")
1221 }
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001222 needsContinue := rp.header.Get("Expect") == "100-continue"
1223 if needsContinue {
1224 rp.header.Del("Expect")
1225 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001226 bodyOpen := rp.stream.state == stateOpen
1227 body := &requestBody{
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001228 conn: sc,
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001229 stream: rp.stream,
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001230 needsContinue: needsContinue,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001231 }
Brad Fitzpatrickad4757f2014-11-26 09:37:40 -08001232 // TODO: handle asterisk '*' requests + test
Brad Fitzpatrickff0471b2014-11-14 21:55:14 -08001233 url, err := url.ParseRequestURI(rp.path)
1234 if err != nil {
1235 // TODO: find the right error code?
1236 return nil, nil, StreamError{rp.stream.id, ErrCodeProtocol}
1237 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001238 req := &http.Request{
1239 Method: rp.method,
Brad Fitzpatrickff0471b2014-11-14 21:55:14 -08001240 URL: url,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001241 RemoteAddr: sc.conn.RemoteAddr().String(),
1242 Header: rp.header,
1243 RequestURI: rp.path,
1244 Proto: "HTTP/2.0",
1245 ProtoMajor: 2,
1246 ProtoMinor: 0,
1247 TLS: tlsState,
1248 Host: authority,
1249 Body: body,
1250 }
1251 if bodyOpen {
1252 body.pipe = &pipe{
Brad Fitzpatrick953b5112014-12-06 17:59:01 -08001253 b: buffer{buf: make([]byte, initialWindowSize)}, // TODO: share/remove XXX
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001254 }
1255 body.pipe.c.L = &body.pipe.m
1256
1257 if vv, ok := rp.header["Content-Length"]; ok {
1258 req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
1259 } else {
1260 req.ContentLength = -1
1261 }
1262 }
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001263
1264 rws := responseWriterStatePool.Get().(*responseWriterState)
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001265 bwSave := rws.bw
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001266 *rws = responseWriterState{} // zero all the fields
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001267 rws.conn = sc
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001268 rws.bw = bwSave
1269 rws.bw.Reset(chunkWriter{rws})
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001270 rws.stream = rp.stream
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001271 rws.req = req
1272 rws.body = body
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001273 rws.frameWriteCh = make(chan error, 1)
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001274
1275 rw := &responseWriter{rws: rws}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001276 return rw, req, nil
1277}
1278
1279// Run on its own goroutine.
1280func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request) {
1281 defer rw.handlerDone()
1282 // TODO: catch panics like net/http.Server
1283 sc.handler.ServeHTTP(rw, req)
1284}
1285
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001286// called from handler goroutines.
1287// h may be nil.
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001288func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders, tempCh chan error) {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001289 sc.serveG.checkNotOn() // NOT on
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001290 var errc chan error
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001291 if headerData.h != nil {
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001292 // If there's a header map (which we don't own), so we have to block on
1293 // waiting for this frame to be written, so an http.Flush mid-handler
1294 // writes out the correct value of keys, before a handler later potentially
1295 // mutates it.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001296 errc = tempCh
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001297 }
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -08001298 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001299 write: headerData,
1300 stream: st,
1301 done: errc,
Brad Fitzpatricka29a3232014-11-15 11:18:25 -08001302 })
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001303 if errc != nil {
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -08001304 select {
1305 case <-errc:
1306 // Ignore. Just for synchronization.
1307 // Any error will be handled in the writing goroutine.
1308 case <-sc.doneServing:
1309 // Client has closed the connection.
1310 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001311 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001312}
1313
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001314// called from handler goroutines.
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001315func (sc *serverConn) write100ContinueHeaders(st *stream) {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -08001316 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001317 write: write100ContinueHeadersFrame{st.id},
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001318 stream: st,
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001319 })
1320}
1321
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -08001322// A bodyReadMsg tells the server loop that the http.Handler read n
1323// bytes of the DATA from the client on the given stream.
1324type bodyReadMsg struct {
1325 st *stream
1326 n int
1327}
1328
1329// called from handler goroutines.
1330// Notes that the handler for the given stream ID read n bytes of its body
1331// and schedules flow control tokens to be sent.
1332func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int) {
1333 sc.serveG.checkNotOn() // NOT on
1334 sc.bodyReadCh <- bodyReadMsg{st, n}
1335}
1336
1337func (sc *serverConn) noteBodyRead(st *stream, n int) {
1338 sc.serveG.check()
1339 sc.sendWindowUpdate(nil, n) // conn-level
Brad Fitzpatrick0f1a8652014-12-07 20:49:33 -08001340 if st.state != stateHalfClosedRemote && st.state != stateClosed {
1341 // Don't send this WINDOW_UPDATE if the stream is closed
1342 // remotely.
1343 sc.sendWindowUpdate(st, n)
1344 }
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -08001345}
1346
1347// st may be nil for conn-level
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001348func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -08001349 sc.serveG.check()
1350 // "The legal range for the increment to the flow control
1351 // window is 1 to 2^31-1 (2,147,483,647) octets."
1352 var streamID uint32
1353 if st != nil {
1354 streamID = st.id
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001355 }
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -08001356 const maxUint31 = 1<<31 - 1
1357 for n >= maxUint31 {
1358 sc.writeFrame(frameWriteMsg{
1359 write: writeWindowUpdate{streamID: streamID, n: maxUint31},
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001360 stream: st,
Brad Fitzpatricka29a3232014-11-15 11:18:25 -08001361 })
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -08001362 n -= maxUint31
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001363 }
1364 if n > 0 {
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -08001365 sc.writeFrame(frameWriteMsg{
1366 write: writeWindowUpdate{streamID: streamID, n: uint32(n)},
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001367 stream: st,
Brad Fitzpatricka29a3232014-11-15 11:18:25 -08001368 })
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001369 }
1370}
1371
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001372type requestBody struct {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001373 stream *stream
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001374 conn *serverConn
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001375 closed bool
1376 pipe *pipe // non-nil if we have a HTTP entity message body
1377 needsContinue bool // need to send a 100-continue
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001378}
1379
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001380func (b *requestBody) Close() error {
1381 if b.pipe != nil {
1382 b.pipe.Close(errClosedBody)
1383 }
1384 b.closed = true
1385 return nil
1386}
1387
1388func (b *requestBody) Read(p []byte) (n int, err error) {
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001389 if b.needsContinue {
1390 b.needsContinue = false
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001391 b.conn.write100ContinueHeaders(b.stream)
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001392 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001393 if b.pipe == nil {
1394 return 0, io.EOF
1395 }
1396 n, err = b.pipe.Read(p)
1397 if n > 0 {
Brad Fitzpatrickc8bab6a2014-12-07 18:51:56 -08001398 b.conn.noteBodyReadFromHandler(b.stream, n)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001399 }
1400 return
1401}
1402
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001403// responseWriter is the http.ResponseWriter implementation. It's
1404// intentionally small (1 pointer wide) to minimize garbage. The
1405// responseWriterState pointer inside is zeroed at the end of a
1406// request (in handlerDone) and calls on the responseWriter thereafter
1407// simply crash (caller's mistake), but the much larger responseWriterState
1408// and buffers are reused between multiple requests.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001409type responseWriter struct {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001410 rws *responseWriterState
1411}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001412
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001413// Optional http.ResponseWriter interfaces implemented.
1414var (
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001415 _ http.CloseNotifier = (*responseWriter)(nil)
1416 _ http.Flusher = (*responseWriter)(nil)
1417 _ stringWriter = (*responseWriter)(nil)
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001418)
1419
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001420type responseWriterState struct {
1421 // immutable within a request:
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001422 stream *stream
1423 req *http.Request
1424 body *requestBody // to close at end of request, if DATA frames didn't
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001425 conn *serverConn
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001426
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001427 // TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001428 bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState}
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001429
1430 // mutated by http.Handler goroutine:
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001431 handlerHeader http.Header // nil until called
1432 snapHeader http.Header // snapshot of handlerHeader at WriteHeader time
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001433 status int // status code passed to WriteHeader
Brad Fitzpatrick3c8c6132014-11-20 18:34:52 -08001434 wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001435 sentHeader bool // have we sent the header frame?
1436 handlerDone bool // handler has finished
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001437 curWrite writeData
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001438 frameWriteCh chan error // re-used whenever we need to block on a frame being written
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001439
1440 closeNotifierMu sync.Mutex // guards closeNotifierCh
1441 closeNotifierCh chan bool // nil until first used
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001442}
1443
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001444type chunkWriter struct{ rws *responseWriterState }
1445
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001446func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001447
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001448// writeChunk writes chunks from the bufio.Writer. But because
1449// bufio.Writer may bypass its chunking, sometimes p may be
1450// arbitrarily large.
1451//
1452// writeChunk is also responsible (on the first chunk) for sending the
1453// HEADER response.
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001454func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
1455 if !rws.wroteHeader {
1456 rws.writeHeader(200)
1457 }
1458 if !rws.sentHeader {
1459 rws.sentHeader = true
1460 var ctype, clen string // implicit ones, if we can calculate it
1461 if rws.handlerDone && rws.snapHeader.Get("Content-Length") == "" {
1462 clen = strconv.Itoa(len(p))
1463 }
1464 if rws.snapHeader.Get("Content-Type") == "" {
1465 ctype = http.DetectContentType(p)
1466 }
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001467 endStream := rws.handlerDone && len(p) == 0
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001468 rws.conn.writeHeaders(rws.stream, &writeResHeaders{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001469 streamID: rws.stream.id,
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001470 httpResCode: rws.status,
1471 h: rws.snapHeader,
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001472 endStream: endStream,
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001473 contentType: ctype,
1474 contentLength: clen,
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001475 }, rws.frameWriteCh)
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001476 if endStream {
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001477 return 0, nil
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001478 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001479 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001480 if len(p) == 0 && !rws.handlerDone {
1481 return 0, nil
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001482 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001483 curWrite := &rws.curWrite
1484 curWrite.streamID = rws.stream.id
1485 curWrite.p = p
1486 curWrite.endStream = rws.handlerDone
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001487 if err := rws.conn.writeDataFromHandler(rws.stream, curWrite, rws.frameWriteCh); err != nil {
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001488 return 0, err
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001489 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001490 return len(p), nil
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001491}
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001492
1493func (w *responseWriter) Flush() {
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001494 rws := w.rws
1495 if rws == nil {
1496 panic("Header called after Handler finished")
1497 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001498 if rws.bw.Buffered() > 0 {
1499 if err := rws.bw.Flush(); err != nil {
1500 // Ignore the error. The frame writer already knows.
1501 return
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001502 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001503 } else {
1504 // The bufio.Writer won't call chunkWriter.Write
1505 // (writeChunk with zero bytes, so we have to do it
1506 // ourselves to force the HTTP response header and/or
1507 // final DATA frame (with END_STREAM) to be sent.
1508 rws.writeChunk(nil)
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001509 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001510}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001511
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001512func (w *responseWriter) CloseNotify() <-chan bool {
1513 rws := w.rws
1514 if rws == nil {
1515 panic("CloseNotify called after Handler finished")
1516 }
1517 rws.closeNotifierMu.Lock()
1518 ch := rws.closeNotifierCh
1519 if ch == nil {
1520 ch = make(chan bool, 1)
1521 rws.closeNotifierCh = ch
1522 go func() {
1523 rws.stream.cw.Wait() // wait for close
1524 ch <- true
1525 }()
1526 }
1527 rws.closeNotifierMu.Unlock()
1528 return ch
1529}
1530
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001531func (w *responseWriter) Header() http.Header {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001532 rws := w.rws
1533 if rws == nil {
1534 panic("Header called after Handler finished")
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001535 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001536 if rws.handlerHeader == nil {
1537 rws.handlerHeader = make(http.Header)
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001538 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001539 return rws.handlerHeader
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001540}
1541
1542func (w *responseWriter) WriteHeader(code int) {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001543 rws := w.rws
1544 if rws == nil {
1545 panic("WriteHeader called after Handler finished")
1546 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001547 rws.writeHeader(code)
1548}
1549
1550func (rws *responseWriterState) writeHeader(code int) {
1551 if !rws.wroteHeader {
1552 rws.wroteHeader = true
1553 rws.status = code
1554 if len(rws.handlerHeader) > 0 {
1555 rws.snapHeader = cloneHeader(rws.handlerHeader)
1556 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001557 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001558}
1559
1560func cloneHeader(h http.Header) http.Header {
1561 h2 := make(http.Header, len(h))
1562 for k, vv := range h {
1563 vv2 := make([]string, len(vv))
1564 copy(vv2, vv)
1565 h2[k] = vv2
1566 }
1567 return h2
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001568}
1569
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001570// The Life Of A Write is like this:
1571//
Brad Fitzpatricked26b482014-11-26 09:16:43 -08001572// * Handler calls w.Write or w.WriteString ->
1573// * -> rws.bw (*bufio.Writer) ->
1574// * (Handler migth call Flush)
1575// * -> chunkWriter{rws}
1576// * -> responseWriterState.writeChunk(p []byte)
1577// * -> responseWriterState.writeChunk (most of the magic; see comment there)
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001578func (w *responseWriter) Write(p []byte) (n int, err error) {
1579 return w.write(len(p), p, "")
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001580}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001581
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001582func (w *responseWriter) WriteString(s string) (n int, err error) {
1583 return w.write(len(s), nil, s)
1584}
1585
1586// either dataB or dataS is non-zero.
1587func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int, err error) {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001588 rws := w.rws
1589 if rws == nil {
1590 panic("Write called after Handler finished")
1591 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001592 if !rws.wroteHeader {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001593 w.WriteHeader(200)
1594 }
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001595 if dataB != nil {
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001596 return rws.bw.Write(dataB)
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001597 } else {
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001598 return rws.bw.WriteString(dataS)
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001599 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001600}
1601
1602func (w *responseWriter) handlerDone() {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001603 rws := w.rws
1604 if rws == nil {
1605 panic("handlerDone called twice")
1606 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001607 rws.handlerDone = true
1608 w.Flush()
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001609 w.rws = nil
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001610 responseWriterStatePool.Put(rws)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001611}