]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/google.golang.org/grpc/internal/transport/transport.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / google.golang.org / grpc / internal / transport / transport.go
similarity index 52%
rename from vendor/google.golang.org/grpc/transport/transport.go
rename to vendor/google.golang.org/grpc/internal/transport/transport.go
index ec0fe678dbf42439e2839a887e0a51bb5f39221a..2580aa7d3ba1c384d1230ba270301091d704c7ab 100644 (file)
  */
 
 // Package transport defines and implements message oriented communication
-// channel to complete various transactions (e.g., an RPC).
-package transport // import "google.golang.org/grpc/transport"
+// channel to complete various transactions (e.g., an RPC).  It is meant for
+// grpc-internal usage and is not intended to be imported directly by users.
+package transport
 
 import (
+       "context"
+       "errors"
        "fmt"
        "io"
        "net"
        "sync"
+       "sync/atomic"
 
-       "golang.org/x/net/context"
-       "golang.org/x/net/http2"
        "google.golang.org/grpc/codes"
        "google.golang.org/grpc/credentials"
        "google.golang.org/grpc/keepalive"
@@ -56,6 +58,7 @@ type recvBuffer struct {
        c       chan recvMsg
        mu      sync.Mutex
        backlog []recvMsg
+       err     error
 }
 
 func newRecvBuffer() *recvBuffer {
@@ -67,20 +70,27 @@ func newRecvBuffer() *recvBuffer {
 
 func (b *recvBuffer) put(r recvMsg) {
        b.mu.Lock()
-       defer b.mu.Unlock()
+       if b.err != nil {
+               b.mu.Unlock()
+               // An error had occurred earlier, don't accept more
+               // data or errors.
+               return
+       }
+       b.err = r.err
        if len(b.backlog) == 0 {
                select {
                case b.c <- r:
+                       b.mu.Unlock()
                        return
                default:
                }
        }
        b.backlog = append(b.backlog, r)
+       b.mu.Unlock()
 }
 
 func (b *recvBuffer) load() {
        b.mu.Lock()
-       defer b.mu.Unlock()
        if len(b.backlog) > 0 {
                select {
                case b.c <- b.backlog[0]:
@@ -89,6 +99,7 @@ func (b *recvBuffer) load() {
                default:
                }
        }
+       b.mu.Unlock()
 }
 
 // get returns the channel that receives a recvMsg in the buffer.
@@ -102,11 +113,12 @@ func (b *recvBuffer) get() <-chan recvMsg {
 // recvBufferReader implements io.Reader interface to read the data from
 // recvBuffer.
 type recvBufferReader struct {
-       ctx    context.Context
-       goAway chan struct{}
-       recv   *recvBuffer
-       last   []byte // Stores the remaining data in the previous calls.
-       err    error
+       closeStream func(error) // Closes the client transport stream with the given error and nil trailer metadata.
+       ctx         context.Context
+       ctxDone     <-chan struct{} // cache of ctx.Done() (for performance).
+       recv        *recvBuffer
+       last        []byte // Stores the remaining data in the previous calls.
+       err         error
 }
 
 // Read reads the next len(p) bytes from last. If last is drained, it tries to
@@ -116,87 +128,54 @@ func (r *recvBufferReader) Read(p []byte) (n int, err error) {
        if r.err != nil {
                return 0, r.err
        }
-       n, r.err = r.read(p)
-       return n, r.err
-}
-
-func (r *recvBufferReader) read(p []byte) (n int, err error) {
        if r.last != nil && len(r.last) > 0 {
                // Read remaining data left in last call.
                copied := copy(p, r.last)
                r.last = r.last[copied:]
                return copied, nil
        }
+       if r.closeStream != nil {
+               n, r.err = r.readClient(p)
+       } else {
+               n, r.err = r.read(p)
+       }
+       return n, r.err
+}
+
+func (r *recvBufferReader) read(p []byte) (n int, err error) {
        select {
-       case <-r.ctx.Done():
+       case <-r.ctxDone:
                return 0, ContextErr(r.ctx.Err())
-       case <-r.goAway:
-               return 0, ErrStreamDrain
        case m := <-r.recv.get():
-               r.recv.load()
-               if m.err != nil {
-                       return 0, m.err
-               }
-               copied := copy(p, m.data)
-               r.last = m.data[copied:]
-               return copied, nil
+               return r.readAdditional(m, p)
        }
 }
 
-// All items in an out of a controlBuffer should be the same type.
-type item interface {
-       item()
-}
-
-// controlBuffer is an unbounded channel of item.
-type controlBuffer struct {
-       c       chan item
-       mu      sync.Mutex
-       backlog []item
-}
-
-func newControlBuffer() *controlBuffer {
-       b := &controlBuffer{
-               c: make(chan item, 1),
+func (r *recvBufferReader) readClient(p []byte) (n int, err error) {
+       // If the context is canceled, then closes the stream with nil metadata.
+       // closeStream writes its error parameter to r.recv as a recvMsg.
+       // r.readAdditional acts on that message and returns the necessary error.
+       select {
+       case <-r.ctxDone:
+               r.closeStream(ContextErr(r.ctx.Err()))
+               m := <-r.recv.get()
+               return r.readAdditional(m, p)
+       case m := <-r.recv.get():
+               return r.readAdditional(m, p)
        }
-       return b
 }
 
-func (b *controlBuffer) put(r item) {
-       b.mu.Lock()
-       defer b.mu.Unlock()
-       if len(b.backlog) == 0 {
-               select {
-               case b.c <- r:
-                       return
-               default:
-               }
+func (r *recvBufferReader) readAdditional(m recvMsg, p []byte) (n int, err error) {
+       r.recv.load()
+       if m.err != nil {
+               return 0, m.err
        }
-       b.backlog = append(b.backlog, r)
+       copied := copy(p, m.data)
+       r.last = m.data[copied:]
+       return copied, nil
 }
 
-func (b *controlBuffer) load() {
-       b.mu.Lock()
-       defer b.mu.Unlock()
-       if len(b.backlog) > 0 {
-               select {
-               case b.c <- b.backlog[0]:
-                       b.backlog[0] = nil
-                       b.backlog = b.backlog[1:]
-               default:
-               }
-       }
-}
-
-// get returns the channel that receives an item in the buffer.
-//
-// Upon receipt of an item, the caller should call load to send another
-// item onto the channel if there is any.
-func (b *controlBuffer) get() <-chan item {
-       return b.c
-}
-
-type streamState uint8
+type streamState uint32
 
 const (
        streamActive    streamState = iota
@@ -207,65 +186,98 @@ const (
 
 // Stream represents an RPC in the transport layer.
 type Stream struct {
-       id uint32
-       // nil for client side Stream.
-       st ServerTransport
-       // ctx is the associated context of the stream.
-       ctx context.Context
-       // cancel is always nil for client side Stream.
-       cancel context.CancelFunc
-       // done is closed when the final status arrives.
-       done chan struct{}
-       // goAway is closed when the server sent GoAways signal before this stream was initiated.
-       goAway chan struct{}
-       // method records the associated RPC method of the stream.
-       method       string
+       id           uint32
+       st           ServerTransport    // nil for client side Stream
+       ctx          context.Context    // the associated context of the stream
+       cancel       context.CancelFunc // always nil for client side Stream
+       done         chan struct{}      // closed at the end of stream to unblock writers. On the client side.
+       ctxDone      <-chan struct{}    // same as done chan but for server side. Cache of ctx.Done() (for performance)
+       method       string             // the associated RPC method of the stream
        recvCompress string
        sendCompress string
        buf          *recvBuffer
        trReader     io.Reader
        fc           *inFlow
-       recvQuota    uint32
-
-       // TODO: Remote this unused variable.
-       // The accumulated inbound quota pending for window update.
-       updateQuota uint32
+       wq           *writeQuota
 
        // Callback to state application's intentions to read data. This
-       // is used to adjust flow control, if need be.
+       // is used to adjust flow control, if needed.
        requestRead func(int)
 
-       sendQuotaPool *quotaPool
-       // Close headerChan to indicate the end of reception of header metadata.
-       headerChan chan struct{}
-       // header caches the received header metadata.
-       header metadata.MD
-       // The key-value map of trailer metadata.
-       trailer metadata.MD
-
-       mu sync.RWMutex // guard the following
-       // headerOK becomes true from the first header is about to send.
-       headerOk bool
-       state    streamState
-       // true iff headerChan is closed. Used to avoid closing headerChan
-       // multiple times.
-       headerDone bool
-       // the status error received from the server.
+       headerChan chan struct{} // closed to indicate the end of header metadata.
+       headerDone uint32        // set when headerChan is closed. Used to avoid closing headerChan multiple times.
+
+       // hdrMu protects header and trailer metadata on the server-side.
+       hdrMu sync.Mutex
+       // On client side, header keeps the received header metadata.
+       //
+       // On server side, header keeps the header set by SetHeader(). The complete
+       // header will merged into this after t.WriteHeader() is called.
+       header  metadata.MD
+       trailer metadata.MD // the key-value map of trailer metadata.
+
+       noHeaders bool // set if the client never received headers (set only after the stream is done).
+
+       // On the server-side, headerSent is atomically set to 1 when the headers are sent out.
+       headerSent uint32
+
+       state streamState
+
+       // On client-side it is the status error received from the server.
+       // On server-side it is unused.
        status *status.Status
-       // rstStream indicates whether a RST_STREAM frame needs to be sent
-       // to the server to signify that this stream is closing.
-       rstStream bool
-       // rstError is the error that needs to be sent along with the RST_STREAM frame.
-       rstError http2.ErrCode
-       // bytesSent and bytesReceived indicates whether any bytes have been sent or
-       // received on this stream.
-       bytesSent     bool
-       bytesReceived bool
+
+       bytesReceived uint32 // indicates whether any bytes have been received on this stream
+       unprocessed   uint32 // set if the server sends a refused stream or GOAWAY including this stream
+
+       // contentSubtype is the content-subtype for requests.
+       // this must be lowercase or the behavior is undefined.
+       contentSubtype string
+}
+
+// isHeaderSent is only valid on the server-side.
+func (s *Stream) isHeaderSent() bool {
+       return atomic.LoadUint32(&s.headerSent) == 1
+}
+
+// updateHeaderSent updates headerSent and returns true
+// if it was alreay set. It is valid only on server-side.
+func (s *Stream) updateHeaderSent() bool {
+       return atomic.SwapUint32(&s.headerSent, 1) == 1
+}
+
+func (s *Stream) swapState(st streamState) streamState {
+       return streamState(atomic.SwapUint32((*uint32)(&s.state), uint32(st)))
+}
+
+func (s *Stream) compareAndSwapState(oldState, newState streamState) bool {
+       return atomic.CompareAndSwapUint32((*uint32)(&s.state), uint32(oldState), uint32(newState))
+}
+
+func (s *Stream) getState() streamState {
+       return streamState(atomic.LoadUint32((*uint32)(&s.state)))
+}
+
+func (s *Stream) waitOnHeader() error {
+       if s.headerChan == nil {
+               // On the server headerChan is always nil since a stream originates
+               // only after having received headers.
+               return nil
+       }
+       select {
+       case <-s.ctx.Done():
+               return ContextErr(s.ctx.Err())
+       case <-s.headerChan:
+               return nil
+       }
 }
 
 // RecvCompress returns the compression algorithm applied to the inbound
 // message. It is empty string if there is no compression applied.
 func (s *Stream) RecvCompress() string {
+       if err := s.waitOnHeader(); err != nil {
+               return ""
+       }
        return s.recvCompress
 }
 
@@ -274,53 +286,68 @@ func (s *Stream) SetSendCompress(str string) {
        s.sendCompress = str
 }
 
-// Done returns a chanel which is closed when it receives the final status
+// Done returns a channel which is closed when it receives the final status
 // from the server.
 func (s *Stream) Done() <-chan struct{} {
        return s.done
 }
 
-// GoAway returns a channel which is closed when the server sent GoAways signal
-// before this stream was initiated.
-func (s *Stream) GoAway() <-chan struct{} {
-       return s.goAway
-}
-
-// Header acquires the key-value pairs of header metadata once it
-// is available. It blocks until i) the metadata is ready or ii) there is no
-// header metadata or iii) the stream is canceled/expired.
+// Header returns the header metadata of the stream.
+//
+// On client side, it acquires the key-value pairs of header metadata once it is
+// available. It blocks until i) the metadata is ready or ii) there is no header
+// metadata or iii) the stream is canceled/expired.
+//
+// On server side, it returns the out header after t.WriteHeader is called.
 func (s *Stream) Header() (metadata.MD, error) {
-       var err error
-       select {
-       case <-s.ctx.Done():
-               err = ContextErr(s.ctx.Err())
-       case <-s.goAway:
-               err = ErrStreamDrain
-       case <-s.headerChan:
+       if s.headerChan == nil && s.header != nil {
+               // On server side, return the header in stream. It will be the out
+               // header after t.WriteHeader is called.
                return s.header.Copy(), nil
        }
+       err := s.waitOnHeader()
        // Even if the stream is closed, header is returned if available.
        select {
        case <-s.headerChan:
+               if s.header == nil {
+                       return nil, nil
+               }
                return s.header.Copy(), nil
        default:
        }
        return nil, err
 }
 
+// TrailersOnly blocks until a header or trailers-only frame is received and
+// then returns true if the stream was trailers-only.  If the stream ends
+// before headers are received, returns true, nil.  If a context error happens
+// first, returns it as a status error.  Client-side only.
+func (s *Stream) TrailersOnly() (bool, error) {
+       err := s.waitOnHeader()
+       if err != nil {
+               return false, err
+       }
+       // if !headerDone, some other connection error occurred.
+       return s.noHeaders && atomic.LoadUint32(&s.headerDone) == 1, nil
+}
+
 // Trailer returns the cached trailer metedata. Note that if it is not called
 // after the entire stream is done, it could return an empty MD. Client
 // side only.
+// It can be safely read only after stream has ended that is either read
+// or write have returned io.EOF.
 func (s *Stream) Trailer() metadata.MD {
-       s.mu.RLock()
-       defer s.mu.RUnlock()
-       return s.trailer.Copy()
+       c := s.trailer.Copy()
+       return c
 }
 
-// ServerTransport returns the underlying ServerTransport for the stream.
-// The client side stream always returns nil.
-func (s *Stream) ServerTransport() ServerTransport {
-       return s.st
+// ContentSubtype returns the content-subtype for a request. For example, a
+// content-subtype of "proto" will result in a content-type of
+// "application/grpc+proto". This will always be lowercase.  See
+// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
+// more details.
+func (s *Stream) ContentSubtype() string {
+       return s.contentSubtype
 }
 
 // Context returns the context of the stream.
@@ -334,34 +361,48 @@ func (s *Stream) Method() string {
 }
 
 // Status returns the status received from the server.
+// Status can be read safely only after the stream has ended,
+// that is, after Done() is closed.
 func (s *Stream) Status() *status.Status {
        return s.status
 }
 
 // SetHeader sets the header metadata. This can be called multiple times.
 // Server side only.
+// This should not be called in parallel to other data writes.
 func (s *Stream) SetHeader(md metadata.MD) error {
-       s.mu.Lock()
-       defer s.mu.Unlock()
-       if s.headerOk || s.state == streamDone {
-               return ErrIllegalHeaderWrite
-       }
        if md.Len() == 0 {
                return nil
        }
+       if s.isHeaderSent() || s.getState() == streamDone {
+               return ErrIllegalHeaderWrite
+       }
+       s.hdrMu.Lock()
        s.header = metadata.Join(s.header, md)
+       s.hdrMu.Unlock()
        return nil
 }
 
+// SendHeader sends the given header metadata. The given metadata is
+// combined with any metadata set by previous calls to SetHeader and
+// then written to the transport stream.
+func (s *Stream) SendHeader(md metadata.MD) error {
+       return s.st.WriteHeader(s, md)
+}
+
 // SetTrailer sets the trailer metadata which will be sent with the RPC status
 // by the server. This can be called multiple times. Server side only.
+// This should not be called parallel to other data writes.
 func (s *Stream) SetTrailer(md metadata.MD) error {
        if md.Len() == 0 {
                return nil
        }
-       s.mu.Lock()
-       defer s.mu.Unlock()
+       if s.getState() == streamDone {
+               return ErrIllegalHeaderWrite
+       }
+       s.hdrMu.Lock()
        s.trailer = metadata.Join(s.trailer, md)
+       s.hdrMu.Unlock()
        return nil
 }
 
@@ -401,26 +442,15 @@ func (t *transportReader) Read(p []byte) (n int, err error) {
        return
 }
 
-// finish sets the stream's state and status, and closes the done channel.
-// s.mu must be held by the caller.  st must always be non-nil.
-func (s *Stream) finish(st *status.Status) {
-       s.status = st
-       s.state = streamDone
-       close(s.done)
-}
-
-// BytesSent indicates whether any bytes have been sent on this stream.
-func (s *Stream) BytesSent() bool {
-       s.mu.Lock()
-       defer s.mu.Unlock()
-       return s.bytesSent
-}
-
 // BytesReceived indicates whether any bytes have been received on this stream.
 func (s *Stream) BytesReceived() bool {
-       s.mu.Lock()
-       defer s.mu.Unlock()
-       return s.bytesReceived
+       return atomic.LoadUint32(&s.bytesReceived) == 1
+}
+
+// Unprocessed indicates whether the server did not process this stream --
+// i.e. it sent a refused stream or GOAWAY including this stream ID.
+func (s *Stream) Unprocessed() bool {
+       return atomic.LoadUint32(&s.unprocessed) == 1
 }
 
 // GoString is implemented by Stream so context.String() won't
@@ -429,27 +459,11 @@ func (s *Stream) GoString() string {
        return fmt.Sprintf("<stream: %p, %v>", s, s.method)
 }
 
-// The key to save transport.Stream in the context.
-type streamKey struct{}
-
-// newContextWithStream creates a new context from ctx and attaches stream
-// to it.
-func newContextWithStream(ctx context.Context, stream *Stream) context.Context {
-       return context.WithValue(ctx, streamKey{}, stream)
-}
-
-// StreamFromContext returns the stream saved in ctx.
-func StreamFromContext(ctx context.Context) (s *Stream, ok bool) {
-       s, ok = ctx.Value(streamKey{}).(*Stream)
-       return
-}
-
 // state of transport
 type transportState int
 
 const (
        reachable transportState = iota
-       unreachable
        closing
        draining
 )
@@ -464,6 +478,10 @@ type ServerConfig struct {
        KeepalivePolicy       keepalive.EnforcementPolicy
        InitialWindowSize     int32
        InitialConnWindowSize int32
+       WriteBufferSize       int
+       ReadBufferSize        int
+       ChannelzParentID      int64
+       MaxHeaderListSize     *uint32
 }
 
 // NewServerTransport creates a ServerTransport with conn or non-nil error
@@ -476,37 +494,47 @@ func NewServerTransport(protocol string, conn net.Conn, config *ServerConfig) (S
 type ConnectOptions struct {
        // UserAgent is the application user agent.
        UserAgent string
-       // Authority is the :authority pseudo-header to use. This field has no effect if
-       // TransportCredentials is set.
-       Authority string
        // Dialer specifies how to dial a network address.
        Dialer func(context.Context, string) (net.Conn, error)
        // FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors.
        FailOnNonTempDialError bool
        // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs.
        PerRPCCredentials []credentials.PerRPCCredentials
-       // TransportCredentials stores the Authenticator required to setup a client connection.
+       // TransportCredentials stores the Authenticator required to setup a client
+       // connection. Only one of TransportCredentials and CredsBundle is non-nil.
        TransportCredentials credentials.TransportCredentials
+       // CredsBundle is the credentials bundle to be used. Only one of
+       // TransportCredentials and CredsBundle is non-nil.
+       CredsBundle credentials.Bundle
        // KeepaliveParams stores the keepalive parameters.
        KeepaliveParams keepalive.ClientParameters
        // StatsHandler stores the handler for stats.
        StatsHandler stats.Handler
-       // InitialWindowSize sets the intial window size for a stream.
+       // InitialWindowSize sets the initial window size for a stream.
        InitialWindowSize int32
-       // InitialConnWindowSize sets the intial window size for a connection.
+       // InitialConnWindowSize sets the initial window size for a connection.
        InitialConnWindowSize int32
+       // WriteBufferSize sets the size of write buffer which in turn determines how much data can be batched before it's written on the wire.
+       WriteBufferSize int
+       // ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
+       ReadBufferSize int
+       // ChannelzParentID sets the addrConn id which initiate the creation of this client transport.
+       ChannelzParentID int64
+       // MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
+       MaxHeaderListSize *uint32
 }
 
 // TargetInfo contains the information of the target such as network address and metadata.
 type TargetInfo struct {
-       Addr     string
-       Metadata interface{}
+       Addr      string
+       Metadata  interface{}
+       Authority string
 }
 
 // NewClientTransport establishes the transport with the required ConnectOptions
 // and returns it to the caller.
-func NewClientTransport(ctx context.Context, target TargetInfo, opts ConnectOptions) (ClientTransport, error) {
-       return newHTTP2Client(ctx, target, opts)
+func NewClientTransport(connectCtx, ctx context.Context, target TargetInfo, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) {
+       return newHTTP2Client(connectCtx, ctx, target, opts, onPrefaceReceipt, onGoAway, onClose)
 }
 
 // Options provides additional hints and information for message
@@ -515,11 +543,6 @@ type Options struct {
        // Last indicates whether this write is the last piece for
        // this stream.
        Last bool
-
-       // Delay is a hint to the transport implementation for whether
-       // the data could be buffered for a batching write. The
-       // Transport implementation may ignore the hint.
-       Delay bool
 }
 
 // CallHdr carries the information of a particular RPC.
@@ -530,10 +553,6 @@ type CallHdr struct {
        // Method specifies the operation to perform.
        Method string
 
-       // RecvCompress specifies the compression algorithm applied on
-       // inbound messages.
-       RecvCompress string
-
        // SendCompress specifies the compression algorithm applied on
        // outbound message.
        SendCompress string
@@ -541,13 +560,15 @@ type CallHdr struct {
        // Creds specifies credentials.PerRPCCredentials for a call.
        Creds credentials.PerRPCCredentials
 
-       // Flush indicates whether a new stream command should be sent
-       // to the peer without waiting for the first data. This is
-       // only a hint.
-       // If it's true, the transport may modify the flush decision
-       // for performance purposes.
-       // If it's false, new stream will never be flushed.
-       Flush bool
+       // ContentSubtype specifies the content-subtype for a request. For example, a
+       // content-subtype of "proto" will result in a content-type of
+       // "application/grpc+proto". The value of ContentSubtype must be all
+       // lowercase, otherwise the behavior is undefined. See
+       // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
+       // for more details.
+       ContentSubtype string
+
+       PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
 }
 
 // ClientTransport is the common interface for all gRPC client-side transport
@@ -564,7 +585,7 @@ type ClientTransport interface {
 
        // Write sends the data for the given stream. A nil stream indicates
        // the write is to be performed on the transport as a whole.
-       Write(s *Stream, data []byte, opts *Options) error
+       Write(s *Stream, hdr []byte, data []byte, opts *Options) error
 
        // NewStream creates a Stream for an RPC.
        NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error)
@@ -589,6 +610,12 @@ type ClientTransport interface {
 
        // GetGoAwayReason returns the reason why GoAway frame was received.
        GetGoAwayReason() GoAwayReason
+
+       // IncrMsgSent increments the number of message sent through this transport.
+       IncrMsgSent()
+
+       // IncrMsgRecv increments the number of message received through this transport.
+       IncrMsgRecv()
 }
 
 // ServerTransport is the common interface for all gRPC server-side transport
@@ -606,7 +633,7 @@ type ServerTransport interface {
 
        // Write sends the data for the given stream.
        // Write may not be called on all streams.
-       Write(s *Stream, data []byte, opts *Options) error
+       Write(s *Stream, hdr []byte, data []byte, opts *Options) error
 
        // WriteStatus sends the status of a stream to the client.  WriteStatus is
        // the final call made on a stream and always occurs.
@@ -622,14 +649,12 @@ type ServerTransport interface {
 
        // Drain notifies the client this ServerTransport stops accepting new RPCs.
        Drain()
-}
 
-// streamErrorf creates an StreamError with the specified error code and description.
-func streamErrorf(c codes.Code, format string, a ...interface{}) StreamError {
-       return StreamError{
-               Code: c,
-               Desc: fmt.Sprintf(format, a...),
-       }
+       // IncrMsgSent increments the number of message sent through this transport.
+       IncrMsgSent()
+
+       // IncrMsgRecv increments the number of message received through this transport.
+       IncrMsgRecv()
 }
 
 // connectionErrorf creates an ConnectionError with the specified error description.
@@ -671,60 +696,63 @@ func (e ConnectionError) Origin() error {
 var (
        // ErrConnClosing indicates that the transport is closing.
        ErrConnClosing = connectionErrorf(true, nil, "transport is closing")
-       // ErrStreamDrain indicates that the stream is rejected by the server because
-       // the server stops accepting new RPCs.
-       ErrStreamDrain = streamErrorf(codes.Unavailable, "the server stops accepting new RPCs")
+       // errStreamDrain indicates that the stream is rejected because the
+       // connection is draining. This could be caused by goaway or balancer
+       // removing the address.
+       errStreamDrain = status.Error(codes.Unavailable, "the connection is draining")
+       // errStreamDone is returned from write at the client side to indiacte application
+       // layer of an error.
+       errStreamDone = errors.New("the stream is done")
+       // StatusGoAway indicates that the server sent a GOAWAY that included this
+       // stream's ID in unprocessed RPCs.
+       statusGoAway = status.New(codes.Unavailable, "the stream is rejected because server is draining the connection")
 )
 
-// TODO: See if we can replace StreamError with status package errors.
-
-// StreamError is an error that only affects one stream within a connection.
-type StreamError struct {
-       Code codes.Code
-       Desc string
-}
-
-func (e StreamError) Error() string {
-       return fmt.Sprintf("stream error: code = %s desc = %q", e.Code, e.Desc)
-}
-
-// wait blocks until it can receive from ctx.Done, closing, or proceed.
-// If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err.
-// If it receives from done, it returns 0, io.EOF if ctx is not done; otherwise
-// it return the StreamError for ctx.Err.
-// If it receives from goAway, it returns 0, ErrStreamDrain.
-// If it receives from closing, it returns 0, ErrConnClosing.
-// If it receives from proceed, it returns the received integer, nil.
-func wait(ctx context.Context, done, goAway, closing <-chan struct{}, proceed <-chan int) (int, error) {
-       select {
-       case <-ctx.Done():
-               return 0, ContextErr(ctx.Err())
-       case <-done:
-               // User cancellation has precedence.
-               select {
-               case <-ctx.Done():
-                       return 0, ContextErr(ctx.Err())
-               default:
-               }
-               return 0, io.EOF
-       case <-goAway:
-               return 0, ErrStreamDrain
-       case <-closing:
-               return 0, ErrConnClosing
-       case i := <-proceed:
-               return i, nil
-       }
-}
-
 // GoAwayReason contains the reason for the GoAway frame received.
 type GoAwayReason uint8
 
 const (
-       // Invalid indicates that no GoAway frame is received.
-       Invalid GoAwayReason = 0
-       // NoReason is the default value when GoAway frame is received.
-       NoReason GoAwayReason = 1
-       // TooManyPings indicates that a GoAway frame with ErrCodeEnhanceYourCalm
-       // was recieved and that the debug data said "too_many_pings".
-       TooManyPings GoAwayReason = 2
+       // GoAwayInvalid indicates that no GoAway frame is received.
+       GoAwayInvalid GoAwayReason = 0
+       // GoAwayNoReason is the default value when GoAway frame is received.
+       GoAwayNoReason GoAwayReason = 1
+       // GoAwayTooManyPings indicates that a GoAway frame with
+       // ErrCodeEnhanceYourCalm was received and that the debug data said
+       // "too_many_pings".
+       GoAwayTooManyPings GoAwayReason = 2
 )
+
+// channelzData is used to store channelz related data for http2Client and http2Server.
+// These fields cannot be embedded in the original structs (e.g. http2Client), since to do atomic
+// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
+// Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
+type channelzData struct {
+       kpCount int64
+       // The number of streams that have started, including already finished ones.
+       streamsStarted int64
+       // Client side: The number of streams that have ended successfully by receiving
+       // EoS bit set frame from server.
+       // Server side: The number of streams that have ended successfully by sending
+       // frame with EoS bit set.
+       streamsSucceeded int64
+       streamsFailed    int64
+       // lastStreamCreatedTime stores the timestamp that the last stream gets created. It is of int64 type
+       // instead of time.Time since it's more costly to atomically update time.Time variable than int64
+       // variable. The same goes for lastMsgSentTime and lastMsgRecvTime.
+       lastStreamCreatedTime int64
+       msgSent               int64
+       msgRecv               int64
+       lastMsgSentTime       int64
+       lastMsgRecvTime       int64
+}
+
+// ContextErr converts the error from context package into a status error.
+func ContextErr(err error) error {
+       switch err {
+       case context.DeadlineExceeded:
+               return status.Error(codes.DeadlineExceeded, err.Error())
+       case context.Canceled:
+               return status.Error(codes.Canceled, err.Error())
+       }
+       return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
+}