Version: v0.0.3 Latest Latest

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

Go to latest
Published: Feb 9, 2022 License: MIT Imports: 62 Imported by: 39



Package rpc provides a remote procedure call (RPC) library based on gRPC.

In a server context, this package should be preferred over gRPC directly since it provides higher level configuration with more features built in, such as grpc-web, gRPC via RESTful JSON, and gRPC via WebRTC.

WebRTC services gRPC over DataChannels. The work was initially adapted from https://github.com/jsmouret/grpc-over-webrtc.


All connections to RPC servers are done by way of the Dial method which will try multiple mechanisms to connect to a target server. By default it will try to connect in the following order: mDNS (direct/WebRTC), WebRTC, Direct gRPC. This ordering can be modified by disabling some of these methods with DialOptions.

Direct gRPC

This is the simplest form of connection and for the most part passes straight through to the gRPC libraries.


This is the most complex form of connection. A WebRTC connection is established by way of a provided WebRTC signaling server that exchanges connection information about the client and server. This exchange has the client and server act as peers and connects them in the best way possible via ICE. If this succeeds a DataChannel is established that we use to tunnel over gRPC method calls (mimicking the gRPC over HTTP2 specification (https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)). Using this is a powerful means of connection because it exposes ContextPeerConnection which makes it possible to use gRPC methods to modify the Video/Audio part of the connection.

Multicast DNS (mDNS)

By default, a server will broadcast its ability to be connected to over gRPC/WebRTC over mDNS. When a dial target that matches an instance name provided by the WithInstanceNames ServerOption is found via mDNS, it will convey information about its internal gRPC IP address so that a connection can be made to it directly, either via gRPC or WebRTC. This is powerful in situations where clients/servers can only communicate in a local direct or a faster connection can be made without going out to the internet. Not that the broadcasted address is that of the internal gRPC listener. That behavior can be changed via the WithExternalListenerAddress ServerOption. That means, if the WithInternalTLSConfig option is used, any mDNS connections made will request client certificates. This will not negatively affect any UI hosted (peer certificate prompt) that uses the server's GRPCHandler because since that handler will only use the tls.Config of the http.Server hosting it, separate from the internal one.


Authentication into gRPC works by configuring a server with a series of authentication handlers provided by this framework. When one authentication handler is enabled, all requests must be authenticated, except for the Authenticate method itself. Each handler is associated with a type of credentials to handle (rpc.CredentialsType) and an rpc.AuthHandler which contains two methods: Authenticate and VerifyEntity. Authenticate is responsible for taking the name of an entity and a payload that proves the caller is allowed to assume the role of that entity. It returns metadata about the entity (e.g. an email, a user ID, etc.). The framework then returns a JWT to the client to use in subsequent requests. On those subsequent requests, the JWT is included in an HTTP header called Authorization with a value of Bearer <token>. The framework then intercepts all calls and ensures that there is a JWT present in the header, is cryptographically valid, and then hands it off to the VerifyEntity method which will pull metadata out of the JWT from Authenticate and return a value that represents the authenticated entity to use in the actual gRPC call. It is accessed via rpc.MustContextAuthEntity.

Additionally, authentication via mutual TLS is supported by way of the WithTLSAuthHandler and WithInternalTLSConfig ServerOptions. Using these two options in tandem will ask clients connecting to present a client certificate, which will be verified. This verified certificate is then caught by the authentication middleware before JWT presence is checked. If any of the DNS names in the verified client certificate match that of the entities checked in WithTLSAuthHandler, then the request will be allowed to proceed.

For WebRTC, we assume that signaling is implemented as an authenticated/authorized service and for now, do not pass any JWTs over the WebRTC data channels that are established. For more info, see https://github.com/viamrobotics/goutils/issues/12.

There is an additional feature, called AuthenticateTo provided by the ExternalAuthService which allows for external authentication on another server to "authenticate to" an entity on the target being connected to. This is an extension that can be used via the WithAuthenticateToHandler ServerOption. When a client is connecting, it will first connect to the external auth server with credentials intended for that server, and then it will call AuthenticateTo to get a JWT destined for the actual target being connected to. AuthenticateTo requires an entity to authenticate as. You can think of this feature as the ability to assume the role of another entity.

Expiration of JWTs is not yet handled/support; see: - https://github.com/viamrobotics/goutils/issues/10 - https://github.com/viamrobotics/goutils/issues/11 - https://github.com/viamrobotics/goutils/issues/13


Authorization is strictly not handled by this framework. It's up to your registered services/methods to handle authorization.



