google.golang.org/grpc@v1.74.2/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 "compress/gzip" 23 "context" 24 "encoding/binary" 25 "fmt" 26 "io" 27 "math" 28 "strings" 29 "sync" 30 "time" 31 32 "google.golang.org/grpc/codes" 33 "google.golang.org/grpc/credentials" 34 "google.golang.org/grpc/encoding" 35 "google.golang.org/grpc/encoding/proto" 36 "google.golang.org/grpc/internal/transport" 37 "google.golang.org/grpc/mem" 38 "google.golang.org/grpc/metadata" 39 "google.golang.org/grpc/peer" 40 "google.golang.org/grpc/stats" 41 "google.golang.org/grpc/status" 42 ) 43 44 // Compressor defines the interface gRPC uses to compress a message. 45 // 46 // Deprecated: use package encoding. 47 type Compressor interface { 48 // Do compresses p into w. 49 Do(w io.Writer, p []byte) error 50 // Type returns the compression algorithm the Compressor uses. 51 Type() string 52 } 53 54 type gzipCompressor struct { 55 pool sync.Pool 56 } 57 58 // NewGZIPCompressor creates a Compressor based on GZIP. 59 // 60 // Deprecated: use package encoding/gzip. 61 func NewGZIPCompressor() Compressor { 62 c, _ := NewGZIPCompressorWithLevel(gzip.DefaultCompression) 63 return c 64 } 65 66 // NewGZIPCompressorWithLevel is like NewGZIPCompressor but specifies the gzip compression level instead 67 // of assuming DefaultCompression. 68 // 69 // The error returned will be nil if the level is valid. 70 // 71 // Deprecated: use package encoding/gzip. 72 func NewGZIPCompressorWithLevel(level int) (Compressor, error) { 73 if level < gzip.DefaultCompression || level > gzip.BestCompression { 74 return nil, fmt.Errorf("grpc: invalid compression level: %d", level) 75 } 76 return &gzipCompressor{ 77 pool: sync.Pool{ 78 New: func() any { 79 w, err := gzip.NewWriterLevel(io.Discard, level) 80 if err != nil { 81 panic(err) 82 } 83 return w 84 }, 85 }, 86 }, nil 87 } 88 89 func (c *gzipCompressor) Do(w io.Writer, p []byte) error { 90 z := c.pool.Get().(*gzip.Writer) 91 defer c.pool.Put(z) 92 z.Reset(w) 93 if _, err := z.Write(p); err != nil { 94 return err 95 } 96 return z.Close() 97 } 98 99 func (c *gzipCompressor) Type() string { 100 return "gzip" 101 } 102 103 // Decompressor defines the interface gRPC uses to decompress a message. 104 // 105 // Deprecated: use package encoding. 106 type Decompressor interface { 107 // Do reads the data from r and uncompress them. 108 Do(r io.Reader) ([]byte, error) 109 // Type returns the compression algorithm the Decompressor uses. 110 Type() string 111 } 112 113 type gzipDecompressor struct { 114 pool sync.Pool 115 } 116 117 // NewGZIPDecompressor creates a Decompressor based on GZIP. 118 // 119 // Deprecated: use package encoding/gzip. 120 func NewGZIPDecompressor() Decompressor { 121 return &gzipDecompressor{} 122 } 123 124 func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) { 125 var z *gzip.Reader 126 switch maybeZ := d.pool.Get().(type) { 127 case nil: 128 newZ, err := gzip.NewReader(r) 129 if err != nil { 130 return nil, err 131 } 132 z = newZ 133 case *gzip.Reader: 134 z = maybeZ 135 if err := z.Reset(r); err != nil { 136 d.pool.Put(z) 137 return nil, err 138 } 139 } 140 141 defer func() { 142 z.Close() 143 d.pool.Put(z) 144 }() 145 return io.ReadAll(z) 146 } 147 148 func (d *gzipDecompressor) Type() string { 149 return "gzip" 150 } 151 152 // callInfo contains all related configuration and information about an RPC. 153 type callInfo struct { 154 compressorName string 155 failFast bool 156 maxReceiveMessageSize *int 157 maxSendMessageSize *int 158 creds credentials.PerRPCCredentials 159 contentSubtype string 160 codec baseCodec 161 maxRetryRPCBufferSize int 162 onFinish []func(err error) 163 authority string 164 } 165 166 func defaultCallInfo() *callInfo { 167 return &callInfo{ 168 failFast: true, 169 maxRetryRPCBufferSize: 256 * 1024, // 256KB 170 } 171 } 172 173 // CallOption configures a Call before it starts or extracts information from 174 // a Call after it completes. 175 type CallOption interface { 176 // before is called before the call is sent to any server. If before 177 // returns a non-nil error, the RPC fails with that error. 178 before(*callInfo) error 179 180 // after is called after the call has completed. after cannot return an 181 // error, so any failures should be reported via output parameters. 182 after(*callInfo, *csAttempt) 183 } 184 185 // EmptyCallOption does not alter the Call configuration. 186 // It can be embedded in another structure to carry satellite data for use 187 // by interceptors. 188 type EmptyCallOption struct{} 189 190 func (EmptyCallOption) before(*callInfo) error { return nil } 191 func (EmptyCallOption) after(*callInfo, *csAttempt) {} 192 193 // StaticMethod returns a CallOption which specifies that a call is being made 194 // to a method that is static, which means the method is known at compile time 195 // and doesn't change at runtime. This can be used as a signal to stats plugins 196 // that this method is safe to include as a key to a measurement. 197 func StaticMethod() CallOption { 198 return StaticMethodCallOption{} 199 } 200 201 // StaticMethodCallOption is a CallOption that specifies that a call comes 202 // from a static method. 203 type StaticMethodCallOption struct { 204 EmptyCallOption 205 } 206 207 // Header returns a CallOptions that retrieves the header metadata 208 // for a unary RPC. 209 func Header(md *metadata.MD) CallOption { 210 return HeaderCallOption{HeaderAddr: md} 211 } 212 213 // HeaderCallOption is a CallOption for collecting response header metadata. 214 // The metadata field will be populated *after* the RPC completes. 215 // 216 // # Experimental 217 // 218 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 219 // later release. 220 type HeaderCallOption struct { 221 HeaderAddr *metadata.MD 222 } 223 224 func (o HeaderCallOption) before(*callInfo) error { return nil } 225 func (o HeaderCallOption) after(_ *callInfo, attempt *csAttempt) { 226 *o.HeaderAddr, _ = attempt.transportStream.Header() 227 } 228 229 // Trailer returns a CallOptions that retrieves the trailer metadata 230 // for a unary RPC. 231 func Trailer(md *metadata.MD) CallOption { 232 return TrailerCallOption{TrailerAddr: md} 233 } 234 235 // TrailerCallOption is a CallOption for collecting response trailer metadata. 236 // The metadata field will be populated *after* the RPC completes. 237 // 238 // # Experimental 239 // 240 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 241 // later release. 242 type TrailerCallOption struct { 243 TrailerAddr *metadata.MD 244 } 245 246 func (o TrailerCallOption) before(*callInfo) error { return nil } 247 func (o TrailerCallOption) after(_ *callInfo, attempt *csAttempt) { 248 *o.TrailerAddr = attempt.transportStream.Trailer() 249 } 250 251 // Peer returns a CallOption that retrieves peer information for a unary RPC. 252 // The peer field will be populated *after* the RPC completes. 253 func Peer(p *peer.Peer) CallOption { 254 return PeerCallOption{PeerAddr: p} 255 } 256 257 // PeerCallOption is a CallOption for collecting the identity of the remote 258 // peer. The peer field will be populated *after* the RPC completes. 259 // 260 // # Experimental 261 // 262 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 263 // later release. 264 type PeerCallOption struct { 265 PeerAddr *peer.Peer 266 } 267 268 func (o PeerCallOption) before(*callInfo) error { return nil } 269 func (o PeerCallOption) after(_ *callInfo, attempt *csAttempt) { 270 if x, ok := peer.FromContext(attempt.transportStream.Context()); ok { 271 *o.PeerAddr = *x 272 } 273 } 274 275 // WaitForReady configures the RPC's behavior when the client is in 276 // TRANSIENT_FAILURE, which occurs when all addresses fail to connect. If 277 // waitForReady is false, the RPC will fail immediately. Otherwise, the client 278 // will wait until a connection becomes available or the RPC's deadline is 279 // reached. 280 // 281 // By default, RPCs do not "wait for ready". 282 func WaitForReady(waitForReady bool) CallOption { 283 return FailFastCallOption{FailFast: !waitForReady} 284 } 285 286 // FailFast is the opposite of WaitForReady. 287 // 288 // Deprecated: use WaitForReady. 289 func FailFast(failFast bool) CallOption { 290 return FailFastCallOption{FailFast: failFast} 291 } 292 293 // FailFastCallOption is a CallOption for indicating whether an RPC should fail 294 // fast or not. 295 // 296 // # Experimental 297 // 298 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 299 // later release. 300 type FailFastCallOption struct { 301 FailFast bool 302 } 303 304 func (o FailFastCallOption) before(c *callInfo) error { 305 c.failFast = o.FailFast 306 return nil 307 } 308 func (o FailFastCallOption) after(*callInfo, *csAttempt) {} 309 310 // OnFinish returns a CallOption that configures a callback to be called when 311 // the call completes. The error passed to the callback is the status of the 312 // RPC, and may be nil. The onFinish callback provided will only be called once 313 // by gRPC. This is mainly used to be used by streaming interceptors, to be 314 // notified when the RPC completes along with information about the status of 315 // the RPC. 316 // 317 // # Experimental 318 // 319 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 320 // later release. 321 func OnFinish(onFinish func(err error)) CallOption { 322 return OnFinishCallOption{ 323 OnFinish: onFinish, 324 } 325 } 326 327 // OnFinishCallOption is CallOption that indicates a callback to be called when 328 // the call completes. 329 // 330 // # Experimental 331 // 332 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 333 // later release. 334 type OnFinishCallOption struct { 335 OnFinish func(error) 336 } 337 338 func (o OnFinishCallOption) before(c *callInfo) error { 339 c.onFinish = append(c.onFinish, o.OnFinish) 340 return nil 341 } 342 343 func (o OnFinishCallOption) after(*callInfo, *csAttempt) {} 344 345 // MaxCallRecvMsgSize returns a CallOption which sets the maximum message size 346 // in bytes the client can receive. If this is not set, gRPC uses the default 347 // 4MB. 348 func MaxCallRecvMsgSize(bytes int) CallOption { 349 return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: bytes} 350 } 351 352 // MaxRecvMsgSizeCallOption is a CallOption that indicates the maximum message 353 // size in bytes the client can receive. 354 // 355 // # Experimental 356 // 357 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 358 // later release. 359 type MaxRecvMsgSizeCallOption struct { 360 MaxRecvMsgSize int 361 } 362 363 func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error { 364 c.maxReceiveMessageSize = &o.MaxRecvMsgSize 365 return nil 366 } 367 func (o MaxRecvMsgSizeCallOption) after(*callInfo, *csAttempt) {} 368 369 // CallAuthority returns a CallOption that sets the HTTP/2 :authority header of 370 // an RPC to the specified value. When using CallAuthority, the credentials in 371 // use must implement the AuthorityValidator interface. 372 // 373 // # Experimental 374 // 375 // Notice: This API is EXPERIMENTAL and may be changed or removed in a later 376 // release. 377 func CallAuthority(authority string) CallOption { 378 return AuthorityOverrideCallOption{Authority: authority} 379 } 380 381 // AuthorityOverrideCallOption is a CallOption that indicates the HTTP/2 382 // :authority header value to use for the call. 383 // 384 // # Experimental 385 // 386 // Notice: This type is EXPERIMENTAL and may be changed or removed in a later 387 // release. 388 type AuthorityOverrideCallOption struct { 389 Authority string 390 } 391 392 func (o AuthorityOverrideCallOption) before(c *callInfo) error { 393 c.authority = o.Authority 394 return nil 395 } 396 397 func (o AuthorityOverrideCallOption) after(*callInfo, *csAttempt) {} 398 399 // MaxCallSendMsgSize returns a CallOption which sets the maximum message size 400 // in bytes the client can send. If this is not set, gRPC uses the default 401 // `math.MaxInt32`. 402 func MaxCallSendMsgSize(bytes int) CallOption { 403 return MaxSendMsgSizeCallOption{MaxSendMsgSize: bytes} 404 } 405 406 // MaxSendMsgSizeCallOption is a CallOption that indicates the maximum message 407 // size in bytes the client can send. 408 // 409 // # Experimental 410 // 411 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 412 // later release. 413 type MaxSendMsgSizeCallOption struct { 414 MaxSendMsgSize int 415 } 416 417 func (o MaxSendMsgSizeCallOption) before(c *callInfo) error { 418 c.maxSendMessageSize = &o.MaxSendMsgSize 419 return nil 420 } 421 func (o MaxSendMsgSizeCallOption) after(*callInfo, *csAttempt) {} 422 423 // PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials 424 // for a call. 425 func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption { 426 return PerRPCCredsCallOption{Creds: creds} 427 } 428 429 // PerRPCCredsCallOption is a CallOption that indicates the per-RPC 430 // credentials to use for the call. 431 // 432 // # Experimental 433 // 434 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 435 // later release. 436 type PerRPCCredsCallOption struct { 437 Creds credentials.PerRPCCredentials 438 } 439 440 func (o PerRPCCredsCallOption) before(c *callInfo) error { 441 c.creds = o.Creds 442 return nil 443 } 444 func (o PerRPCCredsCallOption) after(*callInfo, *csAttempt) {} 445 446 // UseCompressor returns a CallOption which sets the compressor used when 447 // sending the request. If WithCompressor is also set, UseCompressor has 448 // higher priority. 449 // 450 // # Experimental 451 // 452 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 453 // later release. 454 func UseCompressor(name string) CallOption { 455 return CompressorCallOption{CompressorType: name} 456 } 457 458 // CompressorCallOption is a CallOption that indicates the compressor to use. 459 // 460 // # Experimental 461 // 462 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 463 // later release. 464 type CompressorCallOption struct { 465 CompressorType string 466 } 467 468 func (o CompressorCallOption) before(c *callInfo) error { 469 c.compressorName = o.CompressorType 470 return nil 471 } 472 func (o CompressorCallOption) after(*callInfo, *csAttempt) {} 473 474 // CallContentSubtype returns a CallOption that will set the content-subtype 475 // for a call. For example, if content-subtype is "json", the Content-Type over 476 // the wire will be "application/grpc+json". The content-subtype is converted 477 // to lowercase before being included in Content-Type. See Content-Type on 478 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for 479 // more details. 480 // 481 // If ForceCodec is not also used, the content-subtype will be used to look up 482 // the Codec to use in the registry controlled by RegisterCodec. See the 483 // documentation on RegisterCodec for details on registration. The lookup of 484 // content-subtype is case-insensitive. If no such Codec is found, the call 485 // will result in an error with code codes.Internal. 486 // 487 // If ForceCodec is also used, that Codec will be used for all request and 488 // response messages, with the content-subtype set to the given contentSubtype 489 // here for requests. 490 func CallContentSubtype(contentSubtype string) CallOption { 491 return ContentSubtypeCallOption{ContentSubtype: strings.ToLower(contentSubtype)} 492 } 493 494 // ContentSubtypeCallOption is a CallOption that indicates the content-subtype 495 // used for marshaling messages. 496 // 497 // # Experimental 498 // 499 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 500 // later release. 501 type ContentSubtypeCallOption struct { 502 ContentSubtype string 503 } 504 505 func (o ContentSubtypeCallOption) before(c *callInfo) error { 506 c.contentSubtype = o.ContentSubtype 507 return nil 508 } 509 func (o ContentSubtypeCallOption) after(*callInfo, *csAttempt) {} 510 511 // ForceCodec returns a CallOption that will set codec to be used for all 512 // request and response messages for a call. The result of calling Name() will 513 // be used as the content-subtype after converting to lowercase, unless 514 // CallContentSubtype is also used. 515 // 516 // See Content-Type on 517 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for 518 // more details. Also see the documentation on RegisterCodec and 519 // CallContentSubtype for more details on the interaction between Codec and 520 // content-subtype. 521 // 522 // This function is provided for advanced users; prefer to use only 523 // CallContentSubtype to select a registered codec instead. 524 // 525 // # Experimental 526 // 527 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 528 // later release. 529 func ForceCodec(codec encoding.Codec) CallOption { 530 return ForceCodecCallOption{Codec: codec} 531 } 532 533 // ForceCodecCallOption is a CallOption that indicates the codec used for 534 // marshaling messages. 535 // 536 // # Experimental 537 // 538 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 539 // later release. 540 type ForceCodecCallOption struct { 541 Codec encoding.Codec 542 } 543 544 func (o ForceCodecCallOption) before(c *callInfo) error { 545 c.codec = newCodecV1Bridge(o.Codec) 546 return nil 547 } 548 func (o ForceCodecCallOption) after(*callInfo, *csAttempt) {} 549 550 // ForceCodecV2 returns a CallOption that will set codec to be used for all 551 // request and response messages for a call. The result of calling Name() will 552 // be used as the content-subtype after converting to lowercase, unless 553 // CallContentSubtype is also used. 554 // 555 // See Content-Type on 556 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for 557 // more details. Also see the documentation on RegisterCodec and 558 // CallContentSubtype for more details on the interaction between Codec and 559 // content-subtype. 560 // 561 // This function is provided for advanced users; prefer to use only 562 // CallContentSubtype to select a registered codec instead. 563 // 564 // # Experimental 565 // 566 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 567 // later release. 568 func ForceCodecV2(codec encoding.CodecV2) CallOption { 569 return ForceCodecV2CallOption{CodecV2: codec} 570 } 571 572 // ForceCodecV2CallOption is a CallOption that indicates the codec used for 573 // marshaling messages. 574 // 575 // # Experimental 576 // 577 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 578 // later release. 579 type ForceCodecV2CallOption struct { 580 CodecV2 encoding.CodecV2 581 } 582 583 func (o ForceCodecV2CallOption) before(c *callInfo) error { 584 c.codec = o.CodecV2 585 return nil 586 } 587 588 func (o ForceCodecV2CallOption) after(*callInfo, *csAttempt) {} 589 590 // CallCustomCodec behaves like ForceCodec, but accepts a grpc.Codec instead of 591 // an encoding.Codec. 592 // 593 // Deprecated: use ForceCodec instead. 594 func CallCustomCodec(codec Codec) CallOption { 595 return CustomCodecCallOption{Codec: codec} 596 } 597 598 // CustomCodecCallOption is a CallOption that indicates the codec used for 599 // marshaling messages. 600 // 601 // # Experimental 602 // 603 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 604 // later release. 605 type CustomCodecCallOption struct { 606 Codec Codec 607 } 608 609 func (o CustomCodecCallOption) before(c *callInfo) error { 610 c.codec = newCodecV0Bridge(o.Codec) 611 return nil 612 } 613 func (o CustomCodecCallOption) after(*callInfo, *csAttempt) {} 614 615 // MaxRetryRPCBufferSize returns a CallOption that limits the amount of memory 616 // used for buffering this RPC's requests for retry purposes. 617 // 618 // # Experimental 619 // 620 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 621 // later release. 622 func MaxRetryRPCBufferSize(bytes int) CallOption { 623 return MaxRetryRPCBufferSizeCallOption{bytes} 624 } 625 626 // MaxRetryRPCBufferSizeCallOption is a CallOption indicating the amount of 627 // memory to be used for caching this RPC for retry purposes. 628 // 629 // # Experimental 630 // 631 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 632 // later release. 633 type MaxRetryRPCBufferSizeCallOption struct { 634 MaxRetryRPCBufferSize int 635 } 636 637 func (o MaxRetryRPCBufferSizeCallOption) before(c *callInfo) error { 638 c.maxRetryRPCBufferSize = o.MaxRetryRPCBufferSize 639 return nil 640 } 641 func (o MaxRetryRPCBufferSizeCallOption) after(*callInfo, *csAttempt) {} 642 643 // The format of the payload: compressed or not? 644 type payloadFormat uint8 645 646 const ( 647 compressionNone payloadFormat = 0 // no compression 648 compressionMade payloadFormat = 1 // compressed 649 ) 650 651 func (pf payloadFormat) isCompressed() bool { 652 return pf == compressionMade 653 } 654 655 type streamReader interface { 656 ReadMessageHeader(header []byte) error 657 Read(n int) (mem.BufferSlice, error) 658 } 659 660 // parser reads complete gRPC messages from the underlying reader. 661 type parser struct { 662 // r is the underlying reader. 663 // See the comment on recvMsg for the permissible 664 // error types. 665 r streamReader 666 667 // The header of a gRPC message. Find more detail at 668 // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md 669 header [5]byte 670 671 // bufferPool is the pool of shared receive buffers. 672 bufferPool mem.BufferPool 673 } 674 675 // recvMsg reads a complete gRPC message from the stream. 676 // 677 // It returns the message and its payload (compression/encoding) 678 // format. The caller owns the returned msg memory. 679 // 680 // If there is an error, possible values are: 681 // - io.EOF, when no messages remain 682 // - io.ErrUnexpectedEOF 683 // - of type transport.ConnectionError 684 // - an error from the status package 685 // 686 // No other error values or types must be returned, which also means 687 // that the underlying streamReader must not return an incompatible 688 // error. 689 func (p *parser) recvMsg(maxReceiveMessageSize int) (payloadFormat, mem.BufferSlice, error) { 690 err := p.r.ReadMessageHeader(p.header[:]) 691 if err != nil { 692 return 0, nil, err 693 } 694 695 pf := payloadFormat(p.header[0]) 696 length := binary.BigEndian.Uint32(p.header[1:]) 697 698 if int64(length) > int64(maxInt) { 699 return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max length allowed on current machine (%d vs. %d)", length, maxInt) 700 } 701 if int(length) > maxReceiveMessageSize { 702 return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize) 703 } 704 705 data, err := p.r.Read(int(length)) 706 if err != nil { 707 if err == io.EOF { 708 err = io.ErrUnexpectedEOF 709 } 710 return 0, nil, err 711 } 712 return pf, data, nil 713 } 714 715 // encode serializes msg and returns a buffer containing the message, or an 716 // error if it is too large to be transmitted by grpc. If msg is nil, it 717 // generates an empty message. 718 func encode(c baseCodec, msg any) (mem.BufferSlice, error) { 719 if msg == nil { // NOTE: typed nils will not be caught by this check 720 return nil, nil 721 } 722 b, err := c.Marshal(msg) 723 if err != nil { 724 return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error()) 725 } 726 if bufSize := uint(b.Len()); bufSize > math.MaxUint32 { 727 b.Free() 728 return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", bufSize) 729 } 730 return b, nil 731 } 732 733 // compress returns the input bytes compressed by compressor or cp. 734 // If both compressors are nil, or if the message has zero length, returns nil, 735 // indicating no compression was done. 736 // 737 // TODO(dfawley): eliminate cp parameter by wrapping Compressor in an encoding.Compressor. 738 func compress(in mem.BufferSlice, cp Compressor, compressor encoding.Compressor, pool mem.BufferPool) (mem.BufferSlice, payloadFormat, error) { 739 if (compressor == nil && cp == nil) || in.Len() == 0 { 740 return nil, compressionNone, nil 741 } 742 var out mem.BufferSlice 743 w := mem.NewWriter(&out, pool) 744 wrapErr := func(err error) error { 745 out.Free() 746 return status.Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error()) 747 } 748 if compressor != nil { 749 z, err := compressor.Compress(w) 750 if err != nil { 751 return nil, 0, wrapErr(err) 752 } 753 for _, b := range in { 754 if _, err := z.Write(b.ReadOnlyData()); err != nil { 755 return nil, 0, wrapErr(err) 756 } 757 } 758 if err := z.Close(); err != nil { 759 return nil, 0, wrapErr(err) 760 } 761 } else { 762 // This is obviously really inefficient since it fully materializes the data, but 763 // there is no way around this with the old Compressor API. At least it attempts 764 // to return the buffer to the provider, in the hopes it can be reused (maybe 765 // even by a subsequent call to this very function). 766 buf := in.MaterializeToBuffer(pool) 767 defer buf.Free() 768 if err := cp.Do(w, buf.ReadOnlyData()); err != nil { 769 return nil, 0, wrapErr(err) 770 } 771 } 772 return out, compressionMade, nil 773 } 774 775 const ( 776 payloadLen = 1 777 sizeLen = 4 778 headerLen = payloadLen + sizeLen 779 ) 780 781 // msgHeader returns a 5-byte header for the message being transmitted and the 782 // payload, which is compData if non-nil or data otherwise. 783 func msgHeader(data, compData mem.BufferSlice, pf payloadFormat) (hdr []byte, payload mem.BufferSlice) { 784 hdr = make([]byte, headerLen) 785 hdr[0] = byte(pf) 786 787 var length uint32 788 if pf.isCompressed() { 789 length = uint32(compData.Len()) 790 payload = compData 791 } else { 792 length = uint32(data.Len()) 793 payload = data 794 } 795 796 // Write length of payload into buf 797 binary.BigEndian.PutUint32(hdr[payloadLen:], length) 798 return hdr, payload 799 } 800 801 func outPayload(client bool, msg any, dataLength, payloadLength int, t time.Time) *stats.OutPayload { 802 return &stats.OutPayload{ 803 Client: client, 804 Payload: msg, 805 Length: dataLength, 806 WireLength: payloadLength + headerLen, 807 CompressedLength: payloadLength, 808 SentTime: t, 809 } 810 } 811 812 func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool, isServer bool) *status.Status { 813 switch pf { 814 case compressionNone: 815 case compressionMade: 816 if recvCompress == "" || recvCompress == encoding.Identity { 817 return status.New(codes.Internal, "grpc: compressed flag set with identity or empty encoding") 818 } 819 if !haveCompressor { 820 if isServer { 821 return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) 822 } 823 return status.Newf(codes.Internal, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) 824 } 825 default: 826 return status.Newf(codes.Internal, "grpc: received unexpected payload format %d", pf) 827 } 828 return nil 829 } 830 831 type payloadInfo struct { 832 compressedLength int // The compressed length got from wire. 833 uncompressedBytes mem.BufferSlice 834 } 835 836 func (p *payloadInfo) free() { 837 if p != nil && p.uncompressedBytes != nil { 838 p.uncompressedBytes.Free() 839 } 840 } 841 842 // recvAndDecompress reads a message from the stream, decompressing it if necessary. 843 // 844 // Cancelling the returned cancel function releases the buffer back to the pool. So the caller should cancel as soon as 845 // the buffer is no longer needed. 846 // TODO: Refactor this function to reduce the number of arguments. 847 // See: https://google.github.io/styleguide/go/best-practices.html#function-argument-lists 848 func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, isServer bool, 849 ) (out mem.BufferSlice, err error) { 850 pf, compressed, err := p.recvMsg(maxReceiveMessageSize) 851 if err != nil { 852 return nil, err 853 } 854 855 compressedLength := compressed.Len() 856 857 if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil, isServer); st != nil { 858 compressed.Free() 859 return nil, st.Err() 860 } 861 862 if pf.isCompressed() { 863 defer compressed.Free() 864 // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor, 865 // use this decompressor as the default. 866 out, err = decompress(compressor, compressed, dc, maxReceiveMessageSize, p.bufferPool) 867 if err != nil { 868 return nil, err 869 } 870 } else { 871 out = compressed 872 } 873 874 if payInfo != nil { 875 payInfo.compressedLength = compressedLength 876 out.Ref() 877 payInfo.uncompressedBytes = out 878 } 879 880 return out, nil 881 } 882 883 // decompress processes the given data by decompressing it using either a custom decompressor or a standard compressor. 884 // If a custom decompressor is provided, it takes precedence. The function validates that the decompressed data 885 // does not exceed the specified maximum size and returns an error if this limit is exceeded. 886 // On success, it returns the decompressed data. Otherwise, it returns an error if decompression fails or the data exceeds the size limit. 887 func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { 888 if dc != nil { 889 uncompressed, err := dc.Do(d.Reader()) 890 if err != nil { 891 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) 892 } 893 if len(uncompressed) > maxReceiveMessageSize { 894 return nil, status.Errorf(codes.ResourceExhausted, "grpc: message after decompression larger than max (%d vs. %d)", len(uncompressed), maxReceiveMessageSize) 895 } 896 return mem.BufferSlice{mem.SliceBuffer(uncompressed)}, nil 897 } 898 if compressor != nil { 899 dcReader, err := compressor.Decompress(d.Reader()) 900 if err != nil { 901 return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the message: %v", err) 902 } 903 904 // Read at most one byte more than the limit from the decompressor. 905 // Unless the limit is MaxInt64, in which case, that's impossible, so 906 // apply no limit. 907 if limit := int64(maxReceiveMessageSize); limit < math.MaxInt64 { 908 dcReader = io.LimitReader(dcReader, limit+1) 909 } 910 out, err := mem.ReadAll(dcReader, pool) 911 if err != nil { 912 out.Free() 913 return nil, status.Errorf(codes.Internal, "grpc: failed to read decompressed data: %v", err) 914 } 915 916 if out.Len() > maxReceiveMessageSize { 917 out.Free() 918 return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) 919 } 920 return out, nil 921 } 922 return nil, status.Errorf(codes.Internal, "grpc: no decompressor available for compressed payload") 923 } 924 925 type recvCompressor interface { 926 RecvCompress() string 927 } 928 929 // For the two compressor parameters, both should not be set, but if they are, 930 // dc takes precedence over compressor. 931 // TODO(dfawley): wrap the old compressor/decompressor using the new API? 932 func recv(p *parser, c baseCodec, s recvCompressor, dc Decompressor, m any, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, isServer bool) error { 933 data, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor, isServer) 934 if err != nil { 935 return err 936 } 937 938 // If the codec wants its own reference to the data, it can get it. Otherwise, always 939 // free the buffers. 940 defer data.Free() 941 942 if err := c.Unmarshal(data, m); err != nil { 943 return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message: %v", err) 944 } 945 946 return nil 947 } 948 949 // Information about RPC 950 type rpcInfo struct { 951 failfast bool 952 preloaderInfo *compressorInfo 953 } 954 955 // Information about Preloader 956 // Responsible for storing codec, and compressors 957 // If stream (s) has context s.Context which stores rpcInfo that has non nil 958 // pointers to codec, and compressors, then we can use preparedMsg for Async message prep 959 // and reuse marshalled bytes 960 type compressorInfo struct { 961 codec baseCodec 962 cp Compressor 963 comp encoding.Compressor 964 } 965 966 type rpcInfoContextKey struct{} 967 968 func newContextWithRPCInfo(ctx context.Context, failfast bool, codec baseCodec, cp Compressor, comp encoding.Compressor) context.Context { 969 return context.WithValue(ctx, rpcInfoContextKey{}, &rpcInfo{ 970 failfast: failfast, 971 preloaderInfo: &compressorInfo{ 972 codec: codec, 973 cp: cp, 974 comp: comp, 975 }, 976 }) 977 } 978 979 func rpcInfoFromContext(ctx context.Context) (s *rpcInfo, ok bool) { 980 s, ok = ctx.Value(rpcInfoContextKey{}).(*rpcInfo) 981 return 982 } 983 984 // Code returns the error code for err if it was produced by the rpc system. 985 // Otherwise, it returns codes.Unknown. 986 // 987 // Deprecated: use status.Code instead. 988 func Code(err error) codes.Code { 989 return status.Code(err) 990 } 991 992 // ErrorDesc returns the error description of err if it was produced by the rpc system. 993 // Otherwise, it returns err.Error() or empty string when err is nil. 994 // 995 // Deprecated: use status.Convert and Message method instead. 996 func ErrorDesc(err error) string { 997 return status.Convert(err).Message() 998 } 999 1000 // Errorf returns an error containing an error code and a description; 1001 // Errorf returns nil if c is OK. 1002 // 1003 // Deprecated: use status.Errorf instead. 1004 func Errorf(c codes.Code, format string, a ...any) error { 1005 return status.Errorf(c, format, a...) 1006 } 1007 1008 var errContextCanceled = status.Error(codes.Canceled, context.Canceled.Error()) 1009 var errContextDeadline = status.Error(codes.DeadlineExceeded, context.DeadlineExceeded.Error()) 1010 1011 // toRPCErr converts an error into an error from the status package. 1012 func toRPCErr(err error) error { 1013 switch err { 1014 case nil, io.EOF: 1015 return err 1016 case context.DeadlineExceeded: 1017 return errContextDeadline 1018 case context.Canceled: 1019 return errContextCanceled 1020 case io.ErrUnexpectedEOF: 1021 return status.Error(codes.Internal, err.Error()) 1022 } 1023 1024 switch e := err.(type) { 1025 case transport.ConnectionError: 1026 return status.Error(codes.Unavailable, e.Desc) 1027 case *transport.NewStreamError: 1028 return toRPCErr(e.Err) 1029 } 1030 1031 if _, ok := status.FromError(err); ok { 1032 return err 1033 } 1034 1035 return status.Error(codes.Unknown, err.Error()) 1036 } 1037 1038 // setCallInfoCodec should only be called after CallOptions have been applied. 1039 func setCallInfoCodec(c *callInfo) error { 1040 if c.codec != nil { 1041 // codec was already set by a CallOption; use it, but set the content 1042 // subtype if it is not set. 1043 if c.contentSubtype == "" { 1044 // c.codec is a baseCodec to hide the difference between grpc.Codec and 1045 // encoding.Codec (Name vs. String method name). We only support 1046 // setting content subtype from encoding.Codec to avoid a behavior 1047 // change with the deprecated version. 1048 if ec, ok := c.codec.(encoding.CodecV2); ok { 1049 c.contentSubtype = strings.ToLower(ec.Name()) 1050 } 1051 } 1052 return nil 1053 } 1054 1055 if c.contentSubtype == "" { 1056 // No codec specified in CallOptions; use proto by default. 1057 c.codec = getCodec(proto.Name) 1058 return nil 1059 } 1060 1061 // c.contentSubtype is already lowercased in CallContentSubtype 1062 c.codec = getCodec(c.contentSubtype) 1063 if c.codec == nil { 1064 return status.Errorf(codes.Internal, "no codec registered for content-subtype %s", c.contentSubtype) 1065 } 1066 return nil 1067 } 1068 1069 // The SupportPackageIsVersion variables are referenced from generated protocol 1070 // buffer files to ensure compatibility with the gRPC version used. The latest 1071 // support package version is 9. 1072 // 1073 // Older versions are kept for compatibility. 1074 // 1075 // These constants should not be referenced from any other code. 1076 const ( 1077 SupportPackageIsVersion3 = true 1078 SupportPackageIsVersion4 = true 1079 SupportPackageIsVersion5 = true 1080 SupportPackageIsVersion6 = true 1081 SupportPackageIsVersion7 = true 1082 SupportPackageIsVersion8 = true 1083 SupportPackageIsVersion9 = true 1084 ) 1085 1086 const grpcUA = "grpc-go/" + Version