Repository navigation
Expand file tree
/
Copy pathserver.go
More file actions
142 lines (117 loc) · 3.96 KB
/
Copy pathserver.go
File metadata and controls
142 lines (117 loc) · 3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package http2
import (
"bufio"
"errors"
"net"
"time"
"github.com/valyala/fasthttp"
)
// DefaultMaxHeaderListSize is the header list size a server accepts when
// ServerConfig.MaxHeaderListSize is left at zero.
const DefaultMaxHeaderListSize = 1 << 20
// ServerConfig ...
type ServerConfig struct {
// PingInterval is the interval at which the server will send a
// ping message to a client.
//
// To disable pings set the PingInterval to a negative value.
PingInterval time.Duration
// MaxConcurrentStreams bounds how many streams a peer may have open on one
// connection, advertised as SETTINGS_MAX_CONCURRENT_STREAMS. A stream over
// the limit is refused with RST_STREAM.
//
// Handlers run on a goroutine each, and a stream holds its slot until its
// handler returns, so this is also the ceiling on handler goroutines per
// connection. Canceling a stream does not hand the slot back early, which
// is what stops a rapid-reset flood buying unbounded concurrency.
//
// Zero means 1024.
MaxConcurrentStreams int
// MaxHeaderListSize bounds the uncompressed size of a request header list,
// summed across the HEADERS frame and every CONTINUATION frame that
// completes it. Each field counts as name + value + 32 bytes, per RFC 7540
// 6.5.2. Exceeding it is a connection error.
//
// Without a limit a header block that never sets END_HEADERS grows the
// server's memory for as long as the client keeps sending, which is the
// CONTINUATION flood.
//
// Zero means DefaultMaxHeaderListSize. A negative value disables the check.
MaxHeaderListSize int
// Debug is a flag that will allow the library to print debugging information.
Debug bool
}
func (sc *ServerConfig) defaults() {
if sc.PingInterval == 0 {
sc.PingInterval = time.Second * 10
}
if sc.MaxConcurrentStreams <= 0 {
sc.MaxConcurrentStreams = 1024
}
if sc.MaxHeaderListSize == 0 {
sc.MaxHeaderListSize = DefaultMaxHeaderListSize
}
}
// Server defines an HTTP/2 entity that can handle HTTP/2 connections.
type Server struct {
s *fasthttp.Server
cnf ServerConfig
}
// ServeConn starts serving a net.Conn as HTTP/2.
//
// This function will fail if the connection does not support the HTTP/2 protocol.
func (s *Server) ServeConn(c net.Conn) error {
defer func() { _ = c.Close() }()
if !ReadPreface(c) {
return errors.New("wrong preface")
}
sc := &serverConn{
c: c,
h: s.s.Handler,
br: bufio.NewReader(c),
bw: bufio.NewWriterSize(c, 1<<14*10),
lastID: 0,
writer: make(chan *FrameHeader, 128),
reader: make(chan *FrameHeader, 128),
maxRequestTime: s.s.ReadTimeout,
maxIdleTime: s.s.IdleTimeout,
pingInterval: s.cnf.PingInterval,
maxHeaderList: s.cnf.MaxHeaderListSize,
// The HTTP/1 side of this server enforces the same limit, so a body
// that would be refused there is refused here too.
maxRequestBodySize: maxRequestBodySize(s.s),
logger: s.s.Logger,
debug: s.cnf.Debug,
}
if sc.logger == nil {
sc.logger = logger
}
sc.enc.Reset()
sc.dec.Reset()
// Until the peer's SETTINGS arrives its settings are the protocol
// defaults. Left at the zero value, SETTINGS_MAX_FRAME_SIZE would be 0,
// which reads as "no limit".
sc.clientS.Reset()
sc.maxWindow = 1 << 22
sc.currentWindow = sc.maxWindow
sc.st.Reset()
sc.st.SetMaxWindowSize(uint32(sc.maxWindow))
sc.st.SetMaxConcurrentStreams(uint32(s.cnf.MaxConcurrentStreams))
// Advertise the limit so a well-behaved client stops before we have to cut
// the connection.
if sc.maxHeaderList > 0 {
sc.st.SetMaxHeaderListSize(uint32(sc.maxHeaderList))
}
if err := sc.Handshake(); err != nil {
return err
}
return sc.Serve()
}
// maxRequestBodySize is the limit the fasthttp server is configured with,
// falling back to the same default it uses.
func maxRequestBodySize(s *fasthttp.Server) int {
if s.MaxRequestBodySize > 0 {
return s.MaxRequestBodySize
}
return fasthttp.DefaultMaxRequestBodySize
}