mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-05-24 02:26:34 +00:00

Combines the tunnelrpc and quic/schema capnp files into the same module. To help reduce future issues with capnp id generation, capnpids are provided in the capnp files from the existing capnp struct ids generated in the go files. Reduces the overall interface of the Capnp methods to the rest of the code by providing an interface that will handle the quic protocol selection. Introduces a new `rpc-timeout` config that will allow all of the SessionManager and ConfigurationManager RPC requests to have a timeout. The timeout for these values is set to 5 seconds as non of these operations for the managers should take a long time to complete. Removed the RPC-specific logger as it never provided good debugging value as the RPC method names were not visible in the logs.
335 lines
9.0 KiB
Go
335 lines
9.0 KiB
Go
package pogs
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
capnp "zombiezen.com/go/capnproto2"
|
|
"zombiezen.com/go/capnproto2/pogs"
|
|
"zombiezen.com/go/capnproto2/rpc"
|
|
"zombiezen.com/go/capnproto2/server"
|
|
|
|
"github.com/cloudflare/cloudflared/tunnelrpc/proto"
|
|
)
|
|
|
|
const (
|
|
defaultRetryAfterSeconds = 15
|
|
)
|
|
|
|
type Authentication struct {
|
|
Key string
|
|
Email string
|
|
OriginCAKey string
|
|
}
|
|
|
|
func MarshalAuthentication(s proto.Authentication, p *Authentication) error {
|
|
return pogs.Insert(proto.Authentication_TypeID, s.Struct, p)
|
|
}
|
|
|
|
func UnmarshalAuthentication(s proto.Authentication) (*Authentication, error) {
|
|
p := new(Authentication)
|
|
err := pogs.Extract(p, proto.Authentication_TypeID, s.Struct)
|
|
return p, err
|
|
}
|
|
|
|
type TunnelRegistration struct {
|
|
SuccessfulTunnelRegistration
|
|
Err string
|
|
PermanentFailure bool
|
|
RetryAfterSeconds uint16
|
|
}
|
|
|
|
type SuccessfulTunnelRegistration struct {
|
|
Url string
|
|
LogLines []string
|
|
TunnelID string `capnp:"tunnelID"`
|
|
EventDigest []byte
|
|
ConnDigest []byte
|
|
}
|
|
|
|
func NewSuccessfulTunnelRegistration(
|
|
url string,
|
|
logLines []string,
|
|
tunnelID string,
|
|
eventDigest []byte,
|
|
connDigest []byte,
|
|
) *TunnelRegistration {
|
|
// Marshal nil will result in an error
|
|
if logLines == nil {
|
|
logLines = []string{}
|
|
}
|
|
return &TunnelRegistration{
|
|
SuccessfulTunnelRegistration: SuccessfulTunnelRegistration{
|
|
Url: url,
|
|
LogLines: logLines,
|
|
TunnelID: tunnelID,
|
|
EventDigest: eventDigest,
|
|
ConnDigest: connDigest,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Not calling this function Error() to avoid confusion with implementing error interface
|
|
func (tr TunnelRegistration) DeserializeError() TunnelRegistrationError {
|
|
if tr.Err != "" {
|
|
err := fmt.Errorf(tr.Err)
|
|
if tr.PermanentFailure {
|
|
return NewPermanentRegistrationError(err)
|
|
}
|
|
retryAfterSeconds := tr.RetryAfterSeconds
|
|
if retryAfterSeconds < defaultRetryAfterSeconds {
|
|
retryAfterSeconds = defaultRetryAfterSeconds
|
|
}
|
|
return NewRetryableRegistrationError(err, retryAfterSeconds)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type TunnelRegistrationError interface {
|
|
error
|
|
Serialize() *TunnelRegistration
|
|
IsPermanent() bool
|
|
}
|
|
|
|
type PermanentRegistrationError struct {
|
|
err string
|
|
}
|
|
|
|
func NewPermanentRegistrationError(err error) TunnelRegistrationError {
|
|
return &PermanentRegistrationError{
|
|
err: err.Error(),
|
|
}
|
|
}
|
|
|
|
func (pre *PermanentRegistrationError) Error() string {
|
|
return pre.err
|
|
}
|
|
|
|
func (pre *PermanentRegistrationError) Serialize() *TunnelRegistration {
|
|
return &TunnelRegistration{
|
|
Err: pre.err,
|
|
PermanentFailure: true,
|
|
}
|
|
}
|
|
|
|
func (*PermanentRegistrationError) IsPermanent() bool {
|
|
return true
|
|
}
|
|
|
|
type RetryableRegistrationError struct {
|
|
err string
|
|
retryAfterSeconds uint16
|
|
}
|
|
|
|
func NewRetryableRegistrationError(err error, retryAfterSeconds uint16) TunnelRegistrationError {
|
|
return &RetryableRegistrationError{
|
|
err: err.Error(),
|
|
retryAfterSeconds: retryAfterSeconds,
|
|
}
|
|
}
|
|
|
|
func (rre *RetryableRegistrationError) Error() string {
|
|
return rre.err
|
|
}
|
|
|
|
func (rre *RetryableRegistrationError) Serialize() *TunnelRegistration {
|
|
return &TunnelRegistration{
|
|
Err: rre.err,
|
|
PermanentFailure: false,
|
|
RetryAfterSeconds: rre.retryAfterSeconds,
|
|
}
|
|
}
|
|
|
|
func (*RetryableRegistrationError) IsPermanent() bool {
|
|
return false
|
|
}
|
|
|
|
func MarshalTunnelRegistration(s proto.TunnelRegistration, p *TunnelRegistration) error {
|
|
return pogs.Insert(proto.TunnelRegistration_TypeID, s.Struct, p)
|
|
}
|
|
|
|
func UnmarshalTunnelRegistration(s proto.TunnelRegistration) (*TunnelRegistration, error) {
|
|
p := new(TunnelRegistration)
|
|
err := pogs.Extract(p, proto.TunnelRegistration_TypeID, s.Struct)
|
|
return p, err
|
|
}
|
|
|
|
type RegistrationOptions struct {
|
|
ClientID string `capnp:"clientId"`
|
|
Version string
|
|
OS string `capnp:"os"`
|
|
ExistingTunnelPolicy proto.ExistingTunnelPolicy
|
|
PoolName string `capnp:"poolName"`
|
|
Tags []Tag
|
|
ConnectionID uint8 `capnp:"connectionId"`
|
|
OriginLocalIP string `capnp:"originLocalIp"`
|
|
IsAutoupdated bool `capnp:"isAutoupdated"`
|
|
RunFromTerminal bool `capnp:"runFromTerminal"`
|
|
CompressionQuality uint64 `capnp:"compressionQuality"`
|
|
UUID string `capnp:"uuid"`
|
|
NumPreviousAttempts uint8
|
|
Features []string
|
|
}
|
|
|
|
func MarshalRegistrationOptions(s proto.RegistrationOptions, p *RegistrationOptions) error {
|
|
return pogs.Insert(proto.RegistrationOptions_TypeID, s.Struct, p)
|
|
}
|
|
|
|
func UnmarshalRegistrationOptions(s proto.RegistrationOptions) (*RegistrationOptions, error) {
|
|
p := new(RegistrationOptions)
|
|
err := pogs.Extract(p, proto.RegistrationOptions_TypeID, s.Struct)
|
|
return p, err
|
|
}
|
|
|
|
type Tag struct {
|
|
Name string `json:"name"`
|
|
Value string `json:"value"`
|
|
}
|
|
|
|
type ServerInfo struct {
|
|
LocationName string
|
|
}
|
|
|
|
func MarshalServerInfo(s proto.ServerInfo, p *ServerInfo) error {
|
|
return pogs.Insert(proto.ServerInfo_TypeID, s.Struct, p)
|
|
}
|
|
|
|
func UnmarshalServerInfo(s proto.ServerInfo) (*ServerInfo, error) {
|
|
p := new(ServerInfo)
|
|
err := pogs.Extract(p, proto.ServerInfo_TypeID, s.Struct)
|
|
return p, err
|
|
}
|
|
|
|
type TunnelServer interface {
|
|
RegistrationServer
|
|
RegisterTunnel(ctx context.Context, originCert []byte, hostname string, options *RegistrationOptions) *TunnelRegistration
|
|
GetServerInfo(ctx context.Context) (*ServerInfo, error)
|
|
UnregisterTunnel(ctx context.Context, gracePeriodNanoSec int64) error
|
|
Authenticate(ctx context.Context, originCert []byte, hostname string, options *RegistrationOptions) (*AuthenticateResponse, error)
|
|
ReconnectTunnel(ctx context.Context, jwt, eventDigest, connDigest []byte, hostname string, options *RegistrationOptions) (*TunnelRegistration, error)
|
|
}
|
|
|
|
func TunnelServer_ServerToClient(s TunnelServer) proto.TunnelServer {
|
|
return proto.TunnelServer_ServerToClient(TunnelServer_PogsImpl{RegistrationServer_PogsImpl{s}, s})
|
|
}
|
|
|
|
type TunnelServer_PogsImpl struct {
|
|
RegistrationServer_PogsImpl
|
|
impl TunnelServer
|
|
}
|
|
|
|
func (i TunnelServer_PogsImpl) RegisterTunnel(p proto.TunnelServer_registerTunnel) error {
|
|
originCert, err := p.Params.OriginCert()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hostname, err := p.Params.Hostname()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
options, err := p.Params.Options()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pogsOptions, err := UnmarshalRegistrationOptions(options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
server.Ack(p.Options)
|
|
registration := i.impl.RegisterTunnel(p.Ctx, originCert, hostname, pogsOptions)
|
|
|
|
result, err := p.Results.NewResult()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return MarshalTunnelRegistration(result, registration)
|
|
}
|
|
|
|
func (i TunnelServer_PogsImpl) GetServerInfo(p proto.TunnelServer_getServerInfo) error {
|
|
server.Ack(p.Options)
|
|
serverInfo, err := i.impl.GetServerInfo(p.Ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result, err := p.Results.NewResult()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return MarshalServerInfo(result, serverInfo)
|
|
}
|
|
|
|
func (i TunnelServer_PogsImpl) UnregisterTunnel(p proto.TunnelServer_unregisterTunnel) error {
|
|
gracePeriodNanoSec := p.Params.GracePeriodNanoSec()
|
|
server.Ack(p.Options)
|
|
return i.impl.UnregisterTunnel(p.Ctx, gracePeriodNanoSec)
|
|
}
|
|
|
|
func (i TunnelServer_PogsImpl) ObsoleteDeclarativeTunnelConnect(p proto.TunnelServer_obsoleteDeclarativeTunnelConnect) error {
|
|
return fmt.Errorf("RPC to create declarative tunnel connection has been deprecated")
|
|
}
|
|
|
|
type TunnelServer_PogsClient struct {
|
|
RegistrationServer_PogsClient
|
|
Client capnp.Client
|
|
Conn *rpc.Conn
|
|
}
|
|
|
|
func (c TunnelServer_PogsClient) Close() error {
|
|
c.Client.Close()
|
|
return c.Conn.Close()
|
|
}
|
|
|
|
func (c TunnelServer_PogsClient) RegisterTunnel(ctx context.Context, originCert []byte, hostname string, options *RegistrationOptions) *TunnelRegistration {
|
|
client := proto.TunnelServer{Client: c.Client}
|
|
promise := client.RegisterTunnel(ctx, func(p proto.TunnelServer_registerTunnel_Params) error {
|
|
err := p.SetOriginCert(originCert)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = p.SetHostname(hostname)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
registrationOptions, err := p.NewOptions()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = MarshalRegistrationOptions(registrationOptions, options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
retval, err := promise.Result().Struct()
|
|
if err != nil {
|
|
return NewRetryableRegistrationError(err, defaultRetryAfterSeconds).Serialize()
|
|
}
|
|
registration, err := UnmarshalTunnelRegistration(retval)
|
|
if err != nil {
|
|
return NewRetryableRegistrationError(err, defaultRetryAfterSeconds).Serialize()
|
|
}
|
|
return registration
|
|
}
|
|
|
|
func (c TunnelServer_PogsClient) GetServerInfo(ctx context.Context) (*ServerInfo, error) {
|
|
client := proto.TunnelServer{Client: c.Client}
|
|
promise := client.GetServerInfo(ctx, func(p proto.TunnelServer_getServerInfo_Params) error {
|
|
return nil
|
|
})
|
|
retval, err := promise.Result().Struct()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return UnmarshalServerInfo(retval)
|
|
}
|
|
|
|
func (c TunnelServer_PogsClient) UnregisterTunnel(ctx context.Context, gracePeriodNanoSec int64) error {
|
|
client := proto.TunnelServer{Client: c.Client}
|
|
promise := client.UnregisterTunnel(ctx, func(p proto.TunnelServer_unregisterTunnel_Params) error {
|
|
p.SetGracePeriodNanoSec(gracePeriodNanoSec)
|
|
return nil
|
|
})
|
|
_, err := promise.Struct()
|
|
return err
|
|
}
|