diff --git a/Makefile b/Makefile index 402f3af6..da63e656 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,6 @@ tunnelrpc/tunnelrpc.capnp.go: tunnelrpc/tunnelrpc.capnp .PHONY: vet vet: - go vet -composites=false ./... + go vet ./... which go-sumtype # go get github.com/BurntSushi/go-sumtype go-sumtype $$(go list ./...) diff --git a/cmd/cloudflared/tunnel/cmd.go b/cmd/cloudflared/tunnel/cmd.go index 189af390..298487f1 100644 --- a/cmd/cloudflared/tunnel/cmd.go +++ b/cmd/cloudflared/tunnel/cmd.go @@ -427,10 +427,22 @@ func startDeclarativeTunnel(ctx context.Context, return err } + var scope pogs.Scope + if c.IsSet("group") == c.IsSet("system-name") { + err = fmt.Errorf("exactly one of --group or --system-name must be specified") + logger.WithError(err).Error("unable to determine scope") + return err + } else if c.IsSet("group") { + scope = pogs.NewGroup(c.String("group")) + } else { + scope = pogs.NewSystemName(c.String("system-name")) + } + cloudflaredConfig := &connection.CloudflaredConfig{ - CloudflaredID: cloudflaredID, - Tags: tags, BuildInfo: buildInfo, + CloudflaredID: cloudflaredID, + Scope: scope, + Tags: tags, } serviceDiscoverer, err := serviceDiscoverer(c, logger) @@ -838,6 +850,18 @@ func tunnelFlags(shouldHide bool) []cli.Flag { EnvVars: []string{"TUNNEL_USE_DECLARATIVE"}, Hidden: true, }), + altsrc.NewStringFlag(&cli.StringFlag{ + Name: "system-name", + Usage: "Unique identifier for this cloudflared instance. It can be configured individually in the Declarative Tunnel UI. Mutually exclusive with `--group`.", + EnvVars: []string{"TUNNEL_SYSTEM_NAME"}, + Hidden: true, + }), + altsrc.NewStringFlag(&cli.StringFlag{ + Name: "group", + Usage: "Name of a group of cloudflared instances, of which this instance should be an identical copy. They can be configured collectively in the Declarative Tunnel UI. Mutually exclusive with `--system-name`.", + EnvVars: []string{"TUNNEL_GROUP"}, + Hidden: true, + }), altsrc.NewDurationFlag(&cli.DurationFlag{ Name: "dial-edge-timeout", Usage: "Maximum wait time to set up a connection with the edge", diff --git a/connection/manager.go b/connection/manager.go index e266ba0f..29949062 100644 --- a/connection/manager.go +++ b/connection/manager.go @@ -47,6 +47,7 @@ type CloudflaredConfig struct { CloudflaredID uuid.UUID Tags []pogs.Tag BuildInfo *buildinfo.BuildInfo + Scope pogs.Scope } func NewEdgeManager( @@ -120,32 +121,34 @@ func (em *EdgeManager) newConnection(ctx context.Context) error { Logger: em.logger.WithField("subsystem", "muxer"), }) if err != nil { - return errors.Wrap(err, "handshake with edge error") + return errors.Wrap(err, "couldn't perform handshake with edge") } h2muxConn, err := newConnection(muxer, edgeIP) if err != nil { - return errors.Wrap(err, "create h2mux connection error") + return errors.Wrap(err, "couldn't create h2mux connection") } go em.serveConn(ctx, h2muxConn) connResult, err := h2muxConn.Connect(ctx, &pogs.ConnectParameters{ - OriginCert: em.state.getUserCredential(), CloudflaredID: em.cloudflaredConfig.CloudflaredID, - NumPreviousAttempts: 0, CloudflaredVersion: em.cloudflaredConfig.BuildInfo.CloudflaredVersion, + NumPreviousAttempts: 0, + OriginCert: em.state.getUserCredential(), + Scope: em.cloudflaredConfig.Scope, + Tags: em.cloudflaredConfig.Tags, }, em.logger) if err != nil { h2muxConn.Shutdown() - return errors.Wrap(err, "connect with edge error") + return errors.Wrap(err, "couldn't connect to edge") } if connErr := connResult.Err; connErr != nil { if !connErr.ShouldRetry { return errors.Wrap(connErr, em.noRetryMessage()) } - return errors.Wrapf(connErr, "server respond with retry at %v", connErr.RetryAfter) + return errors.Wrapf(connErr, "edge responded with RetryAfter=%v", connErr.RetryAfter) } em.state.newConnection(h2muxConn) diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go index a4fcee22..28b32092 100644 --- a/supervisor/supervisor.go +++ b/supervisor/supervisor.go @@ -57,8 +57,8 @@ func NewSupervisor( tunnelHostnames[i] = reverseProxyConfig.TunnelHostname } defaultEdgeMgrConfigurable := &connection.EdgeManagerConfigurable{ - tunnelHostnames, - defaultClientConfig.EdgeConnectionConfig, + TunnelHostnames: tunnelHostnames, + EdgeConnectionConfig: defaultClientConfig.EdgeConnectionConfig, } return &Supervisor{ connManager: connection.NewEdgeManager(streamHandler, defaultEdgeMgrConfigurable, userCredential, tlsConfig, @@ -139,8 +139,8 @@ func (s *Supervisor) notifySubsystemsNewConfig(newConfig *pogs.ClientConfig) *po } // Update connManager configurable s.connManager.UpdateConfigurable(&connection.EdgeManagerConfigurable{ - tunnelHostnames, - newConfig.EdgeConnectionConfig, + TunnelHostnames: tunnelHostnames, + EdgeConnectionConfig: newConfig.EdgeConnectionConfig, }) // Update streamHandler tunnelHostnameMapper mapping failedConfigs := s.streamHandler.UpdateConfig(newConfig.ReverseProxyConfigs) diff --git a/tunnelrpc/pogs/config_test.go b/tunnelrpc/pogs/config_test.go index bb1299a5..426d5342 100644 --- a/tunnelrpc/pogs/config_test.go +++ b/tunnelrpc/pogs/config_test.go @@ -12,6 +12,15 @@ import ( capnp "zombiezen.com/go/capnproto2" ) +// Assert *HTTPOriginConfig implements OriginConfig +var _ OriginConfig = (*HTTPOriginConfig)(nil) + +// Assert *WebSocketOriginConfig implements OriginConfig +var _ OriginConfig = (*WebSocketOriginConfig)(nil) + +// Assert *HelloWorldOriginConfig implements OriginConfig +var _ OriginConfig = (*HelloWorldOriginConfig)(nil) + func TestVersion(t *testing.T) { firstVersion := InitVersion() secondVersion := Version(1) @@ -35,7 +44,7 @@ func TestClientConfig(t *testing.T) { c.Origin = sampleHTTPOriginConfig() }), sampleReverseProxyConfig(func(c *ReverseProxyConfig) { - c.Origin = sampleHTTPOriginUnixPathConfig() + c.Origin = sampleHTTPOriginConfig(unixPathOverride) }), sampleReverseProxyConfig(func(c *ReverseProxyConfig) { c.Origin = sampleWebSocketOriginConfig() @@ -136,7 +145,7 @@ func TestReverseProxyConfig(t *testing.T) { c.Origin = sampleHTTPOriginConfig() }), sampleReverseProxyConfig(func(c *ReverseProxyConfig) { - c.Origin = sampleHTTPOriginUnixPathConfig() + c.Origin = sampleHTTPOriginConfig(unixPathOverride) }), sampleReverseProxyConfig(func(c *ReverseProxyConfig) { c.Origin = sampleWebSocketOriginConfig() @@ -224,7 +233,17 @@ func TestOriginConfigInvalidURL(t *testing.T) { ////////////////////////////////////////////////////////////////////////////// // Functions to generate sample data for ease of testing +// +// There's one "sample" function per struct type. Each goes like this: +// 1. Initialize an instance of the relevant struct. +// 2. Ensure the instance has no zero-valued fields. (This catches the +// error-case where a field was added, but we forgot to add code to +// marshal/unmarshal this field in CapnProto.) +// 3. Apply one or more "override" functions (which accept a +// pointer-to-struct, so they can mutate the instance). +// sampleClientConfig initializes a new ClientConfig literal, +// applies any number of overrides to it, and returns it. func sampleClientConfig(overrides ...func(*ClientConfig)) *ClientConfig { sample := &ClientConfig{ Version: Version(1337), @@ -247,6 +266,8 @@ func sampleClientConfig(overrides ...func(*ClientConfig)) *ClientConfig { return sample } +// sampleDoHProxyConfig initializes a new DoHProxyConfig struct, +// applies any number of overrides to it, and returns it. func sampleDoHProxyConfig(overrides ...func(*DoHProxyConfig)) *DoHProxyConfig { sample := &DoHProxyConfig{ ListenHost: "127.0.0.1", @@ -260,6 +281,8 @@ func sampleDoHProxyConfig(overrides ...func(*DoHProxyConfig)) *DoHProxyConfig { return sample } +// sampleReverseProxyConfig initializes a new ReverseProxyConfig struct, +// applies any number of overrides to it, and returns it. func sampleReverseProxyConfig(overrides ...func(*ReverseProxyConfig)) *ReverseProxyConfig { sample := &ReverseProxyConfig{ TunnelHostname: "hijk.example.com", @@ -275,9 +298,11 @@ func sampleReverseProxyConfig(overrides ...func(*ReverseProxyConfig)) *ReversePr return sample } +// sampleHTTPOriginConfig initializes a new HTTPOriginConfig literal, +// applies any number of overrides to it, and returns it. func sampleHTTPOriginConfig(overrides ...func(*HTTPOriginConfig)) *HTTPOriginConfig { sample := &HTTPOriginConfig{ - URLString: "https.example.com", + URLString: "https://example.com", TCPKeepAlive: 7 * time.Second, DialDualStack: true, TLSHandshakeTimeout: 11 * time.Second, @@ -297,28 +322,14 @@ func sampleHTTPOriginConfig(overrides ...func(*HTTPOriginConfig)) *HTTPOriginCon return sample } -func sampleHTTPOriginUnixPathConfig(overrides ...func(*HTTPOriginConfig)) *HTTPOriginConfig { - sample := &HTTPOriginConfig{ - URLString: "unix:/var/lib/file.sock", - TCPKeepAlive: 7 * time.Second, - DialDualStack: true, - TLSHandshakeTimeout: 11 * time.Second, - TLSVerify: true, - OriginCAPool: "/etc/cert.pem", - OriginServerName: "secure.example.com", - MaxIdleConnections: 19, - IdleConnectionTimeout: 17 * time.Second, - ProxyConnectionTimeout: 15 * time.Second, - ExpectContinueTimeout: 21 * time.Second, - ChunkedEncoding: true, - } - sample.ensureNoZeroFields() - for _, f := range overrides { - f(sample) - } - return sample +// unixPathOverride sets the URLString of the given HTTPOriginConfig to be a +// Unix socket (i.e. `unix:` scheme plus a file path) +func unixPathOverride(sample *HTTPOriginConfig) { + sample.URLString = "unix:/var/lib/file.sock" } +// sampleWebSocketOriginConfig initializes a new WebSocketOriginConfig +// struct, applies any number of overrides to it, and returns it. func sampleWebSocketOriginConfig(overrides ...func(*WebSocketOriginConfig)) *WebSocketOriginConfig { sample := &WebSocketOriginConfig{ URLString: "ssh://example.com", @@ -366,7 +377,6 @@ func (c *WebSocketOriginConfig) ensureNoZeroFields() { // include a field in the sample value, it won't be covered under tests. // This check reduces that risk by requiring fields to be either initialized // or explicitly uninitialized. -// https://bitbucket.cfdata.org/projects/TUN/repos/cloudflared/pull-requests/151/overview?commentId=348012 func ensureNoZeroFieldsInSample(ptrToSampleValue reflect.Value, allowedZeroFieldNames []string) { sampleValue := ptrToSampleValue.Elem() structType := ptrToSampleValue.Type().Elem() diff --git a/tunnelrpc/pogs/tunnelrpc.go b/tunnelrpc/pogs/tunnelrpc.go index 5339d113..3fac43fa 100644 --- a/tunnelrpc/pogs/tunnelrpc.go +++ b/tunnelrpc/pogs/tunnelrpc.go @@ -2,6 +2,7 @@ package pogs import ( "context" + "fmt" "time" "github.com/cloudflare/cloudflared/tunnelrpc" @@ -127,52 +128,169 @@ func UnmarshalServerInfo(s tunnelrpc.ServerInfo) (*ServerInfo, error) { return p, err } +//go-sumtype:decl Scope +type Scope interface { + Value() string + isScope() +} + +type SystemName struct { + systemName string +} + +func NewSystemName(systemName string) *SystemName { + return &SystemName{systemName: systemName} +} + +func (s *SystemName) Value() string { return s.systemName } + +func (_ *SystemName) isScope() {} + +type Group struct { + group string +} + +func NewGroup(group string) *Group { + return &Group{group: group} +} + +func (g *Group) Value() string { return g.group } + +func (_ *Group) isScope() {} + +func MarshalScope(s tunnelrpc.Scope, p Scope) error { + ss := s.Value() + switch scope := p.(type) { + case *SystemName: + ss.SetSystemName(scope.systemName) + case *Group: + ss.SetGroup(scope.group) + default: + return fmt.Errorf("unexpected Scope value: %v", p) + } + return nil +} + +func UnmarshalScope(s tunnelrpc.Scope) (Scope, error) { + ss := s.Value() + switch ss.Which() { + case tunnelrpc.Scope_value_Which_systemName: + systemName, err := ss.SystemName() + if err != nil { + return nil, err + } + return NewSystemName(systemName), nil + case tunnelrpc.Scope_value_Which_group: + group, err := ss.Group() + if err != nil { + return nil, err + } + return NewGroup(group), nil + default: + return nil, fmt.Errorf("unexpected Scope tag: %v", ss.Which()) + } +} + type ConnectParameters struct { OriginCert []byte CloudflaredID uuid.UUID NumPreviousAttempts uint8 Tags []Tag CloudflaredVersion string -} - -// CapnpConnectParameters is ConnectParameters represented in Cap'n Proto build-in types -type CapnpConnectParameters struct { - OriginCert []byte - CloudflaredID []byte - NumPreviousAttempts uint8 - Tags []Tag - CloudflaredVersion string + Scope Scope } func MarshalConnectParameters(s tunnelrpc.CapnpConnectParameters, p *ConnectParameters) error { + if err := s.SetOriginCert(p.OriginCert); err != nil { + return err + } cloudflaredIDBytes, err := p.CloudflaredID.MarshalBinary() if err != nil { return err } - capnpConnectParameters := &CapnpConnectParameters{ - OriginCert: p.OriginCert, - CloudflaredID: cloudflaredIDBytes, - NumPreviousAttempts: p.NumPreviousAttempts, - CloudflaredVersion: p.CloudflaredVersion, + if err := s.SetCloudflaredID(cloudflaredIDBytes); err != nil { + return err } - return pogs.Insert(tunnelrpc.CapnpConnectParameters_TypeID, s.Struct, capnpConnectParameters) + s.SetNumPreviousAttempts(p.NumPreviousAttempts) + if len(p.Tags) > 0 { + tagsCapnpList, err := s.NewTags(int32(len(p.Tags))) + if err != nil { + return err + } + for i, tag := range p.Tags { + tagCapnp := tagsCapnpList.At(i) + if err := tagCapnp.SetName(tag.Name); err != nil { + return err + } + if err := tagCapnp.SetValue(tag.Value); err != nil { + return err + } + } + } + if err := s.SetCloudflaredVersion(p.CloudflaredVersion); err != nil { + return err + } + scope, err := s.NewScope() + if err != nil { + return err + } + return MarshalScope(scope, p.Scope) } func UnmarshalConnectParameters(s tunnelrpc.CapnpConnectParameters) (*ConnectParameters, error) { - p := new(CapnpConnectParameters) - err := pogs.Extract(p, tunnelrpc.CapnpConnectParameters_TypeID, s.Struct) + originCert, err := s.OriginCert() if err != nil { return nil, err } - cloudflaredID, err := uuid.FromBytes(p.CloudflaredID) + + cloudflaredIDBytes, err := s.CloudflaredID() if err != nil { return nil, err } + cloudflaredID, err := uuid.FromBytes(cloudflaredIDBytes) + if err != nil { + return nil, err + } + + tagsCapnpList, err := s.Tags() + if err != nil { + return nil, err + } + var tags []Tag + for i := 0; i < tagsCapnpList.Len(); i++ { + tagCapnp := tagsCapnpList.At(i) + name, err := tagCapnp.Name() + if err != nil { + return nil, err + } + value, err := tagCapnp.Value() + if err != nil { + return nil, err + } + tags = append(tags, Tag{Name: name, Value: value}) + } + + cloudflaredVersion, err := s.CloudflaredVersion() + if err != nil { + return nil, err + } + + scopeCapnp, err := s.Scope() + if err != nil { + return nil, err + } + scope, err := UnmarshalScope(scopeCapnp) + if err != nil { + return nil, err + } + return &ConnectParameters{ - OriginCert: p.OriginCert, + OriginCert: originCert, CloudflaredID: cloudflaredID, - NumPreviousAttempts: p.NumPreviousAttempts, - CloudflaredVersion: p.CloudflaredVersion, + NumPreviousAttempts: s.NumPreviousAttempts(), + Tags: tags, + CloudflaredVersion: cloudflaredVersion, + Scope: scope, }, nil } diff --git a/tunnelrpc/pogs/tunnelrpc_test.go b/tunnelrpc/pogs/tunnelrpc_test.go new file mode 100644 index 00000000..cad0b0dc --- /dev/null +++ b/tunnelrpc/pogs/tunnelrpc_test.go @@ -0,0 +1,97 @@ +package pogs + +import ( + "reflect" + "testing" + + "github.com/cloudflare/cloudflared/tunnelrpc" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + capnp "zombiezen.com/go/capnproto2" +) + +// Assert *SystemName implements Scope +var _ Scope = (*SystemName)(nil) + +// Assert *Group implements Scope +var _ Scope = (*Group)(nil) + +func TestScope(t *testing.T) { + testCases := []Scope{ + &SystemName{systemName: "my_system"}, + &Group{group: "my_group"}, + } + for i, testCase := range testCases { + _, seg, err := capnp.NewMessage(capnp.SingleSegment(nil)) + capnpEntity, err := tunnelrpc.NewScope(seg) + if !assert.NoError(t, err) { + t.Fatal("Couldn't initialize a new message") + } + err = MarshalScope(capnpEntity, testCase) + if !assert.NoError(t, err, "testCase index %v failed to marshal", i) { + continue + } + result, err := UnmarshalScope(capnpEntity) + if !assert.NoError(t, err, "testCase index %v failed to unmarshal", i) { + continue + } + assert.Equal(t, testCase, result, "testCase index %v didn't preserve struct through marshalling and unmarshalling", i) + } +} + +func TestConnectParameters(t *testing.T) { + testCases := []*ConnectParameters{ + sampleConnectParameters(), + sampleConnectParameters(func(c *ConnectParameters) { + c.Scope = &SystemName{systemName: "my_system"} + }), + sampleConnectParameters(func(c *ConnectParameters) { + c.Tags = nil + }), + } + for i, testCase := range testCases { + _, seg, err := capnp.NewMessage(capnp.SingleSegment(nil)) + capnpEntity, err := tunnelrpc.NewCapnpConnectParameters(seg) + if !assert.NoError(t, err) { + t.Fatal("Couldn't initialize a new message") + } + err = MarshalConnectParameters(capnpEntity, testCase) + if !assert.NoError(t, err, "testCase index %v failed to marshal", i) { + continue + } + result, err := UnmarshalConnectParameters(capnpEntity) + if !assert.NoError(t, err, "testCase index %v failed to unmarshal", i) { + continue + } + assert.Equal(t, testCase, result, "testCase index %v didn't preserve struct through marshalling and unmarshalling", i) + } +} + +func sampleConnectParameters(overrides ...func(*ConnectParameters)) *ConnectParameters { + cloudflaredID, err := uuid.Parse("ED7BA470-8E54-465E-825C-99712043E01C") + if err != nil { + panic(err) + } + sample := &ConnectParameters{ + OriginCert: []byte("my-origin-cert"), + CloudflaredID: cloudflaredID, + NumPreviousAttempts: 19, + Tags: []Tag{ + Tag{ + Name: "provision-method", + Value: "new", + }, + }, + CloudflaredVersion: "7.0", + Scope: &Group{group: "my_group"}, + } + sample.ensureNoZeroFields() + for _, f := range overrides { + f(sample) + } + return sample +} + +func (c *ConnectParameters) ensureNoZeroFields() { + ensureNoZeroFieldsInSample(reflect.ValueOf(c), []string{}) +} diff --git a/tunnelrpc/tunnelrpc.capnp b/tunnelrpc/tunnelrpc.capnp index 5d178278..1f3b20ee 100644 --- a/tunnelrpc/tunnelrpc.capnp +++ b/tunnelrpc/tunnelrpc.capnp @@ -57,6 +57,17 @@ struct CapnpConnectParameters { tags @3 :List(Tag); # release version of cloudflared cloudflaredVersion @4 :Text; + # identifier for this cloudflared instance + scope @5 :Scope; +} + +struct Scope { + value :union { + # Standalone instance + systemName @0 :Text; + # Associated with a group of identical cloudflared instances + group @1 :Text; + } } struct ConnectResult { diff --git a/tunnelrpc/tunnelrpc.capnp.go b/tunnelrpc/tunnelrpc.capnp.go index 14b38c8b..f1f01575 100644 --- a/tunnelrpc/tunnelrpc.capnp.go +++ b/tunnelrpc/tunnelrpc.capnp.go @@ -504,12 +504,12 @@ type CapnpConnectParameters struct{ capnp.Struct } const CapnpConnectParameters_TypeID = 0xa78f37418c1077c8 func NewCapnpConnectParameters(s *capnp.Segment) (CapnpConnectParameters, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 4}) + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 5}) return CapnpConnectParameters{st}, err } func NewRootCapnpConnectParameters(s *capnp.Segment) (CapnpConnectParameters, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 4}) + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 5}) return CapnpConnectParameters{st}, err } @@ -603,12 +603,37 @@ func (s CapnpConnectParameters) SetCloudflaredVersion(v string) error { return s.Struct.SetText(3, v) } +func (s CapnpConnectParameters) Scope() (Scope, error) { + p, err := s.Struct.Ptr(4) + return Scope{Struct: p.Struct()}, err +} + +func (s CapnpConnectParameters) HasScope() bool { + p, err := s.Struct.Ptr(4) + return p.IsValid() || err != nil +} + +func (s CapnpConnectParameters) SetScope(v Scope) error { + return s.Struct.SetPtr(4, v.Struct.ToPtr()) +} + +// NewScope sets the scope field to a newly +// allocated Scope struct, preferring placement in s's segment. +func (s CapnpConnectParameters) NewScope() (Scope, error) { + ss, err := NewScope(s.Struct.Segment()) + if err != nil { + return Scope{}, err + } + err = s.Struct.SetPtr(4, ss.Struct.ToPtr()) + return ss, err +} + // CapnpConnectParameters_List is a list of CapnpConnectParameters. type CapnpConnectParameters_List struct{ capnp.List } // NewCapnpConnectParameters creates a new list of CapnpConnectParameters. func NewCapnpConnectParameters_List(s *capnp.Segment, sz int32) (CapnpConnectParameters_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 4}, sz) + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 5}, sz) return CapnpConnectParameters_List{l}, err } @@ -633,6 +658,147 @@ func (p CapnpConnectParameters_Promise) Struct() (CapnpConnectParameters, error) return CapnpConnectParameters{s}, err } +func (p CapnpConnectParameters_Promise) Scope() Scope_Promise { + return Scope_Promise{Pipeline: p.Pipeline.GetPipeline(4)} +} + +type Scope struct{ capnp.Struct } +type Scope_value Scope +type Scope_value_Which uint16 + +const ( + Scope_value_Which_systemName Scope_value_Which = 0 + Scope_value_Which_group Scope_value_Which = 1 +) + +func (w Scope_value_Which) String() string { + const s = "systemNamegroup" + switch w { + case Scope_value_Which_systemName: + return s[0:10] + case Scope_value_Which_group: + return s[10:15] + + } + return "Scope_value_Which(" + strconv.FormatUint(uint64(w), 10) + ")" +} + +// Scope_TypeID is the unique identifier for the type Scope. +const Scope_TypeID = 0xc54a4a6fd4d87596 + +func NewScope(s *capnp.Segment) (Scope, error) { + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Scope{st}, err +} + +func NewRootScope(s *capnp.Segment) (Scope, error) { + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}) + return Scope{st}, err +} + +func ReadRootScope(msg *capnp.Message) (Scope, error) { + root, err := msg.RootPtr() + return Scope{root.Struct()}, err +} + +func (s Scope) String() string { + str, _ := text.Marshal(0xc54a4a6fd4d87596, s.Struct) + return str +} + +func (s Scope) Value() Scope_value { return Scope_value(s) } + +func (s Scope_value) Which() Scope_value_Which { + return Scope_value_Which(s.Struct.Uint16(0)) +} +func (s Scope_value) SystemName() (string, error) { + if s.Struct.Uint16(0) != 0 { + panic("Which() != systemName") + } + p, err := s.Struct.Ptr(0) + return p.Text(), err +} + +func (s Scope_value) HasSystemName() bool { + if s.Struct.Uint16(0) != 0 { + return false + } + p, err := s.Struct.Ptr(0) + return p.IsValid() || err != nil +} + +func (s Scope_value) SystemNameBytes() ([]byte, error) { + p, err := s.Struct.Ptr(0) + return p.TextBytes(), err +} + +func (s Scope_value) SetSystemName(v string) error { + s.Struct.SetUint16(0, 0) + return s.Struct.SetText(0, v) +} + +func (s Scope_value) Group() (string, error) { + if s.Struct.Uint16(0) != 1 { + panic("Which() != group") + } + p, err := s.Struct.Ptr(0) + return p.Text(), err +} + +func (s Scope_value) HasGroup() bool { + if s.Struct.Uint16(0) != 1 { + return false + } + p, err := s.Struct.Ptr(0) + return p.IsValid() || err != nil +} + +func (s Scope_value) GroupBytes() ([]byte, error) { + p, err := s.Struct.Ptr(0) + return p.TextBytes(), err +} + +func (s Scope_value) SetGroup(v string) error { + s.Struct.SetUint16(0, 1) + return s.Struct.SetText(0, v) +} + +// Scope_List is a list of Scope. +type Scope_List struct{ capnp.List } + +// NewScope creates a new list of Scope. +func NewScope_List(s *capnp.Segment, sz int32) (Scope_List, error) { + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz) + return Scope_List{l}, err +} + +func (s Scope_List) At(i int) Scope { return Scope{s.List.Struct(i)} } + +func (s Scope_List) Set(i int, v Scope) error { return s.List.SetStruct(i, v.Struct) } + +func (s Scope_List) String() string { + str, _ := text.MarshalList(0xc54a4a6fd4d87596, s.List) + return str +} + +// Scope_Promise is a wrapper for a Scope promised by a client call. +type Scope_Promise struct{ *capnp.Pipeline } + +func (p Scope_Promise) Struct() (Scope, error) { + s, err := p.Pipeline.Struct() + return Scope{s}, err +} + +func (p Scope_Promise) Value() Scope_value_Promise { return Scope_value_Promise{p.Pipeline} } + +// Scope_value_Promise is a wrapper for a Scope_value promised by a client call. +type Scope_value_Promise struct{ *capnp.Pipeline } + +func (p Scope_value_Promise) Struct() (Scope_value, error) { + s, err := p.Pipeline.Struct() + return Scope_value{s}, err +} + type ConnectResult struct{ capnp.Struct } // ConnectResult_TypeID is the unique identifier for the type ConnectResult. @@ -3509,218 +3675,228 @@ func (p ClientService_useConfiguration_Results_Promise) Result() UseConfiguratio return UseConfigurationResult_Promise{Pipeline: p.Pipeline.GetPipeline(0)} } -const schema_db8274f9144abc7e = "x\xda\xacY}\x8c\x1c\xe5y\x7f\x9ey\xf7v|\xe6" + - "\xce{\xe3\xb9\x80}\xd8\xba\xd6\x02%\x10Lq\\Z" + - "\xb8\xb6Y\xdf\x9d\xcf\xb9\xbd\xf8c\xe7\xf6\xce\x80\xb1%" + - "\x8fw\xdf\xdb\x1b{vf=\x1f\xf6\x9d\xe5\xc4`\xd9" + - "\x05\xae\x10l\x82%\xec\x90\x08\xdc\xba|\x08\x1aC@" + - "\x15\xd4\xa4\xa1jK\xda\xa8\"U\x93\xaai\xf3O\x03" + - "VU\xd4\x88\x9a\xa4B\xa9\x80\xa9\x9ew>oo9" + - "\xdbU\xf8\x03\x8f\x9e}\xde\xf7}>\x7f\xcf\xc7\xddv" + - "n\xc9\x06i]\xc7_v\x01h\x8fw\xe4\x83\xdfo" + - "\xbc}\xf6wN\xfd\xe0\x18(}R\xf0\xd5\x0bc\xbd" + - "\xbf\xf2\x8e\xfe\x1b\x00\xae\x1f\xc9\x1fB\xf5\x9e\xbc\x0c\xa0" + - "N\xe6\xb7\x01\x06\xfft\xdb\xe1ww\xff\xe2\xe4\x83\xa0" + - "\xf4a\xca\x99\x93\x01\xd67\xf2s\xa8\x1e\xcf\xcb\xc0\x82" + - "o\xde\xdb\xfb\xf7\xf8\xd4\x87'A\xf9\x1c\x02t \xfd" + - "\xac\xe7\x97J\x80\xeal\xbe\x08\x18\xbc}\xcb\x85\xd7O" + - "|\xe7\x81o\x80\xf6YD\x08\xcf\x9f\xce\xff/\x02\xaa" + - "/\x0a\x86K\x7f\xf2\xf9\xdc\x8bo/\xff\x96`\x08\xce" + - "\xfd\xe3]/\x9f\xf8\xceo\xbc\x07\x93\x92\x8c9\x80\xf5" + - "?\xce;\xc4\xfb\xef\xf9\xff\x00\x0c\x1e\xff\x977\xb66" + - "N\x9e9\x0b\xcag\xe3\xbb\xde\x94%\x09r\xc1\xed\xff" + - "zq\xdb\x96\x97\xa7\x9e\x09\x7f\x09\xe5xU~\x99\x8e" + - "\xfe\x8dL\xcf|\xff`\xcf\xc3\x83\xbf\xfb\xe83\xa0\xf5" + - "aF\x9f\x0eq\xc9\x7f\xcas\xa8\xe2\x12\xfa\xfcX\xee" + - "G\xc0`\xee\xce7\xb6\xff\xe2\x0f\xdd\xe7A[\x8b\xb9" + - "\xe0\xaf\x1fz\xe7\xc0M\xcfM\xbd%\xa4b\x00\xebo" + - "\xef\xfa" + - "\xee\xe6\x97\xe8\xea\x8cQC!.v\x0e\xa0\xfa?\x9d" + - "d\xd7K\x82\xfb\x87\xb7l\xff\xeew\xcf\xd7_j\x15" + - "D\"\xee\x93K\xc7P=\xb7\x94\xb8\x9f^J\xdc\x9f" + - ")\xe1O\xbf\xb7.\xf7\xe7\x91^\x8c\x98&\xafy\x8f" + - "\x1e7\xae!\x86{?z\xf5\xafF\xde\xff\xd1kY" + - "\x07tvI\xe4\x80\xd5]\xa4\xf8\xea\x9f\x0fu[\xef" + - "\x1f\xfd\xde|?\x867\x8dt\x8d\xa1zO\x97pz" + - "\xd7\xb7\x01?|\xfe\x81\x13\xa5w6\xbe\xa5\xf5a\xae" + - "U\x91K]\x87P\xed\xe8\xa6O\xec\x166J\xac\xd2" + - "\xc2.4Y\xb7l/\xaa#\xcb\xe8sp\x99`\x1f" + - "\xbb\xf7\xeb\x8fu\\\xfc\xfa[\xadf\x92\x89\xa7Tp" + - "P\xddU\xa0\xcf{\x0a\xcfH\x80A\xdf\xf9\xdf\xfb\xb3" + - "\xa1\xdaO~\xd0\"7]\xae\x8e,\xff@\xd5\x96\xd3" + - "\xd7\x96\xe5\x07\x01\x83\x07>?{h\xeb\x8ds?n" + - "\xb5\xa9\x10\xfc\xb9\xe5s\xa8\xbe)\xb8\xdf\x10\xdc\xd2E" + - "}\xe5}\xff\xfc\xc5\x9ff\xa2h\xad\xfa3\x84\\\xb0" + - "u\xfb\xbd{;\xbf\xf2\xce;\xd9(\xfaMUX\xfb" + - "v\x95\x8c\xf9\x8a\xf2\x98z\xe1\xe9?}\x97\x1e\x92[" + - "\xad9\xa9\xee@\xd5P\xe9\x93\xabB\x87$\x9a\xdb\xf9" + - "Z\xbfv\x00\xd5\xfd\xd7\x92\\\x8dkI\xae\xdbw\x0f" + - "\xf2\x9dw\xdc\xfd\x1e(}l^n\xbeH\x9co\x10" + - "\xe7\xfa\xd7\xae\x95Q5\xae\x93\x01\x82\xaf\xd5w\xfc\xdd" + - "\xa5\xe1\xa7\xff\xbbmDk\xd7\x0d\xa0\xaa\x13\xdf\xfa]" + - "\xd7\x09\xf3\xaf_\xf7G??\xf5\xc7\xc3\x97\x16\xdc\xfe" + - "\xdc\x8a!T_[Ar\xbc\xba\xe2K\xea\xc5\x15\xe2" + - "\xf2\xafn\xdcv\xe7\x9a7?\xc8Z\xe2\x1fV| " + - "Rq\x05Yb\xea\x8e\xff\xfa\xd2\x8d_\xfb\xdb\x0fZ" + - "\xdc#\x18q\xe5\xcd\xa8*+\xe9\xc6\xee\x95E\xc0\xf7" + - "7}\xebG}\x85\xbe_\xb6\x13t\xddJ\x8a\x93\x95" + - "\"NV\x0aA\xef\xfe\xd9\x99\x83\xc5o\xfc\xf2C\xd2" + - "\x8b\xb5 \xcf\xfe\xbe\x1d\xa8\x1e\xef\xa3\x9b\xef\xef\xa3\xf0" + - "\xdf\xfc\xc2O\xbe8}\xea\xfb\xbfj5\x82p\xc8\xda" + - "\xeb\x8f\xa2:x=q\xff\xc1\xf5\x84\x1f\x87\xdf?=" + - "\xfa\xe8\xce\x17>\xc9ju\xe3\xaa\xd7\x85\x7fW\x91V" + - "{O\x1d\xf6F\x9fx$h\x13t\xeb'W\x0d\xa1" + - "\xcaW\xd1m\xfa\xaa\x83\xb06\xf0|\xcb\xe2\xa6\xd3\xcc" + - "U\x7f+\xfe\xac\xdeZ\xd5\x9bVs`d\xc6p=" + - "\xc3\xaaO\x08z\xb1l\x9bFu\xb6\x8c\xa8u\xa1\x04" + - "\xa0\xac\x1e\x00@T>\xb3\x03\x00%E\x19\x02(\x1a" + - "u\xcbvxP3\xdc\xaamY\x1cX\xd5;\xb2G" + - "7u\xab\xca\x93\x87:\x16>4\xcaM\xd3\xbe\xcbv" + - "\xcc\xda6\xc7\xa8\x1b\xd6\xb0mM\x19u\x802br" + - "L^xl\xd84\xb8\xe5U\xb8s\xc0\xa8\xf2[}" + - "\x97\x87\xe7|G\xf7\x0c\xdb\xbaa\x9c\xbb\xbe\xe9\xb9\x00" + - "Z\x8e\xe5\x00r\x08\xa0t\x0f\x00hK\x18j\xbd\x12" + - "\x16\x1d\xc1\x80=i\xe6\x01b\x0f\xa4o\xe6\x17\xbe\x19" + - "\xda\x82\xde\xe4\xce\xad\xbe\xe5\xf0\xba\xe1z\xdc\x09\xc97" + - "\x14\xcb\xba\xa37\xdc\xec\x83g\x00\xb4\x1e\x86\xda*\x09" + - "\x83\xba\xa3Wy\x99;h\xd8\xb5\xad\xbaeW\x18\xaf" + - "b\x07H\xd8\x91y\xb4\x8d#6\xe9\x86\xc9k\xa1v" + - "\xb7V\xfb\xc5\xbfZ\x0f\xcbu\x05\x81xD\xdf\x01\xa0" + - "\xedf\xa8\x99\x12v\xe3'A/\x15)\xc58\x04\xa0" + - "M3\xd4<\x09\xbb\xa5\x8f\x83^\xe1\xb5\xfdk\x004" + - "\x93\xa16#a7\xfb(\xe8\xa5R\xa0\xf8{\x014" + - "\x8f\xa1v\x9f\x84\x81\xeb7\xc9\xa6.0\xdb\xc1\x9e4" + - "\x94#\xeb\xf0Z\x9d,mA\x91W\xc9\xd0\xd8\x13#" + - "n\xc8 \xd7\xeci\xecIKDt\xcc\xe1\x07\xb8\xe3" + - "\xf22\x14\x1c{f\x16{R\xe4m\xb1z\xf7\xd5Z" + - "=vtrj\xf1\xf3\"4\xab\xde\x0d\xe5\xfe\x05\xce" + - "\";v1\xd4VH\x184\xe9W\xeeq`\x8e\x8b" + - "=i\xe9m\x91\xb6M8\x0f\xd3\xff\x87\xc3W\xca\xd1" + - "-\x8e+\xc2Y\xebM\x1e\xfb\x0a=v\x98\xa1\xf6\xa0" + - "\x84\x0ab\xe8\xb3\xe3\x0e\x80v\x8c\xa1vBB\x94B" + - "\x8f=r\x16@;\xc1P{RB\x85I\xa1\xc3N" + - "\xdfL\xbd\x10C\xed\xbc\x84J\x8e\xf5R\x9b\xa1\xbcH" + - "\xc1v\x9e\xa1vA\xc2\xc0\x0eS\x89\xe4\xf7\xb0\x1b$" + - "\xec\x06\x0c\xaa\xa6\xed\xd7\xa6L\x1d\xfa\x1d^+mL" + - "\xe8\x96\xdf(;\xfc\x80\x81\xb6\xef\x0ez\x1eo\xc8M" + - "\xcf\xc5\xb5\x08\xd0\xc6\xef" + - "\x83\xbe7\xcd-\xcf\xa8\x8a\x07\x17\xf8}M\x1a\x9f\x89" + - "\xcdJ_\xc8\x182\xb6\xd9\x96=\xa9!\xe5}|6" + - "6K?o\xe8\x86\x99x?\xb2\xe6 \xc8_Ny" + - "\x16\xed6\xa2\xb2\x12\x16\x95bh\x9e\x16\xc8\x9c\x03\xd0" + - "\xeec\xa8=\x9c\x11\xf2\xa1\xc7\x00\xb4\x87\x19jOd" + - "\x84<5\x94\xc5L\x16a&Y\xf4I\x86\xda\xb3\x12" + - "b.\x84\xccs\x04\x99\xcf2\xd4^\x91\x04\x0a\x8e\x0e" + - "\x0e\xdb\x16FB\xb8\x001\x06\x06\xd3\\w\xbc=\\" + - "G\xafdy\xdc9\xa0\xa3\x19\xe7\xe0\x11\xcfhp\xdb" + - "\xf7\x92\x9cl\xe83\xa2dcm4<%\xeb\x9e\x8b" + - "\x9d a'\xa5\x80\xcb\x9da\x87\xd7\x90\xbc\xa1\x9be" + - "\x9dy\xd3Wb\xa0\xf9xYhc\x9eCiE\xa1" + - "\xff\xd2\xf9O9>\x00\x92H]\xd2\xb91\x946\x06" + - "\xa2\xa0tP_\xf0X\xda\x01\x88\x82\x92\xa7\x1b\xcf\xa4" + - "\x06\x8fD\x1b\xb5\xa1\x18\xa6D,s1t\xf5\x11\x82" + - "'\x83\xa7zFu\xd6@\xdb\x9a\x10\x06\xc2\xd4BU" + - "\xbb\xd1t\xb8\xeb\xa2a[\x9a\xaf\x9b\x06\xf3f\x93\x83" + - "\x8b\xda\x80r?\xcc\x99m\xcd~\xe1$2\xc2m\xb1" + - "\x11\xd4A\x1c\x03\xa8l@\x86\x95\xcd\x98\x86\x89Z\xc2" + - "!\x80\xcaF\xa2\x971\x8d\x14u\x0b\xf6\x01TF\x89" + - ">\x81\x12b\x18+\xaa\x86\xcf\x03T&\x88\xbc\x1b\xd3" + - "\x12\xab\xee\x12\xd7\xef$\xfa4\xd1;r\xc2|*\xc7" + - "\x9b\x01*\xbb\x89~\x98\xe8yIXP\x9d\xc5\xbd\x00" + - "\x95\x19\xa2\x1f#\xba\xdc\xd1\x8b\xa2\xf1G\x07\xa0r\x1f" + - "\xd1\x1f&\xfa\x92\x15\xbd\xb8\x04@}H\xd0\x1f$\xfa" + - "\xe3D\xef\\\xd9\x8b\x9d\x00\xeaI<\x0aP9A\xf4" + - "'\x89\xbe\x14{q)\x80z\x1a\xcf\x00T\x9e$\xfa" + - "\xb3D\xbf&\xdf\x8b\xd7\x00\xa8\xe7\x84" + - "k\x09!?\xc7P\xfbm\x09\x0b\xd9\xa4\xe8?\xa0\x9b" + - ">\xbf\x926h\xb2\xa5\x14\x84\xddl\x88\xcf\x99\xd7\x87" + - "\xd2\xd7\x93\xc7\xa9Y\xbc\x85\xa16*\xe1\x11\xd7\xafV" + - "I\xe9\xd8\x0aS\xd1\xcc\x00\xfdtw\xc6\x1f\xc98\x1f" + - "\xf9\xe3J\xcbn\x9d{\xe1W\xc9\x9a\xb2\xa9^\xc9z" + - "\xc3\xfd\x7f\x9e\x1e\xe7n\x81Z\xf6\xcbNf\xc9\x80~" + - "\xf9\xfa6:1QN\xc7G\x16\x82c\x16\x17\xc6\xb3" + - "\xb8\x90\xc2\xc2\xdel\xfa\xc7m\x98\xaa\x89<,\x13}" + - "'\xa6}\xb7z\x0f\x9e\x9d\x97\xff\xb9\xc1\x10\x17\xb8\xb8" + - "\xbeF\xf4\xa6\xc0\x05\x0cq\xa1!\xee7\x89>\x93\xc5" + - "\x05\x1f\xe7\xe6\xe3\x02\x8bq\x81\xf2\xf9\x18\xd1O\x08\\" + - "\xc8\x85\xb8\xf0\x08\xbe\x8cq\x87\xc0\xac\xb4\xd2\x18\xf4\x8bmY\x18\x96" + - "\xed\x09\xa3\x7f~=nF\xfdn\\\xd7'\x8a-\x05" + - "\x9b\xcf4y\xd5\x1b\xb6\xd1\xf2\x0c\xcb\xe7\x0b.\xa8N" + - "\xfb\xd6>^\x1bA\xabj\xd7\x0c\xab\x0e\x0b\x1am\xf6" + - "iS{\xa6\x91\x11\xd9\x8c\x99e\xb1r\x13\x95e\x8c" + - "\xca\xb22\x90N\x9f\xc5\xaa8Ut\xb8\xee\xb6\x99\xa6" + - "\xd8\xa7e[1L2z\xad\x87u\x00$\xabW\x8c" + - "wa\xca\xfeC )\x86\x8c\xe9\x0a\x11\xe3\x8d\xa1\xb2" + - "\xcb\x01I\x99\x94QJ6\xde\x18o\xab\x95\xd2\x1cH" + - "\xca\x88\x8c,YSc\xbc\x89R\xee\x1c\x02IY+" + - "\x07qk\x0e\xc5P\x9c\x0d\x18\xc4\x89\x0f\xfd\"\xf57" + - "`\x10\xcf\xef\x18\xb7\xf0\x00\x1b\xf0HT\x166`v" + - "\xe9\xc3>\xad\x8fn\xdf\x1e\x12F\xce0\xd4\x8e\xa5\x18" + - "y\xff\\:P'\xb3\xcb#\xcf\xb7\x9b\xa8\x8f\x02h" + - "O\x84\x9d`2Q\xbfD-\xe3+\x0c\xb5\x1fJi" + - "\xbd\x8c\xc3.\xde\x93\xa0\xed\xc4\xc3\xd4\"\xeb\x92(8" + - "\xa3\xce\xadui\x12\xd4\xeci\xd1\xd9ax\x95\x0b)" + - "bg7)\xcb2\x9b\x14\x8c\xc78y\x1e\xc0g\xf7" + - "*\xcb\x16\xc7\xccyC\x89\xa889\x115\xf1>\x1e" + - "\xe3\xbf\x8c(\x0ay\xbf[\x0e\xe2\xc1\x05\xe3rE\xce" + - "\xcb\xba\xec*\xa7\xb7q\xde\xef^I%\x88\xb7\xaf\x97" + - "\x1f\xc2\xc3w\x0a\x14l\xa1B\xc9\xbd{3\xdb\x1d\xd3" + - "\x8e\xe6\xa0\xc2\xd6L\xd5^\xccV\xa1\xc0q\x03Z\xa0" + - "\xc3-\xe1\xb7&\x0d\xbf\xa4A\xb8\x7fMf\xcb\x13O" + - "'\xc7\xc7\xa2\xa0|*i8\x95oR\xa0>\xc5P" + - "{!\x13~\xcf\x8d\xa5\xd3\x89\xcc\x1d'\x96S\xf6\x9d" + - "\x146M\xbb\xbe\xd9\xb0\xb8K-X\xcbH\xdd\xe4N" + - "C\xb7\xb8\x85\x1e\x81\x91\xef\x10\xa2\xceG\xae\xd2\xc6L" + - "\xe7\xb6\x98\xfa\x95(\xd8\xc3X\x8f\xcakf~<\x9b" + - "\xd9e\xc4\xcak\xafG;\x82\xdd\x19\xe5w\xd1\xfc\xb8" + - "\x93\xa16-a\xa0\xfb\x9e=\xd9\xac\xe9\xe8\xf1M\x0e" + - "\xdf\xefs\xd9\xaa\xce\xa6s\x14M\x14Uw\x12\x9b\xd4" + - "\xfbmrxq\xbf\xcf\xb3\x0c\xf1B\x15d\xc3\xae-" + - "\xd8\xa4\xb6i\xb6\xee\xe2{*vu\x1f\xf7\xe6-\x9a" + - "C\xb8\x8cU\xd1\xc7\xd3mj\xac\x891\x9e\x19\x99b" + - "\x18\xd9O\x01\xd5d\xa8\x1d\xce\xc0\xc8\xec\\\xea\xf0\xf6" + - "\xd5\xf5\xd7S\x10\x17Q\xb2\xed\xb6s\xbc\xc8\xaf(\xd1" + - "\xd2\xbf\x1e\\\xbe\xe5\x8a\xc6\xf5\xa8cmiX\xd7\xb4" + - "k\x97wD\x1d\xeb\x1dQ<\xf7\xa4\x7fw\x8c\x9es" + - "\xa3.\x11\xd8\x94\xbd\xb0\x01\xfc\xbf\x00\x00\x00\xff\xff\xde" + - "T\x04\xc0" +const schema_db8274f9144abc7e = "x\xda\xacY}l\x1cez\x7f\x9ey\xd7\x1e;\xf1" + + "f=\xcc\"b\x13\xcb\xa7\x08t\x17\x8e\xa4\x107-" + + "q\xdb\xdb\xd8Nr\xb6/\x1f;\xfe\x08\x10\x12)\x93" + + "\xdd\xd7\xebIfg6\xf3\x91\xd8Q\xee\x02i(\xe0" + + "\x92#\xe1.\x15\xc9\x85\x13\xa4\x97\xf2\xa1\\K\xb8\xa0" + + "\xf6(\x9c\x8e\xaa\x14\xd2;\x09P\xa1\x82\x96\xfe\xd1\x83" + + "\xa8\x025\xa2p'!N\x17\xa6z\xe6\xdb\xeb\xc5!" + + "U\xffIV\xcf<\xef\xfb>\x9f\xbf\xe7\xc3\xb7\\n" + + "Y#\xdc\xdadf\x01\x94SM\xcd\xde\x1fW_;" + + "\xfd\x07\xc7\x7fq\x18\xa4N\xc1\xfb\xce\x0b\xc3\xf9\xcf\x9c" + + "C\xff\x0e\x80=\x8f6\xefG\xf9\\\xb3\x08 \xff\xb8" + + "y3\xa0\xf7/\xb7\x1cx\x7f\xc7\xaf\x8f\xdd\x0fR'" + + "&\x9c\x19\x11\xa0\xe7\xe5\xe6\x19\x94\xff\xa3Y\x04\xe6=" + + "zW\xfe\x9f\xf1\xb1O\x8f\x81\xf45\x04hB\xfa\xfc" + + "\xd3\xe6\x05\x02\xa0\xfcFs\x01\xd0{\xed\xe6\x17\x9e?" + + "\xfa\x93\xfb~\x00\xcaW\x11!8\xffq\xf3o\x11P" + + "n\x12\x89\xe1\xe3\x1f}=\xf3\xe3\xd7\xae\xf9\xa1\xcf\xe0" + + "\x9dy\xe3\xf6g\x8f\xfe\xe4+\x1f\xc2\xb8 b\x06\xa0" + + "g\xb9h\x11\xefj\xf1\xbf\x00\xbd\xef\xbf\xfd\xe2\xa6\xea" + + "\xb1\x93\xa7A\xfajtWG\x8b @\xc6[\xf5o" + + "\x177o|v\xe2\x89\xe0K G\xb6\xe5Y:\xda" + + "\xd5B\xcf\xbc\xba\xaf\xfd\xc1\xbe?|\xe8\x09P:1" + + "\xa5OS\x13q\xf6\xb5\xcc\xa0|g\x0b\xfd\x1co\xb9" + + "\x1d\x01\xbd\x99\xd5/n\xf9\xf5\x9f\xd9O\x83\xb2\x1c3" + + "\xde?>\xf0\xde\xdeeOM\xbc\xe2K\xc5\x00z." + + "\xb4\x9e\xa6\xab\xdfi\xfd\x1b@/\xfb\xf77mz\xe8" + + "\xfd\x0d\xe7\xe8\xea\x94Q\x03!\xa6\x17\xf4\xa2\xfc\xc0\x02" + + "\xb2\xeb\xbd\x0b\x88\xfb\xf5\x9b\xb7\xfc\xecg\xcfT\xce\xd5" + + "\x0b\"\x10\xf7\x8d\x0b\x87Q^\xbd\x90\xb8W-$\xee" + + "k\x87\xf0\xdd\x9f\xdf\x9a\xf9\xdbP/FL\x1f,\xfc" + + "\x90\x1e\xbf\xec3\xdc\xf5\xbb\xe7\xfea\xddGo\xfe4" + + "\xed\x80G\xdb\x04r\xc0\xb96R\xbc\xebR\x7f\xd6\xf8" + + "\xe8\xd0\xcfg\xfb1\xb8\xe9\x9d\xb6a\x94/\xb5\xd1s" + + "\x1f\xb4\xd1m\x7f\xe1\xbe\xfd\xa69<\xfcr\xbdp\xfe" + + "\xb5\xf7f\x05\x94\x8fe\x89\xfbH\xb6\x00\xf8\xe9\xd3\xf7" + + "\x1d\x1dzo\xed+J'f\xeay\x8fe\xf7\xa3|" + + "\x86x{\x1e\xcfv\x93Ec\x1b\xd6\xb1\xfbz\xbf\xb1" + + "h\x17\xca\x17\x17\xd1\xcf\xff\\\xe4\xb3\x0f\xdf\xf5\xbd\x87" + + "\x9b.~\xef\x95z\xa3\x8a\xbe\x05r\x16\xca\x97s\xf4" + + "\xf3\xb3\xdc\x13\x02\xa0\xf7\xdb\xb3\x7f\xca/\xaex\xf5\x02" + + "(_\xc1\x94\x1a\xe3(\xa2\x00\xd0s\xf1\x9a\x95d\xb2" + + "K\xd7\xec\x03\xf4:\x9f\xf9\xa3\xbf\xee/\xbf\xf3\x8b:" + + "\x8b\x90 \xf2F\xf9\x13\xf9N\x99~\x8d\xcb\xc4{\xdf" + + "\xd7\xa7\xf7o\xbaq\xe6\xad\x86\x069'\xcf\xa0|\xc1" + + "\xe7~\xd9\xe7\x16.\xaa\x1dw\xff\xeb7\xdeM\xc5\xe7" + + "\xaa\xfc\xaf\x102\xde\xa6-w\xedj\xfd\xf6{\xef\xa5" + + "\xe3sY\xde\xf7\xe3\x9f\xe4\xc9M\xe7\xa5\x87\xe5\x17\x1e" + + "\xff\xab\xf7\xe9!\xb1\xdeO\xdb\xf3[Q\xde\x93\xa7\x9f" + + "\xd5\xbc\xafo\x9c'\x8d\xa2H\xbb\xae\x17\xe5\xe9\xebH" + + ".\xf7:\x92k\xd5\x8e>\xbe\xed\xb6;>\x04\xa9\x93" + + "\xcd\xca\xfa\xe7\x88\xf3e\xe2\xecy\xe9:\x11\xe5=\x8b" + + "E\x00\xef\xbb\x95\xad\x17>\x1ex\xfc\x7f\xea/\xf7\x15" + + "\xbasq/\xca\x1a\xf1\xf5\xf0\xc5\xbe\xabzn\xfd\xf3" + + "K\xc7\xffr\xe0\xe39\xb7\x9f\xeb\xe8G\xf9\xa5\x0e\x92" + + "\xe3\xc5\x8eo\xca\x97:\xfc\xcb\xbf\xb3v\xf3\xea\xa5/" + + "}\x92\xb6\xc4[\x1d\x9f\x90%>\xe8 KL\xdc\xf6" + + "\xdf\xdf\xbc\xf1\xbb\xff\xf4I\x9d{|\xc6\xd6\xce\x9bP" + + "\xee\xe8\xa4\x1b\xaf\xed,\x00~\xb4\xfe\x87ov\xe6:" + + "\x7f\xd3H\xd0\xd5\x9d\xbbP\xdeH\xbc=C\x9d\xbe\xa0" + + "w\xfc\xea\xe4\xbe\xc2\x0f~\xf3)\xe9\xc5\xea0m\xfa" + + "\xfa\xad(\x1f\xb9\x9en~\xe0zJ\x85\x0dg\xdf\xf9" + + "\xc6\xe4\xf1W?\xab7\x82\xef\x90UK\x0e\xa1<\xb4" + + "\x84\xb8\xd7-!d:\xf0\xd1\x89\xc1\x87\xb6\x9d\xfd<" + + "\xad\xd5\xf2\xae\xe7}\xffv\x91V\xbb\x8e\x1fp\x06\x1f" + + "9\xe25\x08\xba\x9e\xed]\xfd(W\xbb\xe86\xadk" + + "\x1f,\xf7\x1c\xd70\xb8n\xd52\xa5\xdf\x8b~\x96V" + + "\x94\xd4\x9aQ\xeb]7\xa5\xd9\x8efT\xc6|z\xa1" + + "h\xeaZi\xba\x88\xa8\xb4Q\xa0K]\xbd\x00\x88\xd2" + + "\xb5[\x01P\x90\xa4~\x80\x82V1L\x8b{e\xcd" + + ".\x99\x86\xc1\x81\x95\x9c\x83;U]5J<~\xa8" + + "i\xeeC\x83\\\xd7\xcd\xdbMK/o\xb6\xb4\x8af" + + "\x0c\x98\xc6\x84V\x01(\"\xc6\xc7\xc4\xb9\xc7\x06t\x8d" + + "\x1b\xce(\xb7\xf6j%\xbe\xc2\xb5yp\xce\xb5TG" + + "3\x8d\x1bF\xb8\xed\xea\x8e\x0d\xa0dX\x06 \x83\x00" + + "R\xb6\x17@ia\xa8\xe4\x05,X>\x03\xb6'\x99" + + "\x07\x88\xed\x90\xbc\xd9<\xf7\xcd\xc0\x16\xf4&\xb7V\xb8" + + "\x86\xc5+\x9a\xedp+ \xdfP(\xaa\x96Z\xb5\xd3" + + "\x0f\x9e\x04P\xda\x19*K\x04\xf4*\x96Z\xe2En" + + "\xa1f\x967\xa9\x869\xcax\x09\x9b@\xc0\xa6\xd4\xa3" + + "\x0d\x1c\xb1^\xd5t^\x0e\xb4[Q\xea\xf6\xffW\xda" + + "Y\xa6\xcd\xf3\xfcG\xd4\xad\x00\xca\x0e\x86\x8a.`\x16" + + "?\xf7\xf2T\xfe$m?\x802\xc9Pq\x04\xcc\x0a" + + "\x97\xbd\xbc\xef\xb5=K\x01\x14\x9d\xa12%`\x96\xfd" + + "\xce\xcbS\x91\x91\xdc]\x00\x8a\xc3P\xb9[@\xcfv" + + "kdS\x1b\x98ia{\x12\xca\xa1ux\xb9B\x96" + + "6\xa0\xc0Kdhl\x8f\xd09`\x10\xcb\xe6$\xb6" + + "'\xc5'\xfd~\xa2\x7f\x9f\xe8\xad\x1dy" + + "l\x05\x90\x8f\xe1!\x80\xd1\xa3D?E\xf4\x05\x98\xc7" + + "\x05\x00\xf2\x09<\x090z\x8a\xe8O\x12}as\x1e" + + "\x17\x02\xc8g|y\x1e#\xfaY\x8c!h\xa8\x9cF" + + "B\x0a'-\xe9\x02\x98i\xc7a\xc8\xc3I\x03\x03\x98" + + ".\x9a9\x1a50\x97\xec\x90\x001\x07\xe8\xd5LS" + + "\xdf4\x1ba\xaf\xd4\x88\x84a\x019\xd3\x18*\xc7\xf9" + + "\x15\x04\xd1\x06\x13\xbaK\xaa>T\x8b%\xd1\xec>\xd7" + + "1\xdd\x1at\x97U\x87\x97\xe3\x1ai\xb9\xc6z\xcb\xac" + + "\x8e!\xb7\xaa\x9a\xa1\xea\x10\x7f\x99/\xb6r\xae\xab\x95" + + "\xbf4\x9e\xad\x08PKiI:\xfbeT\x9d\xbe\xc6" + + "P\xf9\xfdtg\x7f+A\xed\xcd\x0c\x95\xdb\xa8[\x9f" + + "\xb6\x1d^\xdd\xa4\x02Kr\xa4\xbbb\x99nm\xce\xc3" + + "B\xfd\xc3\xdd\xb5\xde1\xd5O\xeb\x968\xad\x97Q\x07" + + "u\x03C\xe5\x96\x14\xea-_\x99\xc8\x91Kgc " + + "\xf2\x9c\x97\x1atp\xe3uU,\xe8\xda\x83\xd2\x92z" + + "\xbd?y=~\xdc\x0a\xd5\x1d\x14\xf0\xa0\xed\x96Jd" + + "\xed\xc8\xfc\x13\xe1l\x04\xddtw*\x10\xe2\xb5E\x18" + + "\x08_\xb6c\xa8p'\xf85dL\x98TjE\xb5" + + "j\xff\x1fO\x8fp;G\xa3\xc9\x15'\xd0x\x11q" + + "\xe5\xd2<86VL\xc6d\x16\xa0r\x1a\x90F\xd2" + + "\x80\x94\xe0\xd1\xae4\xeeD\x1d\xa4\xac\xf8\x00P$\xfa" + + "6L\xe6\x0b\xf9N<=\x0bx2}\x01 q\xff" + + "\xfa2\xd1k> a\x00HU\xff~\x9d\xe8Si" + + "@rqf6 \xb1\x08\x90\x08H\x0e\x13\xfd\xa8\x0f" + + "H\x99\x00\x90\x8e\xe0\xb3\xb3\x80\xa7\xb5)\x00\xa4\x13\xf8" + + "\xfc,\xe0Y\xd0\x1c\x00\xd2\x19\x9f\xffI\xa2\x9f\xf7\x01" + + "\xa9?\x00\xa4s>\x80=C\xf4\x17\x08\x90\\K\x1f" + + "u,\xcd\x00\xac$\xc1Z\xaa}\x8b\xf3Z\x1f\xe4t" + + "m/\x8f\x8bEYS\xf5\xb5\xae\xaaC\xf7\xa8\xa3\x96" + + "v'm\xb2n\x0f\xaaF\xd9\xc6Iu7\xa7\x12#" + + "\xa6\x8b\xb0\xa3\xdb[\xb8\xa5M\x00&\x8du\xdc\xd6\xe4" + + "\x8a\xa6Y\xdf\xed\xf8\xfd\x19\xb7\x024\x8b\xbfU\xd5\xa9" + + "\xa1\xb2\xce\x070jM\x98\x91\x948\x8d\xbe\x98\x86\x81" + + "A\xbf0\xa6u\xcfn\x04ja\xab\x1e5\x14c\x85" + + "\xbaN\x81O\xd5x\xc9\x190\xd1p4\xc3\xe5s." + + "(M\xba\xc6n^^\x87F\xc9,kF\x05\xe6\xcc" + + "\x08\xec\x8b\xb6\x13\xa9\x0e\xaa%l\xc9\xe2u\xbb\xb4\x8c" + + "\xfa\x01\x0c\xfb\x01\xa97\x99\xb2\x0b%\xffT\xc1\xe2\xaa" + + "\x9d\x94\x86\xf9^\x0b\x97QA\x92\xd1k\xed\xac\x09 " + + "^^c\xb4\xf3\x93\xf6\xec\x07A\xd2DLV\xa5\x18" + + "mF\xa5\xed\x16\x08\xd2\xb8\x88B\xfc7\x03\x8c\xf6\xfd" + + "\xd2\xd0\x0c\x08\xd2:\x11Y\xbc\xe8\xc7h\xe3&\xad\xee" + + "\x07AZ.z\xd1T\x01\x85@\x9c5\xe8E\x89\x0f" + + "\xdd~\xea\xafA/\xdaS`4}\x00\xac\xc1\x83a" + + "=Z\x83\xe9\xe5\x16\xfb\xa2\x11\xa0q_J\x189\xc5" + + "P9\x9c`\xe4=\xd4\xab\x1ef\xa8\x1cM\x8d]G" + + "\x9eN\xb7\xa5\xe1\xe6\xe0\xc4\xa1p\xefp>\xb598" + + "G\xbd\xeay\x86\xca\xebBR\xa8\xa3\xb0\x8b\xf6Ah" + + "Z\xd1\x1c8\xcfZ(\x0c\xce\xb0e\xac_\x0eye" + + "s\xd2o)1\xb8\xca\x86\x04\xb1\xd3\x1b\xa3E\xa9\x8d" + + "\x11F\x13\xa88\x0b\xe0\xd3\xfb\xa3E\xf3c\xe6\xacy" + + "*\x1c\x1b(j\xa2\xbfh`\xf4\xb7%I\"\xefg" + + "E/\x9a\xb90*W\xe4\xbc\xb4\xcb\xaer\xf0\x1c\xe1" + + "\xdd\xf6\x97\xa9\x04\xd1\x96\xf9\xca\xfb\x83\xe0\x9d\x1c\x05[" + + "<\x07\x05\xf7\xeeJm\xb1t3\x1c\xe1r\x9bRU" + + "{>[\x05\x02G\x9do\x8e\x0e\xd7\x85\xdf\xd2$\xfc" + + "\xe2\x06\xe1\x9e\xa5\xc90\x10\x8fE\xf7\x0e\x87A\xf9X" + + "\xdc\xe9J\x8f\xce$\x1b\xae8\xfc\x9e\x1aN\xc6\"\x91" + + "[V$\xa7\xe8Z\x09l\xeafe\x83fp\x9bz" + + "\xbf\xbam@\x8d[U\xd5\xe0\x06:\x04F\xaeE\x88" + + ":\x1b\xb9\x86\xd6\xa6Z\xc6\xf9\xd4\x1f\x0d\x83=\x88\xf5" + + "\xb0\xbc\xa6F\xdf\xd3\xa95L\xa4\xbc\xf2|\xb8\xde\xd8" + + "\x91R~;\x8d\xbe\xdb\x18*\x93\x02z\xaa\xeb\x98\xe3" + + "\xb5\xb2\x8a\x0e_o\xf1=.\x17\x8d\xd2t2\xc0\xd1" + + "(S\xb2\xc7\xb1FM\xe7z\x8b\x17\xf6\xb8<\xcd\x10" + + "-\x8eA\xd4\xcc\xf2\x9c\x8dq\x83f\xebv\xbes\xd4" + + ",\xed\xe6\xce\xac\x85z\x00\x97\x91*\xeaH\xb25\x8e" + + "4\xd1FR\xb3Z\x04#{(\xa0j\x0c\x95\x03)" + + "\x18\x99\x9eI\x1c\xde\xb8\xba\xfe\xff\x14\xc4y\x94l\xb8" + + "\xd5\x1d)\xf0/\x95h\xc9_I\xae\xdcr\x85{\x82" + + "\xb0c\xadkX\x976j\x97\xb7&\x0d\xba\x1f\xcf\xed" + + "\xc9_n\xc3\xe7\xec\xb0K\x046a\xcem\x00\xff7" + + "\x00\x00\xff\xff\xfd\xa0l\x0d" func init() { schemas.Register(schema_db8274f9144abc7e, @@ -3738,9 +3914,11 @@ func init() { 0xb70431c0dc014915, 0xb9d4ef45c2b5fc5b, 0xc082ef6e0d42ed1d, + 0xc54a4a6fd4d87596, 0xc744e349009087aa, 0xc766a92976e389c4, 0xc793e50592935b4a, + 0xc9c82ee56583acfa, 0xcbd96442ae3bb01a, 0xd58a254e7a792b87, 0xdc3ed6801961e502,