grpc_net_conn

package module
Version: v0.0.0-...-eb030e4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2020 License: MIT Imports: 5 Imported by: 1

README

go-grpc-net-conn Godoc

go-grpc-net-conn is a Go library that creates a net.Conn implementation on top of gRPC streams. If the stream is bidirectional (both the request and response of an RPC is a stream) then the net.Conn is a full-duplex connection.

Installation

Standard go get:

$ go get github.com/mitchellh/go-grpc-net-conn

Usage & Example

For usage and examples see the Godoc.

A brief example is shown below. Note that the only minor complexity is populating the required fields for the Conn structure. This package needs to know how to encode and decode the byte slices onto your expected protobuf message types.

Imagine a protobuf service that looks like the following:

syntax = "proto3";

package example;

service ExampleService {
  rpc Stream(stream Bytes) returns (stream Bytes);
}

message Bytes {
  bytes data = 1;
}

You can use this in the following way:

// Call our streaming endpoint
resp, err := client.Stream(context.Background())

// We need to create a callback so the conn knows how to decode/encode
// arbitrary byte slices for our proto type.
fieldFunc := func(msg proto.Message) *[]byte {
	return &msg.(*example.Bytes).Data
}

// Wrap our conn around the response.
conn := &grpc_net_conn.Conn{
	Stream: resp,
	Request: &example.Bytes{},
	Response: &example.Bytes{},
	Encode: SimpleEncoder(fieldFunc),
	Decode: SimpleDecoder(fieldFunc),
}

// conn implements net.Conn so use it as you would!

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Conn

type Conn struct {
	// Stream is the stream to wrap into a Conn. This can be either a client
	// or server stream and we will perform correctly.
	Stream grpc.Stream

	// Request is the type to use for sending request data to the streaming
	// endpoint. This must be a non-nil allocated value and must NOT point to
	// the same value as Response since they may be used concurrently.
	//
	// The Reset method is never called on Request so you may set some
	// fields on the request type and they will be sent for every request
	// unless the Encode field changes it.
	Request proto.Message

	// Response is the type to use for reading response data. This must be
	// a non-nil allocated value and must NOT point to the same value as Request
	// since they may be used concurrently.
	//
	// The Reset method will be called on Response during Reads so data you
	// set initially will be lost.
	Response proto.Message

	// ResponseLock, if non-nil, will be locked while calling SendMsg
	// on the Stream. This can be used to prevent concurrent access to
	// SendMsg which is unsafe.
	ResponseLock *sync.Mutex

	// Encode encodes messages into the Request. See Encoder for more information.
	Encode Encoder

	// Decode decodes messages from the Response into a byte slice. See
	// Decoder for more information.
	Decode Decoder
	// contains filtered or unexported fields
}

Conn implements net.Conn across a gRPC stream. You must populate many of the exported structs on this field so please read the documentation.

There are a number of limitations to this implementation, typically due limitations of visibility given by the gRPC stream. Methods such as LocalAddr, RemoteAddr, deadlines, etc. do not work.

As documented on net.Conn, it is safe for concurrent read/write.

func (*Conn) Close

func (c *Conn) Close() error

Close will close the client if this is a client. If this is a server stream this does nothing since gRPC expects you to close the stream by returning from the RPC call.

This calls CloseSend underneath for clients, so read the documentation for that to understand the semantics of this call.

func (*Conn) LocalAddr

func (c *Conn) LocalAddr() net.Addr

LocalAddr returns nil.

func (*Conn) Read

func (c *Conn) Read(p []byte) (int, error)

Read implements io.Reader.

func (*Conn) RemoteAddr

func (c *Conn) RemoteAddr() net.Addr

RemoteAddr returns nil.

func (*Conn) SetDeadline

func (c *Conn) SetDeadline(time.Time) error

SetDeadline is non-functional due to limitations on how gRPC works. You can mimic deadlines often using call options.

func (*Conn) SetReadDeadline

func (c *Conn) SetReadDeadline(time.Time) error

SetReadDeadline is non-functional, see SetDeadline.

func (*Conn) SetWriteDeadline

func (c *Conn) SetWriteDeadline(time.Time) error

SetWriteDeadline is non-functional, see SetDeadline.

func (*Conn) Write

func (c *Conn) Write(p []byte) (int, error)

Write implements io.Writer.

type Decoder

type Decoder func(m proto.Message, offset int, p []byte) ([]byte, error)

Decode is given a Response value and expects you to decode the response value into the byte slice given. You MUST decode up to len(p) if available.

This should return the data slice directly from m. The length of this is used to determine if there is more data and the offset for the next read.

func SimpleDecoder

func SimpleDecoder(f func(proto.Message) *[]byte) Decoder

SimpleDecoder is the easiest way to generate a Decoder for a proto.Message. Provide a callback that gets the pointer to the byte slice field and a valid decoder will be generated.

type Encoder

type Encoder func(proto.Message, []byte) (int, error)

Encoder encodes a byte slice to write into the destination proto.Message. You do not need to copy the slice; you may use it directly.

You do not have to encode the full byte slice in one packet. You can choose to chunk your packets by returning 0 < n < len(p) and the Conn will repeatedly send subsequent messages by slicing into the byte slice.

func ChunkedEncoder

func ChunkedEncoder(enc Encoder, size int) Encoder

ChunkedEncoder ensures that data to encode is chunked at the proper size.

func SimpleEncoder

func SimpleEncoder(f func(proto.Message) *[]byte) Encoder

SimpleEncoder is the easiest way to generate an Encoder for a proto.Message. You just give it a callback that gets the pointer to the byte slice field and a valid encoder will be generated.

Example: given a structure that has a field "Data []byte", you could:

SimpleEncoder(func(msg proto.Message) *[]byte {
    return &msg.(*MyStruct).Data
})

Source Files

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL