]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/google.golang.org/grpc/transport/http_util.go
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[github/fretlink/terraform-provider-statuscake.git] / vendor / google.golang.org / grpc / transport / http_util.go
1 /*
2 *
3 * Copyright 2014 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 package transport
20
21 import (
22 "bufio"
23 "bytes"
24 "encoding/base64"
25 "fmt"
26 "io"
27 "net"
28 "net/http"
29 "strconv"
30 "strings"
31 "sync/atomic"
32 "time"
33
34 "github.com/golang/protobuf/proto"
35 "golang.org/x/net/http2"
36 "golang.org/x/net/http2/hpack"
37 spb "google.golang.org/genproto/googleapis/rpc/status"
38 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/status"
40 )
41
42 const (
43 // http2MaxFrameLen specifies the max length of a HTTP2 frame.
44 http2MaxFrameLen = 16384 // 16KB frame
45 // http://http2.github.io/http2-spec/#SettingValues
46 http2InitHeaderTableSize = 4096
47 // http2IOBufSize specifies the buffer size for sending frames.
48 http2IOBufSize = 32 * 1024
49 )
50
51 var (
52 clientPreface = []byte(http2.ClientPreface)
53 http2ErrConvTab = map[http2.ErrCode]codes.Code{
54 http2.ErrCodeNo: codes.Internal,
55 http2.ErrCodeProtocol: codes.Internal,
56 http2.ErrCodeInternal: codes.Internal,
57 http2.ErrCodeFlowControl: codes.ResourceExhausted,
58 http2.ErrCodeSettingsTimeout: codes.Internal,
59 http2.ErrCodeStreamClosed: codes.Internal,
60 http2.ErrCodeFrameSize: codes.Internal,
61 http2.ErrCodeRefusedStream: codes.Unavailable,
62 http2.ErrCodeCancel: codes.Canceled,
63 http2.ErrCodeCompression: codes.Internal,
64 http2.ErrCodeConnect: codes.Internal,
65 http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted,
66 http2.ErrCodeInadequateSecurity: codes.PermissionDenied,
67 http2.ErrCodeHTTP11Required: codes.FailedPrecondition,
68 }
69 statusCodeConvTab = map[codes.Code]http2.ErrCode{
70 codes.Internal: http2.ErrCodeInternal,
71 codes.Canceled: http2.ErrCodeCancel,
72 codes.Unavailable: http2.ErrCodeRefusedStream,
73 codes.ResourceExhausted: http2.ErrCodeEnhanceYourCalm,
74 codes.PermissionDenied: http2.ErrCodeInadequateSecurity,
75 }
76 httpStatusConvTab = map[int]codes.Code{
77 // 400 Bad Request - INTERNAL.
78 http.StatusBadRequest: codes.Internal,
79 // 401 Unauthorized - UNAUTHENTICATED.
80 http.StatusUnauthorized: codes.Unauthenticated,
81 // 403 Forbidden - PERMISSION_DENIED.
82 http.StatusForbidden: codes.PermissionDenied,
83 // 404 Not Found - UNIMPLEMENTED.
84 http.StatusNotFound: codes.Unimplemented,
85 // 429 Too Many Requests - UNAVAILABLE.
86 http.StatusTooManyRequests: codes.Unavailable,
87 // 502 Bad Gateway - UNAVAILABLE.
88 http.StatusBadGateway: codes.Unavailable,
89 // 503 Service Unavailable - UNAVAILABLE.
90 http.StatusServiceUnavailable: codes.Unavailable,
91 // 504 Gateway timeout - UNAVAILABLE.
92 http.StatusGatewayTimeout: codes.Unavailable,
93 }
94 )
95
96 // Records the states during HPACK decoding. Must be reset once the
97 // decoding of the entire headers are finished.
98 type decodeState struct {
99 encoding string
100 // statusGen caches the stream status received from the trailer the server
101 // sent. Client side only. Do not access directly. After all trailers are
102 // parsed, use the status method to retrieve the status.
103 statusGen *status.Status
104 // rawStatusCode and rawStatusMsg are set from the raw trailer fields and are not
105 // intended for direct access outside of parsing.
106 rawStatusCode *int
107 rawStatusMsg string
108 httpStatus *int
109 // Server side only fields.
110 timeoutSet bool
111 timeout time.Duration
112 method string
113 // key-value metadata map from the peer.
114 mdata map[string][]string
115 }
116
117 // isReservedHeader checks whether hdr belongs to HTTP2 headers
118 // reserved by gRPC protocol. Any other headers are classified as the
119 // user-specified metadata.
120 func isReservedHeader(hdr string) bool {
121 if hdr != "" && hdr[0] == ':' {
122 return true
123 }
124 switch hdr {
125 case "content-type",
126 "grpc-message-type",
127 "grpc-encoding",
128 "grpc-message",
129 "grpc-status",
130 "grpc-timeout",
131 "grpc-status-details-bin",
132 "te":
133 return true
134 default:
135 return false
136 }
137 }
138
139 // isWhitelistedPseudoHeader checks whether hdr belongs to HTTP2 pseudoheaders
140 // that should be propagated into metadata visible to users.
141 func isWhitelistedPseudoHeader(hdr string) bool {
142 switch hdr {
143 case ":authority":
144 return true
145 default:
146 return false
147 }
148 }
149
150 func validContentType(t string) bool {
151 e := "application/grpc"
152 if !strings.HasPrefix(t, e) {
153 return false
154 }
155 // Support variations on the content-type
156 // (e.g. "application/grpc+blah", "application/grpc;blah").
157 if len(t) > len(e) && t[len(e)] != '+' && t[len(e)] != ';' {
158 return false
159 }
160 return true
161 }
162
163 func (d *decodeState) status() *status.Status {
164 if d.statusGen == nil {
165 // No status-details were provided; generate status using code/msg.
166 d.statusGen = status.New(codes.Code(int32(*(d.rawStatusCode))), d.rawStatusMsg)
167 }
168 return d.statusGen
169 }
170
171 const binHdrSuffix = "-bin"
172
173 func encodeBinHeader(v []byte) string {
174 return base64.RawStdEncoding.EncodeToString(v)
175 }
176
177 func decodeBinHeader(v string) ([]byte, error) {
178 if len(v)%4 == 0 {
179 // Input was padded, or padding was not necessary.
180 return base64.StdEncoding.DecodeString(v)
181 }
182 return base64.RawStdEncoding.DecodeString(v)
183 }
184
185 func encodeMetadataHeader(k, v string) string {
186 if strings.HasSuffix(k, binHdrSuffix) {
187 return encodeBinHeader(([]byte)(v))
188 }
189 return v
190 }
191
192 func decodeMetadataHeader(k, v string) (string, error) {
193 if strings.HasSuffix(k, binHdrSuffix) {
194 b, err := decodeBinHeader(v)
195 return string(b), err
196 }
197 return v, nil
198 }
199
200 func (d *decodeState) decodeResponseHeader(frame *http2.MetaHeadersFrame) error {
201 for _, hf := range frame.Fields {
202 if err := d.processHeaderField(hf); err != nil {
203 return err
204 }
205 }
206
207 // If grpc status exists, no need to check further.
208 if d.rawStatusCode != nil || d.statusGen != nil {
209 return nil
210 }
211
212 // If grpc status doesn't exist and http status doesn't exist,
213 // then it's a malformed header.
214 if d.httpStatus == nil {
215 return streamErrorf(codes.Internal, "malformed header: doesn't contain status(gRPC or HTTP)")
216 }
217
218 if *(d.httpStatus) != http.StatusOK {
219 code, ok := httpStatusConvTab[*(d.httpStatus)]
220 if !ok {
221 code = codes.Unknown
222 }
223 return streamErrorf(code, http.StatusText(*(d.httpStatus)))
224 }
225
226 // gRPC status doesn't exist and http status is OK.
227 // Set rawStatusCode to be unknown and return nil error.
228 // So that, if the stream has ended this Unknown status
229 // will be propogated to the user.
230 // Otherwise, it will be ignored. In which case, status from
231 // a later trailer, that has StreamEnded flag set, is propogated.
232 code := int(codes.Unknown)
233 d.rawStatusCode = &code
234 return nil
235
236 }
237
238 func (d *decodeState) processHeaderField(f hpack.HeaderField) error {
239 switch f.Name {
240 case "content-type":
241 if !validContentType(f.Value) {
242 return streamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value)
243 }
244 case "grpc-encoding":
245 d.encoding = f.Value
246 case "grpc-status":
247 code, err := strconv.Atoi(f.Value)
248 if err != nil {
249 return streamErrorf(codes.Internal, "transport: malformed grpc-status: %v", err)
250 }
251 d.rawStatusCode = &code
252 case "grpc-message":
253 d.rawStatusMsg = decodeGrpcMessage(f.Value)
254 case "grpc-status-details-bin":
255 v, err := decodeBinHeader(f.Value)
256 if err != nil {
257 return streamErrorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
258 }
259 s := &spb.Status{}
260 if err := proto.Unmarshal(v, s); err != nil {
261 return streamErrorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
262 }
263 d.statusGen = status.FromProto(s)
264 case "grpc-timeout":
265 d.timeoutSet = true
266 var err error
267 if d.timeout, err = decodeTimeout(f.Value); err != nil {
268 return streamErrorf(codes.Internal, "transport: malformed time-out: %v", err)
269 }
270 case ":path":
271 d.method = f.Value
272 case ":status":
273 code, err := strconv.Atoi(f.Value)
274 if err != nil {
275 return streamErrorf(codes.Internal, "transport: malformed http-status: %v", err)
276 }
277 d.httpStatus = &code
278 default:
279 if !isReservedHeader(f.Name) || isWhitelistedPseudoHeader(f.Name) {
280 if d.mdata == nil {
281 d.mdata = make(map[string][]string)
282 }
283 v, err := decodeMetadataHeader(f.Name, f.Value)
284 if err != nil {
285 errorf("Failed to decode metadata header (%q, %q): %v", f.Name, f.Value, err)
286 return nil
287 }
288 d.mdata[f.Name] = append(d.mdata[f.Name], v)
289 }
290 }
291 return nil
292 }
293
294 type timeoutUnit uint8
295
296 const (
297 hour timeoutUnit = 'H'
298 minute timeoutUnit = 'M'
299 second timeoutUnit = 'S'
300 millisecond timeoutUnit = 'm'
301 microsecond timeoutUnit = 'u'
302 nanosecond timeoutUnit = 'n'
303 )
304
305 func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) {
306 switch u {
307 case hour:
308 return time.Hour, true
309 case minute:
310 return time.Minute, true
311 case second:
312 return time.Second, true
313 case millisecond:
314 return time.Millisecond, true
315 case microsecond:
316 return time.Microsecond, true
317 case nanosecond:
318 return time.Nanosecond, true
319 default:
320 }
321 return
322 }
323
324 const maxTimeoutValue int64 = 100000000 - 1
325
326 // div does integer division and round-up the result. Note that this is
327 // equivalent to (d+r-1)/r but has less chance to overflow.
328 func div(d, r time.Duration) int64 {
329 if m := d % r; m > 0 {
330 return int64(d/r + 1)
331 }
332 return int64(d / r)
333 }
334
335 // TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it.
336 func encodeTimeout(t time.Duration) string {
337 if t <= 0 {
338 return "0n"
339 }
340 if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
341 return strconv.FormatInt(d, 10) + "n"
342 }
343 if d := div(t, time.Microsecond); d <= maxTimeoutValue {
344 return strconv.FormatInt(d, 10) + "u"
345 }
346 if d := div(t, time.Millisecond); d <= maxTimeoutValue {
347 return strconv.FormatInt(d, 10) + "m"
348 }
349 if d := div(t, time.Second); d <= maxTimeoutValue {
350 return strconv.FormatInt(d, 10) + "S"
351 }
352 if d := div(t, time.Minute); d <= maxTimeoutValue {
353 return strconv.FormatInt(d, 10) + "M"
354 }
355 // Note that maxTimeoutValue * time.Hour > MaxInt64.
356 return strconv.FormatInt(div(t, time.Hour), 10) + "H"
357 }
358
359 func decodeTimeout(s string) (time.Duration, error) {
360 size := len(s)
361 if size < 2 {
362 return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
363 }
364 unit := timeoutUnit(s[size-1])
365 d, ok := timeoutUnitToDuration(unit)
366 if !ok {
367 return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s)
368 }
369 t, err := strconv.ParseInt(s[:size-1], 10, 64)
370 if err != nil {
371 return 0, err
372 }
373 return d * time.Duration(t), nil
374 }
375
376 const (
377 spaceByte = ' '
378 tildaByte = '~'
379 percentByte = '%'
380 )
381
382 // encodeGrpcMessage is used to encode status code in header field
383 // "grpc-message".
384 // It checks to see if each individual byte in msg is an
385 // allowable byte, and then either percent encoding or passing it through.
386 // When percent encoding, the byte is converted into hexadecimal notation
387 // with a '%' prepended.
388 func encodeGrpcMessage(msg string) string {
389 if msg == "" {
390 return ""
391 }
392 lenMsg := len(msg)
393 for i := 0; i < lenMsg; i++ {
394 c := msg[i]
395 if !(c >= spaceByte && c < tildaByte && c != percentByte) {
396 return encodeGrpcMessageUnchecked(msg)
397 }
398 }
399 return msg
400 }
401
402 func encodeGrpcMessageUnchecked(msg string) string {
403 var buf bytes.Buffer
404 lenMsg := len(msg)
405 for i := 0; i < lenMsg; i++ {
406 c := msg[i]
407 if c >= spaceByte && c < tildaByte && c != percentByte {
408 buf.WriteByte(c)
409 } else {
410 buf.WriteString(fmt.Sprintf("%%%02X", c))
411 }
412 }
413 return buf.String()
414 }
415
416 // decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage.
417 func decodeGrpcMessage(msg string) string {
418 if msg == "" {
419 return ""
420 }
421 lenMsg := len(msg)
422 for i := 0; i < lenMsg; i++ {
423 if msg[i] == percentByte && i+2 < lenMsg {
424 return decodeGrpcMessageUnchecked(msg)
425 }
426 }
427 return msg
428 }
429
430 func decodeGrpcMessageUnchecked(msg string) string {
431 var buf bytes.Buffer
432 lenMsg := len(msg)
433 for i := 0; i < lenMsg; i++ {
434 c := msg[i]
435 if c == percentByte && i+2 < lenMsg {
436 parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8)
437 if err != nil {
438 buf.WriteByte(c)
439 } else {
440 buf.WriteByte(byte(parsed))
441 i += 2
442 }
443 } else {
444 buf.WriteByte(c)
445 }
446 }
447 return buf.String()
448 }
449
450 type framer struct {
451 numWriters int32
452 reader io.Reader
453 writer *bufio.Writer
454 fr *http2.Framer
455 }
456
457 func newFramer(conn net.Conn) *framer {
458 f := &framer{
459 reader: bufio.NewReaderSize(conn, http2IOBufSize),
460 writer: bufio.NewWriterSize(conn, http2IOBufSize),
461 }
462 f.fr = http2.NewFramer(f.writer, f.reader)
463 // Opt-in to Frame reuse API on framer to reduce garbage.
464 // Frames aren't safe to read from after a subsequent call to ReadFrame.
465 f.fr.SetReuseFrames()
466 f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
467 return f
468 }
469
470 func (f *framer) adjustNumWriters(i int32) int32 {
471 return atomic.AddInt32(&f.numWriters, i)
472 }
473
474 // The following writeXXX functions can only be called when the caller gets
475 // unblocked from writableChan channel (i.e., owns the privilege to write).
476
477 func (f *framer) writeContinuation(forceFlush bool, streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
478 if err := f.fr.WriteContinuation(streamID, endHeaders, headerBlockFragment); err != nil {
479 return err
480 }
481 if forceFlush {
482 return f.writer.Flush()
483 }
484 return nil
485 }
486
487 func (f *framer) writeData(forceFlush bool, streamID uint32, endStream bool, data []byte) error {
488 if err := f.fr.WriteData(streamID, endStream, data); err != nil {
489 return err
490 }
491 if forceFlush {
492 return f.writer.Flush()
493 }
494 return nil
495 }
496
497 func (f *framer) writeGoAway(forceFlush bool, maxStreamID uint32, code http2.ErrCode, debugData []byte) error {
498 if err := f.fr.WriteGoAway(maxStreamID, code, debugData); err != nil {
499 return err
500 }
501 if forceFlush {
502 return f.writer.Flush()
503 }
504 return nil
505 }
506
507 func (f *framer) writeHeaders(forceFlush bool, p http2.HeadersFrameParam) error {
508 if err := f.fr.WriteHeaders(p); err != nil {
509 return err
510 }
511 if forceFlush {
512 return f.writer.Flush()
513 }
514 return nil
515 }
516
517 func (f *framer) writePing(forceFlush, ack bool, data [8]byte) error {
518 if err := f.fr.WritePing(ack, data); err != nil {
519 return err
520 }
521 if forceFlush {
522 return f.writer.Flush()
523 }
524 return nil
525 }
526
527 func (f *framer) writePriority(forceFlush bool, streamID uint32, p http2.PriorityParam) error {
528 if err := f.fr.WritePriority(streamID, p); err != nil {
529 return err
530 }
531 if forceFlush {
532 return f.writer.Flush()
533 }
534 return nil
535 }
536
537 func (f *framer) writePushPromise(forceFlush bool, p http2.PushPromiseParam) error {
538 if err := f.fr.WritePushPromise(p); err != nil {
539 return err
540 }
541 if forceFlush {
542 return f.writer.Flush()
543 }
544 return nil
545 }
546
547 func (f *framer) writeRSTStream(forceFlush bool, streamID uint32, code http2.ErrCode) error {
548 if err := f.fr.WriteRSTStream(streamID, code); err != nil {
549 return err
550 }
551 if forceFlush {
552 return f.writer.Flush()
553 }
554 return nil
555 }
556
557 func (f *framer) writeSettings(forceFlush bool, settings ...http2.Setting) error {
558 if err := f.fr.WriteSettings(settings...); err != nil {
559 return err
560 }
561 if forceFlush {
562 return f.writer.Flush()
563 }
564 return nil
565 }
566
567 func (f *framer) writeSettingsAck(forceFlush bool) error {
568 if err := f.fr.WriteSettingsAck(); err != nil {
569 return err
570 }
571 if forceFlush {
572 return f.writer.Flush()
573 }
574 return nil
575 }
576
577 func (f *framer) writeWindowUpdate(forceFlush bool, streamID, incr uint32) error {
578 if err := f.fr.WriteWindowUpdate(streamID, incr); err != nil {
579 return err
580 }
581 if forceFlush {
582 return f.writer.Flush()
583 }
584 return nil
585 }
586
587 func (f *framer) flushWrite() error {
588 return f.writer.Flush()
589 }
590
591 func (f *framer) readFrame() (http2.Frame, error) {
592 return f.fr.ReadFrame()
593 }
594
595 func (f *framer) errorDetail() error {
596 return f.fr.ErrorDetail()
597 }