* * Copyright 2014 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http:www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *

package grpc

import (
	
	
	
	
	
	
	
	
	
	
	
	

	
	
	
	
	
	
	
	
	
)
Compressor defines the interface gRPC uses to compress a message. Deprecated: use package encoding.
Do compresses p into w.
Type returns the compression algorithm the Compressor uses.
	Type() string
}

type gzipCompressor struct {
	pool sync.Pool
}
NewGZIPCompressor creates a Compressor based on GZIP. Deprecated: use package encoding/gzip.
NewGZIPCompressorWithLevel is like NewGZIPCompressor but specifies the gzip compression level instead of assuming DefaultCompression. The error returned will be nil if the level is valid. Deprecated: use package encoding/gzip.
func ( int) (Compressor, error) {
	if  < gzip.DefaultCompression ||  > gzip.BestCompression {
		return nil, fmt.Errorf("grpc: invalid compression level: %d", )
	}
	return &gzipCompressor{
		pool: sync.Pool{
			New: func() interface{} {
				,  := gzip.NewWriterLevel(ioutil.Discard, )
				if  != nil {
					panic()
				}
				return 
			},
		},
	}, nil
}

func ( *gzipCompressor) ( io.Writer,  []byte) error {
	 := .pool.Get().(*gzip.Writer)
	defer .pool.Put()
	.Reset()
	if ,  := .Write();  != nil {
		return 
	}
	return .Close()
}

func ( *gzipCompressor) () string {
	return "gzip"
}
Decompressor defines the interface gRPC uses to decompress a message. Deprecated: use package encoding.
Do reads the data from r and uncompress them.
Type returns the compression algorithm the Decompressor uses.
	Type() string
}

type gzipDecompressor struct {
	pool sync.Pool
}
NewGZIPDecompressor creates a Decompressor based on GZIP. Deprecated: use package encoding/gzip.
func () Decompressor {
	return &gzipDecompressor{}
}

func ( *gzipDecompressor) ( io.Reader) ([]byte, error) {
	var  *gzip.Reader
	switch maybeZ := .pool.Get().(type) {
	case nil:
		,  := gzip.NewReader()
		if  != nil {
			return nil, 
		}
		 = 
	case *gzip.Reader:
		 = 
		if  := .Reset();  != nil {
			.pool.Put()
			return nil, 
		}
	}

	defer func() {
		.Close()
		.pool.Put()
	}()
	return ioutil.ReadAll()
}

func ( *gzipDecompressor) () string {
	return "gzip"
}
callInfo contains all related configuration and information about an RPC.
CallOption configures a Call before it starts or extracts information from a Call after it completes.
before is called before the call is sent to any server. If before returns a non-nil error, the RPC fails with that error.
	before(*callInfo) error
after is called after the call has completed. after cannot return an error, so any failures should be reported via output parameters.
	after(*callInfo, *csAttempt)
}
EmptyCallOption does not alter the Call configuration. It can be embedded in another structure to carry satellite data for use by interceptors.
Header returns a CallOptions that retrieves the header metadata for a unary RPC.
HeaderCallOption is a CallOption for collecting response header metadata. The metadata field will be populated *after* the RPC completes. This is an EXPERIMENTAL API.
type HeaderCallOption struct {
	HeaderAddr *metadata.MD
}

func ( HeaderCallOption) ( *callInfo) error { return nil }
func ( HeaderCallOption) ( *callInfo,  *csAttempt) {
	*.HeaderAddr, _ = .s.Header()
}
Trailer returns a CallOptions that retrieves the trailer metadata for a unary RPC.
TrailerCallOption is a CallOption for collecting response trailer metadata. The metadata field will be populated *after* the RPC completes. This is an EXPERIMENTAL API.
type TrailerCallOption struct {
	TrailerAddr *metadata.MD
}

func ( TrailerCallOption) ( *callInfo) error { return nil }
func ( TrailerCallOption) ( *callInfo,  *csAttempt) {
	*.TrailerAddr = .s.Trailer()
}
Peer returns a CallOption that retrieves peer information for a unary RPC. The peer field will be populated *after* the RPC completes.
func ( *peer.Peer) CallOption {
	return PeerCallOption{PeerAddr: }
}
PeerCallOption is a CallOption for collecting the identity of the remote peer. The peer field will be populated *after* the RPC completes. This is an EXPERIMENTAL API.
type PeerCallOption struct {
	PeerAddr *peer.Peer
}

