gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/grpc/rpc_util.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 grpc 20 21 import ( 22 "bytes" 23 "compress/gzip" 24 "context" 25 "encoding/binary" 26 "fmt" 27 "io" 28 "io/ioutil" 29 "math" 30 "strings" 31 "sync" 32 "time" 33 34 "gitee.com/zhaochuninhefei/gmgo/grpc/codes" 35 "gitee.com/zhaochuninhefei/gmgo/grpc/credentials" 36 "gitee.com/zhaochuninhefei/gmgo/grpc/encoding" 37 "gitee.com/zhaochuninhefei/gmgo/grpc/encoding/proto" 38 "gitee.com/zhaochuninhefei/gmgo/grpc/internal/transport" 39 "gitee.com/zhaochuninhefei/gmgo/grpc/metadata" 40 "gitee.com/zhaochuninhefei/gmgo/grpc/peer" 41 "gitee.com/zhaochuninhefei/gmgo/grpc/stats" 42 "gitee.com/zhaochuninhefei/gmgo/grpc/status" 43 ) 44 45 // Compressor defines the interface gRPC uses to compress a message. 46 // 47 // To Deprecated: use package encoding. 48 type Compressor interface { 49 // Do compresses p into w. 50 Do(w io.Writer, p []byte) error 51 // Type returns the compression algorithm the Compressor uses. 52 Type() string 53 } 54 55 type gzipCompressor struct { 56 pool sync.Pool 57 } 58 59 // NewGZIPCompressor creates a Compressor based on GZIP. 60 // 61 // To Deprecated: use package encoding/gzip. 62 func NewGZIPCompressor() Compressor { 63 c, _ := NewGZIPCompressorWithLevel(gzip.DefaultCompression) 64 return c 65 } 66 67 // NewGZIPCompressorWithLevel is like NewGZIPCompressor but specifies the gzip compression level instead 68 // of assuming DefaultCompression. 69 // 70 // The error returned will be nil if the level is valid. 71 // 72 // To Deprecated: use package encoding/gzip. 73 func NewGZIPCompressorWithLevel(level int) (Compressor, error) { 74 if level < gzip.DefaultCompression || level > gzip.BestCompression { 75 return nil, fmt.Errorf("grpc: invalid compression level: %d", level) 76 } 77 return &gzipCompressor{ 78 pool: sync.Pool{ 79 New: func() interface{} { 80 w, err := gzip.NewWriterLevel(ioutil.Discard, level) 81 if err != nil { 82 panic(err) 83 } 84 return w 85 }, 86 }, 87 }, nil 88 } 89 90 func (c *gzipCompressor) Do(w io.Writer, p []byte) error { 91 z := c.pool.Get().(*gzip.Writer) 92 defer c.pool.Put(z) 93 z.Reset(w) 94 if _, err := z.Write(p); err != nil { 95 return err 96 } 97 return z.Close() 98 } 99 100 func (c *gzipCompressor) Type() string { 101 return "gzip" 102 } 103 104 // Decompressor defines the interface gRPC uses to decompress a message. 105 // 106 // To Deprecated: use package encoding. 107 type Decompressor interface { 108 // Do reads the data from r and uncompress them. 109 Do(r io.Reader) ([]byte, error) 110 // Type returns the compression algorithm the Decompressor uses. 111 Type() string 112 } 113 114 type gzipDecompressor struct { 115 pool sync.Pool 116 } 117 118 // NewGZIPDecompressor creates a Decompressor based on GZIP. 119 // 120 // To Deprecated: use package encoding/gzip. 121 func NewGZIPDecompressor() Decompressor { 122 return &gzipDecompressor{} 123 } 124 125 func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) { 126 var z *gzip.Reader 127 switch maybeZ := d.pool.Get().(type) { 128 case nil: 129 newZ, err := gzip.NewReader(r) 130 if err != nil { 131 return nil, err 132 } 133 z = newZ 134 case *gzip.Reader: 135 z = maybeZ 136 if err := z.Reset(r); err != nil { 137 d.pool.Put(z) 138 return nil, err 139 } 140 } 141 142 defer func() { 143 _ = z.Close() 144 d.pool.Put(z) 145 }() 146 return ioutil.ReadAll(z) 147 } 148 149 func (d *gzipDecompressor) Type() string { 150 return "gzip" 151 } 152 153 // callInfo contains all related configuration and information about an RPC. 154 type callInfo struct { 155 compressorType string 156 failFast bool 157 maxReceiveMessageSize *int 158 maxSendMessageSize *int 159 creds credentials.PerRPCCredentials 160 contentSubtype string 161 codec baseCodec 162 maxRetryRPCBufferSize int 163 } 164 165 func defaultCallInfo() *callInfo { 166 return &callInfo{ 167 failFast: true, 168 maxRetryRPCBufferSize: 256 * 1024, // 256KB 169 } 170 } 171 172 // CallOption configures a Call before it starts or extracts information from 173 // a Call after it completes. 174 type CallOption interface { 175 // before is called before the call is sent to any server. If before 176 // returns a non-nil error, the RPC fails with that error. 177 before(*callInfo) error 178 179 // after is called after the call has completed. after cannot return an 180 // error, so any failures should be reported via output parameters. 181 after(*callInfo, *csAttempt) 182 } 183 184 // EmptyCallOption does not alter the Call configuration. 185 // It can be embedded in another structure to carry satellite data for use 186 // by interceptors. 187 type EmptyCallOption struct{} 188 189 func (EmptyCallOption) before(*callInfo) error { return nil } 190 func (EmptyCallOption) after(*callInfo, *csAttempt) {} 191 192 // Header returns a CallOptions that retrieves the header metadata 193 // for a unary RPC. 194 func Header(md *metadata.MD) CallOption { 195 return HeaderCallOption{HeaderAddr: md} 196 } 197 198 // HeaderCallOption is a CallOption for collecting response header metadata. 199 // The metadata field will be populated *after* the RPC completes. 200 // 201 // Experimental 202 // 203 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 204 // later release. 205 type HeaderCallOption struct { 206 HeaderAddr *metadata.MD 207 } 208 209 //goland:noinspection GoUnusedParameter 210 func (o HeaderCallOption) before(c *callInfo) error { return nil } 211 212 //goland:noinspection GoUnusedParameter 213 func (o HeaderCallOption) after(c *callInfo, attempt *csAttempt) { 214 *o.HeaderAddr, _ = attempt.s.Header() 215 } 216 217 // Trailer returns a CallOptions that retrieves the trailer metadata 218 // for a unary RPC. 219 func Trailer(md *metadata.MD) CallOption { 220 return TrailerCallOption{TrailerAddr: md} 221 } 222 223 // TrailerCallOption is a CallOption for collecting response trailer metadata. 224 // The metadata field will be populated *after* the RPC completes. 225 // 226 // Experimental 227 // 228 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 229 // later release. 230 type TrailerCallOption struct { 231 TrailerAddr *metadata.MD 232 } 233 234 //goland:noinspection GoUnusedParameter 235 func (o TrailerCallOption) before(c *callInfo) error { return nil } 236 237 //goland:noinspection GoUnusedParameter 238 func (o TrailerCallOption) after(c *callInfo, attempt *csAttempt) { 239 *o.TrailerAddr = attempt.s.Trailer() 240 } 241 242 // Peer returns a CallOption that retrieves peer information for a unary RPC. 243 // The peer field will be populated *after* the RPC completes. 244 func Peer(p *peer.Peer) CallOption { 245 return PeerCallOption{PeerAddr: p} 246 } 247 248 // PeerCallOption is a CallOption for collecting the identity of the remote 249 // peer. The peer field will be populated *after* the RPC completes. 250 // 251 // Experimental 252 // 253 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 254 // later release. 255 type PeerCallOption struct { 256 PeerAddr *peer.Peer 257 } 258 259 //goland:noinspection GoUnusedParameter 260 func (o PeerCallOption) before(c *callInfo) error { return nil } 261 262 //goland:noinspection GoUnusedParameter 263 func (o PeerCallOption) after(c *callInfo, attempt *csAttempt) { 264 if x, ok := peer.FromContext(attempt.s.Context()); ok { 265 *o.PeerAddr = *x 266 } 267 } 268 269 // WaitForReady configures the action to take when an RPC is attempted on broken 270 // connections or unreachable servers. If waitForReady is false and the 271 // connection is in the TRANSIENT_FAILURE state, the RPC will fail 272 // immediately. Otherwise, the RPC client will block the call until a 273 // connection is available (or the call is canceled or times out) and will 274 // retry the call if it fails due to a transient error. gRPC will not retry if 275 // data was written to the wire unless the server indicates it did not process 276 // the data. Please refer to 277 // https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. 278 // 279 // By default, RPCs don't "wait for ready". 280 func WaitForReady(waitForReady bool) CallOption { 281 return FailFastCallOption{FailFast: !waitForReady} 282 } 283 284 // FailFast is the opposite of WaitForReady. 285 // 286 // To Deprecated: use WaitForReady. 287 func FailFast(failFast bool) CallOption { 288 return FailFastCallOption{FailFast: failFast} 289 } 290 291 // FailFastCallOption is a CallOption for indicating whether an RPC should fail 292 // fast or not. 293 // 294 // Experimental 295 // 296 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 297 // later release. 298 type FailFastCallOption struct { 299 FailFast bool 300 } 301 302 func (o FailFastCallOption) before(c *callInfo) error { 303 c.failFast = o.FailFast 304 return nil 305 } 306 307 //goland:noinspection GoUnusedParameter 308 func (o FailFastCallOption) after(c *callInfo, attempt *csAttempt) {} 309 310 // MaxCallRecvMsgSize returns a CallOption which sets the maximum message size 311 // in bytes the client can receive. 312 func MaxCallRecvMsgSize(bytes int) CallOption { 313 return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: bytes} 314 } 315 316 // MaxRecvMsgSizeCallOption is a CallOption that indicates the maximum message 317 // size in bytes the client can receive. 318 // 319 // Experimental 320 // 321 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 322 // later release. 323 type MaxRecvMsgSizeCallOption struct { 324 MaxRecvMsgSize int 325 } 326 327 func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error { 328 c.maxReceiveMessageSize = &o.MaxRecvMsgSize 329 return nil 330 } 331 332 //goland:noinspection GoUnusedParameter 333 func (o MaxRecvMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {} 334 335 // MaxCallSendMsgSize returns a CallOption which sets the maximum message size 336 // in bytes the client can send. 337 func MaxCallSendMsgSize(bytes int) CallOption { 338 return MaxSendMsgSizeCallOption{MaxSendMsgSize: bytes} 339 } 340 341 // MaxSendMsgSizeCallOption is a CallOption that indicates the maximum message 342 // size in bytes the client can send. 343 // 344 // Experimental 345 // 346 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 347 // later release. 348 type MaxSendMsgSizeCallOption struct { 349 MaxSendMsgSize int 350 } 351 352 func (o MaxSendMsgSizeCallOption) before(c *callInfo) error { 353 c.maxSendMessageSize = &o.MaxSendMsgSize 354 return nil 355 } 356 357 //goland:noinspection GoUnusedParameter 358 func (o MaxSendMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {} 359 360 // PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials 361 // for a call. 362 func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption { 363 return PerRPCCredsCallOption{Creds: creds} 364 } 365 366 // PerRPCCredsCallOption is a CallOption that indicates the per-RPC 367 // credentials to use for the call. 368 // 369 // Experimental 370 // 371 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 372 // later release. 373 type PerRPCCredsCallOption struct { 374 Creds credentials.PerRPCCredentials 375 } 376 377 func (o PerRPCCredsCallOption) before(c *callInfo) error { 378 c.creds = o.Creds 379 return nil 380 } 381 382 //goland:noinspection GoUnusedParameter 383 func (o PerRPCCredsCallOption) after(c *callInfo, attempt *csAttempt) {} 384 385 // UseCompressor returns a CallOption which sets the compressor used when 386 // sending the request. If WithCompressor is also set, UseCompressor has 387 // higher priority. 388 // 389 // Experimental 390 // 391 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 392 // later release. 393 func UseCompressor(name string) CallOption { 394 return CompressorCallOption{CompressorType: name} 395 } 396 397 // CompressorCallOption is a CallOption that indicates the compressor to use. 398 // 399 // Experimental 400 // 401 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 402 // later release. 403 type CompressorCallOption struct { 404 CompressorType string 405 } 406 407 func (o CompressorCallOption) before(c *callInfo) error { 408 c.compressorType = o.CompressorType 409 return nil 410 } 411 412 //goland:noinspection GoUnusedParameter 413 func (o CompressorCallOption) after(c *callInfo, attempt *csAttempt) {} 414 415 // CallContentSubtype returns a CallOption that will set the content-subtype 416 // for a call. For example, if content-subtype is "json", the Content-Type over 417 // the wire will be "application/grpc+json". The content-subtype is converted 418 // to lowercase before being included in Content-Type. See Content-Type on 419 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for 420 // more details. 421 // 422 // If ForceCodec is not also used, the content-subtype will be used to look up 423 // the Codec to use in the registry controlled by RegisterCodec. See the 424 // documentation on RegisterCodec for details on registration. The lookup of 425 // content-subtype is case-insensitive. If no such Codec is found, the call 426 // will result in an error with code codes.Internal. 427 // 428 // If ForceCodec is also used, that Codec will be used for all request and 429 // response messages, with the content-subtype set to the given contentSubtype 430 // here for requests. 431 func CallContentSubtype(contentSubtype string) CallOption { 432 return ContentSubtypeCallOption{ContentSubtype: strings.ToLower(contentSubtype)} 433 } 434 435 // ContentSubtypeCallOption is a CallOption that indicates the content-subtype 436 // used for marshaling messages. 437 // 438 // Experimental 439 // 440 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 441 // later release. 442 type ContentSubtypeCallOption struct { 443 ContentSubtype string 444 } 445 446 func (o ContentSubtypeCallOption) before(c *callInfo) error { 447 c.contentSubtype = o.ContentSubtype 448 return nil 449 } 450 451 //goland:noinspection GoUnusedParameter 452 func (o ContentSubtypeCallOption) after(c *callInfo, attempt *csAttempt) {} 453 454 // ForceCodec returns a CallOption that will set codec to be used for all 455 // request and response messages for a call. The result of calling Name() will 456 // be used as the content-subtype after converting to lowercase, unless 457 // CallContentSubtype is also used. 458 // 459 // See Content-Type on 460 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for 461 // more details. Also see the documentation on RegisterCodec and 462 // CallContentSubtype for more details on the interaction between Codec and 463 // content-subtype. 464 // 465 // This function is provided for advanced users; prefer to use only 466 // CallContentSubtype to select a registered codec instead. 467 // 468 // Experimental 469 // 470 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 471 // later release. 472 func ForceCodec(codec encoding.Codec) CallOption { 473 return ForceCodecCallOption{Codec: codec} 474 } 475 476 // ForceCodecCallOption is a CallOption that indicates the codec used for 477 // marshaling messages. 478 // 479 // Experimental 480 // 481 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 482 // later release. 483 type ForceCodecCallOption struct { 484 Codec encoding.Codec 485 } 486 487 func (o ForceCodecCallOption) before(c *callInfo) error { 488 c.codec = o.Codec 489 return nil 490 } 491 492 //goland:noinspection GoUnusedParameter 493 func (o ForceCodecCallOption) after(c *callInfo, attempt *csAttempt) {} 494 495 // CallCustomCodec behaves like ForceCodec, but accepts a grpc.Codec instead of 496 // an encoding.Codec. 497 // 498 // To Deprecated: use ForceCodec instead. 499 func CallCustomCodec(codec encoding.Codec) CallOption { 500 return CustomCodecCallOption{Codec: codec} 501 } 502 503 // CustomCodecCallOption is a CallOption that indicates the codec used for 504 // marshaling messages. 505 // 506 // Experimental 507 // 508 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 509 // later release. 510 type CustomCodecCallOption struct { 511 Codec encoding.Codec 512 } 513 514 func (o CustomCodecCallOption) before(c *callInfo) error { 515 c.codec = o.Codec 516 return nil 517 } 518 519 //goland:noinspection GoUnusedParameter 520 func (o CustomCodecCallOption) after(c *callInfo, attempt *csAttempt) {} 521 522 // MaxRetryRPCBufferSize returns a CallOption that limits the amount of memory 523 // used for buffering this RPC's requests for retry purposes. 524 // 525 // Experimental 526 // 527 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 528 // later release. 529 func MaxRetryRPCBufferSize(bytes int) CallOption { 530 return MaxRetryRPCBufferSizeCallOption{bytes} 531 } 532 533 // MaxRetryRPCBufferSizeCallOption is a CallOption indicating the amount of 534 // memory to be used for caching this RPC for retry purposes. 535 // 536 // Experimental 537 // 538 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 539 // later release. 540 type MaxRetryRPCBufferSizeCallOption struct { 541 MaxRetryRPCBufferSize int 542 } 543 544 func (o MaxRetryRPCBufferSizeCallOption) before(c *callInfo) error { 545 c.maxRetryRPCBufferSize = o.MaxRetryRPCBufferSize 546 return nil 547 } 548 549 //goland:noinspection GoUnusedParameter 550 func (o MaxRetryRPCBufferSizeCallOption) after(c *callInfo, attempt *csAttempt) {} 551 552 // The format of the payload: compressed or not? 553 type payloadFormat uint8 554 555 const ( 556 compressionNone payloadFormat = 0 // no compression 557 compressionMade payloadFormat = 1 // compressed 558 ) 559 560 // parser reads complete gRPC messages from the underlying reader. 561 type parser struct { 562 // r is the underlying reader. 563 // See the comment on recvMsg for the permissible 564 // error types. 565 r io.Reader 566 567 // The header of a gRPC message. Find more detail at 568 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md 569 header [5]byte 570 } 571 572 // recvMsg reads a complete gRPC message from the stream. 573 // 574 // It returns the message and its payload (compression/encoding) 575 // format. The caller owns the returned msg memory. 576 // 577 // If there is an error, possible values are: 578 // * io.EOF, when no messages remain 579 // * io.ErrUnexpectedEOF 580 // * of type transport.ConnectionError 581 // * an error from the status package 582 // No other error values or types must be returned, which also means 583 // that the underlying io.Reader must not return an incompatible 584 // error. 585 func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byte, err error) { 586 if _, err := p.r.Read(p.header[:]); err != nil { 587 return 0, nil, err 588 } 589 590 pf = payloadFormat(p.header[0]) 591 length := binary.BigEndian.Uint32(p.header[1:]) 592 593 if length == 0 { 594 return pf, nil, nil 595 } 596 if int64(length) > int64(maxInt) { 597 return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max length allowed on current machine (%d vs. %d)", length, maxInt) 598 } 599 if int(length) > maxReceiveMessageSize { 600 return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize) 601 } 602 // TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead 603 // of making it for each message: 604 msg = make([]byte, int(length)) 605 if _, err := p.r.Read(msg); err != nil { 606 if err == io.EOF { 607 err = io.ErrUnexpectedEOF 608 } 609 return 0, nil, err 610 } 611 return pf, msg, nil 612 } 613 614 // encode serializes msg and returns a buffer containing the message, or an 615 // error if it is too large to be transmitted by grpc. If msg is nil, it 616 // generates an empty message. 617 func encode(c baseCodec, msg interface{}) ([]byte, error) { 618 if msg == nil { // NOTE: typed nils will not be caught by this check 619 return nil, nil 620 } 621 b, err := c.Marshal(msg) 622 if err != nil { 623 return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error()) 624 } 625 if uint(len(b)) > math.MaxUint32 { 626 return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b)) 627 } 628 return b, nil 629 } 630 631 // compress returns the input bytes compressed by compressor or cp. If both 632 // compressors are nil, returns nil. 633 // 634 // TODO(dfawley): eliminate cp parameter by wrapping Compressor in an encoding.Compressor. 635 func compress(in []byte, cp Compressor, compressor encoding.Compressor) ([]byte, error) { 636 if compressor == nil && cp == nil { 637 return nil, nil 638 } 639 wrapErr := func(err error) error { 640 return status.Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error()) 641 } 642 cbuf := &bytes.Buffer{} 643 if compressor != nil { 644 z, err := compressor.Compress(cbuf) 645 if err != nil { 646 return nil, wrapErr(err) 647 } 648 if _, err := z.Write(in); err != nil { 649 return nil, wrapErr(err) 650 } 651 if err := z.Close(); err != nil { 652 return nil, wrapErr(err) 653 } 654 } else { 655 if err := cp.Do(cbuf, in); err != nil { 656 return nil, wrapErr(err) 657 } 658 } 659 return cbuf.Bytes(), nil 660 } 661 662 const ( 663 payloadLen = 1 664 sizeLen = 4 665 headerLen = payloadLen + sizeLen 666 ) 667 668 // msgHeader returns a 5-byte header for the message being transmitted and the 669 // payload, which is compData if non-nil or data otherwise. 670 func msgHeader(data, compData []byte) (hdr []byte, payload []byte) { 671 hdr = make([]byte, headerLen) 672 if compData != nil { 673 hdr[0] = byte(compressionMade) 674 data = compData 675 } else { 676 hdr[0] = byte(compressionNone) 677 } 678 679 // Write length of payload into buf 680 binary.BigEndian.PutUint32(hdr[payloadLen:], uint32(len(data))) 681 return hdr, data 682 } 683 684 func outPayload(client bool, msg interface{}, data, payload []byte, t time.Time) *stats.OutPayload { 685 return &stats.OutPayload{ 686 Client: client, 687 Payload: msg, 688 Data: data, 689 Length: len(data), 690 WireLength: len(payload) + headerLen, 691 SentTime: t, 692 } 693 } 694 695 func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool) *status.Status { 696 switch pf { 697 case compressionNone: 698 case compressionMade: 699 if recvCompress == "" || recvCompress == encoding.Identity { 700 return status.New(codes.Internal, "grpc: compressed flag set with identity or empty encoding") 701 } 702 if !haveCompressor { 703 return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) 704 } 705 default: 706 return status.Newf(codes.Internal, "grpc: received unexpected payload format %d", pf) 707 } 708 return nil 709 } 710 711 type payloadInfo struct { 712 wireLength int // The compressed length got from wire. 713 uncompressedBytes []byte 714 } 715 716 func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) ([]byte, error) { 717 pf, d, err := p.recvMsg(maxReceiveMessageSize) 718 if err != nil { 719 return nil, err 720 } 721 if payInfo != nil { 722 payInfo.wireLength = len(d) 723 } 724 725 if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil); st != nil { 726 return nil, st.Err() 727 } 728 729 var size int 730 if pf == compressionMade { 731 // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor, 732 // use this decompressor as the default. 733 if dc != nil { 734 d, err = dc.Do(bytes.NewReader(d)) 735 size = len(d) 736 } else { 737 d, size, err = decompress(compressor, d, maxReceiveMessageSize) 738 } 739 if err != nil { 740 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) 741 } 742 if size > maxReceiveMessageSize { 743 // TODO: Revisit the error code. Currently keep it consistent with java 744 // implementation. 745 return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) 746 } 747 } 748 return d, nil 749 } 750 751 // Using compressor, decompress d, returning data and size. 752 // Optionally, if data will be over maxReceiveMessageSize, just return the size. 753 func decompress(compressor encoding.Compressor, d []byte, maxReceiveMessageSize int) ([]byte, int, error) { 754 dcReader, err := compressor.Decompress(bytes.NewReader(d)) 755 if err != nil { 756 return nil, 0, err 757 } 758 if sizer, ok := compressor.(interface { 759 DecompressedSize(compressedBytes []byte) int 760 }); ok { 761 if size := sizer.DecompressedSize(d); size >= 0 { 762 if size > maxReceiveMessageSize { 763 return nil, size, nil 764 } 765 // size is used as an estimate to size the buffer, but we 766 // will read more data if available. 767 // +MinRead so ReadFrom will not reallocate if size is correct. 768 buf := bytes.NewBuffer(make([]byte, 0, size+bytes.MinRead)) 769 bytesRead, err := buf.ReadFrom(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) 770 return buf.Bytes(), int(bytesRead), err 771 } 772 } 773 // Read from LimitReader with limit max+1. So if the underlying 774 // reader is over limit, the result will be bigger than max. 775 d, err = ioutil.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) 776 return d, len(d), err 777 } 778 779 // For the two compressor parameters, both should not be set, but if they are, 780 // dc takes precedence over compressor. 781 // TODO(dfawley): wrap the old compressor/decompressor using the new API? 782 func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m interface{}, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) error { 783 d, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor) 784 if err != nil { 785 return err 786 } 787 if err := c.Unmarshal(d, m); err != nil { 788 return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) 789 } 790 if payInfo != nil { 791 payInfo.uncompressedBytes = d 792 } 793 return nil 794 } 795 796 // Information about RPC 797 type rpcInfo struct { 798 failfast bool 799 preloaderInfo *compressorInfo 800 } 801 802 // Information about Preloader 803 // Responsible for storing codec, and compressors 804 // If stream (s) has context s.Context which stores rpcInfo that has non nil 805 // pointers to codec, and compressors, then we can use preparedMsg for Async message prep 806 // and reuse marshalled bytes 807 type compressorInfo struct { 808 codec baseCodec 809 cp Compressor 810 comp encoding.Compressor 811 } 812 813 type rpcInfoContextKey struct{} 814 815 func newContextWithRPCInfo(ctx context.Context, failfast bool, codec baseCodec, cp Compressor, comp encoding.Compressor) context.Context { 816 return context.WithValue(ctx, rpcInfoContextKey{}, &rpcInfo{ 817 failfast: failfast, 818 preloaderInfo: &compressorInfo{ 819 codec: codec, 820 cp: cp, 821 comp: comp, 822 }, 823 }) 824 } 825 826 func rpcInfoFromContext(ctx context.Context) (s *rpcInfo, ok bool) { 827 s, ok = ctx.Value(rpcInfoContextKey{}).(*rpcInfo) 828 return 829 } 830 831 // Code returns the error code for err if it was produced by the rpc system. 832 // Otherwise, it returns codes.Unknown. 833 // 834 // Deprecated: use status.Code instead. 835 func Code(err error) codes.Code { 836 return status.Code(err) 837 } 838 839 // ErrorDesc returns the error description of err if it was produced by the rpc system. 840 // Otherwise, it returns err.Error() or empty string when err is nil. 841 // 842 // To Deprecated: use status.Convert and Message method instead. 843 func ErrorDesc(err error) string { 844 return status.Convert(err).Message() 845 } 846 847 // Errorf returns an error containing an error code and a description; 848 // Errorf returns nil if c is OK. 849 // 850 // Deprecated: use status.Errorf instead. 851 func Errorf(c codes.Code, format string, a ...interface{}) error { 852 return status.Errorf(c, format, a...) 853 } 854 855 // toRPCErr converts an error into an error from the status package. 856 //goland:noinspection GoDirectComparisonOfErrors,GoTypeAssertionOnErrors 857 func toRPCErr(err error) error { 858 switch err { 859 case nil, io.EOF: 860 return err 861 case context.DeadlineExceeded: 862 return status.Error(codes.DeadlineExceeded, err.Error()) 863 case context.Canceled: 864 return status.Error(codes.Canceled, err.Error()) 865 case io.ErrUnexpectedEOF: 866 return status.Error(codes.Internal, err.Error()) 867 } 868 869 switch e := err.(type) { 870 case transport.ConnectionError: 871 return status.Error(codes.Unavailable, e.Desc) 872 case *transport.NewStreamError: 873 return toRPCErr(e.Err) 874 } 875 876 if _, ok := status.FromError(err); ok { 877 return err 878 } 879 880 return status.Error(codes.Unknown, err.Error()) 881 } 882 883 // setCallInfoCodec should only be called after CallOptions have been applied. 884 func setCallInfoCodec(c *callInfo) error { 885 if c.codec != nil { 886 // codec was already set by a CallOption; use it, but set the content 887 // subtype if it is not set. 888 if c.contentSubtype == "" { 889 // c.codec is a baseCodec to hide the difference between grpc.Codec and 890 // encoding.Codec (Name vs. String method name). We only support 891 // setting content subtype from encoding.Codec to avoid a behavior 892 // change with the deprecated version. 893 if ec, ok := c.codec.(encoding.Codec); ok { 894 c.contentSubtype = strings.ToLower(ec.Name()) 895 } 896 } 897 return nil 898 } 899 900 if c.contentSubtype == "" { 901 // No codec specified in CallOptions; use proto by default. 902 c.codec = encoding.GetCodec(proto.Name) 903 return nil 904 } 905 906 // c.contentSubtype is already lowercased in CallContentSubtype 907 c.codec = encoding.GetCodec(c.contentSubtype) 908 if c.codec == nil { 909 return status.Errorf(codes.Internal, "no codec registered for content-subtype %s", c.contentSubtype) 910 } 911 return nil 912 } 913 914 // channelzData is used to store channelz related data for ClientConn, addrConn and Server. 915 // These fields cannot be embedded in the original structs (e.g. ClientConn), since to do atomic 916 // operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment. 917 // Here, by grouping those int64 fields inside a struct, we are enforcing the alignment. 918 type channelzData struct { 919 callsStarted int64 920 callsFailed int64 921 callsSucceeded int64 922 // lastCallStartedTime stores the timestamp that last call starts. It is of int64 type instead of 923 // time.Time since it's more costly to atomically update time.Time variable than int64 variable. 924 lastCallStartedTime int64 925 } 926 927 // The SupportPackageIsVersion variables are referenced from generated protocol 928 // buffer files to ensure compatibility with the gRPC version used. The latest 929 // support package version is 7. 930 // 931 // Older versions are kept for compatibility. 932 // 933 // These constants should not be referenced from any other code. 934 //goland:noinspection GoUnusedConst 935 const ( 936 SupportPackageIsVersion3 = true 937 SupportPackageIsVersion4 = true 938 SupportPackageIsVersion5 = true 939 SupportPackageIsVersion6 = true 940 SupportPackageIsVersion7 = true 941 ) 942 943 const grpcUA = "grpc-go/" + Version