http_util.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. *
  3. * Copyright 2014, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. package transport
  34. import (
  35. "bufio"
  36. "fmt"
  37. "io"
  38. "net"
  39. "strconv"
  40. "strings"
  41. "sync/atomic"
  42. "time"
  43. "golang.org/x/net/http2"
  44. "golang.org/x/net/http2/hpack"
  45. "google.golang.org/grpc/codes"
  46. "google.golang.org/grpc/grpclog"
  47. "google.golang.org/grpc/metadata"
  48. )
  49. const (
  50. // The primary user agent
  51. primaryUA = "grpc-go/0.11"
  52. // http2MaxFrameLen specifies the max length of a HTTP2 frame.
  53. http2MaxFrameLen = 16384 // 16KB frame
  54. // http://http2.github.io/http2-spec/#SettingValues
  55. http2InitHeaderTableSize = 4096
  56. // http2IOBufSize specifies the buffer size for sending frames.
  57. http2IOBufSize = 32 * 1024
  58. )
  59. var (
  60. clientPreface = []byte(http2.ClientPreface)
  61. http2ErrConvTab = map[http2.ErrCode]codes.Code{
  62. http2.ErrCodeNo: codes.Internal,
  63. http2.ErrCodeProtocol: codes.Internal,
  64. http2.ErrCodeInternal: codes.Internal,
  65. http2.ErrCodeFlowControl: codes.ResourceExhausted,
  66. http2.ErrCodeSettingsTimeout: codes.Internal,
  67. http2.ErrCodeStreamClosed: codes.Internal,
  68. http2.ErrCodeFrameSize: codes.Internal,
  69. http2.ErrCodeRefusedStream: codes.Unavailable,
  70. http2.ErrCodeCancel: codes.Canceled,
  71. http2.ErrCodeCompression: codes.Internal,
  72. http2.ErrCodeConnect: codes.Internal,
  73. http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted,
  74. http2.ErrCodeInadequateSecurity: codes.PermissionDenied,
  75. http2.ErrCodeHTTP11Required: codes.FailedPrecondition,
  76. }
  77. statusCodeConvTab = map[codes.Code]http2.ErrCode{
  78. codes.Internal: http2.ErrCodeInternal,
  79. codes.Canceled: http2.ErrCodeCancel,
  80. codes.Unavailable: http2.ErrCodeRefusedStream,
  81. codes.ResourceExhausted: http2.ErrCodeEnhanceYourCalm,
  82. codes.PermissionDenied: http2.ErrCodeInadequateSecurity,
  83. }
  84. )
  85. // Records the states during HPACK decoding. Must be reset once the
  86. // decoding of the entire headers are finished.
  87. type decodeState struct {
  88. err error // first error encountered decoding
  89. encoding string
  90. // statusCode caches the stream status received from the trailer
  91. // the server sent. Client side only.
  92. statusCode codes.Code
  93. statusDesc string
  94. // Server side only fields.
  95. timeoutSet bool
  96. timeout time.Duration
  97. method string
  98. // key-value metadata map from the peer.
  99. mdata map[string][]string
  100. }
  101. // isReservedHeader checks whether hdr belongs to HTTP2 headers
  102. // reserved by gRPC protocol. Any other headers are classified as the
  103. // user-specified metadata.
  104. func isReservedHeader(hdr string) bool {
  105. if hdr != "" && hdr[0] == ':' {
  106. return true
  107. }
  108. switch hdr {
  109. case "content-type",
  110. "grpc-message-type",
  111. "grpc-encoding",
  112. "grpc-message",
  113. "grpc-status",
  114. "grpc-timeout",
  115. "te":
  116. return true
  117. default:
  118. return false
  119. }
  120. }
  121. func (d *decodeState) setErr(err error) {
  122. if d.err == nil {
  123. d.err = err
  124. }
  125. }
  126. func (d *decodeState) processHeaderField(f hpack.HeaderField) {
  127. switch f.Name {
  128. case "content-type":
  129. if !strings.Contains(f.Value, "application/grpc") {
  130. d.setErr(StreamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value))
  131. return
  132. }
  133. case "grpc-encoding":
  134. d.encoding = f.Value
  135. case "grpc-status":
  136. code, err := strconv.Atoi(f.Value)
  137. if err != nil {
  138. d.setErr(StreamErrorf(codes.Internal, "transport: malformed grpc-status: %v", err))
  139. return
  140. }
  141. d.statusCode = codes.Code(code)
  142. case "grpc-message":
  143. d.statusDesc = f.Value
  144. case "grpc-timeout":
  145. d.timeoutSet = true
  146. var err error
  147. d.timeout, err = timeoutDecode(f.Value)
  148. if err != nil {
  149. d.setErr(StreamErrorf(codes.Internal, "transport: malformed time-out: %v", err))
  150. return
  151. }
  152. case ":path":
  153. d.method = f.Value
  154. default:
  155. if !isReservedHeader(f.Name) {
  156. if f.Name == "user-agent" {
  157. i := strings.LastIndex(f.Value, " ")
  158. if i == -1 {
  159. // There is no application user agent string being set.
  160. return
  161. }
  162. // Extract the application user agent string.
  163. f.Value = f.Value[:i]
  164. }
  165. if d.mdata == nil {
  166. d.mdata = make(map[string][]string)
  167. }
  168. k, v, err := metadata.DecodeKeyValue(f.Name, f.Value)
  169. if err != nil {
  170. grpclog.Printf("Failed to decode (%q, %q): %v", f.Name, f.Value, err)
  171. return
  172. }
  173. d.mdata[k] = append(d.mdata[k], v)
  174. }
  175. }
  176. }
  177. type timeoutUnit uint8
  178. const (
  179. hour timeoutUnit = 'H'
  180. minute timeoutUnit = 'M'
  181. second timeoutUnit = 'S'
  182. millisecond timeoutUnit = 'm'
  183. microsecond timeoutUnit = 'u'
  184. nanosecond timeoutUnit = 'n'
  185. )
  186. func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) {
  187. switch u {
  188. case hour:
  189. return time.Hour, true
  190. case minute:
  191. return time.Minute, true
  192. case second:
  193. return time.Second, true
  194. case millisecond:
  195. return time.Millisecond, true
  196. case microsecond:
  197. return time.Microsecond, true
  198. case nanosecond:
  199. return time.Nanosecond, true
  200. default:
  201. }
  202. return
  203. }
  204. const maxTimeoutValue int64 = 100000000 - 1
  205. // div does integer division and round-up the result. Note that this is
  206. // equivalent to (d+r-1)/r but has less chance to overflow.
  207. func div(d, r time.Duration) int64 {
  208. if m := d % r; m > 0 {
  209. return int64(d/r + 1)
  210. }
  211. return int64(d / r)
  212. }
  213. // TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it.
  214. func timeoutEncode(t time.Duration) string {
  215. if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
  216. return strconv.FormatInt(d, 10) + "n"
  217. }
  218. if d := div(t, time.Microsecond); d <= maxTimeoutValue {
  219. return strconv.FormatInt(d, 10) + "u"
  220. }
  221. if d := div(t, time.Millisecond); d <= maxTimeoutValue {
  222. return strconv.FormatInt(d, 10) + "m"
  223. }
  224. if d := div(t, time.Second); d <= maxTimeoutValue {
  225. return strconv.FormatInt(d, 10) + "S"
  226. }
  227. if d := div(t, time.Minute); d <= maxTimeoutValue {
  228. return strconv.FormatInt(d, 10) + "M"
  229. }
  230. // Note that maxTimeoutValue * time.Hour > MaxInt64.
  231. return strconv.FormatInt(div(t, time.Hour), 10) + "H"
  232. }
  233. func timeoutDecode(s string) (time.Duration, error) {
  234. size := len(s)
  235. if size < 2 {
  236. return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
  237. }
  238. unit := timeoutUnit(s[size-1])
  239. d, ok := timeoutUnitToDuration(unit)
  240. if !ok {
  241. return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s)
  242. }
  243. t, err := strconv.ParseInt(s[:size-1], 10, 64)
  244. if err != nil {
  245. return 0, err
  246. }
  247. return d * time.Duration(t), nil
  248. }
  249. type framer struct {
  250. numWriters int32
  251. reader io.Reader
  252. writer *bufio.Writer
  253. fr *http2.Framer
  254. }
  255. func newFramer(conn net.Conn) *framer {
  256. f := &framer{
  257. reader: bufio.NewReaderSize(conn, http2IOBufSize),
  258. writer: bufio.NewWriterSize(conn, http2IOBufSize),
  259. }
  260. f.fr = http2.NewFramer(f.writer, f.reader)
  261. f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
  262. return f
  263. }
  264. func (f *framer) adjustNumWriters(i int32) int32 {
  265. return atomic.AddInt32(&f.numWriters, i)
  266. }
  267. // The following writeXXX functions can only be called when the caller gets
  268. // unblocked from writableChan channel (i.e., owns the privilege to write).
  269. func (f *framer) writeContinuation(forceFlush bool, streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
  270. if err := f.fr.WriteContinuation(streamID, endHeaders, headerBlockFragment); err != nil {
  271. return err
  272. }
  273. if forceFlush {
  274. return f.writer.Flush()
  275. }
  276. return nil
  277. }
  278. func (f *framer) writeData(forceFlush bool, streamID uint32, endStream bool, data []byte) error {
  279. if err := f.fr.WriteData(streamID, endStream, data); err != nil {
  280. return err
  281. }
  282. if forceFlush {
  283. return f.writer.Flush()
  284. }
  285. return nil
  286. }
  287. func (f *framer) writeGoAway(forceFlush bool, maxStreamID uint32, code http2.ErrCode, debugData []byte) error {
  288. if err := f.fr.WriteGoAway(maxStreamID, code, debugData); err != nil {
  289. return err
  290. }
  291. if forceFlush {
  292. return f.writer.Flush()
  293. }
  294. return nil
  295. }
  296. func (f *framer) writeHeaders(forceFlush bool, p http2.HeadersFrameParam) error {
  297. if err := f.fr.WriteHeaders(p); err != nil {
  298. return err
  299. }
  300. if forceFlush {
  301. return f.writer.Flush()
  302. }
  303. return nil
  304. }
  305. func (f *framer) writePing(forceFlush, ack bool, data [8]byte) error {
  306. if err := f.fr.WritePing(ack, data); err != nil {
  307. return err
  308. }
  309. if forceFlush {
  310. return f.writer.Flush()
  311. }
  312. return nil
  313. }
  314. func (f *framer) writePriority(forceFlush bool, streamID uint32, p http2.PriorityParam) error {
  315. if err := f.fr.WritePriority(streamID, p); err != nil {
  316. return err
  317. }
  318. if forceFlush {
  319. return f.writer.Flush()
  320. }
  321. return nil
  322. }
  323. func (f *framer) writePushPromise(forceFlush bool, p http2.PushPromiseParam) error {
  324. if err := f.fr.WritePushPromise(p); err != nil {
  325. return err
  326. }
  327. if forceFlush {
  328. return f.writer.Flush()
  329. }
  330. return nil
  331. }
  332. func (f *framer) writeRSTStream(forceFlush bool, streamID uint32, code http2.ErrCode) error {
  333. if err := f.fr.WriteRSTStream(streamID, code); err != nil {
  334. return err
  335. }
  336. if forceFlush {
  337. return f.writer.Flush()
  338. }
  339. return nil
  340. }
  341. func (f *framer) writeSettings(forceFlush bool, settings ...http2.Setting) error {
  342. if err := f.fr.WriteSettings(settings...); err != nil {
  343. return err
  344. }
  345. if forceFlush {
  346. return f.writer.Flush()
  347. }
  348. return nil
  349. }
  350. func (f *framer) writeSettingsAck(forceFlush bool) error {
  351. if err := f.fr.WriteSettingsAck(); err != nil {
  352. return err
  353. }
  354. if forceFlush {
  355. return f.writer.Flush()
  356. }
  357. return nil
  358. }
  359. func (f *framer) writeWindowUpdate(forceFlush bool, streamID, incr uint32) error {
  360. if err := f.fr.WriteWindowUpdate(streamID, incr); err != nil {
  361. return err
  362. }
  363. if forceFlush {
  364. return f.writer.Flush()
  365. }
  366. return nil
  367. }
  368. func (f *framer) flushWrite() error {
  369. return f.writer.Flush()
  370. }
  371. func (f *framer) readFrame() (http2.Frame, error) {
  372. return f.fr.ReadFrame()
  373. }
  374. func (f *framer) errorDetail() error {
  375. return f.fr.ErrorDetail()
  376. }