View Source
const (

	// CredentialsTypeAPIKey is intended for by external users, human and computer.
	CredentialsTypeAPIKey = CredentialsType("api-key")
View Source
const RPCHostMetadataField = "rpc-host"

RPCHostMetadataField is the identifier of a host.


View Source
var DefaultICEServers = []webrtc.ICEServer{

		URLs: []string{"stun:global.stun.twilio.com:3478?transport=udp"},

DefaultICEServers is the default set of ICE servers to use for WebRTC session negotiation. There is no guarantee that the defaults here will remain usable.

View Source
var DefaultWebRTCConfiguration = webrtc.Configuration{
	ICEServers: DefaultICEServers,

DefaultWebRTCConfiguration is the standard configuration used for WebRTC peers.

View Source
var DefaultWebRTCMaxGRPCCalls = 256

DefaultWebRTCMaxGRPCCalls is the maximum number of concurrent gRPC calls to allow for a server.

View Source
var ErrConnectionOptionsExhausted = errors.New("exhausted all connection options with no way to connect")

ErrConnectionOptionsExhausted is returned in cases where the given options have all been used up with no way to connect on any of them.

View Source
var ErrIllegalHeaderWrite = errors.New("transport: the stream is done or WriteHeader was already called")

ErrIllegalHeaderWrite indicates that setting header is illegal because of the state of the stream.

View Source
var ErrInsecureWithCredentials = errors.New("requested address is insecure and will not send credentials")

ErrInsecureWithCredentials is sent when a dial attempt is made to an address where either the insecure option or insecure downgrade with credentials options are not set.

View Source
var ErrNoWebRTCSignaler = errors.New("no signaler present")

ErrNoWebRTCSignaler happens if a gRPC request is made on a server that does not support signaling for WebRTC or explicitly not the host requested.

View Source
var JSONPB = &runtime.JSONPb{
	MarshalOptions: protojson.MarshalOptions{
		UseProtoNames:   true,
		EmitUnpopulated: true,

JSONPB are the JSON protobuf options we use globally.

View Source
var MaxMessageSize = 1 << 25

MaxMessageSize is the maximum size a gRPC message can be.

View Source
var (
	// WebRTCMaxStreamCount is the max number of streams a channel can have.
	WebRTCMaxStreamCount = 256


func ContextAuthMetadata added in v0.0.3

func ContextAuthMetadata(ctx context.Context) map[string]string

ContextAuthMetadata returns authentication metadata. It may be nil if the value was never set.

func ContextPeerConnection added in v0.0.3

func ContextPeerConnection(ctx context.Context) (*webrtc.PeerConnection, bool)

ContextPeerConnection returns a peer connection, if set.

func ContextWithAuthEntity added in v0.0.3

func ContextWithAuthEntity(ctx context.Context, authEntity interface{}) context.Context

ContextWithAuthEntity attaches authentication metadata to the given context.

func ContextWithDialer added in v0.0.2

func ContextWithDialer(ctx context.Context, d Dialer) context.Context

ContextWithDialer attaches a Dialer to the given context.

func ErrorToStatus added in v0.0.2

func ErrorToStatus(err error) *status.Status

ErrorToStatus converts an error to a gRPC status. A nil error becomes a successful status.

func HostFromCtx added in v0.0.3

func HostFromCtx(ctx context.Context) (string, error)

HostFromCtx gets the host being called/answered for from the context.

func HostsFromCtx added in v0.0.3

func HostsFromCtx(ctx context.Context) ([]string, error)

HostsFromCtx gets the hosts being called/answered for from the context.

func InstanceNameFromAddress added in v0.0.3

func InstanceNameFromAddress(addr string) (string, error)

InstanceNameFromAddress returns a suitable instance name given an address. If it's empty or an IP address, a new UUID is returned.

func MakeEntitiesChecker added in v0.0.3

func MakeEntitiesChecker(forEntities []string) func(ctx context.Context, entities ...string) error

MakeEntitiesChecker checks a list of entities against a given one for use in VerifyEntity.

func MakeSimpleVerifyEntity added in v0.0.3

func MakeSimpleVerifyEntity(forEntities []string) func(ctx context.Context, entity string) (interface{}, error)

MakeSimpleVerifyEntity returns a VerifyEntity function to be used in an AuthHandler that only verifies a list of entities for a single match and the returned auth entity is the entity name itself.

func MustContextAuthEntity added in v0.0.3

func MustContextAuthEntity(ctx context.Context) interface{}

MustContextAuthEntity returns the authentication entity associated with this context; it panics if there is none set.


type AuthHandler added in v0.0.2

type AuthHandler interface {
	// Authenticate returns nil if the given payload is valid authentication material.
	// Optional authentication metadata can be returned to be used in future requests
	// via ContextAuthMetadata.
	Authenticate(ctx context.Context, entity, payload string) (map[string]string, error)

	// VerifyEntity verifies that this handler is allowed to authenticate the given entity.
	// The handler can optionally return opaque info about the entity that will be bound to the
	// context accessible via ContextAuthEntity.
	VerifyEntity(ctx context.Context, entity string) (interface{}, error)

An AuthHandler is responsible for authenticating an RPC connection. That means that if the idea of multiple entities can be involved in one connection, that this is not a suitable abstraction to use.

func MakeFuncAuthHandler added in v0.0.2

func MakeFuncAuthHandler(
	auth func(ctx context.Context, entity, payload string) (map[string]string, error),
	verify func(ctx context.Context, entity string) (interface{}, error),
) AuthHandler

MakeFuncAuthHandler encapsulates AuthHandler functionality to a set of functions.

func MakeSimpleAuthHandler added in v0.0.2

func MakeSimpleAuthHandler(forEntities []string, expectedPayload string) AuthHandler

MakeSimpleAuthHandler returns a simple auth handler that handles multiple entities sharing one payload. This is useful for setting up local/internal authentication with a shared key. This is NOT secure for usage over networks exposed to the public internet. For that, use a more sophisticated handler with at least one key per entity.

func WithPublicKeyProvider added in v0.0.2

func WithPublicKeyProvider(
	verifyEntity func(ctx context.Context, entity string) (interface{}, error),
	pubKey *rsa.PublicKey,
) AuthHandler

WithPublicKeyProvider returns an AuthHandler that provides a public key for JWT verification that only can verify entities.

func WithTokenVerificationKeyProvider added in v0.0.2

func WithTokenVerificationKeyProvider(handler AuthHandler, keyFunc func(token *jwt.Token) (interface{}, error)) AuthHandler

WithTokenVerificationKeyProvider returns an AuthHandler that can also provide keys for JWT verification. Note: This function MUST do checks on the token signing method for security purposes.

type AuthenticateToHandler added in v0.0.3

type AuthenticateToHandler func(ctx context.Context, entity string) (map[string]string, error)

An AuthenticateToHandler determines if the given entity should be allowed to be authenticated to by the calling entity, accessible via MustContextAuthEntity. The returned auth metadata will be present in ContextAuthMetadata.

type ClientConn added in v0.0.2

type ClientConn interface {
	Close() error

A ClientConn is a wrapper around the gRPC client connection interface but ensures there is a way to close the connection.

func Dial added in v0.0.2

func Dial(ctx context.Context, address string, logger golog.Logger, opts ...DialOption) (ClientConn, error)

Dial attempts to make the most convenient connection to the given address. It attempts to connect via WebRTC if a signaling server is detected or provided. Otherwise it attempts to connect directly. TODO(https://github.com/viamrobotics/goutils/issues/19): figure out decent way to handle reconnect on connection termination.

func DialDirectGRPC added in v0.0.3

func DialDirectGRPC(ctx context.Context, address string, logger golog.Logger, opts ...DialOption) (ClientConn, error)

DialDirectGRPC dials a gRPC server directly.

func DialWebRTC added in v0.0.2

func DialWebRTC(
	ctx context.Context,
	signalingServer string,
	host string,
	logger golog.Logger,
	opts ...DialOption,
) (conn ClientConn, err error)

DialWebRTC connects to the signaling service at the given address and attempts to establish a WebRTC connection with the corresponding peer reflected in the address. It provider client/server functionality for gRPC serviced over WebRTC data channels. The work is adapted from https://github.com/jsmouret/grpc-over-webrtc.

type Credentials added in v0.0.2

type Credentials struct {
	Type    CredentialsType `json:"type"`
	Payload string          `json:"payload"`

Credentials packages up both a type of credential along with its payload which is formatted specific to the type.

type CredentialsType added in v0.0.2

type CredentialsType string

CredentialsType signifies a means of representing a credential. For example, an API key.

type DialMulticastDNSOptions added in v0.0.3

type DialMulticastDNSOptions struct {
	// Disable disables mDNS service discovery for other robots. You may want to use this
	// if you do not trust the network you're in to to truthfully advertise services. That
	// being said, if this is a concern, you should use TLS server verification.
	Disable bool

	// RemoveAuthCredentials will remove any and all authentication credentials when dialing.
	// This is particularly helpful in managed environments that do inter-robot TLS authN/Z.
	RemoveAuthCredentials bool

DialMulticastDNSOptions dictate any special settings to apply while dialing via mDNS.

type DialOption added in v0.0.2

type DialOption interface {
	// contains filtered or unexported methods

DialOption configures how we set up the connection. Cribbed from https://github.com/grpc/grpc-go/blob/aff571cc86e6e7e740130dbbb32a9741558db805/dialoptions.go#L41

func WithAllowInsecureDowngrade added in v0.0.3

func WithAllowInsecureDowngrade() DialOption

WithAllowInsecureDowngrade returns a DialOption which allows connections to be downgraded to plaintext if TLS cannot be detected properly. This is not used when there are credentials present. For that, use the more explicit WithAllowInsecureWithCredsDowngrade.

func WithAllowInsecureWithCredentialsDowngrade added in v0.0.3

func WithAllowInsecureWithCredentialsDowngrade() DialOption

WithAllowInsecureWithCredentialsDowngrade returns a DialOption which allows connections to be downgraded to plaintext if TLS cannot be detected properly while using credentials. This is generally unsafe to use but can be requested.

func WithCredentials added in v0.0.2

func WithCredentials(creds Credentials) DialOption

WithCredentials returns a DialOption which sets the credentials to use for authenticating the request. The associated entity is assumed to be the address of the server. This is mutually exclusive with WithEntityCredentials.

func WithDialDebug added in v0.0.3

func WithDialDebug() DialOption

WithDialDebug returns a DialOption which informs the client to be in a debug mode as much as possible.

func WithDialMulticastDNSOptions added in v0.0.3

func WithDialMulticastDNSOptions(opts DialMulticastDNSOptions) DialOption

WithDialMulticastDNSOptions returns a DialOption which allows setting options to specifically be used while doing a dial based off mDNS discovery.

func WithDisableDirectGRPC added in v0.0.3

func WithDisableDirectGRPC() DialOption

WithDisableDirectGRPC returns a DialOption which disables directly dialing a gRPC server. There's not really a good reason to use this unless it's for testing.

func WithEntityCredentials added in v0.0.2

func WithEntityCredentials(entity string, creds Credentials) DialOption

WithEntityCredentials returns a DialOption which sets the entity credentials to use for authenticating the request. This is mutually exclusive with WithCredentials.

func WithExternalAuth added in v0.0.2

func WithExternalAuth(addr, toEntity string) DialOption

WithExternalAuth returns a DialOption which sets the address to use to perform authentication. Authentication done in this manner will never have the dialed address be authenticated against but instead have access tokens sent directly to it. The entity which authentication is intended for must also be specified. ExternalAuth uses the ExternalAuthService extension and this library does not provide a standard implementation for it. It is expected that the credentials used in these same dial options will be used to first authenticate to the external server using the AuthService. Note: When making a gRPC connection to the given address, the same dial options are used. That means if the external address is secured, so must the internal target.

func WithExternalAuthInsecure added in v0.0.3

func WithExternalAuthInsecure() DialOption

WithExternalAuthInsecure returns a DialOption which disables transport security for this ClientConn when doing external auth. Note that transport security is required unless WithExternalAuthInsecure is set.

func WithInsecure added in v0.0.2

func WithInsecure() DialOption

WithInsecure returns a DialOption which disables transport security for this ClientConn. Note that transport security is required unless WithInsecure is set.

func WithTLSConfig added in v0.0.3

func WithTLSConfig(config *tls.Config) DialOption

WithTLSConfig sets the TLS configuration to use for all secured connections.

func WithWebRTCOptions added in v0.0.2

func WithWebRTCOptions(webrtcOpts DialWebRTCOptions) DialOption

WithWebRTCOptions returns a DialOption which sets the WebRTC options to use if the dialer tries to establish a WebRTC connection.

type DialWebRTCOptions added in v0.0.2

type DialWebRTCOptions struct {
	// Disable prevents a WebRTC connection attempt.
	Disable bool

	// SignalingInsecure determines if the signaling connection is insecure.
	SignalingInsecure bool

	// SignalingServerAddress specifies the signaling server to
	// contact on behalf of this client for WebRTC communications.
	SignalingServerAddress string

	// SignalingAuthEntity is the entity to authenticate as to the signaler.
	SignalingAuthEntity string

	// SignalingExternalAuthAddress is the address to perform external auth yet.
	// This is unlikely to be needed since the signaler is typically in the same
	// place where authentication happens.
	SignalingExternalAuthAddress string

	// SignalingExternalAuthToEntity is the entity to authenticate for after
	// externally authenticating.
	// This is unlikely to be needed since the signaler is typically in the same
	// place where authentication happens.
	SignalingExternalAuthToEntity string

	// SignalingExternalAuthInsecure is whether or not the external auth server
	// is insecure.
	// This is unlikely to be needed since the signaler is typically in the same
	// place where authentication happens.
	SignalingExternalAuthInsecure bool

	// SignalingCreds are used to authenticate the request to the signaling server.
	SignalingCreds Credentials

	// DisableTrickleICE controls whether to disable Trickle ICE or not.
	// Disabling Trickle ICE can slow down connection establishment.
	DisableTrickleICE bool

	// Config is the WebRTC specific configuration (i.e. ICE settings)
	Config *webrtc.Configuration

DialWebRTCOptions control how WebRTC is utilized in a dial attempt.

type Dialer added in v0.0.2

type Dialer interface {
	// DialDirect makes a connection to the given target over standard gRPC with the supplied options.
		ctx context.Context,
		target string,
		keyExtra string,
		onClose func() error,
		opts ...grpc.DialOption,
	) (conn ClientConn, cached bool, err error)

	// DialFunc makes a connection to the given target for the given proto using the given dial function.
		proto string,
		target string,
		keyExtra string,
		dialNew func() (ClientConn, func() error, error),
	) (conn ClientConn, cached bool, err error)

	// Close ensures all connections made are cleanly closed.
	Close() error

A Dialer is responsible for making connections to gRPC endpoints.

func NewCachedDialer added in v0.0.2

func NewCachedDialer() Dialer

NewCachedDialer returns a Dialer that returns the same connection if it already has been established at a particular target (regardless of the options used).

type JWTClaims added in v0.0.3

type JWTClaims struct {
	CredentialsType CredentialsType   `json:"rpc_creds_type,omitempty"`
	AuthMetadata    map[string]string `json:"rpc_auth_md,omitempty"`

JWTClaims extends jwt.RegisteredClaims with information about the credentials as well as authentication metadata.

type RegisterServiceHandlerFromEndpointFunc added in v0.0.2

type RegisterServiceHandlerFromEndpointFunc func(
	ctx context.Context,
	mux *runtime.ServeMux,
	endpoint string,
	opts []grpc.DialOption,
) (err error)

A RegisterServiceHandlerFromEndpointFunc is a means to have a service attach itself to a gRPC gateway mux.

type Server added in v0.0.2

type Server interface {
	// InternalAddr returns the address from the listener used for
	// gRPC communications. It may be the same listener the server
	// was constructed with.
	InternalAddr() net.Addr

	// InstanceNames are the instance names this server claims to be. Typically
	// set via options.
	InstanceNames() []string

	// Start only starts up the internal gRPC server.
	Start() error

	// Serve will externally serve, on the given listener, the
	// all in one handler described by http.Handler.
	Serve(listener net.Listener) error

	// ServeTLS will externally serve, using the given cert/key, the
	// all in one handler described by http.Handler. The provided tlsConfig
	// will be used for any extra TLS settings. If using mutual TLS authentication
	// (see WithTLSAuthHandler), then the tls.Config should have ClientAuth,
	// at a minimum, set to tls.VerifyClientCertIfGiven.
	ServeTLS(listener net.Listener, certFile, keyFile string, tlsConfig *tls.Config) error

	// Stop stops the internal gRPC and the HTTP server if it
	// was started.
	Stop() error

	// RegisterServiceServer associates a service description with
	// its implementation along with any gateway handlers.
		ctx context.Context,
		svcDesc *grpc.ServiceDesc,
		svcServer interface{},
		svcHandlers ...RegisterServiceHandlerFromEndpointFunc,
	) error

	// GatewayHandler returns a handler for gateway based gRPC requests.
	// See: https://github.com/grpc-ecosystem/grpc-gateway
	GatewayHandler() http.Handler

	// GRPCHandler returns a handler for standard grpc/grpc-web requests which
	// expect to be served from a root path.
	GRPCHandler() http.Handler

	// http.Handler implemented here is an all-in-one handler for any kind of gRPC traffic.
	// This is useful in a scenario where all gRPC is served from the root path due to
	// limitations of normal gRPC being served from a non-root path.

A Server provides a convenient way to get a gRPC server up and running with HTTP facilities.

func NewServer added in v0.0.2

func NewServer(logger golog.Logger, opts ...ServerOption) (Server, error)

NewServer returns a new server ready to be started that will listen on localhost on a random port unless TLS is turned on and authentication is enabled in which case the server will listen on all interfaces.

type ServerOption added in v0.0.2

type ServerOption interface {
	// contains filtered or unexported methods

A ServerOption changes the runtime behavior of the server. Cribbed from https://github.com/grpc/grpc-go/blob/aff571cc86e6e7e740130dbbb32a9741558db805/dialoptions.go#L41

func WithAuthHandler added in v0.0.2

func WithAuthHandler(forType CredentialsType, handler AuthHandler) ServerOption

WithAuthHandler returns a ServerOption which adds an auth handler associated to the given type to use for authentication requests.

func WithAuthRSAPrivateKey added in v0.0.2

func WithAuthRSAPrivateKey(authRSAPrivateKey *rsa.PrivateKey) ServerOption

WithAuthRSAPrivateKey returns a ServerOption which sets the private key to use for signed JWTs.

func WithAuthenticateToHandler added in v0.0.3

func WithAuthenticateToHandler(forType CredentialsType, handler AuthenticateToHandler) ServerOption

WithAuthenticateToHandler returns a ServerOption which adds an authentication handler designed to allow the caller to authenticate itself to some other entity. This is useful when externally authenticating as one entity for the purpose of getting access to another entity. Only one handler can exist and the forType parameter will be the type associated with the JWT made for the authenticated to entity. This can technically be used internal to the same server to "assume" the identity of another entity but is not intended for such usage.

func WithDebug added in v0.0.2

func WithDebug() ServerOption

WithDebug returns a ServerOption which informs the server to be in a debug mode as much as possible.

func WithDisableMulticastDNS added in v0.0.3

func WithDisableMulticastDNS() ServerOption

WithDisableMulticastDNS returns a ServerOption which disables using mDNS to broadcast how to connect to this host.

func WithExternalListenerAddress added in v0.0.3

func WithExternalListenerAddress(address *net.TCPAddr) ServerOption

WithExternalListenerAddress returns a ServerOption which sets the listener address if the server is going to be served via its handlers and not internally. This is only helpful for mDNS broadcasting. If the server has TLS enabled internally (see WithInternalTLSConfig), then the internal listener will bind everywhere and this option may not be needed.

func WithInstanceNames added in v0.0.3

func WithInstanceNames(names ...string) ServerOption

WithInstanceNames returns a ServerOption which sets the names for this server instance. These names will be used for mDNS service discovery to report the server itself. If unset the value is the address set by WithExternalListenerAddress, WithInternalBindAddress, or the localhost and random port address, in preference order from left to right.

func WithInternalBindAddress added in v0.0.3

func WithInternalBindAddress(address string) ServerOption

WithInternalBindAddress returns a ServerOption which sets the bind address for the gRPC listener. If unset, the address is localhost on a random port unless TLS is turned on and authentication is enabled in which case the server will bind to all interfaces.

func WithInternalTLSConfig added in v0.0.3

func WithInternalTLSConfig(config *tls.Config) ServerOption

WithInternalTLSConfig returns a ServerOption which sets the TLS config for the internal listener. This is needed to have mutual TLS authentication work (see WithTLSAuthHandler). When using ServeTLS on the server, which serves from an external listener, with mutual TLS authentication, you will want to pass its own tls.Config with ClientAuth, at a minimum, set to tls.VerifyClientCertIfGiven.

func WithStreamServerInterceptor added in v0.0.2

func WithStreamServerInterceptor(streamInterceptor grpc.StreamServerInterceptor) ServerOption

WithStreamServerInterceptor returns a ServerOption that sets a interceptor for all stream grpc methods registered. It will run after authentication and prior to the registered method.

func WithTLSAuthHandler added in v0.0.3

func WithTLSAuthHandler(entities []string, verifyEntity func(ctx context.Context, entities ...string) (interface{}, error)) ServerOption

WithTLSAuthHandler returns a ServerOption which when TLS info is available to a connection, it will authenticate the given entities in the event that no other authentication has been established via the standard auth handler. Optionally, verifyEntity may be specified which can do further entity checking and return return opaque info about the entity that will be bound to the context accessible via ContextAuthEntity.

func WithUnaryServerInterceptor added in v0.0.2

func WithUnaryServerInterceptor(unaryInterceptor grpc.UnaryServerInterceptor) ServerOption

WithUnaryServerInterceptor returns a ServerOption that sets a interceptor for all unary grpc methods registered. It will run after authentication and prior to the registered method.

func WithUnauthenticated added in v0.0.2

func WithUnauthenticated() ServerOption

WithUnauthenticated returns a ServerOption which turns off all authentication to the server's endpoints.

func WithWebRTCServerOptions added in v0.0.2

func WithWebRTCServerOptions(webrtcOpts WebRTCServerOptions) ServerOption

WithWebRTCServerOptions returns a ServerOption which sets the WebRTC options to use if the server sets up serving WebRTC connections.

type TokenVerificationKeyProvider added in v0.0.2

type TokenVerificationKeyProvider interface {
	// TokenVerificationKey returns the key needed to do JWT verification.
	TokenVerificationKey(token *jwt.Token) (interface{}, error)

TokenVerificationKeyProvider allows an AuthHandler to supply a key needed to peform verification of a JWT. This is helpful when the server itself is not responsible for authentication. For example, this could be for a central auth server with untrusted peers using a public key to verify JWTs.

type WebRTCCallAnswer added in v0.0.2

type WebRTCCallAnswer struct {
	InitialSDP *string
	Candidate  *webrtc.ICECandidateInit
	Err        error

WebRTCCallAnswer is the response to an offer. An agreement to start the call will contain an SDP about how the answerer wishes to speak.

type WebRTCCallOffer added in v0.0.2

type WebRTCCallOffer interface {
	// The UUID uniquely identifies this offer.
	UUID() string

	// The SDP contains initial information the caller wants to tell the answerer about.
	// In this case of Trickle ICE being disabled, this is an SDP with all ICE
	// candidate info gathered.
	SDP() string

	// DisableTrickleICE indicates if Trickle ICE should be used. Currently, both
	// sides must both respect this setting.
	DisableTrickleICE() bool

WebRTCCallOffer contains the information needed to offer to start a call.

type WebRTCCallOfferExchange added in v0.0.2

type WebRTCCallOfferExchange interface {

	// CallerCandidates transmits all candidates the caller discovers.
	CallerCandidates() <-chan webrtc.ICECandidateInit

	// CallerDone indicates when the caller has no more information to offer.
	CallerDone() <-chan struct{}

	// CallerErr returns any error that happened on the caller side. This should only
	// be called after CallerDone is done.
	CallerErr() error

	// Respond responds to the associated call offer with the given answer which contains
	// the SDP of the answerer or an error.
	AnswererRespond(ctx context.Context, ans WebRTCCallAnswer) error

	// AnswererDone signals that there is no more information to expect from the answerer.
	AnswererDone(ctx context.Context) error

A WebRTCCallOfferExchange is used by an answerer to respond to a call offer with an answer.

type WebRTCCallQueue added in v0.0.2

type WebRTCCallQueue interface {
	// SendOfferInit initializes an offer associated with the given SDP to the given host.
	// It returns a UUID to track/authenticate the offer over time, a channel receive offer updates
	// on over time, and a cancel func to stop inform the sender to stop.
	SendOfferInit(ctx context.Context, host, sdp string, disableTrickle bool) (
		uuid string, respCh <-chan WebRTCCallAnswer, respDone <-chan struct{}, cancel func(), err error)

	// SendOfferUpdate updates the offer associated with the given UUID with a newly discovered
	// ICE candidate.
	SendOfferUpdate(ctx context.Context, host, uuid string, candidate webrtc.ICECandidateInit) error

	// SendOfferDone informs the queue that the offer associated with the UUID is done sending any
	// more information.
	SendOfferDone(ctx context.Context, host, uuid string) error

	// SendOfferError informs the queue that the offer associated with the UUID has encountered
	// an error from the sender side.
	SendOfferError(ctx context.Context, host, uuid string, err error) error

	// RecvOffer receives the next offer for the given hosts. It should respond with an answer
	// once a decision is made.
	RecvOffer(ctx context.Context, hosts []string) (WebRTCCallOfferExchange, error)

	// Close shuts down the queue.
	Close() error

A WebRTCCallQueue handles the transmission and reception of call offers. For every sending of an offer done, it is expected that there is someone to receive that offer and subsequently respond to it.

func NewMemoryWebRTCCallQueue added in v0.0.2

func NewMemoryWebRTCCallQueue() WebRTCCallQueue

NewMemoryWebRTCCallQueue returns a new, empty in-memory call queue.

func NewMongoDBWebRTCCallQueue added in v0.0.2

func NewMongoDBWebRTCCallQueue(client *mongo.Client) (WebRTCCallQueue, error)

NewMongoDBWebRTCCallQueue returns a new MongoDB based call queue where calls are transferred through the given client. TODO(https://github.com/viamrobotics/goutils/issues/20): more efficient, multiplexed change streams; uniquely identify host ephemerally TODO(https://github.com/viamrobotics/goutils/issues/21): max queue size.

type WebRTCConfig added in v0.0.2

type WebRTCConfig struct {
	ICEServers []*webrtcpb.ICEServer
	Expires    time.Time

A WebRTCConfig represents a time bound WebRTC configuration.

type WebRTCConfigProvider added in v0.0.2

type WebRTCConfigProvider interface {
	Config(ctx context.Context) (WebRTCConfig, error)

A WebRTCConfigProvider returns time bound WebRTC configurations.

type WebRTCLoggerFactory added in v0.0.2

type WebRTCLoggerFactory struct {
	Logger golog.Logger

WebRTCLoggerFactory wraps a golog.Logger for use with pion's webrtc logging system.

func (WebRTCLoggerFactory) NewLogger added in v0.0.2

func (lf WebRTCLoggerFactory) NewLogger(scope string) logging.LeveledLogger

NewLogger returns a new webrtc logger under the given scope.

type WebRTCServerOptions added in v0.0.2

type WebRTCServerOptions struct {
	// Enable controls if WebRTC should be turned on. It is disabled
	// by default since signaling has the potential to open up random
	// ports on the host which may not be expected.
	Enable bool

	// ExternalSignalingDialOpts are the options used to dial the external signaler.
	ExternalSignalingDialOpts []DialOption

	// ExternalSignalingAddress specifies where the WebRTC signaling
	// answerer should connect to and "listen" from. If it is empty,
	// it will connect to the server's internal address acting as
	// an answerer for itself.
	ExternalSignalingAddress string

	// EnableInternalSignaling specifies whether an internal signaling answerer
	// should be started up. This is useful if you want to have a fallback
	// server if the external cannot be reached. It is started up by default
	// if ExternalSignalingAddress is unset.
	EnableInternalSignaling bool

	// ExternalSignalingHosts specifies what hosts are being listened for when answering
	// externally.
	ExternalSignalingHosts []string

	// InternalSignalingHosts specifies what hosts are being listened for when answering
	// internally.
	InternalSignalingHosts []string

	// Config is the WebRTC specific configuration (i.e. ICE settings)
	Config *webrtc.Configuration

WebRTCServerOptions control how WebRTC is utilized in a server.

type WebRTCSignalingServer added in v0.0.2

type WebRTCSignalingServer struct {
	// contains filtered or unexported fields

A WebRTCSignalingServer implements a signaling service for WebRTC by exchanging SDPs (https://webrtcforthecurious.com/docs/02-signaling/#what-is-the-session-description-protocol-sdp) via gRPC. The service consists of a many-to-many interaction where there are many callers and many answerers. The callers provide an SDP to the service which asks a corresponding waiting answerer to provide an SDP in exchange in order to establish a P2P connection between the two parties. Note: authorization should happen by something wrapping this service server.

func NewWebRTCSignalingServer added in v0.0.2

func NewWebRTCSignalingServer(
	callQueue WebRTCCallQueue,
	webrtcConfigProvider WebRTCConfigProvider,
	forHosts ...string,
) *WebRTCSignalingServer

NewWebRTCSignalingServer makes a new signaling server that uses the given call queue and looks routes based on a given robot host. If forHosts is non-empty, the server will only accept the given hosts and reject all others.

func (*WebRTCSignalingServer) Answer added in v0.0.2

Answer listens on call/offer queue forever responding with SDPs to agreed to calls. Note: See SinalingAnswer.answer for the complementary side of this process.

func (*WebRTCSignalingServer) Call added in v0.0.2

Call is a request/offer to start a caller with the connected answerer.

func (*WebRTCSignalingServer) CallUpdate added in v0.0.2

CallUpdate is used to send additional info in relation to a Call. In a world where https://github.com/grpc/grpc-web/issues/24 is fixed, this should be removed in favor of a bidirectional stream on Call.

func (*WebRTCSignalingServer) OptionalWebRTCConfig added in v0.0.2

OptionalWebRTCConfig returns any WebRTC configuration the caller may want to use.


Path Synopsis
Package main runs a gRPC client over WebRTC connecting to the proto/rpc/examples/echo/v1 service.
Package main runs a gRPC client over WebRTC connecting to the proto/rpc/examples/echo/v1 service.
Package server implement an echo server.
Package server implement an echo server.
Package main runs a gRPC server running the proto/rpc/examples/echo/v1 service.
Package main runs a gRPC server running the proto/rpc/examples/echo/v1 service.
Package server implement a file upload server.
Package server implement a file upload server.
Package main runs a gRPC server running the proto/rpc/examples/fileupload/v1 service.
Package main runs a gRPC server running the proto/rpc/examples/fileupload/v1 service.

Jump to

Keyboard shortcuts

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