TUN-3085: Pass connection authentication information using TunnelAuth struct

This commit is contained in:
Igor Postelnik 2020-06-11 21:47:40 -05:00 committed by Adam Chalmers
parent 448a7798f7
commit 8f75feac94
5 changed files with 334 additions and 189 deletions

View File

@ -14,7 +14,7 @@ import (
) )
type RegistrationServer interface { type RegistrationServer interface {
RegisterConnection(ctx context.Context, auth []byte, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) RegisterConnection(ctx context.Context, auth TunnelAuth, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error)
UnregisterConnection(ctx context.Context) UnregisterConnection(ctx context.Context)
} }
@ -32,6 +32,11 @@ type ConnectionOptions struct {
CompressionQuality uint8 CompressionQuality uint8
} }
type TunnelAuth struct {
AccountTag string
TunnelSecret []byte
}
func (p *ConnectionOptions) MarshalCapnproto(s tunnelrpc.ConnectionOptions) error { func (p *ConnectionOptions) MarshalCapnproto(s tunnelrpc.ConnectionOptions) error {
return pogs.Insert(tunnelrpc.ConnectionOptions_TypeID, s.Struct, p) return pogs.Insert(tunnelrpc.ConnectionOptions_TypeID, s.Struct, p)
} }
@ -40,6 +45,14 @@ func (p *ConnectionOptions) UnmarshalCapnproto(s tunnelrpc.ConnectionOptions) er
return pogs.Extract(p, tunnelrpc.ConnectionOptions_TypeID, s.Struct) return pogs.Extract(p, tunnelrpc.ConnectionOptions_TypeID, s.Struct)
} }
func (a *TunnelAuth) MarshalCapnproto(s tunnelrpc.TunnelAuth) error {
return pogs.Insert(tunnelrpc.TunnelAuth_TypeID, s.Struct, a)
}
func (a *TunnelAuth) UnmarshalCapnproto(s tunnelrpc.TunnelAuth) error {
return pogs.Extract(a, tunnelrpc.TunnelAuth_TypeID, s.Struct)
}
type ConnectionDetails struct { type ConnectionDetails struct {
UUID uuid.UUID UUID uuid.UUID
Location string Location string
@ -92,6 +105,11 @@ func (i TunnelServer_PogsImpl) RegisterConnection(p tunnelrpc.RegistrationServer
if err != nil { if err != nil {
return err return err
} }
var pogsAuth TunnelAuth
err = pogsAuth.UnmarshalCapnproto(auth)
if err != nil {
return err
}
uuidBytes, err := p.Params.TunnelId() uuidBytes, err := p.Params.TunnelId()
if err != nil { if err != nil {
return err return err
@ -111,7 +129,7 @@ func (i TunnelServer_PogsImpl) RegisterConnection(p tunnelrpc.RegistrationServer
return err return err
} }
connDetails, callError := i.impl.RegisterConnection(p.Ctx, auth, tunnelID, connIndex, &pogsOptions) connDetails, callError := i.impl.RegisterConnection(p.Ctx, pogsAuth, tunnelID, connIndex, &pogsOptions)
resp, err := p.Results.NewResult() resp, err := p.Results.NewResult()
if err != nil { if err != nil {
@ -140,10 +158,17 @@ func (i TunnelServer_PogsImpl) UnregisterConnection(p tunnelrpc.RegistrationServ
return nil return nil
} }
func (c TunnelServer_PogsClient) RegisterConnection(ctx context.Context, auth []byte, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) { func (c TunnelServer_PogsClient) RegisterConnection(ctx context.Context, auth TunnelAuth, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) {
client := tunnelrpc.TunnelServer{Client: c.Client} client := tunnelrpc.TunnelServer{Client: c.Client}
promise := client.RegisterConnection(ctx, func(p tunnelrpc.RegistrationServer_registerConnection_Params) error { promise := client.RegisterConnection(ctx, func(p tunnelrpc.RegistrationServer_registerConnection_Params) error {
err := p.SetAuth(auth) tunnelAuth, err := p.NewAuth()
if err != nil {
return err
}
if err = auth.MarshalCapnproto(tunnelAuth); err != nil {
return err
}
err = p.SetAuth(tunnelAuth)
if err != nil { if err != nil {
return err return err
} }

View File

@ -16,6 +16,8 @@ import (
"github.com/cloudflare/cloudflared/tunnelrpc" "github.com/cloudflare/cloudflared/tunnelrpc"
) )
const testAccountTag = "abc123"
func TestMarshalConnectionOptions(t *testing.T) { func TestMarshalConnectionOptions(t *testing.T) {
clientID := uuid.New() clientID := uuid.New()
orig := ConnectionOptions{ orig := ConnectionOptions{
@ -47,6 +49,7 @@ func TestMarshalConnectionOptions(t *testing.T) {
func TestConnectionRegistrationRPC(t *testing.T) { func TestConnectionRegistrationRPC(t *testing.T) {
p1, p2 := net.Pipe() p1, p2 := net.Pipe()
t1, t2 := rpc.StreamTransport(p1), rpc.StreamTransport(p2) t1, t2 := rpc.StreamTransport(p1), rpc.StreamTransport(p2)
// Server-side // Server-side
@ -84,9 +87,14 @@ func TestConnectionRegistrationRPC(t *testing.T) {
testImpl.details = &expectedDetails testImpl.details = &expectedDetails
testImpl.err = nil testImpl.err = nil
auth := TunnelAuth{
AccountTag: testAccountTag,
TunnelSecret: []byte{1, 2, 3, 4},
}
// success // success
tunnelID := uuid.New() tunnelID := uuid.New()
details, err := client.Register(ctx, []byte{1, 2, 3}, tunnelID, 2, options) details, err := client.RegisterConnection(ctx, auth, tunnelID, 2, options)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, expectedDetails, *details) assert.Equal(t, expectedDetails, *details)
@ -94,15 +102,15 @@ func TestConnectionRegistrationRPC(t *testing.T) {
testImpl.details = nil testImpl.details = nil
testImpl.err = errors.New("internal") testImpl.err = errors.New("internal")
_, err = client.Register(ctx, []byte{1, 2, 3}, tunnelID, 2, options) _, err = client.RegisterConnection(ctx, auth, tunnelID, 2, options)
assert.EqualError(t, err, "internal") assert.EqualError(t, err, "internal")
// retriable error // retriable error
testImpl.details = nil testImpl.details = nil
const delay = 27*time.Second const delay = 27 * time.Second
testImpl.err = RetryErrorAfter(errors.New("retryable"), delay) testImpl.err = RetryErrorAfter(errors.New("retryable"), delay)
_, err = client.Register(ctx, []byte{1, 2, 3}, tunnelID, 2, options) _, err = client.RegisterConnection(ctx, auth, tunnelID, 2, options)
assert.EqualError(t, err, "retryable") assert.EqualError(t, err, "retryable")
re, ok := err.(*RetryableError) re, ok := err.(*RetryableError)
@ -117,7 +125,10 @@ type testConnectionRegistrationServer struct {
err error err error
} }
func (t testConnectionRegistrationServer) Register(ctx context.Context, auth []byte, tunnelUUID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) { 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)
}
if t.err != nil { if t.err != nil {
return nil, t.err return nil, t.err
} }

View File

@ -11,12 +11,12 @@ import (
// mocks for specific unit tests without having to implement every method // mocks for specific unit tests without having to implement every method
type mockTunnelServerBase struct{} type mockTunnelServerBase struct{}
func (mockTunnelServerBase) Register(ctx context.Context, auth []byte, tunnelUUID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) { func (mockTunnelServerBase) RegisterConnection(ctx context.Context, auth TunnelAuth, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) {
panic("unexpected call to Register") panic("unexpected call to RegisterConnection")
} }
func (mockTunnelServerBase) Unregister(ctx context.Context) { func (mockTunnelServerBase) UnregisterConnection(ctx context.Context) {
panic("unexpected call to Unregister") panic("unexpected call to UnregisterConnection")
} }
func (mockTunnelServerBase) RegisterTunnel(ctx context.Context, originCert []byte, hostname string, options *RegistrationOptions) *TunnelRegistration { func (mockTunnelServerBase) RegisterTunnel(ctx context.Context, originCert []byte, hostname string, options *RegistrationOptions) *TunnelRegistration {

View File

@ -121,8 +121,13 @@ struct ConnectionDetails {
locationName @1 :Text; locationName @1 :Text;
} }
struct TunnelAuth {
accountTag @0 :Text;
tunnelSecret @1 :Data;
}
interface RegistrationServer { interface RegistrationServer {
registerConnection @0 (auth :Data, tunnelId :Data, connIndex :UInt8, options :ConnectionOptions) -> (result :ConnectionResponse); registerConnection @0 (auth :TunnelAuth, tunnelId :Data, connIndex :UInt8, options :ConnectionOptions) -> (result :ConnectionResponse);
unregisterConnection @1 () -> (); unregisterConnection @1 () -> ();
} }

View File

@ -1484,6 +1484,90 @@ func (p ConnectionDetails_Promise) Struct() (ConnectionDetails, error) {
return ConnectionDetails{s}, err return ConnectionDetails{s}, err
} }
type TunnelAuth struct{ capnp.Struct }
// TunnelAuth_TypeID is the unique identifier for the type TunnelAuth.
const TunnelAuth_TypeID = 0x9496331ab9cd463f
func NewTunnelAuth(s *capnp.Segment) (TunnelAuth, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2})
return TunnelAuth{st}, err
}
func NewRootTunnelAuth(s *capnp.Segment) (TunnelAuth, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2})
return TunnelAuth{st}, err
}
func ReadRootTunnelAuth(msg *capnp.Message) (TunnelAuth, error) {
root, err := msg.RootPtr()
return TunnelAuth{root.Struct()}, err
}
func (s TunnelAuth) String() string {
str, _ := text.Marshal(0x9496331ab9cd463f, s.Struct)
return str
}
func (s TunnelAuth) AccountTag() (string, error) {
p, err := s.Struct.Ptr(0)
return p.Text(), err
}
func (s TunnelAuth) HasAccountTag() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s TunnelAuth) AccountTagBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return p.TextBytes(), err
}
func (s TunnelAuth) SetAccountTag(v string) error {
return s.Struct.SetText(0, v)
}
func (s TunnelAuth) TunnelSecret() ([]byte, error) {
p, err := s.Struct.Ptr(1)
return []byte(p.Data()), err
}
func (s TunnelAuth) HasTunnelSecret() bool {
p, err := s.Struct.Ptr(1)
return p.IsValid() || err != nil
}
func (s TunnelAuth) SetTunnelSecret(v []byte) error {
return s.Struct.SetData(1, v)
}
// TunnelAuth_List is a list of TunnelAuth.
type TunnelAuth_List struct{ capnp.List }
// NewTunnelAuth creates a new list of TunnelAuth.
func NewTunnelAuth_List(s *capnp.Segment, sz int32) (TunnelAuth_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 2}, sz)
return TunnelAuth_List{l}, err
}
func (s TunnelAuth_List) At(i int) TunnelAuth { return TunnelAuth{s.List.Struct(i)} }
func (s TunnelAuth_List) Set(i int, v TunnelAuth) error { return s.List.SetStruct(i, v.Struct) }
func (s TunnelAuth_List) String() string {
str, _ := text.MarshalList(0x9496331ab9cd463f, s.List)
return str
}
// TunnelAuth_Promise is a wrapper for a TunnelAuth promised by a client call.
type TunnelAuth_Promise struct{ *capnp.Pipeline }
func (p TunnelAuth_Promise) Struct() (TunnelAuth, error) {
s, err := p.Pipeline.Struct()
return TunnelAuth{s}, err
}
type RegistrationServer struct{ Client capnp.Client } type RegistrationServer struct{ Client capnp.Client }
// RegistrationServer_TypeID is the unique identifier for the type RegistrationServer. // RegistrationServer_TypeID is the unique identifier for the type RegistrationServer.
@ -1618,9 +1702,9 @@ func (s RegistrationServer_registerConnection_Params) String() string {
return str return str
} }
func (s RegistrationServer_registerConnection_Params) Auth() ([]byte, error) { func (s RegistrationServer_registerConnection_Params) Auth() (TunnelAuth, error) {
p, err := s.Struct.Ptr(0) p, err := s.Struct.Ptr(0)
return []byte(p.Data()), err return TunnelAuth{Struct: p.Struct()}, err
} }
func (s RegistrationServer_registerConnection_Params) HasAuth() bool { func (s RegistrationServer_registerConnection_Params) HasAuth() bool {
@ -1628,8 +1712,19 @@ func (s RegistrationServer_registerConnection_Params) HasAuth() bool {
return p.IsValid() || err != nil return p.IsValid() || err != nil
} }
func (s RegistrationServer_registerConnection_Params) SetAuth(v []byte) error { func (s RegistrationServer_registerConnection_Params) SetAuth(v TunnelAuth) error {
return s.Struct.SetData(0, v) return s.Struct.SetPtr(0, v.Struct.ToPtr())
}
// NewAuth sets the auth field to a newly
// allocated TunnelAuth struct, preferring placement in s's segment.
func (s RegistrationServer_registerConnection_Params) NewAuth() (TunnelAuth, error) {
ss, err := NewTunnelAuth(s.Struct.Segment())
if err != nil {
return TunnelAuth{}, err
}
err = s.Struct.SetPtr(0, ss.Struct.ToPtr())
return ss, err
} }
func (s RegistrationServer_registerConnection_Params) TunnelId() ([]byte, error) { func (s RegistrationServer_registerConnection_Params) TunnelId() ([]byte, error) {
@ -1709,6 +1804,10 @@ func (p RegistrationServer_registerConnection_Params_Promise) Struct() (Registra
return RegistrationServer_registerConnection_Params{s}, err return RegistrationServer_registerConnection_Params{s}, err
} }
func (p RegistrationServer_registerConnection_Params_Promise) Auth() TunnelAuth_Promise {
return TunnelAuth_Promise{Pipeline: p.Pipeline.GetPipeline(0)}
}
func (p RegistrationServer_registerConnection_Params_Promise) Options() ConnectionOptions_Promise { func (p RegistrationServer_registerConnection_Params_Promise) Options() ConnectionOptions_Promise {
return ConnectionOptions_Promise{Pipeline: p.Pipeline.GetPipeline(2)} return ConnectionOptions_Promise{Pipeline: p.Pipeline.GetPipeline(2)}
} }
@ -3264,177 +3363,181 @@ func (p TunnelServer_reconnectTunnel_Results_Promise) Result() TunnelRegistratio
return TunnelRegistration_Promise{Pipeline: p.Pipeline.GetPipeline(0)} return TunnelRegistration_Promise{Pipeline: p.Pipeline.GetPipeline(0)}
} }
const schema_db8274f9144abc7e = "x\xda\xccY\x7fp\x14\xe5\xf9\x7f\x9e}\xef\xb2\x17H" + const schema_db8274f9144abc7e = "x\xda\xccYkl\x1c\xd5\xf5?g\xee\xaeg\xfdb" +
"\xbc[\xf6\x88\x98\xd1o\xbee`\xac\xd1\xa81\xa5\x83" + "=\x99M\x9cX\xf0\xf7\xbfQ\"\x8a!\x80\xe3R\x85" +
"T\x9b\x04\x035\x91\x1f\xd9\x1ct\x1cE\xc7\xcd\xddK" + "\x14j;\xd8)6yx\xbcq\xc5#A\x8cwo" +
"\xb2\xe9\xdd\xee\xb9\xbb\x17\x13\x0a\x82\x11\xaa8\xfe\x16\xaa" + "\xecqwg63\xb3\xc6N\x13\x92\x98\xa4\x10Dy" +
"Ri\x15\xc7v\xb0\xb5J\xd5i\xed\xe8T\xdaZ\xed" + "\x84\x84G\x0a-\x04\xa9UiiI\xa1j\xa9\xa8J" +
"hU\x1c\xe8\x80\xd2i+\xd2V\x06k\x8bv\x1c:" + "\xfa\x82\x8agP\xa8\x02\xa4jKH[\xa2P\xda@" +
"\xeav\x9e\xdd\xdb\x1f\xb9\x84$h\xff\xe8\x7f7\xcf>" + "\x85\xa8\x80\xa9\xce\xcc\xce\xc3kc;\xd0\x0f\xfd\xb6:" +
"\xef\xf3>\xbf\x9f\xcf\xfb\xdc\xf9i\xb1Mh\x8e?>" + "s\xee\xbd\xe7}~\xe7\xec\xf9\xcb\xc56\xa19.V" +
"\x0d@Y\x1b\xafrx\xe3\x1bk\x1e\x9c\xfb\xab\x11P" + "\x03([\xe3\x15\x0eozi\xe3\xfd\x0b\x7f5\x06J" +
"\xea\x11\x9d\xeb\x9f\xedJ\x1f\xb7G\xde\x828\x13\x01Z" + "\x03\xa2s\xdd\x13\xdd\xa9\xf7\xed\xb1\xd7 \xceD\x80\x16" +
".\x8e\xafAY\x89\x8b\x00\xf2\xd2\xf8_\x01\x9d\xcb\xa4" + "-\xbe\x11\xe5\xcdq\x11@\x1e\x8d\xff\x15\xd0\xb9L:" +
"\xf3\xaeL\xbf\xfe\xea\x8d \xd5G\x99c\xc4\xdc\\\xd5" + "\xef\xaa\xd4\x8b\xcf_\x0fRC\x949F\xcc\xeb*\x9a" +
"\x88r{\x151_\\E\xcc\x17\x15^\xdb\xf1\xe5\xad" + "P\xceW\x10\xb3VA\xcc\x17\xe5_\xd8\xf7\xf9=\xcf" +
"/o\x04\xa9^\x08\x99\x01[\xce\x12\xd7\xa0|\xb1H" + "l\x07\xa9A\x08\x99\x01[\xfa\xc4\x8d(k\"qr" +
"\x9c\x17\x8a\xcb\x01\x9d\x0f\xb6\xcc\xfa\xe1C\xaf\xbe\xb4\x09" + "q5\xa0\xf3\xce\xee\xb9\xdf{\xe0\xf9\xa7w\x80t&" +
"\xa43\x11\xcaw+\xe2\x9b\x08(s\xf1q@g\xf6" + "B\xe9\xed\xcd\xe2\xab\x08(\xdf.\xfe\x10\xd0i]\xfe" +
"\xe0\xdck~\xf9\xc2\x93\xf7\x82\xd2\x84\xe8\x1c\xec={" + "\xdc\xe3\x0d-w\xee.{W \xc6\xe6D\x13\xca\xed" +
"\x1f\xdb\xfe\xe8[\xb0\x12E\x14\x00Z\xe2\x89\x1d\xc4;" + "\x09\xba\xed\xe2\xc4\xb5\x80\xce\xfc\xe1\x85\xd7\xfc\xf27\x8f" +
"3q\x1d\xa0\xf3\xda9\xcf\xfe\xfc\xce'o\xfa\x0e(" + "\xde\x05\xca\"D\xe7H\xff\xd9/\xb3\xfb\x1ez\x0d\xfa" +
"g\"\x02\xb8\xba\x0d'\xfeM\x0c\xb7%Z\x01\x9d-" + "PD\x01\xa0\xe5\x81\xc4>\xbax\xbf\xcb\xfb\xc29O" +
"\xfb\x9f[V\xb8k\xdb\x0e\xef6\xf7\xfb\xd3\x09A\x80" + "\xfc\xec\xb6Go\xf8\x06(g\"\x02\xb8\x8a\xcc\xae\xfc" +
"\x98\xb3\xb1\xf3\xa3\xc2\xca\x873\x0f\x97\xf5 \xc3[v" + "71\x9cU\xd9\x0a\xe8\xec>\xfc\xf3U\xf9\xdb\xf7\xee" +
"&\x8e!`\xcbs\x89\x06\x04t\xe6\xbdyx\xf9\xd2" + "\xf3Ds\xbf+\x95\x82\x001g{\xd7{\xf9\xbe\x07" +
"\x9f\xac\xfeA\xe4\xec\x81\xea5t\xf6\xb1\xff\xbb\xacz" + "\xd3\x0f\x96\x84&+\xb5tV\x9eD\xc0\x96+*\x1b" +
"\xe8\xf0\xe2'@j\xf2\xbf\xec\xab\xee\xa1/\xb1\xab\xd8" + "\x11\xd0\xb9\xe0\xd5c\xabW\xfeh\xfdw\"g\x8bU" +
"\xa7\xea}\xbfx\xaa\xd2\xc5\x02\xf1\xec\xa9\xeeE\xf9p" + "\x1b\xe9\xec\xc3\xffwY\xe5\xc8\xb1\xe5\x8f\x80\xb4\xc8\xff" +
"5\xf9\xe2\xcf\xd5\xe4\xb5[vo;;\xf1\xbd\x0f\x9e" + "\xb2\xa1\xaa\x97\xbe\xc4\xd6\xb1\x8f\xd4\xbb\x7f\xf1X\xb9?" +
"\xaep\xb1\xcb\xfc\xc2\xb4^\x94\x0fL#\xe6}\xd3\xc8" + "\\U\xf3U\xfd(o\xab\"U7W\x91\x89o:" +
"\xd6\x99\x9dx\xf0\xf9\xe6\xd8O\xa3\x8e\x9b7\xfd\x08\xd9" + "\xb0\xf7\xec\xc4\xb7\xde\xf9\xf1dvQ\xab\xfbQ.V" +
"\xda9\x9d\x1cw\xc6{\x0bk\xf5\xf7G\x9e\xaf\x90\xe6" + "\x13\xf3\x86j\xd2uv\x17\x1ey\xb29\xf6\x93\xa8\x95" +
"2\xbe;\xbd\x0b\xe5O\xa6\x93\xb4\xe3.s\xd7\x95\xf7" + "\x0fV\x1f']\x8fU\x93\x95\xcfxkY\xad\xfe\xf6" +
"\xdc\x1d?|\xcf\x8b\xa4h$b\xf1\x04qo\xad1" + "\xd8\x93e\xb7\xb9\x8c;j\xbaQ\xbe\xa7\x86n\xdbS" +
"Q\xdeYC?\x1f\xa99\x95\x01:\xf5O|\xe5\xc7" + "C\xcc\xddW\xdd\xb1+~\xec\x8e\xa7H\xd0\x88{\xe3" +
"\x0bs\x07^\x1eGSyn\xea\x98\xdc\x9c\xa2_M" + "\x09\xd7'\xb5&\xca\x9d\xb5\xf4\xb3\xbd\xb6\x9e\x01:\x0d" +
")R\xf4P\xd3\xaeo\xbe{\xdb\x9e\xbdeE\x91\xc4" + "\x8f|\xe1\x07\xcb\xb2\xaf<3\x89\xa4\xf2\x81\xba\x93\xf2" +
"lN\xb9A\xd9\x9e\xa2\xa0\x041\xadp\x92\xcb\xf9\\" + "su\xf4\xebwu$\xe8\xd1E\xfb\xbf\xfa\xe6\xd7\x0f" +
"j\x00\xe5=\xae\xb8\xdf\xb9\xdc\xc2a\xf5\xb4\x0d\xbf\xff" + "\x1e*\x09\x8at\xcdB\xc9u\xca\x85\x129%\xf0i" +
"\xea\xc1H\x18\xf6\xa4\xdeF\x889\xcb\xbe~\xe5@\xf5" + "\x99\x91\\\xce+\xa4!\x94\xf3\x92\x1b\x87.\xb7pL" +
"\xbaC\x87\xa2\x17\xbd\x90r=r\xc0=\xfa\xf7\xef\x1f" + "\x9d\xb7\xf5\xf7_<\x12qC^z\x1d!\xe6\xac\xfa" +
"\xb9\xe3h!\xf7\x177\x95|\x9f\x1dO-\x10\x00e" + "\xf2UC\x95\x9b\x8f\x1e\x8d>\xa4J\xaeE\x8a\xee\xd1" +
"I\xa2\x08\x9c\xdaP\xbbh\xf6\xfe\xee#^$=\x11" + "\xbf\x7f\xfb\xf8\xad'\xf2\xd9\xbf\xb8\xa1\xe4\xdbl\x8f\xb4" +
"\xefI\x0b\x89!>\x83D\xcc\xbb\xa6\x9d\xaf\x9a\x7f\xf9" + "T\x00\x94\x1f\x96\xc8\x03\xf5\x8d\xb5\x9d\xf3\x0f\xf7\x1c\xf7" +
"\x11\x90\xea\xd9\xa8\xc4\x9e;c\x01\xca\xf3f\xb8\xd50" + "<\xe9]\xb1s\xd62bx`\x16]q\xc15\xed" +
"\xe3&\x94;\xe5S\x01\x9c\xdb\xaf\xefX~\xe1\xec\xdd" + "|\xed\x92\xcb\x8f\x83\xd4\xc0\xc6e\xc1\x81YKQ>" +
"\xc7\xa2*](SV\xc9Ke\x92\xb7z\xfe\xd1\xaf" + "8\x8b\x0e<7\xeb\x06\x94\x8f\xc9\xf5\x00\xce-\xd7u" +
"\xcd\xbd\xfd7\xc7*\x1c\xe92\x16\xe4F\x94\xd7\xc9d" + "\xac\xbep\xfe\x81\x93Q\x91^\x96)\xaa\xe47e\xba" +
"\xfa01\xbf\xbf\xf8\xbb{\xeb\x93\xf5\x1fV\xb8\x89\xca" + "o\xfd\x92\x13_Zx\xcboO\x96\x19\xd2e\xacL" +
"\xaee\xbb<\x80\xf2.\xe2myL~\x91\xd2\xf5[" + "5\xa1</E\xaa\xcfN\xb5\x02\xbe\xbd\xfc\x9b\x87\x1a" +
"o]=\xf4\xc6\x8d\x1f\xfc\xab2\xa2\xae\xe8\x87f\xf6" + "\x92\x0d\xef\x96\x99\x89r\xb4\xe5\xc2\xd4\x10\xca+\x89\xb7" +
"\xa0\xfc\xf4L\x12\xbdk&\xc5\xff\xde\x15\x7f[\x7ft" + "\xa5+\xf5\x14\x85\xeb\xd7^\xbbz\xe4\xa5\xeb\xdf\xf9W" +
"k\xddGc\xecR\xea\x06P\xe6u\xc4\xa9\xd6\xdd$" + "\xb9G\xdd\xab/\x9e\xd3\x8b\xb22\x87\xae^9\x87\xfc" +
"\xef\xa6_\xce\xeb\xe2\xc3\xcd\x1d\xeb_>\x1eI\xf8\x9d" + "\x7f\xd7\x9a\xbfm9\xb1g\xce{\x13\xf4zk\xce\x10" +
"u]\x94\xf0\xdf\x16\x1f8\xb4\xe1\x8fW\x7f\x1c5\xf8" + "\xcaXO\x9c\x1f\xce\xb9A^G\xbf\x9c\x17\xc5\x07\x9b" +
"\x91\xba\xb7\xc9\xe0g\xea\xc8\xe0\xb5\xef\xdf\x7f\xe9\x1d\xab" + ";\xb6<\xf3~$\xe0;\xeb\xbb)\xe0\xef\x14\xef=" +
"~\xf4i\xb4\x8a\xeaF\xe8\xa8]\xd2u\x9e7\x8b\xb1" + "\xba\xf5\x8fW\x7f\x10U\xb8\xbd\xfeuR\xb8\xaf\x9e\x14" +
"\xecy\xfe\xcf\xec\xb9Y\xb5\xa8\x17\x17\xb4\x97\xec~\xae" + "\xde\xf4\xf6=\x97\xde\xba\xf6\xfb\x1fE\xb3\xa8~\x8c\x8e" +
"\xdbZV\xb5y\x0fo\xb5\x8a\x86n\xf1nD%\xc5" + "\xdaE]\xe79\xb3\x10\xcb\x9c\xe7\xff\xcc\x9c\x9bQ\x0b" +
"b\x001\x04\x90\xd4\x01\x00\xe5\x1a\x86J^@\x091" + "zai{\xd1\x1e\xe4\xba\xadeT\x9b\xf7\xf2V\xab" +
"M\x01\x964\"\xf63Tl\x01%AHS\xc7\x90" + "`\xe8\x16\xefAT\xeaX\x0c \x86\x00\x92:\x04\xa0" +
"\xae\x9d\x0d\xa0\xe4\x19*C\x02\"K#\x03\x90Jw" + "\\\xc3P\xc9\x09(!\xa6\xc8\xc1\x92F\xc4A\x86\x8a" +
"\x03(C\x0c\x95\x8d\x02:En\x16T\x9d\xeb\x90\xb4" + "-\xa0$\x08)\xaa\x18\xd2\x86\xf9\x00J\x8e\xa12\"" +
"\x17\x99&\xd6\x80\x805\x80\x8e\xc9msX\xed\xcdC" + " \xb2\x142\x00\xa9\xb8\x0b@\x19a\xa8l\x17\xd0)" +
"\x92G\xc8\xe2\xc0u6\xd6\x82\x80\xb5\x80N\xbfQ2" + "p3\xaf\xea\\\x87\xa4\xddi\x9aX\x03\x02\xd6\x00:" +
"\xad\x95\xba\x8dZ\xbe\x87\xaf6\xb9\x85\xfdX\x05\x02V" + "&\xb7\xcdQ\xb5?\x07I\x1e!\x8bC\xd7\xdaX\x0b" +
"\x01\x06\xe6\xb1\xb1\xe6]\x92\xd7\xb8n';\xf5\xd5F" + "\x02\xd6\x02:\x83F\xd1\xb4\xfat\x1b\xb5\\/_o" +
"\x85Q]\xe3\x19\xd5U6jc\xc4\xa8\x1b\x16RS" + "r\x0b\x07\xb1\x02\x04\xac\x00\x0c\xd4c\x13\xd5\xbb$\xa7" +
"g\xa8\xdc,\xa0\xc4\xcaVmj\x04P60Tn" + "q\xddNv\xe9\xeb\x8d2\xa5\xba'S\xaa\xbb\xa4\xd4" +
"\x15\xd0\xc9\xba\x97t\xe6\x00 \xd0w5W\xed\x92\xc9" + "\xf6\x88R\xdb\x96\x01(\x9b\x18*7\x0a(\xb1\x92V" +
"-\xa2\x9d\x02\xd8\xcd\xd05\xeb\x14\xc0\xf5\x83\xdc\xb44" + ";\x9a\xa8-0Tn\x16\xd0\xc9\xb8\x8fte\x01 " +
"C\xf7\xcdL\xaaf\xb6?p\xc5\x04\xa1Z4\xa4Y" + "\x90w=W\xed\xa2\xc9-\xa2\x9d\x06\xd8\xc3\xd0U\xeb" +
"\xb6\xa6\xf7\xadp\xe9\xad\xddF^\xcb\x0e\x93U5\xae" + "4\xc0-\xc3\xdc\xb44C\xf7\xd5L\xaaff00" +
"\x9eg,\x00@\x94f^\x01\x80\x82$-\x04h\xd5" + "\xc5\x14\xae\xea\x1c\xd1,[\xd3\x07\xd6\xb8\xf4\xd6\x1e#" +
"\xfat\xc3\xe4NN\xb3\xb2\x86\xaes`Y{}\xaf" + "\xa7eFI\xab\x1aW\xce3\x96\x02 J\xb3\xaf\x04" +
"\x9aW\xf5,\x0f.\xaa\x1a{\x91wA\x86\x9b\x83\xdc" + "@A\x92\x96\x01\xb4j\x03\xbaar'\xabY\x19C" +
"<W\x8d$\xc8\x9cn\xd5TY\xc1Rj\x02?." + "\xd79\xb0\x8c\xbd\xa5_\xcd\xa9z\x86\x07\x0fUL|" +
"\xba\x02@\xe9`\xa8tG\xfc\xb8\x94\xfc\xb8\x84\xa1r" + "\xc8{ \xcd\xcdan\x9e\xabF\x02dA\x8fj\xaa" +
"y\xc4\x8f+\xc9\x8f\xdd\x0c\x95U\x02:\x86\xa9\xf5i" + ",o)5\x81\x1d;\xaf\x04P:\x18*=\x11;" +
"\xfa%\x1c\x98\x19\x8d\xb1e\xebj\x81\x93\xcf\xca\xfeX" + "\xae$;\xae`\xa8\\\x1e\xb1c\x1f\xd9\xb1\x87\xa1\xb2" +
"o\x14m\xcd\xd0-L\x85}\x14\x10S\x11O\xc5\xc7" + "V@\xc70\xb5\x01M\xbf\x84\x033\xa3>\xb6l]" +
"\x89:Y\x9b\xa5\x83=\xdc\xcb\xe8sMn\x89\xa5\xbc" + "\xcds\xb2Y\xc9\x1e[\x8c\x82\xad\x19\xba\x85ua\x1d" +
"\xad$X\xac\xc6q\\\xd5\xcf\xba\x00@\x99\xc3P9" + "\x05\xc4\xba\xa9\xbd\xee)\x90\xa4\xd8&\xfb$\x02i\xcf" +
"_\xc0Z\xfc\xd4\xf1to\xa2|=\x9f\xa1r\x91\x80" + "\"i?\xcbP\xf9\\D\xdaf\x0a\xe5\xf3\x19*\x17" +
"\x0d\xdc4\x0d\x13Sa\xc5\x97\xef\xce\x96/@C\xef" + "\x09\xe8\xa8\x99\x8cQ\xd4\xed5\xc0\xd4\x812\xa7\xa49" +
"\xe0\xb6\xaa\xe5\x914\x0c\x86L\x85\x86\x93\xb9\xb8\xa4\x9b" + "$3&\x0f\xe5\xf5\x9f\x8dO\x12wd\xef\x0c\x89\xde" +
"\xbcO\xb3lnz\xe49\xad\xe4\xe7\x82\xa5\xc4\x027" + "\xcb\xbd\x9c:\xd7\xe4\x96X\xcc\xd9$M\x8d\xe3x\xe2" +
"\xd7n\x03PR\x0c\x95\xd3\x05t\xfaL5\xcb\xbb\xb9" + ",\x06P\x160T\xce\x17\xb0\x16?r<y\x16\xed" +
"\x89\x9a\x91[\xa6\xeaF\x86\xf1,\xc6A\xc0x\xe4\xd2" + "\x0a\xe5i\xe4\xa6i\x98X\x17\xd6\x9c\x92\xf6\x99\xd2\x03" +
"SN\xf6\xd2\x1en\x95\xf2\xb6\x05\xc1\xa9\x89\xcf\x9b\xbc" + "h\xe8\x1d\xdcV\xb5\x1c\x92\x8d\x826Wf\xa3\xe9\x9c" +
"\xec\x84\xf2\xf1\xee\x06O\xe7t\xa0\xf3\xba\xd9a\xe5\x07" + "\\\xd4M>\xa0Y67=\xf2\x82V\xf2t\xdeR" +
"\xa9qCoX8Ajl\xa6$\xba\x99\xa1\xb2%" + "b\x81\xe9j\xf7\x02(u\x0c\x95\xd3\x05t\x06L5" +
"RbwQ\x12\xdd\xc9Py@@)\x16Kc\x0c" + "\xc3{\xb8\x89\x9a\x91]\xa5\xeaF\x9a\xf1\x0c\xc6A\xc0" +
"@\xba\x9f\x92h\x0bC\xe5Aat\x7f\xe0\x83\\\xb7" + "x\xe4\xd1\xd3N\xf5\xd1^n\x15s\xb6\x05\xc1\xa9\xa9" +
";\xb4>\x10\xb9\x15RI\xc5\x0e\xad\x8f\x03\xb3>o" + "\xcf\x9b\xbcd\x84\xd2\xf1\x9eFO\xe6T \xf3\xe6\xf9" +
"\x9a%&\xf1\x87\xd1k\x19yn\xf3\x0e\x9e\xcd\xab\xa6" + "a\xed\x09\xdc\xbd\xad?L\xdd 8wR`\xdc\xc8" +
"jk\x83\xdc\xfb^NF?\xa8\x13\x09\xecq#B" + "P\xd9\x1dI\xf2\xdb)\x8coc\xa8\xdc+\xa0\x14\x8b" +
"\x87\x0d}L\x98\xc2\xa4.\x87\x0a\xad\x89\xbaE\xc8\xbe" + "\xa50\x06 \xddCa\xbc\x9b\xa1r\xbf0\xbeB\xf1" +
"\xbchk\xa2\xa1[\x15\x0dp\x01\x80\xb2\x8a\xa1\xd2\x1f" + "a\xae\xdb\x1d\xda\x00\x88\xdc\x0a\xa9$b\x876\xc0\x81" +
"\x89\x0e7\x01\x94\x1cC\xa5( \x96\x83S\x18\x09\x9b" + "Y\x9f6\xd0\x13\xd3\xd8\xc3\xe8\xb7\x8c\x1c\xb7y\x07\xcf" +
"\xba\xc4\xb0\xdc\xd5\xb7\x85\xb1m\xf5\xfa\x1f\xa6B [" + "\xe4TS\xb5\xb5a\xee}/\x05\xa3\xef\xd4\xa9.\xec" +
"\xf6\x9dW\xe5K\x0ch\xc8\xaa\xf9\xceb\x10\x01\x93\x17" + "u=B\x87\x0d}\x82\x9b\xc2\xa0.\xb9\x0a\xad\xa9\xea" +
"\xf3j\x96/\xc2rG\x03D\x10\x10\xdd\x80\x15\x8a&" + "U\xc8\xbe\xba`k\xa2\xa1[e%x)\x80\xb2\x96" +
"\xb7,\xd4\x0c])\xa9y\x8d\xd9\xc3c\xfa\xfc\x84\xd6" + "\xa12\x18\xf1\x0e7\x01\x94,C\xa5 \x96\x9c\x93" +
"R=\x8aZ\xde\xb56\x11X{VcX\xeb\x81\xb5" + "\x1f\x0b\xdb\x8a\xc4\xb0\xd4W\xf6\x86\xbem\xf5*0\xd6" +
"M4\xc3\xcea\xa8\xcc\x170Y*i\xb9@\xc1\xbc" + "\x85\xb8\xbbd;\xaf\xce\xac0\xa01\xa3\xe6\xba\x0a\x81" +
"\x91u\x83\x00\xc9ej\x81\x8fi\xceU\x93\xd6\xc6\xa8" + "\x07L^\xc8\xa9\x19\xde\x89\xa5\x9a\x0a\x88 \xba\x0e" +
"\xca\xeaV\x93ni\xfc/u\xcd\x89\xa1\x00\x99\x0e\xee" + "\xcb\x17LnY\xa8\x19\xbaRTs\x1a\xb3G't" +
"h\x09U\xa6jnc\xa8,\x89\xa8\xdcyA\xc4\x0e" + "\x9a)\xb5\xa5|\x14\xb5\x9cUVz\x9a\xc2\\\x0f\xb4" +
"_\xe5\xa5\xbd\xa1\x1d\xe27\xf8\xb0\xafU\x03/P\xa7" + "]D\xa5\xe7\x1c\x86\xca\x12\x01\x93\xc5\xa2\x96\x0d\x04\xcc" +
"\xf4\x9dY6\xa6\x1d\xc4\xcbB\x9e\x89\xf4\x8bV\xc7\xf2" + "\x19\x19\xd7\x09\x90\\\xa5\xe6\xf9\x84\xf6P1mn\x8c" +
"b\x83k!\xe98\xdf\xd7Q\x1e\xc6.\x80\xcc\x102" + "\xcb\xac\x1e5\xe9\xa6\xc6\xffR\xdd\x9e\x1a\x8c\x90\xea\xe0" +
"\xccl\xc4PM\xf9\x06\\\x08\x90YK\xf4\x9b1\xd4" + "6\xb7Pd\xca\xe66\x86\xca\x8a\x88\xc8]\x8b#z" +
"T\xde\x84\xf5\x00\x99\x0dD\xbf\x15\x03\xc8\"o\xc6G" + "\xf8\"\xaf\xec\x0f\xf5\x10\xbf\xc2G}\xa9\x1ay\x9e*" +
"\x012\xb7\x12\xf9>b\x8f1\xb7\xf9\xc8[]\xf1[" + "\xa5o\xcc\x922\xed ^\x16\xf2L%_4;V" +
"\x88\xfe \xd1\xe3\xb14\xc6\x01\xe4\xed\xd8\x08\x90\xb9\x8f" + "\x17\x1a]\x0dI\xc6%\xbe\x8c\xf2(v\x03\xa4G\x90" +
"\xe8O\x11\xbdJHc\x15\xe1?\x1c\x00\xc8<A\xf4" + "az;\x86b\xca\xdbp\x19@z\x13\xd1o\xc4P" +
"g\x89.\xc6\xd3\x84\xda\xe4g\xd0\x04\xc8\xfc\x8c\xe8\xbf" + "Ry\x076\x00\xa4\xb7\x12\xfdf\x0c@\x93\xbc\x13\x1f" +
"&zbV\x1a\x13\x00\xf2n\x97\xfe<\xd1_!z" + "\x02H\xdfL\xe4\xbb\x89=\xc6\xdc\xe2#\xefq\xaf\xdf" +
"\xf5ii\xac\x06\x90\x7f\x8b#\x00\x99\x97\x88\xbe\x97\xe8" + "M\xf4\xfb\x89\x1e\x8f\xa50\x0e \xdf\x87M\x00\xe9\xbb" +
"\xd30\x8d\xd3\x00\xe4=\xb8\x0d \xb3\x97\xe8\x7f\"\xfa" + "\x89\xfe\x18\xd1+\x84\x14V\x00\xc8\xfbq\x08 \xfd\x08" +
"\xf4\xaa4N\x07\x90\xff\xe0\xea\xb3\x9f\xe8\xef\x10\xbd&" + "\xd1\x9f \xba\x18O\x11n\x94\x1fG\x13 \xfdS\xa2" +
"\x96\xc6\x1az\x0a\xe1\x0e\x80\xcc;D\xff\x07\xd1k\xc5" + "\xff\x9a\xe8\x89\xb9)L\xd0\x80\xe1\xd2\x9f$\xfa\xb3D" +
"4\xd6\x02\xc8\xef\xb9v\x1d%zB\xa8\xc03~F" + "\xaf\x9c\x97\xc2J\x1a7p\x0c \xfd4\xd1\x0f\x11\xbd" +
"U\x80\x16fXA\xc8x\xb9\x8a\xd1K\xf7n#I" + "\x0aSX\x05 \x1f\xc4\xbd\x00\xe9CD\xff\x13\xd1\xab" +
"\xc0\x04\x93\xe1S\x15\x10\x93\x80N\xd10\xf2\xcbFg" + "+RX\x0d \xff\xc1\x95\xe70\xd1\xdf zM," +
"j\xd2V\xfb,\x1f \xa5\xc2\xc7\x0f \x11\x839\x0b" + "\x855\x00\xf2\x9fq\x1f@\xfa\x0d\xa2\xff\x83\xe8\xb5b" +
"IC\xef\xcc\x05\x8d\xa0\xb2\xaf\xf8\x9ahV{\xc96" + "\x0ak\x01\xe4\xb7\\\xbdN\x10=!\x94!*?\xa2" +
"JEh\xc8\xa96\xcf\x05]\xc5,\xe9\x8bM\xa3\xb0" + "\xca`\x133\xac\xc0e\xbc\x94\xc5\xe8\x85{\x8f\x91$" +
"\x02\xb9Y\xd0t5?I\xbf\xa9\x06\x01\xab\xa1\xdc\x12" + "h\x84\xc9p\xb2\x06\xc4$\xa0S0\x8c\xdc\xaa\xf1\x91" +
"|\xd9z\xa9\xd0m\xf2A\x0d\x8d\x92\xd5n\xdb\xbc " + "\x9a\xb4\xd5\x01\xcb\x87hu\xe1\xf8\x05H\xc4\xa0\xcfB" +
"\x16m+\xd0\xe8\xc4p/\xc8h\xa12\xa3\x1b\x8a\x0b" + "\xd2\xd0\xbb\xb2A!(\xaf+\xbe$\x9a\xd5^\xb4\x8d" +
"V\xa8}S\xe9STe_d\xa8|I\xc0\xa4\x1e" + "b\x01\x1a\xb3\xaa\xcd\xb3AU1\x8b\xfar\xd3\xc8\xaf" +
"iH\x0d\x83j\xbe\xf4Y\xda\xd3\xe8\xd1\xdd\xd3\xea\x8d" + "An\xe65]\xcdMSo*A\xc0J(\x95\x04" +
"\xfe(\xde\xa0\xe9\x90`\xa8\xa4\x05l5\xbdq\x93\xf2" + "\xffn\xbd\x98\xef1\xf9\xb0\x86F\xd1j\xb7m\x9e\x17" +
"_I\x93\xb7\x92\xd1\x00,\xe9\xbf)\\\xf9\x18Y<" + "\x0b\xb6\x15H\xf4\xf1\x803\x88h\xa1<\xa2\x1b\x0bK" +
"\xd0=BY\xfe\x94\xd5\xef\xe3\xb6\xf7\x8bP=AR" + "\xd7\xa8\x033\xa9S\x8bC\xdc\x94\xd4#\x05\xa9qX" +
"1:VO\xeet\x0f\xb7\x92S1=|MV\x18" + "\xcd\x15?Iy\x1a\xdf\xba{[\xbd\xd6\x1f\xc5\x1b\xd4" +
"/Ni\x8a\x8f3\xc3}\x8c\x17\x99\xc8\x8d\xe3M\xe4" + "\x1d\x12\x0c\x95\x94\x80\xad\xa6\xd7n\xea\xfc9m\xfaR" +
"\xaeq&rOt\"\x0b\xe5\x89L\x83\xa2\xc8PY" + "2\x1e\x80%\xfd\xa9\xc6\xbd\x1f#\xab\x0fzG(\xdd" +
"+`\x92@{0 <\xfdF?O(\x01:\xf5" + "?c\xf1\x07\xb8\xed\xfd\xa2\xb9\x82@\xb1\x18m\xab\xa7" +
"\x1c\x07\x1c\xf2s824\x82\xdd\xca\xe4\x18hj\xc6" + "v\xba\x97[\xc9\x99\xa8\x1e\xce\xb3e\xca\x8b3\xea\xe2" +
"\xfa\xd8rR7\x07\x0b\x8b\x8a\x9b\xd9\x89\xa2\xda\xea]" + "\x93\xf4p\x1f\xe3E:r\xd3d\x1d\xb9{\x92\x8e\xdc" +
"J\xd95\x8b\xc5\x01\x82\xe5\x0d\xfa\x0b\x02i\xd7\x1a\x10" + "\x1b\xed\xc8B\xa9#S\xa3(0T6\x09\x98\xa4\xb1" +
"\xa4\x9d\"\x86\x0b\x0e\xf4\xf7\x19\xd2v\x13\x04i\xab\x88" + "\x01\xeb\xc2}\xd48\xa1\xc7\x8fJ\x14\x0a]z\x96\x03" +
"B\xb0\xe0B\x7f\x91%m\xbe\x05\x04i\x93\x88,\xd8" + "\x8e\xf8\xd1\x1ci\x1f\xc1\x9egz443\xb5}\x94" +
"O\xa1\xff\xc4n\x1e\x9e\x86 H\xebD\x8c\x05k6" + "9\xad\xc1\x83\xe5\xc9L\x07\x8eV\xefQ\x8a\xb3\xb9," +
"\xf4\x1f\xe8\xd2\xb5\x03 H\x9a\x88\xf1`\xf5\x85\xfe\xa6" + "\x0e\x10,\x92\xd0_VH\xfb7\x82 }W\xc4p" +
"F\xbaj\x04\x04i\xa5\xe8\xf8N\x82V\xcf\x8e6t" + "\xd9\x82\xfenE\xba\xcf\x04A\xda#\xa2\x10,\xdb\xd0" +
"\xfc\xcc\x84\x0677\xdb\xd0\xf1\xc1\x1f\xfaP\x02\xa0\x0d" + "_\xaaI;o\x02A\xda!\"\x0bve\xe8\x8f\xfb" +
"\x1d\x1fi\xb2\x13AM\x97\xcb\x7f\xb7A\x92^nm" + "\xcd\xa3U\x08\x82\xb4Y\xc4X\xb0\x1fD\x7fY m" +
"\x04\xba\xbc\xaa\xc7r\xd9C\x1b*1\x8c\xec'\x00>" + "\x18\x02A\xd2D\x8c\x07k8\xf4\xb7F\xd2\xba1\x10" +
"+\xc0\xe9\xe1\x0d\x9f\xa7\x81\x8c\x13\\\xef\x9e\xe0\xdd\x1e" + "\xa4>\xd1\xf1\x8d\x04\xad\x9e\x1em\xe8\xf81\x0a\x8dn" +
"\x91K\x98\xad\x86\xa12K\x98\x14\xa6\xc5Nd\x85\x9f" + "\x94\xb6\xa1\xe3\xc3@\xf4A\x05@\x1b:>\xe6d\x1f" +
"\xb4I:L\xf2\xff?\x90\xbf\x87`\xce+\x0c\x95\xfd" + "\x07:].\x7f\x86\x84$M\x91m\x04\xbf\xbc\xfc\xc7" +
"\x91\"\xdcG\xc4\xd7\x19*\x07#0\xe7\x00U\xe6~" + "R\x01\x806Tb\x18\xd9\x95\x00|R\xa8\xd3\xcb\x1b" +
"\x86\xca\x87\xe1\xb2\xe3\x9f\xb7\x00(\x1f2\xec\x89\xc0\x06" + "?M)\x99\xc4\xb9\xde;\xc1\x0e!r/\xa1\xb7\x1a" +
"\xe9\x13b\xfc\x98\x86\xab\x0b\x1a\xd0\x03\x0dq\xbc\x1b " + "\x86\xca\\aZ\xc0\x16\xfb8-\xfc\xa0M\xd2a\xba" +
"\x93\xa0\xa1\x9bvAC\xcc\x03\x0d\x12\xf6\x02dRD" + "\xff\xff\x83\xfb\x0f\x12\xe0y\x96\xa1r8\x92\x8e/\x13" +
"?=\x0a\x1aN\xc3+\x002\xb3\x88>\x07\x05\x14y" + "\xf1E\x86\xca\x91\x08\xe0y\x85r\xf40C\xe5\xddp" +
"dQR2CX\x957\xfa\x96h\xfa\xb8\x93\xc8\xdf" + "\xf1\xf2\xcf\x9b\x00\x94w\x19\xf6F\x00\x84\xf4!1~" +
"\xbe\xa0\xbdX\xd5\xf2%\x93C8\x08\xcbM\xa2#2" + "@m\xd6\x85\x0f\xe8\xc1\x878\xee\x02H'\xa8\xfd\xa6" +
"\x9b\xbd\xb5L\xfbjJ\xbf\x0c%O\x0e-\x14A@" + "\\\xf8\x10\xf3\xe0\x83\x84\xfd\x00\xe9:\xa2\x9f\x1e\x85\x0f" +
"\xf1\xe4\xde[S\x9a\x13\x8bL\xd3@\xb3\x02r^\x10" + "\xf3\xf0J\x80\xf4\\\xa2/@\x01E\x1eY\xda\x14\xcd" +
"B\xce\x00q\x12r\xbe\x94\xa1\xb2\x82B\xd1\xe6\x85B" + "\x10`\xe5\x8c\x81\x15\x9a>iO\xf27Ah/W" +
"\xe9\x0dArCV-Y|\x8c\x0d\xc0\xb8\x19\xbc\x91" + "\xb5\\\xd1\xe4\x10\xb6\xc4R\x91\xe8\x88tioE\xd4" +
"\xad~\xa3\x94\xcf\xf5p\x10ms\xb8\xc2\x05\x93B\xcf" + "\xbe\x9e\xc2/M\xc1\x93E\x0bE\x10P<\xb5\xc9k" +
"\x0cO\xfa\x1d'\xe1v\x1c\x7f\xf7\x89\xfe\x8aSj\xde" + "F\x1d\xa3\xd34\x0d4\xcb\xc0\xe7\xe2\x10|\x06\xd8\x93" +
"\x06\x82\xd4D\x1d\xc7_\xe7\xa1\xbf\xc8\x96\xbe\xf0(\x08" + "0\xf4\xa5\x0c\x955\xe4\x8a6\xcf\x15J\x7f\x08\x97\x1b" +
"\xd2\x19a\x03@\xdf\x07\xcc\xd0G\x97\xbc\xf7\xc1\xcd\xd1" + "3j\xd1\xe2\x13t\x00\xc6\xcd`Z\xb6\x06\x8db." +
"6\xecF\xfco\xbc\x1c\xbd\xa1s\x12\x95>j\xfdC" + "\xdb\xcbA\xb4\xcd\xd12\x13L\x0bB\xd3<\xe9W\x9c" +
"m\\\x9c\xca\xb4\x0c\xfe\xff\xa8\xa8\xf4\xea\xcf\xfb\x88\xf6" + "\x84[q\xfc=,\xfa\xebV\xa9y/\x08\xd2\"\xaa" +
"\x07\xc9\x7f\x02\x00\x00\xff\xffU\xcf\xfa\xff" "8\xfej\x11\xfd\xa5\xba\xf4\x99\x87@\x90\xce\x08\x0b\x00" +
"\xfa6`\x86>>\xe5\xbd\x0fn\x8c\xb6a\x0f\xe2\x7f" +
"c\x86\xf4\xda\xcf)d\xfa\xb8U\x14\x95qq&}" +
"3\xf8\xe3\xa6,\xd3+?\xed8\xed7\x92\xff\x04\x00" +
"\x00\xff\xff\xed\xc3%H"
func init() { func init() {
schemas.Register(schema_db8274f9144abc7e, schemas.Register(schema_db8274f9144abc7e,
@ -3442,6 +3545,7 @@ func init() {
0x83ced0145b2f114b, 0x83ced0145b2f114b,
0x84cb9536a2cf6d3c, 0x84cb9536a2cf6d3c,
0x85c8cea1ab1894f3, 0x85c8cea1ab1894f3,
0x9496331ab9cd463f,
0x97b3c5c260257622, 0x97b3c5c260257622,
0x9b87b390babc2ccf, 0x9b87b390babc2ccf,
0xa29a916d4ebdd894, 0xa29a916d4ebdd894,