From fb4ae1db8570a93fd6414cd763a7ac6e4e631239 Mon Sep 17 00:00:00 2001 From: cloudflare-warp-bot Date: Wed, 4 Apr 2018 15:47:36 +0000 Subject: [PATCH] Release Argo Tunnel Client 2018.4.1 --- cmd/cloudflared/macos_service.go | 6 +- cmd/cloudflared/main.go | 136 ++++++++------ origin/supervisor.go | 13 +- origin/tunnel.go | 46 ++++- tunnelrpc/pogs/tunnelrpc.go | 19 ++ tunnelrpc/tunnelrpc.capnp | 1 + tunnelrpc/tunnelrpc.capnp.go | 309 +++++++++++++++++++++++-------- 7 files changed, 385 insertions(+), 145 deletions(-) diff --git a/cmd/cloudflared/macos_service.go b/cmd/cloudflared/macos_service.go index 9278d1af..e283a35e 100644 --- a/cmd/cloudflared/macos_service.go +++ b/cmd/cloudflared/macos_service.go @@ -39,8 +39,10 @@ var launchdTemplate = ServiceTemplate{ Label %s - Program - {{ .Path }} + ProgramArguments + + {{ .Path }} + RunAtLoad StandardOutPath diff --git a/cmd/cloudflared/main.go b/cmd/cloudflared/main.go index 46905e4c..4a1a3dd0 100644 --- a/cmd/cloudflared/main.go +++ b/cmd/cloudflared/main.go @@ -53,8 +53,9 @@ var BuildTime = "unknown" var Log *logrus.Logger var defaultConfigFiles = []string{"config.yml", "config.yaml"} +// Launchd doesn't set root env variables, so there is default // Windows default config dir was ~/cloudflare-warp in documentation; let's keep it compatible -var defaultConfigDirs = []string{"~/.cloudflared", "~/.cloudflare-warp", "~/cloudflare-warp"} +var defaultConfigDirs = []string{"~/.cloudflared", "~/.cloudflare-warp", "~/cloudflare-warp", "/usr/local/etc/cloudflared", "/etc/cloudflared"} // Shutdown channel used by the app. When closed, app must terminate. // May be closed by the Windows service runner. @@ -74,6 +75,7 @@ func main() { raven.SetDSN(sentryDSN) raven.SetRelease(Version) shutdownC = make(chan struct{}) + app := &cli.App{} app.Name = "cloudflared" app.Copyright = fmt.Sprintf(`(c) %d Cloudflare Inc. @@ -299,24 +301,31 @@ func main() { EnvVars: []string{"TUNNEL_SKIP_HOSTNAME_PROPAGATION_CHECK"}, }), altsrc.NewUintFlag(&cli.UintFlag{ - Name: "hostname-propagated-retries", - Usage: "How many pings to test whether send DNS record has been propagated before reregistering tunnel", - Value: 25, + Name: "hostname-propagated-retries", + Usage: "How many pings to test whether send DNS record has been propagated before reregistering tunnel", + Value: 25, EnvVars: []string{"TUNNEL_HOSTNAME_PROPAGATED_RETRIES"}, }), altsrc.NewDurationFlag(&cli.DurationFlag{ - Name: "init-wait-time", - Usage: "Initial waiting time to checking whether DNS record has propagated", - Value: minDNSInitWait, + Name: "init-wait-time", + Usage: "Initial waiting time to checking whether DNS record has propagated", + Value: minDNSInitWait, EnvVars: []string{"TUNNEL_INIT_WAIT_TIME"}, - Hidden: true, + Hidden: true, }), altsrc.NewDurationFlag(&cli.DurationFlag{ - Name: "ping-freq", - Usage: "Ping frequency for checking DNS record has propagated", - Value: minPingFreq, + Name: "ping-freq", + Usage: "Ping frequency for checking DNS record has propagated", + Value: minPingFreq, EnvVars: []string{"TUNNEL_PING_FREQ"}, - Hidden: true, + Hidden: true, + }), + altsrc.NewDurationFlag(&cli.DurationFlag{ + Name: "grace-period", + Usage: "Duration to accpet new requests after cloudflared receives first SIGINT/SIGTERM. A second SIGINT/SIGTERM will force cloudflared to shutdown immediately.", + Value: time.Second * 30, + EnvVars: []string{"TUNNEL_GRACE_PERIOD"}, + Hidden: true, }), } app.Action = func(c *cli.Context) error { @@ -415,6 +424,7 @@ func main() { func startServer(c *cli.Context) { var wg sync.WaitGroup errC := make(chan error) + connectedSignal := make(chan struct{}) wg.Add(2) // If the user choose to supply all options through env variables, @@ -452,6 +462,33 @@ func startServer(c *cli.Context) { go autoupdate(c.Duration("autoupdate-freq"), shutdownC) } + if c.IsSet("proxy-dns") { + wg.Add(1) + listener, err := tunneldns.CreateListener(c.String("proxy-dns-address"), uint16(c.Uint("proxy-dns-port")), c.StringSlice("proxy-dns-upstream")) + if err != nil { + listener.Stop() + Log.WithError(err).Fatal("Cannot create the DNS over HTTPS proxy server") + } + go func() { + err := listener.Start() + if err != nil { + Log.WithError(err).Fatal("Cannot start the DNS over HTTPS proxy server") + } else { + <-shutdownC + } + listener.Stop() + wg.Done() + }() + + // Serve DNS proxy stand-alone if no hostname or tag or app is going to run + if !c.IsSet("hostname") && !c.IsSet("tag") && !c.IsSet("hello-world") { + go writePidFile(connectedSignal, c.String("pidfile")) + close(connectedSignal) + runServer(c, &wg, errC, shutdownC) + return + } + } + hostname, err := validation.ValidateHostname(c.String("hostname")) if err != nil { Log.WithError(err).Fatal("Invalid hostname") @@ -482,25 +519,6 @@ func startServer(c *cli.Context) { c.Set("url", "https://"+listener.Addr().String()) } - if c.IsSet("proxy-dns") { - wg.Add(1) - listener, err := tunneldns.CreateListener(c.String("proxy-dns-address"), uint16(c.Uint("proxy-dns-port")), c.StringSlice("proxy-dns-upstream")) - if err != nil { - listener.Stop() - Log.WithError(err).Fatal("Cannot create the DNS over HTTPS proxy server") - } - go func() { - err := listener.Start() - if err != nil { - Log.WithError(err).Fatal("Cannot start the DNS over HTTPS proxy server") - } else { - <-shutdownC - } - listener.Stop() - wg.Done() - }() - } - url, err := validateUrl(c) if err != nil { Log.WithError(err).Fatal("Error validating url") @@ -558,29 +576,29 @@ If you don't have a certificate signed by Cloudflare, run the command: } tunnelConfig := &origin.TunnelConfig{ - EdgeAddrs: c.StringSlice("edge"), - OriginUrl: url, - Hostname: hostname, - OriginCert: originCert, - TlsConfig: tlsconfig.CreateTunnelConfig(c, c.StringSlice("edge")), - ClientTlsConfig: httpTransport.TLSClientConfig, - Retries: c.Uint("retries"), - HeartbeatInterval: c.Duration("heartbeat-interval"), - MaxHeartbeats: c.Uint64("heartbeat-count"), - ClientID: clientID, - ReportedVersion: Version, - LBPool: c.String("lb-pool"), - Tags: tags, - HAConnections: c.Int("ha-connections"), - HTTPTransport: httpTransport, - Metrics: tunnelMetrics, - MetricsUpdateFreq: c.Duration("metrics-update-freq"), - ProtocolLogger: protoLogger, - Logger: Log, - IsAutoupdated: c.Bool("is-autoupdated"), + EdgeAddrs: c.StringSlice("edge"), + OriginUrl: url, + Hostname: hostname, + OriginCert: originCert, + TlsConfig: tlsconfig.CreateTunnelConfig(c, c.StringSlice("edge")), + ClientTlsConfig: httpTransport.TLSClientConfig, + Retries: c.Uint("retries"), + HeartbeatInterval: c.Duration("heartbeat-interval"), + MaxHeartbeats: c.Uint64("heartbeat-count"), + ClientID: clientID, + ReportedVersion: Version, + LBPool: c.String("lb-pool"), + Tags: tags, + HAConnections: c.Int("ha-connections"), + HTTPTransport: httpTransport, + Metrics: tunnelMetrics, + MetricsUpdateFreq: c.Duration("metrics-update-freq"), + ProtocolLogger: protoLogger, + Logger: Log, + IsAutoupdated: c.Bool("is-autoupdated"), + GracePeriod: c.Duration("grace-period"), DNSValidationConfig: getDNSValidationConfig(c), } - connectedSignal := make(chan struct{}) go writePidFile(connectedSignal, c.String("pidfile")) go func() { @@ -588,6 +606,10 @@ If you don't have a certificate signed by Cloudflare, run the command: wg.Done() }() + runServer(c, &wg, errC, shutdownC) +} + +func runServer(c *cli.Context, wg *sync.WaitGroup, errC chan error, shutdownC chan struct{}) { metricsListener, err := listeners.Listen("tcp", c.String("metrics")) if err != nil { Log.WithError(err).Fatal("Error opening metrics server listener") @@ -619,6 +641,7 @@ func WaitForSignal(errC chan error, shutdownC chan struct{}) error { signals := make(chan os.Signal, 10) signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT) defer signal.Stop(signals) + select { case err := <-errC: close(shutdownC) @@ -627,6 +650,7 @@ func WaitForSignal(errC chan error, shutdownC chan struct{}) error { close(shutdownC) case <-shutdownC: } + return nil } @@ -708,7 +732,7 @@ func findDefaultConfigPath() string { for _, configFile := range defaultConfigFiles { dirPath, err := homedir.Expand(configDir) if err != nil { - return "" + continue } path := filepath.Join(dirPath, configFile) if ok, _ := fileExists(path); ok { @@ -828,9 +852,9 @@ func isAutoupdateEnabled(c *cli.Context) bool { func getDNSValidationConfig(c *cli.Context) *origin.DNSValidationConfig { dnsValidationConfig := &origin.DNSValidationConfig{ VerifyDNSPropagated: !c.Bool("skip-hostname-propagation-check"), - DNSPingRetries: c.Uint("hostname-propagated-retries"), - DNSInitWaitTime: c.Duration("init-wait-time"), - PingFreq: c.Duration("ping-freq"), + DNSPingRetries: c.Uint("hostname-propagated-retries"), + DNSInitWaitTime: c.Duration("init-wait-time"), + PingFreq: c.Duration("ping-freq"), } if dnsValidationConfig.DNSInitWaitTime < minDNSInitWait { dnsValidationConfig.DNSInitWaitTime = minDNSInitWait diff --git a/origin/supervisor.go b/origin/supervisor.go index 5856d427..6465f294 100644 --- a/origin/supervisor.go +++ b/origin/supervisor.go @@ -6,8 +6,8 @@ import ( "net/http" "time" - "golang.org/x/net/context" "github.com/pkg/errors" + "golang.org/x/net/context" ) const ( @@ -59,19 +59,21 @@ func (s *Supervisor) Run(ctx context.Context, connectedSignal chan struct{}) err var tunnelsWaiting []int backoff := BackoffHandler{MaxRetries: s.config.Retries, BaseTime: tunnelRetryDuration, RetryForever: true} var backoffTimer <-chan time.Time + tunnelsActive := s.config.HAConnections for { select { // Context cancelled case <-ctx.Done(): - for len(s.tunnelErrors) > 0 { + for tunnelsActive > 0 { <-s.tunnelErrors + tunnelsActive-- } - return nil // startTunnel returned with error // (note that this may also be caused by context cancellation) case tunnelError := <-s.tunnelErrors: + tunnelsActive-- if tunnelError.err != nil { Log.WithError(tunnelError.err).Warn("Tunnel disconnected due to error") tunnelsWaiting = append(tunnelsWaiting, tunnelError.index) @@ -96,6 +98,7 @@ func (s *Supervisor) Run(ctx context.Context, connectedSignal chan struct{}) err for _, index := range tunnelsWaiting { go s.startTunnel(ctx, index, s.newConnectedTunnelSignal(index)) } + tunnelsActive += len(tunnelsWaiting) tunnelsWaiting = nil // Tunnel successfully connected case <-s.nextConnectedSignal: @@ -217,7 +220,7 @@ func (s *Supervisor) verifyDNSPropagated(ctx context.Context) (err error) { } func (s *Supervisor) createPingRequestAndClient() (*http.Request, *http.Client, error) { - url := fmt.Sprintf("https://%s",s.config.Hostname) + url := fmt.Sprintf("https://%s", s.config.Hostname) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, nil, err @@ -225,7 +228,7 @@ func (s *Supervisor) createPingRequestAndClient() (*http.Request, *http.Client, req.Header.Add(CloudflaredPingHeader, s.config.ClientID) transport := s.config.HTTPTransport if transport == nil { - transport = http.DefaultTransport + transport = http.DefaultTransport } return req, &http.Client{Transport: transport}, nil } diff --git a/origin/tunnel.go b/origin/tunnel.go index b68b5002..d18b6413 100644 --- a/origin/tunnel.go +++ b/origin/tunnel.go @@ -39,10 +39,10 @@ const ( ) type DNSValidationConfig struct { - VerifyDNSPropagated bool - DNSPingRetries uint - DNSInitWaitTime time.Duration - PingFreq time.Duration + VerifyDNSPropagated bool + DNSPingRetries uint + DNSInitWaitTime time.Duration + PingFreq time.Duration } type TunnelConfig struct { @@ -66,6 +66,7 @@ type TunnelConfig struct { ProtocolLogger *logrus.Logger Logger *logrus.Logger IsAutoupdated bool + GracePeriod time.Duration *DNSValidationConfig } @@ -211,6 +212,8 @@ func ServeTunnel( for { select { case <-serveCtx.Done(): + // UnregisterTunnel blocks until the RPC call returns + UnregisterTunnel(handler.muxer, config.GracePeriod) handler.muxer.Shutdown() return case <-updateMetricsTickC: @@ -256,7 +259,7 @@ func IsRPCStreamResponse(headers []h2mux.Header) bool { func RegisterTunnel(ctx context.Context, muxer *h2mux.Muxer, config *TunnelConfig, connectionID uint8, originLocalIP string) error { logger := Log.WithField("subsystem", "rpc") - logger.Debug("initiating RPC stream") + logger.Debug("initiating RPC stream to register") stream, err := muxer.OpenStream([]h2mux.Header{ {Name: ":method", Value: "RPC"}, {Name: ":scheme", Value: "capnp"}, @@ -309,6 +312,35 @@ func RegisterTunnel(ctx context.Context, muxer *h2mux.Muxer, config *TunnelConfi return nil } +func UnregisterTunnel(muxer *h2mux.Muxer, gracePeriod time.Duration) error { + logger := Log.WithField("subsystem", "rpc") + logger.Debug("initiating RPC stream to unregister") + stream, err := muxer.OpenStream([]h2mux.Header{ + {Name: ":method", Value: "RPC"}, + {Name: ":scheme", Value: "capnp"}, + {Name: ":path", Value: "*"}, + }, nil) + if err != nil { + // RPC stream open error + raven.CaptureError(err, nil) + return err + } + if !IsRPCStreamResponse(stream.Headers) { + // stream response error + raven.CaptureError(err, nil) + return err + } + ctx := context.Background() + conn := rpc.NewConn( + tunnelrpc.NewTransportLogger(logger, rpc.StreamTransport(stream)), + tunnelrpc.ConnLog(logger.WithField("subsystem", "rpc-transport")), + ) + defer conn.Close() + ts := tunnelpogs.TunnelServer_PogsClient{Client: conn.Bootstrap(ctx)} + // gracePeriod is encoded in int64 using capnproto + return ts.UnregisterTunnel(ctx, gracePeriod.Nanoseconds()) +} + func LogServerInfo(logger *logrus.Entry, promise tunnelrpc.ServerInfo_Promise, connectionID uint8, @@ -369,7 +401,6 @@ func FindCfRayHeader(h1 *http.Request) string { return h1.Header.Get("Cf-Ray") } - type TunnelHandler struct { originUrl string muxer *h2mux.Muxer @@ -379,7 +410,7 @@ type TunnelHandler struct { metrics *tunnelMetrics // connectionID is only used by metrics, and prometheus requires labels to be string connectionID string - clientID string + clientID string } var dialer = net.Dialer{DualStack: true} @@ -516,7 +547,6 @@ func (h *TunnelHandler) logResponse(r *http.Response, cfRay string) { Log.Debugf("Response Headers %+v", r.Header) } - func (h *TunnelHandler) UpdateMetrics(connectionID string) { h.metrics.updateMuxerMetrics(connectionID, h.muxer.Metrics()) } diff --git a/tunnelrpc/pogs/tunnelrpc.go b/tunnelrpc/pogs/tunnelrpc.go index f70545b3..ab14060a 100644 --- a/tunnelrpc/pogs/tunnelrpc.go +++ b/tunnelrpc/pogs/tunnelrpc.go @@ -52,6 +52,7 @@ type RegistrationOptions struct { ConnectionID uint8 `capnp:"connectionId"` OriginLocalIP string `capnp:"originLocalIp"` IsAutoupdated bool `capnp:"isAutoupdated"` + gracePeriodNanoSec int64 `capnp:"gracePeriodNanoSec"` } func MarshalRegistrationOptions(s tunnelrpc.RegistrationOptions, p *RegistrationOptions) error { @@ -86,6 +87,7 @@ func UnmarshalServerInfo(s tunnelrpc.ServerInfo) (*ServerInfo, error) { type TunnelServer interface { RegisterTunnel(ctx context.Context, originCert []byte, hostname string, options *RegistrationOptions) (*TunnelRegistration, error) GetServerInfo(ctx context.Context) (*ServerInfo, error) + UnregisterTunnel(ctx context.Context, gracePeriodNanoSec int64) error } func TunnelServer_ServerToClient(s TunnelServer) tunnelrpc.TunnelServer { @@ -138,6 +140,13 @@ func (i TunnelServer_PogsImpl) GetServerInfo(p tunnelrpc.TunnelServer_getServerI return MarshalServerInfo(result, serverInfo) } +func (i TunnelServer_PogsImpl) UnregisterTunnel(p tunnelrpc.TunnelServer_unregisterTunnel) error { + gracePeriodNanoSec := p.Params.GracePeriodNanoSec() + server.Ack(p.Options) + return i.impl.UnregisterTunnel(p.Ctx, gracePeriodNanoSec) + +} + type TunnelServer_PogsClient struct { Client capnp.Client Conn *rpc.Conn @@ -186,3 +195,13 @@ func (c TunnelServer_PogsClient) GetServerInfo(ctx context.Context) (*ServerInfo } return UnmarshalServerInfo(retval) } + +func (c TunnelServer_PogsClient) UnregisterTunnel(ctx context.Context, gracePeriodNanoSec int64) error { + client := tunnelrpc.TunnelServer{Client: c.Client} + promise := client.UnregisterTunnel(ctx, func(p tunnelrpc.TunnelServer_unregisterTunnel_Params) error { + p.SetGracePeriodNanoSec(gracePeriodNanoSec) + return nil + }) + _, err := promise.Struct() + return err +} diff --git a/tunnelrpc/tunnelrpc.capnp b/tunnelrpc/tunnelrpc.capnp index 3886f534..d90ef200 100644 --- a/tunnelrpc/tunnelrpc.capnp +++ b/tunnelrpc/tunnelrpc.capnp @@ -57,4 +57,5 @@ struct ServerInfo { interface TunnelServer { registerTunnel @0 (originCert :Data, hostname :Text, options :RegistrationOptions) -> (result :TunnelRegistration); getServerInfo @1 () -> (result :ServerInfo); + unregisterTunnel @2 (gracePeriodNanoSec :Int64) -> (); } diff --git a/tunnelrpc/tunnelrpc.capnp.go b/tunnelrpc/tunnelrpc.capnp.go index e6d661de..0b54a66b 100644 --- a/tunnelrpc/tunnelrpc.capnp.go +++ b/tunnelrpc/tunnelrpc.capnp.go @@ -682,11 +682,33 @@ func (c TunnelServer) GetServerInfo(ctx context.Context, params func(TunnelServe } return TunnelServer_getServerInfo_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))} } +func (c TunnelServer) UnregisterTunnel(ctx context.Context, params func(TunnelServer_unregisterTunnel_Params) error, opts ...capnp.CallOption) TunnelServer_unregisterTunnel_Results_Promise { + if c.Client == nil { + return TunnelServer_unregisterTunnel_Results_Promise{Pipeline: capnp.NewPipeline(capnp.ErrorAnswer(capnp.ErrNullClient))} + } + call := &capnp.Call{ + Ctx: ctx, + Method: capnp.Method{ + InterfaceID: 0xea58385c65416035, + MethodID: 2, + InterfaceName: "tunnelrpc/tunnelrpc.capnp:TunnelServer", + MethodName: "unregisterTunnel", + }, + Options: capnp.NewCallOptions(opts), + } + if params != nil { + call.ParamsSize = capnp.ObjectSize{DataSize: 8, PointerCount: 0} + call.ParamsFunc = func(s capnp.Struct) error { return params(TunnelServer_unregisterTunnel_Params{Struct: s}) } + } + return TunnelServer_unregisterTunnel_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))} +} type TunnelServer_Server interface { RegisterTunnel(TunnelServer_registerTunnel) error GetServerInfo(TunnelServer_getServerInfo) error + + UnregisterTunnel(TunnelServer_unregisterTunnel) error } func TunnelServer_ServerToClient(s TunnelServer_Server) TunnelServer { @@ -696,7 +718,7 @@ func TunnelServer_ServerToClient(s TunnelServer_Server) TunnelServer { func TunnelServer_Methods(methods []server.Method, s TunnelServer_Server) []server.Method { if cap(methods) == 0 { - methods = make([]server.Method, 0, 2) + methods = make([]server.Method, 0, 3) } methods = append(methods, server.Method{ @@ -727,6 +749,20 @@ func TunnelServer_Methods(methods []server.Method, s TunnelServer_Server) []serv ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 1}, }) + methods = append(methods, server.Method{ + Method: capnp.Method{ + InterfaceID: 0xea58385c65416035, + MethodID: 2, + InterfaceName: "tunnelrpc/tunnelrpc.capnp:TunnelServer", + MethodName: "unregisterTunnel", + }, + Impl: func(c context.Context, opts capnp.CallOptions, p, r capnp.Struct) error { + call := TunnelServer_unregisterTunnel{c, opts, TunnelServer_unregisterTunnel_Params{Struct: p}, TunnelServer_unregisterTunnel_Results{Struct: r}} + return s.UnregisterTunnel(call) + }, + ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 0}, + }) + return methods } @@ -746,6 +782,14 @@ type TunnelServer_getServerInfo struct { Results TunnelServer_getServerInfo_Results } +// TunnelServer_unregisterTunnel holds the arguments for a server call to TunnelServer.unregisterTunnel. +type TunnelServer_unregisterTunnel struct { + Ctx context.Context + Options capnp.CallOptions + Params TunnelServer_unregisterTunnel_Params + Results TunnelServer_unregisterTunnel_Results +} + type TunnelServer_registerTunnel_Params struct{ capnp.Struct } // TunnelServer_registerTunnel_Params_TypeID is the unique identifier for the type TunnelServer_registerTunnel_Params. @@ -1066,83 +1110,200 @@ func (p TunnelServer_getServerInfo_Results_Promise) Result() ServerInfo_Promise return ServerInfo_Promise{Pipeline: p.Pipeline.GetPipeline(0)} } -const schema_db8274f9144abc7e = "x\xda\x9cUM\x88\x14W\x17\xbd\xe7\xbd\xee\xaa\x11z" + - "\xbe\x9e\xa2z@\x1b\xa4AF>\x95\x8c:Q\x83\x99" + - "H\xe6'j\xe8\xc9\x8c\xf6\x9b1\xc1\xbf\x80e\xf7\xb3" + - "\xa7&\xd5UMU\xb5\x89\x82\x9a\x88\x10\x08(1\x92" + - "E6Y\x08n\x02\xf9\xd9\x85@\x16f\x93,$d" + - "\x13\x02\x12\xb3\x89H@\x14\xc3` BB\x85W5" + - "\xd5]\x8eD\x83\xbb\xd7\xa7\xee\xbb\xf7\xdc{\xcf;\xbd" + - "\xf92\x1bg#\xf9My\"\xb1#\xafE;Z?" + - "\\~\xee\xc3k\xe7\xc8(\xb3\xe8\xf4\xd7S\xa5\x07\xe1" + - "\xd9\x9f\x89\xb0\xe5\x14;\x09\xf3\"\xd3\x89\xcc\xf3l/" + - "!\x1a\xac\xe2\xc6\xd5\x91\xdc\x97d\xfc\x1fDy\xae\x13" + - "m\xb9\xc2n\x83`~\xc5>'D\xab\xefN\xf6\xbb" + - "\xf7\xce^%\xa3\x8c^\xaa$\xf0\x00\x9f\x82\xd9RG" + - "\xd3\xe6*x\xea\xd0\xa5\x0f\xf2\xb7.}G\xa2\x8cl" + - "\xb4\xa6\xa2\xf39\x1f\xe6\xaa\x9c:\x0e\xe6\"\x10\xa2\xf2" + - "\x17/|6\xd9\xb8~mY\xee\x98\xde\x84\xb6h\xce" + - "\xa8{fU{\x93\x10\xb1[\xd6\xaa\xb7\x7fz\xf1F" + - "B4\xcerE\xfb\x15\x94\x8b\xf6\xbcvha\xc5\xa9" + - "\x9b7\x97Z\x80\xfa\xf4\x91\x16\xb7\xf0\xa96F\x88\xb6" + - "\x1d\x99\x90\x87\xb7\xef\xbfMF\x99?4\x8d\xef\xb5Q" + - "\x98\xbf\xc4E\xaek\xef\x9a#\xbaN\x14]8\xbds" + - "\xef\xf3k\xbeY\xcc\xa6[\xa5/\xaat\xc3\xbaJw" + - "l\xfb\x9d\x97\xd7^\xf8vq\x19\xeb8pF\xdf\x00" + - "\xf3u\x95\xc7<\xa0\x82\xef\xed\xfe\xf8\xc7r\xb1|\x7f" + - "\xd9<\xe2\xe9\x9d\xd2\x17`^\x8cc\xcf\xeb\xbf\xd1p" + - "\x14v\\W:~;W\xdf\x94\x1e\xeb\x1b\xebV\xdb" + - "m\x8f\xeez\xcb\x0eB\xdbm\xee\x8b\xf1\xb1\x9a\xe7\xd8" + - "\xf5\x135@\x14\xc0\x88\x8c\xd5\xa3D\x801x\x90\x08" + - "\xcc0&\x89\xc6\xec\xa6\xeb\xf92j\xd8A\xdds]" + - "I\xbc\x1e\x9e9j9\x96[\x97\xddB\xda\xa3\x85\x92" + - "\x02s\xd2?.\xfd\x8d\xbel\xdaA(\xfd\x04\x1c\xaa" + - "YE\xdfj\x05\xa2\xc0sD9\x10\x19\xbb\x0e\x12\x89" + - "\x9d\x1c\xa2\xc6`\x00%(pf\x8aHLs\x88\xfd" + - "\x0c\x06c\xa5\x98\xe1\xab\x93D\xa2\xc6!\x0e3D\x9e" + - "o7m\xf7%I\xdc\x0f\xd1O\x0c\xfd\x84h\xde\x0b" + - "B\xd7jI\"B\x81\x18\x0a\x843^;\xb4=7" + - "\xc0@OY\x04\x0c\x10\x1e7\xab\x89N8/\xdd\xd0" + - "\xae[\xea2Q<\xa6\x1e\xe55Db\x9cCLg" + - "(W\x9f\xcd\xf4\x91R\x9e9\xda\xebC\x7fC\x9eH" + - "YUd\xcb\xb2\x9d\xf4W\xda\xcc\x04\xe9\xaf\xf4b\x1e" + - "\xc7o6\x9e\xaa\x1f\xb3\xdb\xdb\xae\xc4\x1d*\x8eC]" + - "\x8ew\xd5\x04\xefp\x88?3\x1c\xffP\x13\xfc\x9dC" + - "\xfc\x95\xe1\xf8\xa0L$\xees\xcc\x82\x01\xbc\x04Nd" + - "\xfc\xfd\x09\xd1,8\xe6\x0a`0r\xbc\x84\x1c\x91\xb9" + - "\x02SDs}\x0a/)<\x9f+!Od\x1a\xd8" + - "@4WP\xf8:\x85k\xac\x04\x8d\xc8\\\x8b\x05\xa2" + - "\xb9!\x85oV\xb8\x9e/)\x85\x9b\xc3\xf0\x89\xe6\x9e" + - "Q\xf8v\x85\xf7\xad,\xa1\x8f\xc8\xdc\x16\xe3[\x15>" + - "\x0e\x86\xa8\xee\xd8\xd2\x0d\xab\x8d\xec:\x8fK?\xb0=" + - "7\xfd\xcd\xbd\xa0;/\xb9$p$Z\xabyE\xa5" + - "p\x14{VF@\x91\x10\xb5=\xcf\xd9\xf3\xb0L\x8a" + - "\xa1\xd5\x0c\xf0?B\x8d\x03\x03=W!(0\x8a\xf5" + - "_\x0fm*zn\xb5\x01\x8d\x18\xb4\xee\xde\xa6=\xaa" + - "\xd4-\xa7\xda\xee2\xb1\x83\x89N\xe8u\xdaTiX" + - "\xa1l\x00\xc4\x80\xccF\xd9\xf2\x8dV\xda\xa3\xfb\xac\xa6" + - "\xda`_w\x83\xeb7\x10\x89!\x0e\xb19\xb3\xc1a" + - "\xa5\xb2u\x1cb+CQI\xbd\xab\xa8\xe3\x96\xd3\x91" + - "\x8fh\xe7I\xcf\xb3)\xc3\xe4Tu\x8fyC5\xcb" + - "\xd7\xadV\xf0\x94\xb7geP\xec8a r\xdd\x1e" + - "\xfaG\x89D\x1f\x87(1\x8c\xf92\xe88!\x06z" + - "\xee\xb7\xec!\xf2\x7f+7\x96TI\xe6\x93'\xea\xfe" + - "\xe5 uZc\xe4$1c\xbd\x8e\x9e\xcb#5u" + - "c\xb5O\xcc\x18\xd4\xa3\xd4\x8bh,I;\x8e(\xed" + - "\x80*q\x0f\xe3\xa8\x01O\xebm\xb3\xb2\x12\xfc\x97\xfe" + - "SC\x7fr\xf7I\x9d\xa2b\xa6z\xcf\xe4] \x12" + - "\x05\x0e\xb1\x92!r\xbc%\x9b*\xee\xc9\x08\xe2q\xf6" + - "\x91\x10NM\xa4\xa8.\xab\xfc\x03\xdd\xfc\x96r\xb8\xc3" + - "\x1cb>\xa3=\xa9\xc0#\x1c\xc2\xc9\xb8\x87\xad|f" + - "\x9eC\x9c\xeb\xb9\xc7;\xef\x11\x89s\x1c\xe2}\x06]" + - "\xfa~JI\xef\xf8=\xcfs\xbc\xe6\xb4\xed\xca@=" + - "\xc2\xa5w\xa7>\xa9\xd7\xd6\x96~\xcbr\xa5\x8bp\xb7" + - "e;\x1d_*\xa1$O\xe8\x9f\x00\x00\x00\xff\xff\x0d" + - "v6\xc6" +type TunnelServer_unregisterTunnel_Params struct{ capnp.Struct } + +// TunnelServer_unregisterTunnel_Params_TypeID is the unique identifier for the type TunnelServer_unregisterTunnel_Params. +const TunnelServer_unregisterTunnel_Params_TypeID = 0x9b87b390babc2ccf + +func NewTunnelServer_unregisterTunnel_Params(s *capnp.Segment) (TunnelServer_unregisterTunnel_Params, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return TunnelServer_unregisterTunnel_Params{st}, err +} + +func NewRootTunnelServer_unregisterTunnel_Params(s *capnp.Segment) (TunnelServer_unregisterTunnel_Params, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) + return TunnelServer_unregisterTunnel_Params{st}, err +} + +func ReadRootTunnelServer_unregisterTunnel_Params(msg *capnp.Message) (TunnelServer_unregisterTunnel_Params, error) { + root, err := msg.RootPtr() + return TunnelServer_unregisterTunnel_Params{root.Struct()}, err +} + +func (s TunnelServer_unregisterTunnel_Params) String() string { + str, _ := text.Marshal(0x9b87b390babc2ccf, s.Struct) + return str +} + +func (s TunnelServer_unregisterTunnel_Params) GracePeriodNanoSec() int64 { + return int64(s.Struct.Uint64(0)) +} + +func (s TunnelServer_unregisterTunnel_Params) SetGracePeriodNanoSec(v int64) { + s.Struct.SetUint64(0, uint64(v)) +} + +// TunnelServer_unregisterTunnel_Params_List is a list of TunnelServer_unregisterTunnel_Params. +type TunnelServer_unregisterTunnel_Params_List struct{ capnp.List } + +// NewTunnelServer_unregisterTunnel_Params creates a new list of TunnelServer_unregisterTunnel_Params. +func NewTunnelServer_unregisterTunnel_Params_List(s *capnp.Segment, sz int32) (TunnelServer_unregisterTunnel_Params_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) + return TunnelServer_unregisterTunnel_Params_List{l}, err +} + +func (s TunnelServer_unregisterTunnel_Params_List) At(i int) TunnelServer_unregisterTunnel_Params { + return TunnelServer_unregisterTunnel_Params{s.List.Struct(i)} +} + +func (s TunnelServer_unregisterTunnel_Params_List) Set(i int, v TunnelServer_unregisterTunnel_Params) error { + return s.List.SetStruct(i, v.Struct) +} + +// TunnelServer_unregisterTunnel_Params_Promise is a wrapper for a TunnelServer_unregisterTunnel_Params promised by a client call. +type TunnelServer_unregisterTunnel_Params_Promise struct{ *capnp.Pipeline } + +func (p TunnelServer_unregisterTunnel_Params_Promise) Struct() (TunnelServer_unregisterTunnel_Params, error) { + s, err := p.Pipeline.Struct() + return TunnelServer_unregisterTunnel_Params{s}, err +} + +type TunnelServer_unregisterTunnel_Results struct{ capnp.Struct } + +// TunnelServer_unregisterTunnel_Results_TypeID is the unique identifier for the type TunnelServer_unregisterTunnel_Results. +const TunnelServer_unregisterTunnel_Results_TypeID = 0xa29a916d4ebdd894 + +func NewTunnelServer_unregisterTunnel_Results(s *capnp.Segment) (TunnelServer_unregisterTunnel_Results, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return TunnelServer_unregisterTunnel_Results{st}, err +} + +func NewRootTunnelServer_unregisterTunnel_Results(s *capnp.Segment) (TunnelServer_unregisterTunnel_Results, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return TunnelServer_unregisterTunnel_Results{st}, err +} + +func ReadRootTunnelServer_unregisterTunnel_Results(msg *capnp.Message) (TunnelServer_unregisterTunnel_Results, error) { + root, err := msg.RootPtr() + return TunnelServer_unregisterTunnel_Results{root.Struct()}, err +} + +func (s TunnelServer_unregisterTunnel_Results) String() string { + str, _ := text.Marshal(0xa29a916d4ebdd894, s.Struct) + return str +} + +// TunnelServer_unregisterTunnel_Results_List is a list of TunnelServer_unregisterTunnel_Results. +type TunnelServer_unregisterTunnel_Results_List struct{ capnp.List } + +// NewTunnelServer_unregisterTunnel_Results creates a new list of TunnelServer_unregisterTunnel_Results. +func NewTunnelServer_unregisterTunnel_Results_List(s *capnp.Segment, sz int32) (TunnelServer_unregisterTunnel_Results_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) + return TunnelServer_unregisterTunnel_Results_List{l}, err +} + +func (s TunnelServer_unregisterTunnel_Results_List) At(i int) TunnelServer_unregisterTunnel_Results { + return TunnelServer_unregisterTunnel_Results{s.List.Struct(i)} +} + +func (s TunnelServer_unregisterTunnel_Results_List) Set(i int, v TunnelServer_unregisterTunnel_Results) error { + return s.List.SetStruct(i, v.Struct) +} + +// TunnelServer_unregisterTunnel_Results_Promise is a wrapper for a TunnelServer_unregisterTunnel_Results promised by a client call. +type TunnelServer_unregisterTunnel_Results_Promise struct{ *capnp.Pipeline } + +func (p TunnelServer_unregisterTunnel_Results_Promise) Struct() (TunnelServer_unregisterTunnel_Results, error) { + s, err := p.Pipeline.Struct() + return TunnelServer_unregisterTunnel_Results{s}, err +} + +const schema_db8274f9144abc7e = "x\xda\x9cU_\x88Te\x1b\x7f~\xef;3g\x84" + + "]g\x0fg\x04\xbf\xe1\x93\xe5\x93\x15\xff\xe0\xfa\xe9\xa7" + + "\xfb\xa1\xdb\x9f\xd9\xdd\xd4\x98m]\xe7\xdd\xd1\x10\xf5\xc2" + + "\xe3\xcc\xeb\xec\xd9f\xce\x19\xce9c)\xa4%B " + + "$\x96uc\x14\xe4e\x17\x15t\x11\x84\x81\xdd$\xe1" + + "\x85\x08\x19EB\x94l\xa1(\xd6\xa2\x90\x91\x9cx\xcf" + + "\xec\x999\xae\xa5\xd6\xdd9\xcf\xfb>\xcf\xf3{\xfe\xfc" + + "~\xef\xea\x1f\xd9\x10[\x93\xfc.I$6&S\xc1" + + "\xe3\xf5\x0b\xa7\xff\xff\xe6\xf9\xa3\xa4\xe7Xp\xe8\xcch" + + "\xf6\x8e\x7f\xe4[\"\xac\xbd\xc4\x0e\xc2\xb8\xca4\"c" + + "\x9am%\x04\x17V\x9e\xf9\xe4\xc4G\xaf\xbcEb)" + + "@\x94\xd0\x88\xd6\xdee\xbf\x81`\xe8n\x9d$\xb9:\xea\xe7\xd7" + + "\x94\xeb0\xff\x80\x10,\xba1\xd2m\xdf\xba\x89\xa1\x9b" + + "\x10L:\x9eo\x9buID\xe8\"\x86.\xc2a\xa7" + + "\xe1[\x8e\xed\xa1\xa7C\x07\x02zb-\xf8\x93\x01\x0f" + + "7\xfdIi\xfbV\xd9T\xceD\xe1l;\x90\x17\x13" + + "\x89!\x0e1\x16\x83\\\xf8_\xac\x8e\x08\xf2\x96\xbd\x9d" + + ":\xb4\xe7\xe4\x81\x08U\xaf\xac\x9bV-\xfa\x8b\x8a\x19" + + "&\xed\x99\xce\x9d\x07\xe1\x9b\x08\xbb\xea\x86\xe8\xb66z" + + "\xc3\x0a\x15\xc6\xbe6\xc6\x1b\xaa\x83\xd79\xc4\xaf1\x8c" + + "\xb7U\x07\x7f\xe6\x10\xbf\xc70\xde\xc9\x11\x89[\x1c\x13" + + "`\x00\xcf\x82\x13\xe9w\xdf#\x9a\x00G\xa9\x0b\x0cz" + + "\x82g\x91 2\xe6a\x94\xa8\x94V\xf6\xac\xb2'\x13" + + "Y$\x15\xb7\xb0\x82\xa8\xd4\xa5\xec\xcb\x94=\xc5\xb2H" + + "\x11\x19K0ET\xeaS\xf6\xd5\xca\xae%\xb3\x8a\x96" + + "F?\\\xa2\xd2Je_\xaf\xec\xe9\x85Y\xa4\x89\x8c" + + "\x81\xd0\xbeN\xd9\x87\xc0\x10\x94k\x96\xb4\xfdB%>" + + "\xce\xfd\xd2\xf5,\xc7\x8e\xfe\xb9\xe3\xb5\xfb%gY\x89" + + "\xd6\xae\x15\x9d\x8c\xa2%2\x1d\xe9& C\x08\x1a\x8e" + + "S\x1b\xbfwM2\xbeY\xf50\x9fP\xe4@OG" + + "\x0a\x09\xca\x18\x84\xa4-\xfb\x16e\x1c\xbbPA\x8a\x18" + + "R\xed\xb9\x8d9\xd4[6k\x85F\x1b\x89\xe5\x0d7" + + "}\xa7\xd9\xa0\xde\x8a\xe9\xcb\x0a@\x0c\x88M\x94\xcd\x9d" + + "hocp\x9bYU\x13L\xb7'\xb8|\x05\x91\xe8" + + "\xe3\x10\xabc\x13\xecW[\xb6\x8cC\xacc\xc8\xa8U" + + "oo\xd4~\xb3\xd6\x94\xf7\xed\xce\xc34\xa5*\xfd\xd6" + + "W\xc1\xde\xe7\xf4\x15MW3\xeb\xde?\xf4\x9e\x90^" + + "FIC\\\x8f\x06\x89D\x9aCd\x19\xf2n\xa8\x1c" + + "\xe8\xe9H\xf6\x1c\"\xf2\xbfJ\x97oei\xb10I" + + "\xd4~'\x11=\x0f\xba8HL/h\xe8\xa0\x81\xb5\x9ffDO\xb0\xbe" + + "\xfc\x181}\x89\x16D:E\xf9V\xca!\x04Qu" + + "\xd4\x1b\xd67\x84 \x12CDzF4\x84\"\x1e\xbd" + + "\xdd\xf7ii\xaf\xf7(\x1d\x8b\xde\xad\x87\xf7\xab\x95'" + + "\xa3\xf0\xaan\xc5\xe2N\x11\x89.\x0e\xb1\x90!\xa89" + + "\xb3\xc2\x96\x19\x8f\xad\xd0\x83\x04\xa7\x058\x92\x9d\x8cr" + + "V\xf1{\xda\xf1M\xa5\x89\xbb9\xc4dl[\xa52" + + "\xee\xe1\x10\xb5\x98\xdeXJ\x99&9\xc4\xd1\x8e\xde\xbc" + + "|\x8cH\x1c\xe5\x10'\x184\xe9\xba\x11$\xad\xe9v" + + "T\xb2\xe6T\xc7,[z\x8a\xb6\xb3LUG\x8a\x9f" + + "\x0d\xe9\xd6M[\xda\xf07\x9bV\xad\xe9J\xb5Z-" + + "\xd2\xfd\x11\x00\x00\xff\xffy%\x9bh" func init() { schemas.Register(schema_db8274f9144abc7e, 0x84cb9536a2cf6d3c, + 0x9b87b390babc2ccf, + 0xa29a916d4ebdd894, 0xb70431c0dc014915, 0xc082ef6e0d42ed1d, 0xc793e50592935b4a,