blob: cd4f09b6993290f304e82e80ef958a3662288e34 [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
169 doneServing: make(chan struct{}),
170 advMaxStreams: srv.maxConcurrentStreams(),
171 writeSched: writeScheduler{
172 maxFrameSize: initialMaxFrameSize,
173 },
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800174 initialWindowSize: initialWindowSize,
175 headerTableSize: initialHeaderTableSize,
176 serveG: newGoroutineLock(),
177 pushEnabled: true,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800178 }
Brad Fitzpatrick98766182014-12-02 10:30:08 -0800179 sc.flow.add(initialWindowSize)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800180 sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
181 sc.hpackDecoder = hpack.NewDecoder(initialHeaderTableSize, sc.onNewHeaderField)
Brad Fitzpatrick5e4e2dc2014-11-19 16:49:43 -0800182
183 fr := NewFramer(sc.bw, c)
184 fr.SetMaxReadFrameSize(srv.maxReadFrameSize())
185 sc.framer = fr
186
Brad Fitzpatrick0db6d652014-11-15 15:49:19 -0800187 if hook := testHookGetServerConn; hook != nil {
188 hook(sc)
189 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800190 sc.serve()
191}
192
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800193// frameAndGates coordinates the readFrames and serve
194// goroutines. Because the Framer interface only permits the most
195// recently-read Frame from being accessed, the readFrames goroutine
196// blocks until it has a frame, passes it to serve, and then waits for
197// serve to be done with it before reading the next one.
198type frameAndGate struct {
199 f Frame
200 g gate
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800201}
202
203type serverConn struct {
204 // Immutable:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800205 srv *Server
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800206 hs *http.Server
207 conn net.Conn
Brad Fitzpatrick5e4e2dc2014-11-19 16:49:43 -0800208 bw *bufferedWriter // writing to conn
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800209 handler http.Handler
210 framer *Framer
211 hpackDecoder *hpack.Decoder
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800212 doneServing chan struct{} // closed when serverConn.serve ends
213 readFrameCh chan frameAndGate // written by serverConn.readFrames
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800214 readFrameErrCh chan error
215 wantWriteFrameCh chan frameWriteMsg // from handlers -> serve
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800216 wroteFrameCh chan struct{} // from writeFrameAsync -> serve, tickles more frame writes
Brad Fitzpatrick0db6d652014-11-15 15:49:19 -0800217 testHookCh chan func() // code to run on the serve loop
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800218 flow flow // connection-wide (not stream-specific) flow control
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800219
220 // Everything following is owned by the serve loop; use serveG.check():
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800221 serveG goroutineLock // used to verify funcs are on serve()
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800222 pushEnabled bool
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800223 sawFirstSettings bool // got the initial SETTINGS frame after the preface
224 needToSendSettingsAck bool
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -0800225 unackedSettings int // how many SETTINGS have we sent without ACKs?
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800226 clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
227 advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
228 curOpenStreams uint32 // client's number of open streams
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800229 maxStreamID uint32 // max ever seen
230 streams map[uint32]*stream
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800231 initialWindowSize int32
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800232 headerTableSize uint32
233 maxHeaderListSize uint32 // zero means unknown (default)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800234 canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800235 req requestParam // non-zero while reading request headers
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800236 writingFrame bool // started write goroutine but haven't heard back on wroteFrameCh
237 needsFrameFlush bool // last frame write wasn't a flush
Brad Fitzpatricka13c4a42014-11-27 17:47:29 -0800238 writeSched writeScheduler
239 inGoAway bool // we've started to or sent GOAWAY
240 needToSendGoAway bool // we need to schedule a GOAWAY frame write
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800241 goAwayCode ErrCode
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800242 shutdownTimerCh <-chan time.Time // nil until used
243 shutdownTimer *time.Timer // nil until used
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800244
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800245 // Owned by the writeFrameAsync goroutine:
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800246 headerWriteBuf bytes.Buffer
247 hpackEncoder *hpack.Encoder
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800248}
249
250// requestParam is the state of the next request, initialized over
251// potentially several frames HEADERS + zero or more CONTINUATION
252// frames.
253type requestParam struct {
254 // stream is non-nil if we're reading (HEADER or CONTINUATION)
255 // frames for a request (but not DATA).
256 stream *stream
257 header http.Header
258 method, path string
259 scheme, authority string
260 sawRegularHeader bool // saw a non-pseudo header already
261 invalidHeader bool // an invalid header was seen
262}
263
Gabriel Aszalos1aa5b312014-11-19 16:56:22 +0000264// stream represents a stream. This is the minimal metadata needed by
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800265// the serve goroutine. Most of the actual stream state is owned by
266// the http.Handler's goroutine in the responseWriter. Because the
267// responseWriter's responseWriterState is recycled at the end of a
268// handler, this struct intentionally has no pointer to the
269// *responseWriter{,State} itself, as the Handler ending nils out the
270// responseWriter's state field.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800271type stream struct {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800272 // immutable:
273 id uint32
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800274 flow flow // limits writing from Handler to client
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800275 body *pipe // non-nil if expecting DATA frames
276 cw closeWaiter // closed wait stream transitions to closed state
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800277
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800278 // owned by serverConn's serve loop:
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -0800279 parent *stream // or nil
280 weight uint8
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800281 state streamState
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800282 bodyBytes int64 // body bytes seen so far
283 declBodyBytes int64 // or -1 if undeclared
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800284 sentReset bool // only true once detached from streams map
285 gotReset bool // only true once detacted from streams map
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800286}
287
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800288func (sc *serverConn) Framer() *Framer { return sc.framer }
289func (sc *serverConn) CloseConn() error { return sc.conn.Close() }
290func (sc *serverConn) Flush() error { return sc.bw.Flush() }
291func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
292 return sc.hpackEncoder, &sc.headerWriteBuf
293}
294
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800295func (sc *serverConn) state(streamID uint32) streamState {
296 sc.serveG.check()
297 // http://http2.github.io/http2-spec/#rfc.section.5.1
298 if st, ok := sc.streams[streamID]; ok {
299 return st.state
300 }
301 // "The first use of a new stream identifier implicitly closes all
302 // streams in the "idle" state that might have been initiated by
303 // that peer with a lower-valued stream identifier. For example, if
304 // a client sends a HEADERS frame on stream 7 without ever sending a
305 // frame on stream 5, then stream 5 transitions to the "closed"
306 // state when the first frame for stream 7 is sent or received."
307 if streamID <= sc.maxStreamID {
308 return stateClosed
309 }
310 return stateIdle
311}
312
313func (sc *serverConn) vlogf(format string, args ...interface{}) {
314 if VerboseLogs {
315 sc.logf(format, args...)
316 }
317}
318
319func (sc *serverConn) logf(format string, args ...interface{}) {
320 if lg := sc.hs.ErrorLog; lg != nil {
321 lg.Printf(format, args...)
322 } else {
323 log.Printf(format, args...)
324 }
325}
326
327func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
328 if err == nil {
329 return
330 }
331 str := err.Error()
Brad Fitzpatrick95842032014-11-15 09:47:42 -0800332 if err == io.EOF || strings.Contains(str, "use of closed network connection") {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800333 // Boring, expected errors.
334 sc.vlogf(format, args...)
335 } else {
336 sc.logf(format, args...)
337 }
338}
339
340func (sc *serverConn) onNewHeaderField(f hpack.HeaderField) {
341 sc.serveG.check()
342 switch {
343 case !validHeader(f.Name):
344 sc.req.invalidHeader = true
345 case strings.HasPrefix(f.Name, ":"):
346 if sc.req.sawRegularHeader {
347 sc.logf("pseudo-header after regular header")
348 sc.req.invalidHeader = true
349 return
350 }
351 var dst *string
352 switch f.Name {
353 case ":method":
354 dst = &sc.req.method
355 case ":path":
356 dst = &sc.req.path
357 case ":scheme":
358 dst = &sc.req.scheme
359 case ":authority":
360 dst = &sc.req.authority
361 default:
362 // 8.1.2.1 Pseudo-Header Fields
363 // "Endpoints MUST treat a request or response
364 // that contains undefined or invalid
365 // pseudo-header fields as malformed (Section
366 // 8.1.2.6)."
367 sc.logf("invalid pseudo-header %q", f.Name)
368 sc.req.invalidHeader = true
369 return
370 }
371 if *dst != "" {
372 sc.logf("duplicate pseudo-header %q sent", f.Name)
373 sc.req.invalidHeader = true
374 return
375 }
376 *dst = f.Value
377 case f.Name == "cookie":
378 sc.req.sawRegularHeader = true
379 if s, ok := sc.req.header["Cookie"]; ok && len(s) == 1 {
380 s[0] = s[0] + "; " + f.Value
381 } else {
382 sc.req.header.Add("Cookie", f.Value)
383 }
384 default:
385 sc.req.sawRegularHeader = true
386 sc.req.header.Add(sc.canonicalHeader(f.Name), f.Value)
387 }
388}
389
390func (sc *serverConn) canonicalHeader(v string) string {
391 sc.serveG.check()
Brad Fitzpatrick6520e262014-11-15 09:36:47 -0800392 cv, ok := commonCanonHeader[v]
393 if ok {
394 return cv
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800395 }
Brad Fitzpatrick6520e262014-11-15 09:36:47 -0800396 cv, ok = sc.canonHeader[v]
397 if ok {
398 return cv
399 }
400 if sc.canonHeader == nil {
401 sc.canonHeader = make(map[string]string)
402 }
403 cv = http.CanonicalHeaderKey(v)
404 sc.canonHeader[v] = cv
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800405 return cv
406}
407
408// readFrames is the loop that reads incoming frames.
409// It's run on its own goroutine.
410func (sc *serverConn) readFrames() {
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800411 g := make(gate, 1)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800412 for {
413 f, err := sc.framer.ReadFrame()
414 if err != nil {
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800415 sc.readFrameErrCh <- err
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800416 close(sc.readFrameCh)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800417 return
418 }
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800419 sc.readFrameCh <- frameAndGate{f, g}
Brad Fitzpatrickb0a06c82014-11-26 09:21:28 -0800420 // We can't read another frame until this one is
421 // processed, as the ReadFrame interface doesn't copy
422 // memory. The Frame accessor methods access the last
423 // frame's (shared) buffer. So we wait for the
424 // serve goroutine to tell us it's done:
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800425 g.Wait()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800426 }
427}
428
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800429// writeFrameAsync runs in its own goroutine and writes a single frame
430// and then reports when it's done.
431// At most one goroutine can be running writeFrameAsync at a time per
432// serverConn.
433func (sc *serverConn) writeFrameAsync(wm frameWriteMsg) {
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800434 err := wm.write.writeFrame(sc)
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800435 if ch := wm.done; ch != nil {
436 select {
437 case ch <- err:
438 default:
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800439 panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.write))
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800440 }
441 }
442 sc.wroteFrameCh <- struct{}{} // tickle frame selection scheduler
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800443}
444
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -0800445func (sc *serverConn) closeAllStreamsOnConnClose() {
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800446 sc.serveG.check()
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800447 for _, st := range sc.streams {
448 sc.closeStream(st, errClientDisconnected)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800449 }
450}
451
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800452func (sc *serverConn) stopShutdownTimer() {
453 sc.serveG.check()
454 if t := sc.shutdownTimer; t != nil {
455 t.Stop()
456 }
457}
458
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800459func (sc *serverConn) serve() {
460 sc.serveG.check()
461 defer sc.conn.Close()
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -0800462 defer sc.closeAllStreamsOnConnClose()
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800463 defer sc.stopShutdownTimer()
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800464 defer close(sc.doneServing) // unblocks handlers trying to send
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800465
466 sc.vlogf("HTTP/2 connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
467
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800468 sc.writeFrame(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800469 write: writeSettings{
Brad Fitzpatrick23564bf2014-11-27 19:40:04 -0800470 {SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
471 {SettingMaxConcurrentStreams, sc.advMaxStreams},
472 /* TODO: more actual settings */
473 },
474 })
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -0800475 sc.unackedSettings++
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800476
477 if err := sc.readPreface(); err != nil {
gbbrd90e0982014-11-20 22:19:20 +0000478 sc.condlogf(err, "error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800479 return
480 }
481
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800482 go sc.readFrames() // closed by defer sc.conn.Close above
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800483
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800484 settingsTimer := time.NewTimer(firstSettingsTimeout)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800485 for {
486 select {
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800487 case wm := <-sc.wantWriteFrameCh:
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800488 sc.writeFrame(wm)
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800489 case <-sc.wroteFrameCh:
490 sc.writingFrame = false
491 sc.scheduleFrameWrite()
Brad Fitzpatrickda4be5d2014-11-15 09:57:03 -0800492 case fg, ok := <-sc.readFrameCh:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800493 if !ok {
494 sc.readFrameCh = nil
495 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800496 if !sc.processFrameFromReader(fg, ok) {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800497 return
498 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800499 if settingsTimer.C != nil {
500 settingsTimer.Stop()
501 settingsTimer.C = nil
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800502 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800503 case <-settingsTimer.C:
504 sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
505 return
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800506 case <-sc.shutdownTimerCh:
507 sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
508 return
Brad Fitzpatrick0db6d652014-11-15 15:49:19 -0800509 case fn := <-sc.testHookCh:
510 fn()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800511 }
512 }
513}
514
Brad Fitzpatrick95842032014-11-15 09:47:42 -0800515// readPreface reads the ClientPreface greeting from the peer
516// or returns an error on timeout or an invalid greeting.
517func (sc *serverConn) readPreface() error {
518 errc := make(chan error, 1)
519 go func() {
520 // Read the client preface
521 buf := make([]byte, len(ClientPreface))
Brad Fitzpatrick95842032014-11-15 09:47:42 -0800522 if _, err := io.ReadFull(sc.conn, buf); err != nil {
523 errc <- err
524 } else if !bytes.Equal(buf, clientPreface) {
525 errc <- fmt.Errorf("bogus greeting %q", buf)
526 } else {
527 errc <- nil
528 }
529 }()
530 timer := time.NewTimer(5 * time.Second) // TODO: configurable on *Server?
531 defer timer.Stop()
532 select {
533 case <-timer.C:
534 return errors.New("timeout waiting for client preface")
535 case err := <-errc:
536 if err == nil {
537 sc.vlogf("client %v said hello", sc.conn.RemoteAddr())
538 }
539 return err
540 }
541}
542
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800543// writeDataFromHandler writes the data described in req to stream.id.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800544//
545// The provided ch is used to avoid allocating new channels for each
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800546// write operation. It's expected that the caller reuses writeData and ch
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800547// over time.
Brad Fitzpatrick1797e702014-11-26 10:43:20 -0800548//
549// The flow control currently happens in the Handler where it waits
550// for 1 or more bytes to be available to then write here. So at this
551// point we know that we have flow control. But this might have to
552// change when priority is implemented, so the serve goroutine knows
553// the total amount of bytes waiting to be sent and can can have more
554// scheduling decisions available.
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800555func (sc *serverConn) writeDataFromHandler(stream *stream, writeData *writeData, ch chan error) error {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800556 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800557 write: writeData,
558 stream: stream,
559 done: ch,
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800560 })
561 select {
562 case err := <-ch:
563 return err
564 case <-sc.doneServing:
565 return errClientDisconnected
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800566 case <-stream.cw:
567 return errStreamBroken
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800568 }
569}
570
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800571// writeFrameFromHandler sends wm to sc.wantWriteFrameCh, but aborts
572// if the connection has gone away.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800573//
574// This must not be run from the serve goroutine itself, else it might
575// deadlock writing to sc.wantWriteFrameCh (which is only mildly
576// buffered and is read by serve itself). If you're on the serve
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800577// goroutine, call writeFrame instead.
578func (sc *serverConn) writeFrameFromHandler(wm frameWriteMsg) {
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -0800579 sc.serveG.checkNotOn() // NOT
580 select {
581 case sc.wantWriteFrameCh <- wm:
582 case <-sc.doneServing:
583 // Client has closed their connection to the server.
584 }
Brad Fitzpatricka29a3232014-11-15 11:18:25 -0800585}
586
Brad Fitzpatricka92fa952014-12-02 10:31:34 -0800587// writeFrame schedules a frame to write and sends it if there's nothing
588// already being written.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -0800589//
Brad Fitzpatricka92fa952014-12-02 10:31:34 -0800590// There is no pushback here (the serve goroutine never blocks). It's
591// the http.Handlers that block, waiting for their previous frames to
592// make it onto the wire
593//
594// If you're not on the serve goroutine, use writeFrameFromHandler instead.
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800595func (sc *serverConn) writeFrame(wm frameWriteMsg) {
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800596 sc.serveG.check()
Brad Fitzpatricka13c4a42014-11-27 17:47:29 -0800597 sc.writeSched.add(wm)
Tatsuhiro Tsujikawacc1e1da2014-12-02 20:04:27 +0900598 sc.scheduleFrameWrite()
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800599}
600
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800601// startFrameWrite starts a goroutine to write wm (in a separate
602// goroutine since that might block on the network), and updates the
603// serve goroutine's state about the world, updated from info in wm.
604func (sc *serverConn) startFrameWrite(wm frameWriteMsg) {
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800605 sc.serveG.check()
606 if sc.writingFrame {
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800607 panic("internal error: can only be writing one frame at a time")
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800608 }
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800609
610 st := wm.stream
611 if st != nil {
612 switch st.state {
613 case stateHalfClosedLocal:
614 panic("internal error: attempt to send frame on half-closed-local stream")
615 case stateClosed:
616 if st.sentReset || st.gotReset {
617 // Skip this frame. But fake the frame write to reschedule:
618 sc.wroteFrameCh <- struct{}{}
619 return
620 }
Brad Fitzpatricka92fa952014-12-02 10:31:34 -0800621 panic(fmt.Sprintf("internal error: attempt to send a write %v on a closed stream", wm))
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800622 }
623 }
624
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800625 sc.writingFrame = true
Brad Fitzpatrick5e4e2dc2014-11-19 16:49:43 -0800626 sc.needsFrameFlush = true
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800627 if endsStream(wm.write) {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800628 if st == nil {
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800629 panic("internal error: expecting non-nil stream")
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800630 }
631 switch st.state {
632 case stateOpen:
633 st.state = stateHalfClosedLocal
634 case stateHalfClosedRemote:
635 sc.closeStream(st, nil)
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800636 }
637 }
Brad Fitzpatrickaa524f62014-11-25 10:31:37 -0800638 go sc.writeFrameAsync(wm)
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -0800639}
640
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800641// scheduleFrameWrite tickles the frame writing scheduler.
642//
643// If a frame is already being written, nothing happens. This will be called again
644// when the frame is done being written.
645//
646// If a frame isn't being written we need to send one, the best frame
647// to send is selected, preferring first things that aren't
648// stream-specific (e.g. ACKing settings), and then finding the
649// highest priority stream.
650//
651// If a frame isn't being written and there's nothing else to send, we
652// flush the write buffer.
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800653func (sc *serverConn) scheduleFrameWrite() {
654 sc.serveG.check()
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800655 if sc.writingFrame {
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800656 return
657 }
658 if sc.needToSendGoAway {
659 sc.needToSendGoAway = false
Brad Fitzpatrick165c0982014-11-26 08:53:01 -0800660 sc.startFrameWrite(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800661 write: &writeGoAway{
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800662 maxStreamID: sc.maxStreamID,
663 code: sc.goAwayCode,
664 },
665 })
666 return
667 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800668 if sc.needToSendSettingsAck {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800669 sc.needToSendSettingsAck = false
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800670 sc.startFrameWrite(frameWriteMsg{write: writeSettingsAck{}})
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800671 return
672 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800673 if !sc.inGoAway {
674 if wm, ok := sc.writeSched.take(); ok {
675 sc.startFrameWrite(wm)
676 return
677 }
678 }
679 if sc.needsFrameFlush {
680 sc.startFrameWrite(frameWriteMsg{write: flushFrameWriter{}})
681 sc.needsFrameFlush = false // after startFrameWrite, since it sets this true
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800682 return
683 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -0800684}
685
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800686func (sc *serverConn) goAway(code ErrCode) {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800687 sc.serveG.check()
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800688 if sc.inGoAway {
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800689 return
690 }
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800691 if code != ErrCodeNo {
692 sc.shutDownIn(250 * time.Millisecond)
693 } else {
694 // TODO: configurable
695 sc.shutDownIn(1 * time.Second)
696 }
697 sc.inGoAway = true
698 sc.needToSendGoAway = true
699 sc.goAwayCode = code
700 sc.scheduleFrameWrite()
701}
702
703func (sc *serverConn) shutDownIn(d time.Duration) {
704 sc.serveG.check()
705 sc.shutdownTimer = time.NewTimer(d)
706 sc.shutdownTimerCh = sc.shutdownTimer.C
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800707}
708
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800709func (sc *serverConn) resetStream(se StreamError) {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800710 sc.serveG.check()
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -0800711 st, ok := sc.streams[se.StreamID]
712 if !ok {
713 panic("internal package error; resetStream called on non-existent stream")
714 }
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800715 sc.writeFrame(frameWriteMsg{write: se})
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -0800716 st.sentReset = true
717 sc.closeStream(st, se)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800718}
719
Brad Fitzpatrickb0a06c82014-11-26 09:21:28 -0800720// curHeaderStreamID returns the stream ID of the header block we're
721// currently in the middle of reading. If this returns non-zero, the
722// next frame must be a CONTINUATION with this stream id.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800723func (sc *serverConn) curHeaderStreamID() uint32 {
724 sc.serveG.check()
725 st := sc.req.stream
726 if st == nil {
727 return 0
728 }
729 return st.id
730}
731
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800732// processFrameFromReader processes the serve loop's read from readFrameCh from the
733// frame-reading goroutine.
734// processFrameFromReader returns whether the connection should be kept open.
735func (sc *serverConn) processFrameFromReader(fg frameAndGate, fgValid bool) bool {
736 sc.serveG.check()
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800737 var clientGone bool
738 var err error
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800739 if !fgValid {
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800740 err = <-sc.readFrameErrCh
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800741 if err == ErrFrameTooLarge {
742 sc.goAway(ErrCodeFrameSize)
743 return true // goAway will close the loop
744 }
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800745 clientGone = err == io.EOF || strings.Contains(err.Error(), "use of closed network connection")
746 if clientGone {
747 // TODO: could we also get into this state if
748 // the peer does a half close
749 // (e.g. CloseWrite) because they're done
750 // sending frames but they're still wanting
751 // our open replies? Investigate.
752 return false
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800753 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800754 }
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800755
756 if fgValid {
757 f := fg.f
758 sc.vlogf("got %v: %#v", f.Header(), f)
759 err = sc.processFrame(f)
760 fg.g.Done() // unblock the readFrames goroutine
761 if err == nil {
762 return true
763 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800764 }
765
766 switch ev := err.(type) {
767 case StreamError:
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800768 sc.resetStream(ev)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800769 return true
770 case goAwayFlowError:
Brad Fitzpatrick55815ec2014-11-15 13:29:57 -0800771 sc.goAway(ErrCodeFlowControl)
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800772 return true
773 case ConnectionError:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800774 sc.logf("%v: %v", sc.conn.RemoteAddr(), ev)
775 sc.goAway(ErrCode(ev))
776 return true // goAway will handle shutdown
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800777 default:
Brad Fitzpatrick8ec321e2014-11-25 14:08:16 -0800778 if !fgValid {
779 sc.logf("disconnecting; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)
780 } else {
781 sc.logf("disconnection due to other error: %v", err)
782 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800783 }
784 return false
785}
786
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800787func (sc *serverConn) processFrame(f Frame) error {
788 sc.serveG.check()
789
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800790 // First frame received must be SETTINGS.
791 if !sc.sawFirstSettings {
792 if _, ok := f.(*SettingsFrame); !ok {
793 return ConnectionError(ErrCodeProtocol)
794 }
795 sc.sawFirstSettings = true
796 }
797
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800798 if s := sc.curHeaderStreamID(); s != 0 {
799 if cf, ok := f.(*ContinuationFrame); !ok {
800 return ConnectionError(ErrCodeProtocol)
801 } else if cf.Header().StreamID != s {
802 return ConnectionError(ErrCodeProtocol)
803 }
804 }
805
806 switch f := f.(type) {
807 case *SettingsFrame:
808 return sc.processSettings(f)
809 case *HeadersFrame:
810 return sc.processHeaders(f)
811 case *ContinuationFrame:
812 return sc.processContinuation(f)
813 case *WindowUpdateFrame:
814 return sc.processWindowUpdate(f)
815 case *PingFrame:
816 return sc.processPing(f)
817 case *DataFrame:
818 return sc.processData(f)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800819 case *RSTStreamFrame:
820 return sc.processResetStream(f)
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -0800821 case *PriorityFrame:
822 return sc.processPriority(f)
Daniel Morsing9f251692014-12-05 18:17:30 +0000823 case *PushPromiseFrame:
824 // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
825 // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
826 return ConnectionError(ErrCodeProtocol)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800827 default:
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -0800828 log.Printf("Ignoring frame: %v", f.Header())
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800829 return nil
830 }
831}
832
833func (sc *serverConn) processPing(f *PingFrame) error {
834 sc.serveG.check()
835 if f.Flags.Has(FlagSettingsAck) {
836 // 6.7 PING: " An endpoint MUST NOT respond to PING frames
837 // containing this flag."
838 return nil
839 }
840 if f.StreamID != 0 {
841 // "PING frames are not associated with any individual
842 // stream. If a PING frame is received with a stream
843 // identifier field value other than 0x0, the recipient MUST
844 // respond with a connection error (Section 5.4.1) of type
845 // PROTOCOL_ERROR."
846 return ConnectionError(ErrCodeProtocol)
847 }
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -0800848 sc.writeFrame(frameWriteMsg{write: writePingAck{f}})
Brad Fitzpatrick9e0eccc2014-11-15 09:14:49 -0800849 return nil
850}
851
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800852func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
853 sc.serveG.check()
854 switch {
855 case f.StreamID != 0: // stream-level flow control
856 st := sc.streams[f.StreamID]
857 if st == nil {
858 // "WINDOW_UPDATE can be sent by a peer that has sent a
859 // frame bearing the END_STREAM flag. This means that a
860 // receiver could receive a WINDOW_UPDATE frame on a "half
861 // closed (remote)" or "closed" stream. A receiver MUST
862 // NOT treat this as an error, see Section 5.1."
863 return nil
864 }
865 if !st.flow.add(int32(f.Increment)) {
866 return StreamError{f.StreamID, ErrCodeFlowControl}
867 }
868 default: // connection-level flow control
869 if !sc.flow.add(int32(f.Increment)) {
870 return goAwayFlowError{}
871 }
872 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800873 sc.scheduleFrameWrite()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800874 return nil
875}
876
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800877func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
878 sc.serveG.check()
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800879 if sc.state(f.StreamID) == stateIdle {
880 // 6.4 "RST_STREAM frames MUST NOT be sent for a
881 // stream in the "idle" state. If a RST_STREAM frame
882 // identifying an idle stream is received, the
883 // recipient MUST treat this as a connection error
884 // (Section 5.4.1) of type PROTOCOL_ERROR.
885 return ConnectionError(ErrCodeProtocol)
886 }
887 st, ok := sc.streams[f.StreamID]
888 if ok {
889 st.gotReset = true
890 sc.closeStream(st, StreamError{f.StreamID, f.ErrCode})
891 }
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800892 return nil
893}
894
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800895func (sc *serverConn) closeStream(st *stream, err error) {
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800896 sc.serveG.check()
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800897 if st.state == stateIdle || st.state == stateClosed {
898 panic("invariant")
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800899 }
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800900 st.state = stateClosed
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800901 sc.curOpenStreams--
Brad Fitzpatrickbd391962014-11-17 18:58:58 -0800902 delete(sc.streams, st.id)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800903 if p := st.body; p != nil {
904 p.Close(err)
905 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800906 st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
Brad Fitzpatrick5b95eb32014-12-02 10:52:56 -0800907 sc.writeSched.forgetStream(st.id)
Brad Fitzpatrick6d3aa4f2014-11-15 14:55:57 -0800908}
909
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800910func (sc *serverConn) processSettings(f *SettingsFrame) error {
911 sc.serveG.check()
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800912 if f.IsAck() {
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -0800913 sc.unackedSettings--
914 if sc.unackedSettings < 0 {
915 // Why is the peer ACKing settings we never sent?
916 // The spec doesn't mention this case, but
917 // hang up on them anyway.
918 return ConnectionError(ErrCodeProtocol)
919 }
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800920 return nil
921 }
922 if err := f.ForeachSetting(sc.processSetting); err != nil {
923 return err
924 }
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -0800925 sc.needToSendSettingsAck = true
926 sc.scheduleFrameWrite()
Brad Fitzpatrickd07a0e42014-11-15 10:47:12 -0800927 return nil
928}
929
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800930func (sc *serverConn) processSetting(s Setting) error {
931 sc.serveG.check()
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800932 if err := s.Valid(); err != nil {
933 return err
934 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800935 sc.vlogf("processing setting %v", s)
936 switch s.ID {
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800937 case SettingHeaderTableSize:
938 sc.headerTableSize = s.Val
Tatsuhiro Tsujikawac7d67a52014-11-20 01:01:39 +0900939 sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800940 case SettingEnablePush:
941 sc.pushEnabled = s.Val != 0
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800942 case SettingMaxConcurrentStreams:
Brad Fitzpatrick6ec17312014-11-23 10:07:07 -0800943 sc.clientMaxStreams = s.Val
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800944 case SettingInitialWindowSize:
945 return sc.processSettingInitialWindowSize(s.Val)
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800946 case SettingMaxFrameSize:
Brad Fitzpatrick2b459472014-11-30 19:18:57 -0800947 sc.writeSched.maxFrameSize = s.Val
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800948 case SettingMaxHeaderListSize:
949 sc.maxHeaderListSize = s.Val
gbbr0b3b5742014-11-23 00:44:48 +0000950 default:
951 // Unknown setting: "An endpoint that receives a SETTINGS
952 // frame with any unknown or unsupported identifier MUST
953 // ignore that setting."
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800954 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800955 return nil
956}
957
958func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
959 sc.serveG.check()
Brad Fitzpatrickbc00c572014-11-17 12:28:01 -0800960 // Note: val already validated to be within range by
961 // processSetting's Valid call.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800962
963 // "A SETTINGS frame can alter the initial flow control window
964 // size for all current streams. When the value of
965 // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
966 // adjust the size of all stream flow control windows that it
967 // maintains by the difference between the new value and the
968 // old value."
969 old := sc.initialWindowSize
970 sc.initialWindowSize = int32(val)
971 growth := sc.initialWindowSize - old // may be negative
972 for _, st := range sc.streams {
973 if !st.flow.add(growth) {
974 // 6.9.2 Initial Flow Control Window Size
975 // "An endpoint MUST treat a change to
976 // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
977 // control window to exceed the maximum size as a
978 // connection error (Section 5.4.1) of type
979 // FLOW_CONTROL_ERROR."
980 return ConnectionError(ErrCodeFlowControl)
981 }
982 }
983 return nil
984}
985
986func (sc *serverConn) processData(f *DataFrame) error {
987 sc.serveG.check()
988 // "If a DATA frame is received whose stream is not in "open"
989 // or "half closed (local)" state, the recipient MUST respond
990 // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
991 id := f.Header().StreamID
992 st, ok := sc.streams[id]
993 if !ok || (st.state != stateOpen && st.state != stateHalfClosedLocal) {
994 return StreamError{id, ErrCodeStreamClosed}
995 }
996 if st.body == nil {
Brad Fitzpatrickb0a06c82014-11-26 09:21:28 -0800997 panic("internal error: should have a body in this state")
Brad Fitzpatrickb331b812014-11-13 11:51:54 -0800998 }
999 data := f.Data()
1000
1001 // Sender sending more than they'd declared?
1002 if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
gbbrd90e0982014-11-20 22:19:20 +00001003 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 -08001004 return StreamError{id, ErrCodeStreamClosed}
1005 }
1006 if len(data) > 0 {
1007 // TODO: verify they're allowed to write with the flow control
1008 // window we'd advertised to them.
Brad Fitzpatrick0218ba62014-11-26 09:36:05 -08001009 wrote, err := st.body.Write(data)
1010 if err != nil {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001011 return StreamError{id, ErrCodeStreamClosed}
1012 }
Brad Fitzpatrick0218ba62014-11-26 09:36:05 -08001013 if wrote != len(data) {
1014 panic("internal error: bad Writer")
1015 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001016 st.bodyBytes += int64(len(data))
1017 }
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001018 if f.StreamEnded() {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001019 if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
gbbrd90e0982014-11-20 22:19:20 +00001020 st.body.Close(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001021 st.declBodyBytes, st.bodyBytes))
1022 } else {
1023 st.body.Close(io.EOF)
1024 }
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001025 switch st.state {
1026 case stateOpen:
1027 st.state = stateHalfClosedRemote
1028 case stateHalfClosedLocal:
1029 st.state = stateClosed
1030 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001031 }
1032 return nil
1033}
1034
1035func (sc *serverConn) processHeaders(f *HeadersFrame) error {
1036 sc.serveG.check()
1037 id := f.Header().StreamID
Brad Fitzpatrick21896bb2014-11-19 16:05:21 -08001038 if sc.inGoAway {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001039 // Ignore.
1040 return nil
1041 }
1042 // http://http2.github.io/http2-spec/#rfc.section.5.1.1
1043 if id%2 != 1 || id <= sc.maxStreamID || sc.req.stream != nil {
1044 // Streams initiated by a client MUST use odd-numbered
1045 // stream identifiers. [...] The identifier of a newly
1046 // established stream MUST be numerically greater than all
1047 // streams that the initiating endpoint has opened or
1048 // reserved. [...] An endpoint that receives an unexpected
1049 // stream identifier MUST respond with a connection error
1050 // (Section 5.4.1) of type PROTOCOL_ERROR.
1051 return ConnectionError(ErrCodeProtocol)
1052 }
1053 if id > sc.maxStreamID {
1054 sc.maxStreamID = id
1055 }
1056 st := &stream{
1057 id: id,
1058 state: stateOpen,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001059 }
Tatsuhiro Tsujikawacc1e1da2014-12-02 20:04:27 +09001060 // connection-level flow control is shared by all streams.
1061 st.flow.conn = &sc.flow
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001062 st.flow.add(sc.initialWindowSize)
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001063 st.cw.Init() // make Cond use its Mutex, without heap-promoting them separately
1064 if f.StreamEnded() {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001065 st.state = stateHalfClosedRemote
1066 }
1067 sc.streams[id] = st
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -08001068 if f.HasPriority() {
1069 sc.adjustStreamPriority(st.id, f.Priority)
1070 }
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001071 sc.curOpenStreams++
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001072 sc.req = requestParam{
1073 stream: st,
1074 header: make(http.Header),
1075 }
1076 return sc.processHeaderBlockFragment(st, f.HeaderBlockFragment(), f.HeadersEnded())
1077}
1078
1079func (sc *serverConn) processContinuation(f *ContinuationFrame) error {
1080 sc.serveG.check()
1081 st := sc.streams[f.Header().StreamID]
1082 if st == nil || sc.curHeaderStreamID() != st.id {
1083 return ConnectionError(ErrCodeProtocol)
1084 }
1085 return sc.processHeaderBlockFragment(st, f.HeaderBlockFragment(), f.HeadersEnded())
1086}
1087
1088func (sc *serverConn) processHeaderBlockFragment(st *stream, frag []byte, end bool) error {
1089 sc.serveG.check()
1090 if _, err := sc.hpackDecoder.Write(frag); err != nil {
1091 // TODO: convert to stream error I assume?
1092 return err
1093 }
1094 if !end {
1095 return nil
1096 }
1097 if err := sc.hpackDecoder.Close(); err != nil {
1098 // TODO: convert to stream error I assume?
1099 return err
1100 }
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001101 defer sc.resetPendingRequest()
1102 if sc.curOpenStreams > sc.advMaxStreams {
Brad Fitzpatrick6a9b77b2014-12-03 13:56:36 -08001103 // "Endpoints MUST NOT exceed the limit set by their
1104 // peer. An endpoint that receives a HEADERS frame
1105 // that causes their advertised concurrent stream
1106 // limit to be exceeded MUST treat this as a stream
1107 // error (Section 5.4.2) of type PROTOCOL_ERROR or
1108 // REFUSED_STREAM."
1109 if sc.unackedSettings == 0 {
1110 // They should know better.
1111 return StreamError{st.id, ErrCodeProtocol}
1112 }
1113 // Assume it's a network race, where they just haven't
1114 // received our last SETTINGS update. But actually
1115 // this can't happen yet, because we don't yet provide
1116 // a way for users to adjust server parameters at
1117 // runtime.
1118 return StreamError{st.id, ErrCodeRefusedStream}
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001119 }
1120
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001121 rw, req, err := sc.newWriterAndRequest()
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001122 if err != nil {
1123 return err
1124 }
1125 st.body = req.Body.(*requestBody).pipe // may be nil
1126 st.declBodyBytes = req.ContentLength
1127 go sc.runHandler(rw, req)
1128 return nil
1129}
1130
Brad Fitzpatrick2ee3a492014-11-30 23:18:32 -08001131func (sc *serverConn) processPriority(f *PriorityFrame) error {
1132 sc.adjustStreamPriority(f.StreamID, f.PriorityParam)
1133 return nil
1134}
1135
1136func (sc *serverConn) adjustStreamPriority(streamID uint32, priority PriorityParam) {
1137 // TODO: untested
1138 st, ok := sc.streams[streamID]
1139 if !ok {
1140 // TODO: not quite correct (this streamID might
1141 // already exist in the dep tree, but be closed), but
1142 // close enough for now.
1143 return
1144 }
1145 st.weight = priority.Weight
1146 st.parent = sc.streams[priority.StreamDep] // might be nil
1147 if priority.Exclusive && st.parent != nil {
1148 for _, openStream := range sc.streams {
1149 if openStream.parent == st.parent {
1150 openStream.parent = st
1151 }
1152 }
1153 }
1154}
1155
Brad Fitzpatrickb3e0a872014-11-23 21:15:59 -08001156// resetPendingRequest zeros out all state related to a HEADERS frame
1157// and its zero or more CONTINUATION frames sent to start a new
1158// request.
1159func (sc *serverConn) resetPendingRequest() {
1160 sc.serveG.check()
1161 sc.req = requestParam{}
1162}
1163
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001164func (sc *serverConn) newWriterAndRequest() (*responseWriter, *http.Request, error) {
1165 sc.serveG.check()
1166 rp := &sc.req
1167 if rp.invalidHeader || rp.method == "" || rp.path == "" ||
1168 (rp.scheme != "https" && rp.scheme != "http") {
1169 // See 8.1.2.6 Malformed Requests and Responses:
1170 //
1171 // Malformed requests or responses that are detected
1172 // MUST be treated as a stream error (Section 5.4.2)
1173 // of type PROTOCOL_ERROR."
1174 //
1175 // 8.1.2.3 Request Pseudo-Header Fields
1176 // "All HTTP/2 requests MUST include exactly one valid
1177 // value for the :method, :scheme, and :path
1178 // pseudo-header fields"
1179 return nil, nil, StreamError{rp.stream.id, ErrCodeProtocol}
1180 }
1181 var tlsState *tls.ConnectionState // make this non-nil if https
1182 if rp.scheme == "https" {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001183 tlsState = &tls.ConnectionState{}
Brad Fitzpatrick7482ed02014-11-18 15:45:54 -08001184 if tc, ok := sc.conn.(*tls.Conn); ok {
1185 *tlsState = tc.ConnectionState()
1186 if tlsState.Version < tls.VersionTLS12 {
1187 // 9.2 Use of TLS Features
1188 // An implementation of HTTP/2 over TLS MUST use TLS
1189 // 1.2 or higher with the restrictions on feature set
1190 // and cipher suite described in this section. Due to
1191 // implementation limitations, it might not be
1192 // possible to fail TLS negotiation. An endpoint MUST
1193 // immediately terminate an HTTP/2 connection that
1194 // does not meet the TLS requirements described in
1195 // this section with a connection error (Section
1196 // 5.4.1) of type INADEQUATE_SECURITY.
1197 return nil, nil, ConnectionError(ErrCodeInadequateSecurity)
1198 }
1199 // TODO: verify cipher suites. (9.2.1, 9.2.2)
1200 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001201 }
1202 authority := rp.authority
1203 if authority == "" {
1204 authority = rp.header.Get("Host")
1205 }
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001206 needsContinue := rp.header.Get("Expect") == "100-continue"
1207 if needsContinue {
1208 rp.header.Del("Expect")
1209 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001210 bodyOpen := rp.stream.state == stateOpen
1211 body := &requestBody{
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001212 conn: sc,
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001213 stream: rp.stream,
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001214 needsContinue: needsContinue,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001215 }
Brad Fitzpatrickad4757f2014-11-26 09:37:40 -08001216 // TODO: handle asterisk '*' requests + test
Brad Fitzpatrickff0471b2014-11-14 21:55:14 -08001217 url, err := url.ParseRequestURI(rp.path)
1218 if err != nil {
1219 // TODO: find the right error code?
1220 return nil, nil, StreamError{rp.stream.id, ErrCodeProtocol}
1221 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001222 req := &http.Request{
1223 Method: rp.method,
Brad Fitzpatrickff0471b2014-11-14 21:55:14 -08001224 URL: url,
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001225 RemoteAddr: sc.conn.RemoteAddr().String(),
1226 Header: rp.header,
1227 RequestURI: rp.path,
1228 Proto: "HTTP/2.0",
1229 ProtoMajor: 2,
1230 ProtoMinor: 0,
1231 TLS: tlsState,
1232 Host: authority,
1233 Body: body,
1234 }
1235 if bodyOpen {
1236 body.pipe = &pipe{
1237 b: buffer{buf: make([]byte, 65536)}, // TODO: share/remove
1238 }
1239 body.pipe.c.L = &body.pipe.m
1240
1241 if vv, ok := rp.header["Content-Length"]; ok {
1242 req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
1243 } else {
1244 req.ContentLength = -1
1245 }
1246 }
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001247
1248 rws := responseWriterStatePool.Get().(*responseWriterState)
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001249 bwSave := rws.bw
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001250 *rws = responseWriterState{} // zero all the fields
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001251 rws.conn = sc
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001252 rws.bw = bwSave
1253 rws.bw.Reset(chunkWriter{rws})
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001254 rws.stream = rp.stream
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001255 rws.req = req
1256 rws.body = body
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001257 rws.frameWriteCh = make(chan error, 1)
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001258
1259 rw := &responseWriter{rws: rws}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001260 return rw, req, nil
1261}
1262
1263// Run on its own goroutine.
1264func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request) {
1265 defer rw.handlerDone()
1266 // TODO: catch panics like net/http.Server
1267 sc.handler.ServeHTTP(rw, req)
1268}
1269
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001270// called from handler goroutines.
1271// h may be nil.
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001272func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders, tempCh chan error) {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001273 sc.serveG.checkNotOn() // NOT on
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001274 var errc chan error
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001275 if headerData.h != nil {
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001276 // If there's a header map (which we don't own), so we have to block on
1277 // waiting for this frame to be written, so an http.Flush mid-handler
1278 // writes out the correct value of keys, before a handler later potentially
1279 // mutates it.
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001280 errc = tempCh
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001281 }
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -08001282 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001283 write: headerData,
1284 stream: st,
1285 done: errc,
Brad Fitzpatricka29a3232014-11-15 11:18:25 -08001286 })
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001287 if errc != nil {
Brad Fitzpatrick9b41faf2014-11-19 10:45:13 -08001288 select {
1289 case <-errc:
1290 // Ignore. Just for synchronization.
1291 // Any error will be handled in the writing goroutine.
1292 case <-sc.doneServing:
1293 // Client has closed the connection.
1294 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001295 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001296}
1297
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001298// called from handler goroutines.
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001299func (sc *serverConn) write100ContinueHeaders(st *stream) {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -08001300 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001301 write: write100ContinueHeadersFrame{st.id},
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001302 stream: st,
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001303 })
1304}
1305
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001306// called from handler goroutines
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001307func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
1308 if st == nil {
1309 panic("no stream")
1310 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001311 const maxUint32 = 2147483647
1312 for n >= maxUint32 {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -08001313 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001314 write: writeWindowUpdate{streamID: st.id, n: maxUint32},
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001315 stream: st,
Brad Fitzpatricka29a3232014-11-15 11:18:25 -08001316 })
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001317 n -= maxUint32
1318 }
1319 if n > 0 {
Brad Fitzpatrick4e3c9222014-11-22 17:35:09 -08001320 sc.writeFrameFromHandler(frameWriteMsg{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001321 write: writeWindowUpdate{streamID: st.id, n: uint32(n)},
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001322 stream: st,
Brad Fitzpatricka29a3232014-11-15 11:18:25 -08001323 })
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001324 }
1325}
1326
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001327type requestBody struct {
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001328 stream *stream
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001329 conn *serverConn
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001330 closed bool
1331 pipe *pipe // non-nil if we have a HTTP entity message body
1332 needsContinue bool // need to send a 100-continue
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001333}
1334
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001335func (b *requestBody) Close() error {
1336 if b.pipe != nil {
1337 b.pipe.Close(errClosedBody)
1338 }
1339 b.closed = true
1340 return nil
1341}
1342
1343func (b *requestBody) Read(p []byte) (n int, err error) {
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001344 if b.needsContinue {
1345 b.needsContinue = false
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001346 b.conn.write100ContinueHeaders(b.stream)
Brad Fitzpatrick9d63ade2014-11-15 12:02:43 -08001347 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001348 if b.pipe == nil {
1349 return 0, io.EOF
1350 }
1351 n, err = b.pipe.Read(p)
1352 if n > 0 {
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001353 b.conn.sendWindowUpdate(b.stream, n)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001354 }
1355 return
1356}
1357
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001358// responseWriter is the http.ResponseWriter implementation. It's
1359// intentionally small (1 pointer wide) to minimize garbage. The
1360// responseWriterState pointer inside is zeroed at the end of a
1361// request (in handlerDone) and calls on the responseWriter thereafter
1362// simply crash (caller's mistake), but the much larger responseWriterState
1363// and buffers are reused between multiple requests.
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001364type responseWriter struct {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001365 rws *responseWriterState
1366}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001367
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001368// Optional http.ResponseWriter interfaces implemented.
1369var (
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001370 _ http.CloseNotifier = (*responseWriter)(nil)
1371 _ http.Flusher = (*responseWriter)(nil)
1372 _ stringWriter = (*responseWriter)(nil)
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001373)
1374
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001375type responseWriterState struct {
1376 // immutable within a request:
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001377 stream *stream
1378 req *http.Request
1379 body *requestBody // to close at end of request, if DATA frames didn't
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001380 conn *serverConn
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001381
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001382 // TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001383 bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState}
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001384
1385 // mutated by http.Handler goroutine:
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001386 handlerHeader http.Header // nil until called
1387 snapHeader http.Header // snapshot of handlerHeader at WriteHeader time
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001388 status int // status code passed to WriteHeader
Brad Fitzpatrick3c8c6132014-11-20 18:34:52 -08001389 wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001390 sentHeader bool // have we sent the header frame?
1391 handlerDone bool // handler has finished
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001392 curWrite writeData
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001393 frameWriteCh chan error // re-used whenever we need to block on a frame being written
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001394
1395 closeNotifierMu sync.Mutex // guards closeNotifierCh
1396 closeNotifierCh chan bool // nil until first used
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001397}
1398
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001399type chunkWriter struct{ rws *responseWriterState }
1400
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001401func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001402
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001403// writeChunk writes chunks from the bufio.Writer. But because
1404// bufio.Writer may bypass its chunking, sometimes p may be
1405// arbitrarily large.
1406//
1407// writeChunk is also responsible (on the first chunk) for sending the
1408// HEADER response.
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001409func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
1410 if !rws.wroteHeader {
1411 rws.writeHeader(200)
1412 }
1413 if !rws.sentHeader {
1414 rws.sentHeader = true
1415 var ctype, clen string // implicit ones, if we can calculate it
1416 if rws.handlerDone && rws.snapHeader.Get("Content-Length") == "" {
1417 clen = strconv.Itoa(len(p))
1418 }
1419 if rws.snapHeader.Get("Content-Type") == "" {
1420 ctype = http.DetectContentType(p)
1421 }
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001422 endStream := rws.handlerDone && len(p) == 0
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001423 rws.conn.writeHeaders(rws.stream, &writeResHeaders{
Brad Fitzpatrickf16a0b32014-11-28 13:49:30 -08001424 streamID: rws.stream.id,
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001425 httpResCode: rws.status,
1426 h: rws.snapHeader,
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001427 endStream: endStream,
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001428 contentType: ctype,
1429 contentLength: clen,
Brad Fitzpatrickdc0c5c02014-11-20 14:15:26 -08001430 }, rws.frameWriteCh)
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001431 if endStream {
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001432 return 0, nil
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001433 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001434 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001435 if len(p) == 0 && !rws.handlerDone {
1436 return 0, nil
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001437 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001438 curWrite := &rws.curWrite
1439 curWrite.streamID = rws.stream.id
1440 curWrite.p = p
1441 curWrite.endStream = rws.handlerDone
Brad Fitzpatrick914bad52014-11-30 21:05:26 -08001442 if err := rws.conn.writeDataFromHandler(rws.stream, curWrite, rws.frameWriteCh); err != nil {
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001443 return 0, err
Brad Fitzpatrick3d7a3ad2014-11-15 21:38:23 -08001444 }
Brad Fitzpatrick2b459472014-11-30 19:18:57 -08001445 return len(p), nil
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001446}
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001447
1448func (w *responseWriter) Flush() {
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001449 rws := w.rws
1450 if rws == nil {
1451 panic("Header called after Handler finished")
1452 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001453 if rws.bw.Buffered() > 0 {
1454 if err := rws.bw.Flush(); err != nil {
1455 // Ignore the error. The frame writer already knows.
1456 return
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001457 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001458 } else {
1459 // The bufio.Writer won't call chunkWriter.Write
1460 // (writeChunk with zero bytes, so we have to do it
1461 // ourselves to force the HTTP response header and/or
1462 // final DATA frame (with END_STREAM) to be sent.
1463 rws.writeChunk(nil)
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001464 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001465}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001466
Brad Fitzpatrickbd391962014-11-17 18:58:58 -08001467func (w *responseWriter) CloseNotify() <-chan bool {
1468 rws := w.rws
1469 if rws == nil {
1470 panic("CloseNotify called after Handler finished")
1471 }
1472 rws.closeNotifierMu.Lock()
1473 ch := rws.closeNotifierCh
1474 if ch == nil {
1475 ch = make(chan bool, 1)
1476 rws.closeNotifierCh = ch
1477 go func() {
1478 rws.stream.cw.Wait() // wait for close
1479 ch <- true
1480 }()
1481 }
1482 rws.closeNotifierMu.Unlock()
1483 return ch
1484}
1485
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001486func (w *responseWriter) Header() http.Header {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001487 rws := w.rws
1488 if rws == nil {
1489 panic("Header called after Handler finished")
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001490 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001491 if rws.handlerHeader == nil {
1492 rws.handlerHeader = make(http.Header)
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001493 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001494 return rws.handlerHeader
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001495}
1496
1497func (w *responseWriter) WriteHeader(code int) {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001498 rws := w.rws
1499 if rws == nil {
1500 panic("WriteHeader called after Handler finished")
1501 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001502 rws.writeHeader(code)
1503}
1504
1505func (rws *responseWriterState) writeHeader(code int) {
1506 if !rws.wroteHeader {
1507 rws.wroteHeader = true
1508 rws.status = code
1509 if len(rws.handlerHeader) > 0 {
1510 rws.snapHeader = cloneHeader(rws.handlerHeader)
1511 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001512 }
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001513}
1514
1515func cloneHeader(h http.Header) http.Header {
1516 h2 := make(http.Header, len(h))
1517 for k, vv := range h {
1518 vv2 := make([]string, len(vv))
1519 copy(vv2, vv)
1520 h2[k] = vv2
1521 }
1522 return h2
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001523}
1524
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001525// The Life Of A Write is like this:
1526//
Brad Fitzpatricked26b482014-11-26 09:16:43 -08001527// * Handler calls w.Write or w.WriteString ->
1528// * -> rws.bw (*bufio.Writer) ->
1529// * (Handler migth call Flush)
1530// * -> chunkWriter{rws}
1531// * -> responseWriterState.writeChunk(p []byte)
1532// * -> responseWriterState.writeChunk (most of the magic; see comment there)
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001533func (w *responseWriter) Write(p []byte) (n int, err error) {
1534 return w.write(len(p), p, "")
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001535}
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001536
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001537func (w *responseWriter) WriteString(s string) (n int, err error) {
1538 return w.write(len(s), nil, s)
1539}
1540
1541// either dataB or dataS is non-zero.
1542func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int, err error) {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001543 rws := w.rws
1544 if rws == nil {
1545 panic("Write called after Handler finished")
1546 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001547 if !rws.wroteHeader {
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001548 w.WriteHeader(200)
1549 }
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001550 if dataB != nil {
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001551 return rws.bw.Write(dataB)
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001552 } else {
Brad Fitzpatrick390047e2014-11-14 20:37:08 -08001553 return rws.bw.WriteString(dataS)
Brad Fitzpatrick15a4bf32014-11-14 10:56:12 -08001554 }
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001555}
1556
1557func (w *responseWriter) handlerDone() {
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001558 rws := w.rws
1559 if rws == nil {
1560 panic("handlerDone called twice")
1561 }
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001562 rws.handlerDone = true
1563 w.Flush()
Brad Fitzpatrick729bd722014-11-13 14:09:36 -08001564 w.rws = nil
Brad Fitzpatrick520123b2014-11-14 15:57:37 -08001565 responseWriterStatePool.Put(rws)
Brad Fitzpatrickb331b812014-11-13 11:51:54 -08001566}