func ( PeerCallOption) ( *callInfo) error { return nil }
func ( PeerCallOption) ( *callInfo,  *csAttempt) {
	if ,  := peer.FromContext(.s.Context());  {
		*.PeerAddr = *
	}
}
WaitForReady configures the action to take when an RPC is attempted on broken connections or unreachable servers. If waitForReady is false, the RPC will fail immediately. Otherwise, the RPC client will block the call until a connection is available (or the call is canceled or times out) and will retry the call if it fails due to a transient error. gRPC will not retry if data was written to the wire unless the server indicates it did not process the data. Please refer to https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. By default, RPCs don't "wait for ready".
func ( bool) CallOption {
	return FailFastCallOption{FailFast: !}
}
FailFast is the opposite of WaitForReady. Deprecated: use WaitForReady.
func ( bool) CallOption {
	return FailFastCallOption{FailFast: }
}
FailFastCallOption is a CallOption for indicating whether an RPC should fail fast or not. This is an EXPERIMENTAL API.
type FailFastCallOption struct {
	FailFast bool
}

func ( FailFastCallOption) ( *callInfo) error {
	.failFast = .FailFast
	return nil
}
func ( FailFastCallOption) ( *callInfo,  *csAttempt) {}
MaxCallRecvMsgSize returns a CallOption which sets the maximum message size in bytes the client can receive.
MaxRecvMsgSizeCallOption is a CallOption that indicates the maximum message size in bytes the client can receive. This is an EXPERIMENTAL API.
MaxCallSendMsgSize returns a CallOption which sets the maximum message size in bytes the client can send.
MaxSendMsgSizeCallOption is a CallOption that indicates the maximum message size in bytes the client can send. This is an EXPERIMENTAL API.
PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials for a call.
PerRPCCredsCallOption is a CallOption that indicates the per-RPC credentials to use for the call. This is an EXPERIMENTAL API.
UseCompressor returns a CallOption which sets the compressor used when sending the request. If WithCompressor is also set, UseCompressor has higher priority. This API is EXPERIMENTAL.
CompressorCallOption is a CallOption that indicates the compressor to use. This is an EXPERIMENTAL API.
CallContentSubtype returns a CallOption that will set the content-subtype for a call. For example, if content-subtype is "json", the Content-Type over the wire will be "application/grpc+json". The content-subtype is converted to lowercase before being included in Content-Type. See Content-Type on https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for more details. If ForceCodec is not also used, the content-subtype will be used to look up the Codec to use in the registry controlled by RegisterCodec. See the documentation on RegisterCodec for details on registration. The lookup of content-subtype is case-insensitive. If no such Codec is found, the call will result in an error with code codes.Internal. If ForceCodec is also used, that Codec will be used for all request and response messages, with the content-subtype set to the given contentSubtype here for requests.
ContentSubtypeCallOption is a CallOption that indicates the content-subtype used for marshaling messages. This is an EXPERIMENTAL API.
ForceCodec returns a CallOption that will set the given Codec to be used for all request and response messages for a call. The result of calling String() will be used as the content-subtype in a case-insensitive manner. See Content-Type on https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for more details. Also see the documentation on RegisterCodec and CallContentSubtype for more details on the interaction between Codec and content-subtype. This function is provided for advanced users; prefer to use only CallContentSubtype to select a registered codec instead. This is an EXPERIMENTAL API.
ForceCodecCallOption is a CallOption that indicates the codec used for marshaling messages. This is an EXPERIMENTAL API.
CallCustomCodec behaves like ForceCodec, but accepts a grpc.Codec instead of an encoding.Codec. Deprecated: use ForceCodec instead.
CustomCodecCallOption is a CallOption that indicates the codec used for marshaling messages. This is an EXPERIMENTAL API.
type CustomCodecCallOption struct {
	Codec Codec
}

func ( CustomCodecCallOption) ( *callInfo) error {
	.codec = .Codec
	return nil
}
func ( CustomCodecCallOption) ( *callInfo,  *csAttempt) {}
MaxRetryRPCBufferSize returns a CallOption that limits the amount of memory used for buffering this RPC's requests for retry purposes. This API is EXPERIMENTAL.
MaxRetryRPCBufferSizeCallOption is a CallOption indicating the amount of memory to be used for caching this RPC for retry purposes. This is an EXPERIMENTAL API.
The format of the payload: compressed or not?
type payloadFormat uint8

