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