gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/internal/transport/controlbuf.go (about)

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