You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

853 lines
21 KiB

  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. "bytes"
  21. "fmt"
  22. "runtime"
  23. "sync"
  24. "golang.org/x/net/http2"
  25. "golang.org/x/net/http2/hpack"
  26. )
  27. var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
  28. e.SetMaxDynamicTableSizeLimit(v)
  29. }
  30. type itemNode struct {
  31. it interface{}
  32. next *itemNode
  33. }
  34. type itemList struct {
  35. head *itemNode
  36. tail *itemNode
  37. }
  38. func (il *itemList) enqueue(i interface{}) {
  39. n := &itemNode{it: i}
  40. if il.tail == nil {
  41. il.head, il.tail = n, n
  42. return
  43. }
  44. il.tail.next = n
  45. il.tail = n
  46. }
  47. // peek returns the first item in the list without removing it from the
  48. // list.
  49. func (il *itemList) peek() interface{} {
  50. return il.head.it
  51. }
  52. func (il *itemList) dequeue() interface{} {
  53. if il.head == nil {
  54. return nil
  55. }
  56. i := il.head.it
  57. il.head = il.head.next
  58. if il.head == nil {
  59. il.tail = nil
  60. }
  61. return i
  62. }
  63. func (il *itemList) dequeueAll() *itemNode {
  64. h := il.head
  65. il.head, il.tail = nil, nil
  66. return h
  67. }
  68. func (il *itemList) isEmpty() bool {
  69. return il.head == nil
  70. }
  71. // The following defines various control items which could flow through
  72. // the control buffer of transport. They represent different aspects of
  73. // control tasks, e.g., flow control, settings, streaming resetting, etc.
  74. // registerStream is used to register an incoming stream with loopy writer.
  75. type registerStream struct {
  76. streamID uint32
  77. wq *writeQuota
  78. }
  79. // headerFrame is also used to register stream on the client-side.
  80. type headerFrame struct {
  81. streamID uint32
  82. hf []hpack.HeaderField
  83. endStream bool // Valid on server side.
  84. initStream func(uint32) (bool, error) // Used only on the client side.
  85. onWrite func()
  86. wq *writeQuota // write quota for the stream created.
  87. cleanup *cleanupStream // Valid on the server side.
  88. onOrphaned func(error) // Valid on client-side
  89. }
  90. type cleanupStream struct {
  91. streamID uint32
  92. rst bool
  93. rstCode http2.ErrCode
  94. onWrite func()
  95. }
  96. type dataFrame struct {
  97. streamID uint32
  98. endStream bool
  99. h []byte
  100. d []byte
  101. // onEachWrite is called every time
  102. // a part of d is written out.
  103. onEachWrite func()
  104. }
  105. type incomingWindowUpdate struct {
  106. streamID uint32
  107. increment uint32
  108. }
  109. type outgoingWindowUpdate struct {
  110. streamID uint32
  111. increment uint32
  112. }
  113. type incomingSettings struct {
  114. ss []http2.Setting
  115. }
  116. type outgoingSettings struct {
  117. ss []http2.Setting
  118. }
  119. type incomingGoAway struct {
  120. }
  121. type goAway struct {
  122. code http2.ErrCode
  123. debugData []byte
  124. headsUp bool
  125. closeConn bool
  126. }
  127. type ping struct {
  128. ack bool
  129. data [8]byte
  130. }
  131. type outFlowControlSizeRequest struct {
  132. resp chan uint32
  133. }
  134. type outStreamState int
  135. const (
  136. active outStreamState = iota
  137. empty
  138. waitingOnStreamQuota
  139. )
  140. type outStream struct {
  141. id uint32
  142. state outStreamState
  143. itl *itemList
  144. bytesOutStanding int
  145. wq *writeQuota
  146. next *outStream
  147. prev *outStream
  148. }
  149. func (s *outStream) deleteSelf() {
  150. if s.prev != nil {
  151. s.prev.next = s.next
  152. }
  153. if s.next != nil {
  154. s.next.prev = s.prev
  155. }
  156. s.next, s.prev = nil, nil
  157. }
  158. type outStreamList struct {
  159. // Following are sentinel objects that mark the
  160. // beginning and end of the list. They do not
  161. // contain any item lists. All valid objects are
  162. // inserted in between them.
  163. // This is needed so that an outStream object can
  164. // deleteSelf() in O(1) time without knowing which
  165. // list it belongs to.
  166. head *outStream
  167. tail *outStream
  168. }
  169. func newOutStreamList() *outStreamList {
  170. head, tail := new(outStream), new(outStream)
  171. head.next = tail
  172. tail.prev = head
  173. return &outStreamList{
  174. head: head,
  175. tail: tail,
  176. }
  177. }
  178. func (l *outStreamList) enqueue(s *outStream) {
  179. e := l.tail.prev
  180. e.next = s
  181. s.prev = e
  182. s.next = l.tail
  183. l.tail.prev = s
  184. }
  185. // remove from the beginning of the list.
  186. func (l *outStreamList) dequeue() *outStream {
  187. b := l.head.next
  188. if b == l.tail {
  189. return nil
  190. }
  191. b.deleteSelf()
  192. return b
  193. }
  194. // controlBuffer is a way to pass information to loopy.
  195. // Information is passed as specific struct types called control frames.
  196. // A control frame not only represents data, messages or headers to be sent out
  197. // but can also be used to instruct loopy to update its internal state.
  198. // It shouldn't be confused with an HTTP2 frame, although some of the control frames
  199. // like dataFrame and headerFrame do go out on wire as HTTP2 frames.
  200. type controlBuffer struct {
  201. ch chan struct{}
  202. done <-chan struct{}
  203. mu sync.Mutex
  204. consumerWaiting bool
  205. list *itemList
  206. err error
  207. }
  208. func newControlBuffer(done <-chan struct{}) *controlBuffer {
  209. return &controlBuffer{
  210. ch: make(chan struct{}, 1),
  211. list: &itemList{},
  212. done: done,
  213. }
  214. }
  215. func (c *controlBuffer) put(it interface{}) error {
  216. _, err := c.executeAndPut(nil, it)
  217. return err
  218. }
  219. func (c *controlBuffer) executeAndPut(f func(it interface{}) bool, it interface{}) (bool, error) {
  220. var wakeUp bool
  221. c.mu.Lock()
  222. if c.err != nil {
  223. c.mu.Unlock()
  224. return false, c.err
  225. }
  226. if f != nil {
  227. if !f(it) { // f wasn't successful
  228. c.mu.Unlock()
  229. return false, nil
  230. }
  231. }
  232. if c.consumerWaiting {
  233. wakeUp = true
  234. c.consumerWaiting = false
  235. }
  236. c.list.enqueue(it)
  237. c.mu.Unlock()
  238. if wakeUp {
  239. select {
  240. case c.ch <- struct{}{}:
  241. default:
  242. }
  243. }
  244. return true, nil
  245. }
  246. // Note argument f should never be nil.
  247. func (c *controlBuffer) execute(f func(it interface{}) bool, it interface{}) (bool, error) {
  248. c.mu.Lock()
  249. if c.err != nil {
  250. c.mu.Unlock()
  251. return false, c.err
  252. }
  253. if !f(it) { // f wasn't successful
  254. c.mu.Unlock()
  255. return false, nil
  256. }
  257. c.mu.Unlock()
  258. return true, nil
  259. }
  260. func (c *controlBuffer) get(block bool) (interface{}, error) {
  261. for {
  262. c.mu.Lock()
  263. if c.err != nil {
  264. c.mu.Unlock()
  265. return nil, c.err
  266. }
  267. if !c.list.isEmpty() {
  268. h := c.list.dequeue()
  269. c.mu.Unlock()
  270. return h, nil
  271. }
  272. if !block {
  273. c.mu.Unlock()
  274. return nil, nil
  275. }
  276. c.consumerWaiting = true
  277. c.mu.Unlock()
  278. select {
  279. case <-c.ch:
  280. case <-c.done:
  281. c.finish()
  282. return nil, ErrConnClosing
  283. }
  284. }
  285. }
  286. func (c *controlBuffer) finish() {
  287. c.mu.Lock()
  288. if c.err != nil {
  289. c.mu.Unlock()
  290. return
  291. }
  292. c.err = ErrConnClosing
  293. // There may be headers for streams in the control buffer.
  294. // These streams need to be cleaned out since the transport
  295. // is still not aware of these yet.
  296. for head := c.list.dequeueAll(); head != nil; head = head.next {
  297. hdr, ok := head.it.(*headerFrame)
  298. if !ok {
  299. continue
  300. }
  301. if hdr.onOrphaned != nil { // It will be nil on the server-side.
  302. hdr.onOrphaned(ErrConnClosing)
  303. }
  304. }
  305. c.mu.Unlock()
  306. }
  307. type side int
  308. const (
  309. clientSide side = iota
  310. serverSide
  311. )
  312. // Loopy receives frames from the control buffer.
  313. // Each frame is handled individually; most of the work done by loopy goes
  314. // into handling data frames. Loopy maintains a queue of active streams, and each
  315. // stream maintains a queue of data frames; as loopy receives data frames
  316. // it gets added to the queue of the relevant stream.
  317. // Loopy goes over this list of active streams by processing one node every iteration,
  318. // thereby closely resemebling to a round-robin scheduling over all streams. While
  319. // processing a stream, loopy writes out data bytes from this stream capped by the min
  320. // of http2MaxFrameLen, connection-level flow control and stream-level flow control.
  321. type loopyWriter struct {
  322. side side
  323. cbuf *controlBuffer
  324. sendQuota uint32
  325. oiws uint32 // outbound initial window size.
  326. // estdStreams is map of all established streams that are not cleaned-up yet.
  327. // On client-side, this is all streams whose headers were sent out.
  328. // On server-side, this is all streams whose headers were received.
  329. estdStreams map[uint32]*outStream // Established streams.
  330. // activeStreams is a linked-list of all streams that have data to send and some
  331. // stream-level flow control quota.
  332. // Each of these streams internally have a list of data items(and perhaps trailers
  333. // on the server-side) to be sent out.
  334. activeStreams *outStreamList
  335. framer *framer
  336. hBuf *bytes.Buffer // The buffer for HPACK encoding.
  337. hEnc *hpack.Encoder // HPACK encoder.
  338. bdpEst *bdpEstimator
  339. draining bool
  340. // Side-specific handlers
  341. ssGoAwayHandler func(*goAway) (bool, error)
  342. }
  343. func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator) *loopyWriter {
  344. var buf bytes.Buffer
  345. l := &loopyWriter{
  346. side: s,
  347. cbuf: cbuf,
  348. sendQuota: defaultWindowSize,
  349. oiws: defaultWindowSize,
  350. estdStreams: make(map[uint32]*outStream),
  351. activeStreams: newOutStreamList(),
  352. framer: fr,
  353. hBuf: &buf,
  354. hEnc: hpack.NewEncoder(&buf),
  355. bdpEst: bdpEst,
  356. }
  357. return l
  358. }
  359. const minBatchSize = 1000
  360. // run should be run in a separate goroutine.
  361. // It reads control frames from controlBuf and processes them by:
  362. // 1. Updating loopy's internal state, or/and
  363. // 2. Writing out HTTP2 frames on the wire.
  364. //
  365. // Loopy keeps all active streams with data to send in a linked-list.
  366. // All streams in the activeStreams linked-list must have both:
  367. // 1. Data to send, and
  368. // 2. Stream level flow control quota available.
  369. //
  370. // In each iteration of run loop, other than processing the incoming control
  371. // frame, loopy calls processData, which processes one node from the activeStreams linked-list.
  372. // This results in writing of HTTP2 frames into an underlying write buffer.
  373. // When there's no more control frames to read from controlBuf, loopy flushes the write buffer.
  374. // As an optimization, to increase the batch size for each flush, loopy yields the processor, once
  375. // if the batch size is too low to give stream goroutines a chance to fill it up.
  376. func (l *loopyWriter) run() (err error) {
  377. defer func() {
  378. if err == ErrConnClosing {
  379. // Don't log ErrConnClosing as error since it happens
  380. // 1. When the connection is closed by some other known issue.
  381. // 2. User closed the connection.
  382. // 3. A graceful close of connection.
  383. infof("transport: loopyWriter.run returning. %v", err)
  384. err = nil
  385. }
  386. }()
  387. for {
  388. it, err := l.cbuf.get(true)
  389. if err != nil {
  390. return err
  391. }
  392. if err = l.handle(it); err != nil {
  393. return err
  394. }
  395. if _, err = l.processData(); err != nil {
  396. return err
  397. }
  398. gosched := true
  399. hasdata:
  400. for {
  401. it, err := l.cbuf.get(false)
  402. if err != nil {
  403. return err
  404. }
  405. if it != nil {
  406. if err = l.handle(it); err != nil {
  407. return err
  408. }
  409. if _, err = l.processData(); err != nil {
  410. return err
  411. }
  412. continue hasdata
  413. }
  414. isEmpty, err := l.processData()
  415. if err != nil {
  416. return err
  417. }
  418. if !isEmpty {
  419. continue hasdata
  420. }
  421. if gosched {
  422. gosched = false
  423. if l.framer.writer.offset < minBatchSize {
  424. runtime.Gosched()
  425. continue hasdata
  426. }
  427. }
  428. l.framer.writer.Flush()
  429. break hasdata
  430. }
  431. }
  432. }
  433. func (l *loopyWriter) outgoingWindowUpdateHandler(w *outgoingWindowUpdate) error {
  434. return l.framer.fr.WriteWindowUpdate(w.streamID, w.increment)
  435. }
  436. func (l *loopyWriter) incomingWindowUpdateHandler(w *incomingWindowUpdate) error {
  437. // Otherwise update the quota.
  438. if w.streamID == 0 {
  439. l.sendQuota += w.increment
  440. return nil
  441. }
  442. // Find the stream and update it.
  443. if str, ok := l.estdStreams[w.streamID]; ok {
  444. str.bytesOutStanding -= int(w.increment)
  445. if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota > 0 && str.state == waitingOnStreamQuota {
  446. str.state = active
  447. l.activeStreams.enqueue(str)
  448. return nil
  449. }
  450. }
  451. return nil
  452. }
  453. func (l *loopyWriter) outgoingSettingsHandler(s *outgoingSettings) error {
  454. return l.framer.fr.WriteSettings(s.ss...)
  455. }
  456. func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
  457. if err := l.applySettings(s.ss); err != nil {
  458. return err
  459. }
  460. return l.framer.fr.WriteSettingsAck()
  461. }
  462. func (l *loopyWriter) registerStreamHandler(h *registerStream) error {
  463. str := &outStream{
  464. id: h.streamID,
  465. state: empty,
  466. itl: &itemList{},
  467. wq: h.wq,
  468. }
  469. l.estdStreams[h.streamID] = str
  470. return nil
  471. }
  472. func (l *loopyWriter) headerHandler(h *headerFrame) error {
  473. if l.side == serverSide {
  474. str, ok := l.estdStreams[h.streamID]
  475. if !ok {
  476. warningf("transport: loopy doesn't recognize the stream: %d", h.streamID)
  477. return nil
  478. }
  479. // Case 1.A: Server is responding back with headers.
  480. if !h.endStream {
  481. return l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite)
  482. }
  483. // else: Case 1.B: Server wants to close stream.
  484. if str.state != empty { // either active or waiting on stream quota.
  485. // add it str's list of items.
  486. str.itl.enqueue(h)
  487. return nil
  488. }
  489. if err := l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite); err != nil {
  490. return err
  491. }
  492. return l.cleanupStreamHandler(h.cleanup)
  493. }
  494. // Case 2: Client wants to originate stream.
  495. str := &outStream{
  496. id: h.streamID,
  497. state: empty,
  498. itl: &itemList{},
  499. wq: h.wq,
  500. }
  501. str.itl.enqueue(h)
  502. return l.originateStream(str)
  503. }
  504. func (l *loopyWriter) originateStream(str *outStream) error {
  505. hdr := str.itl.dequeue().(*headerFrame)
  506. sendPing, err := hdr.initStream(str.id)
  507. if err != nil {
  508. if err == ErrConnClosing {
  509. return err
  510. }
  511. // Other errors(errStreamDrain) need not close transport.
  512. return nil
  513. }
  514. if err = l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil {
  515. return err
  516. }
  517. l.estdStreams[str.id] = str
  518. if sendPing {
  519. return l.pingHandler(&ping{data: [8]byte{}})
  520. }
  521. return nil
  522. }
  523. func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.HeaderField, onWrite func()) error {
  524. if onWrite != nil {
  525. onWrite()
  526. }
  527. l.hBuf.Reset()
  528. for _, f := range hf {
  529. if err := l.hEnc.WriteField(f); err != nil {
  530. warningf("transport: loopyWriter.writeHeader encountered error while encoding headers:", err)
  531. }
  532. }
  533. var (
  534. err error
  535. endHeaders, first bool
  536. )
  537. first = true
  538. for !endHeaders {
  539. size := l.hBuf.Len()
  540. if size > http2MaxFrameLen {
  541. size = http2MaxFrameLen
  542. } else {
  543. endHeaders = true
  544. }
  545. if first {
  546. first = false
  547. err = l.framer.fr.WriteHeaders(http2.HeadersFrameParam{
  548. StreamID: streamID,
  549. BlockFragment: l.hBuf.Next(size),
  550. EndStream: endStream,
  551. EndHeaders: endHeaders,
  552. })
  553. } else {
  554. err = l.framer.fr.WriteContinuation(
  555. streamID,
  556. endHeaders,
  557. l.hBuf.Next(size),
  558. )
  559. }
  560. if err != nil {
  561. return err
  562. }
  563. }
  564. return nil
  565. }
  566. func (l *loopyWriter) preprocessData(df *dataFrame) error {
  567. str, ok := l.estdStreams[df.streamID]
  568. if !ok {
  569. return nil
  570. }
  571. // If we got data for a stream it means that
  572. // stream was originated and the headers were sent out.
  573. str.itl.enqueue(df)
  574. if str.state == empty {
  575. str.state = active
  576. l.activeStreams.enqueue(str)
  577. }
  578. return nil
  579. }
  580. func (l *loopyWriter) pingHandler(p *ping) error {
  581. if !p.ack {
  582. l.bdpEst.timesnap(p.data)
  583. }
  584. return l.framer.fr.WritePing(p.ack, p.data)
  585. }
  586. func (l *loopyWriter) outFlowControlSizeRequestHandler(o *outFlowControlSizeRequest) error {
  587. o.resp <- l.sendQuota
  588. return nil
  589. }
  590. func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
  591. c.onWrite()
  592. if str, ok := l.estdStreams[c.streamID]; ok {
  593. // On the server side it could be a trailers-only response or
  594. // a RST_STREAM before stream initialization thus the stream might
  595. // not be established yet.
  596. delete(l.estdStreams, c.streamID)
  597. str.deleteSelf()
  598. }
  599. if c.rst { // If RST_STREAM needs to be sent.
  600. if err := l.framer.fr.WriteRSTStream(c.streamID, c.rstCode); err != nil {
  601. return err
  602. }
  603. }
  604. if l.side == clientSide && l.draining && len(l.estdStreams) == 0 {
  605. return ErrConnClosing
  606. }
  607. return nil
  608. }
  609. func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
  610. if l.side == clientSide {
  611. l.draining = true
  612. if len(l.estdStreams) == 0 {
  613. return ErrConnClosing
  614. }
  615. }
  616. return nil
  617. }
  618. func (l *loopyWriter) goAwayHandler(g *goAway) error {
  619. // Handling of outgoing GoAway is very specific to side.
  620. if l.ssGoAwayHandler != nil {
  621. draining, err := l.ssGoAwayHandler(g)
  622. if err != nil {
  623. return err
  624. }
  625. l.draining = draining
  626. }
  627. return nil
  628. }
  629. func (l *loopyWriter) handle(i interface{}) error {
  630. switch i := i.(type) {
  631. case *incomingWindowUpdate:
  632. return l.incomingWindowUpdateHandler(i)
  633. case *outgoingWindowUpdate:
  634. return l.outgoingWindowUpdateHandler(i)
  635. case *incomingSettings:
  636. return l.incomingSettingsHandler(i)
  637. case *outgoingSettings:
  638. return l.outgoingSettingsHandler(i)
  639. case *headerFrame:
  640. return l.headerHandler(i)
  641. case *registerStream:
  642. return l.registerStreamHandler(i)
  643. case *cleanupStream:
  644. return l.cleanupStreamHandler(i)
  645. case *incomingGoAway:
  646. return l.incomingGoAwayHandler(i)
  647. case *dataFrame:
  648. return l.preprocessData(i)
  649. case *ping:
  650. return l.pingHandler(i)
  651. case *goAway:
  652. return l.goAwayHandler(i)
  653. case *outFlowControlSizeRequest:
  654. return l.outFlowControlSizeRequestHandler(i)
  655. default:
  656. return fmt.Errorf("transport: unknown control message type %T", i)
  657. }
  658. }
  659. func (l *loopyWriter) applySettings(ss []http2.Setting) error {
  660. for _, s := range ss {
  661. switch s.ID {
  662. case http2.SettingInitialWindowSize:
  663. o := l.oiws
  664. l.oiws = s.Val
  665. if o < l.oiws {
  666. // If the new limit is greater make all depleted streams active.
  667. for _, stream := range l.estdStreams {
  668. if stream.state == waitingOnStreamQuota {
  669. stream.state = active
  670. l.activeStreams.enqueue(stream)
  671. }
  672. }
  673. }
  674. case http2.SettingHeaderTableSize:
  675. updateHeaderTblSize(l.hEnc, s.Val)
  676. }
  677. }
  678. return nil
  679. }
  680. // processData removes the first stream from active streams, writes out at most 16KB
  681. // of its data and then puts it at the end of activeStreams if there's still more data
  682. // to be sent and stream has some stream-level flow control.
  683. func (l *loopyWriter) processData() (bool, error) {
  684. if l.sendQuota == 0 {
  685. return true, nil
  686. }
  687. str := l.activeStreams.dequeue() // Remove the first stream.
  688. if str == nil {
  689. return true, nil
  690. }
  691. dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
  692. // A data item is represented by a dataFrame, since it later translates into
  693. // multiple HTTP2 data frames.
  694. // Every dataFrame has two buffers; h that keeps grpc-message header and d that is acutal data.
  695. // As an optimization to keep wire traffic low, data from d is copied to h to make as big as the
  696. // maximum possilbe HTTP2 frame size.
  697. if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // Empty data frame
  698. // Client sends out empty data frame with endStream = true
  699. if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
  700. return false, err
  701. }
  702. str.itl.dequeue() // remove the empty data item from stream
  703. if str.itl.isEmpty() {
  704. str.state = empty
  705. } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
  706. if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
  707. return false, err
  708. }
  709. if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
  710. return false, nil
  711. }
  712. } else {
  713. l.activeStreams.enqueue(str)
  714. }
  715. return false, nil
  716. }
  717. var (
  718. idx int
  719. buf []byte
  720. )
  721. if len(dataItem.h) != 0 { // data header has not been written out yet.
  722. buf = dataItem.h
  723. } else {
  724. idx = 1
  725. buf = dataItem.d
  726. }
  727. size := http2MaxFrameLen
  728. if len(buf) < size {
  729. size = len(buf)
  730. }
  731. if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota <= 0 { // stream-level flow control.
  732. str.state = waitingOnStreamQuota
  733. return false, nil
  734. } else if strQuota < size {
  735. size = strQuota
  736. }
  737. if l.sendQuota < uint32(size) { // connection-level flow control.
  738. size = int(l.sendQuota)
  739. }
  740. // Now that outgoing flow controls are checked we can replenish str's write quota
  741. str.wq.replenish(size)
  742. var endStream bool
  743. // If this is the last data message on this stream and all of it can be written in this iteration.
  744. if dataItem.endStream && size == len(buf) {
  745. // buf contains either data or it contains header but data is empty.
  746. if idx == 1 || len(dataItem.d) == 0 {
  747. endStream = true
  748. }
  749. }
  750. if dataItem.onEachWrite != nil {
  751. dataItem.onEachWrite()
  752. }
  753. if err := l.framer.fr.WriteData(dataItem.streamID, endStream, buf[:size]); err != nil {
  754. return false, err
  755. }
  756. buf = buf[size:]
  757. str.bytesOutStanding += size
  758. l.sendQuota -= uint32(size)
  759. if idx == 0 {
  760. dataItem.h = buf
  761. } else {
  762. dataItem.d = buf
  763. }
  764. if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // All the data from that message was written out.
  765. str.itl.dequeue()
  766. }
  767. if str.itl.isEmpty() {
  768. str.state = empty
  769. } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // The next item is trailers.
  770. if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
  771. return false, err
  772. }
  773. if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
  774. return false, err
  775. }
  776. } else if int(l.oiws)-str.bytesOutStanding <= 0 { // Ran out of stream quota.
  777. str.state = waitingOnStreamQuota
  778. } else { // Otherwise add it back to the list of active streams.
  779. l.activeStreams.enqueue(str)
  780. }
  781. return false, nil
  782. }