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/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{ diff --git a/config/configuration.go b/config/configuration.go index 098df734..aecc8eb4 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" ) @@ -393,7 +393,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/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/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) 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= diff --git a/proxy/proxy.go b/proxy/proxy.go index a7f253db..042ecbb9 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -13,6 +13,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" @@ -74,7 +76,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, @@ -103,7 +106,7 @@ func (p *Proxy) ProxyHTTP( case ingress.HTTPOriginProxy: if err := p.proxyHTTPRequest( w, - req, + tr, originProxy, isWebsocket, rule.Config.DisableChunkedEncoding, @@ -175,15 +178,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.Clone(tr.Request.Context()) roundTripReq.Header.Set("Connection", "Upgrade") roundTripReq.Header.Set("Upgrade", "websocket") roundTripReq.Header.Set("Sec-Websocket-Version", "13") @@ -193,7 +196,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) } @@ -207,12 +210,18 @@ 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) + tr.AddSpans(resp.Header, p.log) + err = w.WriteRespHeaders(resp.StatusCode, resp.Header) if err != nil { return errors.Wrap(err, "Error writing response header") @@ -227,7 +236,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/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 diff --git a/tracing/client.go b/tracing/client.go index 6783912e..ffc477e1 100644 --- a/tracing/client.go +++ b/tracing/client.go @@ -12,11 +12,12 @@ import ( ) const ( - maxTraceAmount = 20 + MaxTraceAmount = 20 ) 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 { @@ -45,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...) @@ -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/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 a35d2962..2cab213b 100644 --- a/tracing/tracing.go +++ b/tracing/tracing.go @@ -3,9 +3,13 @@ package tracing import ( "context" "errors" + "fmt" "net/http" + "os" + "runtime" - otelContrib "go.opentelemetry.io/contrib/propagators/Jaeger" + "github.com/rs/zerolog" + otelContrib "go.opentelemetry.io/contrib/propagators/jaeger" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -21,16 +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 ( - 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")) + 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") ) @@ -38,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 { @@ -63,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, )), ) @@ -75,8 +102,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. @@ -88,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) diff --git a/tunnelrpc/pogs/connectionrpc.go b/tunnelrpc/pogs/connectionrpc.go index 997a9bc3..d713edc6 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 @@ -212,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 { @@ -223,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 } @@ -240,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/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..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 { @@ -131,6 +133,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..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 } @@ -1621,11 +1629,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 +1667,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 +1698,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 +1731,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 +2068,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 +2359,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 +2398,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 +2409,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 +2524,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 +4533,231 @@ 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}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, @@ -4561,6 +4784,7 @@ func init() { 0xb5f39f082b9ac18a, 0xb70431c0dc014915, 0xc082ef6e0d42ed1d, + 0xc5d6e311876a3604, 0xc793e50592935b4a, 0xcbd96442ae3bb01a, 0xd4d18de97bb12de3, @@ -4568,6 +4792,7 @@ func init() { 0xdbaa9d03d52b62dc, 0xdc3ed6801961e502, 0xe3e37d096a5b564e, + 0xe5ceae5d6897d7be, 0xe6646dec8feaa6ee, 0xea50d822450d1f17, 0xea58385c65416035, 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