const (
	compressionNone payloadFormat = 0 // no compression
	compressionMade payloadFormat = 1 // compressed
)
parser reads complete gRPC messages from the underlying reader.
r is the underlying reader. See the comment on recvMsg for the permissible error types.
The header of a gRPC message. Find more detail at https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
	header [5]byte
}
recvMsg reads a complete gRPC message from the stream. It returns the message and its payload (compression/encoding) format. The caller owns the returned msg memory. If there is an error, possible values are: * io.EOF, when no messages remain * io.ErrUnexpectedEOF * of type transport.ConnectionError * an error from the status package No other error values or types must be returned, which also means that the underlying io.Reader must not return an incompatible error.
func ( *parser) ( int) ( payloadFormat,  []byte,  error) {
	if ,  := .r.Read(.header[:]);  != nil {
		return 0, nil, 
	}

	 = payloadFormat(.header[0])
	 := binary.BigEndian.Uint32(.header[1:])

	if  == 0 {
		return , nil, nil
	}
	if int64() > int64(maxInt) {
		return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max length allowed on current machine (%d vs. %d)", , maxInt)
	}
	if int() >  {
		return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", , )
TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead of making it for each message:
	 = make([]byte, int())
	if ,  := .r.Read();  != nil {
		if  == io.EOF {
			 = io.ErrUnexpectedEOF
		}
		return 0, nil, 
	}
	return , , nil
}
encode serializes msg and returns a buffer containing the message, or an error if it is too large to be transmitted by grpc. If msg is nil, it generates an empty message.
func ( baseCodec,  interface{}) ([]byte, error) {
	if  == nil { // NOTE: typed nils will not be caught by this check
		return nil, nil
	}
	,  := .Marshal()
	if  != nil {
		return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", .Error())
	}
	if uint(len()) > math.MaxUint32 {
		return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len())
	}
	return , nil
}
compress returns the input bytes compressed by compressor or cp. If both compressors are nil, returns nil. TODO(dfawley): eliminate cp parameter by wrapping Compressor in an encoding.Compressor.
func ( []byte,  Compressor,  encoding.Compressor) ([]byte, error) {
	if  == nil &&  == nil {
		return nil, nil
	}
	 := func( error) error {
		return status.Errorf(codes.Internal, "grpc: error while compressing: %v", .Error())
	}
	 := &bytes.Buffer{}
	if  != nil {
		,  := .Compress()
		if  != nil {
			return nil, ()
		}
		if ,  := .Write();  != nil {
			return nil, ()
		}
		if  := .Close();  != nil {
			return nil, ()
		}
	} else {
		if  := .Do(, );  != nil {
			return nil, ()
		}
	}
	return .Bytes(), nil
}

const (
	payloadLen = 1
	sizeLen    = 4
	headerLen  = payloadLen + sizeLen
)
msgHeader returns a 5-byte header for the message being transmitted and the payload, which is compData if non-nil or data otherwise.
func (,  []byte) ( []byte,  []byte) {
	 = make([]byte, headerLen)
	if  != nil {
		[0] = byte(compressionMade)
		 = 
	} else {
		[0] = byte(compressionNone)
	}
Write length of payload into buf
	binary.BigEndian.PutUint32([payloadLen:], uint32(len()))
	return , 
}

func ( bool,  interface{}, ,  []byte,  time.Time) *stats.OutPayload {
	return &stats.OutPayload{
		Client:     ,
		Payload:    ,
		Data:       ,
		Length:     len(),
		WireLength: len() + headerLen,
		SentTime:   ,
	}
}

func ( payloadFormat,  string,  bool) *status.Status {
	switch  {
	case compressionNone:
	case compressionMade:
		if  == "" ||  == encoding.Identity {
			return status.New(codes.Internal, "grpc: compressed flag set with identity or empty encoding")
		}
		if ! {
			return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", )
		}
	default:
		return status.Newf(codes.Internal, "grpc: received unexpected payload format %d", )
	}
	return nil
}

type payloadInfo struct {
	wireLength        int // The compressed length got from wire.
	uncompressedBytes []byte
}

func ( *parser,  *transport.Stream,  Decompressor,  int,  *payloadInfo,  encoding.Compressor) ([]byte, error) {
	, ,  := .recvMsg()
	if  != nil {
		return nil, 
	}
	if  != nil {
		.wireLength = len()
	}

	if  := checkRecvPayload(, .RecvCompress(),  != nil ||  != nil);  != nil {
		return nil, .Err()
	}

	var  int
To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor, use this decompressor as the default.
		if  != nil {
			,  = .Do(bytes.NewReader())
			 = len()
		} else {
			, ,  = decompress(, , )
		}
		if  != nil {
			return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", )
		}
	} else {
		 = len()
	}
