blob: d3bf65b2bdffd7c276a129445781fb8402cbebd7 [file] [log] [blame]
kesavand2cde6582020-06-22 04:56:23 -04001/*
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 defines and implements message oriented communication
20// channel to complete various transactions (e.g., an RPC). It is meant for
21// grpc-internal usage and is not intended to be imported directly by users.
22package transport
23
24import (
25 "bytes"
26 "context"
27 "errors"
28 "fmt"
29 "io"
30 "net"
31 "sync"
32 "sync/atomic"
Andrea Campanella764f1ed2022-03-24 11:46:38 +010033 "time"
kesavand2cde6582020-06-22 04:56:23 -040034
35 "google.golang.org/grpc/codes"
36 "google.golang.org/grpc/credentials"
37 "google.golang.org/grpc/keepalive"
38 "google.golang.org/grpc/metadata"
Andrea Campanella764f1ed2022-03-24 11:46:38 +010039 "google.golang.org/grpc/resolver"
kesavand2cde6582020-06-22 04:56:23 -040040 "google.golang.org/grpc/stats"
41 "google.golang.org/grpc/status"
42 "google.golang.org/grpc/tap"
43)
44
Andrea Campanella764f1ed2022-03-24 11:46:38 +010045const logLevel = 2
46
kesavand2cde6582020-06-22 04:56:23 -040047type bufferPool struct {
48 pool sync.Pool
49}
50
51func newBufferPool() *bufferPool {
52 return &bufferPool{
53 pool: sync.Pool{
54 New: func() interface{} {
55 return new(bytes.Buffer)
56 },
57 },
58 }
59}
60
61func (p *bufferPool) get() *bytes.Buffer {
62 return p.pool.Get().(*bytes.Buffer)
63}
64
65func (p *bufferPool) put(b *bytes.Buffer) {
66 p.pool.Put(b)
67}
68
69// recvMsg represents the received msg from the transport. All transport
70// protocol specific info has been removed.
71type recvMsg struct {
72 buffer *bytes.Buffer
73 // nil: received some data
74 // io.EOF: stream is completed. data is nil.
75 // other non-nil error: transport failure. data is nil.
76 err error
77}
78
79// recvBuffer is an unbounded channel of recvMsg structs.
80//
81// Note: recvBuffer differs from buffer.Unbounded only in the fact that it
82// holds a channel of recvMsg structs instead of objects implementing "item"
83// interface. recvBuffer is written to much more often and using strict recvMsg
84// structs helps avoid allocation in "recvBuffer.put"
85type recvBuffer struct {
86 c chan recvMsg
87 mu sync.Mutex
88 backlog []recvMsg
89 err error
90}
91
92func newRecvBuffer() *recvBuffer {
93 b := &recvBuffer{
94 c: make(chan recvMsg, 1),
95 }
96 return b
97}
98
99func (b *recvBuffer) put(r recvMsg) {
100 b.mu.Lock()
101 if b.err != nil {
102 b.mu.Unlock()
103 // An error had occurred earlier, don't accept more
104 // data or errors.
105 return
106 }
107 b.err = r.err
108 if len(b.backlog) == 0 {
109 select {
110 case b.c <- r:
111 b.mu.Unlock()
112 return
113 default:
114 }
115 }
116 b.backlog = append(b.backlog, r)
117 b.mu.Unlock()
118}
119
120func (b *recvBuffer) load() {
121 b.mu.Lock()
122 if len(b.backlog) > 0 {
123 select {
124 case b.c <- b.backlog[0]:
125 b.backlog[0] = recvMsg{}
126 b.backlog = b.backlog[1:]
127 default:
128 }
129 }
130 b.mu.Unlock()
131}
132
133// get returns the channel that receives a recvMsg in the buffer.
134//
135// Upon receipt of a recvMsg, the caller should call load to send another
136// recvMsg onto the channel if there is any.
137func (b *recvBuffer) get() <-chan recvMsg {
138 return b.c
139}
140
141// recvBufferReader implements io.Reader interface to read the data from
142// recvBuffer.
143type recvBufferReader struct {
144 closeStream func(error) // Closes the client transport stream with the given error and nil trailer metadata.
145 ctx context.Context
146 ctxDone <-chan struct{} // cache of ctx.Done() (for performance).
147 recv *recvBuffer
148 last *bytes.Buffer // Stores the remaining data in the previous calls.
149 err error
150 freeBuffer func(*bytes.Buffer)
151}
152
153// Read reads the next len(p) bytes from last. If last is drained, it tries to
154// read additional data from recv. It blocks if there no additional data available
155// in recv. If Read returns any non-nil error, it will continue to return that error.
156func (r *recvBufferReader) Read(p []byte) (n int, err error) {
157 if r.err != nil {
158 return 0, r.err
159 }
160 if r.last != nil {
161 // Read remaining data left in last call.
162 copied, _ := r.last.Read(p)
163 if r.last.Len() == 0 {
164 r.freeBuffer(r.last)
165 r.last = nil
166 }
167 return copied, nil
168 }
169 if r.closeStream != nil {
170 n, r.err = r.readClient(p)
171 } else {
172 n, r.err = r.read(p)
173 }
174 return n, r.err
175}
176
177func (r *recvBufferReader) read(p []byte) (n int, err error) {
178 select {
179 case <-r.ctxDone:
180 return 0, ContextErr(r.ctx.Err())
181 case m := <-r.recv.get():
182 return r.readAdditional(m, p)
183 }
184}
185
186func (r *recvBufferReader) readClient(p []byte) (n int, err error) {
187 // If the context is canceled, then closes the stream with nil metadata.
188 // closeStream writes its error parameter to r.recv as a recvMsg.
189 // r.readAdditional acts on that message and returns the necessary error.
190 select {
191 case <-r.ctxDone:
192 // Note that this adds the ctx error to the end of recv buffer, and
193 // reads from the head. This will delay the error until recv buffer is
194 // empty, thus will delay ctx cancellation in Recv().
195 //
196 // It's done this way to fix a race between ctx cancel and trailer. The
197 // race was, stream.Recv() may return ctx error if ctxDone wins the
198 // race, but stream.Trailer() may return a non-nil md because the stream
199 // was not marked as done when trailer is received. This closeStream
200 // call will mark stream as done, thus fix the race.
201 //
202 // TODO: delaying ctx error seems like a unnecessary side effect. What
203 // we really want is to mark the stream as done, and return ctx error
204 // faster.
205 r.closeStream(ContextErr(r.ctx.Err()))
206 m := <-r.recv.get()
207 return r.readAdditional(m, p)
208 case m := <-r.recv.get():
209 return r.readAdditional(m, p)
210 }
211}
212
213func (r *recvBufferReader) readAdditional(m recvMsg, p []byte) (n int, err error) {
214 r.recv.load()
215 if m.err != nil {
216 return 0, m.err
217 }
218 copied, _ := m.buffer.Read(p)
219 if m.buffer.Len() == 0 {
220 r.freeBuffer(m.buffer)
221 r.last = nil
222 } else {
223 r.last = m.buffer
224 }
225 return copied, nil
226}
227
228type streamState uint32
229
230const (
231 streamActive streamState = iota
232 streamWriteDone // EndStream sent
233 streamReadDone // EndStream received
234 streamDone // the entire stream is finished.
235)
236
237// Stream represents an RPC in the transport layer.
238type Stream struct {
239 id uint32
240 st ServerTransport // nil for client side Stream
241 ct *http2Client // nil for server side Stream
242 ctx context.Context // the associated context of the stream
243 cancel context.CancelFunc // always nil for client side Stream
244 done chan struct{} // closed at the end of stream to unblock writers. On the client side.
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100245 doneFunc func() // invoked at the end of stream on client side.
kesavand2cde6582020-06-22 04:56:23 -0400246 ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance)
247 method string // the associated RPC method of the stream
248 recvCompress string
249 sendCompress string
250 buf *recvBuffer
251 trReader io.Reader
252 fc *inFlow
253 wq *writeQuota
254
255 // Callback to state application's intentions to read data. This
256 // is used to adjust flow control, if needed.
257 requestRead func(int)
258
259 headerChan chan struct{} // closed to indicate the end of header metadata.
260 headerChanClosed uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times.
261 // headerValid indicates whether a valid header was received. Only
262 // meaningful after headerChan is closed (always call waitOnHeader() before
263 // reading its value). Not valid on server side.
264 headerValid bool
265
266 // hdrMu protects header and trailer metadata on the server-side.
267 hdrMu sync.Mutex
268 // On client side, header keeps the received header metadata.
269 //
270 // On server side, header keeps the header set by SetHeader(). The complete
271 // header will merged into this after t.WriteHeader() is called.
272 header metadata.MD
273 trailer metadata.MD // the key-value map of trailer metadata.
274
275 noHeaders bool // set if the client never received headers (set only after the stream is done).
276
277 // On the server-side, headerSent is atomically set to 1 when the headers are sent out.
278 headerSent uint32
279
280 state streamState
281
282 // On client-side it is the status error received from the server.
283 // On server-side it is unused.
284 status *status.Status
285
286 bytesReceived uint32 // indicates whether any bytes have been received on this stream
287 unprocessed uint32 // set if the server sends a refused stream or GOAWAY including this stream
288
289 // contentSubtype is the content-subtype for requests.
290 // this must be lowercase or the behavior is undefined.
291 contentSubtype string
292}
293
294// isHeaderSent is only valid on the server-side.
295func (s *Stream) isHeaderSent() bool {
296 return atomic.LoadUint32(&s.headerSent) == 1
297}
298
299// updateHeaderSent updates headerSent and returns true
300// if it was alreay set. It is valid only on server-side.
301func (s *Stream) updateHeaderSent() bool {
302 return atomic.SwapUint32(&s.headerSent, 1) == 1
303}
304
305func (s *Stream) swapState(st streamState) streamState {
306 return streamState(atomic.SwapUint32((*uint32)(&s.state), uint32(st)))
307}
308
309func (s *Stream) compareAndSwapState(oldState, newState streamState) bool {
310 return atomic.CompareAndSwapUint32((*uint32)(&s.state), uint32(oldState), uint32(newState))
311}
312
313func (s *Stream) getState() streamState {
314 return streamState(atomic.LoadUint32((*uint32)(&s.state)))
315}
316
317func (s *Stream) waitOnHeader() {
318 if s.headerChan == nil {
319 // On the server headerChan is always nil since a stream originates
320 // only after having received headers.
321 return
322 }
323 select {
324 case <-s.ctx.Done():
325 // Close the stream to prevent headers/trailers from changing after
326 // this function returns.
327 s.ct.CloseStream(s, ContextErr(s.ctx.Err()))
328 // headerChan could possibly not be closed yet if closeStream raced
329 // with operateHeaders; wait until it is closed explicitly here.
330 <-s.headerChan
331 case <-s.headerChan:
332 }
333}
334
335// RecvCompress returns the compression algorithm applied to the inbound
336// message. It is empty string if there is no compression applied.
337func (s *Stream) RecvCompress() string {
338 s.waitOnHeader()
339 return s.recvCompress
340}
341
342// SetSendCompress sets the compression algorithm to the stream.
343func (s *Stream) SetSendCompress(str string) {
344 s.sendCompress = str
345}
346
347// Done returns a channel which is closed when it receives the final status
348// from the server.
349func (s *Stream) Done() <-chan struct{} {
350 return s.done
351}
352
353// Header returns the header metadata of the stream.
354//
355// On client side, it acquires the key-value pairs of header metadata once it is
356// available. It blocks until i) the metadata is ready or ii) there is no header
357// metadata or iii) the stream is canceled/expired.
358//
359// On server side, it returns the out header after t.WriteHeader is called. It
360// does not block and must not be called until after WriteHeader.
361func (s *Stream) Header() (metadata.MD, error) {
362 if s.headerChan == nil {
363 // On server side, return the header in stream. It will be the out
364 // header after t.WriteHeader is called.
365 return s.header.Copy(), nil
366 }
367 s.waitOnHeader()
368 if !s.headerValid {
369 return nil, s.status.Err()
370 }
371 return s.header.Copy(), nil
372}
373
374// TrailersOnly blocks until a header or trailers-only frame is received and
375// then returns true if the stream was trailers-only. If the stream ends
376// before headers are received, returns true, nil. Client-side only.
377func (s *Stream) TrailersOnly() bool {
378 s.waitOnHeader()
379 return s.noHeaders
380}
381
382// Trailer returns the cached trailer metedata. Note that if it is not called
383// after the entire stream is done, it could return an empty MD. Client
384// side only.
385// It can be safely read only after stream has ended that is either read
386// or write have returned io.EOF.
387func (s *Stream) Trailer() metadata.MD {
388 c := s.trailer.Copy()
389 return c
390}
391
392// ContentSubtype returns the content-subtype for a request. For example, a
393// content-subtype of "proto" will result in a content-type of
394// "application/grpc+proto". This will always be lowercase. See
395// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
396// more details.
397func (s *Stream) ContentSubtype() string {
398 return s.contentSubtype
399}
400
401// Context returns the context of the stream.
402func (s *Stream) Context() context.Context {
403 return s.ctx
404}
405
406// Method returns the method for the stream.
407func (s *Stream) Method() string {
408 return s.method
409}
410
411// Status returns the status received from the server.
412// Status can be read safely only after the stream has ended,
413// that is, after Done() is closed.
414func (s *Stream) Status() *status.Status {
415 return s.status
416}
417
418// SetHeader sets the header metadata. This can be called multiple times.
419// Server side only.
420// This should not be called in parallel to other data writes.
421func (s *Stream) SetHeader(md metadata.MD) error {
422 if md.Len() == 0 {
423 return nil
424 }
425 if s.isHeaderSent() || s.getState() == streamDone {
426 return ErrIllegalHeaderWrite
427 }
428 s.hdrMu.Lock()
429 s.header = metadata.Join(s.header, md)
430 s.hdrMu.Unlock()
431 return nil
432}
433
434// SendHeader sends the given header metadata. The given metadata is
435// combined with any metadata set by previous calls to SetHeader and
436// then written to the transport stream.
437func (s *Stream) SendHeader(md metadata.MD) error {
438 return s.st.WriteHeader(s, md)
439}
440
441// SetTrailer sets the trailer metadata which will be sent with the RPC status
442// by the server. This can be called multiple times. Server side only.
443// This should not be called parallel to other data writes.
444func (s *Stream) SetTrailer(md metadata.MD) error {
445 if md.Len() == 0 {
446 return nil
447 }
448 if s.getState() == streamDone {
449 return ErrIllegalHeaderWrite
450 }
451 s.hdrMu.Lock()
452 s.trailer = metadata.Join(s.trailer, md)
453 s.hdrMu.Unlock()
454 return nil
455}
456
457func (s *Stream) write(m recvMsg) {
458 s.buf.put(m)
459}
460
461// Read reads all p bytes from the wire for this stream.
462func (s *Stream) Read(p []byte) (n int, err error) {
463 // Don't request a read if there was an error earlier
464 if er := s.trReader.(*transportReader).er; er != nil {
465 return 0, er
466 }
467 s.requestRead(len(p))
468 return io.ReadFull(s.trReader, p)
469}
470
471// tranportReader reads all the data available for this Stream from the transport and
472// passes them into the decoder, which converts them into a gRPC message stream.
473// The error is io.EOF when the stream is done or another non-nil error if
474// the stream broke.
475type transportReader struct {
476 reader io.Reader
477 // The handler to control the window update procedure for both this
478 // particular stream and the associated transport.
479 windowHandler func(int)
480 er error
481}
482
483func (t *transportReader) Read(p []byte) (n int, err error) {
484 n, err = t.reader.Read(p)
485 if err != nil {
486 t.er = err
487 return
488 }
489 t.windowHandler(n)
490 return
491}
492
493// BytesReceived indicates whether any bytes have been received on this stream.
494func (s *Stream) BytesReceived() bool {
495 return atomic.LoadUint32(&s.bytesReceived) == 1
496}
497
498// Unprocessed indicates whether the server did not process this stream --
499// i.e. it sent a refused stream or GOAWAY including this stream ID.
500func (s *Stream) Unprocessed() bool {
501 return atomic.LoadUint32(&s.unprocessed) == 1
502}
503
504// GoString is implemented by Stream so context.String() won't
505// race when printing %#v.
506func (s *Stream) GoString() string {
507 return fmt.Sprintf("<stream: %p, %v>", s, s.method)
508}
509
510// state of transport
511type transportState int
512
513const (
514 reachable transportState = iota
515 closing
516 draining
517)
518
519// ServerConfig consists of all the configurations to establish a server transport.
520type ServerConfig struct {
521 MaxStreams uint32
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100522 ConnectionTimeout time.Duration
523 Credentials credentials.TransportCredentials
kesavand2cde6582020-06-22 04:56:23 -0400524 InTapHandle tap.ServerInHandle
525 StatsHandler stats.Handler
526 KeepaliveParams keepalive.ServerParameters
527 KeepalivePolicy keepalive.EnforcementPolicy
528 InitialWindowSize int32
529 InitialConnWindowSize int32
530 WriteBufferSize int
531 ReadBufferSize int
532 ChannelzParentID int64
533 MaxHeaderListSize *uint32
534 HeaderTableSize *uint32
535}
536
kesavand2cde6582020-06-22 04:56:23 -0400537// ConnectOptions covers all relevant options for communicating with the server.
538type ConnectOptions struct {
539 // UserAgent is the application user agent.
540 UserAgent string
541 // Dialer specifies how to dial a network address.
542 Dialer func(context.Context, string) (net.Conn, error)
543 // FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors.
544 FailOnNonTempDialError bool
545 // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs.
546 PerRPCCredentials []credentials.PerRPCCredentials
547 // TransportCredentials stores the Authenticator required to setup a client
548 // connection. Only one of TransportCredentials and CredsBundle is non-nil.
549 TransportCredentials credentials.TransportCredentials
550 // CredsBundle is the credentials bundle to be used. Only one of
551 // TransportCredentials and CredsBundle is non-nil.
552 CredsBundle credentials.Bundle
553 // KeepaliveParams stores the keepalive parameters.
554 KeepaliveParams keepalive.ClientParameters
555 // StatsHandler stores the handler for stats.
556 StatsHandler stats.Handler
557 // InitialWindowSize sets the initial window size for a stream.
558 InitialWindowSize int32
559 // InitialConnWindowSize sets the initial window size for a connection.
560 InitialConnWindowSize int32
561 // WriteBufferSize sets the size of write buffer which in turn determines how much data can be batched before it's written on the wire.
562 WriteBufferSize int
563 // ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
564 ReadBufferSize int
565 // ChannelzParentID sets the addrConn id which initiate the creation of this client transport.
566 ChannelzParentID int64
567 // MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
568 MaxHeaderListSize *uint32
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100569 // UseProxy specifies if a proxy should be used.
570 UseProxy bool
kesavand2cde6582020-06-22 04:56:23 -0400571}
572
573// NewClientTransport establishes the transport with the required ConnectOptions
574// and returns it to the caller.
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100575func NewClientTransport(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) {
576 return newHTTP2Client(connectCtx, ctx, addr, opts, onPrefaceReceipt, onGoAway, onClose)
kesavand2cde6582020-06-22 04:56:23 -0400577}
578
579// Options provides additional hints and information for message
580// transmission.
581type Options struct {
582 // Last indicates whether this write is the last piece for
583 // this stream.
584 Last bool
585}
586
587// CallHdr carries the information of a particular RPC.
588type CallHdr struct {
589 // Host specifies the peer's host.
590 Host string
591
592 // Method specifies the operation to perform.
593 Method string
594
595 // SendCompress specifies the compression algorithm applied on
596 // outbound message.
597 SendCompress string
598
599 // Creds specifies credentials.PerRPCCredentials for a call.
600 Creds credentials.PerRPCCredentials
601
602 // ContentSubtype specifies the content-subtype for a request. For example, a
603 // content-subtype of "proto" will result in a content-type of
604 // "application/grpc+proto". The value of ContentSubtype must be all
605 // lowercase, otherwise the behavior is undefined. See
606 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
607 // for more details.
608 ContentSubtype string
609
610 PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100611
612 DoneFunc func() // called when the stream is finished
kesavand2cde6582020-06-22 04:56:23 -0400613}
614
615// ClientTransport is the common interface for all gRPC client-side transport
616// implementations.
617type ClientTransport interface {
618 // Close tears down this transport. Once it returns, the transport
619 // should not be accessed any more. The caller must make sure this
620 // is called only once.
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100621 Close(err error)
kesavand2cde6582020-06-22 04:56:23 -0400622
623 // GracefulClose starts to tear down the transport: the transport will stop
624 // accepting new RPCs and NewStream will return error. Once all streams are
625 // finished, the transport will close.
626 //
627 // It does not block.
628 GracefulClose()
629
630 // Write sends the data for the given stream. A nil stream indicates
631 // the write is to be performed on the transport as a whole.
632 Write(s *Stream, hdr []byte, data []byte, opts *Options) error
633
634 // NewStream creates a Stream for an RPC.
635 NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error)
636
637 // CloseStream clears the footprint of a stream when the stream is
638 // not needed any more. The err indicates the error incurred when
639 // CloseStream is called. Must be called when a stream is finished
640 // unless the associated transport is closing.
641 CloseStream(stream *Stream, err error)
642
643 // Error returns a channel that is closed when some I/O error
644 // happens. Typically the caller should have a goroutine to monitor
645 // this in order to take action (e.g., close the current transport
646 // and create a new one) in error case. It should not return nil
647 // once the transport is initiated.
648 Error() <-chan struct{}
649
650 // GoAway returns a channel that is closed when ClientTransport
651 // receives the draining signal from the server (e.g., GOAWAY frame in
652 // HTTP/2).
653 GoAway() <-chan struct{}
654
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100655 // GetGoAwayReason returns the reason why GoAway frame was received, along
656 // with a human readable string with debug info.
657 GetGoAwayReason() (GoAwayReason, string)
kesavand2cde6582020-06-22 04:56:23 -0400658
659 // RemoteAddr returns the remote network address.
660 RemoteAddr() net.Addr
661
662 // IncrMsgSent increments the number of message sent through this transport.
663 IncrMsgSent()
664
665 // IncrMsgRecv increments the number of message received through this transport.
666 IncrMsgRecv()
667}
668
669// ServerTransport is the common interface for all gRPC server-side transport
670// implementations.
671//
672// Methods may be called concurrently from multiple goroutines, but
673// Write methods for a given Stream will be called serially.
674type ServerTransport interface {
675 // HandleStreams receives incoming streams using the given handler.
676 HandleStreams(func(*Stream), func(context.Context, string) context.Context)
677
678 // WriteHeader sends the header metadata for the given stream.
679 // WriteHeader may not be called on all streams.
680 WriteHeader(s *Stream, md metadata.MD) error
681
682 // Write sends the data for the given stream.
683 // Write may not be called on all streams.
684 Write(s *Stream, hdr []byte, data []byte, opts *Options) error
685
686 // WriteStatus sends the status of a stream to the client. WriteStatus is
687 // the final call made on a stream and always occurs.
688 WriteStatus(s *Stream, st *status.Status) error
689
690 // Close tears down the transport. Once it is called, the transport
691 // should not be accessed any more. All the pending streams and their
692 // handlers will be terminated asynchronously.
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100693 Close()
kesavand2cde6582020-06-22 04:56:23 -0400694
695 // RemoteAddr returns the remote network address.
696 RemoteAddr() net.Addr
697
698 // Drain notifies the client this ServerTransport stops accepting new RPCs.
699 Drain()
700
701 // IncrMsgSent increments the number of message sent through this transport.
702 IncrMsgSent()
703
704 // IncrMsgRecv increments the number of message received through this transport.
705 IncrMsgRecv()
706}
707
708// connectionErrorf creates an ConnectionError with the specified error description.
709func connectionErrorf(temp bool, e error, format string, a ...interface{}) ConnectionError {
710 return ConnectionError{
711 Desc: fmt.Sprintf(format, a...),
712 temp: temp,
713 err: e,
714 }
715}
716
717// ConnectionError is an error that results in the termination of the
718// entire connection and the retry of all the active streams.
719type ConnectionError struct {
720 Desc string
721 temp bool
722 err error
723}
724
725func (e ConnectionError) Error() string {
726 return fmt.Sprintf("connection error: desc = %q", e.Desc)
727}
728
729// Temporary indicates if this connection error is temporary or fatal.
730func (e ConnectionError) Temporary() bool {
731 return e.temp
732}
733
734// Origin returns the original error of this connection error.
735func (e ConnectionError) Origin() error {
736 // Never return nil error here.
737 // If the original error is nil, return itself.
738 if e.err == nil {
739 return e
740 }
741 return e.err
742}
743
744var (
745 // ErrConnClosing indicates that the transport is closing.
746 ErrConnClosing = connectionErrorf(true, nil, "transport is closing")
747 // errStreamDrain indicates that the stream is rejected because the
748 // connection is draining. This could be caused by goaway or balancer
749 // removing the address.
750 errStreamDrain = status.Error(codes.Unavailable, "the connection is draining")
751 // errStreamDone is returned from write at the client side to indiacte application
752 // layer of an error.
753 errStreamDone = errors.New("the stream is done")
754 // StatusGoAway indicates that the server sent a GOAWAY that included this
755 // stream's ID in unprocessed RPCs.
756 statusGoAway = status.New(codes.Unavailable, "the stream is rejected because server is draining the connection")
757)
758
759// GoAwayReason contains the reason for the GoAway frame received.
760type GoAwayReason uint8
761
762const (
763 // GoAwayInvalid indicates that no GoAway frame is received.
764 GoAwayInvalid GoAwayReason = 0
765 // GoAwayNoReason is the default value when GoAway frame is received.
766 GoAwayNoReason GoAwayReason = 1
767 // GoAwayTooManyPings indicates that a GoAway frame with
768 // ErrCodeEnhanceYourCalm was received and that the debug data said
769 // "too_many_pings".
770 GoAwayTooManyPings GoAwayReason = 2
771)
772
773// channelzData is used to store channelz related data for http2Client and http2Server.
774// These fields cannot be embedded in the original structs (e.g. http2Client), since to do atomic
775// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
776// Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
777type channelzData struct {
778 kpCount int64
779 // The number of streams that have started, including already finished ones.
780 streamsStarted int64
781 // Client side: The number of streams that have ended successfully by receiving
782 // EoS bit set frame from server.
783 // Server side: The number of streams that have ended successfully by sending
784 // frame with EoS bit set.
785 streamsSucceeded int64
786 streamsFailed int64
787 // lastStreamCreatedTime stores the timestamp that the last stream gets created. It is of int64 type
788 // instead of time.Time since it's more costly to atomically update time.Time variable than int64
789 // variable. The same goes for lastMsgSentTime and lastMsgRecvTime.
790 lastStreamCreatedTime int64
791 msgSent int64
792 msgRecv int64
793 lastMsgSentTime int64
794 lastMsgRecvTime int64
795}
796
797// ContextErr converts the error from context package into a status error.
798func ContextErr(err error) error {
799 switch err {
800 case context.DeadlineExceeded:
801 return status.Error(codes.DeadlineExceeded, err.Error())
802 case context.Canceled:
803 return status.Error(codes.Canceled, err.Error())
804 }
805 return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
806}