http_util.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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. package transport
  19. import (
  20. "bufio"
  21. "bytes"
  22. "encoding/base64"
  23. "fmt"
  24. "io"
  25. "net"
  26. "net/http"
  27. "strconv"
  28. "strings"
  29. "time"
  30. "github.com/golang/protobuf/proto"
  31. "golang.org/x/net/http2"
  32. "golang.org/x/net/http2/hpack"
  33. spb "google.golang.org/genproto/googleapis/rpc/status"
  34. "google.golang.org/grpc/codes"
  35. "google.golang.org/grpc/status"
  36. )
  37. const (
  38. // http2MaxFrameLen specifies the max length of a HTTP2 frame.
  39. http2MaxFrameLen = 16384 // 16KB frame
  40. // http://http2.github.io/http2-spec/#SettingValues
  41. http2InitHeaderTableSize = 4096
  42. // http2IOBufSize specifies the buffer size for sending frames.
  43. defaultWriteBufSize = 32 * 1024
  44. defaultReadBufSize = 32 * 1024
  45. )
  46. var (
  47. clientPreface = []byte(http2.ClientPreface)
  48. http2ErrConvTab = map[http2.ErrCode]codes.Code{
  49. http2.ErrCodeNo: codes.Internal,
  50. http2.ErrCodeProtocol: codes.Internal,
  51. http2.ErrCodeInternal: codes.Internal,
  52. http2.ErrCodeFlowControl: codes.ResourceExhausted,
  53. http2.ErrCodeSettingsTimeout: codes.Internal,
  54. http2.ErrCodeStreamClosed: codes.Internal,
  55. http2.ErrCodeFrameSize: codes.Internal,
  56. http2.ErrCodeRefusedStream: codes.Unavailable,
  57. http2.ErrCodeCancel: codes.Canceled,
  58. http2.ErrCodeCompression: codes.Internal,
  59. http2.ErrCodeConnect: codes.Internal,
  60. http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted,
  61. http2.ErrCodeInadequateSecurity: codes.PermissionDenied,
  62. http2.ErrCodeHTTP11Required: codes.FailedPrecondition,
  63. }
  64. statusCodeConvTab = map[codes.Code]http2.ErrCode{
  65. codes.Internal: http2.ErrCodeInternal,
  66. codes.Canceled: http2.ErrCodeCancel,
  67. codes.Unavailable: http2.ErrCodeRefusedStream,
  68. codes.ResourceExhausted: http2.ErrCodeEnhanceYourCalm,
  69. codes.PermissionDenied: http2.ErrCodeInadequateSecurity,
  70. }
  71. httpStatusConvTab = map[int]codes.Code{
  72. // 400 Bad Request - INTERNAL.
  73. http.StatusBadRequest: codes.Internal,
  74. // 401 Unauthorized - UNAUTHENTICATED.
  75. http.StatusUnauthorized: codes.Unauthenticated,
  76. // 403 Forbidden - PERMISSION_DENIED.
  77. http.StatusForbidden: codes.PermissionDenied,
  78. // 404 Not Found - UNIMPLEMENTED.
  79. http.StatusNotFound: codes.Unimplemented,
  80. // 429 Too Many Requests - UNAVAILABLE.
  81. http.StatusTooManyRequests: codes.Unavailable,
  82. // 502 Bad Gateway - UNAVAILABLE.
  83. http.StatusBadGateway: codes.Unavailable,
  84. // 503 Service Unavailable - UNAVAILABLE.
  85. http.StatusServiceUnavailable: codes.Unavailable,
  86. // 504 Gateway timeout - UNAVAILABLE.
  87. http.StatusGatewayTimeout: codes.Unavailable,
  88. }
  89. )
  90. // Records the states during HPACK decoding. Must be reset once the
  91. // decoding of the entire headers are finished.
  92. type decodeState struct {
  93. encoding string
  94. // statusGen caches the stream status received from the trailer the server
  95. // sent. Client side only. Do not access directly. After all trailers are
  96. // parsed, use the status method to retrieve the status.
  97. statusGen *status.Status
  98. // rawStatusCode and rawStatusMsg are set from the raw trailer fields and are not
  99. // intended for direct access outside of parsing.
  100. rawStatusCode *int
  101. rawStatusMsg string
  102. httpStatus *int
  103. // Server side only fields.
  104. timeoutSet bool
  105. timeout time.Duration
  106. method string
  107. // key-value metadata map from the peer.
  108. mdata map[string][]string
  109. statsTags []byte
  110. statsTrace []byte
  111. }
  112. // isReservedHeader checks whether hdr belongs to HTTP2 headers
  113. // reserved by gRPC protocol. Any other headers are classified as the
  114. // user-specified metadata.
  115. func isReservedHeader(hdr string) bool {
  116. if hdr != "" && hdr[0] == ':' {
  117. return true
  118. }
  119. switch hdr {
  120. case "content-type",
  121. "grpc-message-type",
  122. "grpc-encoding",
  123. "grpc-message",
  124. "grpc-status",
  125. "grpc-timeout",
  126. "grpc-status-details-bin",
  127. "te":
  128. return true
  129. default:
  130. return false
  131. }
  132. }
  133. // isWhitelistedPseudoHeader checks whether hdr belongs to HTTP2 pseudoheaders
  134. // that should be propagated into metadata visible to users.
  135. func isWhitelistedPseudoHeader(hdr string) bool {
  136. switch hdr {
  137. case ":authority":
  138. return true
  139. default:
  140. return false
  141. }
  142. }
  143. func validContentType(t string) bool {
  144. e := "application/grpc"
  145. if !strings.HasPrefix(t, e) {
  146. return false
  147. }
  148. // Support variations on the content-type
  149. // (e.g. "application/grpc+blah", "application/grpc;blah").
  150. if len(t) > len(e) && t[len(e)] != '+' && t[len(e)] != ';' {
  151. return false
  152. }
  153. return true
  154. }
  155. func (d *decodeState) status() *status.Status {
  156. if d.statusGen == nil {
  157. // No status-details were provided; generate status using code/msg.
  158. d.statusGen = status.New(codes.Code(int32(*(d.rawStatusCode))), d.rawStatusMsg)
  159. }
  160. return d.statusGen
  161. }
  162. const binHdrSuffix = "-bin"
  163. func encodeBinHeader(v []byte) string {
  164. return base64.RawStdEncoding.EncodeToString(v)
  165. }
  166. func decodeBinHeader(v string) ([]byte, error) {
  167. if len(v)%4 == 0 {
  168. // Input was padded, or padding was not necessary.
  169. return base64.StdEncoding.DecodeString(v)
  170. }
  171. return base64.RawStdEncoding.DecodeString(v)
  172. }
  173. func encodeMetadataHeader(k, v string) string {
  174. if strings.HasSuffix(k, binHdrSuffix) {
  175. return encodeBinHeader(([]byte)(v))
  176. }
  177. return v
  178. }
  179. func decodeMetadataHeader(k, v string) (string, error) {
  180. if strings.HasSuffix(k, binHdrSuffix) {
  181. b, err := decodeBinHeader(v)
  182. return string(b), err
  183. }
  184. return v, nil
  185. }
  186. func (d *decodeState) decodeResponseHeader(frame *http2.MetaHeadersFrame) error {
  187. for _, hf := range frame.Fields {
  188. if err := d.processHeaderField(hf); err != nil {
  189. return err
  190. }
  191. }
  192. // If grpc status exists, no need to check further.
  193. if d.rawStatusCode != nil || d.statusGen != nil {
  194. return nil
  195. }
  196. // If grpc status doesn't exist and http status doesn't exist,
  197. // then it's a malformed header.
  198. if d.httpStatus == nil {
  199. return streamErrorf(codes.Internal, "malformed header: doesn't contain status(gRPC or HTTP)")
  200. }
  201. if *(d.httpStatus) != http.StatusOK {
  202. code, ok := httpStatusConvTab[*(d.httpStatus)]
  203. if !ok {
  204. code = codes.Unknown
  205. }
  206. return streamErrorf(code, http.StatusText(*(d.httpStatus)))
  207. }
  208. // gRPC status doesn't exist and http status is OK.
  209. // Set rawStatusCode to be unknown and return nil error.
  210. // So that, if the stream has ended this Unknown status
  211. // will be propogated to the user.
  212. // Otherwise, it will be ignored. In which case, status from
  213. // a later trailer, that has StreamEnded flag set, is propogated.
  214. code := int(codes.Unknown)
  215. d.rawStatusCode = &code
  216. return nil
  217. }
  218. func (d *decodeState) addMetadata(k, v string) {
  219. if d.mdata == nil {
  220. d.mdata = make(map[string][]string)
  221. }
  222. d.mdata[k] = append(d.mdata[k], v)
  223. }
  224. func (d *decodeState) processHeaderField(f hpack.HeaderField) error {
  225. switch f.Name {
  226. case "content-type":
  227. if !validContentType(f.Value) {
  228. return streamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value)
  229. }
  230. case "grpc-encoding":
  231. d.encoding = f.Value
  232. case "grpc-status":
  233. code, err := strconv.Atoi(f.Value)
  234. if err != nil {
  235. return streamErrorf(codes.Internal, "transport: malformed grpc-status: %v", err)
  236. }
  237. d.rawStatusCode = &code
  238. case "grpc-message":
  239. d.rawStatusMsg = decodeGrpcMessage(f.Value)
  240. case "grpc-status-details-bin":
  241. v, err := decodeBinHeader(f.Value)
  242. if err != nil {
  243. return streamErrorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
  244. }
  245. s := &spb.Status{}
  246. if err := proto.Unmarshal(v, s); err != nil {
  247. return streamErrorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
  248. }
  249. d.statusGen = status.FromProto(s)
  250. case "grpc-timeout":
  251. d.timeoutSet = true
  252. var err error
  253. if d.timeout, err = decodeTimeout(f.Value); err != nil {
  254. return streamErrorf(codes.Internal, "transport: malformed time-out: %v", err)
  255. }
  256. case ":path":
  257. d.method = f.Value
  258. case ":status":
  259. code, err := strconv.Atoi(f.Value)
  260. if err != nil {
  261. return streamErrorf(codes.Internal, "transport: malformed http-status: %v", err)
  262. }
  263. d.httpStatus = &code
  264. case "grpc-tags-bin":
  265. v, err := decodeBinHeader(f.Value)
  266. if err != nil {
  267. return streamErrorf(codes.Internal, "transport: malformed grpc-tags-bin: %v", err)
  268. }
  269. d.statsTags = v
  270. d.addMetadata(f.Name, string(v))
  271. case "grpc-trace-bin":
  272. v, err := decodeBinHeader(f.Value)
  273. if err != nil {
  274. return streamErrorf(codes.Internal, "transport: malformed grpc-trace-bin: %v", err)
  275. }
  276. d.statsTrace = v
  277. d.addMetadata(f.Name, string(v))
  278. default:
  279. if isReservedHeader(f.Name) && !isWhitelistedPseudoHeader(f.Name) {
  280. break
  281. }
  282. v, err := decodeMetadataHeader(f.Name, f.Value)
  283. if err != nil {
  284. errorf("Failed to decode metadata header (%q, %q): %v", f.Name, f.Value, err)
  285. return nil
  286. }
  287. d.addMetadata(f.Name, string(v))
  288. }
  289. return nil
  290. }
  291. type timeoutUnit uint8
  292. const (
  293. hour timeoutUnit = 'H'
  294. minute timeoutUnit = 'M'
  295. second timeoutUnit = 'S'
  296. millisecond timeoutUnit = 'm'
  297. microsecond timeoutUnit = 'u'
  298. nanosecond timeoutUnit = 'n'
  299. )
  300. func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) {
  301. switch u {
  302. case hour:
  303. return time.Hour, true
  304. case minute:
  305. return time.Minute, true
  306. case second:
  307. return time.Second, true
  308. case millisecond:
  309. return time.Millisecond, true
  310. case microsecond:
  311. return time.Microsecond, true
  312. case nanosecond:
  313. return time.Nanosecond, true
  314. default:
  315. }
  316. return
  317. }
  318. const maxTimeoutValue int64 = 100000000 - 1
  319. // div does integer division and round-up the result. Note that this is
  320. // equivalent to (d+r-1)/r but has less chance to overflow.
  321. func div(d, r time.Duration) int64 {
  322. if m := d % r; m > 0 {
  323. return int64(d/r + 1)
  324. }
  325. return int64(d / r)
  326. }
  327. // TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it.
  328. func encodeTimeout(t time.Duration) string {
  329. if t <= 0 {
  330. return "0n"
  331. }
  332. if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
  333. return strconv.FormatInt(d, 10) + "n"
  334. }
  335. if d := div(t, time.Microsecond); d <= maxTimeoutValue {
  336. return strconv.FormatInt(d, 10) + "u"
  337. }
  338. if d := div(t, time.Millisecond); d <= maxTimeoutValue {
  339. return strconv.FormatInt(d, 10) + "m"
  340. }
  341. if d := div(t, time.Second); d <= maxTimeoutValue {
  342. return strconv.FormatInt(d, 10) + "S"
  343. }
  344. if d := div(t, time.Minute); d <= maxTimeoutValue {
  345. return strconv.FormatInt(d, 10) + "M"
  346. }
  347. // Note that maxTimeoutValue * time.Hour > MaxInt64.
  348. return strconv.FormatInt(div(t, time.Hour), 10) + "H"
  349. }
  350. func decodeTimeout(s string) (time.Duration, error) {
  351. size := len(s)
  352. if size < 2 {
  353. return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
  354. }
  355. unit := timeoutUnit(s[size-1])
  356. d, ok := timeoutUnitToDuration(unit)
  357. if !ok {
  358. return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s)
  359. }
  360. t, err := strconv.ParseInt(s[:size-1], 10, 64)
  361. if err != nil {
  362. return 0, err
  363. }
  364. return d * time.Duration(t), nil
  365. }
  366. const (
  367. spaceByte = ' '
  368. tildaByte = '~'
  369. percentByte = '%'
  370. )
  371. // encodeGrpcMessage is used to encode status code in header field
  372. // "grpc-message".
  373. // It checks to see if each individual byte in msg is an
  374. // allowable byte, and then either percent encoding or passing it through.
  375. // When percent encoding, the byte is converted into hexadecimal notation
  376. // with a '%' prepended.
  377. func encodeGrpcMessage(msg string) string {
  378. if msg == "" {
  379. return ""
  380. }
  381. lenMsg := len(msg)
  382. for i := 0; i < lenMsg; i++ {
  383. c := msg[i]
  384. if !(c >= spaceByte && c < tildaByte && c != percentByte) {
  385. return encodeGrpcMessageUnchecked(msg)
  386. }
  387. }
  388. return msg
  389. }
  390. func encodeGrpcMessageUnchecked(msg string) string {
  391. var buf bytes.Buffer
  392. lenMsg := len(msg)
  393. for i := 0; i < lenMsg; i++ {
  394. c := msg[i]
  395. if c >= spaceByte && c < tildaByte && c != percentByte {
  396. buf.WriteByte(c)
  397. } else {
  398. buf.WriteString(fmt.Sprintf("%%%02X", c))
  399. }
  400. }
  401. return buf.String()
  402. }
  403. // decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage.
  404. func decodeGrpcMessage(msg string) string {
  405. if msg == "" {
  406. return ""
  407. }
  408. lenMsg := len(msg)
  409. for i := 0; i < lenMsg; i++ {
  410. if msg[i] == percentByte && i+2 < lenMsg {
  411. return decodeGrpcMessageUnchecked(msg)
  412. }
  413. }
  414. return msg
  415. }
  416. func decodeGrpcMessageUnchecked(msg string) string {
  417. var buf bytes.Buffer
  418. lenMsg := len(msg)
  419. for i := 0; i < lenMsg; i++ {
  420. c := msg[i]
  421. if c == percentByte && i+2 < lenMsg {
  422. parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8)
  423. if err != nil {
  424. buf.WriteByte(c)
  425. } else {
  426. buf.WriteByte(byte(parsed))
  427. i += 2
  428. }
  429. } else {
  430. buf.WriteByte(c)
  431. }
  432. }
  433. return buf.String()
  434. }
  435. type framer struct {
  436. numWriters int32
  437. reader io.Reader
  438. writer *bufio.Writer
  439. fr *http2.Framer
  440. }
  441. func newFramer(conn net.Conn, writeBufferSize, readBufferSize int) *framer {
  442. f := &framer{
  443. reader: bufio.NewReaderSize(conn, readBufferSize),
  444. writer: bufio.NewWriterSize(conn, writeBufferSize),
  445. }
  446. f.fr = http2.NewFramer(f.writer, f.reader)
  447. // Opt-in to Frame reuse API on framer to reduce garbage.
  448. // Frames aren't safe to read from after a subsequent call to ReadFrame.
  449. f.fr.SetReuseFrames()
  450. f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
  451. return f
  452. }