TODO: Revisit the error code. Currently keep it consistent with java implementation.
		return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", , )
	}
	return , nil
}
Using compressor, decompress d, returning data and size. Optionally, if data will be over maxReceiveMessageSize, just return the size.
func ( encoding.Compressor,  []byte,  int) ([]byte, int, error) {
	,  := .Decompress(bytes.NewReader())
	if  != nil {
		return nil, 0, 
	}
	if ,  := .(interface {
		( []byte) int
	});  {
		if  := .();  >= 0 {
			if  >  {
				return nil, , nil
size is used as an estimate to size the buffer, but we will read more data if available. +MinRead so ReadFrom will not reallocate if size is correct.
			 := bytes.NewBuffer(make([]byte, 0, +bytes.MinRead))
			,  := .ReadFrom(io.LimitReader(, int64()+1))
			return .Bytes(), int(), 
		}
Read from LimitReader with limit max+1. So if the underlying reader is over limit, the result will be bigger than max.
	,  = ioutil.ReadAll(io.LimitReader(, int64()+1))
	return , len(), 
}
For the two compressor parameters, both should not be set, but if they are, dc takes precedence over compressor. TODO(dfawley): wrap the old compressor/decompressor using the new API?
func ( *parser,  baseCodec,  *transport.Stream,  Decompressor,  interface{},  int,  *payloadInfo,  encoding.Compressor) error {
	,  := recvAndDecompress(, , , , , )
	if  != nil {
		return 
	}
	if  := .Unmarshal(, );  != nil {
		return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", )
	}
	if  != nil {
		.uncompressedBytes = 
	}
	return nil
}
Information about RPC
Information about Preloader Responsible for storing codec, and compressors If stream (s) has context s.Context which stores rpcInfo that has non nil pointers to codec, and compressors, then we can use preparedMsg for Async message prep and reuse marshalled bytes
Code returns the error code for err if it was produced by the rpc system. Otherwise, it returns codes.Unknown. Deprecated: use status.Code instead.
func ( error) codes.Code {
	return status.Code()
}
ErrorDesc returns the error description of err if it was produced by the rpc system. Otherwise, it returns err.Error() or empty string when err is nil. Deprecated: use status.Convert and Message method instead.
func ( error) string {
	return status.Convert().Message()
}
Errorf returns an error containing an error code and a description; Errorf returns nil if c is OK. Deprecated: use status.Errorf instead.
func ( codes.Code,  string,  ...interface{}) error {
	return status.Errorf(, , ...)
}
toRPCErr converts an error into an error from the status package.
func ( error) error {
	if  == nil ||  == io.EOF {
		return 
	}
	if  == io.ErrUnexpectedEOF {
		return status.Error(codes.Internal, .Error())
	}
	if ,  := status.FromError();  {
		return 
	}
	switch e := .(type) {
	case transport.ConnectionError:
		return status.Error(codes.Unavailable, .Desc)
	default:
		switch  {
		case context.DeadlineExceeded:
			return status.Error(codes.DeadlineExceeded, .Error())
		case context.Canceled:
			return status.Error(codes.Canceled, .Error())
		}
	}
	return status.Error(codes.Unknown, .Error())
}
setCallInfoCodec should only be called after CallOptions have been applied.
codec was already set by a CallOption; use it.
		return nil
	}

No codec specified in CallOptions; use proto by default.
c.contentSubtype is already lowercased in CallContentSubtype
	.codec = encoding.GetCodec(.contentSubtype)
	if .codec == nil {
		return status.Errorf(codes.Internal, "no codec registered for content-subtype %s", .contentSubtype)
	}
	return nil
}
parseDialTarget returns the network and address to pass to dialer
func ( string) ( string,  string) {
	 = "tcp"

	 := strings.Index(, ":")
	 := strings.Index(, ":/")
handle unix:addr which will fail with url.Parse
	if  >= 0 &&  < 0 {
		if  := [0:];  == "unix" {
			 = 
			 = [+1:]
			return , 
		}
	}
	if  >= 0 {
		,  := url.Parse()
		if  != nil {
			return , 
		}
		 := .Scheme
		 = .Path
		if  == "unix" {
			 = 
			if  == "" {
				 = .Host
			}
			return , 
		}
	}

	return , 
}
channelzData is used to store channelz related data for ClientConn, addrConn and Server. These fields cannot be embedded in the original structs (e.g. ClientConn), since to do atomic operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment. Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
lastCallStartedTime stores the timestamp that last call starts. It is of int64 type instead of time.Time since it's more costly to atomically update time.Time variable than int64 variable.
The SupportPackageIsVersion variables are referenced from generated protocol buffer files to ensure compatibility with the gRPC version used. The latest support package version is 7. Older versions are kept for compatibility. They may be removed if compatibility cannot be maintained. These constants should not be referenced from any other code.