Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: third_party/grpc/tools/http2_interop/http2interop.go

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 package http2interop
2
3 import (
4 "crypto/tls"
5 "crypto/x509"
6 "fmt"
7 "io"
8 "net"
9 "testing"
10 "time"
11 )
12
13 const (
14 Preface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
15 )
16
17 var (
18 defaultTimeout = 1 * time.Second
19 )
20
21 type HTTP2InteropCtx struct {
22 // Inputs
23 ServerHost string
24 ServerPort int
25 UseTLS bool
26 UseTestCa bool
27 ServerHostnameOverride string
28
29 T *testing.T
30
31 // Derived
32 serverSpec string
33 authority string
34 rootCAs *x509.CertPool
35 }
36
37 func parseFrame(r io.Reader) (Frame, error) {
38 fh := FrameHeader{}
39 if err := fh.Parse(r); err != nil {
40 return nil, err
41 }
42 var f Frame
43 switch fh.Type {
44 case PingFrameType:
45 f = &PingFrame{
46 Header: fh,
47 }
48 case SettingsFrameType:
49 f = &SettingsFrame{
50 Header: fh,
51 }
52 case HTTP1FrameType:
53 f = &HTTP1Frame{
54 Header: fh,
55 }
56 default:
57 f = &UnknownFrame{
58 Header: fh,
59 }
60 }
61
62 if err := f.ParsePayload(r); err != nil {
63 return nil, err
64 }
65
66 return f, nil
67 }
68
69 func streamFrame(w io.Writer, f Frame) error {
70 raw, err := f.MarshalBinary()
71 if err != nil {
72 return err
73 }
74 if _, err := w.Write(raw); err != nil {
75 return err
76 }
77 return nil
78 }
79
80 func testClientShortSettings(ctx *HTTP2InteropCtx, length int) error {
81 conn, err := connect(ctx)
82 if err != nil {
83 return err
84 }
85 defer conn.Close()
86 conn.SetDeadline(time.Now().Add(defaultTimeout))
87
88 if _, err := conn.Write([]byte(Preface)); err != nil {
89 return err
90 }
91
92 // Bad, settings, non multiple of 6
93 sf := &UnknownFrame{
94 Header: FrameHeader{
95 Type: SettingsFrameType,
96 },
97 Data: make([]byte, length),
98 }
99 if err := streamFrame(conn, sf); err != nil {
100 ctx.T.Log("Unable to stream frame", sf)
101 return err
102 }
103
104 if _, err := expectGoAwaySoon(conn); err != nil {
105 return err
106 }
107
108 return nil
109 }
110
111 func testClientPrefaceWithStreamId(ctx *HTTP2InteropCtx) error {
112 conn, err := connect(ctx)
113 if err != nil {
114 return err
115 }
116 defer conn.Close()
117 conn.SetDeadline(time.Now().Add(defaultTimeout))
118
119 // Good so far
120 if _, err := conn.Write([]byte(Preface)); err != nil {
121 return err
122 }
123
124 // Bad, settings do not have ids
125 sf := &SettingsFrame{
126 Header: FrameHeader{
127 StreamID: 1,
128 },
129 }
130 if err := streamFrame(conn, sf); err != nil {
131 return err
132 }
133
134 if _, err := expectGoAwaySoon(conn); err != nil {
135 return err
136 }
137 return nil
138 }
139
140 func testUnknownFrameType(ctx *HTTP2InteropCtx) error {
141 conn, err := connect(ctx)
142 if err != nil {
143 return err
144 }
145 defer conn.Close()
146 conn.SetDeadline(time.Now().Add(defaultTimeout))
147
148 if err := http2Connect(conn, nil); err != nil {
149 return err
150 }
151
152 // Write a bunch of invalid frame types.
153 for ft := ContinuationFrameType + 1; ft != 0; ft++ {
154 fh := &UnknownFrame{
155 Header: FrameHeader{
156 Type: ft,
157 },
158 }
159 if err := streamFrame(conn, fh); err != nil {
160 ctx.T.Log("Unable to stream frame", fh)
161 return err
162 }
163 }
164
165 pf := &PingFrame{
166 Data: []byte("01234567"),
167 }
168 if err := streamFrame(conn, pf); err != nil {
169 ctx.T.Log("Unable to stream frame", pf)
170 return err
171 }
172
173 for {
174 frame, err := parseFrame(conn)
175 if err != nil {
176 ctx.T.Log("Unable to parse frame", err)
177 return err
178 }
179 if npf, ok := frame.(*PingFrame); !ok {
180 ctx.T.Log("Got frame", frame.GetHeader().Type)
181 continue
182 } else {
183 if string(npf.Data) != string(pf.Data) || npf.Header.Fla gs&PING_ACK == 0 {
184 return fmt.Errorf("Bad ping %+v", *npf)
185 }
186 return nil
187 }
188 }
189
190 return nil
191 }
192
193 func testShortPreface(ctx *HTTP2InteropCtx, prefacePrefix string) error {
194 conn, err := connect(ctx)
195 if err != nil {
196 return err
197 }
198 defer conn.Close()
199 conn.SetDeadline(time.Now().Add(defaultTimeout))
200
201 if _, err := conn.Write([]byte(prefacePrefix)); err != nil {
202 return err
203 }
204
205 if _, err := expectGoAwaySoon(conn); err != nil {
206 return err
207 }
208
209 return nil
210 }
211
212 func testTLSMaxVersion(ctx *HTTP2InteropCtx, version uint16) error {
213 config := buildTlsConfig(ctx)
214 config.MaxVersion = version
215 conn, err := connectWithTls(ctx, config)
216 if err != nil {
217 return err
218 }
219 defer conn.Close()
220 conn.SetDeadline(time.Now().Add(defaultTimeout))
221
222 if err := http2Connect(conn, nil); err != nil {
223 return err
224 }
225
226 gf, err := expectGoAway(conn)
227 if err != nil {
228 return err
229 }
230 // TODO: make an enum out of this
231 if gf.Code != 0xC {
232 return fmt.Errorf("Expected an Inadequate security code: %v", gf )
233 }
234 return nil
235 }
236
237 func testTLSApplicationProtocol(ctx *HTTP2InteropCtx) error {
238 config := buildTlsConfig(ctx)
239 config.NextProtos = []string{"h2c"}
240 conn, err := connectWithTls(ctx, config)
241 if err != nil {
242 return err
243 }
244 defer conn.Close()
245 conn.SetDeadline(time.Now().Add(defaultTimeout))
246
247 if err := http2Connect(conn, nil); err != nil {
248 return err
249 }
250
251 gf, err := expectGoAway(conn)
252 if err != nil {
253 return err
254 }
255 // TODO: make an enum out of this
256 if gf.Code != 0xC {
257 return fmt.Errorf("Expected an Inadequate security code: %v", gf )
258 }
259 return nil
260 }
261
262 func testTLSBadCipherSuites(ctx *HTTP2InteropCtx) error {
263 config := buildTlsConfig(ctx)
264 // These are the suites that Go supports, but are forbidden by http2.
265 config.CipherSuites = []uint16{
266 tls.TLS_RSA_WITH_RC4_128_SHA,
267 tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
268 tls.TLS_RSA_WITH_AES_128_CBC_SHA,
269 tls.TLS_RSA_WITH_AES_256_CBC_SHA,
270 tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
271 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
272 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
273 tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
274 tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
275 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
276 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
277 }
278 conn, err := connectWithTls(ctx, config)
279 if err != nil {
280 return err
281 }
282 defer conn.Close()
283 conn.SetDeadline(time.Now().Add(defaultTimeout))
284
285 if err := http2Connect(conn, nil); err != nil {
286 return err
287 }
288
289 gf, err := expectGoAway(conn)
290 if err != nil {
291 return err
292 }
293 // TODO: make an enum out of this
294 if gf.Code != 0xC {
295 return fmt.Errorf("Expected an Inadequate security code: %v", gf )
296 }
297 return nil
298 }
299
300 func expectGoAway(conn net.Conn) (*GoAwayFrame, error) {
301 f, err := parseFrame(conn)
302 if err != nil {
303 return nil, err
304 }
305 if gf, ok := f.(*GoAwayFrame); !ok {
306 return nil, fmt.Errorf("Expected GoAway Frame %+v", f)
307 } else {
308 return gf, nil
309 }
310 }
311
312 // expectGoAwaySoon checks that a GOAWAY frame eventually comes. Servers usuall y send
313 // the initial settings frames before any data has actually arrived. This funct ion
314 // checks that a go away shows.
315 func expectGoAwaySoon(conn net.Conn) (*GoAwayFrame, error) {
316 for {
317 f, err := parseFrame(conn)
318 if err != nil {
319 return nil, err
320 }
321 if gf, ok := f.(*GoAwayFrame); !ok {
322 continue
323 } else {
324 return gf, nil
325 }
326 }
327 }
328
329 func http2Connect(c net.Conn, sf *SettingsFrame) error {
330 if _, err := c.Write([]byte(Preface)); err != nil {
331 return err
332 }
333
334 if sf == nil {
335 sf = &SettingsFrame{}
336 }
337 if err := streamFrame(c, sf); err != nil {
338 return err
339 }
340 return nil
341 }
342
343 // CapConn captures connection traffic if Log is non-nil
344 type CapConn struct {
345 net.Conn
346 Log func(args ...interface{})
347 }
348
349 func (c *CapConn) Write(data []byte) (int, error) {
350 if c.Log != nil {
351 c.Log(" SEND: ", data)
352 }
353 return c.Conn.Write(data)
354 }
355
356 func (c *CapConn) Read(data []byte) (int, error) {
357 n, err := c.Conn.Read(data)
358 if c.Log != nil {
359 c.Log(" RECV: ", data[:n], err)
360 }
361 return n, err
362 }
363
364 func connect(ctx *HTTP2InteropCtx) (*CapConn, error) {
365 var conn *CapConn
366 var err error
367 if !ctx.UseTLS {
368 conn, err = connectWithoutTls(ctx)
369 } else {
370 config := buildTlsConfig(ctx)
371 conn, err = connectWithTls(ctx, config)
372 }
373 if err != nil {
374 return nil, err
375 }
376 conn.SetDeadline(time.Now().Add(defaultTimeout))
377
378 return conn, nil
379 }
380
381 func buildTlsConfig(ctx *HTTP2InteropCtx) *tls.Config {
382 return &tls.Config{
383 RootCAs: ctx.rootCAs,
384 NextProtos: []string{"h2"},
385 ServerName: ctx.authority,
386 MinVersion: tls.VersionTLS12,
387 }
388 }
389
390 func connectWithoutTls(ctx *HTTP2InteropCtx) (*CapConn, error) {
391 conn, err := net.DialTimeout("tcp", ctx.serverSpec, defaultTimeout)
392 if err != nil {
393 return nil, err
394 }
395 return &CapConn{Conn: conn}, nil
396 }
397
398 func connectWithTls(ctx *HTTP2InteropCtx, config *tls.Config) (*CapConn, error) {
399 conn, err := connectWithoutTls(ctx)
400 if err != nil {
401 return nil, err
402 }
403
404 return &CapConn{Conn: tls.Client(conn, config)}, nil
405 }
OLDNEW
« no previous file with comments | « third_party/grpc/tools/http2_interop/http1frame.go ('k') | third_party/grpc/tools/http2_interop/http2interop_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698