README ¶
The Sansshell Proxy
Overview
The Sansshell proxy is a standalone, optional component from the Sanshell server, which can be deployed to act as an intermediary between clients and Sansshell instances.
It is designed to enable larger deployments of Sansshell by providing:
- a 'gateway' which can bridge connectivity to Sanshell instances to which clients may not have network visibility.
- a centralized 'choke point' for logging and enforcement of fine-grained policy that may need to change rapidly.
- a mechanism for fanning-out identical requests from a single client to multiple Sansshell instances, to simplify and accelerate 'batch' operations.
Like Sansshell itself, it is a policy-enforcing gRPC server written in Go.
Design Goals
The design of the proxy is influenced by the design of Sansshell itself, and in particular, the ability to extend Sansshell functionality via the implementation of 'service modules' that provide new capabilities.
Sansshell service modules provides a multitude of different capabilities that are often best served by a particular calling pattern. For example, a service module for executing remote commands might naturally fit into a unary call/response pattern, while a module for reading (potentially large) remote files might instead be modeled as a stream of data chunks.
Rather than constrain modules to a single pattern in order to fit the needs of the proxy, it is the proxy itself that endeavors to be flexible enough to accomodate any potentially calling pattern supported by gRPC (unary, client stream, server stream, or fully bi-directional streams).
Competing with this desire is the need to support both inspection of the payload, (for policy enforcement and logging) and the ability to 'fan out' requests to multiple backend sansshell instances.
Implementation Notes
The need to support arbitrary gRPC calling conventions yields a client/proxy protocol which effectively mimics many of the concepts in gRPC itself.
Since at least some portion of the requests served by the proxy will be streaming (client, server, or both), the client -> proxy connection must itself be a bidirectional stream.
Further, since we want to be able to fan out requests from a single client to potentially many different servers, we need to provide the ability to multiplex the data returned by multiple different instances over the same connection.
At a high-level, this produces a protocol which somewhat resembles 'gRPC over gRPC', with the client->proxy gRPC connection taking on a similar role as HTTP/2 does in gRPC itself.
The cost of this flexibility for clients is a somewhat complex implementation, requiring a proxy-aware client, and a proxy implementation that is capable of managing the state of many connections.
After establishing a connection to the proxy, clients must explicitly request the establishment of a 'stream' to each intended target using a 'StartStream' request, which specifies the intended target and method they wish to call.
Assuming the client has permission (via the policy) to establish the requested connection, and the target is available, the proxy establishes the connection to the target, and returns to the client a unique 'stream identifier' which must be used for future calls. (Note that this stream identifier is only meanginful in the context of a specific client->proxy connection, and cannot be used by other clients).
Using the stream id, the clients then send one or more StreamData requests to the proxy, which in turn sends them to the Sansshell instances that correspond to the stream ID. Fan-out is provided by the ability to specify multiple stream IDs in each StreamData request, which causes the request to be delivered to each of the specified streams.
Clients read from the proxy stream to obtain any responses (whether data or errors), each of which is identified by a previously returned stream ID.
Finished streams will cause the delivery of an inband "ServerClose" response containing the final status of the target stream (again, identified by its StreamID).
On the proxy, all of the various streams initiated by a clients are 'children' of the single client -> proxy stream, and will be cancelled automatically if the client -> proxy stream is itself broken or times out.
The 'low-level' nature of the proxy protocol is helpful for accommodating multiple gRPC call patterns, but can be somewhat difficult to use as a result. To help manage the complexity of using the proxy, sansshell also includes a grpc plugin for generating 'helper' logic for calling a particular service via the proxy.
This plugin generates new methods on each client stub with a 'OneMany' suffix (e.g. ReadOneMany
for Read
) that allow invoking the method (via the proxy) against multiple backend targets. Since the OneMany
versions also work
for single targets (even if no proxy is used), the Sansshell client code
uses the OnMany
version of all calls unconditionally.
sequenceDiagram
client->>proxy: grpc.Dial / Proxy.Proxy
client->>proxy: StartStream{target:foo, method:bar, nonce:1}
proxy->>proxy: policy check / log
proxy->>foo: grpc.Dial(foo)
proxy->>client: StartStreamReply{nonce: 1, StreamID: 2}
client->>proxy: StreamData{StreamID: 2, data:<Any[Request]>}
proxy->>proxy: PolicyCheck / log
proxy->>foo: Request
foo->>proxy: Response
proxy->>client: StreamData{StreamID: 2, data:<Any[Response]>}
foo->>proxy: Close(status)
proxy->>client: ServerClose{StreamID: 2, Status: status}
Documentation ¶
Overview ¶
Package proxy defines the RPC interface for the sansshell proxy server.
Index ¶
- Constants
- Variables
- func RegisterProxyServer(s grpc.ServiceRegistrar, srv ProxyServer)
- type ClientCancel
- type ClientClose
- type ProxyClient
- type ProxyReply
- func (*ProxyReply) Descriptor() ([]byte, []int)deprecated
- func (m *ProxyReply) GetReply() isProxyReply_Reply
- func (x *ProxyReply) GetServerClose() *ServerClose
- func (x *ProxyReply) GetStartStreamReply() *StartStreamReply
- func (x *ProxyReply) GetStreamData() *StreamData
- func (*ProxyReply) ProtoMessage()
- func (x *ProxyReply) ProtoReflect() protoreflect.Message
- func (x *ProxyReply) Reset()
- func (x *ProxyReply) String() string
- type ProxyReply_ServerClose
- type ProxyReply_StartStreamReply
- type ProxyReply_StreamData
- type ProxyRequest
- func (*ProxyRequest) Descriptor() ([]byte, []int)deprecated
- func (x *ProxyRequest) GetClientCancel() *ClientCancel
- func (x *ProxyRequest) GetClientClose() *ClientClose
- func (m *ProxyRequest) GetRequest() isProxyRequest_Request
- func (x *ProxyRequest) GetStartStream() *StartStream
- func (x *ProxyRequest) GetStreamData() *StreamData
- func (*ProxyRequest) ProtoMessage()
- func (x *ProxyRequest) ProtoReflect() protoreflect.Message
- func (x *ProxyRequest) Reset()
- func (x *ProxyRequest) String() string
- type ProxyRequest_ClientCancel
- type ProxyRequest_ClientClose
- type ProxyRequest_StartStream
- type ProxyRequest_StreamData
- type ProxyServer
- type Proxy_ProxyClient
- type Proxy_ProxyServer
- type ServerClose
- func (*ServerClose) Descriptor() ([]byte, []int)deprecated
- func (x *ServerClose) GetStatus() *Status
- func (x *ServerClose) GetStreamIds() []uint64
- func (*ServerClose) ProtoMessage()
- func (x *ServerClose) ProtoReflect() protoreflect.Message
- func (x *ServerClose) Reset()
- func (x *ServerClose) String() string
- type StartStream
- func (*StartStream) Descriptor() ([]byte, []int)deprecated
- func (x *StartStream) GetDialTimeout() *durationpb.Duration
- func (x *StartStream) GetMethodName() string
- func (x *StartStream) GetNonce() uint32
- func (x *StartStream) GetTarget() string
- func (*StartStream) ProtoMessage()
- func (x *StartStream) ProtoReflect() protoreflect.Message
- func (x *StartStream) Reset()
- func (x *StartStream) String() string
- type StartStreamReply
- func (*StartStreamReply) Descriptor() ([]byte, []int)deprecated
- func (x *StartStreamReply) GetErrorStatus() *Status
- func (x *StartStreamReply) GetNonce() uint32
- func (m *StartStreamReply) GetReply() isStartStreamReply_Reply
- func (x *StartStreamReply) GetStreamId() uint64
- func (x *StartStreamReply) GetTarget() string
- func (*StartStreamReply) ProtoMessage()
- func (x *StartStreamReply) ProtoReflect() protoreflect.Message
- func (x *StartStreamReply) Reset()
- func (x *StartStreamReply) String() string
- type StartStreamReply_ErrorStatus
- type StartStreamReply_StreamId
- type Status
- func (*Status) Descriptor() ([]byte, []int)deprecated
- func (x *Status) GetCode() int32
- func (x *Status) GetDetails() []*anypb.Any
- func (x *Status) GetMessage() string
- func (*Status) ProtoMessage()
- func (x *Status) ProtoReflect() protoreflect.Message
- func (x *Status) Reset()
- func (x *Status) String() string
- type StreamData
- func (*StreamData) Descriptor() ([]byte, []int)deprecated
- func (x *StreamData) GetPayload() *anypb.Any
- func (x *StreamData) GetStreamIds() []uint64
- func (*StreamData) ProtoMessage()
- func (x *StreamData) ProtoReflect() protoreflect.Message
- func (x *StreamData) Reset()
- func (x *StreamData) String() string
- type UnimplementedProxyServer
- type UnsafeProxyServer
Constants ¶
const (
Proxy_Proxy_FullMethodName = "/Proxy.Proxy/Proxy"
)
Variables ¶
var File_proxy_proto protoreflect.FileDescriptor
var Proxy_ServiceDesc = grpc.ServiceDesc{ ServiceName: "Proxy.Proxy", HandlerType: (*ProxyServer)(nil), Methods: []grpc.MethodDesc{}, Streams: []grpc.StreamDesc{ { StreamName: "Proxy", Handler: _Proxy_Proxy_Handler, ServerStreams: true, ClientStreams: true, }, }, Metadata: "proxy.proto", }
Proxy_ServiceDesc is the grpc.ServiceDesc for Proxy service. It's only intended for direct use with grpc.RegisterService, and not to be introspected or modified (even as a copy)
Functions ¶
func RegisterProxyServer ¶
func RegisterProxyServer(s grpc.ServiceRegistrar, srv ProxyServer)
Types ¶
type ClientCancel ¶
type ClientCancel struct { // The server-assigned stream id(s) to cancel. StreamIds []uint64 `protobuf:"varint,1,rep,packed,name=stream_ids,json=streamIds,proto3" json:"stream_ids,omitempty"` // contains filtered or unexported fields }
ClientCancel is sent by the proxy client to request cancellation of the given stream(s).
func (*ClientCancel) Descriptor
deprecated
func (*ClientCancel) Descriptor() ([]byte, []int)
Deprecated: Use ClientCancel.ProtoReflect.Descriptor instead.
func (*ClientCancel) GetStreamIds ¶
func (x *ClientCancel) GetStreamIds() []uint64
func (*ClientCancel) ProtoMessage ¶
func (*ClientCancel) ProtoMessage()
func (*ClientCancel) ProtoReflect ¶
func (x *ClientCancel) ProtoReflect() protoreflect.Message
func (*ClientCancel) Reset ¶
func (x *ClientCancel) Reset()
func (*ClientCancel) String ¶
func (x *ClientCancel) String() string
type ClientClose ¶
type ClientClose struct { // The server-asssigned stream id(s) to close. StreamIds []uint64 `protobuf:"varint,1,rep,packed,name=stream_ids,json=streamIds,proto3" json:"stream_ids,omitempty"` // contains filtered or unexported fields }
ClientClose is sent by the proxy client to indicate that no more messages will be sent to the given stream(s) Note that clients do not need to send a ClientClose for streams where client_streams is false.
func (*ClientClose) Descriptor
deprecated
func (*ClientClose) Descriptor() ([]byte, []int)
Deprecated: Use ClientClose.ProtoReflect.Descriptor instead.
func (*ClientClose) GetStreamIds ¶
func (x *ClientClose) GetStreamIds() []uint64
func (*ClientClose) ProtoMessage ¶
func (*ClientClose) ProtoMessage()
func (*ClientClose) ProtoReflect ¶
func (x *ClientClose) ProtoReflect() protoreflect.Message
func (*ClientClose) Reset ¶
func (x *ClientClose) Reset()
func (*ClientClose) String ¶
func (x *ClientClose) String() string
type ProxyClient ¶
type ProxyClient interface { // Proxy represents a bidirectional stream of requests from a sanshell // client to one or more target sanshell instances reachable from the // proxy server. Proxy(ctx context.Context, opts ...grpc.CallOption) (Proxy_ProxyClient, error) }
ProxyClient is the client API for Proxy service.
For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
func NewProxyClient ¶
func NewProxyClient(cc grpc.ClientConnInterface) ProxyClient
type ProxyReply ¶
type ProxyReply struct { // Types that are assignable to Reply: // // *ProxyReply_StartStreamReply // *ProxyReply_StreamData // *ProxyReply_ServerClose Reply isProxyReply_Reply `protobuf_oneof:"reply"` // contains filtered or unexported fields }
func (*ProxyReply) Descriptor
deprecated
func (*ProxyReply) Descriptor() ([]byte, []int)
Deprecated: Use ProxyReply.ProtoReflect.Descriptor instead.
func (*ProxyReply) GetReply ¶
func (m *ProxyReply) GetReply() isProxyReply_Reply
func (*ProxyReply) GetServerClose ¶
func (x *ProxyReply) GetServerClose() *ServerClose
func (*ProxyReply) GetStartStreamReply ¶
func (x *ProxyReply) GetStartStreamReply() *StartStreamReply
func (*ProxyReply) GetStreamData ¶
func (x *ProxyReply) GetStreamData() *StreamData
func (*ProxyReply) ProtoMessage ¶
func (*ProxyReply) ProtoMessage()
func (*ProxyReply) ProtoReflect ¶
func (x *ProxyReply) ProtoReflect() protoreflect.Message
func (*ProxyReply) Reset ¶
func (x *ProxyReply) Reset()
func (*ProxyReply) String ¶
func (x *ProxyReply) String() string
type ProxyReply_ServerClose ¶
type ProxyReply_ServerClose struct { // An end of stream message for one or more established streams. ServerClose *ServerClose `protobuf:"bytes,3,opt,name=server_close,json=serverClose,proto3,oneof"` }
type ProxyReply_StartStreamReply ¶
type ProxyReply_StartStreamReply struct { // A reply to a request to initiate a stream. StartStreamReply *StartStreamReply `protobuf:"bytes,1,opt,name=start_stream_reply,json=startStreamReply,proto3,oneof"` }
type ProxyReply_StreamData ¶
type ProxyReply_StreamData struct { // Additional server data for one or more established streams. StreamData *StreamData `protobuf:"bytes,2,opt,name=stream_data,json=streamData,proto3,oneof"` }
type ProxyRequest ¶
type ProxyRequest struct { // Types that are assignable to Request: // // *ProxyRequest_StartStream // *ProxyRequest_StreamData // *ProxyRequest_ClientClose // *ProxyRequest_ClientCancel Request isProxyRequest_Request `protobuf_oneof:"request"` // contains filtered or unexported fields }
func (*ProxyRequest) Descriptor
deprecated
func (*ProxyRequest) Descriptor() ([]byte, []int)
Deprecated: Use ProxyRequest.ProtoReflect.Descriptor instead.
func (*ProxyRequest) GetClientCancel ¶
func (x *ProxyRequest) GetClientCancel() *ClientCancel
func (*ProxyRequest) GetClientClose ¶
func (x *ProxyRequest) GetClientClose() *ClientClose
func (*ProxyRequest) GetRequest ¶
func (m *ProxyRequest) GetRequest() isProxyRequest_Request
func (*ProxyRequest) GetStartStream ¶
func (x *ProxyRequest) GetStartStream() *StartStream
func (*ProxyRequest) GetStreamData ¶
func (x *ProxyRequest) GetStreamData() *StreamData
func (*ProxyRequest) ProtoMessage ¶
func (*ProxyRequest) ProtoMessage()
func (*ProxyRequest) ProtoReflect ¶
func (x *ProxyRequest) ProtoReflect() protoreflect.Message
func (*ProxyRequest) Reset ¶
func (x *ProxyRequest) Reset()
func (*ProxyRequest) String ¶
func (x *ProxyRequest) String() string
type ProxyRequest_ClientCancel ¶
type ProxyRequest_ClientCancel struct { // A ClientCancel indicates that the client wants to cancel // one or more established streams. ClientCancel *ClientCancel `protobuf:"bytes,4,opt,name=client_cancel,json=clientCancel,proto3,oneof"` }
type ProxyRequest_ClientClose ¶
type ProxyRequest_ClientClose struct { // A ClientClose indicates that no more data will be sent // for one or more established streams. ClientClose *ClientClose `protobuf:"bytes,3,opt,name=client_close,json=clientClose,proto3,oneof"` }
type ProxyRequest_StartStream ¶
type ProxyRequest_StartStream struct { // A request to open a new stream to a target. StartStream *StartStream `protobuf:"bytes,1,opt,name=start_stream,json=startStream,proto3,oneof"` }
type ProxyRequest_StreamData ¶
type ProxyRequest_StreamData struct { // Additional client data for one or more established streams. StreamData *StreamData `protobuf:"bytes,2,opt,name=stream_data,json=streamData,proto3,oneof"` }
type ProxyServer ¶
type ProxyServer interface { // Proxy represents a bidirectional stream of requests from a sanshell // client to one or more target sanshell instances reachable from the // proxy server. Proxy(Proxy_ProxyServer) error }
ProxyServer is the server API for Proxy service. All implementations should embed UnimplementedProxyServer for forward compatibility
type Proxy_ProxyClient ¶
type Proxy_ProxyClient interface { Send(*ProxyRequest) error Recv() (*ProxyReply, error) grpc.ClientStream }
type Proxy_ProxyServer ¶
type Proxy_ProxyServer interface { Send(*ProxyReply) error Recv() (*ProxyRequest, error) grpc.ServerStream }
type ServerClose ¶
type ServerClose struct { // The stream identifier, as returned in StartStreamReply // This can be repeated, to indicate that the same status is // applicable to multiple streams. StreamIds []uint64 `protobuf:"varint,1,rep,packed,name=stream_ids,json=streamIds,proto3" json:"stream_ids,omitempty"` // The final status of the stream. Status *Status `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` // contains filtered or unexported fields }
A server end-of-stream response, containing the final status of the stream.
func (*ServerClose) Descriptor
deprecated
func (*ServerClose) Descriptor() ([]byte, []int)
Deprecated: Use ServerClose.ProtoReflect.Descriptor instead.
func (*ServerClose) GetStatus ¶
func (x *ServerClose) GetStatus() *Status
func (*ServerClose) GetStreamIds ¶
func (x *ServerClose) GetStreamIds() []uint64
func (*ServerClose) ProtoMessage ¶
func (*ServerClose) ProtoMessage()
func (*ServerClose) ProtoReflect ¶
func (x *ServerClose) ProtoReflect() protoreflect.Message
func (*ServerClose) Reset ¶
func (x *ServerClose) Reset()
func (*ServerClose) String ¶
func (x *ServerClose) String() string
type StartStream ¶
type StartStream struct { // The stream target, as accepted by grpc.Dial. Target string `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` // The fully-qualified method name (e.g. "/Package.Service/Method") MethodName string `protobuf:"bytes,2,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` // A nonce value which will be echoed in the reply // to allow the client to correlate this stream // request with the server-assigned stream ID. Nonce uint32 `protobuf:"varint,3,opt,name=nonce,proto3" json:"nonce,omitempty"` // A dial timeout will bound how long to wait to connect // to the remote target. By default in grpc for Go for instance // this is 20s and handled asychronously when creating the actual // connection. Setting a timeout here will block the Dial() call // to that timeout before proceeding. Each Dial() happens in their // own routine so this will not block the overall progress for a stream. DialTimeout *durationpb.Duration `protobuf:"bytes,4,opt,name=dial_timeout,json=dialTimeout,proto3" json:"dial_timeout,omitempty"` // contains filtered or unexported fields }
A request to start a stream to a target host. The supplied `nonce` is an arbitrary client-chosen value that will be echoed in the returned reply to allow clients to correlate this request with the associated stream id.
func (*StartStream) Descriptor
deprecated
func (*StartStream) Descriptor() ([]byte, []int)
Deprecated: Use StartStream.ProtoReflect.Descriptor instead.
func (*StartStream) GetDialTimeout ¶ added in v1.6.0
func (x *StartStream) GetDialTimeout() *durationpb.Duration
func (*StartStream) GetMethodName ¶
func (x *StartStream) GetMethodName() string
func (*StartStream) GetNonce ¶
func (x *StartStream) GetNonce() uint32
func (*StartStream) GetTarget ¶
func (x *StartStream) GetTarget() string
func (*StartStream) ProtoMessage ¶
func (*StartStream) ProtoMessage()
func (*StartStream) ProtoReflect ¶
func (x *StartStream) ProtoReflect() protoreflect.Message
func (*StartStream) Reset ¶
func (x *StartStream) Reset()
func (*StartStream) String ¶
func (x *StartStream) String() string
type StartStreamReply ¶
type StartStreamReply struct { // The target string originally supplied to StartStream Target string `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` // The nonce value supplied by the client in StartStream. Nonce uint32 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"` // Types that are assignable to Reply: // // *StartStreamReply_StreamId // *StartStreamReply_ErrorStatus Reply isStartStreamReply_Reply `protobuf_oneof:"reply"` // contains filtered or unexported fields }
func (*StartStreamReply) Descriptor
deprecated
func (*StartStreamReply) Descriptor() ([]byte, []int)
Deprecated: Use StartStreamReply.ProtoReflect.Descriptor instead.
func (*StartStreamReply) GetErrorStatus ¶
func (x *StartStreamReply) GetErrorStatus() *Status
func (*StartStreamReply) GetNonce ¶
func (x *StartStreamReply) GetNonce() uint32
func (*StartStreamReply) GetReply ¶
func (m *StartStreamReply) GetReply() isStartStreamReply_Reply
func (*StartStreamReply) GetStreamId ¶
func (x *StartStreamReply) GetStreamId() uint64
func (*StartStreamReply) GetTarget ¶
func (x *StartStreamReply) GetTarget() string
func (*StartStreamReply) ProtoMessage ¶
func (*StartStreamReply) ProtoMessage()
func (*StartStreamReply) ProtoReflect ¶
func (x *StartStreamReply) ProtoReflect() protoreflect.Message
func (*StartStreamReply) Reset ¶
func (x *StartStreamReply) Reset()
func (*StartStreamReply) String ¶
func (x *StartStreamReply) String() string
type StartStreamReply_ErrorStatus ¶
type StartStreamReply_ErrorStatus struct { // Status carries an error if the stream could not be // established. ErrorStatus *Status `protobuf:"bytes,4,opt,name=error_status,json=errorStatus,proto3,oneof"` }
type StartStreamReply_StreamId ¶
type StartStreamReply_StreamId struct { // The server-assigned stream identifier, which should be included // in all future messages for this stream. // stream_ids are only guaranteed to be unique within the // context of a single proxy stream. StreamId uint64 `protobuf:"varint,3,opt,name=stream_id,json=streamId,proto3,oneof"` }
type Status ¶
type Status struct { // The status code (one of google.rpc.Code) Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // A developer-targeted error message. Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // List of messages carrying error details. Details []*anypb.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"` // contains filtered or unexported fields }
A wire-compatible version of google.rpc.Status
func (*Status) Descriptor
deprecated
func (*Status) GetDetails ¶
func (*Status) GetMessage ¶
func (*Status) ProtoMessage ¶
func (*Status) ProtoMessage()
func (*Status) ProtoReflect ¶
func (x *Status) ProtoReflect() protoreflect.Message
type StreamData ¶
type StreamData struct { // The stream identifier, as returned in StartStreamReply // This can be repeated, to indicate that the same data is relevant // to multiple established streams. StreamIds []uint64 `protobuf:"varint,1,rep,packed,name=stream_ids,json=streamIds,proto3" json:"stream_ids,omitempty"` // The message payload Payload *anypb.Any `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` // contains filtered or unexported fields }
StreamData is used by both clients and servers to transmit data for an established stream.
func (*StreamData) Descriptor
deprecated
func (*StreamData) Descriptor() ([]byte, []int)
Deprecated: Use StreamData.ProtoReflect.Descriptor instead.
func (*StreamData) GetPayload ¶
func (x *StreamData) GetPayload() *anypb.Any
func (*StreamData) GetStreamIds ¶
func (x *StreamData) GetStreamIds() []uint64
func (*StreamData) ProtoMessage ¶
func (*StreamData) ProtoMessage()
func (*StreamData) ProtoReflect ¶
func (x *StreamData) ProtoReflect() protoreflect.Message
func (*StreamData) Reset ¶
func (x *StreamData) Reset()
func (*StreamData) String ¶
func (x *StreamData) String() string
type UnimplementedProxyServer ¶
type UnimplementedProxyServer struct { }
UnimplementedProxyServer should be embedded to have forward compatible implementations.
func (UnimplementedProxyServer) Proxy ¶
func (UnimplementedProxyServer) Proxy(Proxy_ProxyServer) error
type UnsafeProxyServer ¶
type UnsafeProxyServer interface {
// contains filtered or unexported methods
}
UnsafeProxyServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to ProxyServer will result in compilation errors.
Directories ¶
Path | Synopsis |
---|---|
Package proxy provides the client side API for working with a proxy server.
|
Package proxy provides the client side API for working with a proxy server. |
Package server provides the server-side implementation of the sansshell proxy server.
|
Package server provides the server-side implementation of the sansshell proxy server. |
Package testutil contains helpers and utilities for writing unittests against the sansshell proxy.
|
Package testutil contains helpers and utilities for writing unittests against the sansshell proxy. |