From f81b0ee9e85504861ee2b6d43e71f6174e1b6968 Mon Sep 17 00:00:00 2001 From: Devin Carr Date: Mon, 11 Apr 2022 12:57:50 -0700 Subject: [PATCH 1/9] TUN-5990: Add otlp span export to response header --- connection/http2.go | 6 ++++++ proxy/proxy.go | 15 +++++++++------ tracing/client.go | 5 +++-- tracing/tracing.go | 30 ++++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/connection/http2.go b/connection/http2.go index 67c67862..715c827c 100644 --- a/connection/http2.go +++ b/connection/http2.go @@ -231,6 +231,12 @@ func (rp *http2RespWriter) WriteRespHeaders(status int, header http.Header) erro dest[name] = values } + if h2name == tracing.IntCloudflaredTracingHeader { + // Add cf-int-cloudflared-tracing header outside of serialized userHeaders + rp.w.Header()[tracing.CanonicalCloudflaredTracingHeader] = values + continue + } + if !IsControlResponseHeader(h2name) || IsWebsocketClientHeader(h2name) { // User headers, on the other hand, must all be serialized so that // HTTP/2 header validation won't be applied to HTTP/1 header values diff --git a/proxy/proxy.go b/proxy/proxy.go index 76e11fe1..f24f0290 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -87,7 +87,7 @@ func (p *Proxy) ProxyHTTP( case ingress.HTTPOriginProxy: if err := p.proxyHTTPRequest( w, - req, + tr, originProxy, isWebsocket, rule.Config.DisableChunkedEncoding, @@ -159,15 +159,15 @@ func ruleField(ing ingress.Ingress, ruleNum int) (ruleID string, srv string) { // ProxyHTTPRequest proxies requests of underlying type http and websocket to the origin service. func (p *Proxy) proxyHTTPRequest( w connection.ResponseWriter, - req *http.Request, + tr *tracing.TracedRequest, httpService ingress.HTTPOriginProxy, isWebsocket bool, disableChunkedEncoding bool, fields logFields, ) error { - roundTripReq := req + roundTripReq := tr.Request if isWebsocket { - roundTripReq = req.Clone(req.Context()) + roundTripReq = tr.Request.Clone(tr.Request.Context()) roundTripReq.Header.Set("Connection", "Upgrade") roundTripReq.Header.Set("Upgrade", "websocket") roundTripReq.Header.Set("Sec-Websocket-Version", "13") @@ -177,7 +177,7 @@ func (p *Proxy) proxyHTTPRequest( // Support for WSGI Servers by switching transfer encoding from chunked to gzip/deflate if disableChunkedEncoding { roundTripReq.TransferEncoding = []string{"gzip", "deflate"} - cLength, err := strconv.Atoi(req.Header.Get("Content-Length")) + cLength, err := strconv.Atoi(tr.Request.Header.Get("Content-Length")) if err == nil { roundTripReq.ContentLength = int64(cLength) } @@ -197,6 +197,9 @@ func (p *Proxy) proxyHTTPRequest( } defer resp.Body.Close() + // Add spans to response header (if available) + tr.AddSpans(resp.Header, p.log) + err = w.WriteRespHeaders(resp.StatusCode, resp.Header) if err != nil { return errors.Wrap(err, "Error writing response header") @@ -211,7 +214,7 @@ func (p *Proxy) proxyHTTPRequest( eyeballStream := &bidirectionalStream{ writer: w, - reader: req.Body, + reader: tr.Request.Body, } websocket.Stream(eyeballStream, rwc, p.log) diff --git a/tracing/client.go b/tracing/client.go index 6783912e..5ed4efb3 100644 --- a/tracing/client.go +++ b/tracing/client.go @@ -16,7 +16,8 @@ const ( ) var ( - errNoTraces = errors.New("no traces recorded to be exported") + errNoTraces = errors.New("no traces recorded to be exported") + errNoopTracer = errors.New("noop tracer has no traces") ) type InMemoryClient interface { @@ -86,5 +87,5 @@ func (mc *NoopOtlpClient) UploadTraces(_ context.Context, _ []*tracepb.ResourceS // Spans always returns no traces error func (mc *NoopOtlpClient) Spans() (string, error) { - return "", errNoTraces + return "", errNoopTracer } diff --git a/tracing/tracing.go b/tracing/tracing.go index a35d2962..f124e367 100644 --- a/tracing/tracing.go +++ b/tracing/tracing.go @@ -5,6 +5,7 @@ import ( "errors" "net/http" + "github.com/rs/zerolog" otelContrib "go.opentelemetry.io/contrib/propagators/Jaeger" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -23,11 +24,14 @@ const ( tracerContextName = "cf-trace-id" tracerContextNameOverride = "uber-trace-id" + + IntCloudflaredTracingHeader = "cf-int-cloudflared-tracing" ) var ( - Http2TransportAttribute = trace.WithAttributes(TransportAttributeKey.String("http2")) - QuicTransportAttribute = trace.WithAttributes(TransportAttributeKey.String("quic")) + CanonicalCloudflaredTracingHeader = http.CanonicalHeaderKey(IntCloudflaredTracingHeader) + Http2TransportAttribute = trace.WithAttributes(TransportAttributeKey.String("http2")) + QuicTransportAttribute = trace.WithAttributes(TransportAttributeKey.String("quic")) TransportAttributeKey = attribute.Key("transport") TrafficAttributeKey = attribute.Key("traffic") @@ -75,8 +79,26 @@ func (cft *TracedRequest) Tracer() trace.Tracer { } // Spans returns the spans as base64 encoded protobuf otlp traces. -func (cft *TracedRequest) Spans() (string, error) { - return cft.exporter.Spans() +func (cft *TracedRequest) AddSpans(headers http.Header, log *zerolog.Logger) { + enc, err := cft.exporter.Spans() + switch err { + case nil: + break + case errNoTraces: + log.Error().Err(err).Msgf("expected traces to be available") + return + case errNoopTracer: + return // noop tracer has no traces + default: + log.Error().Err(err) + return + } + // No need to add header if no traces + if enc == "" { + log.Error().Msgf("no traces provided and no error from exporter") + return + } + headers[CanonicalCloudflaredTracingHeader] = []string{enc} } // EndWithStatus will set a status for the span and then end it. From e4278bab97706e0037738ac6e970b8c38705d39e Mon Sep 17 00:00:00 2001 From: cthuang Date: Tue, 19 Apr 2022 12:37:32 +0100 Subject: [PATCH 2/9] TUN-6070: First connection retries other edge IPs if the error is quic timeout(likely due to firewall blocking UDP) --- supervisor/supervisor.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go index f1661bf3..8f33e279 100644 --- a/supervisor/supervisor.go +++ b/supervisor/supervisor.go @@ -7,6 +7,7 @@ import ( "time" "github.com/google/uuid" + "github.com/lucas-clemente/quic-go" "github.com/rs/zerolog" "github.com/cloudflare/cloudflared/connection" @@ -264,9 +265,9 @@ func (s *Supervisor) startFirstTunnel( switch err.(type) { case nil: return - // try the next address if it was a dialError(network problem) or + // try the next address if it was a quic.IdleTimeoutError, dialError(network problem) or // dupConnRegisterTunnelError - case edgediscovery.DialError, connection.DupConnRegisterTunnelError: + case *quic.IdleTimeoutError, edgediscovery.DialError, connection.DupConnRegisterTunnelError: edgeErrors++ default: return From 775c2bc93ee75e06f8e10b47586959ce85827dec Mon Sep 17 00:00:00 2001 From: Jasmit Tarang Date: Wed, 20 Apr 2022 15:28:49 -0500 Subject: [PATCH 3/9] VULN-8383 Bump yaml.v2 to yaml.v3 --- config/configuration.go | 4 ++-- go.mod | 2 +- go.sum | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/config/configuration.go b/config/configuration.go index c73a3a46..bb7a10b8 100644 --- a/config/configuration.go +++ b/config/configuration.go @@ -15,7 +15,7 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/urfave/cli/v2" - yaml "gopkg.in/yaml.v2" + yaml "gopkg.in/yaml.v3" "github.com/cloudflare/cloudflared/validation" ) @@ -392,7 +392,7 @@ func ReadConfigFile(c *cli.Context, log *zerolog.Logger) (settings *configFileSe // Parse it again, with strict mode, to find warnings. if file, err := os.Open(configFile); err == nil { decoder := yaml.NewDecoder(file) - decoder.SetStrict(true) + decoder.KnownFields(true) var unusedConfig configFileSettings if err := decoder.Decode(&unusedConfig); err != nil { warnings = err.Error() diff --git a/go.mod b/go.mod index 0e8a0932..356ce37a 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,7 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b zombiezen.com/go/capnproto2 v2.18.0+incompatible ) @@ -101,7 +102,6 @@ require ( google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb // indirect google.golang.org/grpc v1.45.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) replace github.com/urfave/cli/v2 => github.com/ipostelnik/cli/v2 v2.3.1-0.20210324024421-b6ea8234fe3d diff --git a/go.sum b/go.sum index d4065e58..9e39dfa6 100644 --- a/go.sum +++ b/go.sum @@ -104,6 +104,7 @@ github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -343,6 +344,7 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= @@ -522,6 +524,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs= github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= From a97233bb3e3abb695e76935037403f7559012e21 Mon Sep 17 00:00:00 2001 From: Devin Carr Date: Mon, 11 Apr 2022 16:02:13 -0700 Subject: [PATCH 4/9] TUN-6030: Add ttfb span for origin http request --- cmd/cloudflared/main.go | 2 ++ proxy/proxy.go | 10 ++++++-- tracing/client.go | 4 ++-- tracing/client_test.go | 4 ++-- tracing/tracing.go | 52 ++++++++++++++++++++++++++++++----------- tracing/tracing_test.go | 10 ++++---- 6 files changed, 57 insertions(+), 25 deletions(-) diff --git a/cmd/cloudflared/main.go b/cmd/cloudflared/main.go index 889e1f64..07271eb4 100644 --- a/cmd/cloudflared/main.go +++ b/cmd/cloudflared/main.go @@ -21,6 +21,7 @@ import ( "github.com/cloudflare/cloudflared/logger" "github.com/cloudflare/cloudflared/metrics" "github.com/cloudflare/cloudflared/overwatch" + "github.com/cloudflare/cloudflared/tracing" "github.com/cloudflare/cloudflared/watcher" ) @@ -86,6 +87,7 @@ func main() { tunnel.Init(bInfo, graceShutdownC) // we need this to support the tunnel sub command... access.Init(graceShutdownC) updater.Init(Version) + tracing.Init(Version) runApp(app, graceShutdownC) } diff --git a/proxy/proxy.go b/proxy/proxy.go index f24f0290..bcdab8de 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -11,6 +11,8 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" "github.com/cloudflare/cloudflared/carrier" "github.com/cloudflare/cloudflared/cfio" @@ -72,7 +74,8 @@ func (p *Proxy) ProxyHTTP( lbProbe := connection.IsLBProbeRequest(req) p.appendTagHeaders(req) - _, ruleSpan := tr.Tracer().Start(req.Context(), "ingress_match") + _, ruleSpan := tr.Tracer().Start(req.Context(), "ingress_match", + trace.WithAttributes(attribute.String("req-host", req.Host))) rule, ruleNum := p.ingressRules.FindMatchingRule(req.Host, req.URL.Path) logFields := logFields{ cfRay: cfRay, @@ -167,7 +170,7 @@ func (p *Proxy) proxyHTTPRequest( ) error { roundTripReq := tr.Request if isWebsocket { - roundTripReq = tr.Request.Clone(tr.Request.Context()) + roundTripReq = tr.Clone(tr.Request.Context()) roundTripReq.Header.Set("Connection", "Upgrade") roundTripReq.Header.Set("Upgrade", "websocket") roundTripReq.Header.Set("Sec-Websocket-Version", "13") @@ -191,10 +194,13 @@ func (p *Proxy) proxyHTTPRequest( roundTripReq.Header.Set("User-Agent", "") } + _, ttfbSpan := tr.Tracer().Start(tr.Context(), "ttfb_origin") resp, err := httpService.RoundTrip(roundTripReq) if err != nil { + tracing.EndWithStatus(ttfbSpan, codes.Error, "") return errors.Wrap(err, "Unable to reach the origin service. The service may be down or it may not be responding to traffic from cloudflared") } + tracing.EndWithStatus(ttfbSpan, codes.Ok, resp.Status) defer resp.Body.Close() // Add spans to response header (if available) diff --git a/tracing/client.go b/tracing/client.go index 5ed4efb3..ffc477e1 100644 --- a/tracing/client.go +++ b/tracing/client.go @@ -12,7 +12,7 @@ import ( ) const ( - maxTraceAmount = 20 + MaxTraceAmount = 20 ) var ( @@ -46,7 +46,7 @@ func (mc *InMemoryOtlpClient) UploadTraces(_ context.Context, protoSpans []*trac defer mc.mu.Unlock() // Catch to make sure too many traces aren't being added to response header. // Returning nil makes sure we don't fail to send the traces we already recorded. - if len(mc.spans)+len(protoSpans) > maxTraceAmount { + if len(mc.spans)+len(protoSpans) > MaxTraceAmount { return nil } mc.spans = append(mc.spans, protoSpans...) diff --git a/tracing/client_test.go b/tracing/client_test.go index 946ee7f5..175c9112 100644 --- a/tracing/client_test.go +++ b/tracing/client_test.go @@ -108,12 +108,12 @@ func TestSpansNil(t *testing.T) { func TestSpansTooManySpans(t *testing.T) { client := &InMemoryOtlpClient{} - for i := 0; i < maxTraceAmount+1; i++ { + for i := 0; i < MaxTraceAmount+1; i++ { spans := createResourceSpans([]*tracepb.Span{createOtlpSpan(traceId)}) err := client.UploadTraces(context.Background(), spans) assert.NoError(t, err) } - assert.Len(t, client.spans, maxTraceAmount) + assert.Len(t, client.spans, MaxTraceAmount) _, err := client.Spans() assert.NoError(t, err) } diff --git a/tracing/tracing.go b/tracing/tracing.go index f124e367..d3786603 100644 --- a/tracing/tracing.go +++ b/tracing/tracing.go @@ -3,7 +3,10 @@ package tracing import ( "context" "errors" + "fmt" "net/http" + "os" + "runtime" "github.com/rs/zerolog" otelContrib "go.opentelemetry.io/contrib/propagators/Jaeger" @@ -22,19 +25,26 @@ const ( service = "cloudflared" tracerInstrumentName = "origin" - tracerContextName = "cf-trace-id" - tracerContextNameOverride = "uber-trace-id" + TracerContextName = "cf-trace-id" + TracerContextNameOverride = "uber-trace-id" IntCloudflaredTracingHeader = "cf-int-cloudflared-tracing" ) var ( CanonicalCloudflaredTracingHeader = http.CanonicalHeaderKey(IntCloudflaredTracingHeader) - Http2TransportAttribute = trace.WithAttributes(TransportAttributeKey.String("http2")) - QuicTransportAttribute = trace.WithAttributes(TransportAttributeKey.String("quic")) + Http2TransportAttribute = trace.WithAttributes(transportAttributeKey.String("http2")) + QuicTransportAttribute = trace.WithAttributes(transportAttributeKey.String("quic")) + HostOSAttribute = semconv.HostTypeKey.String(runtime.GOOS) + HostArchAttribute = semconv.HostArchKey.String(runtime.GOARCH) - TransportAttributeKey = attribute.Key("transport") - TrafficAttributeKey = attribute.Key("traffic") + otelVersionAttribute attribute.KeyValue + hostnameAttribute attribute.KeyValue + cloudflaredVersionAttribute attribute.KeyValue + serviceAttribute = semconv.ServiceNameKey.String(service) + + transportAttributeKey = attribute.Key("transport") + otelVersionAttributeKey = attribute.Key("jaeger.version") errNoopTracerProvider = errors.New("noop tracer provider records no spans") ) @@ -42,6 +52,14 @@ var ( func init() { // Register the jaeger propagator globally. otel.SetTextMapPropagator(otelContrib.Jaeger{}) + otelVersionAttribute = otelVersionAttributeKey.String(fmt.Sprintf("go-otel-%s", otel.Version())) + if hostname, err := os.Hostname(); err == nil { + hostnameAttribute = attribute.String("hostname", hostname) + } +} + +func Init(version string) { + cloudflaredVersionAttribute = semconv.ProcessRuntimeVersionKey.String(version) } type TracedRequest struct { @@ -67,7 +85,12 @@ func NewTracedRequest(req *http.Request) *TracedRequest { // Record information about this application in a Resource. tracesdk.WithResource(resource.NewWithAttributes( semconv.SchemaURL, - semconv.ServiceNameKey.String(service), + serviceAttribute, + otelVersionAttribute, + hostnameAttribute, + cloudflaredVersionAttribute, + HostOSAttribute, + HostArchAttribute, )), ) @@ -110,27 +133,28 @@ func EndWithStatus(span trace.Span, code codes.Code, status string) { span.End() } -// extractTrace attempts to check for a cf-trace-id from a request header. +// extractTrace attempts to check for a cf-trace-id from a request and return the +// trace context with the provided http.Request. func extractTrace(req *http.Request) (context.Context, bool) { // Only add tracing for requests with appropriately tagged headers - remoteTraces := req.Header.Values(tracerContextName) + remoteTraces := req.Header.Values(TracerContextName) if len(remoteTraces) <= 0 { // Strip the cf-trace-id header - req.Header.Del(tracerContextName) + req.Header.Del(TracerContextName) return nil, false } - traceHeader := make(map[string]string, 1) + traceHeader := map[string]string{} for _, t := range remoteTraces { // Override the 'cf-trace-id' as 'uber-trace-id' so the jaeger propagator can extract it. // Last entry wins if multiple provided - traceHeader[tracerContextNameOverride] = t + traceHeader[TracerContextNameOverride] = t } // Strip the cf-trace-id header - req.Header.Del(tracerContextName) + req.Header.Del(TracerContextName) - if traceHeader[tracerContextNameOverride] == "" { + if traceHeader[TracerContextNameOverride] == "" { return nil, false } remoteCtx := otel.GetTextMapPropagator().Extract(req.Context(), propagation.MapCarrier(traceHeader)) diff --git a/tracing/tracing_test.go b/tracing/tracing_test.go index 50dcb3ff..1bd23e89 100644 --- a/tracing/tracing_test.go +++ b/tracing/tracing_test.go @@ -12,7 +12,7 @@ import ( func TestNewCfTracer(t *testing.T) { req := httptest.NewRequest("GET", "http://localhost", nil) - req.Header.Add(tracerContextName, "14cb070dde8e51fc5ae8514e69ba42ca:b38f1bf5eae406f3:0:1") + req.Header.Add(TracerContextName, "14cb070dde8e51fc5ae8514e69ba42ca:b38f1bf5eae406f3:0:1") tr := NewTracedRequest(req) assert.NotNil(t, tr) assert.IsType(t, tracesdk.NewTracerProvider(), tr.TracerProvider) @@ -21,8 +21,8 @@ func TestNewCfTracer(t *testing.T) { func TestNewCfTracerMultiple(t *testing.T) { req := httptest.NewRequest("GET", "http://localhost", nil) - req.Header.Add(tracerContextName, "1241ce3ecdefc68854e8514e69ba42ca:b38f1bf5eae406f3:0:1") - req.Header.Add(tracerContextName, "14cb070dde8e51fc5ae8514e69ba42ca:b38f1bf5eae406f3:0:1") + req.Header.Add(TracerContextName, "1241ce3ecdefc68854e8514e69ba42ca:b38f1bf5eae406f3:0:1") + req.Header.Add(TracerContextName, "14cb070dde8e51fc5ae8514e69ba42ca:b38f1bf5eae406f3:0:1") tr := NewTracedRequest(req) assert.NotNil(t, tr) assert.IsType(t, tracesdk.NewTracerProvider(), tr.TracerProvider) @@ -31,7 +31,7 @@ func TestNewCfTracerMultiple(t *testing.T) { func TestNewCfTracerNilHeader(t *testing.T) { req := httptest.NewRequest("GET", "http://localhost", nil) - req.Header[http.CanonicalHeaderKey(tracerContextName)] = nil + req.Header[http.CanonicalHeaderKey(TracerContextName)] = nil tr := NewTracedRequest(req) assert.NotNil(t, tr) assert.IsType(t, trace.NewNoopTracerProvider(), tr.TracerProvider) @@ -41,7 +41,7 @@ func TestNewCfTracerNilHeader(t *testing.T) { func TestNewCfTracerInvalidHeaders(t *testing.T) { req := httptest.NewRequest("GET", "http://localhost", nil) for _, test := range [][]string{nil, {""}} { - req.Header[http.CanonicalHeaderKey(tracerContextName)] = test + req.Header[http.CanonicalHeaderKey(TracerContextName)] = test tr := NewTracedRequest(req) assert.NotNil(t, tr) assert.IsType(t, trace.NewNoopTracerProvider(), tr.TracerProvider) From 8f0498f66a9276361b630d1a199ecb83759d0aec Mon Sep 17 00:00:00 2001 From: cthuang Date: Thu, 21 Apr 2022 10:52:19 +0100 Subject: [PATCH 5/9] TUN-6123: For a given connection with edge, close all datagram sessions through this connection when it's closed --- datagramsession/manager.go | 48 +++++++++++++++++++++++++-- datagramsession/manager_test.go | 58 ++++++++++++++++++++++++++------- datagramsession/session.go | 14 -------- datagramsession/session_test.go | 31 +++++++----------- 4 files changed, 103 insertions(+), 48 deletions(-) diff --git a/datagramsession/manager.go b/datagramsession/manager.go index c4144279..a691e3f9 100644 --- a/datagramsession/manager.go +++ b/datagramsession/manager.go @@ -2,6 +2,7 @@ package datagramsession import ( "context" + "fmt" "io" "time" @@ -16,6 +17,10 @@ const ( defaultReqTimeout = time.Second * 5 ) +var ( + errSessionManagerClosed = fmt.Errorf("session manager closed") +) + // Manager defines the APIs to manage sessions from the same transport. type Manager interface { // Serve starts the event loop @@ -30,6 +35,7 @@ type manager struct { registrationChan chan *registerSessionEvent unregistrationChan chan *unregisterSessionEvent datagramChan chan *newDatagram + closedChan chan struct{} transport transport sessions map[uuid.UUID]*Session log *zerolog.Logger @@ -43,6 +49,7 @@ func NewManager(transport transport, log *zerolog.Logger) *manager { unregistrationChan: make(chan *unregisterSessionEvent), // datagramChan is buffered, so it can read more datagrams from transport while the event loop is processing other events datagramChan: make(chan *newDatagram, requestChanCapacity), + closedChan: make(chan struct{}), transport: transport, sessions: make(map[uuid.UUID]*Session), log: log, @@ -90,7 +97,24 @@ func (m *manager) Serve(ctx context.Context) error { } } }) - return errGroup.Wait() + err := errGroup.Wait() + close(m.closedChan) + m.shutdownSessions(err) + return err +} + +func (m *manager) shutdownSessions(err error) { + if err == nil { + err = errSessionManagerClosed + } + closeSessionErr := &errClosedSession{ + message: err.Error(), + // Usually connection with remote has been closed, so set this to true to skip unregistering from remote + byRemote: true, + } + for _, s := range m.sessions { + s.close(closeSessionErr) + } } func (m *manager) RegisterSession(ctx context.Context, sessionID uuid.UUID, originProxy io.ReadWriteCloser) (*Session, error) { @@ -104,15 +128,33 @@ func (m *manager) RegisterSession(ctx context.Context, sessionID uuid.UUID, orig case m.registrationChan <- event: session := <-event.resultChan return session, nil + // Once closedChan is closed, manager won't accept more registration because nothing is + // reading from registrationChan and it's an unbuffered channel + case <-m.closedChan: + return nil, errSessionManagerClosed } } func (m *manager) registerSession(ctx context.Context, registration *registerSessionEvent) { - session := newSession(registration.sessionID, m.transport, registration.originProxy, m.log) + session := m.newSession(registration.sessionID, registration.originProxy) m.sessions[registration.sessionID] = session registration.resultChan <- session } +func (m *manager) newSession(id uuid.UUID, dstConn io.ReadWriteCloser) *Session { + return &Session{ + ID: id, + transport: m.transport, + dstConn: dstConn, + // activeAtChan has low capacity. It can be full when there are many concurrent read/write. markActive() will + // drop instead of blocking because last active time only needs to be an approximation + activeAtChan: make(chan time.Time, 2), + // capacity is 2 because close() and dstToTransport routine in Serve() can write to this channel + closeChan: make(chan error, 2), + log: m.log, + } +} + func (m *manager) UnregisterSession(ctx context.Context, sessionID uuid.UUID, message string, byRemote bool) error { ctx, cancel := context.WithTimeout(ctx, m.timeout) defer cancel() @@ -129,6 +171,8 @@ func (m *manager) UnregisterSession(ctx context.Context, sessionID uuid.UUID, me return ctx.Err() case m.unregistrationChan <- event: return nil + case <-m.closedChan: + return errSessionManagerClosed } } diff --git a/datagramsession/manager_test.go b/datagramsession/manager_test.go index 823c55bb..a9361624 100644 --- a/datagramsession/manager_test.go +++ b/datagramsession/manager_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net" + "sync" "testing" "time" @@ -21,12 +22,8 @@ func TestManagerServe(t *testing.T) { msgs = 50 remoteUnregisterMsg = "eyeball closed connection" ) - log := zerolog.Nop() - transport := &mockQUICTransport{ - reqChan: newDatagramChannel(1), - respChan: newDatagramChannel(1), - } - mg := NewManager(transport, &log) + + mg, transport := newTestManager(1) eyeballTracker := make(map[uuid.UUID]*datagramChannel) for i := 0; i < sessions; i++ { @@ -124,12 +121,8 @@ func TestTimeout(t *testing.T) { const ( testTimeout = time.Millisecond * 50 ) - log := zerolog.Nop() - transport := &mockQUICTransport{ - reqChan: newDatagramChannel(1), - respChan: newDatagramChannel(1), - } - mg := NewManager(transport, &log) + + mg, _ := newTestManager(1) mg.timeout = testTimeout ctx := context.Background() sessionID := uuid.New() @@ -142,6 +135,47 @@ func TestTimeout(t *testing.T) { require.ErrorIs(t, err, context.DeadlineExceeded) } +func TestCloseTransportCloseSessions(t *testing.T) { + mg, transport := newTestManager(1) + ctx := context.Background() + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + err := mg.Serve(ctx) + require.Error(t, err) + }() + + cfdConn, eyeballConn := net.Pipe() + session, err := mg.RegisterSession(ctx, uuid.New(), cfdConn) + require.NoError(t, err) + require.NotNil(t, session) + + wg.Add(1) + go func() { + defer wg.Done() + _, err := eyeballConn.Write([]byte(t.Name())) + require.NoError(t, err) + transport.close() + }() + + closedByRemote, err := session.Serve(ctx, time.Minute) + require.True(t, closedByRemote) + require.Error(t, err) + + wg.Wait() +} + +func newTestManager(capacity uint) (*manager, *mockQUICTransport) { + log := zerolog.Nop() + transport := &mockQUICTransport{ + reqChan: newDatagramChannel(capacity), + respChan: newDatagramChannel(capacity), + } + return NewManager(transport, &log), transport +} + type mockOrigin struct { expectMsgCount int expectedMsg []byte diff --git a/datagramsession/session.go b/datagramsession/session.go index 0a1199e8..351ae298 100644 --- a/datagramsession/session.go +++ b/datagramsession/session.go @@ -39,20 +39,6 @@ type Session struct { log *zerolog.Logger } -func newSession(id uuid.UUID, transport transport, dstConn io.ReadWriteCloser, log *zerolog.Logger) *Session { - return &Session{ - ID: id, - transport: transport, - dstConn: dstConn, - // activeAtChan has low capacity. It can be full when there are many concurrent read/write. markActive() will - // drop instead of blocking because last active time only needs to be an approximation - activeAtChan: make(chan time.Time, 2), - // capacity is 2 because close() and dstToTransport routine in Serve() can write to this channel - closeChan: make(chan error, 2), - log: log, - } -} - func (s *Session) Serve(ctx context.Context, closeAfterIdle time.Duration) (closedByRemote bool, err error) { go func() { // QUIC implementation copies data to another buffer before returning https://github.com/lucas-clemente/quic-go/blob/v0.24.0/session.go#L1967-L1975 diff --git a/datagramsession/session_test.go b/datagramsession/session_test.go index bf1b1e20..db4201f6 100644 --- a/datagramsession/session_test.go +++ b/datagramsession/session_test.go @@ -11,7 +11,6 @@ import ( "time" "github.com/google/uuid" - "github.com/rs/zerolog" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) @@ -41,12 +40,9 @@ func testSessionReturns(t *testing.T, closeBy closeMethod, closeAfterIdle time.D sessionID := uuid.New() cfdConn, originConn := net.Pipe() payload := testPayload(sessionID) - transport := &mockQUICTransport{ - reqChan: newDatagramChannel(1), - respChan: newDatagramChannel(1), - } - log := zerolog.Nop() - session := newSession(sessionID, transport, cfdConn, &log) + + mg, _ := newTestManager(1) + session := mg.newSession(sessionID, cfdConn) ctx, cancel := context.WithCancel(context.Background()) sessionDone := make(chan struct{}) @@ -117,12 +113,9 @@ func testActiveSessionNotClosed(t *testing.T, readFromDst bool, writeToDst bool) sessionID := uuid.New() cfdConn, originConn := net.Pipe() payload := testPayload(sessionID) - transport := &mockQUICTransport{ - reqChan: newDatagramChannel(100), - respChan: newDatagramChannel(100), - } - log := zerolog.Nop() - session := newSession(sessionID, transport, cfdConn, &log) + + mg, _ := newTestManager(100) + session := mg.newSession(sessionID, cfdConn) startTime := time.Now() activeUntil := startTime.Add(activeTime) @@ -184,7 +177,8 @@ func testActiveSessionNotClosed(t *testing.T, readFromDst bool, writeToDst bool) func TestMarkActiveNotBlocking(t *testing.T) { const concurrentCalls = 50 - session := newSession(uuid.New(), nil, nil, nil) + mg, _ := newTestManager(1) + session := mg.newSession(uuid.New(), nil) var wg sync.WaitGroup wg.Add(concurrentCalls) for i := 0; i < concurrentCalls; i++ { @@ -199,12 +193,9 @@ func TestMarkActiveNotBlocking(t *testing.T) { func TestZeroBytePayload(t *testing.T) { sessionID := uuid.New() cfdConn, originConn := net.Pipe() - transport := &mockQUICTransport{ - reqChan: newDatagramChannel(1), - respChan: newDatagramChannel(1), - } - log := zerolog.Nop() - session := newSession(sessionID, transport, cfdConn, &log) + + mg, transport := newTestManager(1) + session := mg.newSession(sessionID, cfdConn) ctx, cancel := context.WithCancel(context.Background()) errGroup, ctx := errgroup.WithContext(ctx) From d22cb4a6ca1e1cae4112f2e519c1cbf577c8fee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Oliveirinha?= Date: Wed, 20 Apr 2022 17:52:55 +0100 Subject: [PATCH 6/9] TUN-6015: Add RPC method for pushing local config --- tunnelrpc/pogs/connectionrpc.go | 12 + tunnelrpc/pogs/connectionrpc_test.go | 5 + tunnelrpc/tunnelrpc.capnp | 1 + tunnelrpc/tunnelrpc.capnp.go | 656 ++++++++++++++++++--------- 4 files changed, 454 insertions(+), 220 deletions(-) diff --git a/tunnelrpc/pogs/connectionrpc.go b/tunnelrpc/pogs/connectionrpc.go index 997a9bc3..788a67a8 100644 --- a/tunnelrpc/pogs/connectionrpc.go +++ b/tunnelrpc/pogs/connectionrpc.go @@ -18,6 +18,7 @@ import ( type RegistrationServer interface { RegisterConnection(ctx context.Context, auth TunnelAuth, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) UnregisterConnection(ctx context.Context) + UpdateLocalConfiguration(ctx context.Context, config []byte) error } type RegistrationServer_PogsImpl struct { @@ -88,6 +89,17 @@ func (i RegistrationServer_PogsImpl) UnregisterConnection(p tunnelrpc.Registrati return nil } +func (i RegistrationServer_PogsImpl) UpdateLocalConfiguration(c tunnelrpc.RegistrationServer_updateLocalConfiguration) error { + server.Ack(c.Options) + + configBytes, err := c.Params.Config() + if err != nil { + return err + } + + return i.impl.UpdateLocalConfiguration(c.Ctx, configBytes) +} + type RegistrationServer_PogsClient struct { Client capnp.Client Conn *rpc.Conn diff --git a/tunnelrpc/pogs/connectionrpc_test.go b/tunnelrpc/pogs/connectionrpc_test.go index 99a68ab4..c9ec77ca 100644 --- a/tunnelrpc/pogs/connectionrpc_test.go +++ b/tunnelrpc/pogs/connectionrpc_test.go @@ -129,6 +129,11 @@ type testConnectionRegistrationServer struct { err error } +func (t *testConnectionRegistrationServer) UpdateLocalConfiguration(ctx context.Context, config []byte) error { + // do nothing at this point + return nil +} + func (t *testConnectionRegistrationServer) RegisterConnection(ctx context.Context, auth TunnelAuth, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) { if auth.AccountTag != testAccountTag { panic("bad account tag: " + auth.AccountTag) diff --git a/tunnelrpc/tunnelrpc.capnp b/tunnelrpc/tunnelrpc.capnp index 8d91f6d1..c1d56d6e 100644 --- a/tunnelrpc/tunnelrpc.capnp +++ b/tunnelrpc/tunnelrpc.capnp @@ -131,6 +131,7 @@ struct TunnelAuth { interface RegistrationServer { registerConnection @0 (auth :TunnelAuth, tunnelId :Data, connIndex :UInt8, options :ConnectionOptions) -> (result :ConnectionResponse); unregisterConnection @1 () -> (); + updateLocalConfiguration @2 (config :Data) -> (); } interface TunnelServer extends (RegistrationServer) { diff --git a/tunnelrpc/tunnelrpc.capnp.go b/tunnelrpc/tunnelrpc.capnp.go index ac1e152a..4d1af72f 100644 --- a/tunnelrpc/tunnelrpc.capnp.go +++ b/tunnelrpc/tunnelrpc.capnp.go @@ -1621,11 +1621,35 @@ func (c RegistrationServer) UnregisterConnection(ctx context.Context, params fun } return RegistrationServer_unregisterConnection_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))} } +func (c RegistrationServer) UpdateLocalConfiguration(ctx context.Context, params func(RegistrationServer_updateLocalConfiguration_Params) error, opts ...capnp.CallOption) RegistrationServer_updateLocalConfiguration_Results_Promise { + if c.Client == nil { + return RegistrationServer_updateLocalConfiguration_Results_Promise{Pipeline: capnp.NewPipeline(capnp.ErrorAnswer(capnp.ErrNullClient))} + } + call := &capnp.Call{ + Ctx: ctx, + Method: capnp.Method{ + InterfaceID: 0xf71695ec7fe85497, + MethodID: 2, + InterfaceName: "tunnelrpc/tunnelrpc.capnp:RegistrationServer", + MethodName: "updateLocalConfiguration", + }, + Options: capnp.NewCallOptions(opts), + } + if params != nil { + call.ParamsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} + call.ParamsFunc = func(s capnp.Struct) error { + return params(RegistrationServer_updateLocalConfiguration_Params{Struct: s}) + } + } + return RegistrationServer_updateLocalConfiguration_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))} +} type RegistrationServer_Server interface { RegisterConnection(RegistrationServer_registerConnection) error UnregisterConnection(RegistrationServer_unregisterConnection) error + + UpdateLocalConfiguration(RegistrationServer_updateLocalConfiguration) error } func RegistrationServer_ServerToClient(s RegistrationServer_Server) RegistrationServer { @@ -1635,7 +1659,7 @@ func RegistrationServer_ServerToClient(s RegistrationServer_Server) Registration func RegistrationServer_Methods(methods []server.Method, s RegistrationServer_Server) []server.Method { if cap(methods) == 0 { - methods = make([]server.Method, 0, 2) + methods = make([]server.Method, 0, 3) } methods = append(methods, server.Method{ @@ -1666,6 +1690,20 @@ func RegistrationServer_Methods(methods []server.Method, s RegistrationServer_Se ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 0}, }) + methods = append(methods, server.Method{ + Method: capnp.Method{ + InterfaceID: 0xf71695ec7fe85497, + MethodID: 2, + InterfaceName: "tunnelrpc/tunnelrpc.capnp:RegistrationServer", + MethodName: "updateLocalConfiguration", + }, + Impl: func(c context.Context, opts capnp.CallOptions, p, r capnp.Struct) error { + call := RegistrationServer_updateLocalConfiguration{c, opts, RegistrationServer_updateLocalConfiguration_Params{Struct: p}, RegistrationServer_updateLocalConfiguration_Results{Struct: r}} + return s.UpdateLocalConfiguration(call) + }, + ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 0}, + }) + return methods } @@ -1685,6 +1723,14 @@ type RegistrationServer_unregisterConnection struct { Results RegistrationServer_unregisterConnection_Results } +// RegistrationServer_updateLocalConfiguration holds the arguments for a server call to RegistrationServer.updateLocalConfiguration. +type RegistrationServer_updateLocalConfiguration struct { + Ctx context.Context + Options capnp.CallOptions + Params RegistrationServer_updateLocalConfiguration_Params + Results RegistrationServer_updateLocalConfiguration_Results +} + type RegistrationServer_registerConnection_Params struct{ capnp.Struct } // RegistrationServer_registerConnection_Params_TypeID is the unique identifier for the type RegistrationServer_registerConnection_Params. @@ -2014,6 +2060,130 @@ func (p RegistrationServer_unregisterConnection_Results_Promise) Struct() (Regis return RegistrationServer_unregisterConnection_Results{s}, err } +type RegistrationServer_updateLocalConfiguration_Params struct{ capnp.Struct } + +// RegistrationServer_updateLocalConfiguration_Params_TypeID is the unique identifier for the type RegistrationServer_updateLocalConfiguration_Params. +const RegistrationServer_updateLocalConfiguration_Params_TypeID = 0xc5d6e311876a3604 + +func NewRegistrationServer_updateLocalConfiguration_Params(s *capnp.Segment) (RegistrationServer_updateLocalConfiguration_Params, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return RegistrationServer_updateLocalConfiguration_Params{st}, err +} + +func NewRootRegistrationServer_updateLocalConfiguration_Params(s *capnp.Segment) (RegistrationServer_updateLocalConfiguration_Params, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}) + return RegistrationServer_updateLocalConfiguration_Params{st}, err +} + +func ReadRootRegistrationServer_updateLocalConfiguration_Params(msg *capnp.Message) (RegistrationServer_updateLocalConfiguration_Params, error) { + root, err := msg.RootPtr() + return RegistrationServer_updateLocalConfiguration_Params{root.Struct()}, err +} + +func (s RegistrationServer_updateLocalConfiguration_Params) String() string { + str, _ := text.Marshal(0xc5d6e311876a3604, s.Struct) + return str +} + +func (s RegistrationServer_updateLocalConfiguration_Params) Config() ([]byte, error) { + p, err := s.Struct.Ptr(0) + return []byte(p.Data()), err +} + +func (s RegistrationServer_updateLocalConfiguration_Params) HasConfig() bool { + p, err := s.Struct.Ptr(0) + return p.IsValid() || err != nil +} + +func (s RegistrationServer_updateLocalConfiguration_Params) SetConfig(v []byte) error { + return s.Struct.SetData(0, v) +} + +// RegistrationServer_updateLocalConfiguration_Params_List is a list of RegistrationServer_updateLocalConfiguration_Params. +type RegistrationServer_updateLocalConfiguration_Params_List struct{ capnp.List } + +// NewRegistrationServer_updateLocalConfiguration_Params creates a new list of RegistrationServer_updateLocalConfiguration_Params. +func NewRegistrationServer_updateLocalConfiguration_Params_List(s *capnp.Segment, sz int32) (RegistrationServer_updateLocalConfiguration_Params_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz) + return RegistrationServer_updateLocalConfiguration_Params_List{l}, err +} + +func (s RegistrationServer_updateLocalConfiguration_Params_List) At(i int) RegistrationServer_updateLocalConfiguration_Params { + return RegistrationServer_updateLocalConfiguration_Params{s.List.Struct(i)} +} + +func (s RegistrationServer_updateLocalConfiguration_Params_List) Set(i int, v RegistrationServer_updateLocalConfiguration_Params) error { + return s.List.SetStruct(i, v.Struct) +} + +func (s RegistrationServer_updateLocalConfiguration_Params_List) String() string { + str, _ := text.MarshalList(0xc5d6e311876a3604, s.List) + return str +} + +// RegistrationServer_updateLocalConfiguration_Params_Promise is a wrapper for a RegistrationServer_updateLocalConfiguration_Params promised by a client call. +type RegistrationServer_updateLocalConfiguration_Params_Promise struct{ *capnp.Pipeline } + +func (p RegistrationServer_updateLocalConfiguration_Params_Promise) Struct() (RegistrationServer_updateLocalConfiguration_Params, error) { + s, err := p.Pipeline.Struct() + return RegistrationServer_updateLocalConfiguration_Params{s}, err +} + +type RegistrationServer_updateLocalConfiguration_Results struct{ capnp.Struct } + +// RegistrationServer_updateLocalConfiguration_Results_TypeID is the unique identifier for the type RegistrationServer_updateLocalConfiguration_Results. +const RegistrationServer_updateLocalConfiguration_Results_TypeID = 0xe5ceae5d6897d7be + +func NewRegistrationServer_updateLocalConfiguration_Results(s *capnp.Segment) (RegistrationServer_updateLocalConfiguration_Results, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return RegistrationServer_updateLocalConfiguration_Results{st}, err +} + +func NewRootRegistrationServer_updateLocalConfiguration_Results(s *capnp.Segment) (RegistrationServer_updateLocalConfiguration_Results, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) + return RegistrationServer_updateLocalConfiguration_Results{st}, err +} + +func ReadRootRegistrationServer_updateLocalConfiguration_Results(msg *capnp.Message) (RegistrationServer_updateLocalConfiguration_Results, error) { + root, err := msg.RootPtr() + return RegistrationServer_updateLocalConfiguration_Results{root.Struct()}, err +} + +func (s RegistrationServer_updateLocalConfiguration_Results) String() string { + str, _ := text.Marshal(0xe5ceae5d6897d7be, s.Struct) + return str +} + +// RegistrationServer_updateLocalConfiguration_Results_List is a list of RegistrationServer_updateLocalConfiguration_Results. +type RegistrationServer_updateLocalConfiguration_Results_List struct{ capnp.List } + +// NewRegistrationServer_updateLocalConfiguration_Results creates a new list of RegistrationServer_updateLocalConfiguration_Results. +func NewRegistrationServer_updateLocalConfiguration_Results_List(s *capnp.Segment, sz int32) (RegistrationServer_updateLocalConfiguration_Results_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) + return RegistrationServer_updateLocalConfiguration_Results_List{l}, err +} + +func (s RegistrationServer_updateLocalConfiguration_Results_List) At(i int) RegistrationServer_updateLocalConfiguration_Results { + return RegistrationServer_updateLocalConfiguration_Results{s.List.Struct(i)} +} + +func (s RegistrationServer_updateLocalConfiguration_Results_List) Set(i int, v RegistrationServer_updateLocalConfiguration_Results) error { + return s.List.SetStruct(i, v.Struct) +} + +func (s RegistrationServer_updateLocalConfiguration_Results_List) String() string { + str, _ := text.MarshalList(0xe5ceae5d6897d7be, s.List) + return str +} + +// RegistrationServer_updateLocalConfiguration_Results_Promise is a wrapper for a RegistrationServer_updateLocalConfiguration_Results promised by a client call. +type RegistrationServer_updateLocalConfiguration_Results_Promise struct{ *capnp.Pipeline } + +func (p RegistrationServer_updateLocalConfiguration_Results_Promise) Struct() (RegistrationServer_updateLocalConfiguration_Results, error) { + s, err := p.Pipeline.Struct() + return RegistrationServer_updateLocalConfiguration_Results{s}, err +} + type TunnelServer struct{ Client capnp.Client } // TunnelServer_TypeID is the unique identifier for the type TunnelServer. @@ -2181,6 +2351,28 @@ func (c TunnelServer) UnregisterConnection(ctx context.Context, params func(Regi } return RegistrationServer_unregisterConnection_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))} } +func (c TunnelServer) UpdateLocalConfiguration(ctx context.Context, params func(RegistrationServer_updateLocalConfiguration_Params) error, opts ...capnp.CallOption) RegistrationServer_updateLocalConfiguration_Results_Promise { + if c.Client == nil { + return RegistrationServer_updateLocalConfiguration_Results_Promise{Pipeline: capnp.NewPipeline(capnp.ErrorAnswer(capnp.ErrNullClient))} + } + call := &capnp.Call{ + Ctx: ctx, + Method: capnp.Method{ + InterfaceID: 0xf71695ec7fe85497, + MethodID: 2, + InterfaceName: "tunnelrpc/tunnelrpc.capnp:RegistrationServer", + MethodName: "updateLocalConfiguration", + }, + Options: capnp.NewCallOptions(opts), + } + if params != nil { + call.ParamsSize = capnp.ObjectSize{DataSize: 0, PointerCount: 1} + call.ParamsFunc = func(s capnp.Struct) error { + return params(RegistrationServer_updateLocalConfiguration_Params{Struct: s}) + } + } + return RegistrationServer_updateLocalConfiguration_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))} +} type TunnelServer_Server interface { RegisterTunnel(TunnelServer_registerTunnel) error @@ -2198,6 +2390,8 @@ type TunnelServer_Server interface { RegisterConnection(RegistrationServer_registerConnection) error UnregisterConnection(RegistrationServer_unregisterConnection) error + + UpdateLocalConfiguration(RegistrationServer_updateLocalConfiguration) error } func TunnelServer_ServerToClient(s TunnelServer_Server) TunnelServer { @@ -2207,7 +2401,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, 8) + methods = make([]server.Method, 0, 9) } methods = append(methods, server.Method{ @@ -2322,6 +2516,20 @@ func TunnelServer_Methods(methods []server.Method, s TunnelServer_Server) []serv ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 0}, }) + methods = append(methods, server.Method{ + Method: capnp.Method{ + InterfaceID: 0xf71695ec7fe85497, + MethodID: 2, + InterfaceName: "tunnelrpc/tunnelrpc.capnp:RegistrationServer", + MethodName: "updateLocalConfiguration", + }, + Impl: func(c context.Context, opts capnp.CallOptions, p, r capnp.Struct) error { + call := RegistrationServer_updateLocalConfiguration{c, opts, RegistrationServer_updateLocalConfiguration_Params{Struct: p}, RegistrationServer_updateLocalConfiguration_Results{Struct: r}} + return s.UpdateLocalConfiguration(call) + }, + ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 0}, + }) + return methods } @@ -4317,224 +4525,230 @@ func CloudflaredServer_Methods(methods []server.Method, s CloudflaredServer_Serv return methods } -const schema_db8274f9144abc7e = "x\xda\xccZ{t\x14\xe7u\xbfwfW#\x81V" + - "\xab\xf1\xac\xd1\x03T\xb5:P\x179\xd8\x06Jk\xab" + - "9\xd1\xc3\x12\xb1d\x03\x9a]\x94\xe3cC\x8eG\xbb" + - "\x9f\xa4Qwg\x96\x99Y\x19\x11\x130\x01c\xfb\xb8" + - "\x8eq\xc0\xb1Ih0.\xed\x01\xdb\xad\x89\xdd\xa6\xee" + - "1\xa7\xa6\xcd\xabq\xc0&\x87\xf4\x90@\x9a&\x84>" + - "8\xb8\xae14\x876\xf1\xf4\xdc\x99\x9d\x87v\x17\x09" + - "\x8c\xff\xc8\x7f\xab;\xdf\xe3\xde\xdf\xf7\xbb\x8f\xef~\xba" + - "\xed\xe6\x9a.nq\xf4\xed:\x00\xf9\xa5h\x95\xcd\xda" + - "\x7f\xb0a\xef\x82\x7f\xdc\x02r3\xa2\xfd\xf97\x06\x12" + - "\x97\xad-\xa7 \xca\x0b\x00KW\x08\x1bPR\x04\x01" + - "@Z+\xfc;\xa0\xfd\xc8\x9cW\xbe\xb6\xbfo\xe7\x17" + - "@l\xe6\x83\xc1\x80K\xbb\xab\x07P\x1a\xaa\xa6\x91r" + - "\xf5v\xe9\x10\xfd\xb2\xef\x16o\xbd?\xf1\xce1\x1a\x1d" + - "^:BK?W\xdd\x8e\xd2\x01g\xc2\xfejZ\xfa" + - "\x93\xb9\xb7\xf7\xfd\xc1\xae\xb7\xb6\x82\xd8\xccMYzG" + - "\xcd\x06\x94\xf6\xd7\xd0\xc8\xe7kV\x01\xda\x1f\xecl|" + - "\xf1\xf9c\xdf\xdd\x06\xe2M\x08EM_\xaf\xf91\x02" + - "JGk\xfe\x0a\xd0>z\xe9\xfe\x8b\xaf}{\xd9#" + - " .\xa4\x01H\x03r\xb3\xda8@i\xdb\xacN@" + - "\xfb\xdc\xf9\xff\xdb\xfe\xb9\x85+\x9f\x02y!r\x00Q" + - "\x8eF\xec\x9f\xd5L#\x0e\xcf\"m:\x97\x1f}\xbd" + - "y\xe93;KTw\x06\xee\x99\xdd\x8e\xd2\xcb\xb3I" + - "\xa1\x03\xb3\x1f\x04\xb4?\xf5\x87\xaf>\xd9\xfb\xcc\xe6]" + - " \xde\xea\xef\x17\xab\xbd\x8fV[XK\xfb\xfdO\xdd" + - "W\x8e\x15\xee\xfc\xc63E\x85\x9cU\xfak\xdbi\x80" + - "RK+\xb4M,x\xe0\x1f\xbe\xf5\xea\x97A^\x84" + - "h\x9f\x1e\xbe\xf9\x87\xfc\x9e\x83\xa7`\x08\x05\xd2o\xe9" + - "\x91\xda}d\xddqg\xec\xdb\x9fx\xe3\xef\x9ezu" + - "\xfbW@\xbe\x09\x11\xc0AsY\xec\x7fi@\x7f\x8c" + - "v\xdby\xf2\xf0\xca\xdc\x8e\xdd\xfb\\|\x9c\xef\xebb" + - "\x1c\x07\x11{k\xff/sC/\xa4^(\"\x17\xa5" + - "O,v\x01\x01\x97N\xc6Z\x11\xd0^\xf6\xe3\xb3\xab" + - "V|}\xe4/Bsw\xd5m\xa0\xb9\xdbG.\x1c" + - "\xa9O\xe6^,A\xc41vG\xddA\x94\x0e\xd49" + - "\x87YG*\xbc\xfc[w\xd7\xac?\xbb\xfc\x15\x10\x17" + - "y\xcb|\xab.I\xcbL|\xef\x85\xdf]\xf0\xbd\x07" + - "\x0f\x81|+\xfa`\x1d\xa1o(\xfd\xa4\x8e\xec\x8b\x9c" + - "Zp\xf0\xf0O\x9f|\xad\x8ccw\xc47\xa0\xb4\"" + - "N\xbb\xf4\xc7?-M\xd2/;\xb2\x96\xffPy\xf6" + - "\xef_+\xe5\xaf\x83\xb1\x12\x1fF\xa9\x10w\x10\x88;" + - "\xf6=~d\xf7\xcd\xd5_\xfb\xe0\xaf+\x9d\xebs\xf5" + - "\xc3(\xbd\\\xef\x9ck=irc?\x9e~sq" + - "\xe4\x1ba\xa2\xd5\x88\xe7\x08\xe9\x16\x91\x88\xd6\xf2nO" + - "L{o\xcb\x9b%\xab9\x03\x0f\x8b\x03(\x1d\x17i" + - "\xb5\xa3\xce\xe0\x81\xfb\xbf\xf4t\xf4\xec\x97\xbeC\x9a\x86" + - "\x18\x1e%\x1fX\xaa\xde`\xa0\xb4\xf1\x06\xfa9yC" + - "\x03\x0fh7\xbf\xf2G\x7f\xd9\x93\xf9\xd1[\x154\x95" + - ".\xdfxA\x8a\xce\xa1_8\x87\x14=\xb3\xe8\xd0\xe7" + - "\xfe\xf3O\x8e\x9f(*\xea`\xbav\x8eC\x89us" + - "\xe8<.\xaf\xd9{\xb7j\xdf{\xaa\x14%\xf7\xf4\xe6" + - "|\x1d\xa5\x03\xcer\xfb\x9d\xe5|\xfeU\x1a]\xd30" + - "\x8eRK\x03\x8dnj\xa0\xb5\xb9\xb3J\xd3\xe6\x7f\xfe" + - "\xd4\xe9\x10eZ\x1a~\x8e\x10\xb1W~\xe6\xfe\xf1\x9a" + - "\x8dg\xce\x84\xd5\x12\x1b\x1c\xfc\x168S\xff\xeb\xcf\xcf" + - "}\xf1|.\xf3o\x0e\xed=\x84\xfb\x1a:\x88\x0ck" + - "\x1b\xc8\x0f\x1bZc}m'\x07\xcf\xb9Dr\x97\xb8" + - "\xa3\xb1\x87\x06\xc8\x8d\xb4\xc4\xb2\x07\xba\xd9\x9a\xdb\xef=" + - "W\xc6\x96u\x8d\x1d(=\xdcH\x1366nGi" + - "WS\x03\x80=\xf17;\xee}\xf1\x9b+/\xb8\x9e" + - "\xe8(\xbb\xadi\x09\x11\xf3\xc9\xcf\xf7\xae\xba\xa3\xed\xc8" + - "\x85\xb0\xb2\x1b\x9b\xc87\xa4\x1dM\xb4\xd3\xc8\xed\xe7?" + - "\xbd\xe0\xc9o_\xa8\xe4\x00\x87\x9a\xdaQ:\xd2D\xa0" + - "\x1c\xa6\xc1\xef-\xff\xd3\x13\xcd\xf1\xe6\x8b%\x00V\xd1" + - "\xd8\x9f5\x8d\xa3t\x89\xc6.}\xbf\xe9;D\xca\xe7" + - "\xffl\xdf\xbf\\>v\xd7\xa52\x1b\xce\xce\x1dF\xe9" + - "\xf2\\Z\xf6\xd2\\A\xba4\xf7&\x00\xfb\x91S\x9f" + - "]\xff\x83/|p\xa9\x94G\x8e\"\xef\xceM\xa2\x84" + - "\xf3h\xc6\xaf\xe7\x12\xeb\xbe\xbc\xfa?6\x9d\xdf5\xe7" + - "\x97ek\xef\x997\x8e\xd2!g\xe4\xcb\xf3\xb6K\xb1" + - "\x16\xf2\xa6w\x84\x17\x16\xf7nz\xebr\xc8o/\xcd" + - "\x1b x\x9e\x11\xbezf\xf3O?\xfb\xab0<\xef" + - "\xcf\xfb9\xc1\x13m!x\x1ez\xef\xb9\xbb\xbe\xb8\xe6" + - "\xa5\x0fC4X\xd0\xb2\x85\xa6Z\x05McY#\x1f" + - "I\xdf\xea\xfdL\xdf\x92V\xf2Z\xbe\xa3\xbb`\x8d1" + - "\xcdR\xd3\x8a\xc5\x92\xac\xd3\xcc\xeb\x9a\xc9\x06\x11\xe5z" + - ">\x02\x10A\x00Q\x19\x07\x90\x1f\xe0Q\xcer(\"" + - "&\x88(\xa2J\xc21\x1ee\x8bC\x91\xe3\x12\x14%" + - "\xc5um\x00r\x96Gy=\x87\xc8'\x90\x07\x10\x0b" + - "O\x03\xc8\xeby\x94\xb7rh\xe7\x99\x91S4\xa6A" + - "\xdc\xea3\x0c\xac\x05\x0ek\x01m\x83Y\xc6\xa42\x9c" + - "\x858\x0b\x89\x85\xf1\x07-\x8c\x01\x871@{L/" + - "\x18\xe6\x90f\xa1\x9aM\xb2\x11\x83\x998\x86U\xc0a" + - "\x15\xe0t\xe6\xa5\x98i\xaa\xba\xb6B\xd1\x94Qf\x00" + - "\x90e\xd5|\x14\xc0\xcf@\xe8\xe5*q\xf1n\xe0\xc4" + - "E\x02\x06\xd9\x02=\xb2\x8a\xbfs\x108\xb1E\xb0\x0d" + - "6\xaa\x9a\x163p(\x93w\xd6\xe6u\xad\x0b\xed\x82" + - "\xe6~@f\xb8\x1f\xe2\xb4k\x17\x0eb\xa0\x1d_\xae" + - "\xdd\x9dY\x95iV\xbc_\x1b\xd1K \x1f\xa8\x04\xf9" + - "@\x11\xf2\xad!\xc8\x1f\xee\x01\x90\x1f\xe2Q~\x94C" + - "\x91/b\xbe\xad\x1d@\xde\xcc\xa3\xfc\x04\x87v\xda\xd9" + - "\xa4?\x03\x00>\x9a#L\xb1\x0a\x063IV\x078" + - "\xc8\xa3\x03z\x1d\xe0\xa6\x09f\x90\xee\xde!\xc4\x15#" + - "=\xe6\x1f\xd44H\xf7\xadWMK\xd5FW;\xf2" + - "\xceA=\xab\xa6'\xc9\xaaZG\xcf\x96\x0e\x00D\xf1" + - "\xc6\xfb\x00\x90\x13\xc5\x1e\x80NuT\xd3\x0dfgT" + - "3\xadk\x1a\x03>mm\x1aV\xb2\x8a\x96f\xfeF" + - "U\xe5\x1b\xb9\x1b\xa4\x981\xc1\x8c[\x94\x10}\xe7\x0f" + - "*\x86\xc2\xe7L\xb9\xd6\xc7\xb1\xef>\x00\xb9\x97Gy" + - "0\x84\xe3\x0a\xc2\xf1\x1e\x1e\xe5{C8\x0e\x11\x8e\x83" + - "<\xcak8\xb4uC\x1dU\xb5;\x19\xf0F\x98\x81" + - "\xa6\xa5)9F\x98\x15\xf1\xd8\xa4\xe7-U\xd7L\xac" + - "\x0fr\x0b \xd6\x87\x90\x12f\xe2\xe4-\x1e\xa5(\x09>" + - "\x8e]=\xf8B4LV\xa2\xe1\x12\x009\xc3\xa3\x9c" + - "\xe7\x10\x8b\xe8\xe5zB\xd1\x80G\x97\x85\xebv\x03\xc8" + - "\x16\x8f\xf2f\x0em\xd3\xdd\xa4\x1f0\xe3!\xda\x9a1" + - "\xad\xfe\xbc\xf7\xd7\xa6\x8ci\x0d\xea\x86\x85\x02p(\x00" + - "\xf1V7Y\xf7\x08\xf9T\x7f&\xcb\xeeRy\xcd\xc2" + - "(p\x18\x85i\x9d\xca\xe5G\x9c\x02\x9b\xeb\xed\x9e5" + - "\x0b\x89\x0c\xbf\xc7\xa3\xfc\xfb!k\x16S\x1c\xbb\x8dG" + - "\xf9\x93\x1c\xdaJ:\xad\x174k5\xf0\xcah\x09\xe7" + - "S\x0c\xe2i\x83\x05t\xf0\xb6\xad\xae\xe0\xd6\xba6\xa2" + - "\x8e\x16\x0c\xc5\x0a\x01^\xc8g\x14\x8bM\xf9\xe4\x9cs" + - "\x96\xbf\x8as\xf6\xab\x87k>g/2\x95\x9ct\xdc" + - "Prf\x18\x9bd%l\xe8T?\xc1\xa3|{\xe5" + - "\x03\xdc\x94c\xa6\xa9\x8c\xb2\xb2\xf0\x10\xad\x88\x89\xc6\xd2" + - "du\x92\xb9I\xe6\x16\x83\x99B!k\x91\x16\xb5\xb6" + - "\xed\xaaA\xdc\x9a\xcf\xa3|\x1b\x871\xfc\xd0v\xf5X" + - "\xf4tpF\xad\xcc0t\x03\xeb\x83$\\\x84$]" + - "\xdc\x00u\xad\x97Y\x8a\x9aErK\xbf\xda,\x01n" + - "\xa6\xb8\x12\xc0\xe6\x8a\xe7w\x92w\xe4\xa6\x9c\x14\xd1\xbb" + - "\x9eGy\x1e\x87\xf6\xa8\xa1\xa4\xd9 3P\xd53+" + - "\x15MO\xf1,]F\xd6\xbak\xdd\xd4\xe1\x87e\x82" + - "?k\xfa\xf9\x06+\x82P\x9c>\xd8\xea\xea\x9c\xf0u" + - "\xde\xd8\x16$c\xff\x98\x1f\x1e\x0e\xb2\x85\x1f\x0f\x1f#" + - "gy\x94Gyg(\xaf\xec\xa0\xc8\xf9\x14\x8f\xf2W" + - "9\x14#\x91\x04F\x00\xc4\xe7\x88%;y\x94\xf7r" + - "SS6\x9b`\x9a\xd5\xab\x8e\x82\xc0\xcc@J*\xf6" + - "\xaa\xa3\x0cx\xf3zck\xf5\x0cx\xe8\xc3\xa6\x9ee" + - "\x16\xebe\xe9\xacB.7\xc1\xdc\xefE2z\x87:" + - "\x1do\x93e\xdeC\xfc\x8d{UR\x88\x0em\x81\xe3" + - "\x0a,T\xdcL\xa3\xad\xbb\xb8\x1b\x0c\xca8\x10xL" + - "\x91\x07h~,A\xc7\xb1\x19\xa78\x7fO\xe0u\x1e" + - ")\x16u\x04\x01\xc1\xaf\x09\"\xc0a\x04\xb03\xed," + - "X\x16\x0a#3i\xd5\xe9\xaa\xe5\x02GE\x98w\x17" + - "E\xef\x02/\x8a\xfb\x80\x13c\x82\xedi\x8e\xde|\xa1" + - "\xac\xa0\x8aL\x17eV\xe5-U\xd05\x93\xf6\x0a\xf1" + - "\xbf\xa3\x12\xff\x8d\x80\xff^B{lK\x98\xfe\xc5\x84" + - "\xb6cw\xc0t1\xc2\xb9\xf4\xdf\xb3\x0f@\xde\xcb\xa3" + - "\xfc\x12\x87\x9dn\xad\x85\xf5A\xe3\xa5HY\xb7\xa2\xb8" + - "G\x87\xd6\xb4\x92\x0d\x92\x9em\xb0|VI\xb3>," + - "VO\x80\x08\x1c\xa2\xe3'\xb9\xbc\xc1L\x13U]\x93" + - "\x0bJV\xe5\xadI\xbf\xe2\xd5\x0a\xb9A\x83M\xa8\xa8" + - "\x17\xccn\xcbb9!o\x99WS\x0f\x07\x00Q\x90" + - "\x14\xd4\xacY\x92#\xdb\x03*\xf8\x00-\x1a\x0f\xf2@" + - "\xbcPP\xfd\x04`g\xf5\xb4s\xb2\x10_\xa9\xe4\xca" + - "\xf3@\xd5\x8c\x01kJ\xb8\xf3\xd2\xd2oR\xfd6\xfd" + - "\x95\x89Lw\xee\x14!\x95)\x0et\xf1(\xdf\x13R" + - "\xb9\x7fI\xc8\x0eO\xe5\x15\xc3\x81\x1d\xc2\x1f\xb3IO" + - "\xabV\x96\xa3\xf4\xe5\x81Y4\xa6\x1b\x84\xbb\x831\xd3" + - "\xe9\x17\x8e*\xab\xf2\xad\x8e\x85\xa4\xe3\xed\x9e\x8e\xd2$" + - "\x0e\x00\xa4\xd6#\x8f\xa9\xad\x18\xa8)=\x8c=\x00\xa9" + - "\x87H\xfe(\x06\x9aJ\xdb\xb0\x19 \xb5\x99\xe4O\xa0" + - "\x7f\xb5\x93\x1e\xc3\x83\x00\xa9'H\xfc,\x0d\x8f\xf0\x8e" + - "KH\xbb\x9c\xe5w\x92|/\xc9\xa3\x91\x04F\x01\xa4" + - "=\xd8\x0e\x90z\x96\xe4\xaf\x91\xbc\x8aK`\x15\x80t" + - "\x08\xc7\x01R\xaf\x90\xfc\x0d\x92\x0b\xd1\x04\xddn\xa5\xd7" + - "\xd1\x00H\xfd-\xc9\xbfI\xf2\xea\xc6\x04V\x03HG" + - "\x1c\xf9\x9b$\xff>\xc9k\x9a\x12X\x03 \xfd\x13n" + - "\x01H}\x97\xe4'H>\x0b\x138\x0b@:\x8e\xbb" + - "\x01R'H\xfe\xaf$\x9f]\x95\xc0\xd9\x00\xd2O\x1c" + - "}N\x92\xfc\x17$\xaf\x8d$\xb0\x16@\xfa\x19\xee\x03" + - "H\xfd\x82\xe4\xffM\xf2\x98\x90\xc0\x18\x80\xf4\xaec\xd7" + - "y\x92Ws%7+\x8fQ%\xd7'^7\xfd#" + - "cE\x1fG\x97\xee\x83z\x9c\xaeH\x18\x0f\x1a\xaf\x80" + - "\x18\x07\xb4\xf3\xba\x9e]9\x95\xa9qK\x195\xbd\xab" + - "Z}\xd0\x9a\x02$\xa1_\xfc@\\\xd7\xfa3~ " + - "(\x8d:\x9e&\xaa\xd9]\xb0\xf4B\x1eZ)\xc8f" + - "\xfc\x98c\x14\xb4\xe5\x86\x9e[\x8d\xcc\xc8\xa9\x9a\x92\x9d" + - "!\x1a\xd5\x00\x875P\x0c\x09\xde\xda\xd3\x87\xa6+_" + - "<}Fs\xa5\x8cn\xcdw\xacVF\xaf&N-" + - "\x09rV\\\x0b\x05\xa4\xd6\x09%[\xf8(\xe1ij" + - "=\x95\xect\xeb\xb1\x99\xcau\xaf\xf7T\x12J*T" + - "\x17C\xe5\xf99\xc9\xccV\xbf\x09\x132\xf8`\x10\x83" + - "={\x97\xb5\x85\xee.Y\xc5b\xa6\xd5\x9d\xc7|V" + - "e\x99\xcf0#\x1eN\xd9\x15+\x92\xc8Le\xfa\xd4" + - "2\x07C]r2\x9c+\x1a|\xd5x\x8e2\xcb\xfd" + - "\xd5\xaf\x8d\xe8T\x87\x08\xe1\xe2\xeb\xdaf'\x99\x19\xbf" + - "\x9a\xb3\x08\x9a\x863_\x9d*\x94c\x15\x8a1\xef&" + - "\x10\xba&\x13\x19\xd7\xf0(\x8f\x85\xc8\xc8\x06*\\\x93" + - "\x93A\x7fL\xe4\xb9b\x83\x8c2W\x9eG\xf9!\x0e" + - "\xe3J\xc1\x1a\xc3\xfa\xe0\xf1c\x8a\xd2S{8\xc4\xcd" + - "~-\xc3\x00\xd7{\xee\x15\xcag~W~\xe6\x9a\xf9" + - "\xea\xcc\xf6\xee\"3\x02\xee\xf7\xaeKv\xbe\xe2U\xbd" + - "\xd3\xdd\x94x\xd6\xe8T\x85^\xd7\x1f\xbd\x8e\xb0xh" + - "\x03p\xe2\x01\x01\x83^7z\xadmq\x8f\x01\x9c\xb8" + - "K@\xce\x7f\x97A\xef\xfdE|\xecq\xe0\xc4m\x02" + - "\xf2\xfe\xb3\x0az]\xd2\xc5\x93\xb3\x108q\xa3\x80\x11" + - "\xff=\x0b\xbd\x1e\xab\xb8n\x1c8Q\x150\xea\xbf\xd8" + - "\xa0\xd7\xe2\x17\xd7n\x01N\x1c\x0az\x81\xd0\xe9\xda\xd1" + - "\x85\xb6\xc7QhuX:\xb53\xe8\x8e\x02\xe8B\xdb" + - "\xbb\x99\xf0W\xba\x9a8\xa3\xbc\xe6\x16\xc4\xd3\x8a\xc5\xba" + - "\xa8Zt\x03\x12\x16#\x12t\xa1\x1c\xc1P\x8b\x19\xe0" + - "z[\x03I\xd6\xea\x9c\xf3G\xad\xe1\xbc\xf9\x1f1F" + - "\xf2\x95\xb4\xa6}\xfc&ih]*Kky\x94\x1b" + - "\xb9\x19+\xd1\xc8\x95\xac\xf0\xc8\x1f\xa7\xc9\xb4\xfeo\xfb" + - "\xeb\x1f\xa7\xf0\xfa}\x1e\xe5\x93!\xb7\xfe!\x09\xdf\xe1" + - "Q>\x1d\xaa\xe4~D\xbe~\x92G\xf9b\xd0\xf7~" + - "\xffq\x00\xf9\"\x8f\xc9Pe$\xfe\x9a\x06\xfe\x8a\xea" + - "\x07\xa7.B\xb7.\x8a\xe2\xd3\x00\xa9j\xaa+\x12N" + - "]\x14q\xeb\"\x11\x87\x01R\xf5$\x9f\x17\xae\x8b\x9a" + - "\xf0>\x80T#\xc9\xe7\xe3\xd4\xdb\xa6P0\x82\xca1" + - "\xab\x8f\xde\xa3j\x15\x93\xad\xd7\x88Gk\xb9\xa2f\x0b" + - "\x06\x83 \xd7\x17\x83Mo\xa8\xfcp;\xf4n3." + - "E$\xcc\xa0\xe97\xea\xae\xe1\x9e?]\xe6\xc9\xea\x85" + - "\xccHV1X&\xc5\x0c\xc1\x0d\x08\x83|T\xae\xc6" + - "\xd0\xab7@\xf0:\x19\"\xfb\xb4\x99\xac\xcf0t4" + - "J\xaa\xf4%A\x95\xee\x17\xe9t\xd9\xb8\x8bGy5" + - "\x1dm\x97{\xb4\xf2pp\xafhM+\x05\x93\x95a" + - "\x02<3\xfc^\x8f9\xa6\x17\xb2\x99$\x03\xc12&" + - "K \x9d\xb1ZO\xb1\xb8\x17\x09\xddG\x0a\xefy\x0e" + - "\xbdW\xb8\xd0#\x85\xf7R\x84\xdeSo\xf9#\x85\x87" + - "A\xd9#\x85\xfb\xc1\xe1\xfc\xd4;\xf5u4)\xdc\xb4" + - "\x18:\x94k\xea\xdd_u\xcb\xdb\xffw\x89\x92\xc8Q" + - "s\xbd\xcd /\xc1\xfd\x7f\x00\x00\x00\xff\xff\xf1\xc3d" + - "\xc6" +const schema_db8274f9144abc7e = "x\xda\xccZ{\x94\x14\xe5\x95\xbf\xb7\xaa{\xaa\x07\xa7" + + "\xa9)\xaaa\xa0\x0f\xb3\xb3\xe10\xebB\x82\x0a,Y" + + "\xc3\xc6\xcc\x0c\x0e\xc4\x19yLuC\x8eG1\xc7\x9a" + + "\xeeofj\xb6\xbb\xaa\xad\xaa\x1e\x81hx\x04D<" + + "j\xc4\x80\x0f\x126\x80\xeb\xee\x09\xc6\xacD\xdc,{" + + "tWvc\x8c\x1a\x89\xe4h\x16\x83\xd9lB\xd8]" + + "9\xb8\xae\xa8\x9b\xc3n\xb4\xf6\xdc\xaa\xae\xc7t73" + + "\x8c\xe4\x8f\xfc\xd7s\xeb{\xdc\xfb\xfb~\xf7\xf1\xddo" + + "\xae2\x1b;\xb9\xf9\xf1\x8d\"\x80r8\xde\xe0\xb0\xb9" + + "?\xd9\xb0\xaf\xfd\x9f\xb7\x80\x92Ft\xbe\xfcLo\xea" + + "\xbc\xbd\xe5$\xc4y\x01`\xe1c\xc2\x06\x94\x8f\x08\x02" + + "\x80\xfc\xb4\xf0\x1f\x80\xce\x9d\xd3\x9e\xfc\xe6cKw}" + + "\x05\xa44\x1f\x0e\x06\\\xf8H\xa2\x17\xe5'\x124\xf2" + + "[\x89\xedrc\xa3\x00\xe0\\/]yS\xea\xd5c" + + "4:\xbat\x8c\x96~71\x17e\xa4a\xf2\x87\x09" + + "Z\xfa\xb3\xc5\x1f\x1f\xf8\xf4\xee\x97\xb7\x82\x94\xe6F-" + + "\xfdV\xe3\x06\x94?tG\x9eo\\\x05\xe8\xbc\xb7k" + + "\xfa\xe3\xfb\x8f\xfdp\x1bH\x97#T4\x95&\xfd\x0c" + + "\x01\xe5\xf6I\x7f\x03\xe8\xbc\xf2\xc1M\xef\x1f\xfe\xc1\xa2" + + ";A\x9aC\x03\x90\x06\x9c\x94\xa6\x11S/#m:\x96\xbd" + + "r$\xbd\xf0\xc1]U\xaa\xbb\x03?\xb8l.\xca\xf1" + + "&R\x08\x9bn\x03t>\xf7\xa7O\xdd\xd7\xfd\xe0\xa6" + + "\xdd ]\x19\xec\xc7\x9an\xa4\xd567\xd1~\xff3" + + "\xf9\xeb\xc7\xca\xd7~\xef\xc1\x8aB\xee*\xfb\x9b\xe6\xd2" + + "\x80#\xee\x0a\xb3F\xdao\xf9\xa7\xe7\x9fz\x08\x94y" + + "\x88\xce\x9b\xfd\x9f|\x9d\xdf{\xf0$\xacA\x81\xf4[" + + "8#y\x80\xac\x9b\x93\xa4\xb1?\xfe\xd43\x7f\x7f\xff" + + "S\xdb\xbf\x0e\xca\xe5\x88\x00.\x9a\xf7&\xff\x97\x06\xec" + + "O\xd2n\xbbN<\xbb\xb2\xb8s\xcf\x01\x0f\x1f\xf7\xfb" + + "\x8bI\x8e\x83\x98\xb3\xb5\xe77\xc55\x8ff\x1f\xad " + + "\x17\xa7O\xcf&\xcf!\xe0\xc2\xe3\xc96\x04t\x16\xfd" + + "\xec\xf4\xaa\x15\xdf\x1d\xf8\xeb\xc8\xdc\xb7'o\xa0\xb9\xdb" + + "\x07\xce\x1dm\xce\x14\x1f\xafB\xc45\xf6\xad\xc9\x07Q" + + "F\xd1=\xcc\xc9\xa4\xc2\x13\x7fp}\xe3\xba\xd3\xcb\x9e" + + "\x04i\x9e\xbfL\xab\x98\xa1eF^z\xf4\x8f\xda_" + + "\xba\xed\x10(Wb\x00\xd6\x0c\xfa\x86\xf2\"\x91\xec\x8b" + + "\x9dl?\xf8\xec/\xee;\\\xc3\xb1\x9d\xe2\x06\x94\x1f" + + "sw\xd9/~^>N\xbf\x9c\xd8\xcd\xfcG\xea\xc3" + + "\xffx\xb8\x9a\xbf.\xc6G\xc4~\x94_\x11]\x04D" + + "\xd7\xbe\xbb\x8f\xee\xf9d\xe2\x9b\xef=]\xef\\\xdfm" + + "\xeeG9.\xb9\xe7*\x91&S{\xf0\xcd\xe7\xe6\xc7" + + "\xbe\x17%\x9a*\x9d!\xa4\xcb\x12\x11\xad\xf5\xed%I" + + "\xfd\x9d-\xcfU\xad\xe6\x0e\x9c:\xa5\x17\xe59Sh" + + "\xb5\xf6)48\xf6\xe9\xe1\xed\xd2\xa9\x9f>\xefa\xe2" + + "\x19~t\xca\xb0\xcb\xca)\x04Z\xefM_{ ~" + + "\xfak/\x90)\x11\x17\x88'\\vN1Q\x96d" + + "\xfa\x99\x94[x@'\xfd\xe4\x9f}gI\xfe\x8d\x97" + + "\xeb\x98\"\xdf;\xed\x9c\xfc\xc84\xfa\xb5{\x1aYr" + + "j\xde\xa1/\xbdu\xef\xf1\xd7*\x96\xb8{\xbf;\xcd" + + "\xe5L\xbc\x85\xf6>\xbfv\xdf\xf5\x9as\xc3\xc9j\x18" + + "\xdd\x91\xed-\xdfE\xf9\x9a\x16Z\xee3-\xb4\\@" + + "\xd0z\xa3\xf7\xb6\x0c\xa3|\xc8\x1d\xfd\x84\xbb6wZ" + + "\x9d\xb1\xe9\xa7\x9f{3\xc2\xa9C-\xbfB\x889+" + + "\xbfp\xd3p\xe3\x1d\xa7NE\xd5z\xac\xc5\x05\xf8\x88" + + ";\xf5\x1f\xfe\xe5\xa1\xa1\x9b\xbfs\xect\x84Go\xb4" + + "\x98\xc4\xa3\xff\xfa\xab3_=[\xcc\xff\xbb\xeb1\xfe" + + "\xe1\xbc\xde\xb2\x98\xe0|\xbb\x85\\\xb8\xa5-\xb9t\xd6" + + "\x89\xbe3Q\xbc_\x9c\xbe\x84\x06\xfcr:-\xbe\xe8" + + "\x96.\xb6\xf6\xea\x1b\xce\xd4\x10\x0dg,FY\x9a\xe1" + + "b=c;\xca\xed\xe9\x16\x00g\xe4ow\xde\xf0\xf8" + + "\xf7W\x9e\xf3\x9c\xd8\xd5ejz\x01\xe9r\xdf\x97\xbb" + + "W}f\xd6\xd1sQ3\x92ir+\xf9\x13i\xda" + + "i\xe0\xea\xb3\x9fo\xbf\xef\x07\xe7\xea\xf9NWz." + + "\xcaJ\x9a\xe0ZA\x83\xdfY\xf6\x17\xaf\xa5\xc5\xf4\xfb" + + "U\xd06\xd0\xd8[\xd3\xc3(o\xa3\xb1\x0b7\xa7_" + + " >\xef\xff\xcb\x03\xffz\xfe\xd8u\x1f\xd4\xd8P\x9e" + + "\xd9\x8f\xf2\x8e\x99\xb4\xec\xb6\x99\x82\xbcm\xe6\xe5\x00\xce" + + "\x9d'\xbf\xb8\xee'_y\xef\x83j\x86\xb9\x8a\xdc1" + + "3\x83\xf2Nw\xc6\xbd3\x89\xb0\x0f\xad\xfe\xcf\x8dg" + + "wO\xfbM\xcd\xda\xf3Z\x87Q\xeej\xa5\x91\xd7\xb4" + + "\xbe \x1f\xa7_\xce\xab\xc2\xa3\xf3\xbb7\xbe|>r" + + "TGZ{\x09\x9e\x07\x85o\x9c\xda\xf4\x8b/\xfe6" + + "\x0a\xcf\xd3\xad\xbf\"x^l%xn\x7f\xe7\x91\xeb" + + "\xbe\xba\xf6\xdb\x1fE\x08\xf2V\xeb\x16\x9aj\x97u\x9d" + + "\x15\xccR,w\xa5\xff3wEN-\xe9\xa5\xc5]" + + "e{\x88\xe9\xb6\x96Sm\x96a\x1dV\xc9\xd0-\xd6" + + "\x87\xa84\xf31\x80\x18\x02H\xea0\x80r\x0b\x8fJ" + + "\x81C\x091ED\x914\x12\x0e\xf1\xa8\xd8\x1cJ\x1c" + + "\x97\xa2\x00+\xdd:\x0b@)\xf0\xa8\xac\xe3\x10\xf9\x14" + + "\xf2\x00R\xf9\x01\x00e\x1d\x8f\xcaV\x0e\x9d\x123\x8b" + + "\xaa\xcet\x10\xed\xa5\xa6\x89M\xc0a\x13\xa0c2\xdb" + + "\\\xaf\xf6\x17@d\x11\xb10|\x9b\x8dI\xe00\x09" + + "\xe8\x0c\x19e\xd3Z\xa3\xdb\xa8\x152l\xc0d\x16\x0e" + + "a\x03p\xd8\x008\x96yYfY\x9a\xa1\xafPu" + + "u\x90\x99\x00dY\x82\x8f\x03\x04\xc9\x0b\xfd4'\xcd" + + "\xdf\x03\x9c4O\xc00\xd1\xa0OV\xe9\x13\x07\x81\x93" + + "Z\x05\xc7d\x83\x9ae3\x13\xd7\xe4K\xee\xda\xbc\xa1" + + "w\xa2S\xd6\xbd\x0f\xc8L\xef\x83H\xbbvb\x1f\x86" + + "\xda\xf1\xb5\xda][\xd0\x98n\x8b=\xfa\x80Q\x05y" + + "o=\xc8{+\x90o\x8d@\xbey\x09\x80r;\x8f" + + "\xca]\x1cJ|\x05\xf3ms\x01\x94M<*\xf7p" + + "\xe8\xe4\xdcMz\xf2\x00\x10\xa09\xc0T\xbbl2\x8b" + + "d\x93\x01\xfbxtA\x9f\x0c\xb8q\x84\x99\xa4\xbb\x7f" + + "\x08\xa2j\xe6\x86\x82\x83\x1a\x03\xe9\xa5\xeb4\xcb\xd6\xf4" + + "\xc1\xd5\xae\xbc\xa3\xcf(h\xb9\xf5dU\x93\xabg\xeb" + + "b\x00Di\xea\x8d\x00\xc8I\xd2\x12\x80\x0emP7" + + "L\xe6\xe45+g\xe8:\x03>go\xecW\x0b\xaa" + + "\x9ec\xc1F\x0d\xb5\x1by\x1bd\x999\xc2\xcc+\xd4" + + "\x08}g\xf7\xa9\xa6\xca\x17-\xa5)\xc0q\xe9\x8d\x00" + + "J7\x8fJ_\x04\xc7\x15\x84\xe3r\x1e\x95\x1b\"8" + + "\xae!\x1c\xfbxT\xd6r\xe8\x18\xa66\xa8\xe9\xd72" + + "\xe0\xcd(\x03-[W\x8b\x8c0\xab\xe0\xb1\xd1(\xd9" + + "\x9a\xa1[\xd8\x1cf\x1d@l\x8e %\x8c\xc7\xc9+" + + "|J\xf9\x8c2\xf4\xd9\x19f\x95\x85\x82m)\xb1\xc0" + + "\x92\xe4b\x00%\xc1\xa3\x92\xe2\xb0\xc3dV\xb9`c" + + "sXM\xfc.v\xf5\xe1\x8b\xd00S\x8f\x86\x0b\x00" + + "\x94<\x8fJ\x89C\xac\xa0W\\\x12\x89\x06\xa2my\xcb\xee)\xf9\x7fm\xcc[v\x9fa\xda" + + "(\x00\x87\x02\x10o\x0d\x8bu\x0d\x90O\xf5\xe4\x0b\xec" + + ":\x8d\xd7m\x8c\x03\x87q\x18\xd3\xa9<~\x88\x14\xd8" + + "g?2" + + "U\x9d\xb4h\xaaE+\x8aM\xa6\x1e6t\xaa\x9f\xe2" + + "Q\xb9\xba\xfe\x01n,2\xcbR\x07YMx\x88\xd7" + + "\xc5Dg9\xb2:\xc3\xbc$s\x85\xc9,\xa1\\\xb0" + + "I\x8b&\xc7\xf1\xd4 n\xcd\xe6Q\xb9\x8a\xc3$~" + + "\xe4xz\xcc{ <\xa36f\x9a\x86\x89\xcda\x12" + + "\xae@\x92\xabl\x80\x86\xde\xcdlU+ \xb9eP" + + "\xa8V\x017^\\\x09a\xf3\xc4\xb3;\xc8;\x8a\xa3" + + "N\x8a\xe8\xdd\xcc\xa32\x93Cg\xd0Ts\xac\x8f\x99" + + "\xa8\x19\xf9\x95\xaandy\x96\xab!\xeb\xe4\x89n\xea" + + "\xf2\xc3\xb6 \x985\xf6|\x93U@\xa8L\xefk\xf3" + + "tN\x05:\xdf1+L\xc6\xc11o\xee\x0f\xb3E" + + "\x10\x0fw\x90\xb3\xdc\xc5\xa3\xb2+\x92WvR\xe4\xbc" + + "\x9fG\xe5\x1b\x1cJ\xb1X\x0ac\x00\xd2#\xc4\x92]" + + "<*\xfb\xb8\xd1)\x9b\x8d0\xdd\xee\xd6\x06A`V" + + "(%\x15\xbb\xb5A\x06\xbcu\xa9\xb151\x0e\x1eF" + + "\xbfe\x14\x98\xcd\xbaY\xae\xa0\x92\xcb\x8d0\xef{\x85" + + "\x8c\xfe\xa1\x8e\xc5\xdbL\x8d\xf7\x10\x7fE\xbfJ\x8a\xd0" + + "aV\xe8\xb8\x02\x8b\x147ch\xeb-\xee\x05\x83\x1a" + + "\x0e\x84\x1eS\xe1\x01Z\xbf\x93\xa0\xe3\xda\x8c\xa3\x9c\x7f" + + "I\xe8u>)\xe6-\x0e\x03BP\x13\xc4\x80\xc3\x18" + + "`G\xce]\xb0&\x14\xc6\xc6\xd3\xaa\xc3S\xcb\x03\x8e" + + "\x8a0\xff\x1a\x8b\xfe\xdd_\x92\x0e\x00'%\x05\xc7\xd7" + + "\x1c\xfd\xf9BMA\x15\x1b+\xca\xac*\xd9\x9a`\xe8" + + "\x16\xed\x15\xe1\xff\xe2z\xfc7C\xfe\xfb\x09m\xc7\x96" + + "(\xfd+\x09m\xe7\x9e\x90\xe9R\x8c\xf3\xe8\xbf\xf7\x00" + + "\x80\xb2\x8fG\xe5\xdb\x1cvx\xb5\x166\x87=\x9b\x0a" + + "e\xbd\x8ab\xb9\x01m9\xb5\x10&=\xc7d\xa5\x82" + + "\x9acK\xb1R=\x01\"p\x88\xae\x9f\x14K&\xb3" + + ",\xd4\x0c])\xab\x05\x8d\xb7\xd7\x07\x15\xaf^.\xf6" + + "\x99lDC\xa3lu\xd96+\x0a%\xdb\xba\x98z" + + "8\x04\x88\x82\xa4\xa0\x15\xac\xaa\x1c97\xa4B\x00\xd0" + + "\xbc\xe10\x0f\x88\xe5\xb2\x16$\x00\xa7`\xe4\xdc\x93\x05" + + "q\xa5Z\xac\xcd\x03\x0d\xe3\x06\xacQ\xe1\xceOK\xbf" + + "O\xf5\xdb\xd8W&2\xdd\xbdSDT\xa68\xd0\xc9" + + "\xa3\xb2<\xa2r\xcf\x82\x88\x1d\xbe\xca+\xfaC;\x84" + + "?g\xeb}\xad\xdaX\x91\xd2\x97\x0ff\xc5\x98.\x10" + + "\xae\x0f\xc7L4\xaa\xb8\xde\xb4\xdc\xc8\xa9\x85\xea` " + + "V\xa7\xb5h\x01r\xf1\x8e\x1e\xddtU\xa9\xcd\x85\x95" + + "\x80\xb9\xda_X^\x8f\xbd\x00\xd9u\xc8cv+\x86" + + "\xd8\xc8\x9bq\x09@\xf6v\x92\xdf\x85!<\xf26L" + + "\x03d7\x91\xfc\x1e\x0c\xee\x93\xf2\x0e<\x08\x90\xbd\x87" + + "\xc4\x0f\xd3\xf0\x18\xef\xfa\xa1\xbc\xdb]~\x17\xc9\xf7\x91" + + "<\x1eKa\x1c@\xde\x8bs\x01\xb2\x0f\x93\xfc0\xc9" + + "\x1b\xb8\x146\x00\xc8\x87p\x18 \xfb$\xc9\x9f!\xb9" + + "\x10O\xd1\x95Z>\x82&@\xf6\xefH\xfe}\x92'" + + "\xa6\xa70\x01 \x1fu\xe5\xcf\x91\xfcG$o\x9c\x91" + + "\xc2F\x00\xf9E\xdc\x02\x90\xfd!\xc9_#\xf9$L" + + "\xe1$\x00\xf98\xee\x01\xc8\xbeF\xf2\x7f#\xf9e\x0d" + + ")\xbc\x0c@\xfe\xb9\xab\xcf\x09\x92\xff\x9a\xe4M\xb1\x14" + + "6\x01\xc8\xbf\xc4\x03\x00\xd9_\x93\xfc\xbfI\x9e\x14R" + + "\x98\x04\x90\xdfv\xed:K\xf2\x04Wu\x9d\xf3i\\" + + "ug\xe3\x0d+\xe0\x09\xab\x04\x16\xf4|\xac\xcf\x10\xe9" + + "^\x86b\xd8(\x06D\x11\xd0)\x19Fa\xe5h\xf7" + + "\x10mu\xd0\xf2\xef\x87\xcda\xa7\x0c\x90\x84A\xc5\x05" + + "\xa2\xa1\xf7\xe4\x83\xe8S\x1d\xea|M4\xab\xabl\x1b" + + "\xe5\x12\xb4\x11\x17\xf3A\xa03\xcb\xfa2\xd3(\xaeF" + + "f\x165]-\x8c\x13\x02\x1b\x81\xc3F\xa8\xc4!\x7f" + + "\xed\xb1\xe3\xe1\x85o\xbb\x01\xa3\xb9jF\xb7\x95\x16\xaf" + + "V\x07/&8.\x08\x13\xa5\xa8G\xa2`\xdb\x88Z" + + "(\x7f\x9c\x988\xba\x88\xcbtxE\xe0xw\x04\xbf" + + "\xe1U\x15\xbf\xea\x944kj\x8b\x82\x0c\xb3\xda\x82\xce" + + "O\xc4\xe0\x83a\xe0\xf7\xed]4+ra*\xa86" + + "\xb3\xec\xae\x12\x96\x0a\x1a\xcb\x7f\x81\x99b\xb4N\xa8[" + + "\x06\xc5\xc6\xbb\x1b\x8c\xae\xad0\xd2\xd5'\xc3\xb9\x8a\xc1" + + "\x17\x8d\xe7 \xb3\xbd_=\xfa\x80A\xc5\x8f\x10\xad\xf8" + + "&6;\xc3,\xf1b\xce\"\xecT\x8e_\xb1N$" + + "ZgX\x9b\xcb\x85\xb1\xee\x7fu\xd6\xabSQ\xfa\xd7" + + "\x99\xc8]\x9f\xc8\xbd\x96Ge(Bn\xd6[\xe7\xae" + + "\x9f\x09\x9b|\x12\xcfU\xba|\x94~K<*\xb7s" + + "(\xaae{\x08\x9b\xc3\xc7\x9fQ \x8cnD\x11\xd7" + + "{\xf4<\x03\\\xe7\xbbk$)\x07\xaf\x12\x1f\x0b\xc6" + + "\x0b\x16\xd2\x16\x8c{\x80Ak\xbej\xe7\x0b\xf6\x1b:" + + "\xbcM\x89\xb7\xd3\xdd\xd2\xd6\x7f\xf5@\xbf\xad-\x1d\xda" + + "\x00\x9c\xf4-\x01\xc3V>\xfa\x9d{i\xaf\x09\x9c\xb4" + + "[@.x\x97B\xff\xfdI\xdaq7p\xd26\x01" + + "\xf9\xe0Y\x09\xfdV\xef\xfc\xf5\x93\x108\xe9\x0e\x01c" + + "\xc1{\x1e\xfa\x8db\xe9\xd6a\xe0$M\xc0x\xf0b" + + "\x85\xfe\x0b\x86t\xf3\x16\xe0\xa45aC\x13:<;" + + ":\xd1\xf19\x0fm.\xebG\xb77\xbdQ\x00\x9d\xe8" + + "\xf8\xd7+\xfeB\xf7+w\x94\xdf\xa1\x031\xa7\xda\xac" + + "\x93J^/\xc0a%\xc2A'*1\x8c\xf4\xc9\x01" + + ".\xb5\xbfQ\xe3'\x13,D\xfd\xf9\x1f3\xe6\xf2\xf5" + + "\xb4\xa6}\x82Nod]\xaa\xad\x9bxT\xa6s\xe3" + + "\x96\xd3\xb1\x0bY\xe1\x93_\xa4\xc9\xb4\xfe\x1f\x06\xeb\x1f" + + "\xa7p\xfd#\x1e\x95\x13\x11\xb7~\x9d\x84\xaf\xf2\xa8\xbc" + + "\x19)G\xdf _?\xc1\xa3\xf2~\xd8\xbc\x7f\xf7n" + + "\x00\xe5}\x1e3\x91JK\xfa\x90\x06\xfe\x96\xea\x11\xb7" + + "\xceB\xaf\xce\x8a\xe3\x03\x00\xd9\x04\xd5))\xb7\xce\x8a" + + "yu\x96\x84\xfd\x00\xd9f\x92\xcf\x8c\xd6Y3\xf0F" + + "\x80\xect\x92\xcf\xc6\xd1Wf\xa1l\x86\xe5o\xc1\x18" + + "\\\xae\xe9u\x93\xb7\xff\x9a\x80\xf62U+\x94M\x06" + + "a\xedP\x096\xdd\x91r\xc6{f\xf0:\x8aY\"" + + "a\x1e\xad\xa0\xdb8\x81f\xc5X\x99\xac`\x94\xf3\x03" + + "\x05\xd5d\xf9,3\x05/ \xf4\xf1q%\x81\x91W" + + "\x7f\x80\xf0u6B\xf613\xe3R\xd34\xd0\xac\xba" + + "j,\x08\xaf\x1a\xc1M\x83nL\xd7\xf1\xa8\xac\xa6\xa3" + + "\xed\xf4\x8eV\xe9\x0f/Gm9\xb5l\xb1\x1aL\x80" + + "gf\xd0\xb0\xb2\x86\x8cr!\x9fa \xd8\xe6\xfa*" + + "H\xc7\xad\xfe\xb3L\xf4#a\x93\x1b\x09\xfd7F\xf4" + + "\x9f\x12%e\x0fp\xd2\x0a\x8a\x84\xfes\x17\xfaO\xdd" + + "R\xd7A\xe0\xa4k(\x12\xfa/\xbd\xe8?_J\xf3" + + "_\x02N\x9a\x1fy\x85\xf1\xf1\xa9y\x85\xf1>\xb8\xfe" + + "@\x1f*\x09\x95\xab\xce\xa8\x14\xa1\xa2-\x85K\xe8\xd1" + + "x\x095r\x9c\x13z\xba\xb8\xe8\x8e\x7f\xf0\x8f&U" + + "1\xa7\xf1R{a~j\xfc\xff\x00\x00\x00\xff\xff\xe5" + + "\xf9\xce\x8f" func init() { schemas.Register(schema_db8274f9144abc7e, @@ -4561,6 +4775,7 @@ func init() { 0xb5f39f082b9ac18a, 0xb70431c0dc014915, 0xc082ef6e0d42ed1d, + 0xc5d6e311876a3604, 0xc793e50592935b4a, 0xcbd96442ae3bb01a, 0xd4d18de97bb12de3, @@ -4568,6 +4783,7 @@ func init() { 0xdbaa9d03d52b62dc, 0xdc3ed6801961e502, 0xe3e37d096a5b564e, + 0xe5ceae5d6897d7be, 0xe6646dec8feaa6ee, 0xea50d822450d1f17, 0xea58385c65416035, From f3244db86151eefb7b8b9f447656152698b7e5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Oliveirinha?= Date: Thu, 21 Apr 2022 22:37:16 +0100 Subject: [PATCH 7/9] TUN-6130: Fix vendoring due to case sensitive typo in package --- tracing/tracing.go | 2 +- .../contrib/propagators/{Jaeger => jaeger}/context.go | 0 .../contrib/propagators/{Jaeger => jaeger}/doc.go | 0 .../contrib/propagators/{Jaeger => jaeger}/jaeger_propagator.go | 0 vendor/modules.txt | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) rename vendor/go.opentelemetry.io/contrib/propagators/{Jaeger => jaeger}/context.go (100%) rename vendor/go.opentelemetry.io/contrib/propagators/{Jaeger => jaeger}/doc.go (100%) rename vendor/go.opentelemetry.io/contrib/propagators/{Jaeger => jaeger}/jaeger_propagator.go (100%) diff --git a/tracing/tracing.go b/tracing/tracing.go index d3786603..2cab213b 100644 --- a/tracing/tracing.go +++ b/tracing/tracing.go @@ -9,7 +9,7 @@ import ( "runtime" "github.com/rs/zerolog" - otelContrib "go.opentelemetry.io/contrib/propagators/Jaeger" + otelContrib "go.opentelemetry.io/contrib/propagators/jaeger" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" diff --git a/vendor/go.opentelemetry.io/contrib/propagators/Jaeger/context.go b/vendor/go.opentelemetry.io/contrib/propagators/jaeger/context.go similarity index 100% rename from vendor/go.opentelemetry.io/contrib/propagators/Jaeger/context.go rename to vendor/go.opentelemetry.io/contrib/propagators/jaeger/context.go diff --git a/vendor/go.opentelemetry.io/contrib/propagators/Jaeger/doc.go b/vendor/go.opentelemetry.io/contrib/propagators/jaeger/doc.go similarity index 100% rename from vendor/go.opentelemetry.io/contrib/propagators/Jaeger/doc.go rename to vendor/go.opentelemetry.io/contrib/propagators/jaeger/doc.go diff --git a/vendor/go.opentelemetry.io/contrib/propagators/Jaeger/jaeger_propagator.go b/vendor/go.opentelemetry.io/contrib/propagators/jaeger/jaeger_propagator.go similarity index 100% rename from vendor/go.opentelemetry.io/contrib/propagators/Jaeger/jaeger_propagator.go rename to vendor/go.opentelemetry.io/contrib/propagators/jaeger/jaeger_propagator.go diff --git a/vendor/modules.txt b/vendor/modules.txt index 7830b358..adc719aa 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -347,7 +347,7 @@ github.com/urfave/cli/v2 github.com/urfave/cli/v2/altsrc # go.opentelemetry.io/contrib/propagators v0.22.0 ## explicit; go 1.15 -go.opentelemetry.io/contrib/propagators/Jaeger +go.opentelemetry.io/contrib/propagators/jaeger # go.opentelemetry.io/otel v1.6.3 ## explicit; go 1.16 go.opentelemetry.io/otel From d68ad891591844ba7e6f54ced10d41577676f4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Oliveirinha?= Date: Wed, 27 Apr 2022 14:34:11 +0100 Subject: [PATCH 8/9] TUN-6142: Add tunnel details support to RPC This commit adds the tunnel details to RPC register connection response so we can have access to some of the details associacted to the tunnel that only the edge knows. Currently this is limited to knowing if the tunnel is remotely managed or not. In the future we could extend this with more information. --- tunnelrpc/pogs/connectionrpc.go | 7 +- tunnelrpc/tunnelrpc.capnp | 2 + tunnelrpc/tunnelrpc.capnp.go | 463 ++++++++++++++++---------------- 3 files changed, 243 insertions(+), 229 deletions(-) diff --git a/tunnelrpc/pogs/connectionrpc.go b/tunnelrpc/pogs/connectionrpc.go index 788a67a8..d713edc6 100644 --- a/tunnelrpc/pogs/connectionrpc.go +++ b/tunnelrpc/pogs/connectionrpc.go @@ -224,8 +224,9 @@ func (a *TunnelAuth) UnmarshalCapnproto(s tunnelrpc.TunnelAuth) error { } type ConnectionDetails struct { - UUID uuid.UUID - Location string + UUID uuid.UUID + Location string + TunnelIsRemotelyManaged bool } func (details *ConnectionDetails) MarshalCapnproto(s tunnelrpc.ConnectionDetails) error { @@ -235,6 +236,7 @@ func (details *ConnectionDetails) MarshalCapnproto(s tunnelrpc.ConnectionDetails if err := s.SetLocationName(details.Location); err != nil { return err } + s.SetTunnelIsRemotelyManaged(details.TunnelIsRemotelyManaged) return nil } @@ -252,6 +254,7 @@ func (details *ConnectionDetails) UnmarshalCapnproto(s tunnelrpc.ConnectionDetai if err != nil { return err } + details.TunnelIsRemotelyManaged = s.TunnelIsRemotelyManaged() return err } diff --git a/tunnelrpc/tunnelrpc.capnp b/tunnelrpc/tunnelrpc.capnp index c1d56d6e..3d2d1dd3 100644 --- a/tunnelrpc/tunnelrpc.capnp +++ b/tunnelrpc/tunnelrpc.capnp @@ -121,6 +121,8 @@ struct ConnectionDetails { uuid @0 :Data; # airport code of the colo where this connection landed locationName @1 :Text; + # tells if the tunnel is remotely managed + tunnelIsRemotelyManaged @2: Bool; } struct TunnelAuth { diff --git a/tunnelrpc/tunnelrpc.capnp.go b/tunnelrpc/tunnelrpc.capnp.go index 4d1af72f..a198ca15 100644 --- a/tunnelrpc/tunnelrpc.capnp.go +++ b/tunnelrpc/tunnelrpc.capnp.go @@ -1410,12 +1410,12 @@ type ConnectionDetails struct{ capnp.Struct } const ConnectionDetails_TypeID = 0xb5f39f082b9ac18a func NewConnectionDetails(s *capnp.Segment) (ConnectionDetails, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) return ConnectionDetails{st}, err } func NewRootConnectionDetails(s *capnp.Segment) (ConnectionDetails, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}) + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}) return ConnectionDetails{st}, err } @@ -1462,12 +1462,20 @@ func (s ConnectionDetails) SetLocationName(v string) error { return s.Struct.SetText(1, v) } +func (s ConnectionDetails) TunnelIsRemotelyManaged() bool { + return s.Struct.Bit(0) +} + +func (s ConnectionDetails) SetTunnelIsRemotelyManaged(v bool) { + s.Struct.SetBit(0, v) +} + // ConnectionDetails_List is a list of ConnectionDetails. type ConnectionDetails_List struct{ capnp.List } // NewConnectionDetails creates a new list of ConnectionDetails. func NewConnectionDetails_List(s *capnp.Segment, sz int32) (ConnectionDetails_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz) + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 2}, sz) return ConnectionDetails_List{l}, err } @@ -4525,230 +4533,231 @@ func CloudflaredServer_Methods(methods []server.Method, s CloudflaredServer_Serv return methods } -const schema_db8274f9144abc7e = "x\xda\xccZ{\x94\x14\xe5\x95\xbf\xb7\xaa{\xaa\x07\xa7" + - "\xa9)\xaaa\xa0\x0f\xb3\xb3\xe10\xebB\x82\x0a,Y" + - "\xc3\xc6\xcc\x0c\x0e\xc4\x19yLuC\x8eG1\xc7\x9a" + - "\xeeofj\xb6\xbb\xaa\xad\xaa\x1e\x81hx\x04D<" + - "j\xc4\x80\x0f\x126\x80\xeb\xee\x09\xc6\xacD\xdc,{" + - "tWvc\x8c\x1a\x89\xe4h\x16\x83\xd9lB\xd8]" + - "9\xb8\xae\xa8\x9b\xc3n\xb4\xf6\xdc\xaa\xae\xc7t73" + - "\x8c\xe4\x8f\xfc\xd7s\xeb{\xdc\xfb\xfb~\xf7\xf1\xddo" + - "\xae2\x1b;\xb9\xf9\xf1\x8d\"\x80r8\xde\xe0\xb0\xb9" + - "?\xd9\xb0\xaf\xfd\x9f\xb7\x80\x92Ft\xbe\xfcLo\xea" + - "\xbc\xbd\xe5$\xc4y\x01`\xe1c\xc2\x06\x94\x8f\x08\x02" + - "\x80\xfc\xb4\xf0\x1f\x80\xce\x9d\xd3\x9e\xfc\xe6cKw}" + - "\x05\xa44\x1f\x0e\x06\\\xf8H\xa2\x17\xe5'\x124\xf2" + - "[\x89\xedrc\xa3\x00\xe0\\/]yS\xea\xd5c" + - "4:\xbat\x8c\x96~71\x17e\xa4a\xf2\x87\x09" + - "Z\xfa\xb3\xc5\x1f\x1f\xf8\xf4\xee\x97\xb7\x82\x94\xe6F-" + - "\xfdV\xe3\x06\x94?tG\x9eo\\\x05\xe8\xbc\xb7k" + - "\xfa\xe3\xfb\x8f\xfdp\x1bH\x97#T4\x95&\xfd\x0c" + - "\x01\xe5\xf6I\x7f\x03\xe8\xbc\xf2\xc1M\xef\x1f\xfe\xc1\xa2" + - ";A\x9aC\x03\x90\x06\x9c\x94\xa6\x11S/#m:\x96\xbd" + - "r$\xbd\xf0\xc1]U\xaa\xbb\x03?\xb8l.\xca\xf1" + - "&R\x08\x9bn\x03t>\xf7\xa7O\xdd\xd7\xfd\xe0\xa6" + - "\xdd ]\x19\xec\xc7\x9an\xa4\xd567\xd1~\xff3" + - "\xf9\xeb\xc7\xca\xd7~\xef\xc1\x8aB\xee*\xfb\x9b\xe6\xd2" + - "\x80#\xee\x0a\xb3F\xdao\xf9\xa7\xe7\x9fz\x08\x94y" + - "\x88\xce\x9b\xfd\x9f|\x9d\xdf{\xf0$\xacA\x81\xf4[" + - "8#y\x80\xac\x9b\x93\xa4\xb1?\xfe\xd43\x7f\x7f\xff" + - "S\xdb\xbf\x0e\xca\xe5\x88\x00.\x9a\xf7&\xff\x97\x06\xec" + - "O\xd2n\xbbN<\xbb\xb2\xb8s\xcf\x01\x0f\x1f\xf7\xfb" + - "\x8bI\x8e\x83\x98\xb3\xb5\xe77\xc55\x8ff\x1f\xad " + - "\x17\xa7O\xcf&\xcf!\xe0\xc2\xe3\xc96\x04t\x16\xfd" + - "\xec\xf4\xaa\x15\xdf\x1d\xf8\xeb\xc8\xdc\xb7'o\xa0\xb9\xdb" + - "\x07\xce\x1dm\xce\x14\x1f\xafB\xc45\xf6\xad\xc9\x07Q" + - "F\xd1=\xcc\xc9\xa4\xc2\x13\x7fp}\xe3\xba\xd3\xcb\x9e" + - "\x04i\x9e\xbfL\xab\x98\xa1eF^z\xf4\x8f\xda_" + - "\xba\xed\x10(Wb\x00\xd6\x0c\xfa\x86\xf2\"\x91\xec\x8b" + - "\x9dl?\xf8\xec/\xee;\\\xc3\xb1\x9d\xe2\x06\x94\x1f" + - "sw\xd9/~^>N\xbf\x9c\xd8\xcd\xfcG\xea\xc3" + - "\xffx\xb8\x9a\xbf.\xc6G\xc4~\x94_\x11]\x04D" + - "\xd7\xbe\xbb\x8f\xee\xf9d\xe2\x9b\xef=]\xef\\\xdfm" + - "\xeeG9.\xb9\xe7*\x91&S{\xf0\xcd\xe7\xe6\xc7" + - "\xbe\x17%\x9a*\x9d!\xa4\xcb\x12\x11\xad\xf5\xed%I" + - "\xfd\x9d-\xcfU\xad\xe6\x0e\x9c:\xa5\x17\xe59Sh" + - "\xb5\xf6)48\xf6\xe9\xe1\xed\xd2\xa9\x9f>\xefa\xe2" + - "\x19~t\xca\xb0\xcb\xca)\x04Z\xefM_{ ~" + - "\xfak/\x90)\x11\x17\x88'\\vN1Q\x96d" + - "\xfa\x99\x94[x@'\xfd\xe4\x9f}gI\xfe\x8d\x97" + - "\xeb\x98\"\xdf;\xed\x9c\xfc\xc84\xfa\xb5{\x1aYr" + - "j\xde\xa1/\xbdu\xef\xf1\xd7*\x96\xb8{\xbf;\xcd" + - "\xe5L\xbc\x85\xf6>\xbfv\xdf\xf5\x9as\xc3\xc9j\x18" + - "\xdd\x91\xed-\xdfE\xf9\x9a\x16Z\xee3-\xb4\\@" + - "\xd0z\xa3\xf7\xb6\x0c\xa3|\xc8\x1d\xfd\x84\xbb6wZ" + - "\x9d\xb1\xe9\xa7\x9f{3\xc2\xa9C-\xbfB\x889+" + - "\xbfp\xd3p\xe3\x1d\xa7NE\xd5z\xac\xc5\x05\xf8\x88" + - ";\xf5\x1f\xfe\xe5\xa1\xa1\x9b\xbfs\xect\x84Go\xb4" + - "\x98\xc4\xa3\xff\xfa\xab3_=[\xcc\xff\xbb\xeb1\xfe" + - "\xe1\xbc\xde\xb2\x98\xe0|\xbb\x85\\\xb8\xa5-\xb9t\xd6" + - "\x89\xbe3Q\xbc_\x9c\xbe\x84\x06\xfcr:-\xbe\xe8" + - "\x96.\xb6\xf6\xea\x1b\xce\xd4\x10\x0dg,FY\x9a\xe1" + - "b=c;\xca\xed\xe9\x16\x00g\xe4ow\xde\xf0\xf8" + - "\xf7W\x9e\xf3\x9c\xd8\xd5ejz\x01\xe9r\xdf\x97\xbb" + - "W}f\xd6\xd1sQ3\x92ir+\xf9\x13i\xda" + - "i\xe0\xea\xb3\x9fo\xbf\xef\x07\xe7\xea\xf9NWz." + - "\xcaJ\x9a\xe0ZA\x83\xdfY\xf6\x17\xaf\xa5\xc5\xf4\xfb" + - "U\xd06\xd0\xd8[\xd3\xc3(o\xa3\xb1\x0b7\xa7_" + - " >\xef\xff\xcb\x03\xffz\xfe\xd8u\x1f\xd4\xd8P\x9e" + - "\xd9\x8f\xf2\x8e\x99\xb4\xec\xb6\x99\x82\xbcm\xe6\xe5\x00\xce" + - "\x9d'\xbf\xb8\xee'_y\xef\x83j\x86\xb9\x8a\xdc1" + - "3\x83\xf2Nw\xc6\xbd3\x89\xb0\x0f\xad\xfe\xcf\x8dg" + - "wO\xfbM\xcd\xda\xf3Z\x87Q\xeej\xa5\x91\xd7\xb4" + - "\xbe \x1f\xa7_\xce\xab\xc2\xa3\xf3\xbb7\xbe|>r" + - "TGZ{\x09\x9e\x07\x85o\x9c\xda\xf4\x8b/\xfe6" + - "\x0a\xcf\xd3\xad\xbf\"x^l%xn\x7f\xe7\x91\xeb" + - "\xbe\xba\xf6\xdb\x1fE\x08\xf2V\xeb\x16\x9aj\x97u\x9d" + - "\x15\xccR,w\xa5\xff3wEN-\xe9\xa5\xc5]" + - "e{\x88\xe9\xb6\x96Sm\x96a\x1dV\xc9\xd0-\xd6" + - "\x87\xa84\xf31\x80\x18\x02H\xea0\x80r\x0b\x8fJ" + - "\x81C\x091ED\x914\x12\x0e\xf1\xa8\xd8\x1cJ\x1c" + - "\x97\xa2\x00+\xdd:\x0b@)\xf0\xa8\xac\xe3\x10\xf9\x14" + - "\xf2\x00R\xf9\x01\x00e\x1d\x8f\xcaV\x0e\x9d\x123\x8b" + - "\xaa\xcet\x10\xed\xa5\xa6\x89M\xc0a\x13\xa0c2\xdb" + - "\\\xaf\xf6\x17@d\x11\xb10|\x9b\x8dI\xe00\x09" + - "\xe8\x0c\x19e\xd3Z\xa3\xdb\xa8\x152l\xc0d\x16\x0e" + - "a\x03p\xd8\x008\x96yYfY\x9a\xa1\xafPu" + - "u\x90\x99\x00dY\x82\x8f\x03\x04\xc9\x0b\xfd4'\xcd" + - "\xdf\x03\x9c4O\xc00\xd1\xa0OV\xe9\x13\x07\x81\x93" + - "Z\x05\xc7d\x83\x9ae3\x13\xd7\xe4K\xee\xda\xbc\xa1" + - "w\xa2S\xd6\xbd\x0f\xc8L\xef\x83H\xbbvb\x1f\x86" + - "\xda\xf1\xb5\xda][\xd0\x98n\x8b=\xfa\x80Q\x05y" + - "o=\xc8{+\x90o\x8d@\xbey\x09\x80r;\x8f" + - "\xca]\x1cJ|\x05\xf3ms\x01\x94M<*\xf7p" + - "\xe8\xe4\xdcMz\xf2\x00\x10\xa09\xc0T\xbbl2\x8b" + - "d\x93\x01\xfbxtA\x9f\x0c\xb8q\x84\x99\xa4\xbb\x7f" + - "\x08\xa2j\xe6\x86\x82\x83\x1a\x03\xe9\xa5\xeb4\xcb\xd6\xf4" + - "\xc1\xd5\xae\xbc\xa3\xcf(h\xb9\xf5dU\x93\xabg\xeb" + - "b\x00Di\xea\x8d\x00\xc8I\xd2\x12\x80\x0emP7" + - "L\xe6\xe45+g\xe8:\x03>go\xecW\x0b\xaa" + - "\x9ec\xc1F\x0d\xb5\x1by\x1bd\x999\xc2\xcc+\xd4" + - "\x08}g\xf7\xa9\xa6\xca\x17-\xa5)\xc0q\xe9\x8d\x00" + - "J7\x8fJ_\x04\xc7\x15\x84\xe3r\x1e\x95\x1b\"8" + - "\xae!\x1c\xfbxT\xd6r\xe8\x18\xa66\xa8\xe9\xd72" + - "\xe0\xcd(\x03-[W\x8b\x8c0\xab\xe0\xb1\xd1(\xd9" + - "\x9a\xa1[\xd8\x1cf\x1d@l\x8e %\x8c\xc7\xc9+" + - "|J\xf9\x8c2\xf4\xd9\x19f\x95\x85\x82m)\xb1\xc0" + - "\x92\xe4b\x00%\xc1\xa3\x92\xe2\xb0\xc3dV\xb9`c" + - "sXM\xfc.v\xf5\xe1\x8b\xd00S\x8f\x86\x0b\x00" + - "\x94<\x8fJ\x89C\xac\xa0W\\\x12\x89\x06\xa2my\xcb\xee)\xf9\x7fm\xcc[v\x9fa\xda" + - "(\x00\x87\x02\x10o\x0d\x8bu\x0d\x90O\xf5\xe4\x0b\xec" + - ":\x8d\xd7m\x8c\x03\x87q\x18\xd3\xa9<~\x88\x14\xd8" + - "g?2" + - "U\x9d\xb4h\xaaE+\x8aM\xa6\x1e6t\xaa\x9f\xe2" + - "Q\xb9\xba\xfe\x01n,2\xcbR\x07YMx\x88\xd7" + - "\xc5Dg9\xb2:\xc3\xbc$s\x85\xc9,\xa1\\\xb0" + - "I\x8b&\xc7\xf1\xd4 n\xcd\xe6Q\xb9\x8a\xc3$~" + - "\xe4xz\xcc{ <\xa36f\x9a\x86\x89\xcda\x12" + - "\xae@\x92\xabl\x80\x86\xde\xcdlU+ \xb9eP" + - "\xa8V\x017^\\\x09a\xf3\xc4\xb3;\xc8;\x8a\xa3" + - "N\x8a\xe8\xdd\xcc\xa32\x93Cg\xd0Ts\xac\x8f\x99" + - "\xa8\x19\xf9\x95\xaandy\x96\xab!\xeb\xe4\x89n\xea" + - "\xf2\xc3\xb6 \x985\xf6|\x93U@\xa8L\xefk\xf3" + - "tN\x05:\xdf1+L\xc6\xc11o\xee\x0f\xb3E" + - "\x10\x0fw\x90\xb3\xdc\xc5\xa3\xb2+\x92WvR\xe4\xbc" + - "\x9fG\xe5\x1b\x1cJ\xb1X\x0ac\x00\xd2#\xc4\x92]" + - "<*\xfb\xb8\xd1)\x9b\x8d0\xdd\xee\xd6\x06A`V" + - "(%\x15\xbb\xb5A\x06\xbcu\xa9\xb151\x0e\x1eF" + - "\xbfe\x14\x98\xcd\xbaY\xae\xa0\x92\xcb\x8d0\xef{\x85" + - "\x8c\xfe\xa1\x8e\xc5\xdbL\x8d\xf7\x10\x7fE\xbfJ\x8a\xd0" + - "aV\xe8\xb8\x02\x8b\x147ch\xeb-\xee\x05\x83\x1a" + - "\x0e\x84\x1eS\xe1\x01Z\xbf\x93\xa0\xe3\xda\x8c\xa3\x9c\x7f" + - "I\xe8u>)\xe6-\x0e\x03BP\x13\xc4\x80\xc3\x18" + - "`G\xce]\xb0&\x14\xc6\xc6\xd3\xaa\xc3S\xcb\x03\x8e" + - "\x8a0\xff\x1a\x8b\xfe\xdd_\x92\x0e\x00'%\x05\xc7\xd7" + - "\x1c\xfd\xf9BMA\x15\x1b+\xca\xac*\xd9\x9a`\xe8" + - "\x16\xed\x15\xe1\xff\xe2z\xfc7C\xfe\xfb\x09m\xc7\x96" + - "(\xfd+\x09m\xe7\x9e\x90\xe9R\x8c\xf3\xe8\xbf\xf7\x00" + - "\x80\xb2\x8fG\xe5\xdb\x1cvx\xb5\x166\x87=\x9b\x0a" + - "e\xbd\x8ab\xb9\x01m9\xb5\x10&=\xc7d\xa5\x82" + - "\x9acK\xb1R=\x01\"p\x88\xae\x9f\x14K&\xb3" + - ",\xd4\x0c])\xab\x05\x8d\xb7\xd7\x07\x15\xaf^.\xf6" + - "\x99lDC\xa3lu\xd96+\x0a%\xdb\xba\x98z" + - "8\x04\x88\x82\xa4\xa0\x15\xac\xaa\x1c97\xa4B\x00\xd0" + - "\xbc\xe10\x0f\x88\xe5\xb2\x16$\x00\xa7`\xe4\xdc\x93\x05" + - "q\xa5Z\xac\xcd\x03\x0d\xe3\x06\xacQ\xe1\xceOK\xbf" + - "O\xf5\xdb\xd8W&2\xdd\xbdSDT\xa68\xd0\xc9" + - "\xa3\xb2<\xa2r\xcf\x82\x88\x1d\xbe\xca+\xfaC;\x84" + - "?g\xeb}\xad\xdaX\x91\xd2\x97\x0ff\xc5\x98.\x10" + - "\xae\x0f\xc7L4\xaa\xb8\xde\xb4\xdc\xc8\xa9\x85\xea` " + - "V\xa7\xb5h\x01r\xf1\x8e\x1e\xddtU\xa9\xcd\x85\x95" + - "\x80\xb9\xda_X^\x8f\xbd\x00\xd9u\xc8cv+\x86" + - "\xd8\xc8\x9bq\x09@\xf6v\x92\xdf\x85!<\xf26L" + - "\x03d7\x91\xfc\x1e\x0c\xee\x93\xf2\x0e<\x08\x90\xbd\x87" + - "\xc4\x0f\xd3\xf0\x18\xef\xfa\xa1\xbc\xdb]~\x17\xc9\xf7\x91" + - "<\x1eKa\x1c@\xde\x8bs\x01\xb2\x0f\x93\xfc0\xc9" + - "\x1b\xb8\x146\x00\xc8\x87p\x18 \xfb$\xc9\x9f!\xb9" + - "\x10O\xd1\x95Z>\x82&@\xf6\xefH\xfe}\x92'" + - "\xa6\xa70\x01 \x1fu\xe5\xcf\x91\xfcG$o\x9c\x91" + - "\xc2F\x00\xf9E\xdc\x02\x90\xfd!\xc9_#\xf9$L" + - "\xe1$\x00\xf98\xee\x01\xc8\xbeF\xf2\x7f#\xf9e\x0d" + - ")\xbc\x0c@\xfe\xb9\xab\xcf\x09\x92\xff\x9a\xe4M\xb1\x14" + - "6\x01\xc8\xbf\xc4\x03\x00\xd9_\x93\xfc\xbfI\x9e\x14R" + - "\x98\x04\x90\xdfv\xed:K\xf2\x04Wu\x9d\xf3i\\" + - "ug\xe3\x0d+\xe0\x09\xab\x04\x16\xf4|\xac\xcf\x10\xe9" + - "^\x86b\xd8(\x06D\x11\xd0)\x19Fa\xe5h\xf7" + - "\x10mu\xd0\xf2\xef\x87\xcda\xa7\x0c\x90\x84A\xc5\x05" + - "\xa2\xa1\xf7\xe4\x83\xe8S\x1d\xea|M4\xab\xabl\x1b" + - "\xe5\x12\xb4\x11\x17\xf3A\xa03\xcb\xfa2\xd3(\xaeF" + - "f\x165]-\x8c\x13\x02\x1b\x81\xc3F\xa8\xc4!\x7f" + - "\xed\xb1\xe3\xe1\x85o\xbb\x01\xa3\xb9jF\xb7\x95\x16\xaf" + - "V\x07/&8.\x08\x13\xa5\xa8G\xa2`\xdb\x88Z" + - "(\x7f\x9c\x988\xba\x88\xcbtxE\xe0xw\x04\xbf" + - "\xe1U\x15\xbf\xea\x944kj\x8b\x82\x0c\xb3\xda\x82\xce" + - "O\xc4\xe0\x83a\xe0\xf7\xed]4+ra*\xa86" + - "\xb3\xec\xae\x12\x96\x0a\x1a\xcb\x7f\x81\x99b\xb4N\xa8[" + - "\x06\xc5\xc6\xbb\x1b\x8c\xae\xad0\xd2\xd5'\xc3\xb9\x8a\xc1" + - "\x17\x8d\xe7 \xb3\xbd_=\xfa\x80A\xc5\x8f\x10\xad\xf8" + - "&6;\xc3,\xf1b\xce\"\xecT\x8e_\xb1N$" + - "ZgX\x9b\xcb\x85\xb1\xee\x7fu\xd6\xabSQ\xfa\xd7" + - "\x99\xc8]\x9f\xc8\xbd\x96Ge(Bn\xd6[\xe7\xae" + - "\x9f\x09\x9b|\x12\xcfU\xba|\x94~K<*\xb7s" + - "(\xaae{\x08\x9b\xc3\xc7\x9fQ \x8cnD\x11\xd7" + - "{\xf4<\x03\\\xe7\xbbk$)\x07\xaf\x12\x1f\x0b\xc6" + - "\x0b\x16\xd2\x16\x8c{\x80Ak\xbej\xe7\x0b\xf6\x1b:" + - "\xbcM\x89\xb7\xd3\xdd\xd2\xd6\x7f\xf5@\xbf\xad-\x1d\xda" + - "\x00\x9c\xf4-\x01\xc3V>\xfa\x9d{i\xaf\x09\x9c\xb4" + - "[@.x\x97B\xff\xfdI\xdaq7p\xd26\x01" + - "\xf9\xe0Y\x09\xfdV\xef\xfc\xf5\x93\x108\xe9\x0e\x01c" + - "\xc1{\x1e\xfa\x8db\xe9\xd6a\xe0$M\xc0x\xf0b" + - "\x85\xfe\x0b\x86t\xf3\x16\xe0\xa45aC\x13:<;" + - ":\xd1\xf19\x0fm.\xebG\xb77\xbdQ\x00\x9d\xe8" + - "\xf8\xd7+\xfeB\xf7+w\x94\xdf\xa1\x031\xa7\xda\xac" + - "\x93J^/\xc0a%\xc2A'*1\x8c\xf4\xc9\x01" + - ".\xb5\xbfQ\xe3'\x13,D\xfd\xf9\x1f3\xe6\xf2\xf5" + - "\xb4\xa6}\x82Nod]\xaa\xad\x9bxT\xa6s\xe3" + - "\x96\xd3\xb1\x0bY\xe1\x93_\xa4\xc9\xb4\xfe\x1f\x06\xeb\x1f" + - "\xa7p\xfd#\x1e\x95\x13\x11\xb7~\x9d\x84\xaf\xf2\xa8\xbc" + - "\x19)G\xdf _?\xc1\xa3\xf2~\xd8\xbc\x7f\xf7n" + - "\x00\xe5}\x1e3\x91JK\xfa\x90\x06\xfe\x96\xea\x11\xb7" + - "\xceB\xaf\xce\x8a\xe3\x03\x00\xd9\x04\xd5))\xb7\xce\x8a" + - "yu\x96\x84\xfd\x00\xd9f\x92\xcf\x8c\xd6Y3\xf0F" + - "\x80\xect\x92\xcf\xc6\xd1Wf\xa1l\x86\xe5o\xc1\x18" + - "\\\xae\xe9u\x93\xb7\xff\x9a\x80\xf62U+\x94M\x06" + - "a\xedP\x096\xdd\x91r\xc6{f\xf0:\x8aY\"" + - "a\x1e\xad\xa0\xdb8\x81f\xc5X\x99\xac`\x94\xf3\x03" + - "\x05\xd5d\xf9,3\x05/ \xf4\xf1q%\x81\x91W" + - "\x7f\x80\xf0u6B\xf613\xe3R\xd34\xd0\xac\xba" + - "j,\x08\xaf\x1a\xc1M\x83nL\xd7\xf1\xa8\xac\xa6\xa3" + - "\xed\xf4\x8eV\xe9\x0f/Gm9\xb5l\xb1\x1aL\x80" + - "gf\xd0\xb0\xb2\x86\x8cr!\x9fa \xd8\xe6\xfa*" + - "H\xc7\xad\xfe\xb3L\xf4#a\x93\x1b\x09\xfd7F\xf4" + - "\x9f\x12%e\x0fp\xd2\x0a\x8a\x84\xfes\x17\xfaO\xdd" + - "R\xd7A\xe0\xa4k(\x12\xfa/\xbd\xe8?_J\xf3" + - "_\x02N\x9a\x1fy\x85\xf1\xf1\xa9y\x85\xf1>\xb8\xfe" + - "@\x1f*\x09\x95\xab\xce\xa8\x14\xa1\xa2-\x85K\xe8\xd1" + - "x\x095r\x9c\x13z\xba\xb8\xe8\x8e\x7f\xf0\x8f&U" + - "1\xa7\xf1R{a~j\xfc\xff\x00\x00\x00\xff\xff\xe5" + - "\xf9\xce\x8f" +const schema_db8274f9144abc7e = "x\xda\xccZ}t\x1c\xd5u\xbfwfW#\x19\xad" + + "G\xc3,\x96\xb5\xc7B\x8d\x8e]j'\x06d\xd7)" + + "u\xd3H2\xb2\x83\x84?4\xbbV\x0e1&\x87\xd1" + + "\xee\x934\xea\xee\xcc23+l\x07\xe2\x0fl\x0c\x1c" + + "B0\xb1\xf9pBc\x9b\xd2\x9e\x98$\x85`\x9a\xba" + + "\x07Z\x9c\x86\x10Cpp\x0e\xa4&\x86\xa6\x89\xe3\xb6" + + "\xf8\x98R\x0cn\x8e\xdb\x98\xe9\xb93;\x1f\xda]$" + + "+\xce\x1f\xf9ou\xe7\xbe\xf7\xee\xfb\xbd\xdf\xfdx\xf7" + + "\xe9\xea;\x1a\xba\xb8\x8e\xf8F\x11@9\x10\xafs\xd8" + + "\xbc\x9fl\xd83\xe7\x9f\xb7\x80\x92Bt\xbe\xf8l_" + + "\xf2\x9c\xbd\xe58\xc4y\x01`\xe1\xe3\xc2\x06\x94\x0f\x0a" + + "\x02\x80\xfc\x8c\xf0\x1f\x80\xce\x9d3\x9e\xfc\xfa\xe3Kw" + + "\xde\x01R\x8a\x0f\x95\x01\x17>R\xdf\x87\xf2\xb7\xeaI" + + "\xf3\x1b\xf5\xdb\xe5\x86\x06\x01\xc0\xb9^\xba\xea\xc6\xe4\xab" + + "GH;:u\x8c\xa6~\xaf~\x1e\xcaHj\xf2\xf9" + + "z\x9a\xfaS\x85\x1f\xef\xfb\xe4\xae\x97\xb7\x82\x94\xe2\xc6" + + "M\xfdv\xc3\x06\x94\xcf\xbb\x9a\xe7\x1aV\x01:\xef\xef" + + "\x9c\xf9\xc4\xde#?\xdc\x06\xd2\x15\x08eK\xa5i?" + + "C@y\xce\xb4\xbf\x05t^9{\xe3\x07\x07~\xb0" + + "\xe8N\x90\xe6\x92\x02\x92\xc2\x0b\xd3\xda9@\xf9\xadi" + + "\x9d\x80\xce\xa9\xd3\xff\xb7\xfd\x0bsW\xde\x0f\xca\\\xe4" + + "\x00\xe2\x1ci\x9c\x9f\x96\"\x8d\xcb.!k:\x97\xbd" + + "r0\xb5\xf0\xc1\x9d\x15\xa6\xbb\x8ag/\x99\x87r\xbc" + + "\x91\x0c\xc2\xc6[\x01\x9dO\xff\xc9\xd3\xf7\xf5<\xb8i" + + "\x17HW\x05\xeb\xb1\xc654\xdb\xe6FZ\xef\x7f\xa6" + + "\x7f\xf5H\xe9\xda\xef>X6\xc8\x9deo\xe36\xe7\xe6\xef\xbd\xf0\xf4C\xa0\xccG" + + "t\xde\x1c\xfc\xf8\xeb\xfc\xa3\xfb\x8f\xc3\x00\x0ad\xdf\xc2" + + "\x96\xc4>\xda\xdd\xdc\x04\xe9\xfe\xf8\x13\xcf\xfe\xc3\xfdO" + + "o\xff*(W \x02\xb8h~)\xf1\xbf\xa4\xb07" + + "A\xab\xed<\xf6\xdc\xca\xc2\x8e\xdd\xfb<|\xdc\xef\x87" + + "\x13\x1c\x071gk\xef\xaf\x0b\x03\x8fe\x1e+#\x17" + + "\xa7O\xcf%\xce \xe0\xc2\xa3\x896\x04t\x16\xfd\xec" + + "\xe4\xaa\x15\xdf\x19\xfa\x9b\xc8\xd8w\xa6o\xa0\xb1\xdb\x87" + + "\xce\x1cjJ\x17\x9e\xa8@\xc4\xdd\xec\xdb\xd3\xf7\xa3\x8c" + + "\xa2{\x98\xd3\xc9\x84o]~}\xc3\xba\x93\xcb\x9e\x04" + + "i\xbe?M\xab\x98\xa6i\xc6^z\xec\x0f\xe7\xbct" + + "\xebS\xa0\\\x85\x01X-\xf4\x0d\xe5E\"\xed/v" + + "|\xce\xfe\xe7~~\xdf\x81*\x8e\xed\x107\xa0\xfc\xb8" + + "\xbb\xca^\xf13\xf2Q\xfa\xe5\xc4n\xe2?T\x1f\xfe" + + "\xa7\x03\x95\xfcu1>(\x0e\xa2\xfc\x8a\xe8\" \xba" + + "\xfb\xbb\xe7\xd0\xee\x8f\xd7\x7f\xfd\xfdgj\xaa\xbf\xd74" + + "\x88r\\r\x0fV\"\"]\xd6\x8bo>\xdf\x11\xfb" + + "n\x94i\x8fK\xa7\x08\xea\x83\xaeB\xeb;K\x12\xfa" + + "\xbb[\x9e\xaf\x00\xc5U\xfc\xdc\xa5}(\x17.\xa5\xd9" + + "\xb4KI9\xf6\xc9\xd1\xed\xd2\x89\x9f\xbe\xe0\x81\xe2\xed" + + "<.\x8f\xd2\xce?&\x13j}7~\xe5\x81\xf8\xc9" + + "\xaf\xbcH\xc6E| Nn\xb5\xb0[6Q\x1e\x90" + + "\xe9\xa7\"7\xf3\x80N\xea\xc9?\xfb\xf6\x92\xdc\x1b/" + + "\xd7\xe0\xa8|t\xc6\x19\xf9\xad\x19\xf4\xeb\x8d\x19\x04\xea" + + "\x89\xf9O}\xe1\xed/\x1d}\xad\xbc\x13w\xedE\xcd" + + ".iz\x9bi\xedsk\xf7\\\xaf97\x1c\xaf\x04" + + "\xc6\xd5\xd4\x9a\xbf\x83\xf2\xe6f\x9a\xee\xf6f\x9a.`" + + "h-\xed_4\x8f\xa2|\xd6\xd5~\xcf\x9d\x9b;\xa9" + + "\xb6l\xfa\xe9\xa7\xdf\x8c\x90\xeal\xf3/\x11b\xce\xca" + + "\xcf\xde8\xdap\xfb\x89\x13Q\xb3\xdenv\x01>\xef" + + "\x0e\xfd\xc7\x7fyh\xe4\xa6o\x1f9\x19%\xd2L\x93" + + "\x88\xf4_\x7f}\xea\xcb\xa7\x0b\xb9\x7fw]\xc6?\x9c" + + "\x96\x99\x8b\x09\xce\x8e\x99\xe4\xc3\xcdm\x89\xa5\xed\xc7\xfa" + + "OE\xf1N\xb4,!\x859-4\xf9\xa2\x9b\xbb\xd9" + + "\xdakn8U\xc5\xb4\xa5-\x8bQ\x1ehq\xb1n" + + "\xd9\x8e\xb2\x96j\x06p\xc6\xfen\xc7\x0dO|\x7f\xe5" + + "\x19\xcf\x8b][>\x97Z@\xb6\xdc\xf7\xc5\x9eU\x7f" + + "\xda~\xe8Lt\x1bJ\x8a\xfcJf)Zi\xe8\x9a" + + "\xd3\x9f\x99s\xdf\x0f\xce\xd4r\x9em\xa9y(\xefJ" + + "\x11\\;H\xf9\xdde\x7f\xf9ZJL}P\x01m" + + "\x1d\xe9>\x93\x1aE\xf9p\xca\x0dh\xa9\x17\x89\xd0{" + + "\xffj\xdf\xbf\x9e;r\xdd\xd9\xaa=\x1c\x9cE\xdc\x9f" + + "E\xd3\x1e\x9e%\xc8\x87g]\x01\xe0\xdcy\xfc\xf3\xeb" + + "~r\xc7\xfbg+\x19\xe6\x1arhV\x1a\xe5\xd7\xdd" + + "\x11Gg\x11a\x1fZ\xfd\x9f\x1bO\xef\x9a\xf1\xeb\xaa" + + "\xb9oi\x1dEy[+inn}Q\xbe\xecr" + + "\xf2\xc4W\x85\xc7:z6\xbe|.rT\xe7[\xfb" + + "\x08\x9e\x07\x85\xaf\x9d\xd8\xf4\xf3\xcf\xff&\x0a\xcf\xb9\xd6" + + "_\x12<\x89\xcb\x09\x9e\xdb\xde}\xe4\xba/\xaf\xfd\xe6" + + "\x87\x11\x82\xcc\xbf|\x0b\x0d\xb5K\xba\xce\xf2f1\x96" + + "\xbd\xca\xff\x99\xbd2\xab\x16\xf5\xe2\xe2\xee\x92=\xc2t" + + "[\xcb\xaa6K\xb3N\xabh\xe8\x16\xebGT\x9a\xf8" + + "\x18@\x0c\x01$u\x14@\xb9\x99G%\xcf\xa1\x84\x98" + + "$\xa2H\x1a\x09GxTl\x0e%\x8eKR\x84\x95" + + "ni\x07P\xf2<*\xeb8D>\x89<\x80Tz" + + "\x00@Y\xc7\xa3\xb2\x95C\xa7\xc8\xcc\x82\xaa3\x1dD" + + "{\xa9ib#p\xd8\x08\xe8\x98\xcc6\xd7\xab\x83y" + + "\x10YD,\x8c\xdejc\x028L\x00:#F\xc9" + + "\xb4\x06t\x1b\xb5|\x9a\x0d\x99\xcc\xc2\x11\xac\x03\x0e\xeb" + + "\x00'\xda^\x86Y\x96f\xe8+T]\x1df&\x00" + + "\xed\xac\x9e\x8f\x03\x04\xd9\x0b\xfd<'u\xec\x06N\x9a" + + "/`\x98i\xd0'\xab\xf4\xb1\xfd\xc0I\xad\x82c\xb2" + + "a\xcd\xb2\x99\x89\x03\xb9\xa2;7o\xe8]\xe8\x94t" + + "\xef\x032\xd3\xfb \xd2\xaa]\xd8\x8f\xa1u|\xb5u" + + "\xd7\xe65\xa6\xdbb\xaf>dT@\xdeW\x0b\xf2\xbe" + + "2\xe4[#\x90o^\x02\xa0\xdc\xc6\xa3r\x17\x87\x12" + + "_\xc6|\xdb<\x00e\x13\x8f\xca\xbd\x1c:Yw\x91" + + "\xde\x1c\x00\x04h\x0e1\xd5.\x99\xcc\"\xd9t\xc0~" + + "\x1e]\xd0\xa7\x03n\x1cc&\xd9\xee\x1f\x82\xa8\x9a\xd9" + + "\x91\xe0\xa0&@z\xe9:\xcd\xb25}x\xb5+\xef" + + "\xec7\xf2Zv=\xed\xaa\xd1\xb5\xb3u1\x00\xa2t" + + "\xd9\x1a\x00\xe4$i\x09@\xa76\xac\x1b&sr\x9a" + + "\x955t\x9d\x01\x9f\xb57\x0e\xaayU\xcf\xb2`\xa1" + + "\xba\xea\x85\xbc\x052\xcc\x1cc\xe6\x95j\x84\xbe\xb3\xfb" + + "US\xe5\x0b\x96\xd2\x18\xe0\xb8t\x0d\x80\xd2\xc3\xa3\xd2" + + "\x1f\xc1q\x05\xe1\xb8\x9cG\xe5\x86\x08\x8e\x03\x84c?" + + "\x8f\xcaZ\x0e\x1d\xc3\xd4\x865\xfdZ\x06\xbc\x19e\xa0" + + "e\xebj\x81\x11fe<6\x1aE[3t\x0b\x9b" + + "\xc2\xac\x03\x88M\x11\xa4\x84\xc98y\xa5O)\x9fQ" + + "\x86>;\xcd\xac\x92\x90\xb7-%\x16\xec$\xb1\x18@" + + "\xa9\xe7QIr\xd8i2\xab\x94\xb7\xb1),'~" + + "\x17\xab\xfa\xf0Eh\x98\xaeE\xc3\x05\x00J\x8eG\xa5" + + "\xc8!\x96\xd1+,\x89D\x03\x1e=\x16\xde\xb2\x1b@" + + "\xb1yT6q\xe8X\xde\"\xbd\x809\x1f\xd1\xb6\x9c" + + "e\xf7\x16\xfd\xbf6\xe6,\xbb\xdf0m\x14\x80C\x01" + + "\x88\xb7\x86\xc5\xba\x87\xc8\xa7zsyv\x9d\xc6\xeb6" + + "\xc6\x81\xc38L\xe8T\x1e?D\x0al\x9e\xb7\xfb\xbb" + + "\x99Kd\xf8#\x1e\x95?\x8e\xec\xa6\x83\xe2\xd8\xd5<" + + "*\x9f\xe2\xd0Q\xb3Y\xa3\xa4\xdb\xab\x81W\x87+8" + + "\x9fa fM\x16\xd2\xc1_\xb6\xbe\x86[\x1b\xfa\x90" + + "6\\2U;\x02x\xa9\x98Sm6\xee\x93{\xce" + + "y\xfe\x02\xce9\xa8+\xa6|\xce~d\xaa8i\xd1" + + "T\x0bV\x14\x9bt-l\xe8T?\xc1\xa3rM\xed" + + "\x03\xdcX`\x96\xa5\x0e\xb3\xaa\xf0\x10\xaf\x89\x89\xce\xb2" + + "\xb4\xeb4\xf3\x92\xcc\x95&\xb3\x84R\xde&+\x1a\x1d" + + "\xc73\x83\xb85\x9bG\xe5j\x0e\x13\xf8\xa1\xe3\xd91" + + "\xff\x81\xf0\x8c\xda\x98i\x1a&6\x85I\xb8\x0cI\xb6" + + "\xbc\x00\x1az\x0f\xb3U-\x8f\xe4\x96A\xa5Z\x01\xdc" + + "dq%\x84\xcd\x13\xcf\xee$\xef(\x8c;)\xa2w" + + "\x13\x8f\xca,\x0e\x9daS\xcd\xb2~f\xa2f\xe4V" + + "\xaa\xba\x91\xe1Y\xb6\x8a\xac\xd3\xa7\xba\xa8\xcb\x0f\xdb\x82" + + "`\xd4\xc4\xe3MV\x06\xa1<\xbc\xbf\xcd\xb39\x19\xd8" + + "|{{\x98\x8c\x83c\xde<\x18f\x8b \x1e\xdeM" + + "\xcer\x17\x8f\xca\xceH^\xd9A\x91\xf3~\x1e\x95\xaf" + + "q(\xc5bI\x8c\x01H\x8f\x10Kv\xf2\xa8\xec\xe1" + + "\xc6\xa7l6\xc6t\xbbG\x1b\x06\x81Y\xa1\x94L\xec" + + "\xd1\x86\x19\xf0\xd6\xc5\xc6\xd6\xfaI\xf00\x06-#\xcf" + + "l\xd6\xc3\xb2y\x95\\n\x8cy\xdf\xcbd\xf4\x0fu" + + "\"\xde\xa6\xab\xbc\x87\xf8+\xfaUR\x84\x0e\xed\xa1\xe3" + + "\x0a,R\xdcL`\xad7\xb9\x17\x0c\xaa8\x10zL" + + "\x99\x07h\xfdN\x82\x8e\xbbg\x1c\xe7\xfcKB\xaf\xf3" + + "I1\x7fq\x18\x10\x82\x9a \x06\x1c\xc6\x00;\xb3\xee" + + "\x84U\xa106\x99U\x9d\x9eY\x1epT\x84\xf9\xf7" + + "X\xf4/\xff\x92\xb4\x0f8)!8\xbe\xe5\xe8\x8f\x17" + + "\xaa\x0a\xaa\xd8DQfU\xd1\xd6\x04C\xb7h\xad\x08" + + "\xff\x17\xd7\xe2\xbf\x19\xf2\xdfOhwo\x89\xd2\xbf\x9c" + + "\xd0v\xec\x0e\x99.\xc58\x8f\xfe\x8f\xee\x03P\xf6\xf0" + + "\xa8|\x93\xc3N\xaf\xd6\xc2\xa6\xb0iS\xa6\xacWQ" + + ",7\xa0-\xab\xe6\xc3\xa4\xe7\x98\xac\x98W\xb3l)" + + "\x96\xab'@\x04\x0e\xd1\xf5\x93B\xd1d\x96\x85\x9a\xa1" + + "+%5\xaf\xf1\xf6\xfa\xa0\xe2\xd5K\x85~\x93\x8di" + + "h\x94\xacn\xdbf\x05\xa1h[\x17R\x0f\x87\x00Q" + + "\x90\x14\xb4\xbc\x0bP\xa4`\xa2\xca\xb1\x8bGey\x04" + + "\xa0^\xca\x91\xd7\xf1\xa8\xac\x0e\x01R\xbe\x07\xa0\xac\xe6" + + "Q\xb9\x99C\xb1T\xd2\x82\xa4\xe0\xe4\x8d\xac{\xda " + + "\xaeT\x0b\x95\xb9\xa1\xd7\xe2\xd2\xac`\xd8,\xbf\xde\xe3" + + "h.\xdc\xf1\x85\xc6\xe6\x8a \xe9'\xb3\xdf\xa7\xaao" + + "\xe2\x8b\x16\x81\x03\x15\xb8\xb7\xd7\xc2}Ad\x1f\xbe\xc9" + + "+\x06\xc3}\x08\x7f\xc1\xd6\xfbV\xb5\xb1\x02%=\x1f" + + "\xee\xf2f\xbaA\xb8>\xd4\x99j,r}p\xb9\x91" + + "U\xf3\x95!D\xacL\x86\xd1\xb2\xe5\xc2\xc3Ct\xd1" + + "U\xc56\x17V\x02\xe6\x1a\x7fby=\xf6\x01d\xd6" + + "!\x8f\x99\xad\x18b#o\xc6%\x00\x99\xdbH~\x17" + + "\x86\xf0\xc8\xdb0\x05\x90\xd9D\xf2{1\xb8\x85\xcaw" + + "\xe3~\x80\xcc\xbd$~\x98\xd4c\xbc\xeb\xbd\xf2.w" + + "\xfa\x9d$\xdfC\xf2x,\x89q\x00\xf9Q\x9c\x07\x90" + + "y\x98\xe4\x07H^\xc7%\xb1\x0e@~\x0aG\x012" + + "O\x92\xfcY\x92\x0b\xf1$]\xc4\xe5\x83h\x02d\xfe" + + "\x9e\xe4\xdf'y\xfd\xcc$\xd6\x03\xc8\x87\\\xf9\xf3$" + + "\xff\x11\xc9\x1bZ\x92\xd8\x00 \x1f\xc6-\x00\x99\x1f\x92" + + "\xfc5\x92O\xc3$N\x03\x90\x8f\xe2n\x80\xcck$" + + "\xff7\x92_R\x97\xc4K\x00\xe4\xb7\\{\x8e\x91\xfc" + + "W$o\x8c%\xb1\x11@\xfe\x05\xee\x03\xc8\xfc\x8a\xe4" + + "\xffM\xf2\x84\x90\xc4\x04\x80\xfc\x8e\xbb\xaf\xd3$\xaf\xe7" + + "*.\x81>\x8d+nz\xbca\x05dP\xc9$D\xeb\xc4\xa9\x8d" + + "N3K\xbc\x90\xb3\x08\xfb\x9b\x93\xd7\xb9S\x89\xd6i" + + "\xd6\xe6ra\xa2[c\x8d\xf9j\xd4\xa1\xfe%(\xd2" + + "! r\xaf\xe5Q\x19\x89\x90\x9b\xf5\xd5\xe8\x10\xa4\xc3" + + "\xd6\xa0\xc4s\xe5\xde \xa5\xdf\"\x8f\xcam\x1c\x8aj" + + "\xc9\x1e\xc1\xa6\xf0\xcdh\x1c\x08\xe3\xdbW\xc4\xf5^=" + + "\xc7\x00\xd7\xf9\xee\x1aI\xca\xc1c\xc6o\x05\xe3G\x96" + + "\xdf\x16Lz\x80AC\xbfb\xe5\x8f\xecRtz\x8b" + + "\x12og\xba\x05\xb1\xffV\x82~3\\zj\x03p" + + "\xd27\x04\x0c\x1f\x00\xd0\xef\xf7K\x8f\x9a\xc0I\xbb\x04" + + "\xe4\x82\xe7,\xf4\x9f\xad\xa4\xbb\xef\x01N\xda& \x1f" + + "\xbcF\xa1\xdf \xeeX?\x0d\x81\x93n\x170\x16<" + + "\x03\xa2\xdf^\x96n\x19\x05N\xd2\x04\x8c\x07\x0f]\xe8" + + "\xbf{H7m\x01N\x1a\x08\xdb\xa0\xd0\xe9\xed\xa3\x0b" + + "\x1d\x9f\xf3\xd0\xe6\xb2~|S\xd4\xd3\x02\xe8B\xc7\xbf" + + "\x94\xf1\x1fu+s\xb5\xfc\xbe\x1e\x88Y\xd5f]T" + + "({\x01\x0e\xcb\x11\x0e\xbaP\x89a\xa4\xbb\x0ep\xb1" + + "]\x91*?\x99b!\xea\x8f\xff-c._\xcbj" + + "Z'\xe8\x0fG\xe6\xa5\x8a\xbc\x91Ge&7I\xc1" + + "]3tz\x06\xfb\xe4\x17i0\xcd\xff\x07\xc1\xfcG" + + ")\\\xff\x88G\xe5X\xc4\xad_'\xe1\xab<*o" + + "F\xca\xd17\xc8\xd7\x8f\xf1\xa8|\x10\xb6\xfc\xdf\xbb\x07" + + "@\xf9\x80\xc7t\xa4\xd2\x92\xce\x93\xe2o\xa8\x1eq\xeb" + + ",\xf4\xea\xac8>\x00\x90\xa9\xa7:%\xe9\xd6Y1" + + "\xaf\xce\x92p\x10 \xd3D\xf2Y\xd1:\xab\x05\xd7\x00" + + "df\x92|6\x8e\xbfh\x0b%3,\x7f\xf3\xc6\xf0" + + "rM\xaf\x99\xbc\xfd7\x08\xb4\x97\xa9Z\xbed2\xa8" + + "\xbc\x82\xf4\xf6D\xca\x19\xefq\xc2\xebCf\x88\x849" + + "\xb4\x82\x1e\xe5\x14Z\x1c\x13e\xb2\xbcQ\xca\x0d\xe5U" + + "\x93\xe52\xcc\x14\xbc\x80\xd0\xcf\xc7\x95z\x8c\xfc\xb3\x00" + + "@\xf8\xa8\x1b!\xfb\x84\x99q\xa9i\x1ahV\\5" + + "\x16\x84W\x8d\xe0\xa6\xb1&\xbc\xe1I\\W\xf9\x8a7" + + "\x18^\x8e\xda\xb2j\xc9bU\x98\x00\xcf\xcc\xa0\xcde" + + "\x8d\x18\xa5|.\xcd@\xb0\xcd\xf5U\xb7\xba\xd8d\xd1" + + "W\xf4#a\xa3\x1b\x09\xfd\x97I\xf4\x1f %e7" + + "p\xd2\x0a\x8a\x84\xfe#\x19\xfa/\xe4R\xf7~\xe0\xa4" + + "?\xa7H\xe8\xbf\x0f\xa3\xff\xe8)u\xbc\x04\x9c\xd4\x11" + + "y\xbb\xf1\xf1\xa9z\xbb\xf1>\xb8\xfe@\x1f\xca\x09\x95" + + "\xab\xcc\xa8\x14\xa1\xa2\x8d\x88\x8b\xe8\xecx\x095r\x9c" + + "Sz\xf0\xb8\xe0w\x82\xe0\xffS*bN\xc3\xc5v" + + "\xd0\xfc\xd4\xf8\xff\x01\x00\x00\xff\xff|\xba\xdf\xe8" func init() { schemas.Register(schema_db8274f9144abc7e, From 3254d0817364ac2c40d5d6bf015ea8c9b3c41d05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Oliveirinha?= Date: Thu, 28 Apr 2022 12:00:47 +0100 Subject: [PATCH 9/9] TUN-6014: Add remote config flag as default feature --- cmd/cloudflared/tunnel/configuration.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/cloudflared/tunnel/configuration.go b/cmd/cloudflared/tunnel/configuration.go index 14fd430c..778ec6b3 100644 --- a/cmd/cloudflared/tunnel/configuration.go +++ b/cmd/cloudflared/tunnel/configuration.go @@ -41,7 +41,8 @@ var ( LogFieldHostname = "hostname" - secretFlags = [2]*altsrc.StringFlag{credentialsContentsFlag, tunnelTokenFlag} + secretFlags = [2]*altsrc.StringFlag{credentialsContentsFlag, tunnelTokenFlag} + defaultFeatures = []string{supervisor.FeatureAllowRemoteConfig, supervisor.FeatureSerializedHeaders} ) // returns the first path that contains a cert.pem file. If none of the DefaultConfigSearchDirectories @@ -225,7 +226,7 @@ func prepareTunnelConfig( return nil, nil, errors.Wrap(err, "can't generate connector UUID") } log.Info().Msgf("Generated Connector ID: %s", clientUUID) - features := append(c.StringSlice("features"), supervisor.FeatureSerializedHeaders) + features := append(c.StringSlice("features"), defaultFeatures...) if c.IsSet(TunnelTokenFlag) { if transportProtocol == connection.AutoSelectFlag { protocolFetcher = func() (edgediscovery.ProtocolPercents, error) { @@ -243,7 +244,6 @@ func prepareTunnelConfig( return preferQuic, nil } } - features = append(features, supervisor.FeatureAllowRemoteConfig) log.Info().Msg("Will be fetching remotely managed configuration from Cloudflare API. Defaulting to protocol: quic") } namedTunnel.Client = tunnelpogs.ClientInfo{