TUN-1977: Validate OriginConfig has valid URL, and use scheme to determine if a HTTPOriginService is expecting HTTP or Unix

This commit is contained in:
Chung-Ting Huang 2019-06-20 11:18:59 -05:00
parent 4090049fff
commit 4858ce79d0
10 changed files with 375 additions and 752 deletions

View File

@ -452,34 +452,30 @@ func defaultOriginConfig(c *cli.Context) (pogs.OriginConfig, error) {
return &pogs.HelloWorldOriginConfig{}, nil
}
originConfig := &pogs.HTTPOriginConfig{
TCPKeepAlive: c.Duration("proxy-tcp-keepalive"),
DialDualStack: !c.Bool("proxy-no-happy-eyeballs"),
TLSHandshakeTimeout: c.Duration("proxy-tls-timeout"),
TLSVerify: !c.Bool("no-tls-verify"),
OriginCAPool: c.String("origin-ca-pool"),
OriginServerName: c.String("origin-server-name"),
MaxIdleConnections: c.Uint64("proxy-keepalive-connections"),
IdleConnectionTimeout: c.Duration("proxy-keepalive-timeout"),
ProxyConnectTimeout: c.Duration("proxy-connection-timeout"),
ExpectContinueTimeout: c.Duration("proxy-expect-continue-timeout"),
ChunkedEncoding: c.Bool("no-chunked-encoding"),
TCPKeepAlive: c.Duration("proxy-tcp-keepalive"),
DialDualStack: !c.Bool("proxy-no-happy-eyeballs"),
TLSHandshakeTimeout: c.Duration("proxy-tls-timeout"),
TLSVerify: !c.Bool("no-tls-verify"),
OriginCAPool: c.String("origin-ca-pool"),
OriginServerName: c.String("origin-server-name"),
MaxIdleConnections: c.Uint64("proxy-keepalive-connections"),
IdleConnectionTimeout: c.Duration("proxy-keepalive-timeout"),
ProxyConnectionTimeout: c.Duration("proxy-connection-timeout"),
ExpectContinueTimeout: c.Duration("proxy-expect-continue-timeout"),
ChunkedEncoding: c.Bool("no-chunked-encoding"),
}
if c.IsSet("unix-socket") {
unixSocket, err := config.ValidateUnixSocket(c)
if err != nil {
return nil, errors.Wrap(err, "error validating --unix-socket")
}
originConfig.URL = &pogs.UnixPath{Path: unixSocket}
originConfig.URLString = unixSocket
}
originAddr, err := config.ValidateUrl(c)
if err != nil {
return nil, errors.Wrap(err, "error validating origin URL")
}
originURL, err := url.Parse(originAddr)
if err != nil {
return nil, errors.Wrapf(err, "%s is not a valid URL", originAddr)
}
originConfig.URL = &pogs.HTTPURL{URL: originURL}
originConfig.URLString = originAddr
return originConfig, nil
}

View File

