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