@ -8,6 +8,7 @@ import (
"io"
"net"
"net/http"
"net/url"
"strconv"
"strings"
@ -22,7 +23,7 @@ import (
// OriginService is an interface to proxy requests to different type of origins
type OriginService interface {
Proxy(stream *h2mux.MuxedStream, req *http.Request) (resp *http.Response, err error)
OriginAddr() string
URL() *url.URL
Summary() string
Shutdown()
}
@ -30,14 +31,14 @@ type OriginService interface {
// HTTPService talks to origin using HTTP/HTTPS
type HTTPService struct {
client http.RoundTripper
originAddr string
originURL *url.URL
chunkedEncoding bool
}
func NewHTTPService(transport http.RoundTripper, originAddr string, chunkedEncoding bool) OriginService {
func NewHTTPService(transport http.RoundTripper, url *url.URL, chunkedEncoding bool) OriginService {
return &HTTPService{
client: transport,
originAddr: originAddr,
originURL: url,
chunkedEncoding: chunkedEncoding,
}
}
@ -75,36 +76,36 @@ func (hc *HTTPService) Proxy(stream *h2mux.MuxedStream, req *http.Request) (*htt
return resp, nil
}
func (hc *HTTPService) OriginAddr() string {
return hc.originAddr
func (hc *HTTPService) URL() *url.URL {
return hc.originURL
}
func (hc *HTTPService) Summary() string {
return fmt.Sprintf("HTTP service listening on %s", hc.originAddr)
return fmt.Sprintf("HTTP service listening on %s", hc.originURL)
}
func (hc *HTTPService) Shutdown() {}
// WebsocketService talks to origin using WS/WSS
type WebsocketService struct {
tlsConfig *tls.Config
originAddr string
shutdownC chan struct{}
tlsConfig *tls.Config
originURL *url.URL
shutdownC chan struct{}
}
func NewWebSocketService(tlsConfig *tls.Config, url string) (OriginService, error) {
func NewWebSocketService(tlsConfig *tls.Config, url *url.URL) (OriginService, error) {
listener, err := net.Listen("tcp", "127.0.0.1:")
if err != nil {
return nil, errors.Wrap(err, "cannot start Websocket Proxy Server")
}
shutdownC := make(chan struct{})
go func() {
websocket.StartProxyServer(log.CreateLogger(), listener, url, shutdownC)
websocket.StartProxyServer(log.CreateLogger(), listener, url.String(), shutdownC)
}()
return &WebsocketService{
tlsConfig: tlsConfig,
originAddr: url,
shutdownC: shutdownC,
tlsConfig: tlsConfig,
originURL: url,
shutdownC: shutdownC,
}, nil
}
@ -127,12 +128,12 @@ func (wsc *WebsocketService) Proxy(stream *h2mux.MuxedStream, req *http.Request)
return response, nil
}
func (wsc *WebsocketService) OriginAddr() string {
return wsc.originAddr
func (wsc *WebsocketService) URL() *url.URL {
return wsc.originURL
}
func (wsc *WebsocketService) Summary() string {
return fmt.Sprintf("Websocket listening on %ss", wsc.originAddr)
return fmt.Sprintf("Websocket listening on %s", wsc.originURL)
}
func (wsc *WebsocketService) Shutdown() {
@ -141,10 +142,10 @@ func (wsc *WebsocketService) Shutdown() {
// HelloWorldService talks to the hello world example origin
type HelloWorldService struct {
client http.RoundTripper
listener net.Listener
originAddr string
shutdownC chan struct{}
client http.RoundTripper
listener net.Listener
originURL *url.URL
shutdownC chan struct{}
}
func NewHelloWorldService(transport http.RoundTripper) (OriginService, error) {
@ -157,17 +158,19 @@ func NewHelloWorldService(transport http.RoundTripper) (OriginService, error) {
hello.StartHelloWorldServer(log.CreateLogger(), listener, shutdownC)
}()
return &HelloWorldService{
client: transport,
listener: listener,
originAddr: listener.Addr().String(),
shutdownC: shutdownC,
client: transport,
listener: listener,
originURL: &url.URL{
Scheme: "https",
Host: listener.Addr().String(),
},
shutdownC: shutdownC,
}, nil
}
func (hwc *HelloWorldService) Proxy(stream *h2mux.MuxedStream, req *http.Request) (*http.Response, error) {
// Request origin to keep connection alive to improve performance
req.Header.Set("Connection", "keep-alive")
resp, err := hwc.client.RoundTrip(req)
if err != nil {
return nil, errors.Wrap(err, "error proxying request to Hello World origin")
@ -186,12 +189,12 @@ func (hwc *HelloWorldService) Proxy(stream *h2mux.MuxedStream, req *http.Request
return resp, nil
}
func (hwc *HelloWorldService) OriginAddr() string {
return hwc.originAddr
func (hwc *HelloWorldService) URL() *url.URL {
return hwc.originURL
}
func (hwc *HelloWorldService) Summary() string {
return fmt.Sprintf("Hello World service listening on %s", hwc.originAddr)
return fmt.Sprintf("Hello World service listening on %s", hwc.originURL)
}
func (hwc *HelloWorldService) Shutdown() {

View File

@ -23,8 +23,8 @@ func IsLBProbeRequest(req *http.Request) bool {
return strings.HasPrefix(req.UserAgent(), lbProbeUserAgentPrefix)
}
func createRequest(stream *h2mux.MuxedStream, url string) (*http.Request, error) {
req, err := http.NewRequest(http.MethodGet, url, h2mux.MuxedStreamReader{MuxedStream: stream})
func createRequest(stream *h2mux.MuxedStream, url *url.URL) (*http.Request, error) {
req, err := http.NewRequest(http.MethodGet, url.String(), h2mux.MuxedStreamReader{MuxedStream: stream})
if err != nil {
return nil, errors.Wrap(err, "unexpected error from http.NewRequest")
}

View File

@ -138,7 +138,7 @@ func (s *StreamHandler) serveRequest(stream *h2mux.MuxedStream) error {
return fmt.Errorf("cannot map tunnel hostname %s to origin", tunnelHostname)
}
req, err := createRequest(stream, originService.OriginAddr())
req, err := createRequest(stream, originService.URL())
if err != nil {
s.writeErrorStatus(stream, statusBadRequest)
return errors.Wrap(err, "cannot create request")

View File

@ -6,7 +6,6 @@ import (
"net"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"sync"
"testing"
@ -46,16 +45,12 @@ func TestServeRequest(t *testing.T) {
message := []byte("Hello cloudflared")
httpServer := httptest.NewServer(&mockHTTPHandler{message})
url, err := url.Parse(httpServer.URL)
assert.NoError(t, err)
reverseProxyConfigs := []*pogs.ReverseProxyConfig{
{
TunnelHostname: testTunnelHostname,
Origin: &pogs.HTTPOriginConfig{
URL: &pogs.HTTPURL{
URL: url,
},
URLString: httpServer.URL,
},
},
}
@ -103,9 +98,7 @@ func TestServeBadRequest(t *testing.T) {
{
TunnelHostname: testTunnelHostname,
Origin: &pogs.HTTPOriginConfig{
URL: &pogs.HTTPURL{
URL: &url.URL{},
},
URLString: "",
},
},
}

View File

@ -3,6 +3,7 @@ package tunnelhostnamemapper
import (
"fmt"
"net/http"
"net/url"
"sync"
"testing"
@ -25,7 +26,9 @@ func TestTunnelHostnameMapperConcurrentAccess(t *testing.T) {
assert.Nil(t, os)
})
httpOS := originservice.NewHTTPService(http.DefaultTransport, "127.0.0.1:8080", false)
firstURL, err := url.Parse("https://127.0.0.1:8080")
assert.NoError(t, err)
httpOS := originservice.NewHTTPService(http.DefaultTransport, firstURL, false)
concurrentOps(t, func(i int) {
thm.Add(tunnelHostname(i), httpOS)
})
@ -36,7 +39,9 @@ func TestTunnelHostnameMapperConcurrentAccess(t *testing.T) {
assert.Equal(t, httpOS, os)
})
secondHTTPOS := originservice.NewHTTPService(http.DefaultTransport, "127.0.0.1:8090", true)
secondURL, err := url.Parse("https://127.0.0.1:8080")
assert.NoError(t, err)
secondHTTPOS := originservice.NewHTTPService(http.DefaultTransport, secondURL, true)
concurrentOps(t, func(i int) {
// Add should httpOS with secondHTTPOS
thm.Add(tunnelHostname(i), secondHTTPOS)

View File

@ -134,49 +134,18 @@ type OriginConfig interface {
}
type HTTPOriginConfig struct {
URL OriginAddr `capnp:"url"`
TCPKeepAlive time.Duration `capnp:"tcpKeepAlive"`
DialDualStack bool
TLSHandshakeTimeout time.Duration `capnp:"tlsHandshakeTimeout"`
TLSVerify bool `capnp:"tlsVerify"`
OriginCAPool string
OriginServerName string
MaxIdleConnections uint64
IdleConnectionTimeout time.Duration
ProxyConnectTimeout time.Duration
ExpectContinueTimeout time.Duration
ChunkedEncoding bool
}
type OriginAddr interface {
Addr() string
}
type HTTPURL struct {
URL *url.URL
}
func (ha *HTTPURL) Addr() string {
return ha.URL.String()
}
func (ha *HTTPURL) capnpHTTPURL() *CapnpHTTPURL {
return &CapnpHTTPURL{
URL: ha.URL.String(),
}
}
// URL for a HTTP origin, capnp doesn't have native support for URL, so represent it as string
type CapnpHTTPURL struct {
URL string `capnp:"url"`
}
type UnixPath struct {
Path string
}
func (up *UnixPath) Addr() string {
return up.Path
URLString string `capnp:"urlString"`
TCPKeepAlive time.Duration `capnp:"tcpKeepAlive"`
DialDualStack bool
TLSHandshakeTimeout time.Duration `capnp:"tlsHandshakeTimeout"`
TLSVerify bool `capnp:"tlsVerify"`
OriginCAPool string
OriginServerName string
MaxIdleConnections uint64
IdleConnectionTimeout time.Duration
ProxyConnectionTimeout time.Duration
ExpectContinueTimeout time.Duration
ChunkedEncoding bool
}
func (hc *HTTPOriginConfig) Service() (originservice.OriginService, error) {
@ -184,8 +153,9 @@ func (hc *HTTPOriginConfig) Service() (originservice.OriginService, error) {
if err != nil {
return nil, err
}
dialContext := (&net.Dialer{
Timeout: hc.ProxyConnectTimeout,
Timeout: hc.ProxyConnectionTimeout,
KeepAlive: hc.TCPKeepAlive,
DualStack: hc.DialDualStack,
}).DialContext
@ -202,18 +172,22 @@ func (hc *HTTPOriginConfig) Service() (originservice.OriginService, error) {
IdleConnTimeout: hc.IdleConnectionTimeout,
ExpectContinueTimeout: hc.ExpectContinueTimeout,
}
if unixPath, ok := hc.URL.(*UnixPath); ok {
url, err := url.Parse(hc.URLString)
if err != nil {
return nil, errors.Wrapf(err, "%s is not a valid URL", hc.URLString)
}
if url.Scheme == "unix" {
transport.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
return dialContext(ctx, "unix", unixPath.Addr())
return dialContext(ctx, "unix", url.Host)
}
}
return originservice.NewHTTPService(transport, hc.URL.Addr(), hc.ChunkedEncoding), nil
return originservice.NewHTTPService(transport, url, hc.ChunkedEncoding), nil
}
func (_ *HTTPOriginConfig) isOriginConfig() {}
type WebSocketOriginConfig struct {
URL string `capnp:"url"`
URLString string `capnp:"urlString"`
TLSVerify bool `capnp:"tlsVerify"`
OriginCAPool string
OriginServerName string
@ -229,7 +203,12 @@ func (wsc *WebSocketOriginConfig) Service() (originservice.OriginService, error)
ServerName: wsc.OriginServerName,
InsecureSkipVerify: wsc.TLSVerify,
}
return originservice.NewWebSocketService(tlsConfig, wsc.URL)
url, err := url.Parse(wsc.URLString)
if err != nil {
return nil, errors.Wrapf(err, "%s is not a valid URL", wsc.URLString)
}
return originservice.NewWebSocketService(tlsConfig, url)
}
func (_ *WebSocketOriginConfig) isOriginConfig() {}
@ -550,115 +529,12 @@ func UnmarshalReverseProxyConfig(s tunnelrpc.ReverseProxyConfig) (*ReverseProxyC
}
func MarshalHTTPOriginConfig(s tunnelrpc.HTTPOriginConfig, p *HTTPOriginConfig) error {
switch originAddr := p.URL.(type) {
case *HTTPURL:
ss, err := s.OriginAddr().NewHttp()
if err != nil {
return err
}
if err := MarshalHTTPURL(ss, originAddr); err != nil {
return err
}
case *UnixPath:
ss, err := s.OriginAddr().NewUnix()
if err != nil {
return err
}
if err := MarshalUnixPath(ss, originAddr); err != nil {
return err
}
default:
return fmt.Errorf("Unknown type for OriginAddr: %T", originAddr)
}
s.SetTcpKeepAlive(p.TCPKeepAlive.Nanoseconds())
s.SetDialDualStack(p.DialDualStack)
s.SetTlsHandshakeTimeout(p.TLSHandshakeTimeout.Nanoseconds())
s.SetTlsVerify(p.TLSVerify)
s.SetOriginCAPool(p.OriginCAPool)
s.SetOriginServerName(p.OriginServerName)
s.SetMaxIdleConnections(p.MaxIdleConnections)
s.SetIdleConnectionTimeout(p.IdleConnectionTimeout.Nanoseconds())
s.SetProxyConnectionTimeout(p.ProxyConnectTimeout.Nanoseconds())
s.SetExpectContinueTimeout(p.ExpectContinueTimeout.Nanoseconds())
s.SetChunkedEncoding(p.ChunkedEncoding)
return nil
return pogs.Insert(tunnelrpc.HTTPOriginConfig_TypeID, s.Struct, p)
}
func UnmarshalHTTPOriginConfig(s tunnelrpc.HTTPOriginConfig) (*HTTPOriginConfig, error) {
p := new(HTTPOriginConfig)
switch s.OriginAddr().Which() {
case tunnelrpc.HTTPOriginConfig_originAddr_Which_http:
ss, err := s.OriginAddr().Http()
if err != nil {
return nil, err
}
originAddr, err := UnmarshalCapnpHTTPURL(ss)
if err != nil {
return nil, err
}
p.URL = originAddr
case tunnelrpc.HTTPOriginConfig_originAddr_Which_unix:
ss, err := s.OriginAddr().Unix()
if err != nil {
return nil, err
}
originAddr, err := UnmarshalUnixPath(ss)
if err != nil {
return nil, err
}
p.URL = originAddr
default:
return nil, fmt.Errorf("Unknown type for OriginAddr: %T", s.OriginAddr().Which())
}
p.TCPKeepAlive = time.Duration(s.TcpKeepAlive())
p.DialDualStack = s.DialDualStack()
p.TLSHandshakeTimeout = time.Duration(s.TlsHandshakeTimeout())
p.TLSVerify = s.TlsVerify()
originCAPool, err := s.OriginCAPool()
if err != nil {
return nil, err
}
p.OriginCAPool = originCAPool
originServerName, err := s.OriginServerName()
if err != nil {
return nil, err
}
p.OriginServerName = originServerName
p.MaxIdleConnections = s.MaxIdleConnections()
p.IdleConnectionTimeout = time.Duration(s.IdleConnectionTimeout())
p.ProxyConnectTimeout = time.Duration(s.ProxyConnectionTimeout())
p.ExpectContinueTimeout = time.Duration(s.ExpectContinueTimeout())
p.ChunkedEncoding = s.ChunkedEncoding()
return p, nil
}
func MarshalHTTPURL(s tunnelrpc.CapnpHTTPURL, p *HTTPURL) error {
return pogs.Insert(tunnelrpc.CapnpHTTPURL_TypeID, s.Struct, p.capnpHTTPURL())
}
func UnmarshalCapnpHTTPURL(s tunnelrpc.CapnpHTTPURL) (*HTTPURL, error) {
p := new(CapnpHTTPURL)
err := pogs.Extract(p, tunnelrpc.CapnpHTTPURL_TypeID, s.Struct)
if err != nil {
return nil, err
}
url, err := url.Parse(p.URL)
if err != nil {
return nil, err
}
return &HTTPURL{
URL: url,
}, nil
}
func MarshalUnixPath(s tunnelrpc.UnixPath, p *UnixPath) error {
err := pogs.Insert(tunnelrpc.UnixPath_TypeID, s.Struct, p)
return err
}
func UnmarshalUnixPath(s tunnelrpc.UnixPath) (*UnixPath, error) {
p := new(UnixPath)
err := pogs.Extract(p, tunnelrpc.UnixPath_TypeID, s.Struct)
err := pogs.Extract(p, tunnelrpc.HTTPOriginConfig_TypeID, s.Struct)
return p, err
}

View File

@ -2,7 +2,6 @@ package pogs
import (
"fmt"
"net/url"
"reflect"
"testing"
"time"
@ -205,6 +204,24 @@ func TestWebSocketOriginConfig(t *testing.T) {
}
}
func TestOriginConfigInvalidURL(t *testing.T) {
invalidConfigs := []OriginConfig{
&HTTPOriginConfig{
// this url doesn't have a scheme
URLString: "127.0.0.1:36192",
},
&WebSocketOriginConfig{
URLString: "127.0.0.1:36192",
},
}
for _, config := range invalidConfigs {
service, err := config.Service()
assert.Error(t, err)
assert.Nil(t, service)
}
}
//////////////////////////////////////////////////////////////////////////////
// Functions to generate sample data for ease of testing
@ -260,23 +277,18 @@ func sampleReverseProxyConfig(overrides ...func(*ReverseProxyConfig)) *ReversePr
func sampleHTTPOriginConfig(overrides ...func(*HTTPOriginConfig)) *HTTPOriginConfig {
sample := &HTTPOriginConfig{
URL: &HTTPURL{
URL: &url.URL{
Scheme: "https",
Host: "example.com",
},
},
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,
ProxyConnectTimeout: 15 * time.Second,
ExpectContinueTimeout: 21 * time.Second,
ChunkedEncoding: true,
URLString: "https.example.com",
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 {
@ -287,20 +299,18 @@ func sampleHTTPOriginConfig(overrides ...func(*HTTPOriginConfig)) *HTTPOriginCon
func sampleHTTPOriginUnixPathConfig(overrides ...func(*HTTPOriginConfig)) *HTTPOriginConfig {
sample := &HTTPOriginConfig{
URL: &UnixPath{
Path: "/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,
ProxyConnectTimeout: 15 * time.Second,
ExpectContinueTimeout: 21 * time.Second,
ChunkedEncoding: true,
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 {
@ -311,7 +321,7 @@ func sampleHTTPOriginUnixPathConfig(overrides ...func(*HTTPOriginConfig)) *HTTPO
func sampleWebSocketOriginConfig(overrides ...func(*WebSocketOriginConfig)) *WebSocketOriginConfig {
sample := &WebSocketOriginConfig{
URL: "ssh://example.com",
URLString: "ssh://example.com",
TLSVerify: true,
OriginCAPool: "/etc/cert.pem",
OriginServerName: "secure.example.com",

View File

@ -147,7 +147,7 @@ struct WebSocketOriginConfig {
# cloudflared will start a websocket server that forwards data to this URI
# cloudflared CLI option: `url`
# cloudflared logic: https://github.com/cloudflare/cloudflared/blob/2019.3.2/cmd/cloudflared/tunnel/cmd.go#L304
url @0 :Text;
urlString @0 :Text;
# Whether cloudflared should verify TLS connections to the origin.
# negation of cloudflared CLI option: `no-tls-verify`
tlsVerify @1 :Bool;
@ -168,25 +168,22 @@ struct WebSocketOriginConfig {
struct HTTPOriginConfig {
# HTTP(S) URL of the origin service.
# cloudflared CLI option: `url`
originAddr :union {
http @0 :CapnpHTTPURL;
unix @1 :UnixPath;
}
urlString @0 :Text;
# the TCP keep-alive period (in ns) for an active network connection.
# Zero means keep-alives are not enabled.
# cloudflared CLI option: `proxy-tcp-keepalive`
tcpKeepAlive @2 :Int64;
tcpKeepAlive @1 :Int64;
# whether cloudflared should use a "happy eyeballs"-compliant procedure
# to connect to origins that resolve to both IPv4 and IPv6 addresses
# negation of cloudflared CLI option: `proxy-no-happy-eyeballs`
dialDualStack @3 :Bool;
dialDualStack @2 :Bool;
# maximum time (in ns) for cloudflared to wait for a TLS handshake
# with the origin. Zero means no timeout.
# cloudflared CLI option: `proxy-tls-timeout`
tlsHandshakeTimeout @4 :Int64;
tlsHandshakeTimeout @3 :Int64;
# Whether cloudflared should verify TLS connections to the origin.
# negation of cloudflared CLI option: `no-tls-verify`
tlsVerify @5 :Bool;
tlsVerify @4 :Bool;
# originCAPool specifies the root CA that cloudflared should use when
# verifying TLS connections to the origin.
# - if tlsVerify is false, originCAPool will be ignored.
@ -195,39 +192,29 @@ struct HTTPOriginConfig {
# - if tlsVerify is true and originCAPool is non-empty, cloudflared will
# treat it as the filepath to the root CA.
# cloudflared CLI option: `origin-ca-pool`
originCAPool @6 :Text;
originCAPool @5 :Text;
# Hostname to use when verifying TLS connections to the origin.
# cloudflared CLI option: `origin-server-name`
originServerName @7 :Text;
originServerName @6 :Text;
# maximum number of idle (keep-alive) connections for cloudflared to
# keep open with the origin. Zero means no limit.
# cloudflared CLI option: `proxy-keepalive-connections`
maxIdleConnections @8 :UInt64;
maxIdleConnections @7 :UInt64;
# maximum time (in ns) for an idle (keep-alive) connection to remain
# idle before closing itself. Zero means no timeout.
# cloudflared CLI option: `proxy-keepalive-timeout`
idleConnectionTimeout @9 :Int64;
idleConnectionTimeout @8 :Int64;
# maximum amount of time a dial will wait for a connect to complete.
proxyConnectionTimeout @10 :Int64;
proxyConnectionTimeout @9 :Int64;
# The amount of time to wait for origin's first response headers after fully
# writing the request headers if the request has an "Expect: 100-continue" header.
# Zero means no timeout and causes the body to be sent immediately, without
# waiting for the server to approve.
expectContinueTimeout @11 :Int64;
expectContinueTimeout @10 :Int64;
# Whether cloudflared should allow chunked transfer encoding to the
# origin. (This should be disabled for WSGI origins, for example.)
# negation of cloudflared CLI option: `no-chunked-encoding`
chunkedEncoding @12 :Bool;
}
# URL for a HTTP origin, capnp doesn't have native support for URL, so represent it as Text
struct CapnpHTTPURL {
url @0: Text;
}
# Path to a unix socket
struct UnixPath {
path @0: Text;
chunkedEncoding @11 :Bool;
}
# configuration for cloudflared to provide a DNS over HTTPS proxy server

View File

@ -1451,22 +1451,22 @@ func (s WebSocketOriginConfig) String() string {
return str
}
func (s WebSocketOriginConfig) Url() (string, error) {
func (s WebSocketOriginConfig) UrlString() (string, error) {
p, err := s.Struct.Ptr(0)
return p.Text(), err
}
func (s WebSocketOriginConfig) HasUrl() bool {
func (s WebSocketOriginConfig) HasUrlString() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s WebSocketOriginConfig) UrlBytes() ([]byte, error) {
func (s WebSocketOriginConfig) UrlStringBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return p.TextBytes(), err
}
func (s WebSocketOriginConfig) SetUrl(v string) error {
func (s WebSocketOriginConfig) SetUrlString(v string) error {
return s.Struct.SetText(0, v)
}
@ -1547,25 +1547,6 @@ func (p WebSocketOriginConfig_Promise) Struct() (WebSocketOriginConfig, error) {
}
type HTTPOriginConfig struct{ capnp.Struct }
type HTTPOriginConfig_originAddr HTTPOriginConfig
type HTTPOriginConfig_originAddr_Which uint16
const (
HTTPOriginConfig_originAddr_Which_http HTTPOriginConfig_originAddr_Which = 0
HTTPOriginConfig_originAddr_Which_unix HTTPOriginConfig_originAddr_Which = 1
)
func (w HTTPOriginConfig_originAddr_Which) String() string {
const s = "httpunix"
switch w {
case HTTPOriginConfig_originAddr_Which_http:
return s[0:4]
case HTTPOriginConfig_originAddr_Which_unix:
return s[4:8]
}
return "HTTPOriginConfig_originAddr_Which(" + strconv.FormatUint(uint64(w), 10) + ")"
}
// HTTPOriginConfig_TypeID is the unique identifier for the type HTTPOriginConfig.
const HTTPOriginConfig_TypeID = 0xe4a6a1bc139211b4
@ -1590,93 +1571,39 @@ func (s HTTPOriginConfig) String() string {
return str
}
func (s HTTPOriginConfig) OriginAddr() HTTPOriginConfig_originAddr {
return HTTPOriginConfig_originAddr(s)
}
func (s HTTPOriginConfig_originAddr) Which() HTTPOriginConfig_originAddr_Which {
return HTTPOriginConfig_originAddr_Which(s.Struct.Uint16(0))
}
func (s HTTPOriginConfig_originAddr) Http() (CapnpHTTPURL, error) {
if s.Struct.Uint16(0) != 0 {
panic("Which() != http")
}
func (s HTTPOriginConfig) UrlString() (string, error) {
p, err := s.Struct.Ptr(0)
return CapnpHTTPURL{Struct: p.Struct()}, err
return p.Text(), err
}
func (s HTTPOriginConfig_originAddr) HasHttp() bool {
if s.Struct.Uint16(0) != 0 {
return false
}
func (s HTTPOriginConfig) HasUrlString() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s HTTPOriginConfig_originAddr) SetHttp(v CapnpHTTPURL) error {
s.Struct.SetUint16(0, 0)
return s.Struct.SetPtr(0, v.Struct.ToPtr())
}
// NewHttp sets the http field to a newly
// allocated CapnpHTTPURL struct, preferring placement in s's segment.
func (s HTTPOriginConfig_originAddr) NewHttp() (CapnpHTTPURL, error) {
s.Struct.SetUint16(0, 0)
ss, err := NewCapnpHTTPURL(s.Struct.Segment())
if err != nil {
return CapnpHTTPURL{}, err
}
err = s.Struct.SetPtr(0, ss.Struct.ToPtr())
return ss, err
}
func (s HTTPOriginConfig_originAddr) Unix() (UnixPath, error) {
if s.Struct.Uint16(0) != 1 {
panic("Which() != unix")
}
func (s HTTPOriginConfig) UrlStringBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return UnixPath{Struct: p.Struct()}, err
return p.TextBytes(), err
}
func (s HTTPOriginConfig_originAddr) HasUnix() bool {
if s.Struct.Uint16(0) != 1 {
return false
}
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s HTTPOriginConfig_originAddr) SetUnix(v UnixPath) error {
s.Struct.SetUint16(0, 1)
return s.Struct.SetPtr(0, v.Struct.ToPtr())
}
// NewUnix sets the unix field to a newly
// allocated UnixPath struct, preferring placement in s's segment.
func (s HTTPOriginConfig_originAddr) NewUnix() (UnixPath, error) {
s.Struct.SetUint16(0, 1)
ss, err := NewUnixPath(s.Struct.Segment())
if err != nil {
return UnixPath{}, err
}
err = s.Struct.SetPtr(0, ss.Struct.ToPtr())
return ss, err
func (s HTTPOriginConfig) SetUrlString(v string) error {
return s.Struct.SetText(0, v)
}
func (s HTTPOriginConfig) TcpKeepAlive() int64 {
return int64(s.Struct.Uint64(8))
return int64(s.Struct.Uint64(0))
}
func (s HTTPOriginConfig) SetTcpKeepAlive(v int64) {
s.Struct.SetUint64(8, uint64(v))
s.Struct.SetUint64(0, uint64(v))
}
func (s HTTPOriginConfig) DialDualStack() bool {
return s.Struct.Bit(16)
return s.Struct.Bit(64)
}
func (s HTTPOriginConfig) SetDialDualStack(v bool) {
s.Struct.SetBit(16, v)
s.Struct.SetBit(64, v)
}
func (s HTTPOriginConfig) TlsHandshakeTimeout() int64 {
@ -1688,11 +1615,11 @@ func (s HTTPOriginConfig) SetTlsHandshakeTimeout(v int64) {
}
func (s HTTPOriginConfig) TlsVerify() bool {
return s.Struct.Bit(17)
return s.Struct.Bit(65)
}
func (s HTTPOriginConfig) SetTlsVerify(v bool) {
s.Struct.SetBit(17, v)
s.Struct.SetBit(65, v)
}
func (s HTTPOriginConfig) OriginCAPool() (string, error) {
@ -1766,11 +1693,11 @@ func (s HTTPOriginConfig) SetExpectContinueTimeout(v int64) {
}
func (s HTTPOriginConfig) ChunkedEncoding() bool {
return s.Struct.Bit(18)
return s.Struct.Bit(66)
}
func (s HTTPOriginConfig) SetChunkedEncoding(v bool) {
s.Struct.SetBit(18, v)
s.Struct.SetBit(66, v)
}
// HTTPOriginConfig_List is a list of HTTPOriginConfig.
@ -1801,166 +1728,6 @@ func (p HTTPOriginConfig_Promise) Struct() (HTTPOriginConfig, error) {
return HTTPOriginConfig{s}, err
}
func (p HTTPOriginConfig_Promise) OriginAddr() HTTPOriginConfig_originAddr_Promise {
return HTTPOriginConfig_originAddr_Promise{p.Pipeline}
}
// HTTPOriginConfig_originAddr_Promise is a wrapper for a HTTPOriginConfig_originAddr promised by a client call.
type HTTPOriginConfig_originAddr_Promise struct{ *capnp.Pipeline }
func (p HTTPOriginConfig_originAddr_Promise) Struct() (HTTPOriginConfig_originAddr, error) {
s, err := p.Pipeline.Struct()
return HTTPOriginConfig_originAddr{s}, err
}
func (p HTTPOriginConfig_originAddr_Promise) Http() CapnpHTTPURL_Promise {
return CapnpHTTPURL_Promise{Pipeline: p.Pipeline.GetPipeline(0)}
}
func (p HTTPOriginConfig_originAddr_Promise) Unix() UnixPath_Promise {
return UnixPath_Promise{Pipeline: p.Pipeline.GetPipeline(0)}
}
type CapnpHTTPURL struct{ capnp.Struct }
// CapnpHTTPURL_TypeID is the unique identifier for the type CapnpHTTPURL.
const CapnpHTTPURL_TypeID = 0xa160eb416f17c28e
func NewCapnpHTTPURL(s *capnp.Segment) (CapnpHTTPURL, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return CapnpHTTPURL{st}, err
}
func NewRootCapnpHTTPURL(s *capnp.Segment) (CapnpHTTPURL, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return CapnpHTTPURL{st}, err
}
func ReadRootCapnpHTTPURL(msg *capnp.Message) (CapnpHTTPURL, error) {
root, err := msg.RootPtr()
return CapnpHTTPURL{root.Struct()}, err
}
func (s CapnpHTTPURL) String() string {
str, _ := text.Marshal(0xa160eb416f17c28e, s.Struct)
return str
}
func (s CapnpHTTPURL) Url() (string, error) {
p, err := s.Struct.Ptr(0)
return p.Text(), err
}
func (s CapnpHTTPURL) HasUrl() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s CapnpHTTPURL) UrlBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return p.TextBytes(), err
}
func (s CapnpHTTPURL) SetUrl(v string) error {
return s.Struct.SetText(0, v)
}
// CapnpHTTPURL_List is a list of CapnpHTTPURL.
type CapnpHTTPURL_List struct{ capnp.List }
// NewCapnpHTTPURL creates a new list of CapnpHTTPURL.
func NewCapnpHTTPURL_List(s *capnp.Segment, sz int32) (CapnpHTTPURL_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
return CapnpHTTPURL_List{l}, err
}
func (s CapnpHTTPURL_List) At(i int) CapnpHTTPURL { return CapnpHTTPURL{s.List.Struct(i)} }
func (s CapnpHTTPURL_List) Set(i int, v CapnpHTTPURL) error { return s.List.SetStruct(i, v.Struct) }
func (s CapnpHTTPURL_List) String() string {
str, _ := text.MarshalList(0xa160eb416f17c28e, s.List)
return str
}
// CapnpHTTPURL_Promise is a wrapper for a CapnpHTTPURL promised by a client call.
type CapnpHTTPURL_Promise struct{ *capnp.Pipeline }
func (p CapnpHTTPURL_Promise) Struct() (CapnpHTTPURL, error) {
s, err := p.Pipeline.Struct()
return CapnpHTTPURL{s}, err
}
type UnixPath struct{ capnp.Struct }
// UnixPath_TypeID is the unique identifier for the type UnixPath.
const UnixPath_TypeID = 0xf7e406af6bd5236c
func NewUnixPath(s *capnp.Segment) (UnixPath, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return UnixPath{st}, err
}
func NewRootUnixPath(s *capnp.Segment) (UnixPath, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1})
return UnixPath{st}, err
}
func ReadRootUnixPath(msg *capnp.Message) (UnixPath, error) {
root, err := msg.RootPtr()
return UnixPath{root.Struct()}, err
}
func (s UnixPath) String() string {
str, _ := text.Marshal(0xf7e406af6bd5236c, s.Struct)
return str
}
func (s UnixPath) Path() (string, error) {
p, err := s.Struct.Ptr(0)
return p.Text(), err
}
func (s UnixPath) HasPath() bool {
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s UnixPath) PathBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return p.TextBytes(), err
}
func (s UnixPath) SetPath(v string) error {
return s.Struct.SetText(0, v)
}
// UnixPath_List is a list of UnixPath.
type UnixPath_List struct{ capnp.List }
// NewUnixPath creates a new list of UnixPath.
func NewUnixPath_List(s *capnp.Segment, sz int32) (UnixPath_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 1}, sz)
return UnixPath_List{l}, err
}
func (s UnixPath_List) At(i int) UnixPath { return UnixPath{s.List.Struct(i)} }
func (s UnixPath_List) Set(i int, v UnixPath) error { return s.List.SetStruct(i, v.Struct) }
func (s UnixPath_List) String() string {
str, _ := text.MarshalList(0xf7e406af6bd5236c, s.List)
return str
}
// UnixPath_Promise is a wrapper for a UnixPath promised by a client call.
type UnixPath_Promise struct{ *capnp.Pipeline }
func (p UnixPath_Promise) Struct() (UnixPath, error) {
s, err := p.Pipeline.Struct()
return UnixPath{s}, err
}
type DoHProxyConfig struct{ capnp.Struct }
// DoHProxyConfig_TypeID is the unique identifier for the type DoHProxyConfig.
@ -3742,229 +3509,218 @@ func (p ClientService_useConfiguration_Results_Promise) Result() UseConfiguratio
return UseConfigurationResult_Promise{Pipeline: p.Pipeline.GetPipeline(0)}
}
const schema_db8274f9144abc7e = "x\xda\xacY{p\\\xe5u?\xe7\xde]]\xc9\x96" +
"\xbc{\xb9K\x1d\xc9\xd6l\xeb\x92I0\x98\xe2(\xb4" +
"\xa06Y\xadd9Z\xc7\x8f\xbdz\x180f\xc6\xd7" +
"\xbb\x9f\xa4k\xef\xde\xbb\xbe\x0f[rMl\\(\xa0" +
"\x1a0\x04\xcd\x80CR\xdb\xad\x0b\xa1P0!\xd3\x09" +
"%\x994}\x904\xd3!\x99\x86Ni\x93?\x1a\xf0" +
"t\x86\x96\xa1&x\x18:\x98\xdb9\xdf}j\xb5\xc8" +
"v\xa7\xfe\xc3\xda9\xfb=\xce\xf7;\xe7\xfc\xceco" +
"\xccv\x0c\x08\xeb\xd3\xafv\x01\xa8'\xd3m\xde\xef\xd5" +
"_;\xfd\xdb\xf3?\xbe\x07\xe4\x1e\xc1\xfb\xca+\x9br" +
"\x1f:G\xff\x0d\x00\xfb~\xd4v\x10\x95_\xb4I\x00" +
"\xca\x1bm\xdb\x00\xbd\x7f\xba\xf1\xd0[\xbb~\xf5\xc8\xfd" +
" \xf7`\xbc2%\x01\xf4\x9do\x9bC\xa5C\x92@" +
"\xf4\xbe~G\xee\x1f\xf0\xe4\x07\x8f\x80\xfcY\x04H#" +
"}}\xaem\x99\x00\xa8\\l+\x00z\xaf]\xff\xca" +
"\xcb\xc7\xbfu\xdf\xd7@\xfd\x0c\"\xf8\xfb{\xa5\xffA" +
"@e\xbdD\x0b\xce\xff\xe9u\xa9\xe7^\xbb\xea\x1b|" +
"\x81w\xe6\xa7\xb7\xbex\xfc[\xbf\xfe6L\x08\x12\xa6" +
"\x00\xfan\x97,Z\xcb\xa4\xff\x00\xf4\x1e\xfa\xc1J\xb3" +
"\xf8\x9f\xbbN-\xd4\xc9\xbfu\xb8\xbd\x1f\x95\x89vz" +
"\x80\xdaN\x07?\xf6/\xdf\xddZ\x7f\xe4\xc4i\x90?" +
"\x13^\xbc\xaf]\x10 \xe5\xdd\xf4\xaf\xe7\xb6myq" +
"\xf2)\xff\x1b\x7f;k\x7f\x91\xeeq\xf9\xd6\x1f\x1e\xc8" +
"\x1e+\xfe\xce\xc3O\x81\xda\x83\xc9\x8b\xf8!O\xb4\xcf" +
"\xa1r\x96.\xea{\xae=\x8f\x80\xde\xdc-\xdf\xdd\xfe" +
"\xab?\xb4\x9f\x01u\x1d\xa6\xbc\xbf}\xe0\xcd\xfd\xd7~" +
"s\xf2U\xfe\x04\x91\xf0\xe88MG_\xe8x\x1e\xd0" +
"\xeb\xfa\xab\xb5[\x1f~k\xf3Y:Zh~\xc3\xfc" +
"\xb2~T\xce,\xa37\x9cZF\xab\x7fr\xfd\xf6\xef" +
"}\xef\x85\xa9\xb3\xcd\x8a\x08\xb4\xba\xb8|\x13*\x13\xcb" +
"\xf9\x8b\x97\xd3\xea\xabK\xf8\xf3\xef\xafO\xfde\xf0." +
"\x91\x16\xa5;\xdf\xa6\xcb\xbb;i\xc1\x1d\x1f}\xfb\x07" +
"\xc3\xef\xfe\xec;Ik}\xa7S k\xfdc'=" +
"\xbc\xf7\x9d\xc1.\xe3\xdd\xa3\xdfo\x02\x98\x9ft\xa1s" +
"\x13*\x1d]t]\xba\xeby\xc0\x0f\x9e\xb9\xefx\xe9" +
"\xcd\x0d\xaf\xaa=\x98j~\xc8\xa9\xae\x83\xa8|\x9b\xd6" +
"\xf6\x9d\xed\xe2\x18E\xa84-\xe7/\xf9\xf7\x15{P" +
"\xb9\xb0\x82\xfb\xd6\x0a\xbe|\xd3\x1d_}4}\xee\xab" +
"\xaf6\xc3$\xd1\x9a\x0f3\x16*]Y\xfa\xd8\x91}" +
"J\x00\xf4z^\xf8\xdd\xbf\x18\xac\xbe\xf1\xe3&\xbd\xe9" +
"p\xe5\xc2U\xef)\xa8\xd0\xa7\x8bW\x1d\x00\xf4\xee\xbb" +
"n\xf6\xe0\xd6O\xcf\xbd\xde\x8c)W\xfcve\x0e\x95" +
"}|u]\xa1\xd5\xc29\xad\xfb\xc8?\x7f\xf1\xe7\x09" +
"/\xfa\x85\xf2K\x84\x94\xb7u\xfb\x1d{:\xeez\xf3" +
"\xcd\xa4\x17\xfdT\xe1h\x9fS\x08\xcc\x97\xe4G\x95W" +
"N\xfd\xd9[t\x91\xd4\x8cf:\xb7\x03\x95\xee\x1c}" +
"\xbc:\xc7\xdf\x10\xb9~+[_\xf8\xb5~T\xd2+" +
"I/\\Iz\xdd\xb4\xab\xc8v\xde|\xdb\xdb \xf7" +
"\x88\x0b\x02\xb9\xb8\xb2\x1f\x15\x95V\xf6mY)\xa1r" +
"\x91>z\x0fM\xed\xf8\xd1\xf9\xa1S\xff\xdd\xd2\xa3\xcf" +
"\xd1\x96\x0b|\xcb\xf9\x95\x1c\xfe\xbe\xf5\x7f\xf4\xce\xfc\x9f" +
"\x0c\x9d_t\xfa\x17\xba\x07Q\xd9\xd2Mz\x94\xba\xbf" +
"\xa4\xccv\xf3\xc3\xbf\xb2a\xdb-k\xfe\xfa\xbd$\x12" +
"Z\xf7{<\x9e\xba\x09\x89\xc9\x9b\xff\xebK\x9f~\xe8" +
"\xef\xdfk\x15\xb7\xf3\xddkQ9\xc3O<E\x8b\xdf" +
"\xdd\xf8\x8d\x9f\xf5dz\xdeo\xa5\xe8\xdfu\xefA\xe5" +
"\x0dZ\xdb\xf7z7W\xb4\xf6\x9b\xaf\xef}\xbe\xed\xad" +
"\x0fZ\x9d\x9c^\xd5\x83\xca\xd5\xab\xe8dy\x15\xa9q" +
"\xdb/O\x1c(|\xed\xfd\x0f\x08\x04\xb1\x89\xd3\xd6\xaf" +
"\xda\x81\xca0_\\\\E\xb1\xb2\xf9\xd97\xbe8=" +
"\xff\xc3\x0f\x9b\x11\xe3\xd6{g\xd5QTp5w\xaa" +
"U\xc4L\xbf\xb1\xfd\xcf\x7f\xffo\xfe\xe0\x8f?\x02\xf5" +
":\x94b\xcbO\x88\x12\x0a\xe4\xe0\xab9\xbb\x9c_M" +
"\xa6;\xf4\xee\x13#\x0f\xef|\xf6\xe3$\\[z_" +
"\xa6\x05w\xf6\x92\x9e{\xe6\x0f9#\x8f?\xe8\xb5\xf0" +
"\xe6\xbe\xbbz\x07Qy\xb0\x97n~\xa0\xf7\x00\xac\xf3" +
"\x1c\xd70X\xcdj\xa4*\xbf\x15~\xac\xdcP\xd1\x1a" +
"F\xa3\x7fxF\xb7\x1d\xdd\x98\x1a\xe7\xf2B\xd9\xac\xe9" +
"\x95\xd92\xa2\xdaIJ\xc9\xbd\xfd\x00\x88\xf2\xd5;\x00" +
"P\x90\xe5A\x80\x82>e\x98\x16\xf3\xaa\xba]1\x0d" +
"\x83\x81Xq\x0e\xef\xd6j\x9aQa\xd1E\xe9\xc5\x17" +
"\x8d\xb0Z\xcd\xbc\xd5\xb4j\xd5m\x96>\xa5\x1bC\xa6" +
"1\xa9O\x01\x94\x11\xa3m\xd2\xe2mC5\x9d\x19\xce" +
"\x18\xb3\xf6\xeb\x15v\x83k3\x7f\x9fki\x8en\x1a" +
"\xd7\x8c2\xdb\xad96\x80\x9a\x12S\x00)\x04\x90\xbb" +
"\xfa\x01\xd4v\x11\xd5\x9c\x80\x05\x8b/\xc0l\x1c\xd2\x80" +
"\x98\x85\xf8\xce\xb6\xc5w\xfaX\xd0\x9d\xcc\xba\xc15," +
"6\xa5\xdb\x0e\xb3|\xf15\x85\xb2fiu;y\xe1" +
"\x09\x005+\xa2\xbaZ@o\xca\xd2*\xac\xcc,\xd4" +
"\xcd\xeaV\xcd0\xc7DV\xc14\x08\x98N\\\xda\xc2" +
"\x10\x1b5\xbd\xc6\xaa\xfe\xebn\xa8\xe4\xf9_5+\xa6" +
":=\x8f_\xa2\xed\x00Pw\x89\xa8\xd6\x04\xec\xc2\x8f" +
"\xbd\x1c\xa5JY?\x08\xa0N\x8b\xa8:\x02v\x09\x17" +
"\xbd\x1c\xb7\xda\xbe5\x00jMDuF\xc0.\xf1#" +
"/G9Fv\xf7\x00\xa8\x8e\x88\xea\x11\x01=\xdbm" +
"\x10\xa66\x88\xa6\x85\xd9\xd8\xed\x03tXu\x8a\x906" +
"\xa0\xc0*\x044fC*\xf7\x17HUs\x1a\xb3q" +
"\xee\x09\xb6Yl?\xb3lV\x86\x8ce\xce\xccb6" +
"\xa6\xf4&\xd4\xc5\x16\x96\xa6\xffG\x0a\xe3\xe3\xe5\x89\xd1" +
"\xcd\xe4\x81\x09\x80\xd7\xc4\x16\x95\\\xab\x86\x9d `g" +
"\xe2\xb8\xae+5b\xe87\xd1\xae\xa5\xf7sO\xaf8" +
"\xd7\x94\xf3\x8blOf\xe9\x14Q\xfd\x94\x80^\x83\xbe" +
"e\x0e\x03\xd1\xb21\x1b\x97\x08M\x8fO\x7f\xc2\xe3\x87" +
"\xfc[\xca\xc1)\x96\xcd\xa3C\xcdE\x97\xddE\x97\x1d" +
"\x12Q\xbd_@\x19\xd1w\x81{-\x00\xf5\x1e\x11\xd5" +
"\xe3\x02\xa2\xe0;\xc0\x83\xa7\x01\xd4\xe3\"\xaaO\x0a(" +
"\x8b\x82o\xff'\xd6\x02\xa8\x8f\x89\xa8\xbe \xa0\x9c\x12" +
"sT;\xc9\xcf\x91\xef\xbe \xa2\xfa\x8a\x80\x9e\xe9G" +
"&\xe9\xef`\x17\x08\xd8\x05\xe8Uj\xa6[\x9d\xaci" +
"\x90\xb7X\xb5\xb4!\x92\x1bn\xbdl\xb1\xfd:\x9a\xae" +
"]t\x1cV\x97\x1a\x8e\x8dm `\x1b`\xc6\xd1\xa6" +
"l\\\x01X\x16\x11\xb3q\xee\x05$at&Z\xac" +
"\xba\x9dY\xb6.\x9a\xc6\"\xa3\xb6\x80i4\xf0/\xf2" +
"\xae TLK\x97\xa6tC\xed\x14S\xab=/\xc0" +
"d\x98\x9e: \xa2\xbaY\xc0^\xfc\x98\xc4\x04Ki" +
"\x14@\x1d\x11Q\x1d\x17\xb0W\xb8Hb\x02F%X" +
"\xcb\"\xaa;\x05\xccL;N\x03\xb31=\x07\xb6;" +
"\xc0v\xdbfe/\x03$2\x89\x88?\xf8v: " +
"7\x10kU\xcc\xc6u\xf1ex=\xb7y\xc1\x19\xb6" +
",\xd3\xe2\xbc\x1bY{\xf8s\xf1#Bc\x97v\xc4" +
"/\x90\x85\x01\xffY\xea\xeeX\xff|Esm\x16a" +
"i1\xc7\x9a-N: 2+b!{\xdatk" +
"\xd5Q\x06\x92c\xcd\"\x82\x80\xb847m0G\x12" +
"\x90\xfb^\x99\xd0\x93t\xda \xa2Z\x8e\xf5\xdcB\xb2" +
"\xcd\"\xaa\xb7\x91\x9e\x01\xfc\x13\x04\xff\xb8\x88jC@" +
"\xafF\xe1h\x8c\x98 \xdaN\xa4\xae/,\x9b\xdc\x01" +
"%\x10P\x02\xf4\xdc\x86\xedXL\xab\x03F\x1eE\xeb" +
"W\\\x01\x897E\x7fY\xcb\xf00n\xfd\x86(\xb2" +
"\xb6lJ>\"\x08\xad\x89\xc1\x18\xec\xd6\x013m\xda" +
"\x8e\xa1\xd5\x19\x00\x84\x0f;l6\x88E\x89\x14\xa2\xaa" +
"\xb5\xc97\xae<\xf7\xf9yhA\xe6;\x9dHD\x95" +
"`7\xf2\xedC\xa6!M\xeaS\x98\x8d\xcb\xbc&\x05" +
"Z\xd8\xbd\xe8:\xd3\xccp\xf4\x0a\xbfp\x91\xdd\xd7\xc4" +
"\xfe\x19aV\xfa\\\x02\xc8\x10\xb3-\xbbc \xa5\xbd" +
"l6\x84%\xcf\xea\x9a\x1e\xb3y\x80f\x11\xa4/\xc7" +
"k\x96,^\x82,\xe5\xe7\xa8\x82\x0fO\x13e\xce\x01" +
"\xa8GDT\x8f%\x94|\xe0Q\x00\xf5\x98\x88\xea\xe3" +
"\x09%\xe7\x07\x93\x9c)\x06\x9cI\x88>)\xa2\xfa\xb4" +
"\x80\x98\xf2)\xf3\x0cQ\xe6\xd3\"\xaa/\x09\x9c\x05G" +
"\x8aC\xa6\x81\x81\x126@\xc8\x81\xde4\xd3,g7" +
"\xd3\xd0)\x19\x0e\xb3\xf6kX\x0bc\xf0\xb0\xa3\xd7\x99" +
"\xe9:QL\xd6\xb5\x19^\x01`u\xc4\xdf%i\x8e" +
"\x8d\x1d `\x07\x85\x80\xcd\xac!\x8bU\x91\xac\xa1\xd5" +
"\xca\x9a\xe8L_\x0e@\x0b\xf92\xd3\x02\x9e\x83qF" +
"\xa1\x7fq\x9f*\xdf\xdb\x0f\x02\x0f]zs}0\xae" +
"3xBIS\x99\xf1h\\P\xf0\x84\xd2F'\x9e" +
"\x88\x01\x0fT\x1b1\xa1\xe0\x87D\xa8s\xc17\xf5a" +
"\xa2'\x9d\xc5\xef\x0c\xf2\xac\x8e\xa61\xce\x01\xc2\x18\xa1" +
"\x8aYoX\xcc\xb6Q7\x0d\xd5\xd5j\xba\xe8\xccF" +
"\x1b\x97\xc4\x80b\xdf\x8f\x99m\x8d<7\x12\x81pc" +
"\x08\x82R\xc4M\x00c\x03(\xe2\xd8f\x8c\xddD)" +
"\xe1 \xc0\xd8\x06\x92\x971\xf6\x14e\x0b\xf6\x00\x8c\x8d" +
"\x90|\x1c\x05D\xdfW\x14\x15\x9f\x01\x18\x1b'\xf1." +
"\x8cS\xacr'?~'\xc9\xa7I\x9eNq\xf8\x14" +
"\x86k\x01\xc6v\x91\xfc\x10\xc9\xdb\x04\x8e\xa02\x8b{" +
"\x00\xc6fH~\x0f\xc9\xa5t\x8e\xea\x7f\xe5n\xb4\x00" +
"\xc6\x8e\x90\xfc\x18\xc9\xdb?\x95\xc3v\xaa\xf1\xb9\xfc~" +
"\x92?F\xf2\x8e\xee\x1cv\x00(\x8f\xe0Q\x80\xb1\xe3" +
"$\x7f\x92\xe4\xcb0\x87\xcb\x00\x94'\xf0\x04\xc0\xd8\x93" +
"$\x7f\x9a\xe4\xcb\xdbr\xb8\x1c@9\xc3\xf59I\xf2" +
"g1\"\x90R5\xc9c\xe4Nz\x9c\xabE\xd3\x8e" +
"\xdc\x90\x05\x9d\x04\xfa$[63\xd4J`&\x9e'" +
"\x01b\x06\xd0k\x98fm\xebB~\xbcT\xb9\x10\xb8" +
"\x05dL\xa3T\x8d\xe2\xcbw\xa2\xcd&\xe4+Z\xad" +
"\xd4\x884\xd1\xed\xa2\xeb\x98n\x03\xf2U\xcda\xd5(" +
"\xc3Y\xae\xb1\xd12\xeb\xe3\xc8\xac\xbanh5\x88\xbe" +
"Y\xca\xb72\xae\xabW\x17\x05\x9b\xd0\xech\xf9F\xff" +
"\xb8\xc6\xa3\xab=\x8a\xaek\xa9\x0c\xb9FD\xf5\xc6\x04" +
"\xf9\xac#\x86\xfc\xac\x88\xea\xe7\x05\xcc$\x83\"\xbf_" +
"\xab\xb9\xecr\xca\xa0\x89\xa6T\xe0W\xb3>?'n" +
"\x1f\x8co\x8f.\xa7b\xf1z\x11\xd5\x11\x01\x0f\xdbn" +
"\xa5B\x8f\x0eQ\x98\x0cZ\x10\xc8\xd3\xd9\x09{Dc" +
"\x87\xc0\x1e\x97\x9bv\xa7\x98\xe3\x7f*\x19\x93&\xe5+" +
"I\xab\xdb\xff\xc7\xdd\xa3\xcc\xceP\xc9~\xc9F/\x1a" +
"$\\:\xbf\x8d\x8c\x8f\x97\xe3nT\xf4\xc9\x91\xf3\x02" +
"&\xdau\xa5\x88;@\xe0\xf6\xa3\xe8_\xc7\xc3\xf3z" +
"\x0a\x93\x9b9+d\xfd\xf0\xbf\x89\x87\xe1\xe7I>\x80" +
"\x01KR\xf8\x7f\x01O/`\x97\x94\xec\x87\x7f\x09G" +
"\x93,\"\xa7\xd1\x0f\x7f\x95\x9f_&\xf9\xce\x90\x16(" +
"\xfco\xc7\xb9\x054\"\x89~\xf83\x1e\xce\xd3$w" +
"8-\xa4\xfc\xf0\xdf\x87/\x02\x8c9$?\xc2i!" +
"\xed\x87\xff]\xf8\xf2\x02\x1aY\x16\x84\xff\x03|\xfd1" +
"\x92?\xcei\xe1\xaa\x1cv\x02(\xf3\x9cF\x1e#\xf9" +
"I\x8cj\x9eb\x15\xc4\xaa\xe59\x95\xc6\x97\x19k\x14" +
"!S\xd3\xf7\xb3\x88\xab\xab\xbaV\xdb\xe0j5\xc8\x8f" +
"9Zeo\\c\xd6\xec\x11\xcd\xa8\xda8\xad\xede" +
"\xc4\xf0R2\x07:5{;\xb3\xf4I\xc0\xb8*\x8d" +
"j\x82L\xd94\x9bK\x05^\xdc0\xcb'\x93\xe8\xbb" +
"\xba6S\xaa\xd6\xd8\x10\x86\x95\x81h\xc4\x19F\xa7o" +
"L\xc3@?]\x8f\xeb\xf9\x85y\xb8\x11\xd4\xb9a>" +
"\x1f/4%j6\xd3`\x15g\xc8D\xc3\xd1\x0d\x97" +
"-:\xa02\xed\x1a{Yu\x18\x8d\x8aY\xd5\x8d)" +
"XT`\x8b\x9f\xd4\xfc'\x0a\x98\xf6\xc0\x09\xa3\xc9\xb7" +
"|m\x7f\xe0\x83\x94\x8e\xe5\xfe\xb8\xeb,T\xf8\xae\x82" +
"\xc54\xbbE\x17%~R\x94\x15\xfc\xe0\xa2\xdb\xb2b" +
"\x1a \x1a\x0dc8\xab\x93\xf7\x1d\x04A\xd6%\x8cG" +
"\x9c\x18N4\xe5;-\x10\xe4\x09\x09\x85h|\x8f\xe1" +
"4].\xcd\x81 \x0fK(Fct\x0c\x07Z\xf2" +
"-\x83 \xc8\xeb$/,\xc9\xa1\xe0\xab3\x80^\x18" +
"\xf0\x90\xe7!?\x80^\xd8\xb7cX\xba\x03\x0c\xe0\xe1" +
" \x1d\x0c`rv$~R\xfd\xdc\xba,$n\x9c" +
"\x11Q\xbd'\xe6\xc6\xbb\xe7\xe2F:\xeaY\x1e|\xa6" +
"U'}\x14@}\xdc\xaf\x00\xa3N\xfa,\x95\x8a/" +
"\x89\xa8\xfeD\x88\xf3d\xe8v\xe1\xb8\x05M+l\xa2" +
"\x96\x98\xba\x04\xce\x19Tl\xcd\xb3\x17\xafjN\xf3\x8a" +
"\x0e\xfd\xa3l\x88\x99:9\x90Y\x91\x18\xc8`\xd8\xbe" +
"I\x0b\x88=9\x9eY\xb14W.hF\xc0\x9f\xcf" +
"\x90\xd7\x84\xbf\x17`\xf83\x8f,\x93\xf5\xbb$/l" +
"X0LSd\xbc\xa4\xc9\xae\xb0k\x1bey\xfbr" +
"2@8\x1d\xbet\xf3\xed\xdf\x93!gk\x1a8\xed" +
"ILujf\xd0\xffd\xb6&\xb2\xf5RX\xf9\x0a" +
"\x87\x85g\x8667\xb9\xdf\x9a\xd8\xfd\xa2\xc2\xe0\xee5" +
"\x89\xe9N\xd8\x95\xdc\xbb)p\xca\x93Q\xa1)\x7f\x9d" +
"\x1c\xf5\xa4\x88\xea\xb3\x09\xf7\xfb\xe6\xa6\xb8+\x91\x98e" +
"\x85z.\x98\x97\xd5\xcc\xa9\xcd\xba\xc1l*\xbd\x9aZ" +
"\xe9\x06\xb3\xea\x9a\xc1\x0ct\x88\x8c\\\x8b\x18u!s" +
"\x956$*\xb6\xa5`\x9d0\xf4\x19\xde\xa24\x81\xba" +
"66V\xa6\xa1]^\x073\x16\x04\x8e\x1f7A\x8a" +
"N\xf4\xa0\xa7\x13\xf3\x90\x10H\xf5\xe5`\xce\xb0+\x01" +
"\xe4\x9d\xd4\x83\xee\x14Q\x9d\x16\xd0\xd3\\\xc7\x9chT" +
"5t\xd8F\x8b\xeds\x99dTf\xe3^\x8c\xba\x92" +
"\x8a=\x81\x0d\xaa\x1f7Z\xac\xb0\xcfe\xc9\x05\xe1\x8c" +
"\x17$\xdd\xac.\x1a\xee\xb6(\xd8ne\xbb\xc7\xcc\xca" +
"^\xe6,\x98}\xfb\xd4\x1b>E[\x13+\x18\xbe\x84" +
"\x8d\x02\xa8U\x7fb\x12QR}O<\xdd\x8d(\xc9" +
"\x9d\x8b=j\xe1\x88\xf4\xff'\xa9.5\xd9_PE" +
"\xf9#\xb9)=o\x14\xabU\x8b\x12Y8\xc1NV" +
"\xc3\xf1\x04{\xdd\xdaD9\x1c\x0c\xdf\xa2\xdfp\xfd\x10" +
"\xce\xb8\x86>\x83\xd9\xf8\x87\x9cK\xcfS[NoG" +
"\x0b\xec\xb2\x08$\xfeq\xe5\xd2%d0~\x08*\xf0" +
"\xa6\x02|M\xab\xf2\x7fGP\x81\xdf\x1c\xc4i6\xfe" +
"\xbd7\xb8\xce\x0e\xaa^\x10'\xcd\xc5\x05\xed\xff\x06\x00" +
"\x00\xff\xff\xb0\x8e\x80\xdd"
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<KW\x8ft~\x1b0\xe8\xfe\x8b\x9b\xb7>\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<H\x98\x07,xz\xdd\xc5e\x80e\x86\xd8" +
"\x93\xd64@\"&w\xa2\xc3k\xdb\xb9\xe3\x1a\xcc\xb6" +
"\xb0\x0b$\xecZ\xdcL\xe3Q@P8D\xb1m;" +
"\x86\\7,\xad\x8b\xe5V\x05Ad\x93\x11Ru\x03" +
"Cm\xb3\x84\xab\xf1\x13\"\x93YJ\xe3\x00\xda(C" +
"mB\xc2\xd5\xd2\xc7D&\xc3hd\xd62Cm\xa7" +
"\x84\x85i\xcfkbOZ\xf0\"\xdf\x1d\xe4{\\\xbb" +
"\xba\x8f\x03R\xf6'\xe8\x1b\xfd:\x1d\xa1\x110\xb3\x86" +
"=i\x0b\xd9\xe2x\xd6\xc6\xf1\xc2\xe7Eo\xc4ql" +
"G\x00e\xe2\xed\x91/\xa4J\xc4\xce.\xedH5P" +
"\xa4\x0d\xa1Z\xda\x9eT\xfe\xfe\xaa\xee\xbb<\xb1\xa5\xc3" +
"=gvp\xca\x03\xc6\x9d\x046\xdci\xdb7k\xe3" +
"\x1cd\xcf\x99E\x04\x09qq0\xd9h\x8ffL\x1e" +
"FeFN\x92i#C\xad\x9c\xca\xb9\x85h\x9b\x19" +
"jw\x93\x9c\x91\xf9'\xc9\xfc\x13\x0c\xb5\xa6\x84\x81I" +
"\xe9h\x8d\xda\xc0\\/\x117$\x96m\x11\x802H" +
"(\x03\x06~\xd3\xf5\x1c\xae7\x00\x93\x88\"\xfeeW" +
"\x81\xba-\xd9_\xd6\x0b\"\x8d\xdb\xeb\x90d\xd6\x96\xb1" +
"\xac\x12QjM\x0e\xa5\xc6n\x9f0\xd3\xb6\xebYz" +
"\x83\x03@\xac\xd8\x11\xbbI\xb0G\xa0\x90t\x83-\xb1" +
"q\xf5\xc5*,\x1c\xf3J\xd5\xd9L\xe5\xa8F\xa7Q" +
"\x1c\x1f\xb6-y\xca\xa8cO\xda>\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<O\x11\xfd\x05" +
"L\x00\xa4T\xcb\xe2\x18\x85\x93\x91\xd6jf\xbbI\x18" +
"\xf2\xa8\xf5\xc7\x10d\xcbv\x81z\x7f,\xa4\xab\x17@" +
",\x00\x06M\xdb6\xb7\xce\xc7\xc7\xcb\xb5\x0bQX@" +
"\xc1\xb6J\xb5$\xbf\xc2 \xdalC\x7fU7K\xcd" +
"D\x12\xc3\x1d\xf4=\xdboB\x7fM\xf7x-\xa9p" +
"\x8eomr\xec\xc6\x04r\xa7aX\xba\x09\xc9/\x8b" +
"\xc5V\xc1\xf7\x8d\xda\x82d\x93Z\x03\xad\xbf90\xa1" +
"\x8b\xecZ\x92d\xd7M\xd4\x86\xdc\xc0P\xbb-\x03>" +
"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</\xff;;B\\8\x8d\xaf" +
"\xcf\xcb\xff\xa5\xf9\x10\x17\xce\x09\xfeg\x89\xfe\x8a\xc0\x85" +
"\xa1\x10\x17^\x128r\x9e\xe8\x17\x08\x17|\xc7\xacx" +
"\x8ea\x01\xd6\xd3`\xad6\xbf\xccys\x10\x0a\xa6q" +
"\x80'\x98]3ts\xa3\xaf\x9b\xd0_\xf1\xf4\xea\xbe" +
"\xb4\xd74\xddQ\xdd\xaa\xb98\xad\xef\xe3\x84\xf4r\xb6" +
"\x16z\xa6\xbb\x9d;\xc6\x14`\xda\x9d&\xbdA\xa1l" +
"\xdb\xad-\x83hr\xb8\x13\x82J\xf2[C\x9f)\xd5" +
"L>\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"
func init() {
schemas.Register(schema_db8274f9144abc7e,
@ -3973,7 +3729,6 @@ func init() {
0x91f7a001ca145b9d,
0x9b87b390babc2ccf,
0x9e12cfad042ba4f1,
0xa160eb416f17c28e,
0xa29a916d4ebdd894,
0xa766b24d4fe5da35,
0xa78f37418c1077c8,
@ -3998,10 +3753,8 @@ func init() {
0xf2c122394f447e8e,
0xf2c68e2547ec3866,
0xf41a0f001ad49e46,
0xf7e406af6bd5236c,
0xf7f49b3f779ae258,
0xf9c895683ed9ac4c,
0xfc9f83c37bab5621,
0xfeac5c8f4899ef7c,
0xff8d9848747c956a)
}