From 2b2bdb7bf30592feb812a9bb1f507650715315af Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 2 Aug 2018 19:40:00 +0000 Subject: [PATCH 1/4] Update for newer upstream alertmanager Signed-off-by: Bryan Boreham --- pkg/alertmanager/alertmanager.go | 42 ++++--- pkg/alertmanager/mesh.go | 190 ------------------------------- pkg/alertmanager/multitenant.go | 180 +++++++++++------------------ pkg/alertmanager/peers.go | 88 -------------- pkg/util/flagext/stringslice.go | 19 ++++ 5 files changed, 111 insertions(+), 408 deletions(-) delete mode 100644 pkg/alertmanager/mesh.go delete mode 100644 pkg/alertmanager/peers.go create mode 100644 pkg/util/flagext/stringslice.go diff --git a/pkg/alertmanager/alertmanager.go b/pkg/alertmanager/alertmanager.go index 2bdeb225db2..c7deed935b9 100644 --- a/pkg/alertmanager/alertmanager.go +++ b/pkg/alertmanager/alertmanager.go @@ -11,6 +11,7 @@ import ( "github.com/go-kit/kit/log" "github.com/prometheus/alertmanager/api" + "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/dispatch" "github.com/prometheus/alertmanager/inhibit" @@ -24,7 +25,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/route" "github.com/prometheus/prometheus/pkg/labels" - "github.com/weaveworks/mesh" ) const notificationLogMaintenancePeriod = 15 * time.Minute @@ -35,7 +35,8 @@ type Config struct { // Used to persist notification logs and silences on disk. DataDir string Logger log.Logger - MeshRouter gossipRouter + Peer *cluster.Peer + PeerTimeout time.Duration Retention time.Duration ExternalURL *url.URL } @@ -45,7 +46,7 @@ type Alertmanager struct { cfg *Config api *api.API logger log.Logger - nflog nflog.Log + nflog *nflog.Log silences *silence.Silences marker types.Marker alerts *mem.Alerts @@ -68,9 +69,6 @@ func New(cfg *Config) (*Alertmanager, error) { nflogID := fmt.Sprintf("nflog:%s", cfg.UserID) var err error am.nflog, err = nflog.New( - nflog.WithMesh(func(g mesh.Gossiper) mesh.Gossip { - return cfg.MeshRouter.newGossip(nflogID, g) - }), nflog.WithRetention(cfg.Retention), nflog.WithSnapshot(filepath.Join(cfg.DataDir, nflogID)), nflog.WithMaintenance(notificationLogMaintenancePeriod, am.stop, am.wg.Done), @@ -86,22 +84,25 @@ func New(cfg *Config) (*Alertmanager, error) { am.marker = types.NewMarker() + // TODO(cortex): Build a registry that can merge metrics from multiple users. + // For now, these metrics are ignored, as we can't register the same + // metric twice with a single registry. + localRegistry := prometheus.NewRegistry() + silencesID := fmt.Sprintf("silences:%s", cfg.UserID) am.silences, err = silence.New(silence.Options{ SnapshotFile: filepath.Join(cfg.DataDir, silencesID), Retention: cfg.Retention, Logger: log.With(am.logger, "component", "silences"), - // TODO(cortex): Build a registry that can merge metrics from multiple users. - // For now, these metrics are ignored, as we can't register the same - // metric twice with a single registry. - Metrics: prometheus.NewRegistry(), - Gossip: func(g mesh.Gossiper) mesh.Gossip { - return cfg.MeshRouter.newGossip(silencesID, g) - }, + Metrics: localRegistry, }) if err != nil { return nil, fmt.Errorf("failed to create silences: %v", err) } + if cfg.Peer != nil { + c := cfg.Peer.AddState("sil:"+cfg.UserID, am.silences, localRegistry) + am.silences.SetBroadcast(c.Broadcast) + } am.wg.Add(1) go func() { @@ -122,7 +123,7 @@ func New(cfg *Config) (*Alertmanager, error) { return am.dispatcher.Groups(matchers) }, marker.Status, - nil, // Passing a nil mesh router since we don't show mesh router information in Cortex anyway. + cfg.Peer, log.With(am.logger, "component", "api"), ) @@ -130,7 +131,7 @@ func New(cfg *Config) (*Alertmanager, error) { webReload := make(chan chan error) ui.Register(am.router.WithPrefix(am.cfg.ExternalURL.Path), webReload, log.With(am.logger, "component", "ui")) - am.api.Register(am.router.WithPrefix(path.Join(am.cfg.ExternalURL.Path, "/api"))) + am.api.Register(am.router.WithPrefix(path.Join(am.cfg.ExternalURL.Path, "/api/v1"))) go func() { for { @@ -148,6 +149,14 @@ func New(cfg *Config) (*Alertmanager, error) { return am, nil } +// clusterWait returns a function that inspects the current peer state and returns +// a duration of one base timeout for each peer with a higher ID than ourselves. +func clusterWait(p *cluster.Peer, timeout time.Duration) func() time.Duration { + return func() time.Duration { + return time.Duration(p.Position()) * timeout + } +} + // ApplyConfig applies a new configuration to an Alertmanager. func (am *Alertmanager) ApplyConfig(userID string, conf *config.Config) error { var ( @@ -178,7 +187,7 @@ func (am *Alertmanager) ApplyConfig(userID string, conf *config.Config) error { am.inhibitor = inhibit.NewInhibitor(am.alerts, conf.InhibitRules, am.marker, log.With(am.logger, "component", "inhibitor")) - waitFunc := meshWait(am.cfg.MeshRouter, 5*time.Second) + waitFunc := clusterWait(am.cfg.Peer, am.cfg.PeerTimeout) timeoutFunc := func(d time.Duration) time.Duration { if d < notify.MinTimeout { d = notify.MinTimeout @@ -194,6 +203,7 @@ func (am *Alertmanager) ApplyConfig(userID string, conf *config.Config) error { am.silences, am.nflog, am.marker, + am.cfg.Peer, log.With(am.logger, "component", "pipeline"), ) am.dispatcher = dispatch.NewDispatcher( diff --git a/pkg/alertmanager/mesh.go b/pkg/alertmanager/mesh.go deleted file mode 100644 index 22c24cd39cd..00000000000 --- a/pkg/alertmanager/mesh.go +++ /dev/null @@ -1,190 +0,0 @@ -// Definitions in this file were largely taken from -// https://github.com/prometheus/alertmanager/blob/master/cmd/alertmanager/main.go -// -// Original copyright notice: -// -// Copyright 2015 Prometheus Team -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package alertmanager - -import ( - "fmt" - "net" - "os" - "sort" - "strconv" - "strings" - "sync" - "time" - - "github.com/go-kit/kit/log/level" - - "github.com/cortexproject/cortex/pkg/util" - "github.com/weaveworks/mesh" -) - -type promLog struct{} - -// Printf implements the mesh.Logger interface. -func (p promLog) Printf(format string, args ...interface{}) { - level.Info(util.Logger).Log("msg", fmt.Sprintf(format, args...)) -} - -func initMesh(addr, hwaddr, nickname, pw string) *mesh.Router { - host, portStr, err := net.SplitHostPort(addr) - - if err != nil { - level.Error(util.Logger).Log("msg", "invalid mesh address", "addr", addr, "err", err) - os.Exit(1) - } - port, err := strconv.Atoi(portStr) - if err != nil { - level.Error(util.Logger).Log("msg", "invalid mesh address", "addr", addr, "err", err) - os.Exit(1) - } - - name, err := mesh.PeerNameFromString(hwaddr) - if err != nil { - level.Error(util.Logger).Log("msg", "invalid hardware address", "hwaddr", hwaddr, "err", err) - os.Exit(1) - } - - password := []byte(pw) - if len(password) == 0 { - // Empty password is used to disable secure communication. Using a nil - // password disables encryption in mesh. - password = nil - } - - return mesh.NewRouter(mesh.Config{ - Host: host, - Port: port, - ProtocolMinVersion: mesh.ProtocolMinVersion, - Password: password, - ConnLimit: 64, - PeerDiscovery: true, - TrustedSubnets: []*net.IPNet{}, - }, name, nickname, mesh.NullOverlay{}, promLog{}) - -} - -type stringset map[string]struct{} - -func (ss stringset) Set(value string) error { - ss[value] = struct{}{} - return nil -} - -func (ss stringset) String() string { - return strings.Join(ss.slice(), ",") -} - -func (ss stringset) slice() []string { - slice := make([]string, 0, len(ss)) - for k := range ss { - slice = append(slice, k) - } - sort.Strings(slice) - return slice -} - -func mustHardwareAddr() string { - // TODO(fabxc): consider a safe-guard against colliding MAC addresses. - ifaces, err := net.Interfaces() - if err != nil { - panic(err) - } - for _, iface := range ifaces { - if s := iface.HardwareAddr.String(); s != "" { - return s - } - } - panic("no valid network interfaces") -} - -func mustHostname() string { - hostname, err := os.Hostname() - if err != nil { - panic(err) - } - return hostname -} - -type peerDescSlice []mesh.PeerDescription - -func (s peerDescSlice) Len() int { return len(s) } -func (s peerDescSlice) Less(i, j int) bool { return s[i].UID < s[j].UID } -func (s peerDescSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// meshWait returns a function that inspects the current peer state and returns -// a duration of one base timeout for each peer with a higher ID than ourselves. -func meshWait(r gossipRouter, timeout time.Duration) func() time.Duration { - return func() time.Duration { - var peers peerDescSlice - for _, desc := range r.getPeers().Descriptions() { - peers = append(peers, desc) - } - sort.Sort(peers) - - k := 0 - for _, desc := range peers { - if desc.Self { - break - } - k++ - } - // TODO(fabxc): add metric exposing the "position" from AM's own view. - return time.Duration(k) * timeout - } -} - -// gossipRouter is the interface we use for a mesh router. -type gossipRouter interface { - newGossip(string, mesh.Gossiper) mesh.Gossip - getPeers() *mesh.Peers -} - -// gossipFactory allows safe creation of mesh.Gossips on a mesh.Router. -type gossipFactory struct { - *mesh.Router - gossips map[string]mesh.Gossip - lock sync.Mutex -} - -// newGossipFactory makes a new router factory. -func newGossipFactory(router *mesh.Router) gossipFactory { - return gossipFactory{ - Router: router, - gossips: map[string]mesh.Gossip{}, - } -} - -// newGossip makes a new Gossip with the given `id`. If a gossip with that ID -// already exists, that will be returned instead. -func (gf *gossipFactory) newGossip(id string, g mesh.Gossiper) mesh.Gossip { - gf.lock.Lock() - defer gf.lock.Unlock() - gossip, ok := gf.gossips[id] - if ok { - return gossip - } - gossip = gf.Router.NewGossip(id, g) - gf.gossips[id] = gossip - return gossip -} - -// getPeers returns the peers of a router. -func (gf *gossipFactory) getPeers() *mesh.Peers { - return gf.Router.Peers -} diff --git a/pkg/alertmanager/multitenant.go b/pkg/alertmanager/multitenant.go index 46e380c54d8..e1735d75eb5 100644 --- a/pkg/alertmanager/multitenant.go +++ b/pkg/alertmanager/multitenant.go @@ -6,21 +6,19 @@ import ( "fmt" "html/template" "io/ioutil" - "net" "net/http" "os" "path/filepath" - "sort" - "strconv" "strings" "sync" "time" + "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" + "github.com/prometheus/alertmanager/cluster" amconfig "github.com/prometheus/alertmanager/config" "github.com/prometheus/client_golang/prometheus" "github.com/weaveworks/common/user" - "github.com/weaveworks/mesh" "github.com/cortexproject/cortex/pkg/configs" configs_client "github.com/cortexproject/cortex/pkg/configs/client" @@ -49,36 +47,18 @@ const ( Cortex Alertmanager Status

Cortex Alertmanager Status

-

Mesh router

+

Node

-
Protocol
-
{{.Protocol}} - {{if eq .ProtocolMinVersion .ProtocolMaxVersion}} - {{.ProtocolMaxVersion}} - {{else}} - {{.ProtocolMinVersion}}..{{.ProtocolMaxVersion}} - {{end}} -
- -
Name
{{.Name}} ({{.NickName}})
-
Encryption
{{state .Encryption}}
-
PeerDiscovery
{{state .PeerDiscovery}}
- -
Targets
{{ with .Targets }} -
    {{ range . }}
  • {{ . }}
  • {{ end }}
- {{ else }}No targets{{ end }} -
- -
Connections
{{len .Connections}}{{with connectionCounts .Connections}} ({{.}}){{end}}
-
Peers
{{len .Peers}}{{with peerConnectionCounts .Peers}} (with {{.}} connections){{end}}
-
TrustedSubnets
{{.TrustedSubnets}}
+
Name
{{.self.Name}}
+
Addr
{{.self.Addr}}
+
Port
{{.self.Port}}
-

Peers

- {{ with .Peers }} +

Members

+ {{ with .members }} - + {{ range . }} - + {{ end }}
NameNickNameUIDShortIDVersionEstablished connectionsPending connections
NameAddr
{{ .Name }}{{ .NickName }}{{ .ShortID }}{{ .Version }}{{ . | establishedCount }}{{ . | pendingCount }}
{{ .Name }}{{ .Addr }}
{{ else }} @@ -95,18 +75,12 @@ var ( Name: "alertmanager_configs_total", Help: "How many configs the multitenant alertmanager knows about.", }) - totalPeers = prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "cortex", - Name: "mesh_peers", - Help: "Number of peers the multitenant alertmanager knows about", - }) statusTemplate *template.Template allConnectionStates = []string{"established", "pending", "retrying", "failed", "connecting"} ) func init() { prometheus.MustRegister(totalConfigs) - prometheus.MustRegister(totalPeers) statusTemplate = template.Must(template.New("statusPage").Funcs(map[string]interface{}{ "state": func(enabled bool) string { if enabled { @@ -114,44 +88,6 @@ func init() { } return "disabled" }, - "connectionCounts": func(conns []mesh.LocalConnectionStatus) string { - cs := map[string]int{} - for _, conn := range conns { - cs[conn.State]++ - } - return counts(cs, allConnectionStates) - }, - "peerConnectionCounts": func(peers []mesh.PeerStatus) string { - cs := map[string]int{} - for _, peer := range peers { - for _, conn := range peer.Connections { - if conn.Established { - cs["established"]++ - } else { - cs["pending"]++ - } - } - } - return counts(cs, []string{"established", "pending"}) - }, - "establishedCount": func(peer mesh.PeerStatus) string { - count := 0 - for _, conn := range peer.Connections { - if conn.Established { - count++ - } - } - return fmt.Sprintf("%d", count) - }, - "pendingCount": func(peer mesh.PeerStatus) string { - count := 0 - for _, conn := range peer.Connections { - if !conn.Established { - count++ - } - } - return fmt.Sprintf("%d", count) - }, }).Parse(statusPage)) } @@ -173,20 +109,25 @@ type MultitenantAlertmanagerConfig struct { ExternalURL flagext.URLValue PollInterval time.Duration - MeshListenAddr string - MeshHWAddr string - MeshNickname string - MeshPassword string - - MeshPeerHost string - MeshPeerService string - MeshPeerRefreshInterval time.Duration + clusterBindAddr string + clusterAdvertiseAddr string + peers flagext.StringSlice + peerTimeout time.Duration + gossipInterval time.Duration + pushPullInterval time.Duration + tcpTimeout time.Duration + probeTimeout time.Duration + probeInterval time.Duration + reconnectInterval time.Duration + peerReconnectTimeout time.Duration FallbackConfigFile string AutoWebhookRoot string AutoSlackRoot string } +const defaultClusterAddr = "0.0.0.0:9094" + // RegisterFlags adds the flags required to config this to the given FlagSet. func (cfg *MultitenantAlertmanagerConfig) RegisterFlags(f *flag.FlagSet) { flag.StringVar(&cfg.DataDir, "alertmanager.storage.path", "data/", "Base path for data storage.") @@ -199,14 +140,18 @@ func (cfg *MultitenantAlertmanagerConfig) RegisterFlags(f *flag.FlagSet) { flag.StringVar(&cfg.AutoSlackRoot, "alertmanager.configs.auto-slack-root", "", "Root of URL to generate if config is "+autoSlackURL) flag.DurationVar(&cfg.PollInterval, "alertmanager.configs.poll-interval", 15*time.Second, "How frequently to poll Cortex configs") - flag.StringVar(&cfg.MeshListenAddr, "alertmanager.mesh.listen-address", net.JoinHostPort("0.0.0.0", strconv.Itoa(mesh.Port)), "Mesh listen address") - flag.StringVar(&cfg.MeshHWAddr, "alertmanager.mesh.hardware-address", mustHardwareAddr(), "MAC address, i.e. Mesh peer ID") - flag.StringVar(&cfg.MeshNickname, "alertmanager.mesh.nickname", mustHostname(), "Mesh peer nickname") - flag.StringVar(&cfg.MeshPassword, "alertmanager.mesh.password", "", "Password to join the Mesh peer network (empty password disables encryption)") + flag.StringVar(&cfg.clusterBindAddr, "cluster.listen-address", defaultClusterAddr, "Listen address for cluster.") + flag.StringVar(&cfg.clusterAdvertiseAddr, "cluster.advertise-address", "", "Explicit address to advertise in cluster.") + flag.Var(&cfg.peers, "cluster.peer", "Initial peers (may be repeated).") + flag.DurationVar(&cfg.peerTimeout, "cluster.peer-timeout", time.Second*15, "Time to wait between peers to send notifications.") + flag.DurationVar(&cfg.gossipInterval, "cluster.gossip-interval", cluster.DefaultGossipInterval, "Interval between sending gossip messages. By lowering this value (more frequent) gossip messages are propagated across the cluster more quickly at the expense of increased bandwidth.") + flag.DurationVar(&cfg.pushPullInterval, "cluster.pushpull-interval", cluster.DefaultPushPullInterval, "Interval for gossip state syncs. Setting this interval lower (more frequent) will increase convergence speeds across larger clusters at the expense of increased bandwidth usage.") + flag.DurationVar(&cfg.tcpTimeout, "cluster.tcp-timeout", cluster.DefaultTcpTimeout, "Timeout for establishing a stream connection with a remote node for a full state sync, and for stream read and write operations.") + flag.DurationVar(&cfg.probeTimeout, "cluster.probe-timeout", cluster.DefaultProbeTimeout, "Timeout to wait for an ack from a probed node before assuming it is unhealthy. This should be set to 99-percentile of RTT (round-trip time) on your network.") + flag.DurationVar(&cfg.probeInterval, "cluster.probe-interval", cluster.DefaultProbeInterval, "Interval between random node probes. Setting this lower (more frequent) will cause the cluster to detect failed nodes more quickly at the expense of increased bandwidth usage.") + flag.DurationVar(&cfg.reconnectInterval, "cluster.reconnect-interval", cluster.DefaultReconnectInterval, "Interval between attempting to reconnect to lost peers.") + flag.DurationVar(&cfg.peerReconnectTimeout, "cluster.reconnect-timeout", cluster.DefaultReconnectTimeout, "Length of time to attempt to reconnect to a lost peer.") - flag.StringVar(&cfg.MeshPeerService, "alertmanager.mesh.peer.service", "mesh", "SRV service used to discover peers.") - flag.StringVar(&cfg.MeshPeerHost, "alertmanager.mesh.peer.host", "", "Hostname for mesh peers.") - flag.DurationVar(&cfg.MeshPeerRefreshInterval, "alertmanager.mesh.peer.refresh-interval", 1*time.Minute, "Period with which to poll DNS for mesh peers.") } // A MultitenantAlertmanager manages Alertmanager instances for multiple @@ -230,8 +175,7 @@ type MultitenantAlertmanager struct { latestConfig configs.ID latestMutex sync.RWMutex - meshRouter *gossipFactory - srvDiscovery *srvDiscovery + peer *cluster.Peer stop chan struct{} done chan struct{} @@ -249,9 +193,6 @@ func NewMultitenantAlertmanager(cfg *MultitenantAlertmanagerConfig, cfgCfg confi return nil, err } - mrouter := initMesh(cfg.MeshListenAddr, cfg.MeshHWAddr, cfg.MeshNickname, cfg.MeshPassword) - mrouter.Start() - var fallbackConfig []byte if cfg.FallbackConfigFile != "" { fallbackConfig, err = ioutil.ReadFile(cfg.FallbackConfigFile) @@ -264,15 +205,39 @@ func NewMultitenantAlertmanager(cfg *MultitenantAlertmanagerConfig, cfgCfg confi } } - gf := newGossipFactory(mrouter) + var peer *cluster.Peer + if cfg.clusterBindAddr != "" { + peer, err = cluster.Create( + log.With(util.Logger, "component", "cluster"), + prometheus.DefaultRegisterer, + cfg.clusterBindAddr, + cfg.clusterAdvertiseAddr, + cfg.peers, + true, + cfg.pushPullInterval, + cfg.gossipInterval, + cfg.tcpTimeout, + cfg.probeTimeout, + cfg.probeInterval, + ) + if err != nil { + level.Error(util.Logger).Log("msg", "unable to initialize gossip mesh", "err", err) + os.Exit(1) + } + err = peer.Join(cfg.reconnectInterval, cfg.peerReconnectTimeout) + if err != nil { + level.Warn(util.Logger).Log("msg", "unable to join gossip mesh", "err", err) + } + go peer.Settle(context.Background(), cfg.gossipInterval*10) + } + am := &MultitenantAlertmanager{ cfg: cfg, configsAPI: configsAPI, fallbackConfig: string(fallbackConfig), cfgs: map[string]configs.Config{}, alertmanagers: map[string]*Alertmanager{}, - meshRouter: &gf, - srvDiscovery: newSRVDiscovery(cfg.MeshPeerService, cfg.MeshPeerHost, cfg.MeshPeerRefreshInterval), + peer: peer, stop: make(chan struct{}), done: make(chan struct{}), } @@ -288,18 +253,6 @@ func (am *MultitenantAlertmanager) Run() { ticker := time.NewTicker(am.cfg.PollInterval) for { select { - case addrs := <-am.srvDiscovery.addresses: - var peers []string - for _, srv := range addrs { - peers = append(peers, net.JoinHostPort(srv.Target, strconv.FormatUint(uint64(srv.Port), 10))) - } - sort.Strings(peers) - level.Info(util.Logger).Log("msg", "updating alertmanager peers", "old", am.meshRouter.getPeers(), "new", peers) - errs := am.meshRouter.ConnectionMaker.InitiateConnections(peers, true) - for _, err := range errs { - level.Error(util.Logger).Log("err", err) - } - totalPeers.Set(float64(len(peers))) case now := <-ticker.C: err := am.updateConfigs(now) if err != nil { @@ -314,7 +267,6 @@ func (am *MultitenantAlertmanager) Run() { // Stop stops the MultitenantAlertmanager. func (am *MultitenantAlertmanager) Stop() { - am.srvDiscovery.Stop() close(am.stop) <-am.done am.alertmanagersMtx.Lock() @@ -322,7 +274,7 @@ func (am *MultitenantAlertmanager) Stop() { am.Stop() } am.alertmanagersMtx.Unlock() - am.meshRouter.Stop() + am.peer.Leave(am.cfg.peerTimeout) level.Debug(util.Logger).Log("msg", "MultitenantAlertmanager stopped") } @@ -519,7 +471,8 @@ func (am *MultitenantAlertmanager) newAlertmanager(userID string, amConfig *amco UserID: userID, DataDir: am.cfg.DataDir, Logger: util.Logger, - MeshRouter: am.meshRouter, + Peer: am.peer, + PeerTimeout: am.cfg.peerTimeout, Retention: am.cfg.Retention, ExternalURL: am.cfg.ExternalURL.URL, }) @@ -565,8 +518,7 @@ type StatusHandler struct { // ServeHTTP serves the status of the alertmanager. func (s StatusHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - meshStatus := mesh.NewStatus(s.am.meshRouter.Router) - err := statusTemplate.Execute(w, meshStatus) + err := statusTemplate.Execute(w, s.am.peer.Info()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } diff --git a/pkg/alertmanager/peers.go b/pkg/alertmanager/peers.go deleted file mode 100644 index 03a849d2408..00000000000 --- a/pkg/alertmanager/peers.go +++ /dev/null @@ -1,88 +0,0 @@ -package alertmanager - -import ( - "net" - "time" - - "github.com/cortexproject/cortex/pkg/util" - "github.com/go-kit/kit/log/level" - "github.com/prometheus/client_golang/prometheus" -) - -var ( - srvRequests = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "cortex", - Name: "srv_lookup_requests_total", - Help: "Total number of SRV requests.", - }) - srvRequestFailures = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "cortex", - Name: "srv_lookup_request_failures_total", - Help: "Total number of failed SRV requests.", - }) -) - -func init() { - prometheus.MustRegister(srvRequests) - prometheus.MustRegister(srvRequestFailures) -} - -// TODO: change memcache_client to use this. - -// srvDiscovery discovers SRV services. -type srvDiscovery struct { - service string - hostname string - pollInterval time.Duration - addresses chan []*net.SRV - - stop chan struct{} - done chan struct{} -} - -// newSRVDiscovery makes a new srvDiscovery. -func newSRVDiscovery(service, hostname string, pollInterval time.Duration) *srvDiscovery { - disco := &srvDiscovery{ - service: service, - hostname: hostname, - pollInterval: pollInterval, - addresses: make(chan []*net.SRV), - stop: make(chan struct{}), - done: make(chan struct{}), - } - go disco.loop() - return disco -} - -// Stop the srvDiscovery -func (s *srvDiscovery) Stop() { - close(s.stop) - <-s.done -} - -func (s *srvDiscovery) updatePeers() { - var addrs []*net.SRV - _, addrs, err := net.LookupSRV(s.service, "tcp", s.hostname) - srvRequests.Inc() - if err != nil { - srvRequestFailures.Inc() - level.Warn(util.Logger).Log("msg", "error discovering services for hostname", "service", s.service, "hostname", s.hostname, "err", err) - } else { - s.addresses <- addrs - } -} - -func (s *srvDiscovery) loop() { - defer close(s.done) - ticker := time.NewTicker(s.pollInterval) - s.updatePeers() - for { - select { - case <-ticker.C: - s.updatePeers() - case <-s.stop: - ticker.Stop() - return - } - } -} diff --git a/pkg/util/flagext/stringslice.go b/pkg/util/flagext/stringslice.go new file mode 100644 index 00000000000..5cf70f55744 --- /dev/null +++ b/pkg/util/flagext/stringslice.go @@ -0,0 +1,19 @@ +package flagext + +import ( + "strings" +) + +// StringSlice is a slice of strings that implements flag.Value +type StringSlice []string + +// String implements flag.Value +func (v StringSlice) String() string { + return strings.Join(v, " ") +} + +// Set implements flag.Value +func (v *StringSlice) Set(s string) error { + *v = append(*v, s) + return nil +} From 33944e9bfa25855605b62f0083129285a1b2736b Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 5 Aug 2019 15:10:31 +0000 Subject: [PATCH 2/4] Update vendor for newer alertmanager code Signed-off-by: Bryan Boreham --- go.mod | 3 +- go.sum | 6 +- vendor/github.com/hashicorp/errwrap/LICENSE | 354 +++++ vendor/github.com/hashicorp/errwrap/README.md | 89 ++ .../github.com/hashicorp/errwrap/errwrap.go | 169 ++ vendor/github.com/hashicorp/errwrap/go.mod | 1 + .../github.com/hashicorp/go-msgpack/LICENSE | 25 + .../hashicorp/go-msgpack/codec/0doc.go | 143 ++ .../hashicorp/go-msgpack/codec/README.md | 174 +++ .../hashicorp/go-msgpack/codec/binc.go | 786 ++++++++++ .../hashicorp/go-msgpack/codec/decode.go | 1048 +++++++++++++ .../hashicorp/go-msgpack/codec/encode.go | 1001 ++++++++++++ .../hashicorp/go-msgpack/codec/helper.go | 589 +++++++ .../go-msgpack/codec/helper_internal.go | 127 ++ .../hashicorp/go-msgpack/codec/msgpack.go | 816 ++++++++++ .../go-msgpack/codec/msgpack_test.py | 110 ++ .../hashicorp/go-msgpack/codec/rpc.go | 152 ++ .../hashicorp/go-msgpack/codec/simple.go | 461 ++++++ .../hashicorp/go-msgpack/codec/time.go | 193 +++ .../hashicorp/go-multierror/.travis.yml | 12 + .../hashicorp/go-multierror/LICENSE | 353 +++++ .../hashicorp/go-multierror/Makefile | 31 + .../hashicorp/go-multierror/README.md | 97 ++ .../hashicorp/go-multierror/append.go | 41 + .../hashicorp/go-multierror/flatten.go | 26 + .../hashicorp/go-multierror/format.go | 27 + .../github.com/hashicorp/go-multierror/go.mod | 3 + .../github.com/hashicorp/go-multierror/go.sum | 4 + .../hashicorp/go-multierror/multierror.go | 51 + .../hashicorp/go-multierror/prefix.go | 37 + .../hashicorp/go-multierror/sort.go | 16 + .../mesh => hashicorp/go-sockaddr}/.gitignore | 8 +- .../hashicorp/go-sockaddr/GNUmakefile | 65 + .../github.com/hashicorp/go-sockaddr/LICENSE | 373 +++++ .../hashicorp/go-sockaddr/README.md | 118 ++ .../github.com/hashicorp/go-sockaddr/doc.go | 5 + .../github.com/hashicorp/go-sockaddr/go.mod | 8 + .../github.com/hashicorp/go-sockaddr/go.sum | 24 + .../hashicorp/go-sockaddr/ifaddr.go | 254 +++ .../hashicorp/go-sockaddr/ifaddrs.go | 1304 ++++++++++++++++ .../hashicorp/go-sockaddr/ifattr.go | 65 + .../hashicorp/go-sockaddr/ipaddr.go | 169 ++ .../hashicorp/go-sockaddr/ipaddrs.go | 98 ++ .../hashicorp/go-sockaddr/ipv4addr.go | 516 ++++++ .../hashicorp/go-sockaddr/ipv6addr.go | 591 +++++++ .../github.com/hashicorp/go-sockaddr/rfc.go | 948 ++++++++++++ .../hashicorp/go-sockaddr/route_info.go | 19 + .../go-sockaddr/route_info_android.go | 34 + .../hashicorp/go-sockaddr/route_info_bsd.go | 36 + .../go-sockaddr/route_info_default.go | 10 + .../hashicorp/go-sockaddr/route_info_linux.go | 42 + .../go-sockaddr/route_info_solaris.go | 37 + .../go-sockaddr/route_info_windows.go | 41 + .../hashicorp/go-sockaddr/sockaddr.go | 206 +++ .../hashicorp/go-sockaddr/sockaddrs.go | 193 +++ .../hashicorp/go-sockaddr/unixsock.go | 135 ++ .../hashicorp/memberlist/.gitignore | 25 + .../hashicorp/memberlist/.travis.yml | 15 + .../github.com/hashicorp/memberlist/LICENSE | 354 +++++ .../github.com/hashicorp/memberlist/Makefile | 20 + .../github.com/hashicorp/memberlist/README.md | 75 + .../hashicorp/memberlist/alive_delegate.go | 14 + .../hashicorp/memberlist/awareness.go | 69 + .../hashicorp/memberlist/broadcast.go | 105 ++ .../github.com/hashicorp/memberlist/config.go | 300 ++++ .../hashicorp/memberlist/conflict_delegate.go | 10 + .../hashicorp/memberlist/delegate.go | 37 + .../hashicorp/memberlist/event_delegate.go | 61 + vendor/github.com/hashicorp/memberlist/go.mod | 20 + vendor/github.com/hashicorp/memberlist/go.sum | 38 + .../hashicorp/memberlist/keyring.go | 160 ++ .../hashicorp/memberlist/logging.go | 22 + .../hashicorp/memberlist/memberlist.go | 691 +++++++++ .../hashicorp/memberlist/merge_delegate.go | 14 + .../hashicorp/memberlist/mock_transport.go | 121 ++ vendor/github.com/hashicorp/memberlist/net.go | 1151 ++++++++++++++ .../hashicorp/memberlist/net_transport.go | 312 ++++ .../hashicorp/memberlist/ping_delegate.go | 14 + .../github.com/hashicorp/memberlist/queue.go | 422 +++++ .../hashicorp/memberlist/security.go | 198 +++ .../github.com/hashicorp/memberlist/state.go | 1176 ++++++++++++++ .../hashicorp/memberlist/suspicion.go | 130 ++ vendor/github.com/hashicorp/memberlist/tag.sh | 16 + .../github.com/hashicorp/memberlist/todo.md | 6 + .../hashicorp/memberlist/transport.go | 65 + .../github.com/hashicorp/memberlist/util.go | 309 ++++ .../prometheus/alertmanager/api/api.go | 614 ++------ .../alertmanager/cluster/advertise.go | 66 + .../alertmanager/cluster/channel.go | 149 ++ .../alertmanager/cluster/cluster.go | 749 +++++++++ .../cluster/clusterpb/cluster.pb.go | 476 ++++++ .../cluster/clusterpb/cluster.proto | 18 + .../alertmanager/cluster/delegate.go | 241 +++ .../prometheus/alertmanager/config/config.go | 102 +- .../alertmanager/config/notifiers.go | 177 ++- .../alertmanager/dispatch/dispatch.go | 33 +- .../prometheus/alertmanager/dispatch/route.go | 8 +- .../alertmanager/inhibit/inhibit.go | 10 +- .../prometheus/alertmanager/nflog/nflog.go | 366 ++--- .../alertmanager/nflog/nflogpb/nflog.pb.go | 41 +- .../prometheus/alertmanager/notify/impl.go | 401 +++-- .../prometheus/alertmanager/notify/notify.go | 120 +- .../alertmanager/pkg/parse/parse.go | 41 +- .../alertmanager/silence/silence.go | 371 ++--- .../silence/silencepb/silence.pb.go | 65 +- .../alertmanager/template/default.tmpl | 5 + .../alertmanager/template/email.html | 2 +- .../template/internal/deftmpl/bindata.go | 6 +- .../prometheus/alertmanager/types/types.go | 35 +- .../prometheus/alertmanager/ui/bindata.go | 46 +- .../prometheus/alertmanager/ui/web.go | 346 +---- vendor/github.com/sean-/seed/.gitignore | 24 + vendor/github.com/sean-/seed/LICENSE | 54 + vendor/github.com/sean-/seed/README.md | 44 + vendor/github.com/sean-/seed/init.go | 84 + vendor/github.com/weaveworks/mesh/LICENSE | 201 --- vendor/github.com/weaveworks/mesh/README.md | 79 - vendor/github.com/weaveworks/mesh/circle.yml | 4 - .../github.com/weaveworks/mesh/connection.go | 500 ------ .../weaveworks/mesh/connection_maker.go | 399 ----- vendor/github.com/weaveworks/mesh/gossip.go | 269 ---- .../weaveworks/mesh/gossip_channel.go | 152 -- vendor/github.com/weaveworks/mesh/lint | 22 - .../github.com/weaveworks/mesh/local_peer.go | 296 ---- vendor/github.com/weaveworks/mesh/logger.go | 6 - vendor/github.com/weaveworks/mesh/overlay.go | 123 -- vendor/github.com/weaveworks/mesh/peer.go | 200 --- .../weaveworks/mesh/peer_name_hash.go | 56 - .../weaveworks/mesh/peer_name_mac.go | 110 -- vendor/github.com/weaveworks/mesh/peers.go | 560 ------- vendor/github.com/weaveworks/mesh/protocol.go | 364 ----- .../weaveworks/mesh/protocol_crypto.go | 205 --- vendor/github.com/weaveworks/mesh/router.go | 309 ---- vendor/github.com/weaveworks/mesh/routes.go | 263 ---- vendor/github.com/weaveworks/mesh/status.go | 223 --- .../weaveworks/mesh/surrogate_gossiper.go | 94 -- .../weaveworks/mesh/token_bucket.go | 48 - .../x/crypto/curve25519/const_amd64.h | 8 - .../x/crypto/curve25519/const_amd64.s | 20 - .../x/crypto/curve25519/cswap_amd64.s | 65 - .../x/crypto/curve25519/curve25519.go | 834 ---------- vendor/golang.org/x/crypto/curve25519/doc.go | 23 - .../x/crypto/curve25519/freeze_amd64.s | 73 - .../x/crypto/curve25519/ladderstep_amd64.s | 1377 ----------------- .../x/crypto/curve25519/mont25519_amd64.go | 240 --- .../x/crypto/curve25519/mul_amd64.s | 169 -- .../x/crypto/curve25519/square_amd64.s | 132 -- .../x/crypto/internal/subtle/aliasing.go | 32 - .../internal/subtle/aliasing_appengine.go | 35 - vendor/golang.org/x/crypto/nacl/box/box.go | 103 -- .../x/crypto/nacl/secretbox/secretbox.go | 173 --- .../golang.org/x/crypto/poly1305/mac_noasm.go | 11 - .../golang.org/x/crypto/poly1305/poly1305.go | 83 - .../golang.org/x/crypto/poly1305/sum_amd64.go | 68 - .../golang.org/x/crypto/poly1305/sum_amd64.s | 148 -- .../golang.org/x/crypto/poly1305/sum_arm.go | 22 - vendor/golang.org/x/crypto/poly1305/sum_arm.s | 427 ----- .../x/crypto/poly1305/sum_generic.go | 172 -- .../golang.org/x/crypto/poly1305/sum_noasm.go | 16 - .../golang.org/x/crypto/poly1305/sum_s390x.go | 42 - .../golang.org/x/crypto/poly1305/sum_s390x.s | 378 ----- .../x/crypto/poly1305/sum_vmsl_s390x.s | 909 ----------- .../x/crypto/salsa20/salsa/hsalsa20.go | 144 -- .../x/crypto/salsa20/salsa/salsa208.go | 199 --- .../x/crypto/salsa20/salsa/salsa20_amd64.go | 23 - .../x/crypto/salsa20/salsa/salsa20_amd64.s | 883 ----------- .../x/crypto/salsa20/salsa/salsa20_noasm.go | 14 - .../x/crypto/salsa20/salsa/salsa20_ref.go | 231 --- vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s | 17 - vendor/golang.org/x/sys/cpu/byteorder.go | 30 - vendor/golang.org/x/sys/cpu/cpu.go | 126 -- vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go | 34 - vendor/golang.org/x/sys/cpu/cpu_arm.go | 9 - vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go | 21 - vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 16 - vendor/golang.org/x/sys/cpu/cpu_gccgo.c | 43 - vendor/golang.org/x/sys/cpu/cpu_gccgo.go | 26 - .../golang.org/x/sys/cpu/cpu_gccgo_s390x.go | 22 - vendor/golang.org/x/sys/cpu/cpu_linux.go | 59 - .../golang.org/x/sys/cpu/cpu_linux_arm64.go | 67 - .../golang.org/x/sys/cpu/cpu_linux_ppc64x.go | 33 - .../golang.org/x/sys/cpu/cpu_linux_s390x.go | 161 -- vendor/golang.org/x/sys/cpu/cpu_mips64x.go | 11 - vendor/golang.org/x/sys/cpu/cpu_mipsx.go | 11 - .../golang.org/x/sys/cpu/cpu_other_arm64.go | 11 - vendor/golang.org/x/sys/cpu/cpu_s390x.s | 57 - vendor/golang.org/x/sys/cpu/cpu_wasm.go | 15 - vendor/golang.org/x/sys/cpu/cpu_x86.go | 59 - vendor/golang.org/x/sys/cpu/cpu_x86.s | 27 - .../x/sys/cpu/syscall_aix_ppc64_gc.go | 36 - vendor/modules.txt | 25 +- 191 files changed, 21203 insertions(+), 14138 deletions(-) create mode 100644 vendor/github.com/hashicorp/errwrap/LICENSE create mode 100644 vendor/github.com/hashicorp/errwrap/README.md create mode 100644 vendor/github.com/hashicorp/errwrap/errwrap.go create mode 100644 vendor/github.com/hashicorp/errwrap/go.mod create mode 100644 vendor/github.com/hashicorp/go-msgpack/LICENSE create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/0doc.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/README.md create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/binc.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/decode.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/encode.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/helper.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/helper_internal.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/msgpack.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/rpc.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/simple.go create mode 100644 vendor/github.com/hashicorp/go-msgpack/codec/time.go create mode 100644 vendor/github.com/hashicorp/go-multierror/.travis.yml create mode 100644 vendor/github.com/hashicorp/go-multierror/LICENSE create mode 100644 vendor/github.com/hashicorp/go-multierror/Makefile create mode 100644 vendor/github.com/hashicorp/go-multierror/README.md create mode 100644 vendor/github.com/hashicorp/go-multierror/append.go create mode 100644 vendor/github.com/hashicorp/go-multierror/flatten.go create mode 100644 vendor/github.com/hashicorp/go-multierror/format.go create mode 100644 vendor/github.com/hashicorp/go-multierror/go.mod create mode 100644 vendor/github.com/hashicorp/go-multierror/go.sum create mode 100644 vendor/github.com/hashicorp/go-multierror/multierror.go create mode 100644 vendor/github.com/hashicorp/go-multierror/prefix.go create mode 100644 vendor/github.com/hashicorp/go-multierror/sort.go rename vendor/github.com/{weaveworks/mesh => hashicorp/go-sockaddr}/.gitignore (74%) create mode 100644 vendor/github.com/hashicorp/go-sockaddr/GNUmakefile create mode 100644 vendor/github.com/hashicorp/go-sockaddr/LICENSE create mode 100644 vendor/github.com/hashicorp/go-sockaddr/README.md create mode 100644 vendor/github.com/hashicorp/go-sockaddr/doc.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/go.mod create mode 100644 vendor/github.com/hashicorp/go-sockaddr/go.sum create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ifaddr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ifattr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipaddr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/rfc.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_android.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_default.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/sockaddr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/unixsock.go create mode 100644 vendor/github.com/hashicorp/memberlist/.gitignore create mode 100644 vendor/github.com/hashicorp/memberlist/.travis.yml create mode 100644 vendor/github.com/hashicorp/memberlist/LICENSE create mode 100644 vendor/github.com/hashicorp/memberlist/Makefile create mode 100644 vendor/github.com/hashicorp/memberlist/README.md create mode 100644 vendor/github.com/hashicorp/memberlist/alive_delegate.go create mode 100644 vendor/github.com/hashicorp/memberlist/awareness.go create mode 100644 vendor/github.com/hashicorp/memberlist/broadcast.go create mode 100644 vendor/github.com/hashicorp/memberlist/config.go create mode 100644 vendor/github.com/hashicorp/memberlist/conflict_delegate.go create mode 100644 vendor/github.com/hashicorp/memberlist/delegate.go create mode 100644 vendor/github.com/hashicorp/memberlist/event_delegate.go create mode 100644 vendor/github.com/hashicorp/memberlist/go.mod create mode 100644 vendor/github.com/hashicorp/memberlist/go.sum create mode 100644 vendor/github.com/hashicorp/memberlist/keyring.go create mode 100644 vendor/github.com/hashicorp/memberlist/logging.go create mode 100644 vendor/github.com/hashicorp/memberlist/memberlist.go create mode 100644 vendor/github.com/hashicorp/memberlist/merge_delegate.go create mode 100644 vendor/github.com/hashicorp/memberlist/mock_transport.go create mode 100644 vendor/github.com/hashicorp/memberlist/net.go create mode 100644 vendor/github.com/hashicorp/memberlist/net_transport.go create mode 100644 vendor/github.com/hashicorp/memberlist/ping_delegate.go create mode 100644 vendor/github.com/hashicorp/memberlist/queue.go create mode 100644 vendor/github.com/hashicorp/memberlist/security.go create mode 100644 vendor/github.com/hashicorp/memberlist/state.go create mode 100644 vendor/github.com/hashicorp/memberlist/suspicion.go create mode 100644 vendor/github.com/hashicorp/memberlist/tag.sh create mode 100644 vendor/github.com/hashicorp/memberlist/todo.md create mode 100644 vendor/github.com/hashicorp/memberlist/transport.go create mode 100644 vendor/github.com/hashicorp/memberlist/util.go create mode 100644 vendor/github.com/prometheus/alertmanager/cluster/advertise.go create mode 100644 vendor/github.com/prometheus/alertmanager/cluster/channel.go create mode 100644 vendor/github.com/prometheus/alertmanager/cluster/cluster.go create mode 100644 vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.pb.go create mode 100644 vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.proto create mode 100644 vendor/github.com/prometheus/alertmanager/cluster/delegate.go create mode 100644 vendor/github.com/sean-/seed/.gitignore create mode 100644 vendor/github.com/sean-/seed/LICENSE create mode 100644 vendor/github.com/sean-/seed/README.md create mode 100644 vendor/github.com/sean-/seed/init.go delete mode 100644 vendor/github.com/weaveworks/mesh/LICENSE delete mode 100644 vendor/github.com/weaveworks/mesh/README.md delete mode 100644 vendor/github.com/weaveworks/mesh/circle.yml delete mode 100644 vendor/github.com/weaveworks/mesh/connection.go delete mode 100644 vendor/github.com/weaveworks/mesh/connection_maker.go delete mode 100644 vendor/github.com/weaveworks/mesh/gossip.go delete mode 100644 vendor/github.com/weaveworks/mesh/gossip_channel.go delete mode 100644 vendor/github.com/weaveworks/mesh/lint delete mode 100644 vendor/github.com/weaveworks/mesh/local_peer.go delete mode 100644 vendor/github.com/weaveworks/mesh/logger.go delete mode 100644 vendor/github.com/weaveworks/mesh/overlay.go delete mode 100644 vendor/github.com/weaveworks/mesh/peer.go delete mode 100644 vendor/github.com/weaveworks/mesh/peer_name_hash.go delete mode 100644 vendor/github.com/weaveworks/mesh/peer_name_mac.go delete mode 100644 vendor/github.com/weaveworks/mesh/peers.go delete mode 100644 vendor/github.com/weaveworks/mesh/protocol.go delete mode 100644 vendor/github.com/weaveworks/mesh/protocol_crypto.go delete mode 100644 vendor/github.com/weaveworks/mesh/router.go delete mode 100644 vendor/github.com/weaveworks/mesh/routes.go delete mode 100644 vendor/github.com/weaveworks/mesh/status.go delete mode 100644 vendor/github.com/weaveworks/mesh/surrogate_gossiper.go delete mode 100644 vendor/github.com/weaveworks/mesh/token_bucket.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.h delete mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/cswap_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/doc.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/freeze_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/mul_amd64.s delete mode 100644 vendor/golang.org/x/crypto/curve25519/square_amd64.s delete mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing.go delete mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go delete mode 100644 vendor/golang.org/x/crypto/nacl/box/box.go delete mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/mac_noasm.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_amd64.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_amd64.s delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_arm.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_arm.s delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_generic.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_noasm.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_s390x.go delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_s390x.s delete mode 100644 vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s delete mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go delete mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go delete mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go delete mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s delete mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go delete mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go delete mode 100644 vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s delete mode 100644 vendor/golang.org/x/sys/cpu/byteorder.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_x86.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo.c delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_mips64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_mipsx.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_s390x.s delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_wasm.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.s delete mode 100644 vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go diff --git a/go.mod b/go.mod index 9f210c8c88f..99fae28ec80 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/opentracing/opentracing-go v1.1.0 github.com/philhofer/fwd v0.0.0-20160129035939-98c11a7a6ec8 // indirect github.com/pkg/errors v0.8.1 - github.com/prometheus/alertmanager v0.12.1-0.20190731170042-6e135a0112f5 + github.com/prometheus/alertmanager v0.15.1 github.com/prometheus/client_golang v1.0.0 github.com/prometheus/common v0.4.1 github.com/prometheus/prometheus v0.0.0-20190731144842-63ed2e28f1ac @@ -71,7 +71,6 @@ require ( github.com/uber/jaeger-lib v2.0.0+incompatible // indirect github.com/weaveworks/billing-client v0.0.0-20171006123215-be0d55e547b1 github.com/weaveworks/common v0.0.0-20190714171817-ddeaa31513fd - github.com/weaveworks/mesh v0.0.0-20170131170447-5015f896ab62 github.com/weaveworks/promrus v1.2.0 // indirect go.etcd.io/bbolt v1.3.3 go.etcd.io/etcd v0.0.0-20190709142735-eb7dd97135a5 diff --git a/go.sum b/go.sum index fca54830c08..cdf132de82b 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/alertmanager v0.12.1-0.20190731170042-6e135a0112f5 h1:xqYzIhRFSm2qWLNG9UkSCGOHzlg3IOc0Autvw6fobRQ= -github.com/prometheus/alertmanager v0.12.1-0.20190731170042-6e135a0112f5/go.mod h1:zdz6eCci7rHWB/8/1E/9JEfoKqCAIlxmt8EIKvHi0dI= +github.com/prometheus/alertmanager v0.15.1 h1:LioLwocIFmJvFSZMkMPwPYQ+zFwjQpMHQu6AXhmdpX4= +github.com/prometheus/alertmanager v0.15.1/go.mod h1:zdz6eCci7rHWB/8/1E/9JEfoKqCAIlxmt8EIKvHi0dI= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= @@ -513,8 +513,6 @@ github.com/weaveworks/billing-client v0.0.0-20171006123215-be0d55e547b1 h1:qi+Yk github.com/weaveworks/billing-client v0.0.0-20171006123215-be0d55e547b1/go.mod h1:7gGdEUJaCrSlWi/mjd68CZv0sfqektYPDcro9cE+M9k= github.com/weaveworks/common v0.0.0-20190714171817-ddeaa31513fd h1:yJjtAvkWEyZlz5DGkw3pL12Kbns8rOfPvDrtlIiC82A= github.com/weaveworks/common v0.0.0-20190714171817-ddeaa31513fd/go.mod h1:pSm+0KR57BG3pvGoJWFXJSAC7+sEPewcvdt5StevL3A= -github.com/weaveworks/mesh v0.0.0-20170131170447-5015f896ab62 h1:M8NXuAqtV1qKYA0PFpdu1iJiCwiftOGz8FYfJxqq+GI= -github.com/weaveworks/mesh v0.0.0-20170131170447-5015f896ab62/go.mod h1:mcON9Ws1aW0crSErpXWp7U1ErCDEKliDX2OhVlbWRKk= github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M= github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/errwrap/LICENSE new file mode 100644 index 00000000000..c33dcc7c928 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md new file mode 100644 index 00000000000..444df08f8e7 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/README.md @@ -0,0 +1,89 @@ +# errwrap + +`errwrap` is a package for Go that formalizes the pattern of wrapping errors +and checking if an error contains another error. + +There is a common pattern in Go of taking a returned `error` value and +then wrapping it (such as with `fmt.Errorf`) before returning it. The problem +with this pattern is that you completely lose the original `error` structure. + +Arguably the _correct_ approach is that you should make a custom structure +implementing the `error` interface, and have the original error as a field +on that structure, such [as this example](http://golang.org/pkg/os/#PathError). +This is a good approach, but you have to know the entire chain of possible +rewrapping that happens, when you might just care about one. + +`errwrap` formalizes this pattern (it doesn't matter what approach you use +above) by giving a single interface for wrapping errors, checking if a specific +error is wrapped, and extracting that error. + +## Installation and Docs + +Install using `go get github.com/hashicorp/errwrap`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/errwrap + +## Usage + +#### Basic Usage + +Below is a very basic example of its usage: + +```go +// A function that always returns an error, but wraps it, like a real +// function might. +func tryOpen() error { + _, err := os.Open("/i/dont/exist") + if err != nil { + return errwrap.Wrapf("Doesn't exist: {{err}}", err) + } + + return nil +} + +func main() { + err := tryOpen() + + // We can use the Contains helpers to check if an error contains + // another error. It is safe to do this with a nil error, or with + // an error that doesn't even use the errwrap package. + if errwrap.Contains(err, "does not exist") { + // Do something + } + if errwrap.ContainsType(err, new(os.PathError)) { + // Do something + } + + // Or we can use the associated `Get` functions to just extract + // a specific error. This would return nil if that specific error doesn't + // exist. + perr := errwrap.GetType(err, new(os.PathError)) +} +``` + +#### Custom Types + +If you're already making custom types that properly wrap errors, then +you can get all the functionality of `errwraps.Contains` and such by +implementing the `Wrapper` interface with just one function. Example: + +```go +type AppError { + Code ErrorCode + Err error +} + +func (e *AppError) WrappedErrors() []error { + return []error{e.Err} +} +``` + +Now this works: + +```go +err := &AppError{Err: fmt.Errorf("an error")} +if errwrap.ContainsType(err, fmt.Errorf("")) { + // This will work! +} +``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go new file mode 100644 index 00000000000..a733bef18c0 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/errwrap.go @@ -0,0 +1,169 @@ +// Package errwrap implements methods to formalize error wrapping in Go. +// +// All of the top-level functions that take an `error` are built to be able +// to take any error, not just wrapped errors. This allows you to use errwrap +// without having to type-check and type-cast everywhere. +package errwrap + +import ( + "errors" + "reflect" + "strings" +) + +// WalkFunc is the callback called for Walk. +type WalkFunc func(error) + +// Wrapper is an interface that can be implemented by custom types to +// have all the Contains, Get, etc. functions in errwrap work. +// +// When Walk reaches a Wrapper, it will call the callback for every +// wrapped error in addition to the wrapper itself. Since all the top-level +// functions in errwrap use Walk, this means that all those functions work +// with your custom type. +type Wrapper interface { + WrappedErrors() []error +} + +// Wrap defines that outer wraps inner, returning an error type that +// can be cleanly used with the other methods in this package, such as +// Contains, GetAll, etc. +// +// This function won't modify the error message at all (the outer message +// will be used). +func Wrap(outer, inner error) error { + return &wrappedError{ + Outer: outer, + Inner: inner, + } +} + +// Wrapf wraps an error with a formatting message. This is similar to using +// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap +// errors, you should replace it with this. +// +// format is the format of the error message. The string '{{err}}' will +// be replaced with the original error message. +func Wrapf(format string, err error) error { + outerMsg := "" + if err != nil { + outerMsg = err.Error() + } + + outer := errors.New(strings.Replace( + format, "{{err}}", outerMsg, -1)) + + return Wrap(outer, err) +} + +// Contains checks if the given error contains an error with the +// message msg. If err is not a wrapped error, this will always return +// false unless the error itself happens to match this msg. +func Contains(err error, msg string) bool { + return len(GetAll(err, msg)) > 0 +} + +// ContainsType checks if the given error contains an error with +// the same concrete type as v. If err is not a wrapped error, this will +// check the err itself. +func ContainsType(err error, v interface{}) bool { + return len(GetAllType(err, v)) > 0 +} + +// Get is the same as GetAll but returns the deepest matching error. +func Get(err error, msg string) error { + es := GetAll(err, msg) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetType is the same as GetAllType but returns the deepest matching error. +func GetType(err error, v interface{}) error { + es := GetAllType(err, v) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetAll gets all the errors that might be wrapped in err with the +// given message. The order of the errors is such that the outermost +// matching error (the most recent wrap) is index zero, and so on. +func GetAll(err error, msg string) []error { + var result []error + + Walk(err, func(err error) { + if err.Error() == msg { + result = append(result, err) + } + }) + + return result +} + +// GetAllType gets all the errors that are the same type as v. +// +// The order of the return value is the same as described in GetAll. +func GetAllType(err error, v interface{}) []error { + var result []error + + var search string + if v != nil { + search = reflect.TypeOf(v).String() + } + Walk(err, func(err error) { + var needle string + if err != nil { + needle = reflect.TypeOf(err).String() + } + + if needle == search { + result = append(result, err) + } + }) + + return result +} + +// Walk walks all the wrapped errors in err and calls the callback. If +// err isn't a wrapped error, this will be called once for err. If err +// is a wrapped error, the callback will be called for both the wrapper +// that implements error as well as the wrapped error itself. +func Walk(err error, cb WalkFunc) { + if err == nil { + return + } + + switch e := err.(type) { + case *wrappedError: + cb(e.Outer) + Walk(e.Inner, cb) + case Wrapper: + cb(err) + + for _, err := range e.WrappedErrors() { + Walk(err, cb) + } + default: + cb(err) + } +} + +// wrappedError is an implementation of error that has both the +// outer and inner errors. +type wrappedError struct { + Outer error + Inner error +} + +func (w *wrappedError) Error() string { + return w.Outer.Error() +} + +func (w *wrappedError) WrappedErrors() []error { + return []error{w.Outer, w.Inner} +} diff --git a/vendor/github.com/hashicorp/errwrap/go.mod b/vendor/github.com/hashicorp/errwrap/go.mod new file mode 100644 index 00000000000..c9b84022cf7 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/go.mod @@ -0,0 +1 @@ +module github.com/hashicorp/errwrap diff --git a/vendor/github.com/hashicorp/go-msgpack/LICENSE b/vendor/github.com/hashicorp/go-msgpack/LICENSE new file mode 100644 index 00000000000..ccae99f6a9a --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2012, 2013 Ugorji Nwoke. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/0doc.go b/vendor/github.com/hashicorp/go-msgpack/codec/0doc.go new file mode 100644 index 00000000000..c14d810a73e --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/0doc.go @@ -0,0 +1,143 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +/* +High Performance, Feature-Rich Idiomatic Go encoding library for msgpack and binc . + +Supported Serialization formats are: + + - msgpack: [https://github.com/msgpack/msgpack] + - binc: [http://github.com/ugorji/binc] + +To install: + + go get github.com/ugorji/go/codec + +The idiomatic Go support is as seen in other encoding packages in +the standard library (ie json, xml, gob, etc). + +Rich Feature Set includes: + + - Simple but extremely powerful and feature-rich API + - Very High Performance. + Our extensive benchmarks show us outperforming Gob, Json and Bson by 2-4X. + This was achieved by taking extreme care on: + - managing allocation + - function frame size (important due to Go's use of split stacks), + - reflection use (and by-passing reflection for common types) + - recursion implications + - zero-copy mode (encoding/decoding to byte slice without using temp buffers) + - Correct. + Care was taken to precisely handle corner cases like: + overflows, nil maps and slices, nil value in stream, etc. + - Efficient zero-copying into temporary byte buffers + when encoding into or decoding from a byte slice. + - Standard field renaming via tags + - Encoding from any value + (struct, slice, map, primitives, pointers, interface{}, etc) + - Decoding into pointer to any non-nil typed value + (struct, slice, map, int, float32, bool, string, reflect.Value, etc) + - Supports extension functions to handle the encode/decode of custom types + - Support Go 1.2 encoding.BinaryMarshaler/BinaryUnmarshaler + - Schema-less decoding + (decode into a pointer to a nil interface{} as opposed to a typed non-nil value). + Includes Options to configure what specific map or slice type to use + when decoding an encoded list or map into a nil interface{} + - Provides a RPC Server and Client Codec for net/rpc communication protocol. + - Msgpack Specific: + - Provides extension functions to handle spec-defined extensions (binary, timestamp) + - Options to resolve ambiguities in handling raw bytes (as string or []byte) + during schema-less decoding (decoding into a nil interface{}) + - RPC Server/Client Codec for msgpack-rpc protocol defined at: + https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md + - Fast Paths for some container types: + For some container types, we circumvent reflection and its associated overhead + and allocation costs, and encode/decode directly. These types are: + []interface{} + []int + []string + map[interface{}]interface{} + map[int]interface{} + map[string]interface{} + +Extension Support + +Users can register a function to handle the encoding or decoding of +their custom types. + +There are no restrictions on what the custom type can be. Some examples: + + type BisSet []int + type BitSet64 uint64 + type UUID string + type MyStructWithUnexportedFields struct { a int; b bool; c []int; } + type GifImage struct { ... } + +As an illustration, MyStructWithUnexportedFields would normally be +encoded as an empty map because it has no exported fields, while UUID +would be encoded as a string. However, with extension support, you can +encode any of these however you like. + +RPC + +RPC Client and Server Codecs are implemented, so the codecs can be used +with the standard net/rpc package. + +Usage + +Typical usage model: + + // create and configure Handle + var ( + bh codec.BincHandle + mh codec.MsgpackHandle + ) + + mh.MapType = reflect.TypeOf(map[string]interface{}(nil)) + + // configure extensions + // e.g. for msgpack, define functions and enable Time support for tag 1 + // mh.AddExt(reflect.TypeOf(time.Time{}), 1, myMsgpackTimeEncodeExtFn, myMsgpackTimeDecodeExtFn) + + // create and use decoder/encoder + var ( + r io.Reader + w io.Writer + b []byte + h = &bh // or mh to use msgpack + ) + + dec = codec.NewDecoder(r, h) + dec = codec.NewDecoderBytes(b, h) + err = dec.Decode(&v) + + enc = codec.NewEncoder(w, h) + enc = codec.NewEncoderBytes(&b, h) + err = enc.Encode(v) + + //RPC Server + go func() { + for { + conn, err := listener.Accept() + rpcCodec := codec.GoRpc.ServerCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h) + rpc.ServeCodec(rpcCodec) + } + }() + + //RPC Communication (client side) + conn, err = net.Dial("tcp", "localhost:5555") + rpcCodec := codec.GoRpc.ClientCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h) + client := rpc.NewClientWithCodec(rpcCodec) + +Representative Benchmark Results + +Run the benchmark suite using: + go test -bi -bench=. -benchmem + +To run full benchmark suite (including against vmsgpack and bson), +see notes in ext_dep_test.go + +*/ +package codec diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/README.md b/vendor/github.com/hashicorp/go-msgpack/codec/README.md new file mode 100644 index 00000000000..6c95d1bfd20 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/README.md @@ -0,0 +1,174 @@ +# Codec + +High Performance and Feature-Rich Idiomatic Go Library providing +encode/decode support for different serialization formats. + +Supported Serialization formats are: + + - msgpack: [https://github.com/msgpack/msgpack] + - binc: [http://github.com/ugorji/binc] + +To install: + + go get github.com/ugorji/go/codec + +Online documentation: [http://godoc.org/github.com/ugorji/go/codec] + +The idiomatic Go support is as seen in other encoding packages in +the standard library (ie json, xml, gob, etc). + +Rich Feature Set includes: + + - Simple but extremely powerful and feature-rich API + - Very High Performance. + Our extensive benchmarks show us outperforming Gob, Json and Bson by 2-4X. + This was achieved by taking extreme care on: + - managing allocation + - function frame size (important due to Go's use of split stacks), + - reflection use (and by-passing reflection for common types) + - recursion implications + - zero-copy mode (encoding/decoding to byte slice without using temp buffers) + - Correct. + Care was taken to precisely handle corner cases like: + overflows, nil maps and slices, nil value in stream, etc. + - Efficient zero-copying into temporary byte buffers + when encoding into or decoding from a byte slice. + - Standard field renaming via tags + - Encoding from any value + (struct, slice, map, primitives, pointers, interface{}, etc) + - Decoding into pointer to any non-nil typed value + (struct, slice, map, int, float32, bool, string, reflect.Value, etc) + - Supports extension functions to handle the encode/decode of custom types + - Support Go 1.2 encoding.BinaryMarshaler/BinaryUnmarshaler + - Schema-less decoding + (decode into a pointer to a nil interface{} as opposed to a typed non-nil value). + Includes Options to configure what specific map or slice type to use + when decoding an encoded list or map into a nil interface{} + - Provides a RPC Server and Client Codec for net/rpc communication protocol. + - Msgpack Specific: + - Provides extension functions to handle spec-defined extensions (binary, timestamp) + - Options to resolve ambiguities in handling raw bytes (as string or []byte) + during schema-less decoding (decoding into a nil interface{}) + - RPC Server/Client Codec for msgpack-rpc protocol defined at: + https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md + - Fast Paths for some container types: + For some container types, we circumvent reflection and its associated overhead + and allocation costs, and encode/decode directly. These types are: + []interface{} + []int + []string + map[interface{}]interface{} + map[int]interface{} + map[string]interface{} + +## Extension Support + +Users can register a function to handle the encoding or decoding of +their custom types. + +There are no restrictions on what the custom type can be. Some examples: + + type BisSet []int + type BitSet64 uint64 + type UUID string + type MyStructWithUnexportedFields struct { a int; b bool; c []int; } + type GifImage struct { ... } + +As an illustration, MyStructWithUnexportedFields would normally be +encoded as an empty map because it has no exported fields, while UUID +would be encoded as a string. However, with extension support, you can +encode any of these however you like. + +## RPC + +RPC Client and Server Codecs are implemented, so the codecs can be used +with the standard net/rpc package. + +## Usage + +Typical usage model: + + // create and configure Handle + var ( + bh codec.BincHandle + mh codec.MsgpackHandle + ) + + mh.MapType = reflect.TypeOf(map[string]interface{}(nil)) + + // configure extensions + // e.g. for msgpack, define functions and enable Time support for tag 1 + // mh.AddExt(reflect.TypeOf(time.Time{}), 1, myMsgpackTimeEncodeExtFn, myMsgpackTimeDecodeExtFn) + + // create and use decoder/encoder + var ( + r io.Reader + w io.Writer + b []byte + h = &bh // or mh to use msgpack + ) + + dec = codec.NewDecoder(r, h) + dec = codec.NewDecoderBytes(b, h) + err = dec.Decode(&v) + + enc = codec.NewEncoder(w, h) + enc = codec.NewEncoderBytes(&b, h) + err = enc.Encode(v) + + //RPC Server + go func() { + for { + conn, err := listener.Accept() + rpcCodec := codec.GoRpc.ServerCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h) + rpc.ServeCodec(rpcCodec) + } + }() + + //RPC Communication (client side) + conn, err = net.Dial("tcp", "localhost:5555") + rpcCodec := codec.GoRpc.ClientCodec(conn, h) + //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h) + client := rpc.NewClientWithCodec(rpcCodec) + +## Representative Benchmark Results + +A sample run of benchmark using "go test -bi -bench=. -benchmem": + + /proc/cpuinfo: Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz (HT) + + .............................................. + BENCHMARK INIT: 2013-10-16 11:02:50.345970786 -0400 EDT + To run full benchmark comparing encodings (MsgPack, Binc, JSON, GOB, etc), use: "go test -bench=." + Benchmark: + Struct recursive Depth: 1 + ApproxDeepSize Of benchmark Struct: 4694 bytes + Benchmark One-Pass Run: + v-msgpack: len: 1600 bytes + bson: len: 3025 bytes + msgpack: len: 1560 bytes + binc: len: 1187 bytes + gob: len: 1972 bytes + json: len: 2538 bytes + .............................................. + PASS + Benchmark__Msgpack____Encode 50000 54359 ns/op 14953 B/op 83 allocs/op + Benchmark__Msgpack____Decode 10000 106531 ns/op 14990 B/op 410 allocs/op + Benchmark__Binc_NoSym_Encode 50000 53956 ns/op 14966 B/op 83 allocs/op + Benchmark__Binc_NoSym_Decode 10000 103751 ns/op 14529 B/op 386 allocs/op + Benchmark__Binc_Sym___Encode 50000 65961 ns/op 17130 B/op 88 allocs/op + Benchmark__Binc_Sym___Decode 10000 106310 ns/op 15857 B/op 287 allocs/op + Benchmark__Gob________Encode 10000 135944 ns/op 21189 B/op 237 allocs/op + Benchmark__Gob________Decode 5000 405390 ns/op 83460 B/op 1841 allocs/op + Benchmark__Json_______Encode 20000 79412 ns/op 13874 B/op 102 allocs/op + Benchmark__Json_______Decode 10000 247979 ns/op 14202 B/op 493 allocs/op + Benchmark__Bson_______Encode 10000 121762 ns/op 27814 B/op 514 allocs/op + Benchmark__Bson_______Decode 10000 162126 ns/op 16514 B/op 789 allocs/op + Benchmark__VMsgpack___Encode 50000 69155 ns/op 12370 B/op 344 allocs/op + Benchmark__VMsgpack___Decode 10000 151609 ns/op 20307 B/op 571 allocs/op + ok ugorji.net/codec 30.827s + +To run full benchmark suite (including against vmsgpack and bson), +see notes in ext\_dep\_test.go + diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/binc.go b/vendor/github.com/hashicorp/go-msgpack/codec/binc.go new file mode 100644 index 00000000000..2bb5e8fee85 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/binc.go @@ -0,0 +1,786 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +import ( + "math" + // "reflect" + // "sync/atomic" + "time" + //"fmt" +) + +const bincDoPrune = true // No longer needed. Needed before as C lib did not support pruning. + +//var _ = fmt.Printf + +// vd as low 4 bits (there are 16 slots) +const ( + bincVdSpecial byte = iota + bincVdPosInt + bincVdNegInt + bincVdFloat + + bincVdString + bincVdByteArray + bincVdArray + bincVdMap + + bincVdTimestamp + bincVdSmallInt + bincVdUnicodeOther + bincVdSymbol + + bincVdDecimal + _ // open slot + _ // open slot + bincVdCustomExt = 0x0f +) + +const ( + bincSpNil byte = iota + bincSpFalse + bincSpTrue + bincSpNan + bincSpPosInf + bincSpNegInf + bincSpZeroFloat + bincSpZero + bincSpNegOne +) + +const ( + bincFlBin16 byte = iota + bincFlBin32 + _ // bincFlBin32e + bincFlBin64 + _ // bincFlBin64e + // others not currently supported +) + +type bincEncDriver struct { + w encWriter + m map[string]uint16 // symbols + s uint32 // symbols sequencer + b [8]byte +} + +func (e *bincEncDriver) isBuiltinType(rt uintptr) bool { + return rt == timeTypId +} + +func (e *bincEncDriver) encodeBuiltin(rt uintptr, v interface{}) { + switch rt { + case timeTypId: + bs := encodeTime(v.(time.Time)) + e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs))) + e.w.writeb(bs) + } +} + +func (e *bincEncDriver) encodeNil() { + e.w.writen1(bincVdSpecial<<4 | bincSpNil) +} + +func (e *bincEncDriver) encodeBool(b bool) { + if b { + e.w.writen1(bincVdSpecial<<4 | bincSpTrue) + } else { + e.w.writen1(bincVdSpecial<<4 | bincSpFalse) + } +} + +func (e *bincEncDriver) encodeFloat32(f float32) { + if f == 0 { + e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat) + return + } + e.w.writen1(bincVdFloat<<4 | bincFlBin32) + e.w.writeUint32(math.Float32bits(f)) +} + +func (e *bincEncDriver) encodeFloat64(f float64) { + if f == 0 { + e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat) + return + } + bigen.PutUint64(e.b[:], math.Float64bits(f)) + if bincDoPrune { + i := 7 + for ; i >= 0 && (e.b[i] == 0); i-- { + } + i++ + if i <= 6 { + e.w.writen1(bincVdFloat<<4 | 0x8 | bincFlBin64) + e.w.writen1(byte(i)) + e.w.writeb(e.b[:i]) + return + } + } + e.w.writen1(bincVdFloat<<4 | bincFlBin64) + e.w.writeb(e.b[:]) +} + +func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8) { + if lim == 4 { + bigen.PutUint32(e.b[:lim], uint32(v)) + } else { + bigen.PutUint64(e.b[:lim], v) + } + if bincDoPrune { + i := pruneSignExt(e.b[:lim], pos) + e.w.writen1(bd | lim - 1 - byte(i)) + e.w.writeb(e.b[i:lim]) + } else { + e.w.writen1(bd | lim - 1) + e.w.writeb(e.b[:lim]) + } +} + +func (e *bincEncDriver) encodeInt(v int64) { + const nbd byte = bincVdNegInt << 4 + switch { + case v >= 0: + e.encUint(bincVdPosInt<<4, true, uint64(v)) + case v == -1: + e.w.writen1(bincVdSpecial<<4 | bincSpNegOne) + default: + e.encUint(bincVdNegInt<<4, false, uint64(-v)) + } +} + +func (e *bincEncDriver) encodeUint(v uint64) { + e.encUint(bincVdPosInt<<4, true, v) +} + +func (e *bincEncDriver) encUint(bd byte, pos bool, v uint64) { + switch { + case v == 0: + e.w.writen1(bincVdSpecial<<4 | bincSpZero) + case pos && v >= 1 && v <= 16: + e.w.writen1(bincVdSmallInt<<4 | byte(v-1)) + case v <= math.MaxUint8: + e.w.writen2(bd|0x0, byte(v)) + case v <= math.MaxUint16: + e.w.writen1(bd | 0x01) + e.w.writeUint16(uint16(v)) + case v <= math.MaxUint32: + e.encIntegerPrune(bd, pos, v, 4) + default: + e.encIntegerPrune(bd, pos, v, 8) + } +} + +func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) { + e.encLen(bincVdCustomExt<<4, uint64(length)) + e.w.writen1(xtag) +} + +func (e *bincEncDriver) encodeArrayPreamble(length int) { + e.encLen(bincVdArray<<4, uint64(length)) +} + +func (e *bincEncDriver) encodeMapPreamble(length int) { + e.encLen(bincVdMap<<4, uint64(length)) +} + +func (e *bincEncDriver) encodeString(c charEncoding, v string) { + l := uint64(len(v)) + e.encBytesLen(c, l) + if l > 0 { + e.w.writestr(v) + } +} + +func (e *bincEncDriver) encodeSymbol(v string) { + // if WriteSymbolsNoRefs { + // e.encodeString(c_UTF8, v) + // return + // } + + //symbols only offer benefit when string length > 1. + //This is because strings with length 1 take only 2 bytes to store + //(bd with embedded length, and single byte for string val). + + l := len(v) + switch l { + case 0: + e.encBytesLen(c_UTF8, 0) + return + case 1: + e.encBytesLen(c_UTF8, 1) + e.w.writen1(v[0]) + return + } + if e.m == nil { + e.m = make(map[string]uint16, 16) + } + ui, ok := e.m[v] + if ok { + if ui <= math.MaxUint8 { + e.w.writen2(bincVdSymbol<<4, byte(ui)) + } else { + e.w.writen1(bincVdSymbol<<4 | 0x8) + e.w.writeUint16(ui) + } + } else { + e.s++ + ui = uint16(e.s) + //ui = uint16(atomic.AddUint32(&e.s, 1)) + e.m[v] = ui + var lenprec uint8 + switch { + case l <= math.MaxUint8: + // lenprec = 0 + case l <= math.MaxUint16: + lenprec = 1 + case int64(l) <= math.MaxUint32: + lenprec = 2 + default: + lenprec = 3 + } + if ui <= math.MaxUint8 { + e.w.writen2(bincVdSymbol<<4|0x0|0x4|lenprec, byte(ui)) + } else { + e.w.writen1(bincVdSymbol<<4 | 0x8 | 0x4 | lenprec) + e.w.writeUint16(ui) + } + switch lenprec { + case 0: + e.w.writen1(byte(l)) + case 1: + e.w.writeUint16(uint16(l)) + case 2: + e.w.writeUint32(uint32(l)) + default: + e.w.writeUint64(uint64(l)) + } + e.w.writestr(v) + } +} + +func (e *bincEncDriver) encodeStringBytes(c charEncoding, v []byte) { + l := uint64(len(v)) + e.encBytesLen(c, l) + if l > 0 { + e.w.writeb(v) + } +} + +func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) { + //TODO: support bincUnicodeOther (for now, just use string or bytearray) + if c == c_RAW { + e.encLen(bincVdByteArray<<4, length) + } else { + e.encLen(bincVdString<<4, length) + } +} + +func (e *bincEncDriver) encLen(bd byte, l uint64) { + if l < 12 { + e.w.writen1(bd | uint8(l+4)) + } else { + e.encLenNumber(bd, l) + } +} + +func (e *bincEncDriver) encLenNumber(bd byte, v uint64) { + switch { + case v <= math.MaxUint8: + e.w.writen2(bd, byte(v)) + case v <= math.MaxUint16: + e.w.writen1(bd | 0x01) + e.w.writeUint16(uint16(v)) + case v <= math.MaxUint32: + e.w.writen1(bd | 0x02) + e.w.writeUint32(uint32(v)) + default: + e.w.writen1(bd | 0x03) + e.w.writeUint64(uint64(v)) + } +} + +//------------------------------------ + +type bincDecDriver struct { + r decReader + bdRead bool + bdType valueType + bd byte + vd byte + vs byte + b [8]byte + m map[uint32]string // symbols (use uint32 as key, as map optimizes for it) +} + +func (d *bincDecDriver) initReadNext() { + if d.bdRead { + return + } + d.bd = d.r.readn1() + d.vd = d.bd >> 4 + d.vs = d.bd & 0x0f + d.bdRead = true + d.bdType = valueTypeUnset +} + +func (d *bincDecDriver) currentEncodedType() valueType { + if d.bdType == valueTypeUnset { + switch d.vd { + case bincVdSpecial: + switch d.vs { + case bincSpNil: + d.bdType = valueTypeNil + case bincSpFalse, bincSpTrue: + d.bdType = valueTypeBool + case bincSpNan, bincSpNegInf, bincSpPosInf, bincSpZeroFloat: + d.bdType = valueTypeFloat + case bincSpZero: + d.bdType = valueTypeUint + case bincSpNegOne: + d.bdType = valueTypeInt + default: + decErr("currentEncodedType: Unrecognized special value 0x%x", d.vs) + } + case bincVdSmallInt: + d.bdType = valueTypeUint + case bincVdPosInt: + d.bdType = valueTypeUint + case bincVdNegInt: + d.bdType = valueTypeInt + case bincVdFloat: + d.bdType = valueTypeFloat + case bincVdString: + d.bdType = valueTypeString + case bincVdSymbol: + d.bdType = valueTypeSymbol + case bincVdByteArray: + d.bdType = valueTypeBytes + case bincVdTimestamp: + d.bdType = valueTypeTimestamp + case bincVdCustomExt: + d.bdType = valueTypeExt + case bincVdArray: + d.bdType = valueTypeArray + case bincVdMap: + d.bdType = valueTypeMap + default: + decErr("currentEncodedType: Unrecognized d.vd: 0x%x", d.vd) + } + } + return d.bdType +} + +func (d *bincDecDriver) tryDecodeAsNil() bool { + if d.bd == bincVdSpecial<<4|bincSpNil { + d.bdRead = false + return true + } + return false +} + +func (d *bincDecDriver) isBuiltinType(rt uintptr) bool { + return rt == timeTypId +} + +func (d *bincDecDriver) decodeBuiltin(rt uintptr, v interface{}) { + switch rt { + case timeTypId: + if d.vd != bincVdTimestamp { + decErr("Invalid d.vd. Expecting 0x%x. Received: 0x%x", bincVdTimestamp, d.vd) + } + tt, err := decodeTime(d.r.readn(int(d.vs))) + if err != nil { + panic(err) + } + var vt *time.Time = v.(*time.Time) + *vt = tt + d.bdRead = false + } +} + +func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) { + if vs&0x8 == 0 { + d.r.readb(d.b[0:defaultLen]) + } else { + l := d.r.readn1() + if l > 8 { + decErr("At most 8 bytes used to represent float. Received: %v bytes", l) + } + for i := l; i < 8; i++ { + d.b[i] = 0 + } + d.r.readb(d.b[0:l]) + } +} + +func (d *bincDecDriver) decFloat() (f float64) { + //if true { f = math.Float64frombits(d.r.readUint64()); break; } + switch vs := d.vs; vs & 0x7 { + case bincFlBin32: + d.decFloatPre(vs, 4) + f = float64(math.Float32frombits(bigen.Uint32(d.b[0:4]))) + case bincFlBin64: + d.decFloatPre(vs, 8) + f = math.Float64frombits(bigen.Uint64(d.b[0:8])) + default: + decErr("only float32 and float64 are supported. d.vd: 0x%x, d.vs: 0x%x", d.vd, d.vs) + } + return +} + +func (d *bincDecDriver) decUint() (v uint64) { + // need to inline the code (interface conversion and type assertion expensive) + switch d.vs { + case 0: + v = uint64(d.r.readn1()) + case 1: + d.r.readb(d.b[6:]) + v = uint64(bigen.Uint16(d.b[6:])) + case 2: + d.b[4] = 0 + d.r.readb(d.b[5:]) + v = uint64(bigen.Uint32(d.b[4:])) + case 3: + d.r.readb(d.b[4:]) + v = uint64(bigen.Uint32(d.b[4:])) + case 4, 5, 6: + lim := int(7 - d.vs) + d.r.readb(d.b[lim:]) + for i := 0; i < lim; i++ { + d.b[i] = 0 + } + v = uint64(bigen.Uint64(d.b[:])) + case 7: + d.r.readb(d.b[:]) + v = uint64(bigen.Uint64(d.b[:])) + default: + decErr("unsigned integers with greater than 64 bits of precision not supported") + } + return +} + +func (d *bincDecDriver) decIntAny() (ui uint64, i int64, neg bool) { + switch d.vd { + case bincVdPosInt: + ui = d.decUint() + i = int64(ui) + case bincVdNegInt: + ui = d.decUint() + i = -(int64(ui)) + neg = true + case bincVdSmallInt: + i = int64(d.vs) + 1 + ui = uint64(d.vs) + 1 + case bincVdSpecial: + switch d.vs { + case bincSpZero: + //i = 0 + case bincSpNegOne: + neg = true + ui = 1 + i = -1 + default: + decErr("numeric decode fails for special value: d.vs: 0x%x", d.vs) + } + default: + decErr("number can only be decoded from uint or int values. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd) + } + return +} + +func (d *bincDecDriver) decodeInt(bitsize uint8) (i int64) { + _, i, _ = d.decIntAny() + checkOverflow(0, i, bitsize) + d.bdRead = false + return +} + +func (d *bincDecDriver) decodeUint(bitsize uint8) (ui uint64) { + ui, i, neg := d.decIntAny() + if neg { + decErr("Assigning negative signed value: %v, to unsigned type", i) + } + checkOverflow(ui, 0, bitsize) + d.bdRead = false + return +} + +func (d *bincDecDriver) decodeFloat(chkOverflow32 bool) (f float64) { + switch d.vd { + case bincVdSpecial: + d.bdRead = false + switch d.vs { + case bincSpNan: + return math.NaN() + case bincSpPosInf: + return math.Inf(1) + case bincSpZeroFloat, bincSpZero: + return + case bincSpNegInf: + return math.Inf(-1) + default: + decErr("Invalid d.vs decoding float where d.vd=bincVdSpecial: %v", d.vs) + } + case bincVdFloat: + f = d.decFloat() + default: + _, i, _ := d.decIntAny() + f = float64(i) + } + checkOverflowFloat32(f, chkOverflow32) + d.bdRead = false + return +} + +// bool can be decoded from bool only (single byte). +func (d *bincDecDriver) decodeBool() (b bool) { + switch d.bd { + case (bincVdSpecial | bincSpFalse): + // b = false + case (bincVdSpecial | bincSpTrue): + b = true + default: + decErr("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd) + } + d.bdRead = false + return +} + +func (d *bincDecDriver) readMapLen() (length int) { + if d.vd != bincVdMap { + decErr("Invalid d.vd for map. Expecting 0x%x. Got: 0x%x", bincVdMap, d.vd) + } + length = d.decLen() + d.bdRead = false + return +} + +func (d *bincDecDriver) readArrayLen() (length int) { + if d.vd != bincVdArray { + decErr("Invalid d.vd for array. Expecting 0x%x. Got: 0x%x", bincVdArray, d.vd) + } + length = d.decLen() + d.bdRead = false + return +} + +func (d *bincDecDriver) decLen() int { + if d.vs <= 3 { + return int(d.decUint()) + } + return int(d.vs - 4) +} + +func (d *bincDecDriver) decodeString() (s string) { + switch d.vd { + case bincVdString, bincVdByteArray: + if length := d.decLen(); length > 0 { + s = string(d.r.readn(length)) + } + case bincVdSymbol: + //from vs: extract numSymbolBytes, containsStringVal, strLenPrecision, + //extract symbol + //if containsStringVal, read it and put in map + //else look in map for string value + var symbol uint32 + vs := d.vs + //fmt.Printf(">>>> d.vs: 0b%b, & 0x8: %v, & 0x4: %v\n", d.vs, vs & 0x8, vs & 0x4) + if vs&0x8 == 0 { + symbol = uint32(d.r.readn1()) + } else { + symbol = uint32(d.r.readUint16()) + } + if d.m == nil { + d.m = make(map[uint32]string, 16) + } + + if vs&0x4 == 0 { + s = d.m[symbol] + } else { + var slen int + switch vs & 0x3 { + case 0: + slen = int(d.r.readn1()) + case 1: + slen = int(d.r.readUint16()) + case 2: + slen = int(d.r.readUint32()) + case 3: + slen = int(d.r.readUint64()) + } + s = string(d.r.readn(slen)) + d.m[symbol] = s + } + default: + decErr("Invalid d.vd for string. Expecting string:0x%x, bytearray:0x%x or symbol: 0x%x. Got: 0x%x", + bincVdString, bincVdByteArray, bincVdSymbol, d.vd) + } + d.bdRead = false + return +} + +func (d *bincDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) { + var clen int + switch d.vd { + case bincVdString, bincVdByteArray: + clen = d.decLen() + default: + decErr("Invalid d.vd for bytes. Expecting string:0x%x or bytearray:0x%x. Got: 0x%x", + bincVdString, bincVdByteArray, d.vd) + } + if clen > 0 { + // if no contents in stream, don't update the passed byteslice + if len(bs) != clen { + if len(bs) > clen { + bs = bs[:clen] + } else { + bs = make([]byte, clen) + } + bsOut = bs + changed = true + } + d.r.readb(bs) + } + d.bdRead = false + return +} + +func (d *bincDecDriver) decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) { + switch d.vd { + case bincVdCustomExt: + l := d.decLen() + xtag = d.r.readn1() + if verifyTag && xtag != tag { + decErr("Wrong extension tag. Got %b. Expecting: %v", xtag, tag) + } + xbs = d.r.readn(l) + case bincVdByteArray: + xbs, _ = d.decodeBytes(nil) + default: + decErr("Invalid d.vd for extensions (Expecting extensions or byte array). Got: 0x%x", d.vd) + } + d.bdRead = false + return +} + +func (d *bincDecDriver) decodeNaked() (v interface{}, vt valueType, decodeFurther bool) { + d.initReadNext() + + switch d.vd { + case bincVdSpecial: + switch d.vs { + case bincSpNil: + vt = valueTypeNil + case bincSpFalse: + vt = valueTypeBool + v = false + case bincSpTrue: + vt = valueTypeBool + v = true + case bincSpNan: + vt = valueTypeFloat + v = math.NaN() + case bincSpPosInf: + vt = valueTypeFloat + v = math.Inf(1) + case bincSpNegInf: + vt = valueTypeFloat + v = math.Inf(-1) + case bincSpZeroFloat: + vt = valueTypeFloat + v = float64(0) + case bincSpZero: + vt = valueTypeUint + v = int64(0) // int8(0) + case bincSpNegOne: + vt = valueTypeInt + v = int64(-1) // int8(-1) + default: + decErr("decodeNaked: Unrecognized special value 0x%x", d.vs) + } + case bincVdSmallInt: + vt = valueTypeUint + v = uint64(int8(d.vs)) + 1 // int8(d.vs) + 1 + case bincVdPosInt: + vt = valueTypeUint + v = d.decUint() + case bincVdNegInt: + vt = valueTypeInt + v = -(int64(d.decUint())) + case bincVdFloat: + vt = valueTypeFloat + v = d.decFloat() + case bincVdSymbol: + vt = valueTypeSymbol + v = d.decodeString() + case bincVdString: + vt = valueTypeString + v = d.decodeString() + case bincVdByteArray: + vt = valueTypeBytes + v, _ = d.decodeBytes(nil) + case bincVdTimestamp: + vt = valueTypeTimestamp + tt, err := decodeTime(d.r.readn(int(d.vs))) + if err != nil { + panic(err) + } + v = tt + case bincVdCustomExt: + vt = valueTypeExt + l := d.decLen() + var re RawExt + re.Tag = d.r.readn1() + re.Data = d.r.readn(l) + v = &re + vt = valueTypeExt + case bincVdArray: + vt = valueTypeArray + decodeFurther = true + case bincVdMap: + vt = valueTypeMap + decodeFurther = true + default: + decErr("decodeNaked: Unrecognized d.vd: 0x%x", d.vd) + } + + if !decodeFurther { + d.bdRead = false + } + return +} + +//------------------------------------ + +//BincHandle is a Handle for the Binc Schema-Free Encoding Format +//defined at https://github.com/ugorji/binc . +// +//BincHandle currently supports all Binc features with the following EXCEPTIONS: +// - only integers up to 64 bits of precision are supported. +// big integers are unsupported. +// - Only IEEE 754 binary32 and binary64 floats are supported (ie Go float32 and float64 types). +// extended precision and decimal IEEE 754 floats are unsupported. +// - Only UTF-8 strings supported. +// Unicode_Other Binc types (UTF16, UTF32) are currently unsupported. +//Note that these EXCEPTIONS are temporary and full support is possible and may happen soon. +type BincHandle struct { + BasicHandle +} + +func (h *BincHandle) newEncDriver(w encWriter) encDriver { + return &bincEncDriver{w: w} +} + +func (h *BincHandle) newDecDriver(r decReader) decDriver { + return &bincDecDriver{r: r} +} + +func (_ *BincHandle) writeExt() bool { + return true +} + +func (h *BincHandle) getBasicHandle() *BasicHandle { + return &h.BasicHandle +} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/decode.go b/vendor/github.com/hashicorp/go-msgpack/codec/decode.go new file mode 100644 index 00000000000..851b54ac7e7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/decode.go @@ -0,0 +1,1048 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +import ( + "io" + "reflect" + // "runtime/debug" +) + +// Some tagging information for error messages. +const ( + msgTagDec = "codec.decoder" + msgBadDesc = "Unrecognized descriptor byte" + msgDecCannotExpandArr = "cannot expand go array from %v to stream length: %v" +) + +// decReader abstracts the reading source, allowing implementations that can +// read from an io.Reader or directly off a byte slice with zero-copying. +type decReader interface { + readn(n int) []byte + readb([]byte) + readn1() uint8 + readUint16() uint16 + readUint32() uint32 + readUint64() uint64 +} + +type decDriver interface { + initReadNext() + tryDecodeAsNil() bool + currentEncodedType() valueType + isBuiltinType(rt uintptr) bool + decodeBuiltin(rt uintptr, v interface{}) + //decodeNaked: Numbers are decoded as int64, uint64, float64 only (no smaller sized number types). + decodeNaked() (v interface{}, vt valueType, decodeFurther bool) + decodeInt(bitsize uint8) (i int64) + decodeUint(bitsize uint8) (ui uint64) + decodeFloat(chkOverflow32 bool) (f float64) + decodeBool() (b bool) + // decodeString can also decode symbols + decodeString() (s string) + decodeBytes(bs []byte) (bsOut []byte, changed bool) + decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) + readMapLen() int + readArrayLen() int +} + +type DecodeOptions struct { + // An instance of MapType is used during schema-less decoding of a map in the stream. + // If nil, we use map[interface{}]interface{} + MapType reflect.Type + // An instance of SliceType is used during schema-less decoding of an array in the stream. + // If nil, we use []interface{} + SliceType reflect.Type + // ErrorIfNoField controls whether an error is returned when decoding a map + // from a codec stream into a struct, and no matching struct field is found. + ErrorIfNoField bool +} + +// ------------------------------------ + +// ioDecReader is a decReader that reads off an io.Reader +type ioDecReader struct { + r io.Reader + br io.ByteReader + x [8]byte //temp byte array re-used internally for efficiency +} + +func (z *ioDecReader) readn(n int) (bs []byte) { + if n <= 0 { + return + } + bs = make([]byte, n) + if _, err := io.ReadAtLeast(z.r, bs, n); err != nil { + panic(err) + } + return +} + +func (z *ioDecReader) readb(bs []byte) { + if _, err := io.ReadAtLeast(z.r, bs, len(bs)); err != nil { + panic(err) + } +} + +func (z *ioDecReader) readn1() uint8 { + if z.br != nil { + b, err := z.br.ReadByte() + if err != nil { + panic(err) + } + return b + } + z.readb(z.x[:1]) + return z.x[0] +} + +func (z *ioDecReader) readUint16() uint16 { + z.readb(z.x[:2]) + return bigen.Uint16(z.x[:2]) +} + +func (z *ioDecReader) readUint32() uint32 { + z.readb(z.x[:4]) + return bigen.Uint32(z.x[:4]) +} + +func (z *ioDecReader) readUint64() uint64 { + z.readb(z.x[:8]) + return bigen.Uint64(z.x[:8]) +} + +// ------------------------------------ + +// bytesDecReader is a decReader that reads off a byte slice with zero copying +type bytesDecReader struct { + b []byte // data + c int // cursor + a int // available +} + +func (z *bytesDecReader) consume(n int) (oldcursor int) { + if z.a == 0 { + panic(io.EOF) + } + if n > z.a { + decErr("Trying to read %v bytes. Only %v available", n, z.a) + } + // z.checkAvailable(n) + oldcursor = z.c + z.c = oldcursor + n + z.a = z.a - n + return +} + +func (z *bytesDecReader) readn(n int) (bs []byte) { + if n <= 0 { + return + } + c0 := z.consume(n) + bs = z.b[c0:z.c] + return +} + +func (z *bytesDecReader) readb(bs []byte) { + copy(bs, z.readn(len(bs))) +} + +func (z *bytesDecReader) readn1() uint8 { + c0 := z.consume(1) + return z.b[c0] +} + +// Use binaryEncoding helper for 4 and 8 bits, but inline it for 2 bits +// creating temp slice variable and copying it to helper function is expensive +// for just 2 bits. + +func (z *bytesDecReader) readUint16() uint16 { + c0 := z.consume(2) + return uint16(z.b[c0+1]) | uint16(z.b[c0])<<8 +} + +func (z *bytesDecReader) readUint32() uint32 { + c0 := z.consume(4) + return bigen.Uint32(z.b[c0:z.c]) +} + +func (z *bytesDecReader) readUint64() uint64 { + c0 := z.consume(8) + return bigen.Uint64(z.b[c0:z.c]) +} + +// ------------------------------------ + +// decFnInfo has methods for registering handling decoding of a specific type +// based on some characteristics (builtin, extension, reflect Kind, etc) +type decFnInfo struct { + ti *typeInfo + d *Decoder + dd decDriver + xfFn func(reflect.Value, []byte) error + xfTag byte + array bool +} + +func (f *decFnInfo) builtin(rv reflect.Value) { + f.dd.decodeBuiltin(f.ti.rtid, rv.Addr().Interface()) +} + +func (f *decFnInfo) rawExt(rv reflect.Value) { + xtag, xbs := f.dd.decodeExt(false, 0) + rv.Field(0).SetUint(uint64(xtag)) + rv.Field(1).SetBytes(xbs) +} + +func (f *decFnInfo) ext(rv reflect.Value) { + _, xbs := f.dd.decodeExt(true, f.xfTag) + if fnerr := f.xfFn(rv, xbs); fnerr != nil { + panic(fnerr) + } +} + +func (f *decFnInfo) binaryMarshal(rv reflect.Value) { + var bm binaryUnmarshaler + if f.ti.unmIndir == -1 { + bm = rv.Addr().Interface().(binaryUnmarshaler) + } else if f.ti.unmIndir == 0 { + bm = rv.Interface().(binaryUnmarshaler) + } else { + for j, k := int8(0), f.ti.unmIndir; j < k; j++ { + if rv.IsNil() { + rv.Set(reflect.New(rv.Type().Elem())) + } + rv = rv.Elem() + } + bm = rv.Interface().(binaryUnmarshaler) + } + xbs, _ := f.dd.decodeBytes(nil) + if fnerr := bm.UnmarshalBinary(xbs); fnerr != nil { + panic(fnerr) + } +} + +func (f *decFnInfo) kErr(rv reflect.Value) { + decErr("Unhandled value for kind: %v: %s", rv.Kind(), msgBadDesc) +} + +func (f *decFnInfo) kString(rv reflect.Value) { + rv.SetString(f.dd.decodeString()) +} + +func (f *decFnInfo) kBool(rv reflect.Value) { + rv.SetBool(f.dd.decodeBool()) +} + +func (f *decFnInfo) kInt(rv reflect.Value) { + rv.SetInt(f.dd.decodeInt(intBitsize)) +} + +func (f *decFnInfo) kInt64(rv reflect.Value) { + rv.SetInt(f.dd.decodeInt(64)) +} + +func (f *decFnInfo) kInt32(rv reflect.Value) { + rv.SetInt(f.dd.decodeInt(32)) +} + +func (f *decFnInfo) kInt8(rv reflect.Value) { + rv.SetInt(f.dd.decodeInt(8)) +} + +func (f *decFnInfo) kInt16(rv reflect.Value) { + rv.SetInt(f.dd.decodeInt(16)) +} + +func (f *decFnInfo) kFloat32(rv reflect.Value) { + rv.SetFloat(f.dd.decodeFloat(true)) +} + +func (f *decFnInfo) kFloat64(rv reflect.Value) { + rv.SetFloat(f.dd.decodeFloat(false)) +} + +func (f *decFnInfo) kUint8(rv reflect.Value) { + rv.SetUint(f.dd.decodeUint(8)) +} + +func (f *decFnInfo) kUint64(rv reflect.Value) { + rv.SetUint(f.dd.decodeUint(64)) +} + +func (f *decFnInfo) kUint(rv reflect.Value) { + rv.SetUint(f.dd.decodeUint(uintBitsize)) +} + +func (f *decFnInfo) kUint32(rv reflect.Value) { + rv.SetUint(f.dd.decodeUint(32)) +} + +func (f *decFnInfo) kUint16(rv reflect.Value) { + rv.SetUint(f.dd.decodeUint(16)) +} + +// func (f *decFnInfo) kPtr(rv reflect.Value) { +// debugf(">>>>>>> ??? decode kPtr called - shouldn't get called") +// if rv.IsNil() { +// rv.Set(reflect.New(rv.Type().Elem())) +// } +// f.d.decodeValue(rv.Elem()) +// } + +func (f *decFnInfo) kInterface(rv reflect.Value) { + // debugf("\t===> kInterface") + if !rv.IsNil() { + f.d.decodeValue(rv.Elem()) + return + } + // nil interface: + // use some hieristics to set the nil interface to an + // appropriate value based on the first byte read (byte descriptor bd) + v, vt, decodeFurther := f.dd.decodeNaked() + if vt == valueTypeNil { + return + } + // Cannot decode into nil interface with methods (e.g. error, io.Reader, etc) + // if non-nil value in stream. + if num := f.ti.rt.NumMethod(); num > 0 { + decErr("decodeValue: Cannot decode non-nil codec value into nil %v (%v methods)", + f.ti.rt, num) + } + var rvn reflect.Value + var useRvn bool + switch vt { + case valueTypeMap: + if f.d.h.MapType == nil { + var m2 map[interface{}]interface{} + v = &m2 + } else { + rvn = reflect.New(f.d.h.MapType).Elem() + useRvn = true + } + case valueTypeArray: + if f.d.h.SliceType == nil { + var m2 []interface{} + v = &m2 + } else { + rvn = reflect.New(f.d.h.SliceType).Elem() + useRvn = true + } + case valueTypeExt: + re := v.(*RawExt) + var bfn func(reflect.Value, []byte) error + rvn, bfn = f.d.h.getDecodeExtForTag(re.Tag) + if bfn == nil { + rvn = reflect.ValueOf(*re) + } else if fnerr := bfn(rvn, re.Data); fnerr != nil { + panic(fnerr) + } + rv.Set(rvn) + return + } + if decodeFurther { + if useRvn { + f.d.decodeValue(rvn) + } else if v != nil { + // this v is a pointer, so we need to dereference it when done + f.d.decode(v) + rvn = reflect.ValueOf(v).Elem() + useRvn = true + } + } + if useRvn { + rv.Set(rvn) + } else if v != nil { + rv.Set(reflect.ValueOf(v)) + } +} + +func (f *decFnInfo) kStruct(rv reflect.Value) { + fti := f.ti + if currEncodedType := f.dd.currentEncodedType(); currEncodedType == valueTypeMap { + containerLen := f.dd.readMapLen() + if containerLen == 0 { + return + } + tisfi := fti.sfi + for j := 0; j < containerLen; j++ { + // var rvkencname string + // ddecode(&rvkencname) + f.dd.initReadNext() + rvkencname := f.dd.decodeString() + // rvksi := ti.getForEncName(rvkencname) + if k := fti.indexForEncName(rvkencname); k > -1 { + sfik := tisfi[k] + if sfik.i != -1 { + f.d.decodeValue(rv.Field(int(sfik.i))) + } else { + f.d.decEmbeddedField(rv, sfik.is) + } + // f.d.decodeValue(ti.field(k, rv)) + } else { + if f.d.h.ErrorIfNoField { + decErr("No matching struct field found when decoding stream map with key: %v", + rvkencname) + } else { + var nilintf0 interface{} + f.d.decodeValue(reflect.ValueOf(&nilintf0).Elem()) + } + } + } + } else if currEncodedType == valueTypeArray { + containerLen := f.dd.readArrayLen() + if containerLen == 0 { + return + } + for j, si := range fti.sfip { + if j == containerLen { + break + } + if si.i != -1 { + f.d.decodeValue(rv.Field(int(si.i))) + } else { + f.d.decEmbeddedField(rv, si.is) + } + } + if containerLen > len(fti.sfip) { + // read remaining values and throw away + for j := len(fti.sfip); j < containerLen; j++ { + var nilintf0 interface{} + f.d.decodeValue(reflect.ValueOf(&nilintf0).Elem()) + } + } + } else { + decErr("Only encoded map or array can be decoded into a struct. (valueType: %x)", + currEncodedType) + } +} + +func (f *decFnInfo) kSlice(rv reflect.Value) { + // A slice can be set from a map or array in stream. + currEncodedType := f.dd.currentEncodedType() + + switch currEncodedType { + case valueTypeBytes, valueTypeString: + if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 { + if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 { + rv.SetBytes(bs2) + } + return + } + } + + if shortCircuitReflectToFastPath && rv.CanAddr() { + switch f.ti.rtid { + case intfSliceTypId: + f.d.decSliceIntf(rv.Addr().Interface().(*[]interface{}), currEncodedType, f.array) + return + case uint64SliceTypId: + f.d.decSliceUint64(rv.Addr().Interface().(*[]uint64), currEncodedType, f.array) + return + case int64SliceTypId: + f.d.decSliceInt64(rv.Addr().Interface().(*[]int64), currEncodedType, f.array) + return + case strSliceTypId: + f.d.decSliceStr(rv.Addr().Interface().(*[]string), currEncodedType, f.array) + return + } + } + + containerLen, containerLenS := decContLens(f.dd, currEncodedType) + + // an array can never return a nil slice. so no need to check f.array here. + + if rv.IsNil() { + rv.Set(reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS)) + } + + if containerLen == 0 { + return + } + + if rvcap, rvlen := rv.Len(), rv.Cap(); containerLenS > rvcap { + if f.array { // !rv.CanSet() + decErr(msgDecCannotExpandArr, rvcap, containerLenS) + } + rvn := reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS) + if rvlen > 0 { + reflect.Copy(rvn, rv) + } + rv.Set(rvn) + } else if containerLenS > rvlen { + rv.SetLen(containerLenS) + } + + for j := 0; j < containerLenS; j++ { + f.d.decodeValue(rv.Index(j)) + } +} + +func (f *decFnInfo) kArray(rv reflect.Value) { + // f.d.decodeValue(rv.Slice(0, rv.Len())) + f.kSlice(rv.Slice(0, rv.Len())) +} + +func (f *decFnInfo) kMap(rv reflect.Value) { + if shortCircuitReflectToFastPath && rv.CanAddr() { + switch f.ti.rtid { + case mapStrIntfTypId: + f.d.decMapStrIntf(rv.Addr().Interface().(*map[string]interface{})) + return + case mapIntfIntfTypId: + f.d.decMapIntfIntf(rv.Addr().Interface().(*map[interface{}]interface{})) + return + case mapInt64IntfTypId: + f.d.decMapInt64Intf(rv.Addr().Interface().(*map[int64]interface{})) + return + case mapUint64IntfTypId: + f.d.decMapUint64Intf(rv.Addr().Interface().(*map[uint64]interface{})) + return + } + } + + containerLen := f.dd.readMapLen() + + if rv.IsNil() { + rv.Set(reflect.MakeMap(f.ti.rt)) + } + + if containerLen == 0 { + return + } + + ktype, vtype := f.ti.rt.Key(), f.ti.rt.Elem() + ktypeId := reflect.ValueOf(ktype).Pointer() + for j := 0; j < containerLen; j++ { + rvk := reflect.New(ktype).Elem() + f.d.decodeValue(rvk) + + // special case if a byte array. + // if ktype == intfTyp { + if ktypeId == intfTypId { + rvk = rvk.Elem() + if rvk.Type() == uint8SliceTyp { + rvk = reflect.ValueOf(string(rvk.Bytes())) + } + } + rvv := rv.MapIndex(rvk) + if !rvv.IsValid() || !rvv.CanSet() { + rvv = reflect.New(vtype).Elem() + } + + f.d.decodeValue(rvv) + rv.SetMapIndex(rvk, rvv) + } +} + +// ---------------------------------------- + +type decFn struct { + i *decFnInfo + f func(*decFnInfo, reflect.Value) +} + +// A Decoder reads and decodes an object from an input stream in the codec format. +type Decoder struct { + r decReader + d decDriver + h *BasicHandle + f map[uintptr]decFn + x []uintptr + s []decFn +} + +// NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader. +// +// For efficiency, Users are encouraged to pass in a memory buffered writer +// (eg bufio.Reader, bytes.Buffer). +func NewDecoder(r io.Reader, h Handle) *Decoder { + z := ioDecReader{ + r: r, + } + z.br, _ = r.(io.ByteReader) + return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()} +} + +// NewDecoderBytes returns a Decoder which efficiently decodes directly +// from a byte slice with zero copying. +func NewDecoderBytes(in []byte, h Handle) *Decoder { + z := bytesDecReader{ + b: in, + a: len(in), + } + return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()} +} + +// Decode decodes the stream from reader and stores the result in the +// value pointed to by v. v cannot be a nil pointer. v can also be +// a reflect.Value of a pointer. +// +// Note that a pointer to a nil interface is not a nil pointer. +// If you do not know what type of stream it is, pass in a pointer to a nil interface. +// We will decode and store a value in that nil interface. +// +// Sample usages: +// // Decoding into a non-nil typed value +// var f float32 +// err = codec.NewDecoder(r, handle).Decode(&f) +// +// // Decoding into nil interface +// var v interface{} +// dec := codec.NewDecoder(r, handle) +// err = dec.Decode(&v) +// +// When decoding into a nil interface{}, we will decode into an appropriate value based +// on the contents of the stream: +// - Numbers are decoded as float64, int64 or uint64. +// - Other values are decoded appropriately depending on the type: +// bool, string, []byte, time.Time, etc +// - Extensions are decoded as RawExt (if no ext function registered for the tag) +// Configurations exist on the Handle to override defaults +// (e.g. for MapType, SliceType and how to decode raw bytes). +// +// When decoding into a non-nil interface{} value, the mode of encoding is based on the +// type of the value. When a value is seen: +// - If an extension is registered for it, call that extension function +// - If it implements BinaryUnmarshaler, call its UnmarshalBinary(data []byte) error +// - Else decode it based on its reflect.Kind +// +// There are some special rules when decoding into containers (slice/array/map/struct). +// Decode will typically use the stream contents to UPDATE the container. +// - A map can be decoded from a stream map, by updating matching keys. +// - A slice can be decoded from a stream array, +// by updating the first n elements, where n is length of the stream. +// - A slice can be decoded from a stream map, by decoding as if +// it contains a sequence of key-value pairs. +// - A struct can be decoded from a stream map, by updating matching fields. +// - A struct can be decoded from a stream array, +// by updating fields as they occur in the struct (by index). +// +// When decoding a stream map or array with length of 0 into a nil map or slice, +// we reset the destination map or slice to a zero-length value. +// +// However, when decoding a stream nil, we reset the destination container +// to its "zero" value (e.g. nil for slice/map, etc). +// +func (d *Decoder) Decode(v interface{}) (err error) { + defer panicToErr(&err) + d.decode(v) + return +} + +func (d *Decoder) decode(iv interface{}) { + d.d.initReadNext() + + switch v := iv.(type) { + case nil: + decErr("Cannot decode into nil.") + + case reflect.Value: + d.chkPtrValue(v) + d.decodeValue(v.Elem()) + + case *string: + *v = d.d.decodeString() + case *bool: + *v = d.d.decodeBool() + case *int: + *v = int(d.d.decodeInt(intBitsize)) + case *int8: + *v = int8(d.d.decodeInt(8)) + case *int16: + *v = int16(d.d.decodeInt(16)) + case *int32: + *v = int32(d.d.decodeInt(32)) + case *int64: + *v = d.d.decodeInt(64) + case *uint: + *v = uint(d.d.decodeUint(uintBitsize)) + case *uint8: + *v = uint8(d.d.decodeUint(8)) + case *uint16: + *v = uint16(d.d.decodeUint(16)) + case *uint32: + *v = uint32(d.d.decodeUint(32)) + case *uint64: + *v = d.d.decodeUint(64) + case *float32: + *v = float32(d.d.decodeFloat(true)) + case *float64: + *v = d.d.decodeFloat(false) + case *[]byte: + *v, _ = d.d.decodeBytes(*v) + + case *[]interface{}: + d.decSliceIntf(v, valueTypeInvalid, false) + case *[]uint64: + d.decSliceUint64(v, valueTypeInvalid, false) + case *[]int64: + d.decSliceInt64(v, valueTypeInvalid, false) + case *[]string: + d.decSliceStr(v, valueTypeInvalid, false) + case *map[string]interface{}: + d.decMapStrIntf(v) + case *map[interface{}]interface{}: + d.decMapIntfIntf(v) + case *map[uint64]interface{}: + d.decMapUint64Intf(v) + case *map[int64]interface{}: + d.decMapInt64Intf(v) + + case *interface{}: + d.decodeValue(reflect.ValueOf(iv).Elem()) + + default: + rv := reflect.ValueOf(iv) + d.chkPtrValue(rv) + d.decodeValue(rv.Elem()) + } +} + +func (d *Decoder) decodeValue(rv reflect.Value) { + d.d.initReadNext() + + if d.d.tryDecodeAsNil() { + // If value in stream is nil, set the dereferenced value to its "zero" value (if settable) + if rv.Kind() == reflect.Ptr { + if !rv.IsNil() { + rv.Set(reflect.Zero(rv.Type())) + } + return + } + // for rv.Kind() == reflect.Ptr { + // rv = rv.Elem() + // } + if rv.IsValid() { // rv.CanSet() // always settable, except it's invalid + rv.Set(reflect.Zero(rv.Type())) + } + return + } + + // If stream is not containing a nil value, then we can deref to the base + // non-pointer value, and decode into that. + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + rv.Set(reflect.New(rv.Type().Elem())) + } + rv = rv.Elem() + } + + rt := rv.Type() + rtid := reflect.ValueOf(rt).Pointer() + + // retrieve or register a focus'ed function for this type + // to eliminate need to do the retrieval multiple times + + // if d.f == nil && d.s == nil { debugf("---->Creating new dec f map for type: %v\n", rt) } + var fn decFn + var ok bool + if useMapForCodecCache { + fn, ok = d.f[rtid] + } else { + for i, v := range d.x { + if v == rtid { + fn, ok = d.s[i], true + break + } + } + } + if !ok { + // debugf("\tCreating new dec fn for type: %v\n", rt) + fi := decFnInfo{ti: getTypeInfo(rtid, rt), d: d, dd: d.d} + fn.i = &fi + // An extension can be registered for any type, regardless of the Kind + // (e.g. type BitSet int64, type MyStruct { / * unexported fields * / }, type X []int, etc. + // + // We can't check if it's an extension byte here first, because the user may have + // registered a pointer or non-pointer type, meaning we may have to recurse first + // before matching a mapped type, even though the extension byte is already detected. + // + // NOTE: if decoding into a nil interface{}, we return a non-nil + // value except even if the container registers a length of 0. + if rtid == rawExtTypId { + fn.f = (*decFnInfo).rawExt + } else if d.d.isBuiltinType(rtid) { + fn.f = (*decFnInfo).builtin + } else if xfTag, xfFn := d.h.getDecodeExt(rtid); xfFn != nil { + fi.xfTag, fi.xfFn = xfTag, xfFn + fn.f = (*decFnInfo).ext + } else if supportBinaryMarshal && fi.ti.unm { + fn.f = (*decFnInfo).binaryMarshal + } else { + switch rk := rt.Kind(); rk { + case reflect.String: + fn.f = (*decFnInfo).kString + case reflect.Bool: + fn.f = (*decFnInfo).kBool + case reflect.Int: + fn.f = (*decFnInfo).kInt + case reflect.Int64: + fn.f = (*decFnInfo).kInt64 + case reflect.Int32: + fn.f = (*decFnInfo).kInt32 + case reflect.Int8: + fn.f = (*decFnInfo).kInt8 + case reflect.Int16: + fn.f = (*decFnInfo).kInt16 + case reflect.Float32: + fn.f = (*decFnInfo).kFloat32 + case reflect.Float64: + fn.f = (*decFnInfo).kFloat64 + case reflect.Uint8: + fn.f = (*decFnInfo).kUint8 + case reflect.Uint64: + fn.f = (*decFnInfo).kUint64 + case reflect.Uint: + fn.f = (*decFnInfo).kUint + case reflect.Uint32: + fn.f = (*decFnInfo).kUint32 + case reflect.Uint16: + fn.f = (*decFnInfo).kUint16 + // case reflect.Ptr: + // fn.f = (*decFnInfo).kPtr + case reflect.Interface: + fn.f = (*decFnInfo).kInterface + case reflect.Struct: + fn.f = (*decFnInfo).kStruct + case reflect.Slice: + fn.f = (*decFnInfo).kSlice + case reflect.Array: + fi.array = true + fn.f = (*decFnInfo).kArray + case reflect.Map: + fn.f = (*decFnInfo).kMap + default: + fn.f = (*decFnInfo).kErr + } + } + if useMapForCodecCache { + if d.f == nil { + d.f = make(map[uintptr]decFn, 16) + } + d.f[rtid] = fn + } else { + d.s = append(d.s, fn) + d.x = append(d.x, rtid) + } + } + + fn.f(fn.i, rv) + + return +} + +func (d *Decoder) chkPtrValue(rv reflect.Value) { + // We can only decode into a non-nil pointer + if rv.Kind() == reflect.Ptr && !rv.IsNil() { + return + } + if !rv.IsValid() { + decErr("Cannot decode into a zero (ie invalid) reflect.Value") + } + if !rv.CanInterface() { + decErr("Cannot decode into a value without an interface: %v", rv) + } + rvi := rv.Interface() + decErr("Cannot decode into non-pointer or nil pointer. Got: %v, %T, %v", + rv.Kind(), rvi, rvi) +} + +func (d *Decoder) decEmbeddedField(rv reflect.Value, index []int) { + // d.decodeValue(rv.FieldByIndex(index)) + // nil pointers may be here; so reproduce FieldByIndex logic + enhancements + for _, j := range index { + if rv.Kind() == reflect.Ptr { + if rv.IsNil() { + rv.Set(reflect.New(rv.Type().Elem())) + } + // If a pointer, it must be a pointer to struct (based on typeInfo contract) + rv = rv.Elem() + } + rv = rv.Field(j) + } + d.decodeValue(rv) +} + +// -------------------------------------------------- + +// short circuit functions for common maps and slices + +func (d *Decoder) decSliceIntf(v *[]interface{}, currEncodedType valueType, doNotReset bool) { + _, containerLenS := decContLens(d.d, currEncodedType) + s := *v + if s == nil { + s = make([]interface{}, containerLenS, containerLenS) + } else if containerLenS > cap(s) { + if doNotReset { + decErr(msgDecCannotExpandArr, cap(s), containerLenS) + } + s = make([]interface{}, containerLenS, containerLenS) + copy(s, *v) + } else if containerLenS > len(s) { + s = s[:containerLenS] + } + for j := 0; j < containerLenS; j++ { + d.decode(&s[j]) + } + *v = s +} + +func (d *Decoder) decSliceInt64(v *[]int64, currEncodedType valueType, doNotReset bool) { + _, containerLenS := decContLens(d.d, currEncodedType) + s := *v + if s == nil { + s = make([]int64, containerLenS, containerLenS) + } else if containerLenS > cap(s) { + if doNotReset { + decErr(msgDecCannotExpandArr, cap(s), containerLenS) + } + s = make([]int64, containerLenS, containerLenS) + copy(s, *v) + } else if containerLenS > len(s) { + s = s[:containerLenS] + } + for j := 0; j < containerLenS; j++ { + // d.decode(&s[j]) + d.d.initReadNext() + s[j] = d.d.decodeInt(intBitsize) + } + *v = s +} + +func (d *Decoder) decSliceUint64(v *[]uint64, currEncodedType valueType, doNotReset bool) { + _, containerLenS := decContLens(d.d, currEncodedType) + s := *v + if s == nil { + s = make([]uint64, containerLenS, containerLenS) + } else if containerLenS > cap(s) { + if doNotReset { + decErr(msgDecCannotExpandArr, cap(s), containerLenS) + } + s = make([]uint64, containerLenS, containerLenS) + copy(s, *v) + } else if containerLenS > len(s) { + s = s[:containerLenS] + } + for j := 0; j < containerLenS; j++ { + // d.decode(&s[j]) + d.d.initReadNext() + s[j] = d.d.decodeUint(intBitsize) + } + *v = s +} + +func (d *Decoder) decSliceStr(v *[]string, currEncodedType valueType, doNotReset bool) { + _, containerLenS := decContLens(d.d, currEncodedType) + s := *v + if s == nil { + s = make([]string, containerLenS, containerLenS) + } else if containerLenS > cap(s) { + if doNotReset { + decErr(msgDecCannotExpandArr, cap(s), containerLenS) + } + s = make([]string, containerLenS, containerLenS) + copy(s, *v) + } else if containerLenS > len(s) { + s = s[:containerLenS] + } + for j := 0; j < containerLenS; j++ { + // d.decode(&s[j]) + d.d.initReadNext() + s[j] = d.d.decodeString() + } + *v = s +} + +func (d *Decoder) decMapIntfIntf(v *map[interface{}]interface{}) { + containerLen := d.d.readMapLen() + m := *v + if m == nil { + m = make(map[interface{}]interface{}, containerLen) + *v = m + } + for j := 0; j < containerLen; j++ { + var mk interface{} + d.decode(&mk) + // special case if a byte array. + if bv, bok := mk.([]byte); bok { + mk = string(bv) + } + mv := m[mk] + d.decode(&mv) + m[mk] = mv + } +} + +func (d *Decoder) decMapInt64Intf(v *map[int64]interface{}) { + containerLen := d.d.readMapLen() + m := *v + if m == nil { + m = make(map[int64]interface{}, containerLen) + *v = m + } + for j := 0; j < containerLen; j++ { + d.d.initReadNext() + mk := d.d.decodeInt(intBitsize) + mv := m[mk] + d.decode(&mv) + m[mk] = mv + } +} + +func (d *Decoder) decMapUint64Intf(v *map[uint64]interface{}) { + containerLen := d.d.readMapLen() + m := *v + if m == nil { + m = make(map[uint64]interface{}, containerLen) + *v = m + } + for j := 0; j < containerLen; j++ { + d.d.initReadNext() + mk := d.d.decodeUint(intBitsize) + mv := m[mk] + d.decode(&mv) + m[mk] = mv + } +} + +func (d *Decoder) decMapStrIntf(v *map[string]interface{}) { + containerLen := d.d.readMapLen() + m := *v + if m == nil { + m = make(map[string]interface{}, containerLen) + *v = m + } + for j := 0; j < containerLen; j++ { + d.d.initReadNext() + mk := d.d.decodeString() + mv := m[mk] + d.decode(&mv) + m[mk] = mv + } +} + +// ---------------------------------------- + +func decContLens(dd decDriver, currEncodedType valueType) (containerLen, containerLenS int) { + if currEncodedType == valueTypeInvalid { + currEncodedType = dd.currentEncodedType() + } + switch currEncodedType { + case valueTypeArray: + containerLen = dd.readArrayLen() + containerLenS = containerLen + case valueTypeMap: + containerLen = dd.readMapLen() + containerLenS = containerLen * 2 + default: + decErr("Only encoded map or array can be decoded into a slice. (valueType: %0x)", + currEncodedType) + } + return +} + +func decErr(format string, params ...interface{}) { + doPanic(msgTagDec, format, params...) +} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/encode.go b/vendor/github.com/hashicorp/go-msgpack/codec/encode.go new file mode 100644 index 00000000000..4914be0c748 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/encode.go @@ -0,0 +1,1001 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +import ( + "io" + "reflect" +) + +const ( + // Some tagging information for error messages. + msgTagEnc = "codec.encoder" + defEncByteBufSize = 1 << 6 // 4:16, 6:64, 8:256, 10:1024 + // maxTimeSecs32 = math.MaxInt32 / 60 / 24 / 366 +) + +// AsSymbolFlag defines what should be encoded as symbols. +type AsSymbolFlag uint8 + +const ( + // AsSymbolDefault is default. + // Currently, this means only encode struct field names as symbols. + // The default is subject to change. + AsSymbolDefault AsSymbolFlag = iota + + // AsSymbolAll means encode anything which could be a symbol as a symbol. + AsSymbolAll = 0xfe + + // AsSymbolNone means do not encode anything as a symbol. + AsSymbolNone = 1 << iota + + // AsSymbolMapStringKeys means encode keys in map[string]XXX as symbols. + AsSymbolMapStringKeysFlag + + // AsSymbolStructFieldName means encode struct field names as symbols. + AsSymbolStructFieldNameFlag +) + +// encWriter abstracting writing to a byte array or to an io.Writer. +type encWriter interface { + writeUint16(uint16) + writeUint32(uint32) + writeUint64(uint64) + writeb([]byte) + writestr(string) + writen1(byte) + writen2(byte, byte) + atEndOfEncode() +} + +// encDriver abstracts the actual codec (binc vs msgpack, etc) +type encDriver interface { + isBuiltinType(rt uintptr) bool + encodeBuiltin(rt uintptr, v interface{}) + encodeNil() + encodeInt(i int64) + encodeUint(i uint64) + encodeBool(b bool) + encodeFloat32(f float32) + encodeFloat64(f float64) + encodeExtPreamble(xtag byte, length int) + encodeArrayPreamble(length int) + encodeMapPreamble(length int) + encodeString(c charEncoding, v string) + encodeSymbol(v string) + encodeStringBytes(c charEncoding, v []byte) + //TODO + //encBignum(f *big.Int) + //encStringRunes(c charEncoding, v []rune) +} + +type ioEncWriterWriter interface { + WriteByte(c byte) error + WriteString(s string) (n int, err error) + Write(p []byte) (n int, err error) +} + +type ioEncStringWriter interface { + WriteString(s string) (n int, err error) +} + +type EncodeOptions struct { + // Encode a struct as an array, and not as a map. + StructToArray bool + + // AsSymbols defines what should be encoded as symbols. + // + // Encoding as symbols can reduce the encoded size significantly. + // + // However, during decoding, each string to be encoded as a symbol must + // be checked to see if it has been seen before. Consequently, encoding time + // will increase if using symbols, because string comparisons has a clear cost. + // + // Sample values: + // AsSymbolNone + // AsSymbolAll + // AsSymbolMapStringKeys + // AsSymbolMapStringKeysFlag | AsSymbolStructFieldNameFlag + AsSymbols AsSymbolFlag +} + +// --------------------------------------------- + +type simpleIoEncWriterWriter struct { + w io.Writer + bw io.ByteWriter + sw ioEncStringWriter +} + +func (o *simpleIoEncWriterWriter) WriteByte(c byte) (err error) { + if o.bw != nil { + return o.bw.WriteByte(c) + } + _, err = o.w.Write([]byte{c}) + return +} + +func (o *simpleIoEncWriterWriter) WriteString(s string) (n int, err error) { + if o.sw != nil { + return o.sw.WriteString(s) + } + return o.w.Write([]byte(s)) +} + +func (o *simpleIoEncWriterWriter) Write(p []byte) (n int, err error) { + return o.w.Write(p) +} + +// ---------------------------------------- + +// ioEncWriter implements encWriter and can write to an io.Writer implementation +type ioEncWriter struct { + w ioEncWriterWriter + x [8]byte // temp byte array re-used internally for efficiency +} + +func (z *ioEncWriter) writeUint16(v uint16) { + bigen.PutUint16(z.x[:2], v) + z.writeb(z.x[:2]) +} + +func (z *ioEncWriter) writeUint32(v uint32) { + bigen.PutUint32(z.x[:4], v) + z.writeb(z.x[:4]) +} + +func (z *ioEncWriter) writeUint64(v uint64) { + bigen.PutUint64(z.x[:8], v) + z.writeb(z.x[:8]) +} + +func (z *ioEncWriter) writeb(bs []byte) { + if len(bs) == 0 { + return + } + n, err := z.w.Write(bs) + if err != nil { + panic(err) + } + if n != len(bs) { + encErr("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", len(bs), n) + } +} + +func (z *ioEncWriter) writestr(s string) { + n, err := z.w.WriteString(s) + if err != nil { + panic(err) + } + if n != len(s) { + encErr("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", len(s), n) + } +} + +func (z *ioEncWriter) writen1(b byte) { + if err := z.w.WriteByte(b); err != nil { + panic(err) + } +} + +func (z *ioEncWriter) writen2(b1 byte, b2 byte) { + z.writen1(b1) + z.writen1(b2) +} + +func (z *ioEncWriter) atEndOfEncode() {} + +// ---------------------------------------- + +// bytesEncWriter implements encWriter and can write to an byte slice. +// It is used by Marshal function. +type bytesEncWriter struct { + b []byte + c int // cursor + out *[]byte // write out on atEndOfEncode +} + +func (z *bytesEncWriter) writeUint16(v uint16) { + c := z.grow(2) + z.b[c] = byte(v >> 8) + z.b[c+1] = byte(v) +} + +func (z *bytesEncWriter) writeUint32(v uint32) { + c := z.grow(4) + z.b[c] = byte(v >> 24) + z.b[c+1] = byte(v >> 16) + z.b[c+2] = byte(v >> 8) + z.b[c+3] = byte(v) +} + +func (z *bytesEncWriter) writeUint64(v uint64) { + c := z.grow(8) + z.b[c] = byte(v >> 56) + z.b[c+1] = byte(v >> 48) + z.b[c+2] = byte(v >> 40) + z.b[c+3] = byte(v >> 32) + z.b[c+4] = byte(v >> 24) + z.b[c+5] = byte(v >> 16) + z.b[c+6] = byte(v >> 8) + z.b[c+7] = byte(v) +} + +func (z *bytesEncWriter) writeb(s []byte) { + if len(s) == 0 { + return + } + c := z.grow(len(s)) + copy(z.b[c:], s) +} + +func (z *bytesEncWriter) writestr(s string) { + c := z.grow(len(s)) + copy(z.b[c:], s) +} + +func (z *bytesEncWriter) writen1(b1 byte) { + c := z.grow(1) + z.b[c] = b1 +} + +func (z *bytesEncWriter) writen2(b1 byte, b2 byte) { + c := z.grow(2) + z.b[c] = b1 + z.b[c+1] = b2 +} + +func (z *bytesEncWriter) atEndOfEncode() { + *(z.out) = z.b[:z.c] +} + +func (z *bytesEncWriter) grow(n int) (oldcursor int) { + oldcursor = z.c + z.c = oldcursor + n + if z.c > cap(z.b) { + // Tried using appendslice logic: (if cap < 1024, *2, else *1.25). + // However, it was too expensive, causing too many iterations of copy. + // Using bytes.Buffer model was much better (2*cap + n) + bs := make([]byte, 2*cap(z.b)+n) + copy(bs, z.b[:oldcursor]) + z.b = bs + } else if z.c > len(z.b) { + z.b = z.b[:cap(z.b)] + } + return +} + +// --------------------------------------------- + +type encFnInfo struct { + ti *typeInfo + e *Encoder + ee encDriver + xfFn func(reflect.Value) ([]byte, error) + xfTag byte +} + +func (f *encFnInfo) builtin(rv reflect.Value) { + f.ee.encodeBuiltin(f.ti.rtid, rv.Interface()) +} + +func (f *encFnInfo) rawExt(rv reflect.Value) { + f.e.encRawExt(rv.Interface().(RawExt)) +} + +func (f *encFnInfo) ext(rv reflect.Value) { + bs, fnerr := f.xfFn(rv) + if fnerr != nil { + panic(fnerr) + } + if bs == nil { + f.ee.encodeNil() + return + } + if f.e.hh.writeExt() { + f.ee.encodeExtPreamble(f.xfTag, len(bs)) + f.e.w.writeb(bs) + } else { + f.ee.encodeStringBytes(c_RAW, bs) + } + +} + +func (f *encFnInfo) binaryMarshal(rv reflect.Value) { + var bm binaryMarshaler + if f.ti.mIndir == 0 { + bm = rv.Interface().(binaryMarshaler) + } else if f.ti.mIndir == -1 { + bm = rv.Addr().Interface().(binaryMarshaler) + } else { + for j, k := int8(0), f.ti.mIndir; j < k; j++ { + if rv.IsNil() { + f.ee.encodeNil() + return + } + rv = rv.Elem() + } + bm = rv.Interface().(binaryMarshaler) + } + // debugf(">>>> binaryMarshaler: %T", rv.Interface()) + bs, fnerr := bm.MarshalBinary() + if fnerr != nil { + panic(fnerr) + } + if bs == nil { + f.ee.encodeNil() + } else { + f.ee.encodeStringBytes(c_RAW, bs) + } +} + +func (f *encFnInfo) kBool(rv reflect.Value) { + f.ee.encodeBool(rv.Bool()) +} + +func (f *encFnInfo) kString(rv reflect.Value) { + f.ee.encodeString(c_UTF8, rv.String()) +} + +func (f *encFnInfo) kFloat64(rv reflect.Value) { + f.ee.encodeFloat64(rv.Float()) +} + +func (f *encFnInfo) kFloat32(rv reflect.Value) { + f.ee.encodeFloat32(float32(rv.Float())) +} + +func (f *encFnInfo) kInt(rv reflect.Value) { + f.ee.encodeInt(rv.Int()) +} + +func (f *encFnInfo) kUint(rv reflect.Value) { + f.ee.encodeUint(rv.Uint()) +} + +func (f *encFnInfo) kInvalid(rv reflect.Value) { + f.ee.encodeNil() +} + +func (f *encFnInfo) kErr(rv reflect.Value) { + encErr("Unsupported kind: %s, for: %#v", rv.Kind(), rv) +} + +func (f *encFnInfo) kSlice(rv reflect.Value) { + if rv.IsNil() { + f.ee.encodeNil() + return + } + + if shortCircuitReflectToFastPath { + switch f.ti.rtid { + case intfSliceTypId: + f.e.encSliceIntf(rv.Interface().([]interface{})) + return + case strSliceTypId: + f.e.encSliceStr(rv.Interface().([]string)) + return + case uint64SliceTypId: + f.e.encSliceUint64(rv.Interface().([]uint64)) + return + case int64SliceTypId: + f.e.encSliceInt64(rv.Interface().([]int64)) + return + } + } + + // If in this method, then there was no extension function defined. + // So it's okay to treat as []byte. + if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 { + f.ee.encodeStringBytes(c_RAW, rv.Bytes()) + return + } + + l := rv.Len() + if f.ti.mbs { + if l%2 == 1 { + encErr("mapBySlice: invalid length (must be divisible by 2): %v", l) + } + f.ee.encodeMapPreamble(l / 2) + } else { + f.ee.encodeArrayPreamble(l) + } + if l == 0 { + return + } + for j := 0; j < l; j++ { + // TODO: Consider perf implication of encoding odd index values as symbols if type is string + f.e.encodeValue(rv.Index(j)) + } +} + +func (f *encFnInfo) kArray(rv reflect.Value) { + // We cannot share kSlice method, because the array may be non-addressable. + // E.g. type struct S{B [2]byte}; Encode(S{}) will bomb on "panic: slice of unaddressable array". + // So we have to duplicate the functionality here. + // f.e.encodeValue(rv.Slice(0, rv.Len())) + // f.kSlice(rv.Slice(0, rv.Len())) + + l := rv.Len() + // Handle an array of bytes specially (in line with what is done for slices) + if f.ti.rt.Elem().Kind() == reflect.Uint8 { + if l == 0 { + f.ee.encodeStringBytes(c_RAW, nil) + return + } + var bs []byte + if rv.CanAddr() { + bs = rv.Slice(0, l).Bytes() + } else { + bs = make([]byte, l) + for i := 0; i < l; i++ { + bs[i] = byte(rv.Index(i).Uint()) + } + } + f.ee.encodeStringBytes(c_RAW, bs) + return + } + + if f.ti.mbs { + if l%2 == 1 { + encErr("mapBySlice: invalid length (must be divisible by 2): %v", l) + } + f.ee.encodeMapPreamble(l / 2) + } else { + f.ee.encodeArrayPreamble(l) + } + if l == 0 { + return + } + for j := 0; j < l; j++ { + // TODO: Consider perf implication of encoding odd index values as symbols if type is string + f.e.encodeValue(rv.Index(j)) + } +} + +func (f *encFnInfo) kStruct(rv reflect.Value) { + fti := f.ti + newlen := len(fti.sfi) + rvals := make([]reflect.Value, newlen) + var encnames []string + e := f.e + tisfi := fti.sfip + toMap := !(fti.toArray || e.h.StructToArray) + // if toMap, use the sorted array. If toArray, use unsorted array (to match sequence in struct) + if toMap { + tisfi = fti.sfi + encnames = make([]string, newlen) + } + newlen = 0 + for _, si := range tisfi { + if si.i != -1 { + rvals[newlen] = rv.Field(int(si.i)) + } else { + rvals[newlen] = rv.FieldByIndex(si.is) + } + if toMap { + if si.omitEmpty && isEmptyValue(rvals[newlen]) { + continue + } + encnames[newlen] = si.encName + } else { + if si.omitEmpty && isEmptyValue(rvals[newlen]) { + rvals[newlen] = reflect.Value{} //encode as nil + } + } + newlen++ + } + + // debugf(">>>> kStruct: newlen: %v", newlen) + if toMap { + ee := f.ee //don't dereference everytime + ee.encodeMapPreamble(newlen) + // asSymbols := e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0 + asSymbols := e.h.AsSymbols == AsSymbolDefault || e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0 + for j := 0; j < newlen; j++ { + if asSymbols { + ee.encodeSymbol(encnames[j]) + } else { + ee.encodeString(c_UTF8, encnames[j]) + } + e.encodeValue(rvals[j]) + } + } else { + f.ee.encodeArrayPreamble(newlen) + for j := 0; j < newlen; j++ { + e.encodeValue(rvals[j]) + } + } +} + +// func (f *encFnInfo) kPtr(rv reflect.Value) { +// debugf(">>>>>>> ??? encode kPtr called - shouldn't get called") +// if rv.IsNil() { +// f.ee.encodeNil() +// return +// } +// f.e.encodeValue(rv.Elem()) +// } + +func (f *encFnInfo) kInterface(rv reflect.Value) { + if rv.IsNil() { + f.ee.encodeNil() + return + } + f.e.encodeValue(rv.Elem()) +} + +func (f *encFnInfo) kMap(rv reflect.Value) { + if rv.IsNil() { + f.ee.encodeNil() + return + } + + if shortCircuitReflectToFastPath { + switch f.ti.rtid { + case mapIntfIntfTypId: + f.e.encMapIntfIntf(rv.Interface().(map[interface{}]interface{})) + return + case mapStrIntfTypId: + f.e.encMapStrIntf(rv.Interface().(map[string]interface{})) + return + case mapStrStrTypId: + f.e.encMapStrStr(rv.Interface().(map[string]string)) + return + case mapInt64IntfTypId: + f.e.encMapInt64Intf(rv.Interface().(map[int64]interface{})) + return + case mapUint64IntfTypId: + f.e.encMapUint64Intf(rv.Interface().(map[uint64]interface{})) + return + } + } + + l := rv.Len() + f.ee.encodeMapPreamble(l) + if l == 0 { + return + } + // keyTypeIsString := f.ti.rt.Key().Kind() == reflect.String + keyTypeIsString := f.ti.rt.Key() == stringTyp + var asSymbols bool + if keyTypeIsString { + asSymbols = f.e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + } + mks := rv.MapKeys() + // for j, lmks := 0, len(mks); j < lmks; j++ { + for j := range mks { + if keyTypeIsString { + if asSymbols { + f.ee.encodeSymbol(mks[j].String()) + } else { + f.ee.encodeString(c_UTF8, mks[j].String()) + } + } else { + f.e.encodeValue(mks[j]) + } + f.e.encodeValue(rv.MapIndex(mks[j])) + } + +} + +// -------------------------------------------------- + +// encFn encapsulates the captured variables and the encode function. +// This way, we only do some calculations one times, and pass to the +// code block that should be called (encapsulated in a function) +// instead of executing the checks every time. +type encFn struct { + i *encFnInfo + f func(*encFnInfo, reflect.Value) +} + +// -------------------------------------------------- + +// An Encoder writes an object to an output stream in the codec format. +type Encoder struct { + w encWriter + e encDriver + h *BasicHandle + hh Handle + f map[uintptr]encFn + x []uintptr + s []encFn +} + +// NewEncoder returns an Encoder for encoding into an io.Writer. +// +// For efficiency, Users are encouraged to pass in a memory buffered writer +// (eg bufio.Writer, bytes.Buffer). +func NewEncoder(w io.Writer, h Handle) *Encoder { + ww, ok := w.(ioEncWriterWriter) + if !ok { + sww := simpleIoEncWriterWriter{w: w} + sww.bw, _ = w.(io.ByteWriter) + sww.sw, _ = w.(ioEncStringWriter) + ww = &sww + //ww = bufio.NewWriterSize(w, defEncByteBufSize) + } + z := ioEncWriter{ + w: ww, + } + return &Encoder{w: &z, hh: h, h: h.getBasicHandle(), e: h.newEncDriver(&z)} +} + +// NewEncoderBytes returns an encoder for encoding directly and efficiently +// into a byte slice, using zero-copying to temporary slices. +// +// It will potentially replace the output byte slice pointed to. +// After encoding, the out parameter contains the encoded contents. +func NewEncoderBytes(out *[]byte, h Handle) *Encoder { + in := *out + if in == nil { + in = make([]byte, defEncByteBufSize) + } + z := bytesEncWriter{ + b: in, + out: out, + } + return &Encoder{w: &z, hh: h, h: h.getBasicHandle(), e: h.newEncDriver(&z)} +} + +// Encode writes an object into a stream in the codec format. +// +// Encoding can be configured via the "codec" struct tag for the fields. +// +// The "codec" key in struct field's tag value is the key name, +// followed by an optional comma and options. +// +// To set an option on all fields (e.g. omitempty on all fields), you +// can create a field called _struct, and set flags on it. +// +// Struct values "usually" encode as maps. Each exported struct field is encoded unless: +// - the field's codec tag is "-", OR +// - the field is empty and its codec tag specifies the "omitempty" option. +// +// When encoding as a map, the first string in the tag (before the comma) +// is the map key string to use when encoding. +// +// However, struct values may encode as arrays. This happens when: +// - StructToArray Encode option is set, OR +// - the codec tag on the _struct field sets the "toarray" option +// +// Values with types that implement MapBySlice are encoded as stream maps. +// +// The empty values (for omitempty option) are false, 0, any nil pointer +// or interface value, and any array, slice, map, or string of length zero. +// +// Anonymous fields are encoded inline if no struct tag is present. +// Else they are encoded as regular fields. +// +// Examples: +// +// type MyStruct struct { +// _struct bool `codec:",omitempty"` //set omitempty for every field +// Field1 string `codec:"-"` //skip this field +// Field2 int `codec:"myName"` //Use key "myName" in encode stream +// Field3 int32 `codec:",omitempty"` //use key "Field3". Omit if empty. +// Field4 bool `codec:"f4,omitempty"` //use key "f4". Omit if empty. +// ... +// } +// +// type MyStruct struct { +// _struct bool `codec:",omitempty,toarray"` //set omitempty for every field +// //and encode struct as an array +// } +// +// The mode of encoding is based on the type of the value. When a value is seen: +// - If an extension is registered for it, call that extension function +// - If it implements BinaryMarshaler, call its MarshalBinary() (data []byte, err error) +// - Else encode it based on its reflect.Kind +// +// Note that struct field names and keys in map[string]XXX will be treated as symbols. +// Some formats support symbols (e.g. binc) and will properly encode the string +// only once in the stream, and use a tag to refer to it thereafter. +func (e *Encoder) Encode(v interface{}) (err error) { + defer panicToErr(&err) + e.encode(v) + e.w.atEndOfEncode() + return +} + +func (e *Encoder) encode(iv interface{}) { + switch v := iv.(type) { + case nil: + e.e.encodeNil() + + case reflect.Value: + e.encodeValue(v) + + case string: + e.e.encodeString(c_UTF8, v) + case bool: + e.e.encodeBool(v) + case int: + e.e.encodeInt(int64(v)) + case int8: + e.e.encodeInt(int64(v)) + case int16: + e.e.encodeInt(int64(v)) + case int32: + e.e.encodeInt(int64(v)) + case int64: + e.e.encodeInt(v) + case uint: + e.e.encodeUint(uint64(v)) + case uint8: + e.e.encodeUint(uint64(v)) + case uint16: + e.e.encodeUint(uint64(v)) + case uint32: + e.e.encodeUint(uint64(v)) + case uint64: + e.e.encodeUint(v) + case float32: + e.e.encodeFloat32(v) + case float64: + e.e.encodeFloat64(v) + + case []interface{}: + e.encSliceIntf(v) + case []string: + e.encSliceStr(v) + case []int64: + e.encSliceInt64(v) + case []uint64: + e.encSliceUint64(v) + case []uint8: + e.e.encodeStringBytes(c_RAW, v) + + case map[interface{}]interface{}: + e.encMapIntfIntf(v) + case map[string]interface{}: + e.encMapStrIntf(v) + case map[string]string: + e.encMapStrStr(v) + case map[int64]interface{}: + e.encMapInt64Intf(v) + case map[uint64]interface{}: + e.encMapUint64Intf(v) + + case *string: + e.e.encodeString(c_UTF8, *v) + case *bool: + e.e.encodeBool(*v) + case *int: + e.e.encodeInt(int64(*v)) + case *int8: + e.e.encodeInt(int64(*v)) + case *int16: + e.e.encodeInt(int64(*v)) + case *int32: + e.e.encodeInt(int64(*v)) + case *int64: + e.e.encodeInt(*v) + case *uint: + e.e.encodeUint(uint64(*v)) + case *uint8: + e.e.encodeUint(uint64(*v)) + case *uint16: + e.e.encodeUint(uint64(*v)) + case *uint32: + e.e.encodeUint(uint64(*v)) + case *uint64: + e.e.encodeUint(*v) + case *float32: + e.e.encodeFloat32(*v) + case *float64: + e.e.encodeFloat64(*v) + + case *[]interface{}: + e.encSliceIntf(*v) + case *[]string: + e.encSliceStr(*v) + case *[]int64: + e.encSliceInt64(*v) + case *[]uint64: + e.encSliceUint64(*v) + case *[]uint8: + e.e.encodeStringBytes(c_RAW, *v) + + case *map[interface{}]interface{}: + e.encMapIntfIntf(*v) + case *map[string]interface{}: + e.encMapStrIntf(*v) + case *map[string]string: + e.encMapStrStr(*v) + case *map[int64]interface{}: + e.encMapInt64Intf(*v) + case *map[uint64]interface{}: + e.encMapUint64Intf(*v) + + default: + e.encodeValue(reflect.ValueOf(iv)) + } +} + +func (e *Encoder) encodeValue(rv reflect.Value) { + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + e.e.encodeNil() + return + } + rv = rv.Elem() + } + + rt := rv.Type() + rtid := reflect.ValueOf(rt).Pointer() + + // if e.f == nil && e.s == nil { debugf("---->Creating new enc f map for type: %v\n", rt) } + var fn encFn + var ok bool + if useMapForCodecCache { + fn, ok = e.f[rtid] + } else { + for i, v := range e.x { + if v == rtid { + fn, ok = e.s[i], true + break + } + } + } + if !ok { + // debugf("\tCreating new enc fn for type: %v\n", rt) + fi := encFnInfo{ti: getTypeInfo(rtid, rt), e: e, ee: e.e} + fn.i = &fi + if rtid == rawExtTypId { + fn.f = (*encFnInfo).rawExt + } else if e.e.isBuiltinType(rtid) { + fn.f = (*encFnInfo).builtin + } else if xfTag, xfFn := e.h.getEncodeExt(rtid); xfFn != nil { + fi.xfTag, fi.xfFn = xfTag, xfFn + fn.f = (*encFnInfo).ext + } else if supportBinaryMarshal && fi.ti.m { + fn.f = (*encFnInfo).binaryMarshal + } else { + switch rk := rt.Kind(); rk { + case reflect.Bool: + fn.f = (*encFnInfo).kBool + case reflect.String: + fn.f = (*encFnInfo).kString + case reflect.Float64: + fn.f = (*encFnInfo).kFloat64 + case reflect.Float32: + fn.f = (*encFnInfo).kFloat32 + case reflect.Int, reflect.Int8, reflect.Int64, reflect.Int32, reflect.Int16: + fn.f = (*encFnInfo).kInt + case reflect.Uint8, reflect.Uint64, reflect.Uint, reflect.Uint32, reflect.Uint16: + fn.f = (*encFnInfo).kUint + case reflect.Invalid: + fn.f = (*encFnInfo).kInvalid + case reflect.Slice: + fn.f = (*encFnInfo).kSlice + case reflect.Array: + fn.f = (*encFnInfo).kArray + case reflect.Struct: + fn.f = (*encFnInfo).kStruct + // case reflect.Ptr: + // fn.f = (*encFnInfo).kPtr + case reflect.Interface: + fn.f = (*encFnInfo).kInterface + case reflect.Map: + fn.f = (*encFnInfo).kMap + default: + fn.f = (*encFnInfo).kErr + } + } + if useMapForCodecCache { + if e.f == nil { + e.f = make(map[uintptr]encFn, 16) + } + e.f[rtid] = fn + } else { + e.s = append(e.s, fn) + e.x = append(e.x, rtid) + } + } + + fn.f(fn.i, rv) + +} + +func (e *Encoder) encRawExt(re RawExt) { + if re.Data == nil { + e.e.encodeNil() + return + } + if e.hh.writeExt() { + e.e.encodeExtPreamble(re.Tag, len(re.Data)) + e.w.writeb(re.Data) + } else { + e.e.encodeStringBytes(c_RAW, re.Data) + } +} + +// --------------------------------------------- +// short circuit functions for common maps and slices + +func (e *Encoder) encSliceIntf(v []interface{}) { + e.e.encodeArrayPreamble(len(v)) + for _, v2 := range v { + e.encode(v2) + } +} + +func (e *Encoder) encSliceStr(v []string) { + e.e.encodeArrayPreamble(len(v)) + for _, v2 := range v { + e.e.encodeString(c_UTF8, v2) + } +} + +func (e *Encoder) encSliceInt64(v []int64) { + e.e.encodeArrayPreamble(len(v)) + for _, v2 := range v { + e.e.encodeInt(v2) + } +} + +func (e *Encoder) encSliceUint64(v []uint64) { + e.e.encodeArrayPreamble(len(v)) + for _, v2 := range v { + e.e.encodeUint(v2) + } +} + +func (e *Encoder) encMapStrStr(v map[string]string) { + e.e.encodeMapPreamble(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + for k2, v2 := range v { + if asSymbols { + e.e.encodeSymbol(k2) + } else { + e.e.encodeString(c_UTF8, k2) + } + e.e.encodeString(c_UTF8, v2) + } +} + +func (e *Encoder) encMapStrIntf(v map[string]interface{}) { + e.e.encodeMapPreamble(len(v)) + asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0 + for k2, v2 := range v { + if asSymbols { + e.e.encodeSymbol(k2) + } else { + e.e.encodeString(c_UTF8, k2) + } + e.encode(v2) + } +} + +func (e *Encoder) encMapInt64Intf(v map[int64]interface{}) { + e.e.encodeMapPreamble(len(v)) + for k2, v2 := range v { + e.e.encodeInt(k2) + e.encode(v2) + } +} + +func (e *Encoder) encMapUint64Intf(v map[uint64]interface{}) { + e.e.encodeMapPreamble(len(v)) + for k2, v2 := range v { + e.e.encodeUint(uint64(k2)) + e.encode(v2) + } +} + +func (e *Encoder) encMapIntfIntf(v map[interface{}]interface{}) { + e.e.encodeMapPreamble(len(v)) + for k2, v2 := range v { + e.encode(k2) + e.encode(v2) + } +} + +// ---------------------------------------- + +func encErr(format string, params ...interface{}) { + doPanic(msgTagEnc, format, params...) +} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/helper.go b/vendor/github.com/hashicorp/go-msgpack/codec/helper.go new file mode 100644 index 00000000000..e6dc0563f09 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/helper.go @@ -0,0 +1,589 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +// Contains code shared by both encode and decode. + +import ( + "encoding/binary" + "fmt" + "math" + "reflect" + "sort" + "strings" + "sync" + "time" + "unicode" + "unicode/utf8" +) + +const ( + structTagName = "codec" + + // Support + // encoding.BinaryMarshaler: MarshalBinary() (data []byte, err error) + // encoding.BinaryUnmarshaler: UnmarshalBinary(data []byte) error + // This constant flag will enable or disable it. + supportBinaryMarshal = true + + // Each Encoder or Decoder uses a cache of functions based on conditionals, + // so that the conditionals are not run every time. + // + // Either a map or a slice is used to keep track of the functions. + // The map is more natural, but has a higher cost than a slice/array. + // This flag (useMapForCodecCache) controls which is used. + useMapForCodecCache = false + + // For some common container types, we can short-circuit an elaborate + // reflection dance and call encode/decode directly. + // The currently supported types are: + // - slices of strings, or id's (int64,uint64) or interfaces. + // - maps of str->str, str->intf, id(int64,uint64)->intf, intf->intf + shortCircuitReflectToFastPath = true + + // for debugging, set this to false, to catch panic traces. + // Note that this will always cause rpc tests to fail, since they need io.EOF sent via panic. + recoverPanicToErr = true +) + +type charEncoding uint8 + +const ( + c_RAW charEncoding = iota + c_UTF8 + c_UTF16LE + c_UTF16BE + c_UTF32LE + c_UTF32BE +) + +// valueType is the stream type +type valueType uint8 + +const ( + valueTypeUnset valueType = iota + valueTypeNil + valueTypeInt + valueTypeUint + valueTypeFloat + valueTypeBool + valueTypeString + valueTypeSymbol + valueTypeBytes + valueTypeMap + valueTypeArray + valueTypeTimestamp + valueTypeExt + + valueTypeInvalid = 0xff +) + +var ( + bigen = binary.BigEndian + structInfoFieldName = "_struct" + + cachedTypeInfo = make(map[uintptr]*typeInfo, 4) + cachedTypeInfoMutex sync.RWMutex + + intfSliceTyp = reflect.TypeOf([]interface{}(nil)) + intfTyp = intfSliceTyp.Elem() + + strSliceTyp = reflect.TypeOf([]string(nil)) + boolSliceTyp = reflect.TypeOf([]bool(nil)) + uintSliceTyp = reflect.TypeOf([]uint(nil)) + uint8SliceTyp = reflect.TypeOf([]uint8(nil)) + uint16SliceTyp = reflect.TypeOf([]uint16(nil)) + uint32SliceTyp = reflect.TypeOf([]uint32(nil)) + uint64SliceTyp = reflect.TypeOf([]uint64(nil)) + intSliceTyp = reflect.TypeOf([]int(nil)) + int8SliceTyp = reflect.TypeOf([]int8(nil)) + int16SliceTyp = reflect.TypeOf([]int16(nil)) + int32SliceTyp = reflect.TypeOf([]int32(nil)) + int64SliceTyp = reflect.TypeOf([]int64(nil)) + float32SliceTyp = reflect.TypeOf([]float32(nil)) + float64SliceTyp = reflect.TypeOf([]float64(nil)) + + mapIntfIntfTyp = reflect.TypeOf(map[interface{}]interface{}(nil)) + mapStrIntfTyp = reflect.TypeOf(map[string]interface{}(nil)) + mapStrStrTyp = reflect.TypeOf(map[string]string(nil)) + + mapIntIntfTyp = reflect.TypeOf(map[int]interface{}(nil)) + mapInt64IntfTyp = reflect.TypeOf(map[int64]interface{}(nil)) + mapUintIntfTyp = reflect.TypeOf(map[uint]interface{}(nil)) + mapUint64IntfTyp = reflect.TypeOf(map[uint64]interface{}(nil)) + + stringTyp = reflect.TypeOf("") + timeTyp = reflect.TypeOf(time.Time{}) + rawExtTyp = reflect.TypeOf(RawExt{}) + + mapBySliceTyp = reflect.TypeOf((*MapBySlice)(nil)).Elem() + binaryMarshalerTyp = reflect.TypeOf((*binaryMarshaler)(nil)).Elem() + binaryUnmarshalerTyp = reflect.TypeOf((*binaryUnmarshaler)(nil)).Elem() + + rawExtTypId = reflect.ValueOf(rawExtTyp).Pointer() + intfTypId = reflect.ValueOf(intfTyp).Pointer() + timeTypId = reflect.ValueOf(timeTyp).Pointer() + + intfSliceTypId = reflect.ValueOf(intfSliceTyp).Pointer() + strSliceTypId = reflect.ValueOf(strSliceTyp).Pointer() + + boolSliceTypId = reflect.ValueOf(boolSliceTyp).Pointer() + uintSliceTypId = reflect.ValueOf(uintSliceTyp).Pointer() + uint8SliceTypId = reflect.ValueOf(uint8SliceTyp).Pointer() + uint16SliceTypId = reflect.ValueOf(uint16SliceTyp).Pointer() + uint32SliceTypId = reflect.ValueOf(uint32SliceTyp).Pointer() + uint64SliceTypId = reflect.ValueOf(uint64SliceTyp).Pointer() + intSliceTypId = reflect.ValueOf(intSliceTyp).Pointer() + int8SliceTypId = reflect.ValueOf(int8SliceTyp).Pointer() + int16SliceTypId = reflect.ValueOf(int16SliceTyp).Pointer() + int32SliceTypId = reflect.ValueOf(int32SliceTyp).Pointer() + int64SliceTypId = reflect.ValueOf(int64SliceTyp).Pointer() + float32SliceTypId = reflect.ValueOf(float32SliceTyp).Pointer() + float64SliceTypId = reflect.ValueOf(float64SliceTyp).Pointer() + + mapStrStrTypId = reflect.ValueOf(mapStrStrTyp).Pointer() + mapIntfIntfTypId = reflect.ValueOf(mapIntfIntfTyp).Pointer() + mapStrIntfTypId = reflect.ValueOf(mapStrIntfTyp).Pointer() + mapIntIntfTypId = reflect.ValueOf(mapIntIntfTyp).Pointer() + mapInt64IntfTypId = reflect.ValueOf(mapInt64IntfTyp).Pointer() + mapUintIntfTypId = reflect.ValueOf(mapUintIntfTyp).Pointer() + mapUint64IntfTypId = reflect.ValueOf(mapUint64IntfTyp).Pointer() + // Id = reflect.ValueOf().Pointer() + // mapBySliceTypId = reflect.ValueOf(mapBySliceTyp).Pointer() + + binaryMarshalerTypId = reflect.ValueOf(binaryMarshalerTyp).Pointer() + binaryUnmarshalerTypId = reflect.ValueOf(binaryUnmarshalerTyp).Pointer() + + intBitsize uint8 = uint8(reflect.TypeOf(int(0)).Bits()) + uintBitsize uint8 = uint8(reflect.TypeOf(uint(0)).Bits()) + + bsAll0x00 = []byte{0, 0, 0, 0, 0, 0, 0, 0} + bsAll0xff = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} +) + +type binaryUnmarshaler interface { + UnmarshalBinary(data []byte) error +} + +type binaryMarshaler interface { + MarshalBinary() (data []byte, err error) +} + +// MapBySlice represents a slice which should be encoded as a map in the stream. +// The slice contains a sequence of key-value pairs. +type MapBySlice interface { + MapBySlice() +} + +// WARNING: DO NOT USE DIRECTLY. EXPORTED FOR GODOC BENEFIT. WILL BE REMOVED. +// +// BasicHandle encapsulates the common options and extension functions. +type BasicHandle struct { + extHandle + EncodeOptions + DecodeOptions +} + +// Handle is the interface for a specific encoding format. +// +// Typically, a Handle is pre-configured before first time use, +// and not modified while in use. Such a pre-configured Handle +// is safe for concurrent access. +type Handle interface { + writeExt() bool + getBasicHandle() *BasicHandle + newEncDriver(w encWriter) encDriver + newDecDriver(r decReader) decDriver +} + +// RawExt represents raw unprocessed extension data. +type RawExt struct { + Tag byte + Data []byte +} + +type extTypeTagFn struct { + rtid uintptr + rt reflect.Type + tag byte + encFn func(reflect.Value) ([]byte, error) + decFn func(reflect.Value, []byte) error +} + +type extHandle []*extTypeTagFn + +// AddExt registers an encode and decode function for a reflect.Type. +// Note that the type must be a named type, and specifically not +// a pointer or Interface. An error is returned if that is not honored. +// +// To Deregister an ext, call AddExt with 0 tag, nil encfn and nil decfn. +func (o *extHandle) AddExt( + rt reflect.Type, + tag byte, + encfn func(reflect.Value) ([]byte, error), + decfn func(reflect.Value, []byte) error, +) (err error) { + // o is a pointer, because we may need to initialize it + if rt.PkgPath() == "" || rt.Kind() == reflect.Interface { + err = fmt.Errorf("codec.Handle.AddExt: Takes named type, especially not a pointer or interface: %T", + reflect.Zero(rt).Interface()) + return + } + + // o cannot be nil, since it is always embedded in a Handle. + // if nil, let it panic. + // if o == nil { + // err = errors.New("codec.Handle.AddExt: extHandle cannot be a nil pointer.") + // return + // } + + rtid := reflect.ValueOf(rt).Pointer() + for _, v := range *o { + if v.rtid == rtid { + v.tag, v.encFn, v.decFn = tag, encfn, decfn + return + } + } + + *o = append(*o, &extTypeTagFn{rtid, rt, tag, encfn, decfn}) + return +} + +func (o extHandle) getExt(rtid uintptr) *extTypeTagFn { + for _, v := range o { + if v.rtid == rtid { + return v + } + } + return nil +} + +func (o extHandle) getExtForTag(tag byte) *extTypeTagFn { + for _, v := range o { + if v.tag == tag { + return v + } + } + return nil +} + +func (o extHandle) getDecodeExtForTag(tag byte) ( + rv reflect.Value, fn func(reflect.Value, []byte) error) { + if x := o.getExtForTag(tag); x != nil { + // ext is only registered for base + rv = reflect.New(x.rt).Elem() + fn = x.decFn + } + return +} + +func (o extHandle) getDecodeExt(rtid uintptr) (tag byte, fn func(reflect.Value, []byte) error) { + if x := o.getExt(rtid); x != nil { + tag = x.tag + fn = x.decFn + } + return +} + +func (o extHandle) getEncodeExt(rtid uintptr) (tag byte, fn func(reflect.Value) ([]byte, error)) { + if x := o.getExt(rtid); x != nil { + tag = x.tag + fn = x.encFn + } + return +} + +type structFieldInfo struct { + encName string // encode name + + // only one of 'i' or 'is' can be set. If 'i' is -1, then 'is' has been set. + + is []int // (recursive/embedded) field index in struct + i int16 // field index in struct + omitEmpty bool + toArray bool // if field is _struct, is the toArray set? + + // tag string // tag + // name string // field name + // encNameBs []byte // encoded name as byte stream + // ikind int // kind of the field as an int i.e. int(reflect.Kind) +} + +func parseStructFieldInfo(fname string, stag string) *structFieldInfo { + if fname == "" { + panic("parseStructFieldInfo: No Field Name") + } + si := structFieldInfo{ + // name: fname, + encName: fname, + // tag: stag, + } + + if stag != "" { + for i, s := range strings.Split(stag, ",") { + if i == 0 { + if s != "" { + si.encName = s + } + } else { + switch s { + case "omitempty": + si.omitEmpty = true + case "toarray": + si.toArray = true + } + } + } + } + // si.encNameBs = []byte(si.encName) + return &si +} + +type sfiSortedByEncName []*structFieldInfo + +func (p sfiSortedByEncName) Len() int { + return len(p) +} + +func (p sfiSortedByEncName) Less(i, j int) bool { + return p[i].encName < p[j].encName +} + +func (p sfiSortedByEncName) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +// typeInfo keeps information about each type referenced in the encode/decode sequence. +// +// During an encode/decode sequence, we work as below: +// - If base is a built in type, en/decode base value +// - If base is registered as an extension, en/decode base value +// - If type is binary(M/Unm)arshaler, call Binary(M/Unm)arshal method +// - Else decode appropriately based on the reflect.Kind +type typeInfo struct { + sfi []*structFieldInfo // sorted. Used when enc/dec struct to map. + sfip []*structFieldInfo // unsorted. Used when enc/dec struct to array. + + rt reflect.Type + rtid uintptr + + // baseId gives pointer to the base reflect.Type, after deferencing + // the pointers. E.g. base type of ***time.Time is time.Time. + base reflect.Type + baseId uintptr + baseIndir int8 // number of indirections to get to base + + mbs bool // base type (T or *T) is a MapBySlice + + m bool // base type (T or *T) is a binaryMarshaler + unm bool // base type (T or *T) is a binaryUnmarshaler + mIndir int8 // number of indirections to get to binaryMarshaler type + unmIndir int8 // number of indirections to get to binaryUnmarshaler type + toArray bool // whether this (struct) type should be encoded as an array +} + +func (ti *typeInfo) indexForEncName(name string) int { + //tisfi := ti.sfi + const binarySearchThreshold = 16 + if sfilen := len(ti.sfi); sfilen < binarySearchThreshold { + // linear search. faster than binary search in my testing up to 16-field structs. + for i, si := range ti.sfi { + if si.encName == name { + return i + } + } + } else { + // binary search. adapted from sort/search.go. + h, i, j := 0, 0, sfilen + for i < j { + h = i + (j-i)/2 + if ti.sfi[h].encName < name { + i = h + 1 + } else { + j = h + } + } + if i < sfilen && ti.sfi[i].encName == name { + return i + } + } + return -1 +} + +func getTypeInfo(rtid uintptr, rt reflect.Type) (pti *typeInfo) { + var ok bool + cachedTypeInfoMutex.RLock() + pti, ok = cachedTypeInfo[rtid] + cachedTypeInfoMutex.RUnlock() + if ok { + return + } + + cachedTypeInfoMutex.Lock() + defer cachedTypeInfoMutex.Unlock() + if pti, ok = cachedTypeInfo[rtid]; ok { + return + } + + ti := typeInfo{rt: rt, rtid: rtid} + pti = &ti + + var indir int8 + if ok, indir = implementsIntf(rt, binaryMarshalerTyp); ok { + ti.m, ti.mIndir = true, indir + } + if ok, indir = implementsIntf(rt, binaryUnmarshalerTyp); ok { + ti.unm, ti.unmIndir = true, indir + } + if ok, _ = implementsIntf(rt, mapBySliceTyp); ok { + ti.mbs = true + } + + pt := rt + var ptIndir int8 + // for ; pt.Kind() == reflect.Ptr; pt, ptIndir = pt.Elem(), ptIndir+1 { } + for pt.Kind() == reflect.Ptr { + pt = pt.Elem() + ptIndir++ + } + if ptIndir == 0 { + ti.base = rt + ti.baseId = rtid + } else { + ti.base = pt + ti.baseId = reflect.ValueOf(pt).Pointer() + ti.baseIndir = ptIndir + } + + if rt.Kind() == reflect.Struct { + var siInfo *structFieldInfo + if f, ok := rt.FieldByName(structInfoFieldName); ok { + siInfo = parseStructFieldInfo(structInfoFieldName, f.Tag.Get(structTagName)) + ti.toArray = siInfo.toArray + } + sfip := make([]*structFieldInfo, 0, rt.NumField()) + rgetTypeInfo(rt, nil, make(map[string]bool), &sfip, siInfo) + + // // try to put all si close together + // const tryToPutAllStructFieldInfoTogether = true + // if tryToPutAllStructFieldInfoTogether { + // sfip2 := make([]structFieldInfo, len(sfip)) + // for i, si := range sfip { + // sfip2[i] = *si + // } + // for i := range sfip { + // sfip[i] = &sfip2[i] + // } + // } + + ti.sfip = make([]*structFieldInfo, len(sfip)) + ti.sfi = make([]*structFieldInfo, len(sfip)) + copy(ti.sfip, sfip) + sort.Sort(sfiSortedByEncName(sfip)) + copy(ti.sfi, sfip) + } + // sfi = sfip + cachedTypeInfo[rtid] = pti + return +} + +func rgetTypeInfo(rt reflect.Type, indexstack []int, fnameToHastag map[string]bool, + sfi *[]*structFieldInfo, siInfo *structFieldInfo, +) { + // for rt.Kind() == reflect.Ptr { + // // indexstack = append(indexstack, 0) + // rt = rt.Elem() + // } + for j := 0; j < rt.NumField(); j++ { + f := rt.Field(j) + stag := f.Tag.Get(structTagName) + if stag == "-" { + continue + } + if r1, _ := utf8.DecodeRuneInString(f.Name); r1 == utf8.RuneError || !unicode.IsUpper(r1) { + continue + } + // if anonymous and there is no struct tag and its a struct (or pointer to struct), inline it. + if f.Anonymous && stag == "" { + ft := f.Type + for ft.Kind() == reflect.Ptr { + ft = ft.Elem() + } + if ft.Kind() == reflect.Struct { + indexstack2 := append(append(make([]int, 0, len(indexstack)+4), indexstack...), j) + rgetTypeInfo(ft, indexstack2, fnameToHastag, sfi, siInfo) + continue + } + } + // do not let fields with same name in embedded structs override field at higher level. + // this must be done after anonymous check, to allow anonymous field + // still include their child fields + if _, ok := fnameToHastag[f.Name]; ok { + continue + } + si := parseStructFieldInfo(f.Name, stag) + // si.ikind = int(f.Type.Kind()) + if len(indexstack) == 0 { + si.i = int16(j) + } else { + si.i = -1 + si.is = append(append(make([]int, 0, len(indexstack)+4), indexstack...), j) + } + + if siInfo != nil { + if siInfo.omitEmpty { + si.omitEmpty = true + } + } + *sfi = append(*sfi, si) + fnameToHastag[f.Name] = stag != "" + } +} + +func panicToErr(err *error) { + if recoverPanicToErr { + if x := recover(); x != nil { + //debug.PrintStack() + panicValToErr(x, err) + } + } +} + +func doPanic(tag string, format string, params ...interface{}) { + params2 := make([]interface{}, len(params)+1) + params2[0] = tag + copy(params2[1:], params) + panic(fmt.Errorf("%s: "+format, params2...)) +} + +func checkOverflowFloat32(f float64, doCheck bool) { + if !doCheck { + return + } + // check overflow (logic adapted from std pkg reflect/value.go OverflowFloat() + f2 := f + if f2 < 0 { + f2 = -f + } + if math.MaxFloat32 < f2 && f2 <= math.MaxFloat64 { + decErr("Overflow float32 value: %v", f2) + } +} + +func checkOverflow(ui uint64, i int64, bitsize uint8) { + // check overflow (logic adapted from std pkg reflect/value.go OverflowUint() + if bitsize == 0 { + return + } + if i != 0 { + if trunc := (i << (64 - bitsize)) >> (64 - bitsize); i != trunc { + decErr("Overflow int value: %v", i) + } + } + if ui != 0 { + if trunc := (ui << (64 - bitsize)) >> (64 - bitsize); ui != trunc { + decErr("Overflow uint value: %v", ui) + } + } +} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/helper_internal.go b/vendor/github.com/hashicorp/go-msgpack/codec/helper_internal.go new file mode 100644 index 00000000000..58417da958f --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/helper_internal.go @@ -0,0 +1,127 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +// All non-std package dependencies live in this file, +// so porting to different environment is easy (just update functions). + +import ( + "errors" + "fmt" + "math" + "reflect" +) + +var ( + raisePanicAfterRecover = false + debugging = true +) + +func panicValToErr(panicVal interface{}, err *error) { + switch xerr := panicVal.(type) { + case error: + *err = xerr + case string: + *err = errors.New(xerr) + default: + *err = fmt.Errorf("%v", panicVal) + } + if raisePanicAfterRecover { + panic(panicVal) + } + return +} + +func isEmptyValueDeref(v reflect.Value, deref bool) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + if deref { + if v.IsNil() { + return true + } + return isEmptyValueDeref(v.Elem(), deref) + } else { + return v.IsNil() + } + case reflect.Struct: + // return true if all fields are empty. else return false. + + // we cannot use equality check, because some fields may be maps/slices/etc + // and consequently the structs are not comparable. + // return v.Interface() == reflect.Zero(v.Type()).Interface() + for i, n := 0, v.NumField(); i < n; i++ { + if !isEmptyValueDeref(v.Field(i), deref) { + return false + } + } + return true + } + return false +} + +func isEmptyValue(v reflect.Value) bool { + return isEmptyValueDeref(v, true) +} + +func debugf(format string, args ...interface{}) { + if debugging { + if len(format) == 0 || format[len(format)-1] != '\n' { + format = format + "\n" + } + fmt.Printf(format, args...) + } +} + +func pruneSignExt(v []byte, pos bool) (n int) { + if len(v) < 2 { + } else if pos && v[0] == 0 { + for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ { + } + } else if !pos && v[0] == 0xff { + for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ { + } + } + return +} + +func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) { + if typ == nil { + return + } + rt := typ + // The type might be a pointer and we need to keep + // dereferencing to the base type until we find an implementation. + for { + if rt.Implements(iTyp) { + return true, indir + } + if p := rt; p.Kind() == reflect.Ptr { + indir++ + if indir >= math.MaxInt8 { // insane number of indirections + return false, 0 + } + rt = p.Elem() + continue + } + break + } + // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. + if typ.Kind() != reflect.Ptr { + // Not a pointer, but does the pointer work? + if reflect.PtrTo(typ).Implements(iTyp) { + return true, -1 + } + } + return false, 0 +} diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/msgpack.go b/vendor/github.com/hashicorp/go-msgpack/codec/msgpack.go new file mode 100644 index 00000000000..da0500d1922 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/msgpack.go @@ -0,0 +1,816 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +/* +MSGPACK + +Msgpack-c implementation powers the c, c++, python, ruby, etc libraries. +We need to maintain compatibility with it and how it encodes integer values +without caring about the type. + +For compatibility with behaviour of msgpack-c reference implementation: + - Go intX (>0) and uintX + IS ENCODED AS + msgpack +ve fixnum, unsigned + - Go intX (<0) + IS ENCODED AS + msgpack -ve fixnum, signed + +*/ +package codec + +import ( + "fmt" + "io" + "math" + "net/rpc" +) + +const ( + mpPosFixNumMin byte = 0x00 + mpPosFixNumMax = 0x7f + mpFixMapMin = 0x80 + mpFixMapMax = 0x8f + mpFixArrayMin = 0x90 + mpFixArrayMax = 0x9f + mpFixStrMin = 0xa0 + mpFixStrMax = 0xbf + mpNil = 0xc0 + _ = 0xc1 + mpFalse = 0xc2 + mpTrue = 0xc3 + mpFloat = 0xca + mpDouble = 0xcb + mpUint8 = 0xcc + mpUint16 = 0xcd + mpUint32 = 0xce + mpUint64 = 0xcf + mpInt8 = 0xd0 + mpInt16 = 0xd1 + mpInt32 = 0xd2 + mpInt64 = 0xd3 + + // extensions below + mpBin8 = 0xc4 + mpBin16 = 0xc5 + mpBin32 = 0xc6 + mpExt8 = 0xc7 + mpExt16 = 0xc8 + mpExt32 = 0xc9 + mpFixExt1 = 0xd4 + mpFixExt2 = 0xd5 + mpFixExt4 = 0xd6 + mpFixExt8 = 0xd7 + mpFixExt16 = 0xd8 + + mpStr8 = 0xd9 // new + mpStr16 = 0xda + mpStr32 = 0xdb + + mpArray16 = 0xdc + mpArray32 = 0xdd + + mpMap16 = 0xde + mpMap32 = 0xdf + + mpNegFixNumMin = 0xe0 + mpNegFixNumMax = 0xff +) + +// MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec +// that the backend RPC service takes multiple arguments, which have been arranged +// in sequence in the slice. +// +// The Codec then passes it AS-IS to the rpc service (without wrapping it in an +// array of 1 element). +type MsgpackSpecRpcMultiArgs []interface{} + +// A MsgpackContainer type specifies the different types of msgpackContainers. +type msgpackContainerType struct { + fixCutoff int + bFixMin, b8, b16, b32 byte + hasFixMin, has8, has8Always bool +} + +var ( + msgpackContainerStr = msgpackContainerType{32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false} + msgpackContainerBin = msgpackContainerType{0, 0, mpBin8, mpBin16, mpBin32, false, true, true} + msgpackContainerList = msgpackContainerType{16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false} + msgpackContainerMap = msgpackContainerType{16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false} +) + +//--------------------------------------------- + +type msgpackEncDriver struct { + w encWriter + h *MsgpackHandle +} + +func (e *msgpackEncDriver) isBuiltinType(rt uintptr) bool { + //no builtin types. All encodings are based on kinds. Types supported as extensions. + return false +} + +func (e *msgpackEncDriver) encodeBuiltin(rt uintptr, v interface{}) {} + +func (e *msgpackEncDriver) encodeNil() { + e.w.writen1(mpNil) +} + +func (e *msgpackEncDriver) encodeInt(i int64) { + + switch { + case i >= 0: + e.encodeUint(uint64(i)) + case i >= -32: + e.w.writen1(byte(i)) + case i >= math.MinInt8: + e.w.writen2(mpInt8, byte(i)) + case i >= math.MinInt16: + e.w.writen1(mpInt16) + e.w.writeUint16(uint16(i)) + case i >= math.MinInt32: + e.w.writen1(mpInt32) + e.w.writeUint32(uint32(i)) + default: + e.w.writen1(mpInt64) + e.w.writeUint64(uint64(i)) + } +} + +func (e *msgpackEncDriver) encodeUint(i uint64) { + switch { + case i <= math.MaxInt8: + e.w.writen1(byte(i)) + case i <= math.MaxUint8: + e.w.writen2(mpUint8, byte(i)) + case i <= math.MaxUint16: + e.w.writen1(mpUint16) + e.w.writeUint16(uint16(i)) + case i <= math.MaxUint32: + e.w.writen1(mpUint32) + e.w.writeUint32(uint32(i)) + default: + e.w.writen1(mpUint64) + e.w.writeUint64(uint64(i)) + } +} + +func (e *msgpackEncDriver) encodeBool(b bool) { + if b { + e.w.writen1(mpTrue) + } else { + e.w.writen1(mpFalse) + } +} + +func (e *msgpackEncDriver) encodeFloat32(f float32) { + e.w.writen1(mpFloat) + e.w.writeUint32(math.Float32bits(f)) +} + +func (e *msgpackEncDriver) encodeFloat64(f float64) { + e.w.writen1(mpDouble) + e.w.writeUint64(math.Float64bits(f)) +} + +func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) { + switch { + case l == 1: + e.w.writen2(mpFixExt1, xtag) + case l == 2: + e.w.writen2(mpFixExt2, xtag) + case l == 4: + e.w.writen2(mpFixExt4, xtag) + case l == 8: + e.w.writen2(mpFixExt8, xtag) + case l == 16: + e.w.writen2(mpFixExt16, xtag) + case l < 256: + e.w.writen2(mpExt8, byte(l)) + e.w.writen1(xtag) + case l < 65536: + e.w.writen1(mpExt16) + e.w.writeUint16(uint16(l)) + e.w.writen1(xtag) + default: + e.w.writen1(mpExt32) + e.w.writeUint32(uint32(l)) + e.w.writen1(xtag) + } +} + +func (e *msgpackEncDriver) encodeArrayPreamble(length int) { + e.writeContainerLen(msgpackContainerList, length) +} + +func (e *msgpackEncDriver) encodeMapPreamble(length int) { + e.writeContainerLen(msgpackContainerMap, length) +} + +func (e *msgpackEncDriver) encodeString(c charEncoding, s string) { + if c == c_RAW && e.h.WriteExt { + e.writeContainerLen(msgpackContainerBin, len(s)) + } else { + e.writeContainerLen(msgpackContainerStr, len(s)) + } + if len(s) > 0 { + e.w.writestr(s) + } +} + +func (e *msgpackEncDriver) encodeSymbol(v string) { + e.encodeString(c_UTF8, v) +} + +func (e *msgpackEncDriver) encodeStringBytes(c charEncoding, bs []byte) { + if c == c_RAW && e.h.WriteExt { + e.writeContainerLen(msgpackContainerBin, len(bs)) + } else { + e.writeContainerLen(msgpackContainerStr, len(bs)) + } + if len(bs) > 0 { + e.w.writeb(bs) + } +} + +func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) { + switch { + case ct.hasFixMin && l < ct.fixCutoff: + e.w.writen1(ct.bFixMin | byte(l)) + case ct.has8 && l < 256 && (ct.has8Always || e.h.WriteExt): + e.w.writen2(ct.b8, uint8(l)) + case l < 65536: + e.w.writen1(ct.b16) + e.w.writeUint16(uint16(l)) + default: + e.w.writen1(ct.b32) + e.w.writeUint32(uint32(l)) + } +} + +//--------------------------------------------- + +type msgpackDecDriver struct { + r decReader + h *MsgpackHandle + bd byte + bdRead bool + bdType valueType +} + +func (d *msgpackDecDriver) isBuiltinType(rt uintptr) bool { + //no builtin types. All encodings are based on kinds. Types supported as extensions. + return false +} + +func (d *msgpackDecDriver) decodeBuiltin(rt uintptr, v interface{}) {} + +// Note: This returns either a primitive (int, bool, etc) for non-containers, +// or a containerType, or a specific type denoting nil or extension. +// It is called when a nil interface{} is passed, leaving it up to the DecDriver +// to introspect the stream and decide how best to decode. +// It deciphers the value by looking at the stream first. +func (d *msgpackDecDriver) decodeNaked() (v interface{}, vt valueType, decodeFurther bool) { + d.initReadNext() + bd := d.bd + + switch bd { + case mpNil: + vt = valueTypeNil + d.bdRead = false + case mpFalse: + vt = valueTypeBool + v = false + case mpTrue: + vt = valueTypeBool + v = true + + case mpFloat: + vt = valueTypeFloat + v = float64(math.Float32frombits(d.r.readUint32())) + case mpDouble: + vt = valueTypeFloat + v = math.Float64frombits(d.r.readUint64()) + + case mpUint8: + vt = valueTypeUint + v = uint64(d.r.readn1()) + case mpUint16: + vt = valueTypeUint + v = uint64(d.r.readUint16()) + case mpUint32: + vt = valueTypeUint + v = uint64(d.r.readUint32()) + case mpUint64: + vt = valueTypeUint + v = uint64(d.r.readUint64()) + + case mpInt8: + vt = valueTypeInt + v = int64(int8(d.r.readn1())) + case mpInt16: + vt = valueTypeInt + v = int64(int16(d.r.readUint16())) + case mpInt32: + vt = valueTypeInt + v = int64(int32(d.r.readUint32())) + case mpInt64: + vt = valueTypeInt + v = int64(int64(d.r.readUint64())) + + default: + switch { + case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax: + // positive fixnum (always signed) + vt = valueTypeInt + v = int64(int8(bd)) + case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax: + // negative fixnum + vt = valueTypeInt + v = int64(int8(bd)) + case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax: + if d.h.RawToString { + var rvm string + vt = valueTypeString + v = &rvm + } else { + var rvm = []byte{} + vt = valueTypeBytes + v = &rvm + } + decodeFurther = true + case bd == mpBin8, bd == mpBin16, bd == mpBin32: + var rvm = []byte{} + vt = valueTypeBytes + v = &rvm + decodeFurther = true + case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax: + vt = valueTypeArray + decodeFurther = true + case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax: + vt = valueTypeMap + decodeFurther = true + case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32: + clen := d.readExtLen() + var re RawExt + re.Tag = d.r.readn1() + re.Data = d.r.readn(clen) + v = &re + vt = valueTypeExt + default: + decErr("Nil-Deciphered DecodeValue: %s: hex: %x, dec: %d", msgBadDesc, bd, bd) + } + } + if !decodeFurther { + d.bdRead = false + } + return +} + +// int can be decoded from msgpack type: intXXX or uintXXX +func (d *msgpackDecDriver) decodeInt(bitsize uint8) (i int64) { + switch d.bd { + case mpUint8: + i = int64(uint64(d.r.readn1())) + case mpUint16: + i = int64(uint64(d.r.readUint16())) + case mpUint32: + i = int64(uint64(d.r.readUint32())) + case mpUint64: + i = int64(d.r.readUint64()) + case mpInt8: + i = int64(int8(d.r.readn1())) + case mpInt16: + i = int64(int16(d.r.readUint16())) + case mpInt32: + i = int64(int32(d.r.readUint32())) + case mpInt64: + i = int64(d.r.readUint64()) + default: + switch { + case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax: + i = int64(int8(d.bd)) + case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax: + i = int64(int8(d.bd)) + default: + decErr("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd) + } + } + // check overflow (logic adapted from std pkg reflect/value.go OverflowUint() + if bitsize > 0 { + if trunc := (i << (64 - bitsize)) >> (64 - bitsize); i != trunc { + decErr("Overflow int value: %v", i) + } + } + d.bdRead = false + return +} + +// uint can be decoded from msgpack type: intXXX or uintXXX +func (d *msgpackDecDriver) decodeUint(bitsize uint8) (ui uint64) { + switch d.bd { + case mpUint8: + ui = uint64(d.r.readn1()) + case mpUint16: + ui = uint64(d.r.readUint16()) + case mpUint32: + ui = uint64(d.r.readUint32()) + case mpUint64: + ui = d.r.readUint64() + case mpInt8: + if i := int64(int8(d.r.readn1())); i >= 0 { + ui = uint64(i) + } else { + decErr("Assigning negative signed value: %v, to unsigned type", i) + } + case mpInt16: + if i := int64(int16(d.r.readUint16())); i >= 0 { + ui = uint64(i) + } else { + decErr("Assigning negative signed value: %v, to unsigned type", i) + } + case mpInt32: + if i := int64(int32(d.r.readUint32())); i >= 0 { + ui = uint64(i) + } else { + decErr("Assigning negative signed value: %v, to unsigned type", i) + } + case mpInt64: + if i := int64(d.r.readUint64()); i >= 0 { + ui = uint64(i) + } else { + decErr("Assigning negative signed value: %v, to unsigned type", i) + } + default: + switch { + case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax: + ui = uint64(d.bd) + case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax: + decErr("Assigning negative signed value: %v, to unsigned type", int(d.bd)) + default: + decErr("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd) + } + } + // check overflow (logic adapted from std pkg reflect/value.go OverflowUint() + if bitsize > 0 { + if trunc := (ui << (64 - bitsize)) >> (64 - bitsize); ui != trunc { + decErr("Overflow uint value: %v", ui) + } + } + d.bdRead = false + return +} + +// float can either be decoded from msgpack type: float, double or intX +func (d *msgpackDecDriver) decodeFloat(chkOverflow32 bool) (f float64) { + switch d.bd { + case mpFloat: + f = float64(math.Float32frombits(d.r.readUint32())) + case mpDouble: + f = math.Float64frombits(d.r.readUint64()) + default: + f = float64(d.decodeInt(0)) + } + checkOverflowFloat32(f, chkOverflow32) + d.bdRead = false + return +} + +// bool can be decoded from bool, fixnum 0 or 1. +func (d *msgpackDecDriver) decodeBool() (b bool) { + switch d.bd { + case mpFalse, 0: + // b = false + case mpTrue, 1: + b = true + default: + decErr("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd) + } + d.bdRead = false + return +} + +func (d *msgpackDecDriver) decodeString() (s string) { + clen := d.readContainerLen(msgpackContainerStr) + if clen > 0 { + s = string(d.r.readn(clen)) + } + d.bdRead = false + return +} + +// Callers must check if changed=true (to decide whether to replace the one they have) +func (d *msgpackDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) { + // bytes can be decoded from msgpackContainerStr or msgpackContainerBin + var clen int + switch d.bd { + case mpBin8, mpBin16, mpBin32: + clen = d.readContainerLen(msgpackContainerBin) + default: + clen = d.readContainerLen(msgpackContainerStr) + } + // if clen < 0 { + // changed = true + // panic("length cannot be zero. this cannot be nil.") + // } + if clen > 0 { + // if no contents in stream, don't update the passed byteslice + if len(bs) != clen { + // Return changed=true if length of passed slice diff from length of bytes in stream + if len(bs) > clen { + bs = bs[:clen] + } else { + bs = make([]byte, clen) + } + bsOut = bs + changed = true + } + d.r.readb(bs) + } + d.bdRead = false + return +} + +// Every top-level decode funcs (i.e. decodeValue, decode) must call this first. +func (d *msgpackDecDriver) initReadNext() { + if d.bdRead { + return + } + d.bd = d.r.readn1() + d.bdRead = true + d.bdType = valueTypeUnset +} + +func (d *msgpackDecDriver) currentEncodedType() valueType { + if d.bdType == valueTypeUnset { + bd := d.bd + switch bd { + case mpNil: + d.bdType = valueTypeNil + case mpFalse, mpTrue: + d.bdType = valueTypeBool + case mpFloat, mpDouble: + d.bdType = valueTypeFloat + case mpUint8, mpUint16, mpUint32, mpUint64: + d.bdType = valueTypeUint + case mpInt8, mpInt16, mpInt32, mpInt64: + d.bdType = valueTypeInt + default: + switch { + case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax: + d.bdType = valueTypeInt + case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax: + d.bdType = valueTypeInt + case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax: + if d.h.RawToString { + d.bdType = valueTypeString + } else { + d.bdType = valueTypeBytes + } + case bd == mpBin8, bd == mpBin16, bd == mpBin32: + d.bdType = valueTypeBytes + case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax: + d.bdType = valueTypeArray + case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax: + d.bdType = valueTypeMap + case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32: + d.bdType = valueTypeExt + default: + decErr("currentEncodedType: Undeciphered descriptor: %s: hex: %x, dec: %d", msgBadDesc, bd, bd) + } + } + } + return d.bdType +} + +func (d *msgpackDecDriver) tryDecodeAsNil() bool { + if d.bd == mpNil { + d.bdRead = false + return true + } + return false +} + +func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int) { + bd := d.bd + switch { + case bd == mpNil: + clen = -1 // to represent nil + case bd == ct.b8: + clen = int(d.r.readn1()) + case bd == ct.b16: + clen = int(d.r.readUint16()) + case bd == ct.b32: + clen = int(d.r.readUint32()) + case (ct.bFixMin & bd) == ct.bFixMin: + clen = int(ct.bFixMin ^ bd) + default: + decErr("readContainerLen: %s: hex: %x, dec: %d", msgBadDesc, bd, bd) + } + d.bdRead = false + return +} + +func (d *msgpackDecDriver) readMapLen() int { + return d.readContainerLen(msgpackContainerMap) +} + +func (d *msgpackDecDriver) readArrayLen() int { + return d.readContainerLen(msgpackContainerList) +} + +func (d *msgpackDecDriver) readExtLen() (clen int) { + switch d.bd { + case mpNil: + clen = -1 // to represent nil + case mpFixExt1: + clen = 1 + case mpFixExt2: + clen = 2 + case mpFixExt4: + clen = 4 + case mpFixExt8: + clen = 8 + case mpFixExt16: + clen = 16 + case mpExt8: + clen = int(d.r.readn1()) + case mpExt16: + clen = int(d.r.readUint16()) + case mpExt32: + clen = int(d.r.readUint32()) + default: + decErr("decoding ext bytes: found unexpected byte: %x", d.bd) + } + return +} + +func (d *msgpackDecDriver) decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) { + xbd := d.bd + switch { + case xbd == mpBin8, xbd == mpBin16, xbd == mpBin32: + xbs, _ = d.decodeBytes(nil) + case xbd == mpStr8, xbd == mpStr16, xbd == mpStr32, + xbd >= mpFixStrMin && xbd <= mpFixStrMax: + xbs = []byte(d.decodeString()) + default: + clen := d.readExtLen() + xtag = d.r.readn1() + if verifyTag && xtag != tag { + decErr("Wrong extension tag. Got %b. Expecting: %v", xtag, tag) + } + xbs = d.r.readn(clen) + } + d.bdRead = false + return +} + +//-------------------------------------------------- + +//MsgpackHandle is a Handle for the Msgpack Schema-Free Encoding Format. +type MsgpackHandle struct { + BasicHandle + + // RawToString controls how raw bytes are decoded into a nil interface{}. + RawToString bool + // WriteExt flag supports encoding configured extensions with extension tags. + // It also controls whether other elements of the new spec are encoded (ie Str8). + // + // With WriteExt=false, configured extensions are serialized as raw bytes + // and Str8 is not encoded. + // + // A stream can still be decoded into a typed value, provided an appropriate value + // is provided, but the type cannot be inferred from the stream. If no appropriate + // type is provided (e.g. decoding into a nil interface{}), you get back + // a []byte or string based on the setting of RawToString. + WriteExt bool +} + +func (h *MsgpackHandle) newEncDriver(w encWriter) encDriver { + return &msgpackEncDriver{w: w, h: h} +} + +func (h *MsgpackHandle) newDecDriver(r decReader) decDriver { + return &msgpackDecDriver{r: r, h: h} +} + +func (h *MsgpackHandle) writeExt() bool { + return h.WriteExt +} + +func (h *MsgpackHandle) getBasicHandle() *BasicHandle { + return &h.BasicHandle +} + +//-------------------------------------------------- + +type msgpackSpecRpcCodec struct { + rpcCodec +} + +// /////////////// Spec RPC Codec /////////////////// +func (c *msgpackSpecRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error { + // WriteRequest can write to both a Go service, and other services that do + // not abide by the 1 argument rule of a Go service. + // We discriminate based on if the body is a MsgpackSpecRpcMultiArgs + var bodyArr []interface{} + if m, ok := body.(MsgpackSpecRpcMultiArgs); ok { + bodyArr = ([]interface{})(m) + } else { + bodyArr = []interface{}{body} + } + r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr} + return c.write(r2, nil, false, true) +} + +func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error { + var moe interface{} + if r.Error != "" { + moe = r.Error + } + if moe != nil && body != nil { + body = nil + } + r2 := []interface{}{1, uint32(r.Seq), moe, body} + return c.write(r2, nil, false, true) +} + +func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error { + return c.parseCustomHeader(1, &r.Seq, &r.Error) +} + +func (c *msgpackSpecRpcCodec) ReadRequestHeader(r *rpc.Request) error { + return c.parseCustomHeader(0, &r.Seq, &r.ServiceMethod) +} + +func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error { + if body == nil { // read and discard + return c.read(nil) + } + bodyArr := []interface{}{body} + return c.read(&bodyArr) +} + +func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) { + + if c.cls { + return io.EOF + } + + // We read the response header by hand + // so that the body can be decoded on its own from the stream at a later time. + + const fia byte = 0x94 //four item array descriptor value + // Not sure why the panic of EOF is swallowed above. + // if bs1 := c.dec.r.readn1(); bs1 != fia { + // err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1) + // return + // } + var b byte + b, err = c.br.ReadByte() + if err != nil { + return + } + if b != fia { + err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, b) + return + } + + if err = c.read(&b); err != nil { + return + } + if b != expectTypeByte { + err = fmt.Errorf("Unexpected byte descriptor in header. Expecting %v. Received %v", expectTypeByte, b) + return + } + if err = c.read(msgid); err != nil { + return + } + if err = c.read(methodOrError); err != nil { + return + } + return +} + +//-------------------------------------------------- + +// msgpackSpecRpc is the implementation of Rpc that uses custom communication protocol +// as defined in the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md +type msgpackSpecRpc struct{} + +// MsgpackSpecRpc implements Rpc using the communication protocol defined in +// the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md . +// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered. +var MsgpackSpecRpc msgpackSpecRpc + +func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec { + return &msgpackSpecRpcCodec{newRPCCodec(conn, h)} +} + +func (x msgpackSpecRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec { + return &msgpackSpecRpcCodec{newRPCCodec(conn, h)} +} + +var _ decDriver = (*msgpackDecDriver)(nil) +var _ encDriver = (*msgpackEncDriver)(nil) diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py b/vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py new file mode 100644 index 00000000000..e933838c56a --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +# This will create golden files in a directory passed to it. +# A Test calls this internally to create the golden files +# So it can process them (so we don't have to checkin the files). + +import msgpack, msgpackrpc, sys, os, threading + +def get_test_data_list(): + # get list with all primitive types, and a combo type + l0 = [ + -8, + -1616, + -32323232, + -6464646464646464, + 192, + 1616, + 32323232, + 6464646464646464, + 192, + -3232.0, + -6464646464.0, + 3232.0, + 6464646464.0, + False, + True, + None, + "someday", + "", + "bytestring", + 1328176922000002000, + -2206187877999998000, + 0, + -6795364578871345152 + ] + l1 = [ + { "true": True, + "false": False }, + { "true": "True", + "false": False, + "uint16(1616)": 1616 }, + { "list": [1616, 32323232, True, -3232.0, {"TRUE":True, "FALSE":False}, [True, False] ], + "int32":32323232, "bool": True, + "LONG STRING": "123456789012345678901234567890123456789012345678901234567890", + "SHORT STRING": "1234567890" }, + { True: "true", 8: False, "false": 0 } + ] + + l = [] + l.extend(l0) + l.append(l0) + l.extend(l1) + return l + +def build_test_data(destdir): + l = get_test_data_list() + for i in range(len(l)): + packer = msgpack.Packer() + serialized = packer.pack(l[i]) + f = open(os.path.join(destdir, str(i) + '.golden'), 'wb') + f.write(serialized) + f.close() + +def doRpcServer(port, stopTimeSec): + class EchoHandler(object): + def Echo123(self, msg1, msg2, msg3): + return ("1:%s 2:%s 3:%s" % (msg1, msg2, msg3)) + def EchoStruct(self, msg): + return ("%s" % msg) + + addr = msgpackrpc.Address('localhost', port) + server = msgpackrpc.Server(EchoHandler()) + server.listen(addr) + # run thread to stop it after stopTimeSec seconds if > 0 + if stopTimeSec > 0: + def myStopRpcServer(): + server.stop() + t = threading.Timer(stopTimeSec, myStopRpcServer) + t.start() + server.start() + +def doRpcClientToPythonSvc(port): + address = msgpackrpc.Address('localhost', port) + client = msgpackrpc.Client(address, unpack_encoding='utf-8') + print client.call("Echo123", "A1", "B2", "C3") + print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}) + +def doRpcClientToGoSvc(port): + # print ">>>> port: ", port, " <<<<<" + address = msgpackrpc.Address('localhost', port) + client = msgpackrpc.Client(address, unpack_encoding='utf-8') + print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"]) + print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}) + +def doMain(args): + if len(args) == 2 and args[0] == "testdata": + build_test_data(args[1]) + elif len(args) == 3 and args[0] == "rpc-server": + doRpcServer(int(args[1]), int(args[2])) + elif len(args) == 2 and args[0] == "rpc-client-python-service": + doRpcClientToPythonSvc(int(args[1])) + elif len(args) == 2 and args[0] == "rpc-client-go-service": + doRpcClientToGoSvc(int(args[1])) + else: + print("Usage: msgpack_test.py " + + "[testdata|rpc-server|rpc-client-python-service|rpc-client-go-service] ...") + +if __name__ == "__main__": + doMain(sys.argv[1:]) + diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/rpc.go b/vendor/github.com/hashicorp/go-msgpack/codec/rpc.go new file mode 100644 index 00000000000..d014dbdcc7d --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/rpc.go @@ -0,0 +1,152 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +import ( + "bufio" + "io" + "net/rpc" + "sync" +) + +// Rpc provides a rpc Server or Client Codec for rpc communication. +type Rpc interface { + ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec + ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec +} + +// RpcCodecBuffered allows access to the underlying bufio.Reader/Writer +// used by the rpc connection. It accomodates use-cases where the connection +// should be used by rpc and non-rpc functions, e.g. streaming a file after +// sending an rpc response. +type RpcCodecBuffered interface { + BufferedReader() *bufio.Reader + BufferedWriter() *bufio.Writer +} + +// ------------------------------------- + +// rpcCodec defines the struct members and common methods. +type rpcCodec struct { + rwc io.ReadWriteCloser + dec *Decoder + enc *Encoder + bw *bufio.Writer + br *bufio.Reader + mu sync.Mutex + cls bool +} + +func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec { + bw := bufio.NewWriter(conn) + br := bufio.NewReader(conn) + return rpcCodec{ + rwc: conn, + bw: bw, + br: br, + enc: NewEncoder(bw, h), + dec: NewDecoder(br, h), + } +} + +func (c *rpcCodec) BufferedReader() *bufio.Reader { + return c.br +} + +func (c *rpcCodec) BufferedWriter() *bufio.Writer { + return c.bw +} + +func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2, doFlush bool) (err error) { + if c.cls { + return io.EOF + } + if err = c.enc.Encode(obj1); err != nil { + return + } + if writeObj2 { + if err = c.enc.Encode(obj2); err != nil { + return + } + } + if doFlush && c.bw != nil { + return c.bw.Flush() + } + return +} + +func (c *rpcCodec) read(obj interface{}) (err error) { + if c.cls { + return io.EOF + } + //If nil is passed in, we should still attempt to read content to nowhere. + if obj == nil { + var obj2 interface{} + return c.dec.Decode(&obj2) + } + return c.dec.Decode(obj) +} + +func (c *rpcCodec) Close() error { + if c.cls { + return io.EOF + } + c.cls = true + return c.rwc.Close() +} + +func (c *rpcCodec) ReadResponseBody(body interface{}) error { + return c.read(body) +} + +// ------------------------------------- + +type goRpcCodec struct { + rpcCodec +} + +func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error { + // Must protect for concurrent access as per API + c.mu.Lock() + defer c.mu.Unlock() + return c.write(r, body, true, true) +} + +func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error { + c.mu.Lock() + defer c.mu.Unlock() + return c.write(r, body, true, true) +} + +func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error { + return c.read(r) +} + +func (c *goRpcCodec) ReadRequestHeader(r *rpc.Request) error { + return c.read(r) +} + +func (c *goRpcCodec) ReadRequestBody(body interface{}) error { + return c.read(body) +} + +// ------------------------------------- + +// goRpc is the implementation of Rpc that uses the communication protocol +// as defined in net/rpc package. +type goRpc struct{} + +// GoRpc implements Rpc using the communication protocol defined in net/rpc package. +// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered. +var GoRpc goRpc + +func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec { + return &goRpcCodec{newRPCCodec(conn, h)} +} + +func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec { + return &goRpcCodec{newRPCCodec(conn, h)} +} + +var _ RpcCodecBuffered = (*rpcCodec)(nil) // ensure *rpcCodec implements RpcCodecBuffered diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/simple.go b/vendor/github.com/hashicorp/go-msgpack/codec/simple.go new file mode 100644 index 00000000000..9e4d148a2a1 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/simple.go @@ -0,0 +1,461 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +import "math" + +const ( + _ uint8 = iota + simpleVdNil = 1 + simpleVdFalse = 2 + simpleVdTrue = 3 + simpleVdFloat32 = 4 + simpleVdFloat64 = 5 + + // each lasts for 4 (ie n, n+1, n+2, n+3) + simpleVdPosInt = 8 + simpleVdNegInt = 12 + + // containers: each lasts for 4 (ie n, n+1, n+2, ... n+7) + simpleVdString = 216 + simpleVdByteArray = 224 + simpleVdArray = 232 + simpleVdMap = 240 + simpleVdExt = 248 +) + +type simpleEncDriver struct { + h *SimpleHandle + w encWriter + //b [8]byte +} + +func (e *simpleEncDriver) isBuiltinType(rt uintptr) bool { + return false +} + +func (e *simpleEncDriver) encodeBuiltin(rt uintptr, v interface{}) { +} + +func (e *simpleEncDriver) encodeNil() { + e.w.writen1(simpleVdNil) +} + +func (e *simpleEncDriver) encodeBool(b bool) { + if b { + e.w.writen1(simpleVdTrue) + } else { + e.w.writen1(simpleVdFalse) + } +} + +func (e *simpleEncDriver) encodeFloat32(f float32) { + e.w.writen1(simpleVdFloat32) + e.w.writeUint32(math.Float32bits(f)) +} + +func (e *simpleEncDriver) encodeFloat64(f float64) { + e.w.writen1(simpleVdFloat64) + e.w.writeUint64(math.Float64bits(f)) +} + +func (e *simpleEncDriver) encodeInt(v int64) { + if v < 0 { + e.encUint(uint64(-v), simpleVdNegInt) + } else { + e.encUint(uint64(v), simpleVdPosInt) + } +} + +func (e *simpleEncDriver) encodeUint(v uint64) { + e.encUint(v, simpleVdPosInt) +} + +func (e *simpleEncDriver) encUint(v uint64, bd uint8) { + switch { + case v <= math.MaxUint8: + e.w.writen2(bd, uint8(v)) + case v <= math.MaxUint16: + e.w.writen1(bd + 1) + e.w.writeUint16(uint16(v)) + case v <= math.MaxUint32: + e.w.writen1(bd + 2) + e.w.writeUint32(uint32(v)) + case v <= math.MaxUint64: + e.w.writen1(bd + 3) + e.w.writeUint64(v) + } +} + +func (e *simpleEncDriver) encLen(bd byte, length int) { + switch { + case length == 0: + e.w.writen1(bd) + case length <= math.MaxUint8: + e.w.writen1(bd + 1) + e.w.writen1(uint8(length)) + case length <= math.MaxUint16: + e.w.writen1(bd + 2) + e.w.writeUint16(uint16(length)) + case int64(length) <= math.MaxUint32: + e.w.writen1(bd + 3) + e.w.writeUint32(uint32(length)) + default: + e.w.writen1(bd + 4) + e.w.writeUint64(uint64(length)) + } +} + +func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) { + e.encLen(simpleVdExt, length) + e.w.writen1(xtag) +} + +func (e *simpleEncDriver) encodeArrayPreamble(length int) { + e.encLen(simpleVdArray, length) +} + +func (e *simpleEncDriver) encodeMapPreamble(length int) { + e.encLen(simpleVdMap, length) +} + +func (e *simpleEncDriver) encodeString(c charEncoding, v string) { + e.encLen(simpleVdString, len(v)) + e.w.writestr(v) +} + +func (e *simpleEncDriver) encodeSymbol(v string) { + e.encodeString(c_UTF8, v) +} + +func (e *simpleEncDriver) encodeStringBytes(c charEncoding, v []byte) { + e.encLen(simpleVdByteArray, len(v)) + e.w.writeb(v) +} + +//------------------------------------ + +type simpleDecDriver struct { + h *SimpleHandle + r decReader + bdRead bool + bdType valueType + bd byte + //b [8]byte +} + +func (d *simpleDecDriver) initReadNext() { + if d.bdRead { + return + } + d.bd = d.r.readn1() + d.bdRead = true + d.bdType = valueTypeUnset +} + +func (d *simpleDecDriver) currentEncodedType() valueType { + if d.bdType == valueTypeUnset { + switch d.bd { + case simpleVdNil: + d.bdType = valueTypeNil + case simpleVdTrue, simpleVdFalse: + d.bdType = valueTypeBool + case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3: + d.bdType = valueTypeUint + case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3: + d.bdType = valueTypeInt + case simpleVdFloat32, simpleVdFloat64: + d.bdType = valueTypeFloat + case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4: + d.bdType = valueTypeString + case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4: + d.bdType = valueTypeBytes + case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4: + d.bdType = valueTypeExt + case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4: + d.bdType = valueTypeArray + case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4: + d.bdType = valueTypeMap + default: + decErr("currentEncodedType: Unrecognized d.vd: 0x%x", d.bd) + } + } + return d.bdType +} + +func (d *simpleDecDriver) tryDecodeAsNil() bool { + if d.bd == simpleVdNil { + d.bdRead = false + return true + } + return false +} + +func (d *simpleDecDriver) isBuiltinType(rt uintptr) bool { + return false +} + +func (d *simpleDecDriver) decodeBuiltin(rt uintptr, v interface{}) { +} + +func (d *simpleDecDriver) decIntAny() (ui uint64, i int64, neg bool) { + switch d.bd { + case simpleVdPosInt: + ui = uint64(d.r.readn1()) + i = int64(ui) + case simpleVdPosInt + 1: + ui = uint64(d.r.readUint16()) + i = int64(ui) + case simpleVdPosInt + 2: + ui = uint64(d.r.readUint32()) + i = int64(ui) + case simpleVdPosInt + 3: + ui = uint64(d.r.readUint64()) + i = int64(ui) + case simpleVdNegInt: + ui = uint64(d.r.readn1()) + i = -(int64(ui)) + neg = true + case simpleVdNegInt + 1: + ui = uint64(d.r.readUint16()) + i = -(int64(ui)) + neg = true + case simpleVdNegInt + 2: + ui = uint64(d.r.readUint32()) + i = -(int64(ui)) + neg = true + case simpleVdNegInt + 3: + ui = uint64(d.r.readUint64()) + i = -(int64(ui)) + neg = true + default: + decErr("decIntAny: Integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd) + } + // don't do this check, because callers may only want the unsigned value. + // if ui > math.MaxInt64 { + // decErr("decIntAny: Integer out of range for signed int64: %v", ui) + // } + return +} + +func (d *simpleDecDriver) decodeInt(bitsize uint8) (i int64) { + _, i, _ = d.decIntAny() + checkOverflow(0, i, bitsize) + d.bdRead = false + return +} + +func (d *simpleDecDriver) decodeUint(bitsize uint8) (ui uint64) { + ui, i, neg := d.decIntAny() + if neg { + decErr("Assigning negative signed value: %v, to unsigned type", i) + } + checkOverflow(ui, 0, bitsize) + d.bdRead = false + return +} + +func (d *simpleDecDriver) decodeFloat(chkOverflow32 bool) (f float64) { + switch d.bd { + case simpleVdFloat32: + f = float64(math.Float32frombits(d.r.readUint32())) + case simpleVdFloat64: + f = math.Float64frombits(d.r.readUint64()) + default: + if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 { + _, i, _ := d.decIntAny() + f = float64(i) + } else { + decErr("Float only valid from float32/64: Invalid descriptor: %v", d.bd) + } + } + checkOverflowFloat32(f, chkOverflow32) + d.bdRead = false + return +} + +// bool can be decoded from bool only (single byte). +func (d *simpleDecDriver) decodeBool() (b bool) { + switch d.bd { + case simpleVdTrue: + b = true + case simpleVdFalse: + default: + decErr("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd) + } + d.bdRead = false + return +} + +func (d *simpleDecDriver) readMapLen() (length int) { + d.bdRead = false + return d.decLen() +} + +func (d *simpleDecDriver) readArrayLen() (length int) { + d.bdRead = false + return d.decLen() +} + +func (d *simpleDecDriver) decLen() int { + switch d.bd % 8 { + case 0: + return 0 + case 1: + return int(d.r.readn1()) + case 2: + return int(d.r.readUint16()) + case 3: + ui := uint64(d.r.readUint32()) + checkOverflow(ui, 0, intBitsize) + return int(ui) + case 4: + ui := d.r.readUint64() + checkOverflow(ui, 0, intBitsize) + return int(ui) + } + decErr("decLen: Cannot read length: bd%8 must be in range 0..4. Got: %d", d.bd%8) + return -1 +} + +func (d *simpleDecDriver) decodeString() (s string) { + s = string(d.r.readn(d.decLen())) + d.bdRead = false + return +} + +func (d *simpleDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) { + if clen := d.decLen(); clen > 0 { + // if no contents in stream, don't update the passed byteslice + if len(bs) != clen { + if len(bs) > clen { + bs = bs[:clen] + } else { + bs = make([]byte, clen) + } + bsOut = bs + changed = true + } + d.r.readb(bs) + } + d.bdRead = false + return +} + +func (d *simpleDecDriver) decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) { + switch d.bd { + case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4: + l := d.decLen() + xtag = d.r.readn1() + if verifyTag && xtag != tag { + decErr("Wrong extension tag. Got %b. Expecting: %v", xtag, tag) + } + xbs = d.r.readn(l) + case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4: + xbs, _ = d.decodeBytes(nil) + default: + decErr("Invalid d.vd for extensions (Expecting extensions or byte array). Got: 0x%x", d.bd) + } + d.bdRead = false + return +} + +func (d *simpleDecDriver) decodeNaked() (v interface{}, vt valueType, decodeFurther bool) { + d.initReadNext() + + switch d.bd { + case simpleVdNil: + vt = valueTypeNil + case simpleVdFalse: + vt = valueTypeBool + v = false + case simpleVdTrue: + vt = valueTypeBool + v = true + case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3: + vt = valueTypeUint + ui, _, _ := d.decIntAny() + v = ui + case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3: + vt = valueTypeInt + _, i, _ := d.decIntAny() + v = i + case simpleVdFloat32: + vt = valueTypeFloat + v = d.decodeFloat(true) + case simpleVdFloat64: + vt = valueTypeFloat + v = d.decodeFloat(false) + case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4: + vt = valueTypeString + v = d.decodeString() + case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4: + vt = valueTypeBytes + v, _ = d.decodeBytes(nil) + case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4: + vt = valueTypeExt + l := d.decLen() + var re RawExt + re.Tag = d.r.readn1() + re.Data = d.r.readn(l) + v = &re + vt = valueTypeExt + case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4: + vt = valueTypeArray + decodeFurther = true + case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4: + vt = valueTypeMap + decodeFurther = true + default: + decErr("decodeNaked: Unrecognized d.vd: 0x%x", d.bd) + } + + if !decodeFurther { + d.bdRead = false + } + return +} + +//------------------------------------ + +// SimpleHandle is a Handle for a very simple encoding format. +// +// simple is a simplistic codec similar to binc, but not as compact. +// - Encoding of a value is always preceeded by the descriptor byte (bd) +// - True, false, nil are encoded fully in 1 byte (the descriptor) +// - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte). +// There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers. +// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte) +// - Lenght of containers (strings, bytes, array, map, extensions) +// are encoded in 0, 1, 2, 4 or 8 bytes. +// Zero-length containers have no length encoded. +// For others, the number of bytes is given by pow(2, bd%3) +// - maps are encoded as [bd] [length] [[key][value]]... +// - arrays are encoded as [bd] [length] [value]... +// - extensions are encoded as [bd] [length] [tag] [byte]... +// - strings/bytearrays are encoded as [bd] [length] [byte]... +// +// The full spec will be published soon. +type SimpleHandle struct { + BasicHandle +} + +func (h *SimpleHandle) newEncDriver(w encWriter) encDriver { + return &simpleEncDriver{w: w, h: h} +} + +func (h *SimpleHandle) newDecDriver(r decReader) decDriver { + return &simpleDecDriver{r: r, h: h} +} + +func (_ *SimpleHandle) writeExt() bool { + return true +} + +func (h *SimpleHandle) getBasicHandle() *BasicHandle { + return &h.BasicHandle +} + +var _ decDriver = (*simpleDecDriver)(nil) +var _ encDriver = (*simpleEncDriver)(nil) diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/time.go b/vendor/github.com/hashicorp/go-msgpack/codec/time.go new file mode 100644 index 00000000000..c86d65328d7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-msgpack/codec/time.go @@ -0,0 +1,193 @@ +// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. +// Use of this source code is governed by a BSD-style license found in the LICENSE file. + +package codec + +import ( + "time" +) + +var ( + timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} +) + +// EncodeTime encodes a time.Time as a []byte, including +// information on the instant in time and UTC offset. +// +// Format Description +// +// A timestamp is composed of 3 components: +// +// - secs: signed integer representing seconds since unix epoch +// - nsces: unsigned integer representing fractional seconds as a +// nanosecond offset within secs, in the range 0 <= nsecs < 1e9 +// - tz: signed integer representing timezone offset in minutes east of UTC, +// and a dst (daylight savings time) flag +// +// When encoding a timestamp, the first byte is the descriptor, which +// defines which components are encoded and how many bytes are used to +// encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it +// is not encoded in the byte array explicitly*. +// +// Descriptor 8 bits are of the form `A B C DDD EE`: +// A: Is secs component encoded? 1 = true +// B: Is nsecs component encoded? 1 = true +// C: Is tz component encoded? 1 = true +// DDD: Number of extra bytes for secs (range 0-7). +// If A = 1, secs encoded in DDD+1 bytes. +// If A = 0, secs is not encoded, and is assumed to be 0. +// If A = 1, then we need at least 1 byte to encode secs. +// DDD says the number of extra bytes beyond that 1. +// E.g. if DDD=0, then secs is represented in 1 byte. +// if DDD=2, then secs is represented in 3 bytes. +// EE: Number of extra bytes for nsecs (range 0-3). +// If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above) +// +// Following the descriptor bytes, subsequent bytes are: +// +// secs component encoded in `DDD + 1` bytes (if A == 1) +// nsecs component encoded in `EE + 1` bytes (if B == 1) +// tz component encoded in 2 bytes (if C == 1) +// +// secs and nsecs components are integers encoded in a BigEndian +// 2-complement encoding format. +// +// tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to +// Least significant bit 0 are described below: +// +// Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes). +// Bit 15 = have\_dst: set to 1 if we set the dst flag. +// Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not. +// Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format. +// +func encodeTime(t time.Time) []byte { + //t := rv.Interface().(time.Time) + tsecs, tnsecs := t.Unix(), t.Nanosecond() + var ( + bd byte + btmp [8]byte + bs [16]byte + i int = 1 + ) + l := t.Location() + if l == time.UTC { + l = nil + } + if tsecs != 0 { + bd = bd | 0x80 + bigen.PutUint64(btmp[:], uint64(tsecs)) + f := pruneSignExt(btmp[:], tsecs >= 0) + bd = bd | (byte(7-f) << 2) + copy(bs[i:], btmp[f:]) + i = i + (8 - f) + } + if tnsecs != 0 { + bd = bd | 0x40 + bigen.PutUint32(btmp[:4], uint32(tnsecs)) + f := pruneSignExt(btmp[:4], true) + bd = bd | byte(3-f) + copy(bs[i:], btmp[f:4]) + i = i + (4 - f) + } + if l != nil { + bd = bd | 0x20 + // Note that Go Libs do not give access to dst flag. + _, zoneOffset := t.Zone() + //zoneName, zoneOffset := t.Zone() + zoneOffset /= 60 + z := uint16(zoneOffset) + bigen.PutUint16(btmp[:2], z) + // clear dst flags + bs[i] = btmp[0] & 0x3f + bs[i+1] = btmp[1] + i = i + 2 + } + bs[0] = bd + return bs[0:i] +} + +// DecodeTime decodes a []byte into a time.Time. +func decodeTime(bs []byte) (tt time.Time, err error) { + bd := bs[0] + var ( + tsec int64 + tnsec uint32 + tz uint16 + i byte = 1 + i2 byte + n byte + ) + if bd&(1<<7) != 0 { + var btmp [8]byte + n = ((bd >> 2) & 0x7) + 1 + i2 = i + n + copy(btmp[8-n:], bs[i:i2]) + //if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it) + if bs[i]&(1<<7) != 0 { + copy(btmp[0:8-n], bsAll0xff) + //for j,k := byte(0), 8-n; j < k; j++ { btmp[j] = 0xff } + } + i = i2 + tsec = int64(bigen.Uint64(btmp[:])) + } + if bd&(1<<6) != 0 { + var btmp [4]byte + n = (bd & 0x3) + 1 + i2 = i + n + copy(btmp[4-n:], bs[i:i2]) + i = i2 + tnsec = bigen.Uint32(btmp[:]) + } + if bd&(1<<5) == 0 { + tt = time.Unix(tsec, int64(tnsec)).UTC() + return + } + // In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name. + // However, we need name here, so it can be shown when time is printed. + // Zone name is in form: UTC-08:00. + // Note that Go Libs do not give access to dst flag, so we ignore dst bits + + i2 = i + 2 + tz = bigen.Uint16(bs[i:i2]) + i = i2 + // sign extend sign bit into top 2 MSB (which were dst bits): + if tz&(1<<13) == 0 { // positive + tz = tz & 0x3fff //clear 2 MSBs: dst bits + } else { // negative + tz = tz | 0xc000 //set 2 MSBs: dst bits + //tzname[3] = '-' (TODO: verify. this works here) + } + tzint := int16(tz) + if tzint == 0 { + tt = time.Unix(tsec, int64(tnsec)).UTC() + } else { + // For Go Time, do not use a descriptive timezone. + // It's unnecessary, and makes it harder to do a reflect.DeepEqual. + // The Offset already tells what the offset should be, if not on UTC and unknown zone name. + // var zoneName = timeLocUTCName(tzint) + tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60)) + } + return +} + +func timeLocUTCName(tzint int16) string { + if tzint == 0 { + return "UTC" + } + var tzname = []byte("UTC+00:00") + //tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below. + //tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first + var tzhr, tzmin int16 + if tzint < 0 { + tzname[3] = '-' // (TODO: verify. this works here) + tzhr, tzmin = -tzint/60, (-tzint)%60 + } else { + tzhr, tzmin = tzint/60, tzint%60 + } + tzname[4] = timeDigits[tzhr/10] + tzname[5] = timeDigits[tzhr%10] + tzname[7] = timeDigits[tzmin/10] + tzname[8] = timeDigits[tzmin%10] + return string(tzname) + //return time.FixedZone(string(tzname), int(tzint)*60) +} diff --git a/vendor/github.com/hashicorp/go-multierror/.travis.yml b/vendor/github.com/hashicorp/go-multierror/.travis.yml new file mode 100644 index 00000000000..304a8359558 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/.travis.yml @@ -0,0 +1,12 @@ +sudo: false + +language: go + +go: + - 1.x + +branches: + only: + - master + +script: make test testrace diff --git a/vendor/github.com/hashicorp/go-multierror/LICENSE b/vendor/github.com/hashicorp/go-multierror/LICENSE new file mode 100644 index 00000000000..82b4de97c7e --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/LICENSE @@ -0,0 +1,353 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-multierror/Makefile b/vendor/github.com/hashicorp/go-multierror/Makefile new file mode 100644 index 00000000000..b97cd6ed02b --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/Makefile @@ -0,0 +1,31 @@ +TEST?=./... + +default: test + +# test runs the test suite and vets the code. +test: generate + @echo "==> Running tests..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} + +# testrace runs the race checker +testrace: generate + @echo "==> Running tests (race)..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -race ${TESTARGS} + +# updatedeps installs all the dependencies needed to run and build. +updatedeps: + @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" + +# generate runs `go generate` to build the dynamically generated source files. +generate: + @echo "==> Generating..." + @find . -type f -name '.DS_Store' -delete + @go list ./... \ + | grep -v "/vendor/" \ + | xargs -n1 go generate + +.PHONY: default test testrace updatedeps generate diff --git a/vendor/github.com/hashicorp/go-multierror/README.md b/vendor/github.com/hashicorp/go-multierror/README.md new file mode 100644 index 00000000000..ead5830f7b7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/README.md @@ -0,0 +1,97 @@ +# go-multierror + +[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis] +[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] + +[travis]: https://travis-ci.org/hashicorp/go-multierror +[godocs]: https://godoc.org/github.com/hashicorp/go-multierror + +`go-multierror` is a package for Go that provides a mechanism for +representing a list of `error` values as a single `error`. + +This allows a function in Go to return an `error` that might actually +be a list of errors. If the caller knows this, they can unwrap the +list and access the errors. If the caller doesn't know, the error +formats to a nice human-readable format. + +`go-multierror` implements the +[errwrap](https://github.com/hashicorp/errwrap) interface so that it can +be used with that library, as well. + +## Installation and Docs + +Install using `go get github.com/hashicorp/go-multierror`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/go-multierror + +## Usage + +go-multierror is easy to use and purposely built to be unobtrusive in +existing Go applications/libraries that may not be aware of it. + +**Building a list of errors** + +The `Append` function is used to create a list of errors. This function +behaves a lot like the Go built-in `append` function: it doesn't matter +if the first argument is nil, a `multierror.Error`, or any other `error`, +the function behaves as you would expect. + +```go +var result error + +if err := step1(); err != nil { + result = multierror.Append(result, err) +} +if err := step2(); err != nil { + result = multierror.Append(result, err) +} + +return result +``` + +**Customizing the formatting of the errors** + +By specifying a custom `ErrorFormat`, you can customize the format +of the `Error() string` function: + +```go +var result *multierror.Error + +// ... accumulate errors here, maybe using Append + +if result != nil { + result.ErrorFormat = func([]error) string { + return "errors!" + } +} +``` + +**Accessing the list of errors** + +`multierror.Error` implements `error` so if the caller doesn't know about +multierror, it will work just fine. But if you're aware a multierror might +be returned, you can use type switches to access the list of errors: + +```go +if err := something(); err != nil { + if merr, ok := err.(*multierror.Error); ok { + // Use merr.Errors + } +} +``` + +**Returning a multierror only if there are errors** + +If you build a `multierror.Error`, you can use the `ErrorOrNil` function +to return an `error` implementation only if there are errors to return: + +```go +var result *multierror.Error + +// ... accumulate errors here + +// Return the `error` only if errors were added to the multierror, otherwise +// return nil since there are no errors. +return result.ErrorOrNil() +``` diff --git a/vendor/github.com/hashicorp/go-multierror/append.go b/vendor/github.com/hashicorp/go-multierror/append.go new file mode 100644 index 00000000000..775b6e753e7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/append.go @@ -0,0 +1,41 @@ +package multierror + +// Append is a helper function that will append more errors +// onto an Error in order to create a larger multi-error. +// +// If err is not a multierror.Error, then it will be turned into +// one. If any of the errs are multierr.Error, they will be flattened +// one level into err. +func Append(err error, errs ...error) *Error { + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Go through each error and flatten + for _, e := range errs { + switch e := e.(type) { + case *Error: + if e != nil { + err.Errors = append(err.Errors, e.Errors...) + } + default: + if e != nil { + err.Errors = append(err.Errors, e) + } + } + } + + return err + default: + newErrs := make([]error, 0, len(errs)+1) + if err != nil { + newErrs = append(newErrs, err) + } + newErrs = append(newErrs, errs...) + + return Append(&Error{}, newErrs...) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/flatten.go b/vendor/github.com/hashicorp/go-multierror/flatten.go new file mode 100644 index 00000000000..aab8e9abec9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/flatten.go @@ -0,0 +1,26 @@ +package multierror + +// Flatten flattens the given error, merging any *Errors together into +// a single *Error. +func Flatten(err error) error { + // If it isn't an *Error, just return the error as-is + if _, ok := err.(*Error); !ok { + return err + } + + // Otherwise, make the result and flatten away! + flatErr := new(Error) + flatten(err, flatErr) + return flatErr +} + +func flatten(err error, flatErr *Error) { + switch err := err.(type) { + case *Error: + for _, e := range err.Errors { + flatten(e, flatErr) + } + default: + flatErr.Errors = append(flatErr.Errors, err) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/format.go b/vendor/github.com/hashicorp/go-multierror/format.go new file mode 100644 index 00000000000..47f13c49a67 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/format.go @@ -0,0 +1,27 @@ +package multierror + +import ( + "fmt" + "strings" +) + +// ErrorFormatFunc is a function callback that is called by Error to +// turn the list of errors into a string. +type ErrorFormatFunc func([]error) string + +// ListFormatFunc is a basic formatter that outputs the number of errors +// that occurred along with a bullet point list of the errors. +func ListFormatFunc(es []error) string { + if len(es) == 1 { + return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0]) + } + + points := make([]string, len(es)) + for i, err := range es { + points[i] = fmt.Sprintf("* %s", err) + } + + return fmt.Sprintf( + "%d errors occurred:\n\t%s\n\n", + len(es), strings.Join(points, "\n\t")) +} diff --git a/vendor/github.com/hashicorp/go-multierror/go.mod b/vendor/github.com/hashicorp/go-multierror/go.mod new file mode 100644 index 00000000000..2534331d5f9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/go.mod @@ -0,0 +1,3 @@ +module github.com/hashicorp/go-multierror + +require github.com/hashicorp/errwrap v1.0.0 diff --git a/vendor/github.com/hashicorp/go-multierror/go.sum b/vendor/github.com/hashicorp/go-multierror/go.sum new file mode 100644 index 00000000000..85b1f8ff333 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/go.sum @@ -0,0 +1,4 @@ +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/vendor/github.com/hashicorp/go-multierror/multierror.go b/vendor/github.com/hashicorp/go-multierror/multierror.go new file mode 100644 index 00000000000..89b1422d1d1 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/multierror.go @@ -0,0 +1,51 @@ +package multierror + +import ( + "fmt" +) + +// Error is an error type to track multiple errors. This is used to +// accumulate errors in cases and return them as a single "error". +type Error struct { + Errors []error + ErrorFormat ErrorFormatFunc +} + +func (e *Error) Error() string { + fn := e.ErrorFormat + if fn == nil { + fn = ListFormatFunc + } + + return fn(e.Errors) +} + +// ErrorOrNil returns an error interface if this Error represents +// a list of errors, or returns nil if the list of errors is empty. This +// function is useful at the end of accumulation to make sure that the value +// returned represents the existence of errors. +func (e *Error) ErrorOrNil() error { + if e == nil { + return nil + } + if len(e.Errors) == 0 { + return nil + } + + return e +} + +func (e *Error) GoString() string { + return fmt.Sprintf("*%#v", *e) +} + +// WrappedErrors returns the list of errors that this Error is wrapping. +// It is an implementation of the errwrap.Wrapper interface so that +// multierror.Error can be used with that library. +// +// This method is not safe to be called concurrently and is no different +// than accessing the Errors field directly. It is implemented only to +// satisfy the errwrap.Wrapper interface. +func (e *Error) WrappedErrors() []error { + return e.Errors +} diff --git a/vendor/github.com/hashicorp/go-multierror/prefix.go b/vendor/github.com/hashicorp/go-multierror/prefix.go new file mode 100644 index 00000000000..5c477abe44f --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/prefix.go @@ -0,0 +1,37 @@ +package multierror + +import ( + "fmt" + + "github.com/hashicorp/errwrap" +) + +// Prefix is a helper function that will prefix some text +// to the given error. If the error is a multierror.Error, then +// it will be prefixed to each wrapped error. +// +// This is useful to use when appending multiple multierrors +// together in order to give better scoping. +func Prefix(err error, prefix string) error { + if err == nil { + return nil + } + + format := fmt.Sprintf("%s {{err}}", prefix) + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Wrap each of the errors + for i, e := range err.Errors { + err.Errors[i] = errwrap.Wrapf(format, e) + } + + return err + default: + return errwrap.Wrapf(format, err) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/sort.go b/vendor/github.com/hashicorp/go-multierror/sort.go new file mode 100644 index 00000000000..fecb14e81c5 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/sort.go @@ -0,0 +1,16 @@ +package multierror + +// Len implements sort.Interface function for length +func (err Error) Len() int { + return len(err.Errors) +} + +// Swap implements sort.Interface function for swapping elements +func (err Error) Swap(i, j int) { + err.Errors[i], err.Errors[j] = err.Errors[j], err.Errors[i] +} + +// Less implements sort.Interface function for determining order +func (err Error) Less(i, j int) bool { + return err.Errors[i].Error() < err.Errors[j].Error() +} diff --git a/vendor/github.com/weaveworks/mesh/.gitignore b/vendor/github.com/hashicorp/go-sockaddr/.gitignore similarity index 74% rename from vendor/github.com/weaveworks/mesh/.gitignore rename to vendor/github.com/hashicorp/go-sockaddr/.gitignore index 8c06417c57c..41720b86e3e 100644 --- a/vendor/github.com/weaveworks/mesh/.gitignore +++ b/vendor/github.com/hashicorp/go-sockaddr/.gitignore @@ -22,9 +22,5 @@ _testmain.go *.exe *.test *.prof - -# Bad smells -Makefile -Dockerfile - -examples/increment-only-counter/increment-only-counter +.cover.out* +coverage.html diff --git a/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile b/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile new file mode 100644 index 00000000000..0f3ae1661e2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile @@ -0,0 +1,65 @@ +TOOLS= golang.org/x/tools/cover +GOCOVER_TMPFILE?= $(GOCOVER_FILE).tmp +GOCOVER_FILE?= .cover.out +GOCOVERHTML?= coverage.html +FIND=`/usr/bin/which 2> /dev/null gfind find | /usr/bin/grep -v ^no | /usr/bin/head -n 1` +XARGS=`/usr/bin/which 2> /dev/null gxargs xargs | /usr/bin/grep -v ^no | /usr/bin/head -n 1` + +test:: $(GOCOVER_FILE) + @$(MAKE) -C cmd/sockaddr test + +cover:: coverage_report + +$(GOCOVER_FILE):: + @${FIND} . -type d ! -path '*cmd*' ! -path '*.git*' -print0 | ${XARGS} -0 -I % sh -ec "cd % && rm -f $(GOCOVER_TMPFILE) && go test -coverprofile=$(GOCOVER_TMPFILE)" + + @echo 'mode: set' > $(GOCOVER_FILE) + @${FIND} . -type f ! -path '*cmd*' ! -path '*.git*' -name "$(GOCOVER_TMPFILE)" -print0 | ${XARGS} -0 -n1 cat $(GOCOVER_TMPFILE) | grep -v '^mode: ' >> ${PWD}/$(GOCOVER_FILE) + +$(GOCOVERHTML): $(GOCOVER_FILE) + go tool cover -html=$(GOCOVER_FILE) -o $(GOCOVERHTML) + +coverage_report:: $(GOCOVER_FILE) + go tool cover -html=$(GOCOVER_FILE) + +audit_tools:: + @go get -u github.com/golang/lint/golint && echo "Installed golint:" + @go get -u github.com/fzipp/gocyclo && echo "Installed gocyclo:" + @go get -u github.com/remyoudompheng/go-misc/deadcode && echo "Installed deadcode:" + @go get -u github.com/client9/misspell/cmd/misspell && echo "Installed misspell:" + @go get -u github.com/gordonklaus/ineffassign && echo "Installed ineffassign:" + +audit:: + deadcode + go tool vet -all *.go + go tool vet -shadow=true *.go + golint *.go + ineffassign . + gocyclo -over 65 *.go + misspell *.go + +clean:: + rm -f $(GOCOVER_FILE) $(GOCOVERHTML) + +dev:: + @go build + @$(MAKE) -B -C cmd/sockaddr sockaddr + +install:: + @go install + @$(MAKE) -C cmd/sockaddr install + +doc:: + @echo Visit: http://127.0.0.1:6161/pkg/github.com/hashicorp/go-sockaddr/ + godoc -http=:6161 -goroot $GOROOT + +world:: + @set -e; \ + for os in solaris darwin freebsd linux windows android; do \ + for arch in amd64; do \ + printf "Building on %s-%s\n" "$${os}" "$${arch}" ; \ + env GOOS="$${os}" GOARCH="$${arch}" go build -o /dev/null; \ + done; \ + done + + $(MAKE) -C cmd/sockaddr world diff --git a/vendor/github.com/hashicorp/go-sockaddr/LICENSE b/vendor/github.com/hashicorp/go-sockaddr/LICENSE new file mode 100644 index 00000000000..a612ad9813b --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-sockaddr/README.md b/vendor/github.com/hashicorp/go-sockaddr/README.md new file mode 100644 index 00000000000..a2e170ae09c --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/README.md @@ -0,0 +1,118 @@ +# go-sockaddr + +## `sockaddr` Library + +Socket address convenience functions for Go. `go-sockaddr` is a convenience +library that makes doing the right thing with IP addresses easy. `go-sockaddr` +is loosely modeled after the UNIX `sockaddr_t` and creates a union of the family +of `sockaddr_t` types (see below for an ascii diagram). Library documentation +is available +at +[https://godoc.org/github.com/hashicorp/go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr). +The primary intent of the library was to make it possible to define heuristics +for selecting the correct IP addresses when a configuration is evaluated at +runtime. See +the +[docs](https://godoc.org/github.com/hashicorp/go-sockaddr), +[`template` package](https://godoc.org/github.com/hashicorp/go-sockaddr/template), +tests, +and +[CLI utility](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr) +for details and hints as to how to use this library. + +For example, with this library it is possible to find an IP address that: + +* is attached to a default route + ([`GetDefaultInterfaces()`](https://godoc.org/github.com/hashicorp/go-sockaddr#GetDefaultInterfaces)) +* is contained within a CIDR block ([`IfByNetwork()`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByNetwork)) +* is an RFC1918 address + ([`IfByRFC("1918")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC)) +* is ordered + ([`OrderedIfAddrBy(args)`](https://godoc.org/github.com/hashicorp/go-sockaddr#OrderedIfAddrBy) where + `args` includes, but is not limited + to, + [`AscIfType`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscIfType), + [`AscNetworkSize`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscNetworkSize)) +* excludes all IPv6 addresses + ([`IfByType("^(IPv4)$")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByType)) +* is larger than a `/32` + ([`IfByMaskSize(32)`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByMaskSize)) +* is not on a `down` interface + ([`ExcludeIfs("flags", "down")`](https://godoc.org/github.com/hashicorp/go-sockaddr#ExcludeIfs)) +* preferences an IPv6 address over an IPv4 address + ([`SortIfByType()`](https://godoc.org/github.com/hashicorp/go-sockaddr#SortIfByType) + + [`ReverseIfAddrs()`](https://godoc.org/github.com/hashicorp/go-sockaddr#ReverseIfAddrs)); and +* excludes any IP in RFC6890 address + ([`IfByRFC("6890")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC)) + +Or any combination or variation therein. + +There are also a few simple helper functions such as `GetPublicIP` and +`GetPrivateIP` which both return strings and select the first public or private +IP address on the default interface, respectively. Similarly, there is also a +helper function called `GetInterfaceIP` which returns the first usable IP +address on the named interface. + +## `sockaddr` CLI + +Given the possible complexity of the `sockaddr` library, there is a CLI utility +that accompanies the library, also +called +[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr). +The +[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr) +utility exposes nearly all of the functionality of the library and can be used +either as an administrative tool or testing tool. To install +the +[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr), +run: + +```text +$ go get -u github.com/hashicorp/go-sockaddr/cmd/sockaddr +``` + +If you're familiar with UNIX's `sockaddr` struct's, the following diagram +mapping the C `sockaddr` (top) to `go-sockaddr` structs (bottom) and +interfaces will be helpful: + +``` ++-------------------------------------------------------+ +| | +| sockaddr | +| SockAddr | +| | +| +--------------+ +----------------------------------+ | +| | sockaddr_un | | | | +| | SockAddrUnix | | sockaddr_in{,6} | | +| +--------------+ | IPAddr | | +| | | | +| | +-------------+ +--------------+ | | +| | | sockaddr_in | | sockaddr_in6 | | | +| | | IPv4Addr | | IPv6Addr | | | +| | +-------------+ +--------------+ | | +| | | | +| +----------------------------------+ | +| | ++-------------------------------------------------------+ +``` + +## Inspiration and Design + +There were many subtle inspirations that led to this design, but the most direct +inspiration for the filtering syntax was +OpenBSD's +[`pf.conf(5)`](https://www.freebsd.org/cgi/man.cgi?query=pf.conf&apropos=0&sektion=0&arch=default&format=html#PARAMETERS) firewall +syntax that lets you select the first IP address on a given named interface. +The original problem stemmed from: + +* needing to create immutable images using [Packer](https://www.packer.io) that + ran the [Consul](https://www.consul.io) process (Consul can only use one IP + address at a time); +* images that may or may not have multiple interfaces or IP addresses at + runtime; and +* we didn't want to rely on configuration management to render out the correct + IP address if the VM image was being used in an auto-scaling group. + +Instead we needed some way to codify a heuristic that would correctly select the +right IP address but the input parameters were not known when the image was +created. diff --git a/vendor/github.com/hashicorp/go-sockaddr/doc.go b/vendor/github.com/hashicorp/go-sockaddr/doc.go new file mode 100644 index 00000000000..90671deb51d --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/doc.go @@ -0,0 +1,5 @@ +/* +Package sockaddr is a Go implementation of the UNIX socket family data types and +related helper functions. +*/ +package sockaddr diff --git a/vendor/github.com/hashicorp/go-sockaddr/go.mod b/vendor/github.com/hashicorp/go-sockaddr/go.mod new file mode 100644 index 00000000000..21f8d8e8e75 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/go.mod @@ -0,0 +1,8 @@ +module github.com/hashicorp/go-sockaddr + +require ( + github.com/hashicorp/errwrap v1.0.0 + github.com/mitchellh/cli v1.0.0 + github.com/mitchellh/go-wordwrap v1.0.0 + github.com/ryanuber/columnize v2.1.0+incompatible +) diff --git a/vendor/github.com/hashicorp/go-sockaddr/go.sum b/vendor/github.com/hashicorp/go-sockaddr/go.sum new file mode 100644 index 00000000000..1b2bdd48280 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/go.sum @@ -0,0 +1,24 @@ +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc h1:MeuS1UDyZyFH++6vVy44PuufTeFF0d0nfI6XB87YGSk= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go new file mode 100644 index 00000000000..0811b275990 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go @@ -0,0 +1,254 @@ +package sockaddr + +import "strings" + +// ifAddrAttrMap is a map of the IfAddr type-specific attributes. +var ifAddrAttrMap map[AttrName]func(IfAddr) string +var ifAddrAttrs []AttrName + +func init() { + ifAddrAttrInit() +} + +// GetPrivateIP returns a string with a single IP address that is part of RFC +// 6890 and has a default route. If the system can't determine its IP address +// or find an RFC 6890 IP address, an empty string will be returned instead. +// This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetPrivateInterfaces | attr "address"}}' +/// ``` +func GetPrivateIP() (string, error) { + privateIfs, err := GetPrivateInterfaces() + if err != nil { + return "", err + } + if len(privateIfs) < 1 { + return "", nil + } + + ifAddr := privateIfs[0] + ip := *ToIPAddr(ifAddr.SockAddr) + return ip.NetIP().String(), nil +} + +// GetPrivateIPs returns a string with all IP addresses that are part of RFC +// 6890 (regardless of whether or not there is a default route, unlike +// GetPublicIP). If the system can't find any RFC 6890 IP addresses, an empty +// string will be returned instead. This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "RFC" "6890" | join "address" " "}}' +/// ``` +func GetPrivateIPs() (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } else if len(ifAddrs) < 1 { + return "", nil + } + + ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP) + if len(ifAddrs) == 0 { + return "", nil + } + + OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs) + + ifAddrs, _, err = IfByRFC("6890", ifAddrs) + if err != nil { + return "", err + } else if len(ifAddrs) == 0 { + return "", nil + } + + _, ifAddrs, err = IfByRFC(ForwardingBlacklistRFC, ifAddrs) + if err != nil { + return "", err + } else if len(ifAddrs) == 0 { + return "", nil + } + + ips := make([]string, 0, len(ifAddrs)) + for _, ifAddr := range ifAddrs { + ip := *ToIPAddr(ifAddr.SockAddr) + s := ip.NetIP().String() + ips = append(ips, s) + } + + return strings.Join(ips, " "), nil +} + +// GetPublicIP returns a string with a single IP address that is NOT part of RFC +// 6890 and has a default route. If the system can't determine its IP address +// or find a non RFC 6890 IP address, an empty string will be returned instead. +// This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetPublicInterfaces | attr "address"}}' +/// ``` +func GetPublicIP() (string, error) { + publicIfs, err := GetPublicInterfaces() + if err != nil { + return "", err + } else if len(publicIfs) < 1 { + return "", nil + } + + ifAddr := publicIfs[0] + ip := *ToIPAddr(ifAddr.SockAddr) + return ip.NetIP().String(), nil +} + +// GetPublicIPs returns a string with all IP addresses that are NOT part of RFC +// 6890 (regardless of whether or not there is a default route, unlike +// GetPublicIP). If the system can't find any non RFC 6890 IP addresses, an +// empty string will be returned instead. This function is the `eval` +// equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | exclude "RFC" "6890" | join "address" " "}}' +/// ``` +func GetPublicIPs() (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } else if len(ifAddrs) < 1 { + return "", nil + } + + ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP) + if len(ifAddrs) == 0 { + return "", nil + } + + OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs) + + _, ifAddrs, err = IfByRFC("6890", ifAddrs) + if err != nil { + return "", err + } else if len(ifAddrs) == 0 { + return "", nil + } + + ips := make([]string, 0, len(ifAddrs)) + for _, ifAddr := range ifAddrs { + ip := *ToIPAddr(ifAddr.SockAddr) + s := ip.NetIP().String() + ips = append(ips, s) + } + + return strings.Join(ips, " "), nil +} + +// GetInterfaceIP returns a string with a single IP address sorted by the size +// of the network (i.e. IP addresses with a smaller netmask, larger network +// size, are sorted first). This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <> | sort "type,size" | include "flag" "forwardable" | attr "address" }}' +/// ``` +func GetInterfaceIP(namedIfRE string) (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } + + ifAddrs, _, err = IfByName(namedIfRE, ifAddrs) + if err != nil { + return "", err + } + + ifAddrs, _, err = IfByFlag("forwardable", ifAddrs) + if err != nil { + return "", err + } + + ifAddrs, err = SortIfBy("+type,+size", ifAddrs) + if err != nil { + return "", err + } + + if len(ifAddrs) == 0 { + return "", err + } + + ip := ToIPAddr(ifAddrs[0].SockAddr) + if ip == nil { + return "", err + } + + return IPAddrAttr(*ip, "address"), nil +} + +// GetInterfaceIPs returns a string with all IPs, sorted by the size of the +// network (i.e. IP addresses with a smaller netmask, larger network size, are +// sorted first), on a named interface. This function is the `eval` equivalent +// of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <> | sort "type,size" | join "address" " "}}' +/// ``` +func GetInterfaceIPs(namedIfRE string) (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } + + ifAddrs, _, err = IfByName(namedIfRE, ifAddrs) + if err != nil { + return "", err + } + + ifAddrs, err = SortIfBy("+type,+size", ifAddrs) + if err != nil { + return "", err + } + + if len(ifAddrs) == 0 { + return "", err + } + + ips := make([]string, 0, len(ifAddrs)) + for _, ifAddr := range ifAddrs { + ip := *ToIPAddr(ifAddr.SockAddr) + s := ip.NetIP().String() + ips = append(ips, s) + } + + return strings.Join(ips, " "), nil +} + +// IfAddrAttrs returns a list of attributes supported by the IfAddr type +func IfAddrAttrs() []AttrName { + return ifAddrAttrs +} + +// IfAddrAttr returns a string representation of an attribute for the given +// IfAddr. +func IfAddrAttr(ifAddr IfAddr, attrName AttrName) string { + fn, found := ifAddrAttrMap[attrName] + if !found { + return "" + } + + return fn(ifAddr) +} + +// ifAddrAttrInit is called once at init() +func ifAddrAttrInit() { + // Sorted for human readability + ifAddrAttrs = []AttrName{ + "flags", + "name", + } + + ifAddrAttrMap = map[AttrName]func(ifAddr IfAddr) string{ + "flags": func(ifAddr IfAddr) string { + return ifAddr.Interface.Flags.String() + }, + "name": func(ifAddr IfAddr) string { + return ifAddr.Interface.Name + }, + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go new file mode 100644 index 00000000000..80f61bef680 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go @@ -0,0 +1,1304 @@ +package sockaddr + +import ( + "encoding/binary" + "errors" + "fmt" + "math/big" + "net" + "regexp" + "sort" + "strconv" + "strings" +) + +var ( + // Centralize all regexps and regexp.Copy() where necessary. + signRE *regexp.Regexp = regexp.MustCompile(`^[\s]*[+-]`) + whitespaceRE *regexp.Regexp = regexp.MustCompile(`[\s]+`) + ifNameRE *regexp.Regexp = regexp.MustCompile(`^(?:Ethernet|Wireless LAN) adapter ([^:]+):`) + ipAddrRE *regexp.Regexp = regexp.MustCompile(`^ IPv[46] Address\. \. \. \. \. \. \. \. \. \. \. : ([^\s]+)`) +) + +// IfAddrs is a slice of IfAddr +type IfAddrs []IfAddr + +func (ifs IfAddrs) Len() int { return len(ifs) } + +// CmpIfFunc is the function signature that must be met to be used in the +// OrderedIfAddrBy multiIfAddrSorter +type CmpIfAddrFunc func(p1, p2 *IfAddr) int + +// multiIfAddrSorter implements the Sort interface, sorting the IfAddrs within. +type multiIfAddrSorter struct { + ifAddrs IfAddrs + cmp []CmpIfAddrFunc +} + +// Sort sorts the argument slice according to the Cmp functions passed to +// OrderedIfAddrBy. +func (ms *multiIfAddrSorter) Sort(ifAddrs IfAddrs) { + ms.ifAddrs = ifAddrs + sort.Sort(ms) +} + +// OrderedIfAddrBy sorts SockAddr by the list of sort function pointers. +func OrderedIfAddrBy(cmpFuncs ...CmpIfAddrFunc) *multiIfAddrSorter { + return &multiIfAddrSorter{ + cmp: cmpFuncs, + } +} + +// Len is part of sort.Interface. +func (ms *multiIfAddrSorter) Len() int { + return len(ms.ifAddrs) +} + +// Less is part of sort.Interface. It is implemented by looping along the Cmp() +// functions until it finds a comparison that is either less than or greater +// than. A return value of 0 defers sorting to the next function in the +// multisorter (which means the results of sorting may leave the resutls in a +// non-deterministic order). +func (ms *multiIfAddrSorter) Less(i, j int) bool { + p, q := &ms.ifAddrs[i], &ms.ifAddrs[j] + // Try all but the last comparison. + var k int + for k = 0; k < len(ms.cmp)-1; k++ { + cmp := ms.cmp[k] + x := cmp(p, q) + switch x { + case -1: + // p < q, so we have a decision. + return true + case 1: + // p > q, so we have a decision. + return false + } + // p == q; try the next comparison. + } + // All comparisons to here said "equal", so just return whatever the + // final comparison reports. + switch ms.cmp[k](p, q) { + case -1: + return true + case 1: + return false + default: + // Still a tie! Now what? + return false + panic("undefined sort order for remaining items in the list") + } +} + +// Swap is part of sort.Interface. +func (ms *multiIfAddrSorter) Swap(i, j int) { + ms.ifAddrs[i], ms.ifAddrs[j] = ms.ifAddrs[j], ms.ifAddrs[i] +} + +// AscIfAddress is a sorting function to sort IfAddrs by their respective +// address type. Non-equal types are deferred in the sort. +func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int { + return AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfDefault is a sorting function to sort IfAddrs by whether or not they +// have a default route or not. Non-equal types are deferred in the sort. +// +// FIXME: This is a particularly expensive sorting operation because of the +// non-memoized calls to NewRouteInfo(). In an ideal world the routeInfo data +// once at the start of the sort and pass it along as a context or by wrapping +// the IfAddr type with this information (this would also solve the inability to +// return errors and the possibility of failing silently). Fortunately, +// N*log(N) where N = 3 is only ~6.2 invocations. Not ideal, but not worth +// optimizing today. The common case is this gets called once or twice. +// Patches welcome. +func AscIfDefault(p1Ptr, p2Ptr *IfAddr) int { + ri, err := NewRouteInfo() + if err != nil { + return sortDeferDecision + } + + defaultIfName, err := ri.GetDefaultInterfaceName() + if err != nil { + return sortDeferDecision + } + + switch { + case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName: + return sortDeferDecision + case p1Ptr.Interface.Name == defaultIfName: + return sortReceiverBeforeArg + case p2Ptr.Interface.Name == defaultIfName: + return sortArgBeforeReceiver + default: + return sortDeferDecision + } +} + +// AscIfName is a sorting function to sort IfAddrs by their interface names. +func AscIfName(p1Ptr, p2Ptr *IfAddr) int { + return strings.Compare(p1Ptr.Name, p2Ptr.Name) +} + +// AscIfNetworkSize is a sorting function to sort IfAddrs by their respective +// network mask size. +func AscIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int { + return AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfPort is a sorting function to sort IfAddrs by their respective +// port type. Non-equal types are deferred in the sort. +func AscIfPort(p1Ptr, p2Ptr *IfAddr) int { + return AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfPrivate is a sorting function to sort IfAddrs by "private" values before +// "public" values. Both IPv4 and IPv6 are compared against RFC6890 (RFC6890 +// includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and IPv6 +// includes RFC4193). +func AscIfPrivate(p1Ptr, p2Ptr *IfAddr) int { + return AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfType is a sorting function to sort IfAddrs by their respective address +// type. Non-equal types are deferred in the sort. +func AscIfType(p1Ptr, p2Ptr *IfAddr) int { + return AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfAddress is identical to AscIfAddress but reverse ordered. +func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfDefault is identical to AscIfDefault but reverse ordered. +func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscIfDefault(p1Ptr, p2Ptr) +} + +// DescIfName is identical to AscIfName but reverse ordered. +func DescIfName(p1Ptr, p2Ptr *IfAddr) int { + return -1 * strings.Compare(p1Ptr.Name, p2Ptr.Name) +} + +// DescIfNetworkSize is identical to AscIfNetworkSize but reverse ordered. +func DescIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfPort is identical to AscIfPort but reverse ordered. +func DescIfPort(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfPrivate is identical to AscIfPrivate but reverse ordered. +func DescIfPrivate(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfType is identical to AscIfType but reverse ordered. +func DescIfType(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// FilterIfByType filters IfAddrs and returns a list of the matching type +func FilterIfByType(ifAddrs IfAddrs, type_ SockAddrType) (matchedIfs, excludedIfs IfAddrs) { + excludedIfs = make(IfAddrs, 0, len(ifAddrs)) + matchedIfs = make(IfAddrs, 0, len(ifAddrs)) + + for _, ifAddr := range ifAddrs { + if ifAddr.SockAddr.Type()&type_ != 0 { + matchedIfs = append(matchedIfs, ifAddr) + } else { + excludedIfs = append(excludedIfs, ifAddr) + } + } + return matchedIfs, excludedIfs +} + +// IfAttr forwards the selector to IfAttr.Attr() for resolution. If there is +// more than one IfAddr, only the first IfAddr is used. +func IfAttr(selectorName string, ifAddr IfAddr) (string, error) { + attrName := AttrName(strings.ToLower(selectorName)) + attrVal, err := ifAddr.Attr(attrName) + return attrVal, err +} + +// IfAttrs forwards the selector to IfAttrs.Attr() for resolution. If there is +// more than one IfAddr, only the first IfAddr is used. +func IfAttrs(selectorName string, ifAddrs IfAddrs) (string, error) { + if len(ifAddrs) == 0 { + return "", nil + } + + attrName := AttrName(strings.ToLower(selectorName)) + attrVal, err := ifAddrs[0].Attr(attrName) + return attrVal, err +} + +// GetAllInterfaces iterates over all available network interfaces and finds all +// available IP addresses on each interface and converts them to +// sockaddr.IPAddrs, and returning the result as an array of IfAddr. +func GetAllInterfaces() (IfAddrs, error) { + ifs, err := net.Interfaces() + if err != nil { + return nil, err + } + + ifAddrs := make(IfAddrs, 0, len(ifs)) + for _, intf := range ifs { + addrs, err := intf.Addrs() + if err != nil { + return nil, err + } + + for _, addr := range addrs { + var ipAddr IPAddr + ipAddr, err = NewIPAddr(addr.String()) + if err != nil { + return IfAddrs{}, fmt.Errorf("unable to create an IP address from %q", addr.String()) + } + + ifAddr := IfAddr{ + SockAddr: ipAddr, + Interface: intf, + } + ifAddrs = append(ifAddrs, ifAddr) + } + } + + return ifAddrs, nil +} + +// GetDefaultInterfaces returns IfAddrs of the addresses attached to the default +// route. +func GetDefaultInterfaces() (IfAddrs, error) { + ri, err := NewRouteInfo() + if err != nil { + return nil, err + } + + defaultIfName, err := ri.GetDefaultInterfaceName() + if err != nil { + return nil, err + } + + var defaultIfs, ifAddrs IfAddrs + ifAddrs, err = GetAllInterfaces() + for _, ifAddr := range ifAddrs { + if ifAddr.Name == defaultIfName { + defaultIfs = append(defaultIfs, ifAddr) + } + } + + return defaultIfs, nil +} + +// GetPrivateInterfaces returns an IfAddrs that are part of RFC 6890 and have a +// default route. If the system can't determine its IP address or find an RFC +// 6890 IP address, an empty IfAddrs will be returned instead. This function is +// the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | include "RFC" "6890" }}' +/// ``` +func GetPrivateInterfaces() (IfAddrs, error) { + privateIfs, err := GetAllInterfaces() + if err != nil { + return IfAddrs{}, err + } + if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + privateIfs, _ = FilterIfByType(privateIfs, TypeIP) + if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + privateIfs, _, err = IfByFlag("forwardable", privateIfs) + if err != nil { + return IfAddrs{}, err + } + + privateIfs, _, err = IfByFlag("up", privateIfs) + if err != nil { + return IfAddrs{}, err + } + + if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs) + + privateIfs, _, err = IfByRFC("6890", privateIfs) + if err != nil { + return IfAddrs{}, err + } else if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + return privateIfs, nil +} + +// GetPublicInterfaces returns an IfAddrs that are NOT part of RFC 6890 and has a +// default route. If the system can't determine its IP address or find a non +// RFC 6890 IP address, an empty IfAddrs will be returned instead. This +// function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | exclude "RFC" "6890" }}' +/// ``` +func GetPublicInterfaces() (IfAddrs, error) { + publicIfs, err := GetAllInterfaces() + if err != nil { + return IfAddrs{}, err + } + if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + publicIfs, _ = FilterIfByType(publicIfs, TypeIP) + if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + publicIfs, _, err = IfByFlag("forwardable", publicIfs) + if err != nil { + return IfAddrs{}, err + } + + publicIfs, _, err = IfByFlag("up", publicIfs) + if err != nil { + return IfAddrs{}, err + } + + if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs) + + _, publicIfs, err = IfByRFC("6890", publicIfs) + if err != nil { + return IfAddrs{}, err + } else if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + return publicIfs, nil +} + +// IfByAddress returns a list of matched and non-matched IfAddrs, or an error if +// the regexp fails to compile. +func IfByAddress(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + re, err := regexp.Compile(inputRe) + if err != nil { + return nil, nil, fmt.Errorf("Unable to compile address regexp %+q: %v", inputRe, err) + } + + matchedAddrs := make(IfAddrs, 0, len(ifAddrs)) + excludedAddrs := make(IfAddrs, 0, len(ifAddrs)) + for _, addr := range ifAddrs { + if re.MatchString(addr.SockAddr.String()) { + matchedAddrs = append(matchedAddrs, addr) + } else { + excludedAddrs = append(excludedAddrs, addr) + } + } + + return matchedAddrs, excludedAddrs, nil +} + +// IfByName returns a list of matched and non-matched IfAddrs, or an error if +// the regexp fails to compile. +func IfByName(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + re, err := regexp.Compile(inputRe) + if err != nil { + return nil, nil, fmt.Errorf("Unable to compile name regexp %+q: %v", inputRe, err) + } + + matchedAddrs := make(IfAddrs, 0, len(ifAddrs)) + excludedAddrs := make(IfAddrs, 0, len(ifAddrs)) + for _, addr := range ifAddrs { + if re.MatchString(addr.Name) { + matchedAddrs = append(matchedAddrs, addr) + } else { + excludedAddrs = append(excludedAddrs, addr) + } + } + + return matchedAddrs, excludedAddrs, nil +} + +// IfByPort returns a list of matched and non-matched IfAddrs, or an error if +// the regexp fails to compile. +func IfByPort(inputRe string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) { + re, err := regexp.Compile(inputRe) + if err != nil { + return nil, nil, fmt.Errorf("Unable to compile port regexp %+q: %v", inputRe, err) + } + + ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP) + matchedIfs = make(IfAddrs, 0, len(ipIfs)) + excludedIfs = append(IfAddrs(nil), nonIfs...) + for _, addr := range ipIfs { + ipAddr := ToIPAddr(addr.SockAddr) + if ipAddr == nil { + continue + } + + port := strconv.FormatInt(int64((*ipAddr).IPPort()), 10) + if re.MatchString(port) { + matchedIfs = append(matchedIfs, addr) + } else { + excludedIfs = append(excludedIfs, addr) + } + } + + return matchedIfs, excludedIfs, nil +} + +// IfByRFC returns a list of matched and non-matched IfAddrs that contain the +// relevant RFC-specified traits. +func IfByRFC(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + inputRFC, err := strconv.ParseUint(selectorParam, 10, 64) + if err != nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to parse RFC number %q: %v", selectorParam, err) + } + + matchedIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + + rfcNetMap := KnownRFCs() + rfcNets, ok := rfcNetMap[uint(inputRFC)] + if !ok { + return nil, nil, fmt.Errorf("unsupported RFC %d", inputRFC) + } + + for _, ifAddr := range ifAddrs { + var contained bool + for _, rfcNet := range rfcNets { + if rfcNet.Contains(ifAddr.SockAddr) { + matchedIfAddrs = append(matchedIfAddrs, ifAddr) + contained = true + break + } + } + if !contained { + remainingIfAddrs = append(remainingIfAddrs, ifAddr) + } + } + + return matchedIfAddrs, remainingIfAddrs, nil +} + +// IfByRFCs returns a list of matched and non-matched IfAddrs that contain the +// relevant RFC-specified traits. Multiple RFCs can be specified and separated +// by the `|` symbol. No protection is taken to ensure an IfAddr does not end +// up in both the included and excluded list. +func IfByRFCs(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + var includedIfs, excludedIfs IfAddrs + for _, rfcStr := range strings.Split(selectorParam, "|") { + includedRFCIfs, excludedRFCIfs, err := IfByRFC(rfcStr, ifAddrs) + if err != nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to lookup RFC number %q: %v", rfcStr, err) + } + includedIfs = append(includedIfs, includedRFCIfs...) + excludedIfs = append(excludedIfs, excludedRFCIfs...) + } + + return includedIfs, excludedIfs, nil +} + +// IfByMaskSize returns a list of matched and non-matched IfAddrs that have the +// matching mask size. +func IfByMaskSize(selectorParam string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) { + maskSize, err := strconv.ParseUint(selectorParam, 10, 64) + if err != nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("invalid exclude size argument (%q): %v", selectorParam, err) + } + + ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP) + matchedIfs = make(IfAddrs, 0, len(ipIfs)) + excludedIfs = append(IfAddrs(nil), nonIfs...) + for _, addr := range ipIfs { + ipAddr := ToIPAddr(addr.SockAddr) + if ipAddr == nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to filter mask sizes on non-IP type %s: %v", addr.SockAddr.Type().String(), addr.SockAddr.String()) + } + + switch { + case (*ipAddr).Type()&TypeIPv4 != 0 && maskSize > 32: + return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv4 address: %d", maskSize) + case (*ipAddr).Type()&TypeIPv6 != 0 && maskSize > 128: + return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv6 address: %d", maskSize) + } + + if (*ipAddr).Maskbits() == int(maskSize) { + matchedIfs = append(matchedIfs, addr) + } else { + excludedIfs = append(excludedIfs, addr) + } + } + + return matchedIfs, excludedIfs, nil +} + +// IfByType returns a list of matching and non-matching IfAddr that match the +// specified type. For instance: +// +// include "type" "IPv4,IPv6" +// +// will include any IfAddrs that is either an IPv4 or IPv6 address. Any +// addresses on those interfaces that don't match will be included in the +// remainder results. +func IfByType(inputTypes string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + matchingIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + + ifTypes := strings.Split(strings.ToLower(inputTypes), "|") + for _, ifType := range ifTypes { + switch ifType { + case "ip", "ipv4", "ipv6", "unix": + // Valid types + default: + return nil, nil, fmt.Errorf("unsupported type %q %q", ifType, inputTypes) + } + } + + for _, ifAddr := range ifAddrs { + for _, ifType := range ifTypes { + var matched bool + switch { + case ifType == "ip" && ifAddr.SockAddr.Type()&TypeIP != 0: + matched = true + case ifType == "ipv4" && ifAddr.SockAddr.Type()&TypeIPv4 != 0: + matched = true + case ifType == "ipv6" && ifAddr.SockAddr.Type()&TypeIPv6 != 0: + matched = true + case ifType == "unix" && ifAddr.SockAddr.Type()&TypeUnix != 0: + matched = true + } + + if matched { + matchingIfAddrs = append(matchingIfAddrs, ifAddr) + } else { + remainingIfAddrs = append(remainingIfAddrs, ifAddr) + } + } + } + + return matchingIfAddrs, remainingIfAddrs, nil +} + +// IfByFlag returns a list of matching and non-matching IfAddrs that match the +// specified type. For instance: +// +// include "flag" "up,broadcast" +// +// will include any IfAddrs that have both the "up" and "broadcast" flags set. +// Any addresses on those interfaces that don't match will be omitted from the +// results. +func IfByFlag(inputFlags string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + matchedAddrs := make(IfAddrs, 0, len(ifAddrs)) + excludedAddrs := make(IfAddrs, 0, len(ifAddrs)) + + var wantForwardable, + wantGlobalUnicast, + wantInterfaceLocalMulticast, + wantLinkLocalMulticast, + wantLinkLocalUnicast, + wantLoopback, + wantMulticast, + wantUnspecified bool + var ifFlags net.Flags + var checkFlags, checkAttrs bool + for _, flagName := range strings.Split(strings.ToLower(inputFlags), "|") { + switch flagName { + case "broadcast": + checkFlags = true + ifFlags = ifFlags | net.FlagBroadcast + case "down": + checkFlags = true + ifFlags = (ifFlags &^ net.FlagUp) + case "forwardable": + checkAttrs = true + wantForwardable = true + case "global unicast": + checkAttrs = true + wantGlobalUnicast = true + case "interface-local multicast": + checkAttrs = true + wantInterfaceLocalMulticast = true + case "link-local multicast": + checkAttrs = true + wantLinkLocalMulticast = true + case "link-local unicast": + checkAttrs = true + wantLinkLocalUnicast = true + case "loopback": + checkAttrs = true + checkFlags = true + ifFlags = ifFlags | net.FlagLoopback + wantLoopback = true + case "multicast": + checkAttrs = true + checkFlags = true + ifFlags = ifFlags | net.FlagMulticast + wantMulticast = true + case "point-to-point": + checkFlags = true + ifFlags = ifFlags | net.FlagPointToPoint + case "unspecified": + checkAttrs = true + wantUnspecified = true + case "up": + checkFlags = true + ifFlags = ifFlags | net.FlagUp + default: + return nil, nil, fmt.Errorf("Unknown interface flag: %+q", flagName) + } + } + + for _, ifAddr := range ifAddrs { + var matched bool + if checkFlags && ifAddr.Interface.Flags&ifFlags == ifFlags { + matched = true + } + if checkAttrs { + if ip := ToIPAddr(ifAddr.SockAddr); ip != nil { + netIP := (*ip).NetIP() + switch { + case wantGlobalUnicast && netIP.IsGlobalUnicast(): + matched = true + case wantInterfaceLocalMulticast && netIP.IsInterfaceLocalMulticast(): + matched = true + case wantLinkLocalMulticast && netIP.IsLinkLocalMulticast(): + matched = true + case wantLinkLocalUnicast && netIP.IsLinkLocalUnicast(): + matched = true + case wantLoopback && netIP.IsLoopback(): + matched = true + case wantMulticast && netIP.IsMulticast(): + matched = true + case wantUnspecified && netIP.IsUnspecified(): + matched = true + case wantForwardable && !IsRFC(ForwardingBlacklist, ifAddr.SockAddr): + matched = true + } + } + } + if matched { + matchedAddrs = append(matchedAddrs, ifAddr) + } else { + excludedAddrs = append(excludedAddrs, ifAddr) + } + } + return matchedAddrs, excludedAddrs, nil +} + +// IfByNetwork returns an IfAddrs that are equal to or included within the +// network passed in by selector. +func IfByNetwork(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, IfAddrs, error) { + var includedIfs, excludedIfs IfAddrs + for _, netStr := range strings.Split(selectorParam, "|") { + netAddr, err := NewIPAddr(netStr) + if err != nil { + return nil, nil, fmt.Errorf("unable to create an IP address from %+q: %v", netStr, err) + } + + for _, ifAddr := range inputIfAddrs { + if netAddr.Contains(ifAddr.SockAddr) { + includedIfs = append(includedIfs, ifAddr) + } else { + excludedIfs = append(excludedIfs, ifAddr) + } + } + } + + return includedIfs, excludedIfs, nil +} + +// IfAddrMath will return a new IfAddr struct with a mutated value. +func IfAddrMath(operation, value string, inputIfAddr IfAddr) (IfAddr, error) { + // Regexp used to enforce the sign being a required part of the grammar for + // some values. + signRe := signRE.Copy() + + switch strings.ToLower(operation) { + case "address": + // "address" operates on the IP address and is allowed to overflow or + // underflow networks, however it will wrap along the underlying address's + // underlying type. + + if !signRe.MatchString(value) { + return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation) + } + + switch sockType := inputIfAddr.SockAddr.Type(); sockType { + case TypeIPv4: + // 33 == Accept any uint32 value + // TODO(seanc@): Add the ability to parse hex + i, err := strconv.ParseInt(value, 10, 33) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr) + ipv4Uint32 := uint32(ipv4.Address) + ipv4Uint32 += uint32(i) + return IfAddr{ + SockAddr: IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: ipv4.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + case TypeIPv6: + // 64 == Accept any int32 value + // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int. + i, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr) + ipv6BigIntA := new(big.Int) + ipv6BigIntA.Set(ipv6.Address) + ipv6BigIntB := big.NewInt(i) + + ipv6Addr := ipv6BigIntA.Add(ipv6BigIntA, ipv6BigIntB) + ipv6Addr.And(ipv6Addr, ipv6HostMask) + + return IfAddr{ + SockAddr: IPv6Addr{ + Address: IPv6Address(ipv6Addr), + Mask: ipv6.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + default: + return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType) + } + case "network": + // "network" operates on the network address. Positive values start at the + // network address and negative values wrap at the network address, which + // means a "-1" value on a network will be the broadcast address after + // wrapping is applied. + + if !signRe.MatchString(value) { + return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation) + } + + switch sockType := inputIfAddr.SockAddr.Type(); sockType { + case TypeIPv4: + // 33 == Accept any uint32 value + // TODO(seanc@): Add the ability to parse hex + i, err := strconv.ParseInt(value, 10, 33) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr) + ipv4Uint32 := uint32(ipv4.NetworkAddress()) + + // Wrap along network mask boundaries. EZ-mode wrapping made possible by + // use of int64 vs a uint. + var wrappedMask int64 + if i >= 0 { + wrappedMask = i + } else { + wrappedMask = 1 + i + int64(^uint32(ipv4.Mask)) + } + + ipv4Uint32 = ipv4Uint32 + (uint32(wrappedMask) &^ uint32(ipv4.Mask)) + + return IfAddr{ + SockAddr: IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: ipv4.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + case TypeIPv6: + // 64 == Accept any int32 value + // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int. + i, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr) + ipv6BigInt := new(big.Int) + ipv6BigInt.Set(ipv6.NetworkAddress()) + + mask := new(big.Int) + mask.Set(ipv6.Mask) + if i > 0 { + wrappedMask := new(big.Int) + wrappedMask.SetInt64(i) + + wrappedMask.AndNot(wrappedMask, mask) + ipv6BigInt.Add(ipv6BigInt, wrappedMask) + } else { + // Mask off any bits that exceed the network size. Subtract the + // wrappedMask from the last usable - 1 + wrappedMask := new(big.Int) + wrappedMask.SetInt64(-1 * i) + wrappedMask.Sub(wrappedMask, big.NewInt(1)) + + wrappedMask.AndNot(wrappedMask, mask) + + lastUsable := new(big.Int) + lastUsable.Set(ipv6.LastUsable().(IPv6Addr).Address) + + ipv6BigInt = lastUsable.Sub(lastUsable, wrappedMask) + } + + return IfAddr{ + SockAddr: IPv6Addr{ + Address: IPv6Address(ipv6BigInt), + Mask: ipv6.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + default: + return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType) + } + case "mask": + // "mask" operates on the IP address and returns the IP address on + // which the given integer mask has been applied. If the applied mask + // corresponds to a larger network than the mask of the IP address, + // the latter will be replaced by the former. + switch sockType := inputIfAddr.SockAddr.Type(); sockType { + case TypeIPv4: + i, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + if i > 32 { + return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv4 addresses must be between 0 and 32", operation) + } + + ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr) + + ipv4Mask := net.CIDRMask(int(i), 32) + ipv4MaskUint32 := binary.BigEndian.Uint32(ipv4Mask) + + maskedIpv4 := ipv4.NetIP().Mask(ipv4Mask) + maskedIpv4Uint32 := binary.BigEndian.Uint32(maskedIpv4) + + maskedIpv4MaskUint32 := uint32(ipv4.Mask) + + if ipv4MaskUint32 < maskedIpv4MaskUint32 { + maskedIpv4MaskUint32 = ipv4MaskUint32 + } + + return IfAddr{ + SockAddr: IPv4Addr{ + Address: IPv4Address(maskedIpv4Uint32), + Mask: IPv4Mask(maskedIpv4MaskUint32), + }, + Interface: inputIfAddr.Interface, + }, nil + case TypeIPv6: + i, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + if i > 128 { + return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv6 addresses must be between 0 and 64", operation) + } + + ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr) + + ipv6Mask := net.CIDRMask(int(i), 128) + ipv6MaskBigInt := new(big.Int) + ipv6MaskBigInt.SetBytes(ipv6Mask) + + maskedIpv6 := ipv6.NetIP().Mask(ipv6Mask) + maskedIpv6BigInt := new(big.Int) + maskedIpv6BigInt.SetBytes(maskedIpv6) + + maskedIpv6MaskBigInt := new(big.Int) + maskedIpv6MaskBigInt.Set(ipv6.Mask) + + if ipv6MaskBigInt.Cmp(maskedIpv6MaskBigInt) == -1 { + maskedIpv6MaskBigInt = ipv6MaskBigInt + } + + return IfAddr{ + SockAddr: IPv6Addr{ + Address: IPv6Address(maskedIpv6BigInt), + Mask: IPv6Mask(maskedIpv6MaskBigInt), + }, + Interface: inputIfAddr.Interface, + }, nil + default: + return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType) + } + default: + return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation) + } +} + +// IfAddrsMath will apply an IfAddrMath operation each IfAddr struct. Any +// failure will result in zero results. +func IfAddrsMath(operation, value string, inputIfAddrs IfAddrs) (IfAddrs, error) { + outputAddrs := make(IfAddrs, 0, len(inputIfAddrs)) + for _, ifAddr := range inputIfAddrs { + result, err := IfAddrMath(operation, value, ifAddr) + if err != nil { + return IfAddrs{}, fmt.Errorf("unable to perform an IPMath operation on %s: %v", ifAddr, err) + } + outputAddrs = append(outputAddrs, result) + } + return outputAddrs, nil +} + +// IncludeIfs returns an IfAddrs based on the passed in selector. +func IncludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) { + var includedIfs IfAddrs + var err error + + switch strings.ToLower(selectorName) { + case "address": + includedIfs, _, err = IfByAddress(selectorParam, inputIfAddrs) + case "flag", "flags": + includedIfs, _, err = IfByFlag(selectorParam, inputIfAddrs) + case "name": + includedIfs, _, err = IfByName(selectorParam, inputIfAddrs) + case "network": + includedIfs, _, err = IfByNetwork(selectorParam, inputIfAddrs) + case "port": + includedIfs, _, err = IfByPort(selectorParam, inputIfAddrs) + case "rfc", "rfcs": + includedIfs, _, err = IfByRFCs(selectorParam, inputIfAddrs) + case "size": + includedIfs, _, err = IfByMaskSize(selectorParam, inputIfAddrs) + case "type": + includedIfs, _, err = IfByType(selectorParam, inputIfAddrs) + default: + return IfAddrs{}, fmt.Errorf("invalid include selector %q", selectorName) + } + + if err != nil { + return IfAddrs{}, err + } + + return includedIfs, nil +} + +// ExcludeIfs returns an IfAddrs based on the passed in selector. +func ExcludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) { + var excludedIfs IfAddrs + var err error + + switch strings.ToLower(selectorName) { + case "address": + _, excludedIfs, err = IfByAddress(selectorParam, inputIfAddrs) + case "flag", "flags": + _, excludedIfs, err = IfByFlag(selectorParam, inputIfAddrs) + case "name": + _, excludedIfs, err = IfByName(selectorParam, inputIfAddrs) + case "network": + _, excludedIfs, err = IfByNetwork(selectorParam, inputIfAddrs) + case "port": + _, excludedIfs, err = IfByPort(selectorParam, inputIfAddrs) + case "rfc", "rfcs": + _, excludedIfs, err = IfByRFCs(selectorParam, inputIfAddrs) + case "size": + _, excludedIfs, err = IfByMaskSize(selectorParam, inputIfAddrs) + case "type": + _, excludedIfs, err = IfByType(selectorParam, inputIfAddrs) + default: + return IfAddrs{}, fmt.Errorf("invalid exclude selector %q", selectorName) + } + + if err != nil { + return IfAddrs{}, err + } + + return excludedIfs, nil +} + +// SortIfBy returns an IfAddrs sorted based on the passed in selector. Multiple +// sort clauses can be passed in as a comma delimited list without whitespace. +func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) { + sortedIfs := append(IfAddrs(nil), inputIfAddrs...) + + clauses := strings.Split(selectorParam, ",") + sortFuncs := make([]CmpIfAddrFunc, len(clauses)) + + for i, clause := range clauses { + switch strings.TrimSpace(strings.ToLower(clause)) { + case "+address", "address": + // The "address" selector returns an array of IfAddrs + // ordered by the network address. IfAddrs that are not + // comparable will be at the end of the list and in a + // non-deterministic order. + sortFuncs[i] = AscIfAddress + case "-address": + sortFuncs[i] = DescIfAddress + case "+default", "default": + sortFuncs[i] = AscIfDefault + case "-default": + sortFuncs[i] = DescIfDefault + case "+name", "name": + // The "name" selector returns an array of IfAddrs + // ordered by the interface name. + sortFuncs[i] = AscIfName + case "-name": + sortFuncs[i] = DescIfName + case "+port", "port": + // The "port" selector returns an array of IfAddrs + // ordered by the port, if included in the IfAddr. + // IfAddrs that are not comparable will be at the end of + // the list and in a non-deterministic order. + sortFuncs[i] = AscIfPort + case "-port": + sortFuncs[i] = DescIfPort + case "+private", "private": + // The "private" selector returns an array of IfAddrs + // ordered by private addresses first. IfAddrs that are + // not comparable will be at the end of the list and in + // a non-deterministic order. + sortFuncs[i] = AscIfPrivate + case "-private": + sortFuncs[i] = DescIfPrivate + case "+size", "size": + // The "size" selector returns an array of IfAddrs + // ordered by the size of the network mask, smaller mask + // (larger number of hosts per network) to largest + // (e.g. a /24 sorts before a /32). + sortFuncs[i] = AscIfNetworkSize + case "-size": + sortFuncs[i] = DescIfNetworkSize + case "+type", "type": + // The "type" selector returns an array of IfAddrs + // ordered by the type of the IfAddr. The sort order is + // Unix, IPv4, then IPv6. + sortFuncs[i] = AscIfType + case "-type": + sortFuncs[i] = DescIfType + default: + // Return an empty list for invalid sort types. + return IfAddrs{}, fmt.Errorf("unknown sort type: %q", clause) + } + } + + OrderedIfAddrBy(sortFuncs...).Sort(sortedIfs) + + return sortedIfs, nil +} + +// UniqueIfAddrsBy creates a unique set of IfAddrs based on the matching +// selector. UniqueIfAddrsBy assumes the input has already been sorted. +func UniqueIfAddrsBy(selectorName string, inputIfAddrs IfAddrs) (IfAddrs, error) { + attrName := strings.ToLower(selectorName) + + ifs := make(IfAddrs, 0, len(inputIfAddrs)) + var lastMatch string + for _, ifAddr := range inputIfAddrs { + var out string + switch attrName { + case "address": + out = ifAddr.SockAddr.String() + case "name": + out = ifAddr.Name + default: + return nil, fmt.Errorf("unsupported unique constraint %+q", selectorName) + } + + switch { + case lastMatch == "", lastMatch != out: + lastMatch = out + ifs = append(ifs, ifAddr) + case lastMatch == out: + continue + } + } + + return ifs, nil +} + +// JoinIfAddrs joins an IfAddrs and returns a string +func JoinIfAddrs(selectorName string, joinStr string, inputIfAddrs IfAddrs) (string, error) { + outputs := make([]string, 0, len(inputIfAddrs)) + attrName := AttrName(strings.ToLower(selectorName)) + + for _, ifAddr := range inputIfAddrs { + var attrVal string + var err error + attrVal, err = ifAddr.Attr(attrName) + if err != nil { + return "", err + } + outputs = append(outputs, attrVal) + } + return strings.Join(outputs, joinStr), nil +} + +// LimitIfAddrs returns a slice of IfAddrs based on the specified limit. +func LimitIfAddrs(lim uint, in IfAddrs) (IfAddrs, error) { + // Clamp the limit to the length of the array + if int(lim) > len(in) { + lim = uint(len(in)) + } + + return in[0:lim], nil +} + +// OffsetIfAddrs returns a slice of IfAddrs based on the specified offset. +func OffsetIfAddrs(off int, in IfAddrs) (IfAddrs, error) { + var end bool + if off < 0 { + end = true + off = off * -1 + } + + if off > len(in) { + return IfAddrs{}, fmt.Errorf("unable to seek past the end of the interface array: offset (%d) exceeds the number of interfaces (%d)", off, len(in)) + } + + if end { + return in[len(in)-off:], nil + } + return in[off:], nil +} + +func (ifAddr IfAddr) String() string { + return fmt.Sprintf("%s %v", ifAddr.SockAddr, ifAddr.Interface) +} + +// parseDefaultIfNameFromRoute parses standard route(8)'s output for the *BSDs +// and Solaris. +func parseDefaultIfNameFromRoute(routeOut string) (string, error) { + lines := strings.Split(routeOut, "\n") + for _, line := range lines { + kvs := strings.SplitN(line, ":", 2) + if len(kvs) != 2 { + continue + } + + if strings.TrimSpace(kvs[0]) == "interface" { + ifName := strings.TrimSpace(kvs[1]) + return ifName, nil + } + } + + return "", errors.New("No default interface found") +} + +// parseDefaultIfNameFromIPCmd parses the default interface from ip(8) for +// Linux. +func parseDefaultIfNameFromIPCmd(routeOut string) (string, error) { + parsedLines := parseIfNameFromIPCmd(routeOut) + for _, parsedLine := range parsedLines { + if parsedLine[0] == "default" && + parsedLine[1] == "via" && + parsedLine[3] == "dev" { + ifName := strings.TrimSpace(parsedLine[4]) + return ifName, nil + } + } + + return "", errors.New("No default interface found") +} + +// parseDefaultIfNameFromIPCmdAndroid parses the default interface from ip(8) for +// Android. +func parseDefaultIfNameFromIPCmdAndroid(routeOut string) (string, error) { + parsedLines := parseIfNameFromIPCmd(routeOut) + if (len(parsedLines) > 0) { + ifName := strings.TrimSpace(parsedLines[0][4]) + return ifName, nil + } + + return "", errors.New("No default interface found") +} + + +// parseIfNameFromIPCmd parses interfaces from ip(8) for +// Linux. +func parseIfNameFromIPCmd(routeOut string) [][]string { + lines := strings.Split(routeOut, "\n") + re := whitespaceRE.Copy() + parsedLines := make([][]string, 0, len(lines)) + for _, line := range lines { + kvs := re.Split(line, -1) + if len(kvs) < 5 { + continue + } + parsedLines = append(parsedLines, kvs) + } + return parsedLines +} + +// parseDefaultIfNameWindows parses the default interface from `netstat -rn` and +// `ipconfig` on Windows. +func parseDefaultIfNameWindows(routeOut, ipconfigOut string) (string, error) { + defaultIPAddr, err := parseDefaultIPAddrWindowsRoute(routeOut) + if err != nil { + return "", err + } + + ifName, err := parseDefaultIfNameWindowsIPConfig(defaultIPAddr, ipconfigOut) + if err != nil { + return "", err + } + + return ifName, nil +} + +// parseDefaultIPAddrWindowsRoute parses the IP address on the default interface +// `netstat -rn`. +// +// NOTES(sean): Only IPv4 addresses are parsed at this time. If you have an +// IPv6 connected host, submit an issue on github.com/hashicorp/go-sockaddr with +// the output from `netstat -rn`, `ipconfig`, and version of Windows to see IPv6 +// support added. +func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) { + lines := strings.Split(routeOut, "\n") + re := whitespaceRE.Copy() + for _, line := range lines { + kvs := re.Split(strings.TrimSpace(line), -1) + if len(kvs) < 3 { + continue + } + + if kvs[0] == "0.0.0.0" && kvs[1] == "0.0.0.0" { + defaultIPAddr := strings.TrimSpace(kvs[3]) + return defaultIPAddr, nil + } + } + + return "", errors.New("No IP on default interface found") +} + +// parseDefaultIfNameWindowsIPConfig parses the output of `ipconfig` to find the +// interface name forwarding traffic to the default gateway. +func parseDefaultIfNameWindowsIPConfig(defaultIPAddr, routeOut string) (string, error) { + lines := strings.Split(routeOut, "\n") + ifNameRe := ifNameRE.Copy() + ipAddrRe := ipAddrRE.Copy() + var ifName string + for _, line := range lines { + switch ifNameMatches := ifNameRe.FindStringSubmatch(line); { + case len(ifNameMatches) > 1: + ifName = ifNameMatches[1] + continue + } + + switch ipAddrMatches := ipAddrRe.FindStringSubmatch(line); { + case len(ipAddrMatches) > 1 && ipAddrMatches[1] == defaultIPAddr: + return ifName, nil + } + } + + return "", errors.New("No default interface found with matching IP") +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifattr.go b/vendor/github.com/hashicorp/go-sockaddr/ifattr.go new file mode 100644 index 00000000000..6984cb4a354 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ifattr.go @@ -0,0 +1,65 @@ +package sockaddr + +import ( + "fmt" + "net" +) + +// IfAddr is a union of a SockAddr and a net.Interface. +type IfAddr struct { + SockAddr + net.Interface +} + +// Attr returns the named attribute as a string +func (ifAddr IfAddr) Attr(attrName AttrName) (string, error) { + val := IfAddrAttr(ifAddr, attrName) + if val != "" { + return val, nil + } + + return Attr(ifAddr.SockAddr, attrName) +} + +// Attr returns the named attribute as a string +func Attr(sa SockAddr, attrName AttrName) (string, error) { + switch sockType := sa.Type(); { + case sockType&TypeIP != 0: + ip := *ToIPAddr(sa) + attrVal := IPAddrAttr(ip, attrName) + if attrVal != "" { + return attrVal, nil + } + + if sockType == TypeIPv4 { + ipv4 := *ToIPv4Addr(sa) + attrVal := IPv4AddrAttr(ipv4, attrName) + if attrVal != "" { + return attrVal, nil + } + } else if sockType == TypeIPv6 { + ipv6 := *ToIPv6Addr(sa) + attrVal := IPv6AddrAttr(ipv6, attrName) + if attrVal != "" { + return attrVal, nil + } + } + + case sockType == TypeUnix: + us := *ToUnixSock(sa) + attrVal := UnixSockAttr(us, attrName) + if attrVal != "" { + return attrVal, nil + } + } + + // Non type-specific attributes + switch attrName { + case "string": + return sa.String(), nil + case "type": + return sa.Type().String(), nil + } + + return "", fmt.Errorf("unsupported attribute name %q", attrName) +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go new file mode 100644 index 00000000000..b47d15c2016 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go @@ -0,0 +1,169 @@ +package sockaddr + +import ( + "fmt" + "math/big" + "net" + "strings" +) + +// Constants for the sizes of IPv3, IPv4, and IPv6 address types. +const ( + IPv3len = 6 + IPv4len = 4 + IPv6len = 16 +) + +// IPAddr is a generic IP address interface for IPv4 and IPv6 addresses, +// networks, and socket endpoints. +type IPAddr interface { + SockAddr + AddressBinString() string + AddressHexString() string + Cmp(SockAddr) int + CmpAddress(SockAddr) int + CmpPort(SockAddr) int + FirstUsable() IPAddr + Host() IPAddr + IPPort() IPPort + LastUsable() IPAddr + Maskbits() int + NetIP() *net.IP + NetIPMask() *net.IPMask + NetIPNet() *net.IPNet + Network() IPAddr + Octets() []int +} + +// IPPort is the type for an IP port number for the TCP and UDP IP transports. +type IPPort uint16 + +// IPPrefixLen is a typed integer representing the prefix length for a given +// IPAddr. +type IPPrefixLen byte + +// ipAddrAttrMap is a map of the IPAddr type-specific attributes. +var ipAddrAttrMap map[AttrName]func(IPAddr) string +var ipAddrAttrs []AttrName + +func init() { + ipAddrInit() +} + +// NewIPAddr creates a new IPAddr from a string. Returns nil if the string is +// not an IPv4 or an IPv6 address. +func NewIPAddr(addr string) (IPAddr, error) { + ipv4Addr, err := NewIPv4Addr(addr) + if err == nil { + return ipv4Addr, nil + } + + ipv6Addr, err := NewIPv6Addr(addr) + if err == nil { + return ipv6Addr, nil + } + + return nil, fmt.Errorf("invalid IPAddr %v", addr) +} + +// IPAddrAttr returns a string representation of an attribute for the given +// IPAddr. +func IPAddrAttr(ip IPAddr, selector AttrName) string { + fn, found := ipAddrAttrMap[selector] + if !found { + return "" + } + + return fn(ip) +} + +// IPAttrs returns a list of attributes supported by the IPAddr type +func IPAttrs() []AttrName { + return ipAddrAttrs +} + +// MustIPAddr is a helper method that must return an IPAddr or panic on invalid +// input. +func MustIPAddr(addr string) IPAddr { + ip, err := NewIPAddr(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create an IPAddr from %+q: %v", addr, err)) + } + return ip +} + +// ipAddrInit is called once at init() +func ipAddrInit() { + // Sorted for human readability + ipAddrAttrs = []AttrName{ + "host", + "address", + "port", + "netmask", + "network", + "mask_bits", + "binary", + "hex", + "first_usable", + "last_usable", + "octets", + } + + ipAddrAttrMap = map[AttrName]func(ip IPAddr) string{ + "address": func(ip IPAddr) string { + return ip.NetIP().String() + }, + "binary": func(ip IPAddr) string { + return ip.AddressBinString() + }, + "first_usable": func(ip IPAddr) string { + return ip.FirstUsable().String() + }, + "hex": func(ip IPAddr) string { + return ip.AddressHexString() + }, + "host": func(ip IPAddr) string { + return ip.Host().String() + }, + "last_usable": func(ip IPAddr) string { + return ip.LastUsable().String() + }, + "mask_bits": func(ip IPAddr) string { + return fmt.Sprintf("%d", ip.Maskbits()) + }, + "netmask": func(ip IPAddr) string { + switch v := ip.(type) { + case IPv4Addr: + ipv4Mask := IPv4Addr{ + Address: IPv4Address(v.Mask), + Mask: IPv4HostMask, + } + return ipv4Mask.String() + case IPv6Addr: + ipv6Mask := new(big.Int) + ipv6Mask.Set(v.Mask) + ipv6MaskAddr := IPv6Addr{ + Address: IPv6Address(ipv6Mask), + Mask: ipv6HostMask, + } + return ipv6MaskAddr.String() + default: + return fmt.Sprintf("", ip) + } + }, + "network": func(ip IPAddr) string { + return ip.Network().NetIP().String() + }, + "octets": func(ip IPAddr) string { + octets := ip.Octets() + octetStrs := make([]string, 0, len(octets)) + for _, octet := range octets { + octetStrs = append(octetStrs, fmt.Sprintf("%d", octet)) + } + return strings.Join(octetStrs, " ") + }, + "port": func(ip IPAddr) string { + return fmt.Sprintf("%d", ip.IPPort()) + }, + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go new file mode 100644 index 00000000000..6eeb7ddd2f1 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go @@ -0,0 +1,98 @@ +package sockaddr + +import "bytes" + +type IPAddrs []IPAddr + +func (s IPAddrs) Len() int { return len(s) } +func (s IPAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// // SortIPAddrsByCmp is a type that satisfies sort.Interface and can be used +// // by the routines in this package. The SortIPAddrsByCmp type is used to +// // sort IPAddrs by Cmp() +// type SortIPAddrsByCmp struct{ IPAddrs } + +// // Less reports whether the element with index i should sort before the +// // element with index j. +// func (s SortIPAddrsByCmp) Less(i, j int) bool { +// // Sort by Type, then address, then port number. +// return Less(s.IPAddrs[i], s.IPAddrs[j]) +// } + +// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and +// can be used by the routines in this package. The +// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest +// network (most specific to largest network). +type SortIPAddrsByNetworkSize struct{ IPAddrs } + +// Less reports whether the element with index i should sort before the +// element with index j. +func (s SortIPAddrsByNetworkSize) Less(i, j int) bool { + // Sort masks with a larger binary value (i.e. fewer hosts per network + // prefix) after masks with a smaller value (larger number of hosts per + // prefix). + switch bytes.Compare([]byte(*s.IPAddrs[i].NetIPMask()), []byte(*s.IPAddrs[j].NetIPMask())) { + case 0: + // Fall through to the second test if the net.IPMasks are the + // same. + break + case 1: + return true + case -1: + return false + default: + panic("bad, m'kay?") + } + + // Sort IPs based on the length (i.e. prefer IPv4 over IPv6). + iLen := len(*s.IPAddrs[i].NetIP()) + jLen := len(*s.IPAddrs[j].NetIP()) + if iLen != jLen { + return iLen > jLen + } + + // Sort IPs based on their network address from lowest to highest. + switch bytes.Compare(s.IPAddrs[i].NetIPNet().IP, s.IPAddrs[j].NetIPNet().IP) { + case 0: + break + case 1: + return false + case -1: + return true + default: + panic("lol wut?") + } + + // If a host does not have a port set, it always sorts after hosts + // that have a port (e.g. a host with a /32 and port number is more + // specific and should sort first over a host with a /32 but no port + // set). + if s.IPAddrs[i].IPPort() == 0 || s.IPAddrs[j].IPPort() == 0 { + return false + } + return s.IPAddrs[i].IPPort() < s.IPAddrs[j].IPPort() +} + +// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and +// can be used by the routines in this package. The +// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest +// network (most specific to largest network). +type SortIPAddrsBySpecificMaskLen struct{ IPAddrs } + +// Less reports whether the element with index i should sort before the +// element with index j. +func (s SortIPAddrsBySpecificMaskLen) Less(i, j int) bool { + return s.IPAddrs[i].Maskbits() > s.IPAddrs[j].Maskbits() +} + +// SortIPAddrsByBroadMaskLen is a type that satisfies sort.Interface and can +// be used by the routines in this package. The SortIPAddrsByBroadMaskLen +// type is used to sort IPAddrs by largest network (i.e. largest subnets +// first). +type SortIPAddrsByBroadMaskLen struct{ IPAddrs } + +// Less reports whether the element with index i should sort before the +// element with index j. +func (s SortIPAddrsByBroadMaskLen) Less(i, j int) bool { + return s.IPAddrs[i].Maskbits() < s.IPAddrs[j].Maskbits() +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go b/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go new file mode 100644 index 00000000000..4d395dc954b --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go @@ -0,0 +1,516 @@ +package sockaddr + +import ( + "encoding/binary" + "fmt" + "net" + "regexp" + "strconv" + "strings" +) + +type ( + // IPv4Address is a named type representing an IPv4 address. + IPv4Address uint32 + + // IPv4Network is a named type representing an IPv4 network. + IPv4Network uint32 + + // IPv4Mask is a named type representing an IPv4 network mask. + IPv4Mask uint32 +) + +// IPv4HostMask is a constant represents a /32 IPv4 Address +// (i.e. 255.255.255.255). +const IPv4HostMask = IPv4Mask(0xffffffff) + +// ipv4AddrAttrMap is a map of the IPv4Addr type-specific attributes. +var ipv4AddrAttrMap map[AttrName]func(IPv4Addr) string +var ipv4AddrAttrs []AttrName +var trailingHexNetmaskRE *regexp.Regexp + +// IPv4Addr implements a convenience wrapper around the union of Go's +// built-in net.IP and net.IPNet types. In UNIX-speak, IPv4Addr implements +// `sockaddr` when the the address family is set to AF_INET +// (i.e. `sockaddr_in`). +type IPv4Addr struct { + IPAddr + Address IPv4Address + Mask IPv4Mask + Port IPPort +} + +func init() { + ipv4AddrInit() + trailingHexNetmaskRE = regexp.MustCompile(`/([0f]{8})$`) +} + +// NewIPv4Addr creates an IPv4Addr from a string. String can be in the form +// of either an IPv4:port (e.g. `1.2.3.4:80`, in which case the mask is +// assumed to be a `/32`), an IPv4 address (e.g. `1.2.3.4`, also with a `/32` +// mask), or an IPv4 CIDR (e.g. `1.2.3.4/24`, which has its IP port +// initialized to zero). ipv4Str can not be a hostname. +// +// NOTE: Many net.*() routines will initialize and return an IPv6 address. +// To create uint32 values from net.IP, always test to make sure the address +// returned can be converted to a 4 byte array using To4(). +func NewIPv4Addr(ipv4Str string) (IPv4Addr, error) { + // Strip off any bogus hex-encoded netmasks that will be mis-parsed by Go. In + // particular, clients with the Barracuda VPN client will see something like: + // `192.168.3.51/00ffffff` as their IP address. + trailingHexNetmaskRe := trailingHexNetmaskRE.Copy() + if match := trailingHexNetmaskRe.FindStringIndex(ipv4Str); match != nil { + ipv4Str = ipv4Str[:match[0]] + } + + // Parse as an IPv4 CIDR + ipAddr, network, err := net.ParseCIDR(ipv4Str) + if err == nil { + ipv4 := ipAddr.To4() + if ipv4 == nil { + return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address", ipv4Str) + } + + // If we see an IPv6 netmask, convert it to an IPv4 mask. + netmaskSepPos := strings.LastIndexByte(ipv4Str, '/') + if netmaskSepPos != -1 && netmaskSepPos+1 < len(ipv4Str) { + netMask, err := strconv.ParseUint(ipv4Str[netmaskSepPos+1:], 10, 8) + if err != nil { + return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: unable to parse CIDR netmask: %v", ipv4Str, err) + } else if netMask > 128 { + return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: invalid CIDR netmask", ipv4Str) + } + + if netMask >= 96 { + // Convert the IPv6 netmask to an IPv4 netmask + network.Mask = net.CIDRMask(int(netMask-96), IPv4len*8) + } + } + ipv4Addr := IPv4Addr{ + Address: IPv4Address(binary.BigEndian.Uint32(ipv4)), + Mask: IPv4Mask(binary.BigEndian.Uint32(network.Mask)), + } + return ipv4Addr, nil + } + + // Attempt to parse ipv4Str as a /32 host with a port number. + tcpAddr, err := net.ResolveTCPAddr("tcp4", ipv4Str) + if err == nil { + ipv4 := tcpAddr.IP.To4() + if ipv4 == nil { + return IPv4Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv4 address", ipv4Str) + } + + ipv4Uint32 := binary.BigEndian.Uint32(ipv4) + ipv4Addr := IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: IPv4HostMask, + Port: IPPort(tcpAddr.Port), + } + + return ipv4Addr, nil + } + + // Parse as a naked IPv4 address + ip := net.ParseIP(ipv4Str) + if ip != nil { + ipv4 := ip.To4() + if ipv4 == nil { + return IPv4Addr{}, fmt.Errorf("Unable to string convert %+q to an IPv4 address", ipv4Str) + } + + ipv4Uint32 := binary.BigEndian.Uint32(ipv4) + ipv4Addr := IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: IPv4HostMask, + } + return ipv4Addr, nil + } + + return IPv4Addr{}, fmt.Errorf("Unable to parse %+q to an IPv4 address: %v", ipv4Str, err) +} + +// AddressBinString returns a string with the IPv4Addr's Address represented +// as a sequence of '0' and '1' characters. This method is useful for +// debugging or by operators who want to inspect an address. +func (ipv4 IPv4Addr) AddressBinString() string { + return fmt.Sprintf("%032s", strconv.FormatUint(uint64(ipv4.Address), 2)) +} + +// AddressHexString returns a string with the IPv4Addr address represented as +// a sequence of hex characters. This method is useful for debugging or by +// operators who want to inspect an address. +func (ipv4 IPv4Addr) AddressHexString() string { + return fmt.Sprintf("%08s", strconv.FormatUint(uint64(ipv4.Address), 16)) +} + +// Broadcast is an IPv4Addr-only method that returns the broadcast address of +// the network. +// +// NOTE: IPv6 only supports multicast, so this method only exists for +// IPv4Addr. +func (ipv4 IPv4Addr) Broadcast() IPAddr { + // Nothing should listen on a broadcast address. + return IPv4Addr{ + Address: IPv4Address(ipv4.BroadcastAddress()), + Mask: IPv4HostMask, + } +} + +// BroadcastAddress returns a IPv4Network of the IPv4Addr's broadcast +// address. +func (ipv4 IPv4Addr) BroadcastAddress() IPv4Network { + return IPv4Network(uint32(ipv4.Address)&uint32(ipv4.Mask) | ^uint32(ipv4.Mask)) +} + +// CmpAddress follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its address is lower than arg +// - 0 if the SockAddr arg is equal to the receiving IPv4Addr or the argument is +// of a different type. +// - 1 If the argument should sort first. +func (ipv4 IPv4Addr) CmpAddress(sa SockAddr) int { + ipv4b, ok := sa.(IPv4Addr) + if !ok { + return sortDeferDecision + } + + switch { + case ipv4.Address == ipv4b.Address: + return sortDeferDecision + case ipv4.Address < ipv4b.Address: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// CmpPort follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its port is lower than arg +// - 0 if the SockAddr arg's port number is equal to the receiving IPv4Addr, +// regardless of type. +// - 1 If the argument should sort first. +func (ipv4 IPv4Addr) CmpPort(sa SockAddr) int { + var saPort IPPort + switch v := sa.(type) { + case IPv4Addr: + saPort = v.Port + case IPv6Addr: + saPort = v.Port + default: + return sortDeferDecision + } + + switch { + case ipv4.Port == saPort: + return sortDeferDecision + case ipv4.Port < saPort: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// CmpRFC follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because it belongs to the RFC and its +// arg does not +// - 0 if the receiver and arg both belong to the same RFC or neither do. +// - 1 If the arg belongs to the RFC but receiver does not. +func (ipv4 IPv4Addr) CmpRFC(rfcNum uint, sa SockAddr) int { + recvInRFC := IsRFC(rfcNum, ipv4) + ipv4b, ok := sa.(IPv4Addr) + if !ok { + // If the receiver is part of the desired RFC and the SockAddr + // argument is not, return -1 so that the receiver sorts before + // the non-IPv4 SockAddr. Conversely, if the receiver is not + // part of the RFC, punt on sorting and leave it for the next + // sorter. + if recvInRFC { + return sortReceiverBeforeArg + } else { + return sortDeferDecision + } + } + + argInRFC := IsRFC(rfcNum, ipv4b) + switch { + case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC): + // If a and b both belong to the RFC, or neither belong to + // rfcNum, defer sorting to the next sorter. + return sortDeferDecision + case recvInRFC && !argInRFC: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// Contains returns true if the SockAddr is contained within the receiver. +func (ipv4 IPv4Addr) Contains(sa SockAddr) bool { + ipv4b, ok := sa.(IPv4Addr) + if !ok { + return false + } + + return ipv4.ContainsNetwork(ipv4b) +} + +// ContainsAddress returns true if the IPv4Address is contained within the +// receiver. +func (ipv4 IPv4Addr) ContainsAddress(x IPv4Address) bool { + return IPv4Address(ipv4.NetworkAddress()) <= x && + IPv4Address(ipv4.BroadcastAddress()) >= x +} + +// ContainsNetwork returns true if the network from IPv4Addr is contained +// within the receiver. +func (ipv4 IPv4Addr) ContainsNetwork(x IPv4Addr) bool { + return ipv4.NetworkAddress() <= x.NetworkAddress() && + ipv4.BroadcastAddress() >= x.BroadcastAddress() +} + +// DialPacketArgs returns the arguments required to be passed to +// net.DialUDP(). If the Mask of ipv4 is not a /32 or the Port is 0, +// DialPacketArgs() will fail. See Host() to create an IPv4Addr with its +// mask set to /32. +func (ipv4 IPv4Addr) DialPacketArgs() (network, dialArgs string) { + if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 { + return "udp4", "" + } + return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// DialStreamArgs returns the arguments required to be passed to +// net.DialTCP(). If the Mask of ipv4 is not a /32 or the Port is 0, +// DialStreamArgs() will fail. See Host() to create an IPv4Addr with its +// mask set to /32. +func (ipv4 IPv4Addr) DialStreamArgs() (network, dialArgs string) { + if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 { + return "tcp4", "" + } + return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// Equal returns true if a SockAddr is equal to the receiving IPv4Addr. +func (ipv4 IPv4Addr) Equal(sa SockAddr) bool { + ipv4b, ok := sa.(IPv4Addr) + if !ok { + return false + } + + if ipv4.Port != ipv4b.Port { + return false + } + + if ipv4.Address != ipv4b.Address { + return false + } + + if ipv4.NetIPNet().String() != ipv4b.NetIPNet().String() { + return false + } + + return true +} + +// FirstUsable returns an IPv4Addr set to the first address following the +// network prefix. The first usable address in a network is normally the +// gateway and should not be used except by devices forwarding packets +// between two administratively distinct networks (i.e. a router). This +// function does not discriminate against first usable vs "first address that +// should be used." For example, FirstUsable() on "192.168.1.10/24" would +// return the address "192.168.1.1/24". +func (ipv4 IPv4Addr) FirstUsable() IPAddr { + addr := ipv4.NetworkAddress() + + // If /32, return the address itself. If /31 assume a point-to-point + // link and return the lower address. + if ipv4.Maskbits() < 31 { + addr++ + } + + return IPv4Addr{ + Address: IPv4Address(addr), + Mask: IPv4HostMask, + } +} + +// Host returns a copy of ipv4 with its mask set to /32 so that it can be +// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or +// ListenStreamArgs(). +func (ipv4 IPv4Addr) Host() IPAddr { + // Nothing should listen on a broadcast address. + return IPv4Addr{ + Address: ipv4.Address, + Mask: IPv4HostMask, + Port: ipv4.Port, + } +} + +// IPPort returns the Port number attached to the IPv4Addr +func (ipv4 IPv4Addr) IPPort() IPPort { + return ipv4.Port +} + +// LastUsable returns the last address before the broadcast address in a +// given network. +func (ipv4 IPv4Addr) LastUsable() IPAddr { + addr := ipv4.BroadcastAddress() + + // If /32, return the address itself. If /31 assume a point-to-point + // link and return the upper address. + if ipv4.Maskbits() < 31 { + addr-- + } + + return IPv4Addr{ + Address: IPv4Address(addr), + Mask: IPv4HostMask, + } +} + +// ListenPacketArgs returns the arguments required to be passed to +// net.ListenUDP(). If the Mask of ipv4 is not a /32, ListenPacketArgs() +// will fail. See Host() to create an IPv4Addr with its mask set to /32. +func (ipv4 IPv4Addr) ListenPacketArgs() (network, listenArgs string) { + if ipv4.Mask != IPv4HostMask { + return "udp4", "" + } + return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// ListenStreamArgs returns the arguments required to be passed to +// net.ListenTCP(). If the Mask of ipv4 is not a /32, ListenStreamArgs() +// will fail. See Host() to create an IPv4Addr with its mask set to /32. +func (ipv4 IPv4Addr) ListenStreamArgs() (network, listenArgs string) { + if ipv4.Mask != IPv4HostMask { + return "tcp4", "" + } + return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// Maskbits returns the number of network mask bits in a given IPv4Addr. For +// example, the Maskbits() of "192.168.1.1/24" would return 24. +func (ipv4 IPv4Addr) Maskbits() int { + mask := make(net.IPMask, IPv4len) + binary.BigEndian.PutUint32(mask, uint32(ipv4.Mask)) + maskOnes, _ := mask.Size() + return maskOnes +} + +// MustIPv4Addr is a helper method that must return an IPv4Addr or panic on +// invalid input. +func MustIPv4Addr(addr string) IPv4Addr { + ipv4, err := NewIPv4Addr(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create an IPv4Addr from %+q: %v", addr, err)) + } + return ipv4 +} + +// NetIP returns the address as a net.IP (address is always presized to +// IPv4). +func (ipv4 IPv4Addr) NetIP() *net.IP { + x := make(net.IP, IPv4len) + binary.BigEndian.PutUint32(x, uint32(ipv4.Address)) + return &x +} + +// NetIPMask create a new net.IPMask from the IPv4Addr. +func (ipv4 IPv4Addr) NetIPMask() *net.IPMask { + ipv4Mask := net.IPMask{} + ipv4Mask = make(net.IPMask, IPv4len) + binary.BigEndian.PutUint32(ipv4Mask, uint32(ipv4.Mask)) + return &ipv4Mask +} + +// NetIPNet create a new net.IPNet from the IPv4Addr. +func (ipv4 IPv4Addr) NetIPNet() *net.IPNet { + ipv4net := &net.IPNet{} + ipv4net.IP = make(net.IP, IPv4len) + binary.BigEndian.PutUint32(ipv4net.IP, uint32(ipv4.NetworkAddress())) + ipv4net.Mask = *ipv4.NetIPMask() + return ipv4net +} + +// Network returns the network prefix or network address for a given network. +func (ipv4 IPv4Addr) Network() IPAddr { + return IPv4Addr{ + Address: IPv4Address(ipv4.NetworkAddress()), + Mask: ipv4.Mask, + } +} + +// NetworkAddress returns an IPv4Network of the IPv4Addr's network address. +func (ipv4 IPv4Addr) NetworkAddress() IPv4Network { + return IPv4Network(uint32(ipv4.Address) & uint32(ipv4.Mask)) +} + +// Octets returns a slice of the four octets in an IPv4Addr's Address. The +// order of the bytes is big endian. +func (ipv4 IPv4Addr) Octets() []int { + return []int{ + int(ipv4.Address >> 24), + int((ipv4.Address >> 16) & 0xff), + int((ipv4.Address >> 8) & 0xff), + int(ipv4.Address & 0xff), + } +} + +// String returns a string representation of the IPv4Addr +func (ipv4 IPv4Addr) String() string { + if ipv4.Port != 0 { + return fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) + } + + if ipv4.Maskbits() == 32 { + return ipv4.NetIP().String() + } + + return fmt.Sprintf("%s/%d", ipv4.NetIP().String(), ipv4.Maskbits()) +} + +// Type is used as a type switch and returns TypeIPv4 +func (IPv4Addr) Type() SockAddrType { + return TypeIPv4 +} + +// IPv4AddrAttr returns a string representation of an attribute for the given +// IPv4Addr. +func IPv4AddrAttr(ipv4 IPv4Addr, selector AttrName) string { + fn, found := ipv4AddrAttrMap[selector] + if !found { + return "" + } + + return fn(ipv4) +} + +// IPv4Attrs returns a list of attributes supported by the IPv4Addr type +func IPv4Attrs() []AttrName { + return ipv4AddrAttrs +} + +// ipv4AddrInit is called once at init() +func ipv4AddrInit() { + // Sorted for human readability + ipv4AddrAttrs = []AttrName{ + "size", // Same position as in IPv6 for output consistency + "broadcast", + "uint32", + } + + ipv4AddrAttrMap = map[AttrName]func(ipv4 IPv4Addr) string{ + "broadcast": func(ipv4 IPv4Addr) string { + return ipv4.Broadcast().String() + }, + "size": func(ipv4 IPv4Addr) string { + return fmt.Sprintf("%d", 1< 2 && ipv6Str[0] == '[' && ipv6Str[len(ipv6Str)-1] == ']' { + ipv6Str = ipv6Str[1 : len(ipv6Str)-1] + } + ip := net.ParseIP(ipv6Str) + if ip != nil { + ipv6 := ip.To16() + if ipv6 == nil { + return IPv6Addr{}, fmt.Errorf("Unable to string convert %+q to a 16byte IPv6 address", ipv6Str) + } + + ipv6BigIntAddr := new(big.Int) + ipv6BigIntAddr.SetBytes(ipv6) + + ipv6BigIntMask := new(big.Int) + ipv6BigIntMask.Set(ipv6HostMask) + + return IPv6Addr{ + Address: IPv6Address(ipv6BigIntAddr), + Mask: IPv6Mask(ipv6BigIntMask), + }, nil + } + + // Parse as an IPv6 CIDR + ipAddr, network, err := net.ParseCIDR(ipv6Str) + if err == nil { + ipv6 := ipAddr.To16() + if ipv6 == nil { + return IPv6Addr{}, fmt.Errorf("Unable to convert %+q to a 16byte IPv6 address", ipv6Str) + } + + ipv6BigIntAddr := new(big.Int) + ipv6BigIntAddr.SetBytes(ipv6) + + ipv6BigIntMask := new(big.Int) + ipv6BigIntMask.SetBytes(network.Mask) + + ipv6Addr := IPv6Addr{ + Address: IPv6Address(ipv6BigIntAddr), + Mask: IPv6Mask(ipv6BigIntMask), + } + return ipv6Addr, nil + } + + return IPv6Addr{}, fmt.Errorf("Unable to parse %+q to an IPv6 address: %v", ipv6Str, err) +} + +// AddressBinString returns a string with the IPv6Addr's Address represented +// as a sequence of '0' and '1' characters. This method is useful for +// debugging or by operators who want to inspect an address. +func (ipv6 IPv6Addr) AddressBinString() string { + bi := big.Int(*ipv6.Address) + return fmt.Sprintf("%0128s", bi.Text(2)) +} + +// AddressHexString returns a string with the IPv6Addr address represented as +// a sequence of hex characters. This method is useful for debugging or by +// operators who want to inspect an address. +func (ipv6 IPv6Addr) AddressHexString() string { + bi := big.Int(*ipv6.Address) + return fmt.Sprintf("%032s", bi.Text(16)) +} + +// CmpAddress follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its address is lower than arg +// - 0 if the SockAddr arg equal to the receiving IPv6Addr or the argument is of a +// different type. +// - 1 If the argument should sort first. +func (ipv6 IPv6Addr) CmpAddress(sa SockAddr) int { + ipv6b, ok := sa.(IPv6Addr) + if !ok { + return sortDeferDecision + } + + ipv6aBigInt := new(big.Int) + ipv6aBigInt.Set(ipv6.Address) + ipv6bBigInt := new(big.Int) + ipv6bBigInt.Set(ipv6b.Address) + + return ipv6aBigInt.Cmp(ipv6bBigInt) +} + +// CmpPort follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its port is lower than arg +// - 0 if the SockAddr arg's port number is equal to the receiving IPv6Addr, +// regardless of type. +// - 1 If the argument should sort first. +func (ipv6 IPv6Addr) CmpPort(sa SockAddr) int { + var saPort IPPort + switch v := sa.(type) { + case IPv4Addr: + saPort = v.Port + case IPv6Addr: + saPort = v.Port + default: + return sortDeferDecision + } + + switch { + case ipv6.Port == saPort: + return sortDeferDecision + case ipv6.Port < saPort: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// CmpRFC follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because it belongs to the RFC and its +// arg does not +// - 0 if the receiver and arg both belong to the same RFC or neither do. +// - 1 If the arg belongs to the RFC but receiver does not. +func (ipv6 IPv6Addr) CmpRFC(rfcNum uint, sa SockAddr) int { + recvInRFC := IsRFC(rfcNum, ipv6) + ipv6b, ok := sa.(IPv6Addr) + if !ok { + // If the receiver is part of the desired RFC and the SockAddr + // argument is not, sort receiver before the non-IPv6 SockAddr. + // Conversely, if the receiver is not part of the RFC, punt on + // sorting and leave it for the next sorter. + if recvInRFC { + return sortReceiverBeforeArg + } else { + return sortDeferDecision + } + } + + argInRFC := IsRFC(rfcNum, ipv6b) + switch { + case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC): + // If a and b both belong to the RFC, or neither belong to + // rfcNum, defer sorting to the next sorter. + return sortDeferDecision + case recvInRFC && !argInRFC: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// Contains returns true if the SockAddr is contained within the receiver. +func (ipv6 IPv6Addr) Contains(sa SockAddr) bool { + ipv6b, ok := sa.(IPv6Addr) + if !ok { + return false + } + + return ipv6.ContainsNetwork(ipv6b) +} + +// ContainsAddress returns true if the IPv6Address is contained within the +// receiver. +func (ipv6 IPv6Addr) ContainsAddress(x IPv6Address) bool { + xAddr := IPv6Addr{ + Address: x, + Mask: ipv6HostMask, + } + + { + xIPv6 := xAddr.FirstUsable().(IPv6Addr) + yIPv6 := ipv6.FirstUsable().(IPv6Addr) + if xIPv6.CmpAddress(yIPv6) >= 1 { + return false + } + } + + { + xIPv6 := xAddr.LastUsable().(IPv6Addr) + yIPv6 := ipv6.LastUsable().(IPv6Addr) + if xIPv6.CmpAddress(yIPv6) <= -1 { + return false + } + } + return true +} + +// ContainsNetwork returns true if the network from IPv6Addr is contained within +// the receiver. +func (x IPv6Addr) ContainsNetwork(y IPv6Addr) bool { + { + xIPv6 := x.FirstUsable().(IPv6Addr) + yIPv6 := y.FirstUsable().(IPv6Addr) + if ret := xIPv6.CmpAddress(yIPv6); ret >= 1 { + return false + } + } + + { + xIPv6 := x.LastUsable().(IPv6Addr) + yIPv6 := y.LastUsable().(IPv6Addr) + if ret := xIPv6.CmpAddress(yIPv6); ret <= -1 { + return false + } + } + return true +} + +// DialPacketArgs returns the arguments required to be passed to +// net.DialUDP(). If the Mask of ipv6 is not a /128 or the Port is 0, +// DialPacketArgs() will fail. See Host() to create an IPv6Addr with its +// mask set to /128. +func (ipv6 IPv6Addr) DialPacketArgs() (network, dialArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 { + return "udp6", "" + } + return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// DialStreamArgs returns the arguments required to be passed to +// net.DialTCP(). If the Mask of ipv6 is not a /128 or the Port is 0, +// DialStreamArgs() will fail. See Host() to create an IPv6Addr with its +// mask set to /128. +func (ipv6 IPv6Addr) DialStreamArgs() (network, dialArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 { + return "tcp6", "" + } + return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// Equal returns true if a SockAddr is equal to the receiving IPv4Addr. +func (ipv6a IPv6Addr) Equal(sa SockAddr) bool { + ipv6b, ok := sa.(IPv6Addr) + if !ok { + return false + } + + if ipv6a.NetIP().String() != ipv6b.NetIP().String() { + return false + } + + if ipv6a.NetIPNet().String() != ipv6b.NetIPNet().String() { + return false + } + + if ipv6a.Port != ipv6b.Port { + return false + } + + return true +} + +// FirstUsable returns an IPv6Addr set to the first address following the +// network prefix. The first usable address in a network is normally the +// gateway and should not be used except by devices forwarding packets +// between two administratively distinct networks (i.e. a router). This +// function does not discriminate against first usable vs "first address that +// should be used." For example, FirstUsable() on "2001:0db8::0003/64" would +// return "2001:0db8::00011". +func (ipv6 IPv6Addr) FirstUsable() IPAddr { + return IPv6Addr{ + Address: IPv6Address(ipv6.NetworkAddress()), + Mask: ipv6HostMask, + } +} + +// Host returns a copy of ipv6 with its mask set to /128 so that it can be +// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or +// ListenStreamArgs(). +func (ipv6 IPv6Addr) Host() IPAddr { + // Nothing should listen on a broadcast address. + return IPv6Addr{ + Address: ipv6.Address, + Mask: ipv6HostMask, + Port: ipv6.Port, + } +} + +// IPPort returns the Port number attached to the IPv6Addr +func (ipv6 IPv6Addr) IPPort() IPPort { + return ipv6.Port +} + +// LastUsable returns the last address in a given network. +func (ipv6 IPv6Addr) LastUsable() IPAddr { + addr := new(big.Int) + addr.Set(ipv6.Address) + + mask := new(big.Int) + mask.Set(ipv6.Mask) + + negMask := new(big.Int) + negMask.Xor(ipv6HostMask, mask) + + lastAddr := new(big.Int) + lastAddr.And(addr, mask) + lastAddr.Or(lastAddr, negMask) + + return IPv6Addr{ + Address: IPv6Address(lastAddr), + Mask: ipv6HostMask, + } +} + +// ListenPacketArgs returns the arguments required to be passed to +// net.ListenUDP(). If the Mask of ipv6 is not a /128, ListenPacketArgs() +// will fail. See Host() to create an IPv6Addr with its mask set to /128. +func (ipv6 IPv6Addr) ListenPacketArgs() (network, listenArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 { + return "udp6", "" + } + return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// ListenStreamArgs returns the arguments required to be passed to +// net.ListenTCP(). If the Mask of ipv6 is not a /128, ListenStreamArgs() +// will fail. See Host() to create an IPv6Addr with its mask set to /128. +func (ipv6 IPv6Addr) ListenStreamArgs() (network, listenArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 { + return "tcp6", "" + } + return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// Maskbits returns the number of network mask bits in a given IPv6Addr. For +// example, the Maskbits() of "2001:0db8::0003/64" would return 64. +func (ipv6 IPv6Addr) Maskbits() int { + maskOnes, _ := ipv6.NetIPNet().Mask.Size() + + return maskOnes +} + +// MustIPv6Addr is a helper method that must return an IPv6Addr or panic on +// invalid input. +func MustIPv6Addr(addr string) IPv6Addr { + ipv6, err := NewIPv6Addr(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create an IPv6Addr from %+q: %v", addr, err)) + } + return ipv6 +} + +// NetIP returns the address as a net.IP. +func (ipv6 IPv6Addr) NetIP() *net.IP { + return bigIntToNetIPv6(ipv6.Address) +} + +// NetIPMask create a new net.IPMask from the IPv6Addr. +func (ipv6 IPv6Addr) NetIPMask() *net.IPMask { + ipv6Mask := make(net.IPMask, IPv6len) + m := big.Int(*ipv6.Mask) + copy(ipv6Mask, m.Bytes()) + return &ipv6Mask +} + +// Network returns a pointer to the net.IPNet within IPv4Addr receiver. +func (ipv6 IPv6Addr) NetIPNet() *net.IPNet { + ipv6net := &net.IPNet{} + ipv6net.IP = make(net.IP, IPv6len) + copy(ipv6net.IP, *ipv6.NetIP()) + ipv6net.Mask = *ipv6.NetIPMask() + return ipv6net +} + +// Network returns the network prefix or network address for a given network. +func (ipv6 IPv6Addr) Network() IPAddr { + return IPv6Addr{ + Address: IPv6Address(ipv6.NetworkAddress()), + Mask: ipv6.Mask, + } +} + +// NetworkAddress returns an IPv6Network of the IPv6Addr's network address. +func (ipv6 IPv6Addr) NetworkAddress() IPv6Network { + addr := new(big.Int) + addr.SetBytes((*ipv6.Address).Bytes()) + + mask := new(big.Int) + mask.SetBytes(*ipv6.NetIPMask()) + + netAddr := new(big.Int) + netAddr.And(addr, mask) + + return IPv6Network(netAddr) +} + +// Octets returns a slice of the 16 octets in an IPv6Addr's Address. The +// order of the bytes is big endian. +func (ipv6 IPv6Addr) Octets() []int { + x := make([]int, IPv6len) + for i, b := range *bigIntToNetIPv6(ipv6.Address) { + x[i] = int(b) + } + + return x +} + +// String returns a string representation of the IPv6Addr +func (ipv6 IPv6Addr) String() string { + if ipv6.Port != 0 { + return fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) + } + + if ipv6.Maskbits() == 128 { + return ipv6.NetIP().String() + } + + return fmt.Sprintf("%s/%d", ipv6.NetIP().String(), ipv6.Maskbits()) +} + +// Type is used as a type switch and returns TypeIPv6 +func (IPv6Addr) Type() SockAddrType { + return TypeIPv6 +} + +// IPv6Attrs returns a list of attributes supported by the IPv6Addr type +func IPv6Attrs() []AttrName { + return ipv6AddrAttrs +} + +// IPv6AddrAttr returns a string representation of an attribute for the given +// IPv6Addr. +func IPv6AddrAttr(ipv6 IPv6Addr, selector AttrName) string { + fn, found := ipv6AddrAttrMap[selector] + if !found { + return "" + } + + return fn(ipv6) +} + +// ipv6AddrInit is called once at init() +func ipv6AddrInit() { + // Sorted for human readability + ipv6AddrAttrs = []AttrName{ + "size", // Same position as in IPv6 for output consistency + "uint128", + } + + ipv6AddrAttrMap = map[AttrName]func(ipv6 IPv6Addr) string{ + "size": func(ipv6 IPv6Addr) string { + netSize := big.NewInt(1) + netSize = netSize.Lsh(netSize, uint(IPv6len*8-ipv6.Maskbits())) + return netSize.Text(10) + }, + "uint128": func(ipv6 IPv6Addr) string { + b := big.Int(*ipv6.Address) + return b.Text(10) + }, + } +} + +// bigIntToNetIPv6 is a helper function that correctly returns a net.IP with the +// correctly padded values. +func bigIntToNetIPv6(bi *big.Int) *net.IP { + x := make(net.IP, IPv6len) + ipv6Bytes := bi.Bytes() + + // It's possibe for ipv6Bytes to be less than IPv6len bytes in size. If + // they are different sizes we to pad the size of response. + if len(ipv6Bytes) < IPv6len { + buf := new(bytes.Buffer) + buf.Grow(IPv6len) + + for i := len(ipv6Bytes); i < IPv6len; i++ { + if err := binary.Write(buf, binary.BigEndian, byte(0)); err != nil { + panic(fmt.Sprintf("Unable to pad byte %d of input %v: %v", i, bi, err)) + } + } + + for _, b := range ipv6Bytes { + if err := binary.Write(buf, binary.BigEndian, b); err != nil { + panic(fmt.Sprintf("Unable to preserve endianness of input %v: %v", bi, err)) + } + } + + ipv6Bytes = buf.Bytes() + } + i := copy(x, ipv6Bytes) + if i != IPv6len { + panic("IPv6 wrong size") + } + return &x +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/rfc.go b/vendor/github.com/hashicorp/go-sockaddr/rfc.go new file mode 100644 index 00000000000..02e188f6fe6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/rfc.go @@ -0,0 +1,948 @@ +package sockaddr + +// ForwardingBlacklist is a faux RFC that includes a list of non-forwardable IP +// blocks. +const ForwardingBlacklist = 4294967295 +const ForwardingBlacklistRFC = "4294967295" + +// IsRFC tests to see if an SockAddr matches the specified RFC +func IsRFC(rfcNum uint, sa SockAddr) bool { + rfcNetMap := KnownRFCs() + rfcNets, ok := rfcNetMap[rfcNum] + if !ok { + return false + } + + var contained bool + for _, rfcNet := range rfcNets { + if rfcNet.Contains(sa) { + contained = true + break + } + } + return contained +} + +// KnownRFCs returns an initial set of known RFCs. +// +// NOTE (sean@): As this list evolves over time, please submit patches to keep +// this list current. If something isn't right, inquire, as it may just be a +// bug on my part. Some of the inclusions were based on my judgement as to what +// would be a useful value (e.g. RFC3330). +// +// Useful resources: +// +// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml +// * https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.xhtml +// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml +func KnownRFCs() map[uint]SockAddrs { + // NOTE(sean@): Multiple SockAddrs per RFC lend themselves well to a + // RADIX tree, but `ENOTIME`. Patches welcome. + return map[uint]SockAddrs{ + 919: { + // [RFC919] Broadcasting Internet Datagrams + MustIPv4Addr("255.255.255.255/32"), // [RFC1122], §7 Broadcast IP Addressing - Proposed Standards + }, + 1122: { + // [RFC1122] Requirements for Internet Hosts -- Communication Layers + MustIPv4Addr("0.0.0.0/8"), // [RFC1122], §3.2.1.3 + MustIPv4Addr("127.0.0.0/8"), // [RFC1122], §3.2.1.3 + }, + 1112: { + // [RFC1112] Host Extensions for IP Multicasting + MustIPv4Addr("224.0.0.0/4"), // [RFC1112], §4 Host Group Addresses + }, + 1918: { + // [RFC1918] Address Allocation for Private Internets + MustIPv4Addr("10.0.0.0/8"), + MustIPv4Addr("172.16.0.0/12"), + MustIPv4Addr("192.168.0.0/16"), + }, + 2544: { + // [RFC2544] Benchmarking Methodology for Network + // Interconnect Devices + MustIPv4Addr("198.18.0.0/15"), + }, + 2765: { + // [RFC2765] Stateless IP/ICMP Translation Algorithm + // (SIIT) (obsoleted by RFCs 6145, which itself was + // later obsoleted by 7915). + + // [RFC2765], §2.1 Addresses + MustIPv6Addr("0:0:0:0:0:ffff:0:0/96"), + }, + 2928: { + // [RFC2928] Initial IPv6 Sub-TLA ID Assignments + MustIPv6Addr("2001::/16"), // Superblock + //MustIPv6Addr("2001:0000::/23"), // IANA + //MustIPv6Addr("2001:0200::/23"), // APNIC + //MustIPv6Addr("2001:0400::/23"), // ARIN + //MustIPv6Addr("2001:0600::/23"), // RIPE NCC + //MustIPv6Addr("2001:0800::/23"), // (future assignment) + // ... + //MustIPv6Addr("2001:FE00::/23"), // (future assignment) + }, + 3056: { // 6to4 address + // [RFC3056] Connection of IPv6 Domains via IPv4 Clouds + + // [RFC3056], §2 IPv6 Prefix Allocation + MustIPv6Addr("2002::/16"), + }, + 3068: { + // [RFC3068] An Anycast Prefix for 6to4 Relay Routers + // (obsolete by RFC7526) + + // [RFC3068], § 6to4 Relay anycast address + MustIPv4Addr("192.88.99.0/24"), + + // [RFC3068], §2.5 6to4 IPv6 relay anycast address + // + // NOTE: /120 == 128-(32-24) + MustIPv6Addr("2002:c058:6301::/120"), + }, + 3171: { + // [RFC3171] IANA Guidelines for IPv4 Multicast Address Assignments + MustIPv4Addr("224.0.0.0/4"), + }, + 3330: { + // [RFC3330] Special-Use IPv4 Addresses + + // Addresses in this block refer to source hosts on + // "this" network. Address 0.0.0.0/32 may be used as a + // source address for this host on this network; other + // addresses within 0.0.0.0/8 may be used to refer to + // specified hosts on this network [RFC1700, page 4]. + MustIPv4Addr("0.0.0.0/8"), + + // 10.0.0.0/8 - This block is set aside for use in + // private networks. Its intended use is documented in + // [RFC1918]. Addresses within this block should not + // appear on the public Internet. + MustIPv4Addr("10.0.0.0/8"), + + // 14.0.0.0/8 - This block is set aside for assignments + // to the international system of Public Data Networks + // [RFC1700, page 181]. The registry of assignments + // within this block can be accessed from the "Public + // Data Network Numbers" link on the web page at + // http://www.iana.org/numbers.html. Addresses within + // this block are assigned to users and should be + // treated as such. + + // 24.0.0.0/8 - This block was allocated in early 1996 + // for use in provisioning IP service over cable + // television systems. Although the IANA initially was + // involved in making assignments to cable operators, + // this responsibility was transferred to American + // Registry for Internet Numbers (ARIN) in May 2001. + // Addresses within this block are assigned in the + // normal manner and should be treated as such. + + // 39.0.0.0/8 - This block was used in the "Class A + // Subnet Experiment" that commenced in May 1995, as + // documented in [RFC1797]. The experiment has been + // completed and this block has been returned to the + // pool of addresses reserved for future allocation or + // assignment. This block therefore no longer has a + // special use and is subject to allocation to a + // Regional Internet Registry for assignment in the + // normal manner. + + // 127.0.0.0/8 - This block is assigned for use as the Internet host + // loopback address. A datagram sent by a higher level protocol to an + // address anywhere within this block should loop back inside the host. + // This is ordinarily implemented using only 127.0.0.1/32 for loopback, + // but no addresses within this block should ever appear on any network + // anywhere [RFC1700, page 5]. + MustIPv4Addr("127.0.0.0/8"), + + // 128.0.0.0/16 - This block, corresponding to the + // numerically lowest of the former Class B addresses, + // was initially and is still reserved by the IANA. + // Given the present classless nature of the IP address + // space, the basis for the reservation no longer + // applies and addresses in this block are subject to + // future allocation to a Regional Internet Registry for + // assignment in the normal manner. + + // 169.254.0.0/16 - This is the "link local" block. It + // is allocated for communication between hosts on a + // single link. Hosts obtain these addresses by + // auto-configuration, such as when a DHCP server may + // not be found. + MustIPv4Addr("169.254.0.0/16"), + + // 172.16.0.0/12 - This block is set aside for use in + // private networks. Its intended use is documented in + // [RFC1918]. Addresses within this block should not + // appear on the public Internet. + MustIPv4Addr("172.16.0.0/12"), + + // 191.255.0.0/16 - This block, corresponding to the numerically highest + // to the former Class B addresses, was initially and is still reserved + // by the IANA. Given the present classless nature of the IP address + // space, the basis for the reservation no longer applies and addresses + // in this block are subject to future allocation to a Regional Internet + // Registry for assignment in the normal manner. + + // 192.0.0.0/24 - This block, corresponding to the + // numerically lowest of the former Class C addresses, + // was initially and is still reserved by the IANA. + // Given the present classless nature of the IP address + // space, the basis for the reservation no longer + // applies and addresses in this block are subject to + // future allocation to a Regional Internet Registry for + // assignment in the normal manner. + + // 192.0.2.0/24 - This block is assigned as "TEST-NET" for use in + // documentation and example code. It is often used in conjunction with + // domain names example.com or example.net in vendor and protocol + // documentation. Addresses within this block should not appear on the + // public Internet. + MustIPv4Addr("192.0.2.0/24"), + + // 192.88.99.0/24 - This block is allocated for use as 6to4 relay + // anycast addresses, according to [RFC3068]. + MustIPv4Addr("192.88.99.0/24"), + + // 192.168.0.0/16 - This block is set aside for use in private networks. + // Its intended use is documented in [RFC1918]. Addresses within this + // block should not appear on the public Internet. + MustIPv4Addr("192.168.0.0/16"), + + // 198.18.0.0/15 - This block has been allocated for use + // in benchmark tests of network interconnect devices. + // Its use is documented in [RFC2544]. + MustIPv4Addr("198.18.0.0/15"), + + // 223.255.255.0/24 - This block, corresponding to the + // numerically highest of the former Class C addresses, + // was initially and is still reserved by the IANA. + // Given the present classless nature of the IP address + // space, the basis for the reservation no longer + // applies and addresses in this block are subject to + // future allocation to a Regional Internet Registry for + // assignment in the normal manner. + + // 224.0.0.0/4 - This block, formerly known as the Class + // D address space, is allocated for use in IPv4 + // multicast address assignments. The IANA guidelines + // for assignments from this space are described in + // [RFC3171]. + MustIPv4Addr("224.0.0.0/4"), + + // 240.0.0.0/4 - This block, formerly known as the Class E address + // space, is reserved. The "limited broadcast" destination address + // 255.255.255.255 should never be forwarded outside the (sub-)net of + // the source. The remainder of this space is reserved + // for future use. [RFC1700, page 4] + MustIPv4Addr("240.0.0.0/4"), + }, + 3849: { + // [RFC3849] IPv6 Address Prefix Reserved for Documentation + MustIPv6Addr("2001:db8::/32"), // [RFC3849], §4 IANA Considerations + }, + 3927: { + // [RFC3927] Dynamic Configuration of IPv4 Link-Local Addresses + MustIPv4Addr("169.254.0.0/16"), // [RFC3927], §2.1 Link-Local Address Selection + }, + 4038: { + // [RFC4038] Application Aspects of IPv6 Transition + + // [RFC4038], §4.2. IPv6 Applications in a Dual-Stack Node + MustIPv6Addr("0:0:0:0:0:ffff::/96"), + }, + 4193: { + // [RFC4193] Unique Local IPv6 Unicast Addresses + MustIPv6Addr("fc00::/7"), + }, + 4291: { + // [RFC4291] IP Version 6 Addressing Architecture + + // [RFC4291], §2.5.2 The Unspecified Address + MustIPv6Addr("::/128"), + + // [RFC4291], §2.5.3 The Loopback Address + MustIPv6Addr("::1/128"), + + // [RFC4291], §2.5.5.1. IPv4-Compatible IPv6 Address + MustIPv6Addr("::/96"), + + // [RFC4291], §2.5.5.2. IPv4-Mapped IPv6 Address + MustIPv6Addr("::ffff:0:0/96"), + + // [RFC4291], §2.5.6 Link-Local IPv6 Unicast Addresses + MustIPv6Addr("fe80::/10"), + + // [RFC4291], §2.5.7 Site-Local IPv6 Unicast Addresses + // (depreciated) + MustIPv6Addr("fec0::/10"), + + // [RFC4291], §2.7 Multicast Addresses + MustIPv6Addr("ff00::/8"), + + // IPv6 Multicast Information. + // + // In the following "table" below, `ff0x` is replaced + // with the following values depending on the scope of + // the query: + // + // IPv6 Multicast Scopes: + // * ff00/9 // reserved + // * ff01/9 // interface-local + // * ff02/9 // link-local + // * ff03/9 // realm-local + // * ff04/9 // admin-local + // * ff05/9 // site-local + // * ff08/9 // organization-local + // * ff0e/9 // global + // * ff0f/9 // reserved + // + // IPv6 Multicast Addresses: + // * ff0x::2 // All routers + // * ff02::5 // OSPFIGP + // * ff02::6 // OSPFIGP Designated Routers + // * ff02::9 // RIP Routers + // * ff02::a // EIGRP Routers + // * ff02::d // All PIM Routers + // * ff02::1a // All RPL Routers + // * ff0x::fb // mDNSv6 + // * ff0x::101 // All Network Time Protocol (NTP) servers + // * ff02::1:1 // Link Name + // * ff02::1:2 // All-dhcp-agents + // * ff02::1:3 // Link-local Multicast Name Resolution + // * ff05::1:3 // All-dhcp-servers + // * ff02::1:ff00:0/104 // Solicited-node multicast address. + // * ff02::2:ff00:0/104 // Node Information Queries + }, + 4380: { + // [RFC4380] Teredo: Tunneling IPv6 over UDP through + // Network Address Translations (NATs) + + // [RFC4380], §2.6 Global Teredo IPv6 Service Prefix + MustIPv6Addr("2001:0000::/32"), + }, + 4773: { + // [RFC4773] Administration of the IANA Special Purpose IPv6 Address Block + MustIPv6Addr("2001:0000::/23"), // IANA + }, + 4843: { + // [RFC4843] An IPv6 Prefix for Overlay Routable Cryptographic Hash Identifiers (ORCHID) + MustIPv6Addr("2001:10::/28"), // [RFC4843], §7 IANA Considerations + }, + 5180: { + // [RFC5180] IPv6 Benchmarking Methodology for Network Interconnect Devices + MustIPv6Addr("2001:0200::/48"), // [RFC5180], §8 IANA Considerations + }, + 5735: { + // [RFC5735] Special Use IPv4 Addresses + MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1 + MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2 + MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3 + MustIPv4Addr("198.18.0.0/15"), // Benchmarks + }, + 5737: { + // [RFC5737] IPv4 Address Blocks Reserved for Documentation + MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1 + MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2 + MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3 + }, + 6052: { + // [RFC6052] IPv6 Addressing of IPv4/IPv6 Translators + MustIPv6Addr("64:ff9b::/96"), // [RFC6052], §2.1. Well-Known Prefix + }, + 6333: { + // [RFC6333] Dual-Stack Lite Broadband Deployments Following IPv4 Exhaustion + MustIPv4Addr("192.0.0.0/29"), // [RFC6333], §5.7 Well-Known IPv4 Address + }, + 6598: { + // [RFC6598] IANA-Reserved IPv4 Prefix for Shared Address Space + MustIPv4Addr("100.64.0.0/10"), + }, + 6666: { + // [RFC6666] A Discard Prefix for IPv6 + MustIPv6Addr("0100::/64"), + }, + 6890: { + // [RFC6890] Special-Purpose IP Address Registries + + // From "RFC6890 §2.2.1 Information Requirements": + /* + The IPv4 and IPv6 Special-Purpose Address Registries maintain the + following information regarding each entry: + + o Address Block - A block of IPv4 or IPv6 addresses that has been + registered for a special purpose. + + o Name - A descriptive name for the special-purpose address block. + + o RFC - The RFC through which the special-purpose address block was + requested. + + o Allocation Date - The date upon which the special-purpose address + block was allocated. + + o Termination Date - The date upon which the allocation is to be + terminated. This field is applicable for limited-use allocations + only. + + o Source - A boolean value indicating whether an address from the + allocated special-purpose address block is valid when used as the + source address of an IP datagram that transits two devices. + + o Destination - A boolean value indicating whether an address from + the allocated special-purpose address block is valid when used as + the destination address of an IP datagram that transits two + devices. + + o Forwardable - A boolean value indicating whether a router may + forward an IP datagram whose destination address is drawn from the + allocated special-purpose address block between external + interfaces. + + o Global - A boolean value indicating whether an IP datagram whose + destination address is drawn from the allocated special-purpose + address block is forwardable beyond a specified administrative + domain. + + o Reserved-by-Protocol - A boolean value indicating whether the + special-purpose address block is reserved by IP, itself. This + value is "TRUE" if the RFC that created the special-purpose + address block requires all compliant IP implementations to behave + in a special way when processing packets either to or from + addresses contained by the address block. + + If the value of "Destination" is FALSE, the values of "Forwardable" + and "Global" must also be false. + */ + + /*+----------------------+----------------------------+ + * | Attribute | Value | + * +----------------------+----------------------------+ + * | Address Block | 0.0.0.0/8 | + * | Name | "This host on this network"| + * | RFC | [RFC1122], Section 3.2.1.3 | + * | Allocation Date | September 1981 | + * | Termination Date | N/A | + * | Source | True | + * | Destination | False | + * | Forwardable | False | + * | Global | False | + * | Reserved-by-Protocol | True | + * +----------------------+----------------------------+*/ + MustIPv4Addr("0.0.0.0/8"), + + /*+----------------------+---------------+ + * | Attribute | Value | + * +----------------------+---------------+ + * | Address Block | 10.0.0.0/8 | + * | Name | Private-Use | + * | RFC | [RFC1918] | + * | Allocation Date | February 1996 | + * | Termination Date | N/A | + * | Source | True | + * | Destination | True | + * | Forwardable | True | + * | Global | False | + * | Reserved-by-Protocol | False | + * +----------------------+---------------+ */ + MustIPv4Addr("10.0.0.0/8"), + + /*+----------------------+----------------------+ + | Attribute | Value | + +----------------------+----------------------+ + | Address Block | 100.64.0.0/10 | + | Name | Shared Address Space | + | RFC | [RFC6598] | + | Allocation Date | April 2012 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------+*/ + MustIPv4Addr("100.64.0.0/10"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 127.0.0.0/8 | + | Name | Loopback | + | RFC | [RFC1122], Section 3.2.1.3 | + | Allocation Date | September 1981 | + | Termination Date | N/A | + | Source | False [1] | + | Destination | False [1] | + | Forwardable | False [1] | + | Global | False [1] | + | Reserved-by-Protocol | True | + +----------------------+----------------------------+*/ + // [1] Several protocols have been granted exceptions to + // this rule. For examples, see [RFC4379] and + // [RFC5884]. + MustIPv4Addr("127.0.0.0/8"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 169.254.0.0/16 | + | Name | Link Local | + | RFC | [RFC3927] | + | Allocation Date | May 2005 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+----------------+*/ + MustIPv4Addr("169.254.0.0/16"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 172.16.0.0/12 | + | Name | Private-Use | + | RFC | [RFC1918] | + | Allocation Date | February 1996 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + MustIPv4Addr("172.16.0.0/12"), + + /*+----------------------+---------------------------------+ + | Attribute | Value | + +----------------------+---------------------------------+ + | Address Block | 192.0.0.0/24 [2] | + | Name | IETF Protocol Assignments | + | RFC | Section 2.1 of this document | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------------------------+*/ + // [2] Not usable unless by virtue of a more specific + // reservation. + MustIPv4Addr("192.0.0.0/24"), + + /*+----------------------+--------------------------------+ + | Attribute | Value | + +----------------------+--------------------------------+ + | Address Block | 192.0.0.0/29 | + | Name | IPv4 Service Continuity Prefix | + | RFC | [RFC6333], [RFC7335] | + | Allocation Date | June 2011 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+--------------------------------+*/ + MustIPv4Addr("192.0.0.0/29"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 192.0.2.0/24 | + | Name | Documentation (TEST-NET-1) | + | RFC | [RFC5737] | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv4Addr("192.0.2.0/24"), + + /*+----------------------+--------------------+ + | Attribute | Value | + +----------------------+--------------------+ + | Address Block | 192.88.99.0/24 | + | Name | 6to4 Relay Anycast | + | RFC | [RFC3068] | + | Allocation Date | June 2001 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | True | + | Reserved-by-Protocol | False | + +----------------------+--------------------+*/ + MustIPv4Addr("192.88.99.0/24"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 192.168.0.0/16 | + | Name | Private-Use | + | RFC | [RFC1918] | + | Allocation Date | February 1996 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------+*/ + MustIPv4Addr("192.168.0.0/16"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 198.18.0.0/15 | + | Name | Benchmarking | + | RFC | [RFC2544] | + | Allocation Date | March 1999 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + MustIPv4Addr("198.18.0.0/15"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 198.51.100.0/24 | + | Name | Documentation (TEST-NET-2) | + | RFC | [RFC5737] | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv4Addr("198.51.100.0/24"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 203.0.113.0/24 | + | Name | Documentation (TEST-NET-3) | + | RFC | [RFC5737] | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv4Addr("203.0.113.0/24"), + + /*+----------------------+----------------------+ + | Attribute | Value | + +----------------------+----------------------+ + | Address Block | 240.0.0.0/4 | + | Name | Reserved | + | RFC | [RFC1112], Section 4 | + | Allocation Date | August 1989 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+----------------------+*/ + MustIPv4Addr("240.0.0.0/4"), + + /*+----------------------+----------------------+ + | Attribute | Value | + +----------------------+----------------------+ + | Address Block | 255.255.255.255/32 | + | Name | Limited Broadcast | + | RFC | [RFC0919], Section 7 | + | Allocation Date | October 1984 | + | Termination Date | N/A | + | Source | False | + | Destination | True | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------+*/ + MustIPv4Addr("255.255.255.255/32"), + + /*+----------------------+------------------+ + | Attribute | Value | + +----------------------+------------------+ + | Address Block | ::1/128 | + | Name | Loopback Address | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+------------------+*/ + MustIPv6Addr("::1/128"), + + /*+----------------------+---------------------+ + | Attribute | Value | + +----------------------+---------------------+ + | Address Block | ::/128 | + | Name | Unspecified Address | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | True | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+---------------------+*/ + MustIPv6Addr("::/128"), + + /*+----------------------+---------------------+ + | Attribute | Value | + +----------------------+---------------------+ + | Address Block | 64:ff9b::/96 | + | Name | IPv4-IPv6 Translat. | + | RFC | [RFC6052] | + | Allocation Date | October 2010 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | True | + | Reserved-by-Protocol | False | + +----------------------+---------------------+*/ + MustIPv6Addr("64:ff9b::/96"), + + /*+----------------------+---------------------+ + | Attribute | Value | + +----------------------+---------------------+ + | Address Block | ::ffff:0:0/96 | + | Name | IPv4-mapped Address | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+---------------------+*/ + MustIPv6Addr("::ffff:0:0/96"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 100::/64 | + | Name | Discard-Only Address Block | + | RFC | [RFC6666] | + | Allocation Date | June 2012 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv6Addr("100::/64"), + + /*+----------------------+---------------------------+ + | Attribute | Value | + +----------------------+---------------------------+ + | Address Block | 2001::/23 | + | Name | IETF Protocol Assignments | + | RFC | [RFC2928] | + | Allocation Date | September 2000 | + | Termination Date | N/A | + | Source | False[1] | + | Destination | False[1] | + | Forwardable | False[1] | + | Global | False[1] | + | Reserved-by-Protocol | False | + +----------------------+---------------------------+*/ + // [1] Unless allowed by a more specific allocation. + MustIPv6Addr("2001::/16"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 2001::/32 | + | Name | TEREDO | + | RFC | [RFC4380] | + | Allocation Date | January 2006 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001::/16"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 2001:2::/48 | + | Name | Benchmarking | + | RFC | [RFC5180] | + | Allocation Date | April 2008 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001:2::/48"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 2001:db8::/32 | + | Name | Documentation | + | RFC | [RFC3849] | + | Allocation Date | July 2004 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001:db8::/32"), + + /*+----------------------+--------------+ + | Attribute | Value | + +----------------------+--------------+ + | Address Block | 2001:10::/28 | + | Name | ORCHID | + | RFC | [RFC4843] | + | Allocation Date | March 2007 | + | Termination Date | March 2014 | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+--------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001:10::/28"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 2002::/16 [2] | + | Name | 6to4 | + | RFC | [RFC3056] | + | Allocation Date | February 2001 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | N/A [2] | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + // [2] See [RFC3056] for details. + MustIPv6Addr("2002::/16"), + + /*+----------------------+--------------+ + | Attribute | Value | + +----------------------+--------------+ + | Address Block | fc00::/7 | + | Name | Unique-Local | + | RFC | [RFC4193] | + | Allocation Date | October 2005 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+--------------+*/ + MustIPv6Addr("fc00::/7"), + + /*+----------------------+-----------------------+ + | Attribute | Value | + +----------------------+-----------------------+ + | Address Block | fe80::/10 | + | Name | Linked-Scoped Unicast | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+-----------------------+*/ + MustIPv6Addr("fe80::/10"), + }, + 7335: { + // [RFC7335] IPv4 Service Continuity Prefix + MustIPv4Addr("192.0.0.0/29"), // [RFC7335], §6 IANA Considerations + }, + ForwardingBlacklist: { // Pseudo-RFC + // Blacklist of non-forwardable IP blocks taken from RFC6890 + // + // TODO: the attributes for forwardable should be + // searcahble and embedded in the main list of RFCs + // above. + MustIPv4Addr("0.0.0.0/8"), + MustIPv4Addr("127.0.0.0/8"), + MustIPv4Addr("169.254.0.0/16"), + MustIPv4Addr("192.0.0.0/24"), + MustIPv4Addr("192.0.2.0/24"), + MustIPv4Addr("198.51.100.0/24"), + MustIPv4Addr("203.0.113.0/24"), + MustIPv4Addr("240.0.0.0/4"), + MustIPv4Addr("255.255.255.255/32"), + MustIPv6Addr("::1/128"), + MustIPv6Addr("::/128"), + MustIPv6Addr("::ffff:0:0/96"), + + // There is no way of expressing a whitelist per RFC2928 + // atm without creating a negative mask, which I don't + // want to do atm. + //MustIPv6Addr("2001::/23"), + + MustIPv6Addr("2001:db8::/32"), + MustIPv6Addr("2001:10::/28"), + MustIPv6Addr("fe80::/10"), + }, + } +} + +// VisitAllRFCs iterates over all known RFCs and calls the visitor +func VisitAllRFCs(fn func(rfcNum uint, sockaddrs SockAddrs)) { + rfcNetMap := KnownRFCs() + + // Blacklist of faux-RFCs. Don't show the world that we're abusing the + // RFC system in this library. + rfcBlacklist := map[uint]struct{}{ + ForwardingBlacklist: {}, + } + + for rfcNum, sas := range rfcNetMap { + if _, found := rfcBlacklist[rfcNum]; !found { + fn(rfcNum, sas) + } + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info.go b/vendor/github.com/hashicorp/go-sockaddr/route_info.go new file mode 100644 index 00000000000..2a3ee1db9e8 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info.go @@ -0,0 +1,19 @@ +package sockaddr + +// RouteInterface specifies an interface for obtaining memoized route table and +// network information from a given OS. +type RouteInterface interface { + // GetDefaultInterfaceName returns the name of the interface that has a + // default route or an error and an empty string if a problem was + // encountered. + GetDefaultInterfaceName() (string, error) +} + +// VisitCommands visits each command used by the platform-specific RouteInfo +// implementation. +func (ri routeInfo) VisitCommands(fn func(name string, cmd []string)) { + for k, v := range ri.cmds { + cmds := append([]string(nil), v...) + fn(k, cmds) + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_android.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_android.go new file mode 100644 index 00000000000..9885915a6ba --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_android.go @@ -0,0 +1,34 @@ +package sockaddr + +import ( + "errors" + "os/exec" +) + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a Android-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: map[string][]string{"ip": {"/system/bin/ip", "route", "get", "8.8.8.8"}}, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output() + if err != nil { + return "", err + } + + + var ifName string + if ifName, err = parseDefaultIfNameFromIPCmdAndroid(string(out)); err != nil { + return "", errors.New("No default interface found") + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go new file mode 100644 index 00000000000..705757abc7b --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go @@ -0,0 +1,36 @@ +// +build darwin dragonfly freebsd netbsd openbsd + +package sockaddr + +import "os/exec" + +var cmds map[string][]string = map[string][]string{ + "route": {"/sbin/route", "-n", "get", "default"}, +} + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a BSD-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: cmds, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output() + if err != nil { + return "", err + } + + var ifName string + if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil { + return "", err + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go new file mode 100644 index 00000000000..d1b009f6538 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go @@ -0,0 +1,10 @@ +// +build android nacl plan9 + +package sockaddr + +import "errors" + +// getDefaultIfName is the default interface function for unsupported platforms. +func getDefaultIfName() (string, error) { + return "", errors.New("No default interface found (unsupported platform)") +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go new file mode 100644 index 00000000000..b62ce6ecb21 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go @@ -0,0 +1,42 @@ +// +build !android + +package sockaddr + +import ( + "errors" + "os/exec" +) + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a Linux-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + // CoreOS Container Linux moved ip to /usr/bin/ip, so look it up on + // $PATH and fallback to /sbin/ip on error. + path, _ := exec.LookPath("ip") + if path == "" { + path = "/sbin/ip" + } + + return routeInfo{ + cmds: map[string][]string{"ip": {path, "route"}}, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output() + if err != nil { + return "", err + } + + var ifName string + if ifName, err = parseDefaultIfNameFromIPCmd(string(out)); err != nil { + return "", errors.New("No default interface found") + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go new file mode 100644 index 00000000000..ee8e7984d79 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go @@ -0,0 +1,37 @@ +package sockaddr + +import ( + "errors" + "os/exec" +) + +var cmds map[string][]string = map[string][]string{ + "route": {"/usr/sbin/route", "-n", "get", "default"}, +} + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a BSD-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: cmds, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output() + if err != nil { + return "", err + } + + var ifName string + if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil { + return "", errors.New("No default interface found") + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go new file mode 100644 index 00000000000..3da972883e8 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go @@ -0,0 +1,41 @@ +package sockaddr + +import "os/exec" + +var cmds map[string][]string = map[string][]string{ + "netstat": {"netstat", "-rn"}, + "ipconfig": {"ipconfig"}, +} + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a BSD-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: cmds, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + ifNameOut, err := exec.Command(cmds["netstat"][0], cmds["netstat"][1:]...).Output() + if err != nil { + return "", err + } + + ipconfigOut, err := exec.Command(cmds["ipconfig"][0], cmds["ipconfig"][1:]...).Output() + if err != nil { + return "", err + } + + ifName, err := parseDefaultIfNameWindows(string(ifNameOut), string(ipconfigOut)) + if err != nil { + return "", err + } + + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go new file mode 100644 index 00000000000..826c91c2e3d --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go @@ -0,0 +1,206 @@ +package sockaddr + +import ( + "encoding/json" + "fmt" + "strings" +) + +type SockAddrType int +type AttrName string + +const ( + TypeUnknown SockAddrType = 0x0 + TypeUnix = 0x1 + TypeIPv4 = 0x2 + TypeIPv6 = 0x4 + + // TypeIP is the union of TypeIPv4 and TypeIPv6 + TypeIP = 0x6 +) + +type SockAddr interface { + // CmpRFC returns 0 if SockAddr exactly matches one of the matched RFC + // networks, -1 if the receiver is contained within the RFC network, or + // 1 if the address is not contained within the RFC. + CmpRFC(rfcNum uint, sa SockAddr) int + + // Contains returns true if the SockAddr arg is contained within the + // receiver + Contains(SockAddr) bool + + // Equal allows for the comparison of two SockAddrs + Equal(SockAddr) bool + + DialPacketArgs() (string, string) + DialStreamArgs() (string, string) + ListenPacketArgs() (string, string) + ListenStreamArgs() (string, string) + + // String returns the string representation of SockAddr + String() string + + // Type returns the SockAddrType + Type() SockAddrType +} + +// sockAddrAttrMap is a map of the SockAddr type-specific attributes. +var sockAddrAttrMap map[AttrName]func(SockAddr) string +var sockAddrAttrs []AttrName + +func init() { + sockAddrInit() +} + +// New creates a new SockAddr from the string. The order in which New() +// attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix. +// +// NOTE: New() relies on the heuristic wherein if the path begins with either a +// '.' or '/' character before creating a new UnixSock. For UNIX sockets that +// are absolute paths or are nested within a sub-directory, this works as +// expected, however if the UNIX socket is contained in the current working +// directory, this will fail unless the path begins with "./" +// (e.g. "./my-local-socket"). Calls directly to NewUnixSock() do not suffer +// this limitation. Invalid IP addresses such as "256.0.0.0/-1" will run afoul +// of this heuristic and be assumed to be a valid UNIX socket path (which they +// are, but it is probably not what you want and you won't realize it until you +// stat(2) the file system to discover it doesn't exist). +func NewSockAddr(s string) (SockAddr, error) { + ipv4Addr, err := NewIPv4Addr(s) + if err == nil { + return ipv4Addr, nil + } + + ipv6Addr, err := NewIPv6Addr(s) + if err == nil { + return ipv6Addr, nil + } + + // Check to make sure the string begins with either a '.' or '/', or + // contains a '/'. + if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) { + unixSock, err := NewUnixSock(s) + if err == nil { + return unixSock, nil + } + } + + return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s) +} + +// ToIPAddr returns an IPAddr type or nil if the type conversion fails. +func ToIPAddr(sa SockAddr) *IPAddr { + ipa, ok := sa.(IPAddr) + if !ok { + return nil + } + return &ipa +} + +// ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails. +func ToIPv4Addr(sa SockAddr) *IPv4Addr { + switch v := sa.(type) { + case IPv4Addr: + return &v + default: + return nil + } +} + +// ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails. +func ToIPv6Addr(sa SockAddr) *IPv6Addr { + switch v := sa.(type) { + case IPv6Addr: + return &v + default: + return nil + } +} + +// ToUnixSock returns a UnixSock type or nil if the type conversion fails. +func ToUnixSock(sa SockAddr) *UnixSock { + switch v := sa.(type) { + case UnixSock: + return &v + default: + return nil + } +} + +// SockAddrAttr returns a string representation of an attribute for the given +// SockAddr. +func SockAddrAttr(sa SockAddr, selector AttrName) string { + fn, found := sockAddrAttrMap[selector] + if !found { + return "" + } + + return fn(sa) +} + +// String() for SockAddrType returns a string representation of the +// SockAddrType (e.g. "IPv4", "IPv6", "UNIX", "IP", or "unknown"). +func (sat SockAddrType) String() string { + switch sat { + case TypeIPv4: + return "IPv4" + case TypeIPv6: + return "IPv6" + // There is no concrete "IP" type. Leaving here as a reminder. + // case TypeIP: + // return "IP" + case TypeUnix: + return "UNIX" + default: + panic("unsupported type") + } +} + +// sockAddrInit is called once at init() +func sockAddrInit() { + sockAddrAttrs = []AttrName{ + "type", // type should be first + "string", + } + + sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{ + "string": func(sa SockAddr) string { + return sa.String() + }, + "type": func(sa SockAddr) string { + return sa.Type().String() + }, + } +} + +// UnixSockAttrs returns a list of attributes supported by the UnixSock type +func SockAddrAttrs() []AttrName { + return sockAddrAttrs +} + +// Although this is pretty trivial to do in a program, having the logic here is +// useful all around. Note that this marshals into a *string* -- the underlying +// string representation of the sockaddr. If you then unmarshal into this type +// in Go, all will work as expected, but externally you can take what comes out +// and use the string value directly. +type SockAddrMarshaler struct { + SockAddr +} + +func (s *SockAddrMarshaler) MarshalJSON() ([]byte, error) { + return json.Marshal(s.SockAddr.String()) +} + +func (s *SockAddrMarshaler) UnmarshalJSON(in []byte) error { + var str string + err := json.Unmarshal(in, &str) + if err != nil { + return err + } + sa, err := NewSockAddr(str) + if err != nil { + return err + } + s.SockAddr = sa + return nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go new file mode 100644 index 00000000000..75fbffb1eab --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go @@ -0,0 +1,193 @@ +package sockaddr + +import ( + "bytes" + "sort" +) + +// SockAddrs is a slice of SockAddrs +type SockAddrs []SockAddr + +func (s SockAddrs) Len() int { return len(s) } +func (s SockAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// CmpAddrFunc is the function signature that must be met to be used in the +// OrderedAddrBy multiAddrSorter +type CmpAddrFunc func(p1, p2 *SockAddr) int + +// multiAddrSorter implements the Sort interface, sorting the SockAddrs within. +type multiAddrSorter struct { + addrs SockAddrs + cmp []CmpAddrFunc +} + +// Sort sorts the argument slice according to the Cmp functions passed to +// OrderedAddrBy. +func (ms *multiAddrSorter) Sort(sockAddrs SockAddrs) { + ms.addrs = sockAddrs + sort.Sort(ms) +} + +// OrderedAddrBy sorts SockAddr by the list of sort function pointers. +func OrderedAddrBy(cmpFuncs ...CmpAddrFunc) *multiAddrSorter { + return &multiAddrSorter{ + cmp: cmpFuncs, + } +} + +// Len is part of sort.Interface. +func (ms *multiAddrSorter) Len() int { + return len(ms.addrs) +} + +// Less is part of sort.Interface. It is implemented by looping along the +// Cmp() functions until it finds a comparison that is either less than, +// equal to, or greater than. +func (ms *multiAddrSorter) Less(i, j int) bool { + p, q := &ms.addrs[i], &ms.addrs[j] + // Try all but the last comparison. + var k int + for k = 0; k < len(ms.cmp)-1; k++ { + cmp := ms.cmp[k] + x := cmp(p, q) + switch x { + case -1: + // p < q, so we have a decision. + return true + case 1: + // p > q, so we have a decision. + return false + } + // p == q; try the next comparison. + } + // All comparisons to here said "equal", so just return whatever the + // final comparison reports. + switch ms.cmp[k](p, q) { + case -1: + return true + case 1: + return false + default: + // Still a tie! Now what? + return false + } +} + +// Swap is part of sort.Interface. +func (ms *multiAddrSorter) Swap(i, j int) { + ms.addrs[i], ms.addrs[j] = ms.addrs[j], ms.addrs[i] +} + +const ( + // NOTE (sean@): These constants are here for code readability only and + // are sprucing up the code for readability purposes. Some of the + // Cmp*() variants have confusing logic (especially when dealing with + // mixed-type comparisons) and this, I think, has made it easier to grok + // the code faster. + sortReceiverBeforeArg = -1 + sortDeferDecision = 0 + sortArgBeforeReceiver = 1 +) + +// AscAddress is a sorting function to sort SockAddrs by their respective +// address type. Non-equal types are deferred in the sort. +func AscAddress(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + + switch v := p1.(type) { + case IPv4Addr: + return v.CmpAddress(p2) + case IPv6Addr: + return v.CmpAddress(p2) + case UnixSock: + return v.CmpAddress(p2) + default: + return sortDeferDecision + } +} + +// AscPort is a sorting function to sort SockAddrs by their respective address +// type. Non-equal types are deferred in the sort. +func AscPort(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + + switch v := p1.(type) { + case IPv4Addr: + return v.CmpPort(p2) + case IPv6Addr: + return v.CmpPort(p2) + default: + return sortDeferDecision + } +} + +// AscPrivate is a sorting function to sort "more secure" private values before +// "more public" values. Both IPv4 and IPv6 are compared against RFC6890 +// (RFC6890 includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and +// IPv6 includes RFC4193). +func AscPrivate(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + + switch v := p1.(type) { + case IPv4Addr, IPv6Addr: + return v.CmpRFC(6890, p2) + default: + return sortDeferDecision + } +} + +// AscNetworkSize is a sorting function to sort SockAddrs based on their network +// size. Non-equal types are deferred in the sort. +func AscNetworkSize(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + p1Type := p1.Type() + p2Type := p2.Type() + + // Network size operations on non-IP types make no sense + if p1Type != p2Type && p1Type != TypeIP { + return sortDeferDecision + } + + ipA := p1.(IPAddr) + ipB := p2.(IPAddr) + + return bytes.Compare([]byte(*ipA.NetIPMask()), []byte(*ipB.NetIPMask())) +} + +// AscType is a sorting function to sort "more secure" types before +// "less-secure" types. +func AscType(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + p1Type := p1.Type() + p2Type := p2.Type() + switch { + case p1Type < p2Type: + return sortReceiverBeforeArg + case p1Type == p2Type: + return sortDeferDecision + case p1Type > p2Type: + return sortArgBeforeReceiver + default: + return sortDeferDecision + } +} + +// FilterByType returns two lists: a list of matched and unmatched SockAddrs +func (sas SockAddrs) FilterByType(type_ SockAddrType) (matched, excluded SockAddrs) { + matched = make(SockAddrs, 0, len(sas)) + excluded = make(SockAddrs, 0, len(sas)) + + for _, sa := range sas { + if sa.Type()&type_ != 0 { + matched = append(matched, sa) + } else { + excluded = append(excluded, sa) + } + } + return matched, excluded +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/unixsock.go b/vendor/github.com/hashicorp/go-sockaddr/unixsock.go new file mode 100644 index 00000000000..f3be3f67e77 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/unixsock.go @@ -0,0 +1,135 @@ +package sockaddr + +import ( + "fmt" + "strings" +) + +type UnixSock struct { + SockAddr + path string +} +type UnixSocks []*UnixSock + +// unixAttrMap is a map of the UnixSockAddr type-specific attributes. +var unixAttrMap map[AttrName]func(UnixSock) string +var unixAttrs []AttrName + +func init() { + unixAttrInit() +} + +// NewUnixSock creates an UnixSock from a string path. String can be in the +// form of either URI-based string (e.g. `file:///etc/passwd`), an absolute +// path (e.g. `/etc/passwd`), or a relative path (e.g. `./foo`). +func NewUnixSock(s string) (ret UnixSock, err error) { + ret.path = s + return ret, nil +} + +// CmpAddress follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its name lexically sorts before arg +// - 0 if the SockAddr arg is not a UnixSock, or is a UnixSock with the same path. +// - 1 If the argument should sort first. +func (us UnixSock) CmpAddress(sa SockAddr) int { + usb, ok := sa.(UnixSock) + if !ok { + return sortDeferDecision + } + + return strings.Compare(us.Path(), usb.Path()) +} + +// DialPacketArgs returns the arguments required to be passed to net.DialUnix() +// with the `unixgram` network type. +func (us UnixSock) DialPacketArgs() (network, dialArgs string) { + return "unixgram", us.path +} + +// DialStreamArgs returns the arguments required to be passed to net.DialUnix() +// with the `unix` network type. +func (us UnixSock) DialStreamArgs() (network, dialArgs string) { + return "unix", us.path +} + +// Equal returns true if a SockAddr is equal to the receiving UnixSock. +func (us UnixSock) Equal(sa SockAddr) bool { + usb, ok := sa.(UnixSock) + if !ok { + return false + } + + if us.Path() != usb.Path() { + return false + } + + return true +} + +// ListenPacketArgs returns the arguments required to be passed to +// net.ListenUnixgram() with the `unixgram` network type. +func (us UnixSock) ListenPacketArgs() (network, dialArgs string) { + return "unixgram", us.path +} + +// ListenStreamArgs returns the arguments required to be passed to +// net.ListenUnix() with the `unix` network type. +func (us UnixSock) ListenStreamArgs() (network, dialArgs string) { + return "unix", us.path +} + +// MustUnixSock is a helper method that must return an UnixSock or panic on +// invalid input. +func MustUnixSock(addr string) UnixSock { + us, err := NewUnixSock(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create a UnixSock from %+q: %v", addr, err)) + } + return us +} + +// Path returns the given path of the UnixSock +func (us UnixSock) Path() string { + return us.path +} + +// String returns the path of the UnixSock +func (us UnixSock) String() string { + return fmt.Sprintf("%+q", us.path) +} + +// Type is used as a type switch and returns TypeUnix +func (UnixSock) Type() SockAddrType { + return TypeUnix +} + +// UnixSockAttrs returns a list of attributes supported by the UnixSockAddr type +func UnixSockAttrs() []AttrName { + return unixAttrs +} + +// UnixSockAttr returns a string representation of an attribute for the given +// UnixSock. +func UnixSockAttr(us UnixSock, attrName AttrName) string { + fn, found := unixAttrMap[attrName] + if !found { + return "" + } + + return fn(us) +} + +// unixAttrInit is called once at init() +func unixAttrInit() { + // Sorted for human readability + unixAttrs = []AttrName{ + "path", + } + + unixAttrMap = map[AttrName]func(us UnixSock) string{ + "path": func(us UnixSock) string { + return us.Path() + }, + } +} diff --git a/vendor/github.com/hashicorp/memberlist/.gitignore b/vendor/github.com/hashicorp/memberlist/.gitignore new file mode 100644 index 00000000000..9158f171a5f --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +.vagrant/ + diff --git a/vendor/github.com/hashicorp/memberlist/.travis.yml b/vendor/github.com/hashicorp/memberlist/.travis.yml new file mode 100644 index 00000000000..b4f8f1c47b3 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/.travis.yml @@ -0,0 +1,15 @@ +language: go + +sudo: true + +go: + - "1.x" + +branches: + only: + - master + +install: true + +env: + - GO111MODULE=on # Enable Go modules in 1.11 diff --git a/vendor/github.com/hashicorp/memberlist/LICENSE b/vendor/github.com/hashicorp/memberlist/LICENSE new file mode 100644 index 00000000000..c33dcc7c928 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/memberlist/Makefile b/vendor/github.com/hashicorp/memberlist/Makefile new file mode 100644 index 00000000000..4ee0ee4efb9 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/Makefile @@ -0,0 +1,20 @@ +DEPS := $(shell go list -f '{{range .Imports}}{{.}} {{end}}' ./...) + +test: subnet + go test ./... + +integ: subnet + INTEG_TESTS=yes go test ./... + +subnet: + ./test/setup_subnet.sh + +cov: + gocov test github.com/hashicorp/memberlist | gocov-html > /tmp/coverage.html + open /tmp/coverage.html + +deps: + go get -t -d -v ./... + echo $(DEPS) | xargs -n1 go get -d + +.PHONY: test cov integ diff --git a/vendor/github.com/hashicorp/memberlist/README.md b/vendor/github.com/hashicorp/memberlist/README.md new file mode 100644 index 00000000000..f47fb81aa66 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/README.md @@ -0,0 +1,75 @@ +# memberlist [![GoDoc](https://godoc.org/github.com/hashicorp/memberlist?status.png)](https://godoc.org/github.com/hashicorp/memberlist) [![Build Status](https://travis-ci.org/hashicorp/memberlist.svg?branch=master)](https://travis-ci.org/hashicorp/memberlist) + +memberlist is a [Go](http://www.golang.org) library that manages cluster +membership and member failure detection using a gossip based protocol. + +The use cases for such a library are far-reaching: all distributed systems +require membership, and memberlist is a re-usable solution to managing +cluster membership and node failure detection. + +memberlist is eventually consistent but converges quickly on average. +The speed at which it converges can be heavily tuned via various knobs +on the protocol. Node failures are detected and network partitions are partially +tolerated by attempting to communicate to potentially dead nodes through +multiple routes. + +## Building + +If you wish to build memberlist you'll need Go version 1.2+ installed. + +Please check your installation with: + +``` +go version +``` + +Run `make deps` to fetch dependencies before building + +## Usage + +Memberlist is surprisingly simple to use. An example is shown below: + +```go +/* Create the initial memberlist from a safe configuration. + Please reference the godoc for other default config types. + http://godoc.org/github.com/hashicorp/memberlist#Config +*/ +list, err := memberlist.Create(memberlist.DefaultLocalConfig()) +if err != nil { + panic("Failed to create memberlist: " + err.Error()) +} + +// Join an existing cluster by specifying at least one known member. +n, err := list.Join([]string{"1.2.3.4"}) +if err != nil { + panic("Failed to join cluster: " + err.Error()) +} + +// Ask for members of the cluster +for _, member := range list.Members() { + fmt.Printf("Member: %s %s\n", member.Name, member.Addr) +} + +// Continue doing whatever you need, memberlist will maintain membership +// information in the background. Delegates can be used for receiving +// events when members join or leave. +``` + +The most difficult part of memberlist is configuring it since it has many +available knobs in order to tune state propagation delay and convergence times. +Memberlist provides a default configuration that offers a good starting point, +but errs on the side of caution, choosing values that are optimized for +higher convergence at the cost of higher bandwidth usage. + +For complete documentation, see the associated [Godoc](http://godoc.org/github.com/hashicorp/memberlist). + +## Protocol + +memberlist is based on ["SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol"](http://ieeexplore.ieee.org/document/1028914/). However, we extend the protocol in a number of ways: + +* Several extensions are made to increase propagation speed and +convergence rate. +* Another set of extensions, that we call Lifeguard, are made to make memberlist more robust in the presence of slow message processing (due to factors such as CPU starvation, and network delay or loss). + +For details on all of these extensions, please read our paper "[Lifeguard : SWIM-ing with Situational Awareness](https://arxiv.org/abs/1707.00788)", along with the memberlist source. We welcome any questions related +to the protocol on our issue tracker. diff --git a/vendor/github.com/hashicorp/memberlist/alive_delegate.go b/vendor/github.com/hashicorp/memberlist/alive_delegate.go new file mode 100644 index 00000000000..51a0ba9054a --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/alive_delegate.go @@ -0,0 +1,14 @@ +package memberlist + +// AliveDelegate is used to involve a client in processing +// a node "alive" message. When a node joins, either through +// a UDP gossip or TCP push/pull, we update the state of +// that node via an alive message. This can be used to filter +// a node out and prevent it from being considered a peer +// using application specific logic. +type AliveDelegate interface { + // NotifyMerge is invoked when a merge could take place. + // Provides a list of the nodes known by the peer. If + // the return value is non-nil, the merge is canceled. + NotifyAlive(peer *Node) error +} diff --git a/vendor/github.com/hashicorp/memberlist/awareness.go b/vendor/github.com/hashicorp/memberlist/awareness.go new file mode 100644 index 00000000000..ea95c753880 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/awareness.go @@ -0,0 +1,69 @@ +package memberlist + +import ( + "sync" + "time" + + "github.com/armon/go-metrics" +) + +// awareness manages a simple metric for tracking the estimated health of the +// local node. Health is primary the node's ability to respond in the soft +// real-time manner required for correct health checking of other nodes in the +// cluster. +type awareness struct { + sync.RWMutex + + // max is the upper threshold for the timeout scale (the score will be + // constrained to be from 0 <= score < max). + max int + + // score is the current awareness score. Lower values are healthier and + // zero is the minimum value. + score int +} + +// newAwareness returns a new awareness object. +func newAwareness(max int) *awareness { + return &awareness{ + max: max, + score: 0, + } +} + +// ApplyDelta takes the given delta and applies it to the score in a thread-safe +// manner. It also enforces a floor of zero and a max of max, so deltas may not +// change the overall score if it's railed at one of the extremes. +func (a *awareness) ApplyDelta(delta int) { + a.Lock() + initial := a.score + a.score += delta + if a.score < 0 { + a.score = 0 + } else if a.score > (a.max - 1) { + a.score = (a.max - 1) + } + final := a.score + a.Unlock() + + if initial != final { + metrics.SetGauge([]string{"memberlist", "health", "score"}, float32(final)) + } +} + +// GetHealthScore returns the raw health score. +func (a *awareness) GetHealthScore() int { + a.RLock() + score := a.score + a.RUnlock() + return score +} + +// ScaleTimeout takes the given duration and scales it based on the current +// score. Less healthyness will lead to longer timeouts. +func (a *awareness) ScaleTimeout(timeout time.Duration) time.Duration { + a.RLock() + score := a.score + a.RUnlock() + return timeout * (time.Duration(score) + 1) +} diff --git a/vendor/github.com/hashicorp/memberlist/broadcast.go b/vendor/github.com/hashicorp/memberlist/broadcast.go new file mode 100644 index 00000000000..d07d41bb69d --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/broadcast.go @@ -0,0 +1,105 @@ +package memberlist + +/* +The broadcast mechanism works by maintaining a sorted list of messages to be +sent out. When a message is to be broadcast, the retransmit count +is set to zero and appended to the queue. The retransmit count serves +as the "priority", ensuring that newer messages get sent first. Once +a message hits the retransmit limit, it is removed from the queue. + +Additionally, older entries can be invalidated by new messages that +are contradictory. For example, if we send "{suspect M1 inc: 1}, +then a following {alive M1 inc: 2} will invalidate that message +*/ + +type memberlistBroadcast struct { + node string + msg []byte + notify chan struct{} +} + +func (b *memberlistBroadcast) Invalidates(other Broadcast) bool { + // Check if that broadcast is a memberlist type + mb, ok := other.(*memberlistBroadcast) + if !ok { + return false + } + + // Invalidates any message about the same node + return b.node == mb.node +} + +// memberlist.NamedBroadcast optional interface +func (b *memberlistBroadcast) Name() string { + return b.node +} + +func (b *memberlistBroadcast) Message() []byte { + return b.msg +} + +func (b *memberlistBroadcast) Finished() { + select { + case b.notify <- struct{}{}: + default: + } +} + +// encodeAndBroadcast encodes a message and enqueues it for broadcast. Fails +// silently if there is an encoding error. +func (m *Memberlist) encodeAndBroadcast(node string, msgType messageType, msg interface{}) { + m.encodeBroadcastNotify(node, msgType, msg, nil) +} + +// encodeBroadcastNotify encodes a message and enqueues it for broadcast +// and notifies the given channel when transmission is finished. Fails +// silently if there is an encoding error. +func (m *Memberlist) encodeBroadcastNotify(node string, msgType messageType, msg interface{}, notify chan struct{}) { + buf, err := encode(msgType, msg) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to encode message for broadcast: %s", err) + } else { + m.queueBroadcast(node, buf.Bytes(), notify) + } +} + +// queueBroadcast is used to start dissemination of a message. It will be +// sent up to a configured number of times. The message could potentially +// be invalidated by a future message about the same node +func (m *Memberlist) queueBroadcast(node string, msg []byte, notify chan struct{}) { + b := &memberlistBroadcast{node, msg, notify} + m.broadcasts.QueueBroadcast(b) +} + +// getBroadcasts is used to return a slice of broadcasts to send up to +// a maximum byte size, while imposing a per-broadcast overhead. This is used +// to fill a UDP packet with piggybacked data +func (m *Memberlist) getBroadcasts(overhead, limit int) [][]byte { + // Get memberlist messages first + toSend := m.broadcasts.GetBroadcasts(overhead, limit) + + // Check if the user has anything to broadcast + d := m.config.Delegate + if d != nil { + // Determine the bytes used already + bytesUsed := 0 + for _, msg := range toSend { + bytesUsed += len(msg) + overhead + } + + // Check space remaining for user messages + avail := limit - bytesUsed + if avail > overhead+userMsgOverhead { + userMsgs := d.GetBroadcasts(overhead+userMsgOverhead, avail) + + // Frame each user message + for _, msg := range userMsgs { + buf := make([]byte, 1, len(msg)+1) + buf[0] = byte(userMsg) + buf = append(buf, msg...) + toSend = append(toSend, buf) + } + } + } + return toSend +} diff --git a/vendor/github.com/hashicorp/memberlist/config.go b/vendor/github.com/hashicorp/memberlist/config.go new file mode 100644 index 00000000000..c85b1657a2c --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/config.go @@ -0,0 +1,300 @@ +package memberlist + +import ( + "io" + "log" + "os" + "time" +) + +type Config struct { + // The name of this node. This must be unique in the cluster. + Name string + + // Transport is a hook for providing custom code to communicate with + // other nodes. If this is left nil, then memberlist will by default + // make a NetTransport using BindAddr and BindPort from this structure. + Transport Transport + + // Configuration related to what address to bind to and ports to + // listen on. The port is used for both UDP and TCP gossip. It is + // assumed other nodes are running on this port, but they do not need + // to. + BindAddr string + BindPort int + + // Configuration related to what address to advertise to other + // cluster members. Used for nat traversal. + AdvertiseAddr string + AdvertisePort int + + // ProtocolVersion is the configured protocol version that we + // will _speak_. This must be between ProtocolVersionMin and + // ProtocolVersionMax. + ProtocolVersion uint8 + + // TCPTimeout is the timeout for establishing a stream connection with + // a remote node for a full state sync, and for stream read and write + // operations. This is a legacy name for backwards compatibility, but + // should really be called StreamTimeout now that we have generalized + // the transport. + TCPTimeout time.Duration + + // IndirectChecks is the number of nodes that will be asked to perform + // an indirect probe of a node in the case a direct probe fails. Memberlist + // waits for an ack from any single indirect node, so increasing this + // number will increase the likelihood that an indirect probe will succeed + // at the expense of bandwidth. + IndirectChecks int + + // RetransmitMult is the multiplier for the number of retransmissions + // that are attempted for messages broadcasted over gossip. The actual + // count of retransmissions is calculated using the formula: + // + // Retransmits = RetransmitMult * log(N+1) + // + // This allows the retransmits to scale properly with cluster size. The + // higher the multiplier, the more likely a failed broadcast is to converge + // at the expense of increased bandwidth. + RetransmitMult int + + // SuspicionMult is the multiplier for determining the time an + // inaccessible node is considered suspect before declaring it dead. + // The actual timeout is calculated using the formula: + // + // SuspicionTimeout = SuspicionMult * log(N+1) * ProbeInterval + // + // This allows the timeout to scale properly with expected propagation + // delay with a larger cluster size. The higher the multiplier, the longer + // an inaccessible node is considered part of the cluster before declaring + // it dead, giving that suspect node more time to refute if it is indeed + // still alive. + SuspicionMult int + + // SuspicionMaxTimeoutMult is the multiplier applied to the + // SuspicionTimeout used as an upper bound on detection time. This max + // timeout is calculated using the formula: + // + // SuspicionMaxTimeout = SuspicionMaxTimeoutMult * SuspicionTimeout + // + // If everything is working properly, confirmations from other nodes will + // accelerate suspicion timers in a manner which will cause the timeout + // to reach the base SuspicionTimeout before that elapses, so this value + // will typically only come into play if a node is experiencing issues + // communicating with other nodes. It should be set to a something fairly + // large so that a node having problems will have a lot of chances to + // recover before falsely declaring other nodes as failed, but short + // enough for a legitimately isolated node to still make progress marking + // nodes failed in a reasonable amount of time. + SuspicionMaxTimeoutMult int + + // PushPullInterval is the interval between complete state syncs. + // Complete state syncs are done with a single node over TCP and are + // quite expensive relative to standard gossiped messages. Setting this + // to zero will disable state push/pull syncs completely. + // + // Setting this interval lower (more frequent) will increase convergence + // speeds across larger clusters at the expense of increased bandwidth + // usage. + PushPullInterval time.Duration + + // ProbeInterval and ProbeTimeout are used to configure probing + // behavior for memberlist. + // + // ProbeInterval is the interval between random node probes. Setting + // this lower (more frequent) will cause the memberlist cluster to detect + // failed nodes more quickly at the expense of increased bandwidth usage. + // + // ProbeTimeout is the timeout to wait for an ack from a probed node + // before assuming it is unhealthy. This should be set to 99-percentile + // of RTT (round-trip time) on your network. + ProbeInterval time.Duration + ProbeTimeout time.Duration + + // DisableTcpPings will turn off the fallback TCP pings that are attempted + // if the direct UDP ping fails. These get pipelined along with the + // indirect UDP pings. + DisableTcpPings bool + + // AwarenessMaxMultiplier will increase the probe interval if the node + // becomes aware that it might be degraded and not meeting the soft real + // time requirements to reliably probe other nodes. + AwarenessMaxMultiplier int + + // GossipInterval and GossipNodes are used to configure the gossip + // behavior of memberlist. + // + // GossipInterval is the interval between sending messages that need + // to be gossiped that haven't been able to piggyback on probing messages. + // If this is set to zero, non-piggyback gossip is disabled. By lowering + // this value (more frequent) gossip messages are propagated across + // the cluster more quickly at the expense of increased bandwidth. + // + // GossipNodes is the number of random nodes to send gossip messages to + // per GossipInterval. Increasing this number causes the gossip messages + // to propagate across the cluster more quickly at the expense of + // increased bandwidth. + // + // GossipToTheDeadTime is the interval after which a node has died that + // we will still try to gossip to it. This gives it a chance to refute. + GossipInterval time.Duration + GossipNodes int + GossipToTheDeadTime time.Duration + + // GossipVerifyIncoming controls whether to enforce encryption for incoming + // gossip. It is used for upshifting from unencrypted to encrypted gossip on + // a running cluster. + GossipVerifyIncoming bool + + // GossipVerifyOutgoing controls whether to enforce encryption for outgoing + // gossip. It is used for upshifting from unencrypted to encrypted gossip on + // a running cluster. + GossipVerifyOutgoing bool + + // EnableCompression is used to control message compression. This can + // be used to reduce bandwidth usage at the cost of slightly more CPU + // utilization. This is only available starting at protocol version 1. + EnableCompression bool + + // SecretKey is used to initialize the primary encryption key in a keyring. + // The primary encryption key is the only key used to encrypt messages and + // the first key used while attempting to decrypt messages. Providing a + // value for this primary key will enable message-level encryption and + // verification, and automatically install the key onto the keyring. + // The value should be either 16, 24, or 32 bytes to select AES-128, + // AES-192, or AES-256. + SecretKey []byte + + // The keyring holds all of the encryption keys used internally. It is + // automatically initialized using the SecretKey and SecretKeys values. + Keyring *Keyring + + // Delegate and Events are delegates for receiving and providing + // data to memberlist via callback mechanisms. For Delegate, see + // the Delegate interface. For Events, see the EventDelegate interface. + // + // The DelegateProtocolMin/Max are used to guarantee protocol-compatibility + // for any custom messages that the delegate might do (broadcasts, + // local/remote state, etc.). If you don't set these, then the protocol + // versions will just be zero, and version compliance won't be done. + Delegate Delegate + DelegateProtocolVersion uint8 + DelegateProtocolMin uint8 + DelegateProtocolMax uint8 + Events EventDelegate + Conflict ConflictDelegate + Merge MergeDelegate + Ping PingDelegate + Alive AliveDelegate + + // DNSConfigPath points to the system's DNS config file, usually located + // at /etc/resolv.conf. It can be overridden via config for easier testing. + DNSConfigPath string + + // LogOutput is the writer where logs should be sent. If this is not + // set, logging will go to stderr by default. You cannot specify both LogOutput + // and Logger at the same time. + LogOutput io.Writer + + // Logger is a custom logger which you provide. If Logger is set, it will use + // this for the internal logger. If Logger is not set, it will fall back to the + // behavior for using LogOutput. You cannot specify both LogOutput and Logger + // at the same time. + Logger *log.Logger + + // Size of Memberlist's internal channel which handles UDP messages. The + // size of this determines the size of the queue which Memberlist will keep + // while UDP messages are handled. + HandoffQueueDepth int + + // Maximum number of bytes that memberlist will put in a packet (this + // will be for UDP packets by default with a NetTransport). A safe value + // for this is typically 1400 bytes (which is the default). However, + // depending on your network's MTU (Maximum Transmission Unit) you may + // be able to increase this to get more content into each gossip packet. + // This is a legacy name for backward compatibility but should really be + // called PacketBufferSize now that we have generalized the transport. + UDPBufferSize int +} + +// DefaultLANConfig returns a sane set of configurations for Memberlist. +// It uses the hostname as the node name, and otherwise sets very conservative +// values that are sane for most LAN environments. The default configuration +// errs on the side of caution, choosing values that are optimized +// for higher convergence at the cost of higher bandwidth usage. Regardless, +// these values are a good starting point when getting started with memberlist. +func DefaultLANConfig() *Config { + hostname, _ := os.Hostname() + return &Config{ + Name: hostname, + BindAddr: "0.0.0.0", + BindPort: 7946, + AdvertiseAddr: "", + AdvertisePort: 7946, + ProtocolVersion: ProtocolVersion2Compatible, + TCPTimeout: 10 * time.Second, // Timeout after 10 seconds + IndirectChecks: 3, // Use 3 nodes for the indirect ping + RetransmitMult: 4, // Retransmit a message 4 * log(N+1) nodes + SuspicionMult: 4, // Suspect a node for 4 * log(N+1) * Interval + SuspicionMaxTimeoutMult: 6, // For 10k nodes this will give a max timeout of 120 seconds + PushPullInterval: 30 * time.Second, // Low frequency + ProbeTimeout: 500 * time.Millisecond, // Reasonable RTT time for LAN + ProbeInterval: 1 * time.Second, // Failure check every second + DisableTcpPings: false, // TCP pings are safe, even with mixed versions + AwarenessMaxMultiplier: 8, // Probe interval backs off to 8 seconds + + GossipNodes: 3, // Gossip to 3 nodes + GossipInterval: 200 * time.Millisecond, // Gossip more rapidly + GossipToTheDeadTime: 30 * time.Second, // Same as push/pull + GossipVerifyIncoming: true, + GossipVerifyOutgoing: true, + + EnableCompression: true, // Enable compression by default + + SecretKey: nil, + Keyring: nil, + + DNSConfigPath: "/etc/resolv.conf", + + HandoffQueueDepth: 1024, + UDPBufferSize: 1400, + } +} + +// DefaultWANConfig works like DefaultConfig, however it returns a configuration +// that is optimized for most WAN environments. The default configuration is +// still very conservative and errs on the side of caution. +func DefaultWANConfig() *Config { + conf := DefaultLANConfig() + conf.TCPTimeout = 30 * time.Second + conf.SuspicionMult = 6 + conf.PushPullInterval = 60 * time.Second + conf.ProbeTimeout = 3 * time.Second + conf.ProbeInterval = 5 * time.Second + conf.GossipNodes = 4 // Gossip less frequently, but to an additional node + conf.GossipInterval = 500 * time.Millisecond + conf.GossipToTheDeadTime = 60 * time.Second + return conf +} + +// DefaultLocalConfig works like DefaultConfig, however it returns a configuration +// that is optimized for a local loopback environments. The default configuration is +// still very conservative and errs on the side of caution. +func DefaultLocalConfig() *Config { + conf := DefaultLANConfig() + conf.TCPTimeout = time.Second + conf.IndirectChecks = 1 + conf.RetransmitMult = 2 + conf.SuspicionMult = 3 + conf.PushPullInterval = 15 * time.Second + conf.ProbeTimeout = 200 * time.Millisecond + conf.ProbeInterval = time.Second + conf.GossipInterval = 100 * time.Millisecond + conf.GossipToTheDeadTime = 15 * time.Second + return conf +} + +// Returns whether or not encryption is enabled +func (c *Config) EncryptionEnabled() bool { + return c.Keyring != nil && len(c.Keyring.GetKeys()) > 0 +} diff --git a/vendor/github.com/hashicorp/memberlist/conflict_delegate.go b/vendor/github.com/hashicorp/memberlist/conflict_delegate.go new file mode 100644 index 00000000000..f52b136ebad --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/conflict_delegate.go @@ -0,0 +1,10 @@ +package memberlist + +// ConflictDelegate is a used to inform a client that +// a node has attempted to join which would result in a +// name conflict. This happens if two clients are configured +// with the same name but different addresses. +type ConflictDelegate interface { + // NotifyConflict is invoked when a name conflict is detected + NotifyConflict(existing, other *Node) +} diff --git a/vendor/github.com/hashicorp/memberlist/delegate.go b/vendor/github.com/hashicorp/memberlist/delegate.go new file mode 100644 index 00000000000..55154889216 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/delegate.go @@ -0,0 +1,37 @@ +package memberlist + +// Delegate is the interface that clients must implement if they want to hook +// into the gossip layer of Memberlist. All the methods must be thread-safe, +// as they can and generally will be called concurrently. +type Delegate interface { + // NodeMeta is used to retrieve meta-data about the current node + // when broadcasting an alive message. It's length is limited to + // the given byte size. This metadata is available in the Node structure. + NodeMeta(limit int) []byte + + // NotifyMsg is called when a user-data message is received. + // Care should be taken that this method does not block, since doing + // so would block the entire UDP packet receive loop. Additionally, the byte + // slice may be modified after the call returns, so it should be copied if needed + NotifyMsg([]byte) + + // GetBroadcasts is called when user data messages can be broadcast. + // It can return a list of buffers to send. Each buffer should assume an + // overhead as provided with a limit on the total byte size allowed. + // The total byte size of the resulting data to send must not exceed + // the limit. Care should be taken that this method does not block, + // since doing so would block the entire UDP packet receive loop. + GetBroadcasts(overhead, limit int) [][]byte + + // LocalState is used for a TCP Push/Pull. This is sent to + // the remote side in addition to the membership information. Any + // data can be sent here. See MergeRemoteState as well. The `join` + // boolean indicates this is for a join instead of a push/pull. + LocalState(join bool) []byte + + // MergeRemoteState is invoked after a TCP Push/Pull. This is the + // state received from the remote side and is the result of the + // remote side's LocalState call. The 'join' + // boolean indicates this is for a join instead of a push/pull. + MergeRemoteState(buf []byte, join bool) +} diff --git a/vendor/github.com/hashicorp/memberlist/event_delegate.go b/vendor/github.com/hashicorp/memberlist/event_delegate.go new file mode 100644 index 00000000000..35e2a56fdd0 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/event_delegate.go @@ -0,0 +1,61 @@ +package memberlist + +// EventDelegate is a simpler delegate that is used only to receive +// notifications about members joining and leaving. The methods in this +// delegate may be called by multiple goroutines, but never concurrently. +// This allows you to reason about ordering. +type EventDelegate interface { + // NotifyJoin is invoked when a node is detected to have joined. + // The Node argument must not be modified. + NotifyJoin(*Node) + + // NotifyLeave is invoked when a node is detected to have left. + // The Node argument must not be modified. + NotifyLeave(*Node) + + // NotifyUpdate is invoked when a node is detected to have + // updated, usually involving the meta data. The Node argument + // must not be modified. + NotifyUpdate(*Node) +} + +// ChannelEventDelegate is used to enable an application to receive +// events about joins and leaves over a channel instead of a direct +// function call. +// +// Care must be taken that events are processed in a timely manner from +// the channel, since this delegate will block until an event can be sent. +type ChannelEventDelegate struct { + Ch chan<- NodeEvent +} + +// NodeEventType are the types of events that can be sent from the +// ChannelEventDelegate. +type NodeEventType int + +const ( + NodeJoin NodeEventType = iota + NodeLeave + NodeUpdate +) + +// NodeEvent is a single event related to node activity in the memberlist. +// The Node member of this struct must not be directly modified. It is passed +// as a pointer to avoid unnecessary copies. If you wish to modify the node, +// make a copy first. +type NodeEvent struct { + Event NodeEventType + Node *Node +} + +func (c *ChannelEventDelegate) NotifyJoin(n *Node) { + c.Ch <- NodeEvent{NodeJoin, n} +} + +func (c *ChannelEventDelegate) NotifyLeave(n *Node) { + c.Ch <- NodeEvent{NodeLeave, n} +} + +func (c *ChannelEventDelegate) NotifyUpdate(n *Node) { + c.Ch <- NodeEvent{NodeUpdate, n} +} diff --git a/vendor/github.com/hashicorp/memberlist/go.mod b/vendor/github.com/hashicorp/memberlist/go.mod new file mode 100644 index 00000000000..0c025ff115b --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/go.mod @@ -0,0 +1,20 @@ +module github.com/hashicorp/memberlist + +require ( + github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c + github.com/hashicorp/go-immutable-radix v1.0.0 // indirect + github.com/hashicorp/go-msgpack v0.5.3 + github.com/hashicorp/go-multierror v1.0.0 + github.com/hashicorp/go-sockaddr v1.0.0 + github.com/miekg/dns v1.0.14 + github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 + github.com/stretchr/testify v1.2.2 + golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 // indirect + golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 // indirect + golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect + golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 // indirect +) diff --git a/vendor/github.com/hashicorp/memberlist/go.sum b/vendor/github.com/hashicorp/memberlist/go.sum new file mode 100644 index 00000000000..39534ac2fc1 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/go.sum @@ -0,0 +1,38 @@ +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 h1:x6rhz8Y9CjbgQkccRGmELH6K+LJj7tOoh3XWeC1yaQM= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 h1:x6r4Jo0KNzOOzYd8lbcRsqjuqEASK6ob3auvWYM4/8U= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/hashicorp/memberlist/keyring.go b/vendor/github.com/hashicorp/memberlist/keyring.go new file mode 100644 index 00000000000..a2774a0ce08 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/keyring.go @@ -0,0 +1,160 @@ +package memberlist + +import ( + "bytes" + "fmt" + "sync" +) + +type Keyring struct { + // Keys stores the key data used during encryption and decryption. It is + // ordered in such a way where the first key (index 0) is the primary key, + // which is used for encrypting messages, and is the first key tried during + // message decryption. + keys [][]byte + + // The keyring lock is used while performing IO operations on the keyring. + l sync.Mutex +} + +// Init allocates substructures +func (k *Keyring) init() { + k.keys = make([][]byte, 0) +} + +// NewKeyring constructs a new container for a set of encryption keys. The +// keyring contains all key data used internally by memberlist. +// +// While creating a new keyring, you must do one of: +// - Omit keys and primary key, effectively disabling encryption +// - Pass a set of keys plus the primary key +// - Pass only a primary key +// +// If only a primary key is passed, then it will be automatically added to the +// keyring. If creating a keyring with multiple keys, one key must be designated +// primary by passing it as the primaryKey. If the primaryKey does not exist in +// the list of secondary keys, it will be automatically added at position 0. +// +// A key should be either 16, 24, or 32 bytes to select AES-128, +// AES-192, or AES-256. +func NewKeyring(keys [][]byte, primaryKey []byte) (*Keyring, error) { + keyring := &Keyring{} + keyring.init() + + if len(keys) > 0 || len(primaryKey) > 0 { + if len(primaryKey) == 0 { + return nil, fmt.Errorf("Empty primary key not allowed") + } + if err := keyring.AddKey(primaryKey); err != nil { + return nil, err + } + for _, key := range keys { + if err := keyring.AddKey(key); err != nil { + return nil, err + } + } + } + + return keyring, nil +} + +// ValidateKey will check to see if the key is valid and returns an error if not. +// +// key should be either 16, 24, or 32 bytes to select AES-128, +// AES-192, or AES-256. +func ValidateKey(key []byte) error { + if l := len(key); l != 16 && l != 24 && l != 32 { + return fmt.Errorf("key size must be 16, 24 or 32 bytes") + } + return nil +} + +// AddKey will install a new key on the ring. Adding a key to the ring will make +// it available for use in decryption. If the key already exists on the ring, +// this function will just return noop. +// +// key should be either 16, 24, or 32 bytes to select AES-128, +// AES-192, or AES-256. +func (k *Keyring) AddKey(key []byte) error { + if err := ValidateKey(key); err != nil { + return err + } + + // No-op if key is already installed + for _, installedKey := range k.keys { + if bytes.Equal(installedKey, key) { + return nil + } + } + + keys := append(k.keys, key) + primaryKey := k.GetPrimaryKey() + if primaryKey == nil { + primaryKey = key + } + k.installKeys(keys, primaryKey) + return nil +} + +// UseKey changes the key used to encrypt messages. This is the only key used to +// encrypt messages, so peers should know this key before this method is called. +func (k *Keyring) UseKey(key []byte) error { + for _, installedKey := range k.keys { + if bytes.Equal(key, installedKey) { + k.installKeys(k.keys, key) + return nil + } + } + return fmt.Errorf("Requested key is not in the keyring") +} + +// RemoveKey drops a key from the keyring. This will return an error if the key +// requested for removal is currently at position 0 (primary key). +func (k *Keyring) RemoveKey(key []byte) error { + if bytes.Equal(key, k.keys[0]) { + return fmt.Errorf("Removing the primary key is not allowed") + } + for i, installedKey := range k.keys { + if bytes.Equal(key, installedKey) { + keys := append(k.keys[:i], k.keys[i+1:]...) + k.installKeys(keys, k.keys[0]) + } + } + return nil +} + +// installKeys will take out a lock on the keyring, and replace the keys with a +// new set of keys. The key indicated by primaryKey will be installed as the new +// primary key. +func (k *Keyring) installKeys(keys [][]byte, primaryKey []byte) { + k.l.Lock() + defer k.l.Unlock() + + newKeys := [][]byte{primaryKey} + for _, key := range keys { + if !bytes.Equal(key, primaryKey) { + newKeys = append(newKeys, key) + } + } + k.keys = newKeys +} + +// GetKeys returns the current set of keys on the ring. +func (k *Keyring) GetKeys() [][]byte { + k.l.Lock() + defer k.l.Unlock() + + return k.keys +} + +// GetPrimaryKey returns the key on the ring at position 0. This is the key used +// for encrypting messages, and is the first key tried for decrypting messages. +func (k *Keyring) GetPrimaryKey() (key []byte) { + k.l.Lock() + defer k.l.Unlock() + + if len(k.keys) > 0 { + key = k.keys[0] + } + return +} diff --git a/vendor/github.com/hashicorp/memberlist/logging.go b/vendor/github.com/hashicorp/memberlist/logging.go new file mode 100644 index 00000000000..f31acfb2fa3 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/logging.go @@ -0,0 +1,22 @@ +package memberlist + +import ( + "fmt" + "net" +) + +func LogAddress(addr net.Addr) string { + if addr == nil { + return "from=" + } + + return fmt.Sprintf("from=%s", addr.String()) +} + +func LogConn(conn net.Conn) string { + if conn == nil { + return LogAddress(nil) + } + + return LogAddress(conn.RemoteAddr()) +} diff --git a/vendor/github.com/hashicorp/memberlist/memberlist.go b/vendor/github.com/hashicorp/memberlist/memberlist.go new file mode 100644 index 00000000000..3a4ce967b81 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/memberlist.go @@ -0,0 +1,691 @@ +/* +memberlist is a library that manages cluster +membership and member failure detection using a gossip based protocol. + +The use cases for such a library are far-reaching: all distributed systems +require membership, and memberlist is a re-usable solution to managing +cluster membership and node failure detection. + +memberlist is eventually consistent but converges quickly on average. +The speed at which it converges can be heavily tuned via various knobs +on the protocol. Node failures are detected and network partitions are partially +tolerated by attempting to communicate to potentially dead nodes through +multiple routes. +*/ +package memberlist + +import ( + "container/list" + "fmt" + "log" + "net" + "os" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + + multierror "github.com/hashicorp/go-multierror" + sockaddr "github.com/hashicorp/go-sockaddr" + "github.com/miekg/dns" +) + +type Memberlist struct { + sequenceNum uint32 // Local sequence number + incarnation uint32 // Local incarnation number + numNodes uint32 // Number of known nodes (estimate) + pushPullReq uint32 // Number of push/pull requests + + config *Config + shutdown int32 // Used as an atomic boolean value + shutdownCh chan struct{} + leave int32 // Used as an atomic boolean value + leaveBroadcast chan struct{} + + shutdownLock sync.Mutex // Serializes calls to Shutdown + leaveLock sync.Mutex // Serializes calls to Leave + + transport Transport + + handoffCh chan struct{} + highPriorityMsgQueue *list.List + lowPriorityMsgQueue *list.List + msgQueueLock sync.Mutex + + nodeLock sync.RWMutex + nodes []*nodeState // Known nodes + nodeMap map[string]*nodeState // Maps Addr.String() -> NodeState + nodeTimers map[string]*suspicion // Maps Addr.String() -> suspicion timer + awareness *awareness + + tickerLock sync.Mutex + tickers []*time.Ticker + stopTick chan struct{} + probeIndex int + + ackLock sync.Mutex + ackHandlers map[uint32]*ackHandler + + broadcasts *TransmitLimitedQueue + + logger *log.Logger +} + +// newMemberlist creates the network listeners. +// Does not schedule execution of background maintenance. +func newMemberlist(conf *Config) (*Memberlist, error) { + if conf.ProtocolVersion < ProtocolVersionMin { + return nil, fmt.Errorf("Protocol version '%d' too low. Must be in range: [%d, %d]", + conf.ProtocolVersion, ProtocolVersionMin, ProtocolVersionMax) + } else if conf.ProtocolVersion > ProtocolVersionMax { + return nil, fmt.Errorf("Protocol version '%d' too high. Must be in range: [%d, %d]", + conf.ProtocolVersion, ProtocolVersionMin, ProtocolVersionMax) + } + + if len(conf.SecretKey) > 0 { + if conf.Keyring == nil { + keyring, err := NewKeyring(nil, conf.SecretKey) + if err != nil { + return nil, err + } + conf.Keyring = keyring + } else { + if err := conf.Keyring.AddKey(conf.SecretKey); err != nil { + return nil, err + } + if err := conf.Keyring.UseKey(conf.SecretKey); err != nil { + return nil, err + } + } + } + + if conf.LogOutput != nil && conf.Logger != nil { + return nil, fmt.Errorf("Cannot specify both LogOutput and Logger. Please choose a single log configuration setting.") + } + + logDest := conf.LogOutput + if logDest == nil { + logDest = os.Stderr + } + + logger := conf.Logger + if logger == nil { + logger = log.New(logDest, "", log.LstdFlags) + } + + // Set up a network transport by default if a custom one wasn't given + // by the config. + transport := conf.Transport + if transport == nil { + nc := &NetTransportConfig{ + BindAddrs: []string{conf.BindAddr}, + BindPort: conf.BindPort, + Logger: logger, + } + + // See comment below for details about the retry in here. + makeNetRetry := func(limit int) (*NetTransport, error) { + var err error + for try := 0; try < limit; try++ { + var nt *NetTransport + if nt, err = NewNetTransport(nc); err == nil { + return nt, nil + } + if strings.Contains(err.Error(), "address already in use") { + logger.Printf("[DEBUG] memberlist: Got bind error: %v", err) + continue + } + } + + return nil, fmt.Errorf("failed to obtain an address: %v", err) + } + + // The dynamic bind port operation is inherently racy because + // even though we are using the kernel to find a port for us, we + // are attempting to bind multiple protocols (and potentially + // multiple addresses) with the same port number. We build in a + // few retries here since this often gets transient errors in + // busy unit tests. + limit := 1 + if conf.BindPort == 0 { + limit = 10 + } + + nt, err := makeNetRetry(limit) + if err != nil { + return nil, fmt.Errorf("Could not set up network transport: %v", err) + } + if conf.BindPort == 0 { + port := nt.GetAutoBindPort() + conf.BindPort = port + conf.AdvertisePort = port + logger.Printf("[DEBUG] memberlist: Using dynamic bind port %d", port) + } + transport = nt + } + + m := &Memberlist{ + config: conf, + shutdownCh: make(chan struct{}), + leaveBroadcast: make(chan struct{}, 1), + transport: transport, + handoffCh: make(chan struct{}, 1), + highPriorityMsgQueue: list.New(), + lowPriorityMsgQueue: list.New(), + nodeMap: make(map[string]*nodeState), + nodeTimers: make(map[string]*suspicion), + awareness: newAwareness(conf.AwarenessMaxMultiplier), + ackHandlers: make(map[uint32]*ackHandler), + broadcasts: &TransmitLimitedQueue{RetransmitMult: conf.RetransmitMult}, + logger: logger, + } + m.broadcasts.NumNodes = func() int { + return m.estNumNodes() + } + go m.streamListen() + go m.packetListen() + go m.packetHandler() + return m, nil +} + +// Create will create a new Memberlist using the given configuration. +// This will not connect to any other node (see Join) yet, but will start +// all the listeners to allow other nodes to join this memberlist. +// After creating a Memberlist, the configuration given should not be +// modified by the user anymore. +func Create(conf *Config) (*Memberlist, error) { + m, err := newMemberlist(conf) + if err != nil { + return nil, err + } + if err := m.setAlive(); err != nil { + m.Shutdown() + return nil, err + } + m.schedule() + return m, nil +} + +// Join is used to take an existing Memberlist and attempt to join a cluster +// by contacting all the given hosts and performing a state sync. Initially, +// the Memberlist only contains our own state, so doing this will cause +// remote nodes to become aware of the existence of this node, effectively +// joining the cluster. +// +// This returns the number of hosts successfully contacted and an error if +// none could be reached. If an error is returned, the node did not successfully +// join the cluster. +func (m *Memberlist) Join(existing []string) (int, error) { + numSuccess := 0 + var errs error + for _, exist := range existing { + addrs, err := m.resolveAddr(exist) + if err != nil { + err = fmt.Errorf("Failed to resolve %s: %v", exist, err) + errs = multierror.Append(errs, err) + m.logger.Printf("[WARN] memberlist: %v", err) + continue + } + + for _, addr := range addrs { + hp := joinHostPort(addr.ip.String(), addr.port) + if err := m.pushPullNode(hp, true); err != nil { + err = fmt.Errorf("Failed to join %s: %v", addr.ip, err) + errs = multierror.Append(errs, err) + m.logger.Printf("[DEBUG] memberlist: %v", err) + continue + } + numSuccess++ + } + + } + if numSuccess > 0 { + errs = nil + } + return numSuccess, errs +} + +// ipPort holds information about a node we want to try to join. +type ipPort struct { + ip net.IP + port uint16 +} + +// tcpLookupIP is a helper to initiate a TCP-based DNS lookup for the given host. +// The built-in Go resolver will do a UDP lookup first, and will only use TCP if +// the response has the truncate bit set, which isn't common on DNS servers like +// Consul's. By doing the TCP lookup directly, we get the best chance for the +// largest list of hosts to join. Since joins are relatively rare events, it's ok +// to do this rather expensive operation. +func (m *Memberlist) tcpLookupIP(host string, defaultPort uint16) ([]ipPort, error) { + // Don't attempt any TCP lookups against non-fully qualified domain + // names, since those will likely come from the resolv.conf file. + if !strings.Contains(host, ".") { + return nil, nil + } + + // Make sure the domain name is terminated with a dot (we know there's + // at least one character at this point). + dn := host + if dn[len(dn)-1] != '.' { + dn = dn + "." + } + + // See if we can find a server to try. + cc, err := dns.ClientConfigFromFile(m.config.DNSConfigPath) + if err != nil { + return nil, err + } + if len(cc.Servers) > 0 { + // We support host:port in the DNS config, but need to add the + // default port if one is not supplied. + server := cc.Servers[0] + if !hasPort(server) { + server = net.JoinHostPort(server, cc.Port) + } + + // Do the lookup. + c := new(dns.Client) + c.Net = "tcp" + msg := new(dns.Msg) + msg.SetQuestion(dn, dns.TypeANY) + in, _, err := c.Exchange(msg, server) + if err != nil { + return nil, err + } + + // Handle any IPs we get back that we can attempt to join. + var ips []ipPort + for _, r := range in.Answer { + switch rr := r.(type) { + case (*dns.A): + ips = append(ips, ipPort{rr.A, defaultPort}) + case (*dns.AAAA): + ips = append(ips, ipPort{rr.AAAA, defaultPort}) + case (*dns.CNAME): + m.logger.Printf("[DEBUG] memberlist: Ignoring CNAME RR in TCP-first answer for '%s'", host) + } + } + return ips, nil + } + + return nil, nil +} + +// resolveAddr is used to resolve the address into an address, +// port, and error. If no port is given, use the default +func (m *Memberlist) resolveAddr(hostStr string) ([]ipPort, error) { + // This captures the supplied port, or the default one. + hostStr = ensurePort(hostStr, m.config.BindPort) + host, sport, err := net.SplitHostPort(hostStr) + if err != nil { + return nil, err + } + lport, err := strconv.ParseUint(sport, 10, 16) + if err != nil { + return nil, err + } + port := uint16(lport) + + // If it looks like an IP address we are done. The SplitHostPort() above + // will make sure the host part is in good shape for parsing, even for + // IPv6 addresses. + if ip := net.ParseIP(host); ip != nil { + return []ipPort{ipPort{ip, port}}, nil + } + + // First try TCP so we have the best chance for the largest list of + // hosts to join. If this fails it's not fatal since this isn't a standard + // way to query DNS, and we have a fallback below. + ips, err := m.tcpLookupIP(host, port) + if err != nil { + m.logger.Printf("[DEBUG] memberlist: TCP-first lookup failed for '%s', falling back to UDP: %s", hostStr, err) + } + if len(ips) > 0 { + return ips, nil + } + + // If TCP didn't yield anything then use the normal Go resolver which + // will try UDP, then might possibly try TCP again if the UDP response + // indicates it was truncated. + ans, err := net.LookupIP(host) + if err != nil { + return nil, err + } + ips = make([]ipPort, 0, len(ans)) + for _, ip := range ans { + ips = append(ips, ipPort{ip, port}) + } + return ips, nil +} + +// setAlive is used to mark this node as being alive. This is the same +// as if we received an alive notification our own network channel for +// ourself. +func (m *Memberlist) setAlive() error { + // Get the final advertise address from the transport, which may need + // to see which address we bound to. + addr, port, err := m.transport.FinalAdvertiseAddr( + m.config.AdvertiseAddr, m.config.AdvertisePort) + if err != nil { + return fmt.Errorf("Failed to get final advertise address: %v", err) + } + + // Check if this is a public address without encryption + ipAddr, err := sockaddr.NewIPAddr(addr.String()) + if err != nil { + return fmt.Errorf("Failed to parse interface addresses: %v", err) + } + ifAddrs := []sockaddr.IfAddr{ + sockaddr.IfAddr{ + SockAddr: ipAddr, + }, + } + _, publicIfs, err := sockaddr.IfByRFC("6890", ifAddrs) + if len(publicIfs) > 0 && !m.config.EncryptionEnabled() { + m.logger.Printf("[WARN] memberlist: Binding to public address without encryption!") + } + + // Set any metadata from the delegate. + var meta []byte + if m.config.Delegate != nil { + meta = m.config.Delegate.NodeMeta(MetaMaxSize) + if len(meta) > MetaMaxSize { + panic("Node meta data provided is longer than the limit") + } + } + + a := alive{ + Incarnation: m.nextIncarnation(), + Node: m.config.Name, + Addr: addr, + Port: uint16(port), + Meta: meta, + Vsn: []uint8{ + ProtocolVersionMin, ProtocolVersionMax, m.config.ProtocolVersion, + m.config.DelegateProtocolMin, m.config.DelegateProtocolMax, + m.config.DelegateProtocolVersion, + }, + } + m.aliveNode(&a, nil, true) + return nil +} + +// LocalNode is used to return the local Node +func (m *Memberlist) LocalNode() *Node { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + state := m.nodeMap[m.config.Name] + return &state.Node +} + +// UpdateNode is used to trigger re-advertising the local node. This is +// primarily used with a Delegate to support dynamic updates to the local +// meta data. This will block until the update message is successfully +// broadcasted to a member of the cluster, if any exist or until a specified +// timeout is reached. +func (m *Memberlist) UpdateNode(timeout time.Duration) error { + // Get the node meta data + var meta []byte + if m.config.Delegate != nil { + meta = m.config.Delegate.NodeMeta(MetaMaxSize) + if len(meta) > MetaMaxSize { + panic("Node meta data provided is longer than the limit") + } + } + + // Get the existing node + m.nodeLock.RLock() + state := m.nodeMap[m.config.Name] + m.nodeLock.RUnlock() + + // Format a new alive message + a := alive{ + Incarnation: m.nextIncarnation(), + Node: m.config.Name, + Addr: state.Addr, + Port: state.Port, + Meta: meta, + Vsn: []uint8{ + ProtocolVersionMin, ProtocolVersionMax, m.config.ProtocolVersion, + m.config.DelegateProtocolMin, m.config.DelegateProtocolMax, + m.config.DelegateProtocolVersion, + }, + } + notifyCh := make(chan struct{}) + m.aliveNode(&a, notifyCh, true) + + // Wait for the broadcast or a timeout + if m.anyAlive() { + var timeoutCh <-chan time.Time + if timeout > 0 { + timeoutCh = time.After(timeout) + } + select { + case <-notifyCh: + case <-timeoutCh: + return fmt.Errorf("timeout waiting for update broadcast") + } + } + return nil +} + +// SendTo is deprecated in favor of SendBestEffort, which requires a node to +// target. +func (m *Memberlist) SendTo(to net.Addr, msg []byte) error { + // Encode as a user message + buf := make([]byte, 1, len(msg)+1) + buf[0] = byte(userMsg) + buf = append(buf, msg...) + + // Send the message + return m.rawSendMsgPacket(to.String(), nil, buf) +} + +// SendToUDP is deprecated in favor of SendBestEffort. +func (m *Memberlist) SendToUDP(to *Node, msg []byte) error { + return m.SendBestEffort(to, msg) +} + +// SendToTCP is deprecated in favor of SendReliable. +func (m *Memberlist) SendToTCP(to *Node, msg []byte) error { + return m.SendReliable(to, msg) +} + +// SendBestEffort uses the unreliable packet-oriented interface of the transport +// to target a user message at the given node (this does not use the gossip +// mechanism). The maximum size of the message depends on the configured +// UDPBufferSize for this memberlist instance. +func (m *Memberlist) SendBestEffort(to *Node, msg []byte) error { + // Encode as a user message + buf := make([]byte, 1, len(msg)+1) + buf[0] = byte(userMsg) + buf = append(buf, msg...) + + // Send the message + return m.rawSendMsgPacket(to.Address(), to, buf) +} + +// SendReliable uses the reliable stream-oriented interface of the transport to +// target a user message at the given node (this does not use the gossip +// mechanism). Delivery is guaranteed if no error is returned, and there is no +// limit on the size of the message. +func (m *Memberlist) SendReliable(to *Node, msg []byte) error { + return m.sendUserMsg(to.Address(), msg) +} + +// Members returns a list of all known live nodes. The node structures +// returned must not be modified. If you wish to modify a Node, make a +// copy first. +func (m *Memberlist) Members() []*Node { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + + nodes := make([]*Node, 0, len(m.nodes)) + for _, n := range m.nodes { + if n.State != stateDead { + nodes = append(nodes, &n.Node) + } + } + + return nodes +} + +// NumMembers returns the number of alive nodes currently known. Between +// the time of calling this and calling Members, the number of alive nodes +// may have changed, so this shouldn't be used to determine how many +// members will be returned by Members. +func (m *Memberlist) NumMembers() (alive int) { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + + for _, n := range m.nodes { + if n.State != stateDead { + alive++ + } + } + + return +} + +// Leave will broadcast a leave message but will not shutdown the background +// listeners, meaning the node will continue participating in gossip and state +// updates. +// +// This will block until the leave message is successfully broadcasted to +// a member of the cluster, if any exist or until a specified timeout +// is reached. +// +// This method is safe to call multiple times, but must not be called +// after the cluster is already shut down. +func (m *Memberlist) Leave(timeout time.Duration) error { + m.leaveLock.Lock() + defer m.leaveLock.Unlock() + + if m.hasShutdown() { + panic("leave after shutdown") + } + + if !m.hasLeft() { + atomic.StoreInt32(&m.leave, 1) + + m.nodeLock.Lock() + state, ok := m.nodeMap[m.config.Name] + m.nodeLock.Unlock() + if !ok { + m.logger.Printf("[WARN] memberlist: Leave but we're not in the node map.") + return nil + } + + d := dead{ + Incarnation: state.Incarnation, + Node: state.Name, + } + m.deadNode(&d) + + // Block until the broadcast goes out + if m.anyAlive() { + var timeoutCh <-chan time.Time + if timeout > 0 { + timeoutCh = time.After(timeout) + } + select { + case <-m.leaveBroadcast: + case <-timeoutCh: + return fmt.Errorf("timeout waiting for leave broadcast") + } + } + } + + return nil +} + +// Check for any other alive node. +func (m *Memberlist) anyAlive() bool { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + for _, n := range m.nodes { + if n.State != stateDead && n.Name != m.config.Name { + return true + } + } + return false +} + +// GetHealthScore gives this instance's idea of how well it is meeting the soft +// real-time requirements of the protocol. Lower numbers are better, and zero +// means "totally healthy". +func (m *Memberlist) GetHealthScore() int { + return m.awareness.GetHealthScore() +} + +// ProtocolVersion returns the protocol version currently in use by +// this memberlist. +func (m *Memberlist) ProtocolVersion() uint8 { + // NOTE: This method exists so that in the future we can control + // any locking if necessary, if we change the protocol version at + // runtime, etc. + return m.config.ProtocolVersion +} + +// Shutdown will stop any background maintanence of network activity +// for this memberlist, causing it to appear "dead". A leave message +// will not be broadcasted prior, so the cluster being left will have +// to detect this node's shutdown using probing. If you wish to more +// gracefully exit the cluster, call Leave prior to shutting down. +// +// This method is safe to call multiple times. +func (m *Memberlist) Shutdown() error { + m.shutdownLock.Lock() + defer m.shutdownLock.Unlock() + + if m.hasShutdown() { + return nil + } + + // Shut down the transport first, which should block until it's + // completely torn down. If we kill the memberlist-side handlers + // those I/O handlers might get stuck. + if err := m.transport.Shutdown(); err != nil { + m.logger.Printf("[ERR] Failed to shutdown transport: %v", err) + } + + // Now tear down everything else. + atomic.StoreInt32(&m.shutdown, 1) + close(m.shutdownCh) + m.deschedule() + return nil +} + +func (m *Memberlist) hasShutdown() bool { + return atomic.LoadInt32(&m.shutdown) == 1 +} + +func (m *Memberlist) hasLeft() bool { + return atomic.LoadInt32(&m.leave) == 1 +} + +func (m *Memberlist) getNodeState(addr string) nodeStateType { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + + n := m.nodeMap[addr] + return n.State +} + +func (m *Memberlist) getNodeStateChange(addr string) time.Time { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + + n := m.nodeMap[addr] + return n.StateChange +} + +func (m *Memberlist) changeNode(addr string, f func(*nodeState)) { + m.nodeLock.Lock() + defer m.nodeLock.Unlock() + + n := m.nodeMap[addr] + f(n) +} diff --git a/vendor/github.com/hashicorp/memberlist/merge_delegate.go b/vendor/github.com/hashicorp/memberlist/merge_delegate.go new file mode 100644 index 00000000000..89afb59f201 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/merge_delegate.go @@ -0,0 +1,14 @@ +package memberlist + +// MergeDelegate is used to involve a client in +// a potential cluster merge operation. Namely, when +// a node does a TCP push/pull (as part of a join), +// the delegate is involved and allowed to cancel the join +// based on custom logic. The merge delegate is NOT invoked +// as part of the push-pull anti-entropy. +type MergeDelegate interface { + // NotifyMerge is invoked when a merge could take place. + // Provides a list of the nodes known by the peer. If + // the return value is non-nil, the merge is canceled. + NotifyMerge(peers []*Node) error +} diff --git a/vendor/github.com/hashicorp/memberlist/mock_transport.go b/vendor/github.com/hashicorp/memberlist/mock_transport.go new file mode 100644 index 00000000000..b8bafa80260 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/mock_transport.go @@ -0,0 +1,121 @@ +package memberlist + +import ( + "fmt" + "net" + "strconv" + "time" +) + +// MockNetwork is used as a factory that produces MockTransport instances which +// are uniquely addressed and wired up to talk to each other. +type MockNetwork struct { + transports map[string]*MockTransport + port int +} + +// NewTransport returns a new MockTransport with a unique address, wired up to +// talk to the other transports in the MockNetwork. +func (n *MockNetwork) NewTransport() *MockTransport { + n.port += 1 + addr := fmt.Sprintf("127.0.0.1:%d", n.port) + transport := &MockTransport{ + net: n, + addr: &MockAddress{addr}, + packetCh: make(chan *Packet), + streamCh: make(chan net.Conn), + } + + if n.transports == nil { + n.transports = make(map[string]*MockTransport) + } + n.transports[addr] = transport + return transport +} + +// MockAddress is a wrapper which adds the net.Addr interface to our mock +// address scheme. +type MockAddress struct { + addr string +} + +// See net.Addr. +func (a *MockAddress) Network() string { + return "mock" +} + +// See net.Addr. +func (a *MockAddress) String() string { + return a.addr +} + +// MockTransport directly plumbs messages to other transports its MockNetwork. +type MockTransport struct { + net *MockNetwork + addr *MockAddress + packetCh chan *Packet + streamCh chan net.Conn +} + +// See Transport. +func (t *MockTransport) FinalAdvertiseAddr(string, int) (net.IP, int, error) { + host, portStr, err := net.SplitHostPort(t.addr.String()) + if err != nil { + return nil, 0, err + } + + ip := net.ParseIP(host) + if ip == nil { + return nil, 0, fmt.Errorf("Failed to parse IP %q", host) + } + + port, err := strconv.ParseInt(portStr, 10, 16) + if err != nil { + return nil, 0, err + } + + return ip, int(port), nil +} + +// See Transport. +func (t *MockTransport) WriteTo(b []byte, addr string) (time.Time, error) { + dest, ok := t.net.transports[addr] + if !ok { + return time.Time{}, fmt.Errorf("No route to %q", addr) + } + + now := time.Now() + dest.packetCh <- &Packet{ + Buf: b, + From: t.addr, + Timestamp: now, + } + return now, nil +} + +// See Transport. +func (t *MockTransport) PacketCh() <-chan *Packet { + return t.packetCh +} + +// See Transport. +func (t *MockTransport) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) { + dest, ok := t.net.transports[addr] + if !ok { + return nil, fmt.Errorf("No route to %q", addr) + } + + p1, p2 := net.Pipe() + dest.streamCh <- p1 + return p2, nil +} + +// See Transport. +func (t *MockTransport) StreamCh() <-chan net.Conn { + return t.streamCh +} + +// See Transport. +func (t *MockTransport) Shutdown() error { + return nil +} diff --git a/vendor/github.com/hashicorp/memberlist/net.go b/vendor/github.com/hashicorp/memberlist/net.go new file mode 100644 index 00000000000..f6a0d45fedb --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/net.go @@ -0,0 +1,1151 @@ +package memberlist + +import ( + "bufio" + "bytes" + "encoding/binary" + "fmt" + "hash/crc32" + "io" + "net" + "sync/atomic" + "time" + + metrics "github.com/armon/go-metrics" + "github.com/hashicorp/go-msgpack/codec" +) + +// This is the minimum and maximum protocol version that we can +// _understand_. We're allowed to speak at any version within this +// range. This range is inclusive. +const ( + ProtocolVersionMin uint8 = 1 + + // Version 3 added support for TCP pings but we kept the default + // protocol version at 2 to ease transition to this new feature. + // A memberlist speaking version 2 of the protocol will attempt + // to TCP ping another memberlist who understands version 3 or + // greater. + // + // Version 4 added support for nacks as part of indirect probes. + // A memberlist speaking version 2 of the protocol will expect + // nacks from another memberlist who understands version 4 or + // greater, and likewise nacks will be sent to memberlists who + // understand version 4 or greater. + ProtocolVersion2Compatible = 2 + + ProtocolVersionMax = 5 +) + +// messageType is an integer ID of a type of message that can be received +// on network channels from other members. +type messageType uint8 + +// The list of available message types. +const ( + pingMsg messageType = iota + indirectPingMsg + ackRespMsg + suspectMsg + aliveMsg + deadMsg + pushPullMsg + compoundMsg + userMsg // User mesg, not handled by us + compressMsg + encryptMsg + nackRespMsg + hasCrcMsg + errMsg +) + +// compressionType is used to specify the compression algorithm +type compressionType uint8 + +const ( + lzwAlgo compressionType = iota +) + +const ( + MetaMaxSize = 512 // Maximum size for node meta data + compoundHeaderOverhead = 2 // Assumed header overhead + compoundOverhead = 2 // Assumed overhead per entry in compoundHeader + userMsgOverhead = 1 + blockingWarning = 10 * time.Millisecond // Warn if a UDP packet takes this long to process + maxPushStateBytes = 20 * 1024 * 1024 + maxPushPullRequests = 128 // Maximum number of concurrent push/pull requests +) + +// ping request sent directly to node +type ping struct { + SeqNo uint32 + + // Node is sent so the target can verify they are + // the intended recipient. This is to protect again an agent + // restart with a new name. + Node string +} + +// indirect ping sent to an indirect ndoe +type indirectPingReq struct { + SeqNo uint32 + Target []byte + Port uint16 + Node string + Nack bool // true if we'd like a nack back +} + +// ack response is sent for a ping +type ackResp struct { + SeqNo uint32 + Payload []byte +} + +// nack response is sent for an indirect ping when the pinger doesn't hear from +// the ping-ee within the configured timeout. This lets the original node know +// that the indirect ping attempt happened but didn't succeed. +type nackResp struct { + SeqNo uint32 +} + +// err response is sent to relay the error from the remote end +type errResp struct { + Error string +} + +// suspect is broadcast when we suspect a node is dead +type suspect struct { + Incarnation uint32 + Node string + From string // Include who is suspecting +} + +// alive is broadcast when we know a node is alive. +// Overloaded for nodes joining +type alive struct { + Incarnation uint32 + Node string + Addr []byte + Port uint16 + Meta []byte + + // The versions of the protocol/delegate that are being spoken, order: + // pmin, pmax, pcur, dmin, dmax, dcur + Vsn []uint8 +} + +// dead is broadcast when we confirm a node is dead +// Overloaded for nodes leaving +type dead struct { + Incarnation uint32 + Node string + From string // Include who is suspecting +} + +// pushPullHeader is used to inform the +// otherside how many states we are transferring +type pushPullHeader struct { + Nodes int + UserStateLen int // Encodes the byte lengh of user state + Join bool // Is this a join request or a anti-entropy run +} + +// userMsgHeader is used to encapsulate a userMsg +type userMsgHeader struct { + UserMsgLen int // Encodes the byte lengh of user state +} + +// pushNodeState is used for pushPullReq when we are +// transferring out node states +type pushNodeState struct { + Name string + Addr []byte + Port uint16 + Meta []byte + Incarnation uint32 + State nodeStateType + Vsn []uint8 // Protocol versions +} + +// compress is used to wrap an underlying payload +// using a specified compression algorithm +type compress struct { + Algo compressionType + Buf []byte +} + +// msgHandoff is used to transfer a message between goroutines +type msgHandoff struct { + msgType messageType + buf []byte + from net.Addr +} + +// encryptionVersion returns the encryption version to use +func (m *Memberlist) encryptionVersion() encryptionVersion { + switch m.ProtocolVersion() { + case 1: + return 0 + default: + return 1 + } +} + +// streamListen is a long running goroutine that pulls incoming streams from the +// transport and hands them off for processing. +func (m *Memberlist) streamListen() { + for { + select { + case conn := <-m.transport.StreamCh(): + go m.handleConn(conn) + + case <-m.shutdownCh: + return + } + } +} + +// handleConn handles a single incoming stream connection from the transport. +func (m *Memberlist) handleConn(conn net.Conn) { + m.logger.Printf("[DEBUG] memberlist: Stream connection %s", LogConn(conn)) + + defer conn.Close() + metrics.IncrCounter([]string{"memberlist", "tcp", "accept"}, 1) + + conn.SetDeadline(time.Now().Add(m.config.TCPTimeout)) + msgType, bufConn, dec, err := m.readStream(conn) + if err != nil { + if err != io.EOF { + m.logger.Printf("[ERR] memberlist: failed to receive: %s %s", err, LogConn(conn)) + + resp := errResp{err.Error()} + out, err := encode(errMsg, &resp) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to encode error response: %s", err) + return + } + + err = m.rawSendMsgStream(conn, out.Bytes()) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send error: %s %s", err, LogConn(conn)) + return + } + } + return + } + + switch msgType { + case userMsg: + if err := m.readUserMsg(bufConn, dec); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to receive user message: %s %s", err, LogConn(conn)) + } + case pushPullMsg: + // Increment counter of pending push/pulls + numConcurrent := atomic.AddUint32(&m.pushPullReq, 1) + defer atomic.AddUint32(&m.pushPullReq, ^uint32(0)) + + // Check if we have too many open push/pull requests + if numConcurrent >= maxPushPullRequests { + m.logger.Printf("[ERR] memberlist: Too many pending push/pull requests") + return + } + + join, remoteNodes, userState, err := m.readRemoteState(bufConn, dec) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to read remote state: %s %s", err, LogConn(conn)) + return + } + + if err := m.sendLocalState(conn, join); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to push local state: %s %s", err, LogConn(conn)) + return + } + + if err := m.mergeRemoteState(join, remoteNodes, userState); err != nil { + m.logger.Printf("[ERR] memberlist: Failed push/pull merge: %s %s", err, LogConn(conn)) + return + } + case pingMsg: + var p ping + if err := dec.Decode(&p); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode ping: %s %s", err, LogConn(conn)) + return + } + + if p.Node != "" && p.Node != m.config.Name { + m.logger.Printf("[WARN] memberlist: Got ping for unexpected node %s %s", p.Node, LogConn(conn)) + return + } + + ack := ackResp{p.SeqNo, nil} + out, err := encode(ackRespMsg, &ack) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to encode ack: %s", err) + return + } + + err = m.rawSendMsgStream(conn, out.Bytes()) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send ack: %s %s", err, LogConn(conn)) + return + } + default: + m.logger.Printf("[ERR] memberlist: Received invalid msgType (%d) %s", msgType, LogConn(conn)) + } +} + +// packetListen is a long running goroutine that pulls packets out of the +// transport and hands them off for processing. +func (m *Memberlist) packetListen() { + for { + select { + case packet := <-m.transport.PacketCh(): + m.ingestPacket(packet.Buf, packet.From, packet.Timestamp) + + case <-m.shutdownCh: + return + } + } +} + +func (m *Memberlist) ingestPacket(buf []byte, from net.Addr, timestamp time.Time) { + // Check if encryption is enabled + if m.config.EncryptionEnabled() { + // Decrypt the payload + plain, err := decryptPayload(m.config.Keyring.GetKeys(), buf, nil) + if err != nil { + if !m.config.GossipVerifyIncoming { + // Treat the message as plaintext + plain = buf + } else { + m.logger.Printf("[ERR] memberlist: Decrypt packet failed: %v %s", err, LogAddress(from)) + return + } + } + + // Continue processing the plaintext buffer + buf = plain + } + + // See if there's a checksum included to verify the contents of the message + if len(buf) >= 5 && messageType(buf[0]) == hasCrcMsg { + crc := crc32.ChecksumIEEE(buf[5:]) + expected := binary.BigEndian.Uint32(buf[1:5]) + if crc != expected { + m.logger.Printf("[WARN] memberlist: Got invalid checksum for UDP packet: %x, %x", crc, expected) + return + } + m.handleCommand(buf[5:], from, timestamp) + } else { + m.handleCommand(buf, from, timestamp) + } +} + +func (m *Memberlist) handleCommand(buf []byte, from net.Addr, timestamp time.Time) { + // Decode the message type + msgType := messageType(buf[0]) + buf = buf[1:] + + // Switch on the msgType + switch msgType { + case compoundMsg: + m.handleCompound(buf, from, timestamp) + case compressMsg: + m.handleCompressed(buf, from, timestamp) + + case pingMsg: + m.handlePing(buf, from) + case indirectPingMsg: + m.handleIndirectPing(buf, from) + case ackRespMsg: + m.handleAck(buf, from, timestamp) + case nackRespMsg: + m.handleNack(buf, from) + + case suspectMsg: + fallthrough + case aliveMsg: + fallthrough + case deadMsg: + fallthrough + case userMsg: + // Determine the message queue, prioritize alive + queue := m.lowPriorityMsgQueue + if msgType == aliveMsg { + queue = m.highPriorityMsgQueue + } + + // Check for overflow and append if not full + m.msgQueueLock.Lock() + if queue.Len() >= m.config.HandoffQueueDepth { + m.logger.Printf("[WARN] memberlist: handler queue full, dropping message (%d) %s", msgType, LogAddress(from)) + } else { + queue.PushBack(msgHandoff{msgType, buf, from}) + } + m.msgQueueLock.Unlock() + + // Notify of pending message + select { + case m.handoffCh <- struct{}{}: + default: + } + + default: + m.logger.Printf("[ERR] memberlist: msg type (%d) not supported %s", msgType, LogAddress(from)) + } +} + +// getNextMessage returns the next message to process in priority order, using LIFO +func (m *Memberlist) getNextMessage() (msgHandoff, bool) { + m.msgQueueLock.Lock() + defer m.msgQueueLock.Unlock() + + if el := m.highPriorityMsgQueue.Back(); el != nil { + m.highPriorityMsgQueue.Remove(el) + msg := el.Value.(msgHandoff) + return msg, true + } else if el := m.lowPriorityMsgQueue.Back(); el != nil { + m.lowPriorityMsgQueue.Remove(el) + msg := el.Value.(msgHandoff) + return msg, true + } + return msgHandoff{}, false +} + +// packetHandler is a long running goroutine that processes messages received +// over the packet interface, but is decoupled from the listener to avoid +// blocking the listener which may cause ping/ack messages to be delayed. +func (m *Memberlist) packetHandler() { + for { + select { + case <-m.handoffCh: + for { + msg, ok := m.getNextMessage() + if !ok { + break + } + msgType := msg.msgType + buf := msg.buf + from := msg.from + + switch msgType { + case suspectMsg: + m.handleSuspect(buf, from) + case aliveMsg: + m.handleAlive(buf, from) + case deadMsg: + m.handleDead(buf, from) + case userMsg: + m.handleUser(buf, from) + default: + m.logger.Printf("[ERR] memberlist: Message type (%d) not supported %s (packet handler)", msgType, LogAddress(from)) + } + } + + case <-m.shutdownCh: + return + } + } +} + +func (m *Memberlist) handleCompound(buf []byte, from net.Addr, timestamp time.Time) { + // Decode the parts + trunc, parts, err := decodeCompoundMessage(buf) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode compound request: %s %s", err, LogAddress(from)) + return + } + + // Log any truncation + if trunc > 0 { + m.logger.Printf("[WARN] memberlist: Compound request had %d truncated messages %s", trunc, LogAddress(from)) + } + + // Handle each message + for _, part := range parts { + m.handleCommand(part, from, timestamp) + } +} + +func (m *Memberlist) handlePing(buf []byte, from net.Addr) { + var p ping + if err := decode(buf, &p); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode ping request: %s %s", err, LogAddress(from)) + return + } + // If node is provided, verify that it is for us + if p.Node != "" && p.Node != m.config.Name { + m.logger.Printf("[WARN] memberlist: Got ping for unexpected node '%s' %s", p.Node, LogAddress(from)) + return + } + var ack ackResp + ack.SeqNo = p.SeqNo + if m.config.Ping != nil { + ack.Payload = m.config.Ping.AckPayload() + } + if err := m.encodeAndSendMsg(from.String(), ackRespMsg, &ack); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send ack: %s %s", err, LogAddress(from)) + } +} + +func (m *Memberlist) handleIndirectPing(buf []byte, from net.Addr) { + var ind indirectPingReq + if err := decode(buf, &ind); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode indirect ping request: %s %s", err, LogAddress(from)) + return + } + + // For proto versions < 2, there is no port provided. Mask old + // behavior by using the configured port. + if m.ProtocolVersion() < 2 || ind.Port == 0 { + ind.Port = uint16(m.config.BindPort) + } + + // Send a ping to the correct host. + localSeqNo := m.nextSeqNo() + ping := ping{SeqNo: localSeqNo, Node: ind.Node} + + // Setup a response handler to relay the ack + cancelCh := make(chan struct{}) + respHandler := func(payload []byte, timestamp time.Time) { + // Try to prevent the nack if we've caught it in time. + close(cancelCh) + + // Forward the ack back to the requestor. + ack := ackResp{ind.SeqNo, nil} + if err := m.encodeAndSendMsg(from.String(), ackRespMsg, &ack); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to forward ack: %s %s", err, LogAddress(from)) + } + } + m.setAckHandler(localSeqNo, respHandler, m.config.ProbeTimeout) + + // Send the ping. + addr := joinHostPort(net.IP(ind.Target).String(), ind.Port) + if err := m.encodeAndSendMsg(addr, pingMsg, &ping); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send ping: %s %s", err, LogAddress(from)) + } + + // Setup a timer to fire off a nack if no ack is seen in time. + if ind.Nack { + go func() { + select { + case <-cancelCh: + return + case <-time.After(m.config.ProbeTimeout): + nack := nackResp{ind.SeqNo} + if err := m.encodeAndSendMsg(from.String(), nackRespMsg, &nack); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send nack: %s %s", err, LogAddress(from)) + } + } + }() + } +} + +func (m *Memberlist) handleAck(buf []byte, from net.Addr, timestamp time.Time) { + var ack ackResp + if err := decode(buf, &ack); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode ack response: %s %s", err, LogAddress(from)) + return + } + m.invokeAckHandler(ack, timestamp) +} + +func (m *Memberlist) handleNack(buf []byte, from net.Addr) { + var nack nackResp + if err := decode(buf, &nack); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode nack response: %s %s", err, LogAddress(from)) + return + } + m.invokeNackHandler(nack) +} + +func (m *Memberlist) handleSuspect(buf []byte, from net.Addr) { + var sus suspect + if err := decode(buf, &sus); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode suspect message: %s %s", err, LogAddress(from)) + return + } + m.suspectNode(&sus) +} + +func (m *Memberlist) handleAlive(buf []byte, from net.Addr) { + var live alive + if err := decode(buf, &live); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode alive message: %s %s", err, LogAddress(from)) + return + } + + // For proto versions < 2, there is no port provided. Mask old + // behavior by using the configured port + if m.ProtocolVersion() < 2 || live.Port == 0 { + live.Port = uint16(m.config.BindPort) + } + + m.aliveNode(&live, nil, false) +} + +func (m *Memberlist) handleDead(buf []byte, from net.Addr) { + var d dead + if err := decode(buf, &d); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decode dead message: %s %s", err, LogAddress(from)) + return + } + m.deadNode(&d) +} + +// handleUser is used to notify channels of incoming user data +func (m *Memberlist) handleUser(buf []byte, from net.Addr) { + d := m.config.Delegate + if d != nil { + d.NotifyMsg(buf) + } +} + +// handleCompressed is used to unpack a compressed message +func (m *Memberlist) handleCompressed(buf []byte, from net.Addr, timestamp time.Time) { + // Try to decode the payload + payload, err := decompressPayload(buf) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to decompress payload: %v %s", err, LogAddress(from)) + return + } + + // Recursively handle the payload + m.handleCommand(payload, from, timestamp) +} + +// encodeAndSendMsg is used to combine the encoding and sending steps +func (m *Memberlist) encodeAndSendMsg(addr string, msgType messageType, msg interface{}) error { + out, err := encode(msgType, msg) + if err != nil { + return err + } + if err := m.sendMsg(addr, out.Bytes()); err != nil { + return err + } + return nil +} + +// sendMsg is used to send a message via packet to another host. It will +// opportunistically create a compoundMsg and piggy back other broadcasts. +func (m *Memberlist) sendMsg(addr string, msg []byte) error { + // Check if we can piggy back any messages + bytesAvail := m.config.UDPBufferSize - len(msg) - compoundHeaderOverhead + if m.config.EncryptionEnabled() && m.config.GossipVerifyOutgoing { + bytesAvail -= encryptOverhead(m.encryptionVersion()) + } + extra := m.getBroadcasts(compoundOverhead, bytesAvail) + + // Fast path if nothing to piggypack + if len(extra) == 0 { + return m.rawSendMsgPacket(addr, nil, msg) + } + + // Join all the messages + msgs := make([][]byte, 0, 1+len(extra)) + msgs = append(msgs, msg) + msgs = append(msgs, extra...) + + // Create a compound message + compound := makeCompoundMessage(msgs) + + // Send the message + return m.rawSendMsgPacket(addr, nil, compound.Bytes()) +} + +// rawSendMsgPacket is used to send message via packet to another host without +// modification, other than compression or encryption if enabled. +func (m *Memberlist) rawSendMsgPacket(addr string, node *Node, msg []byte) error { + // Check if we have compression enabled + if m.config.EnableCompression { + buf, err := compressPayload(msg) + if err != nil { + m.logger.Printf("[WARN] memberlist: Failed to compress payload: %v", err) + } else { + // Only use compression if it reduced the size + if buf.Len() < len(msg) { + msg = buf.Bytes() + } + } + } + + // Try to look up the destination node + if node == nil { + toAddr, _, err := net.SplitHostPort(addr) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed to parse address %q: %v", addr, err) + return err + } + m.nodeLock.RLock() + nodeState, ok := m.nodeMap[toAddr] + m.nodeLock.RUnlock() + if ok { + node = &nodeState.Node + } + } + + // Add a CRC to the end of the payload if the recipient understands + // ProtocolVersion >= 5 + if node != nil && node.PMax >= 5 { + crc := crc32.ChecksumIEEE(msg) + header := make([]byte, 5, 5+len(msg)) + header[0] = byte(hasCrcMsg) + binary.BigEndian.PutUint32(header[1:], crc) + msg = append(header, msg...) + } + + // Check if we have encryption enabled + if m.config.EncryptionEnabled() && m.config.GossipVerifyOutgoing { + // Encrypt the payload + var buf bytes.Buffer + primaryKey := m.config.Keyring.GetPrimaryKey() + err := encryptPayload(m.encryptionVersion(), primaryKey, msg, nil, &buf) + if err != nil { + m.logger.Printf("[ERR] memberlist: Encryption of message failed: %v", err) + return err + } + msg = buf.Bytes() + } + + metrics.IncrCounter([]string{"memberlist", "udp", "sent"}, float32(len(msg))) + _, err := m.transport.WriteTo(msg, addr) + return err +} + +// rawSendMsgStream is used to stream a message to another host without +// modification, other than applying compression and encryption if enabled. +func (m *Memberlist) rawSendMsgStream(conn net.Conn, sendBuf []byte) error { + // Check if compresion is enabled + if m.config.EnableCompression { + compBuf, err := compressPayload(sendBuf) + if err != nil { + m.logger.Printf("[ERROR] memberlist: Failed to compress payload: %v", err) + } else { + sendBuf = compBuf.Bytes() + } + } + + // Check if encryption is enabled + if m.config.EncryptionEnabled() && m.config.GossipVerifyOutgoing { + crypt, err := m.encryptLocalState(sendBuf) + if err != nil { + m.logger.Printf("[ERROR] memberlist: Failed to encrypt local state: %v", err) + return err + } + sendBuf = crypt + } + + // Write out the entire send buffer + metrics.IncrCounter([]string{"memberlist", "tcp", "sent"}, float32(len(sendBuf))) + + if n, err := conn.Write(sendBuf); err != nil { + return err + } else if n != len(sendBuf) { + return fmt.Errorf("only %d of %d bytes written", n, len(sendBuf)) + } + + return nil +} + +// sendUserMsg is used to stream a user message to another host. +func (m *Memberlist) sendUserMsg(addr string, sendBuf []byte) error { + conn, err := m.transport.DialTimeout(addr, m.config.TCPTimeout) + if err != nil { + return err + } + defer conn.Close() + + bufConn := bytes.NewBuffer(nil) + if err := bufConn.WriteByte(byte(userMsg)); err != nil { + return err + } + + header := userMsgHeader{UserMsgLen: len(sendBuf)} + hd := codec.MsgpackHandle{} + enc := codec.NewEncoder(bufConn, &hd) + if err := enc.Encode(&header); err != nil { + return err + } + if _, err := bufConn.Write(sendBuf); err != nil { + return err + } + return m.rawSendMsgStream(conn, bufConn.Bytes()) +} + +// sendAndReceiveState is used to initiate a push/pull over a stream with a +// remote host. +func (m *Memberlist) sendAndReceiveState(addr string, join bool) ([]pushNodeState, []byte, error) { + // Attempt to connect + conn, err := m.transport.DialTimeout(addr, m.config.TCPTimeout) + if err != nil { + return nil, nil, err + } + defer conn.Close() + m.logger.Printf("[DEBUG] memberlist: Initiating push/pull sync with: %s", conn.RemoteAddr()) + metrics.IncrCounter([]string{"memberlist", "tcp", "connect"}, 1) + + // Send our state + if err := m.sendLocalState(conn, join); err != nil { + return nil, nil, err + } + + conn.SetDeadline(time.Now().Add(m.config.TCPTimeout)) + msgType, bufConn, dec, err := m.readStream(conn) + if err != nil { + return nil, nil, err + } + + if msgType == errMsg { + var resp errResp + if err := dec.Decode(&resp); err != nil { + return nil, nil, err + } + return nil, nil, fmt.Errorf("remote error: %v", resp.Error) + } + + // Quit if not push/pull + if msgType != pushPullMsg { + err := fmt.Errorf("received invalid msgType (%d), expected pushPullMsg (%d) %s", msgType, pushPullMsg, LogConn(conn)) + return nil, nil, err + } + + // Read remote state + _, remoteNodes, userState, err := m.readRemoteState(bufConn, dec) + return remoteNodes, userState, err +} + +// sendLocalState is invoked to send our local state over a stream connection. +func (m *Memberlist) sendLocalState(conn net.Conn, join bool) error { + // Setup a deadline + conn.SetDeadline(time.Now().Add(m.config.TCPTimeout)) + + // Prepare the local node state + m.nodeLock.RLock() + localNodes := make([]pushNodeState, len(m.nodes)) + for idx, n := range m.nodes { + localNodes[idx].Name = n.Name + localNodes[idx].Addr = n.Addr + localNodes[idx].Port = n.Port + localNodes[idx].Incarnation = n.Incarnation + localNodes[idx].State = n.State + localNodes[idx].Meta = n.Meta + localNodes[idx].Vsn = []uint8{ + n.PMin, n.PMax, n.PCur, + n.DMin, n.DMax, n.DCur, + } + } + m.nodeLock.RUnlock() + + // Get the delegate state + var userData []byte + if m.config.Delegate != nil { + userData = m.config.Delegate.LocalState(join) + } + + // Create a bytes buffer writer + bufConn := bytes.NewBuffer(nil) + + // Send our node state + header := pushPullHeader{Nodes: len(localNodes), UserStateLen: len(userData), Join: join} + hd := codec.MsgpackHandle{} + enc := codec.NewEncoder(bufConn, &hd) + + // Begin state push + if _, err := bufConn.Write([]byte{byte(pushPullMsg)}); err != nil { + return err + } + + if err := enc.Encode(&header); err != nil { + return err + } + for i := 0; i < header.Nodes; i++ { + if err := enc.Encode(&localNodes[i]); err != nil { + return err + } + } + + // Write the user state as well + if userData != nil { + if _, err := bufConn.Write(userData); err != nil { + return err + } + } + + // Get the send buffer + return m.rawSendMsgStream(conn, bufConn.Bytes()) +} + +// encryptLocalState is used to help encrypt local state before sending +func (m *Memberlist) encryptLocalState(sendBuf []byte) ([]byte, error) { + var buf bytes.Buffer + + // Write the encryptMsg byte + buf.WriteByte(byte(encryptMsg)) + + // Write the size of the message + sizeBuf := make([]byte, 4) + encVsn := m.encryptionVersion() + encLen := encryptedLength(encVsn, len(sendBuf)) + binary.BigEndian.PutUint32(sizeBuf, uint32(encLen)) + buf.Write(sizeBuf) + + // Write the encrypted cipher text to the buffer + key := m.config.Keyring.GetPrimaryKey() + err := encryptPayload(encVsn, key, sendBuf, buf.Bytes()[:5], &buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// decryptRemoteState is used to help decrypt the remote state +func (m *Memberlist) decryptRemoteState(bufConn io.Reader) ([]byte, error) { + // Read in enough to determine message length + cipherText := bytes.NewBuffer(nil) + cipherText.WriteByte(byte(encryptMsg)) + _, err := io.CopyN(cipherText, bufConn, 4) + if err != nil { + return nil, err + } + + // Ensure we aren't asked to download too much. This is to guard against + // an attack vector where a huge amount of state is sent + moreBytes := binary.BigEndian.Uint32(cipherText.Bytes()[1:5]) + if moreBytes > maxPushStateBytes { + return nil, fmt.Errorf("Remote node state is larger than limit (%d)", moreBytes) + } + + // Read in the rest of the payload + _, err = io.CopyN(cipherText, bufConn, int64(moreBytes)) + if err != nil { + return nil, err + } + + // Decrypt the cipherText + dataBytes := cipherText.Bytes()[:5] + cipherBytes := cipherText.Bytes()[5:] + + // Decrypt the payload + keys := m.config.Keyring.GetKeys() + return decryptPayload(keys, cipherBytes, dataBytes) +} + +// readStream is used to read from a stream connection, decrypting and +// decompressing the stream if necessary. +func (m *Memberlist) readStream(conn net.Conn) (messageType, io.Reader, *codec.Decoder, error) { + // Created a buffered reader + var bufConn io.Reader = bufio.NewReader(conn) + + // Read the message type + buf := [1]byte{0} + if _, err := bufConn.Read(buf[:]); err != nil { + return 0, nil, nil, err + } + msgType := messageType(buf[0]) + + // Check if the message is encrypted + if msgType == encryptMsg { + if !m.config.EncryptionEnabled() { + return 0, nil, nil, + fmt.Errorf("Remote state is encrypted and encryption is not configured") + } + + plain, err := m.decryptRemoteState(bufConn) + if err != nil { + return 0, nil, nil, err + } + + // Reset message type and bufConn + msgType = messageType(plain[0]) + bufConn = bytes.NewReader(plain[1:]) + } else if m.config.EncryptionEnabled() && m.config.GossipVerifyIncoming { + return 0, nil, nil, + fmt.Errorf("Encryption is configured but remote state is not encrypted") + } + + // Get the msgPack decoders + hd := codec.MsgpackHandle{} + dec := codec.NewDecoder(bufConn, &hd) + + // Check if we have a compressed message + if msgType == compressMsg { + var c compress + if err := dec.Decode(&c); err != nil { + return 0, nil, nil, err + } + decomp, err := decompressBuffer(&c) + if err != nil { + return 0, nil, nil, err + } + + // Reset the message type + msgType = messageType(decomp[0]) + + // Create a new bufConn + bufConn = bytes.NewReader(decomp[1:]) + + // Create a new decoder + dec = codec.NewDecoder(bufConn, &hd) + } + + return msgType, bufConn, dec, nil +} + +// readRemoteState is used to read the remote state from a connection +func (m *Memberlist) readRemoteState(bufConn io.Reader, dec *codec.Decoder) (bool, []pushNodeState, []byte, error) { + // Read the push/pull header + var header pushPullHeader + if err := dec.Decode(&header); err != nil { + return false, nil, nil, err + } + + // Allocate space for the transfer + remoteNodes := make([]pushNodeState, header.Nodes) + + // Try to decode all the states + for i := 0; i < header.Nodes; i++ { + if err := dec.Decode(&remoteNodes[i]); err != nil { + return false, nil, nil, err + } + } + + // Read the remote user state into a buffer + var userBuf []byte + if header.UserStateLen > 0 { + userBuf = make([]byte, header.UserStateLen) + bytes, err := io.ReadAtLeast(bufConn, userBuf, header.UserStateLen) + if err == nil && bytes != header.UserStateLen { + err = fmt.Errorf( + "Failed to read full user state (%d / %d)", + bytes, header.UserStateLen) + } + if err != nil { + return false, nil, nil, err + } + } + + // For proto versions < 2, there is no port provided. Mask old + // behavior by using the configured port + for idx := range remoteNodes { + if m.ProtocolVersion() < 2 || remoteNodes[idx].Port == 0 { + remoteNodes[idx].Port = uint16(m.config.BindPort) + } + } + + return header.Join, remoteNodes, userBuf, nil +} + +// mergeRemoteState is used to merge the remote state with our local state +func (m *Memberlist) mergeRemoteState(join bool, remoteNodes []pushNodeState, userBuf []byte) error { + if err := m.verifyProtocol(remoteNodes); err != nil { + return err + } + + // Invoke the merge delegate if any + if join && m.config.Merge != nil { + nodes := make([]*Node, len(remoteNodes)) + for idx, n := range remoteNodes { + nodes[idx] = &Node{ + Name: n.Name, + Addr: n.Addr, + Port: n.Port, + Meta: n.Meta, + PMin: n.Vsn[0], + PMax: n.Vsn[1], + PCur: n.Vsn[2], + DMin: n.Vsn[3], + DMax: n.Vsn[4], + DCur: n.Vsn[5], + } + } + if err := m.config.Merge.NotifyMerge(nodes); err != nil { + return err + } + } + + // Merge the membership state + m.mergeState(remoteNodes) + + // Invoke the delegate for user state + if userBuf != nil && m.config.Delegate != nil { + m.config.Delegate.MergeRemoteState(userBuf, join) + } + return nil +} + +// readUserMsg is used to decode a userMsg from a stream. +func (m *Memberlist) readUserMsg(bufConn io.Reader, dec *codec.Decoder) error { + // Read the user message header + var header userMsgHeader + if err := dec.Decode(&header); err != nil { + return err + } + + // Read the user message into a buffer + var userBuf []byte + if header.UserMsgLen > 0 { + userBuf = make([]byte, header.UserMsgLen) + bytes, err := io.ReadAtLeast(bufConn, userBuf, header.UserMsgLen) + if err == nil && bytes != header.UserMsgLen { + err = fmt.Errorf( + "Failed to read full user message (%d / %d)", + bytes, header.UserMsgLen) + } + if err != nil { + return err + } + + d := m.config.Delegate + if d != nil { + d.NotifyMsg(userBuf) + } + } + + return nil +} + +// sendPingAndWaitForAck makes a stream connection to the given address, sends +// a ping, and waits for an ack. All of this is done as a series of blocking +// operations, given the deadline. The bool return parameter is true if we +// we able to round trip a ping to the other node. +func (m *Memberlist) sendPingAndWaitForAck(addr string, ping ping, deadline time.Time) (bool, error) { + conn, err := m.transport.DialTimeout(addr, deadline.Sub(time.Now())) + if err != nil { + // If the node is actually dead we expect this to fail, so we + // shouldn't spam the logs with it. After this point, errors + // with the connection are real, unexpected errors and should + // get propagated up. + return false, nil + } + defer conn.Close() + conn.SetDeadline(deadline) + + out, err := encode(pingMsg, &ping) + if err != nil { + return false, err + } + + if err = m.rawSendMsgStream(conn, out.Bytes()); err != nil { + return false, err + } + + msgType, _, dec, err := m.readStream(conn) + if err != nil { + return false, err + } + + if msgType != ackRespMsg { + return false, fmt.Errorf("Unexpected msgType (%d) from ping %s", msgType, LogConn(conn)) + } + + var ack ackResp + if err = dec.Decode(&ack); err != nil { + return false, err + } + + if ack.SeqNo != ping.SeqNo { + return false, fmt.Errorf("Sequence number from ack (%d) doesn't match ping (%d)", ack.SeqNo, ping.SeqNo) + } + + return true, nil +} diff --git a/vendor/github.com/hashicorp/memberlist/net_transport.go b/vendor/github.com/hashicorp/memberlist/net_transport.go new file mode 100644 index 00000000000..4723127f54f --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/net_transport.go @@ -0,0 +1,312 @@ +package memberlist + +import ( + "fmt" + "log" + "net" + "sync" + "sync/atomic" + "time" + + "github.com/armon/go-metrics" + sockaddr "github.com/hashicorp/go-sockaddr" +) + +const ( + // udpPacketBufSize is used to buffer incoming packets during read + // operations. + udpPacketBufSize = 65536 + + // udpRecvBufSize is a large buffer size that we attempt to set UDP + // sockets to in order to handle a large volume of messages. + udpRecvBufSize = 2 * 1024 * 1024 +) + +// NetTransportConfig is used to configure a net transport. +type NetTransportConfig struct { + // BindAddrs is a list of addresses to bind to for both TCP and UDP + // communications. + BindAddrs []string + + // BindPort is the port to listen on, for each address above. + BindPort int + + // Logger is a logger for operator messages. + Logger *log.Logger +} + +// NetTransport is a Transport implementation that uses connectionless UDP for +// packet operations, and ad-hoc TCP connections for stream operations. +type NetTransport struct { + config *NetTransportConfig + packetCh chan *Packet + streamCh chan net.Conn + logger *log.Logger + wg sync.WaitGroup + tcpListeners []*net.TCPListener + udpListeners []*net.UDPConn + shutdown int32 +} + +// NewNetTransport returns a net transport with the given configuration. On +// success all the network listeners will be created and listening. +func NewNetTransport(config *NetTransportConfig) (*NetTransport, error) { + // If we reject the empty list outright we can assume that there's at + // least one listener of each type later during operation. + if len(config.BindAddrs) == 0 { + return nil, fmt.Errorf("At least one bind address is required") + } + + // Build out the new transport. + var ok bool + t := NetTransport{ + config: config, + packetCh: make(chan *Packet), + streamCh: make(chan net.Conn), + logger: config.Logger, + } + + // Clean up listeners if there's an error. + defer func() { + if !ok { + t.Shutdown() + } + }() + + // Build all the TCP and UDP listeners. + port := config.BindPort + for _, addr := range config.BindAddrs { + ip := net.ParseIP(addr) + + tcpAddr := &net.TCPAddr{IP: ip, Port: port} + tcpLn, err := net.ListenTCP("tcp", tcpAddr) + if err != nil { + return nil, fmt.Errorf("Failed to start TCP listener on %q port %d: %v", addr, port, err) + } + t.tcpListeners = append(t.tcpListeners, tcpLn) + + // If the config port given was zero, use the first TCP listener + // to pick an available port and then apply that to everything + // else. + if port == 0 { + port = tcpLn.Addr().(*net.TCPAddr).Port + } + + udpAddr := &net.UDPAddr{IP: ip, Port: port} + udpLn, err := net.ListenUDP("udp", udpAddr) + if err != nil { + return nil, fmt.Errorf("Failed to start UDP listener on %q port %d: %v", addr, port, err) + } + if err := setUDPRecvBuf(udpLn); err != nil { + return nil, fmt.Errorf("Failed to resize UDP buffer: %v", err) + } + t.udpListeners = append(t.udpListeners, udpLn) + } + + // Fire them up now that we've been able to create them all. + for i := 0; i < len(config.BindAddrs); i++ { + t.wg.Add(2) + go t.tcpListen(t.tcpListeners[i]) + go t.udpListen(t.udpListeners[i]) + } + + ok = true + return &t, nil +} + +// GetAutoBindPort returns the bind port that was automatically given by the +// kernel, if a bind port of 0 was given. +func (t *NetTransport) GetAutoBindPort() int { + // We made sure there's at least one TCP listener, and that one's + // port was applied to all the others for the dynamic bind case. + return t.tcpListeners[0].Addr().(*net.TCPAddr).Port +} + +// See Transport. +func (t *NetTransport) FinalAdvertiseAddr(ip string, port int) (net.IP, int, error) { + var advertiseAddr net.IP + var advertisePort int + if ip != "" { + // If they've supplied an address, use that. + advertiseAddr = net.ParseIP(ip) + if advertiseAddr == nil { + return nil, 0, fmt.Errorf("Failed to parse advertise address %q", ip) + } + + // Ensure IPv4 conversion if necessary. + if ip4 := advertiseAddr.To4(); ip4 != nil { + advertiseAddr = ip4 + } + advertisePort = port + } else { + if t.config.BindAddrs[0] == "0.0.0.0" { + // Otherwise, if we're not bound to a specific IP, let's + // use a suitable private IP address. + var err error + ip, err = sockaddr.GetPrivateIP() + if err != nil { + return nil, 0, fmt.Errorf("Failed to get interface addresses: %v", err) + } + if ip == "" { + return nil, 0, fmt.Errorf("No private IP address found, and explicit IP not provided") + } + + advertiseAddr = net.ParseIP(ip) + if advertiseAddr == nil { + return nil, 0, fmt.Errorf("Failed to parse advertise address: %q", ip) + } + } else { + // Use the IP that we're bound to, based on the first + // TCP listener, which we already ensure is there. + advertiseAddr = t.tcpListeners[0].Addr().(*net.TCPAddr).IP + } + + // Use the port we are bound to. + advertisePort = t.GetAutoBindPort() + } + + return advertiseAddr, advertisePort, nil +} + +// See Transport. +func (t *NetTransport) WriteTo(b []byte, addr string) (time.Time, error) { + udpAddr, err := net.ResolveUDPAddr("udp", addr) + if err != nil { + return time.Time{}, err + } + + // We made sure there's at least one UDP listener, so just use the + // packet sending interface on the first one. Take the time after the + // write call comes back, which will underestimate the time a little, + // but help account for any delays before the write occurs. + _, err = t.udpListeners[0].WriteTo(b, udpAddr) + return time.Now(), err +} + +// See Transport. +func (t *NetTransport) PacketCh() <-chan *Packet { + return t.packetCh +} + +// See Transport. +func (t *NetTransport) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) { + dialer := net.Dialer{Timeout: timeout} + return dialer.Dial("tcp", addr) +} + +// See Transport. +func (t *NetTransport) StreamCh() <-chan net.Conn { + return t.streamCh +} + +// See Transport. +func (t *NetTransport) Shutdown() error { + // This will avoid log spam about errors when we shut down. + atomic.StoreInt32(&t.shutdown, 1) + + // Rip through all the connections and shut them down. + for _, conn := range t.tcpListeners { + conn.Close() + } + for _, conn := range t.udpListeners { + conn.Close() + } + + // Block until all the listener threads have died. + t.wg.Wait() + return nil +} + +// tcpListen is a long running goroutine that accepts incoming TCP connections +// and hands them off to the stream channel. +func (t *NetTransport) tcpListen(tcpLn *net.TCPListener) { + defer t.wg.Done() + + // baseDelay is the initial delay after an AcceptTCP() error before attempting again + const baseDelay = 5 * time.Millisecond + + // maxDelay is the maximum delay after an AcceptTCP() error before attempting again. + // In the case that tcpListen() is error-looping, it will delay the shutdown check. + // Therefore, changes to maxDelay may have an effect on the latency of shutdown. + const maxDelay = 1 * time.Second + + var loopDelay time.Duration + for { + conn, err := tcpLn.AcceptTCP() + if err != nil { + if s := atomic.LoadInt32(&t.shutdown); s == 1 { + break + } + + if loopDelay == 0 { + loopDelay = baseDelay + } else { + loopDelay *= 2 + } + + if loopDelay > maxDelay { + loopDelay = maxDelay + } + + t.logger.Printf("[ERR] memberlist: Error accepting TCP connection: %v", err) + time.Sleep(loopDelay) + continue + } + // No error, reset loop delay + loopDelay = 0 + + t.streamCh <- conn + } +} + +// udpListen is a long running goroutine that accepts incoming UDP packets and +// hands them off to the packet channel. +func (t *NetTransport) udpListen(udpLn *net.UDPConn) { + defer t.wg.Done() + for { + // Do a blocking read into a fresh buffer. Grab a time stamp as + // close as possible to the I/O. + buf := make([]byte, udpPacketBufSize) + n, addr, err := udpLn.ReadFrom(buf) + ts := time.Now() + if err != nil { + if s := atomic.LoadInt32(&t.shutdown); s == 1 { + break + } + + t.logger.Printf("[ERR] memberlist: Error reading UDP packet: %v", err) + continue + } + + // Check the length - it needs to have at least one byte to be a + // proper message. + if n < 1 { + t.logger.Printf("[ERR] memberlist: UDP packet too short (%d bytes) %s", + len(buf), LogAddress(addr)) + continue + } + + // Ingest the packet. + metrics.IncrCounter([]string{"memberlist", "udp", "received"}, float32(n)) + t.packetCh <- &Packet{ + Buf: buf[:n], + From: addr, + Timestamp: ts, + } + } +} + +// setUDPRecvBuf is used to resize the UDP receive window. The function +// attempts to set the read buffer to `udpRecvBuf` but backs off until +// the read buffer can be set. +func setUDPRecvBuf(c *net.UDPConn) error { + size := udpRecvBufSize + var err error + for size > 0 { + if err = c.SetReadBuffer(size); err == nil { + return nil + } + size = size / 2 + } + return err +} diff --git a/vendor/github.com/hashicorp/memberlist/ping_delegate.go b/vendor/github.com/hashicorp/memberlist/ping_delegate.go new file mode 100644 index 00000000000..1566c8b3d50 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/ping_delegate.go @@ -0,0 +1,14 @@ +package memberlist + +import "time" + +// PingDelegate is used to notify an observer how long it took for a ping message to +// complete a round trip. It can also be used for writing arbitrary byte slices +// into ack messages. Note that in order to be meaningful for RTT estimates, this +// delegate does not apply to indirect pings, nor fallback pings sent over TCP. +type PingDelegate interface { + // AckPayload is invoked when an ack is being sent; the returned bytes will be appended to the ack + AckPayload() []byte + // NotifyPing is invoked when an ack for a ping is received + NotifyPingComplete(other *Node, rtt time.Duration, payload []byte) +} diff --git a/vendor/github.com/hashicorp/memberlist/queue.go b/vendor/github.com/hashicorp/memberlist/queue.go new file mode 100644 index 00000000000..c970176e18f --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/queue.go @@ -0,0 +1,422 @@ +package memberlist + +import ( + "math" + "sync" + + "github.com/google/btree" +) + +// TransmitLimitedQueue is used to queue messages to broadcast to +// the cluster (via gossip) but limits the number of transmits per +// message. It also prioritizes messages with lower transmit counts +// (hence newer messages). +type TransmitLimitedQueue struct { + // NumNodes returns the number of nodes in the cluster. This is + // used to determine the retransmit count, which is calculated + // based on the log of this. + NumNodes func() int + + // RetransmitMult is the multiplier used to determine the maximum + // number of retransmissions attempted. + RetransmitMult int + + mu sync.Mutex + tq *btree.BTree // stores *limitedBroadcast as btree.Item + tm map[string]*limitedBroadcast + idGen int64 +} + +type limitedBroadcast struct { + transmits int // btree-key[0]: Number of transmissions attempted. + msgLen int64 // btree-key[1]: copied from len(b.Message()) + id int64 // btree-key[2]: unique incrementing id stamped at submission time + b Broadcast + + name string // set if Broadcast is a NamedBroadcast +} + +// Less tests whether the current item is less than the given argument. +// +// This must provide a strict weak ordering. +// If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only +// hold one of either a or b in the tree). +// +// default ordering is +// - [transmits=0, ..., transmits=inf] +// - [transmits=0:len=999, ..., transmits=0:len=2, ...] +// - [transmits=0:len=999,id=999, ..., transmits=0:len=999:id=1, ...] +func (b *limitedBroadcast) Less(than btree.Item) bool { + o := than.(*limitedBroadcast) + if b.transmits < o.transmits { + return true + } else if b.transmits > o.transmits { + return false + } + if b.msgLen > o.msgLen { + return true + } else if b.msgLen < o.msgLen { + return false + } + return b.id > o.id +} + +// for testing; emits in transmit order if reverse=false +func (q *TransmitLimitedQueue) orderedView(reverse bool) []*limitedBroadcast { + q.mu.Lock() + defer q.mu.Unlock() + + out := make([]*limitedBroadcast, 0, q.lenLocked()) + q.walkReadOnlyLocked(reverse, func(cur *limitedBroadcast) bool { + out = append(out, cur) + return true + }) + + return out +} + +// walkReadOnlyLocked calls f for each item in the queue traversing it in +// natural order (by Less) when reverse=false and the opposite when true. You +// must hold the mutex. +// +// This method panics if you attempt to mutate the item during traversal. The +// underlying btree should also not be mutated during traversal. +func (q *TransmitLimitedQueue) walkReadOnlyLocked(reverse bool, f func(*limitedBroadcast) bool) { + if q.lenLocked() == 0 { + return + } + + iter := func(item btree.Item) bool { + cur := item.(*limitedBroadcast) + + prevTransmits := cur.transmits + prevMsgLen := cur.msgLen + prevID := cur.id + + keepGoing := f(cur) + + if prevTransmits != cur.transmits || prevMsgLen != cur.msgLen || prevID != cur.id { + panic("edited queue while walking read only") + } + + return keepGoing + } + + if reverse { + q.tq.Descend(iter) // end with transmit 0 + } else { + q.tq.Ascend(iter) // start with transmit 0 + } +} + +// Broadcast is something that can be broadcasted via gossip to +// the memberlist cluster. +type Broadcast interface { + // Invalidates checks if enqueuing the current broadcast + // invalidates a previous broadcast + Invalidates(b Broadcast) bool + + // Returns a byte form of the message + Message() []byte + + // Finished is invoked when the message will no longer + // be broadcast, either due to invalidation or to the + // transmit limit being reached + Finished() +} + +// NamedBroadcast is an optional extension of the Broadcast interface that +// gives each message a unique string name, and that is used to optimize +// +// You shoud ensure that Invalidates() checks the same uniqueness as the +// example below: +// +// func (b *foo) Invalidates(other Broadcast) bool { +// nb, ok := other.(NamedBroadcast) +// if !ok { +// return false +// } +// return b.Name() == nb.Name() +// } +// +// Invalidates() isn't currently used for NamedBroadcasts, but that may change +// in the future. +type NamedBroadcast interface { + Broadcast + // The unique identity of this broadcast message. + Name() string +} + +// UniqueBroadcast is an optional interface that indicates that each message is +// intrinsically unique and there is no need to scan the broadcast queue for +// duplicates. +// +// You should ensure that Invalidates() always returns false if implementing +// this interface. Invalidates() isn't currently used for UniqueBroadcasts, but +// that may change in the future. +type UniqueBroadcast interface { + Broadcast + // UniqueBroadcast is just a marker method for this interface. + UniqueBroadcast() +} + +// QueueBroadcast is used to enqueue a broadcast +func (q *TransmitLimitedQueue) QueueBroadcast(b Broadcast) { + q.queueBroadcast(b, 0) +} + +// lazyInit initializes internal data structures the first time they are +// needed. You must already hold the mutex. +func (q *TransmitLimitedQueue) lazyInit() { + if q.tq == nil { + q.tq = btree.New(32) + } + if q.tm == nil { + q.tm = make(map[string]*limitedBroadcast) + } +} + +// queueBroadcast is like QueueBroadcast but you can use a nonzero value for +// the initial transmit tier assigned to the message. This is meant to be used +// for unit testing. +func (q *TransmitLimitedQueue) queueBroadcast(b Broadcast, initialTransmits int) { + q.mu.Lock() + defer q.mu.Unlock() + + q.lazyInit() + + if q.idGen == math.MaxInt64 { + // it's super duper unlikely to wrap around within the retransmit limit + q.idGen = 1 + } else { + q.idGen++ + } + id := q.idGen + + lb := &limitedBroadcast{ + transmits: initialTransmits, + msgLen: int64(len(b.Message())), + id: id, + b: b, + } + unique := false + if nb, ok := b.(NamedBroadcast); ok { + lb.name = nb.Name() + } else if _, ok := b.(UniqueBroadcast); ok { + unique = true + } + + // Check if this message invalidates another. + if lb.name != "" { + if old, ok := q.tm[lb.name]; ok { + old.b.Finished() + q.deleteItem(old) + } + } else if !unique { + // Slow path, hopefully nothing hot hits this. + var remove []*limitedBroadcast + q.tq.Ascend(func(item btree.Item) bool { + cur := item.(*limitedBroadcast) + + // Special Broadcasts can only invalidate each other. + switch cur.b.(type) { + case NamedBroadcast: + // noop + case UniqueBroadcast: + // noop + default: + if b.Invalidates(cur.b) { + cur.b.Finished() + remove = append(remove, cur) + } + } + return true + }) + for _, cur := range remove { + q.deleteItem(cur) + } + } + + // Append to the relevant queue. + q.addItem(lb) +} + +// deleteItem removes the given item from the overall datastructure. You +// must already hold the mutex. +func (q *TransmitLimitedQueue) deleteItem(cur *limitedBroadcast) { + _ = q.tq.Delete(cur) + if cur.name != "" { + delete(q.tm, cur.name) + } + + if q.tq.Len() == 0 { + // At idle there's no reason to let the id generator keep going + // indefinitely. + q.idGen = 0 + } +} + +// addItem adds the given item into the overall datastructure. You must already +// hold the mutex. +func (q *TransmitLimitedQueue) addItem(cur *limitedBroadcast) { + _ = q.tq.ReplaceOrInsert(cur) + if cur.name != "" { + q.tm[cur.name] = cur + } +} + +// getTransmitRange returns a pair of min/max values for transmit values +// represented by the current queue contents. Both values represent actual +// transmit values on the interval [0, len). You must already hold the mutex. +func (q *TransmitLimitedQueue) getTransmitRange() (minTransmit, maxTransmit int) { + if q.lenLocked() == 0 { + return 0, 0 + } + minItem, maxItem := q.tq.Min(), q.tq.Max() + if minItem == nil || maxItem == nil { + return 0, 0 + } + + min := minItem.(*limitedBroadcast).transmits + max := maxItem.(*limitedBroadcast).transmits + + return min, max +} + +// GetBroadcasts is used to get a number of broadcasts, up to a byte limit +// and applying a per-message overhead as provided. +func (q *TransmitLimitedQueue) GetBroadcasts(overhead, limit int) [][]byte { + q.mu.Lock() + defer q.mu.Unlock() + + // Fast path the default case + if q.lenLocked() == 0 { + return nil + } + + transmitLimit := retransmitLimit(q.RetransmitMult, q.NumNodes()) + + var ( + bytesUsed int + toSend [][]byte + reinsert []*limitedBroadcast + ) + + // Visit fresher items first, but only look at stuff that will fit. + // We'll go tier by tier, grabbing the largest items first. + minTr, maxTr := q.getTransmitRange() + for transmits := minTr; transmits <= maxTr; /*do not advance automatically*/ { + free := int64(limit - bytesUsed - overhead) + if free <= 0 { + break // bail out early + } + + // Search for the least element on a given tier (by transmit count) as + // defined in the limitedBroadcast.Less function that will fit into our + // remaining space. + greaterOrEqual := &limitedBroadcast{ + transmits: transmits, + msgLen: free, + id: math.MaxInt64, + } + lessThan := &limitedBroadcast{ + transmits: transmits + 1, + msgLen: math.MaxInt64, + id: math.MaxInt64, + } + var keep *limitedBroadcast + q.tq.AscendRange(greaterOrEqual, lessThan, func(item btree.Item) bool { + cur := item.(*limitedBroadcast) + // Check if this is within our limits + if int64(len(cur.b.Message())) > free { + // If this happens it's a bug in the datastructure or + // surrounding use doing something like having len(Message()) + // change over time. There's enough going on here that it's + // probably sane to just skip it and move on for now. + return true + } + keep = cur + return false + }) + if keep == nil { + // No more items of an appropriate size in the tier. + transmits++ + continue + } + + msg := keep.b.Message() + + // Add to slice to send + bytesUsed += overhead + len(msg) + toSend = append(toSend, msg) + + // Check if we should stop transmission + q.deleteItem(keep) + if keep.transmits+1 >= transmitLimit { + keep.b.Finished() + } else { + // We need to bump this item down to another transmit tier, but + // because it would be in the same direction that we're walking the + // tiers, we will have to delay the reinsertion until we are + // finished our search. Otherwise we'll possibly re-add the message + // when we ascend to the next tier. + keep.transmits++ + reinsert = append(reinsert, keep) + } + } + + for _, cur := range reinsert { + q.addItem(cur) + } + + return toSend +} + +// NumQueued returns the number of queued messages +func (q *TransmitLimitedQueue) NumQueued() int { + q.mu.Lock() + defer q.mu.Unlock() + return q.lenLocked() +} + +// lenLocked returns the length of the overall queue datastructure. You must +// hold the mutex. +func (q *TransmitLimitedQueue) lenLocked() int { + if q.tq == nil { + return 0 + } + return q.tq.Len() +} + +// Reset clears all the queued messages. Should only be used for tests. +func (q *TransmitLimitedQueue) Reset() { + q.mu.Lock() + defer q.mu.Unlock() + + q.walkReadOnlyLocked(false, func(cur *limitedBroadcast) bool { + cur.b.Finished() + return true + }) + + q.tq = nil + q.tm = nil + q.idGen = 0 +} + +// Prune will retain the maxRetain latest messages, and the rest +// will be discarded. This can be used to prevent unbounded queue sizes +func (q *TransmitLimitedQueue) Prune(maxRetain int) { + q.mu.Lock() + defer q.mu.Unlock() + + // Do nothing if queue size is less than the limit + for q.tq.Len() > maxRetain { + item := q.tq.Max() + if item == nil { + break + } + cur := item.(*limitedBroadcast) + cur.b.Finished() + q.deleteItem(cur) + } +} diff --git a/vendor/github.com/hashicorp/memberlist/security.go b/vendor/github.com/hashicorp/memberlist/security.go new file mode 100644 index 00000000000..d90114eb0c4 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/security.go @@ -0,0 +1,198 @@ +package memberlist + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "fmt" + "io" +) + +/* + +Encrypted messages are prefixed with an encryptionVersion byte +that is used for us to be able to properly encode/decode. We +currently support the following versions: + + 0 - AES-GCM 128, using PKCS7 padding + 1 - AES-GCM 128, no padding. Padding not needed, caused bloat. + +*/ +type encryptionVersion uint8 + +const ( + minEncryptionVersion encryptionVersion = 0 + maxEncryptionVersion encryptionVersion = 1 +) + +const ( + versionSize = 1 + nonceSize = 12 + tagSize = 16 + maxPadOverhead = 16 + blockSize = aes.BlockSize +) + +// pkcs7encode is used to pad a byte buffer to a specific block size using +// the PKCS7 algorithm. "Ignores" some bytes to compensate for IV +func pkcs7encode(buf *bytes.Buffer, ignore, blockSize int) { + n := buf.Len() - ignore + more := blockSize - (n % blockSize) + for i := 0; i < more; i++ { + buf.WriteByte(byte(more)) + } +} + +// pkcs7decode is used to decode a buffer that has been padded +func pkcs7decode(buf []byte, blockSize int) []byte { + if len(buf) == 0 { + panic("Cannot decode a PKCS7 buffer of zero length") + } + n := len(buf) + last := buf[n-1] + n -= int(last) + return buf[:n] +} + +// encryptOverhead returns the maximum possible overhead of encryption by version +func encryptOverhead(vsn encryptionVersion) int { + switch vsn { + case 0: + return 45 // Version: 1, IV: 12, Padding: 16, Tag: 16 + case 1: + return 29 // Version: 1, IV: 12, Tag: 16 + default: + panic("unsupported version") + } +} + +// encryptedLength is used to compute the buffer size needed +// for a message of given length +func encryptedLength(vsn encryptionVersion, inp int) int { + // If we are on version 1, there is no padding + if vsn >= 1 { + return versionSize + nonceSize + inp + tagSize + } + + // Determine the padding size + padding := blockSize - (inp % blockSize) + + // Sum the extra parts to get total size + return versionSize + nonceSize + inp + padding + tagSize +} + +// encryptPayload is used to encrypt a message with a given key. +// We make use of AES-128 in GCM mode. New byte buffer is the version, +// nonce, ciphertext and tag +func encryptPayload(vsn encryptionVersion, key []byte, msg []byte, data []byte, dst *bytes.Buffer) error { + // Get the AES block cipher + aesBlock, err := aes.NewCipher(key) + if err != nil { + return err + } + + // Get the GCM cipher mode + gcm, err := cipher.NewGCM(aesBlock) + if err != nil { + return err + } + + // Grow the buffer to make room for everything + offset := dst.Len() + dst.Grow(encryptedLength(vsn, len(msg))) + + // Write the encryption version + dst.WriteByte(byte(vsn)) + + // Add a random nonce + io.CopyN(dst, rand.Reader, nonceSize) + afterNonce := dst.Len() + + // Ensure we are correctly padded (only version 0) + if vsn == 0 { + io.Copy(dst, bytes.NewReader(msg)) + pkcs7encode(dst, offset+versionSize+nonceSize, aes.BlockSize) + } + + // Encrypt message using GCM + slice := dst.Bytes()[offset:] + nonce := slice[versionSize : versionSize+nonceSize] + + // Message source depends on the encryption version. + // Version 0 uses padding, version 1 does not + var src []byte + if vsn == 0 { + src = slice[versionSize+nonceSize:] + } else { + src = msg + } + out := gcm.Seal(nil, nonce, src, data) + + // Truncate the plaintext, and write the cipher text + dst.Truncate(afterNonce) + dst.Write(out) + return nil +} + +// decryptMessage performs the actual decryption of ciphertext. This is in its +// own function to allow it to be called on all keys easily. +func decryptMessage(key, msg []byte, data []byte) ([]byte, error) { + // Get the AES block cipher + aesBlock, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + // Get the GCM cipher mode + gcm, err := cipher.NewGCM(aesBlock) + if err != nil { + return nil, err + } + + // Decrypt the message + nonce := msg[versionSize : versionSize+nonceSize] + ciphertext := msg[versionSize+nonceSize:] + plain, err := gcm.Open(nil, nonce, ciphertext, data) + if err != nil { + return nil, err + } + + // Success! + return plain, nil +} + +// decryptPayload is used to decrypt a message with a given key, +// and verify it's contents. Any padding will be removed, and a +// slice to the plaintext is returned. Decryption is done IN PLACE! +func decryptPayload(keys [][]byte, msg []byte, data []byte) ([]byte, error) { + // Ensure we have at least one byte + if len(msg) == 0 { + return nil, fmt.Errorf("Cannot decrypt empty payload") + } + + // Verify the version + vsn := encryptionVersion(msg[0]) + if vsn > maxEncryptionVersion { + return nil, fmt.Errorf("Unsupported encryption version %d", msg[0]) + } + + // Ensure the length is sane + if len(msg) < encryptedLength(vsn, 0) { + return nil, fmt.Errorf("Payload is too small to decrypt: %d", len(msg)) + } + + for _, key := range keys { + plain, err := decryptMessage(key, msg, data) + if err == nil { + // Remove the PKCS7 padding for vsn 0 + if vsn == 0 { + return pkcs7decode(plain, aes.BlockSize), nil + } else { + return plain, nil + } + } + } + + return nil, fmt.Errorf("No installed keys could decrypt the message") +} diff --git a/vendor/github.com/hashicorp/memberlist/state.go b/vendor/github.com/hashicorp/memberlist/state.go new file mode 100644 index 00000000000..6caded31358 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/state.go @@ -0,0 +1,1176 @@ +package memberlist + +import ( + "bytes" + "fmt" + "math" + "math/rand" + "net" + "sync/atomic" + "time" + + "github.com/armon/go-metrics" +) + +type nodeStateType int + +const ( + stateAlive nodeStateType = iota + stateSuspect + stateDead +) + +// Node represents a node in the cluster. +type Node struct { + Name string + Addr net.IP + Port uint16 + Meta []byte // Metadata from the delegate for this node. + PMin uint8 // Minimum protocol version this understands + PMax uint8 // Maximum protocol version this understands + PCur uint8 // Current version node is speaking + DMin uint8 // Min protocol version for the delegate to understand + DMax uint8 // Max protocol version for the delegate to understand + DCur uint8 // Current version delegate is speaking +} + +// Address returns the host:port form of a node's address, suitable for use +// with a transport. +func (n *Node) Address() string { + return joinHostPort(n.Addr.String(), n.Port) +} + +// String returns the node name +func (n *Node) String() string { + return n.Name +} + +// NodeState is used to manage our state view of another node +type nodeState struct { + Node + Incarnation uint32 // Last known incarnation number + State nodeStateType // Current state + StateChange time.Time // Time last state change happened +} + +// Address returns the host:port form of a node's address, suitable for use +// with a transport. +func (n *nodeState) Address() string { + return n.Node.Address() +} + +// ackHandler is used to register handlers for incoming acks and nacks. +type ackHandler struct { + ackFn func([]byte, time.Time) + nackFn func() + timer *time.Timer +} + +// NoPingResponseError is used to indicate a 'ping' packet was +// successfully issued but no response was received +type NoPingResponseError struct { + node string +} + +func (f NoPingResponseError) Error() string { + return fmt.Sprintf("No response from node %s", f.node) +} + +// Schedule is used to ensure the Tick is performed periodically. This +// function is safe to call multiple times. If the memberlist is already +// scheduled, then it won't do anything. +func (m *Memberlist) schedule() { + m.tickerLock.Lock() + defer m.tickerLock.Unlock() + + // If we already have tickers, then don't do anything, since we're + // scheduled + if len(m.tickers) > 0 { + return + } + + // Create the stop tick channel, a blocking channel. We close this + // when we should stop the tickers. + stopCh := make(chan struct{}) + + // Create a new probeTicker + if m.config.ProbeInterval > 0 { + t := time.NewTicker(m.config.ProbeInterval) + go m.triggerFunc(m.config.ProbeInterval, t.C, stopCh, m.probe) + m.tickers = append(m.tickers, t) + } + + // Create a push pull ticker if needed + if m.config.PushPullInterval > 0 { + go m.pushPullTrigger(stopCh) + } + + // Create a gossip ticker if needed + if m.config.GossipInterval > 0 && m.config.GossipNodes > 0 { + t := time.NewTicker(m.config.GossipInterval) + go m.triggerFunc(m.config.GossipInterval, t.C, stopCh, m.gossip) + m.tickers = append(m.tickers, t) + } + + // If we made any tickers, then record the stopTick channel for + // later. + if len(m.tickers) > 0 { + m.stopTick = stopCh + } +} + +// triggerFunc is used to trigger a function call each time a +// message is received until a stop tick arrives. +func (m *Memberlist) triggerFunc(stagger time.Duration, C <-chan time.Time, stop <-chan struct{}, f func()) { + // Use a random stagger to avoid syncronizing + randStagger := time.Duration(uint64(rand.Int63()) % uint64(stagger)) + select { + case <-time.After(randStagger): + case <-stop: + return + } + for { + select { + case <-C: + f() + case <-stop: + return + } + } +} + +// pushPullTrigger is used to periodically trigger a push/pull until +// a stop tick arrives. We don't use triggerFunc since the push/pull +// timer is dynamically scaled based on cluster size to avoid network +// saturation +func (m *Memberlist) pushPullTrigger(stop <-chan struct{}) { + interval := m.config.PushPullInterval + + // Use a random stagger to avoid syncronizing + randStagger := time.Duration(uint64(rand.Int63()) % uint64(interval)) + select { + case <-time.After(randStagger): + case <-stop: + return + } + + // Tick using a dynamic timer + for { + tickTime := pushPullScale(interval, m.estNumNodes()) + select { + case <-time.After(tickTime): + m.pushPull() + case <-stop: + return + } + } +} + +// Deschedule is used to stop the background maintenance. This is safe +// to call multiple times. +func (m *Memberlist) deschedule() { + m.tickerLock.Lock() + defer m.tickerLock.Unlock() + + // If we have no tickers, then we aren't scheduled. + if len(m.tickers) == 0 { + return + } + + // Close the stop channel so all the ticker listeners stop. + close(m.stopTick) + + // Explicitly stop all the tickers themselves so they don't take + // up any more resources, and get rid of the list. + for _, t := range m.tickers { + t.Stop() + } + m.tickers = nil +} + +// Tick is used to perform a single round of failure detection and gossip +func (m *Memberlist) probe() { + // Track the number of indexes we've considered probing + numCheck := 0 +START: + m.nodeLock.RLock() + + // Make sure we don't wrap around infinitely + if numCheck >= len(m.nodes) { + m.nodeLock.RUnlock() + return + } + + // Handle the wrap around case + if m.probeIndex >= len(m.nodes) { + m.nodeLock.RUnlock() + m.resetNodes() + m.probeIndex = 0 + numCheck++ + goto START + } + + // Determine if we should probe this node + skip := false + var node nodeState + + node = *m.nodes[m.probeIndex] + if node.Name == m.config.Name { + skip = true + } else if node.State == stateDead { + skip = true + } + + // Potentially skip + m.nodeLock.RUnlock() + m.probeIndex++ + if skip { + numCheck++ + goto START + } + + // Probe the specific node + m.probeNode(&node) +} + +// probeNodeByAddr just safely calls probeNode given only the address of the node (for tests) +func (m *Memberlist) probeNodeByAddr(addr string) { + m.nodeLock.RLock() + n := m.nodeMap[addr] + m.nodeLock.RUnlock() + + m.probeNode(n) +} + +// probeNode handles a single round of failure checking on a node. +func (m *Memberlist) probeNode(node *nodeState) { + defer metrics.MeasureSince([]string{"memberlist", "probeNode"}, time.Now()) + + // We use our health awareness to scale the overall probe interval, so we + // slow down if we detect problems. The ticker that calls us can handle + // us running over the base interval, and will skip missed ticks. + probeInterval := m.awareness.ScaleTimeout(m.config.ProbeInterval) + if probeInterval > m.config.ProbeInterval { + metrics.IncrCounter([]string{"memberlist", "degraded", "probe"}, 1) + } + + // Prepare a ping message and setup an ack handler. + ping := ping{SeqNo: m.nextSeqNo(), Node: node.Name} + ackCh := make(chan ackMessage, m.config.IndirectChecks+1) + nackCh := make(chan struct{}, m.config.IndirectChecks+1) + m.setProbeChannels(ping.SeqNo, ackCh, nackCh, probeInterval) + + // Mark the sent time here, which should be after any pre-processing but + // before system calls to do the actual send. This probably over-reports + // a bit, but it's the best we can do. We had originally put this right + // after the I/O, but that would sometimes give negative RTT measurements + // which was not desirable. + sent := time.Now() + + // Send a ping to the node. If this node looks like it's suspect or dead, + // also tack on a suspect message so that it has a chance to refute as + // soon as possible. + deadline := sent.Add(probeInterval) + addr := node.Address() + if node.State == stateAlive { + if err := m.encodeAndSendMsg(addr, pingMsg, &ping); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send ping: %s", err) + return + } + } else { + var msgs [][]byte + if buf, err := encode(pingMsg, &ping); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to encode ping message: %s", err) + return + } else { + msgs = append(msgs, buf.Bytes()) + } + s := suspect{Incarnation: node.Incarnation, Node: node.Name, From: m.config.Name} + if buf, err := encode(suspectMsg, &s); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to encode suspect message: %s", err) + return + } else { + msgs = append(msgs, buf.Bytes()) + } + + compound := makeCompoundMessage(msgs) + if err := m.rawSendMsgPacket(addr, &node.Node, compound.Bytes()); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send compound ping and suspect message to %s: %s", addr, err) + return + } + } + + // Arrange for our self-awareness to get updated. At this point we've + // sent the ping, so any return statement means the probe succeeded + // which will improve our health until we get to the failure scenarios + // at the end of this function, which will alter this delta variable + // accordingly. + awarenessDelta := -1 + defer func() { + m.awareness.ApplyDelta(awarenessDelta) + }() + + // Wait for response or round-trip-time. + select { + case v := <-ackCh: + if v.Complete == true { + if m.config.Ping != nil { + rtt := v.Timestamp.Sub(sent) + m.config.Ping.NotifyPingComplete(&node.Node, rtt, v.Payload) + } + return + } + + // As an edge case, if we get a timeout, we need to re-enqueue it + // here to break out of the select below. + if v.Complete == false { + ackCh <- v + } + case <-time.After(m.config.ProbeTimeout): + // Note that we don't scale this timeout based on awareness and + // the health score. That's because we don't really expect waiting + // longer to help get UDP through. Since health does extend the + // probe interval it will give the TCP fallback more time, which + // is more active in dealing with lost packets, and it gives more + // time to wait for indirect acks/nacks. + m.logger.Printf("[DEBUG] memberlist: Failed ping: %v (timeout reached)", node.Name) + } + + // Get some random live nodes. + m.nodeLock.RLock() + kNodes := kRandomNodes(m.config.IndirectChecks, m.nodes, func(n *nodeState) bool { + return n.Name == m.config.Name || + n.Name == node.Name || + n.State != stateAlive + }) + m.nodeLock.RUnlock() + + // Attempt an indirect ping. + expectedNacks := 0 + ind := indirectPingReq{SeqNo: ping.SeqNo, Target: node.Addr, Port: node.Port, Node: node.Name} + for _, peer := range kNodes { + // We only expect nack to be sent from peers who understand + // version 4 of the protocol. + if ind.Nack = peer.PMax >= 4; ind.Nack { + expectedNacks++ + } + + if err := m.encodeAndSendMsg(peer.Address(), indirectPingMsg, &ind); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send indirect ping: %s", err) + } + } + + // Also make an attempt to contact the node directly over TCP. This + // helps prevent confused clients who get isolated from UDP traffic + // but can still speak TCP (which also means they can possibly report + // misinformation to other nodes via anti-entropy), avoiding flapping in + // the cluster. + // + // This is a little unusual because we will attempt a TCP ping to any + // member who understands version 3 of the protocol, regardless of + // which protocol version we are speaking. That's why we've included a + // config option to turn this off if desired. + fallbackCh := make(chan bool, 1) + if (!m.config.DisableTcpPings) && (node.PMax >= 3) { + go func() { + defer close(fallbackCh) + didContact, err := m.sendPingAndWaitForAck(node.Address(), ping, deadline) + if err != nil { + m.logger.Printf("[ERR] memberlist: Failed fallback ping: %s", err) + } else { + fallbackCh <- didContact + } + }() + } else { + close(fallbackCh) + } + + // Wait for the acks or timeout. Note that we don't check the fallback + // channel here because we want to issue a warning below if that's the + // *only* way we hear back from the peer, so we have to let this time + // out first to allow the normal UDP-based acks to come in. + select { + case v := <-ackCh: + if v.Complete == true { + return + } + } + + // Finally, poll the fallback channel. The timeouts are set such that + // the channel will have something or be closed without having to wait + // any additional time here. + for didContact := range fallbackCh { + if didContact { + m.logger.Printf("[WARN] memberlist: Was able to connect to %s but other probes failed, network may be misconfigured", node.Name) + return + } + } + + // Update our self-awareness based on the results of this failed probe. + // If we don't have peers who will send nacks then we penalize for any + // failed probe as a simple health metric. If we do have peers to nack + // verify, then we can use that as a more sophisticated measure of self- + // health because we assume them to be working, and they can help us + // decide if the probed node was really dead or if it was something wrong + // with ourselves. + awarenessDelta = 0 + if expectedNacks > 0 { + if nackCount := len(nackCh); nackCount < expectedNacks { + awarenessDelta += (expectedNacks - nackCount) + } + } else { + awarenessDelta += 1 + } + + // No acks received from target, suspect it as failed. + m.logger.Printf("[INFO] memberlist: Suspect %s has failed, no acks received", node.Name) + s := suspect{Incarnation: node.Incarnation, Node: node.Name, From: m.config.Name} + m.suspectNode(&s) +} + +// Ping initiates a ping to the node with the specified name. +func (m *Memberlist) Ping(node string, addr net.Addr) (time.Duration, error) { + // Prepare a ping message and setup an ack handler. + ping := ping{SeqNo: m.nextSeqNo(), Node: node} + ackCh := make(chan ackMessage, m.config.IndirectChecks+1) + m.setProbeChannels(ping.SeqNo, ackCh, nil, m.config.ProbeInterval) + + // Send a ping to the node. + if err := m.encodeAndSendMsg(addr.String(), pingMsg, &ping); err != nil { + return 0, err + } + + // Mark the sent time here, which should be after any pre-processing and + // system calls to do the actual send. This probably under-reports a bit, + // but it's the best we can do. + sent := time.Now() + + // Wait for response or timeout. + select { + case v := <-ackCh: + if v.Complete == true { + return v.Timestamp.Sub(sent), nil + } + case <-time.After(m.config.ProbeTimeout): + // Timeout, return an error below. + } + + m.logger.Printf("[DEBUG] memberlist: Failed UDP ping: %v (timeout reached)", node) + return 0, NoPingResponseError{ping.Node} +} + +// resetNodes is used when the tick wraps around. It will reap the +// dead nodes and shuffle the node list. +func (m *Memberlist) resetNodes() { + m.nodeLock.Lock() + defer m.nodeLock.Unlock() + + // Move dead nodes, but respect gossip to the dead interval + deadIdx := moveDeadNodes(m.nodes, m.config.GossipToTheDeadTime) + + // Deregister the dead nodes + for i := deadIdx; i < len(m.nodes); i++ { + delete(m.nodeMap, m.nodes[i].Name) + m.nodes[i] = nil + } + + // Trim the nodes to exclude the dead nodes + m.nodes = m.nodes[0:deadIdx] + + // Update numNodes after we've trimmed the dead nodes + atomic.StoreUint32(&m.numNodes, uint32(deadIdx)) + + // Shuffle live nodes + shuffleNodes(m.nodes) +} + +// gossip is invoked every GossipInterval period to broadcast our gossip +// messages to a few random nodes. +func (m *Memberlist) gossip() { + defer metrics.MeasureSince([]string{"memberlist", "gossip"}, time.Now()) + + // Get some random live, suspect, or recently dead nodes + m.nodeLock.RLock() + kNodes := kRandomNodes(m.config.GossipNodes, m.nodes, func(n *nodeState) bool { + if n.Name == m.config.Name { + return true + } + + switch n.State { + case stateAlive, stateSuspect: + return false + + case stateDead: + return time.Since(n.StateChange) > m.config.GossipToTheDeadTime + + default: + return true + } + }) + m.nodeLock.RUnlock() + + // Compute the bytes available + bytesAvail := m.config.UDPBufferSize - compoundHeaderOverhead + if m.config.EncryptionEnabled() { + bytesAvail -= encryptOverhead(m.encryptionVersion()) + } + + for _, node := range kNodes { + // Get any pending broadcasts + msgs := m.getBroadcasts(compoundOverhead, bytesAvail) + if len(msgs) == 0 { + return + } + + addr := node.Address() + if len(msgs) == 1 { + // Send single message as is + if err := m.rawSendMsgPacket(addr, &node.Node, msgs[0]); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", addr, err) + } + } else { + // Otherwise create and send a compound message + compound := makeCompoundMessage(msgs) + if err := m.rawSendMsgPacket(addr, &node.Node, compound.Bytes()); err != nil { + m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", addr, err) + } + } + } +} + +// pushPull is invoked periodically to randomly perform a complete state +// exchange. Used to ensure a high level of convergence, but is also +// reasonably expensive as the entire state of this node is exchanged +// with the other node. +func (m *Memberlist) pushPull() { + // Get a random live node + m.nodeLock.RLock() + nodes := kRandomNodes(1, m.nodes, func(n *nodeState) bool { + return n.Name == m.config.Name || + n.State != stateAlive + }) + m.nodeLock.RUnlock() + + // If no nodes, bail + if len(nodes) == 0 { + return + } + node := nodes[0] + + // Attempt a push pull + if err := m.pushPullNode(node.Address(), false); err != nil { + m.logger.Printf("[ERR] memberlist: Push/Pull with %s failed: %s", node.Name, err) + } +} + +// pushPullNode does a complete state exchange with a specific node. +func (m *Memberlist) pushPullNode(addr string, join bool) error { + defer metrics.MeasureSince([]string{"memberlist", "pushPullNode"}, time.Now()) + + // Attempt to send and receive with the node + remote, userState, err := m.sendAndReceiveState(addr, join) + if err != nil { + return err + } + + if err := m.mergeRemoteState(join, remote, userState); err != nil { + return err + } + return nil +} + +// verifyProtocol verifies that all the remote nodes can speak with our +// nodes and vice versa on both the core protocol as well as the +// delegate protocol level. +// +// The verification works by finding the maximum minimum and +// minimum maximum understood protocol and delegate versions. In other words, +// it finds the common denominator of protocol and delegate version ranges +// for the entire cluster. +// +// After this, it goes through the entire cluster (local and remote) and +// verifies that everyone's speaking protocol versions satisfy this range. +// If this passes, it means that every node can understand each other. +func (m *Memberlist) verifyProtocol(remote []pushNodeState) error { + m.nodeLock.RLock() + defer m.nodeLock.RUnlock() + + // Maximum minimum understood and minimum maximum understood for both + // the protocol and delegate versions. We use this to verify everyone + // can be understood. + var maxpmin, minpmax uint8 + var maxdmin, mindmax uint8 + minpmax = math.MaxUint8 + mindmax = math.MaxUint8 + + for _, rn := range remote { + // If the node isn't alive, then skip it + if rn.State != stateAlive { + continue + } + + // Skip nodes that don't have versions set, it just means + // their version is zero. + if len(rn.Vsn) == 0 { + continue + } + + if rn.Vsn[0] > maxpmin { + maxpmin = rn.Vsn[0] + } + + if rn.Vsn[1] < minpmax { + minpmax = rn.Vsn[1] + } + + if rn.Vsn[3] > maxdmin { + maxdmin = rn.Vsn[3] + } + + if rn.Vsn[4] < mindmax { + mindmax = rn.Vsn[4] + } + } + + for _, n := range m.nodes { + // Ignore non-alive nodes + if n.State != stateAlive { + continue + } + + if n.PMin > maxpmin { + maxpmin = n.PMin + } + + if n.PMax < minpmax { + minpmax = n.PMax + } + + if n.DMin > maxdmin { + maxdmin = n.DMin + } + + if n.DMax < mindmax { + mindmax = n.DMax + } + } + + // Now that we definitively know the minimum and maximum understood + // version that satisfies the whole cluster, we verify that every + // node in the cluster satisifies this. + for _, n := range remote { + var nPCur, nDCur uint8 + if len(n.Vsn) > 0 { + nPCur = n.Vsn[2] + nDCur = n.Vsn[5] + } + + if nPCur < maxpmin || nPCur > minpmax { + return fmt.Errorf( + "Node '%s' protocol version (%d) is incompatible: [%d, %d]", + n.Name, nPCur, maxpmin, minpmax) + } + + if nDCur < maxdmin || nDCur > mindmax { + return fmt.Errorf( + "Node '%s' delegate protocol version (%d) is incompatible: [%d, %d]", + n.Name, nDCur, maxdmin, mindmax) + } + } + + for _, n := range m.nodes { + nPCur := n.PCur + nDCur := n.DCur + + if nPCur < maxpmin || nPCur > minpmax { + return fmt.Errorf( + "Node '%s' protocol version (%d) is incompatible: [%d, %d]", + n.Name, nPCur, maxpmin, minpmax) + } + + if nDCur < maxdmin || nDCur > mindmax { + return fmt.Errorf( + "Node '%s' delegate protocol version (%d) is incompatible: [%d, %d]", + n.Name, nDCur, maxdmin, mindmax) + } + } + + return nil +} + +// nextSeqNo returns a usable sequence number in a thread safe way +func (m *Memberlist) nextSeqNo() uint32 { + return atomic.AddUint32(&m.sequenceNum, 1) +} + +// nextIncarnation returns the next incarnation number in a thread safe way +func (m *Memberlist) nextIncarnation() uint32 { + return atomic.AddUint32(&m.incarnation, 1) +} + +// skipIncarnation adds the positive offset to the incarnation number. +func (m *Memberlist) skipIncarnation(offset uint32) uint32 { + return atomic.AddUint32(&m.incarnation, offset) +} + +// estNumNodes is used to get the current estimate of the number of nodes +func (m *Memberlist) estNumNodes() int { + return int(atomic.LoadUint32(&m.numNodes)) +} + +type ackMessage struct { + Complete bool + Payload []byte + Timestamp time.Time +} + +// setProbeChannels is used to attach the ackCh to receive a message when an ack +// with a given sequence number is received. The `complete` field of the message +// will be false on timeout. Any nack messages will cause an empty struct to be +// passed to the nackCh, which can be nil if not needed. +func (m *Memberlist) setProbeChannels(seqNo uint32, ackCh chan ackMessage, nackCh chan struct{}, timeout time.Duration) { + // Create handler functions for acks and nacks + ackFn := func(payload []byte, timestamp time.Time) { + select { + case ackCh <- ackMessage{true, payload, timestamp}: + default: + } + } + nackFn := func() { + select { + case nackCh <- struct{}{}: + default: + } + } + + // Add the handlers + ah := &ackHandler{ackFn, nackFn, nil} + m.ackLock.Lock() + m.ackHandlers[seqNo] = ah + m.ackLock.Unlock() + + // Setup a reaping routing + ah.timer = time.AfterFunc(timeout, func() { + m.ackLock.Lock() + delete(m.ackHandlers, seqNo) + m.ackLock.Unlock() + select { + case ackCh <- ackMessage{false, nil, time.Now()}: + default: + } + }) +} + +// setAckHandler is used to attach a handler to be invoked when an ack with a +// given sequence number is received. If a timeout is reached, the handler is +// deleted. This is used for indirect pings so does not configure a function +// for nacks. +func (m *Memberlist) setAckHandler(seqNo uint32, ackFn func([]byte, time.Time), timeout time.Duration) { + // Add the handler + ah := &ackHandler{ackFn, nil, nil} + m.ackLock.Lock() + m.ackHandlers[seqNo] = ah + m.ackLock.Unlock() + + // Setup a reaping routing + ah.timer = time.AfterFunc(timeout, func() { + m.ackLock.Lock() + delete(m.ackHandlers, seqNo) + m.ackLock.Unlock() + }) +} + +// Invokes an ack handler if any is associated, and reaps the handler immediately +func (m *Memberlist) invokeAckHandler(ack ackResp, timestamp time.Time) { + m.ackLock.Lock() + ah, ok := m.ackHandlers[ack.SeqNo] + delete(m.ackHandlers, ack.SeqNo) + m.ackLock.Unlock() + if !ok { + return + } + ah.timer.Stop() + ah.ackFn(ack.Payload, timestamp) +} + +// Invokes nack handler if any is associated. +func (m *Memberlist) invokeNackHandler(nack nackResp) { + m.ackLock.Lock() + ah, ok := m.ackHandlers[nack.SeqNo] + m.ackLock.Unlock() + if !ok || ah.nackFn == nil { + return + } + ah.nackFn() +} + +// refute gossips an alive message in response to incoming information that we +// are suspect or dead. It will make sure the incarnation number beats the given +// accusedInc value, or you can supply 0 to just get the next incarnation number. +// This alters the node state that's passed in so this MUST be called while the +// nodeLock is held. +func (m *Memberlist) refute(me *nodeState, accusedInc uint32) { + // Make sure the incarnation number beats the accusation. + inc := m.nextIncarnation() + if accusedInc >= inc { + inc = m.skipIncarnation(accusedInc - inc + 1) + } + me.Incarnation = inc + + // Decrease our health because we are being asked to refute a problem. + m.awareness.ApplyDelta(1) + + // Format and broadcast an alive message. + a := alive{ + Incarnation: inc, + Node: me.Name, + Addr: me.Addr, + Port: me.Port, + Meta: me.Meta, + Vsn: []uint8{ + me.PMin, me.PMax, me.PCur, + me.DMin, me.DMax, me.DCur, + }, + } + m.encodeAndBroadcast(me.Addr.String(), aliveMsg, a) +} + +// aliveNode is invoked by the network layer when we get a message about a +// live node. +func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) { + m.nodeLock.Lock() + defer m.nodeLock.Unlock() + state, ok := m.nodeMap[a.Node] + + // It is possible that during a Leave(), there is already an aliveMsg + // in-queue to be processed but blocked by the locks above. If we let + // that aliveMsg process, it'll cause us to re-join the cluster. This + // ensures that we don't. + if m.hasLeft() && a.Node == m.config.Name { + return + } + + // Invoke the Alive delegate if any. This can be used to filter out + // alive messages based on custom logic. For example, using a cluster name. + // Using a merge delegate is not enough, as it is possible for passive + // cluster merging to still occur. + if m.config.Alive != nil { + node := &Node{ + Name: a.Node, + Addr: a.Addr, + Port: a.Port, + Meta: a.Meta, + PMin: a.Vsn[0], + PMax: a.Vsn[1], + PCur: a.Vsn[2], + DMin: a.Vsn[3], + DMax: a.Vsn[4], + DCur: a.Vsn[5], + } + if err := m.config.Alive.NotifyAlive(node); err != nil { + m.logger.Printf("[WARN] memberlist: ignoring alive message for '%s': %s", + a.Node, err) + return + } + } + + // Check if we've never seen this node before, and if not, then + // store this node in our node map. + if !ok { + state = &nodeState{ + Node: Node{ + Name: a.Node, + Addr: a.Addr, + Port: a.Port, + Meta: a.Meta, + }, + State: stateDead, + } + + // Add to map + m.nodeMap[a.Node] = state + + // Get a random offset. This is important to ensure + // the failure detection bound is low on average. If all + // nodes did an append, failure detection bound would be + // very high. + n := len(m.nodes) + offset := randomOffset(n) + + // Add at the end and swap with the node at the offset + m.nodes = append(m.nodes, state) + m.nodes[offset], m.nodes[n] = m.nodes[n], m.nodes[offset] + + // Update numNodes after we've added a new node + atomic.AddUint32(&m.numNodes, 1) + } + + // Check if this address is different than the existing node + if !bytes.Equal([]byte(state.Addr), a.Addr) || state.Port != a.Port { + m.logger.Printf("[ERR] memberlist: Conflicting address for %s. Mine: %v:%d Theirs: %v:%d", + state.Name, state.Addr, state.Port, net.IP(a.Addr), a.Port) + + // Inform the conflict delegate if provided + if m.config.Conflict != nil { + other := Node{ + Name: a.Node, + Addr: a.Addr, + Port: a.Port, + Meta: a.Meta, + } + m.config.Conflict.NotifyConflict(&state.Node, &other) + } + return + } + + // Bail if the incarnation number is older, and this is not about us + isLocalNode := state.Name == m.config.Name + if a.Incarnation <= state.Incarnation && !isLocalNode { + return + } + + // Bail if strictly less and this is about us + if a.Incarnation < state.Incarnation && isLocalNode { + return + } + + // Clear out any suspicion timer that may be in effect. + delete(m.nodeTimers, a.Node) + + // Store the old state and meta data + oldState := state.State + oldMeta := state.Meta + + // If this is us we need to refute, otherwise re-broadcast + if !bootstrap && isLocalNode { + // Compute the version vector + versions := []uint8{ + state.PMin, state.PMax, state.PCur, + state.DMin, state.DMax, state.DCur, + } + + // If the Incarnation is the same, we need special handling, since it + // possible for the following situation to happen: + // 1) Start with configuration C, join cluster + // 2) Hard fail / Kill / Shutdown + // 3) Restart with configuration C', join cluster + // + // In this case, other nodes and the local node see the same incarnation, + // but the values may not be the same. For this reason, we always + // need to do an equality check for this Incarnation. In most cases, + // we just ignore, but we may need to refute. + // + if a.Incarnation == state.Incarnation && + bytes.Equal(a.Meta, state.Meta) && + bytes.Equal(a.Vsn, versions) { + return + } + + m.refute(state, a.Incarnation) + m.logger.Printf("[WARN] memberlist: Refuting an alive message") + } else { + m.encodeBroadcastNotify(a.Node, aliveMsg, a, notify) + + // Update protocol versions if it arrived + if len(a.Vsn) > 0 { + state.PMin = a.Vsn[0] + state.PMax = a.Vsn[1] + state.PCur = a.Vsn[2] + state.DMin = a.Vsn[3] + state.DMax = a.Vsn[4] + state.DCur = a.Vsn[5] + } + + // Update the state and incarnation number + state.Incarnation = a.Incarnation + state.Meta = a.Meta + if state.State != stateAlive { + state.State = stateAlive + state.StateChange = time.Now() + } + } + + // Update metrics + metrics.IncrCounter([]string{"memberlist", "msg", "alive"}, 1) + + // Notify the delegate of any relevant updates + if m.config.Events != nil { + if oldState == stateDead { + // if Dead -> Alive, notify of join + m.config.Events.NotifyJoin(&state.Node) + + } else if !bytes.Equal(oldMeta, state.Meta) { + // if Meta changed, trigger an update notification + m.config.Events.NotifyUpdate(&state.Node) + } + } +} + +// suspectNode is invoked by the network layer when we get a message +// about a suspect node +func (m *Memberlist) suspectNode(s *suspect) { + m.nodeLock.Lock() + defer m.nodeLock.Unlock() + state, ok := m.nodeMap[s.Node] + + // If we've never heard about this node before, ignore it + if !ok { + return + } + + // Ignore old incarnation numbers + if s.Incarnation < state.Incarnation { + return + } + + // See if there's a suspicion timer we can confirm. If the info is new + // to us we will go ahead and re-gossip it. This allows for multiple + // independent confirmations to flow even when a node probes a node + // that's already suspect. + if timer, ok := m.nodeTimers[s.Node]; ok { + if timer.Confirm(s.From) { + m.encodeAndBroadcast(s.Node, suspectMsg, s) + } + return + } + + // Ignore non-alive nodes + if state.State != stateAlive { + return + } + + // If this is us we need to refute, otherwise re-broadcast + if state.Name == m.config.Name { + m.refute(state, s.Incarnation) + m.logger.Printf("[WARN] memberlist: Refuting a suspect message (from: %s)", s.From) + return // Do not mark ourself suspect + } else { + m.encodeAndBroadcast(s.Node, suspectMsg, s) + } + + // Update metrics + metrics.IncrCounter([]string{"memberlist", "msg", "suspect"}, 1) + + // Update the state + state.Incarnation = s.Incarnation + state.State = stateSuspect + changeTime := time.Now() + state.StateChange = changeTime + + // Setup a suspicion timer. Given that we don't have any known phase + // relationship with our peers, we set up k such that we hit the nominal + // timeout two probe intervals short of what we expect given the suspicion + // multiplier. + k := m.config.SuspicionMult - 2 + + // If there aren't enough nodes to give the expected confirmations, just + // set k to 0 to say that we don't expect any. Note we subtract 2 from n + // here to take out ourselves and the node being probed. + n := m.estNumNodes() + if n-2 < k { + k = 0 + } + + // Compute the timeouts based on the size of the cluster. + min := suspicionTimeout(m.config.SuspicionMult, n, m.config.ProbeInterval) + max := time.Duration(m.config.SuspicionMaxTimeoutMult) * min + fn := func(numConfirmations int) { + m.nodeLock.Lock() + state, ok := m.nodeMap[s.Node] + timeout := ok && state.State == stateSuspect && state.StateChange == changeTime + m.nodeLock.Unlock() + + if timeout { + if k > 0 && numConfirmations < k { + metrics.IncrCounter([]string{"memberlist", "degraded", "timeout"}, 1) + } + + m.logger.Printf("[INFO] memberlist: Marking %s as failed, suspect timeout reached (%d peer confirmations)", + state.Name, numConfirmations) + d := dead{Incarnation: state.Incarnation, Node: state.Name, From: m.config.Name} + m.deadNode(&d) + } + } + m.nodeTimers[s.Node] = newSuspicion(s.From, k, min, max, fn) +} + +// deadNode is invoked by the network layer when we get a message +// about a dead node +func (m *Memberlist) deadNode(d *dead) { + m.nodeLock.Lock() + defer m.nodeLock.Unlock() + state, ok := m.nodeMap[d.Node] + + // If we've never heard about this node before, ignore it + if !ok { + return + } + + // Ignore old incarnation numbers + if d.Incarnation < state.Incarnation { + return + } + + // Clear out any suspicion timer that may be in effect. + delete(m.nodeTimers, d.Node) + + // Ignore if node is already dead + if state.State == stateDead { + return + } + + // Check if this is us + if state.Name == m.config.Name { + // If we are not leaving we need to refute + if !m.hasLeft() { + m.refute(state, d.Incarnation) + m.logger.Printf("[WARN] memberlist: Refuting a dead message (from: %s)", d.From) + return // Do not mark ourself dead + } + + // If we are leaving, we broadcast and wait + m.encodeBroadcastNotify(d.Node, deadMsg, d, m.leaveBroadcast) + } else { + m.encodeAndBroadcast(d.Node, deadMsg, d) + } + + // Update metrics + metrics.IncrCounter([]string{"memberlist", "msg", "dead"}, 1) + + // Update the state + state.Incarnation = d.Incarnation + state.State = stateDead + state.StateChange = time.Now() + + // Notify of death + if m.config.Events != nil { + m.config.Events.NotifyLeave(&state.Node) + } +} + +// mergeState is invoked by the network layer when we get a Push/Pull +// state transfer +func (m *Memberlist) mergeState(remote []pushNodeState) { + for _, r := range remote { + switch r.State { + case stateAlive: + a := alive{ + Incarnation: r.Incarnation, + Node: r.Name, + Addr: r.Addr, + Port: r.Port, + Meta: r.Meta, + Vsn: r.Vsn, + } + m.aliveNode(&a, nil, false) + + case stateDead: + // If the remote node believes a node is dead, we prefer to + // suspect that node instead of declaring it dead instantly + fallthrough + case stateSuspect: + s := suspect{Incarnation: r.Incarnation, Node: r.Name, From: m.config.Name} + m.suspectNode(&s) + } + } +} diff --git a/vendor/github.com/hashicorp/memberlist/suspicion.go b/vendor/github.com/hashicorp/memberlist/suspicion.go new file mode 100644 index 00000000000..f8aa9e20a8e --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/suspicion.go @@ -0,0 +1,130 @@ +package memberlist + +import ( + "math" + "sync/atomic" + "time" +) + +// suspicion manages the suspect timer for a node and provides an interface +// to accelerate the timeout as we get more independent confirmations that +// a node is suspect. +type suspicion struct { + // n is the number of independent confirmations we've seen. This must + // be updated using atomic instructions to prevent contention with the + // timer callback. + n int32 + + // k is the number of independent confirmations we'd like to see in + // order to drive the timer to its minimum value. + k int32 + + // min is the minimum timer value. + min time.Duration + + // max is the maximum timer value. + max time.Duration + + // start captures the timestamp when we began the timer. This is used + // so we can calculate durations to feed the timer during updates in + // a way the achieves the overall time we'd like. + start time.Time + + // timer is the underlying timer that implements the timeout. + timer *time.Timer + + // f is the function to call when the timer expires. We hold on to this + // because there are cases where we call it directly. + timeoutFn func() + + // confirmations is a map of "from" nodes that have confirmed a given + // node is suspect. This prevents double counting. + confirmations map[string]struct{} +} + +// newSuspicion returns a timer started with the max time, and that will drive +// to the min time after seeing k or more confirmations. The from node will be +// excluded from confirmations since we might get our own suspicion message +// gossiped back to us. The minimum time will be used if no confirmations are +// called for (k <= 0). +func newSuspicion(from string, k int, min time.Duration, max time.Duration, fn func(int)) *suspicion { + s := &suspicion{ + k: int32(k), + min: min, + max: max, + confirmations: make(map[string]struct{}), + } + + // Exclude the from node from any confirmations. + s.confirmations[from] = struct{}{} + + // Pass the number of confirmations into the timeout function for + // easy telemetry. + s.timeoutFn = func() { + fn(int(atomic.LoadInt32(&s.n))) + } + + // If there aren't any confirmations to be made then take the min + // time from the start. + timeout := max + if k < 1 { + timeout = min + } + s.timer = time.AfterFunc(timeout, s.timeoutFn) + + // Capture the start time right after starting the timer above so + // we should always err on the side of a little longer timeout if + // there's any preemption that separates this and the step above. + s.start = time.Now() + return s +} + +// remainingSuspicionTime takes the state variables of the suspicion timer and +// calculates the remaining time to wait before considering a node dead. The +// return value can be negative, so be prepared to fire the timer immediately in +// that case. +func remainingSuspicionTime(n, k int32, elapsed time.Duration, min, max time.Duration) time.Duration { + frac := math.Log(float64(n)+1.0) / math.Log(float64(k)+1.0) + raw := max.Seconds() - frac*(max.Seconds()-min.Seconds()) + timeout := time.Duration(math.Floor(1000.0*raw)) * time.Millisecond + if timeout < min { + timeout = min + } + + // We have to take into account the amount of time that has passed so + // far, so we get the right overall timeout. + return timeout - elapsed +} + +// Confirm registers that a possibly new peer has also determined the given +// node is suspect. This returns true if this was new information, and false +// if it was a duplicate confirmation, or if we've got enough confirmations to +// hit the minimum. +func (s *suspicion) Confirm(from string) bool { + // If we've got enough confirmations then stop accepting them. + if atomic.LoadInt32(&s.n) >= s.k { + return false + } + + // Only allow one confirmation from each possible peer. + if _, ok := s.confirmations[from]; ok { + return false + } + s.confirmations[from] = struct{}{} + + // Compute the new timeout given the current number of confirmations and + // adjust the timer. If the timeout becomes negative *and* we can cleanly + // stop the timer then we will call the timeout function directly from + // here. + n := atomic.AddInt32(&s.n, 1) + elapsed := time.Since(s.start) + remaining := remainingSuspicionTime(n, s.k, elapsed, s.min, s.max) + if s.timer.Stop() { + if remaining > 0 { + s.timer.Reset(remaining) + } else { + go s.timeoutFn() + } + } + return true +} diff --git a/vendor/github.com/hashicorp/memberlist/tag.sh b/vendor/github.com/hashicorp/memberlist/tag.sh new file mode 100644 index 00000000000..cd16623a70d --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/tag.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e + +# The version must be supplied from the environment. Do not include the +# leading "v". +if [ -z $VERSION ]; then + echo "Please specify a version." + exit 1 +fi + +# Generate the tag. +echo "==> Tagging version $VERSION..." +git commit --allow-empty -a --gpg-sign=348FFC4C -m "Release v$VERSION" +git tag -a -m "Version $VERSION" -s -u 348FFC4C "v${VERSION}" master + +exit 0 diff --git a/vendor/github.com/hashicorp/memberlist/todo.md b/vendor/github.com/hashicorp/memberlist/todo.md new file mode 100644 index 00000000000..009c1d647a1 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/todo.md @@ -0,0 +1,6 @@ +# TODO +* Dynamic RTT discovery + * Compute 99th percentile for ping/ack + * Better lower bound for ping/ack, faster failure detection +* Dynamic MTU discovery + * Prevent lost updates, increases efficiency diff --git a/vendor/github.com/hashicorp/memberlist/transport.go b/vendor/github.com/hashicorp/memberlist/transport.go new file mode 100644 index 00000000000..6ce55ea47f8 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/transport.go @@ -0,0 +1,65 @@ +package memberlist + +import ( + "net" + "time" +) + +// Packet is used to provide some metadata about incoming packets from peers +// over a packet connection, as well as the packet payload. +type Packet struct { + // Buf has the raw contents of the packet. + Buf []byte + + // From has the address of the peer. This is an actual net.Addr so we + // can expose some concrete details about incoming packets. + From net.Addr + + // Timestamp is the time when the packet was received. This should be + // taken as close as possible to the actual receipt time to help make an + // accurate RTT measurement during probes. + Timestamp time.Time +} + +// Transport is used to abstract over communicating with other peers. The packet +// interface is assumed to be best-effort and the stream interface is assumed to +// be reliable. +type Transport interface { + // FinalAdvertiseAddr is given the user's configured values (which + // might be empty) and returns the desired IP and port to advertise to + // the rest of the cluster. + FinalAdvertiseAddr(ip string, port int) (net.IP, int, error) + + // WriteTo is a packet-oriented interface that fires off the given + // payload to the given address in a connectionless fashion. This should + // return a time stamp that's as close as possible to when the packet + // was transmitted to help make accurate RTT measurements during probes. + // + // This is similar to net.PacketConn, though we didn't want to expose + // that full set of required methods to keep assumptions about the + // underlying plumbing to a minimum. We also treat the address here as a + // string, similar to Dial, so it's network neutral, so this usually is + // in the form of "host:port". + WriteTo(b []byte, addr string) (time.Time, error) + + // PacketCh returns a channel that can be read to receive incoming + // packets from other peers. How this is set up for listening is left as + // an exercise for the concrete transport implementations. + PacketCh() <-chan *Packet + + // DialTimeout is used to create a connection that allows us to perform + // two-way communication with a peer. This is generally more expensive + // than packet connections so is used for more infrequent operations + // such as anti-entropy or fallback probes if the packet-oriented probe + // failed. + DialTimeout(addr string, timeout time.Duration) (net.Conn, error) + + // StreamCh returns a channel that can be read to handle incoming stream + // connections from other peers. How this is set up for listening is + // left as an exercise for the concrete transport implementations. + StreamCh() <-chan net.Conn + + // Shutdown is called when memberlist is shutting down; this gives the + // transport a chance to clean up any listeners. + Shutdown() error +} diff --git a/vendor/github.com/hashicorp/memberlist/util.go b/vendor/github.com/hashicorp/memberlist/util.go new file mode 100644 index 00000000000..1e582a8a1b0 --- /dev/null +++ b/vendor/github.com/hashicorp/memberlist/util.go @@ -0,0 +1,309 @@ +package memberlist + +import ( + "bytes" + "compress/lzw" + "encoding/binary" + "fmt" + "io" + "math" + "math/rand" + "net" + "strconv" + "strings" + "time" + + "github.com/hashicorp/go-msgpack/codec" + "github.com/sean-/seed" +) + +// pushPullScale is the minimum number of nodes +// before we start scaling the push/pull timing. The scale +// effect is the log2(Nodes) - log2(pushPullScale). This means +// that the 33rd node will cause us to double the interval, +// while the 65th will triple it. +const pushPullScaleThreshold = 32 + +const ( + // Constant litWidth 2-8 + lzwLitWidth = 8 +) + +func init() { + seed.Init() +} + +// Decode reverses the encode operation on a byte slice input +func decode(buf []byte, out interface{}) error { + r := bytes.NewReader(buf) + hd := codec.MsgpackHandle{} + dec := codec.NewDecoder(r, &hd) + return dec.Decode(out) +} + +// Encode writes an encoded object to a new bytes buffer +func encode(msgType messageType, in interface{}) (*bytes.Buffer, error) { + buf := bytes.NewBuffer(nil) + buf.WriteByte(uint8(msgType)) + hd := codec.MsgpackHandle{} + enc := codec.NewEncoder(buf, &hd) + err := enc.Encode(in) + return buf, err +} + +// Returns a random offset between 0 and n +func randomOffset(n int) int { + if n == 0 { + return 0 + } + return int(rand.Uint32() % uint32(n)) +} + +// suspicionTimeout computes the timeout that should be used when +// a node is suspected +func suspicionTimeout(suspicionMult, n int, interval time.Duration) time.Duration { + nodeScale := math.Max(1.0, math.Log10(math.Max(1.0, float64(n)))) + // multiply by 1000 to keep some precision because time.Duration is an int64 type + timeout := time.Duration(suspicionMult) * time.Duration(nodeScale*1000) * interval / 1000 + return timeout +} + +// retransmitLimit computes the limit of retransmissions +func retransmitLimit(retransmitMult, n int) int { + nodeScale := math.Ceil(math.Log10(float64(n + 1))) + limit := retransmitMult * int(nodeScale) + return limit +} + +// shuffleNodes randomly shuffles the input nodes using the Fisher-Yates shuffle +func shuffleNodes(nodes []*nodeState) { + n := len(nodes) + rand.Shuffle(n, func(i, j int) { + nodes[i], nodes[j] = nodes[j], nodes[i] + }) +} + +// pushPushScale is used to scale the time interval at which push/pull +// syncs take place. It is used to prevent network saturation as the +// cluster size grows +func pushPullScale(interval time.Duration, n int) time.Duration { + // Don't scale until we cross the threshold + if n <= pushPullScaleThreshold { + return interval + } + + multiplier := math.Ceil(math.Log2(float64(n))-math.Log2(pushPullScaleThreshold)) + 1.0 + return time.Duration(multiplier) * interval +} + +// moveDeadNodes moves nodes that are dead and beyond the gossip to the dead interval +// to the end of the slice and returns the index of the first moved node. +func moveDeadNodes(nodes []*nodeState, gossipToTheDeadTime time.Duration) int { + numDead := 0 + n := len(nodes) + for i := 0; i < n-numDead; i++ { + if nodes[i].State != stateDead { + continue + } + + // Respect the gossip to the dead interval + if time.Since(nodes[i].StateChange) <= gossipToTheDeadTime { + continue + } + + // Move this node to the end + nodes[i], nodes[n-numDead-1] = nodes[n-numDead-1], nodes[i] + numDead++ + i-- + } + return n - numDead +} + +// kRandomNodes is used to select up to k random nodes, excluding any nodes where +// the filter function returns true. It is possible that less than k nodes are +// returned. +func kRandomNodes(k int, nodes []*nodeState, filterFn func(*nodeState) bool) []*nodeState { + n := len(nodes) + kNodes := make([]*nodeState, 0, k) +OUTER: + // Probe up to 3*n times, with large n this is not necessary + // since k << n, but with small n we want search to be + // exhaustive + for i := 0; i < 3*n && len(kNodes) < k; i++ { + // Get random node + idx := randomOffset(n) + node := nodes[idx] + + // Give the filter a shot at it. + if filterFn != nil && filterFn(node) { + continue OUTER + } + + // Check if we have this node already + for j := 0; j < len(kNodes); j++ { + if node == kNodes[j] { + continue OUTER + } + } + + // Append the node + kNodes = append(kNodes, node) + } + return kNodes +} + +// makeCompoundMessage takes a list of messages and generates +// a single compound message containing all of them +func makeCompoundMessage(msgs [][]byte) *bytes.Buffer { + // Create a local buffer + buf := bytes.NewBuffer(nil) + + // Write out the type + buf.WriteByte(uint8(compoundMsg)) + + // Write out the number of message + buf.WriteByte(uint8(len(msgs))) + + // Add the message lengths + for _, m := range msgs { + binary.Write(buf, binary.BigEndian, uint16(len(m))) + } + + // Append the messages + for _, m := range msgs { + buf.Write(m) + } + + return buf +} + +// decodeCompoundMessage splits a compound message and returns +// the slices of individual messages. Also returns the number +// of truncated messages and any potential error +func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) { + if len(buf) < 1 { + err = fmt.Errorf("missing compound length byte") + return + } + numParts := uint8(buf[0]) + buf = buf[1:] + + // Check we have enough bytes + if len(buf) < int(numParts*2) { + err = fmt.Errorf("truncated len slice") + return + } + + // Decode the lengths + lengths := make([]uint16, numParts) + for i := 0; i < int(numParts); i++ { + lengths[i] = binary.BigEndian.Uint16(buf[i*2 : i*2+2]) + } + buf = buf[numParts*2:] + + // Split each message + for idx, msgLen := range lengths { + if len(buf) < int(msgLen) { + trunc = int(numParts) - idx + return + } + + // Extract the slice, seek past on the buffer + slice := buf[:msgLen] + buf = buf[msgLen:] + parts = append(parts, slice) + } + return +} + +// compressPayload takes an opaque input buffer, compresses it +// and wraps it in a compress{} message that is encoded. +func compressPayload(inp []byte) (*bytes.Buffer, error) { + var buf bytes.Buffer + compressor := lzw.NewWriter(&buf, lzw.LSB, lzwLitWidth) + + _, err := compressor.Write(inp) + if err != nil { + return nil, err + } + + // Ensure we flush everything out + if err := compressor.Close(); err != nil { + return nil, err + } + + // Create a compressed message + c := compress{ + Algo: lzwAlgo, + Buf: buf.Bytes(), + } + return encode(compressMsg, &c) +} + +// decompressPayload is used to unpack an encoded compress{} +// message and return its payload uncompressed +func decompressPayload(msg []byte) ([]byte, error) { + // Decode the message + var c compress + if err := decode(msg, &c); err != nil { + return nil, err + } + return decompressBuffer(&c) +} + +// decompressBuffer is used to decompress the buffer of +// a single compress message, handling multiple algorithms +func decompressBuffer(c *compress) ([]byte, error) { + // Verify the algorithm + if c.Algo != lzwAlgo { + return nil, fmt.Errorf("Cannot decompress unknown algorithm %d", c.Algo) + } + + // Create a uncompressor + uncomp := lzw.NewReader(bytes.NewReader(c.Buf), lzw.LSB, lzwLitWidth) + defer uncomp.Close() + + // Read all the data + var b bytes.Buffer + _, err := io.Copy(&b, uncomp) + if err != nil { + return nil, err + } + + // Return the uncompressed bytes + return b.Bytes(), nil +} + +// joinHostPort returns the host:port form of an address, for use with a +// transport. +func joinHostPort(host string, port uint16) string { + return net.JoinHostPort(host, strconv.Itoa(int(port))) +} + +// hasPort is given a string of the form "host", "host:port", "ipv6::address", +// or "[ipv6::address]:port", and returns true if the string includes a port. +func hasPort(s string) bool { + // IPv6 address in brackets. + if strings.LastIndex(s, "[") == 0 { + return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") + } + + // Otherwise the presence of a single colon determines if there's a port + // since IPv6 addresses outside of brackets (count > 1) can't have a + // port. + return strings.Count(s, ":") == 1 +} + +// ensurePort makes sure the given string has a port number on it, otherwise it +// appends the given port as a default. +func ensurePort(s string, port int) string { + if hasPort(s) { + return s + } + + // If this is an IPv6 address, the join call will add another set of + // brackets, so we have to trim before we add the default port. + s = strings.Trim(s, "[]") + s = net.JoinHostPort(s, strconv.Itoa(port)) + return s +} diff --git a/vendor/github.com/prometheus/alertmanager/api/api.go b/vendor/github.com/prometheus/alertmanager/api/api.go index b369bde0743..ec66c7f42b8 100644 --- a/vendor/github.com/prometheus/alertmanager/api/api.go +++ b/vendor/github.com/prometheus/alertmanager/api/api.go @@ -14,16 +14,12 @@ package api import ( - "bufio" "encoding/json" + "errors" "fmt" - "io" - "net" "net/http" "regexp" "sort" - "strconv" - "strings" "sync" "time" @@ -35,6 +31,7 @@ import ( "github.com/prometheus/common/version" "github.com/prometheus/prometheus/pkg/labels" + "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/dispatch" "github.com/prometheus/alertmanager/pkg/parse" @@ -42,7 +39,6 @@ import ( "github.com/prometheus/alertmanager/silence" "github.com/prometheus/alertmanager/silence/silencepb" "github.com/prometheus/alertmanager/types" - "github.com/weaveworks/mesh" ) var ( @@ -60,6 +56,9 @@ var ( ) func init() { + numReceivedAlerts.WithLabelValues("firing") + numReceivedAlerts.WithLabelValues("resolved") + prometheus.Register(numReceivedAlerts) prometheus.Register(numInvalidAlerts) } @@ -86,7 +85,7 @@ type API struct { route *dispatch.Route resolveTimeout time.Duration uptime time.Time - mrouter *mesh.Router + peer *cluster.Peer logger log.Logger groups groupsFn @@ -99,14 +98,25 @@ type groupsFn func([]*labels.Matcher) dispatch.AlertOverview type getAlertStatusFn func(model.Fingerprint) types.AlertStatus // New returns a new API. -func New(alerts provider.Alerts, silences *silence.Silences, gf groupsFn, sf getAlertStatusFn, router *mesh.Router, l log.Logger) *API { +func New( + alerts provider.Alerts, + silences *silence.Silences, + gf groupsFn, + sf getAlertStatusFn, + peer *cluster.Peer, + l log.Logger, +) *API { + if l == nil { + l = log.NewNopLogger() + } + return &API{ alerts: alerts, silences: silences, groups: gf, getAlertStatus: sf, uptime: time.Now(), - mrouter: router, + peer: peer, logger: l, } } @@ -114,32 +124,26 @@ func New(alerts provider.Alerts, silences *silence.Silences, gf groupsFn, sf get // Register registers the API handlers under their correct routes // in the given router. func (api *API) Register(r *route.Router) { - ihf := func(name string, f http.HandlerFunc) http.HandlerFunc { - return InstrumentHandlerFunc(name, func(w http.ResponseWriter, r *http.Request) { + wrap := func(f http.HandlerFunc) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { setCORS(w) f(w, r) }) } - r.Options("/*path", ihf("options", func(w http.ResponseWriter, r *http.Request) {})) - - // Register legacy forwarder for alert pushing. - r.Post("/alerts", ihf("legacy_add_alerts", api.legacyAddAlerts)) - - // Register actual API. - r = r.WithPrefix("/v1") + r.Options("/*path", wrap(func(w http.ResponseWriter, r *http.Request) {})) - r.Get("/status", ihf("status", api.status)) - r.Get("/receivers", ihf("receivers", api.receivers)) - r.Get("/alerts/groups", ihf("alert_groups", api.alertGroups)) + r.Get("/status", wrap(api.status)) + r.Get("/receivers", wrap(api.receivers)) - r.Get("/alerts", ihf("list_alerts", api.listAlerts)) - r.Post("/alerts", ihf("add_alerts", api.addAlerts)) + r.Get("/alerts/groups", wrap(api.alertGroups)) + r.Get("/alerts", wrap(api.listAlerts)) + r.Post("/alerts", wrap(api.addAlerts)) - r.Get("/silences", ihf("list_silences", api.listSilences)) - r.Post("/silences", ihf("add_silence", api.setSilence)) - r.Get("/silence/:sid", ihf("get_silence", api.getSilence)) - r.Del("/silence/:sid", ihf("del_silence", api.delSilence)) + r.Get("/silences", wrap(api.listSilences)) + r.Post("/silences", wrap(api.setSilence)) + r.Get("/silence/:sid", wrap(api.getSilence)) + r.Del("/silence/:sid", wrap(api.delSilence)) } // Update sets the configuration string to a new value. @@ -157,8 +161,8 @@ type errorType string const ( errorNone errorType = "" - errorInternal = "server_error" - errorBadData = "bad_data" + errorInternal errorType = "server_error" + errorBadData errorType = "bad_data" ) type apiError struct { @@ -186,11 +190,11 @@ func (api *API) status(w http.ResponseWriter, req *http.Request) { api.mtx.RLock() var status = struct { - ConfigYAML string `json:"configYAML"` - ConfigJSON *config.Config `json:"configJSON"` - VersionInfo map[string]string `json:"versionInfo"` - Uptime time.Time `json:"uptime"` - MeshStatus *meshStatus `json:"meshStatus"` + ConfigYAML string `json:"configYAML"` + ConfigJSON *config.Config `json:"configJSON"` + VersionInfo map[string]string `json:"versionInfo"` + Uptime time.Time `json:"uptime"` + ClusterStatus *clusterStatus `json:"clusterStatus"` }{ ConfigYAML: api.config.String(), ConfigJSON: api.config, @@ -202,8 +206,8 @@ func (api *API) status(w http.ResponseWriter, req *http.Request) { "buildDate": version.BuildDate, "goVersion": version.GoVersion, }, - Uptime: api.uptime, - MeshStatus: getMeshStatus(api), + Uptime: api.uptime, + ClusterStatus: getClusterStatus(api.peer), } api.mtx.RUnlock() @@ -211,56 +215,30 @@ func (api *API) status(w http.ResponseWriter, req *http.Request) { api.respond(w, status) } -type meshStatus struct { - Name string `json:"name"` - NickName string `json:"nickName"` - Peers []peerStatus `json:"peers"` - Connections []connectionStatus `json:"connections"` -} - type peerStatus struct { - Name string `json:"name"` // e.g. "00:00:00:00:00:01" - NickName string `json:"nickName"` // e.g. "a" - UID uint64 `json:"uid"` // e.g. "14015114173033265000" + Name string `json:"name"` + Address string `json:"address"` } -type connectionStatus struct { - Address string `json:"address"` - Outbound bool `json:"outbound"` - State string `json:"state"` - Info string `json:"info"` +type clusterStatus struct { + Name string `json:"name"` + Status string `json:"status"` + Peers []peerStatus `json:"peers"` } -func getMeshStatus(api *API) *meshStatus { - if api.mrouter == nil { +func getClusterStatus(p *cluster.Peer) *clusterStatus { + if p == nil { return nil } + s := &clusterStatus{Name: p.Name(), Status: p.Status()} - status := mesh.NewStatus(api.mrouter) - strippedStatus := &meshStatus{ - Name: status.Name, - NickName: status.NickName, - Peers: make([]peerStatus, len(status.Peers)), - Connections: make([]connectionStatus, len(status.Connections)), - } - - for i := 0; i < len(status.Peers); i++ { - strippedStatus.Peers[i] = peerStatus{ - Name: status.Peers[i].Name, - NickName: status.Peers[i].NickName, - UID: uint64(status.Peers[i].UID), - } - } - for i := 0; i < len(status.Connections); i++ { - strippedStatus.Connections[i] = connectionStatus{ - Address: status.Connections[i].Address, - Outbound: status.Connections[i].Outbound, - State: status.Connections[i].State, - Info: status.Connections[i].Info, - } + for _, n := range p.Peers() { + s.Peers = append(s.Peers, peerStatus{ + Name: n.Name, + Address: n.Address(), + }) } - - return strippedStatus + return s } func (api *API) alertGroups(w http.ResponseWriter, r *http.Request) { @@ -289,51 +267,61 @@ func (api *API) listAlerts(w http.ResponseWriter, r *http.Request) { receiverFilter *regexp.Regexp // Initialize result slice to prevent api returning `null` when there // are no alerts present - res = []*dispatch.APIAlert{} - matchers = []*labels.Matcher{} - showSilenced = true - showInhibited = true + res = []*dispatch.APIAlert{} + matchers = []*labels.Matcher{} + + showActive, showInhibited bool + showSilenced, showUnprocessed bool ) - if filter := r.FormValue("filter"); filter != "" { - matchers, err = parse.Matchers(filter) - if err != nil { + getBoolParam := func(name string) (bool, error) { + v := r.FormValue(name) + if v == "" { + return true, nil + } + if v == "false" { + return false, nil + } + if v != "true" { + err := fmt.Errorf("parameter %q can either be 'true' or 'false', not %q", name, v) api.respondError(w, apiError{ typ: errorBadData, err: err, }, nil) - return + return false, err } + return true, nil } - if silencedParam := r.FormValue("silenced"); silencedParam != "" { - if silencedParam == "false" { - showSilenced = false - } else if silencedParam != "true" { + if filter := r.FormValue("filter"); filter != "" { + matchers, err = parse.Matchers(filter) + if err != nil { api.respondError(w, apiError{ typ: errorBadData, - err: fmt.Errorf( - "parameter 'silenced' can either be 'true' or 'false', not '%v'", - silencedParam, - ), + err: err, }, nil) return } } - if inhibitedParam := r.FormValue("inhibited"); inhibitedParam != "" { - if inhibitedParam == "false" { - showInhibited = false - } else if inhibitedParam != "true" { - api.respondError(w, apiError{ - typ: errorBadData, - err: fmt.Errorf( - "parameter 'inhibited' can either be 'true' or 'false', not '%v'", - inhibitedParam, - ), - }, nil) - return - } + showActive, err = getBoolParam("active") + if err != nil { + return + } + + showSilenced, err = getBoolParam("silenced") + if err != nil { + return + } + + showInhibited, err = getBoolParam("inhibited") + if err != nil { + return + } + + showUnprocessed, err = getBoolParam("unprocessed") + if err != nil { + return } if receiverParam := r.FormValue("receiver"); receiverParam != "" { @@ -374,13 +362,21 @@ func (api *API) listAlerts(w http.ResponseWriter, r *http.Request) { continue } - // Continue if alert is resolved + // Continue if the alert is resolved. if !a.Alert.EndsAt.IsZero() && a.Alert.EndsAt.Before(time.Now()) { continue } status := api.getAlertStatus(a.Fingerprint()) + if !showActive && status.State == types.AlertStateActive { + continue + } + + if !showUnprocessed && status.State == types.AlertStateUnprocessed { + continue + } + if !showSilenced && len(status.SilencedBy) != 0 { continue } @@ -431,40 +427,6 @@ func alertMatchesFilterLabels(a *model.Alert, matchers []*labels.Matcher) bool { return matchFilterLabels(matchers, sms) } -func (api *API) legacyAddAlerts(w http.ResponseWriter, r *http.Request) { - var legacyAlerts = []struct { - Summary model.LabelValue `json:"summary"` - Description model.LabelValue `json:"description"` - Runbook model.LabelValue `json:"runbook"` - Labels model.LabelSet `json:"labels"` - Payload model.LabelSet `json:"payload"` - }{} - if err := api.receive(r, &legacyAlerts); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - var alerts []*types.Alert - for _, la := range legacyAlerts { - a := &types.Alert{ - Alert: model.Alert{ - Labels: la.Labels, - Annotations: la.Payload, - }, - } - if a.Annotations == nil { - a.Annotations = model.LabelSet{} - } - a.Annotations["summary"] = la.Summary - a.Annotations["description"] = la.Description - a.Annotations["runbook"] = la.Runbook - - alerts = append(alerts, a) - } - - api.insertAlerts(w, r, alerts...) -} - func (api *API) addAlerts(w http.ResponseWriter, r *http.Request) { var alerts []*types.Alert if err := api.receive(r, &alerts); err != nil { @@ -490,14 +452,19 @@ func (api *API) insertAlerts(w http.ResponseWriter, r *http.Request, alerts ...* // Ensure StartsAt is set. if alert.StartsAt.IsZero() { - alert.StartsAt = now + if alert.EndsAt.IsZero() { + alert.StartsAt = now + } else { + alert.StartsAt = alert.EndsAt + } } // If no end time is defined, set a timeout after which an alert // is marked resolved if it is not updated. if alert.EndsAt.IsZero() { alert.Timeout = true alert.EndsAt = now.Add(resolveTimeout) - + } + if alert.EndsAt.After(time.Now()) { numReceivedAlerts.WithLabelValues("firing").Inc() } else { numReceivedAlerts.WithLabelValues("resolved").Inc() @@ -510,6 +477,8 @@ func (api *API) insertAlerts(w http.ResponseWriter, r *http.Request, alerts ...* validationErrs = &types.MultiError{} ) for _, a := range alerts { + removeEmptyLabels(a.Labels) + if err := a.Validate(); err != nil { validationErrs.Add(err) numInvalidAlerts.Inc() @@ -536,6 +505,14 @@ func (api *API) insertAlerts(w http.ResponseWriter, r *http.Request, alerts ...* api.respond(w, nil) } +func removeEmptyLabels(ls model.LabelSet) { + for k, v := range ls { + if string(v) == "" { + delete(ls, k) + } + } +} + func (api *API) setSilence(w http.ResponseWriter, r *http.Request) { var sil types.Silence if err := api.receive(r, &sil); err != nil { @@ -545,6 +522,27 @@ func (api *API) setSilence(w http.ResponseWriter, r *http.Request) { }, nil) return } + + // This is an API only validation, it cannot be done internally + // because the expired silence is semantically important. + // But one should not be able to create expired silences, that + // won't have any use. + if sil.Expired() { + api.respondError(w, apiError{ + typ: errorBadData, + err: errors.New("start time must not be equal to end time"), + }, nil) + return + } + + if sil.EndsAt.Before(time.Now()) { + api.respondError(w, apiError{ + typ: errorBadData, + err: errors.New("end time can't be in the past"), + }, nil) + return + } + psil, err := silenceToProto(&sil) if err != nil { api.respondError(w, apiError{ @@ -688,11 +686,17 @@ func matchFilterLabels(matchers []*labels.Matcher, sms map[string]string) bool { for _, m := range matchers { v, prs := sms[m.Name] switch m.Type { - case labels.MatchNotEqual, labels.MatchNotRegexp: + case labels.MatchNotRegexp, labels.MatchNotEqual: + if string(m.Value) == "" && prs { + continue + } if !m.Matches(string(v)) { return false } default: + if string(m.Value) == "" && !prs { + continue + } if !prs || !m.Matches(string(v)) { return false } @@ -759,7 +763,7 @@ type status string const ( statusSuccess status = "success" - statusError = "error" + statusError status = "error" ) type response struct { @@ -793,7 +797,7 @@ func (api *API) respondError(w http.ResponseWriter, apiErr apiError, data interf case errorInternal: w.WriteHeader(http.StatusInternalServerError) default: - panic(fmt.Sprintf("unknown error type %q", apiErr)) + panic(fmt.Sprintf("unknown error type %q", apiErr.Error())) } b, err := json.Marshal(&response{ @@ -820,321 +824,3 @@ func (api *API) receive(r *http.Request, v interface{}) error { } return err } - -// InstrumentHandlerFunc wraps the given function for instrumentation. It -// otherwise works in the same way as InstrumentHandler (and shares the same -// issues). -// -// Deprecated: InstrumentHandlerFunc has several issues: -// -// - It uses Summaries rather than Histograms. Summaries are not useful if -// aggregation across multiple instances is required. -// -// - It uses microseconds as unit, which is deprecated and should be replaced by -// seconds. -// -// - The size of the request is calculated in a separate goroutine. Since this -// calculator requires access to the request header, it creates a race with -// any writes to the header performed during request handling. -// httputil.ReverseProxy is a prominent example for a handler -// performing such writes. -// -// Upcoming versions of this package will provide ways of instrumenting HTTP -// handlers that are more flexible and have fewer issues. Please prefer direct -// instrumentation in the meantime. -func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - return InstrumentHandlerFuncWithOpts( - prometheus.SummaryOpts{ - Subsystem: "http", - ConstLabels: prometheus.Labels{"handler": handlerName}, - }, - handlerFunc, - ) -} - -// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares -// the same issues) but provides more flexibility (at the cost of a more complex -// call syntax). See InstrumentHandlerWithOpts for details how the provided -// SummaryOpts are used. -// -// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons -// as InstrumentHandlerFunc is. -func InstrumentHandlerFuncWithOpts(opts prometheus.SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - reqCnt := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: opts.Namespace, - Subsystem: opts.Subsystem, - Name: "requests_total", - Help: "Total number of HTTP requests made.", - ConstLabels: opts.ConstLabels, - }, - instLabels, - ) - - opts.Name = "request_duration_microseconds" - opts.Help = "The HTTP request latencies in microseconds." - reqDur := prometheus.NewSummary(opts) - - opts.Name = "request_size_bytes" - opts.Help = "The HTTP request sizes in bytes." - reqSz := prometheus.NewSummary(opts) - - opts.Name = "response_size_bytes" - opts.Help = "The HTTP response sizes in bytes." - resSz := prometheus.NewSummary(opts) - - regReqCnt := MustRegisterOrGet(reqCnt).(*prometheus.CounterVec) - regReqDur := MustRegisterOrGet(reqDur).(prometheus.Summary) - regReqSz := MustRegisterOrGet(reqSz).(prometheus.Summary) - regResSz := MustRegisterOrGet(resSz).(prometheus.Summary) - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - - delegate := &responseWriterDelegator{ResponseWriter: w} - out := make(chan int) - urlLen := 0 - if r.URL != nil { - urlLen = len(r.URL.String()) - } - go computeApproximateRequestSize(r, out, urlLen) - - _, cn := w.(http.CloseNotifier) - _, fl := w.(http.Flusher) - _, hj := w.(http.Hijacker) - _, rf := w.(io.ReaderFrom) - var rw http.ResponseWriter - if cn && fl && hj && rf { - rw = &fancyResponseWriterDelegator{delegate} - } else { - rw = delegate - } - handlerFunc(rw, r) - - elapsed := float64(time.Since(now)) / float64(time.Microsecond) - - method := sanitizeMethod(r.Method) - code := sanitizeCode(delegate.status) - regReqCnt.WithLabelValues(method, code).Inc() - regReqDur.Observe(elapsed) - regResSz.Observe(float64(delegate.written)) - regReqSz.Observe(float64(<-out)) - }) -} - -func computeApproximateRequestSize(r *http.Request, out chan int, s int) { - s += len(r.Method) - s += len(r.Proto) - for name, values := range r.Header { - s += len(name) - for _, value := range values { - s += len(value) - } - } - s += len(r.Host) - - // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. - - if r.ContentLength != -1 { - s += int(r.ContentLength) - } - out <- s -} - -func sanitizeMethod(m string) string { - switch m { - case "GET", "get": - return "get" - case "PUT", "put": - return "put" - case "HEAD", "head": - return "head" - case "POST", "post": - return "post" - case "DELETE", "delete": - return "delete" - case "CONNECT", "connect": - return "connect" - case "OPTIONS", "options": - return "options" - case "NOTIFY", "notify": - return "notify" - default: - return strings.ToLower(m) - } -} - -var instLabels = []string{"method", "code"} - -type responseWriterDelegator struct { - http.ResponseWriter - - handler, method string - status int - written int64 - wroteHeader bool -} - -func (r *responseWriterDelegator) WriteHeader(code int) { - r.status = code - r.wroteHeader = true - r.ResponseWriter.WriteHeader(code) -} - -func (r *responseWriterDelegator) Write(b []byte) (int, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.Write(b) - r.written += int64(n) - return n, err -} - -type fancyResponseWriterDelegator struct { - *responseWriterDelegator -} - -func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool { - return f.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - -func (f *fancyResponseWriterDelegator) Flush() { - f.ResponseWriter.(http.Flusher).Flush() -} - -func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return f.ResponseWriter.(http.Hijacker).Hijack() -} - -func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) { - if !f.wroteHeader { - f.WriteHeader(http.StatusOK) - } - n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r) - f.written += n - return n, err -} - -func sanitizeCode(s int) string { - switch s { - case 100: - return "100" - case 101: - return "101" - - case 200: - return "200" - case 201: - return "201" - case 202: - return "202" - case 203: - return "203" - case 204: - return "204" - case 205: - return "205" - case 206: - return "206" - - case 300: - return "300" - case 301: - return "301" - case 302: - return "302" - case 304: - return "304" - case 305: - return "305" - case 307: - return "307" - - case 400: - return "400" - case 401: - return "401" - case 402: - return "402" - case 403: - return "403" - case 404: - return "404" - case 405: - return "405" - case 406: - return "406" - case 407: - return "407" - case 408: - return "408" - case 409: - return "409" - case 410: - return "410" - case 411: - return "411" - case 412: - return "412" - case 413: - return "413" - case 414: - return "414" - case 415: - return "415" - case 416: - return "416" - case 417: - return "417" - case 418: - return "418" - - case 500: - return "500" - case 501: - return "501" - case 502: - return "502" - case 503: - return "503" - case 504: - return "504" - case 505: - return "505" - - case 428: - return "428" - case 429: - return "429" - case 431: - return "431" - case 511: - return "511" - - default: - return strconv.Itoa(s) - } -} - -// RegisterOrGet registers the provided Collector with the DefaultRegisterer and -// returns the Collector, unless an equal Collector was registered before, in -// which case that Collector is returned. -func RegisterOrGet(c prometheus.Collector) (prometheus.Collector, error) { - if err := prometheus.Register(c); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - return are.ExistingCollector, nil - } - return nil, err - } - return c, nil -} - -// MustRegisterOrGet behaves like RegisterOrGet but panics instead of returning -// an error. -func MustRegisterOrGet(c prometheus.Collector) prometheus.Collector { - c, err := RegisterOrGet(c) - if err != nil { - panic(err) - } - return c -} diff --git a/vendor/github.com/prometheus/alertmanager/cluster/advertise.go b/vendor/github.com/prometheus/alertmanager/cluster/advertise.go new file mode 100644 index 00000000000..c6f44b927be --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/cluster/advertise.go @@ -0,0 +1,66 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cluster + +import ( + "net" + + "github.com/hashicorp/go-sockaddr" + "github.com/pkg/errors" +) + +type getPrivateIPFunc func() (string, error) + +// This is overriden in unit tests to mock the sockaddr.GetPrivateIP function. +var getPrivateAddress getPrivateIPFunc = sockaddr.GetPrivateIP + +// calculateAdvertiseAddress attempts to clone logic from deep within memberlist +// (NetTransport.FinalAdvertiseAddr) in order to surface its conclusions to the +// application, so we can provide more actionable error messages if the user has +// inadvertantly misconfigured their cluster. +// +// https://github.com/hashicorp/memberlist/blob/022f081/net_transport.go#L126 +func calculateAdvertiseAddress(bindAddr, advertiseAddr string) (net.IP, error) { + if advertiseAddr != "" { + ip := net.ParseIP(advertiseAddr) + if ip == nil { + return nil, errors.Errorf("failed to parse advertise addr '%s'", advertiseAddr) + } + if ip4 := ip.To4(); ip4 != nil { + ip = ip4 + } + return ip, nil + } + + if isAny(bindAddr) { + privateIP, err := getPrivateAddress() + if err != nil { + return nil, errors.Wrap(err, "failed to get private IP") + } + if privateIP == "" { + return nil, errors.New("no private IP found, explicit advertise addr not provided") + } + ip := net.ParseIP(privateIP) + if ip == nil { + return nil, errors.Errorf("failed to parse private IP '%s'", privateIP) + } + return ip, nil + } + + ip := net.ParseIP(bindAddr) + if ip == nil { + return nil, errors.Errorf("failed to parse bind addr '%s'", bindAddr) + } + return ip, nil +} diff --git a/vendor/github.com/prometheus/alertmanager/cluster/channel.go b/vendor/github.com/prometheus/alertmanager/cluster/channel.go new file mode 100644 index 00000000000..aba87b64a14 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/cluster/channel.go @@ -0,0 +1,149 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cluster + +import ( + "sync" + "time" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/gogo/protobuf/proto" + "github.com/hashicorp/memberlist" + "github.com/prometheus/alertmanager/cluster/clusterpb" + "github.com/prometheus/client_golang/prometheus" +) + +// Channel allows clients to send messages for a specific state type that will be +// broadcasted in a best-effort manner. +type Channel struct { + key string + send func([]byte) + peers func() []*memberlist.Node + sendOversize func(*memberlist.Node, []byte) error + + msgc chan []byte + logger log.Logger + + oversizeGossipMessageFailureTotal prometheus.Counter + oversizeGossipMessageDroppedTotal prometheus.Counter + oversizeGossipMessageSentTotal prometheus.Counter + oversizeGossipDuration prometheus.Histogram +} + +// NewChannel creates a new Channel struct, which handles sending normal and +// oversize messages to peers. +func NewChannel( + key string, + send func([]byte), + peers func() []*memberlist.Node, + sendOversize func(*memberlist.Node, []byte) error, + logger log.Logger, + stopc chan struct{}, + reg prometheus.Registerer, +) *Channel { + oversizeGossipMessageFailureTotal := prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_oversized_gossip_message_failure_total", + Help: "Number of oversized gossip message sends that failed.", + ConstLabels: prometheus.Labels{"key": key}, + }) + oversizeGossipMessageSentTotal := prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_oversized_gossip_message_sent_total", + Help: "Number of oversized gossip message sent.", + ConstLabels: prometheus.Labels{"key": key}, + }) + oversizeGossipMessageDroppedTotal := prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_oversized_gossip_message_dropped_total", + Help: "Number of oversized gossip messages that were dropped due to a full message queue.", + ConstLabels: prometheus.Labels{"key": key}, + }) + oversizeGossipDuration := prometheus.NewHistogram(prometheus.HistogramOpts{ + Name: "alertmanager_oversize_gossip_message_duration_seconds", + Help: "Duration of oversized gossip message requests.", + ConstLabels: prometheus.Labels{"key": key}, + }) + + reg.MustRegister(oversizeGossipDuration, oversizeGossipMessageFailureTotal, oversizeGossipMessageDroppedTotal, oversizeGossipMessageSentTotal) + + c := &Channel{ + key: key, + send: send, + peers: peers, + logger: logger, + msgc: make(chan []byte, 200), + sendOversize: sendOversize, + oversizeGossipMessageFailureTotal: oversizeGossipMessageFailureTotal, + oversizeGossipMessageDroppedTotal: oversizeGossipMessageDroppedTotal, + oversizeGossipMessageSentTotal: oversizeGossipMessageSentTotal, + oversizeGossipDuration: oversizeGossipDuration, + } + + go c.handleOverSizedMessages(stopc) + + return c +} + +// handleOverSizedMessages prevents memberlist from opening too many parallel +// TCP connections to its peers. +func (c *Channel) handleOverSizedMessages(stopc chan struct{}) { + var wg sync.WaitGroup + for { + select { + case b := <-c.msgc: + for _, n := range c.peers() { + wg.Add(1) + go func(n *memberlist.Node) { + defer wg.Done() + c.oversizeGossipMessageSentTotal.Inc() + start := time.Now() + if err := c.sendOversize(n, b); err != nil { + level.Debug(c.logger).Log("msg", "failed to send reliable", "key", c.key, "node", n, "err", err) + c.oversizeGossipMessageFailureTotal.Inc() + return + } + c.oversizeGossipDuration.Observe(time.Since(start).Seconds()) + }(n) + } + + wg.Wait() + case <-stopc: + return + } + } +} + +// Broadcast enqueues a message for broadcasting. +func (c *Channel) Broadcast(b []byte) { + b, err := proto.Marshal(&clusterpb.Part{Key: c.key, Data: b}) + if err != nil { + return + } + + if OversizedMessage(b) { + select { + case c.msgc <- b: + default: + level.Debug(c.logger).Log("msg", "oversized gossip channel full") + c.oversizeGossipMessageDroppedTotal.Inc() + } + } else { + c.send(b) + } +} + +// OversizedMessage indicates whether or not the byte payload should be sent +// via TCP. +func OversizedMessage(b []byte) bool { + return len(b) > maxGossipPacketSize/2 +} diff --git a/vendor/github.com/prometheus/alertmanager/cluster/cluster.go b/vendor/github.com/prometheus/alertmanager/cluster/cluster.go new file mode 100644 index 00000000000..5881a7e71ac --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/cluster/cluster.go @@ -0,0 +1,749 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cluster + +import ( + "context" + "fmt" + "math/rand" + "net" + "sort" + "strconv" + "strings" + "sync" + "time" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/hashicorp/memberlist" + "github.com/oklog/ulid" + "github.com/pkg/errors" + + "github.com/prometheus/client_golang/prometheus" +) + +// Peer is a single peer in a gossip cluster. +type Peer struct { + mlist *memberlist.Memberlist + delegate *delegate + + resolvedPeers []string + + mtx sync.RWMutex + states map[string]State + stopc chan struct{} + readyc chan struct{} + + peerLock sync.RWMutex + peers map[string]peer + failedPeers []peer + + failedReconnectionsCounter prometheus.Counter + reconnectionsCounter prometheus.Counter + peerLeaveCounter prometheus.Counter + peerUpdateCounter prometheus.Counter + peerJoinCounter prometheus.Counter + + logger log.Logger +} + +// peer is an internal type used for bookkeeping. It holds the state of peers +// in the cluster. +type peer struct { + status PeerStatus + leaveTime time.Time + + *memberlist.Node +} + +// PeerStatus is the state that a peer is in. +type PeerStatus int + +const ( + StatusNone PeerStatus = iota + StatusAlive + StatusFailed +) + +func (s PeerStatus) String() string { + switch s { + case StatusNone: + return "none" + case StatusAlive: + return "alive" + case StatusFailed: + return "failed" + default: + panic(fmt.Sprintf("unknown PeerStatus: %d", s)) + } +} + +const ( + DefaultPushPullInterval = 60 * time.Second + DefaultGossipInterval = 200 * time.Millisecond + DefaultTcpTimeout = 10 * time.Second + DefaultProbeTimeout = 500 * time.Millisecond + DefaultProbeInterval = 1 * time.Second + DefaultReconnectInterval = 10 * time.Second + DefaultReconnectTimeout = 6 * time.Hour + maxGossipPacketSize = 1400 +) + +func Create( + l log.Logger, + reg prometheus.Registerer, + bindAddr string, + advertiseAddr string, + knownPeers []string, + waitIfEmpty bool, + pushPullInterval time.Duration, + gossipInterval time.Duration, + tcpTimeout time.Duration, + probeTimeout time.Duration, + probeInterval time.Duration, +) (*Peer, error) { + bindHost, bindPortStr, err := net.SplitHostPort(bindAddr) + if err != nil { + return nil, err + } + bindPort, err := strconv.Atoi(bindPortStr) + if err != nil { + return nil, errors.Wrap(err, "invalid listen address") + } + + var advertiseHost string + var advertisePort int + if advertiseAddr != "" { + var advertisePortStr string + advertiseHost, advertisePortStr, err = net.SplitHostPort(advertiseAddr) + if err != nil { + return nil, errors.Wrap(err, "invalid advertise address") + } + advertisePort, err = strconv.Atoi(advertisePortStr) + if err != nil { + return nil, errors.Wrap(err, "invalid advertise address, wrong port") + } + } + + resolvedPeers, err := resolvePeers(context.Background(), knownPeers, advertiseAddr, net.Resolver{}, waitIfEmpty) + if err != nil { + return nil, errors.Wrap(err, "resolve peers") + } + level.Debug(l).Log("msg", "resolved peers to following addresses", "peers", strings.Join(resolvedPeers, ",")) + + // Initial validation of user-specified advertise address. + addr, err := calculateAdvertiseAddress(bindHost, advertiseHost) + if err != nil { + level.Warn(l).Log("err", "couldn't deduce an advertise address: "+err.Error()) + } else if hasNonlocal(resolvedPeers) && isUnroutable(addr.String()) { + level.Warn(l).Log("err", "this node advertises itself on an unroutable address", "addr", addr.String()) + level.Warn(l).Log("err", "this node will be unreachable in the cluster") + level.Warn(l).Log("err", "provide --cluster.advertise-address as a routable IP address or hostname") + } else if isAny(bindAddr) && advertiseHost == "" { + // memberlist doesn't advertise properly when the bind address is empty or unspecified. + level.Info(l).Log("msg", "setting advertise address explicitly", "addr", addr.String(), "port", bindPort) + advertiseHost = addr.String() + advertisePort = bindPort + } + + // TODO(fabxc): generate human-readable but random names? + name, err := ulid.New(ulid.Now(), rand.New(rand.NewSource(time.Now().UnixNano()))) + if err != nil { + return nil, err + } + + p := &Peer{ + states: map[string]State{}, + stopc: make(chan struct{}), + readyc: make(chan struct{}), + logger: l, + peers: map[string]peer{}, + resolvedPeers: resolvedPeers, + } + + p.register(reg) + + retransmit := len(knownPeers) / 2 + if retransmit < 3 { + retransmit = 3 + } + p.delegate = newDelegate(l, reg, p, retransmit) + + cfg := memberlist.DefaultLANConfig() + cfg.Name = name.String() + cfg.BindAddr = bindHost + cfg.BindPort = bindPort + cfg.Delegate = p.delegate + cfg.Events = p.delegate + cfg.GossipInterval = gossipInterval + cfg.PushPullInterval = pushPullInterval + cfg.TCPTimeout = tcpTimeout + cfg.ProbeTimeout = probeTimeout + cfg.ProbeInterval = probeInterval + cfg.LogOutput = &logWriter{l: l} + cfg.GossipNodes = retransmit + cfg.UDPBufferSize = maxGossipPacketSize + + if advertiseHost != "" { + cfg.AdvertiseAddr = advertiseHost + cfg.AdvertisePort = advertisePort + p.setInitialFailed(resolvedPeers, fmt.Sprintf("%s:%d", advertiseHost, advertisePort)) + } else { + p.setInitialFailed(resolvedPeers, bindAddr) + } + + ml, err := memberlist.Create(cfg) + if err != nil { + return nil, errors.Wrap(err, "create memberlist") + } + p.mlist = ml + return p, nil +} + +func (p *Peer) Join( + reconnectInterval time.Duration, + reconnectTimeout time.Duration) error { + n, err := p.mlist.Join(p.resolvedPeers) + if err != nil { + level.Warn(p.logger).Log("msg", "failed to join cluster", "err", err) + if reconnectInterval != 0 { + level.Info(p.logger).Log("msg", fmt.Sprintf("will retry joining cluster every %v", reconnectInterval.String())) + } + } else { + level.Debug(p.logger).Log("msg", "joined cluster", "peers", n) + } + + if reconnectInterval != 0 { + go p.handleReconnect(reconnectInterval) + } + if reconnectTimeout != 0 { + go p.handleReconnectTimeout(5*time.Minute, reconnectTimeout) + } + + return err +} + +// All peers are initially added to the failed list. They will be removed from +// this list in peerJoin when making their initial connection. +func (p *Peer) setInitialFailed(peers []string, myAddr string) { + if len(peers) == 0 { + return + } + + p.peerLock.RLock() + defer p.peerLock.RUnlock() + + now := time.Now() + for _, peerAddr := range peers { + if peerAddr == myAddr { + // Don't add ourselves to the initially failing list, + // we don't connect to ourselves. + continue + } + host, port, err := net.SplitHostPort(peerAddr) + if err != nil { + continue + } + ip := net.ParseIP(host) + if ip == nil { + // Don't add textual addresses since memberlist only advertises + // dotted decimal or IPv6 addresses. + continue + } + portUint, err := strconv.ParseUint(port, 10, 16) + if err != nil { + continue + } + + pr := peer{ + status: StatusFailed, + leaveTime: now, + Node: &memberlist.Node{ + Addr: ip, + Port: uint16(portUint), + }, + } + p.failedPeers = append(p.failedPeers, pr) + p.peers[peerAddr] = pr + } +} + +type logWriter struct { + l log.Logger +} + +func (l *logWriter) Write(b []byte) (int, error) { + return len(b), level.Debug(l.l).Log("memberlist", string(b)) +} + +func (p *Peer) register(reg prometheus.Registerer) { + clusterFailedPeers := prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "alertmanager_cluster_failed_peers", + Help: "Number indicating the current number of failed peers in the cluster.", + }, func() float64 { + p.peerLock.RLock() + defer p.peerLock.RUnlock() + + return float64(len(p.failedPeers)) + }) + p.failedReconnectionsCounter = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_cluster_reconnections_failed_total", + Help: "A counter of the number of failed cluster peer reconnection attempts.", + }) + + p.reconnectionsCounter = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_cluster_reconnections_total", + Help: "A counter of the number of cluster peer reconnections.", + }) + + p.peerLeaveCounter = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_cluster_peers_left_total", + Help: "A counter of the number of peers that have left.", + }) + p.peerUpdateCounter = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_cluster_peers_update_total", + Help: "A counter of the number of peers that have updated metadata.", + }) + p.peerJoinCounter = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_cluster_peers_joined_total", + Help: "A counter of the number of peers that have joined.", + }) + + reg.MustRegister(clusterFailedPeers, p.failedReconnectionsCounter, p.reconnectionsCounter, + p.peerLeaveCounter, p.peerUpdateCounter, p.peerJoinCounter) +} + +func (p *Peer) handleReconnectTimeout(d time.Duration, timeout time.Duration) { + tick := time.NewTicker(d) + defer tick.Stop() + + for { + select { + case <-p.stopc: + return + case <-tick.C: + p.removeFailedPeers(timeout) + } + } +} + +func (p *Peer) removeFailedPeers(timeout time.Duration) { + p.peerLock.Lock() + defer p.peerLock.Unlock() + + now := time.Now() + + keep := make([]peer, 0, len(p.failedPeers)) + for _, pr := range p.failedPeers { + if pr.leaveTime.Add(timeout).After(now) { + keep = append(keep, pr) + } else { + level.Debug(p.logger).Log("msg", "failed peer has timed out", "peer", pr.Node, "addr", pr.Address()) + delete(p.peers, pr.Name) + } + } + + p.failedPeers = keep +} + +func (p *Peer) handleReconnect(d time.Duration) { + tick := time.NewTicker(d) + defer tick.Stop() + + for { + select { + case <-p.stopc: + return + case <-tick.C: + p.reconnect() + } + } +} + +func (p *Peer) reconnect() { + p.peerLock.RLock() + failedPeers := p.failedPeers + p.peerLock.RUnlock() + + logger := log.With(p.logger, "msg", "reconnect") + for _, pr := range failedPeers { + // No need to do book keeping on failedPeers here. If a + // reconnect is successful, they will be announced in + // peerJoin(). + if _, err := p.mlist.Join([]string{pr.Address()}); err != nil { + p.failedReconnectionsCounter.Inc() + level.Debug(logger).Log("result", "failure", "peer", pr.Node, "addr", pr.Address()) + } else { + p.reconnectionsCounter.Inc() + level.Debug(logger).Log("result", "success", "peer", pr.Node, "addr", pr.Address()) + } + } +} + +func (p *Peer) peerJoin(n *memberlist.Node) { + p.peerLock.Lock() + defer p.peerLock.Unlock() + + var oldStatus PeerStatus + pr, ok := p.peers[n.Address()] + if !ok { + oldStatus = StatusNone + pr = peer{ + status: StatusAlive, + Node: n, + } + } else { + oldStatus = pr.status + pr.Node = n + pr.status = StatusAlive + pr.leaveTime = time.Time{} + } + + p.peers[n.Address()] = pr + p.peerJoinCounter.Inc() + + if oldStatus == StatusFailed { + level.Debug(p.logger).Log("msg", "peer rejoined", "peer", pr.Node) + p.failedPeers = removeOldPeer(p.failedPeers, pr.Address()) + } +} + +func (p *Peer) peerLeave(n *memberlist.Node) { + p.peerLock.Lock() + defer p.peerLock.Unlock() + + pr, ok := p.peers[n.Address()] + if !ok { + // Why are we receiving a leave notification from a node that + // never joined? + return + } + + pr.status = StatusFailed + pr.leaveTime = time.Now() + p.failedPeers = append(p.failedPeers, pr) + p.peers[n.Address()] = pr + + p.peerLeaveCounter.Inc() + level.Debug(p.logger).Log("msg", "peer left", "peer", pr.Node) +} + +func (p *Peer) peerUpdate(n *memberlist.Node) { + p.peerLock.Lock() + defer p.peerLock.Unlock() + + pr, ok := p.peers[n.Address()] + if !ok { + // Why are we receiving an update from a node that never + // joined? + return + } + + pr.Node = n + p.peers[n.Address()] = pr + + p.peerUpdateCounter.Inc() + level.Debug(p.logger).Log("msg", "peer updated", "peer", pr.Node) +} + +// AddState adds a new state that will be gossiped. It returns a channel to which +// broadcast messages for the state can be sent. +func (p *Peer) AddState(key string, s State, reg prometheus.Registerer) *Channel { + p.states[key] = s + send := func(b []byte) { + p.delegate.bcast.QueueBroadcast(simpleBroadcast(b)) + } + peers := func() []*memberlist.Node { + nodes := p.Peers() + for i, n := range nodes { + if n.Name == p.Self().Name { + nodes = append(nodes[:i], nodes[i+1:]...) + break + } + } + return nodes + } + sendOversize := func(n *memberlist.Node, b []byte) error { + return p.mlist.SendReliable(n, b) + } + return NewChannel(key, send, peers, sendOversize, p.logger, p.stopc, reg) +} + +// Leave the cluster, waiting up to timeout. +func (p *Peer) Leave(timeout time.Duration) error { + close(p.stopc) + level.Debug(p.logger).Log("msg", "leaving cluster") + return p.mlist.Leave(timeout) +} + +// Name returns the unique ID of this peer in the cluster. +func (p *Peer) Name() string { + return p.mlist.LocalNode().Name +} + +// ClusterSize returns the current number of alive members in the cluster. +func (p *Peer) ClusterSize() int { + return p.mlist.NumMembers() +} + +// Return true when router has settled. +func (p *Peer) Ready() bool { + select { + case <-p.readyc: + return true + default: + } + return false +} + +// Wait until Settle() has finished. +func (p *Peer) WaitReady() { + <-p.readyc +} + +// Return a status string representing the peer state. +func (p *Peer) Status() string { + if p.Ready() { + return "ready" + } else { + return "settling" + } +} + +// Info returns a JSON-serializable dump of cluster state. +// Useful for debug. +func (p *Peer) Info() map[string]interface{} { + p.mtx.RLock() + defer p.mtx.RUnlock() + + return map[string]interface{}{ + "self": p.mlist.LocalNode(), + "members": p.mlist.Members(), + } +} + +// Self returns the node information about the peer itself. +func (p *Peer) Self() *memberlist.Node { + return p.mlist.LocalNode() +} + +// Peers returns the peers in the cluster. +func (p *Peer) Peers() []*memberlist.Node { + return p.mlist.Members() +} + +// Position returns the position of the peer in the cluster. +func (p *Peer) Position() int { + all := p.Peers() + sort.Slice(all, func(i, j int) bool { + return all[i].Name < all[j].Name + }) + + k := 0 + for _, n := range all { + if n.Name == p.Self().Name { + break + } + k++ + } + return k +} + +// Settle waits until the mesh is ready (and sets the appropriate internal state when it is). +// The idea is that we don't want to start "working" before we get a chance to know most of the alerts and/or silences. +// Inspired from https://github.com/apache/cassandra/blob/7a40abb6a5108688fb1b10c375bb751cbb782ea4/src/java/org/apache/cassandra/gms/Gossiper.java +// This is clearly not perfect or strictly correct but should prevent the alertmanager to send notification before it is obviously not ready. +// This is especially important for those that do not have persistent storage. +func (p *Peer) Settle(ctx context.Context, interval time.Duration) { + const NumOkayRequired = 3 + level.Info(p.logger).Log("msg", "Waiting for gossip to settle...", "interval", interval) + start := time.Now() + nPeers := 0 + nOkay := 0 + totalPolls := 0 + for { + select { + case <-ctx.Done(): + elapsed := time.Since(start) + level.Info(p.logger).Log("msg", "gossip not settled but continuing anyway", "polls", totalPolls, "elapsed", elapsed) + close(p.readyc) + return + case <-time.After(interval): + } + elapsed := time.Since(start) + n := len(p.Peers()) + if nOkay >= NumOkayRequired { + level.Info(p.logger).Log("msg", "gossip settled; proceeding", "elapsed", elapsed) + break + } + if n == nPeers { + nOkay++ + level.Debug(p.logger).Log("msg", "gossip looks settled", "elapsed", elapsed) + } else { + nOkay = 0 + level.Info(p.logger).Log("msg", "gossip not settled", "polls", totalPolls, "before", nPeers, "now", n, "elapsed", elapsed) + } + nPeers = n + totalPolls++ + } + close(p.readyc) +} + +// State is a piece of state that can be serialized and merged with other +// serialized state. +type State interface { + // MarshalBinary serializes the underlying state. + MarshalBinary() ([]byte, error) + + // Merge merges serialized state into the underlying state. + Merge(b []byte) error +} + +// We use a simple broadcast implementation in which items are never invalidated by others. +type simpleBroadcast []byte + +func (b simpleBroadcast) Message() []byte { return []byte(b) } +func (b simpleBroadcast) Invalidates(memberlist.Broadcast) bool { return false } +func (b simpleBroadcast) Finished() {} + +func resolvePeers(ctx context.Context, peers []string, myAddress string, res net.Resolver, waitIfEmpty bool) ([]string, error) { + var resolvedPeers []string + + for _, peer := range peers { + host, port, err := net.SplitHostPort(peer) + if err != nil { + return nil, errors.Wrapf(err, "split host/port for peer %s", peer) + } + + retryCtx, cancel := context.WithCancel(ctx) + + ips, err := res.LookupIPAddr(ctx, host) + if err != nil { + // Assume direct address. + resolvedPeers = append(resolvedPeers, peer) + continue + } + + if len(ips) == 0 { + var lookupErrSpotted bool + + err := retry(2*time.Second, retryCtx.Done(), func() error { + if lookupErrSpotted { + // We need to invoke cancel in next run of retry when lookupErrSpotted to preserve LookupIPAddr error. + cancel() + } + + ips, err = res.LookupIPAddr(retryCtx, host) + if err != nil { + lookupErrSpotted = true + return errors.Wrapf(err, "IP Addr lookup for peer %s", peer) + } + + ips = removeMyAddr(ips, port, myAddress) + if len(ips) == 0 { + if !waitIfEmpty { + return nil + } + return errors.New("empty IPAddr result. Retrying") + } + + return nil + }) + if err != nil { + return nil, err + } + } + + for _, ip := range ips { + resolvedPeers = append(resolvedPeers, net.JoinHostPort(ip.String(), port)) + } + } + + return resolvedPeers, nil +} + +func removeMyAddr(ips []net.IPAddr, targetPort string, myAddr string) []net.IPAddr { + var result []net.IPAddr + + for _, ip := range ips { + if net.JoinHostPort(ip.String(), targetPort) == myAddr { + continue + } + result = append(result, ip) + } + + return result +} + +func hasNonlocal(clusterPeers []string) bool { + for _, peer := range clusterPeers { + if host, _, err := net.SplitHostPort(peer); err == nil { + peer = host + } + if ip := net.ParseIP(peer); ip != nil && !ip.IsLoopback() { + return true + } else if ip == nil && strings.ToLower(peer) != "localhost" { + return true + } + } + return false +} + +func isUnroutable(addr string) bool { + if host, _, err := net.SplitHostPort(addr); err == nil { + addr = host + } + if ip := net.ParseIP(addr); ip != nil && (ip.IsUnspecified() || ip.IsLoopback()) { + return true // typically 0.0.0.0 or localhost + } else if ip == nil && strings.ToLower(addr) == "localhost" { + return true + } + return false +} + +func isAny(addr string) bool { + if host, _, err := net.SplitHostPort(addr); err == nil { + addr = host + } + return addr == "" || net.ParseIP(addr).IsUnspecified() +} + +// retry executes f every interval seconds until timeout or no error is returned from f. +func retry(interval time.Duration, stopc <-chan struct{}, f func() error) error { + tick := time.NewTicker(interval) + defer tick.Stop() + + var err error + for { + if err = f(); err == nil { + return nil + } + select { + case <-stopc: + return err + case <-tick.C: + } + } +} + +func removeOldPeer(old []peer, addr string) []peer { + new := make([]peer, 0, len(old)) + for _, p := range old { + if p.Address() != addr { + new = append(new, p) + } + } + + return new +} diff --git a/vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.pb.go b/vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.pb.go new file mode 100644 index 00000000000..34ae90b702a --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.pb.go @@ -0,0 +1,476 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cluster.proto + +/* + Package clusterpb is a generated protocol buffer package. + + It is generated from these files: + cluster.proto + + It has these top-level messages: + Part + FullState +*/ +package clusterpb + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type Part struct { + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *Part) Reset() { *m = Part{} } +func (m *Part) String() string { return proto.CompactTextString(m) } +func (*Part) ProtoMessage() {} +func (*Part) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{0} } + +type FullState struct { + Parts []Part `protobuf:"bytes,1,rep,name=parts" json:"parts"` +} + +func (m *FullState) Reset() { *m = FullState{} } +func (m *FullState) String() string { return proto.CompactTextString(m) } +func (*FullState) ProtoMessage() {} +func (*FullState) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{1} } + +func init() { + proto.RegisterType((*Part)(nil), "clusterpb.Part") + proto.RegisterType((*FullState)(nil), "clusterpb.FullState") +} +func (m *Part) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Part) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Key) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintCluster(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + } + if len(m.Data) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintCluster(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + return i, nil +} + +func (m *FullState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FullState) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Parts) > 0 { + for _, msg := range m.Parts { + dAtA[i] = 0xa + i++ + i = encodeVarintCluster(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func encodeVarintCluster(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Part) Size() (n int) { + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovCluster(uint64(l)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovCluster(uint64(l)) + } + return n +} + +func (m *FullState) Size() (n int) { + var l int + _ = l + if len(m.Parts) > 0 { + for _, e := range m.Parts { + l = e.Size() + n += 1 + l + sovCluster(uint64(l)) + } + } + return n +} + +func sovCluster(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozCluster(x uint64) (n int) { + return sovCluster(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Part) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCluster + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Part: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Part: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCluster + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCluster + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCluster + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCluster + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCluster(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCluster + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *FullState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCluster + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FullState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FullState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Parts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCluster + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCluster + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Parts = append(m.Parts, Part{}) + if err := m.Parts[len(m.Parts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCluster(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCluster + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCluster(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCluster + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCluster + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCluster + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthCluster + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCluster + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipCluster(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthCluster = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCluster = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("cluster.proto", fileDescriptorCluster) } + +var fileDescriptorCluster = []byte{ + // 168 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0xce, 0x29, 0x2d, + 0x2e, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x72, 0x0b, 0x92, 0xa4, + 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xa2, 0xfa, 0x20, 0x16, 0x44, 0x81, 0x92, 0x0e, 0x17, 0x4b, + 0x40, 0x62, 0x51, 0x89, 0x90, 0x00, 0x17, 0x73, 0x76, 0x6a, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, + 0x67, 0x10, 0x88, 0x29, 0x24, 0xc4, 0xc5, 0x92, 0x92, 0x58, 0x92, 0x28, 0xc1, 0xa4, 0xc0, 0xa8, + 0xc1, 0x13, 0x04, 0x66, 0x2b, 0x59, 0x70, 0x71, 0xba, 0x95, 0xe6, 0xe4, 0x04, 0x97, 0x24, 0x96, + 0xa4, 0x0a, 0x69, 0x73, 0xb1, 0x16, 0x24, 0x16, 0x95, 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70, + 0x1b, 0xf1, 0xeb, 0xc1, 0xed, 0xd2, 0x03, 0x19, 0xe9, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, + 0x44, 0x8d, 0x93, 0xc0, 0x89, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, + 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x12, 0x1b, 0xd8, 0x01, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xfd, 0x3c, 0xdb, 0xe7, 0xb2, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.proto b/vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.proto new file mode 100644 index 00000000000..5387a6f7713 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/cluster/clusterpb/cluster.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package clusterpb; +import "gogoproto/gogo.proto"; + +option (gogoproto.marshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.goproto_getters_all) = false; + +message Part { + string key = 1; + bytes data = 2; +} + +message FullState { + repeated Part parts = 1 [(gogoproto.nullable) = false]; +} diff --git a/vendor/github.com/prometheus/alertmanager/cluster/delegate.go b/vendor/github.com/prometheus/alertmanager/cluster/delegate.go new file mode 100644 index 00000000000..9c00318d529 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/cluster/delegate.go @@ -0,0 +1,241 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cluster + +import ( + "time" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/gogo/protobuf/proto" + "github.com/hashicorp/memberlist" + "github.com/prometheus/alertmanager/cluster/clusterpb" + "github.com/prometheus/client_golang/prometheus" +) + +// Maximum number of messages to be held in the queue. +const maxQueueSize = 4096 + +// delegate implements memberlist.Delegate and memberlist.EventDelegate +// and broadcasts its peer's state in the cluster. +type delegate struct { + *Peer + + logger log.Logger + bcast *memberlist.TransmitLimitedQueue + + messagesReceived *prometheus.CounterVec + messagesReceivedSize *prometheus.CounterVec + messagesSent *prometheus.CounterVec + messagesSentSize *prometheus.CounterVec + messagesPruned prometheus.Counter +} + +func newDelegate(l log.Logger, reg prometheus.Registerer, p *Peer, retransmit int) *delegate { + bcast := &memberlist.TransmitLimitedQueue{ + NumNodes: p.ClusterSize, + RetransmitMult: retransmit, + } + messagesReceived := prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "alertmanager_cluster_messages_received_total", + Help: "Total number of cluster messsages received.", + }, []string{"msg_type"}) + messagesReceivedSize := prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "alertmanager_cluster_messages_received_size_total", + Help: "Total size of cluster messages received.", + }, []string{"msg_type"}) + messagesSent := prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "alertmanager_cluster_messages_sent_total", + Help: "Total number of cluster messsages sent.", + }, []string{"msg_type"}) + messagesSentSize := prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "alertmanager_cluster_messages_sent_size_total", + Help: "Total size of cluster messages sent.", + }, []string{"msg_type"}) + messagesPruned := prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_cluster_messages_pruned_total", + Help: "Total number of cluster messsages pruned.", + }) + gossipClusterMembers := prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "alertmanager_cluster_members", + Help: "Number indicating current number of members in cluster.", + }, func() float64 { + return float64(p.ClusterSize()) + }) + peerPosition := prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "alertmanager_peer_position", + Help: "Position the Alertmanager instance believes it's in. The position determines a peer's behavior in the cluster.", + }, func() float64 { + return float64(p.Position()) + }) + healthScore := prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "alertmanager_cluster_health_score", + Help: "Health score of the cluster. Lower values are better and zero means 'totally healthy'.", + }, func() float64 { + return float64(p.mlist.GetHealthScore()) + }) + messagesQueued := prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "alertmanager_cluster_messages_queued", + Help: "Number of cluster messsages which are queued.", + }, func() float64 { + return float64(bcast.NumQueued()) + }) + + messagesReceived.WithLabelValues("full_state") + messagesReceivedSize.WithLabelValues("full_state") + messagesReceived.WithLabelValues("update") + messagesReceivedSize.WithLabelValues("update") + messagesSent.WithLabelValues("full_state") + messagesSentSize.WithLabelValues("full_state") + messagesSent.WithLabelValues("update") + messagesSentSize.WithLabelValues("update") + + reg.MustRegister(messagesReceived, messagesReceivedSize, messagesSent, messagesSentSize, + gossipClusterMembers, peerPosition, healthScore, messagesQueued, messagesPruned) + + d := &delegate{ + logger: l, + Peer: p, + bcast: bcast, + messagesReceived: messagesReceived, + messagesReceivedSize: messagesReceivedSize, + messagesSent: messagesSent, + messagesSentSize: messagesSentSize, + messagesPruned: messagesPruned, + } + + go d.handleQueueDepth() + + return d +} + +// NodeMeta retrieves meta-data about the current node when broadcasting an alive message. +func (d *delegate) NodeMeta(limit int) []byte { + return []byte{} +} + +// NotifyMsg is the callback invoked when a user-level gossip message is received. +func (d *delegate) NotifyMsg(b []byte) { + d.messagesReceived.WithLabelValues("update").Inc() + d.messagesReceivedSize.WithLabelValues("update").Add(float64(len(b))) + + var p clusterpb.Part + if err := proto.Unmarshal(b, &p); err != nil { + level.Warn(d.logger).Log("msg", "decode broadcast", "err", err) + return + } + + s, ok := d.states[p.Key] + if !ok { + return + } + if err := s.Merge(p.Data); err != nil { + level.Warn(d.logger).Log("msg", "merge broadcast", "err", err, "key", p.Key) + return + } +} + +// GetBroadcasts is called when user data messages can be broadcasted. +func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte { + msgs := d.bcast.GetBroadcasts(overhead, limit) + d.messagesSent.WithLabelValues("update").Add(float64(len(msgs))) + for _, m := range msgs { + d.messagesSentSize.WithLabelValues("update").Add(float64(len(m))) + } + return msgs +} + +// LocalState is called when gossip fetches local state. +func (d *delegate) LocalState(_ bool) []byte { + all := &clusterpb.FullState{ + Parts: make([]clusterpb.Part, 0, len(d.states)), + } + + for key, s := range d.states { + b, err := s.MarshalBinary() + if err != nil { + level.Warn(d.logger).Log("msg", "encode local state", "err", err, "key", key) + return nil + } + all.Parts = append(all.Parts, clusterpb.Part{Key: key, Data: b}) + } + b, err := proto.Marshal(all) + if err != nil { + level.Warn(d.logger).Log("msg", "encode local state", "err", err) + return nil + } + d.messagesSent.WithLabelValues("full_state").Inc() + d.messagesSentSize.WithLabelValues("full_state").Add(float64(len(b))) + return b +} + +func (d *delegate) MergeRemoteState(buf []byte, _ bool) { + d.messagesReceived.WithLabelValues("full_state").Inc() + d.messagesReceivedSize.WithLabelValues("full_state").Add(float64(len(buf))) + + var fs clusterpb.FullState + if err := proto.Unmarshal(buf, &fs); err != nil { + level.Warn(d.logger).Log("msg", "merge remote state", "err", err) + return + } + d.mtx.RLock() + defer d.mtx.RUnlock() + for _, p := range fs.Parts { + s, ok := d.states[p.Key] + if !ok { + level.Warn(d.logger).Log("received", "unknown state key", "len", len(buf), "key", p.Key) + continue + } + if err := s.Merge(p.Data); err != nil { + level.Warn(d.logger).Log("msg", "merge remote state", "err", err, "key", p.Key) + return + } + } +} + +// NotifyJoin is called if a peer joins the cluster. +func (d *delegate) NotifyJoin(n *memberlist.Node) { + level.Debug(d.logger).Log("received", "NotifyJoin", "node", n.Name, "addr", n.Address()) + d.Peer.peerJoin(n) +} + +// NotifyLeave is called if a peer leaves the cluster. +func (d *delegate) NotifyLeave(n *memberlist.Node) { + level.Debug(d.logger).Log("received", "NotifyLeave", "node", n.Name, "addr", n.Address()) + d.Peer.peerLeave(n) +} + +// NotifyUpdate is called if a cluster peer gets updated. +func (d *delegate) NotifyUpdate(n *memberlist.Node) { + level.Debug(d.logger).Log("received", "NotifyUpdate", "node", n.Name, "addr", n.Address()) + d.Peer.peerUpdate(n) +} + +// handleQueueDepth ensures that the queue doesn't grow unbounded by pruning +// older messages at regular interval. +func (d *delegate) handleQueueDepth() { + for { + select { + case <-d.stopc: + return + case <-time.After(15 * time.Minute): + n := d.bcast.NumQueued() + if n > maxQueueSize { + level.Warn(d.logger).Log("msg", "dropping messages because too many are queued", "current", n, "limit", maxQueueSize) + d.bcast.Prune(maxQueueSize) + d.messagesPruned.Add(float64(n - maxQueueSize)) + } + } + } +} diff --git a/vendor/github.com/prometheus/alertmanager/config/config.go b/vendor/github.com/prometheus/alertmanager/config/config.go index 5996543592a..77afda477cd 100644 --- a/vendor/github.com/prometheus/alertmanager/config/config.go +++ b/vendor/github.com/prometheus/alertmanager/config/config.go @@ -23,6 +23,7 @@ import ( "strings" "time" + commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" "gopkg.in/yaml.v2" ) @@ -52,7 +53,7 @@ func (s Secret) MarshalJSON() ([]byte, error) { // Load parses the YAML input s into a Config. func Load(s string) (*Config, error) { cfg := &Config{} - err := yaml.Unmarshal([]byte(s), cfg) + err := yaml.UnmarshalStrict([]byte(s), cfg) if err != nil { return nil, err } @@ -110,24 +111,10 @@ type Config struct { Receivers []*Receiver `yaml:"receivers,omitempty" json:"receivers,omitempty"` Templates []string `yaml:"templates" json:"templates"` - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` - // original is the input from which the config was parsed. original string } -func checkOverflow(m map[string]interface{}, ctx string) error { - if len(m) > 0 { - var keys []string - for k := range m { - keys = append(keys, k) - } - return fmt.Errorf("unknown fields in %s: %s", ctx, strings.Join(keys, ", ")) - } - return nil -} - func (c Config) String() string { b, err := yaml.Marshal(c) if err != nil { @@ -159,6 +146,11 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { if _, ok := names[rcv.Name]; ok { return fmt.Errorf("notification config name %q is not unique", rcv.Name) } + for _, wh := range rcv.WebhookConfigs { + if wh.HTTPConfig == nil { + wh.HTTPConfig = c.Global.HTTPConfig + } + } for _, ec := range rcv.EmailConfigs { if ec.Smarthost == "" { if c.Global.SMTPSmarthost == "" { @@ -193,6 +185,9 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } } for _, sc := range rcv.SlackConfigs { + if sc.HTTPConfig == nil { + sc.HTTPConfig = c.Global.HTTPConfig + } if sc.APIURL == "" { if c.Global.SlackAPIURL == "" { return fmt.Errorf("no global Slack API URL set") @@ -201,6 +196,9 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } } for _, hc := range rcv.HipchatConfigs { + if hc.HTTPConfig == nil { + hc.HTTPConfig = c.Global.HTTPConfig + } if hc.APIURL == "" { if c.Global.HipchatAPIURL == "" { return fmt.Errorf("no global Hipchat API URL set") @@ -217,7 +215,15 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { hc.AuthToken = c.Global.HipchatAuthToken } } + for _, poc := range rcv.PushoverConfigs { + if poc.HTTPConfig == nil { + poc.HTTPConfig = c.Global.HTTPConfig + } + } for _, pdc := range rcv.PagerdutyConfigs { + if pdc.HTTPConfig == nil { + pdc.HTTPConfig = c.Global.HTTPConfig + } if pdc.URL == "" { if c.Global.PagerdutyURL == "" { return fmt.Errorf("no global PagerDuty URL set") @@ -226,6 +232,9 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } } for _, ogc := range rcv.OpsGenieConfigs { + if ogc.HTTPConfig == nil { + ogc.HTTPConfig = c.Global.HTTPConfig + } if ogc.APIURL == "" { if c.Global.OpsGenieAPIURL == "" { return fmt.Errorf("no global OpsGenie URL set") @@ -235,31 +244,47 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { if !strings.HasSuffix(ogc.APIURL, "/") { ogc.APIURL += "/" } + if ogc.APIKey == "" { + if c.Global.OpsGenieAPIKey == "" { + return fmt.Errorf("no global OpsGenie API Key set") + } + ogc.APIKey = c.Global.OpsGenieAPIKey + } } for _, wcc := range rcv.WechatConfigs { - wcc.APIURL = c.Global.WeChatAPIURL + if wcc.HTTPConfig == nil { + wcc.HTTPConfig = c.Global.HTTPConfig + } + if wcc.APIURL == "" { if c.Global.WeChatAPIURL == "" { return fmt.Errorf("no global Wechat URL set") } + wcc.APIURL = c.Global.WeChatAPIURL } - wcc.APISecret = c.Global.WeChatAPISecret + if wcc.APISecret == "" { if c.Global.WeChatAPISecret == "" { return fmt.Errorf("no global Wechat ApiSecret set") } + wcc.APISecret = c.Global.WeChatAPISecret } + if wcc.CorpID == "" { if c.Global.WeChatAPICorpID == "" { return fmt.Errorf("no global Wechat CorpID set") } wcc.CorpID = c.Global.WeChatAPICorpID } + if !strings.HasSuffix(wcc.APIURL, "/") { wcc.APIURL += "/" } } for _, voc := range rcv.VictorOpsConfigs { + if voc.HTTPConfig == nil { + voc.HTTPConfig = c.Global.HTTPConfig + } if voc.APIURL == "" { if c.Global.VictorOpsAPIURL == "" { return fmt.Errorf("no global VictorOps URL set") @@ -292,11 +317,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } // Validate that all receivers used in the routing tree are defined. - if err := checkReceiver(c.Route, names); err != nil { - return err - } - - return checkOverflow(c.XXX, "config") + return checkReceiver(c.Route, names) } // checkReceiver returns an error if a node in the routing tree @@ -319,7 +340,9 @@ func checkReceiver(r *Route, receivers map[string]struct{}) error { // DefaultGlobalConfig provides global default values. var DefaultGlobalConfig = GlobalConfig{ ResolveTimeout: model.Duration(5 * time.Minute), + HTTPConfig: &commoncfg.HTTPClientConfig{}, + SMTPHello: "localhost", SMTPRequireTLS: true, PagerdutyURL: "https://events.pagerduty.com/v2/enqueue", HipchatAPIURL: "https://api.hipchat.com/", @@ -335,6 +358,8 @@ type GlobalConfig struct { // if it has not been updated. ResolveTimeout model.Duration `yaml:"resolve_timeout" json:"resolve_timeout"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + SMTPFrom string `yaml:"smtp_from,omitempty" json:"smtp_from,omitempty"` SMTPHello string `yaml:"smtp_hello,omitempty" json:"smtp_hello,omitempty"` SMTPSmarthost string `yaml:"smtp_smarthost,omitempty" json:"smtp_smarthost,omitempty"` @@ -348,24 +373,19 @@ type GlobalConfig struct { HipchatAPIURL string `yaml:"hipchat_api_url,omitempty" json:"hipchat_api_url,omitempty"` HipchatAuthToken Secret `yaml:"hipchat_auth_token,omitempty" json:"hipchat_auth_token,omitempty"` OpsGenieAPIURL string `yaml:"opsgenie_api_url,omitempty" json:"opsgenie_api_url,omitempty"` + OpsGenieAPIKey Secret `yaml:"opsgenie_api_key,omitempty" json:"opsgenie_api_key,omitempty"` WeChatAPIURL string `yaml:"wechat_api_url,omitempty" json:"wechat_api_url,omitempty"` - WeChatAPISecret string `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"` + WeChatAPISecret Secret `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"` WeChatAPICorpID string `yaml:"wechat_api_corp_id,omitempty" json:"wechat_api_corp_id,omitempty"` VictorOpsAPIURL string `yaml:"victorops_api_url,omitempty" json:"victorops_api_url,omitempty"` VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. func (c *GlobalConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { *c = DefaultGlobalConfig type plain GlobalConfig - if err := unmarshal((*plain)(c)); err != nil { - return err - } - return checkOverflow(c.XXX, "global") + return unmarshal((*plain)(c)) } // A Route is a node that contains definitions of how to handle alerts. @@ -381,9 +401,6 @@ type Route struct { GroupWait *model.Duration `yaml:"group_wait,omitempty" json:"group_wait,omitempty"` GroupInterval *model.Duration `yaml:"group_interval,omitempty" json:"group_interval,omitempty"` RepeatInterval *model.Duration `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -414,7 +431,14 @@ func (r *Route) UnmarshalYAML(unmarshal func(interface{}) error) error { groupBy[ln] = struct{}{} } - return checkOverflow(r.XXX, "route") + if r.GroupInterval != nil && time.Duration(*r.GroupInterval) == time.Duration(0) { + return fmt.Errorf("group_interval cannot be zero") + } + if r.RepeatInterval != nil && time.Duration(*r.RepeatInterval) == time.Duration(0) { + return fmt.Errorf("repeat_interval cannot be zero") + } + + return nil } // InhibitRule defines an inhibition rule that mutes alerts that match the @@ -436,9 +460,6 @@ type InhibitRule struct { // A set of labels that must be equal between the source and target alert // for them to be a match. Equal model.LabelNames `yaml:"equal,omitempty" json:"equal,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -472,7 +493,7 @@ func (r *InhibitRule) UnmarshalYAML(unmarshal func(interface{}) error) error { } } - return checkOverflow(r.XXX, "inhibit rule") + return nil } // Receiver configuration provides configuration on how to contact a receiver. @@ -489,9 +510,6 @@ type Receiver struct { WechatConfigs []*WechatConfig `yaml:"wechat_configs,omitempty" json:"wechat_configs,omitempty"` PushoverConfigs []*PushoverConfig `yaml:"pushover_configs,omitempty" json:"pushover_configs,omitempty"` VictorOpsConfigs []*VictorOpsConfig `yaml:"victorops_configs,omitempty" json:"victorops_configs,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -503,7 +521,7 @@ func (c *Receiver) UnmarshalYAML(unmarshal func(interface{}) error) error { if c.Name == "" { return fmt.Errorf("missing name in receiver") } - return checkOverflow(c.XXX, "receiver config") + return nil } // Regexp encapsulates a regexp.Regexp and makes it YAML marshalable. diff --git a/vendor/github.com/prometheus/alertmanager/config/notifiers.go b/vendor/github.com/prometheus/alertmanager/config/notifiers.go index e92736a7520..ba4517e8852 100644 --- a/vendor/github.com/prometheus/alertmanager/config/notifiers.go +++ b/vendor/github.com/prometheus/alertmanager/config/notifiers.go @@ -18,6 +18,8 @@ import ( "net/url" "strings" "time" + + commoncfg "github.com/prometheus/common/config" ) var ( @@ -40,6 +42,14 @@ var ( // DefaultEmailSubject defines the default Subject header of an Email. DefaultEmailSubject = `{{ template "email.default.subject" . }}` + // DefaultPagerdutyDetails defines the default values for PagerDuty details. + DefaultPagerdutyDetails = map[string]string{ + "firing": `{{ template "pagerduty.default.instances" .Alerts.Firing }}`, + "resolved": `{{ template "pagerduty.default.instances" .Alerts.Resolved }}`, + "num_firing": `{{ .Alerts.Firing | len }}`, + "num_resolved": `{{ .Alerts.Resolved | len }}`, + } + // DefaultPagerdutyConfig defines default values for PagerDuty configurations. DefaultPagerdutyConfig = PagerdutyConfig{ NotifierConfig: NotifierConfig{ @@ -48,12 +58,6 @@ var ( Description: `{{ template "pagerduty.default.description" .}}`, Client: `{{ template "pagerduty.default.client" . }}`, ClientURL: `{{ template "pagerduty.default.clientURL" . }}`, - Details: map[string]string{ - "firing": `{{ template "pagerduty.default.instances" .Alerts.Firing }}`, - "resolved": `{{ template "pagerduty.default.instances" .Alerts.Resolved }}`, - "num_firing": `{{ .Alerts.Firing | len }}`, - "num_resolved": `{{ .Alerts.Resolved | len }}`, - }, } // DefaultSlackConfig defines default values for Slack configurations. @@ -99,16 +103,14 @@ var ( // DefaultWechatConfig defines default values for wechat configurations. DefaultWechatConfig = WechatConfig{ NotifierConfig: NotifierConfig{ - VSendResolved: true, + VSendResolved: false, }, Message: `{{ template "wechat.default.message" . }}`, - APIURL: `{{ template "wechat.default.api_url" . }}`, APISecret: `{{ template "wechat.default.api_secret" . }}`, ToUser: `{{ template "wechat.default.to_user" . }}`, ToParty: `{{ template "wechat.default.to_party" . }}`, ToTag: `{{ template "wechat.default.to_tag" . }}`, AgentID: `{{ template "wechat.default.agent_id" . }}`, - // TODO: Add a details field with all the alerts. } // DefaultVictorOpsConfig defines default values for VictorOps configurations. @@ -162,9 +164,6 @@ type EmailConfig struct { HTML string `yaml:"html,omitempty" json:"html,omitempty"` Text string `yaml:"text,omitempty" json:"text,omitempty"` RequireTLS *bool `yaml:"require_tls,omitempty" json:"require_tls,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -188,13 +187,15 @@ func (c *EmailConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { } c.Headers = normalizedHeaders - return checkOverflow(c.XXX, "email config") + return nil } // PagerdutyConfig configures notifications via PagerDuty. type PagerdutyConfig struct { NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + ServiceKey Secret `yaml:"service_key,omitempty" json"service_key,omitempty"` RoutingKey Secret `yaml:"routing_key,omitempty" json:"routing_key,omitempty"` URL string `yaml:"url,omitempty" json:"url,omitempty"` @@ -203,11 +204,9 @@ type PagerdutyConfig struct { Description string `yaml:"description,omitempty" json:"description,omitempty"` Details map[string]string `yaml:"details,omitempty" json:"details,omitempty"` Severity string `yaml:"severity,omitempty" json:"severity,omitempty"` + Class string `yaml:"class,omitempty" json:"class,omitempty"` Component string `yaml:"component,omitempty" json:"component,omitempty"` Group string `yaml:"group,omitempty" json:"group,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -220,13 +219,76 @@ func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(interface{}) error) error if c.RoutingKey == "" && c.ServiceKey == "" { return fmt.Errorf("missing service or routing key in PagerDuty config") } - return checkOverflow(c.XXX, "pagerduty config") + if c.Details == nil { + c.Details = make(map[string]string) + } + for k, v := range DefaultPagerdutyDetails { + if _, ok := c.Details[k]; !ok { + c.Details[k] = v + } + } + return nil +} + +// SlackAction configures a single Slack action that is sent with each notification. +// Each action must contain a type, text, and url. +// See https://api.slack.com/docs/message-attachments#action_fields for more information. +type SlackAction struct { + Type string `yaml:"type,omitempty" json:"type,omitempty"` + Text string `yaml:"text,omitempty" json:"text,omitempty"` + URL string `yaml:"url,omitempty" json:"url,omitempty"` + Style string `yaml:"style,omitempty" json:"style,omitempty"` +} + +// UnmarshalYAML implements the yaml.Unmarshaler interface for SlackAction. +func (c *SlackAction) UnmarshalYAML(unmarshal func(interface{}) error) error { + type plain SlackAction + if err := unmarshal((*plain)(c)); err != nil { + return err + } + if c.Type == "" { + return fmt.Errorf("missing type in Slack action configuration") + } + if c.Text == "" { + return fmt.Errorf("missing value in Slack text configuration") + } + if c.URL == "" { + return fmt.Errorf("missing value in Slack url configuration") + } + return nil +} + +// SlackField configures a single Slack field that is sent with each notification. +// Each field must contain a title, value, and optionally, a boolean value to indicate if the field +// is short enough to be displayed next to other fields designated as short. +// See https://api.slack.com/docs/message-attachments#fields for more information. +type SlackField struct { + Title string `yaml:"title,omitempty" json:"title,omitempty"` + Value string `yaml:"value,omitempty" json:"value,omitempty"` + Short *bool `yaml:"short,omitempty" json:"short,omitempty"` +} + +// UnmarshalYAML implements the yaml.Unmarshaler interface for SlackField. +func (c *SlackField) UnmarshalYAML(unmarshal func(interface{}) error) error { + type plain SlackField + if err := unmarshal((*plain)(c)); err != nil { + return err + } + if c.Title == "" { + return fmt.Errorf("missing title in Slack field configuration") + } + if c.Value == "" { + return fmt.Errorf("missing value in Slack field configuration") + } + return nil } // SlackConfig configures notifications via Slack. type SlackConfig struct { NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + APIURL Secret `yaml:"api_url,omitempty" json:"api_url,omitempty"` // Slack channel override, (like #other-channel or @username). @@ -234,36 +296,33 @@ type SlackConfig struct { Username string `yaml:"username,omitempty" json:"username,omitempty"` Color string `yaml:"color,omitempty" json:"color,omitempty"` - Title string `yaml:"title,omitempty" json:"title,omitempty"` - TitleLink string `yaml:"title_link,omitempty" json:"title_link,omitempty"` - Pretext string `yaml:"pretext,omitempty" json:"pretext,omitempty"` - Text string `yaml:"text,omitempty" json:"text,omitempty"` - Fields []map[string]string `yaml:"fields,omitempty" json:"fields,omitempty"` - ShortFields bool `yaml:"short_fields,omitempty" json:"short_fields,omitempty"` - Footer string `yaml:"footer,omitempty" json:"footer,omitempty"` - Fallback string `yaml:"fallback,omitempty" json:"fallback,omitempty"` - IconEmoji string `yaml:"icon_emoji,omitempty" json:"icon_emoji,omitempty"` - IconURL string `yaml:"icon_url,omitempty" json:"icon_url,omitempty"` - LinkNames bool `yaml:"link_names,omitempty" json:"link_names,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` + Title string `yaml:"title,omitempty" json:"title,omitempty"` + TitleLink string `yaml:"title_link,omitempty" json:"title_link,omitempty"` + Pretext string `yaml:"pretext,omitempty" json:"pretext,omitempty"` + Text string `yaml:"text,omitempty" json:"text,omitempty"` + Fields []*SlackField `yaml:"fields,omitempty" json:"fields,omitempty"` + ShortFields bool `yaml:"short_fields,omitempty" json:"short_fields,omitempty"` + Footer string `yaml:"footer,omitempty" json:"footer,omitempty"` + Fallback string `yaml:"fallback,omitempty" json:"fallback,omitempty"` + IconEmoji string `yaml:"icon_emoji,omitempty" json:"icon_emoji,omitempty"` + IconURL string `yaml:"icon_url,omitempty" json:"icon_url,omitempty"` + LinkNames bool `yaml:"link_names,omitempty" json:"link_names,omitempty"` + Actions []*SlackAction `yaml:"actions,omitempty" json:"actions,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. func (c *SlackConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { *c = DefaultSlackConfig type plain SlackConfig - if err := unmarshal((*plain)(c)); err != nil { - return err - } - return checkOverflow(c.XXX, "slack config") + return unmarshal((*plain)(c)) } // HipchatConfig configures notifications via Hipchat. type HipchatConfig struct { NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + APIURL string `yaml:"api_url,omitempty" json:"api_url,omitempty"` AuthToken Secret `yaml:"auth_token,omitempty" json:"auth_token,omitempty"` RoomID string `yaml:"room_id,omitempty" json:"room_id,omitempty"` @@ -272,9 +331,6 @@ type HipchatConfig struct { Message string `yaml:"message,omitempty" json:"message,omitempty"` MessageFormat string `yaml:"message_format,omitempty" json:"message_format,omitempty"` Color string `yaml:"color,omitempty" json:"color,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" ,json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -287,19 +343,17 @@ func (c *HipchatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { if c.RoomID == "" { return fmt.Errorf("missing room id in Hipchat config") } - - return checkOverflow(c.XXX, "hipchat config") + return nil } // WebhookConfig configures notifications via a generic webhook. type WebhookConfig struct { NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + // URL to send POST request to. URL string `yaml:"url" json:"url"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -320,14 +374,16 @@ func (c *WebhookConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { return fmt.Errorf("scheme required for webhook url") } c.URL = url.String() - return checkOverflow(c.XXX, "webhook config") + return nil } // WechatConfig configures notifications via Wechat. type WechatConfig struct { NotifierConfig `yaml:",inline" json:",inline"` - APISecret string `yaml:"api_secret,omitempty" json:"api_secret,omitempty"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + + APISecret Secret `yaml:"api_secret,omitempty" json:"api_secret,omitempty"` CorpID string `yaml:"corp_id,omitempty" json:"corp_id,omitempty"` Message string `yaml:"message,omitempty" json:"message,omitempty"` APIURL string `yaml:"api_url,omitempty" json:"api_url,omitempty"` @@ -335,9 +391,6 @@ type WechatConfig struct { ToParty string `yaml:"to_party,omitempty" json:"to_party,omitempty"` ToTag string `yaml:"to_tag,omitempty" json:"to_tag,omitempty"` AgentID string `yaml:"agent_id,omitempty" json:"agent_id,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -353,13 +406,15 @@ func (c *WechatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { if c.CorpID == "" { return fmt.Errorf("missing Wechat CorpID in Wechat config") } - return checkOverflow(c.XXX, "Wechat config") + return nil } // OpsGenieConfig configures notifications via OpsGenie. type OpsGenieConfig struct { NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + APIKey Secret `yaml:"api_key,omitempty" json:"api_key,omitempty"` APIURL string `yaml:"api_url,omitempty" json:"api_url,omitempty"` Message string `yaml:"message,omitempty" json:"message,omitempty"` @@ -370,28 +425,21 @@ type OpsGenieConfig struct { Tags string `yaml:"tags,omitempty" json:"tags,omitempty"` Note string `yaml:"note,omitempty" json:"note,omitempty"` Priority string `yaml:"priority,omitempty" json:"priority,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. func (c *OpsGenieConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { *c = DefaultOpsGenieConfig type plain OpsGenieConfig - if err := unmarshal((*plain)(c)); err != nil { - return err - } - if c.APIKey == "" { - return fmt.Errorf("missing API key in OpsGenie config") - } - return checkOverflow(c.XXX, "opsgenie config") + return unmarshal((*plain)(c)) } // VictorOpsConfig configures notifications via VictorOps. type VictorOpsConfig struct { NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + APIKey Secret `yaml:"api_key" json:"api_key"` APIURL string `yaml:"api_url" json:"api_url"` RoutingKey string `yaml:"routing_key" json:"routing_key"` @@ -399,8 +447,6 @@ type VictorOpsConfig struct { StateMessage string `yaml:"state_message" json:"state_message"` EntityDisplayName string `yaml:"entity_display_name" json:"entity_display_name"` MonitoringTool string `yaml:"monitoring_tool" json:"monitoring_tool"` - - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -413,7 +459,7 @@ func (c *VictorOpsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error if c.RoutingKey == "" { return fmt.Errorf("missing Routing key in VictorOps config") } - return checkOverflow(c.XXX, "victorops config") + return nil } type duration time.Duration @@ -433,6 +479,8 @@ func (d duration) MarshalText() ([]byte, error) { type PushoverConfig struct { NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + UserKey Secret `yaml:"user_key,omitempty" json:"user_key,omitempty"` Token Secret `yaml:"token,omitempty" json:"token,omitempty"` Title string `yaml:"title,omitempty" json:"title,omitempty"` @@ -441,9 +489,6 @@ type PushoverConfig struct { Priority string `yaml:"priority,omitempty" json:"priority,omitempty"` Retry duration `yaml:"retry,omitempty" json:"retry,omitempty"` Expire duration `yaml:"expire,omitempty" json:"expire,omitempty"` - - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `yaml:",inline" json:"-"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -459,5 +504,5 @@ func (c *PushoverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error if c.Token == "" { return fmt.Errorf("missing token in Pushover config") } - return checkOverflow(c.XXX, "pushover config") + return nil } diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go index f8461e97e21..892a08f9620 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go @@ -1,3 +1,16 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package dispatch import ( @@ -247,12 +260,13 @@ func (d *Dispatcher) processAlert(alert *types.Alert, route *Route) { fp := groupLabels.Fingerprint() d.mtx.Lock() + defer d.mtx.Unlock() + group, ok := d.aggrGroups[route] if !ok { group = map[model.Fingerprint]*aggrGroup{} d.aggrGroups[route] = group } - d.mtx.Unlock() // If the group does not exist, create it. ag, ok := group[fp] @@ -287,9 +301,9 @@ type aggrGroup struct { next *time.Timer timeout func(time.Duration) time.Duration - mtx sync.RWMutex - alerts map[model.Fingerprint]*types.Alert - hasSent bool + mtx sync.RWMutex + alerts map[model.Fingerprint]*types.Alert + hasFlushed bool } // newAggrGroup returns a new aggregation group. @@ -366,6 +380,7 @@ func (ag *aggrGroup) run(nf notifyFunc) { // Wait the configured interval before calling flush again. ag.mtx.Lock() ag.next.Reset(ag.opts.GroupInterval) + ag.hasFlushed = true ag.mtx.Unlock() ag.flush(func(alerts ...*types.Alert) bool { @@ -387,8 +402,7 @@ func (ag *aggrGroup) stop() { <-ag.done } -// insert inserts the alert into the aggregation group. If the aggregation group -// is empty afterwards, it returns true. +// insert inserts the alert into the aggregation group. func (ag *aggrGroup) insert(alert *types.Alert) { ag.mtx.Lock() defer ag.mtx.Unlock() @@ -397,7 +411,7 @@ func (ag *aggrGroup) insert(alert *types.Alert) { // Immediately trigger a flush if the wait duration for this // alert is already over. - if !ag.hasSent && alert.StartsAt.Add(ag.opts.GroupWait).Before(time.Now()) { + if !ag.hasFlushed && alert.StartsAt.Add(ag.opts.GroupWait).Before(time.Now()) { ag.next.Reset(0) } } @@ -418,12 +432,13 @@ func (ag *aggrGroup) flush(notify func(...*types.Alert) bool) { var ( alerts = make(map[model.Fingerprint]*types.Alert, len(ag.alerts)) - alertsSlice = make([]*types.Alert, 0, len(ag.alerts)) + alertsSlice = make(types.AlertSlice, 0, len(ag.alerts)) ) for fp, alert := range ag.alerts { alerts[fp] = alert alertsSlice = append(alertsSlice, alert) } + sort.Stable(alertsSlice) ag.mtx.Unlock() @@ -438,8 +453,6 @@ func (ag *aggrGroup) flush(notify func(...*types.Alert) bool) { delete(ag.alerts, fp) } } - - ag.hasSent = true ag.mtx.Unlock() } } diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/route.go b/vendor/github.com/prometheus/alertmanager/dispatch/route.go index 4f7a67a368d..add2afb64b0 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/route.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/route.go @@ -31,9 +31,7 @@ var DefaultRouteOpts = RouteOpts{ GroupWait: 30 * time.Second, GroupInterval: 5 * time.Minute, RepeatInterval: 4 * time.Hour, - GroupBy: map[model.LabelName]struct{}{ - model.AlertNameLabel: struct{}{}, - }, + GroupBy: map[model.LabelName]struct{}{}, } // A Route is a node that contains definitions of how to handle alerts. @@ -154,14 +152,14 @@ func (r *Route) Key() string { // RouteOpts holds various routing options necessary for processing alerts // that match a given route. type RouteOpts struct { - // The identifier of the associated notification configuration + // The identifier of the associated notification configuration. Receiver string // What labels to group alerts by for notifications. GroupBy map[model.LabelName]struct{} // How long to wait to group matching alerts before sending - // a notificaiton + // a notification. GroupWait time.Duration GroupInterval time.Duration RepeatInterval time.Duration diff --git a/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go b/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go index b1c61920512..80575ec73e8 100644 --- a/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go +++ b/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go @@ -15,7 +15,6 @@ package inhibit import ( "context" - "fmt" "sync" "time" @@ -81,12 +80,7 @@ func (ih *Inhibitor) run(ctx context.Context) { level.Error(ih.logger).Log("msg", "Error iterating alerts", "err", err) continue } - if a.Resolved() { - // As alerts can also time out without an update, we never - // handle new resolved alerts but invalidate the cache on read. - continue - } - // Populate the inhibition rules' cache. + // Update the inhibition rules' cache. for _, r := range ih.rules { if r.SourceMatchers.Match(a.Labels) { r.set(a) @@ -145,7 +139,7 @@ func (ih *Inhibitor) Mutes(lset model.LabelSet) bool { for _, r := range ih.rules { // Only inhibit if target matchers match but source matchers don't. if inhibitedByFP, eq := r.hasEqual(lset); !r.SourceMatchers.Match(lset) && r.TargetMatchers.Match(lset) && eq { - ih.marker.SetInhibited(fp, fmt.Sprintf("%d", inhibitedByFP)) + ih.marker.SetInhibited(fp, inhibitedByFP.String()) return true } } diff --git a/vendor/github.com/prometheus/alertmanager/nflog/nflog.go b/vendor/github.com/prometheus/alertmanager/nflog/nflog.go index 4eb67a327f2..1b65fb1b46e 100644 --- a/vendor/github.com/prometheus/alertmanager/nflog/nflog.go +++ b/vendor/github.com/prometheus/alertmanager/nflog/nflog.go @@ -30,36 +30,16 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/matttproud/golang_protobuf_extensions/pbutil" + "github.com/prometheus/alertmanager/cluster" pb "github.com/prometheus/alertmanager/nflog/nflogpb" "github.com/prometheus/client_golang/prometheus" - "github.com/weaveworks/mesh" ) // ErrNotFound is returned for empty query results. var ErrNotFound = errors.New("not found") -// Log stores and serves information about notifications -// about byte-slice addressed alert objects to different receivers. -type Log interface { - // The Log* methods store a notification log entry for - // a fully qualified receiver and a given IDs identifying the - // alert object. - Log(r *pb.Receiver, key string, firing, resolved []uint64) error - - // Query the log along the given Paramteres. - // - // TODO(fabxc): - // - extend the interface by a `QueryOne` method? - // - return an iterator rather than a materialized list? - Query(p ...QueryParam) ([]*pb.Entry, error) - - // Snapshot the current log state and return the number - // of bytes written. - Snapshot(w io.Writer) (int, error) - // GC removes expired entries from the log. It returns - // the total number of deleted entries. - GC() (int, error) -} +// ErrInvalidState is returned if the state isn't valid. +var ErrInvalidState = fmt.Errorf("invalid state") // query currently allows filtering by and/or receiver group key. // It is configured via QueryParameter functions. @@ -92,7 +72,7 @@ func QGroupKey(gk string) QueryParam { } } -type nlog struct { +type Log struct { logger log.Logger metrics *metrics now func() time.Time @@ -103,24 +83,21 @@ type nlog struct { stopc chan struct{} done func() - gossip mesh.Gossip // gossip channel for sharing log state. - // For now we only store the most recently added log entry. // The key is a serialized concatenation of group key and receiver. - // Currently our memory state is equivalent to the mesh.GossipData - // representation. This may change in the future as we support history - // and indexing. - mtx sync.RWMutex - st gossipData + mtx sync.RWMutex + st state + broadcast func([]byte) } type metrics struct { - gcDuration prometheus.Summary - snapshotDuration prometheus.Summary - snapshotSize prometheus.Gauge - queriesTotal prometheus.Counter - queryErrorsTotal prometheus.Counter - queryDuration prometheus.Histogram + gcDuration prometheus.Summary + snapshotDuration prometheus.Summary + snapshotSize prometheus.Gauge + queriesTotal prometheus.Counter + queryErrorsTotal prometheus.Counter + queryDuration prometheus.Histogram + propagatedMessagesTotal prometheus.Counter } func newMetrics(r prometheus.Registerer) *metrics { @@ -150,34 +127,31 @@ func newMetrics(r prometheus.Registerer) *metrics { Name: "alertmanager_nflog_query_duration_seconds", Help: "Duration of notification log query evaluation.", }) + m.propagatedMessagesTotal = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_nflog_gossip_messages_propagated_total", + Help: "Number of received gossip messages that have been further gossiped.", + }) if r != nil { r.MustRegister( m.gcDuration, m.snapshotDuration, + m.snapshotSize, m.queriesTotal, m.queryErrorsTotal, m.queryDuration, + m.propagatedMessagesTotal, ) } return m } // Option configures a new Log implementation. -type Option func(*nlog) error - -// WithMesh registers the log with a mesh network with which -// the log state will be shared. -func WithMesh(create func(g mesh.Gossiper) mesh.Gossip) Option { - return func(l *nlog) error { - l.gossip = create(l) - return nil - } -} +type Option func(*Log) error // WithRetention sets the retention time for log st. func WithRetention(d time.Duration) Option { - return func(l *nlog) error { + return func(l *Log) error { l.retention = d return nil } @@ -187,7 +161,7 @@ func WithRetention(d time.Duration) Option { // for the current point in time. // This is generally useful for injection during tests. func WithNow(f func() time.Time) Option { - return func(l *nlog) error { + return func(l *Log) error { l.now = f return nil } @@ -195,7 +169,7 @@ func WithNow(f func() time.Time) Option { // WithLogger configures a logger for the notification log. func WithLogger(logger log.Logger) Option { - return func(l *nlog) error { + return func(l *Log) error { l.logger = logger return nil } @@ -203,7 +177,7 @@ func WithLogger(logger log.Logger) Option { // WithMetrics registers metrics for the notification log. func WithMetrics(r prometheus.Registerer) Option { - return func(l *nlog) error { + return func(l *Log) error { l.metrics = newMetrics(r) return nil } @@ -215,7 +189,7 @@ func WithMetrics(r prometheus.Registerer) Option { // The maintenance terminates on receiving from the provided channel. // The done function is called after the final snapshot was completed. func WithMaintenance(d time.Duration, stopc chan struct{}, done func()) Option { - return func(l *nlog) error { + return func(l *Log) error { if d == 0 { return fmt.Errorf("maintenance interval must not be 0") } @@ -230,7 +204,7 @@ func WithMaintenance(d time.Duration, stopc chan struct{}, done func()) Option { // If maintenance is configured, a snapshot will be saved periodically and on // shutdown as well. func WithSnapshot(sf string) Option { - return func(l *nlog) error { + return func(l *Log) error { l.snapf = sf return nil } @@ -240,13 +214,76 @@ func utcNow() time.Time { return time.Now().UTC() } +type state map[string]*pb.MeshEntry + +func (s state) clone() state { + c := make(state, len(s)) + for k, v := range s { + c[k] = v + } + return c +} + +// merge returns true or false whether the MeshEntry was merged or +// not. This information is used to decide to gossip the message further. +func (s state) merge(e *pb.MeshEntry) bool { + k := stateKey(string(e.Entry.GroupKey), e.Entry.Receiver) + + prev, ok := s[k] + if !ok || prev.Entry.Timestamp.Before(e.Entry.Timestamp) { + s[k] = e + return true + } + return false +} + +func (s state) MarshalBinary() ([]byte, error) { + var buf bytes.Buffer + + for _, e := range s { + if _, err := pbutil.WriteDelimited(&buf, e); err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} + +func decodeState(r io.Reader) (state, error) { + st := state{} + for { + var e pb.MeshEntry + _, err := pbutil.ReadDelimited(r, &e) + if err == nil { + if e.Entry == nil || e.Entry.Receiver == nil { + return nil, ErrInvalidState + } + st[stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)] = &e + continue + } + if err == io.EOF { + break + } + return nil, err + } + return st, nil +} + +func marshalMeshEntry(e *pb.MeshEntry) ([]byte, error) { + var buf bytes.Buffer + if _, err := pbutil.WriteDelimited(&buf, e); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + // New creates a new notification log based on the provided options. // The snapshot is loaded into the Log if it is set. -func New(opts ...Option) (Log, error) { - l := &nlog{ - logger: log.NewNopLogger(), - now: utcNow, - st: map[string]*pb.MeshEntry{}, +func New(opts ...Option) (*Log, error) { + l := &Log{ + logger: log.NewNopLogger(), + now: utcNow, + st: state{}, + broadcast: func([]byte) {}, } for _, o := range opts { if err := o(l); err != nil { @@ -276,7 +313,7 @@ func New(opts ...Option) (Log, error) { } // run periodic background maintenance. -func (l *nlog) run() { +func (l *Log) run() { if l.runInterval == 0 || l.stopc == nil { return } @@ -289,10 +326,11 @@ func (l *nlog) run() { f := func() error { start := l.now() - var size int - level.Info(l.logger).Log("msg", "Running maintenance") + var size int64 + + level.Debug(l.logger).Log("msg", "Running maintenance") defer func() { - level.Info(l.logger).Log("msg", "Maintenance done", "duration", l.now().Sub(start), "size", size) + level.Debug(l.logger).Log("msg", "Maintenance done", "duration", l.now().Sub(start), "size", size) l.metrics.snapshotSize.Set(float64(size)) }() @@ -342,7 +380,7 @@ func stateKey(k string, r *pb.Receiver) string { return fmt.Sprintf("%s:%s", k, receiverKey(r)) } -func (l *nlog) Log(r *pb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error { +func (l *Log) Log(r *pb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error { // Write all st with the same timestamp. now := l.now() key := stateKey(gkey, r) @@ -368,18 +406,19 @@ func (l *nlog) Log(r *pb.Receiver, gkey string, firingAlerts, resolvedAlerts []u }, ExpiresAt: now.Add(l.retention), } - if l.gossip != nil { - l.gossip.GossipBroadcast(gossipData{ - key: e, - }) + + b, err := marshalMeshEntry(e) + if err != nil { + return err } - l.st[key] = e + l.st.merge(e) + l.broadcast(b) return nil } // GC implements the Log interface. -func (l *nlog) GC() (int, error) { +func (l *Log) GC() (int, error) { start := time.Now() defer func() { l.metrics.gcDuration.Observe(time.Since(start).Seconds()) }() @@ -403,7 +442,7 @@ func (l *nlog) GC() (int, error) { } // Query implements the Log interface. -func (l *nlog) Query(params ...QueryParam) ([]*pb.Entry, error) { +func (l *Log) Query(params ...QueryParam) ([]*pb.Entry, error) { start := time.Now() l.metrics.queriesTotal.Inc() @@ -438,189 +477,72 @@ func (l *nlog) Query(params ...QueryParam) ([]*pb.Entry, error) { } // loadSnapshot loads a snapshot generated by Snapshot() into the state. -func (l *nlog) loadSnapshot(r io.Reader) error { - l.mtx.Lock() - defer l.mtx.Unlock() - - st := gossipData{} - - for { - var e pb.MeshEntry - if _, err := pbutil.ReadDelimited(r, &e); err != nil { - if err == io.EOF { - break - } - return err - } - st[stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)] = &e +func (l *Log) loadSnapshot(r io.Reader) error { + st, err := decodeState(r) + if err != nil { + return err } + + l.mtx.Lock() l.st = st + l.mtx.Unlock() return nil } // Snapshot implements the Log interface. -func (l *nlog) Snapshot(w io.Writer) (int, error) { +func (l *Log) Snapshot(w io.Writer) (int64, error) { start := time.Now() defer func() { l.metrics.snapshotDuration.Observe(time.Since(start).Seconds()) }() l.mtx.RLock() defer l.mtx.RUnlock() - var n int - for _, e := range l.st { - m, err := pbutil.WriteDelimited(w, e) - if err != nil { - return n + m, err - } - n += m + b, err := l.st.MarshalBinary() + if err != nil { + return 0, err } - return n, nil -} -// Gossip implements the mesh.Gossiper interface. -func (l *nlog) Gossip() mesh.GossipData { - l.mtx.RLock() - defer l.mtx.RUnlock() - - gd := make(gossipData, len(l.st)) - for k, v := range l.st { - gd[k] = v - } - return gd + return io.Copy(w, bytes.NewReader(b)) } -// OnGossip implements the mesh.Gossiper interface. -func (l *nlog) OnGossip(msg []byte) (mesh.GossipData, error) { - gd, err := decodeGossipData(msg) - if err != nil { - return nil, err - } +// MarshalBinary serializes all contents of the notification log. +func (l *Log) MarshalBinary() ([]byte, error) { l.mtx.Lock() defer l.mtx.Unlock() - var delta gossipData - if l.st, delta = l.st.mergeDelta(gd); len(delta) > 0 { - return delta, nil - } - return nil, nil + return l.st.MarshalBinary() } -// OnGossipBroadcast implements the mesh.Gossiper interface. -func (l *nlog) OnGossipBroadcast(src mesh.PeerName, msg []byte) (mesh.GossipData, error) { - gd, err := decodeGossipData(msg) +// Merge merges notification log state received from the cluster with the local state. +func (l *Log) Merge(b []byte) error { + st, err := decodeState(bytes.NewReader(b)) if err != nil { - return nil, err + return err } l.mtx.Lock() defer l.mtx.Unlock() - var delta mesh.GossipData - l.st, delta = l.st.mergeDelta(gd) - - return delta, nil -} - -// OnGossipUnicast implements the mesh.Gossiper interface. -func (l *nlog) OnGossipUnicast(src mesh.PeerName, msg []byte) error { - panic("not implemented") -} - -// gossipData is a representation of the current log state that -// implements the mesh.GossipData interface. -type gossipData map[string]*pb.MeshEntry - -func decodeGossipData(msg []byte) (gossipData, error) { - gd := gossipData{} - rd := bytes.NewReader(msg) - - for { - var e pb.MeshEntry - if _, err := pbutil.ReadDelimited(rd, &e); err != nil { - if err == io.EOF { - break - } - return gd, err + for _, e := range st { + if merged := l.st.merge(e); merged && !cluster.OversizedMessage(b) { + // If this is the first we've seen the message and it's + // not oversized, gossip it to other nodes. We don't + // propagate oversized messages because they're sent to + // all nodes already. + l.broadcast(b) + l.metrics.propagatedMessagesTotal.Inc() + level.Debug(l.logger).Log("msg", "gossiping new entry", "entry", e) } - gd[stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)] = &e - } - - return gd, nil -} - -// Encode implements the mesh.GossipData interface. -func (gd gossipData) Encode() [][]byte { - // Split into sub-messages of ~1MB. - const maxSize = 1024 * 1024 - - var ( - buf bytes.Buffer - res [][]byte - n int - ) - for _, e := range gd { - m, err := pbutil.WriteDelimited(&buf, e) - n += m - if err != nil { - // TODO(fabxc): log error and skip entry. Or can this really not happen with a bytes.Buffer? - panic(err) - } - if n > maxSize { - res = append(res, buf.Bytes()) - buf = bytes.Buffer{} - } - } - if buf.Len() > 0 { - res = append(res, buf.Bytes()) - } - return res -} - -func (gd gossipData) clone() gossipData { - res := make(gossipData, len(gd)) - for k, e := range gd { - res[k] = e } - return res -} - -// Merge the notification set with gossip data and return a new notification -// state. -// TODO(fabxc): can we just return the receiver. Does it have to remain -// unmodified. Needs to be clarified upstream. -func (gd gossipData) Merge(other mesh.GossipData) mesh.GossipData { - merged := gd.clone() - for k, e := range other.(gossipData) { - prev, ok := merged[k] - if !ok { - merged[k] = e - continue - } - if prev.Entry.Timestamp.Before(e.Entry.Timestamp) { - merged[k] = e - } - } - return merged + return nil } -// mergeDelta behaves like Merge but in addition returns a gossipData only -// containing things that have changed. -func (gd gossipData) mergeDelta(od gossipData) (merged gossipData, delta gossipData) { - merged = gd.clone() - delta = gossipData{} - for k, e := range od { - prev, ok := merged[k] - if !ok { - merged[k] = e - delta[k] = e - continue - } - if prev.Entry.Timestamp.Before(e.Entry.Timestamp) { - merged[k] = e - delta[k] = e - } - } - return merged, delta +// SetBroadcast sets a broadcast callback that will be invoked with serialized state +// on updates. +func (l *Log) SetBroadcast(f func([]byte)) { + l.mtx.Lock() + l.broadcast = f + l.mtx.Unlock() } // replaceFile wraps a file that is moved to another filename on closing. diff --git a/vendor/github.com/prometheus/alertmanager/nflog/nflogpb/nflog.pb.go b/vendor/github.com/prometheus/alertmanager/nflog/nflogpb/nflog.pb.go index 5b33d3229d1..598f9dec838 100644 --- a/vendor/github.com/prometheus/alertmanager/nflog/nflogpb/nflog.pb.go +++ b/vendor/github.com/prometheus/alertmanager/nflog/nflogpb/nflog.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: nflog.proto -// DO NOT EDIT! /* Package nflogpb is a generated protocol buffer package. @@ -19,9 +18,11 @@ import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + import time "time" -import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" +import types "github.com/gogo/protobuf/types" import io "io" @@ -182,8 +183,8 @@ func (m *Entry) MarshalTo(dAtA []byte) (int, error) { } dAtA[i] = 0x2a i++ - i = encodeVarintNflog(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp))) - n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) + i = encodeVarintNflog(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp))) + n2, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) if err != nil { return 0, err } @@ -252,8 +253,8 @@ func (m *MeshEntry) MarshalTo(dAtA []byte) (int, error) { } dAtA[i] = 0x12 i++ - i = encodeVarintNflog(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExpiresAt))) - n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExpiresAt, dAtA[i:]) + i = encodeVarintNflog(dAtA, i, uint64(types.SizeOfStdTime(m.ExpiresAt))) + n8, err := types.StdTimeMarshalTo(m.ExpiresAt, dAtA[i:]) if err != nil { return 0, err } @@ -261,24 +262,6 @@ func (m *MeshEntry) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Nflog(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Nflog(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintNflog(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -323,7 +306,7 @@ func (m *Entry) Size() (n int) { if m.Resolved { n += 2 } - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) + l = types.SizeOfStdTime(m.Timestamp) n += 1 + l + sovNflog(uint64(l)) if len(m.FiringAlerts) > 0 { l = 0 @@ -349,7 +332,7 @@ func (m *MeshEntry) Size() (n int) { l = m.Entry.Size() n += 1 + l + sovNflog(uint64(l)) } - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExpiresAt) + l = types.SizeOfStdTime(m.ExpiresAt) n += 1 + l + sovNflog(uint64(l)) return n } @@ -664,7 +647,7 @@ func (m *Entry) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -901,7 +884,7 @@ func (m *MeshEntry) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExpiresAt, dAtA[iNdEx:postIndex]); err != nil { + if err := types.StdTimeUnmarshal(&m.ExpiresAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/vendor/github.com/prometheus/alertmanager/notify/impl.go b/vendor/github.com/prometheus/alertmanager/notify/impl.go index 50eb97dee6c..7c98edecaf3 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/impl.go +++ b/vendor/github.com/prometheus/alertmanager/notify/impl.go @@ -34,6 +34,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" + commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" "github.com/prometheus/common/version" "golang.org/x/net/context" @@ -44,10 +45,6 @@ import ( "github.com/prometheus/alertmanager/types" ) -type notifierConfig interface { - SendResolved() bool -} - // A Notifier notifies about alerts under constraints of the given context. // It returns an error if unsuccessful and a flag whether the error is // recoverable. This information is useful for a retry logic. @@ -66,24 +63,7 @@ type Integration struct { // Notify implements the Notifier interface. func (i *Integration) Notify(ctx context.Context, alerts ...*types.Alert) (bool, error) { - var res []*types.Alert - - // Resolved alerts have to be filtered only at this point, because they need - // to end up unfiltered in the SetNotifiesStage. - if i.conf.SendResolved() { - res = alerts - } else { - for _, a := range alerts { - if a.Status() != model.AlertResolved { - res = append(res, a) - } - } - } - if len(res) == 0 { - return false, nil - } - - return i.notifier.Notify(ctx, res...) + return i.notifier.Notify(ctx, alerts...) } // BuildReceiverIntegrations builds a list of integration notifiers off of a @@ -146,15 +126,14 @@ var userAgentHeader = fmt.Sprintf("Alertmanager/%s", version.Version) // Webhook implements a Notifier for generic webhooks. type Webhook struct { - // The URL to which notifications are sent. - URL string + conf *config.WebhookConfig tmpl *template.Template logger log.Logger } // NewWebhook returns a new Webhook. func NewWebhook(conf *config.WebhookConfig, t *template.Template, l log.Logger) *Webhook { - return &Webhook{URL: conf.URL, tmpl: t, logger: l} + return &Webhook{conf: conf, tmpl: t, logger: l} } // WebhookMessage defines the JSON object send to webhook endpoints. @@ -186,14 +165,19 @@ func (w *Webhook) Notify(ctx context.Context, alerts ...*types.Alert) (bool, err return false, err } - req, err := http.NewRequest("POST", w.URL, &buf) + req, err := http.NewRequest("POST", w.conf.URL, &buf) if err != nil { return true, err } req.Header.Set("Content-Type", contentTypeJSON) req.Header.Set("User-Agent", userAgentHeader) - resp, err := ctxhttp.Do(ctx, http.DefaultClient, req) + c, err := commoncfg.NewClientFromConfig(*w.conf.HTTPConfig, "webhook") + if err != nil { + return false, err + } + + resp, err := ctxhttp.Do(ctx, c, req) if err != nil { return true, err } @@ -206,7 +190,7 @@ func (w *Webhook) retry(statusCode int) (bool, error) { // Webhooks are assumed to respond with 2xx response codes on a successful // request and 5xx response codes are assumed to be recoverable. if statusCode/100 != 2 { - return (statusCode/100 == 5), fmt.Errorf("unexpected status code %v from %s", statusCode, w.URL) + return (statusCode/100 == 5), fmt.Errorf("unexpected status code %v from %s", statusCode, w.conf.URL) } return false, nil @@ -460,12 +444,13 @@ type pagerDutyPayload struct { Source string `json:"source"` Severity string `json:"severity"` Timestamp string `json:"timestamp,omitempty"` + Class string `json:"class,omitempty"` Component string `json:"component,omitempty"` Group string `json:"group,omitempty"` CustomDetails map[string]string `json:"custom_details,omitempty"` } -func (n *PagerDuty) notifyV1(ctx context.Context, eventType, key string, tmpl func(string) string, details map[string]string, as ...*types.Alert) (bool, error) { +func (n *PagerDuty) notifyV1(ctx context.Context, c *http.Client, eventType, key string, tmpl func(string) string, details map[string]string, as ...*types.Alert) (bool, error) { msg := &pagerDutyMessage{ ServiceKey: tmpl(string(n.conf.ServiceKey)), @@ -487,7 +472,7 @@ func (n *PagerDuty) notifyV1(ctx context.Context, eventType, key string, tmpl fu return false, err } - resp, err := ctxhttp.Post(ctx, http.DefaultClient, n.conf.URL, contentTypeJSON, &buf) + resp, err := ctxhttp.Post(ctx, c, n.conf.URL, contentTypeJSON, &buf) if err != nil { return true, err } @@ -496,7 +481,7 @@ func (n *PagerDuty) notifyV1(ctx context.Context, eventType, key string, tmpl fu return n.retryV1(resp.StatusCode) } -func (n *PagerDuty) notifyV2(ctx context.Context, eventType, key string, tmpl func(string) string, details map[string]string, as ...*types.Alert) (bool, error) { +func (n *PagerDuty) notifyV2(ctx context.Context, c *http.Client, eventType, key string, tmpl func(string) string, details map[string]string, as ...*types.Alert) (bool, error) { if n.conf.Severity == "" { n.conf.Severity = "error" } @@ -506,10 +491,11 @@ func (n *PagerDuty) notifyV2(ctx context.Context, eventType, key string, tmpl fu payload = &pagerDutyPayload{ Summary: tmpl(n.conf.Description), Source: tmpl(n.conf.Client), - Severity: n.conf.Severity, + Severity: tmpl(n.conf.Severity), CustomDetails: details, - Component: n.conf.Component, - Group: n.conf.Group, + Class: tmpl(n.conf.Class), + Component: tmpl(n.conf.Component), + Group: tmpl(n.conf.Group), } } @@ -530,7 +516,7 @@ func (n *PagerDuty) notifyV2(ctx context.Context, eventType, key string, tmpl fu return false, err } - resp, err := ctxhttp.Post(ctx, http.DefaultClient, n.conf.URL, contentTypeJSON, &buf) + resp, err := ctxhttp.Post(ctx, c, n.conf.URL, contentTypeJSON, &buf) if err != nil { return true, err } @@ -570,10 +556,15 @@ func (n *PagerDuty) Notify(ctx context.Context, as ...*types.Alert) (bool, error return false, err } + c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "pagerduty") + if err != nil { + return false, err + } + if n.conf.ServiceKey != "" { - return n.notifyV1(ctx, eventType, key, tmpl, details, as...) + return n.notifyV1(ctx, c, eventType, key, tmpl, details, as...) } - return n.notifyV2(ctx, eventType, key, tmpl, details, as...) + return n.notifyV2(ctx, c, eventType, key, tmpl, details, as...) } func (n *PagerDuty) retryV1(statusCode int) (bool, error) { @@ -626,25 +617,19 @@ type slackReq struct { // slackAttachment is used to display a richly-formatted message block. type slackAttachment struct { - Title string `json:"title,omitempty"` - TitleLink string `json:"title_link,omitempty"` - Pretext string `json:"pretext,omitempty"` - Text string `json:"text"` - Fallback string `json:"fallback"` - Fields []slackAttachmentField `json:"fields"` - Footer string `json:"footer"` + Title string `json:"title,omitempty"` + TitleLink string `json:"title_link,omitempty"` + Pretext string `json:"pretext,omitempty"` + Text string `json:"text"` + Fallback string `json:"fallback"` + Fields []config.SlackField `json:"fields,omitempty"` + Actions []config.SlackAction `json:"actions,omitempty"` + Footer string `json:"footer"` Color string `json:"color,omitempty"` MrkdwnIn []string `json:"mrkdwn_in,omitempty"` } -// slackAttachmentField is displayed in a table inside the message attachment. -type slackAttachmentField struct { - Title string `json:"title"` - Value string `json:"value"` - Short bool `json:"short,omitempty"` -} - // Notify implements the Notifier interface. func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { var err error @@ -666,17 +651,40 @@ func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { var numFields = len(n.conf.Fields) if numFields > 0 { - var fields = make([]slackAttachmentField, numFields) - for k, v := range n.conf.Fields { - fields[k] = slackAttachmentField{ - tmplText(v["title"]), - tmplText(v["value"]), - n.conf.ShortFields, + var fields = make([]config.SlackField, numFields) + for index, field := range n.conf.Fields { + // Check if short was defined for the field otherwise fallback to the global setting + var short bool + if field.Short != nil { + short = *field.Short + } else { + short = n.conf.ShortFields + } + + // Rebuild the field by executing any templates and setting the new value for short + fields[index] = config.SlackField{ + Title: tmplText(field.Title), + Value: tmplText(field.Value), + Short: &short, } } attachment.Fields = fields } + var numActions = len(n.conf.Actions) + if numActions > 0 { + var actions = make([]config.SlackAction, numActions) + for index, action := range n.conf.Actions { + actions[index] = config.SlackAction{ + Type: tmplText(action.Type), + Text: tmplText(action.Text), + URL: tmplText(action.URL), + Style: tmplText(action.Style), + } + } + attachment.Actions = actions + } + req := &slackReq{ Channel: tmplText(n.conf.Channel), Username: tmplText(n.conf.Username), @@ -694,7 +702,12 @@ func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { return false, err } - resp, err := ctxhttp.Post(ctx, http.DefaultClient, string(n.conf.APIURL), contentTypeJSON, &buf) + c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "slack") + if err != nil { + return false, err + } + + resp, err := ctxhttp.Post(ctx, c, string(n.conf.APIURL), contentTypeJSON, &buf) if err != nil { return true, err } @@ -771,7 +784,12 @@ func (n *Hipchat) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - resp, err := ctxhttp.Post(ctx, http.DefaultClient, url, contentTypeJSON, &buf) + c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "hipchat") + if err != nil { + return false, err + } + + resp, err := ctxhttp.Post(ctx, c, url, contentTypeJSON, &buf) if err != nil { return true, err } @@ -797,36 +815,31 @@ type Wechat struct { conf *config.WechatConfig tmpl *template.Template logger log.Logger + + accessToken string + accessTokenAt time.Time } + +// Wechat AccessToken with corpid and corpsecret. type WechatToken struct { AccessToken string `json:"access_token"` - // Catches all undefined fields and must be empty after parsing. - XXX map[string]interface{} `json:"-"` } + type weChatMessage struct { - Content string `json:"content"` -} -type weChatCreateMessage struct { - Text weChatMessage `yaml:"text,omitempty" json:"text,omitempty"` - ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"` - ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"` - Totag string `yaml:"totag,omitempty" json:"totag,omitempty"` - AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"` - Safe string `yaml:"safe,omitempty" json:"safe,omitempty"` - Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"` + Text weChatMessageContent `yaml:"text,omitempty" json:"text,omitempty"` + ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"` + ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"` + Totag string `yaml:"totag,omitempty" json:"totag,omitempty"` + AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"` + Safe string `yaml:"safe,omitempty" json:"safe,omitempty"` + Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"` } -type weChatCloseMessage struct { - Text weChatMessage `yaml:"text,omitempty" json:"text,omitempty"` - ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"` - ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"` - Totag string `yaml:"totag,omitempty" json:"totag,omitempty"` - AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"` - Safe string `yaml:"safe,omitempty" json:"safe,omitempty"` - Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"` +type weChatMessageContent struct { + Content string `json:"content"` } -type weChatErrorResponse struct { +type weChatResponse struct { Code int `json:"code"` Error string `json:"error"` } @@ -842,84 +855,123 @@ func (n *Wechat) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { if !ok { return false, fmt.Errorf("group key missing") } - data := n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...) + level.Debug(n.logger).Log("msg", "Notifying Wechat", "incident", key) + data := n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...) var err error tmpl := tmplText(n.tmpl, data, &err) - - var ( - msg interface{} - apiURL string - apiMsg = weChatMessage{ - Content: tmpl(n.conf.Message), - } - alerts = types.Alerts(as...) - ) - parameters := url.Values{} - parameters.Add("corpsecret", tmpl(string(n.conf.APISecret))) - parameters.Add("corpid", tmpl(string(n.conf.CorpID))) - apiURL = n.conf.APIURL + "gettoken" - u, err := url.Parse(apiURL) if err != nil { return false, err } - u.RawQuery = parameters.Encode() - level.Debug(n.logger).Log("msg", "Sending Wechat message", "incident", key, "url", u.String()) - resp, err := ctxhttp.Get(ctx, http.DefaultClient, u.String()) + + c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "wechat") if err != nil { - return true, err - } - defer resp.Body.Close() - var wechatToken WechatToken - if err := json.NewDecoder(resp.Body).Decode(&wechatToken); err != nil { return false, err } - postMessageURL := n.conf.APIURL + "message/send?access_token=" + wechatToken.AccessToken - switch alerts.Status() { - case model.AlertResolved: - msg = &weChatCloseMessage{Text: apiMsg, - ToUser: tmpl(n.conf.ToUser), - ToParty: tmpl(n.conf.ToParty), - Totag: tmpl(n.conf.ToTag), - AgentID: tmpl(n.conf.AgentID), - Type: "text", - Safe: "0"} - default: - msg = &weChatCreateMessage{ - Text: weChatMessage{ - Content: tmpl(n.conf.Message), - }, - ToUser: tmpl(n.conf.ToUser), - ToParty: tmpl(n.conf.ToParty), - Totag: tmpl(n.conf.ToTag), - AgentID: tmpl(n.conf.AgentID), - Type: "text", - Safe: "0", + + // Refresh AccessToken over 2 hours + if n.accessToken == "" || time.Now().Sub(n.accessTokenAt) > 2*time.Hour { + parameters := url.Values{} + parameters.Add("corpsecret", tmpl(string(n.conf.APISecret))) + parameters.Add("corpid", tmpl(string(n.conf.CorpID))) + if err != nil { + return false, fmt.Errorf("templating error: %s", err) + } + + apiURL := n.conf.APIURL + "gettoken" + + u, err := url.Parse(apiURL) + if err != nil { + return false, err } + + u.RawQuery = parameters.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return true, err + } + + req.Header.Set("Content-Type", contentTypeJSON) + + resp, err := c.Do(req.WithContext(ctx)) + if err != nil { + return true, err + } + defer resp.Body.Close() + + var wechatToken WechatToken + if err := json.NewDecoder(resp.Body).Decode(&wechatToken); err != nil { + return false, err + } + + if wechatToken.AccessToken == "" { + return false, fmt.Errorf("invalid APISecret for CorpID: %s", n.conf.CorpID) + } + + // Cache accessToken + n.accessToken = wechatToken.AccessToken + n.accessTokenAt = time.Now() + } + + msg := &weChatMessage{ + Text: weChatMessageContent{ + Content: tmpl(n.conf.Message), + }, + ToUser: tmpl(n.conf.ToUser), + ToParty: tmpl(n.conf.ToParty), + Totag: tmpl(n.conf.ToTag), + AgentID: tmpl(n.conf.AgentID), + Type: "text", + Safe: "0", } + if err != nil { + return false, fmt.Errorf("templating error: %s", err) + } + var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(msg); err != nil { return false, err } - resp, err = ctxhttp.Post(ctx, http.DefaultClient, postMessageURL, contentTypeJSON, &buf) + + postMessageURL := n.conf.APIURL + "message/send?access_token=" + n.accessToken + + req, err := http.NewRequest(http.MethodPost, postMessageURL, &buf) + if err != nil { + return true, err + } + + resp, err := c.Do(req.WithContext(ctx)) if err != nil { return true, err } + defer resp.Body.Close() + body, _ := ioutil.ReadAll(resp.Body) level.Debug(n.logger).Log("msg", "response: "+string(body), "incident", key) - defer resp.Body.Close() - return n.retry(resp.StatusCode) -} -func (n *Wechat) retry(statusCode int) (bool, error) { - // https://work.weixin.qq.com/api/doc#10649 - if statusCode/100 == 5 || statusCode == 429 { - return true, fmt.Errorf("unexpected status code %v", statusCode) - } else if statusCode/100 != 2 { - return false, fmt.Errorf("unexpected status code %v", statusCode) - } - return false, nil + if resp.StatusCode != 200 { + return true, fmt.Errorf("unexpected status code %v", resp.StatusCode) + } else { + var weResp weChatResponse + if err := json.Unmarshal(body, &weResp); err != nil { + return true, err + } + + // https://work.weixin.qq.com/api/doc#10649 + if weResp.Code == 0 { + return false, nil + } + + // AccessToken is expired + if weResp.Code == 42001 { + n.accessToken = "" + return true, errors.New(weResp.Error) + } + + return false, errors.New(weResp.Error) + } } // OpsGenie implements a Notifier for OpsGenie notifications. @@ -952,9 +1004,43 @@ type opsGenieCloseMessage struct { // Notify implements the Notifier interface. func (n *OpsGenie) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { + req, retry, err := n.createRequest(ctx, as...) + if err != nil { + return retry, err + } + + c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "opsgenie") + if err != nil { + return false, err + } + + resp, err := ctxhttp.Do(ctx, c, req) + + if err != nil { + return true, err + } + defer resp.Body.Close() + + return n.retry(resp.StatusCode) +} + +// Like Split but filter out empty strings. +func safeSplit(s string, sep string) []string { + a := strings.Split(strings.TrimSpace(s), sep) + b := a[:0] + for _, x := range a { + if x != "" { + b = append(b, x) + } + } + return b +} + +// Create requests for a list of alerts. +func (n *OpsGenie) createRequest(ctx context.Context, as ...*types.Alert) (*http.Request, bool, error) { key, ok := GroupKey(ctx) if !ok { - return false, fmt.Errorf("group key missing") + return nil, false, fmt.Errorf("group key missing") } data := n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...) @@ -987,9 +1073,11 @@ func (n *OpsGenie) Notify(ctx context.Context, as ...*types.Alert) (bool, error) apiURL = n.conf.APIURL + "v2/alerts" var teams []map[string]string - for _, t := range strings.Split(string(tmpl(n.conf.Teams)), ",") { + for _, t := range safeSplit(string(tmpl(n.conf.Teams)), ",") { teams = append(teams, map[string]string{"name": t}) } + tags := safeSplit(string(tmpl(n.conf.Tags)), ",") + msg = &opsGenieCreateMessage{ Alias: alias, Message: message, @@ -997,35 +1085,27 @@ func (n *OpsGenie) Notify(ctx context.Context, as ...*types.Alert) (bool, error) Details: details, Source: tmpl(n.conf.Source), Teams: teams, - Tags: strings.Split(string(tmpl(n.conf.Tags)), ","), + Tags: tags, Note: tmpl(n.conf.Note), Priority: tmpl(n.conf.Priority), } } if err != nil { - return false, fmt.Errorf("templating error: %s", err) + return nil, false, fmt.Errorf("templating error: %s", err) } var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(msg); err != nil { - return false, err + return nil, false, err } req, err := http.NewRequest("POST", apiURL, &buf) if err != nil { - return true, err + return nil, true, err } req.Header.Set("Content-Type", contentTypeJSON) req.Header.Set("Authorization", fmt.Sprintf("GenieKey %s", n.conf.APIKey)) - - resp, err := ctxhttp.Do(ctx, http.DefaultClient, req) - - if err != nil { - return true, err - } - defer resp.Body.Close() - - return n.retry(resp.StatusCode) + return req, true, nil } func (n *OpsGenie) retry(statusCode int) (bool, error) { @@ -1069,11 +1149,6 @@ type victorOpsMessage struct { MonitoringTool string `json:"monitoring_tool"` } -type victorOpsErrorResponse struct { - Result string `json:"result"` - Message string `json:"message"` -} - // Notify implements the Notifier interface. func (n *VictorOps) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { victorOpsAllowedEvents := map[string]bool{ @@ -1127,7 +1202,12 @@ func (n *VictorOps) Notify(ctx context.Context, as ...*types.Alert) (bool, error return false, err } - resp, err := ctxhttp.Post(ctx, http.DefaultClient, apiURL, contentTypeJSON, &buf) + c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "victorops") + if err != nil { + return false, err + } + + resp, err := ctxhttp.Post(ctx, c, apiURL, contentTypeJSON, &buf) if err != nil { return true, err } @@ -1219,7 +1299,12 @@ func (n *Pushover) Notify(ctx context.Context, as ...*types.Alert) (bool, error) u.RawQuery = parameters.Encode() level.Debug(n.logger).Log("msg", "Sending Pushover message", "incident", key, "url", u.String()) - resp, err := ctxhttp.Post(ctx, http.DefaultClient, u.String(), "text/plain", nil) + c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "pushover") + if err != nil { + return false, err + } + + resp, err := ctxhttp.Post(ctx, c, u.String(), "text/plain", nil) if err != nil { return true, err } diff --git a/vendor/github.com/prometheus/alertmanager/notify/notify.go b/vendor/github.com/prometheus/alertmanager/notify/notify.go index 9ee2e2714c6..75b791e61a6 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/notify.go +++ b/vendor/github.com/prometheus/alertmanager/notify/notify.go @@ -27,6 +27,7 @@ import ( "github.com/prometheus/common/model" "golang.org/x/net/context" + "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/nflog" "github.com/prometheus/alertmanager/nflog/nflogpb" @@ -47,6 +48,13 @@ var ( Name: "notifications_failed_total", Help: "The total number of failed notifications.", }, []string{"integration"}) + + notificationLatencySeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: "alertmanager", + Name: "notification_latency_seconds", + Help: "The latency of notifications in seconds.", + Buckets: []float64{1, 5, 10, 15, 20}, + }, []string{"integration"}) ) func init() { @@ -68,9 +76,23 @@ func init() { numFailedNotifications.WithLabelValues("opsgenie") numFailedNotifications.WithLabelValues("webhook") numFailedNotifications.WithLabelValues("victorops") + notificationLatencySeconds.WithLabelValues("email") + notificationLatencySeconds.WithLabelValues("hipchat") + notificationLatencySeconds.WithLabelValues("pagerduty") + notificationLatencySeconds.WithLabelValues("wechat") + notificationLatencySeconds.WithLabelValues("pushover") + notificationLatencySeconds.WithLabelValues("slack") + notificationLatencySeconds.WithLabelValues("opsgenie") + notificationLatencySeconds.WithLabelValues("webhook") + notificationLatencySeconds.WithLabelValues("victorops") prometheus.Register(numNotifications) prometheus.Register(numFailedNotifications) + prometheus.Register(notificationLatencySeconds) +} + +type notifierConfig interface { + SendResolved() bool } // MinTimeout is the minimum timeout that is set for the context of a call @@ -204,6 +226,11 @@ func (f StageFunc) Exec(ctx context.Context, l log.Logger, alerts ...*types.Aler return f(ctx, l, alerts...) } +type NotificationLog interface { + Log(r *nflogpb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error + Query(params ...nflog.QueryParam) ([]*nflogpb.Entry, error) +} + // BuildPipeline builds a map of receivers to Stages. func BuildPipeline( confs []*config.Receiver, @@ -211,23 +238,25 @@ func BuildPipeline( wait func() time.Duration, muter types.Muter, silences *silence.Silences, - notificationLog nflog.Log, + notificationLog NotificationLog, marker types.Marker, + peer *cluster.Peer, logger log.Logger, ) RoutingStage { rs := RoutingStage{} + ms := NewGossipSettleStage(peer) is := NewInhibitStage(muter) ss := NewSilenceStage(silences, marker) for _, rc := range confs { - rs[rc.Name] = MultiStage{is, ss, createStage(rc, tmpl, wait, notificationLog, logger)} + rs[rc.Name] = MultiStage{ms, is, ss, createStage(rc, tmpl, wait, notificationLog, logger)} } return rs } // createStage creates a pipeline of stages for a receiver. -func createStage(rc *config.Receiver, tmpl *template.Template, wait func() time.Duration, notificationLog nflog.Log, logger log.Logger) Stage { +func createStage(rc *config.Receiver, tmpl *template.Template, wait func() time.Duration, notificationLog NotificationLog, logger log.Logger) Stage { var fs FanoutStage for _, i := range BuildReceiverIntegrations(rc, tmpl, logger) { recv := &nflogpb.Receiver{ @@ -237,8 +266,8 @@ func createStage(rc *config.Receiver, tmpl *template.Template, wait func() time. } var s MultiStage s = append(s, NewWaitStage(wait)) - s = append(s, NewDedupStage(notificationLog, recv)) - s = append(s, NewRetryStage(i)) + s = append(s, NewDedupStage(i, notificationLog, recv)) + s = append(s, NewRetryStage(i, rc.Name)) s = append(s, NewSetNotifiesStage(notificationLog, recv)) fs = append(fs, s) @@ -313,10 +342,26 @@ func (fs FanoutStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.A return ctx, alerts, nil } +// GossipSettleStage waits until the Gossip has settled to forward alerts. +type GossipSettleStage struct { + peer *cluster.Peer +} + +// NewGossipSettleStage returns a new GossipSettleStage. +func NewGossipSettleStage(p *cluster.Peer) *GossipSettleStage { + return &GossipSettleStage{peer: p} +} + +func (n *GossipSettleStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { + if n.peer != nil { + n.peer.WaitReady() + } + return ctx, alerts, nil +} + // InhibitStage filters alerts through an inhibition muter. type InhibitStage struct { - muter types.Muter - marker types.Marker + muter types.Muter } // NewInhibitStage return a new InhibitStage. @@ -409,18 +454,20 @@ func (ws *WaitStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Al // DedupStage filters alerts. // Filtering happens based on a notification log. type DedupStage struct { - nflog nflog.Log + nflog NotificationLog recv *nflogpb.Receiver + conf notifierConfig now func() time.Time hash func(*types.Alert) uint64 } // NewDedupStage wraps a DedupStage that runs against the given notification log. -func NewDedupStage(l nflog.Log, recv *nflogpb.Receiver) *DedupStage { +func NewDedupStage(i Integration, l NotificationLog, recv *nflogpb.Receiver) *DedupStage { return &DedupStage{ nflog: l, recv: recv, + conf: i.conf, now: utcNow, hash: hashAlert, } @@ -470,23 +517,34 @@ func hashAlert(a *types.Alert) uint64 { return hash } -func (n *DedupStage) needsUpdate(entry *nflogpb.Entry, firing, resolved map[uint64]struct{}, repeat time.Duration) (bool, error) { +func (n *DedupStage) needsUpdate(entry *nflogpb.Entry, firing, resolved map[uint64]struct{}, repeat time.Duration) bool { // If we haven't notified about the alert group before, notify right away // unless we only have resolved alerts. if entry == nil { - return len(firing) > 0, nil + return len(firing) > 0 } if !entry.IsFiringSubset(firing) { - return true, nil + return true + } + + // Notify about all alerts being resolved. + // This is done irrespective of the send_resolved flag to make sure that + // the firing alerts are cleared from the notification log. + if len(firing) == 0 { + // If the current alert group and last notification contain no firing + // alert, it means that some alerts have been fired and resolved during the + // last interval. In this case, there is no need to notify the receiver + // since it doesn't know about them. + return len(entry.FiringAlerts) > 0 } - if !entry.IsResolvedSubset(resolved) { - return true, nil + if n.conf.SendResolved() && !entry.IsResolvedSubset(resolved) { + return true } // Nothing changed, only notify if the repeat interval has passed. - return entry.Timestamp.Before(n.now().Add(-repeat)), nil + return entry.Timestamp.Before(n.now().Add(-repeat)) } // Exec implements the Stage interface. @@ -534,9 +592,7 @@ func (n *DedupStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Al case 2: return ctx, nil, fmt.Errorf("unexpected entry result size %d", len(entries)) } - if ok, err := n.needsUpdate(entry, firingSet, resolvedSet, repeatInterval); err != nil { - return ctx, nil, err - } else if ok { + if n.needsUpdate(entry, firingSet, resolvedSet, repeatInterval) { return ctx, alerts, nil } return ctx, nil, nil @@ -546,28 +602,39 @@ func (n *DedupStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Al // succeeds. It aborts if the context is canceled or timed out. type RetryStage struct { integration Integration + groupName string } // NewRetryStage returns a new instance of a RetryStage. -func NewRetryStage(i Integration) *RetryStage { +func NewRetryStage(i Integration, groupName string) *RetryStage { return &RetryStage{ integration: i, + groupName: groupName, } } // Exec implements the Stage interface. func (r RetryStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { + var sent []*types.Alert + // If we shouldn't send notifications for resolved alerts, but there are only // resolved alerts, report them all as successfully notified (we still want the - // notification log to log them). + // notification log to log them for the next run of DedupStage). if !r.integration.conf.SendResolved() { firing, ok := FiringAlerts(ctx) if !ok { - return ctx, alerts, fmt.Errorf("firing alerts missing") + return ctx, nil, fmt.Errorf("firing alerts missing") } if len(firing) == 0 { return ctx, alerts, nil } + for _, a := range alerts { + if a.Status() != model.AlertResolved { + sent = append(sent, a) + } + } + } else { + sent = alerts } var ( @@ -593,9 +660,12 @@ func (r RetryStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Ale select { case <-tick.C: - if retry, err := r.integration.Notify(ctx, alerts...); err != nil { + now := time.Now() + retry, err := r.integration.Notify(ctx, sent...) + notificationLatencySeconds.WithLabelValues(r.integration.name).Observe(time.Since(now).Seconds()) + if err != nil { numFailedNotifications.WithLabelValues(r.integration.name).Inc() - level.Debug(l).Log("msg", "Notify attempt failed", "attempt", i, "integration", r.integration.name, "err", err) + level.Debug(l).Log("msg", "Notify attempt failed", "attempt", i, "integration", r.integration.name, "receiver", r.groupName, "err", err) if !retry { return ctx, alerts, fmt.Errorf("cancelling notify retry for %q due to unrecoverable error: %s", r.integration.name, err) } @@ -620,12 +690,12 @@ func (r RetryStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Ale // SetNotifiesStage sets the notification information about passed alerts. The // passed alerts should have already been sent to the receivers. type SetNotifiesStage struct { - nflog nflog.Log + nflog NotificationLog recv *nflogpb.Receiver } // NewSetNotifiesStage returns a new instance of a SetNotifiesStage. -func NewSetNotifiesStage(l nflog.Log, recv *nflogpb.Receiver) *SetNotifiesStage { +func NewSetNotifiesStage(l NotificationLog, recv *nflogpb.Receiver) *SetNotifiesStage { return &SetNotifiesStage{ nflog: l, recv: recv, diff --git a/vendor/github.com/prometheus/alertmanager/pkg/parse/parse.go b/vendor/github.com/prometheus/alertmanager/pkg/parse/parse.go index 593e3e2433d..1a03592dd04 100644 --- a/vendor/github.com/prometheus/alertmanager/pkg/parse/parse.go +++ b/vendor/github.com/prometheus/alertmanager/pkg/parse/parse.go @@ -1,3 +1,16 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package parse import ( @@ -9,7 +22,7 @@ import ( ) var ( - re = regexp.MustCompile(`(?:\s?)(\w+)(=|=~|!=|!~)(?:\"([^"=~!]+)\"|([^"=~!]+))`) + re = regexp.MustCompile(`(?:\s?)(\w+)(=|=~|!=|!~)(?:\"([^"=~!]+)\"|([^"=~!]+)|\"\")`) typeMap = map[string]labels.MatchType{ "=": labels.MatchEqual, "!=": labels.MatchNotEqual, @@ -27,13 +40,31 @@ func Matchers(s string) ([]*labels.Matcher, error) { s = s[:len(s)-1] } - for _, toParse := range strings.Split(s, ",") { - m, err := Matcher(toParse) + var insideQuotes bool + var token string + var tokens []string + for _, r := range s { + if !insideQuotes && r == ',' { + tokens = append(tokens, token) + token = "" + continue + } + token += string(r) + if r == '"' { + insideQuotes = !insideQuotes + } + } + if token != "" { + tokens = append(tokens, token) + } + for _, token := range tokens { + m, err := Matcher(token) if err != nil { return nil, err } matchers = append(matchers, m) } + return matchers, nil } @@ -53,7 +84,7 @@ func Matcher(s string) (*labels.Matcher, error) { func Input(s string) (name, value string, matchType labels.MatchType, err error) { ms := re.FindStringSubmatch(s) if len(ms) < 4 { - return "", "", labels.MatchEqual, fmt.Errorf("bad matcher format") + return "", "", labels.MatchEqual, fmt.Errorf("bad matcher format: %s", s) } var prs bool @@ -66,7 +97,7 @@ func Input(s string) (name, value string, matchType labels.MatchType, err error) value = ms[4] } - if name == "" || value == "" || !prs { + if name == "" || !prs { return "", "", labels.MatchEqual, fmt.Errorf("failed to parse") } diff --git a/vendor/github.com/prometheus/alertmanager/silence/silence.go b/vendor/github.com/prometheus/alertmanager/silence/silence.go index 8dcfe335228..1fd3d594163 100644 --- a/vendor/github.com/prometheus/alertmanager/silence/silence.go +++ b/vendor/github.com/prometheus/alertmanager/silence/silence.go @@ -30,17 +30,20 @@ import ( "github.com/go-kit/kit/log/level" "github.com/matttproud/golang_protobuf_extensions/pbutil" "github.com/pkg/errors" + "github.com/prometheus/alertmanager/cluster" pb "github.com/prometheus/alertmanager/silence/silencepb" "github.com/prometheus/alertmanager/types" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/satori/go.uuid" - "github.com/weaveworks/mesh" ) // ErrNotFound is returned if a silence was not found. var ErrNotFound = fmt.Errorf("not found") +// ErrInvalidState is returned if the state isn't valid. +var ErrInvalidState = fmt.Errorf("invalid state") + func utcNow() time.Time { return time.Now().UTC() } @@ -96,28 +99,23 @@ type Silences struct { now func() time.Time retention time.Duration - gossip mesh.Gossip // gossip channel for sharing silences - - // We store silences in a map of IDs for now. Currently, the memory - // state is equivalent to the mesh.GossipData representation. - // In the future we'll want support for efficient queries by time - // range and affected labels. - // Mutex also guards the matcherCache, which always need write lock access. - mtx sync.Mutex - st *gossipData - mc matcherCache + mtx sync.RWMutex + st state + broadcast func([]byte) + mc matcherCache } type metrics struct { - gcDuration prometheus.Summary - snapshotDuration prometheus.Summary - snapshotSize prometheus.Gauge - queriesTotal prometheus.Counter - queryErrorsTotal prometheus.Counter - queryDuration prometheus.Histogram - silencesActive prometheus.GaugeFunc - silencesPending prometheus.GaugeFunc - silencesExpired prometheus.GaugeFunc + gcDuration prometheus.Summary + snapshotDuration prometheus.Summary + snapshotSize prometheus.Gauge + queriesTotal prometheus.Counter + queryErrorsTotal prometheus.Counter + queryDuration prometheus.Histogram + silencesActive prometheus.GaugeFunc + silencesPending prometheus.GaugeFunc + silencesExpired prometheus.GaugeFunc + propagatedMessagesTotal prometheus.Counter } func newSilenceMetricByState(s *Silences, st types.SilenceState) prometheus.GaugeFunc { @@ -164,6 +162,10 @@ func newMetrics(r prometheus.Registerer, s *Silences) *metrics { Name: "alertmanager_silences_query_duration_seconds", Help: "Duration of silence query evaluation.", }) + m.propagatedMessagesTotal = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "alertmanager_silences_gossip_messages_propagated_total", + Help: "Number of received gossip messages that have been further gossiped.", + }) if s != nil { m.silencesActive = newSilenceMetricByState(s, types.SilenceStateActive) m.silencesPending = newSilenceMetricByState(s, types.SilenceStatePending) @@ -181,6 +183,7 @@ func newMetrics(r prometheus.Registerer, s *Silences) *metrics { m.silencesActive, m.silencesPending, m.silencesExpired, + m.propagatedMessagesTotal, ) } return m @@ -198,9 +201,6 @@ type Options struct { // garbage collected after the given duration after they ended. Retention time.Duration - // A function creating a mesh.Gossip on being called with a mesh.Gossiper. - Gossip func(g mesh.Gossiper) mesh.Gossip - // A logger used by background processing. Logger log.Logger Metrics prometheus.Registerer @@ -232,17 +232,14 @@ func New(o Options) (*Silences, error) { logger: log.NewNopLogger(), retention: o.Retention, now: utcNow, - gossip: nopGossip{}, - st: newGossipData(), + broadcast: func([]byte) {}, + st: state{}, } s.metrics = newMetrics(o.Metrics, s) if o.Logger != nil { s.logger = o.Logger } - if o.Gossip != nil { - s.gossip = o.Gossip(gossiper{s}) - } if o.SnapshotReader != nil { if err := s.loadSnapshot(o.SnapshotReader); err != nil { return s, err @@ -251,11 +248,6 @@ func New(o Options) (*Silences, error) { return s, nil } -type nopGossip struct{} - -func (nopGossip) GossipBroadcast(d mesh.GossipData) {} -func (nopGossip) GossipUnicast(mesh.PeerName, []byte) error { return nil } - // Maintenance garbage collects the silence state at the given interval. If the snapshot // file is set, a snapshot is written to it afterwards. // Terminates on receiving from stopc. @@ -265,10 +257,11 @@ func (s *Silences) Maintenance(interval time.Duration, snapf string, stopc <-cha f := func() error { start := s.now() - var size int - level.Info(s.logger).Log("msg", "Running maintenance") + var size int64 + + level.Debug(s.logger).Log("msg", "Running maintenance") defer func() { - level.Info(s.logger).Log("msg", "Maintenance done", "duration", s.now().Sub(start), "size", size) + level.Debug(s.logger).Log("msg", "Maintenance done", "duration", s.now().Sub(start), "size", size) s.metrics.snapshotSize.Set(float64(size)) }() @@ -320,12 +313,12 @@ func (s *Silences) GC() (int, error) { s.mtx.Lock() defer s.mtx.Unlock() - for id, sil := range s.st.data { + for id, sil := range s.st { if sil.ExpiresAt.IsZero() { return n, errors.New("unexpected zero expiration timestamp") } if !sil.ExpiresAt.After(now) { - delete(s.st.data, id) + delete(s.st, id) delete(s.mc, sil.Silence) n++ } @@ -387,7 +380,7 @@ func cloneSilence(sil *pb.Silence) *pb.Silence { } func (s *Silences) getSilence(id string) (*pb.Silence, bool) { - msil, ok := s.st.data[id] + msil, ok := s.st[id] if !ok { return nil, false } @@ -405,14 +398,13 @@ func (s *Silences) setSilence(sil *pb.Silence) error { Silence: sil, ExpiresAt: sil.EndsAt.Add(s.retention), } - st := &gossipData{ - data: silenceMap{sil.Id: msil}, + b, err := marshalMeshSilence(msil) + if err != nil { + return err } - s.st.Merge(st) - // setSilence() is called with s.mtx locked, which can produce - // a deadlock if we call GossipBroadcast from here. - go s.gossip.GossipBroadcast(st) + s.st.merge(msil) + s.broadcast(b) return nil } @@ -637,12 +629,12 @@ func (s *Silences) query(q *query, now time.Time) ([]*pb.Silence, error) { if q.ids != nil { for _, id := range q.ids { - if s, ok := s.st.data[string(id)]; ok { + if s, ok := s.st[id]; ok { res = append(res, s.Silence) } } } else { - for _, sil := range s.st.data { + for _, sil := range s.st { res = append(res, sil.Silence) } } @@ -671,252 +663,137 @@ func (s *Silences) query(q *query, now time.Time) ([]*pb.Silence, error) { // loadSnapshot loads a snapshot generated by Snapshot() into the state. // Any previous state is wiped. func (s *Silences) loadSnapshot(r io.Reader) error { - st := newGossipData() - - s.mtx.Lock() - defer s.mtx.Unlock() - - for { - var sil pb.MeshSilence - if _, err := pbutil.ReadDelimited(r, &sil); err != nil { - if err == io.EOF { - break - } - return err - } + st, err := decodeState(r) + if err != nil { + return err + } + for _, e := range st { // Comments list was moved to a single comment. Upgrade on loading the snapshot. - if len(sil.Silence.Comments) > 0 { - sil.Silence.Comment = sil.Silence.Comments[0].Comment - sil.Silence.CreatedBy = sil.Silence.Comments[0].Author - sil.Silence.Comments = nil - } - - st.data[sil.Silence.Id] = &sil - _, err := s.mc.Get(sil.Silence) - if err != nil { - return err + if len(e.Silence.Comments) > 0 { + e.Silence.Comment = e.Silence.Comments[0].Comment + e.Silence.CreatedBy = e.Silence.Comments[0].Author + e.Silence.Comments = nil } + st[e.Silence.Id] = e } - - s.st.data = st.data + s.mtx.Lock() + s.st = st + s.mtx.Unlock() return nil } // Snapshot writes the full internal state into the writer and returns the number of bytes // written. -func (s *Silences) Snapshot(w io.Writer) (int, error) { +func (s *Silences) Snapshot(w io.Writer) (int64, error) { start := time.Now() defer func() { s.metrics.snapshotDuration.Observe(time.Since(start).Seconds()) }() - s.mtx.Lock() - defer s.mtx.Unlock() + s.mtx.RLock() + defer s.mtx.RUnlock() - var n int - for _, s := range s.st.data { - m, err := pbutil.WriteDelimited(w, s) - if err != nil { - return n + m, err - } - n += m + b, err := s.st.MarshalBinary() + if err != nil { + return 0, err } - return n, nil -} -type gossiper struct { - *Silences + return io.Copy(w, bytes.NewReader(b)) } -// Gossip implements the mesh.Gossiper interface. -func (g gossiper) Gossip() mesh.GossipData { - g.mtx.Lock() - defer g.mtx.Unlock() +// MarshalBinary serializes all silences. +func (s *Silences) MarshalBinary() ([]byte, error) { + s.mtx.Lock() + defer s.mtx.Unlock() - return g.st.clone() + return s.st.MarshalBinary() } -// OnGossip implements the mesh.Gossiper interface. -func (g gossiper) OnGossip(msg []byte) (mesh.GossipData, error) { - gd, err := decodeGossipData(msg) +// Merge merges silence state received from the cluster with the local state. +func (s *Silences) Merge(b []byte) error { + st, err := decodeState(bytes.NewReader(b)) if err != nil { - return nil, err - } - g.mtx.Lock() - defer g.mtx.Unlock() - - if delta := g.st.mergeDelta(gd); len(delta.data) > 0 { - return delta, nil + return err } - return nil, nil -} + s.mtx.Lock() + defer s.mtx.Unlock() -// OnGossipBroadcast implements the mesh.Gossiper interface. -func (g gossiper) OnGossipBroadcast(src mesh.PeerName, msg []byte) (mesh.GossipData, error) { - gd, err := decodeGossipData(msg) - if err != nil { - return nil, err + for _, e := range st { + if merged := s.st.merge(e); merged && !cluster.OversizedMessage(b) { + // If this is the first we've seen the message and it's + // not oversized, gossip it to other nodes. We don't + // propagate oversized messages because they're sent to + // all nodes already. + s.broadcast(b) + s.metrics.propagatedMessagesTotal.Inc() + level.Debug(s.logger).Log("msg", "gossiping new silence", "silence", e) + } } - g.mtx.Lock() - defer g.mtx.Unlock() - - return g.st.mergeDelta(gd), nil -} - -// OnGossipUnicast implements the mesh.Gossiper interface. -// It always panics. -func (g gossiper) OnGossipUnicast(src mesh.PeerName, msg []byte) error { - panic("not implemented") + return nil } -type silenceMap map[string]*pb.MeshSilence - -type gossipData struct { - data silenceMap - mtx sync.RWMutex +func (s *Silences) SetBroadcast(f func([]byte)) { + s.mtx.Lock() + s.broadcast = f + s.mtx.Unlock() } -var _ mesh.GossipData = &gossipData{} +type state map[string]*pb.MeshSilence -func newGossipData() *gossipData { - return &gossipData{ - data: silenceMap{}, +func (s state) merge(e *pb.MeshSilence) bool { + // Comments list was moved to a single comment. Apply upgrade + // on silences received from peers. + if len(e.Silence.Comments) > 0 { + e.Silence.Comment = e.Silence.Comments[0].Comment + e.Silence.CreatedBy = e.Silence.Comments[0].Author + e.Silence.Comments = nil } -} - -func decodeGossipData(msg []byte) (*gossipData, error) { - gd := newGossipData() - rd := bytes.NewReader(msg) + id := e.Silence.Id - for { - var s pb.MeshSilence - if _, err := pbutil.ReadDelimited(rd, &s); err != nil { - if err == io.EOF { - break - } - return gd, err - } - gd.data[s.Silence.Id] = &s + prev, ok := s[id] + if !ok || prev.Silence.UpdatedAt.Before(e.Silence.UpdatedAt) { + s[id] = e + return true } - return gd, nil + return false } -// Encode implements the mesh.GossipData interface. -func (gd *gossipData) Encode() [][]byte { - // Split into sub-messages of ~1MB. - const maxSize = 1024 * 1024 - - var ( - buf bytes.Buffer - res [][]byte - n int - ) - - gd.mtx.RLock() - defer gd.mtx.RUnlock() +func (s state) MarshalBinary() ([]byte, error) { + var buf bytes.Buffer - for _, s := range gd.data { - m, err := pbutil.WriteDelimited(&buf, s) - n += m - if err != nil { - // TODO(fabxc): log error and skip entry. Or can this really not happen with a bytes.Buffer? - panic(err) - } - if n > maxSize { - res = append(res, buf.Bytes()) - buf = bytes.Buffer{} + for _, e := range s { + if _, err := pbutil.WriteDelimited(&buf, e); err != nil { + return nil, err } } - if buf.Len() > 0 { - res = append(res, buf.Bytes()) - } - return res -} - -func (gd *gossipData) clone() *gossipData { - gd.mtx.RLock() - defer gd.mtx.RUnlock() - - data := make(silenceMap, len(gd.data)) - for id, s := range gd.data { - data[id] = s - } - return &gossipData{data: data} + return buf.Bytes(), nil } -// Merge the silence set with gossip data and return a new silence state. -func (gd *gossipData) Merge(other mesh.GossipData) mesh.GossipData { - ot := other.(*gossipData) - ot.mtx.RLock() - defer ot.mtx.RUnlock() - - gd.mtx.Lock() - defer gd.mtx.Unlock() - - for id, s := range ot.data { - // Comments list was moved to a single comment. Apply upgrade - // on silences received from peers. - if len(s.Silence.Comments) > 0 { - s.Silence.Comment = s.Silence.Comments[0].Comment - s.Silence.CreatedBy = s.Silence.Comments[0].Author - s.Silence.Comments = nil - } - - prev, ok := gd.data[id] - if !ok { - gd.data[id] = s +func decodeState(r io.Reader) (state, error) { + st := state{} + for { + var s pb.MeshSilence + _, err := pbutil.ReadDelimited(r, &s) + if err == nil { + if s.Silence == nil { + return nil, ErrInvalidState + } + st[s.Silence.Id] = &s continue } - if prev.Silence.UpdatedAt.Before(s.Silence.UpdatedAt) { - gd.data[id] = s + if err == io.EOF { + break } + return nil, err } - return gd + return st, nil } -// mergeDelta behaves like Merge but ignores expired silences, and -// returns a gossipData only containing things that have changed. -func (gd *gossipData) mergeDelta(od *gossipData) *gossipData { - delta := newGossipData() - - od.mtx.RLock() - defer od.mtx.RUnlock() - - gd.mtx.Lock() - defer gd.mtx.Unlock() - - for id, s := range od.data { - // If a gossiped silence is expired, skip it. - // For a given silence duration exceeding a few minutes, - // active silences will have already been gossiped. - // Once the active silence is gossiped, its expiration - // should happen more or less simultaneously on the different - // alertmanager nodes. Preventing the gossiping of expired - // silences allows them to be GC'd, and doesn't affect - // consistency across the mesh. - if !s.ExpiresAt.After(utcNow()) { - continue - } - - // Comments list was moved to a single comment. Apply upgrade - // on silences received from peers. - if len(s.Silence.Comments) > 0 { - s.Silence.Comment = s.Silence.Comments[0].Comment - s.Silence.CreatedBy = s.Silence.Comments[0].Author - s.Silence.Comments = nil - } - - prev, ok := gd.data[id] - if !ok { - gd.data[id] = s - delta.data[id] = s - continue - } - if prev.Silence.UpdatedAt.Before(s.Silence.UpdatedAt) { - gd.data[id] = s - delta.data[id] = s - } +func marshalMeshSilence(e *pb.MeshSilence) ([]byte, error) { + var buf bytes.Buffer + if _, err := pbutil.WriteDelimited(&buf, e); err != nil { + return nil, err } - return delta + return buf.Bytes(), nil } // replaceFile wraps a file that is moved to another filename on closing. diff --git a/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go b/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go index baac66dc58f..164ae17cf5b 100644 --- a/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go +++ b/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-gogo. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: silence.proto -// DO NOT EDIT! /* Package silencepb is a generated protocol buffer package. @@ -20,9 +19,11 @@ import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + import time "time" -import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" +import types "github.com/gogo/protobuf/types" import io "io" @@ -196,8 +197,8 @@ func (m *Comment) MarshalTo(dAtA []byte) (int, error) { } dAtA[i] = 0x1a i++ - i = encodeVarintSilence(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp))) - n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) + i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp))) + n1, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:]) if err != nil { return 0, err } @@ -240,24 +241,24 @@ func (m *Silence) MarshalTo(dAtA []byte) (int, error) { } dAtA[i] = 0x1a i++ - i = encodeVarintSilence(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartsAt))) - n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartsAt, dAtA[i:]) + i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.StartsAt))) + n2, err := types.StdTimeMarshalTo(m.StartsAt, dAtA[i:]) if err != nil { return 0, err } i += n2 dAtA[i] = 0x22 i++ - i = encodeVarintSilence(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.EndsAt))) - n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.EndsAt, dAtA[i:]) + i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.EndsAt))) + n3, err := types.StdTimeMarshalTo(m.EndsAt, dAtA[i:]) if err != nil { return 0, err } i += n3 dAtA[i] = 0x2a i++ - i = encodeVarintSilence(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt))) - n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) + i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt))) + n4, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:]) if err != nil { return 0, err } @@ -316,8 +317,8 @@ func (m *MeshSilence) MarshalTo(dAtA []byte) (int, error) { } dAtA[i] = 0x12 i++ - i = encodeVarintSilence(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExpiresAt))) - n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExpiresAt, dAtA[i:]) + i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.ExpiresAt))) + n6, err := types.StdTimeMarshalTo(m.ExpiresAt, dAtA[i:]) if err != nil { return 0, err } @@ -325,24 +326,6 @@ func (m *MeshSilence) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Silence(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Silence(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintSilence(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -380,7 +363,7 @@ func (m *Comment) Size() (n int) { if l > 0 { n += 1 + l + sovSilence(uint64(l)) } - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) + l = types.SizeOfStdTime(m.Timestamp) n += 1 + l + sovSilence(uint64(l)) return n } @@ -398,11 +381,11 @@ func (m *Silence) Size() (n int) { n += 1 + l + sovSilence(uint64(l)) } } - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartsAt) + l = types.SizeOfStdTime(m.StartsAt) n += 1 + l + sovSilence(uint64(l)) - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.EndsAt) + l = types.SizeOfStdTime(m.EndsAt) n += 1 + l + sovSilence(uint64(l)) - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) + l = types.SizeOfStdTime(m.UpdatedAt) n += 1 + l + sovSilence(uint64(l)) if len(m.Comments) > 0 { for _, e := range m.Comments { @@ -428,7 +411,7 @@ func (m *MeshSilence) Size() (n int) { l = m.Silence.Size() n += 1 + l + sovSilence(uint64(l)) } - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExpiresAt) + l = types.SizeOfStdTime(m.ExpiresAt) n += 1 + l + sovSilence(uint64(l)) return n } @@ -686,7 +669,7 @@ func (m *Comment) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -826,7 +809,7 @@ func (m *Silence) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartsAt, dAtA[iNdEx:postIndex]); err != nil { + if err := types.StdTimeUnmarshal(&m.StartsAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -856,7 +839,7 @@ func (m *Silence) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.EndsAt, dAtA[iNdEx:postIndex]); err != nil { + if err := types.StdTimeUnmarshal(&m.EndsAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -886,7 +869,7 @@ func (m *Silence) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { + if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1088,7 +1071,7 @@ func (m *MeshSilence) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExpiresAt, dAtA[iNdEx:postIndex]); err != nil { + if err := types.StdTimeUnmarshal(&m.ExpiresAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/vendor/github.com/prometheus/alertmanager/template/default.tmpl b/vendor/github.com/prometheus/alertmanager/template/default.tmpl index 5dd460a93b3..69e71f05120 100644 --- a/vendor/github.com/prometheus/alertmanager/template/default.tmpl +++ b/vendor/github.com/prometheus/alertmanager/template/default.tmpl @@ -60,6 +60,11 @@ Alerts Resolved: AlertmanagerUrl: {{ template "__alertmanagerURL" . }} {{- end }} +{{ define "wechat.default.api_secret" }}{{ end }} +{{ define "wechat.default.to_user" }}{{ end }} +{{ define "wechat.default.to_party" }}{{ end }} +{{ define "wechat.default.to_tag" }}{{ end }} +{{ define "wechat.default.agent_id" }}{{ end }} diff --git a/vendor/github.com/prometheus/alertmanager/template/email.html b/vendor/github.com/prometheus/alertmanager/template/email.html index 01ac523367c..52b6b2f4083 100644 --- a/vendor/github.com/prometheus/alertmanager/template/email.html +++ b/vendor/github.com/prometheus/alertmanager/template/email.html @@ -236,7 +236,7 @@ font-size: 16px; } .alert.alert-warning { - background-color: ##E6522C; + background-color: #E6522C; } .alert.alert-bad { background-color: #D0021B; diff --git a/vendor/github.com/prometheus/alertmanager/template/internal/deftmpl/bindata.go b/vendor/github.com/prometheus/alertmanager/template/internal/deftmpl/bindata.go index 858ed7ad17c..b27f250a3f9 100644 --- a/vendor/github.com/prometheus/alertmanager/template/internal/deftmpl/bindata.go +++ b/vendor/github.com/prometheus/alertmanager/template/internal/deftmpl/bindata.go @@ -68,7 +68,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _templateDefaultTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x1b\xff\x4f\xdb\xb8\xfe\xf7\xfc\x15\x9f\xcb\xe9\xe9\x86\xd4\x36\x85\xdd\x4d\x47\x69\x79\xea\x4a\x18\xd1\x2b\x29\x4a\xc3\x76\xd3\xe9\x84\xdc\xc4\x6d\xbd\x25\x76\xce\x76\x28\x3d\xd6\xff\xfd\xc9\x4e\xfa\x25\x34\x85\x82\x76\xd0\xf7\x0e\xd0\x46\xe2\xf8\xf3\xfd\xab\x63\xe7\xf6\x16\x42\x3c\x24\x14\x83\x79\x75\x85\x22\xcc\x65\x8c\x28\x1a\x61\x6e\xc2\x6c\xd6\x56\xf7\xe7\xd9\xfd\xed\x2d\x60\x1a\xc2\x6c\x66\x6c\x04\xb9\xf4\xba\x0a\xea\xf6\x16\x6a\xf6\x8d\xc4\x9c\xa2\xe8\xd2\xeb\xc2\x6c\x66\xfd\x68\xe9\x79\xe2\xdf\x1c\x07\x98\x5c\x63\xde\x52\x93\xbc\xfc\x26\x83\xc9\xb1\x17\xd1\x8b\x74\xf0\x05\x07\x52\xa1\xfd\x5d\x81\xf4\x25\x92\xa9\x80\x6f\x20\xd9\x65\x92\xcc\x41\xc9\x10\xf0\x9f\x8b\x87\xe6\x90\x70\x42\x47\x0a\xa6\xa1\x60\xb4\x14\xa2\x76\xaa\x47\xe1\x1b\x44\x98\xae\x52\xfc\x03\xd4\xa4\x0f\x9c\xa5\x49\x17\x0d\x70\x24\x6a\x7d\xc6\x25\x0e\x2f\x10\xe1\xa2\xf6\x11\x45\x29\x56\x04\xbf\x30\x42\xc1\x04\x85\x15\x32\x92\x23\x09\x6f\x14\xae\x5a\x87\xc5\x31\xa3\x19\xf0\x5e\x3e\xb6\x82\x6f\x0f\x66\xb3\x37\xb7\xb7\x30\x21\x72\x5c\x9c\x5c\xf3\x70\xcc\xae\x71\x91\xba\x8b\x62\x2c\x72\x35\x96\x51\x5f\x30\xbe\xb7\xb8\xda\x60\x9b\x10\x8b\x80\x93\x44\x12\x46\xcd\x7b\x74\x2c\xf1\x8d\xcc\xec\x78\x15\x11\x21\xf3\xa9\x1c\xd1\x11\x86\x1a\xcc\x66\x19\x5f\x0d\x63\x39\xb8\xae\x27\xa5\x95\xaa\x56\xa4\x62\x5f\xdd\xb5\x60\x21\x40\xce\x58\x46\xbc\x4d\x29\x93\x48\xf1\x54\x40\xb9\x32\xfc\x34\xbc\x7d\x96\xf2\x00\x37\x32\x63\x62\x8a\x39\x92\x8c\x67\xee\x67\x94\x28\xaa\xa0\x03\x11\xa1\xe0\x6b\x2d\xc4\x43\x94\x46\xb2\x26\x89\x8c\x70\xae\x05\x89\xe3\x24\x42\xb2\xe8\x8b\xb5\x4d\x2a\x2f\xe2\x49\x85\x0a\x81\xb8\x0c\x55\x31\xd0\xb6\xc4\x37\x44\x51\x34\x40\xc1\xd7\x35\x7c\xa5\xec\x2b\xa4\xf0\x0d\x1e\x9a\x18\x11\xfa\x75\x6b\x0e\x12\x8e\x95\xb3\x98\xdb\xcd\x5e\xc1\x7f\xaf\x02\x74\xda\xd8\x92\x03\x12\x30\x8a\x63\xf6\x85\x6c\xc9\x83\x9a\x9f\xf2\x68\x5b\x8e\xb7\x17\x6e\xc8\x98\xcc\x92\xe4\x06\x9f\x1a\x93\x24\x18\x23\xb9\x04\xe0\x2c\x7e\xba\x27\xdc\xc5\x16\x63\x21\xd0\xe8\x11\x5e\x5a\xe0\x2d\x51\xd4\xc2\x54\x4e\x17\xf8\xd6\x53\xc5\xe3\x3c\x7f\x1d\x63\x10\x11\x4c\xe5\xd3\x25\xde\x84\x71\x59\x64\x9e\xe6\x4f\xeb\x78\x09\x15\x12\xd1\x00\x8b\x12\xbc\x6b\xb9\xf1\x1e\xad\xb2\x44\x8c\x30\x25\xf8\xe9\x46\xba\x0f\xd9\xba\x85\xf2\x52\xb2\x21\x73\x96\xd6\x0e\xe3\x4e\xe5\x2a\x94\xc6\x3d\xa8\x43\x75\x36\x33\xb2\x41\xc8\x06\x75\x8e\xbe\x5f\x23\xc5\xfa\xaa\x89\x54\x57\x24\x2a\xa1\xe7\x61\xc1\xa2\x6b\x1c\xde\xa1\x38\x1f\xde\x9e\xe6\x1c\x62\x8d\x6a\x75\x1b\x95\x0a\x5d\x32\x1e\xef\x4d\x05\xab\x4f\xf0\x53\x02\xd3\x78\xb5\xdf\x3d\xf6\x6b\xaf\xea\x9f\x47\x6b\xf8\x4a\xed\xb3\x8a\xa0\x68\xa2\x6b\x12\x48\xc6\x59\x22\x96\x96\x97\x48\xe2\xab\xa2\xad\x5e\xcd\xf1\xb8\x70\x5a\xd7\x2a\xa6\x92\xc8\xe9\x55\x48\x44\x12\xa1\xe9\xd5\x86\xde\xe7\xe1\xdc\xb7\x8e\x39\x66\x94\x48\xa6\x14\x72\x25\x19\x8b\x1e\x59\x55\x56\x71\xe3\x18\x91\x68\xe9\x07\xcb\xe5\xc5\xa3\xb9\x2c\x62\x1a\xcb\x58\xb3\x65\x34\x7f\x38\xe9\x75\xfc\xcf\x17\x36\xa8\x21\xb8\xb8\x7c\xdf\x75\x3a\x60\x56\x2d\xeb\xd3\xdb\x8e\x65\x9d\xf8\x27\xf0\xdb\x99\x7f\xde\x85\xfd\x5a\x1d\x7c\x8e\xa8\x20\xca\xd9\x50\x64\x59\xb6\x6b\x82\x39\x96\x32\x69\x58\xd6\x64\x32\xa9\x4d\xde\xd6\x18\x1f\x59\xbe\x67\xdd\x28\x5c\xfb\x0a\x38\xbf\xac\xca\x15\xc8\x5a\x28\x43\xf3\xd8\x68\xfe\x50\xad\x1a\x7d\x39\x8d\x30\x20\x1a\x82\x26\x12\x62\x4e\x94\x41\x55\xf7\x01\x0a\xb5\x68\x58\xd6\x88\xc8\x71\x3a\xa8\x05\x2c\xb6\x94\x0c\xa3\x94\x5a\x1a\x1d\x0a\x32\x7c\x55\x2d\x5a\x75\xae\x0e\x61\x18\x86\x3f\xc6\x70\xee\xf8\xd0\x25\x01\xa6\x02\xc3\x9b\x73\xc7\xdf\x33\x8c\x0e\x4b\xa6\x9c\x8c\xc6\x12\xde\x04\x7b\x70\x50\xdf\xff\x19\xce\x33\x8c\x86\x71\x81\x79\x4c\x84\x20\x8c\x02\x11\x30\xc6\x1c\x0f\xa6\x30\xe2\x88\x4a\x1c\x56\x60\xc8\x31\x06\x36\x84\x60\x8c\xf8\x08\x57\x40\x32\x40\x74\x0a\x09\xe6\x82\x51\x60\x03\x89\x08\x55\xfe\x8f\x20\x60\xc9\xd4\x60\x43\x90\x63\x22\x40\xb0\xa1\x9c\x20\x9e\x49\x88\x84\x60\x01\x41\x12\x87\x10\xb2\x20\x8d\x31\xcd\x02\x17\x86\x24\xc2\x02\xde\xc8\x31\x06\xb3\x9f\x43\x98\x7b\x9a\x48\x88\x51\x64\x10\x0a\xea\xd9\xfc\x91\x5e\x99\xb1\x54\x02\xc7\x42\x72\xa2\xb5\x50\x01\x42\x83\x28\x0d\x15\x0f\xf3\xc7\x11\x89\x49\x4e\x41\x81\x6b\xc1\x85\x21\x19\xa4\x02\x57\x34\x9f\x15\x88\x59\x48\x86\xea\x2f\xd6\x62\x25\xe9\x20\x22\x62\x5c\x81\x90\x28\xd4\x83\x54\xe2\x0a\x08\x35\xa8\xf5\x58\x51\x72\x58\x8c\x83\xc0\x51\x64\x04\x2c\x21\x58\x80\x96\x75\xc9\x9d\x9e\xa3\x58\x4f\x94\x42\x65\xae\x22\xa1\x46\x26\x63\x16\x17\x25\x21\xc2\x18\xa6\x9c\x12\x31\xc6\x1a\x26\x64\x20\x98\xa6\xa8\xbc\x59\x8d\xa8\xe9\x43\x16\x45\x6c\xa2\x44\x0b\x18\x0d\x49\xbe\x18\xd3\x46\x46\x03\xb5\x20\x0d\x16\x76\xa5\x4c\x92\x20\x53\xb7\x36\x40\xb2\xb4\x6a\xfe\x48\x8c\x51\x14\xc1\x00\xe7\x0a\xc3\x21\x10\x0a\x68\x45\x1c\xae\xc8\xab\x16\x4b\x12\x14\x41\xc2\xb8\xa6\x77\x57\xcc\x9a\x61\xf8\x67\x36\xf4\x7b\xa7\xfe\xa7\xb6\x67\x83\xd3\x87\x0b\xaf\xf7\xd1\x39\xb1\x4f\xc0\x6c\xf7\xc1\xe9\x9b\x15\xf8\xe4\xf8\x67\xbd\x4b\x1f\x3e\xb5\x3d\xaf\xed\xfa\x9f\xa1\x77\x0a\x6d\xf7\x33\xfc\xc7\x71\x4f\x2a\x60\xff\x76\xe1\xd9\xfd\x3e\xf4\x3c\xc3\x39\xbf\xe8\x3a\xf6\x49\x05\x1c\xb7\xd3\xbd\x3c\x71\xdc\x0f\xf0\xfe\xd2\x07\xb7\xe7\x43\xd7\x39\x77\x7c\xfb\x04\xfc\x1e\x28\x82\x39\x2a\xc7\xee\x2b\x64\xe7\xb6\xd7\x39\x6b\xbb\x7e\xfb\xbd\xd3\x75\xfc\xcf\x15\xe3\xd4\xf1\x5d\x85\xf3\xb4\xe7\x41\x1b\x2e\xda\x9e\xef\x74\x2e\xbb\x6d\x0f\x2e\x2e\xbd\x8b\x5e\xdf\x86\xb6\x7b\x02\x6e\xcf\x75\xdc\x53\xcf\x71\x3f\xd8\xe7\xb6\xeb\xd7\xc0\x71\xc1\xed\x81\xfd\xd1\x76\x7d\xe8\x9f\xb5\xbb\x5d\x45\xca\x68\x5f\xfa\x67\x3d\x4f\xf1\x07\x9d\xde\xc5\x67\xcf\xf9\x70\xe6\xc3\x59\xaf\x7b\x62\x7b\x7d\x78\x6f\x43\xd7\x69\xbf\xef\xda\x19\x29\xf7\x33\x74\xba\x6d\xe7\xbc\x02\x27\xed\xf3\xf6\x07\x5b\x43\xf5\xfc\x33\xdb\x33\xd4\xb4\x8c\x3b\xf8\x74\x66\xab\x21\x45\xaf\xed\x42\xbb\xe3\x3b\x3d\x57\x89\xd1\xe9\xb9\xbe\xd7\xee\xf8\x15\xf0\x7b\x9e\xbf\x00\xfd\xe4\xf4\xed\x0a\xb4\x3d\xa7\xaf\x14\x72\xea\xf5\xce\x2b\x86\x52\x67\xef\x54\x4d\x71\x5c\x05\xe7\xda\x19\x16\xa5\x6a\x28\x58\xa4\xe7\xe9\xfb\xcb\xbe\xbd\x40\x08\x27\x76\xbb\xeb\xb8\x1f\xfa\x0a\x58\x89\x38\x9f\x5c\x33\xaa\xd5\x63\xa3\xa9\x53\xe0\x4d\x1c\x51\xd1\x2a\x49\x6c\xfb\x87\x87\x87\x59\x3e\x33\xb7\x9b\x24\x54\x72\x6b\x99\x43\x46\x65\x75\x88\x62\x12\x4d\x1b\xf0\xd3\x19\x8e\xae\xb1\x24\x01\x02\x17\xa7\xf8\xa7\x0a\x2c\x06\x2a\xd0\xe6\x04\x45\x15\x10\x88\x8a\xaa\xc0\x9c\x0c\x8f\x60\xc0\x6e\xaa\x82\xfc\xa5\x6a\x31\x0c\x18\x0f\x31\xaf\x0e\xd8\xcd\x11\x68\xa4\x82\xfc\x85\x1b\xb0\xff\x73\x72\x73\x04\x31\xe2\x23\x42\x1b\x50\x3f\x52\xb9\x75\x8c\x51\xf8\x92\xf4\x63\x2c\x11\xa8\x8a\xda\x32\xaf\x09\x9e\xa8\x28\x32\x55\xf4\x4a\x4c\x65\xcb\x9c\x90\x50\x8e\x5b\x21\xbe\x26\x01\xae\xea\x9b\x97\x53\x16\x58\x73\x76\x95\x31\xab\xf8\xcf\x94\x5c\xb7\xcc\x4e\xc6\x6a\xd5\x9f\x26\x78\x85\x71\xd5\x8a\x58\xca\xb8\x47\xba\x12\x08\x2c\x5b\x97\xfe\x69\xf5\xd7\x17\x66\x5f\xbf\xba\x78\x39\x73\xdf\xd7\x8b\x34\x2d\xcd\xdc\xb1\x61\x34\x2d\xe5\x94\xea\x62\xc0\xc2\x29\x10\x89\x63\x11\xb0\x04\xb7\x4c\x53\xdf\xc8\xa9\xba\xce\x23\x4a\x04\x63\x1c\x23\x1d\x51\xb6\xaa\xee\xe7\xf3\xde\xf7\x59\x85\xac\x4e\xf0\xe0\x2b\x91\xd5\xec\x41\xcc\x98\x1c\x6b\xa0\xac\x36\x10\x24\x70\xb8\x9c\xa4\x7c\x43\x43\x57\x51\xf8\x25\x15\xb2\x01\x94\x51\x7c\x04\x63\xac\x2a\x53\x03\xf6\xeb\xf5\x7f\x1d\x41\x44\x28\xae\x2e\x86\x6a\xef\x70\x7c\x04\x3a\x02\xb2\x09\xf0\x03\x89\x55\xb0\x20\x2a\x8f\x60\x80\x82\xaf\x23\xce\x52\x1a\x56\x03\x16\x31\xde\x80\x1f\x87\xef\xd4\xef\xaa\xfa\x21\x41\x61\xa8\xb9\x52\xde\x30\x18\xe9\x99\x2d\x33\x9f\x69\x2a\x7d\x4b\x34\x78\x6e\xf7\x58\x11\x69\x4b\x39\x4a\x79\x07\x68\x4a\xfe\x82\x79\x0c\x40\x71\xf0\xcc\x99\xf4\x1a\x73\x85\x24\xaa\xa2\x88\x8c\x68\x03\x24\x4b\x8a\x8a\xba\xd6\x0f\x5a\xa6\x64\x89\x79\xdc\xb4\x64\xb8\x64\x34\xcb\xac\xe6\xbb\x7a\xfd\x99\x43\xa5\x94\xe9\x7c\x69\xd5\x80\x41\xc4\x82\xaf\x05\xdf\x8e\xd1\x4d\x35\x77\x92\x77\xf5\x7a\x72\x53\x78\x18\x44\x18\x71\x45\x50\x8e\x0b\xe3\x9b\x02\x65\xa1\x1c\x40\xa9\x64\x77\x42\xa2\xa0\x2d\xad\x28\x80\x66\x48\xae\x9f\xdb\xad\x8a\xf2\xde\x55\xce\xfd\x42\xcc\xf9\x56\x46\xd6\xc1\x9c\xdb\x59\x69\xc2\x84\x00\x47\x51\x3e\xbb\x65\xd6\xb3\x7b\x91\xa0\x60\x7e\xff\xac\x82\xe6\x0f\x39\x0a\x49\x2a\x1a\xf0\x56\x8f\x95\x24\x80\xe1\xb0\x90\xc5\x32\xb0\x06\xec\x27\x37\x20\x58\x44\x42\xf8\x11\x1f\xaa\xdf\x62\x62\x18\x0e\x57\x74\xb1\x0b\xd9\x61\xc9\xc9\xf3\x65\x89\x77\x1b\x03\xae\xa0\x5d\x0d\x32\xc9\x4b\xcd\x2f\xf5\xfa\x11\xe8\x12\x95\xcf\x0f\x30\x95\x98\x97\xd9\x4b\xff\xab\x6b\xa3\xac\xdb\xcd\x7e\xf7\xcb\xc1\x41\xa7\xbc\x00\x1d\x28\xbf\x36\x21\x8f\xb7\x8c\xc0\xaa\xf5\x32\xd8\xf2\x88\x9c\xff\x2c\x77\x40\x17\x5b\x9f\xa0\x5f\x96\x94\xbe\x4b\xda\x83\x7d\x98\xcd\xc4\xe2\x85\x07\x0c\x19\x87\xe5\x2e\xdd\x86\x5d\x52\x98\xcd\xee\x50\x85\xd5\x3d\xbb\x56\x61\xc7\x6e\x6d\x5a\xfe\x6a\xa5\x60\xfc\x45\x0e\x5e\xdc\xf3\x57\x37\xdd\xa6\x98\x2d\x9d\x67\x3f\x73\x9e\xfb\x7c\x63\xe7\x73\xdf\x46\xb5\xef\x96\x13\xec\xba\x2b\xd4\xa1\x3e\xcf\x25\xf7\xb9\x43\x2e\x06\x82\x31\xc7\xc3\x96\xb9\xcd\x4b\xf7\x67\xf6\x87\x79\xd2\x3c\x3d\x3d\xcd\x93\x6f\x88\x03\xc6\xf5\x3b\xb9\xf9\xf2\xa0\xb0\x20\x38\x50\xcb\x81\x42\xde\x1e\xb0\x28\x2c\x4f\xdc\x41\xca\x85\xc2\x9e\x30\x92\x0d\x2c\x1a\x0a\x42\x35\xd2\xbc\xaf\xb8\x93\xe0\x7f\x51\x8c\x69\x7c\xfa\x25\xea\x90\xf1\xb8\x01\x01\x4a\x88\x44\x11\xf9\x0b\x97\x26\xfd\xb7\x3f\xff\x8a\x43\x54\x52\xaf\xd7\x66\xe4\xc3\x5a\xcb\x8d\xac\x90\x2f\x06\x17\xdd\x5b\x72\x93\x9b\xf7\xf8\x23\xc1\x13\x20\x14\x1e\x7c\x3b\xde\xb4\x50\xa9\x0f\xdf\x49\xbc\xe5\xe9\x37\xfb\x79\x68\xf3\xa3\xa4\x28\xbc\x86\xec\xdf\x13\xb2\x42\x72\x46\x47\x2f\xa7\xda\xdf\x37\x9f\xb3\xfa\x23\xdf\xf9\x6a\x5a\x19\x93\xdf\xc1\xeb\x4a\x1a\x86\xfc\xc9\xfc\x30\xd1\xdd\x2d\xb4\x57\x3f\xfc\x67\xf8\x61\xd6\x9a\x2e\x5c\xad\x39\x78\x39\x33\x83\x55\xae\xa3\x07\x4e\xd1\x6d\x3e\xea\xf6\xc2\xc2\x6c\x8e\x3b\x28\xa9\x05\xcb\x4d\xf4\xac\x12\xbc\xb8\x67\xac\x70\xb4\x2b\xee\xf1\xa0\x46\x1f\x3c\x1a\xf9\x3f\xea\x2c\xab\x1d\xe6\xdd\xb3\x9a\x2f\xd4\x50\xce\xdb\xad\xb5\x9e\x32\xa5\x21\xe6\xaa\xfb\x2b\xba\x53\x76\xda\x54\x35\x51\xbb\x97\x63\x9e\x56\x4d\xb7\x6c\xef\x56\xcf\x9a\x94\x9a\xf7\xb5\x2b\xdc\x99\x6a\xbc\x73\x9e\x09\xd0\x1c\xef\x20\x4f\x3b\xa7\xa7\xc7\x44\xf0\x7d\x1d\xf1\x6b\x60\xfd\x7f\xb6\xb9\xab\xcb\xad\xc5\x99\xbd\xe5\x82\x6b\x3e\xf4\x02\x4b\xae\xd5\x13\x84\xaf\xde\xf8\xcf\xf0\xc6\xd7\x45\xd7\xeb\xa2\xeb\x75\xd1\xb5\xeb\xce\xf2\xba\xe8\xda\x99\x96\x6d\x93\xa1\x9a\x96\xde\x8f\x3b\x7e\xc4\x56\xe8\x02\x64\x39\xf2\xec\x27\x31\x0a\x47\x93\x56\x4e\x9a\x2c\x0d\x7d\x78\x78\x78\xdf\x06\x77\x71\x67\x77\x7d\x4b\x72\x37\x9a\x86\x5d\x6a\x5f\x9e\xb3\x75\x39\xd8\xd8\xba\x94\x6e\xa2\x3d\x64\xf2\x95\xde\xe6\xce\xb9\x86\xe2\x29\xac\xd5\x74\x55\xfc\x9a\xfc\xf9\x1c\xe2\x60\x35\x5b\x69\x89\xb6\x4e\x55\x98\x4a\x18\x4c\xb7\xdb\x87\x5b\xcf\x1d\x6b\xe7\x1d\xee\x66\x86\xa6\x15\x92\xeb\xe3\xec\x7f\xa3\x98\x26\x76\xad\xad\xdd\x70\xbc\x2e\x13\x71\x99\xbf\x9a\xd6\x80\x85\x53\x35\x32\x96\x71\x74\x6c\x18\xe5\xdf\xef\x24\xa9\x18\xb3\x6b\xcc\xbf\xc3\xd7\xda\x6b\xa8\xfe\xfe\xef\xc1\xbe\xcf\xe7\x60\xdb\x7f\x0d\xf6\xfd\x3e\x06\x5b\xa1\xb9\x85\x26\x97\x9f\x5c\x3f\xe2\xb3\xca\xff\x06\x00\x00\xff\xff\x96\x70\x0b\x9a\x8b\x42\x00\x00") +var _templateDefaultTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3b\xff\x6f\xdb\xb6\xb3\xbf\xeb\xaf\xb8\x69\x78\x58\x03\xd8\x96\xd3\x6e\xc5\xea\xd8\x79\x70\x1d\xa5\x11\x9e\x63\x07\xb6\xd2\xae\x18\x86\x80\x96\xce\x36\x5b\x89\xd4\x48\x3a\x89\x97\xf9\x7f\x7f\x20\x25\x7f\x91\x2d\x27\x4e\xd1\x25\xfe\x7c\x96\x04\x6d\x24\xea\xbe\xdf\xf1\xee\x28\x52\x77\x77\x10\xe2\x90\x32\x04\xfb\xea\x8a\x44\x28\x54\x4c\x18\x19\xa1\xb0\x61\x36\x6b\xea\xfb\xf3\xf4\xfe\xee\x0e\x90\x85\x30\x9b\x59\x5b\x51\x2e\x7b\x6d\x8d\x75\x77\x07\x15\xf7\x56\xa1\x60\x24\xba\xec\xb5\x61\x36\x73\x7e\x74\x0c\x9c\xfc\x5f\x81\x01\xd2\x6b\x14\x0d\x0d\xd4\xcb\x6e\x52\x9c\x8c\x7a\x9e\xbc\x9c\x0c\xbe\x60\xa0\x34\xd9\xdf\x35\x4a\x5f\x11\x35\x91\xf0\x37\x28\x7e\x99\x24\x73\x54\x3a\x04\xfc\x73\xf1\xd0\x1e\x52\x41\xd9\x48\xe3\xd4\x34\x8e\xd1\x42\x56\x4e\xcd\x28\xfc\x0d\x11\xb2\x55\x8e\x7f\x80\x06\xfa\x20\xf8\x24\x69\x93\x01\x46\xb2\xd2\xe7\x42\x61\x78\x41\xa8\x90\x95\x8f\x24\x9a\xa0\x66\xf8\x85\x53\x06\x36\x68\xaa\x90\xb2\x1c\x29\x78\xa5\x69\x55\x5a\x3c\x8e\x39\x4b\x91\x0f\xb2\xb1\x15\x7a\x07\x30\x9b\xbd\xba\xbb\x83\x1b\xaa\xc6\x79\xe0\x4a\x0f\x63\x7e\x8d\x79\xee\x1d\x12\xa3\xcc\xcc\x58\xc4\x7d\x21\xf8\xc1\xe2\x6a\x8b\x6f\x42\x94\x81\xa0\x89\xa2\x9c\xd9\xf7\xd8\x58\xe1\xad\x4a\xfd\x78\x15\x51\xa9\x32\x50\x41\xd8\x08\xa1\x02\xb3\x59\x2a\x57\xcd\x5a\x0e\x6e\xda\x49\x5b\xa5\x6c\x0c\xa9\xc5\xd7\x77\x0d\x58\x28\x90\x09\x96\x32\x6f\x32\xc6\x15\xd1\x32\xe5\x48\xae\x0c\x7f\x1b\xdd\x3e\x9f\x88\x00\x6b\xa9\x33\x91\xa1\x20\x8a\x8b\x34\xfc\xac\x02\x43\xe5\x6c\x20\x23\x12\x7c\xad\x84\x38\x24\x93\x48\x55\x14\x55\x11\x66\x56\x50\x18\x27\x11\x51\xf9\x58\xac\x6c\x33\x79\x9e\xce\x44\xea\x29\x10\x17\x91\xca\x4f\xb4\x1d\xe9\x0d\x49\x14\x0d\x48\xf0\x75\x83\x5e\xa1\xf8\x9a\x28\xfc\x0d\x0f\x01\x46\x94\x7d\xdd\x59\x82\x44\xa0\x0e\x16\x7b\x37\xe8\x15\xfa\xf7\x1a\xc0\xa4\x8d\x1d\x25\xa0\x01\x67\x18\xf3\x2f\x74\x47\x19\x34\xfc\x44\x44\xbb\x4a\xbc\xbb\x72\x43\xce\x55\x9a\x24\xb7\xc4\xd4\x98\x26\xc1\x98\xa8\x25\x82\xe0\xf1\xb7\x47\xc2\x3a\xb5\x18\xa5\x24\xa3\x47\x44\x69\x4e\xb6\x44\x73\x0b\x27\x6a\xba\xa0\xb7\x99\x2a\x1e\x17\xf9\x9b\x14\x83\x88\x22\x53\xdf\xae\xf1\x36\x8a\xcb\x22\xf3\x6d\xf1\xb4\x49\x97\x32\xa9\x08\x0b\x50\x16\xd0\xdd\xc8\x8d\xf7\x58\x95\x27\x72\x84\x8c\xe2\xb7\x3b\xe9\x3e\x62\x9b\x1e\xca\x4a\xc9\x96\xcc\x59\x58\x3b\xac\xb5\xca\x95\x2b\x8d\x07\x50\x85\xf2\x6c\x66\xa5\x83\x90\x0e\x9a\x1c\x7d\xbf\x45\xf2\xf5\xd5\x30\x29\xaf\x68\x54\xc0\xaf\x87\x92\x47\xd7\x18\xae\x71\x9c\x0f\xef\xce\x73\x8e\xb1\xc1\xb5\xbc\x8b\x49\xa5\x29\x19\x8f\x8f\xa6\x9c\xd7\x6f\xf0\x5b\x26\xa6\xf5\xe2\xbf\x7b\xfc\xd7\x5c\xb5\xbf\x88\x36\xe8\x15\xfa\x67\x8b\xd7\xd7\xfc\x43\x12\x7a\x25\x31\x10\xb8\x3d\xd1\xaf\x61\x28\x7e\xa5\x2b\xf9\x23\xc0\x13\x22\xd4\xf4\x11\xf0\x8a\x8c\x76\x85\x26\x23\x64\xea\x8a\x86\xeb\x85\x67\x15\xe5\x9a\x06\x8a\x0b\x9e\xc8\x65\xa0\x2b\xa2\xf0\x2a\x1f\x9a\x2f\xd1\xf7\xb8\xec\xb1\x69\x55\x64\x8a\xaa\xe9\x55\x48\x65\x12\x91\xe9\xd5\x96\x56\xef\xe1\x54\xbf\x49\x39\xe6\x8c\x2a\xae\x0d\x72\xa5\x38\x8f\x1e\x59\x44\x57\x69\x63\x4c\x68\xb4\x8c\x83\xe5\x6a\xea\xd1\x52\xe6\x29\x8d\x55\x6c\xc4\xb2\xea\x3f\x9c\x74\x5b\xfe\xe7\x0b\x17\xf4\x10\x5c\x5c\xbe\x6f\x7b\x2d\xb0\xcb\x8e\xf3\xe9\x4d\xcb\x71\x4e\xfc\x13\xf8\xed\xcc\x3f\x6f\xc3\x61\xa5\x0a\xbe\x20\x4c\x52\x1d\x6c\x24\x72\x1c\xb7\x63\x83\x3d\x56\x2a\xa9\x39\xce\xcd\xcd\x4d\xe5\xe6\x4d\x85\x8b\x91\xe3\xf7\x9c\x5b\x4d\xeb\x50\x23\x67\x97\x65\xb5\x82\x59\x09\x55\x68\x1f\x5b\xf5\x1f\xca\x65\xab\xaf\xa6\x11\x02\x61\x21\x18\x26\x21\x0a\xaa\x1d\xaa\x9b\x2d\xd0\xa4\x65\xcd\x71\x46\x54\x8d\x27\x83\x4a\xc0\x63\x47\xeb\x30\x9a\x30\xc7\x90\x23\x41\x4a\xaf\x6c\x54\x2b\xcf\xcd\x21\x2d\xcb\xf2\xc7\x08\xe7\x9e\x0f\x6d\x1a\x20\x93\x08\xaf\xce\x3d\xff\xc0\xb2\x5a\x3c\x99\x0a\x3a\x1a\x2b\x78\x15\x1c\xc0\xeb\xea\xe1\xcf\x70\x9e\x52\xb4\xac\x0b\x14\x31\x95\x92\x72\x06\x54\xc2\x18\x05\x0e\xa6\x30\x12\x84\x29\x0c\x4b\x30\x14\x88\xc0\x87\x10\x8c\x89\x18\x61\x09\x14\x07\xc2\xa6\x90\xa0\x90\x9c\x01\x1f\x28\x42\x99\x8e\x7f\x02\x01\x4f\xa6\x16\x1f\x82\x1a\x53\x09\x92\x0f\xd5\x0d\x11\xa9\x86\x44\x4a\x1e\x50\xa2\x30\x84\x90\x07\x93\x18\x59\x3a\x71\x61\x48\x23\x94\xf0\x4a\x8d\x11\xec\x7e\x86\x61\x1f\x18\x26\x21\x92\xc8\xa2\x0c\xf4\xb3\xf9\x23\xb3\x10\xe5\x13\x05\x02\xa5\x12\xd4\x58\xa1\x04\x94\x05\xd1\x24\xd4\x32\xcc\x1f\x47\x34\xa6\x19\x07\x8d\x6e\x14\x97\x96\xe2\x30\x91\x58\x32\x72\x96\x20\xe6\x21\x1d\xea\xbf\x68\xd4\x4a\x26\x83\x88\xca\x71\x09\x42\xaa\x49\x0f\x26\x0a\x4b\x20\xf5\xa0\xb1\x63\x49\xeb\xe1\x70\x01\x12\xa3\xc8\x0a\x78\x42\x51\x82\xd1\x75\x29\x9d\x81\xd1\xa2\x27\xda\xa0\x2a\x33\x91\xd4\x23\x37\x63\x1e\xe7\x35\xa1\xd2\x1a\x4e\x04\xa3\x72\x8c\x06\x27\xe4\x20\xb9\xe1\xa8\xa3\x59\x8f\x68\xf0\x21\x8f\x22\x7e\xa3\x55\x0b\x38\x0b\x69\xb6\xf6\x34\x4e\x26\x03\xbd\xfe\x0e\x16\x7e\x65\x5c\xd1\x20\x35\xb7\x71\x40\xb2\xf4\x6a\xf6\x48\x8e\x49\x14\xc1\x00\x33\x83\x61\x08\x94\x01\x59\x51\x47\x68\xf6\xba\xa3\x54\x94\x44\x90\x70\x61\xf8\xad\xab\x59\xb1\x2c\xff\xcc\x85\x7e\xf7\xd4\xff\xd4\xec\xb9\xe0\xf5\xe1\xa2\xd7\xfd\xe8\x9d\xb8\x27\x60\x37\xfb\xe0\xf5\xed\x12\x7c\xf2\xfc\xb3\xee\xa5\x0f\x9f\x9a\xbd\x5e\xb3\xe3\x7f\x86\xee\x29\x34\x3b\x9f\xe1\xff\xbc\xce\x49\x09\xdc\xdf\x2e\x7a\x6e\xbf\x0f\xdd\x9e\xe5\x9d\x5f\xb4\x3d\xf7\xa4\x04\x5e\xa7\xd5\xbe\x3c\xf1\x3a\x1f\xe0\xfd\xa5\x0f\x9d\xae\x0f\x6d\xef\xdc\xf3\xdd\x13\xf0\xbb\xa0\x19\x66\xa4\x3c\xb7\xaf\x89\x9d\xbb\xbd\xd6\x59\xb3\xe3\x37\xdf\x7b\x6d\xcf\xff\x5c\xb2\x4e\x3d\xbf\xa3\x69\x9e\x76\x7b\xd0\x84\x8b\x66\xcf\xf7\x5a\x97\xed\x66\x0f\x2e\x2e\x7b\x17\xdd\xbe\x0b\xcd\xce\x09\x74\xba\x1d\xaf\x73\xda\xf3\x3a\x1f\xdc\x73\xb7\xe3\x57\xc0\xeb\x40\xa7\x0b\xee\x47\xb7\xe3\x43\xff\xac\xd9\x6e\x6b\x56\x56\xf3\xd2\x3f\xeb\xf6\xb4\x7c\xd0\xea\x5e\x7c\xee\x79\x1f\xce\x7c\x38\xeb\xb6\x4f\xdc\x5e\x1f\xde\xbb\xd0\xf6\x9a\xef\xdb\x6e\xca\xaa\xf3\x19\x5a\xed\xa6\x77\x5e\x82\x93\xe6\x79\xf3\x83\x6b\xb0\xba\xfe\x99\xdb\xb3\x34\x58\x2a\x1d\x7c\x3a\x73\xf5\x90\xe6\xd7\xec\x40\xb3\xe5\x7b\xdd\x8e\x56\xa3\xd5\xed\xf8\xbd\x66\xcb\x2f\x81\xdf\xed\xf9\x0b\xd4\x4f\x5e\xdf\x2d\x41\xb3\xe7\xf5\xb5\x41\x4e\x7b\xdd\xf3\x92\xa5\xcd\xd9\x3d\xd5\x20\x5e\x47\xe3\x75\xdc\x94\x8a\x36\x35\xe4\x3c\xd2\xed\x99\xfb\xcb\xbe\xbb\x20\x08\x27\x6e\xb3\xed\x75\x3e\xf4\x35\xb2\x56\x71\x0e\x5c\xb1\xca\xe5\x63\xab\x6e\x52\xe0\x6d\x1c\x31\xd9\x28\x48\x6c\x87\xef\xde\xbd\x4b\xf3\x99\xbd\x1b\x90\xd4\xc9\xad\x61\x0f\x39\x53\xe5\x21\x89\x69\x34\xad\xc1\x4f\x67\x18\x5d\xa3\xa2\x01\x81\x0e\x4e\xf0\xa7\x12\x2c\x06\x4a\xd0\x14\x94\x44\x25\x90\x84\xc9\xb2\x44\x41\x87\x47\x30\xe0\xb7\x65\x49\xff\xd2\xb5\x18\x06\x5c\x84\x28\xca\x03\x7e\x7b\x04\x86\xa8\xa4\x7f\x61\x0d\x0e\x7f\x4e\x6e\x8f\x20\x26\x62\x44\x59\x0d\xaa\x47\x3a\xb7\x8e\x91\x84\xcf\xc9\x3f\x46\x45\x40\x57\xd4\x86\x7d\x4d\xf1\x46\xcf\x22\x5b\xcf\x5e\x85\x4c\x35\xec\x1b\x1a\xaa\x71\x23\xc4\x6b\x1a\x60\xd9\xdc\x3c\x9f\xb1\xc0\x99\x8b\xab\x9d\x59\xc6\x3f\x27\xf4\xba\x61\xb7\x52\x51\xcb\xfe\x34\xc1\x15\xc1\x75\x2b\xe2\x68\xe7\x1e\x99\x4a\x20\x51\x35\x2e\xfd\xd3\xf2\xaf\xcf\x2c\xbe\x79\x53\xf3\x7c\xee\xbe\xaf\x17\xa9\x3b\x46\xb8\x63\xcb\xaa\x3b\x3a\x28\xf5\xc5\x80\x87\x53\xa0\x0a\x63\x19\xf0\x04\x1b\xb6\x6d\x6e\xd4\x54\x5f\x67\x33\x4a\x06\x63\x8c\x89\x99\x51\xae\xae\xee\xe7\xf3\xde\xf7\x49\x95\x2c\xdf\xe0\xe0\x2b\x55\xe5\xf4\x41\xcc\xb9\x1a\x1b\xa4\xb4\x36\x50\x22\x31\x5c\x02\xe9\xd8\x30\xd8\x65\x12\x7e\x99\x48\x55\x03\xc6\x19\x1e\xc1\x18\x75\x65\xaa\xc1\x61\xb5\xfa\x3f\x47\x10\x51\x86\xe5\xc5\x50\xe5\x2d\xc6\x47\x60\x66\x40\x0a\x00\x3f\xd0\x58\x4f\x16\xc2\xd4\x11\x0c\x48\xf0\x75\x24\xf8\x84\x85\xe5\x80\x47\x5c\xd4\xe0\xc7\xe1\x5b\xfd\xbb\x6a\x7e\x48\x48\x18\x1a\xa9\x74\x34\x0c\x46\x06\xb2\x61\x67\x90\xb6\xb6\xb7\x22\x83\xa7\x0e\x8f\x15\x95\x76\xd4\xa3\x50\x76\x80\xba\x12\xcf\x98\xc7\x00\xb4\x04\x4f\x9c\x49\xaf\x51\x68\x22\x51\x99\x44\x74\xc4\x6a\xa0\x78\x92\x37\xd4\xb5\x79\xd0\xb0\x15\x4f\xec\xe3\xba\xa3\xc2\xa5\xa0\x69\x66\xb5\xdf\x56\xab\x4f\x3c\x55\x0a\x85\xce\x96\x56\x35\x18\x44\x3c\xf8\x9a\x8b\xed\x98\xdc\x96\xb3\x20\x79\x5b\xad\x26\xb7\xb9\x87\x41\x84\x44\x68\x86\x6a\x9c\x1b\xdf\x36\x51\x16\xc6\x01\x32\x51\x7c\x6d\x4a\xe4\xac\x65\x0c\x05\x50\x0f\xe9\xf5\x53\x87\x55\x5e\xdf\x75\xe3\xdc\xaf\xc4\x5c\x6e\xed\x64\x33\x99\x33\x3f\x6b\x4b\xd8\x10\x60\x14\x65\xd0\x0d\xbb\x9a\xde\xcb\x84\x04\xf3\xfb\x27\x55\x34\x7b\x28\x48\x48\x27\xb2\x06\x6f\xcc\x58\x41\x02\x18\x0e\x73\x59\x2c\x45\xab\xc1\x61\x72\x0b\x92\x47\x34\x84\x1f\xf1\x9d\xfe\xcd\x27\x86\xe1\x70\xc5\x16\xfb\x90\x1d\x96\x92\x3c\x5d\x96\x78\xbb\x75\xc2\xe5\xac\x6b\x50\x6e\xb2\x52\xf3\x4b\xb5\x7a\x04\xa6\x44\x65\xf0\x01\x32\x85\xa2\xc8\x5f\xe6\x5f\xd5\x38\x65\xd3\x6f\xee\xdb\x5f\x5e\xbf\x6e\x15\x17\xa0\xd7\x3a\xae\x6d\xc8\xe6\x5b\xca\x60\xd5\x7b\x29\x6e\xf1\x8c\x9c\xff\x2c\x37\x7c\x17\x3b\xbd\x60\x5e\x96\x14\xbe\x4b\x3a\x80\x43\x98\xcd\xe4\xe2\x85\x07\x0c\xb9\x80\xe5\xa6\xe4\x96\x4d\x61\x98\xcd\xd6\xb8\xc2\xea\x16\x65\x23\xb7\x41\xb9\x01\x96\xbd\x5a\xc9\x39\x7f\x91\x83\x17\xf7\xe2\x25\x4c\x77\x29\x66\xcb\xe0\x39\x4c\x83\xe7\xbe\xd8\xd8\xfb\xdc\xb7\xd5\xec\xfb\x15\x04\xfb\x1e\x0a\x55\xa8\xce\x73\xc9\x7d\xe1\x90\xa9\x41\x60\x2c\x70\xd8\xb0\x77\xd9\x63\x78\xe2\x78\x98\x27\xcd\xd3\xd3\xd3\x2c\xf9\x86\x18\x70\x61\xde\xc9\xcd\x97\x07\xb9\x05\xc1\x6b\xbd\x1c\xc8\xe5\xed\x01\x8f\xc2\xe2\xc4\x1d\x4c\x84\xd4\xd4\x13\x4e\xd3\x81\x45\x43\x41\x99\x21\x9a\xf5\x15\x6b\x09\xfe\x17\x2d\x98\xa1\x67\x5e\xa2\x0e\xb9\x88\x6b\x10\x90\x84\x2a\x12\xd1\xbf\xb0\x30\xe9\xbf\xf9\xf9\x57\x0c\x49\x41\xbd\xde\x80\xc8\x86\x8d\x95\x6b\x69\x21\x5f\x0c\x2e\xba\xb7\xe4\x36\x73\xef\xf1\x47\x8a\x37\x40\x19\x3c\xf8\x76\xbc\xee\x90\xc2\x18\x5e\x4b\xbc\xc5\xe9\x37\xfd\x79\x68\xf3\xa3\xa0\x28\xbc\x4c\xd9\x7f\x66\xca\x4a\x25\x38\x1b\x3d\x9f\x69\x7f\xdf\x7e\xac\xec\x8f\x6c\xe7\xab\xee\xa4\x42\x7e\x87\xa8\x2b\x68\x18\xb2\x27\xf3\xb3\x53\xeb\x5b\x68\x2f\x71\xf8\xef\x88\xc3\xb4\x35\x5d\x84\x5a\x7d\xf0\x7c\x6e\x06\xa7\xd8\x46\x0f\x1c\x1a\xdc\x7e\xb2\xef\x99\x95\xd9\x3e\xef\xa0\xa0\x16\x2c\x37\xd1\xd3\x4a\xf0\xec\x91\xb1\x22\xd1\xbe\x84\xc7\x83\x16\x7d\xf0\x24\xe8\x7f\x68\xb0\xac\x76\x98\xeb\x47\x53\x9f\xa9\xa1\x9c\xb7\x5b\x1b\x3d\xe5\x84\x85\x28\x74\xf7\x97\x0f\xa7\xf4\x70\xad\x6e\xa2\xf6\x2f\xc7\x7c\x5b\x35\xdd\xb1\xbd\x5b\x3d\x6b\x52\xe8\xde\x97\xae\x70\x6f\xaa\xf1\xde\x45\x26\x40\x7d\xbc\x87\x32\xed\x9d\x9d\x1e\x33\x83\xef\xeb\x88\x5f\x26\xd6\x7f\x67\x9b\xbb\xba\xdc\x5a\x9c\xd9\x5b\x2e\xb8\xe6\x43\xcf\xb0\xe4\x5a\x3d\x41\xf8\x12\x8d\xff\x8e\x68\x7c\x59\x74\xbd\x2c\xba\x5e\x16\x5d\xfb\x1e\x2c\x2f\x8b\xae\xbd\x69\xd9\xb6\x39\xaa\xee\x98\xfd\xb8\xe3\x47\x6c\x85\x2e\x50\x96\x23\x4f\x7e\x12\x23\x77\x34\x69\xe5\xa4\xc9\xd2\xd1\xef\xde\xbd\xbb\x6f\x83\x3b\xbf\xb3\xbb\xb9\x25\xb9\x1f\x4d\xc3\x3e\xb5\x2f\x4f\xd9\xba\xbc\xde\xda\xba\x14\x6e\xa2\x3d\xe4\xf2\x95\xde\x66\xed\x5c\x43\xfe\x14\xd6\x6a\xba\xca\x7f\x3c\xff\x74\x01\xf1\x7a\x35\x5b\x19\x8d\x76\x4e\x55\xc8\x14\x0c\xa6\xbb\xed\xc3\x6d\xe6\x8e\x8d\xf3\x0e\xeb\x99\xa1\xee\x84\xf4\xfa\x38\xfd\xdf\xca\xa7\x89\x7d\x6b\x6b\xb7\x1c\xaf\x4b\x55\x5c\xe6\xaf\xba\x33\xe0\xe1\x54\x8f\x8c\x55\x1c\x1d\x5b\x56\xf1\xf7\x3b\xc9\x44\x8e\xf9\x35\x8a\xef\xf0\x71\xfa\x06\xa9\x7f\xfe\x7b\xb0\xef\xf3\x39\xd8\xee\x5f\x83\x7d\xbf\x8f\xc1\x56\x78\xee\x60\xc9\xe5\x17\xe6\x8f\xf8\x8a\xf4\xff\x03\x00\x00\xff\xff\x99\xde\x39\x7b\x7a\x43\x00\x00") func templateDefaultTmplBytes() ([]byte, error) { return bindataRead( @@ -83,7 +83,7 @@ func templateDefaultTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/default.tmpl", size: 17035, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/default.tmpl", size: 17274, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -182,6 +182,7 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "template": &bintree{nil, map[string]*bintree{ "default.tmpl": &bintree{templateDefaultTmpl, map[string]*bintree{}}, @@ -234,4 +235,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/vendor/github.com/prometheus/alertmanager/types/types.go b/vendor/github.com/prometheus/alertmanager/types/types.go index ce9641025d6..94545f82711 100644 --- a/vendor/github.com/prometheus/alertmanager/types/types.go +++ b/vendor/github.com/prometheus/alertmanager/types/types.go @@ -25,8 +25,8 @@ type AlertState string const ( AlertStateUnprocessed AlertState = "unprocessed" - AlertStateActive = "active" - AlertStateSuppressed = "suppressed" + AlertStateActive AlertState = "active" + AlertStateSuppressed AlertState = "suppressed" ) // AlertStatus stores the state and values associated with an Alert. @@ -266,9 +266,28 @@ type Alert struct { // AlertSlice is a sortable slice of Alerts. type AlertSlice []*Alert -func (as AlertSlice) Less(i, j int) bool { return as[i].UpdatedAt.Before(as[j].UpdatedAt) } -func (as AlertSlice) Swap(i, j int) { as[i], as[j] = as[j], as[i] } -func (as AlertSlice) Len() int { return len(as) } +func (as AlertSlice) Less(i, j int) bool { + // Look at labels.job, then labels.instance. + for _, overrideKey := range [...]model.LabelName{"job", "instance"} { + iVal, iOk := as[i].Labels[overrideKey] + jVal, jOk := as[j].Labels[overrideKey] + if !iOk && !jOk { + continue + } + if !iOk { + return false + } + if !jOk { + return true + } + if iVal != jVal { + return iVal < jVal + } + } + return as[i].Labels.Before(as[j].Labels) +} +func (as AlertSlice) Swap(i, j int) { as[i], as[j] = as[j], as[i] } +func (as AlertSlice) Len() int { return len(as) } // Alerts turns a sequence of internal alerts into a list of // exposable model.Alert structures. @@ -356,6 +375,12 @@ type Silence struct { Status SilenceStatus `json:"status"` } +// Expired return if the silence is expired +// meaning that both StartsAt and EndsAt are equal +func (s *Silence) Expired() bool { + return s.StartsAt.Equal(s.EndsAt) +} + type SilenceStatus struct { State SilenceState `json:"state"` } diff --git a/vendor/github.com/prometheus/alertmanager/ui/bindata.go b/vendor/github.com/prometheus/alertmanager/ui/bindata.go index 3a23395f84e..48d912578ac 100644 --- a/vendor/github.com/prometheus/alertmanager/ui/bindata.go +++ b/vendor/github.com/prometheus/alertmanager/ui/bindata.go @@ -80,7 +80,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _uiAppScriptJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x77\xdb\x36\xb2\x38\x8e\xbf\x15\x9a\xbf\x5e\x15\x58\x8d\x15\x29\x49\x77\xef\xa5\x8c\xf8\xe4\xb1\x4d\x9b\x38\x69\x92\x36\xbb\xab\xf8\x2a\x34\x05\x49\xac\x29\x40\x01\x41\x39\x8e\xad\xf7\xfe\x3b\x78\x24\x48\x51\x76\xda\xed\xd9\xbb\x9f\x73\xbe\xfe\xc3\x22\x41\x3c\xcc\x0c\x06\x83\x01\x30\x33\x40\xf3\x8a\x65\x32\xe7\x0c\xe1\xab\xb8\x2a\x69\x54\x4a\x91\x67\x32\x1e\xbb\xf4\x48\x22\x89\xaf\xfc\x9b\x40\x02\x5f\x09\x2a\x2b\xc1\x22\x5f\x94\xfa\x24\x89\x04\x50\xbc\xdd\xda\x57\x31\x48\x45\x2e\x2f\xc9\x5d\x10\x03\x95\x9b\x48\x10\xdb\xa0\xae\xdf\x51\xb3\x4f\x62\xcd\xc6\x80\xe1\xed\x4e\x7b\xf7\x3a\xdb\xa3\xff\x62\x7b\x3e\x89\xb7\x41\x00\xae\x80\x68\x43\x71\xbf\x13\x0a\xf6\xe7\x43\xe1\x93\xb2\x5d\xc0\x20\xd3\xa0\xb5\x61\xfb\xae\x13\x36\xfe\x6f\x81\xcd\x27\x55\x5d\xe0\x42\x65\x00\x6e\x43\xfc\xd7\x4e\x88\xb3\xff\x2b\x88\x7d\xd2\xb4\x1b\x09\x98\x5a\x34\xda\x78\xfc\xad\x13\x8f\xea\x3f\x08\x0f\x9f\x94\xef\x43\x0d\x72\x87\x5c\x1b\xbb\xff\xee\xc4\x6e\xfa\x9f\x8d\x9d\x4f\x4a\xf7\x23\x0c\xa9\x47\xb9\x8d\xf3\xff\x74\xe2\x9c\x23\x09\x4a\x18\xba\x1a\xef\x12\x42\xa4\x29\x71\x2c\x75\x7e\x2d\x2b\x13\x89\x04\x46\x14\xd7\x05\x53\x53\x10\x6a\xf4\xef\x75\x16\x05\xe6\x0b\x23\x16\x94\x2f\x5d\x79\xa8\xa9\x75\x7f\x4f\x0d\xc0\xc3\x3a\x10\x0f\xaa\x99\xd7\xd5\x40\x4d\xe3\xef\xf6\x56\x04\x59\xab\x2a\x94\x05\xb5\x15\x61\x6d\x50\x77\xd0\x5f\x6f\xa8\x0f\xaa\xdd\x1a\x51\x15\x54\x3a\x6b\x56\x0a\x75\x27\xff\xed\xc6\x6a\x61\xda\x59\x31\x9a\x06\x75\xaf\xdb\x75\x43\xcd\x2f\xff\x7d\x4b\xed\x90\xef\xab\x1f\xe5\x78\xbb\x49\x45\xb4\x24\xc1\xbc\x1b\x4e\x50\x20\xf0\x55\x3e\x47\xf2\x68\x78\x7d\x2d\x1f\x90\xe7\x48\x60\x2c\x97\x82\x5f\x44\x8c\x5e\x44\x4f\x85\xe0\x02\xc5\xcf\xd9\x8c\x7e\x8e\xe2\xbe\xec\xc7\x51\x5e\x46\xbc\x92\x11\x9f\x47\x22\x65\x0b\x3a\x88\x1e\x2f\x69\x76\x1e\xc9\x25\x8d\x0a\xca\x16\x72\xa9\x3e\x5d\xf2\x4a\x44\xa9\x10\xe9\x65\x34\xcf\x45\x29\x23\x2e\x22\x35\xd9\x2f\xa8\x7c\x99\x5e\x9e\x51\xf5\xbe\xa0\xf2\x7d\x2e\x97\x4f\xe8\x3c\xad\x0a\x39\x88\xf1\xd8\x62\xcb\x34\x54\x8d\x09\x4c\x41\x39\xe7\x02\x29\x54\x28\x11\x83\x25\xcd\x17\x4b\x39\xa6\x0f\x86\x63\x7a\x78\x58\x7f\x63\x44\x3e\x78\xf0\xdd\x5f\xe8\x58\x0c\x0c\x30\xe5\x84\x9d\x1e\x11\x39\xc6\xac\xdf\x1f\xb3\x07\xc3\x5e\x0f\xc9\x43\x12\x7c\x3d\x1c\x9d\x62\x10\x44\x0c\x64\x7a\x56\xd0\x09\x3b\xad\x07\x9b\x49\x91\xa7\x8d\xe9\xaa\x31\xc4\x34\xd5\x9e\x23\x8a\x8f\x88\x3c\xa6\x49\x66\x3f\x37\x66\x0b\x53\x20\x9f\xa3\x21\x21\x04\x51\xf2\x02\x51\x8c\x2d\x02\x98\xfa\x46\x88\x18\xd3\xa2\xa4\x57\x06\x8b\x57\x48\x02\xc5\x35\xc0\xb4\x05\x30\xf5\xe0\x12\xdb\x84\x4f\xc0\x0e\x01\xda\x10\xf6\x20\x02\xa8\xc9\xf0\xf8\xe7\x64\x8a\x04\xbc\x4c\xe5\x72\x30\x2f\x38\x17\x48\x3f\x16\x7c\x81\x24\xbe\xe3\x9f\xbf\x60\x0c\x43\x90\xb8\x21\x59\x9d\xb0\xb0\x38\x05\x5d\xc3\x89\x62\x9a\x87\xaa\xdf\x11\x62\x87\x14\xff\x17\xfa\xd2\x1f\x61\x0c\x19\x19\x8e\xb3\x23\x6e\xb1\x18\x67\xfd\x3e\xe6\x93\xec\x94\x48\x44\xfb\x99\xeb\xf8\xab\x4c\x72\x91\xc4\x53\x5d\x3e\x06\x43\xa2\x64\x08\x1a\xb3\x84\x6f\xb7\xae\x99\x8a\x68\x00\xd7\xfc\x02\x7d\x01\x81\x21\x6c\x56\x7f\xc9\x68\x5e\x18\x00\xee\x54\x18\x43\x1e\x7c\x77\x30\xec\x87\x49\x63\x78\x38\x02\xda\xcf\xfe\x52\x19\x0a\xad\x72\x86\x68\x1f\x65\xfd\x11\xfe\x4b\x05\x4c\x55\xa9\x72\x3e\x47\xaa\x00\xee\xa3\xec\xc1\xf0\x38\x9f\x64\x87\xa3\xd3\x64\x78\x33\x36\xc2\x61\x03\xb6\x43\x93\x7c\xdb\x90\xc4\x9a\xac\xf1\xe4\x34\xd6\x43\x5e\xd5\x81\x6d\xb7\xfd\x3c\x76\xf8\x8b\x00\x9f\x2f\x18\x28\x99\x9c\x02\x23\xc3\xb1\x2a\x76\xe0\x8a\x8d\xb1\x50\xec\x21\x07\xd3\x21\x48\xf5\x33\x82\x7e\x9f\x11\x42\xbe\xf4\x7a\xa8\x44\x9c\xdc\x4c\x6e\xb1\x05\xaa\x06\x46\xa3\x25\x46\x86\x78\x9c\xcf\x11\x7b\x30\xc4\x57\xa6\xc3\x6f\xa9\x65\x50\xae\x8b\x3c\xa3\x68\xa8\xd4\xe6\x71\x89\xb8\x1e\x1e\x16\x0f\xd3\x03\x8e\xb7\x0f\x47\xba\x0f\xe8\x24\x3b\x35\xcc\x6c\xd3\xd5\x18\x28\x91\x4a\x56\x43\xc2\xf4\x3f\x9d\xd4\xa5\x4e\x9d\xdc\xa8\xec\xa8\x52\x05\x46\x84\x90\xaa\x51\xcd\xb1\x7d\x9d\x0c\x4f\x93\xaa\x35\x79\x19\x64\x28\x91\x4e\xb0\xe4\x73\xe4\x64\x04\x21\x84\x62\x3b\x2c\xbb\x91\xa5\xfd\x91\x45\x77\x72\xea\xbb\x75\x72\xba\x1d\x8b\xc1\xba\x2a\x97\x6a\xae\x14\x13\xea\x90\xd2\x49\xd2\x20\xc2\xc9\x73\xf5\xa8\xbf\xda\x82\x01\xd2\x88\xf7\x49\xf8\x69\xd2\x91\xcf\x88\xaf\x30\x5d\xd7\xcf\x6d\x62\x48\x00\xdf\xf5\xea\x8b\x1a\x36\xea\xf7\x77\xa2\xd4\x9e\xae\x1d\xe1\xf4\x6c\x5b\x0b\xf0\xaa\x28\x0e\x08\xa1\xc7\x34\xf9\x05\x09\x78\xad\x3e\x3a\x89\xd7\x9e\xa2\x6b\x31\xe2\x72\x34\xe5\xaf\x05\xfe\xe8\xcb\x31\xba\x9d\x67\x6d\x91\x52\xb3\x1c\xde\xe2\x26\xc9\x95\xee\xa1\x40\x1b\xd7\x30\x7f\x52\xd3\x9d\xe6\x68\x0b\xb2\x6d\x1d\x71\xf2\x42\x7d\xb2\x2c\xc3\x1b\xb0\x1c\x8e\x4e\x09\x05\xee\xbb\x85\xef\xf6\x49\xbf\x0f\xdc\x30\x51\x13\x09\xc7\x48\x21\x49\x0e\x47\x4a\x82\xa9\xe6\x1c\xfd\x78\x08\x37\xc3\x75\x53\xb6\x73\x6f\x6c\xf9\x39\x52\xf2\x89\x6f\x83\xbe\x68\x28\x30\x7e\x1a\x58\xa3\x1f\x07\x27\x79\xd1\x90\xee\xeb\xdd\xa9\xb6\x89\xf9\x98\x3e\x20\x66\xce\x95\x24\xec\xb5\xe3\x1f\x07\x8f\x39\x2b\x1d\xc2\x8a\xc3\x24\x4e\x74\x75\x3e\xc5\xe3\x27\xeb\x06\x97\x21\x17\xed\x11\x99\xb6\x09\xdb\xc9\xb5\x40\x6a\xc2\x86\xd5\x78\xab\x05\x00\xf2\x53\x66\x3d\xdb\xe3\x71\xad\x27\x0c\xc7\xec\xa8\x59\xc1\x98\x29\xe9\x53\x4f\xac\x0d\xf4\x24\xaa\x35\x04\x9c\x2c\x03\xbc\x58\x8d\x57\x30\xe3\x6e\x1a\x33\xee\x4a\x4f\x9a\xc3\x80\xd0\x2b\xa7\x18\xdc\x24\x58\xfe\x20\xe6\xec\x26\xcc\x39\x19\x8e\x79\x1b\x73\xde\xef\x63\xe6\x78\xbd\x85\xb9\x5a\x56\xd0\x3e\xf7\xf8\xf2\x53\x9c\xac\x02\xfc\xf9\x29\x0c\x09\xe1\xc7\x34\xa1\xfd\x5a\xaf\xe2\x4a\x30\x79\x79\x50\xe3\xbd\x68\x29\x44\xd4\x8d\x7a\x05\x9f\xe9\x15\xba\xdb\x2b\x82\x68\x28\x3c\xc5\x95\xac\x51\xda\x52\xd4\xec\xcf\xce\x92\x8b\xb6\x7e\xe4\xa0\x0a\x96\x4e\x67\x37\x43\xd5\xae\xf7\xf0\x70\xfc\x35\x20\x75\x17\x3b\xfb\x0a\x78\x2e\x77\xf5\x4c\xa5\x07\xf6\x89\xd2\x35\x31\x08\xfd\x2a\xdc\xeb\x05\x92\xf0\x4e\xaf\xed\x02\x06\x7b\x57\xab\xf6\x84\x18\xb5\xde\xb5\x33\xee\x96\xb8\xfb\xc5\xab\x13\xa4\xa4\x29\x60\x95\x62\x08\xdc\x4a\xd3\x57\xba\x3d\x60\xe4\x1d\x92\x87\x88\x3e\x18\x1e\xd7\xcc\x40\x8d\x62\xd4\x10\x05\x8e\xd2\x0e\x2a\x36\xbe\x49\x9f\x68\x8d\x84\x36\x1c\x14\xfb\x49\xca\xb7\x1a\x7c\xdc\x7a\x46\xdc\x51\x2c\x10\xf7\x30\x11\x16\xc8\x74\xaa\xb4\x3b\x86\xfb\x1a\x13\xde\xc6\x44\xc9\x57\x4f\xe9\x8b\xc6\x34\x26\xff\x74\x32\xfb\xa1\x66\xa1\xe8\x8f\x3a\xa8\x7e\xf1\xd5\x54\xa7\x1a\xa4\xa6\x54\xff\x13\x3a\x81\x76\x40\xe9\xfa\x64\x9f\xe0\x3a\x54\x5d\xc3\xbd\x5a\x46\xd8\x38\xd0\x0c\xa1\x22\xc3\x71\x75\xd4\x9c\x7a\xc7\x55\xbf\x8f\x33\xc5\xf8\xae\x58\x75\x1a\xcc\x8f\x93\xea\x94\x64\x7e\x16\xad\xbb\xe8\xbc\xd9\x45\x4d\xe9\xb9\xdb\x5f\x5d\x9f\xa5\xa5\xf8\x5b\xa3\xe9\x28\x42\x4e\x86\x4d\x05\xab\x4f\x27\xa3\x66\xca\x11\xf9\x52\xcb\x94\x76\x76\x57\xb3\x2a\xe5\x87\x43\xbb\x86\x3a\xd3\xf0\xb4\xd9\x68\x58\x61\xc6\x59\x96\x4a\x54\x97\xc6\xa0\xbf\xba\x49\x21\x5c\x20\x3f\xd7\x75\x28\x95\x43\x4d\x04\xba\x48\x53\x89\xd0\xb3\x41\x98\x3e\xe1\xa7\x7d\xc2\xc6\xba\x46\x37\xb3\x84\x2f\x8d\xe6\xdd\x84\xb3\x0d\x00\xdf\x3a\xc0\x6b\x78\x4c\x27\x3f\x34\xc4\xcc\x1e\x7c\xaf\x26\x6c\xf2\x58\xe7\x02\x55\x0f\x64\xd8\x57\xf1\x4b\x9d\x1c\x08\xb8\xb7\xad\x3e\x35\x75\xf7\x7a\x1d\x43\x6e\x22\x41\x68\xea\x8d\x0e\xea\x9c\xd7\xd7\xea\xcd\xe7\x54\x82\xd2\x3e\x87\x15\x48\xf2\x42\x69\x8e\x42\xeb\x67\xf0\x19\x49\x40\x8a\x07\x3e\xa9\xc4\x67\x4a\xa8\x62\x05\x15\x3c\x52\xe2\x57\x91\xd5\xcc\x01\x41\x65\x0f\x7c\x55\x9f\x91\xad\xac\xae\x41\x60\xac\xfb\x42\x90\x27\x9a\x7a\x1a\x47\x9b\xbf\x3f\xc2\xf5\x8e\x80\xe1\xbb\x67\xc8\xc0\x81\xf5\x4a\xac\x8b\xa7\x8e\x87\xc9\x48\xf5\x2c\x21\x84\x1d\x8f\x92\xe1\xd8\x00\xc6\x4e\x31\x48\xdd\x06\x57\x6d\xf0\xa0\x8d\x6d\xe7\xa0\xb8\xbe\xde\x3b\x12\x0c\x31\x1b\xfd\x67\xfb\x29\x3b\x22\xdf\x1f\xeb\xcf\xc9\x63\x3d\x81\x85\xfb\x71\x9f\x9b\xeb\xac\x96\x56\x29\x6b\x29\x2c\x40\x36\xa5\xb0\xc0\x8d\x94\x3e\x51\x62\x4e\xb6\xc4\x5c\xdd\xd0\x23\xcf\x17\xa2\x25\xed\xf1\x95\xac\x65\x4d\xd8\xcc\xd0\x34\x33\xae\xd5\xde\xe7\xa8\xce\xaa\x88\x3d\x1a\xb3\x23\xd9\x1e\x27\x5a\x5f\xec\x07\x79\x35\x99\x83\x8d\x27\x42\xb7\xba\x07\x1d\xba\xe5\x32\x9f\x4b\x64\xda\xb9\xa1\xce\x46\x15\xe1\xcb\x61\x08\xf2\xb8\x2e\x6b\xeb\x0d\x36\x12\x1e\xb6\xf5\xf8\x21\x18\x15\x49\x76\xa8\xbc\x7d\x52\x23\xd0\xfc\x5c\x2b\x65\x5d\xaa\x72\x3f\xd8\x35\x6b\x7e\x76\x32\xb3\x29\x1e\x5b\xc2\x1f\x05\x9b\x4f\x88\x1e\x8e\xf0\x9d\x2f\x58\x31\xa4\x47\xe2\xa4\xa5\x05\x51\x4f\xae\x63\x39\xa1\xa7\x89\x98\x50\x4f\x91\x60\x93\xee\x4d\xbd\x43\xd5\x2a\x41\x58\xb3\x0c\x09\x14\xd3\xa7\x75\xa9\x37\xae\x43\xdd\x94\xa6\x93\xed\xd4\xa8\x87\xdd\xf5\x35\xd5\x43\xa6\xd9\x79\xc7\xc3\xe4\x04\xf9\xc4\x9a\x13\x40\x21\x37\x7e\x13\x7c\x12\xf5\x27\xe0\x66\xc5\x56\x43\xf2\xd2\x2e\x1d\x8c\x92\x47\x86\x78\x7c\xd3\xea\xa8\x63\x71\x50\xeb\x3b\xed\x95\x50\x98\x09\x43\xb0\x5c\x79\xec\x48\x5d\xcf\x13\x2f\xbd\x08\xab\xf7\xc0\xbe\xc0\xcd\x5d\xaa\xb4\x51\x1e\x96\x64\xad\x2e\xbf\xbd\x78\x46\x86\xe3\x93\x9d\x0e\xc8\x70\x23\xe7\x7f\x7d\x21\x64\x38\xc6\x6f\x90\xad\x1f\xb8\xcb\x07\x5d\x65\x31\xbc\xa9\x17\x45\xb5\xb6\x60\x73\xef\x76\x8a\x2a\x91\xf5\xfb\xe3\x7a\xbf\x31\x83\xa9\x26\x5e\x8d\xda\xe1\x08\x86\x18\x72\x32\x1c\x67\x87\xd5\x21\x9a\xb6\x64\x8d\x12\xbe\xf8\x88\x8e\x8d\xc4\x4b\x49\x17\x58\x50\x92\x9a\xb2\x87\xcd\x1a\x20\x6d\xca\x5e\x35\x7b\xd9\x1c\x64\xda\x9c\xf5\xd3\x86\x1e\x96\x43\x89\x31\x4c\xeb\xa9\xd6\x21\x31\x27\xd3\x16\xbf\x42\x41\xe6\xe3\xe2\x68\xde\x2f\x0f\xf3\x71\xd1\xef\x63\x9f\x61\x52\x28\x89\x68\xdb\x99\x14\xa7\xaa\xc2\xfa\x53\x9f\x14\x0f\x86\xc7\x41\x8a\x96\xc0\xe3\xbc\x4f\xca\x16\xd8\x47\xa4\xec\xf5\x50\xd6\xef\x2b\x42\xa9\x4a\x3a\xf6\xa3\x9e\x22\x06\x5c\x1f\x91\xc0\x94\xb4\xe9\xab\xd4\x3d\xbd\x5d\xd8\xa6\x6f\xb3\xa0\xca\x36\xce\x8e\x6e\xe4\xae\x31\x76\x05\xba\x59\x44\x41\x59\xf5\xfb\x76\xe8\x4c\x18\xf0\x40\xa6\x7c\x0a\xf6\x4d\x9c\xb0\x6c\x4f\x62\x41\xf6\x67\x1d\xd9\x87\xc1\x77\xa5\x06\x5c\x99\x9d\xdc\x3d\xa3\xba\xa9\x6a\xcb\xd6\xc6\x56\x2d\x60\x83\x65\xbf\xe7\xdf\x40\x30\xd9\x02\x38\x3c\x27\x7c\x1e\x00\x17\xaa\x4e\xc7\x4d\x84\x92\x7a\xb2\x69\x0b\xba\x06\xae\xaf\xda\x53\x8d\x3e\x81\xf1\x47\x34\xc1\x7a\xc4\x1c\xc4\x50\x4f\xe3\x70\xbf\xe4\x75\x63\xbf\x44\x2b\x1f\xc7\x37\x6f\xf6\x4d\xe4\xe9\x36\xb9\x79\x93\x7d\xf2\xda\x6c\xe5\xe3\x60\x0f\x73\x74\x1a\x4c\x93\x4f\x1a\xad\x8a\x06\x31\x6e\xab\xfb\xc9\x6e\xdd\x8a\xb2\x61\xf5\xbf\x84\xd5\xdf\xdc\xd1\xf5\x7e\xab\xd2\x9f\x9a\x55\x82\xfa\xd7\x57\x1a\x4a\x58\xf9\xaf\x35\x0f\xd5\x62\x5d\xe5\xf4\xfa\xd8\x7b\x24\xf4\xe1\x4d\xd8\xf9\xef\x77\x05\xfd\x9e\x9d\x93\x70\x1f\xe4\x58\x4e\x44\x5f\xe9\x33\x7e\xbe\x4f\x74\x45\x7d\x64\x34\xcd\x61\xb2\xff\x80\x2a\x98\xd9\x7e\xd8\xe1\x3c\x3b\x71\xfe\x9c\xfc\x86\x64\xf7\x61\x94\x13\x80\x3b\x67\x52\x7e\xf3\xcb\x57\xff\x5b\xc7\xd1\xd4\xd7\x9c\x2c\x49\xbf\x84\x65\x78\x1b\x6c\x94\x35\x0f\x99\xb2\x1b\x0e\x99\x38\xc6\x50\x05\xdf\x33\x07\x1c\x4c\xc9\x70\x3c\x3d\x72\xef\xe3\xa9\x5a\xbe\x4e\xa6\xa7\xe4\x37\x7f\xc8\x34\xfd\x0b\x6f\x1c\x32\x4d\xfb\x23\xfc\x17\xae\x0f\x99\x2a\x95\xf3\x39\x52\x05\x70\x1f\x4d\x1f\x0c\x8f\xab\xc9\xf4\x77\x1c\x32\x65\x9e\x8f\xaa\xad\x3e\x05\xfe\x42\xee\xdd\x85\xef\xc9\x5d\xf8\xf9\x96\x9d\x74\x7d\x7a\x61\x5a\xa0\xab\xb5\xbc\x4c\x7e\x86\xb9\xe0\xab\x17\x79\x29\x93\x14\x24\xd7\x0f\x33\xc8\x59\x2e\xf3\xb4\xc8\xbf\xd0\x44\xa2\x0a\x43\xba\x5e\x53\x36\x4b\x24\x3a\xc7\xb0\xae\xca\x65\x22\xd1\x1c\x83\xa6\x6e\x22\xd0\x25\x86\x05\x95\x89\x44\x14\x43\x49\x65\x22\x10\xc7\xb0\x4a\xd7\x89\x44\x4b\x0c\x39\x9b\xd1\xcf\x74\xf6\x52\xbf\x6f\x30\xcc\x79\x31\x2b\x12\x81\x16\xe6\x51\x24\x02\x9d\xb9\x2d\x85\xe4\x39\x48\xfe\xe3\x5b\x0d\x7b\xf2\xab\x06\xcd\xbd\xfd\xb0\xdd\x22\x0c\x9b\x9b\x8e\xbb\x9d\xf0\xbc\x23\xae\x87\x3b\xa7\xcc\xee\xe3\x7f\x89\xd6\xb1\x6f\xc0\x54\x3b\xe7\xe3\x8f\x53\xc6\xb8\x8c\xd6\x54\xcc\xb9\x58\x45\x2b\x3e\x8b\x86\x83\xe8\x49\xbe\xc9\x4b\xbd\xbd\x78\x19\x7d\xa1\x82\x47\x54\xe5\x1e\xc4\x4e\xa1\x93\xff\x25\xec\x3a\x4e\x1e\x0f\x13\xa1\x56\x35\x0f\xc8\xd0\x6c\xa4\x26\x87\x1c\x1d\x4a\x38\x0c\x0e\x55\xb4\x4c\x1c\x26\xac\x75\xba\xec\x41\xf6\x03\x44\x04\x83\x25\xdc\xdc\xaf\xea\xe1\x77\x28\x5b\xb6\x32\xf5\x46\xe3\xf1\xa1\x4c\x64\xcb\xaa\xa4\xde\xc8\x1e\x64\x2b\x73\x46\x70\x34\x3c\x96\x89\x68\x19\x91\x74\xe4\x7b\xd0\xca\x57\xb6\x94\x7a\x93\x93\x82\x34\x35\xba\x57\x5d\x50\x24\x74\xe7\xbc\x29\xe4\xfb\x77\x93\xba\x9d\x7e\x43\xb0\x17\xcd\xce\x54\x0b\xfd\xce\x43\x90\x03\xd9\x38\xfb\xa8\x4b\x10\x42\x46\x77\x86\xd7\xd7\xea\xe1\x70\x74\x67\xd8\x38\xb1\xa8\x85\xd8\xb5\x6c\x6c\xf9\xd7\xe5\xff\xa2\x7b\xe0\xf5\xf3\x3b\xa3\xff\x1e\x36\x76\xbf\x6b\xf3\x1c\x97\xe5\x2f\xb2\xb1\x11\xed\x84\xba\x3e\xb8\xa5\xfa\xe0\x76\xec\x69\xf5\xae\x5a\x17\xf4\x2e\x12\xa6\x6c\xc6\x4b\x35\x96\xec\x5b\xa9\xe4\x47\xb8\x90\xb8\xfc\xba\xca\x4c\xe1\x4f\x42\x22\xf1\x17\xd1\xa7\x7f\xa1\xd8\xc8\xa3\x54\xa6\xec\xae\xee\x0a\x63\x42\xf2\x8e\x4c\xe2\x17\xef\x62\x88\x9f\xfe\x1c\x43\xfc\xfd\xbb\xd8\x1d\xbc\x5e\xcd\xf2\x8d\x19\xd5\x82\xae\x12\x89\x18\x86\x15\x57\x52\x80\x63\x58\xe7\x89\x45\x13\xa8\x79\x7a\x0a\x19\x2f\x13\x07\x3f\x94\x39\x4b\x1c\xf8\x20\x53\xfb\x22\x53\x06\xa9\xcf\xa7\x9e\x20\xf5\x39\xd5\x13\xa4\x3e\x6f\xaa\x33\x2b\x60\x13\x89\x6a\xc8\x31\xcc\xe8\x42\x50\x5a\x26\x1b\x50\x50\x96\xc9\x42\x0b\x8a\xd7\xbc\x48\x45\x72\x06\x92\x9b\xa7\x4b\x50\xb8\x27\x9e\x0a\x50\xf0\xc5\xa3\xb4\x54\x12\x2d\xc3\xc0\xe8\x22\x95\x34\xa9\x20\x3d\x2b\x93\x29\xac\x72\x96\x48\x94\x2b\xb1\xf5\x39\x91\x28\xc5\x90\x15\xe9\x6a\x9d\x08\x54\x62\xc8\xf8\x6a\x9d\x0a\x6a\x84\xde\x67\x2e\x12\x89\x0a\x0c\x8c\x2b\x49\x29\x45\xa5\x94\x75\x9a\x2c\x41\xcd\x1b\x39\x5b\x24\x7e\x12\x01\x3d\xe7\x25\xf5\xf4\x07\x82\x57\x6c\x66\x12\xf4\x23\x48\xfe\xac\xe0\xa9\x4c\xbc\x54\x0b\x58\x6d\x0b\x79\x79\x92\x9e\x24\xfa\x3f\xe4\xe5\x73\x36\x57\x72\x99\x26\x6b\x2d\x0a\x57\x9d\xa2\x50\x34\xb5\x36\x06\x9c\x4c\x4e\x21\x23\xd4\x9c\x54\x01\xc7\xe3\xac\xd7\x43\x8c\xf0\xc1\x9a\xaf\x11\xc6\x63\xac\x3e\xb2\xc1\x67\x60\x83\x4b\x93\xc1\x6d\xfb\x6c\x9b\x02\xd6\xd8\x81\x69\x2b\x81\xd1\x70\x88\xfd\x99\xa6\x3e\xbb\xbc\xfa\x9c\x48\xb8\x4c\xc4\x16\xc3\xc1\x70\x6c\x4f\x27\xdc\x34\x6d\x52\x62\x7e\xf6\x1b\xcd\x64\x7c\x40\xe4\xe5\x9a\xf2\x79\x64\x6d\x22\x5c\x2b\x31\xa9\x3f\xb4\x25\xf1\xb7\xef\xc4\x65\xce\x16\x91\xe4\xda\xdc\xe8\x23\x22\x04\x7f\x8c\x78\x6d\x71\x57\x0e\xa2\x77\x4b\x2a\x68\x94\x97\x11\xe3\xd1\x45\x7a\xa9\xf2\x9e\x33\x7e\x11\xe5\xf3\x3a\x57\x94\x0a\x1a\xc5\x72\x49\xa3\x32\x5d\xd1\x38\xca\x99\x36\x70\x7a\x5a\xac\xa2\x92\xb2\x92\x0e\xa2\x37\x34\x9d\x45\x2b\x2e\x68\x94\x9e\xf1\x4a\x46\x72\x99\x97\x51\x2a\xa3\xa5\x94\xeb\xe4\xce\x9d\x75\x9a\x9d\xa7\x0b\x3a\xa0\xc5\xea\xb0\x48\xd9\x62\xc0\xc5\xc2\x25\x96\x77\x5c\xea\x9d\x8c\x0b\x7a\xa7\x48\x25\x2d\xe5\x9d\x47\x69\x99\x67\xe5\xff\x8f\x90\xe8\x62\x99\x67\xcb\x68\x46\xcb\x4c\xe4\x67\xb4\x8c\x2e\x96\x97\x51\x2e\x15\xc8\xba\x15\x05\x74\xca\x66\xd1\xc5\x32\x95\x1a\xac\x33\x2a\x25\x15\xd1\x86\x0a\x3d\xdd\x5c\xe4\x45\x11\x15\x9c\x9f\x47\x45\x7e\x4e\x07\xdf\xba\x9e\x3a\x18\x6d\xed\x49\xb7\x9a\x72\xae\xaf\xed\x93\xa7\xfe\x48\xf7\x47\x94\xb3\x52\xa6\x2c\x53\x04\x7e\x92\x4a\x7f\x40\x23\x07\x0b\x2a\xdf\xe5\x2b\x8a\xb0\xde\x1a\xf4\x6f\xaa\xd4\x01\x8a\x95\x44\x8e\x15\x9d\x70\xcd\x56\x99\x26\x1c\x56\x19\x28\x92\x93\xec\x14\x84\xfa\xc7\xfa\x23\xe0\xb8\x6e\xd6\xf5\xbe\x02\x2f\x7e\xf3\xe8\x84\xcf\xe8\x94\x16\xab\xe9\x59\x95\x17\x32\x67\xb5\x4d\x4b\xaf\x17\xbf\x79\xf4\x54\x29\x24\xdd\xdf\xaf\xaf\x91\x24\x2f\x84\xdd\xb1\x15\x7a\x97\x23\x7e\x4b\x65\x23\x37\xa9\x6b\x53\xb9\x99\xcd\xcd\x4c\xee\x24\x09\x2c\x6f\xae\xea\x1d\x00\x09\x53\x22\xc6\xf6\x73\xe5\xa0\x31\xaf\x53\x6b\x70\x73\x65\x10\xad\x94\xb0\x9d\xaa\x7f\x6d\x44\x2b\x52\x0d\xa6\x23\x98\x92\xe9\x60\x3a\xda\x7a\xb3\x15\x55\xda\x57\xa3\x89\x60\xd5\xb2\x00\x12\x05\x45\x4e\x96\x03\xaf\xf7\x28\xb0\xd3\x46\x82\x39\x96\xc8\xad\xae\x79\x40\x48\xda\xdc\xb9\x3d\x18\x79\xe5\xb6\x24\xc3\x71\x79\xe4\xb2\x8e\xcb\x7e\xdf\x76\x52\x3e\x29\x4f\x21\x55\xff\x6e\xea\x24\xd5\x9b\x1a\x2e\x10\xe6\xa7\x9d\xf9\x8f\x32\x40\x5b\x1b\xeb\x16\x07\xc1\x24\x2d\x8e\x57\x89\x3c\x12\xc7\x9b\x64\xb1\xc3\xbd\x6f\xa5\xc8\xd9\xa2\xde\x73\xde\xa4\x45\x45\x5f\xcd\x11\x06\x4e\x44\xfd\xe6\x57\xa3\x84\x10\x7e\xbc\x4a\xe8\x11\x57\xd5\xe9\x7e\x08\xb9\xe1\xfa\xba\x69\x96\xa5\x99\x63\xdc\xc8\xe2\x39\x42\x04\x1c\x81\x32\xc2\x90\x9e\x80\xc5\x60\x3a\xc4\xf8\x80\x90\x95\x43\x21\x1b\x5b\xd3\x2c\x41\x44\xc0\x12\xd2\xb1\x84\xa9\xe7\x78\x95\x34\x9a\xf6\xe0\x4d\xf5\x14\x5e\x7f\xf0\x67\x9e\x7f\xc5\xf6\x88\x05\xaa\xe6\xa7\xbf\xe2\xc3\xa1\x3b\x6c\xaa\x1c\x14\x2b\x95\x52\x3d\x20\xa3\xaf\x80\xd7\xe4\xbc\xdb\xc8\x39\x52\x39\x47\xdd\x39\xef\x35\x72\xde\x55\x39\xef\x76\xe7\xbc\xdf\xc8\x79\x4f\xe5\xbc\xd7\x9d\xf3\xbb\x46\xce\xfb\x2a\xe7\xfd\xee\x9c\x7f\x6d\xe4\xfc\x4e\xe5\xfc\xae\x3b\xe7\xdf\x3a\xb4\x7a\x3d\x9f\xe7\xa5\x9a\xd8\x54\x4a\x12\x65\x46\xcf\xb7\x13\x7d\x24\x15\xf5\xcb\xe8\x22\x97\x4b\x33\x15\xc8\x65\xca\xa2\xbf\x46\xb4\xa0\x2b\xca\x64\x39\x88\x9b\x9e\x05\xab\xed\xd7\xb4\x51\xa7\xe4\x65\xc4\x59\x71\x19\xcd\xe8\x3c\x67\x74\xa6\xe6\xb1\x9c\xc9\x12\xa2\xb9\x52\x06\x4a\x88\x64\xbe\xa2\x25\x44\xd9\x32\x15\x25\x68\x4f\x1a\xb6\x28\x21\x2a\xf2\x52\x96\x11\x9f\xdb\xba\xd4\x8a\x2e\xd2\xec\x5e\x82\x9e\x38\x2c\xdc\x5d\x19\x14\xc8\xed\x75\x4f\x73\xa9\x69\xb4\xc6\x18\xa6\xc3\x44\xc2\x74\x94\x88\x6d\xcb\x39\xc2\xad\x57\xe8\x85\x1d\x81\xfb\x16\x21\xd1\x59\xbf\xdf\x32\x2c\xf5\x96\x40\xf5\x3a\x9c\x19\x11\xa2\x4d\x72\xe4\x84\x9d\x36\x3f\x08\xf3\x41\xa8\x0f\xbb\xbb\x4a\x79\x07\x02\x49\xd2\x0d\x7b\x5a\x4b\x1c\x43\xc8\x50\xcf\x70\xe3\xb2\xaf\x4f\x89\x3b\xcd\x33\x85\x5d\xd5\xe5\x66\xec\x5c\x62\x60\x84\x6a\x60\xcd\x10\x6f\x5b\x67\xb2\xc1\x74\x14\x64\xb6\x72\x80\x11\x16\xe8\xe8\x3a\x8f\x08\x37\xea\xcb\xc6\xc2\x26\x74\x66\xd8\x61\xad\x37\xa9\x66\x17\x1e\xa5\xd1\xc7\x27\xf4\xac\x5a\x0c\x32\x91\x96\xcb\x8f\x8a\x6c\x2b\x3e\xab\x0a\x1a\x7d\xd4\x26\xdd\x1f\xa3\xb8\x5f\x20\x81\xfb\xf1\x07\xf6\x6e\x49\xa3\x15\x2d\xcb\x74\x41\xa3\xb5\xe0\x9b\x7c\x46\x67\x6a\xfd\xaa\xd4\x8c\x8c\xcf\x68\x94\x56\x72\xc9\x45\x94\x97\xc9\x07\xf6\x81\x45\x51\x14\xc5\x7d\x1a\x1e\x3d\xcd\x5b\x0b\xbc\xd0\xbb\xe2\x5f\x80\x51\xb5\xf6\xce\x68\x3f\x65\x94\xa5\x55\x59\xc3\xf5\x31\x4b\x4b\xfa\x31\xa2\x9f\xd7\x82\x96\x5a\x03\x72\xf8\x0c\x3e\xb0\x57\x8c\x2a\x46\xd7\x6a\x92\x48\x59\xb6\xa4\x65\x44\x99\xc2\x4a\x0f\xdb\x34\xd2\x0d\x9a\x61\xb1\xa4\xd1\x9c\x17\x05\xbf\x50\x2a\xa4\x1e\x0f\xd1\x82\x2b\x15\x4b\xf0\x6a\xb1\x0c\x10\x9e\x21\xaa\xa9\xf5\x07\xe9\xc5\x70\x73\xa9\x1a\xec\x15\x97\x32\x15\x72\x50\xe4\x8c\x2a\x4e\xa1\x6c\xa6\x9f\x8f\x63\x95\x31\x67\x34\x8a\xfb\x61\x9e\x24\x3e\xa3\xf2\x82\x52\xf3\xb1\x6c\x7d\xed\xc7\x1a\x2d\x95\xe8\x2a\x6a\x2d\x82\xed\xe2\xd0\x72\xf9\xb8\xa5\x65\x7b\xcd\x30\x3e\x72\xa9\x0f\x62\x9d\xe9\x8c\xf3\x82\xa6\x8d\x3c\x91\x3c\x8e\xdf\x89\x8a\xc6\x49\xfc\x2c\x2d\x4a\x6a\x32\xb2\x6a\x75\x46\x45\x33\x5f\x3f\x8e\xf7\x4d\xd5\xb6\xb9\x6f\xe3\xbe\x5a\xd4\x1f\x0c\x71\x3f\xfe\xd6\x54\xe4\x87\xa4\xaf\xe8\xdb\xf8\x5b\x93\x6b\x84\xfb\xdf\xc6\xdf\x8e\x03\xd5\xd6\xd5\xa3\xde\xe3\x70\x49\xa1\x8a\xf7\x7a\x81\xaa\xea\x75\x03\x33\x45\x56\x67\xa6\x1d\x34\x84\xef\xb4\x32\x65\xc4\x5d\x6c\x6c\x80\xa7\x64\x72\xda\x16\x4b\xa6\xae\x03\x42\x58\xaf\x37\x35\x4b\x9c\x19\x52\x62\xca\x6f\xc3\xc6\x28\xee\x4f\x07\xbf\xf1\x9c\xa1\x18\x62\xdc\x8f\x71\x6c\xe7\xee\xb4\x3c\x8f\x03\x13\xa8\xf8\x48\xa6\xe5\xb9\xa5\xf0\x8e\x02\x68\xf3\xe8\xe4\x81\xdb\x8b\xd3\xac\xb8\x94\x7a\xd3\x57\x95\x3a\x9a\x51\xc5\x74\xe2\xc1\x6e\xc1\xfa\x93\xa9\xff\xb5\xe0\x19\x2d\xcb\x8e\x8c\x6b\xf3\x25\x51\x7c\x93\xcf\xfa\xb1\x2d\xd1\x54\x8c\xa7\x24\x9e\xa8\xc6\x95\xf8\xc2\x0d\x29\x17\xe6\x1b\xe3\x69\x9f\xc4\xe0\x33\x5a\x29\xe7\xc4\xdb\xb4\x1f\x9f\x1a\x62\x74\x08\x54\x95\xa6\x1b\xde\xab\xbf\xbb\x8c\x6f\xa9\x6c\x52\x44\xeb\xf4\x86\x22\x1d\xab\x89\x50\xa1\xeb\x5a\x4d\xec\xd4\xff\x24\xcf\xda\x0d\x08\xdd\xc0\x94\xc4\x71\xbd\x5f\xec\x55\x5d\xcf\x13\xdc\xd9\xb9\x28\x96\xe0\xa7\x18\x2a\x92\x4d\x86\xa7\x63\x45\x94\x28\xee\xa3\xf8\x4a\x2f\x26\xae\xaf\x63\xe4\x1e\x8e\xec\xc3\xb7\xf1\xb7\xe6\x21\x1b\xe8\x8d\xd1\x57\x73\x14\x47\x31\x3e\x1a\x1e\x67\x89\xe2\xa8\x4c\xf1\x11\x6e\xea\x8b\xfd\xe9\xb6\xc5\xeb\xc6\xfe\x6f\xcf\x8a\x2e\x3e\x52\x3d\x2c\xb9\x9d\xa4\xb1\xeb\x69\xa9\x16\xad\xd3\x0b\x7a\x36\x2d\x79\x76\x4e\xfd\x68\x3a\xba\xa0\x67\x26\xe5\x41\xac\xe7\xba\xae\xf1\x60\xc7\x00\xeb\xc7\x11\xd1\xa4\x6a\x8c\x05\xbd\xeb\xef\x0e\x0e\x8f\xe3\xab\x6d\x9c\xc4\x57\x51\x30\x3e\x22\x35\x40\xa2\x6d\xbc\x75\x6d\xe6\x4c\x52\xc1\xd2\x42\x29\x37\x55\x26\x2b\x41\x1f\xc4\x3b\xe6\xca\x6e\x10\x0b\xba\x2e\xd2\x8c\xa2\x3b\x1f\x3e\xdc\x59\x40\xfc\xe1\xc3\x87\x0f\x31\x0e\x52\x99\x49\x65\x8d\x44\x69\x12\x65\x23\x51\x98\x44\xd1\x48\xdc\x98\xc4\x4d\x23\x71\x68\x12\x87\xb5\xfb\x92\x38\xa6\xc1\xf7\x6f\xcd\xf7\x6f\x63\x9c\x84\xc9\xf1\x9d\x05\x7c\xfb\xe1\x43\xfc\xad\xd9\x5b\xdb\x90\xc3\x11\xac\xc8\x10\x16\x64\x04\x67\x64\x08\x97\x6e\x83\x7e\x72\x1a\xd7\x5b\xf1\x9f\x12\x01\xd9\x6a\x9d\x30\xd0\x5a\xd8\x30\x69\x28\x65\xc3\x78\x6b\xd2\xef\x26\x1c\xb2\xa5\x48\x32\xa8\xd6\xb3\x54\xd2\x64\x0a\x8b\x2a\x9f\x25\x55\xbd\x41\x9f\x62\xd0\x13\x5f\x52\x9a\xdf\xc7\x69\x49\x93\x39\x38\x6e\x48\x66\x7a\xef\x68\x41\x64\xed\xaf\x1d\x90\x5a\x38\x5c\x8d\x0d\xec\x74\xa8\xfe\x8d\xf0\x16\xc3\x19\x41\xa2\x51\x24\xb4\x62\x45\x1d\x3a\xa4\x50\x7a\x18\xdd\xaa\xb2\x7b\x0b\xea\x56\x40\xe0\x2d\xc6\x70\xb9\x03\x92\xdf\x07\xc3\xf0\x8e\x74\x6f\x90\x5d\x90\x8b\xeb\xeb\xab\xed\xf8\x62\x12\x1f\x5d\xc7\xa7\x7b\xab\x40\xaa\x0d\x40\x36\x3b\x9e\xc4\xd7\x0f\xf6\xe7\x56\x32\xa0\x99\xfb\x81\xca\xbd\x17\x0b\x81\xa4\xde\x9f\x6d\x14\x39\x3a\xba\xa9\x88\x44\x62\xb7\x48\xbf\x1f\x9f\x92\xd5\xc0\x74\xa5\x1e\x88\xe7\x64\xe5\xc7\x31\xbc\x25\x68\x33\xa8\x77\x01\x41\xbd\x9c\xa4\x27\xb0\x19\xd8\x4d\x44\x0c\x9f\x55\x16\xbb\x0d\x09\x1b\xb3\xe7\x88\xe1\x91\x4a\x75\xfb\x94\xb0\x31\x3b\x8f\x78\xbc\x19\x30\x2e\x61\x33\xf8\xcc\xc5\x38\xa4\x8c\xa2\xe3\x66\xc0\x45\x08\x5a\xaf\xa7\x13\x53\x0b\xd7\x43\xb2\x19\xac\xd2\xcf\x70\xa2\x6a\x5e\xe5\x0c\x36\x03\xbb\x74\xc2\x61\x55\x0f\x88\x2e\xb5\xa0\x0d\xc2\x98\xc4\xa2\x91\xf8\xc0\x64\x94\x8d\x8c\x26\x5f\x23\xed\x8e\x29\xcc\xe8\xa7\x30\x95\x98\x54\xfa\x69\xbc\x19\x28\x04\xd7\xb9\x86\xf2\x0d\xd9\x0c\xf4\x2e\x2e\x3c\x55\x70\xda\xed\x5f\xd8\x0c\xd2\xb3\x12\xc3\x4b\x5d\xcf\x22\x95\x74\xbc\x31\xfb\xc3\x1b\xb3\xbf\x6c\x7f\xd5\x4f\xa9\x51\xd3\xbb\xd4\x9b\x81\x49\x2b\x2d\xb6\x65\x88\xe8\xff\x9a\xf6\x3f\xaf\x43\xa8\xfe\x4b\x27\xae\xf8\x6c\xbc\x19\x08\xba\x0a\xf3\xdf\xb9\xa3\xbf\xcd\xf2\x4d\x03\x39\x9d\xa8\x97\x80\x4f\x9a\x5f\xfe\x62\xaa\xaa\x8a\x30\xf1\x50\x27\x96\xd5\x59\x83\x87\x4c\x3f\xcd\x54\xa3\x76\x23\x5c\x31\x82\xdb\x1e\x57\x68\x54\x82\x29\x74\xec\x26\xba\xa6\xd4\xe3\x5b\xc4\x41\xfc\x63\x55\xea\x89\x87\x9a\x6d\x0a\x25\x19\x12\x35\x2e\x3f\x39\x69\x76\xc2\xe5\x52\xe9\x71\x5b\x78\xf6\x3b\xeb\x92\x48\xd5\x86\x93\x4f\x5b\x0c\x2f\x3a\x86\xb9\x6d\x40\x97\xd2\xeb\xbb\xed\x16\x9e\xff\xce\x36\x5e\x20\xdb\x8a\x69\xe6\x55\xc7\xc0\x6c\xba\x6b\xec\xca\x31\x57\xb3\xfb\x44\x08\x61\x6e\x6b\xc8\xb5\xc6\x06\xd3\x61\x47\xda\xc8\x01\xa1\xc4\x9d\xce\x33\x1d\x82\x4e\xf7\x10\xfd\x48\x10\x6d\x81\x04\xac\xed\x89\xa7\x5b\xbe\x17\x00\x05\xd3\xbb\x09\x6b\x41\x76\x4f\x35\xca\xdb\x50\xf0\x0e\xc8\xb8\x83\xac\x99\x76\xd7\x41\xab\xd6\xcd\xdc\x42\xcb\x0d\xb4\xa0\xbf\x7b\xa8\xd9\x0e\xc8\xe0\x35\xa3\x06\xd0\xf7\xdb\x40\xc3\xf4\x5e\xc2\x5b\x90\xdf\x57\x00\x64\x6d\x88\xb2\x0e\xc8\xb3\x0e\xc8\x33\x07\x79\x33\xed\x9e\xc3\x46\xad\xaf\x33\x8b\x4d\x66\xb1\xc9\x0c\x36\xa0\xf3\x79\xac\x78\x07\x56\x90\x19\xbc\xaa\x26\x5e\xdf\x75\xe2\x05\xd3\xfb\x49\xd6\x42\xee\xbb\xc6\xee\xb2\x03\xb0\xea\x40\xae\xea\x40\xae\xea\x40\xae\x72\xc8\x35\xd3\xee\x3b\x84\xd5\x72\xbd\xb2\x08\x57\x16\xe1\xca\x22\x5c\x19\x84\x41\xe7\xf7\x88\x77\x1d\x27\x65\xbf\x63\xa3\xc5\x44\x9e\xf0\xae\xac\x97\xfa\x5c\xd2\x6e\x44\x53\xe3\x23\x93\x21\x69\x7c\x14\x3b\x7c\x63\xa6\xcd\xe2\x93\xd3\x1d\xb7\x57\xeb\xef\xd7\xb1\xe0\x10\x3b\xf1\x01\x42\x43\x98\x29\xa2\x7a\x6b\x18\x32\xe2\xac\x05\xc7\x99\x02\x88\x6b\x5f\x1f\x36\xc9\x4e\x83\x63\x2f\xbe\x13\x16\x20\xac\xab\x06\x4b\x38\xea\x9b\x57\xea\xb7\x7f\x34\x94\x7a\x87\xca\x2a\x50\x43\x8c\xed\x3e\x30\x50\x42\x03\xb0\xab\x46\xb8\x85\x75\x3d\xf0\x6b\x5b\x95\x5b\xda\xf3\xaf\xcc\x36\x6f\x8f\xe3\xd2\xb0\x79\x2d\x74\xda\x30\xb4\x76\xa4\xaa\x46\xc8\x86\x65\x38\xa0\x6b\xdf\x8d\xdf\x07\x8c\x7f\xe5\x16\xb6\xcc\xc0\x56\xee\xc0\xa6\xe5\xcc\x1e\x00\x81\x6b\x49\x55\xc3\x19\x1a\x9f\x6f\x9a\x43\xd4\x41\x3a\xfd\xd7\x20\xf5\xaf\x99\x5b\xec\x1a\xc0\xe7\xdd\x80\x6b\xb9\x72\x33\xf4\x90\x69\xa1\x55\x23\x11\x06\x88\x58\x34\xb4\xcf\x0a\x4d\x91\xc0\x83\x92\x8b\x60\x8e\xdb\x35\xac\x90\xda\x7c\xde\x28\x91\xb8\xe5\xf0\xf6\x15\x75\xd9\x98\x0a\x26\xb4\x84\xc1\xd2\xca\xab\xa7\x3f\xc7\xd6\xf4\x2b\x7e\xf1\xce\x3c\x1e\x8e\x92\xd1\xd6\x1a\x0b\x74\xae\x5f\x4e\xf2\x22\xb9\x84\xc7\x9c\x95\x49\x06\x99\xfa\xd1\x67\xec\x92\x1b\xd3\x9d\xa9\x3e\x9f\x37\xcf\x95\x37\xfa\x29\xb4\x8d\xd0\xdd\x44\xa0\x99\x7e\xba\x97\x50\xb4\xd6\x4f\xf7\x13\x86\x96\xfa\xe9\xbb\x84\xa3\x0d\x06\x85\xc0\xa3\xcb\x44\xa2\x85\x79\x7e\x9f\xcb\x65\x22\xd1\x19\x56\x8b\x19\x0c\xaf\x09\xfa\x71\xe0\xd2\xc1\x3c\x3e\xba\xc4\xf0\x64\x47\x4d\xd0\x27\x3b\xe6\xf4\xc6\x59\x98\x0c\xf1\xd1\xa8\xbd\xd5\x1b\x6e\x06\xd3\xd6\x66\xb0\x24\xf2\x70\x04\x42\x77\xf2\x76\x8b\xe1\x17\xd5\xb8\x02\x15\xf4\xcf\x7d\xf3\x73\xcf\xfc\xdc\xc5\xf0\xeb\x5e\x20\x6e\x69\xcb\x1e\xdb\x5a\xc5\xc5\x1f\xa4\x4b\x22\x83\xd6\xdf\x13\xd4\xbd\x8a\x39\xc8\xd1\xaf\xb5\x44\xaf\x93\xf5\x52\x48\x2f\xb9\xe0\xc7\x81\xee\x0a\x0c\x3f\x74\xe8\x43\x21\x90\x8c\xd0\x00\x48\xd6\xb1\x3b\xce\x89\x84\x8c\x38\xfd\x46\xc9\x77\x49\x38\x08\x92\x01\xd5\xc3\x40\x81\xfa\x1b\xd9\x05\x27\x4a\xd1\x0f\xb0\x6f\x19\xd6\x1f\x6d\x31\xa8\xca\xb6\xf0\xe5\x77\x96\x95\x7d\xe1\xcb\x7e\xbf\x6f\x9d\xd7\x4d\xa1\x68\x35\xa0\x9f\x90\x00\xe9\xc8\xf4\x73\x87\x52\xda\xd8\xd7\xda\xc2\x3f\x1a\x59\xec\xe6\xab\x1b\x50\xe1\xc1\xe1\xf1\x0b\x24\xac\xb6\x0b\x3f\x91\x9f\xf4\xda\xf5\xa7\x89\xca\x72\x4a\x7e\x1c\xa8\x91\xa3\xc9\xf9\x4f\xb2\x67\xec\xa7\xe8\x7d\x13\x65\xda\x3d\x37\xeb\x93\x72\xad\xb7\x6e\x31\x04\x03\x16\xa8\xc2\xe8\xef\x3b\xd5\x3b\x71\xd0\x55\xb3\x5e\x0f\x1f\x77\xcc\xfd\x74\xab\xd6\xf7\xe3\x00\x34\xb6\xdb\xd6\x37\x7b\x75\x6d\x59\x3b\xc6\x07\xda\xb2\xa6\x52\xb3\x31\xcd\x52\xbe\x3d\x90\x72\x5f\x87\x2a\x10\xbe\x51\x98\x87\x50\xe8\x3e\x14\xf2\xf7\x31\x50\xb7\xa6\xb3\x53\x31\x50\xd9\xd8\x16\x69\xa8\xed\x6d\x6a\xba\x91\xd4\x60\x8b\x4e\x84\x73\xc5\x7e\x66\xd2\xb6\x78\x07\xed\xd6\x14\x17\x12\x29\x0c\x38\x34\x4b\x53\x55\x26\x2c\x00\x4c\xef\x34\x74\xb3\x54\x43\xf2\x1c\x8b\x64\x87\xc3\x6e\xa5\x89\xdb\xc0\x61\xb2\x6b\x93\x46\xd5\x47\x65\x83\x70\x6a\x64\xf1\xbd\x9d\xc8\x24\xca\xd1\x3f\x41\x6a\xf3\x34\x0c\x99\xfc\x4a\x66\xb5\xe4\x05\xae\x97\x61\x5a\xd5\x0b\xf4\xc3\x80\x85\xc3\xc5\x5d\x07\x4e\x7c\xab\xfe\x67\xdb\xa4\x23\x3b\x0f\x48\x1b\x96\xc9\xb6\xdb\x3d\x03\xa1\xa3\x31\x4d\x83\x76\x17\xe9\xb1\x52\xc9\x86\x34\x17\x21\xd7\xec\x91\xbf\xe1\x64\xdc\xcd\x76\x9d\xe2\x61\x0f\x1e\x54\xe1\x01\x19\x51\x28\xf0\x46\x9f\x29\x62\xb6\x6c\x93\x5b\xa3\x33\xdb\x76\xee\xf4\xdd\x32\xe3\xd2\xb1\x41\x50\xec\x9d\x60\xa8\x9f\x71\x99\xd1\xae\xf6\x09\x87\xad\x62\xc2\xe9\x5e\xbe\xd2\xa3\xa5\x92\x8a\xb1\x42\xcc\x34\x93\xe5\xb2\x43\x4a\x79\x88\x45\x08\x71\x9b\xe0\x37\xee\x19\xc8\x64\xc6\xaf\x84\xfa\x57\x1b\x75\xdc\xad\xd5\x4e\x7c\x26\x68\x7a\x6e\xcf\xe7\x1c\xee\x76\xf5\x57\xa3\x6f\xcf\x68\x0e\xec\x47\xf7\x5d\x55\x39\xb2\x9b\x0e\xb6\x22\x31\xb6\x15\x6e\xcb\x8b\x5c\x66\x4b\xa4\xbf\x5d\x65\x69\x49\xa3\x51\xe2\xf2\xe8\xd7\xbb\xc9\x9e\xbe\x1c\x59\x7a\x76\x7d\x68\x7d\xd3\x9c\xbb\x35\xf5\xdd\x4b\xea\xa3\x24\x9f\x79\xd4\xc1\xa9\x7f\xa8\xa5\xf6\xb7\x4e\x40\xb6\x0e\xfb\xf1\xcc\x44\x1e\xdb\x0f\x92\x37\xe7\x09\x6b\x1c\x05\x06\x59\x9c\x34\xdb\xca\x48\x00\x57\x45\x3c\xf4\xad\x0a\xa6\x43\x28\xdb\x49\x81\x5d\xae\x61\xff\x11\xbd\x87\x1f\x0c\x5b\x22\xbf\xda\xc5\x36\xdb\x4d\xea\x90\x3f\x53\x95\x94\xa3\xa9\x04\x71\x78\x1f\x4a\x6d\x97\x92\xfc\x99\x75\xa7\x28\x97\x20\xfb\xa3\xa0\xfe\xad\x63\xb3\xed\xc5\x32\x2f\x28\x3a\xd8\x2f\x1a\x3a\x7b\xaa\x5d\x2a\x52\xd3\x7a\x7a\xc3\xb4\x9e\x4b\x18\xea\x19\x61\x8b\xa1\xec\x1a\xab\x3b\x52\xa6\x31\x66\x23\x39\x96\xa4\x63\x92\x94\x5b\xb5\x66\x3b\xd4\x4b\x36\x25\xbd\xe6\x72\x9f\x36\x1d\xa5\xa8\x6c\x4d\x62\x56\xb1\xb8\x09\x94\x03\x14\x98\xd5\x8f\x70\x5b\xe6\x75\xc8\x64\x25\x33\xb4\x7e\x6f\xa0\x62\x5a\xa6\x15\x37\x50\x66\xbe\x2b\xd0\xb6\x18\x66\x37\x94\xf8\x05\x24\xe4\xa8\x50\x14\xfd\x0d\x09\x7c\x38\xc2\x06\x93\xb5\x24\x68\x69\x0f\x1f\x60\xe9\x3c\x09\x97\xc6\xbc\x4c\xfd\x52\xb9\x4f\xdb\x36\x58\x0e\x41\xe2\xa3\x51\xaf\xe7\x70\x76\x75\x20\x81\xf1\xd1\x50\x6f\x7f\x2e\x07\x0b\x2a\xcd\xd4\x9e\x7c\x52\xa8\x2d\x75\xa3\x6a\x71\x0d\xcb\x81\x76\x48\xd9\x51\x53\x6e\x57\x4d\x73\x57\x85\xfa\xd2\x54\x49\x97\x7a\x89\x53\x00\xf3\xd5\xeb\x89\xd6\x24\x0b\x70\x9f\x97\x83\xda\x49\x05\x96\x6a\xe1\x06\xcb\x81\x71\x86\xc1\xb0\x91\x64\xe9\x4f\x89\x61\xa5\xde\x6a\xf7\x18\x58\xec\xe7\x99\x1c\xad\x14\xb2\xda\x27\xb7\xb9\xbd\x66\x07\x8b\xaa\xf4\x31\x9f\xd1\x2e\xeb\xef\xd5\x20\x5b\x0a\x64\x8e\x7e\x74\xeb\x8f\x97\xa9\x50\x99\x91\xc4\x78\x0b\x92\xef\x2b\x28\x07\x99\xcd\xf9\x50\xa2\xa1\xce\xfa\xcb\x7a\x4d\xc5\xfe\x46\xe4\xc0\x66\x79\x9c\x96\x14\x99\xda\x5f\xf0\x8b\xdb\x8a\xe8\x2c\x8d\x22\x59\x5a\xd0\xaf\x68\x2b\xc8\xb8\x53\xfc\xab\xda\xf5\x19\x5d\x71\xb3\x0d\x70\x26\x09\x5a\x98\x03\x7d\x85\x3e\x2c\x54\x6e\xf5\x84\xe1\xd2\x7c\x6a\x14\x86\x45\x0b\x18\x97\xe0\xbf\xe9\x54\x0c\xef\xba\x24\x8e\x61\xcb\x33\x89\x28\x6e\x0a\x78\x06\x67\xda\x6e\xe3\xc1\xa1\x1f\x0b\x3a\x49\x8d\x02\xb5\xa0\xbd\x90\x24\x47\xef\x24\x18\x84\xe2\x87\x31\x76\x8f\xff\x8c\x31\x86\xf3\xe6\xe7\xb4\xfe\xfc\x45\x7d\x7e\xdb\xfc\x3c\xac\x3f\xff\x8f\xfa\xfc\x59\x12\xb4\xe7\xfb\xdf\xd4\xf7\x0e\xc2\xbe\x55\xd0\x5e\x5f\xa7\xdd\x8d\xce\x63\x0c\xed\xcf\x01\xc8\xcf\xf4\xe7\x2d\x86\x47\xb2\xd3\x1b\x41\x36\x7d\x19\x9f\xa4\x92\xea\xb8\x78\x76\x80\x94\x27\xe9\x09\x0a\x2c\xce\xf1\xf1\x6b\x89\xe2\x5f\x98\xb6\x5b\x94\x3c\x5a\xa7\xa2\xa4\xd1\xb7\xda\x50\xec\xdb\x28\x2d\xa3\x34\x9a\xa5\x92\x0e\x74\x45\x65\xb4\xaa\x4a\x19\x9d\x51\x67\xc4\xff\xfc\xed\xab\xe8\xbf\xff\x3a\x1c\x45\x73\x2e\x56\xa9\x1c\xc4\x38\x79\xa2\xb7\x3b\xec\x86\x72\xfc\xb6\x62\x31\xc4\x2f\xb9\xfa\xff\xae\xa2\x31\xc4\xef\xe9\x4c\x3d\x2f\xab\x18\xe2\x67\x22\x8f\x21\x7e\x9b\xca\xf8\x14\x28\x99\xc4\x3f\xa6\x2a\xdf\x33\x7a\xa6\xca\xa4\x22\x86\xf8\xe1\x5a\xe8\xe7\xcb\x18\xe2\x1f\x75\x5d\x3f\x56\x85\x4a\xaf\x16\xaa\x24\x5d\xc7\x10\xbf\xca\x64\x0c\xf1\x09\xdf\xc4\x10\x3f\xa1\x59\xed\x4b\xa3\xd8\xd2\x9e\xc1\x4b\xb8\xa4\x69\x27\x97\x6b\x5b\xfc\x67\x55\x51\xfc\x83\xa6\x02\xe1\x2d\xac\x38\x93\xcb\x8e\x9c\x46\xe0\xd3\x89\x2e\xf0\x52\x65\x42\xf8\x74\xbb\x85\x59\x7a\xb9\xb7\x5e\x4d\x7d\xbc\x85\x25\xaf\xf6\x37\xfe\x03\xaf\x44\xa9\x5b\xce\x59\x25\xf7\x48\x18\xd5\xa6\xfe\xac\x73\x96\x34\xe3\x6c\xb6\x37\xe7\x5b\xfd\xd9\xd6\x59\x14\xf9\x2d\xd9\x5f\xd6\x79\x74\x19\xc9\x15\x6f\xec\xcd\x6e\x18\x67\xab\x77\x18\xf7\x65\x0c\x58\x4f\x53\xe8\xd5\xfc\x3d\xa5\xe7\x7b\xa9\x2a\x26\x96\x5c\x97\x9a\xa6\xda\x60\xe2\x61\x37\x7f\x8b\x9d\x73\x4a\x6d\xfd\x35\x2d\xab\x2c\xa3\x8a\xb7\xb4\xb1\x61\x22\xb7\xad\xd8\xf1\x1d\x45\xe6\x69\x5e\x74\xe5\xdf\x3d\x0a\x35\xf9\x59\x2a\xf3\x0d\x7d\x94\xb3\x59\xce\x16\x31\x64\x69\x51\x9c\xa5\xd9\x79\x22\x21\x4b\x59\x46\x0b\x1d\x11\x71\x7b\x9b\xcd\xaf\xaa\x29\x65\xb3\x77\x4b\xca\x1a\x75\xc8\xb4\x3c\x6f\x5b\x00\xef\x29\xce\x99\xb6\xf9\xbc\xb9\x78\xb5\x07\x0b\x41\x33\x9a\x6f\x68\x58\x78\xdb\x3a\x12\x6a\xba\xd3\x3b\xf3\x36\xc8\x67\xc9\x6a\xb0\xa8\xf2\x19\xc2\x20\x38\x97\x89\x84\x52\xaa\x0a\x14\xde\xb0\x4a\xf3\xe2\x8c\x7f\x0e\xfc\x5d\xa3\x35\x12\xb8\x15\x56\xbb\xe6\x10\x14\x5a\xdc\x52\x24\x90\x6a\x5a\x4d\xdb\x3b\x76\xc4\x72\x60\xeb\x36\x67\x02\x02\xc3\xba\x61\x07\x5d\x36\x14\x94\xa0\x62\x86\xaf\x52\xfd\x0d\x18\x12\xc8\x7a\xe9\x0d\x9b\x6d\xcc\xf7\xc2\x64\xd5\xa0\x81\x42\x75\xdc\xc9\x02\xc1\x89\x34\x1b\x18\x1e\xa8\x9f\x10\x06\x53\x96\x68\xf2\xd0\xbd\x10\x14\xb7\x40\x50\x9a\x21\xc7\x2b\x19\x5e\xf8\xd0\xaa\x0f\x6a\x19\x1f\x64\xca\x0a\x9a\x0a\x57\x98\xe1\xed\xb6\x1d\x80\xdb\x2a\xcf\xf2\x68\x53\xef\x8e\x6b\xa0\xcd\x01\x85\x37\xae\xf4\xc3\x4b\x07\xf6\xac\x93\xf5\x10\x6a\xa5\x39\xe6\x6e\x25\x3b\xa6\xd5\xc9\x57\x75\xfa\x0e\x49\x55\x57\x5a\x18\x34\x21\x3d\x44\x96\x5f\x51\x43\x8a\x18\x12\x4b\x58\x6b\x83\x23\xb3\x20\xad\x8d\x42\x3d\xb7\xeb\x56\xdb\x36\xd3\x36\x06\x2e\x23\xc2\x71\x98\xf3\xe7\x70\x87\x96\x66\x99\x3f\xb6\xad\xb4\x01\x61\x2e\x5c\x10\x86\x7e\x5f\xea\x00\x45\x91\x18\xe8\x31\x41\x6e\x19\xb0\xad\xaa\x40\xd0\x52\x26\xb6\xec\x16\x9a\xed\xa9\xa1\xad\x1a\x18\xef\x6f\x60\x57\xa0\xfc\xe1\x06\x0c\x47\xd8\x9c\xbd\x5e\xab\x01\xbd\xaf\xae\x3f\xf9\x23\x62\x03\x8e\x4b\x55\xed\x04\x06\xc4\x36\xb9\x4d\x47\x5b\x83\x23\xa4\x85\x43\x8b\x62\x0c\x5d\x55\x7a\x02\x77\x83\xe7\x08\xfc\x7f\x0a\x9e\x37\x21\x3d\xda\x1c\xcb\xfe\x28\x41\x5a\xfe\xb5\x62\xc2\xe2\xab\x33\x1f\x44\x77\x71\x7d\x8d\x82\xd1\xbd\x84\x21\x86\x05\x39\x18\x36\x8e\x85\xeb\x33\x56\xb5\x4a\x1d\x8e\xc5\xd1\x46\x7b\xdb\x9d\x79\xe6\x1b\x63\x23\x68\x74\x8c\xa3\x99\x3e\x48\xc1\x63\x79\xdc\xaa\x39\x59\x90\x83\x91\xb5\x90\x1c\xd1\xfb\xaa\xa1\x11\x9c\x91\x89\x57\x97\xec\x10\x4f\x04\xa8\x51\x9d\x50\x68\x8c\xcc\x84\x81\xe5\x01\xe3\x8d\x6c\x29\x6e\x8e\x1d\xed\x28\x4b\x2a\x28\xd7\xe9\x05\x4b\x72\x38\xcf\x8b\x22\x99\x43\x59\x50\xba\x4e\x0a\x28\x8d\xa9\x64\x89\x41\xa4\x17\x6f\x75\x9e\xa9\x7e\x54\xe9\xa9\x9e\xef\x4f\xba\xe7\xfb\x60\xf2\x8e\x3a\x0e\x14\x5a\x1b\xec\x83\x0b\x2e\xce\xa9\x68\x1c\x3d\xe4\x73\xb4\xe1\xf9\x2c\x1a\x1e\x74\x06\x1c\x78\xb7\xd4\x8e\x11\xb4\x1f\x7f\x74\x7e\x12\x33\x4e\xcb\x88\x71\x19\x31\x4a\x67\xd1\xbc\x48\x17\xe5\xe0\x03\x7b\x9c\x16\x45\xa4\x33\xda\x56\x10\x36\x8e\x0f\x8c\x47\xa9\x58\x54\xda\x4f\x49\xbb\x09\x5c\xf2\x2a\x2a\x97\xbc\x2a\x66\x4a\x57\x56\xc5\x4a\x2a\x0f\x6a\xb3\xd6\x0a\x49\xbd\xa0\x05\x39\x30\x56\xa5\x20\xb5\xc1\x7c\x26\xf2\xb5\x82\xba\xb4\x77\xd2\x74\x69\x24\x37\x12\xc1\x44\xea\xda\x21\x02\x0d\x88\xd0\x1d\x75\xe1\xa1\xa0\x1a\x6a\xe9\x7d\x7e\x4b\x46\xd3\xf3\x28\x8d\x4e\xe8\x86\x0a\xeb\xc1\xa1\xdd\x4b\x9e\x16\xab\xe3\xe8\x9d\xc8\xb3\xf3\x52\x52\x71\xf0\x81\x3d\x97\xda\x43\xb6\xd4\x2e\xb2\x51\xdc\x67\xfd\x58\x89\x53\xed\x73\xe5\xdc\xad\x34\x9d\x3e\xae\x05\x5f\x88\x74\xf5\x3e\x97\xcb\x67\x8a\xa8\x1f\xa3\xb3\x4a\x46\xcb\xb4\x8c\xe4\xe5\x9a\x46\x1f\x5f\x9b\xef\xa6\xcd\x8f\x83\x0f\xec\x97\x92\xfa\x52\x1f\xb5\xed\x35\x4d\x67\x51\xae\x2f\x45\x88\x66\x5c\xf7\xd1\x45\xca\xa4\xed\x23\x1b\x0e\x22\x23\x39\xfa\x89\x0e\x44\xc5\xf4\xc2\x51\xcf\x62\x4f\x85\xa8\x8d\x9d\x76\xf0\x67\x75\x9f\x0e\x06\x03\x6c\x1d\x63\x8a\xc2\xbb\xb6\xb0\xa8\x62\xf4\xf3\x9a\x66\x92\xce\x7c\x67\x0f\x3e\xb0\xe7\x91\x14\x39\x9d\x29\x82\x65\x9c\x6d\xa8\x90\x51\x2e\xd5\x5b\xca\xb4\x87\xb3\xa6\x1b\x68\x34\x85\xf3\xcf\xd1\x8e\xc7\x6b\xc1\xcf\x0a\xba\xd2\x9e\x2c\x71\x5f\x9b\x33\xb4\xb9\x03\x65\xc6\xec\xe6\x2b\x79\x84\x77\xbb\x33\x49\x7c\xd5\xd0\x29\xbd\xe5\xde\xc6\xc4\xac\xc6\xc0\x88\x8f\x5f\xe0\x14\x0a\xa8\x97\xd8\x5f\x18\xba\x52\xd0\x24\x0c\x36\x39\xbd\xe8\xdc\x28\x48\x73\xb6\x75\xf6\xd1\xfb\xce\x98\xb6\x18\x1a\xe0\x77\x55\x44\x1b\x0a\x4a\x15\x18\xe7\x84\x48\xd6\x77\xab\x3c\x94\x83\x86\x8c\xaa\x9b\xf6\x46\x71\xf6\x60\x0f\x8f\x99\xb6\x6b\x83\x0a\xd9\xf0\x73\x53\x6d\x1e\x02\x25\xa1\x2a\xe5\x0c\xa5\x30\x85\x12\x03\x47\x0f\x15\x9d\xb5\x24\xd4\xb1\xe4\x70\xcb\x25\xef\xa1\x1c\x58\xb9\x85\x4a\x25\xdb\xb5\x8d\x1a\xa4\xe4\x6a\x0b\x25\x59\xa3\xfd\x20\xf9\x7d\x6e\x39\x98\x0e\xc7\x15\x61\x28\x03\xee\x60\xd1\x0e\x6b\x39\xa1\x88\x3b\x58\x72\x0c\x22\x84\x85\xeb\x1d\x2d\x8e\x61\x4e\xa6\x28\x85\xac\x56\xf7\x8e\xaf\xd6\x5c\xc8\x32\x99\x6f\x93\xab\x6d\xb7\x13\x60\xd3\xb5\xe0\xc4\x41\x72\x32\x61\xa7\x63\x3e\xc8\xcb\x67\x5c\xd0\x7c\xc1\x7a\x3d\x84\x28\xa1\xc6\xb0\x95\x9d\x92\x38\x5b\xcd\x8c\x8d\xa2\x4c\x17\xc7\x9f\x11\xc3\xc9\x43\xc4\x40\x60\x0c\x52\x7d\x9f\x23\x0e\xa2\xeb\x92\x0c\x1b\x60\x24\x14\xe2\xde\x21\x90\x16\xf3\x5d\x8f\xbf\x14\x55\xc0\x40\x5a\x4b\x06\xe7\x84\x30\x1d\x8e\xed\xb1\x0a\x37\x67\x2a\x1a\xa0\xc4\x97\xc9\x80\x01\x1d\x64\xab\x59\xa9\x43\x9f\xaa\x0c\x65\x75\xb6\x93\x41\xf1\x9d\xcf\x30\xff\xec\xbf\x97\x61\x05\x3e\x9b\x09\xef\xc3\xc8\x95\x62\xeb\x44\x80\x02\x38\x31\xb2\x73\x0b\x5c\xc7\x77\x5c\x40\x46\xe4\x80\xb3\xa7\xf3\x39\xcd\x64\xa9\x1d\x83\x39\x7b\x4b\x8b\xf9\xcb\x72\x01\x53\xb2\x76\xf2\xbd\x1e\x46\x6c\xa0\xea\x21\x53\x98\xee\x8b\xac\xb2\x9f\x73\xa8\x5d\x02\x29\x1e\x02\x1a\x32\x45\xf7\x82\x62\xd6\xda\x13\x55\x05\x28\x9b\x29\x01\x42\x8b\xb9\xdb\xb9\xd6\x1d\xa1\xb7\xc1\xb7\x1d\x51\xeb\x1b\xd3\xaf\xe1\x16\xc5\xf9\x66\x9e\x6f\x80\xe6\xf7\x85\xa9\xde\x97\xaa\xdd\x19\x18\x50\x25\xa3\x0c\x35\x1f\xca\x81\x55\x1f\x80\x13\xf3\xad\x5e\xb1\xd8\x31\xa5\xd4\x82\xb6\x4d\xdc\x0d\xd3\xde\x95\x9a\x34\x92\xb8\xa0\xe9\x3c\x86\x25\x5f\xd1\x44\xda\xc5\xbc\x08\xe5\x62\x10\x4b\xc6\x96\x60\x7c\x46\x63\x70\x2e\x8c\x8d\xe5\x6f\xc3\x30\xcc\x66\x5f\xa5\xeb\x18\x64\xba\x58\x50\xa1\xd6\xd9\x82\xd2\xc6\x3a\xfb\xac\x65\xcf\xbc\x1d\x5f\xa2\x83\xa1\x8e\xdd\xa1\x94\x4c\x0c\x97\xe8\x60\xa4\x0d\xe6\xf4\x6b\xdb\xc9\xc9\xca\x29\xfd\xc6\x8e\xd9\x84\x9f\x26\x57\x8a\x21\x13\x73\xa3\x80\x62\x4a\xf3\xb8\x1d\x07\xa2\x47\x4e\xf8\xa9\xeb\xc8\xf9\x67\x73\xc0\xb4\x0d\x5d\x21\x2f\x6b\xe1\x69\x87\x90\x18\x28\x74\xec\x38\xd2\x44\x4b\x4c\xbf\x8a\x81\x22\x1e\x64\xe4\x1d\x92\xc0\x81\x81\x75\xe8\xf7\xdd\xa3\x98\x5f\xc7\xbb\x25\x17\x48\x42\xa6\xa3\xde\x62\x3b\x9c\x34\x2d\x93\x3a\xb6\x83\x18\x38\xba\x3a\x6b\xc0\xca\x6a\xe2\x97\xd6\x3a\x56\x03\x05\x26\x7c\x83\x6d\xc1\x54\xa5\xe8\x9c\x04\x4d\x1a\x1c\x06\x8a\xe0\x40\xe1\xca\xf6\x80\x18\x98\x07\xb3\xa0\x61\x0d\xa4\xdf\x75\xcf\x18\xa1\x8d\x2b\x1d\x8b\x31\x96\xc4\xd5\x62\x02\x56\x08\xb3\x2c\x70\xea\xfb\xd6\xb3\xb0\x3c\x3e\x99\x88\x53\x25\x20\x5e\xa6\xeb\x44\x3f\x97\xd5\xd9\xcb\x74\xad\xe8\x84\x5b\x71\xcb\xc3\xf0\xaa\x5a\x88\x76\x77\x23\xc8\x63\x64\x64\x0e\x71\x17\x3d\x58\x19\x84\x81\xe2\x04\x19\x41\x14\x7e\x53\xef\xb8\x71\x17\xd2\xb9\xbd\xdc\x46\x1a\x71\xde\xa5\xd3\x0a\x1a\x65\x29\x33\x4e\xef\x67\x34\xe2\x8c\x46\x6a\x9a\x88\x58\xba\xa2\x33\xe7\x09\x6c\x34\x13\x7d\xc3\x94\xd5\xb2\xb4\x36\xb6\xaa\x0a\x99\xaf\x0b\xda\xf0\x60\x7f\xdb\x90\x2a\x0a\x02\x38\x99\xc8\x53\xa2\x3a\x26\xd1\x82\x19\x2c\x9d\xde\x80\xd5\x85\x54\x77\x81\x9f\x5d\x92\x83\xe1\x16\x96\x8d\x9d\x9b\xcf\x8d\xbb\xe5\x68\xe3\x40\xaf\x61\x4c\x3a\x0e\x0d\x82\x33\xe0\xa4\x32\x56\x5d\x3a\x6a\x68\x7e\xe4\x6d\x8c\xf3\x7e\x1f\xb3\x49\x7e\xaa\xe6\xd1\x66\x1c\x88\x69\x4b\x9b\xce\xdc\x2a\xac\x75\x83\xa2\x61\x13\x94\x91\xcc\x47\x7c\xf4\x6e\x83\x4a\x62\x3d\x20\xc3\x5e\x2f\x73\x77\xf1\x08\x18\x19\x09\x97\x91\xc9\x29\x54\x44\x51\x64\xe0\xb1\x87\x29\x09\xb5\x09\x3d\xfc\x2d\x38\x3a\xa3\x9a\x23\xc8\x54\x93\xb1\x9e\x4d\x88\x40\x14\xc3\x95\x55\x96\xce\x68\xc2\xa0\x62\xf5\x1b\xdf\xee\xc4\x67\xde\xd3\x25\x6a\x2a\x04\xc3\xae\xc9\xd3\xaf\xee\x92\x87\x66\x33\x2d\x24\x56\xdb\x20\xdb\x5d\xdd\x65\xaf\x7d\xf2\x01\x97\xb3\x7e\x1f\x4f\x51\x39\xc9\xea\x8b\x18\x4a\xb3\xf9\xb5\x26\x53\x98\x11\x0e\x6c\xff\xfd\x5f\x73\x22\x60\xd9\x71\xdb\x97\xfd\xec\xec\xc2\x5b\xfb\x9b\xe5\x6e\x2f\xb6\x8c\xda\xe7\x6d\x46\xa2\x9a\x73\x90\xf4\xe6\xc3\xe1\x7e\xa3\xd7\x8e\x73\x54\x31\x28\x6c\x78\x7a\xb7\x7a\xa0\xdd\xab\x87\xb8\x8e\x94\xa4\xe6\xd9\xd6\x6a\x41\x2f\x6d\xf8\xdc\x2e\xa1\xac\x03\xbc\x19\x8b\x76\x14\x26\x6a\x09\xa0\x6d\x4e\xc7\x6b\x63\x7b\xba\x35\x81\x65\x26\xa7\x30\x27\x46\x80\x14\x6d\xd6\x9a\x11\x06\x6b\x52\xc1\xf2\x2b\x58\x6c\xb9\xcb\x62\x99\x62\x31\xbb\xf8\x56\x8d\x9d\x28\x05\xf6\xcd\x5e\x4b\x9e\x2d\x86\xa7\xfb\x3e\x76\x28\x03\xce\xd9\xce\xab\x03\xba\xad\x77\xfc\xe1\x7a\x6d\x22\x79\x99\x57\xa5\x31\x25\x12\xcd\x30\x50\x0d\xd8\xcb\x94\xa5\x0b\x2a\xca\xe4\x04\x78\x25\x17\x3c\x67\x8b\xd7\x5c\xc8\xe4\x2d\xe4\x2c\xe3\x2b\xf7\xfa\x08\x96\x72\x55\xbc\xe3\x76\xb9\x98\x64\x60\x85\x57\x42\xa1\xbd\xc4\x4c\x58\x18\x59\xb1\x02\x35\xf1\x25\x4b\x38\x4b\x65\xb6\x4c\x36\x36\x64\xe2\x42\x5b\x35\xc3\x1b\x49\x4e\xe4\x40\x7f\x82\xa7\x92\xbc\xf1\x4e\x96\xfa\x90\x1f\x5e\x4a\xf2\x52\x6a\xfb\xd1\x97\x72\x12\x1f\xec\xf5\x66\xdc\x17\xdd\xe3\x8d\x3e\x19\xdb\x1a\xf5\xf6\xb1\x6e\x6b\x95\xae\xe1\x53\xd0\xea\x33\x49\x3e\xb5\x5a\x7d\x21\x09\xb2\x39\xeb\x8e\x86\x13\xa3\xd2\x19\x12\x62\x78\xae\xeb\xf0\x34\x86\x57\xa6\x50\x9b\x18\x50\xa7\x35\xce\x25\x5b\xe6\xb3\xaf\xce\x3b\xcd\x67\x31\xfc\xb8\x6b\xe4\xd0\xf2\x02\x33\x45\xdb\x3e\x6b\xaf\xbb\xec\x14\x2d\x96\x6a\x68\x39\x27\xb3\x27\x1d\x27\xfb\x37\x35\xe0\x1c\xd9\x5e\xdb\x87\x6d\xd7\x71\xab\x6d\xe7\xd5\xb9\x6b\x06\xc3\x2f\xbf\x0f\x8f\x27\xb2\x76\x66\x0b\x9a\xfa\x75\xff\x21\xf5\xed\x4e\x6d\xa6\x01\xef\xbe\x76\x5c\x27\x8c\x7c\xa3\xdd\xce\x6b\xaf\x25\x72\x2f\xf6\x79\x68\x01\x7a\x2f\xff\x04\x9f\x36\x03\x07\x6f\x03\xe6\x5d\xd7\x82\x84\xbb\x1e\xd2\x9b\x1d\xd7\x5e\x4b\xe4\x5e\xec\xf3\x28\x78\x76\xd0\xff\x59\xae\x6d\x06\xbc\xac\x8d\x40\xd6\x46\xc0\xbb\xaf\x05\x09\xf7\x3c\x46\x5f\xe7\xbc\xf6\x5a\x6f\xd2\xdc\x73\xd8\x64\x01\x96\x59\x80\x65\x56\x63\xf9\x27\xbb\xba\x19\xc8\xab\x36\xb2\x55\x1b\xd9\xaa\x8d\xac\xf7\x65\x0b\x12\xee\x7b\xec\x7f\x9f\x27\xdb\x6b\x89\xdc\x8b\x7d\xbe\x17\x3c\xdf\x0d\x9e\x47\xc1\xb3\xa5\x08\x86\x1f\x7e\xf7\x68\xf4\xa3\xde\x0d\xcb\x2d\x86\xdf\x6e\x97\x1d\x2d\x17\xd5\x46\x45\xaa\x8a\x87\x7a\x4d\xaf\xa6\x74\x0c\x5f\x64\xb8\x64\xfd\xfe\x36\x10\xd5\x12\x56\x6f\x7d\xa3\x1c\x7d\x91\xf0\x5c\xd5\x08\x1e\xb6\x9f\x75\x65\xf3\x34\x2f\xe0\x1f\x37\x19\x2f\xfd\x26\xbb\xbc\x23\x7e\x96\xda\xf5\xc8\x39\x47\xd4\xb3\x00\x86\x9f\xf6\x5a\x9d\x69\x30\x3a\x2a\xfb\x47\xb3\xb2\x7f\x76\xc9\xb0\x5b\xaa\x68\xa6\xd3\xb0\x6a\x77\x6f\x32\xd6\xe6\xd5\xa6\x89\xbf\xef\x91\x4a\x7f\xb0\x95\x66\x3a\x0b\x5b\xaf\x2f\x5f\xc6\x5b\xb5\x3c\xab\x61\xe8\x96\x2d\x7f\x32\x04\xcd\x74\x1e\x42\x16\x5e\xeb\x8c\xb7\xc0\xdb\xf0\xed\x93\x0a\xff\x26\x08\x9b\xe9\x59\x08\x79\xf3\x26\x69\xbc\x85\xac\x0b\xfe\xf6\x26\x67\x30\xe8\x1a\xce\x0e\xff\x68\x2a\x37\x49\x8a\xfe\xb9\xcf\xc4\x71\xaf\xef\x83\x92\x3d\x7f\xd7\x43\x77\xa4\x07\xd7\x37\x37\xb2\xf0\x4f\x72\xbf\x4a\xe0\x43\x7d\x6c\x55\x85\x39\xfa\x27\x7c\x2f\xed\x55\x42\xda\x7b\x43\x90\x7f\xb4\xe2\x6c\x0c\x95\x46\x26\xc4\xfe\x06\xbb\x0a\x28\xa0\x85\xd2\xcf\x94\xee\x89\x62\x1d\xab\x08\x03\x13\xfb\x75\xa2\xd7\x26\xf8\xb5\xd7\x8b\xb8\xd8\x37\xcc\xa9\x40\x4c\x20\x8d\xa6\x74\x70\x67\xb7\xe6\xee\x96\x33\x5a\x34\xbc\xd6\xd2\x01\x6f\xe1\x46\x01\xf2\xc4\xe5\x52\xff\xb5\x1f\xc5\xde\x36\x03\xf0\xac\x38\x1c\x9f\xc8\x41\x53\xdf\x1f\x28\x9a\x90\xab\xf5\xf9\x22\x89\x1b\xf1\x5c\x63\xad\xbc\x27\x52\x80\x5f\xbb\x24\xdf\x48\xf0\x7b\xad\x89\x10\xb0\xb3\xfd\x50\x09\xe3\x27\x30\x15\x37\x85\xeb\xb5\x7b\xcc\xfd\x38\x89\xe2\x7e\x1d\xf3\x03\xe9\x2b\xe0\x98\x56\xf3\xeb\xad\x5b\x39\xe3\x95\x3c\x76\x0f\x83\x0b\x91\x4b\x8a\x28\x4e\x32\xce\x4a\x5e\x50\x1d\x1e\x9c\x36\x4c\x5d\xf4\xbe\x69\x7b\xa1\x28\xdd\x5e\xf9\x95\x09\x18\x43\xa1\xe0\x8b\xc4\x2c\x0b\x10\x86\xbc\x1b\x60\xba\x27\xd4\xff\xde\x78\xeb\x7d\xd1\xb9\xa7\x21\x27\xc3\xd3\x3a\xb0\xce\x0b\x14\x9c\xfa\x64\x4b\x61\xee\x86\x32\x5b\x1e\x23\xac\xad\x85\xbb\x2d\x91\x9a\xf5\x87\x31\x08\x7f\x1c\x58\xf7\x53\x24\xb1\x8d\x42\x14\xb7\x17\xe6\xde\x90\xac\x8d\x43\x8a\x76\xae\x4b\x2d\xd7\x45\x2e\x55\x1d\xc0\x48\xf3\xea\x47\x13\xc1\xd0\x02\x4e\x1b\x61\x91\x68\x47\xcb\xcd\x48\x7f\x41\xc5\x6a\x59\x65\x6a\xc1\x83\x79\x5e\x48\xbd\x21\xd8\x51\xc1\xbc\x19\x58\xce\x17\x17\x74\x43\x45\x49\x51\x57\x99\x0e\xaf\x78\x7f\x23\x8d\xb9\x30\x8e\x8d\xfb\x7d\x6e\x6f\xbf\x74\xa8\xf0\x53\xdc\xed\xab\xdf\xe1\x18\xdf\x75\x8b\x66\x40\x92\xee\x7a\xd6\x0d\x5a\xfc\x38\xf0\x7e\xc2\xc8\xd1\xa5\x71\xb1\xf0\xb2\x95\xdd\xf5\xb0\xb0\x28\xcb\xb6\x6b\x78\xd8\x85\x71\x3c\x96\x0f\x86\x63\x3c\xea\xc9\x5e\x0f\xd1\x3e\x51\x3c\xf6\xe0\x01\x19\x81\xe8\xd7\xaa\x13\xed\xb8\xd2\xd4\x77\xa6\xbf\xb7\x71\xaf\xc7\xb5\x3c\x1a\x1d\xc7\x71\x22\x82\x9b\x34\x5b\xdb\xe0\xfb\xb2\x1e\xca\xdd\x4b\x3e\x83\x9c\xc2\x67\x94\xed\xad\xde\x3d\xf9\x86\xd0\xa8\xf2\xbc\xb9\x28\x44\xf2\xd0\xdf\x41\x74\xe7\xae\xdf\x5c\x0f\x6e\xc0\x60\xaa\xcf\xfa\xb4\xbf\x41\xc3\x6b\xd6\x40\xf9\x6d\x9b\x30\xfd\x4d\x50\x5d\x23\xeb\xe7\x56\xd6\x56\xc6\x3e\x6d\xec\x1f\x06\x6c\x2d\x45\xbe\x42\xcd\x9d\xc0\xe0\xab\x8f\xb7\xf5\xbf\x1f\xca\xfe\x1d\x68\xb0\xfa\x49\x77\xce\x0f\x65\xff\x9b\x56\xce\x37\x0d\x71\x51\xf3\x9e\x6b\xdd\xb2\xa0\x2a\x7a\x67\x11\xf2\xe1\xd3\xbd\x05\x5d\x09\xf1\x81\x5d\x7f\x10\xd7\x1f\x58\xb3\xe0\xcb\x26\x8e\xa1\xd9\x7d\xe3\xce\xae\x46\xa6\xc0\xd4\xbd\x71\x13\x51\x5b\x42\x85\xa1\x36\xb4\xe7\xb8\x15\xa5\x13\x7a\x8a\x03\x07\x72\xfb\x30\x6a\x5c\x1c\x74\x4b\x5d\x07\xdd\x95\x75\x05\x78\x7e\xd5\x12\x6f\xf5\x76\xf5\x83\xc3\xd1\x8d\xf7\x02\x05\x59\xf7\xde\xe4\xe3\xee\x89\xf2\xf3\x4e\xaf\x27\x06\x45\x5a\xca\xe7\xbe\xac\xae\xca\xde\x67\xb4\x2b\xd9\x7f\x69\x4c\xb8\x7e\xa7\x7e\x8e\x68\xed\x2e\xa4\x37\x39\xc3\x2b\xa5\x75\x10\xfd\x31\x62\x21\x8c\x4a\xb1\x7f\x70\x38\xf2\x11\x37\x18\x06\xd6\xf7\xee\xbd\x0d\xb6\x08\x4f\x11\x7f\x0d\xef\x6e\xa8\x5b\x0f\x2f\xb5\x89\xde\xbb\x6b\xe4\xa9\x99\x26\xf3\x39\x8a\x87\x5a\x71\xed\xf5\xe2\xcf\xfa\xbc\x7a\x32\x3a\x35\x1d\xc6\xc8\xdd\x31\x3b\x12\xe3\x7e\x9f\x61\x13\xaf\x7d\x18\x1f\x11\x44\x75\x48\x5d\xdc\xeb\xd1\x23\x12\xff\x4f\x7c\x7d\x1d\x3f\x8c\x8f\x54\x79\xf5\xfe\x4c\xbd\xa7\xf5\xfb\x3c\xc6\x8d\xa6\xed\xf3\x13\x89\xb4\x01\xfe\x73\x26\x91\x84\xd1\x5f\xb1\xbe\x53\x92\x3e\xd0\xf5\xd1\xa3\x78\x18\xf7\x7a\xf1\xa1\x36\x66\xec\xf5\xe2\x7e\x1c\x5c\xb3\x6e\xea\xa9\x29\x38\x0a\x61\x74\xc0\xa9\x1a\xae\xaf\xe3\xff\x89\x8f\xe8\x57\x34\x3f\x0c\xc7\xd1\xfb\x60\x88\xbc\x96\x28\xce\xb4\x79\x93\x09\xe1\x6c\x0c\x5f\x4c\xbc\x4f\xef\x3b\x60\x8c\x60\x9e\x33\x19\xb7\xaf\x2d\xf2\xd7\x64\xba\x0b\x32\xef\x4c\x3e\x94\x9f\xcf\xf8\xe9\x9d\x81\xa4\xa5\x9e\x80\x6c\x43\xbf\xb9\x6e\x11\xa4\xef\xcf\xe7\x74\x30\xef\x63\xad\x82\x26\xbf\x35\x38\xf7\xb7\x3f\x02\x63\xa4\x23\xb9\x85\x40\x7e\xb9\x45\xd6\x34\x15\x87\xa0\xe0\xf7\xb7\x2a\x43\x56\xfd\xcb\x4b\x1d\x2b\x33\xa1\x2e\x74\x07\xc3\x50\x31\xfd\xcc\xeb\xc0\x82\x19\x06\x73\x2f\x9d\xde\xb7\xd6\x97\xf5\x4c\xed\x8e\x75\x8a\xc1\xe8\x2b\xd6\xa8\xce\xe8\x21\xc9\xdc\x5f\xf5\x53\xd4\x57\xfd\xcc\x30\x68\xb8\x13\x89\xd6\x18\x14\x28\xe6\x96\x20\x41\xd7\x34\x95\xe6\x86\x20\x77\xaf\xd0\x02\x43\x41\xe7\x52\x47\xfa\x00\x61\xae\xd5\x42\x97\x18\x66\x82\xaf\x5f\x98\x0f\xef\xcc\xdb\x1b\xfb\xf1\x02\xc3\x3a\x9d\x25\x42\xdf\x53\x94\xce\x74\x26\x81\x3e\xeb\x17\x93\x47\xa0\xb7\x6a\x31\x95\xaf\x92\x47\xfa\x47\x67\x79\xa8\x1f\x4d\x86\x13\xb8\xe0\x62\x56\x26\x6f\x40\x87\xde\x4d\x9e\x7a\x07\xaa\x97\xde\x2f\xea\x31\xa4\xec\x32\x91\xe8\x19\x86\xb4\x28\x12\x89\x9e\x6b\xe2\xc8\x34\xd7\xf4\x7b\x85\x41\x07\xeb\x2d\x6d\x9c\x92\xd7\x18\x28\x9b\xb9\xb7\x27\xee\x4a\x24\x95\xf5\x17\x0c\x92\x3f\x67\x32\xf9\xd5\x5f\x05\xf2\x83\xbb\x86\xe9\x4b\x7d\x35\xd3\xf7\x5a\x25\x4f\x05\xc9\x45\xed\x8a\x56\xea\x57\x93\x19\xe6\xf6\x45\xd7\x01\x85\x7d\x7b\xce\x24\xcc\x04\x41\xb9\x15\x5c\xb4\x84\xe6\xa3\x83\x0b\xc3\x5a\x17\xa9\xe1\x86\xa5\x4e\x70\x68\xc1\xc6\x54\x93\x16\x85\x2a\x97\xb2\x4b\x30\x8d\x2b\x82\x60\x58\xd9\x06\xad\x23\x95\xc9\xab\x09\xa8\xb2\x69\x8a\x62\x38\x33\xc9\x9e\xd6\x60\x5f\x54\x1f\xb8\x67\x0c\x97\x26\x97\xeb\x31\x30\xcf\x2a\x0f\x86\x77\xfe\x9b\x4a\xf6\x3d\x8f\xe1\x42\xb7\xef\x18\x03\xce\xf5\xab\x66\x19\x78\x6b\x81\xb1\x8d\x68\xe6\xc2\xf0\xd9\xa4\x1a\xb6\x53\xe9\x8a\x15\x31\x3c\x32\x54\x50\x1c\x0a\x0f\x4d\x16\xe3\x2a\x68\x1f\x34\xf2\x96\xc1\x75\x9a\xe6\x7b\xf5\xb4\x4a\xd7\x90\x0b\x7f\x3f\xd8\x89\xa3\x5e\x96\x4a\x78\x63\x69\x67\x9c\x2b\x73\x31\x30\xc3\x0b\xc3\x53\x97\xab\x84\x97\x5d\x4b\xf0\x28\x47\x4f\x05\x48\xad\xb6\xc0\x63\x9d\xd9\x8e\x56\xf8\xd4\xb5\xf0\xef\x8a\xda\xb2\x27\x14\xee\xfe\x30\x2e\xa9\xd9\xe9\x1f\xa9\x7f\x77\x21\x45\x9f\x84\xf6\x31\x65\x3a\x18\x7f\x33\xb0\xcb\xbd\xed\x16\xc3\xb3\x4e\xc8\x75\xb9\x7d\x5b\x13\xdd\xb1\x07\xf0\x4e\x98\x88\x17\xff\x6a\xd5\xfb\x83\xdb\xef\x6d\xf3\xf9\xbf\x8d\xb0\xcf\x3d\x61\xef\xb5\x09\x7b\x5f\x41\xf6\x4a\x90\x60\x2f\xce\x6e\x7b\xe9\x8b\x31\xed\xad\x21\x2d\x38\xb3\x26\x9c\xe6\x76\xd3\xca\x18\xf3\x69\x63\x97\x39\xc9\x83\x58\x03\xf3\x0e\xf7\xfc\x90\x50\xb9\x71\xff\xe6\x1a\xc8\x29\x36\xfb\x18\x05\x99\xab\x0a\x67\xea\x67\xa8\x9e\xd6\xf6\x69\x38\x0e\x3c\x9e\xd7\xfa\xda\x2f\x3f\x73\xd6\x89\xb5\xe3\xfb\x4d\x2d\x75\x75\x5b\xa1\xf2\x94\x88\xc1\x1a\x66\x16\x1e\xeb\x2a\x0d\x59\xd7\x11\x57\x61\xea\xa4\x3a\xff\x14\xeb\xc8\x16\x73\xa2\x89\x9e\x77\x45\xe7\x78\xa1\x8f\xa1\xa7\xa3\x64\xba\x85\x0a\x83\xc6\x73\x68\xf0\x1c\xd5\x0e\xc5\xbb\x01\x63\xac\x63\x4e\x9d\x85\x9a\x18\x48\xba\xa3\xf5\x7e\xe4\x0c\x0a\x1d\x6e\x49\x90\x1b\x76\x9e\xa7\xc2\x44\xc8\x47\x27\x02\x35\x59\x38\x7e\xee\x42\x25\x0b\x3a\x3b\x3c\x2b\xd2\xec\x3c\x92\x82\xd2\x28\x67\x9b\x54\xe4\x29\x93\xd1\x26\xe7\x45\x2a\xe9\x0c\x22\x7f\xd0\x1f\xef\x09\xf1\xd1\xaa\x5b\x5b\x88\x2f\xb8\xec\xca\x7f\x8e\x04\xee\x28\x72\xa7\x23\x2b\xfd\xca\x7c\xac\x23\xdf\x07\xf6\xba\xa0\x69\x49\x23\x41\xb5\x1d\x82\xb6\x48\x3e\xab\xb4\x05\xc3\xd1\x52\xca\x75\x99\xdc\xb9\xb3\xc8\xe5\xb2\x3a\x1b\x64\x7c\xd5\xba\x63\x29\x2f\xcb\x8a\x96\x0f\xe2\xdd\x70\x10\xe6\x4f\x6f\x08\xbe\x16\x9d\x01\x9a\xa4\x8b\xcc\xd1\x1d\x4c\x5c\xd4\x81\x36\xe2\x47\x8f\x14\xdd\x4d\xaa\x3d\xde\xaa\x57\x54\x2e\x1c\x82\xca\xf8\xe2\xab\x72\xb6\x23\x20\x1c\x8c\xb6\xf0\x64\x77\xd7\xb2\x2b\x52\xd8\x1e\xa9\xd3\x0c\x53\x26\xc7\x92\xe4\xe8\x89\xd0\x81\x1b\xa8\x12\xdc\x26\x66\x98\x96\xd7\xbf\xec\x36\x24\x93\x3f\xdc\xd4\x27\x67\x15\x9b\xa3\x13\x90\x26\x5e\xb4\x25\x9c\x36\xa4\x7b\xf1\x2e\x4e\x7c\xcc\xb2\x7b\x63\xa5\x4f\xe4\xac\xa2\x91\x34\x76\x76\x4f\x7f\xf6\x66\x76\x2f\x10\x1d\x4c\xef\x62\x1f\xbe\xc3\x97\xba\x1f\x94\xd2\xe3\xf8\xd7\x7d\x1b\xbc\xfe\x54\x2d\x47\xbf\x68\xe1\x6a\x40\xd9\x62\x78\xff\x67\x4a\xf5\xfd\xb3\xca\x58\x9a\x30\x35\x3a\x5a\xcd\xdd\x40\x96\xff\xe0\x5d\x18\x4f\x0c\x83\x6c\xe1\x37\x9f\xf4\xc8\x25\x7d\xa9\x93\x6c\xca\xf7\xdd\xac\x7b\x3b\xd7\xba\x95\xfc\x74\x58\xfb\xa7\xd3\x4f\x88\xc2\x17\x81\xaf\xaf\xed\xf3\x6f\xde\x60\xfa\x60\xb8\x85\x9f\x7d\xeb\x6f\xe8\x2c\xde\xc2\x3f\x9a\x6d\xdb\x7e\x96\x61\xef\x1a\x30\x5d\x0f\xfe\x66\xa2\xcb\xe8\xe2\x2e\xed\x8b\x4d\x3b\x69\x66\xfd\x59\xf8\x7e\x6e\x4b\xc0\xf8\x71\xca\xbe\x95\xd1\x2a\x3d\xa7\x51\x1a\xcd\x78\x75\x56\xd0\xc8\xc8\x3d\xc6\x67\xd4\xdc\xc8\xa3\xdf\x0f\x62\xbc\xdd\xc2\x4f\x5f\x01\x66\xb3\x71\x07\xd3\x0e\x48\x3b\xd0\xff\xf0\xb5\x60\xea\x50\xd2\xf9\xa6\x01\x68\x41\xcb\x32\x04\xf4\x9f\x9e\xbe\x2f\x7c\x8f\xff\x3d\x48\xb3\x49\xdf\xdc\x70\x18\xd3\xc5\x9d\xee\x60\x46\x52\xf2\x8d\x40\x7f\x17\x6a\x31\x45\x6e\x3a\x64\xf4\x75\xed\xf0\x4f\xcd\xc9\x30\xbd\xab\xa4\xfa\x3d\x25\xb2\xef\x27\x5c\x1f\x76\xd1\x9b\xc2\xdc\xdd\xc4\x8d\xbd\x9e\x26\x6a\x28\x13\x8f\xe7\x48\x28\x5e\xd4\x37\x4c\xe9\xcb\xa3\xf4\xbd\x50\xe6\xca\xa7\x44\x6e\x81\xfd\xe1\xd6\x4c\xd5\x3f\x09\x6b\x94\xd9\xd9\x80\x21\xd4\x16\x38\xed\x52\x30\x3b\x4e\x9a\x3a\x0e\x36\x3b\xce\x34\x3b\x8e\x33\x3b\x4e\x32\x7d\x52\xb5\x9b\x34\xdd\x4d\xca\x77\x93\xd2\xdd\xa4\xb2\x4e\xb2\xe8\x4b\xac\x35\x46\x4f\x68\xa0\xc6\x93\xc3\x25\x28\x55\x32\x85\x12\xe3\x7a\xb6\xdc\x42\x76\x0b\xd9\x3b\x85\xa3\xa5\xbb\x21\x6a\x72\x53\xcf\x6e\xa1\xfa\x17\x1a\xa8\xc7\x5e\x16\x8e\xbd\x17\x34\x9d\x2b\xe5\x28\xb6\x6d\xff\xbc\xaf\xed\x69\x77\xdb\x75\x98\x2e\xaa\xfe\x31\xf5\x8f\xab\x7f\x99\xfa\x57\xdd\xa0\x25\x78\x4b\xce\x46\x28\xaf\x7d\xcc\x69\x8d\x5c\xf0\x8d\x79\x8c\xdd\x0b\xf6\x76\xf2\xda\x7c\x25\x94\x65\x5a\x3c\xd5\x9f\xef\x77\x7d\xbe\x05\x8a\x3a\x72\x74\x3d\x2c\xef\x85\x2d\x19\x6c\xaa\xdb\xb0\xb1\xc0\xb6\xeb\xb9\xdf\xaa\x27\xbb\xb9\x9e\xfb\x9d\xf0\xdc\xdf\x85\x87\xdf\x5a\x4f\x07\x3c\xf7\x77\xe1\x61\x3e\x52\x58\x63\x66\xfa\x4f\x24\x5a\x87\x36\xa9\xef\xca\xfc\x0a\x52\x86\x25\x43\x62\xde\x52\xfe\xfe\x9e\xf2\x6d\xf8\x68\x67\xb8\xb5\xff\x24\xfa\x39\x65\xbb\xd1\xc9\xff\xca\xc0\xf9\x3f\x60\xd4\x3f\xc0\x03\xf7\xf6\xf0\xc0\xbd\xaf\xe4\x81\x7b\x7b\x78\xa0\x83\xc6\x62\xff\x40\xea\x5a\x06\xdd\xb8\xd6\xfa\xf7\xf2\xee\x57\xf3\xea\xbf\x8b\x82\xdb\xae\xd1\xf4\xff\x40\xcf\x6f\x1d\xbc\xff\x8f\x0d\xac\xdf\xc3\xb8\xff\xb1\x12\xd7\xc7\x61\xd4\xb1\x38\x6e\x51\x19\xfe\x43\xc5\xf3\xbf\xdc\x03\xff\x27\xf2\xae\xdd\x03\x3a\x18\xc8\x4d\x4a\xa2\xd3\xeb\x5c\x05\xff\xdf\x70\xf9\x3f\x1c\x2e\xbb\x11\x48\xb9\x71\xc4\xc2\xc8\x33\xce\x28\x78\xbe\xeb\x9e\x7d\xa2\x49\x31\xaf\x77\x83\x9c\xf7\x82\xe7\xfb\xee\xd9\x3c\xdc\xc7\xb7\x36\xdb\xaa\xde\x70\xe0\x28\x78\xee\x6e\x36\xc8\x10\x3e\x7f\x5d\xb3\x61\x65\xf7\x03\x28\xee\x07\x80\xdc\x0f\x12\x6d\xb3\x41\x9e\xf0\xf9\xbe\x7b\xfe\x9d\xcd\xb6\xaa\xbf\xdf\x4c\xec\x68\x36\xf8\x14\x3e\x77\x35\x1b\xac\x47\x2d\x82\xf5\xe3\x5d\xb8\x61\xb5\x6a\xb1\x83\x39\xca\x83\x0a\x5c\xe9\xbb\x75\x9e\xfb\x50\x51\x8f\x37\xbe\x19\x84\x7b\x75\x25\xb6\x4f\xc3\xfa\xef\xd5\x9f\xee\xda\x4a\x0d\x0c\x41\x0f\xef\x01\xd9\x34\x6f\xef\xcc\xde\x05\x41\x6e\x21\xdf\xb7\x2d\x64\xfc\x5a\x74\xb5\x75\xaa\x2b\xf8\xbd\x40\x19\x3e\x9e\x52\x94\xe1\x24\xdb\x62\x48\x6f\xde\x5c\x8a\x5e\x0b\xc4\xf0\xf5\xf5\x6b\x81\x38\x3e\xd6\xa8\xfd\xc3\x78\x36\xab\x7c\x54\xdb\xc9\x50\xc4\xb1\x5d\xab\xd7\xe5\xb7\x18\xca\x9b\x01\xe4\xb7\xec\x12\x98\x78\x2a\xc7\x29\x9a\xab\x7a\x55\xc1\x64\x8e\xd2\xba\x8d\x39\x2a\xa9\xf6\xa3\xd1\x4e\x34\xda\x83\x46\xbb\xcf\xa8\x7f\xf7\x4d\x8c\x56\xfa\x47\xbc\xa8\xf6\x6d\x1b\x1f\x04\x3e\x55\x4e\xf9\xdd\xb3\xb9\xdc\x19\x7d\xda\xc6\x9d\x36\x8e\x2f\x5d\x2e\x53\x26\xf8\x3c\x4c\xef\xee\x5c\xa6\x75\x2f\x0e\xef\x9b\xf2\x92\x32\xbc\x70\xca\x4a\xfc\xf0\xbe\xa9\x17\x61\xc6\xbb\xcd\x7d\x3a\x66\xcf\xfb\xcc\xef\x5d\xfb\x7b\xcf\xfe\xde\xc7\x49\x89\x7e\x14\x60\x9a\xba\xf3\x86\xce\xee\xd8\xca\x40\xc2\x39\xca\x30\x9c\xeb\xa0\x21\x26\xc0\x88\xab\x23\xb7\x4f\xf7\xa1\x20\xae\xfe\x19\xd1\xdd\xe4\xf0\x2e\x60\xea\x9b\xca\x31\xac\x49\x8a\xde\x0b\x9d\x9a\x63\x58\x92\xb5\xca\xb3\x51\x3f\xa3\x7a\xac\xe9\x2e\x5f\xc2\x06\x66\x40\xb5\xcd\xd2\x0d\xbd\x13\xd2\x7d\xe5\xe9\xbe\xf0\x74\x3f\xdb\x4b\xf7\x85\xa2\xfb\xaa\x8b\xee\x67\x3b\x74\x3f\x0b\xe8\xfe\x22\x4c\x1d\xb5\x7a\xe3\xac\x8b\xee\x23\x4b\xf7\x91\xa5\xfb\xc8\xd2\x7d\xb4\x43\xf7\x17\x9e\xfc\x86\xee\x0b\x45\xf7\x15\xc6\xdb\xae\x4d\xf1\x70\x9f\xdb\x6c\xdd\x75\xed\x8a\x7f\x23\xd0\x3f\x05\xde\xbf\x0b\x6e\xaf\xce\x5f\xa6\x1b\x1a\x9d\x99\xcd\x6f\x2e\x22\x56\x6f\x83\x97\x51\x6a\x0f\xf5\xd6\x3c\xd7\x06\x58\x5b\x0c\x05\xdd\xeb\xc3\xf4\xd5\x27\x4f\x16\x66\x67\x7e\x1c\x72\x80\xa0\xf6\x8e\x26\xd0\x6e\x8b\xa0\x0f\x96\x20\x47\x05\x35\x47\x54\xf7\xc2\x17\x33\xf4\x67\xfe\x66\x81\xb7\xe9\x8a\xc6\x5b\x58\xd3\xfa\x34\x64\xc5\x37\x2a\x69\xe9\x93\x9e\xb3\x92\x0a\x19\x6f\x61\xb3\x5f\x62\x84\x5b\xc6\x66\x58\xdf\x78\xc2\xc4\x03\x4e\xcc\x88\x40\x9f\xfc\xed\x28\xee\x72\xc5\x5a\xc4\x75\x08\xa3\x99\x09\x69\x4e\x3b\x0f\xcf\x97\xfa\xa3\xdb\x1c\x35\xce\x84\x20\x29\x48\x6a\x23\xcc\x54\xda\x85\x12\xa6\xea\xe7\x3e\x94\xea\xe7\x1e\x14\xe6\xee\xaa\x99\x76\xc0\x6c\x1e\xf3\x15\x8d\x33\xbe\xa7\x3f\x9b\xf0\x1d\x6b\x22\xd0\x0b\x54\xe1\x2e\xc8\xd7\x7b\x21\x5f\x53\x73\x54\x3f\xa7\x30\x83\x72\xdf\xf9\xff\xac\x46\x61\x06\x05\xe8\x81\xaf\x33\x8f\xfd\x31\xa3\x02\x61\x49\x18\x2a\x31\x6c\xc8\x52\x65\x58\xa9\x9f\x91\x03\x7d\x13\xc2\xac\x7b\x39\xd9\x7b\x9e\xd7\x6a\xae\x82\x55\xdd\x96\xed\xfc\xfd\x85\x1d\xb9\xf3\x66\xe1\xe6\x18\xda\x4b\x09\x2d\xc0\x82\x72\x7e\x89\xad\xf0\x5b\x10\x86\xa6\x0a\xbf\x85\x91\x4e\x8b\x3f\x0b\xbf\x12\xce\xfe\x38\x7e\xa6\xf0\xef\xc7\x4f\x97\xdb\x6e\xb7\xc0\x89\x1a\x26\x90\x69\x56\x83\xca\x5c\xf9\x66\xd1\xca\xf6\xa1\x15\x55\x5d\xf0\x46\x94\xa2\x6a\x47\x60\x65\x2a\x51\x49\x9e\x55\xd7\x80\xf5\xc6\x1b\x1b\xaa\x23\xb6\xbf\x40\x02\x63\x13\x2b\x7e\x41\x6f\xb8\x14\x60\x65\x94\x0b\x49\x5b\x17\xec\x34\x73\x3d\x17\xb0\xa2\xa0\xaf\x94\xc2\x18\xce\xe8\x9e\xbb\x6b\x76\x2f\x12\xf2\x46\x60\x06\xcc\x63\xdd\xa0\xf9\x96\xb0\x30\xce\xfd\x73\x01\x4c\x8d\x67\x0d\xc7\x25\xdd\x77\x7d\x54\x8e\xce\xe8\x3e\x30\x73\xf4\xab\xd0\x11\xf4\xb7\xf6\x42\x80\x77\x5f\x0f\xa7\x55\x5a\x4c\xf7\x8d\x4c\xf7\x0d\xc7\x6d\xe8\x3b\x18\xc2\x23\x54\xe1\xfd\xb7\xee\x54\x46\x3c\xd8\x9c\x19\xde\xee\x60\xde\x75\x1e\xef\xc4\xa1\xc1\xe8\x82\x7e\xed\x05\x50\xd6\xee\x7a\x1c\xf6\xb1\xbf\x09\xdb\x50\x46\xea\x2b\x8f\xe0\x7c\x77\x0e\x6b\xf3\xd1\x27\x4b\xcb\xb7\xbb\xb4\x0c\x31\xb8\xc1\x65\xf0\x9c\xba\x4e\xb1\x3f\x9f\xe9\x4d\x8e\x64\xb6\xdc\x8d\xe1\xbb\x7c\x20\x5f\x6d\x58\xb4\x49\x8b\x30\x92\x6f\x18\xfd\x4a\xdc\x18\xc9\xd7\x97\x36\xa1\x7c\xed\xa0\x67\xfc\x22\xd9\xdf\xba\xc4\x57\x32\x0c\x19\xf6\x24\x95\x74\xc0\xf8\x05\x32\x8e\x7b\x01\x4c\xd3\xda\x13\xed\x11\x25\x9f\xe9\x20\xfc\x06\x0f\xf7\xcf\xba\xfb\x6f\x12\xfa\x87\x74\x31\x76\xfd\x1d\x51\x9d\x3c\xf1\x90\x82\xb5\xd3\xd3\x9d\xcf\x9d\x13\x71\x45\x02\xbf\xea\x47\xea\x43\x8e\x5e\x48\x90\xc0\x31\x0e\x22\x8d\x7d\x91\x90\x41\xa5\xd0\x39\xd9\xa7\xe4\x48\x30\x0a\x0b\x70\x42\x0d\x20\xda\x5e\x85\xd7\x4e\x52\x1d\x73\xbe\x05\x66\xbf\x41\x95\xb9\x49\x4a\xe0\x64\x7f\x4e\x35\xef\x5b\x2f\xd9\x37\x9a\xaa\x8c\x5f\xc0\xd3\xfd\xc4\xd4\x60\x09\xa0\x36\x40\x55\xd9\x05\x1e\xf3\xde\xb4\x14\x27\x4d\x47\x4d\x19\x3a\x6a\xd2\x1b\xfc\x38\xad\xc7\x6b\xc7\x21\x7b\x8e\x9e\x2b\x12\x53\xe3\x26\x6e\x2e\x32\xdd\xc2\x1b\x73\x79\xfa\x4b\x1a\x78\xb2\xe6\x2b\x1a\x63\x78\xbc\x6f\x50\xda\x90\x5d\x65\x22\x61\x6d\x62\x88\xd3\xd2\x38\xf1\x7e\xa2\x44\x7b\x8b\x3f\xa6\x56\x25\xc2\xf0\xac\x45\x92\x70\x11\x0a\xd5\x5e\x72\xd1\x71\xc7\xd4\x77\xaf\x71\x4f\x95\xe6\xab\xe9\xdd\xbd\x84\x62\x83\xe9\xdd\x2d\x3c\x94\x83\xf3\xbc\x28\x34\xd2\x5b\x0c\xd3\x4e\xcb\x41\xcb\xc9\xfb\xdb\xe4\xb6\x4d\x3b\x4f\x51\x1d\x0d\x03\xeb\xe5\xa2\x6a\x45\x0d\xb8\x3f\x82\x4a\x87\x55\x21\xd3\x7c\x15\xa0\xc7\x6c\x03\x73\xa2\x64\xec\x89\xa6\x2c\xc3\x30\x23\x05\x7a\x25\x94\xde\x06\x15\xcc\x21\x1b\xf8\xae\x80\xfd\x0d\xb9\x0b\xd3\xa4\x0e\x3c\xb1\xc7\xa9\x79\x4d\x66\x0a\xdb\xa5\xfa\x19\xc1\x46\xfd\xdc\x6d\x8c\xc9\x6e\xa6\xd4\xbd\x3e\x07\x79\x93\x93\xb1\x95\x08\x6b\x58\xe2\x2d\x6c\x34\xe3\xbd\xd8\xcb\x65\x06\xb4\xa7\x1b\x2a\x2e\x5b\xbe\xe2\xcf\xf7\x2b\x12\x2f\x29\xca\xd1\x0b\xea\x2f\xbd\xbb\x25\xbc\x83\xce\xab\x05\x47\x07\xb4\xc6\x19\xdd\xdc\x39\xb3\xc5\x9d\xfe\xcd\xf9\x8a\xde\xe0\xdf\xfc\x89\x06\xfe\xcd\xcf\x68\xe0\xdf\xfc\x94\xc2\x4e\x2c\xaf\xe7\xd4\xd8\x05\xbf\xa2\xf0\x23\x25\x8f\xe4\x20\xb8\xe3\x01\x5e\xeb\x14\xfb\xf2\xc4\x7e\x66\x95\xa4\xf0\x8b\x7e\x59\xf2\x4a\xc0\xaf\xfa\xd1\x5f\xcb\x00\xef\xdd\x3b\xfc\x60\x4a\x70\x26\x97\xf0\x9b\x7e\xbe\xa4\xa9\x80\x2f\xfa\xd1\x5d\xf8\x00\xdf\xeb\x57\x73\x4d\x04\xfc\x4c\x09\xb2\x1f\x8d\x0b\x35\x68\x7f\xef\x2f\x54\x89\x0c\xc7\x63\x6f\x2b\x16\x6f\x31\xfc\xc3\xaf\xe6\x7e\x4c\x59\xbc\x85\x9f\x28\x41\x6e\x5d\x0b\x53\x31\x28\xf8\xa2\xf3\x4e\xec\x7c\xc7\x2a\xeb\x68\x46\x33\x3e\xa3\xe2\x41\xec\x08\x64\xaf\x7f\x58\x95\x8b\x46\x44\xc7\xf4\xd6\xa2\xe6\x1a\x88\x76\xb9\xf2\xb6\x72\x61\xe6\x79\x07\x43\xb6\xb3\x83\x7d\x6f\x04\x8f\x2c\x6e\x85\x8e\x55\x45\xe7\x25\x15\xb3\xdb\x9b\x8c\xe7\x39\x2d\x66\x31\xe8\x9f\x3d\x00\xac\xbf\xa2\x1a\xed\xbc\x12\x1b\x17\x9a\x3d\xd5\x6c\x6e\xc5\xe3\x9c\x5e\x1e\x6a\x2c\x62\x5f\xc1\xfe\xc0\x9b\xdd\x55\xac\xd2\xf5\xe1\x2a\x65\x97\xb1\xe6\x91\x1a\x92\x72\x37\x1e\xe7\x2d\x35\xf9\x70\xf9\x1e\x97\xee\xdb\x30\x2e\x6f\x45\x8b\x33\xfa\x6a\x1e\xd7\x90\xc8\x76\x38\x4a\x2f\x25\x14\x86\x13\x71\x7a\x43\xd4\x48\x93\x03\xe8\xe9\xae\x0f\x71\xb0\x34\x71\xb9\x80\x9d\xee\x3a\x08\x37\xb6\x85\xeb\x9c\xc0\x4f\x77\x3d\x84\x5b\x41\x46\xc2\xdc\x90\x85\xf9\x1f\x85\xf9\xa1\xda\x53\x02\xaa\xd3\x56\x18\xc1\xe0\x13\x4c\xf7\x96\x82\xe9\x69\xd3\x95\xb8\x59\x0e\xf2\x1b\x4a\x42\x7e\xda\xed\x5c\x6c\x22\x20\xf2\xf3\xae\x91\xf3\xb4\xad\xa3\x24\xf1\x5a\xe4\xab\x5c\xea\x5b\x51\x74\xcc\xd7\x20\x90\x6c\xe8\x48\xdc\x2e\xd6\x1a\x18\xe6\x8a\x85\x6d\xc3\xad\xb8\x5d\xa4\x35\x24\x77\x8a\xfc\x81\x56\x9e\xed\xa0\x6d\x78\xd2\x86\x18\x6f\xf2\xe4\xf3\x76\xe6\x6e\xe9\xf7\xaa\x19\x44\x31\x9e\xc6\x63\x39\xc6\x7e\x4b\x53\xa6\x0b\xbb\x39\x50\x53\xce\x2e\xfb\xe3\xa7\xda\x1f\x22\x67\x8b\x28\xee\x4b\x1d\x73\xb6\x8f\xe2\xa9\x3e\x34\x3c\x8e\xe3\x24\x8e\x52\x19\xc5\x7d\x81\xfb\xb1\x0e\x3e\xea\x82\xba\x2f\xb8\x4c\xa2\xb8\xff\x1a\xb9\x7b\x16\xcc\x46\x83\x41\x3e\x11\x7d\x12\x4f\x54\x7d\xfa\xbd\x1f\x9f\xc6\x20\x89\x34\x61\x5b\xcd\xdd\x0d\x26\xb8\xb3\xa6\xae\xce\x3d\x50\xb9\xf5\x7b\x67\x4e\x43\xa3\xa4\x76\xc0\xd6\x91\xf1\x34\xbd\x80\x91\xe1\x98\x1d\xd5\xd1\x15\xfa\x7d\x13\x70\xe2\x95\x89\xab\xe0\x14\xf2\xe7\x61\x48\x77\x1a\xcd\x79\x51\xf0\x0b\x85\xb7\xab\x28\xde\x87\xb8\x8d\xfa\xee\x42\x55\x7c\x60\xb1\x0b\x4e\xad\x3a\x23\xd9\xad\x3f\x8d\x3e\xaa\x4f\x1f\x23\x2b\x67\xf6\xd7\xac\x89\xbe\x2a\x17\xdb\x86\xdf\x77\x1d\x0c\xc0\xdd\x01\x20\x8f\xe3\x8a\xd9\xe8\xfc\x71\xf2\xe3\xdb\x57\x27\x03\xe3\x1b\x9b\xcf\x2f\xbb\xbc\xc1\x4d\x18\x71\x29\x2e\xaf\x28\xd1\xb9\xb5\xa3\xb0\x5a\x2f\x66\xa9\xe6\x89\x86\xe3\xed\xf7\xf9\x86\xb2\x48\x43\xbf\x49\x8b\x7c\x16\xa9\x22\x16\x36\x5a\x96\xe9\x82\xfa\xa8\xe1\xbf\xe8\xb5\xf9\x1e\x6f\xf1\x5f\xf5\x8b\x23\x38\xb7\x61\xc0\x64\xba\x30\xc1\xbb\x0c\xa3\x24\xaf\x25\x7a\xa5\xc3\x4d\x86\x2e\xdf\xaa\x92\x0e\x7e\x3d\xe3\xbc\xa6\xb0\x7a\xa1\x29\x8b\x09\x51\x6c\xca\xe7\x91\x38\x7e\x83\x04\x4e\x9e\xa2\x38\x8d\x1e\xa9\x9c\x3e\x6c\x78\xce\xfc\x6e\x57\xcc\xaa\xd5\x19\x15\xf1\x41\x5d\x4a\x15\x30\xbe\xce\x6a\x31\x78\x78\x77\x74\xff\x6f\xf7\xff\xfb\xde\x5f\xef\xff\xed\x48\xf4\x7a\xe2\xa8\x7e\xef\xf5\xd0\xf0\x5a\x68\x87\x79\xd3\xd4\x41\x5e\x3e\x53\x3a\xa0\x22\xe5\xf5\xb5\xf8\xaf\x51\xab\x2e\x95\xc9\xf2\x86\x76\x53\x6e\xc1\xd0\x09\xb9\x71\x68\xae\x43\xa2\xeb\x7e\xf5\x25\xed\x6b\xbb\xa4\xd0\x23\x31\x65\x99\x4a\x33\x8a\x9c\xfa\xd0\x8f\x63\x5b\xab\x49\xab\xab\xd5\x8a\x89\xdb\xeb\x73\xd7\xa9\x1c\xbf\xf1\xe3\x57\x95\x32\xca\x8b\x2b\x61\xa6\x7f\x57\xa4\xc6\xac\xc8\x4b\xa9\x4d\x1b\x0e\x50\x03\x0a\xed\x3e\xed\x3d\xda\x34\x10\x2f\x54\x56\x55\x61\x3d\x70\x4d\x7c\x54\x56\x47\x50\xd0\xd1\x50\xf4\xd9\x1f\x3f\x8f\x0f\x08\x41\x1b\xc5\x47\x03\x3b\x74\x40\xe8\x70\x31\x9a\x25\xdc\x5a\x00\x31\xd8\xe0\x31\x75\x31\x97\x37\x06\x03\xa8\x99\xf4\x0d\x72\xf2\x28\x55\x30\x7d\x1d\xb0\xcc\xa4\x35\xc0\xe5\x1e\x4c\xc8\xf4\xfd\x7c\x2e\x5c\x01\x30\xc2\xff\x30\xe4\x99\x92\x4e\x16\xea\x1a\x64\x73\x85\xe6\x8f\x6f\x4d\x13\x99\x8b\xd8\xbd\x4a\x2f\xcf\xc2\x5e\xb0\xc3\xaa\xdd\x96\x69\xe8\xf8\x85\xa3\x06\x4e\x3e\xe1\x86\x90\x35\x67\x18\x56\xc6\xfa\x21\x7a\xf6\x1b\xcd\x64\xc0\x5c\xbd\x9e\xe2\x81\x03\x42\x44\xaf\x57\x45\x39\x8b\xc4\xf1\x9e\x06\x27\x95\x45\xee\x78\x93\x3c\x46\x15\x6c\x0c\xdf\xb1\xc8\xd4\x69\x2f\xe2\x88\x74\x73\x75\x14\xeb\xaa\x1f\x7f\x0c\x47\xa9\x9e\x2d\xdc\x9d\x0a\xfa\xd5\x87\x0d\xd8\xe9\xad\xe3\xe9\x03\xdf\x1d\x7a\xd8\x45\x05\x67\x0b\x2a\x22\xdd\xc9\x83\xe8\x84\xd2\x59\xa4\xeb\x88\xe2\xfe\xd4\xce\x57\x52\x87\xd6\x4e\x05\x35\xa1\xb5\xe3\xbe\xab\xa1\x1f\x47\x94\x49\x91\xd3\x52\x0f\xdc\x7d\x58\x4e\x6b\x2c\x5f\xa2\x69\x8d\x65\xea\x79\x45\x63\x52\xab\xcb\xda\xe6\xc7\xd2\xb5\x16\x39\xd7\xd7\x6e\xc8\x5d\x5f\x77\xf0\x61\x83\x0d\x6d\x61\x77\xb3\x42\x4e\x9a\xd1\x36\x52\xdd\x2d\x37\xf2\x5d\xda\xe2\xbb\xc7\x28\x55\x7c\x67\xa2\x14\xfb\x38\x52\x29\x38\x5e\x19\xe7\x6e\x2c\x95\x90\x07\xa3\x28\xf7\x3c\x68\x35\x79\x3f\x01\xcf\x15\x27\x55\x2c\x83\x82\xf8\x86\xdd\x4c\x5c\x84\x33\x71\x1b\xcc\x62\xc2\x4e\x1d\xb7\x3a\xf0\x36\xe3\x39\x99\x7b\xc6\xad\x9b\x9f\xbb\x41\x6c\xd5\xff\xa4\x9e\x58\x3a\xb0\xf6\xfd\xa4\x52\xfd\x5d\x50\x1b\x7f\x0d\x14\xee\xd4\x24\x66\x64\x72\x0a\xeb\x00\x09\x17\x7f\xda\x9c\xc6\x59\xd7\x37\xd5\xd4\xda\xde\x76\x61\x11\x22\x84\x6c\x9a\x48\xcc\x4c\x98\x93\x0d\x86\xb5\x3e\x6e\x77\x88\x3c\x43\xb3\x0e\x7d\x41\xa9\x76\x6a\xe6\xf7\x17\x61\x98\x05\x71\x3d\xd0\xcd\xd7\x6d\x23\xa4\x87\xbd\x95\x43\x06\xb1\x50\x0e\xb4\x5b\xb1\x9e\x33\xb5\x19\x5d\x0d\xd2\x81\x3f\x1f\x0a\x67\x54\xdf\xd0\x2e\x44\xba\x45\x6d\x2d\xb6\x2a\x17\xe3\x60\xfe\xad\xa7\xd4\x70\x6a\x6b\xcc\x56\xbb\x33\xc6\xc1\xb0\x63\xe2\xb1\xb3\x8d\x6e\x44\x3f\x85\x53\x4a\x28\xb1\x43\xd9\xd7\x1e\x61\xb6\xae\xf7\x61\xef\xbb\xa7\xa6\xd0\xf3\xad\xea\x77\xdd\xaa\x7e\xea\xf5\x6e\x2a\xec\x94\x58\x57\x58\xbf\xd7\xf1\x77\x6e\x2e\x5c\x8f\x95\xba\xf1\x8a\x65\xa6\xed\x8a\x65\xbd\xde\x0f\x28\x18\x32\xbe\x78\xd9\xcd\xec\x51\xcd\xcb\xc6\xcb\xc7\xbe\xdc\x0c\x84\x65\x72\x5b\xc5\xbe\x06\xb7\x8d\x40\x2f\x7b\x82\xfe\x1c\xd4\xc1\x82\x6a\xbe\x0a\x22\xff\x28\xd5\x5b\x8f\x74\x35\xc7\xbe\x47\x52\x8f\x6f\x3d\xf3\xf9\xdc\x8e\x1f\x1a\x91\x5f\xc2\x30\x65\x4d\x75\x56\xe8\x9b\x37\x1a\x71\xc1\xc2\x10\x2f\xb2\x15\xc0\xa5\x5e\xf6\x5c\x6d\xdd\xe0\x95\xe1\xe0\xb5\x57\xd3\x88\x09\x1d\x4c\x87\xa7\xe6\x58\x41\xea\x2b\x7c\xdc\x08\x15\xee\x6c\x86\x32\x45\x9a\x44\xa2\xdf\x30\x88\x8a\xbd\x62\xee\x3e\x5a\xf4\x44\x27\x98\x78\x24\x86\x80\x27\x55\x51\x24\x85\x7d\x79\xed\xd6\x55\x49\x69\x53\x1e\x9b\xb0\x20\x3a\xe4\xcb\xdc\x95\x79\x66\xd6\x91\x68\xe6\x12\x9e\x9b\x55\x22\x5a\x63\x58\xa5\xeb\x91\x89\xd7\xb2\x4a\xd7\x77\x13\x81\x2e\xf4\xd3\xbd\x84\xa2\x73\xfd\x74\x3f\x61\xe8\xad\x7e\xfa\x2e\xe1\xe8\xb3\x7e\xfa\x6b\x92\xa1\x47\xfa\xe9\x6f\x49\x85\x1e\xea\xa7\xff\x4e\xa6\xe8\xc4\x35\xf0\x13\xbd\xfc\x55\x8d\x9a\xd7\x69\x2e\xca\x64\x13\x5c\x0a\x77\x86\xcd\xc5\x71\x29\xb8\x9b\xe4\x72\xd0\x7c\x93\x5c\x42\x3e\xa3\x4c\xe6\xf2\x32\xf9\x02\x86\x24\x1a\x59\x73\x31\xa6\x7e\xd7\xd3\x56\xb2\x1c\x48\x6e\x15\x16\x9b\xae\x63\xb1\xf8\x58\x3a\x36\xf1\x95\x9e\xd0\x92\xef\x81\x7e\xaa\xd2\x42\x55\xfb\xde\xdc\x47\xfd\x4f\x4a\x7e\xa2\x83\xba\x24\xfc\x9d\x12\xe4\x53\x4c\x15\xfe\xd5\xd4\x82\xe1\x9b\x30\x8f\x82\x4b\x65\x71\x00\x63\x90\x4c\x7f\x76\x09\xb0\xe7\x19\x83\x60\x75\xe3\x40\x4d\xa9\xba\x67\xc1\xbf\xf9\xae\x45\x56\xbe\x61\x0c\x4c\x97\xf5\x37\xe4\xe8\x37\x1d\x2f\x38\xd3\x8f\x2e\xec\x7b\xa5\xdf\x44\xc5\x60\xea\x9e\x1c\x4b\x41\x6a\x5a\x54\xfd\x05\xe6\xf7\x6f\xf6\xf7\xaf\x18\x4a\xff\xf1\x3b\x9b\x78\x1f\xc3\x5c\xd7\xa1\x58\x02\x0a\xf7\x78\x17\x66\xee\x71\x04\x6b\x53\x4a\x77\x62\xd7\x6e\x7e\x5e\xa3\xe8\xb9\x13\xac\x90\x35\x97\x54\x2f\x43\x32\x68\xde\xac\xe9\xa0\x79\x17\xc3\x86\xed\x3f\xd3\x7d\x0f\x4b\x66\x4f\xf1\x61\xa5\xe1\xea\x60\x42\x58\xb0\xee\x38\x2e\x5d\xc0\xe9\x89\x41\x07\x1d\x39\x0b\x41\x0b\xfa\xc4\x4c\x46\xb8\xb3\xbf\xb4\x31\x15\x86\xcb\x00\x94\xe0\xab\x9e\xdb\x30\xbc\xeb\xfe\x6a\x27\x36\x0c\x17\xac\xf3\x38\x99\x75\x07\xd1\x9b\x1c\x7e\xb8\xf3\xe1\xc3\xff\x7e\xf3\x97\xfe\xf1\x00\xe1\xeb\xc9\x87\xd3\xab\xed\xe9\x9d\x05\xc4\x1f\x3e\x7c\xd3\x8b\xdb\xb7\x97\xb8\xe5\x18\xbd\x88\xde\xd0\xc5\xd3\xcf\x6b\x24\x07\x25\xaf\x44\x46\x21\x5e\xe4\x71\xfb\x32\xb3\x8e\xec\x10\x2f\xe2\xf6\x25\x6c\x75\x46\xab\xcb\x0f\x56\x76\xd1\xdf\xba\x6e\x0c\x28\xbe\x92\x24\x7e\x58\x14\xb1\xbf\xe2\xeb\x78\x74\x67\x98\x68\x81\xe9\x85\xbc\x0e\xee\x06\x19\x19\x42\x45\x28\x4c\x49\x10\x4f\x0e\x72\x72\x38\x1a\x67\xfd\xfe\x91\xec\xf5\x74\xf8\x37\xfa\x99\x66\xa8\xc2\xb8\xd7\xcb\xcd\xd4\xe1\xb2\x06\x77\xc2\xa4\xfe\xc2\xd6\xc3\x11\x94\xc1\xc2\x2a\xc5\xe3\xf4\xc1\xd0\xca\xed\x39\x61\x93\xf4\x74\x5c\x4e\x0e\x0f\xd3\x53\xe2\xb7\x42\xe6\xc7\x9f\x92\x17\x68\x8e\xb7\x36\xac\xdc\x95\x46\x2e\x61\x93\xe1\x29\x94\xd5\x99\x7e\xa3\x65\x12\x46\x02\x2b\x6d\x40\xa9\x84\x99\x19\x1c\xcc\x72\x5c\x1b\xeb\xe6\x21\x8c\x7e\x42\xa8\x93\xc8\x14\xf6\x45\xaa\xcb\x51\xd7\xfd\x45\x46\x45\xcb\xfa\xfd\x07\x44\xd6\x31\x6e\xea\x19\xd3\xdf\x3d\xe9\x48\x70\x0f\x78\x40\x02\x86\xc7\xcc\x93\xa0\xaa\x73\xeb\xbb\xdf\x26\x87\x87\x2c\x20\x45\xa5\x49\x51\xd5\x57\xba\x39\x62\x88\x7d\x94\xe0\x8e\x12\x75\xbd\x3b\xf0\xdc\x3d\x0d\xe8\xb3\xdd\xcf\x1f\xe6\xb4\x77\x58\xc7\xdd\x75\x83\x40\x00\x6f\xdf\x0a\x0d\xe6\x4e\x4b\xb4\xb7\x36\x4c\x08\x19\xdd\x19\xd6\x01\x06\x6b\x98\xa9\x8d\xe3\x26\x30\x6e\xf0\x24\x05\x7b\x8b\x4f\xc8\x8f\x0d\xee\x1c\xcb\xc3\xc3\x90\x2d\x39\xc6\x63\x6c\x6f\x12\xe2\x36\x08\x68\x05\x96\x29\x30\x6e\x56\xe5\xf0\x6a\xe7\xc7\x18\xf6\xb3\x47\xe6\xcd\x3c\x04\x5d\xd0\xcf\x49\x06\x4a\x1f\x7b\xce\x4a\xca\x4a\xa3\x1f\x70\xa0\x65\x96\xae\x69\xc2\xc2\x80\x68\x15\x86\x79\xce\x66\x89\x40\x53\x1d\xe9\x4d\xd1\x31\xa1\x28\x77\xb1\xe0\x04\x4a\x8d\xa9\xc7\xb9\xbe\x9b\xed\x3c\x2f\x0a\x78\xcb\x88\xb6\x14\x29\x28\x35\x97\x8d\xac\xd3\x0b\x86\xe1\xf3\xae\x80\x6e\x9e\x8e\x76\xd8\x02\x51\x7b\x0e\x6e\xe3\x74\x6f\xb7\x18\x1e\xb1\xdb\x02\xf4\x77\xd9\x14\x99\x10\xfd\xda\xea\x5b\xe9\x57\x9d\x37\x7c\x44\x5a\xf5\xc2\xf0\xb0\x73\x1e\x90\xfa\xa0\xfc\x84\x91\x0b\x66\xa3\x8c\xbd\xd1\xcf\x96\x28\xf0\x54\xbf\x29\x62\xc1\x4b\x46\xd0\x05\xab\x03\xb0\xa9\xe7\x26\xb5\x41\x17\x5c\xd0\xcf\x18\x1e\xeb\x72\x86\xf6\xf0\x89\xdd\x14\xe4\xde\x0e\x22\x19\x0e\x22\x61\xc7\x0d\x75\x63\x83\x75\x23\x67\x89\xf2\x50\xbe\xe4\x6a\xe6\x72\x57\x98\x3c\xf3\xe6\xf1\x8a\xfd\xb7\xf0\x82\x11\xd4\x30\x2c\xe8\xb0\x57\xd8\x89\xe2\xd5\x65\xf3\xc6\x74\xbc\x72\x7d\x9b\x87\xb6\x4b\xbb\xbd\xce\xe7\xbf\xb7\xce\x8e\x4e\x7a\x26\x90\xb4\x5f\x9f\xef\xd5\x07\xac\xbd\x9c\xb0\x19\x5f\x75\x75\xb7\x3b\x6f\xa6\xb2\x33\x60\xc7\x8f\x8c\xbc\x62\x48\x52\x0c\xaf\xf7\x36\xf3\x8a\x21\x6b\xbe\xd1\xb6\x7a\xf0\x21\xcc\xe1\x49\x27\xab\xa5\xe8\x07\x78\xcd\xe0\x47\xa6\x15\x8c\x5f\x3a\x18\xde\x66\x7c\xc2\xb4\xf1\x8d\x84\x17\x0c\xb9\x68\xf3\x7b\x81\xb1\x16\x69\xbe\xed\x5b\x4c\x15\x74\x89\x05\x35\x97\x69\xd2\xdf\x53\xe8\xf2\x8f\x14\x7a\x7b\x43\xa1\x0e\xe3\x16\x53\xa8\x6d\x13\x19\x5e\x23\xa9\x95\x3d\x76\x4b\x6d\xfa\x12\xc9\x77\x5f\x55\x4b\xcb\xc2\x75\xaf\xa8\x79\xc5\x6c\x34\xb2\x57\xcc\xda\xad\x76\x69\x69\xdd\xd7\x51\x37\x78\xfe\xc6\x5b\x69\x9b\xfa\x97\x59\x66\xea\xbb\xc6\xf4\x7d\x98\x8d\xab\x97\x7a\xbd\xd0\x32\x90\x21\xcb\x00\x5e\xac\xa5\xb3\xd9\xd3\x0d\x65\x52\x2d\x74\x28\xa3\x02\x09\xc8\x1a\x40\x2b\x2d\x72\xc5\x37\x74\x37\xd7\xb6\x71\x6d\x22\xfb\x7a\x43\xc6\xb3\xd0\x70\xd1\xf4\xc5\x8c\x67\xe6\x36\xe4\x05\x95\x4f\x0b\xaa\x1e\x1f\x5d\x3e\x9f\x21\x89\xc7\x14\x59\x85\x91\x1d\x07\x16\x88\x02\x31\x8c\x13\x7b\x21\x8a\xb3\x2c\x3a\xe1\xf2\x19\xaf\xd8\xcc\x8e\x54\x63\x4a\xb3\x47\xb9\x45\x9d\xa6\x45\x72\x30\xe7\x59\x55\x22\x0c\xee\x56\xd4\x9d\xbb\x7b\x6f\xab\xe0\xac\xa8\xc4\x9e\xf2\xd5\xd7\x94\x2f\x33\xc1\x8b\xe2\x1d\x5f\x6f\xdb\x8a\xf1\xef\x28\x4b\x44\x27\x00\xe9\xef\x02\x80\xb8\xe7\x1f\xa8\x8e\xc8\xd9\x55\x63\xf9\xf5\x35\xbe\xa0\x73\xb9\xc5\x7b\xec\x5d\xbe\xa6\xf0\x1e\xa4\x8a\xdf\x07\x82\xc7\xea\x7d\x3e\x93\xcb\xce\x1a\x67\x2d\xc8\x44\xc3\x60\xab\xcb\x27\x47\x2d\x0e\x69\x7d\xba\x17\x89\xb0\x0d\xb3\xfb\xf5\x6b\x5e\xe6\x67\x05\xdd\xcd\x99\x15\x39\x65\x72\x6f\xce\xf7\xb9\x5c\x3e\xe2\x62\x46\x45\x19\x14\xe2\xf3\x79\x49\xbf\xaa\xd0\x43\x36\x7b\x99\x8a\x45\xce\x4a\x73\xa6\x41\x89\x50\xa3\xec\x91\x1a\x28\x39\x5b\x3c\xd6\xad\xbf\xa1\x99\x44\xc1\xf5\x07\x3a\x04\xab\x8e\xf8\x3e\x97\xdb\x8e\xab\x7d\xff\x04\xd2\x18\xa6\xfa\x2a\xda\xec\xcf\x7a\x13\x71\xbe\xaa\xd4\x1f\xa2\xce\x19\x97\x92\xaf\x0e\xe9\x40\xf2\xb5\xa2\x8e\x71\x60\xb9\x6a\xcb\xd2\x24\x10\x73\x5b\xe8\x10\xa3\x8d\x0c\x5b\xd8\x10\x8a\x82\x03\x75\x7f\x4e\xe3\x84\xe3\xb1\x7b\x48\x96\x18\x16\x7b\x32\x5f\xe4\x6c\xc6\x2f\x8e\xcd\x8f\xca\x78\x46\xba\xb2\x09\xfa\xa9\xa2\xa5\x7c\xc8\xf2\x55\xaa\x20\x78\x26\xd2\x15\x3d\xee\x4c\x4d\x9a\x66\xe0\xd8\xb9\xce\x5d\x71\xf6\xc4\x01\x24\xd0\x06\x03\x67\xef\x4d\xab\x3a\x04\xb4\x16\xa4\x09\x07\x25\x0f\x93\x0c\x16\x54\xbe\x75\x82\x25\xa9\xa0\x0c\x5f\xa5\x5a\x5f\xf8\x0c\x3a\xb4\x73\x59\xe7\xb0\x21\xa3\xe7\x18\x24\x7f\xa4\x29\x9f\xa4\x20\xb9\x09\xfb\x5c\xc0\x92\xda\x20\xd2\x6b\x0c\x17\x6a\x3c\xe8\x9d\x4c\xb3\x95\xf7\x2b\x23\xe8\x17\xa6\x45\x32\xfc\xc2\x8c\x6c\xc7\xf0\x9e\x91\x5f\xd8\xc0\x41\x0b\x3f\x98\x4c\x35\x36\x9d\x73\x36\xdb\xb9\x01\x5a\xd2\xcf\x32\x06\xf5\xbf\x61\xf5\xc2\x1b\x46\x9d\x9d\x9a\x45\x86\x9c\xcb\x46\xc7\x5d\xa5\xf5\x9a\x7c\x89\x04\x56\xab\xf0\x01\x4b\x57\xb4\x5c\xab\x75\x46\x46\xd8\x60\x9e\x9a\xeb\xc2\x27\xa7\x30\x25\x43\xb7\xb9\x4c\xc3\xcd\xe5\x5c\xdb\xa7\x8f\xa7\x7d\x92\x0f\x66\xb4\xcc\x28\x9b\xa5\x4c\x96\x8f\x79\xc5\xe4\xf5\xf5\x10\x2a\xb3\x7a\xcc\x31\x50\xbd\xf3\xec\xef\xb7\xed\x93\xca\x1d\x2d\x37\xee\xb9\x36\xc6\x87\xba\x65\xb5\x7a\x5c\xe6\xc5\x4c\x50\x96\x54\xe0\x41\x4b\x38\xb4\x5b\x4a\xa6\xdb\x9d\x8b\xf8\xff\x7c\xfc\xa6\xa3\x7f\x15\xc5\x73\x7a\x49\x67\x87\x7f\x16\xa2\xd3\x56\x5c\x63\xd3\x46\x56\x95\x92\xaf\x62\x5b\xf3\x12\x49\x6c\xf1\x5c\xf1\x19\x2d\xd4\x42\x6e\xb5\x2e\x12\xba\xdd\x73\xdf\x8c\x63\x39\x6d\x0b\x1f\x5c\x24\xae\x80\x4e\xc4\x2e\x40\xa3\x3e\x12\x5d\x64\xc1\x6d\x7b\xd3\x1d\x40\xe5\xb2\x62\xe7\xde\x38\x32\x15\x0b\xb5\xca\xd4\x89\x6a\x95\xa9\x9a\xb3\xd7\xd8\xef\xbb\x82\x7e\x6e\x4c\x14\xc3\x41\xe4\x47\x83\xd8\xbd\x62\x3e\xbc\xbd\xd7\x99\x2e\x76\x94\x75\xde\x48\x3b\x73\x51\x43\x6b\x9e\xd7\x66\x8d\x1d\x75\xd4\x57\xbb\x6d\xdb\xf7\xc3\xfb\xe3\x1a\xa0\xfb\x0e\x6c\x98\x3e\xb0\xd1\xfc\x7a\x4e\x2f\xc7\xf9\x1c\x71\x42\xc8\x4c\x5e\x5f\xab\xdf\xb5\xfd\x2d\xfc\x65\xec\x74\xc2\x4f\xf5\x0d\x50\xd9\x44\x2d\xf7\xd3\xe2\x27\x7a\x79\x4a\x98\x33\x0b\x99\xf0\x53\x92\x99\x00\x30\xb6\xaa\x79\x00\x47\xe5\x8b\xc3\xd4\x95\x71\x50\x4d\x9b\x23\x61\xaa\x46\x42\x35\xc9\xf5\x31\x52\xae\xed\xf8\x55\xda\x68\xab\x9b\xa8\x7c\x13\xb1\xe7\x60\xed\xb5\x8a\x85\xaf\xd7\xe7\xc8\x8a\xb4\x2c\x4f\xd2\x95\xcd\x71\x65\x76\x45\x55\x3d\x63\x5d\x99\xdf\xe2\x4b\x8f\x6d\xd9\x24\xed\xc7\x51\xdc\xb7\x6f\xa6\x2d\x9d\xd5\xd5\xdd\x38\xd2\xba\x32\xdc\x4f\x83\xc1\xb4\xcf\xfe\xf7\x9c\x5e\x26\x73\xd9\x61\x78\xd9\xb4\xf1\x55\xd9\xba\xec\x2c\xcf\x76\x72\xcd\x24\xd8\x4e\xe8\x2c\x70\xd9\x1a\x0c\xaa\xc8\xba\x2e\x22\x6c\x91\x2b\xf3\x13\x62\x20\xb7\xbb\x97\xc7\x37\xaa\x29\x76\x5b\xbe\xe2\x6b\x95\xbd\xd4\x43\xd7\x18\x0f\xd3\xb0\x9a\xc6\xfd\x40\x48\x0e\x6c\x76\xbd\xaa\xb3\xcf\xd7\xd7\x3e\x79\x50\x4a\xbe\x7e\x2d\xf8\x3a\x5d\xe8\x59\x3b\xcc\xd6\xfe\xd6\xeb\xd5\xc5\xd6\x82\x2a\x6d\xe4\x89\xf1\xb8\x6c\x94\x6a\x7e\xc2\xbd\xde\x4f\x74\xe0\xce\xc9\x3a\x4f\x78\x5b\xc6\xc6\xf5\x22\x5a\x0d\x96\x03\x35\x2e\x8e\x45\xf2\x0e\x09\x37\x12\xc0\x9e\xb4\xbb\x16\x21\x47\x33\xa6\x37\x28\x4c\xb2\xab\x77\xf7\xee\xf8\xda\x7a\xe0\x72\x4d\xad\x8e\x69\x84\x56\x7d\x38\xad\xe4\xd4\xf5\x35\x32\x0f\x44\x0e\xf4\x77\xa5\x10\xbc\xb5\x69\xde\xf0\xc2\x4a\xd4\x86\x0d\xa7\xce\xa0\x86\xbb\xf9\x38\x76\x99\x8c\xdd\xe0\xe5\x9a\x8e\xf1\x8e\x2d\x0d\x3b\x66\x64\xc2\xbc\xc7\xd5\x69\xc2\xcc\xfc\xe3\x12\xcc\x34\xa4\x6a\xb6\x9e\x6c\xd6\xaf\x29\x61\xb0\x4e\x85\x56\xa1\x9c\x5e\x85\xa6\xe4\x2d\xa2\xc0\x31\x1e\xd0\x62\x35\xd5\x1d\x31\x55\x25\xa7\x82\xce\x09\x87\xa9\x85\x5c\xa9\x1f\x0e\xe5\xa5\x1c\x64\x82\xa6\x92\xbe\xa3\x9f\xe5\x09\x9f\x51\x45\x1f\xfa\x59\x3a\x33\x3b\x35\xb7\x25\x9f\xd1\x54\x61\xe7\x38\xf7\xd8\x17\xb2\x2b\xee\x13\x4d\x1d\x3f\x17\x1b\xfb\x8c\xa4\x9d\xcb\xda\x6d\x80\x00\x69\xa6\xb0\x7a\xff\x3b\x53\x12\xd3\x4e\x99\x50\x91\xe1\xb8\x3a\xca\xdc\xa9\x7d\xd5\xef\xe3\xa9\xbd\x4a\xe1\xb1\xca\x83\xde\xa2\x6c\x52\x69\xb3\x1b\xa7\x59\x4f\xbd\xd9\x92\x9b\x8f\xff\x33\x61\x36\x1e\xa5\x6d\xb0\xed\x14\x5f\x1b\x8e\xad\xd6\xc5\x40\x50\x36\xa3\x02\xc9\x81\x9e\xe7\x7d\x91\xcf\x68\x1a\x00\x03\xa1\xfe\xf0\x79\x47\x51\x8a\x72\x16\xd5\xb1\x08\x26\xec\xd4\x59\xd0\x30\xc3\xfe\xd1\x5c\x26\x8f\x90\x04\x8e\x03\xe3\xe4\xa8\x90\x89\xb1\x9f\x6f\x26\xcf\x64\xf2\x66\x27\xef\x5a\x26\x4f\xdb\x89\xce\x6e\x46\x4e\xd8\xe9\x01\x21\xbc\xd7\xd3\x66\x14\xc4\x67\xf2\xf1\xbe\x75\x6a\x28\xbe\x1e\x35\xed\x36\x4a\x79\x59\xd0\x71\x03\x1d\x61\x8c\xa1\xc5\x84\x9d\xee\x98\xfb\xd7\xd3\xad\x62\xff\x65\xca\x66\x05\x15\xa5\x9e\x4a\xbd\x05\x64\x40\x92\x8c\xb0\x09\x3f\x05\x33\x63\xaa\x69\xb9\x3e\x88\xc2\xdd\x9b\x57\x1c\x32\x0c\xac\x9e\xd0\xfc\x04\xe8\x4b\x66\xf8\x2a\x23\x27\x48\x40\x85\xc7\x1d\x7b\x64\x75\x05\x76\x06\xcf\x06\x39\x9b\x73\x52\x6d\x9b\x30\x13\xd6\xf2\x49\x68\xec\x01\xfa\x4b\x08\xa8\x2e\xad\x77\x23\xed\xc1\x3c\x0b\x0c\xc8\xb4\x69\x97\xbb\x2e\x3b\x0c\x35\xc1\x9c\xec\x1c\x67\xbb\x52\x5e\xb4\x93\x10\xd6\x6e\x7b\xa1\x58\x57\xb9\x9a\x29\xa8\x1e\x17\xc6\x19\x1c\xa6\x44\x8e\xa7\x63\xa7\x0a\x4c\x9d\x48\x54\x30\x39\x54\x6a\x43\xcd\x14\x57\x24\x45\x15\x36\x04\x75\x35\x95\x24\x75\x03\xaa\x3c\x3c\x1c\xab\x3c\x93\xf2\x54\x65\x53\x8a\x8a\x91\x7e\xdb\xad\x3f\x2d\x34\xa4\x14\x40\x1b\x3e\x19\x8d\x8b\xce\xac\xad\xa1\x75\x1c\x9e\xd0\xd3\xb1\xef\x39\x76\xec\xfa\xfc\xa1\x94\x22\x3f\xab\xcc\x1d\x9b\x72\x50\x52\x19\xa4\x28\x1d\x70\xc7\x99\x63\x7f\xfd\x1d\xab\x14\xa3\xde\xd4\x1c\xb3\xdb\xee\xc9\x5b\xc4\x61\xa7\x6d\x93\xaa\xb7\x4f\xdb\xfe\x1a\x66\xbc\x4c\xfc\xfd\x9a\x9f\xac\xbe\x3a\xc4\x21\x31\x1e\xb7\x54\x0c\x73\x02\x24\x9c\xcf\xc9\x2c\x95\x69\x42\x61\xc6\x57\x27\xb5\xb2\x0e\xba\x93\x4f\x3a\xb5\xf7\x4f\xb5\x16\x9d\xcf\x91\x3c\x20\xc4\x87\x33\x32\x73\x2c\x64\x44\x98\x69\xcf\x2a\xaa\x99\xf3\xe1\xc8\x9a\xd3\x6f\xcd\x3a\x72\xa0\x16\x0e\xfa\xd8\x53\x3f\xe4\xf5\x9a\x2b\x25\x3b\xa6\x67\x39\x51\x4a\xad\x65\x91\xb4\xd7\xcb\x15\x97\xa4\xa4\x9a\xe4\xa7\xea\xcb\x24\xd7\xc3\x3a\xf5\x36\x8d\x3c\x9f\x21\xe1\xa6\x76\xf5\x83\xc7\xf6\x55\xb8\x99\xde\x5a\x95\x36\x68\x69\x27\x7e\xf3\x53\x2a\xaa\xea\x9a\xdc\x09\xf3\x83\x61\xaf\x47\xcd\xa4\xfd\x18\xc5\xeb\x43\xbb\x10\x62\x50\x62\xbc\x47\x59\x98\x7b\x1d\x01\x0a\x63\xe4\xa8\x1e\x67\xe4\x60\xa4\x8d\x37\xf5\x6c\x1f\x28\x0f\x6b\xab\x3c\xcc\xc8\xc1\x10\x76\x34\x88\xf9\xf1\x9c\x4c\xe6\xb0\xf6\x1a\xc4\xdc\x00\xb3\xf6\x1a\xc4\x9a\xac\x4d\x9d\xae\xfd\x25\x11\x3b\x8d\x2c\x6f\x6c\xa4\x38\x2e\xc8\xa4\x80\xa5\x6f\xa4\x30\x8d\x2c\x7d\x23\x4b\xb2\x34\x75\x5a\xc2\xcd\x7a\xbd\xb9\xa5\x90\x52\xe3\x9c\xa5\xb3\x66\xa3\x90\x5c\x82\xce\x44\x7a\xa1\xe8\x25\x30\x4e\x10\x9a\x1d\x3f\x43\x73\x28\x70\x32\x57\xab\x22\x7c\x7d\xdd\xa0\xad\x5d\xc7\x32\x28\xb0\xe9\x86\xe8\x13\x5a\xc3\x52\xb1\x61\x7f\xe4\xc9\xad\x35\x1c\x63\x47\x4a\x3f\x4b\x63\x48\xaa\x94\x9a\x80\x11\x1a\x30\x98\x1d\x19\x06\x36\x9b\x9b\x6d\x43\x1d\xc8\xab\x88\x81\x65\xaa\x52\xa5\xfd\xe0\xd6\x89\xb5\xbe\x71\x1b\x9e\x66\x38\x19\xc3\xdf\x17\xc8\x4e\xe8\x20\xec\xc4\x8e\x9b\x2c\xa5\x13\x55\xd1\x8d\xc3\xfa\xb9\x1f\x7c\x78\x57\xf7\xf9\x0f\x83\xf5\x55\x1b\x56\xa7\xf0\xe8\x1e\x52\xda\x8e\x86\x47\x3d\xec\xed\xa1\x06\x44\x63\x63\xc4\xbc\x0b\xca\xd8\x43\xba\xd9\x0f\xd4\xd8\x84\xfe\x32\x0d\x0e\x66\xf9\xdc\x9c\x27\x28\x51\xb1\xda\xdb\xbe\xdb\x86\x61\xb0\xf2\xec\x61\x57\xad\xfb\xa0\xdc\xde\x70\x79\xe7\x70\x4c\x8f\xbc\x5d\x2a\x35\xe6\xa6\x72\x42\x95\xbe\xa4\x6f\xdc\xbc\xc1\xd8\xf4\x45\x43\xd9\x69\x6a\x36\x52\xd5\xc3\x0f\x08\x99\xcb\x5e\x8f\xeb\xd5\x93\xf9\x9d\xd9\xdf\xb5\xc9\x11\xcc\x53\x19\x91\x46\x0b\x12\x4a\x0b\x52\xd2\xb5\xea\xf5\xac\x0a\xa7\xb4\xb7\xeb\x6b\x4a\x4c\x3d\x17\x28\x83\x0a\x5f\x5f\x23\x64\xaf\xa8\xc6\x7a\x9f\x00\x6b\x32\x34\xd2\xfc\xe4\x46\x8f\x77\x1c\x7e\x54\x6b\xc7\x71\xac\xad\x2f\x13\xaa\x77\x2f\xd4\xab\x69\xc4\x34\x36\x93\x86\x23\x87\xc9\x55\xb0\x5a\x9e\xf0\xd3\x60\x26\x35\xcb\x61\x3b\x27\x69\xb5\xe1\xca\xa8\xcf\x2f\x90\xc6\x47\xb8\x5d\x10\x8e\xc7\xd3\x5e\xaf\x09\xf3\x14\x6f\x1d\xd9\x72\x43\x0a\xfd\x23\x1b\xb8\xe5\x4a\xcb\xcc\xbd\xc3\x5d\xc4\x5a\xf7\xa7\x86\xf6\x08\xc1\x4a\x40\xcd\x79\xc1\xb2\x80\xbb\xe9\x6b\x4a\xea\xd5\xc1\x83\xe9\x71\x93\x6b\xd4\xf4\x7f\x58\xa4\xa5\x16\x42\xd5\xe1\x14\xe3\xa4\x3a\x9a\x36\x59\xd8\xac\x26\x54\x86\xac\xb6\xdd\xa9\xd5\xae\x9c\x30\x48\x49\x75\x34\x3d\xae\x92\x29\x94\x64\x38\x2e\x8f\xd2\x71\xa9\x7d\x16\xfa\xfd\xb1\x99\x75\xf8\xa4\x3c\x1d\x7f\x42\x73\xc8\x26\xe5\x29\x50\xc8\x31\xe4\x7d\x32\xef\xda\xf0\xdb\xb6\x6e\x78\xb5\x86\x61\xde\x93\x48\x9b\xd0\x5d\x6d\xdd\x76\x6b\x40\x81\x3c\xa4\x40\xea\x27\x68\x28\x49\xee\x1e\xe7\x64\x08\x05\x19\xc2\x8c\xb0\xf1\xfc\x28\xed\xf5\x8a\xa3\xd2\xea\x8a\x6b\x32\x9d\xcc\x4f\x61\x49\xf2\x49\x71\x6a\x22\xfd\xd9\xb0\x5e\x43\x58\x68\x47\x04\x38\x33\x41\xbe\x94\xde\x7d\x40\xc8\xca\x94\xbb\x24\xf3\xfe\xe8\x28\x85\x77\xa4\xe8\x8f\x8e\x4a\xf5\xf5\x12\xab\x0f\x17\xaa\xc2\xfe\xe8\x14\xce\xc9\x85\xaa\xe4\xad\xfa\x19\xc1\x67\xb2\x22\x84\x9c\xab\x7c\xef\x74\xbe\x47\xaa\x45\x95\xef\x21\x79\xa4\xf2\x9d\xa8\x9f\x11\xbc\x21\x1b\x42\xc8\x43\x5d\x5f\xaf\xf7\xae\xd7\x7b\xd3\xeb\x7d\xc6\x9f\xd0\x02\x4e\x80\x43\xbf\x3f\xc3\xf0\x23\xca\x80\xc3\x06\xce\xa0\x80\x0a\xc3\xac\x4f\x16\x9d\x3b\xcb\xaf\x6d\xbe\xb7\xa6\xd8\xac\x4f\xde\x76\xe6\x9b\xf7\xc9\x5d\x28\xfa\xe4\xae\x5f\x5f\xa8\x66\xf1\xac\xdf\xb7\x4d\xad\x5c\x53\x0e\x8c\xd9\x0d\xad\xce\xfb\x64\xd4\xac\xed\x52\x61\xe0\x80\x59\x78\x60\xba\x8b\x7f\x42\x6f\xe1\xcc\x61\x7a\x2b\xc8\xa3\xb1\x0b\x8c\x7c\x70\x79\x7d\x7d\xf0\xee\xfa\xfa\xfc\x80\x90\x87\x26\x42\xef\xb8\xd5\x66\x0b\x99\x1b\x41\x38\xf9\x6a\x10\xee\xda\xe8\xd8\x8a\x36\x21\xe0\xfb\xa8\xd3\x87\xa2\xdf\xd7\xf2\x40\xb1\xe2\x18\x5f\xcd\xfa\xfd\xf1\x82\x20\xc3\x88\x58\x71\x9a\x81\x5b\x73\xe2\xe2\x16\x5a\xf7\xbd\x64\x79\x3a\xd6\x4c\xfd\x94\x3c\xbd\xbe\x9e\x9c\x5a\x64\x91\xe1\x6b\xac\x43\x97\xe8\xc0\x25\x46\xcd\x7e\x8a\x15\x14\x63\xc4\xbd\x4e\x79\x7d\x5d\x05\xcf\x7e\x5e\x7b\xda\x9a\x6d\x05\xd5\xc7\x91\x4a\x2c\x5c\xad\xad\x71\x17\x87\x5c\x07\x48\x2b\x93\x0a\x28\x9b\x3d\xb7\x2f\x4f\xb7\xe1\xa6\xd8\x8f\x4d\x37\x7c\xab\x7e\xab\x25\x51\x73\x25\x6c\xa5\x5f\x45\x9c\x3b\xb8\x0e\xbd\x06\x1b\xbd\xa3\xcf\xac\x19\x19\x37\xab\x07\x2b\x8e\xc1\xda\x18\x5e\xb9\x8f\x94\x49\x71\x99\x54\x5b\xab\x38\xab\x56\x48\x65\xd6\xa7\x46\xf6\x99\x08\xa4\xc6\xab\x67\x6f\x59\x9d\x81\xc4\x3a\xff\xd8\x08\xfb\x50\x4d\xaf\x06\x1b\xb3\xff\x06\x53\xa8\xac\x0d\xa4\x7b\x20\xdc\xb4\x5c\x0d\x14\x9c\xfa\x1f\xf1\xe4\x9a\xd6\x6d\x6c\x2d\x55\xfa\x1b\x69\x09\xd3\xba\xc0\xba\x19\x9f\x76\x87\x5c\x19\xbe\x9a\x92\x40\xa6\xc7\xc0\x6d\x0f\xd7\x97\xe1\x1b\xfc\xa6\x21\x2d\x0c\x69\x5d\x91\x4e\xd2\x4e\xb7\x26\xb0\xa9\xa5\xff\x01\x21\x99\xa6\xd7\xeb\x06\xc0\x66\x01\x7d\x95\xb5\x29\xa5\x84\xf4\xf8\x13\x52\x53\x87\x21\x52\xa5\xf2\x1a\x1a\xb6\xc0\xf5\x64\xa9\x2c\x59\xb2\xad\x5a\x25\x59\xa0\xb7\x2d\xd7\x6c\x33\x2b\xfc\xe2\xd6\x9b\x30\x84\xdd\xd3\x23\xb5\x64\x6e\x3a\x58\x87\xd1\x1c\xdc\x70\x99\xea\x0d\x2a\xc8\xc9\xd4\x3a\x4e\xaa\xc5\x1d\x0f\x37\x10\xec\x42\xd2\xaf\xb0\x08\x21\x29\xd6\x50\x98\x95\xd9\x54\xf7\x2b\xb8\x5d\x04\x93\xd5\x8d\x0f\x9d\x79\x3a\xb0\xab\x5b\x22\x61\x3a\xf0\x4b\x5b\x52\x01\x9a\x13\x53\x7c\x60\xd1\xc7\xc1\xe2\xce\xc0\x3c\x87\xa1\x85\xb9\x59\xbf\xe3\xdf\x14\x5f\xed\xad\xdf\xae\x2a\x4d\x13\x35\xc7\x1c\x10\x52\xe2\xab\x72\xa0\x09\x6d\xb8\x52\xda\x99\xba\x74\x80\x8c\xe7\x37\x40\x62\x45\xdd\xfe\x76\xf3\x39\x62\xfd\x3e\x1c\x20\x43\x5e\xa5\xbd\x79\x0a\xe3\x07\x19\xf6\xba\x8d\x0f\x4f\x1f\x6e\x8e\xb7\x56\xad\x45\xc7\xaa\xb1\xb0\xab\xc6\x82\x14\x8d\xd5\x9f\x82\xb4\x30\xfd\xdc\x1f\x41\x06\xb2\x63\x4b\xba\xb1\xc7\x5c\x7b\x30\x06\xda\xc3\xda\xe9\x15\x0a\x9d\x12\x96\x64\x38\x5e\x1e\xcd\x9c\x1e\xb5\x54\xca\xcd\x8a\xf4\xfb\xbc\x8f\xd0\x86\xcc\x26\xcb\x53\xdc\x79\x76\xa9\xf7\x1f\x8e\x48\xde\xeb\xe5\x47\x64\xa5\x4d\xa8\x7f\x41\xeb\xc9\xf2\x14\x36\x96\x15\x57\x6a\x02\xda\x4b\x25\x4f\xa6\x31\x27\xab\xad\x7f\xd9\x59\x77\xfd\x51\x1c\xb8\x55\xd0\x0c\x0e\x6a\x5a\x58\x11\xde\x47\x9b\x7f\x3b\x32\x66\xe1\x1c\x6e\xcd\xc8\xa5\xe0\x17\xda\x45\xe3\xa9\x10\x5c\xa0\xb8\x5c\x9a\x6b\xcd\xe9\x86\x8a\x48\x8a\x54\xdf\x8c\x1c\x7d\x54\x25\x3f\x46\x5c\x44\x1f\x75\xc1\x8f\x36\x12\x70\x91\x9f\x53\x1d\x0b\x38\x0e\x45\xc7\xaf\x3b\xe7\xaf\x7a\xb1\xe0\xb6\x08\x64\x82\x6a\xe1\x02\xef\xb5\x05\x04\xde\x71\x1c\x6d\x2e\xa6\x44\xb8\x98\x6a\x6f\xc0\xd9\xd1\x01\x19\xf9\x01\x71\x60\x78\xcc\x09\x21\xb2\xd7\x43\x92\x64\xb5\x49\xe3\x8e\xfb\x60\xd7\x98\xf0\x6b\x3c\x7f\x05\xa2\x16\x40\x5a\xf2\x88\x7a\xe8\x59\xd6\x76\x0b\xcf\xc4\xef\xde\xcb\x30\x97\x2d\x88\x41\xba\xec\x8d\xb3\x19\xef\x87\xf3\x24\x95\x29\x1a\x82\x5b\x30\x76\x14\x6b\x1c\x63\xbd\xf7\x20\x79\x30\xdc\x50\x0e\x97\xb7\x43\x7d\x50\xbd\x3b\x2c\x8f\xbb\x12\xed\x36\x0f\x31\xf5\x26\x5d\x59\xfc\xc9\x94\x25\x87\x3b\x9e\xaa\xf1\xdd\xd6\x10\x87\x6b\x1e\x3d\x6e\x98\xad\xda\x84\x21\x70\x7b\xa2\xe6\xf0\x44\x6a\x07\x05\xfd\x5c\x87\xb7\x77\x35\xd9\x75\x51\x70\x10\x67\xdb\xef\x08\xa4\x22\x5b\x67\x32\x7a\xca\x09\xbb\x6d\xb7\x7a\x2b\xe0\x13\x17\x3f\xa1\x29\xc1\xcd\x81\xb8\xeb\x2e\x83\xb1\xaa\xa8\x09\xbe\xea\x29\x1b\x4c\xd0\xc8\xfa\x71\xbb\x1f\x32\xe7\x8b\x7b\x53\x25\x99\x99\x22\x54\xf7\x72\x3f\x4f\x85\x24\x35\x53\x9d\xbf\xf4\xd2\x6c\x6b\xd8\xaf\xe1\x21\x53\xe5\xf0\x70\xca\x9d\x22\x4b\x71\xf9\xda\xb8\x55\x41\x65\x79\xc7\x9f\xd3\xb4\x65\xc0\x1b\x1f\x19\x86\x45\x15\x3b\x67\xfc\x82\x45\x1a\x9e\x83\xc6\x30\xff\xad\x7d\x2c\x53\xa3\x06\x9c\xbc\xd5\x26\xd5\x4d\x4a\xe8\xa3\x8a\x5d\xce\xea\xf5\x50\x57\x72\x27\xf7\x62\x60\x66\xab\x43\xf6\x7a\xde\xcd\xc2\x90\x90\x83\xc4\xc0\x1b\x6e\xb8\x81\x5d\xb9\x63\x9a\xef\x11\x1d\xd4\x5a\xb3\xa2\xa0\xd4\x24\xa7\x9e\xe4\x41\x3c\x0d\x3a\xb0\xaa\x36\x64\x64\x38\xce\x8e\x9c\xfe\x3e\xce\x9c\x18\xaa\x08\x9f\x64\xa7\xfa\x5e\x6e\xdd\xf5\x90\x5b\xc5\x4c\xef\x5d\xcb\x74\x71\x6c\xb4\x82\xe4\x2d\x9a\x5a\xe5\xac\x21\x47\xa4\x6d\xe1\x11\x9d\x73\x41\x51\x0e\xe1\x6c\x32\xb1\xfa\xed\xa9\x97\x62\x9e\xa3\xf4\x81\x7d\xc8\xed\x0c\x43\xd3\xd7\xd8\x7a\xdf\xd7\xb2\x20\x94\xa9\xfe\x20\xd4\xd9\xb6\x3d\x13\xe9\x42\x9f\x88\x62\x3b\xb0\x64\x23\x2e\x82\xdd\x07\x99\xb0\x53\xcb\xe1\xb4\xd1\xb8\x47\x99\x6b\x94\xb9\x43\x99\x77\xa0\x5c\xfb\x7f\x05\xbc\xf4\xf3\xed\xc6\x71\x3e\xb1\xeb\x7a\x4e\xa3\x6c\x1a\x45\x53\x28\x45\x18\x8f\x03\xbf\xb3\x6f\x10\xd5\x1a\xd5\x14\x27\x54\xa2\x5c\x8d\x01\xa0\xd8\x26\x6d\x1b\x76\xac\xff\x40\x9e\x65\x7c\xe8\x09\x67\x0a\x0c\x4f\x65\x10\x17\x76\x25\xe1\x15\x85\x2b\x1d\x63\x91\xc2\x26\xa7\x17\xc9\xae\x69\x91\xd8\x42\xb5\x9e\xa5\x92\x26\x12\xed\x7e\xa5\x5b\x0c\x65\x75\x56\x66\x22\xb7\x76\x1f\xbb\x79\x9e\xc9\xed\x16\xa3\x00\xc2\x9f\x9a\x56\x55\x2d\x07\x9a\x50\x74\xd1\xfa\xfa\xe8\xbf\xa3\xf8\xdd\x92\x46\x1f\xe3\xbe\xe8\xc7\x1f\xa3\x15\x9f\x55\x05\x8d\x66\x9c\x96\x11\xe3\x32\x62\x94\xce\xa2\x79\x91\x2e\xca\xc1\x07\xf6\x9c\xe5\x32\x4f\x8b\xfc\x0b\x8d\x72\x1b\x19\x85\xf1\xc8\x3b\xde\xe9\x2b\xc6\x2f\x79\x15\x59\x55\xe1\x8c\x46\x69\x51\x44\x25\x95\x07\x71\xf3\xf8\xec\x9f\xdd\x90\xba\x35\x96\x8f\x16\xd5\xeb\xfd\x1d\x55\x24\x7e\x28\xa8\xae\x57\x8a\xcb\x9c\xe9\xeb\xc2\x4b\x46\xd3\xf3\x28\x8d\x4e\xb4\x36\xa2\xf7\x04\x8d\x60\x7a\x5a\xac\x8e\xa3\x77\x22\xcf\xce\x4b\x49\xc5\xc1\x07\xf6\x5c\x46\x05\xe7\xe7\x56\x23\xd1\x58\x0e\x56\x69\xce\xa2\xbc\x8c\xac\x8d\xab\xc1\xe4\xe3\x5a\xf0\x85\x48\x57\xef\x73\xb9\x7c\xa6\x10\xfe\xa8\x03\xaf\x2c\xd3\x32\x52\x6a\x40\xf4\xf1\xb5\xf9\x6e\xda\xfc\x38\xf8\xc0\x7e\x51\xfa\x8f\x2d\xf5\xd1\x47\x14\xcb\xe7\x1a\xd6\x19\xd7\xf4\xbb\x48\x99\xb4\xf4\x8b\xdd\xd2\x2b\xab\x8f\x6d\xd5\x1a\x29\x38\xae\xcd\x1a\x61\x8c\x29\xca\x06\xd3\x21\xb6\x0b\xb9\xf8\x9d\xc7\x3e\xaf\xfb\x41\xee\xf6\x9d\x89\x58\xa3\x04\xb4\xbf\x23\x5e\x01\xa0\xfa\x2f\x92\x22\xa7\x33\x55\x45\xc6\xd9\x86\x0a\xa9\xfa\xd1\x88\xf3\xa7\xc5\xca\xd0\x11\x34\xda\x41\x8c\xb1\xbc\x74\xa1\xc5\x6c\x00\x31\x05\xd5\xf8\xef\x48\x2d\x25\x83\x3e\xfd\xbb\xe9\x53\x33\x67\x88\x5e\x0f\x89\x41\xce\x18\x15\x3f\xbc\x7b\xf9\x82\x7c\x7b\x34\xcb\x37\x91\x3e\xd6\x27\xf1\x3a\x9d\xcd\x72\xb6\x38\x2c\xe8\x5c\x26\x23\xba\x1a\xc7\x0f\x8e\x96\x77\xdd\xd7\x39\x67\xf2\xf0\xc2\x98\xe8\x32\x2e\x56\x69\xa1\xbe\x9f\x3d\x78\xc5\xd7\xe5\xc1\xd1\x9d\xb3\x07\xd1\x5b\xbe\xa2\x3a\x28\x71\x74\x41\x99\x8c\x2e\x04\x57\x8f\x4b\xca\xa2\x52\xa6\x42\xc7\x80\xbb\xe4\x95\xd0\x28\xd9\xee\x19\x1c\xdd\x59\xde\x7d\x70\xb4\x16\xf4\x06\x20\xbe\xed\xcb\x7e\x7c\x74\x67\x2d\xe8\x83\xa3\x3b\xb3\x7c\xf3\x20\xc6\x50\x4f\x7e\xa1\xd7\xf1\x37\x81\x1e\x3b\xa0\xab\x33\x3a\x23\x4d\x7f\x21\xbd\xab\x24\x6a\xed\x65\x8c\x45\x63\x52\x17\x1d\x8a\xcd\x89\x92\xf8\xae\x63\x11\x43\xe6\x15\x28\x08\x0c\x72\x60\x84\x05\xc8\x41\x43\x2c\x80\x94\x48\x80\x1c\x28\x21\x83\xf1\x16\xc4\x60\x5e\x15\x45\x99\x09\x4a\x59\x57\xcc\xeb\x3d\x6d\x08\xf0\xee\x34\x67\x7c\x76\x79\x73\x7b\x8d\xac\x75\xdb\x35\x75\xa4\xdc\x3b\xbc\xdd\x7c\xe1\x34\x46\xea\x94\x45\xbf\x83\xa4\x84\x34\x86\x8a\xbc\x45\x59\x70\x35\x51\x73\x46\xab\x30\x08\x89\x2a\x10\x90\x35\x79\x50\xc8\x4e\x57\x66\xaf\xd1\x57\x56\x99\x3f\x79\x35\x7d\xf3\xf4\xe7\x5f\x9e\xbe\x7d\xd7\xb1\xd0\xf9\xa5\x1e\x37\x4a\xe1\x8f\x5c\xa8\x92\xc1\x07\xf6\xba\xa0\x69\x49\x23\x41\xd7\x5c\xd8\xab\x4e\x24\x8f\x8e\x96\x52\xae\xcb\xe4\xce\x9d\x45\x2e\x97\xd5\xd9\x20\xe3\xab\x3b\x3e\xde\xee\x26\x17\xb2\x4a\x8b\xc3\x19\x5f\xdd\xc9\xcb\xb2\xa2\xe5\x83\x81\x8b\xbb\xf7\xfa\xe9\xc9\x93\xe7\x27\xdf\xd7\xb0\x9c\x49\xc4\x15\xf2\xf1\xd3\xbf\xbf\x7b\xf3\xd0\xa7\x8f\xad\xa6\x82\x32\x0c\x39\x79\x89\xa6\x81\xfe\x24\x75\xb4\xba\x29\xe4\x6a\xc9\xa4\x77\x96\xa6\xc4\xad\x42\x9a\xb5\x84\x6b\x00\x25\x55\x03\x22\xd8\xbb\x41\x32\x68\x26\xc3\xb4\x76\xa0\x0b\x4d\xfa\xc3\x3c\xe6\xdc\xc8\x03\xde\x46\x09\x32\x12\xda\x62\x52\x19\x8e\x9c\x3d\xbc\x6a\x59\x64\xc6\x33\x7f\xce\xf3\x07\xd9\xf7\xff\xcf\xde\xbf\xa8\xb7\x6d\x2b\x0b\xc3\xf0\xad\x28\x7c\xd3\x6c\xb0\x1e\x29\x92\x9d\xa6\x2d\xb3\xb8\xbc\x1d\xdb\x49\x9c\xd8\x8e\x13\x3b\xc7\xb6\x5b\x3f\x45\x42\x16\x63\x8a\x90\x41\xd0\x87\xd8\xdc\xb7\xf1\x5f\xd0\x77\x63\xdf\x83\x13\x8f\x20\x25\x27\x5d\xdd\xab\xdf\xbb\xd7\xea\x13\x53\x38\x63\x30\x18\x0c\x06\x73\x40\x31\x1f\x97\xdd\xc0\x62\xc2\x10\xae\xd6\x01\xa2\x30\x59\xfd\xd9\x8b\xd5\xc7\xeb\x94\xc9\x8d\xd5\xd8\xe6\xb9\x34\xf0\x0e\x23\x25\xe5\xcd\xcc\x47\xe7\xb7\x8d\x8e\x0a\xd9\x49\xfb\x88\x4a\x76\x74\xac\x64\xb7\xd4\x6e\x46\x57\x52\xaf\x0a\x88\x88\x39\x5c\xd8\x35\x96\x8c\xe8\x92\xa7\xd7\xdb\x5a\xa9\x17\x59\x01\x9e\xa4\x7c\xa3\xf6\x93\x30\xc0\x13\x8f\xf6\x95\x1f\xc5\xc4\xb2\x7f\x1b\xfe\xf1\x24\x7e\xf0\x00\xc5\x25\xf3\xaf\xb8\x62\xa9\x63\x67\xb4\x1c\x02\x40\x33\x4b\x76\xd5\xc4\x8e\x19\xdd\xc2\xe6\xc3\x16\x3e\x5c\xe5\x3b\x97\x26\x1a\x69\x9d\x68\x78\xed\x59\x89\x8c\xa2\x32\x75\x8f\x85\x4f\xb0\x27\xb4\x42\x48\xa6\xf2\x70\x8d\x5c\xca\xd0\x14\x62\xe0\x45\x20\x70\x09\x1a\xdb\x83\xf1\x08\x16\xee\x31\x0a\xc0\xab\xd7\x5a\xc8\x5a\x33\x5e\x6b\x01\x63\x86\x42\x58\x00\xb1\x81\x17\x85\x0b\xd7\x67\x68\x0c\x3e\x78\x20\x4d\x36\x4c\x1b\x28\xe2\xb7\xba\x19\xff\xe7\x82\x9f\x2b\xa5\xc5\xf4\x99\x41\x3c\x0f\x63\x53\x23\xf2\x11\x3d\xd9\x51\x4b\xf4\x7a\x81\x25\x97\x77\xcf\xe7\x0b\x5c\xc8\xef\x45\x4c\x36\x45\x19\x52\x26\x39\x62\xe0\x37\xde\x19\x73\x45\x51\x15\x58\x49\x94\xe3\xe4\x25\xe5\x4c\xc9\xd8\x7d\x8f\xc6\x90\x42\xc8\xf9\xe1\xd4\x8d\x61\xc6\x72\x9b\xcb\xf2\x80\xd3\x36\x92\x4b\x79\xd3\xea\x45\x18\xc6\x03\x3f\x22\x09\x46\xd2\xf2\xc9\x77\xe5\xae\x1f\x08\xeb\x9b\xfe\xaf\xc3\x21\xa4\x3a\x49\x1a\xe7\xf4\x37\x1e\x0f\x61\xec\x4a\x9b\xa4\x01\x59\xe0\x18\x59\x16\xf0\xff\x44\x15\x97\x57\x91\x25\x5d\x5e\x92\x1f\xe2\xae\xb5\xe6\xaf\x59\xc0\xc8\xc2\xb5\xd6\x52\x31\xbb\xf1\x40\x8f\x18\xe4\x68\x66\x0c\x66\x6c\xc0\x42\xc6\x39\x00\x0d\xb8\x5e\xbf\x67\xad\x89\x0c\x4e\x08\xa4\xee\xe1\x60\x2e\x4c\xbc\x5c\x6b\x68\xd5\x32\x14\xdf\xc0\x73\x94\x5b\xbb\x63\x71\xb0\x3d\x29\xf4\x6a\x45\xe9\x32\xc2\x84\x36\x6f\xa4\xa1\x14\x68\x9d\xe1\xeb\x80\x5c\xc6\x56\xc5\x00\x91\x0d\xe6\x98\x79\xaf\xf0\xf5\x83\x07\xbf\xac\x0b\x07\x13\x97\xb3\xd0\x9f\x3d\x78\xa0\x80\x11\x11\x5f\xa8\xe7\x0d\x28\x8e\x88\x17\x20\x1b\x36\x7e\x29\x17\x43\xb1\x12\xd9\x68\x1b\xd7\x77\x0b\x2b\xe3\x44\xa6\xae\xb8\x67\xc3\xa3\x61\x67\xc5\x1d\x3e\x36\x73\xd5\xcc\x06\x35\x9c\xe6\xac\xd2\x98\x8f\x8b\x73\xbb\x30\xee\xc8\x2e\x5f\x68\xca\xa8\xa2\xda\x35\xa9\x61\x96\x9b\xae\x0f\x76\x9b\xe3\x97\x8c\x10\x50\xc2\x54\x08\x4b\x66\x36\xac\x22\x96\x00\xe2\x26\x0c\x51\x1b\x7c\xd7\x3a\x14\x7c\xa6\x05\x69\xa1\x9e\x35\x2e\x7b\xcb\xc9\x1a\xfb\x8f\xe6\x66\x45\xbc\x09\xcf\x0d\x75\xdc\xb7\x27\x65\x1d\x9c\x53\x4c\xf3\xc6\x85\x11\x44\xea\x8c\xc1\xbf\xe7\xba\xde\x83\x07\x28\x64\xfa\x15\xac\x32\x4b\x4b\x6c\x7c\xe0\xb9\x75\xe0\xf1\x2c\xcf\x86\x52\x8b\xbe\x10\x03\x57\x4e\x32\x85\xa7\xe4\x02\xd3\x69\x44\x2e\xa1\x2b\xd3\xb5\x66\x61\x10\xe0\xd8\xaa\x34\xca\x07\xd7\x59\x2b\xe6\x40\xf3\x6c\x08\x85\x6f\x8c\x1c\xc0\x61\x0e\x60\xc5\x6e\x69\xd9\xa9\x6a\xda\x29\x2b\x57\x1d\x79\x69\x52\x68\x2c\x79\xb2\xea\xb5\x56\x3f\x3f\x90\xc7\x4c\x3d\xff\x84\x95\x0f\x3e\x8f\x35\x2d\xc4\x1a\x92\xbf\xca\x44\x7e\x63\x7f\x28\xd1\x1f\xdc\x1b\x96\x6d\x92\x99\xd1\xbe\x5e\x7a\x7d\xd4\xbb\x54\x2a\x54\x5d\x2f\xf0\xed\xed\x3d\xaa\x37\xe9\xed\xed\x2f\xeb\x22\x43\x6c\xa2\xb2\x20\xc5\x92\x47\xa1\x34\xac\x97\xd5\xac\xcb\x19\xc6\xa5\x14\xe1\x3e\x96\x79\xf4\x14\xb3\x27\xda\x64\x5d\x79\x62\xe5\xfc\x23\x87\x77\xe4\x5d\xeb\x33\xb7\x1f\x60\xe6\x85\x51\xa2\x42\xb1\xe8\x43\xfa\xc1\x03\x7d\x9b\x17\x8f\x3e\xf2\xda\x7c\x2f\x4f\x8b\xdd\xb8\x24\x7e\xcb\x4c\x5a\xbe\x4d\x9d\xde\x4c\xf2\x83\x9c\xa8\x1e\x9f\x7c\xda\xdf\xb5\x20\x62\xae\xb5\xfb\x7e\xf7\xf0\xc4\x82\x80\xb9\xd6\xd6\xc9\xc9\x5b\x0b\x16\xea\x6b\x7c\x78\xcc\xc9\xa4\xd1\x6c\xb4\x69\x8a\x7a\x93\xc1\x05\x73\xad\x31\x8e\xe6\x1f\x1e\x3f\xdd\xb7\x60\xce\xdc\x37\xe8\x95\x0d\xa7\xfc\xef\x67\x1b\x26\xe6\x96\xbe\xd5\x00\x35\xc1\xec\x24\x9c\x63\x22\x4e\xaa\x11\xde\x78\xf8\x78\x68\x67\x70\xcd\xdc\xdf\x2c\x3f\x0a\xfd\x33\x0b\xac\x60\x12\xe9\xcf\x39\x49\x13\xf5\x26\x2a\xbf\xd3\x85\xfe\x92\xb4\x5a\x7e\xe3\x98\xf1\xfd\x28\x7f\x44\xd8\x13\xe5\x19\x49\xfd\x99\xb8\x83\xea\x1f\x42\x71\x47\x7e\xfa\x5e\xec\xe3\x48\xff\x52\x3d\x88\x40\x89\x98\xaa\x96\xd5\x2f\xd1\xa3\xfa\xe6\x38\x50\xfa\x95\xb2\xe2\x87\x1e\x82\xfa\xa9\x07\xa1\x7e\x56\x3b\xc8\x3b\x0f\xa8\x77\xaa\x47\xc8\xbf\xd5\x1f\x39\x4e\xf9\x25\x5b\xe5\xdf\xaa\x73\xfe\xa9\x5b\x0f\x28\xe1\xa3\x3b\xc3\xd7\xa9\xfa\xab\xc6\x7e\x86\xaf\x17\x14\x27\x89\x05\x56\x18\x2f\xc4\x38\xfd\x99\x17\x9f\xf2\x4a\xc2\x8a\xd6\x02\x6b\x12\xa5\xd4\xfa\x03\x4e\x98\x7b\xcd\x06\x3e\x89\x7d\x8f\x21\xb5\x27\x40\x6f\x17\x7d\x90\xde\x88\xc7\x70\x22\xad\x65\x63\x90\x52\x6c\x67\x0c\x73\x6f\xe1\x30\x94\xd8\x40\x62\x87\xa2\x13\x1b\x04\x6d\x72\x2e\x60\x41\xc9\x02\x53\x76\xed\x30\x74\x6a\x83\xa7\xb5\xa7\xa5\x87\x40\xaf\x50\xa6\x76\x28\xba\x16\xfe\x05\x8f\x8a\x0a\x67\x36\x44\xde\x57\xfe\x15\xc9\xaf\x75\x87\xa2\x40\x7e\x6e\x38\x18\x2d\x6c\x10\xcf\x7d\x42\x1f\x9a\xf2\xfb\xa7\x92\x2b\x38\x73\x06\x75\xb9\x91\x73\xca\x20\x61\x1e\x0b\x7d\x25\x31\x72\x3e\x49\xdb\xe2\x2f\x2d\x0e\xe3\x5e\xc4\x83\x7a\x1b\x5a\x3d\x84\xd9\x19\x7c\x5d\x5a\x0d\x5e\x63\x51\xf2\x79\xec\xf2\xd4\x7c\xa8\xf0\x22\x1e\x88\x29\xe8\x8f\x75\xfd\x01\x37\x35\x32\xe0\xdc\x1b\x41\x95\x0a\x38\xf7\x46\x99\x0d\x6f\x62\xf7\x45\x3c\x20\x31\x7c\xea\xf0\x97\xf7\x26\x06\x06\xcf\x63\x19\x6e\xea\x95\xa8\x21\x56\x05\x3e\xcb\x01\x95\x80\xcd\x07\x50\x5a\x8c\xca\x4f\x1b\x3e\x8a\xba\x7a\x25\xe1\xbe\xf8\x39\xf7\x16\xc0\x08\xff\xe2\xb8\x00\x54\x7c\x0a\xe1\x31\x26\x6d\xae\x6e\x1a\xd3\x63\xf5\xd9\x89\x48\x3d\x5f\x62\x1b\x62\xe2\x7e\x8d\x81\x10\xf7\x7e\x0c\x3e\x71\x19\x81\x94\xb8\x94\xc0\x98\xb8\x28\x25\xc8\xe2\xe7\x86\x65\x03\xff\x4c\xb0\x34\x5f\x90\xbf\x62\xef\xc2\xb2\x6d\x08\x55\x39\x8f\xb2\xd0\x8f\xb0\xca\xf4\xf8\x85\x49\x7d\xcf\x46\xbc\x9c\x47\x5c\xf1\x63\xdd\xb2\x21\x51\xdf\x1b\x96\x0d\x53\x55\x7f\xf6\x48\x17\xff\x49\x7f\x3c\xd6\x1f\xd8\x0b\x30\xe5\x8d\x44\xaa\xf0\x94\x10\xbe\x4d\x55\x5f\x41\x20\x76\x9e\xfc\x35\xf7\x42\x3d\xc2\x05\xaf\xb2\xd0\xed\xeb\xe2\x0b\x2a\x7c\x3f\xce\xf4\xfc\x22\xe2\x9f\x9d\xa7\x84\xe9\xe1\x92\xc8\x12\x0a\xbc\x62\x88\x69\x64\xd9\x30\x97\xdf\x51\x68\xd9\x70\xaa\xaa\x05\x91\x2a\x1e\x30\xfd\x11\xa8\x8f\x69\x78\x9a\x52\x5c\xfc\xf0\xbd\x45\x09\x6c\x41\x28\xc0\x36\x91\x6d\x7a\x96\x0d\xd7\xaa\x49\x3c\xd7\x70\x66\x94\xc4\xa7\xbc\xd4\x89\x2c\x95\xcc\x3d\x4e\x1a\xe0\x52\x95\xd4\x73\xf5\xc3\x7c\xd4\xe7\xba\xf9\xa9\xee\xc8\x9b\x4c\xf4\x94\x99\x0c\x19\x26\xaa\x90\x40\x4c\xff\x4c\x35\x75\xe1\xe9\x42\x89\x37\x5f\xa8\xcf\xb3\x89\x9e\x4b\x92\x4e\xf2\x2f\x9d\x1b\xf2\xfa\xc7\x72\x64\x3c\xf7\x4a\x35\x95\xe6\x2b\x40\xcf\xd4\x27\x4d\x27\x1a\x79\xa8\x86\x13\xd5\xed\x4c\x82\x30\xff\x22\xba\x97\x85\x17\xf3\xe6\x9f\xea\xd5\xd1\xa3\xbb\xcc\xbf\xc2\x58\x4f\x3f\xc0\x7a\x11\xc2\xf9\xa9\xfe\x9a\xf2\x03\x90\x37\xb1\x95\x83\x75\x82\xf5\x74\x94\x76\xbf\x42\x04\x8f\x7a\x1a\xe4\x17\x61\x80\xf5\x18\xbc\x34\x08\xf3\xf1\x08\x2f\x8e\x1a\x8c\xd4\xf3\xf5\xcc\x7c\x2f\xbe\xf0\x0a\x9c\x63\x33\x5d\xc6\x9b\x44\xa2\xfb\x43\xd5\x7d\x75\xf5\x7d\x12\x9d\x52\x92\x83\xd2\x27\x7a\x06\xac\xb4\xcf\x18\x47\x78\xfd\xcd\x51\x3d\xef\x9f\x37\xfc\x56\x42\x9e\xf1\x12\xbb\xea\x9b\xf7\x7e\x90\xef\x0d\x3a\xcf\x91\x0f\x47\x41\x82\x75\xfd\x08\x8b\x83\x4e\xfd\xf0\x26\x58\x60\xfa\xb6\x6c\x43\x9e\x5a\x36\x9c\xab\x85\x4d\x19\x13\xa3\x7e\xa6\x71\x0e\x47\x05\xe8\x02\x8f\x79\xc2\xa7\xa7\x02\xeb\x82\x95\x67\x45\xca\x33\xe6\x44\xcb\xa3\xd8\xe3\x5d\xed\xab\xb6\xce\xf0\xf5\x29\xd6\x05\x48\xca\x64\xcf\x72\x73\x92\xd3\xf2\x66\xc6\xc5\x36\xd7\xec\x9f\x46\xc7\xf9\xdc\xa3\xd7\x79\xb9\x38\x0d\x59\xbe\x81\xf8\x4f\xcb\x86\xcf\xb1\x0d\x7b\xc4\x7c\x7a\xec\x13\xe0\x6b\xb5\x27\xa3\xbc\x9c\x21\x21\xe5\x7a\xdd\x51\x98\xf2\x53\x9a\x9f\x32\x2f\x89\xfb\x31\x86\x23\xd2\xee\x2f\xed\x25\x01\x06\x2c\x96\xa1\xc9\x60\xa7\xa5\xd1\x23\x02\x25\xfb\x71\xe9\xbb\xac\xa3\x68\x18\xc8\x32\xef\x3b\xca\x88\x9b\xbd\x2c\xf6\xa1\xa3\x58\x42\x7d\x59\xe8\x45\x57\x5b\xd7\x0b\xd5\xd4\x97\x8e\x52\x2a\xb6\x94\x38\xa7\x3b\x8a\xcd\xd8\x3c\x7a\x46\xa8\x2c\xf8\xbc\xab\x20\xc5\x53\x59\xea\x4d\xd7\xd8\xc4\x9d\x41\x96\xfb\xb4\x6c\x21\xee\x63\xb5\x10\xaf\x5a\x5a\xfc\xc4\x17\x62\x86\xfd\x33\xac\x40\xfc\xb9\xa3\x60\x10\x26\x7c\x87\xab\x92\x1f\x8d\x25\x77\x08\x0a\xd1\x15\x05\xab\x67\x41\x88\x3e\xc3\x56\x0c\x21\xfa\x08\x4f\x63\x60\xb6\xcd\xf1\xec\x3e\x71\x5f\xc5\xc0\x7c\x37\x44\xb3\x58\xf0\x8e\xdb\xc2\x97\xc6\x24\xb6\x81\xf2\xd4\x8b\xb8\x16\xd4\x32\x9f\x72\x11\x05\x53\xe7\xe4\x43\xaf\x05\xc8\xcc\xe0\x3a\xb6\x01\xdf\xb5\x39\xb5\xa2\x8d\xc6\x4e\x38\xaf\xe0\xbb\xcf\x63\x20\xbe\xfb\x29\x06\xdf\x37\x03\x89\xf8\x39\xc3\xeb\xc7\x72\x5b\xa5\x1d\x45\x05\x4f\x9c\x97\x1c\xfb\x2e\x9a\xe7\xe2\x61\x1f\x6e\xea\x3c\xd9\xd0\xec\xc8\x50\xb6\xa5\x19\x6e\x6d\x19\xef\x8b\x65\x0f\x3b\x7a\x57\xac\xba\xaa\x80\x79\x05\xf0\x3a\xca\x97\xaf\x3b\x7a\xcc\xc9\xb2\xf2\xea\x4a\xa1\xcb\x4f\x3b\xca\xab\x5b\x98\x2e\x1a\xf9\xdf\xc9\xe0\x99\xfc\xf2\xd0\x52\xaf\xd2\x6d\xf6\xbb\xb7\x7b\xdb\x64\xbe\x20\xb1\x30\xfc\x2e\xc9\x05\x84\xdb\x3d\x46\xaf\x75\xf1\x7d\x24\xad\x6c\x6b\x15\x9a\xd1\x88\xce\xbf\xcd\xcf\x9d\x94\x61\xc4\xf8\xb2\xf7\xf1\x60\xff\x05\x63\x8b\xb7\xf2\x76\xfb\x84\x20\xce\x5d\x43\x6c\x90\xa7\x61\x4a\x39\x61\x29\xcd\x14\xa3\xba\x97\x3b\xcc\x2e\x09\x3d\x13\xef\x5b\x96\x70\x72\x67\x6c\x89\xc9\x5b\x72\x77\x5b\xea\x2a\xdd\xd1\x4c\x43\xbc\x87\xd1\x18\xc5\xc0\x06\xf2\x59\x6d\x40\x71\xb2\x20\x71\x82\x4f\xc8\x5b\x9c\xa4\x11\x07\x9f\x2d\x42\x3c\xc5\x52\xd0\x2b\x04\xa0\x33\x12\x00\x1b\xa4\x34\x12\x82\x1a\x09\xde\x02\x88\x8d\x51\x3d\xf5\x82\x77\x34\x92\x5e\xfc\x78\xad\xac\x50\x26\xf1\x79\xdf\x36\xa4\x62\x08\xf2\x79\xa8\x34\xb6\x78\xe0\x4d\x08\x15\x22\x8f\xaa\xdf\x3f\xbe\x64\x79\xf0\xdb\x7b\x85\x73\x44\x93\x1c\x37\x3f\xb4\x6b\x82\x5c\x29\x86\xe2\x98\x92\x0a\xb6\xa8\xea\x5a\x91\x0e\xc6\x43\x74\x33\xb9\x66\x38\x71\xd8\x80\x43\x0d\x07\x20\x7e\xee\xaa\xf7\x47\x87\x0d\x18\x61\x5e\x94\xd9\x4d\xc7\x4f\x75\xc3\x70\x61\x33\xac\xd0\xe5\x85\xb8\x2f\x88\x0e\x80\x0a\x47\xb8\x9c\x0a\x63\xa0\x03\x79\x93\x48\x6c\x28\x2d\xc3\xf5\x02\x0b\xc7\xc2\xd5\xc5\xb9\x5e\x60\x60\x83\xcb\x90\xcd\xb6\x29\x16\xce\xe6\xbd\x28\x71\x69\x3d\x05\xac\x97\x69\xc2\x94\x48\x4b\xa2\x86\x02\x14\x62\x3a\xa1\x94\x35\x1e\x36\x9d\x7c\xe7\xda\x96\x25\x17\x70\xbb\xf3\x05\xbb\x7e\xca\x39\xc2\x8a\xe6\x22\x9f\x64\x1c\x20\x25\x24\x94\x1e\xe8\x2b\xa5\x0c\x50\xd0\xee\xe4\xfa\x27\xe2\x40\x17\xee\x2c\xa1\xdc\x9a\x80\x90\x6c\xf1\x19\xa1\xf3\x1d\x8f\x79\xad\x3d\x4b\x27\xb0\x0d\x2f\x8b\x52\xe2\x97\x20\x66\xcb\x20\x26\xfc\xfa\x9f\x26\xff\x58\x1f\x0e\x6f\x6f\x37\x86\xc3\x7f\xb8\x3a\x29\x57\xed\x10\x98\xe8\x96\xe0\xcd\xaf\xb6\x4d\xa4\x3e\x16\xb5\xa4\x6f\xe3\xcc\xce\x1f\x6a\xf2\x57\x25\xa5\x37\xa2\x22\x33\x97\x1e\xdb\x84\x0f\x52\x07\xad\xda\xcf\x91\x77\x2d\xb7\x6d\x29\x80\x31\xae\x98\x8d\x94\x03\x93\xca\xb9\x38\x37\x32\xc8\x84\x9a\x1a\x28\x31\x65\x9e\xc0\xbb\xca\x40\x61\x9c\xc3\xc1\x72\x8a\xd9\x56\x14\xbd\x55\x43\x91\xeb\x93\x20\xdb\x86\x94\x46\x4e\x31\xc6\x77\x6f\xf7\x81\x0f\xbb\x94\x54\x75\x42\xa5\x3d\x98\x32\x61\x17\x70\xcf\xe0\x9e\x5c\x38\x91\x10\xde\xb6\xad\xdf\xe9\xef\x9c\xd3\x8e\x5d\x5c\x8d\xd4\x55\x38\xc7\x10\xae\x5a\x85\x3a\xdd\xeb\x29\xb2\x9c\x9e\x25\x56\xd1\xff\xe7\x30\x57\xe4\x13\x0f\xb4\x02\xdb\xd0\x10\x7c\x1b\xc6\x95\x24\x7f\x6d\xdd\x7e\x42\x5d\x11\x0b\x3e\x35\x9d\xce\xfb\x28\xdf\x25\xca\x5d\xf8\x78\xcd\x02\x11\x97\x6e\x3c\x74\xc6\xb6\x08\xd4\x5d\x04\xf1\xc8\xa7\x5a\x0e\xd3\x5a\xde\x98\xda\x93\x5c\x9d\x92\x76\x44\x6a\xad\x54\xa7\xd5\x6d\xde\x68\xa6\x79\x24\xd1\x06\xd5\x2e\x70\xb0\x17\xa2\x77\x4c\x68\x32\x65\xd5\x08\xaf\xe5\x98\x26\xfc\x4c\xd3\xbb\xab\x33\xba\x89\x7a\x38\x43\x79\x24\x7e\xbb\x1a\xe4\x44\xe1\x6c\x65\xa7\x72\xac\xa5\x1a\x80\x37\x8c\x9c\x78\xc9\x99\xc3\x10\xe7\xfe\x04\x55\x93\x84\x42\xe3\x9d\x13\xc1\xdc\x5b\x48\x1a\x2b\x63\x98\xcc\xd3\x88\x85\x0b\x8f\x32\x67\xa1\x42\x7d\xbc\xa3\x61\xee\x69\x89\x7f\x63\x29\xc1\x0b\x5a\xf9\x91\x5e\xce\xb5\x51\xb8\x91\xbd\x3a\x21\x8a\xfc\x41\xde\x95\x70\x55\x24\x73\x84\x97\x59\xf0\x1b\x8e\xbb\xab\x81\x4e\x6f\xe4\x31\xe8\xb0\x7c\x0f\x51\xb1\x51\xb0\xdc\x1c\xb1\x9a\x9c\x43\x40\x51\x57\xc7\x87\x1a\x75\x76\xd2\x4e\xef\xde\x8a\x50\x16\xee\xbd\x17\x7e\x77\xb4\xeb\x12\xc5\xad\x86\xbc\x9e\xf9\xda\x2f\x78\x41\xb9\x33\xb8\x68\x67\xdf\x64\x61\x49\x02\x6a\x6d\x45\xfe\x20\x07\xbc\x0d\x73\xdf\x8d\xfc\x41\xbe\x2a\x70\x2a\x7f\x1b\xd6\x15\x26\x46\xc6\xf2\xd4\x47\x06\x45\xa8\x10\x8d\xa5\xf3\x28\xc1\x11\x64\x76\x06\xd7\xbe\x8b\xca\x65\x4b\xd7\x19\x86\x98\x2e\xc7\x47\x97\xa3\x8b\x99\x13\x5f\xf8\x60\x79\x8b\x45\x14\xca\x77\xda\x87\x5f\x12\x12\x73\x16\x9b\xc6\x30\x14\xf1\xc7\x6d\x38\xf1\xdd\x99\x0f\x97\xbe\x1b\xf8\x70\xe6\xd7\x5c\xa8\x97\x1d\xdc\x5d\xfa\x48\xa3\x81\x75\xf4\xfa\xf8\xc4\xca\x71\xa1\x1c\x32\x5d\x90\x4f\x89\x15\x54\x63\xc5\xc4\x47\xd8\xce\x31\xe3\xbc\x81\x19\xf7\x46\x59\x87\xff\xef\x72\xbf\xcf\x77\x97\x77\x7b\xe2\x97\xfa\xa5\x2b\xf4\x5b\x86\x9c\x22\xe6\x05\x39\x89\xfc\x81\xdc\xc4\xe2\xb4\x86\x73\x5e\xe1\xb8\x0d\x35\x7b\x21\xf2\x29\x30\x38\xf3\xd5\x35\xf7\xca\xef\x74\x8a\x2f\x47\xad\x8e\x30\x9a\x4f\x4c\xef\xaa\xac\x15\x28\xe6\xd3\xb2\xc0\xdb\x15\x76\xce\x91\x78\x78\xa9\xd4\x32\xdd\x50\x56\x56\xe8\x19\x4a\x75\xf7\x59\x98\x30\x42\xaf\x07\xa7\x04\x31\x1b\x56\x50\xba\xa1\xab\x76\xa0\x5b\x5e\xa4\xc9\x8c\xf3\x22\x18\xdd\x64\x60\xf1\xbb\x7f\xb5\x1b\x1f\xd9\xd5\x1e\xf0\x5d\x7b\x50\x0a\xfb\x77\xea\x24\x5e\xb5\x93\xfc\x11\xb8\xae\x3c\xb1\x1a\xb8\xc8\xaa\xfd\xf0\x5b\x4c\x4d\x4d\xc3\x65\xc5\xe5\xb0\x75\x18\xf7\x46\x2b\xe9\x4a\xf9\xca\xfb\x79\xa1\xdf\x90\xb7\xa4\x5f\xcd\x66\x14\x4f\x1d\x36\xe0\x7f\x60\x46\x12\xc6\xbf\x49\xc2\xc4\x77\xec\xcd\xb1\xfa\xcd\x3f\x61\x41\x09\x23\x3e\xe1\xac\x97\xfe\x04\x42\xc3\xd3\x30\x76\xd8\x40\x7e\xc0\x82\x50\x36\xe6\x05\x08\x65\xb0\xf0\xd8\x4c\x35\xa2\x3f\x21\xc1\x1e\xf5\x67\xc2\x65\x11\xff\x80\x99\x97\xf0\x5f\xfc\x0f\xa4\x09\xa6\xaa\xbc\xfe\x84\x85\x97\x24\x97\x84\x06\xa2\x0d\xf9\x59\xf1\xf9\xaa\x01\xdd\x1f\xdd\x73\xb5\xfe\x4f\xec\x5d\x84\xa7\x1e\x23\x54\x34\xb3\x75\xca\x27\x9e\xf3\x6b\x27\x54\xc4\xc2\xb2\xf2\x88\x25\xa7\x84\xef\x6f\xcc\xf6\x15\x68\x1c\x02\x12\xcc\x47\x9c\x3b\x8d\x21\xc7\x65\x87\x42\x19\xeb\x1c\x0c\xa7\xa5\x5a\x3e\x84\xc9\x5e\xcc\x30\x8d\x31\xdb\xbd\x5a\x44\x84\x62\x3a\x1a\xf1\x13\x95\x73\x02\x4f\x7d\xf7\xca\xaf\x20\x2d\x6c\x89\xa4\xbc\x75\x38\x14\xbf\x4f\x09\xbc\x55\x65\xf5\x18\x60\x57\x24\x94\x86\x08\x07\xbe\x7b\xe0\x0b\x87\x65\x07\xfe\x6f\xd6\x83\x7f\x5a\x7f\xb4\x53\xbb\xaf\xc6\x73\x87\x66\x22\x5e\x95\xb8\x22\x6c\xfb\x6e\xf3\x44\x91\x8c\x9c\xf1\x28\xdc\x63\x2a\xd0\x83\x08\x67\x5c\xd0\x61\x3d\x16\xf8\xc8\x44\xe0\x08\xe1\xdd\x04\x3e\x31\x54\x8f\x50\x21\xe8\xee\x79\x7b\xaf\x38\xf7\x3f\x57\xbe\xe4\xbd\x4c\xe7\x8b\xfc\x96\x75\xe8\xcb\x3b\x8b\xbc\x88\x1d\xe2\xc2\xd0\x4e\xcc\x38\x44\xdb\x3e\x1f\xa4\x0d\x5b\xaa\xa0\xd6\x14\x21\x41\x38\xbd\x6e\x2b\xfc\xb4\x5a\xf8\x7d\x98\x84\x85\x99\xdd\xae\xee\x52\xdb\x3b\xa9\xf4\xb7\x2a\x5d\x04\x3c\xa9\xf2\x14\xd5\xa3\xaa\xa4\x33\x23\x6f\xaf\x9b\x67\x2a\x5e\x82\x53\x02\x9e\x4e\x53\x1f\x23\xdb\xce\x60\xdf\x04\xab\x26\xdc\x3d\x39\x11\x2c\x2e\x1b\x7c\x3e\x9f\x98\x58\x22\x1b\xf6\x7c\xf7\x90\x0d\x22\xec\x4d\x91\x75\x28\xb7\x87\x7c\x72\x78\xdd\x96\xf1\xb2\x95\xb7\xe3\x8d\x3b\x0c\x16\x64\xf1\x41\x18\x3a\x51\x79\x32\x1d\xf9\xee\x27\xbe\xee\x2f\x7d\x28\x9f\xfa\xe7\xb6\x0d\x3b\x26\x4e\x2b\x67\x2a\x8b\xb3\x31\xcb\xe0\x9d\xef\xa2\xd7\x3e\xda\xf1\x39\x91\xe3\xc3\x13\x9f\x43\xbb\x83\x2d\x95\xab\x94\x33\xa5\xef\x3b\x3a\x53\xab\xaf\x3b\xfb\xd0\x51\x94\xa3\x94\x2e\xf7\xc2\xc8\x29\xbe\xf6\xd1\x07\x5f\x0a\x1e\xbf\x74\x34\x24\xd0\x56\xb7\xf4\xb5\x09\x55\x1d\xae\x44\x2b\x41\xb5\xa2\xfc\x17\x5f\x86\x19\x6a\xa2\xfc\x87\x4a\x4e\x0d\xc5\xdf\x57\x32\xab\x28\xfd\x4e\xe7\xd5\x50\x7a\x47\xa5\x73\x78\x3e\xef\x84\x67\x1c\x32\x42\xf3\xe9\xbd\x31\x70\xf0\xda\x6c\x2e\x8c\x43\x86\x38\x85\x2b\xe8\x98\x81\x30\x40\x89\xe6\x14\x38\x7e\x9e\xd3\x10\x25\x76\xdf\xf3\xd1\x73\x01\xfb\xa6\x44\x9e\x56\xd5\xa3\x39\x5b\x5b\x17\xce\x17\x44\x2b\x26\xa8\x62\x78\x45\xa5\x0a\xb5\x32\xb5\xa2\xda\xac\xa1\x6a\x5b\x15\x1b\x59\x61\x39\xcf\xbf\x72\xf0\x58\x0f\xde\x78\xaf\x90\x10\x07\x06\x4b\x61\x9e\xdd\x61\xee\x98\xcf\xdd\x86\x4f\xed\x78\xac\x06\xf0\xdc\x78\x8f\x92\x91\xb2\x24\xe7\x9d\xd9\xf0\x6a\xc9\x05\xb2\x7e\xa0\xd6\x98\xe1\xcf\x5d\xfb\x57\xe9\x68\x2a\xcc\xfc\x68\x22\xcc\xc6\xd3\x6d\x7f\x35\x98\xe5\x8e\x56\xfd\x81\xe9\xe0\x6f\x56\xd9\xf4\xd0\x67\x06\xaf\x7c\x38\x8e\x91\x87\x3e\xc4\x60\x2d\xc8\x82\xdf\x2b\xb0\x05\x58\x1e\x95\x79\x0e\x67\x87\xf4\xeb\x8c\xcc\xe3\x47\xc4\x2b\x06\x9f\x3b\xaa\xdb\x19\xdc\xf7\x5d\xd3\x55\x46\xca\xae\xe2\x41\x41\xb2\xc1\x2f\xeb\xab\x4a\x68\x98\x02\xa4\x71\x50\x93\xec\x09\x73\x02\x22\xf4\x0c\x7f\xfb\x43\x9e\x5e\x4a\x7b\x55\x2a\x1f\x16\x22\xdd\xf1\xa8\x62\x91\x56\x3a\x9a\x9e\xf9\xe2\x30\x13\x07\x9b\x3e\x26\x30\x3f\x1c\x94\xb3\xd7\x1e\x13\x6e\x4b\xb4\x04\xdd\xdc\xda\xab\x96\x2b\xb4\x68\x6b\x5f\x92\xe2\x8f\x62\x67\xe5\x8d\x5e\xce\xc2\x08\xf3\xb3\x44\xaf\x57\xd1\x39\xb1\xed\x0c\xd9\xed\xec\x4b\x88\xce\xc5\x69\x6a\x8b\xb5\xf1\x39\xb7\x74\xc8\x06\x78\x3a\xc5\x3e\x3b\xf0\x62\xef\x14\xd3\x64\x50\x9c\x99\xee\xcd\xe2\xec\xd4\xb1\x72\x4b\x9e\xb8\x38\x4d\x41\xec\xd2\x23\x1f\x48\xbc\x2b\xaa\x27\xce\x7d\xfe\xe3\x18\x47\xd3\x83\xe4\xd4\xd9\xf7\x45\x58\x00\x6b\x7a\x65\x81\x3f\x0f\x0e\xbc\x85\xf3\xd5\xe7\x1b\x8f\x7f\x7d\xf2\x33\xc1\xa5\xb1\xd4\x18\x90\x53\x2a\xb5\x56\xbd\xf3\x94\x02\x19\x6b\x67\x62\x7d\xfa\x8f\xb4\x30\x14\xec\x8f\xa4\x17\x98\xc2\xa9\xca\xf0\xc9\xf8\x1f\xe9\x93\xb1\x36\xd1\x0d\x5d\xf6\xdb\x58\xf8\xac\x09\xef\xb9\xae\xff\x1b\x5d\x1b\xff\xd1\xac\x1e\x4e\xd1\x4f\x3f\xad\xff\xfa\xf8\x9e\x8b\x1e\x6f\x3c\xfa\xe5\x97\x07\xfe\xc0\x9f\x79\x74\x9b\x04\x78\x4b\x04\x2e\xb4\xad\xdf\x85\x22\x6c\xb8\x49\xd6\xd6\x1c\xe1\x62\x84\xb8\x23\x3b\x77\xfe\x34\x5e\x5b\x03\xde\x51\x47\x1f\x64\x6d\xad\x70\xdd\x8a\xe8\x5a\x2a\x92\x2b\x37\xc7\x8a\xb7\xd2\x32\x12\x6f\x94\xe8\x05\x8c\xd7\x2b\xd1\x0f\xfc\x52\x7c\x46\xfa\xcf\x5c\xda\x6b\xeb\xeb\x44\x3e\x39\x57\x4f\x0e\xd7\x27\x97\xd3\xb4\x31\xc2\x4a\xbe\x8b\x28\xac\xdb\xb6\xbd\x49\xd7\xd6\x9d\xfe\x48\x09\xe0\xf1\x6f\x34\xf7\x3f\xc4\x0b\xc7\xb6\xbd\xc9\x01\x23\xbc\xc9\xf6\xd7\x1d\xba\x36\x72\xfa\xa3\x7a\x24\x8b\x5c\xbc\x27\x17\x28\xcd\xaf\x30\x54\x19\x81\xf6\x47\xae\xeb\x8e\x2b\x10\xe3\x48\x50\xf2\xf4\xc6\x36\xc7\xce\x38\x0f\xfd\xff\x24\xfe\x47\xf8\x44\xaf\x48\xfa\x5b\xfc\xc7\x66\x75\xf1\xd2\xf2\xfc\xf8\x18\xc5\x7a\xf9\x6b\x6b\x36\x5f\x39\x77\x3d\xff\x5c\x03\xc2\x33\xdc\x62\x53\x61\xa4\xbc\x20\xc9\xb1\xce\x07\xfe\x2c\x0f\x97\x18\x26\xc7\xe9\x44\x05\x94\x8e\x85\xcd\x08\x4f\xd8\x9e\x79\xd4\x11\x16\x6a\xd3\x30\x0e\x8a\x12\x44\x44\x35\x43\x36\xd0\xd4\x45\x2c\x1d\x54\x72\x81\xa5\x83\xbc\xb6\x0d\x38\x75\x75\x82\xca\x8f\x53\x13\xa3\x36\x1f\xe0\x73\xc4\x40\x8c\x0a\x59\x6b\x96\x6d\xdf\xde\x56\xd3\xfa\x16\x27\x1d\x64\x85\xda\x43\x51\xd2\x5f\xa1\x24\x36\xf4\xb3\x2b\x6a\xa7\x2b\xd4\x1e\x88\x92\x63\x63\xc9\x63\x86\x98\x7d\x7b\x7b\x29\xff\x9c\xc9\x3f\xa6\xea\x61\x6a\xb8\x36\x08\x5b\xd3\x3c\xe4\x84\x87\x68\x0a\x32\x47\x38\xb6\x1c\xf8\xf3\x05\x8a\x61\x68\xff\x63\x58\x3c\x93\x30\x97\x01\x75\x63\xc0\x2e\xe6\xc7\xae\x67\x6a\x56\x37\x17\xe6\xcd\x95\xe7\xc5\x0f\xa8\xcd\x23\x8e\x56\x8e\xf8\x2d\xba\x1d\xf3\xbd\x8c\x6d\xe8\x8f\xec\xcd\x1d\x91\x27\x4a\x08\x5b\xf6\x16\xf6\x42\xd4\xf3\x45\x17\x6a\xbc\xf8\x1c\x61\xde\x82\x5d\x92\xbe\xea\x97\x2f\x51\x3a\x4e\xa5\x4d\x2c\x71\xd5\x48\x78\x77\xd8\x89\x2b\xe3\x13\x25\x49\x2a\x0d\xee\x78\x81\x22\xf5\x98\x15\xa9\x47\x0c\x11\xdb\xf1\x90\x97\x27\x3b\x22\x49\x08\xe6\xba\x86\x9c\xaa\x21\x97\xfb\x14\xc3\xde\x0c\x51\x22\xf3\x1c\xf1\x25\x00\x78\xac\xcc\x78\x85\x82\x6c\x94\xba\x88\x18\x65\xff\xc5\x8d\x4c\x68\xdd\x39\x0c\x64\x5c\x2a\x15\xb5\x33\xe6\x5c\xad\x4f\x62\xa5\x12\x4d\xc9\xa5\x43\xc0\x27\x91\xe3\x77\x4a\xf9\x8f\x3c\x9a\x60\x5a\xdc\xa7\x82\xe6\xc4\xea\x02\xce\x1a\x5b\xb6\x58\x52\xe3\x39\x21\xf5\x2a\xb3\x36\xe8\xe5\x64\x44\xcd\x11\xeb\x40\xd1\x6a\xaa\x58\xc5\xe2\xca\x67\x3c\x90\x1f\xf9\xc4\x99\x98\x38\x1e\x50\x72\x29\x26\x8f\x07\x3e\x89\x78\x97\x17\xcb\xba\xec\x45\x69\xc3\x1c\x32\x76\x29\x10\x11\x1b\x08\x29\x4b\x7c\x3e\xfd\xc2\x73\x7a\xce\x4c\x04\xa9\x08\x24\xca\xff\x19\xd9\xb9\x53\x97\xf1\x08\x52\xd7\x43\xc7\x14\x62\x3d\x6e\x5f\x7f\xc4\x6a\x66\x25\x8e\x64\x91\x82\xf4\x31\x41\x64\x88\x48\xc9\x34\xcf\x8d\x44\x21\x44\x17\x29\x5c\x0b\x2d\xab\x53\xd3\xfe\xcc\x37\x37\x85\xa1\xfd\xcf\xfe\xa8\x18\xea\x34\x95\xfb\xb5\xb4\x83\x8f\x99\x64\x7c\x88\x2b\xb2\xc5\x2e\xf5\x5d\x22\x26\xbc\x4b\x69\xd3\xf7\x00\x51\x5e\x07\x84\xad\x7f\x19\xc9\x53\x60\x62\xdb\xa4\xb6\x43\x32\x1b\x26\x2b\x90\xbe\x2b\x41\xbb\xae\x57\x26\xc6\x27\xa6\xe9\x96\xcb\x53\xb1\xd1\xf4\xae\xe5\x13\x2b\x11\xa1\x89\x9c\x7d\x6d\xd3\x8f\x4b\xa9\x3b\xfc\xb4\xe7\xfb\x9c\xaa\xad\x7f\xc5\x80\xad\xad\x8b\x58\x41\x70\xd9\x86\xeb\x15\xec\xa9\x84\x04\xd5\x0b\xcd\x79\x70\x84\x79\x47\x71\x81\x03\x1c\x4d\xe3\x81\x10\xad\xda\x20\xe1\x29\x5c\xc2\x8e\x47\xe0\xf1\x3f\xeb\x35\xe8\x4a\x12\x12\xa4\x20\x6c\xd3\x62\x4e\x45\x16\x69\x33\x24\xac\xde\x3e\x44\xef\x9b\x54\x6f\x98\xb8\xbe\x61\x64\x64\x61\xa9\x3a\x7f\xe9\x8c\xc5\xa6\xf1\x32\x89\x7a\x67\xed\x94\x5f\xec\x8b\x8e\x9d\x83\xdd\x58\xde\xfc\xca\xbb\x06\x37\x77\x8d\x78\xc8\xa5\x7a\xcb\x60\xb9\x65\x38\xfe\x23\x5f\x56\x15\xd4\x43\xf8\x81\xac\xd6\x55\x9b\x45\xd4\x4f\xc5\x7e\x49\xf3\xbd\xc7\xd9\xa7\xf1\x10\x3c\xfe\x67\x54\x81\xa0\x2f\x20\xee\xf1\x7f\xed\x07\x0f\x54\x12\x07\xbf\xc7\xff\x55\xb0\x1d\x4b\xf2\x2c\xbe\x3c\x09\x89\xe3\xb4\x22\xe9\x28\xe3\x9c\x87\xce\xd2\xb6\x87\x32\x9a\xd9\x2a\xca\x94\xe9\x26\x53\x03\x9b\x4c\x45\x43\x30\x48\x50\xf9\x04\x65\xb4\x2b\x1b\xae\xbe\x8d\x92\xa9\x9b\xb8\x16\x4e\xaa\x25\x51\xba\x21\x62\xb6\x42\xb5\x23\xe6\x50\x74\xc4\x28\x84\x98\x53\xf4\x2c\x12\x45\xe7\x4f\x5b\x37\x80\x8c\xc6\x05\x5b\x7f\x11\xce\xe0\x2a\xa5\x1d\xca\x98\xde\xb5\xd9\xf9\xa5\xd9\x89\xbd\xe5\x8b\xd9\x55\xb1\xc7\x97\xd4\x36\x9f\xe2\x61\xea\x1e\xa6\x42\xda\x7e\x98\xfe\x66\xdd\xba\xed\xd2\x76\x0f\x6d\xa5\xf0\x54\x9e\xe7\x99\x0d\x28\xaf\x69\xff\x66\xdd\x0e\x96\xd4\xbb\x56\xd5\xc4\x1c\xde\xfe\x29\x6b\xaa\xf7\x4a\xbe\xa8\x8b\x54\x2f\xa3\x5a\xd7\xda\x3a\x8b\xf9\xee\x1a\x49\xaf\x11\x39\xe5\xbe\x93\xe3\xce\xe0\xa0\x6d\xd0\x9a\xfc\x50\x4d\x7e\x86\x9a\xfc\x8c\x72\xba\x53\x16\x1a\x73\xca\x33\x12\x94\x67\x94\x81\x8c\x8b\x56\x52\x62\xaa\xcd\x6a\x47\xcd\x88\x93\xe8\x1b\x5e\x93\xcf\x24\x3f\xef\xc5\x0f\xbe\xa1\xf3\x21\x68\xef\x34\x62\xd6\x05\xd5\x13\xc5\xc4\x0f\x01\x84\xed\xd4\x45\xb1\x81\xed\x2a\x54\x64\xc8\xa5\xc3\x44\x17\x54\xb7\x8d\x8b\xb6\xf3\x86\x49\x56\x8f\x4f\x5e\xbe\xad\x96\x1b\x09\x70\x2e\x67\xe3\x37\x55\xdb\x86\xf3\x74\x59\x30\xfa\x76\x1e\xa5\x20\xe3\x42\x6d\x3a\xad\x69\x34\x7b\x68\x3b\xad\x1c\x37\xcc\x96\xb2\x1e\x10\xee\x54\xb0\x22\xb8\x35\x88\xa7\x25\x3c\x12\x14\x55\xb4\x4c\x24\xa5\xb5\x85\x67\xdc\x0e\xce\xf2\x99\x17\x46\xa5\xd8\xf0\x77\xc2\xb2\x20\x85\xf3\x54\xbc\xbf\x0a\x4c\xdb\x4f\x73\x05\x12\xa1\x47\x10\xc6\xa7\xef\x3d\x1a\x0a\x63\x92\x0c\xf6\x4c\x4d\xd7\xcb\xbf\xc2\xd7\x97\x84\x16\x2f\x0f\xaf\x5b\xd8\xaa\xcb\x14\xf6\x52\x69\xc9\xb0\x4a\xb3\xc7\xd7\xf3\x09\x29\xe4\x8e\x47\xed\xad\xbe\x94\xad\xee\x34\xa7\xb2\x1b\x07\x56\x06\xef\x52\xb7\x0c\x8d\x1a\x13\xb4\x45\x11\xd3\x1c\x23\x30\xc5\x40\xd8\x9b\xe6\xe3\x9f\xa9\x8d\xbe\x23\xba\xb4\xe1\x7d\xde\xe7\x53\x2f\x78\x8b\x17\xd8\x63\x56\x06\x1f\x52\xa3\xf4\x50\x5f\x18\x73\x0e\x92\xf1\xeb\xe1\xa8\x72\xf2\x52\x86\x30\x67\x3f\x54\xec\x31\xca\xb9\xe3\x9b\xfc\xb4\xbe\xb7\x3a\x7f\x9c\x5f\xea\x24\x6e\xfa\xe5\x83\x59\x22\xaa\x38\x9e\xed\x4a\x4b\xef\x53\xf0\x6d\x7e\x4b\xed\x8f\x80\xba\x22\xc4\x62\x05\xd9\x49\xae\xa2\x08\xb1\xeb\x67\x1c\xfb\x5e\x74\xcf\x75\xc9\x34\x6e\x4a\x03\xae\x5c\x73\xbb\x07\xcd\x93\x0a\x00\x6e\x56\x20\xe7\x14\x30\x51\x72\x94\xd4\x04\x90\xb4\xd9\x76\x6a\x04\x48\xba\x32\x40\x52\x01\x90\x2f\xad\x07\x8e\x38\x1c\x0a\x7d\x9b\x28\x45\xd6\xee\x95\xe7\xb3\xe8\xba\x44\x84\x0d\x68\x9a\xa0\x0f\xea\x68\xc1\x95\x17\x41\x66\x67\xa6\x17\x8b\x04\xbd\x68\x2b\xce\x51\xf6\x6b\xea\xa6\x2d\x1a\x70\x30\x5e\x0d\x49\x5b\xb9\xe2\xfc\x36\x19\xeb\x63\x89\xe4\xf4\xdb\x17\x87\x51\x2a\x68\xf4\x38\xd3\x71\x7f\xc4\x25\x81\x8a\x8b\x51\xbe\x40\x49\x59\x0c\xa1\x97\xe1\x5b\xba\x28\x35\xb8\x6e\xdb\x37\xe5\x65\xc4\x10\xbb\xf1\xda\x08\x88\x4b\xc0\x77\x7d\x48\xdd\x74\x6d\x04\x63\x77\x24\x1d\x3c\xd7\x8b\x26\xe5\x82\x30\x76\xc7\x6b\x23\xf1\xa4\xb7\x1a\x2c\x97\x4d\xf5\x46\xba\xa0\xbe\xfb\x14\x8b\x3d\x53\xdf\x0d\x8d\x25\x9a\xaa\x8d\xf1\x3e\x85\xa9\xf0\x6c\xfe\xaf\x85\xcc\x9b\xb6\x5d\xd0\x86\xfe\xb8\x89\xfe\xca\x8b\xa9\xae\xb0\x40\x5f\xf5\xad\x26\xbf\xe3\x97\x6f\x7c\xea\xfa\x55\x9c\xd7\xa5\x53\xb9\xb6\x53\x1a\x2d\x3f\xff\x8e\x96\xf9\xa6\xfa\xd4\xca\xbc\xcf\x53\x14\xa2\x37\x92\xb5\x13\x2f\x75\xe5\x13\xe3\x59\x44\xc4\x81\xf1\xb9\x71\x42\x29\x85\x07\xe0\x64\x43\x0f\xc8\xa5\xa2\x5b\xe2\xd2\x5c\xe6\x21\x9e\x83\xc5\xe0\x52\x97\xe6\xc3\x1b\x8b\xef\x08\x38\xce\x9d\x72\xb6\x42\xa0\xde\x35\xff\xc2\xb6\x42\x3f\x2d\x7e\x48\x4a\x84\x78\xea\x26\x25\xb1\x83\x40\x97\x57\x86\x9d\x37\xd5\x68\xe9\xe7\x68\x99\x0a\xb4\x8c\x25\x5a\xae\xa1\x69\x9f\xd8\x2a\xda\x7a\x24\xda\x84\xc0\x9d\x52\x24\x04\x36\x04\x22\x28\xfc\xfe\xea\x61\x04\x72\xf9\xe7\x03\x9f\x7a\xc9\x6c\xdb\x4b\x30\xca\x05\x68\x37\xc2\x71\x82\x73\x13\x85\x31\x76\x7e\xde\xd8\xe0\xbd\xa4\xf3\xd8\xf9\x35\x03\x1c\x07\x3a\xfd\xd1\x4f\x3a\x7d\xf4\x38\xcb\x20\xb0\x95\x83\x4d\xd9\xca\x60\xca\x41\xfd\xff\xeb\x2d\xc4\xaf\x5e\x82\xf1\x5c\xf8\x90\x9b\x79\x17\xb8\xe7\xf5\x26\xe9\x69\xc3\xcd\x9c\x17\xf7\x8e\x8f\xb7\xb7\x77\xbb\x5c\xcd\x31\x42\xa2\xe4\xa1\x6c\xb4\xe4\x66\x4e\xde\x83\x02\x3e\xf1\x06\xf4\xa2\xa5\xd0\x8b\x24\xf4\x6c\xf8\x58\xc6\x95\xbd\x98\x63\xca\xfd\xd4\x45\xff\x2a\x54\x39\xf9\x3e\x54\xf9\xf8\xa7\xa1\x4a\xf4\xe7\xa0\xca\xe3\x8d\x5f\x8c\xa8\xf2\xf8\xa7\x61\x27\xaa\x84\xf1\xdf\x0d\x51\x5a\xb9\xe9\xa7\x5e\xf0\x3a\xc6\xaf\xa7\xc5\x6d\x81\x8d\x97\x3e\x65\xc8\xa8\x0f\xf2\x85\x3a\x6e\xb2\x9b\xf7\x53\x44\xc5\xbb\x1d\x30\xcd\xa6\x72\x6e\x83\x5f\x74\x58\x55\xb2\x44\x6a\xa2\x4d\xe1\x25\x4d\x4a\x1e\x25\x7a\xaa\xfb\xa5\x7d\x7b\xab\x93\x85\xc0\x4e\xdd\x34\xed\xa2\xa6\x7c\x38\x31\xf3\x5e\x34\x03\x21\xdf\x18\x09\xf6\x8b\x8e\x57\xbf\x0d\x79\x88\x8d\x81\x36\x99\x24\xc0\xa6\x46\xf2\xcb\x85\x3c\xb3\xf4\xc5\x24\xee\x28\xbb\xc5\xf6\xb1\x57\x28\xfa\x03\x19\xbb\xf1\x18\x0d\x6d\xf0\xc5\xc7\xc8\x86\xd4\x54\xfb\xde\x30\x83\xf1\xd8\x95\x07\x07\x19\x9b\x24\x5c\x55\xf9\x6d\xcf\xf0\x44\xf6\x7b\x6c\x4a\xa4\x96\xdd\xa1\x7e\x4e\xf9\x65\x39\x1c\x77\x4a\x57\xc6\x63\x2d\x95\xf1\xc6\xae\x37\x16\xe2\x1c\x6f\xfc\x9b\x75\xdb\xb7\xfe\x70\xc3\xb1\xe4\xeb\xc6\x6e\xd7\x95\xbf\x47\xc7\x35\x4d\x9e\x10\x5d\x95\x2c\x78\x4a\xee\x08\x51\x32\x06\x5d\xbf\x5a\xc5\x97\xd7\x6c\x3b\x83\x10\x09\x71\xd2\xc0\xfa\xa3\xe5\x53\xbc\x01\x1d\xa5\x28\xb6\xa5\x0a\x42\x43\x5b\x28\x44\x7a\x06\xbc\x18\xb3\x61\x57\xe0\x38\xb1\x6d\x93\xda\x90\x0d\xd3\xb6\xf9\xc9\xeb\x8c\x71\x22\xd3\xa5\x13\x29\xa8\x69\xc8\xd1\xd2\x00\xa4\x7c\x94\xd5\x01\xc7\x7c\x5a\x20\x60\xe8\x73\x82\xf9\x9d\x13\x14\x8f\x65\xdf\x30\xc3\x68\xf9\x52\xa5\x6e\x75\xa5\x0b\x84\xce\x07\x94\xc9\x11\xda\xdf\x09\x0d\x33\x8a\x71\xf0\x34\xa1\x93\x1a\x60\xb0\x5a\xa9\xcc\x86\xe0\xbb\x71\x5d\x29\x2c\x92\xb2\xc2\xe2\x33\x42\x27\xd2\x45\x9c\xb3\x22\x06\x95\x47\xa6\x74\x14\x5f\x0b\x19\x58\xe1\x01\x6e\xe9\x1a\x55\xdb\xa8\xe9\x32\x9a\x01\x5e\xfa\xa4\xc5\x1e\x83\x65\x1b\xb7\xd2\x93\x9d\x65\xc6\x75\x31\x61\x6d\xa9\x62\xcb\xe6\x5c\x8c\x8d\x12\x09\xfd\xe6\x5f\x3a\x09\x48\x49\x8e\x14\x8e\x41\x93\x5b\x66\xc4\x9e\x70\xcc\x07\x81\x6d\x50\xaf\xdf\x23\x7b\xb3\x18\x4e\xf1\x9e\xe0\x24\x68\x91\xcf\x9c\x5f\xee\x4c\xd3\x92\x6d\x51\x1b\xca\x85\xd7\xda\x0b\x8b\x91\x61\x75\x60\x54\x6b\x19\x80\x90\x29\xa5\xc0\xd9\xb8\x4d\xea\x69\xd0\x50\x7b\x2b\xdc\x90\x8e\x47\xfc\x83\xda\xd9\x93\x9a\x12\x19\xce\x35\xd5\x14\xc4\x9e\xa5\xa8\xe4\x19\x5d\x30\x36\x3d\xaf\x27\x4c\xb4\xfa\x9c\xcb\xea\xf9\x64\x2e\x3c\x41\x0a\xb7\xe6\x6c\x86\xa5\x93\xf0\x1e\x23\x67\x38\xee\xf9\x5e\x1c\x13\xd6\x9b\x48\x47\xea\x78\xbe\x60\xd7\x3d\x69\xd5\x79\x4f\x5a\x81\xd6\xfa\x1e\x7d\x67\xdf\x38\x0e\x56\xea\xb9\xa6\xac\x5f\x9c\xc8\xea\x18\xc5\x92\xd1\x19\x8c\x87\xf6\x83\x07\xa5\xc4\x91\x4a\x2c\xd1\xf0\xfc\xf4\x91\xa8\x2b\xd6\x4c\x98\xbe\xc1\xc8\x6e\xb1\xc4\x92\x2c\xfc\xc2\xf3\x71\xf2\xa4\x73\xd3\x71\xe4\x19\x08\x78\x72\x1e\x1d\xa6\x28\x18\x03\x1d\xe0\x38\x10\xc6\xe6\x21\xc3\x73\xa0\x83\x04\x2f\x3c\xea\x31\x42\x81\x0e\x18\xf5\xc2\x28\x8c\x4f\x45\xcf\x17\x63\xb7\xdd\x06\xb2\xcc\x0a\x8e\x0b\xad\x16\x52\xc8\x2c\xc6\x25\xf1\x4c\xe3\x39\x94\xb6\x31\xad\x58\x3e\x22\x64\xe5\x66\x94\xe8\x01\xa8\x4b\xd7\x46\x80\x5d\xbc\x36\x82\xd8\xad\x88\x1e\x72\xa1\x03\x50\x77\x6c\x96\x4e\x70\xae\x6f\x6e\xe2\x6a\x0d\xbc\x5f\xa1\xc3\x09\xbe\x4b\xc4\x83\xa8\xba\x32\x8d\x5d\x22\x78\xd2\xc4\x25\xfa\xca\x34\x55\xe6\xc9\x31\x83\x88\xf3\xb2\xea\xca\xb4\xd0\x50\x49\x20\x2d\xa0\xb2\x68\x08\xad\xf6\x85\x30\x55\x7a\x2c\xd6\x45\xd6\xed\xcd\x00\x5d\xf0\xf3\x2c\x59\x1b\xc1\x78\x6d\x04\x23\x48\x41\x44\x5f\x56\xe9\x0b\x18\x03\xef\x2b\x5a\xd3\x39\x70\x21\x35\x1d\x12\x98\xe9\x91\xa5\xa5\xd3\x71\x2f\x86\x0b\xc0\xea\x81\x55\xf4\x29\x2f\x15\x17\x30\x93\x64\xe0\x74\xec\x16\xc6\xbb\xea\x50\xc9\x60\x62\x20\x0e\xaa\xcd\xd9\x18\xa9\x7b\x94\xf5\x9b\x05\x39\x1a\x39\x16\x58\xe2\x16\x65\xfd\x61\x81\xc4\x52\x87\x01\x47\x36\x87\x82\x46\x30\xe7\x74\xdc\x65\xdf\x58\x6a\xfa\xc6\xd8\x74\xb6\xb4\x69\x1b\xae\x57\x1a\x3a\x32\xb6\x6f\x7f\xeb\xd0\xb5\x53\xdf\x38\xc6\x89\x70\x2a\xb1\x2d\x69\xcc\x5d\x8c\x11\x0f\x3b\xab\x36\x1f\x6d\x43\xf4\x94\x82\xe5\x5a\x85\xc2\x13\x3f\x15\x72\x61\xd9\x83\x07\xf9\x4f\x45\x20\x1f\x3c\x50\xd7\x36\x49\x92\x64\xe2\xa6\x87\x5e\x77\x8f\xab\x7c\x0e\x14\xe3\xb9\x50\xb6\x0b\xea\x43\xa8\x1c\xdb\xce\x79\x66\xc3\x89\xf1\x8e\x75\x89\x51\x88\x18\x83\x6b\x7e\x5e\xf1\x81\x3f\xb0\x20\x44\x97\x14\x46\xda\xfd\xd0\xe5\xd8\xa0\x3b\x2e\xcb\x3e\xb4\x80\xd5\x26\xa9\x3d\x7f\x58\x5a\x53\x7a\x93\x0e\xe4\x75\xef\xac\xda\x4e\x99\x64\x51\x97\x3d\x29\xeb\x57\x97\x8f\x8d\xf3\x27\x15\x41\x3c\x1e\xa4\xf1\x45\x98\x84\x0c\x07\xad\x17\xde\x7d\x84\x07\xc2\x31\x91\x3c\x94\x64\x81\xf1\x30\x87\x73\x5c\x3f\x9a\x4a\x15\x98\xd0\xbc\xce\x32\x38\xee\x20\x4e\x67\x63\x24\x1e\x65\x6f\xd4\x48\xaa\x86\xbe\x7a\x7c\xce\xe5\x98\x73\x0b\xc2\x71\x5c\xe2\xe8\x60\xcc\x27\x92\x01\xbd\xea\xb8\xaf\x1d\x73\x3e\x41\x2d\x02\x15\xc6\x81\x7c\xf5\xf8\xe1\x21\xac\x06\x45\xfd\xa7\xed\xdb\x49\x35\x40\x0b\xb3\xc3\x7a\xe5\x25\xca\x66\x7a\xfc\x78\xa0\xbe\x4a\x73\x2a\xc1\x3f\x9f\xd9\x40\x7e\xa8\x09\xb2\x1c\x98\x82\x23\xdf\xea\x62\xec\xf2\xae\x58\xa9\x0b\x5a\x07\x99\x30\x33\x3e\xec\xb8\xb1\x57\x95\xf6\xe0\xad\x11\xd3\x0f\xc7\x06\x0d\x0b\xba\x1a\x4a\x95\xd6\xb7\x24\x3c\xa9\x3c\x7e\x11\x60\xf6\x66\x95\x0b\x4c\xd0\xd6\xb8\xc6\x46\x13\xf1\xee\xa4\xe1\x9a\x09\xb5\x03\xc8\x01\xa8\x01\x57\x67\x0e\xab\x8c\x77\x06\xbb\xad\xc8\x53\x9e\x24\xcb\xa5\xf7\xdf\x33\x49\x11\x64\x84\xd4\x5c\xa8\x28\x45\x92\x3f\x67\xba\x32\x70\xcf\xb2\x49\xdb\x70\x30\x76\x43\xb4\x3b\x06\xeb\xf8\xe4\xed\xde\xe1\x73\x0b\x76\x98\x0d\xdb\x42\xe2\xc2\x53\x0f\xdf\x1d\x3c\xdd\x7d\x6b\x41\x44\x79\xaa\x50\x3b\x79\xb2\x3d\xfe\xcd\xfa\xc7\x43\x93\x81\x68\x01\x99\x5c\x99\xa0\x06\xbb\xfc\xac\x26\x4c\x3d\xcc\x49\x61\x99\x38\x9f\x05\x80\xce\x9b\xcb\x50\xd3\x4f\x30\xe0\x5c\xa9\xc3\x10\x7d\x86\xa7\x63\x14\xeb\x55\xc7\x15\x9a\x12\x1b\x76\x5f\xdc\xdc\x7d\x71\x6d\xf7\xe9\x7b\xc4\xb3\xb1\x6b\x9c\x50\x75\x81\x58\xf3\x32\xf6\x04\x6d\x8f\x5d\x05\xc0\xdf\xac\x7f\x6c\xfe\xab\xa0\xb7\xdf\xb1\xa1\xdf\xa4\x98\x5e\xd7\x76\xf5\x5e\x2b\xd2\xef\x8f\x5b\x75\x0d\x25\x6c\x9e\x98\xa6\x2e\xd0\xb5\x00\x72\x19\xb4\x04\xd4\x9a\x20\x8a\x42\xf4\x8e\x02\x03\x62\xb7\x89\x95\x5e\x1b\xa9\x4d\x88\xf6\x38\x11\x3e\xb1\x33\x78\x39\x76\x2f\xea\x46\x70\x06\x43\x0d\xeb\xa5\x17\xa7\x1e\xbd\x16\xde\xf4\x36\x46\x30\x5e\x77\x36\x46\x59\xf3\x6e\x69\xaa\xfa\x0c\x4f\x68\x5e\x77\xfd\x17\x5e\x77\xfd\xd7\x15\xeb\x1e\xf0\x63\xe1\x5b\x3a\xdd\x5a\x50\xa1\xd1\x32\x72\x36\x86\xa2\xe2\x70\xe5\x1e\xbf\x69\x92\x2f\xd3\x18\x7f\x4b\x77\x2f\xd3\xe8\x9b\xfa\xdb\x4a\x4f\xd3\x84\x7d\x4b\xcd\x63\xbc\x60\x78\x3e\x11\xc8\x7b\xe7\xe1\xbe\xf6\x19\xc9\xab\xde\xad\xdf\x43\x72\xf1\xcd\xdd\xee\x60\xbf\x54\xd7\xd0\xaf\x12\x53\xe4\xff\xb3\xe1\xc8\xc4\x19\x8a\xc3\x70\xc8\xd9\x97\xdf\xac\x1f\xac\x3f\x80\xc1\xa3\x21\xa7\xee\xd8\x90\x33\x12\x39\x71\xed\x89\xc0\xd0\x82\x49\xc6\x82\x0d\xf6\xa3\xcd\xe1\x16\xc6\x7b\x92\x3f\x8d\x15\x7f\x7a\x6f\x58\x70\x85\x3a\x47\x73\x85\xe2\xc5\x63\xa4\x93\xc6\x43\xbb\x52\xbf\xe0\xd1\xab\x0c\x65\x91\x6e\xeb\x07\x81\x8a\x71\x5f\xb3\xbe\xec\x68\x58\x6e\x40\xf5\x75\x87\x66\x3b\x8b\x8e\xf2\xa2\xf5\xbf\x75\xcb\xc0\x7b\xa3\x0c\x76\xda\xce\xb3\x10\x2d\x18\xd0\xfe\x08\x5e\x8e\x73\x46\x40\x9b\x3d\x2a\x15\x80\xa3\x31\x62\xf6\xa6\x94\xb4\xac\x3b\xf2\xef\xc8\x19\x66\x36\xbc\x5b\xe1\xed\xaa\x1f\xa2\x1d\xf9\x42\x21\x9f\x9b\x4a\x96\x38\xff\x1c\xda\x76\xeb\xbd\x87\x4a\x35\x9e\x27\x65\x79\x44\x2c\x70\xf3\xbd\x91\x2a\xcb\x51\x6e\x3c\x7e\xec\x6c\x3c\xfe\x29\x83\x0f\x63\x93\x37\xa1\x92\x32\xcd\xbd\x5c\x9d\x86\x96\x06\xd2\xc3\x4a\xe4\xc4\x80\x88\x4e\x7d\xf7\x3d\x67\xf5\x9f\x30\x37\x06\xea\x12\xc0\x6e\x8b\x91\x49\x2f\x44\xdb\x30\x84\xd7\x0c\x45\x94\x1f\x86\xfc\xfc\x78\x91\xdf\xf4\xb7\xa6\x0c\x53\x2b\x83\x2f\x79\x8a\x0c\x67\x6a\x65\xf0\xd5\x04\x44\xe6\x94\x86\xaa\x6a\xe7\x5e\xd3\xec\x1b\x0e\x57\x39\xae\x8a\x69\xd3\x3f\x87\xf6\x0d\x73\x5f\x8c\x0b\x80\x3d\xf1\x49\xcc\xc2\x38\xc5\x3d\x96\x55\xf4\xb9\x60\x98\xb3\xb4\x15\xa8\xaf\x8d\x40\x2c\xae\xd3\xbe\x24\x99\x5a\xd9\xb5\x7c\x04\xf7\xaa\xe6\x55\x4b\x16\x55\x54\x5b\x13\x4b\xfb\x45\x0c\xb5\xaf\xd6\xd6\x86\xe7\x26\xb2\xc3\x06\x09\xf6\x49\x1c\x00\x76\xd9\x60\x1e\xc6\x29\xc3\x42\x75\x76\x46\x52\x5a\xb3\xc5\x5a\x7f\x94\xab\xa2\xe1\x35\x61\x0f\x32\xdc\x3c\x62\xc8\xe2\x45\x7b\x61\xd2\x23\x29\xeb\x91\x69\x8f\x0a\x03\x64\xdb\x29\x8f\xfa\xf6\x56\xff\x5a\x7f\xb4\x52\x35\x5c\xa9\x86\xe1\xa7\x5f\x75\x35\x39\xc6\xd6\x8a\xb4\x52\x91\x96\x2a\xca\x79\x1a\x2a\x0a\xdb\xaf\x0c\xde\x18\x31\x5f\xe1\xf1\x60\x4e\x62\x36\x83\x51\xa9\xed\x3c\x6d\x3d\x1f\x1a\xff\xdd\x3a\x32\x36\x08\xbc\xeb\x5a\x0b\x3c\x45\x6e\xe1\xc1\x35\xf6\x28\xa8\x36\x6d\xdd\x62\xe0\x5d\x1b\xda\x7b\x3e\x16\x03\xfe\x34\x6e\x04\xb4\xc3\x0d\x42\xa4\x9e\x5b\x98\x7a\x69\x59\xcb\x5f\x47\xa8\x7c\x35\xe9\x97\x9c\x9a\x5c\xfe\x66\xad\xad\x89\x83\x83\x36\xde\x43\x84\x90\x24\x76\x3d\xb4\x1b\xc3\x79\x8c\x46\x36\x1c\xc4\xc8\x42\xbf\xf5\xd7\xfe\xb0\xd1\xef\xbf\x07\xbf\xff\x1e\xd8\xce\xa6\xfe\xb2\x6c\xe0\x3b\xd6\xb2\xc4\x0b\x24\x71\x39\xc7\x6e\x00\xae\x88\x49\x37\x97\x71\x8f\x85\x0a\xb1\xef\x22\xd1\xec\xe7\x5b\xf4\xdb\x5a\xff\x8f\xdf\x7f\x0f\x6e\xd6\x33\x67\x53\xfe\xb5\xed\x4d\xcb\x06\x62\xd7\x8f\x26\xbf\x2a\x1f\xf2\xb5\xf0\xfe\xc1\x83\x9c\xd8\xfa\x4a\x92\xdd\x2c\x58\x1c\x49\xd5\xb2\xa3\xaa\xb1\x7a\xb5\x46\xf9\x1c\x6a\xd6\x1b\x95\x7a\x92\xa7\x4c\x39\x6b\xd4\xc8\x1a\x19\x2e\x93\xe5\x7d\xfd\x61\x8c\x42\x84\xc1\xcf\xa5\xf1\x50\x1a\xa2\xbe\x01\x7e\x18\xa3\xea\x00\x84\x7c\xbe\x79\xe0\xfd\x59\xfd\x0d\xb3\xc6\x11\x59\x3f\x1a\x0d\x4d\x0f\x65\xd5\x0c\x5e\x19\x69\x51\xfd\x2d\xa4\x2a\xd1\x1a\x3e\xd1\x1e\x50\xdf\x96\x71\xf0\x37\x18\xfc\x61\x99\x0e\x0d\x6b\x38\xb0\x32\xe5\x8a\x35\x76\xf3\x13\x64\x4a\x11\xb6\x8b\x17\xd7\xa7\x68\x84\x37\x7e\x8c\xed\x0c\x3e\x8b\x7b\x72\xa9\xe9\x62\x47\x58\x1c\xb1\x6f\x1e\x65\xf6\x66\x7f\xd3\x82\x7a\xfa\x7a\x47\x7a\x25\xf5\xa4\xa5\x90\x73\xc7\xf4\x6a\xea\x6f\x03\x10\x3b\x65\x04\x8d\xac\xcf\xb7\x86\x6d\xb4\x69\x81\x85\x06\x3f\xf2\xdd\x54\xfc\x0f\x3e\xae\x42\x4d\x14\xcc\x04\x86\x6c\x03\x55\x8e\x06\xe3\xd5\xf6\xf7\x67\x7e\x34\xd5\xc4\x9e\x71\x75\x4b\xc6\x8d\x4d\x1a\x57\x37\x69\x35\xb1\x23\xbd\x3b\x6b\x69\xee\x2a\x05\x56\x2c\xb3\x7a\x31\x03\x7b\xdc\x5e\xd2\xc8\x4b\x0b\x96\x32\xa7\x48\xdd\xf5\x87\x8a\x01\x65\xc8\x2a\x05\x71\x16\x3e\x5f\x6d\xe7\xcd\x18\xdd\xf0\x13\xc9\xe1\x94\x40\x29\x3c\x81\x35\x14\x61\x5a\x62\x36\x2b\x25\x8f\x44\xce\xc8\xb2\x21\xf0\xae\xab\xe9\x45\x16\x3f\xeb\x1b\x79\xa3\xa2\x4d\x71\xa6\x9b\x0a\x14\x65\xe4\xf1\xdd\x52\xa6\xdc\x54\x14\x85\xaa\xec\xab\x31\x6a\x03\xc1\xd0\xd6\x6f\x78\x9f\xda\x0b\x89\x72\x99\xb0\x10\xb2\xd2\xf8\x2c\x26\x97\x71\x4f\x3a\x42\xb7\x33\xb8\xdf\xc2\x2e\x88\x47\xd2\xa1\xbd\x69\x59\xfa\xdc\x87\x11\x67\x49\x36\x4b\xfb\x72\x30\x1c\xaa\x68\x18\xa5\x32\xcd\x42\xba\x4c\x39\x31\x8f\xa2\xc1\x42\x03\x05\xe5\x79\x75\x35\xe9\x46\xef\x43\xde\x3b\xed\xea\xba\x5e\x00\x6f\xd4\x0b\x88\x7c\x9a\x01\x0d\x3b\x98\x26\x43\xd7\x7a\x4a\x67\x82\x83\xc1\xa6\x39\x88\x53\x60\xa8\x5e\x41\x1e\x3c\x50\x5f\x5a\x27\xdf\xfa\x6c\x55\x1f\x36\x0a\x7e\xf1\x9f\xfd\xd1\x26\x67\x70\xac\xbe\xf5\xa4\xc1\xd3\xc4\x25\xba\x48\x43\xb4\xcb\xcf\x00\xfe\x21\x7d\xa5\xd9\x19\xc4\xc6\x99\xc8\x08\x13\x56\x4d\x3c\xcb\x42\x24\x19\x36\xc3\xf5\xda\xea\x1b\xe2\x3d\xd0\x50\xb3\x8b\x77\xaa\x11\x78\xd7\xa6\xf2\x27\x6d\xe5\xf9\x36\x33\x55\x70\x5a\x87\x24\x36\xde\x9d\xaa\xc8\xbd\x65\xa8\x72\x7f\x2c\x1a\xcc\xb7\x9f\x49\xf4\xc0\x1b\x50\x36\x47\x1d\x12\x92\xcc\xce\x80\x84\xae\x24\x40\x43\x45\x71\x46\x82\xbe\x8c\x24\x29\x19\x6a\x92\x31\xd4\x74\x61\x58\xd9\xf9\x43\xbd\xbb\xbb\x78\x10\xdf\x88\x7d\x6a\x7c\x1a\x83\x36\x1e\xe3\x9f\x7e\xe4\xa8\xb6\xf6\x18\x3f\xfa\x51\xbc\x71\x41\x5a\xad\xa8\xa5\x1e\x9a\xa9\x17\x9c\xfc\xe8\xd7\x9f\xa5\xc1\xbc\x6a\xf7\xab\x70\x0e\xb4\x33\xce\x11\x27\x44\x11\x83\x51\xc1\xf1\xdb\x80\xc5\x31\xfa\x7e\x2c\xb3\x64\xb9\xb5\x11\x8c\x7e\x7d\xfc\xab\x41\xda\xf3\xcb\xe3\x47\xf8\xa7\x1f\xbf\x22\xd3\xea\xc9\x3c\xf4\x3e\xef\xad\x6f\x42\x0b\x55\xca\x74\xff\xe8\xb7\xe1\xde\x2f\xeb\xbf\xe0\x9f\xfa\x02\x28\x12\xdd\x9a\x45\x36\x7e\x7a\x84\x1f\xf5\x39\xb4\xf2\x0b\x65\xa3\xcc\x63\xfc\xa8\xcf\xd9\xae\xfc\xf6\xd9\x28\xe1\x87\xa8\x0d\x47\xf4\xd2\x0c\xfb\xe8\x2b\x8a\xf9\x58\xcb\x58\x97\xc9\x27\x98\x4e\x68\x0b\x4d\xa5\x2a\xb8\xf9\x7a\x29\x28\x88\xdc\xbb\x83\xfb\x2b\x22\xed\x40\x16\xf0\xec\x8f\x0c\x05\x3a\x61\xd9\x0d\xc5\x6e\x08\xf6\x47\x3f\xae\x00\x44\x0e\xc1\xb5\x0a\x04\x33\x18\x9b\x36\x46\x61\x75\xc3\xe9\xec\x8b\xb1\xf3\x65\x2c\x40\x58\x08\x25\xf1\x86\x7c\x37\xce\x05\x2a\xb4\xa4\x42\x1f\x97\x8a\x3e\xe4\x73\xbe\x1d\xc2\xfa\x23\x79\x37\xcc\xd3\x1f\xe3\x47\xb7\x43\x78\x3c\xb4\x85\xf5\x69\x9e\x3c\xc2\x1b\x2a\x39\x75\x3d\xf4\x75\x0c\x2f\xc6\x6a\xbd\x1e\x0a\xf0\xde\x0e\x6d\x50\xb6\xfa\x89\xb0\xd5\x87\xa9\xeb\xa1\x77\x63\x18\xc3\x08\x92\xb5\x91\x0d\x91\x3b\x55\x76\x19\x15\xdb\x3b\xe5\x4c\x9d\x84\x70\xa3\x08\x87\xaf\x09\x0b\x91\x84\x26\x16\x54\x27\x50\x34\x28\x02\x41\x92\xc6\x15\x5a\x83\x95\x42\xff\xc2\xcd\x87\x03\xb3\x32\x60\x44\xa2\x0d\x17\x52\x90\x3b\xe3\xcc\x81\x98\xc5\x97\xb1\xd8\xdb\xb0\x58\x1b\xd9\x4e\x35\x85\xcf\xe7\x42\xce\xe7\x82\xcf\xe7\xb4\x34\x1f\x3e\x9b\x53\x39\x9b\x53\x9e\x57\x02\xd5\xac\x04\x2a\x52\x4e\x2e\x00\x1b\x97\x93\x8b\x75\xf8\x17\xc0\x04\xc2\xd0\x45\x5d\x06\x63\xea\x96\x28\xaa\x33\xd5\x1a\x15\x6d\x63\xdd\x51\xde\x71\x69\x28\x45\x2f\xa9\xa6\xf2\xe3\x2c\xb3\xf5\x11\x7d\x9c\x8a\x70\xd2\x5e\xe8\xa2\xb6\xd7\xa3\x93\x59\x6a\xb5\x4b\xf7\x9f\xd1\xb0\x23\xf7\x58\x98\x30\x35\x15\x17\xc3\xd6\x1a\x07\x24\xee\x68\xef\x24\xc5\x1d\xb9\x1f\x70\x60\xb5\xbc\x25\x34\xb5\x11\xee\xe5\x3f\xed\x1b\x29\xcb\xac\x38\xaa\x3b\x25\x15\xdd\xff\x86\xe2\x65\x57\xb6\x4f\x90\xb5\x35\x21\x22\x80\x5c\x5d\x9f\xd5\xa4\xc5\x59\xf4\xa5\x92\x76\x74\x88\xc0\xbe\x0a\xf1\x10\x5e\xe0\x66\x5b\x8d\x41\x3d\x5d\xa5\x9d\xbe\x8a\x49\xd7\x18\xc7\x07\x82\x68\x93\xfc\x95\xa7\xd9\x39\x9b\xe2\xa9\xf2\x8a\xa0\xe6\x30\x26\x5e\x70\x6a\x98\x83\x0d\xa7\xa6\xd2\x97\x58\xc4\x96\x5c\xad\xf0\x97\x74\x3e\x21\x8c\x0a\x8f\xba\x8d\x1a\x2d\xd0\xf5\x23\xec\xd1\x69\x78\xd5\x0e\x55\x39\xe1\x10\x5d\x19\x57\x5a\xe9\x18\x27\xa1\x8b\x8c\x63\x9a\x12\x3a\xef\xeb\xf8\x83\xab\x4d\x83\x92\x4b\x43\x59\x1b\xa6\x61\xab\x0e\x4e\x12\x36\x54\x91\xcd\xb3\x25\x51\xff\x2a\xe9\x3f\x36\xcc\x96\xad\x8e\x91\x1d\xad\x18\x10\xc7\x6e\x9b\xa7\x4f\x62\xe6\x85\x31\xa6\xfd\x69\x94\x86\xc1\xca\xf0\xc9\xeb\x99\x6a\x78\x28\x25\x60\x45\x61\x7c\x56\xbf\x7d\xbc\x16\xc1\x4b\xaf\x23\x9c\xcc\x30\x66\x26\xc4\x7f\x4e\x90\xa5\x4d\xb3\xe6\xde\x95\x1f\xc4\x83\x09\x21\x2c\x61\xd4\x5b\xf0\x1f\x3e\x99\x3f\xcc\x13\x1e\x6e\x0c\x36\x06\x8f\x1f\xfa\x49\x52\xa4\x71\x96\x63\xe0\x8b\x00\x91\xdd\xdb\x47\xfd\xd8\xc7\x53\xc6\x7f\x46\x61\xfe\x02\x43\x18\x23\x73\x2b\x83\x20\x4f\x7a\x1b\x9e\xce\x38\xf1\x5c\xe4\x29\x27\x64\x61\x65\x30\x0b\xbb\x7d\x66\xf4\x0c\xab\xf7\xb1\x0e\x4f\x03\xa3\x6f\x2d\xc8\x82\x5c\x60\xda\x9b\x7a\x81\x7c\x00\xbf\xb7\xf4\x51\x57\xd5\x0c\x63\x4b\x19\x5b\xad\x54\x9c\x91\x85\x28\xaf\x6e\xff\x8b\xd0\x5e\xb1\x22\x15\x20\x29\x55\x0d\x56\xae\x3a\x91\x00\x2e\xd5\x8d\x56\xae\x1b\xf1\xe5\x2a\xd5\x9c\x56\x6b\x16\xa7\x8c\xe9\x9a\x47\x4a\x72\x51\x0c\xcb\x3b\x0b\xc2\x64\x11\x29\xcd\x05\x19\x07\xb8\x79\xa4\x19\x54\x44\x1a\x67\x81\x71\x07\x7b\xd4\x48\x64\xda\x68\xbc\xaa\x59\x3a\x28\x65\xa4\x83\xb8\xfe\x3a\xcb\xb4\xcb\x92\xc4\xd4\xab\x42\xac\xbe\x8c\x04\xba\xec\x18\xf3\x89\xd0\x7a\x6c\xee\x71\xc7\x0b\x33\xb4\x3a\xb5\xd2\xbd\xfa\x32\xd4\xd8\xd2\x7e\xc9\xf2\xc3\x4d\xd0\xb4\x10\xbd\x68\xd3\x60\x56\x8e\xd0\xce\xed\x4d\xe6\xd0\xcc\x86\xf3\x56\x5d\x67\xb6\xb9\x8f\xa8\x54\x98\xed\x70\xec\xd4\x5e\xa8\xa6\x00\x56\x0a\x66\xa5\x1e\xca\xf1\x60\x3c\x74\x84\x1b\x92\x36\xbf\x50\x06\xe4\xd3\xef\xdc\x6a\x75\x75\x56\x59\xf0\x5c\x11\x96\x36\xd3\x94\x4c\x75\x1f\x85\x88\xe5\x82\xd0\xb8\xa2\x20\xcc\x18\x3a\x69\x9b\x90\x61\x4c\x4a\xe7\xb8\xf0\xee\xdf\x34\x3b\xd9\x3c\x77\x8c\x26\x21\x9b\xe7\xce\x3e\x32\x34\xa9\x0c\x35\xa4\xd2\xa0\x18\x5a\x97\x5a\x7a\x59\xe7\xab\xf4\xbc\xce\x20\x44\x7b\x02\x9e\x52\x01\xf5\xc2\x24\x10\xab\x6d\x90\x0c\xe6\xad\x67\xf9\x8d\x1f\x91\x04\x1f\xa8\x78\x6d\xbc\x6d\x06\x74\x50\x4e\xb4\x21\x3f\x01\xb7\x23\x2f\x49\x1c\x69\xa9\x5d\x24\xa8\xb8\x39\xa2\x32\x91\x61\x67\x54\x70\x41\x5b\x06\xd2\x29\x67\xa8\xa8\x8b\x22\x66\x79\x25\x43\x26\xd9\xad\x9a\x05\xdf\x76\xb8\xcc\x49\xe0\x45\xfd\x89\xe7\x9f\x05\x94\x2c\x7a\xea\xc4\xb8\x08\x85\x60\x73\xd9\xc6\xab\xd0\x27\xce\x1e\xb4\x08\x1f\x8d\x74\x40\xf6\x9c\x07\x67\xef\x26\x02\x0d\x45\x45\x3b\x83\xc9\xdd\x7b\x53\x71\xb3\xef\xde\xd7\x75\x4b\x5f\xe7\x66\x1e\x96\x24\xd8\xc4\xd0\x4c\x7d\x93\x20\xc3\x70\x49\x31\xb0\xbf\x76\x06\x27\x61\xab\xc3\x0a\x79\x00\x9e\x6b\xdf\x38\x82\xd6\x79\x61\x1b\x09\x96\xc0\xd0\x91\xf2\x97\x80\xc3\x43\xb3\x10\xbc\x10\xae\xc3\x16\x9e\x74\x9b\xe7\xb6\x30\x9a\x97\x26\x19\x8c\xc0\xae\xca\x8d\xae\x76\x92\x51\x37\x44\xcf\xcc\x2f\x71\xd5\x9d\x95\x95\x0c\x10\x1a\x0f\xae\x9b\xa5\xd1\x38\x0d\x20\x50\xd3\x59\xc6\xcf\xb1\xa5\x87\xd8\xea\xfb\xea\xfb\xb9\x35\x05\x49\x23\xff\x72\x37\x9e\x85\x6e\x2a\xae\xc5\xb1\x62\x12\x63\x03\xf3\xf2\x8d\xbc\x8b\x44\xa6\x20\xf4\x22\x72\xba\xc2\x5d\xb8\xa3\x8d\x76\x8e\xa0\x81\x1f\xdd\x6f\xec\x35\x04\x0e\xeb\xed\x95\x9e\x5e\x8c\xba\xc1\x21\x3a\x09\x01\x57\x88\x3c\xe0\x9c\x64\x37\xd6\x42\xef\x90\x09\xaf\x24\xe9\x77\x6b\x99\x53\x5e\x46\x91\x72\x03\xaf\x8a\x9a\x2c\xe4\x2a\xa2\x8a\xb9\x51\x42\x6a\x67\x70\xb6\xe4\x52\x52\x3d\xdd\x58\xe3\x24\xd3\x47\x57\x1e\x47\x51\x1d\x4c\xdd\x8e\xfd\xc2\xe4\x2d\x3e\xc5\x57\x0e\x03\x11\xd1\x8a\x2a\xe5\x74\xe9\xd7\xef\xb8\xfd\xa8\x65\x0e\x83\xa4\xd3\x26\x2b\x28\x4a\xb4\x6a\x8f\x1f\xa7\xbe\x2f\x02\x0c\x6b\xf7\x19\x57\x26\xe2\xad\x0a\x3f\xf3\xc2\x28\xa5\x58\x17\x86\xa7\xf9\xad\x6e\x9f\x78\x01\x47\xae\x0c\xb6\xf2\xb4\xbd\x38\x64\xa1\x17\x59\x19\x1c\x86\x1d\xf6\x98\xaa\x07\x61\xb5\x2a\x82\x20\x24\x0e\x83\xc8\x9b\xe0\x88\x83\x34\x09\x23\x1c\xfb\x78\x2f\x70\xb0\x08\x9b\x35\x0b\x27\x52\xbb\x1f\x84\x15\x5c\xb2\xc5\x1c\x02\xa7\x38\xc6\xc2\x0c\xee\x1d\x8d\x1c\x1f\xc2\x40\x86\xa7\x7c\xdb\x76\x04\xdc\xc8\xd8\x61\x40\x05\xe0\x05\x80\x76\xdb\x01\x1d\x8e\x7e\x89\x1d\x06\x53\x42\xe7\x5e\x3d\xfa\x37\x2b\xb4\xad\x2a\xd1\x78\xbc\xc2\xac\x7d\xa4\x22\x00\xe3\x49\x9e\xb4\xae\xc2\xef\x78\x34\x4f\xda\x90\x49\x5b\x8b\x22\xe9\x91\x2e\x55\x44\xe8\xf9\xe9\x89\x0a\xf6\x53\x34\xff\x58\x27\x15\x46\xf0\x3f\xab\xb6\xd2\xd3\x3c\xe9\x17\x15\xd8\x18\x17\x41\x82\x7e\x55\x26\xf4\x7e\x11\xe4\x67\x34\x54\x11\x83\xc8\x45\x91\x36\xaa\xab\x85\x8d\xd6\x39\x08\x0e\x5a\x5e\x81\xf1\x39\xaa\x68\x23\x43\x61\x48\x5c\xd3\x66\x86\xa1\xf6\xde\x51\x53\x80\x86\xa1\x9d\xc1\x76\x73\xf1\x4c\xf1\x9c\xcb\x90\xde\x30\x80\xfa\x80\x6f\xf6\xcd\xf5\x5f\x9d\xf5\x5f\x0c\x40\x1f\x35\xa1\xbe\x31\x6c\x82\x5d\x97\x2b\xc3\x5d\x97\x13\x80\x6f\xc0\x5b\xd7\x28\x03\x5c\xd7\x28\x43\x5c\x97\x2b\x43\x7c\x63\x58\x87\xf8\x86\xf0\x38\x76\x6e\x84\xf8\x15\x7a\x8e\xa5\x76\xc0\x33\x63\xfe\x57\x8c\x8e\x65\xfe\x7e\x35\xdf\x84\xb7\x07\xa4\x81\xb7\x27\x29\xae\xe3\xed\x07\x1c\xd4\xf1\xf6\x64\x96\xd6\xf1\xf6\x19\x0d\xeb\x78\x7b\xec\xb1\x12\xde\xd6\x26\xf9\x73\x96\xc1\x5e\xe8\x5e\xa1\x91\x0d\xaf\x43\x77\x84\x37\x7e\xdc\x0b\xe1\x65\xe8\x3e\x1e\xfe\xf8\x3a\x84\x23\xf1\xf1\x32\x84\x9d\xd0\x5d\x7f\xf4\xe3\x51\x08\xef\x42\xf7\xe7\x1f\x77\x42\x78\x6f\xd8\xba\xf2\xcc\x7a\xc9\x21\xd3\x7f\x89\x85\xc3\x6b\xf7\x48\xfc\x3a\x12\xbf\x88\xbb\x23\x7e\xed\x88\x5f\xbe\xfb\x4e\xfc\x7a\x27\x7e\xa5\x2e\x3a\xe7\x58\xd3\x3f\x0f\x11\xb5\xfb\xfe\x8f\x47\x61\x9f\xfc\xf8\x32\xec\xc7\x3f\xbe\x0e\xfb\xf8\xc7\xbd\xd0\x7e\xb8\x13\xde\x0e\x61\x5c\x0e\xb3\x92\xeb\x0d\xa7\x52\x67\x57\x49\x19\x76\x51\xda\xa1\x1b\x77\x80\xd8\xc3\x9f\x6f\x25\x6b\x75\x50\xde\x06\x3f\xdb\x79\xdc\x66\x43\xb5\x94\x57\xe2\x75\xf2\x1a\x29\xfc\x2c\x82\x61\xe8\xae\x2e\x31\x3e\x73\xc6\xe2\xc5\xc8\xbb\xe6\x1f\xea\x11\xdd\x6f\x3c\xaf\xc4\xb5\x47\x9c\xea\x51\x55\x75\x2d\xf1\x2c\xe4\x57\xe2\x96\xab\xfe\x1a\xcd\x6c\xc0\x3f\x52\x38\x0f\x51\x2c\xd4\xb5\x6d\xf8\x60\x56\xf6\x30\x6d\xe4\x83\x62\x14\x39\x8e\xec\x85\x7a\x17\x55\x92\x5f\xab\xe4\x03\x31\x95\x3c\xf9\xa5\x4a\x7e\x41\xd2\x62\x3b\x1f\xa9\xc4\x9d\xd2\x76\xde\x09\x35\x1e\xe3\xb3\x22\xc0\x59\x98\x23\x64\x83\xe1\xe9\xed\x85\x3f\xe2\xf2\x7b\xe9\xda\x6b\x9e\xa0\xbe\x5f\xca\x4c\x3e\x96\xb5\x23\xfe\xcd\x21\xbd\xb6\xc3\xbf\x02\xef\x7a\xed\x1d\xff\xe0\xeb\x91\x65\xf0\xc2\xb8\x45\xdf\x87\xe8\x43\xa8\xc2\xc3\x85\x4b\x43\x38\x88\xa5\x65\x62\x5d\xa9\x5c\x54\xac\x17\x35\xd6\x8b\x4a\x2a\x8b\xda\x1d\xc5\x61\x07\x47\xcc\x2b\xce\xff\xaf\xf9\xf9\xad\xc0\x9b\xc1\xf3\x52\x52\xb1\x48\x19\xbc\x09\x5b\xfd\x75\x23\x34\xfa\x69\xe3\x47\x44\xd7\xf2\x50\x02\x42\x63\xba\xbf\xe1\xfc\x6a\xdb\x6b\xeb\xf6\xc3\x9f\x6e\x87\xf6\x1a\xee\x8f\x80\xb8\xac\x5f\x2a\xf4\x8f\xd1\xe6\xc8\x11\x8f\xc1\x2a\x91\xa8\xd7\x67\xe2\x90\xfe\xc6\xaf\xbf\xda\x0f\x1f\x0d\x87\xb7\x43\x48\x5d\xd2\x7f\x34\x1c\xfe\xe8\xeb\x25\x1a\x3d\x7a\x3c\xfc\xf5\xe7\x1f\xfd\x35\xb4\xf1\xf8\xa7\x1f\xd3\x35\x94\x3e\x7c\x74\x3b\xb4\xfb\x28\x7d\x38\xe2\x35\xec\xb5\xd8\xee\xff\x3c\xfa\xf5\xd1\xe3\x5f\x32\x1b\x3e\x75\x71\x24\xd2\x33\xc4\x6e\x28\xfc\x97\x94\x1e\xc1\xff\x31\xdc\xe4\x17\xde\xa9\xeb\xa1\xb7\x30\x82\x10\x6d\x87\x20\x82\x27\x62\x1b\x22\xd7\x43\x6f\xf8\xcf\x31\x4c\xf3\xeb\xda\x87\x10\x7d\x09\xd1\x4d\x79\x2d\x78\xd5\x21\xfc\xfa\xeb\xaf\x90\xe6\xfa\x6d\x32\xed\xa7\x5f\xc1\xcf\xd5\xe2\xf2\x24\xa2\x14\xe9\x64\xc2\xfa\x06\xc4\x52\xe9\x2e\x02\x81\x07\x43\x69\x21\xfd\xca\x88\x57\x01\xfa\x14\xc2\x17\x4e\xd9\xe0\x85\xf8\xf7\x83\xf8\x57\xd0\x3a\x10\xf4\x0f\x04\x4d\x84\x97\xea\x04\xf9\x6c\xda\xae\xaf\x4a\x17\x50\xa4\x4f\x9b\x3e\xb5\x1f\xbe\x0c\x6f\x87\x19\x7c\xac\x9c\xd3\x65\xcb\xef\xe5\xd4\x82\x72\x7a\x7e\x1e\x0a\xdd\xdc\xcc\x86\xfb\xed\x6f\x44\x1e\x7a\x11\xc2\xd7\x10\x3e\x0b\x92\xfc\x39\xd4\xfe\x9d\xe1\x65\x68\x03\xf3\xdc\xdd\x10\xa8\xe7\xee\x87\x80\xbd\x56\x47\xd8\x9e\x3c\x06\xa8\xd7\x50\x98\x8b\x01\xf3\xc5\xfd\x79\x2d\xee\x63\x27\xee\x63\xbe\x0d\x30\x12\xf6\x56\x5e\x3d\xfa\x19\xe3\xc7\xd0\x3b\x8c\xb0\x67\xaf\xed\x88\x3f\x15\x93\x89\x2f\x22\x49\x2a\xf0\x6c\x0e\xfb\x88\xf5\x47\x8f\x1e\x0d\x6d\x67\xd8\x67\xfc\xbe\x4c\x3c\xf7\x73\x08\xbe\x67\x80\xb3\x98\xe2\xf3\x10\xd8\x5a\xec\xfd\x78\x9f\xcf\xc4\x06\xec\x12\x0f\x35\x82\xc1\xc4\x9e\xbd\xc9\x31\x42\x82\x04\xf7\x63\x8f\xc3\x02\x52\xcf\x45\x1e\x5a\xc6\x68\xf7\x7c\x0f\x09\xc4\xa8\xe6\x72\x58\x0a\xfd\x8a\x4f\x18\x46\x36\x48\xa6\xf7\x26\xf0\xae\x8f\x67\x84\x56\xe3\x06\x2e\x61\x1c\xc4\x77\x83\x77\x10\xdf\x0d\xf6\x41\x7c\x37\x38\x08\xf1\xdd\x60\x22\xc4\x77\x83\x8f\x10\xdf\x35\x56\x42\xea\x03\x64\x7c\x9f\x1c\x72\x46\xff\x8e\x83\x0f\xbc\x6b\xf3\xf8\x93\x22\xa7\x36\x87\xb8\x9c\x57\x9b\x09\x2d\x65\xd5\xa6\x53\x64\xd4\x66\x94\x52\x91\xd5\x9c\x16\x4f\xce\x32\xa9\x38\xb1\xda\xca\x94\x18\x64\xf1\xdd\x60\x91\xc5\x77\x83\x37\x16\xdf\x0d\xee\x58\x7c\x37\xf8\x63\xf1\xdd\xe0\x90\xc5\x77\xe3\x72\x22\xbe\x1b\xf7\x13\xf1\xdd\xe0\x98\xc5\x77\x83\x67\x16\xdf\x0d\xae\x59\x7c\xd7\x01\xb6\x83\xfd\x1c\x5a\x2b\x61\x42\x0d\x58\xc2\x4c\xd8\x08\x30\x5a\xca\xaa\x41\xcd\x9f\x99\xe1\x16\x46\x77\x81\x1c\x36\x83\xee\xda\x0c\xbb\x34\x61\x66\xf0\x29\xd3\x5a\x23\x10\x49\x91\x53\x03\xa4\xaa\xd4\x84\xa6\xcc\x90\x5b\xeb\xf5\xf4\x80\xc3\xf5\x43\xc8\x66\xc7\xe9\x74\x1a\x5e\x39\x4b\xe2\x9c\x16\x17\x38\x09\xed\xde\x48\xb7\x3c\xd2\xc3\xef\xad\xe7\x69\xeb\xa5\xc4\x3c\x2d\x0e\x74\x52\x91\x56\x24\x6e\xe8\xb4\x0d\x9a\x97\xcb\xd3\xd6\x8b\xc4\x8d\xbc\x93\x0d\xd1\x49\xc3\x0d\x9c\x7e\xea\x3c\xe3\x27\x86\xc5\x66\x56\x99\xb7\xee\xb1\x4d\x0f\x5d\x53\x78\x54\xf2\x4d\x09\xd8\x96\xfa\x4f\x4a\x48\x70\x23\x02\xa3\x5a\x3f\xf4\xe7\x0f\x7f\xe8\x07\x0f\x7f\xf8\x64\x41\x44\xe2\xd3\x1d\x99\xba\x05\xbd\x1f\x9e\xf6\x7e\x08\xa0\xc7\x33\x58\x38\x17\x45\x5f\x38\x3f\x1c\xf4\x7e\x58\xc8\x92\x27\xa5\x44\xe7\x87\x63\x91\xce\xdb\xd4\xe9\xba\xdd\xde\x0f\xfd\x3d\x5d\x6f\x1a\xd2\x84\xed\xf0\x85\xe1\x8c\xad\xf3\x46\xf0\xf2\x63\xaf\x5d\x9c\x53\x79\xa1\x7a\xf8\x78\x58\xbb\x53\x30\x78\x3c\xb4\xb3\x0c\x42\xaf\x4d\x92\x6e\x78\x55\x12\xa0\xe1\x47\xcb\x19\x92\x8f\x4a\xe0\x99\x46\xd0\x2b\xdb\x9d\x94\xab\xae\x03\x13\x60\xe7\x1d\x27\xc6\x9a\x0d\x51\xc2\xba\x0d\x43\x7b\x73\xb4\xee\x54\x13\x33\x98\x36\x07\x2e\x51\x72\xec\xa1\x5d\xe1\xdf\x55\x86\x41\x91\x71\xba\x46\x4d\x05\xf2\x92\x79\x61\xae\x66\x5e\xd2\x29\x0f\x91\xe7\x95\x02\x4c\x71\xd6\xac\x6c\x50\x57\xcf\x16\x6e\x11\x32\x1b\x22\xe3\xb4\x42\xf4\x0c\x4e\x44\x98\x87\xc0\xeb\x08\xcd\x2a\x4c\xec\x7a\x16\x44\x1e\xfa\x84\xe2\x92\xad\x8d\x6d\xdb\xfa\x5e\x45\x14\x35\xfb\x94\x5f\x6e\x3c\x14\x7a\x05\xc2\xf2\xc1\x70\x3e\x45\x07\x2f\x2f\x07\x39\x3f\xe3\x4b\x20\x8a\xaf\x37\x8b\xab\xf2\xf3\x52\xf9\xea\x14\x99\x87\x5e\x94\x4b\x8e\xcd\x45\x7b\x86\xa2\xfd\xa2\xe8\x19\xaa\x67\x3e\xcd\xf3\xd8\x80\x73\x26\x83\x9c\xa4\xab\x72\xb2\xd8\x7f\x15\xe5\xe6\x14\xb5\x14\x55\x65\x27\xc6\x26\xc5\x99\x5a\x6d\x73\xd2\xd6\x66\xb9\xac\x2a\x1c\xb4\x42\xe6\x43\xa9\xc9\x7e\x50\x9a\x6a\x25\xe3\x3f\xcb\x0d\xa8\xbe\x4c\xa4\x16\xee\x8d\x2a\x2d\xe2\x56\x30\x97\x4b\xfd\x27\x5e\xb5\xf5\x61\xa5\xde\x56\x1d\x54\x8a\xb1\x42\xef\xcb\x70\xda\x32\xc0\xa9\x5a\x50\x95\xf4\x0c\xcd\x49\x58\x56\xda\xf3\xcc\xed\x95\x4b\xaa\xa2\x2f\x5a\xa1\xfe\xae\x0c\xdc\x17\x25\xa8\x97\x33\xce\x5a\x81\x57\x2e\xb5\xd7\xda\x49\xe2\xa9\xe6\x74\x47\x7b\xa5\x8e\xea\x99\x51\x6b\x67\xf5\x92\x85\xe0\x50\x92\x21\x91\xc9\x09\xdb\x3f\x86\x9b\xd6\xd6\x81\xe5\x58\x47\x07\xea\xf8\x3e\xea\x2a\xea\xcd\x2d\xc7\x5a\xcc\x35\xf3\xd1\x3a\x8d\x9d\xd2\x64\x8f\x5b\x4b\x1d\x95\x4a\xed\x57\xe9\xcb\x46\xb9\xdc\xcb\x52\xb9\x1f\xf2\x72\x44\x26\x7c\x2d\x35\x3f\xf5\xa4\xc9\xb0\xcc\x71\xea\x59\x8e\xd5\x34\x4c\xb6\xc4\xbb\xce\xc2\x73\x0f\x62\x64\xfd\x80\xae\x6f\x3f\xdd\xce\x6f\xc7\xf3\xdb\xfe\xfc\xf6\xe9\xed\x7f\x3d\xbd\x9d\xdc\xfe\xd7\xe4\x36\xb8\xed\x07\xb7\xfd\xff\x0c\x6e\xf1\xed\x7f\xe2\xdb\xad\xdb\xff\xda\xba\xf5\x6e\xff\xcb\xbb\x7d\x71\xdb\x7f\x71\x7b\x76\xbb\x77\xdb\xdf\xbb\x8d\x6e\x17\xb7\x47\xb7\x07\xb7\xc7\xb7\x3f\xdc\xee\xdf\x7e\xbd\x75\xbe\xda\x96\x0d\xb3\x2e\xfa\x4b\x3c\x14\xe7\x9c\x80\xb0\x4a\x7d\x16\xc3\xc2\x03\x0f\x05\x9e\x38\xf7\x42\xf4\x31\x04\xd2\xa7\xc2\x71\xa9\x08\xdf\x76\xe1\xb5\x7b\x47\x4b\xd0\x8c\x57\x23\x1e\x5f\x30\x15\xee\x6d\xbe\xbc\xfc\x50\x97\x3d\xf5\x5c\x14\xa2\x0b\x0f\x52\x0f\xac\x1f\x3e\xf5\x7f\x98\xf7\x7f\x08\x4e\x7e\x50\x6c\xc3\xe0\x87\xfd\x1f\x9c\xaf\xc2\x30\xbb\xa3\x88\xd1\x90\x56\xbf\x92\x5b\x96\x08\xca\x68\x1d\xcf\x48\x1a\x05\x3d\xe5\x59\x54\x78\x15\x15\xce\xdd\x5f\x30\xb8\x46\xd6\x07\x4a\xe2\xd3\xde\xde\xf1\xeb\x5f\x1e\x0f\x47\x3d\xc9\x04\x89\x6e\xdf\x19\xe3\x70\x1f\xa3\x54\xc9\xbb\x3e\x8e\xb5\x6b\x87\x89\xf1\x54\x8c\x43\x34\x0e\xd1\x53\x59\x08\xae\x8d\x65\x3c\x34\x57\x93\x53\x73\xb2\xf8\xed\x5d\x34\x7f\xb2\xa4\x82\x82\x46\x51\xe1\xb2\xe5\x6c\xd6\xa7\xfa\x89\x27\xe2\x12\x17\xd6\x6d\x3d\x0b\xae\x3d\x35\xbc\xb3\x15\xa6\x70\xec\xb9\xcb\x9f\xa2\xb5\x0b\x9e\x9f\x7e\x7a\xfc\xeb\xfa\x63\xbc\xb1\xe2\x9b\x78\x20\xaa\x09\xd3\x83\x15\x6b\x28\x5f\x46\x8f\x57\xae\x20\x95\x0f\x1f\xe3\x47\x2b\x96\x4f\x44\xf9\x51\x75\x0a\xb9\xae\x21\x5c\x79\x6e\xc9\x8f\xac\xf0\xbe\xde\x26\x30\xfa\x91\x66\x36\x7c\x4e\x81\x8e\x51\xdd\xf2\x58\x8b\x95\xf3\xd5\xca\x5b\xdc\x4d\xa5\xb1\x9f\xf4\x27\x3b\x1e\xca\x15\xb0\x6d\xbb\x70\x85\xdc\xa9\x23\x42\xed\xcc\x46\x25\x17\xf4\xb6\x0d\x4f\x3d\xd7\xc0\xbb\x56\x02\xa6\x6e\xee\xa3\x09\x45\x5b\x31\xf2\x0c\x5a\x76\x65\x37\x73\xe3\x11\x10\x97\x82\x8c\x42\x08\x69\x39\x4a\x94\x01\x98\x32\x8e\xe7\xc3\xf8\x76\xc8\xf9\x5d\xbf\x64\x22\xea\x43\xf9\xce\x22\x8a\x94\x91\x54\xf0\xb8\x72\xfc\xb5\x47\x83\xd8\x2e\x59\x51\x54\x16\x4e\xac\xdb\x53\x44\x35\xc0\x6c\xe7\x3c\x83\xad\xca\x72\xa9\x4f\x57\xc2\x39\x44\x1f\x5a\xd7\x4e\x08\xfb\x86\x02\xea\x5f\x04\xd4\xaf\x3c\xdb\x86\x77\xa9\x0d\x87\x2d\xfb\xad\x4c\x56\x82\x94\x8a\x77\xe1\x32\x5d\x39\x48\x61\xcb\x13\xa6\xe8\xf0\xd6\x73\xdf\x7a\xc2\x49\xff\x5b\xef\x37\xeb\xd6\xb1\xfe\x70\x27\x28\x8a\xdb\x24\x89\x14\x31\x3b\xe3\x87\x2c\x5f\x88\x5d\x93\x20\x2e\x44\x81\xf6\xd7\xb9\x19\xa2\x13\xe9\xde\xd3\x61\xcd\xeb\x01\x2f\xe5\x2d\xc2\x87\x17\x23\xcb\xce\xe0\x80\x03\x27\x8e\x0d\x98\x79\x5a\x92\x38\x2a\xa7\x80\x4a\xe9\xc6\x8f\x25\x5a\x3a\xa4\xe2\x79\x60\x3b\xa7\xb5\x01\xf6\x49\x80\x7b\xfc\x8e\xd8\xb3\x6a\xb7\x8b\xbc\xb8\xd3\xb3\xa4\xcb\x03\x41\x61\x4e\x62\x1b\xb6\xbd\x6e\x97\xed\x97\x3e\xba\x99\x63\x36\x23\x81\xc3\x94\xd6\x42\xe2\x50\x48\x69\x54\x28\x2f\x48\xf3\x70\x67\xe2\x23\x62\x8b\x4b\x2a\x49\x99\x73\x0e\x97\x21\x9b\x6d\x53\x1c\xe0\x98\x85\x5e\x94\x38\xf7\x46\x42\x77\xe9\xbc\xfd\x92\x88\xb6\x3d\xb0\x76\x76\xf7\x77\x4f\x76\xad\x6a\x28\x0a\x38\xf1\xa5\x14\xf7\x59\xc7\x91\x27\xeb\x1f\xbd\x3e\x3e\xa9\xd7\x56\x67\xe0\xfe\x92\xae\x9f\xef\x36\x6a\xea\x7e\xf7\x8c\xe8\xf7\x9a\xa1\x10\x8d\x63\x08\xd1\x2c\x06\x4b\x5a\x7f\x0b\xb0\x0a\x7c\x7b\x6d\xc2\x19\xf3\x9b\xd6\x89\x84\x5a\x21\x0d\x94\xbf\x7b\xf8\xca\xc7\x38\xc8\x45\x9f\x87\x98\x5d\x12\x7a\xb6\x2b\x3a\xca\xc5\x30\x32\x51\x19\x9f\xab\x6b\x90\x17\x1c\x33\x8f\xa5\x89\x65\x78\xa3\xe2\x37\xc3\x32\x19\xc0\x83\x44\x94\x1d\x70\x0c\xaa\x9f\x59\x79\xe6\x5c\xa9\x65\x72\x58\x20\xa5\x90\x63\xe7\xbd\x1d\x79\xd7\x11\xf1\x02\x83\xbf\x18\xeb\x5d\xe1\x3f\x40\x99\xe5\xe0\xde\x94\x92\x79\xcf\x5b\x84\x39\x42\xb6\x8b\x56\xac\x03\x2f\xe2\xfb\x19\x07\x3d\x8e\x75\xba\x42\x96\xc1\x4b\xcf\x3d\xf6\x4d\xf1\x7f\x6a\x51\x72\xd4\x16\xba\x0a\xd1\x6b\x4f\x11\x77\xe7\x38\x94\x5f\x99\x0d\x47\x6d\x97\x7f\xad\x6f\x9c\xab\xbe\xd4\xf5\x8d\x33\x1b\x76\x3c\xf7\x53\x8a\x84\x3f\x7a\x1b\xde\x19\x91\xe4\xac\x12\x5a\xbf\x1a\x84\x64\x2c\x02\x93\x1c\x4b\x1f\x43\xef\x8d\x07\x46\x88\xde\xa6\x70\x45\x91\x65\x29\xaa\xe8\x8f\x4d\x3e\xf9\x73\x0a\x5b\x25\xb6\x2d\xf8\x5e\x75\xe7\x93\xd9\x7c\x22\xad\x61\x21\x8b\x90\x29\xbf\x5b\x76\x7b\xe1\x7b\x43\x63\xac\x88\x10\x7d\x12\x63\x36\x54\xc8\xcf\xce\xc2\x81\x7c\xb5\xa7\xa6\xee\x15\xdf\x57\x1f\x38\xfd\xfc\x9e\x70\x30\x4c\x36\xfe\xc2\x33\x38\x35\xa1\x46\xd5\x6b\xbf\xe9\x98\xd5\xf2\x22\x4c\x59\xec\xcd\xb1\x55\x1f\xa6\x13\xa2\x8f\x60\x5c\xca\x56\x26\x42\xfb\x43\xfb\xc7\x90\x1f\x80\xb0\x45\x85\x64\x4b\x79\x8f\x06\x4b\x9c\xcc\xe2\xd9\xd7\x88\x62\x6f\x10\xb3\x37\xf7\x39\x8a\x68\xa3\x8d\x95\xc7\x6a\x0b\xb5\x71\xe9\xc9\x00\x2c\x49\xb8\xbe\x9a\x09\x57\x2e\x5c\x96\x4a\xde\x4d\xa7\xd4\xe7\x0e\xcb\xe0\xb9\x11\x8b\xf7\x90\x51\xb1\x7c\x45\xf4\x84\xca\x51\xea\x5a\x36\xcc\x7d\x21\x35\xb4\x33\x78\x63\x5c\x45\x61\xca\xca\x18\x9c\xa2\xe7\x5e\x5d\xf9\xd4\xc8\x7e\x4a\xed\x31\xc9\x18\xef\xa3\x0b\x8a\xce\x84\x17\x9b\x7b\x23\x4e\x01\x67\xe4\xf2\x58\x15\x90\x47\xe7\x8a\x9a\xa7\x4a\x07\xad\xb5\xd1\x5c\x4b\xed\x0e\xad\x4e\xc3\x88\x29\x87\x92\x5f\x39\x21\x66\xf8\x8a\xad\x6c\x51\x84\x7d\x1c\x5e\x94\x6b\xeb\x94\x55\x5b\x90\x36\x7e\xd2\x96\x40\x7c\x1b\xd9\xf5\xda\xab\xe9\x17\x14\xdb\xd2\x23\xdc\xea\x2b\x6e\x09\x67\x45\x57\xd2\x77\x7a\x6c\xdb\x8e\x65\x65\xf0\xc9\x73\x6f\x44\x20\x85\x73\x10\x9d\x3b\xe7\xa0\x27\xe0\x9c\x43\x79\x99\xd4\xcf\x42\x0d\xf0\x3c\x83\x57\xdd\xbc\x8e\x6c\x99\xa9\x96\x69\xd1\x32\xae\xb6\x1c\xd7\x5a\x16\x4a\x9b\x9f\xdb\xf9\x92\x9b\x33\x7c\xed\x30\x20\x8b\x8a\xc6\x26\x7c\xcc\xef\x77\x42\xab\xf3\xc0\x63\xfe\xcc\xca\xe0\x7e\x9e\xbc\x7b\xce\x39\x90\x64\x85\x5b\xa0\xfb\xdf\x62\x45\x3e\x7a\x2b\x2e\xe2\xbd\xff\x2e\x93\x81\x43\xc2\xca\x23\x58\xb1\x0d\x57\x34\x71\x7f\xe5\x2e\xdd\x5a\x97\x7c\x76\x26\xdc\x01\x9a\x74\x50\xe5\x5e\xf9\xae\x72\x86\xaf\x2b\x32\x76\xe1\x52\x2e\x44\x7b\xb0\x15\xc3\x27\x74\x77\x1a\x9c\x5f\xe4\x00\x0f\xc8\x02\x9e\xc6\x92\x06\xb3\xc4\x96\xf7\x40\xdd\xd3\x7f\x58\xff\x51\xb9\x33\x89\x45\xe5\xa9\x72\x17\xe3\xae\x09\xe4\x41\x09\xc4\x89\x62\x59\x4e\x79\x02\x2b\xef\x8d\x1b\xbd\x37\x40\xf0\xfa\x9f\x81\x26\x80\xf9\x20\xad\x8c\x5f\x30\xe2\xc4\x35\x33\x04\x55\xde\xe0\xb3\x67\x83\x87\xe6\x63\x78\xe7\xf1\xff\x5e\x8a\x78\x45\xdf\x74\x69\x7e\x5d\x5c\x9a\x05\xb4\xcc\xa6\x34\xa6\xfb\x60\xb5\xb5\x13\x71\xff\x3e\x90\x5e\x3c\xe1\xbd\x10\x97\x94\x52\x32\x75\xc3\x96\xa0\x06\x92\xb4\x5f\x32\x4f\xf8\x82\x4d\xc6\xf0\xc1\x83\x38\x51\x57\x48\x3f\x69\xe5\xe1\x0f\x52\x20\x89\x3c\xfc\x52\x53\xab\xcb\x46\xfd\xc1\xb3\x79\x3f\xe2\x2f\xef\x6a\xdc\xd9\x55\xaa\xba\x0a\x13\x37\x40\x5e\x0c\x87\x21\x34\x2e\x84\xaa\x8a\x1f\x8b\x13\xa3\x72\x29\xe1\x55\x17\x3c\x9d\x5f\x3a\x4a\xda\xd0\x16\xcc\x63\x74\x12\x2b\x6c\xe5\x99\x52\x39\x3a\x4f\x97\xb5\x2e\xea\x51\xa8\x2c\xc9\xe1\x1b\x7c\xfa\xe4\xc7\xe2\xd3\x6b\x53\xee\xb0\xc1\x4d\x64\xe2\x56\xc9\xbb\x0f\xe2\x96\x4b\xfe\xbd\xb2\xc4\xe4\xfc\x1b\xc6\x94\x1f\xab\x77\x1c\x94\x06\x8a\x56\x07\xb7\xe0\xc0\xd3\x69\x85\x5e\xf8\xdb\x7d\x4b\x4e\xc1\xe3\x78\xc0\xf3\x02\x8f\x79\x96\x9c\x51\xc0\x4c\xb1\x13\x3b\xe5\x07\x48\xbe\x51\xda\x70\x1a\xa3\x50\xec\x8d\x24\x69\x75\x08\x7c\x25\xc5\x09\xed\x86\x53\x39\x4f\x9d\xdf\x8e\x04\x67\x97\x58\xf0\xc6\x43\xd4\xe4\x4b\x5d\x6f\xdb\x97\x1e\x0a\xd1\xbe\x07\x18\xbc\x44\x06\x5d\x32\xa2\xa8\x2e\x56\xa6\x39\xd6\x43\x7d\x14\x26\x96\x06\x98\x04\x0a\x9f\x13\x87\x8b\x71\xbb\xbf\x0d\x81\xc1\x76\xac\xe4\xab\x02\x2d\xed\x0c\xa2\xc4\x7c\xc9\xd9\x1b\x03\x85\x3d\x73\xa0\xfe\xe5\x88\x04\xd6\xd4\x8b\x12\x6c\xc1\x85\x64\x9c\x79\x4f\x01\x5f\xc0\xf3\x31\xbc\xe2\xb3\x11\x31\x0b\x36\xff\x29\xcf\x89\x3b\x7d\xbf\x1d\x23\x0d\x64\x1b\x5e\x8f\x91\x66\xc0\x6c\xf9\x4b\x39\x3d\x90\x3f\x72\xfe\xca\xb6\x21\x4a\x50\xc1\x55\xaa\xdf\x05\x47\xc8\x11\x61\xa1\x06\x68\x7a\xf4\x46\xaf\x3c\x60\x70\x2e\xff\x2f\x2e\x02\xd5\x11\xa9\x96\x1b\x63\xb2\x61\xc6\x5b\xcd\x43\x34\xd4\x0b\x1f\x8c\x6d\xb8\xe8\x2c\x51\xce\x3a\x18\x8b\x5c\x1c\x84\x4c\xb4\x3d\x6f\x1f\x71\x9d\x4a\x85\xe8\x19\xf8\x9a\xce\x2d\xed\x2d\x9f\x57\x8c\x2f\x1b\x53\xb2\xe1\xb4\x05\x69\x56\x3e\x30\xff\xcf\x43\xdd\xe7\xc3\x18\x5f\x6e\xca\xb6\x5d\x4b\x5c\x23\x92\x65\x27\x9e\x87\x3e\x7b\x42\xe8\x00\xf7\xc5\xdf\x91\x9d\x01\x95\xd8\x3c\x49\x5c\x31\x21\x49\xac\x6c\xb8\x4e\xdc\x1b\xf9\xcc\x4e\x93\xf2\x46\x84\x89\xe7\x9f\x89\x68\x4b\x47\x14\x27\x09\x0e\x9c\x7b\x23\x50\x05\x4f\x38\xdb\xc9\xb9\xdb\x93\xc4\xe4\x38\x5b\x31\x91\x79\xab\xac\xd9\x16\xad\x34\x85\x4b\x92\xda\x43\x42\x16\x56\x66\xc3\xa5\x69\xb3\xab\x32\xef\x84\x4f\x9f\x83\xa2\x85\xdc\x6a\xe7\xac\xa3\x96\xe8\x3b\x8c\x4f\x9f\xea\xc1\xe4\xb5\x8e\x9b\xf4\xad\x52\x73\x07\x47\x98\xe1\x67\x62\x09\x54\xaf\x65\xd3\xe7\xcc\x86\xab\x25\x2d\x6c\x05\x41\x57\xf5\xa7\x89\x7b\x13\x85\x09\x73\x5e\xc6\x30\x0d\x71\x14\x28\x08\xcb\x1f\xd5\x75\x51\x3a\x11\x95\xb4\x29\xf1\x53\xb5\x44\x14\x27\x69\xc4\x92\x17\xe4\x02\x53\x99\x62\x5e\xc8\xeb\x09\x3e\xc6\x91\x10\x72\x89\x31\x09\x19\x78\xb2\x92\x87\x23\x31\x52\x56\x1a\x28\xd5\xe3\xc4\xf9\xe8\xe2\x66\xb7\x24\x1f\xa6\x5f\x1f\x65\x6a\x1a\xd0\xd8\x80\x15\x87\x4b\xb1\xe2\x99\x1e\x55\xbe\xba\x6f\x3b\xea\xbc\xad\x8c\x23\xaf\xb2\xdb\x51\xe5\x19\x9f\x44\x5e\xf2\xe0\x9b\x10\x6e\xbb\xa3\x96\x04\x42\x5e\xf4\x7c\x45\xdc\xc4\x51\x50\x43\xaa\x67\xab\xe0\x64\xb3\xda\x7e\xe2\xde\xe4\xa7\xe7\x72\xcc\x2b\x63\x6b\xa2\xd6\xef\x6d\xf5\x86\xfb\x36\x6f\xcd\x84\x9f\x19\xec\x25\x4b\x0d\x03\x8a\x01\xb1\x7c\x18\xb4\xd4\x39\x6e\xf6\x1d\xd7\xfa\x26\xf5\xae\x7d\x03\x7e\xbd\xce\x2f\xaf\x4f\xa3\x94\xea\xca\x12\x4c\x19\xbc\xbc\x3b\x26\x1d\xad\xbe\xd2\x3b\x5d\x48\x27\x88\xc7\xd3\xeb\xb7\x85\x38\x44\x56\x7a\x97\x0f\x78\x37\x08\x59\x3e\x5b\x2b\x83\xf7\x4b\xb7\x4a\xa3\xb1\x0f\x9d\xf3\x53\x4d\x3f\xc3\x1c\xfc\xc5\x0c\x5f\x2c\x5f\x3d\xc9\x8c\x08\xa3\x44\xd9\xc8\x53\x8f\x3a\x54\x8a\x2d\xf8\x27\x06\x79\xbc\xf1\xef\x18\x98\x37\x71\x08\x78\x3e\x0b\x2f\xf0\xde\x32\x0b\x8f\x63\xcc\x4e\xbc\x49\x61\xe2\xf1\xa5\x13\xde\x6c\x4b\xb4\x9a\x8f\xfd\x6b\x47\xe9\x13\x72\x7a\x1a\xe1\xbd\x92\x44\x4c\xd6\x79\xbe\xb4\xce\x71\x21\x99\x93\x55\xde\x74\x54\x39\x48\x4e\x9f\x11\xfa\x5c\x81\x22\xaf\xf2\x69\x69\x95\x67\x1a\x64\x79\x9d\x57\x4b\xeb\xbc\x2d\xe0\x9f\xd7\xfa\x9c\x63\x90\x58\xd9\x2d\xc9\x38\x66\xf0\xb1\xa3\x35\x59\xa8\x8e\x09\xf7\xf3\x96\xc4\x74\xf8\xba\x64\xc0\xa6\x6e\x05\x87\x65\x2a\x9d\xba\x1a\x2b\xb6\xc2\x0a\x5a\xec\x27\x05\x5e\x3c\x4d\x4a\x88\x71\x9d\x08\xcc\x60\xd3\x02\x35\xce\x33\xc0\xd3\xa5\x86\x7f\x6a\xcd\xf5\xe3\x93\xac\xad\xb5\x8b\x70\x2c\x6c\x7b\x75\xe6\x42\xfd\xae\x6b\xe5\xe0\xab\x45\xc8\xb7\x75\x96\x41\x3c\x75\x3d\x74\x16\xc2\xbd\x11\x58\x16\x58\x96\x0d\x64\xea\xae\x70\x6a\x86\x81\xc3\xc0\xa7\xd8\x13\xf7\x40\x87\x82\x8a\x73\xcb\x69\x97\x36\xf7\x8d\x01\xc7\x81\xb4\xfb\x95\x7e\x0b\x83\x2d\xe6\xf8\x90\x73\x52\x29\x48\xbe\x4d\x9e\x8d\xfe\xd4\xb4\x42\xbc\x04\x16\xeb\x91\xe6\xa0\xdf\xd5\xc3\x87\xf1\xd4\xe5\x23\xb1\xac\xd2\x50\xf8\x0f\x35\x16\x4e\xc4\xf5\x60\x86\x7a\x30\xc3\xd2\x60\x86\x50\x67\x16\xd5\x05\x2f\x9e\x36\x8c\xf5\xd5\x58\xd5\x88\xd2\x69\x96\x81\x97\x0f\x49\x43\x3e\x83\x24\x4f\x53\x2b\x95\xc1\x74\xea\xde\x68\xf6\x97\x23\x48\x03\x0b\x92\xa9\xa0\xee\xdb\x24\x9e\x86\x74\x2e\x84\x09\x3b\xc2\xf1\x00\xc7\x89\x68\xea\xa2\x8e\x58\x83\x79\xc3\xac\xd4\x2e\x15\xcd\xe2\xb6\x56\xe3\x3b\x11\xa1\xc0\xb8\x30\xdd\x9b\x77\x31\xad\x6c\xc3\x63\x7d\xe1\xc8\x60\xd6\xd1\x9a\x2e\x26\xea\xe4\x6d\x5d\x4c\x97\xf1\x0c\x09\xa3\xe4\x5a\x55\xae\x9d\xff\xf3\x25\x95\x15\x74\x3a\xdb\x38\x2d\xd6\x8f\x2f\x5f\xb1\xd3\x5b\xc0\xcb\xb9\x80\xc9\xb4\xe3\x2e\xa1\x1b\x63\xba\x2d\xda\xd6\x14\xee\x5c\xa9\xb7\x58\xbc\xf9\xe6\x2b\x75\xfd\x27\x4c\xf6\xa4\x63\x7d\xf6\xe2\x90\xa9\x5a\xef\x43\x7c\x99\xaf\xd0\x65\x47\x1d\x41\x5c\x05\x05\x4d\x8e\x28\xbe\x28\x57\x3b\x5b\x8e\x0a\x75\xa2\x7c\x6c\xaa\xd2\xdb\xa6\x68\x22\x24\x94\x1d\x0a\x70\x2a\x8e\xcc\xd5\xb4\xd5\x7b\x80\x0a\x35\x08\x17\x5e\x14\x06\x62\x11\x8e\xc5\x56\xef\x76\xcb\xb0\x17\x8b\xf2\xc5\x22\x3c\xcd\x51\xff\xbd\xc8\xc8\x60\x6b\xda\xf5\x9c\x57\x51\x33\x79\x3a\x75\xae\xa6\xea\x65\x1c\x0e\xdb\x96\xb3\x70\x04\x4b\xe1\xa6\x3e\xdc\xad\x29\x62\x88\xaa\xe8\x8b\x32\x6a\xe2\xdb\x69\xd3\xd3\xc3\xae\x11\xf8\x6d\x30\x78\xcb\xc9\xdd\xc1\xaa\xe3\x69\x6b\x82\x8f\x65\xbb\x0b\x18\xd2\xdd\xc3\x2e\x87\x00\xff\xb2\xd5\x7b\x8d\x48\x50\xe1\x24\xb5\x13\x0e\x3a\x50\x5f\xfc\x56\xd1\xd5\x66\x2f\x44\x7b\x26\x81\x89\x38\xf6\x18\x50\xf1\x8c\xa1\x9b\xaf\xf8\x64\xc9\x15\x45\xc8\xa2\x7c\x02\xef\x9e\xe7\x5a\x16\xfb\x22\xa0\x8a\x48\x2d\x3d\xe1\x94\x72\x9b\x8a\x15\xe7\xc2\x1b\x4a\x06\xcf\xa6\xdd\xcf\x2c\xef\x59\x77\xa0\xe4\xb2\x70\x92\x4a\x97\x94\xef\x19\x9c\x85\x08\x6b\xc0\xd8\x70\x3c\x45\x58\x00\x52\x03\x4f\x24\x88\x6f\x8d\x1f\x76\x06\xfb\xfc\x10\x55\x50\xbd\x37\x02\xbd\x04\x9c\x17\xc8\xc1\x6f\x59\x76\x06\x7b\x86\xd3\x56\x15\xd4\x27\xae\xfa\x99\x9f\xba\xea\xb7\x3a\x7a\xd5\x2f\xad\x26\xa6\x7f\x9b\x04\x36\x19\xbc\x9e\xb6\x6b\x1a\xe5\xf8\xb6\x37\x85\x9b\x72\x67\x67\x9e\x08\x1d\x50\xf4\xc7\x13\xd6\x7e\x5e\xc7\x3f\xd9\xd5\x7e\xd5\x6b\xd5\x53\x0f\xc9\x4c\xbb\x3a\x27\x56\x1a\xd5\x1b\x44\xeb\x31\x70\xf7\x1b\xec\x81\x23\x5e\xbb\x8d\x72\xb9\x3d\xd8\x9e\xc2\xf9\x54\xca\x61\xa9\xdc\x91\x2f\x97\xef\x82\x10\x1d\x4e\xe1\x78\x0a\xd5\xad\x50\xa4\x76\xec\x87\xa3\xe6\x46\x6d\x75\x78\x27\x54\xde\xf8\x6c\x4e\x3d\x44\x6d\x11\x13\x5f\x91\x24\x5c\xf2\xb9\x97\xa7\x8c\x2a\x5e\xc3\x95\x3f\xbb\xea\x6b\xb3\xf6\x77\x17\xeb\x38\x59\xdb\x5e\xfc\x1f\x82\x16\x87\x71\x8f\xcd\x70\x6f\xe1\x25\x4c\x52\xe4\xd8\xd6\xa1\xd9\x78\x4b\x99\x0d\x3b\x46\xb8\x00\x76\xe9\x40\x2f\xf3\x93\x82\x03\xa5\x83\x30\x28\xad\x5b\x01\x9b\x3c\xad\xc0\xcc\x52\xa6\x4c\x29\x61\xa9\xc8\x3b\xf5\x00\xe7\x98\x23\x52\x8e\xf2\xdd\x62\x03\x1d\xc8\x9c\x12\x16\x89\x32\x87\x1e\xd0\x81\x4e\x2a\x21\x4d\x88\x3e\xc3\x4b\xde\x9b\x4e\xb1\xf9\xf5\x76\xf9\xec\x20\x76\x75\x57\xed\x13\x15\xf4\xd0\x30\x47\x99\xde\x98\x5e\xcb\xbe\x88\x5b\xb7\x44\xdc\x17\x8f\x99\x95\xc9\x6c\xd7\x27\xf3\x7e\xe5\xa5\xea\xbd\x66\x28\x42\x1f\x18\x54\x5e\xff\x6b\xd7\xea\x62\x4f\x8f\xa7\x50\xcc\x59\xcd\x8c\x15\x83\xc1\x25\x40\x54\x7c\x0b\xa9\xc9\xf9\x62\x83\x1d\x97\x40\xa1\xd7\xd0\x43\x1f\xe0\xd9\x14\x76\x72\xc7\xe3\xd2\x01\x69\x69\x5a\xaa\x9a\x6e\x5f\x57\x3c\xf5\x0a\x44\x08\xd1\xd1\x34\x7f\x73\xd6\x4b\x55\xa2\xa6\x1f\xa6\xee\xcd\x94\xd0\xb9\xb3\x37\x2d\xb9\x44\x2a\xb3\x8d\x19\xbc\xe8\x62\x0e\x45\x65\x56\xaa\x4b\x75\x55\xc1\x0c\x2e\x75\xcf\x74\xc7\x9b\x59\x8e\x01\xe5\x8b\x59\xa7\x1b\x2c\xe5\x92\x49\xd2\x23\x9a\x13\xa0\x6e\x56\x55\xf1\x73\xdb\x62\x5c\x25\x01\xc7\x8a\x2c\x60\x21\xe3\x68\x3f\x15\xb4\xf0\x0b\x6b\x55\x91\x67\x94\xcc\x95\x84\x3a\xd9\x8a\x83\x93\x70\x5e\x66\x76\x61\xbc\x2e\xc7\xfc\x7c\x09\xd7\x6c\x6e\xb0\x76\xfa\xbe\xe9\x98\x48\xf9\x0a\x54\x88\x44\xbe\x8d\x67\x7e\x55\x5c\x39\x65\x8e\x6e\x37\x83\xcf\x79\x96\x84\x72\x91\xf3\xb1\xa3\xaf\x92\x9c\xb9\x10\x7d\x2c\x81\x48\xe5\xc5\x42\xac\x7e\x0d\x1a\x2c\x6a\xef\xf0\xbd\xe4\x0b\x75\xf5\xf7\x1c\x8d\xf2\x9e\x69\x74\x87\x9e\x4b\x55\xf3\x9e\xf1\xea\x3d\x1f\x7a\xf3\xa2\xe3\xf8\x2e\x1d\x17\x35\xf3\x7e\x49\xe4\xd6\x7a\xd9\x96\xdb\xce\xca\xc0\xef\x18\x93\x6c\x57\x97\xd5\xa3\x49\x9b\xad\xe9\x0d\x6d\x65\x30\x5e\xde\x5e\x5e\x5a\xb7\x18\x36\x5a\x14\xdb\x21\x03\x6f\x69\x63\x3b\x8a\x42\xe4\x6d\x25\x4b\xab\xec\x0a\xea\x92\x57\x98\x2e\xad\x70\x9c\xeb\x04\xa8\x2a\x51\x47\x15\xf9\x48\x50\x79\x7b\xca\x32\x08\xf2\x19\x6e\x05\x81\xce\xcc\x60\x11\x19\x6d\xc4\x74\x83\xfc\x46\x7c\xea\x30\x48\x17\xc2\xba\x9b\xc2\x05\xa6\x49\x48\xe2\xbd\x78\x4a\x1c\x0c\x73\x9c\xcc\xa4\x22\xb7\x14\x9a\xcc\x22\x77\x89\x74\x78\x42\xbd\xd8\x9f\x39\x0c\x26\x69\x18\x05\xc2\x8e\x9c\xca\xef\x77\x89\xd0\x65\x3b\x25\xef\x65\x17\x4e\x0c\x7c\x0b\x8b\x4f\xa2\xfb\x95\x02\xe2\x8b\xce\x41\x2b\x02\x1c\x87\xfe\xd9\xa1\x74\x44\xb8\xc0\xea\x64\x24\x71\x8c\x45\x25\x35\xde\x79\xd4\x4e\x2e\x9b\xcd\xa4\xa1\xf2\x2b\x75\xda\xd9\xbf\x17\x04\x14\x27\x89\xc3\x80\xa4\x6c\x42\xd2\x98\x9f\x51\x52\x2c\x86\x21\xe4\x80\x13\x7d\x4f\x22\xf7\x46\x0a\xcd\x04\x30\xf9\xc1\x77\x1d\x95\x2f\xa2\x12\xb0\x42\x92\x90\xc1\x49\xc7\x82\x73\x0a\xac\xd5\x51\x94\xc4\xc1\x54\xda\x64\xaa\x6e\xd0\x7a\xcd\x93\xe2\x66\x12\x69\x26\xf9\xcd\xa4\xb4\x99\x34\x6e\x26\x85\xcd\x24\xaf\x99\x94\x34\x93\xa6\xcd\xa4\xa8\x2e\x3b\xda\x97\xaf\x96\x49\x21\x8d\x29\x5c\x30\x3e\xe3\x1c\x04\x96\x5c\x83\x28\x17\x03\x25\xd2\x95\x98\x14\x11\x3a\xbe\x96\x66\xa6\x30\xf1\x12\x7c\xe4\xb1\x99\x33\x06\x6f\x11\xbe\xa3\x91\x13\x42\x14\x4e\xf8\x87\x07\x79\xc8\x81\xed\xe3\x63\x27\x81\x29\x89\xd9\xd6\x25\x4e\xc8\x1c\xf3\x84\x29\xa8\xbb\xad\x20\x37\x84\x3a\x51\x35\x50\x18\x9c\x75\xac\xe9\x31\x66\x3b\x95\xda\x85\x8c\xa7\xa3\xd6\xb3\xca\x08\xf6\x89\x17\x94\x84\x43\x57\x1d\x15\x9f\x96\x66\x52\xab\xf6\x34\x2a\x14\x41\x83\x90\x62\x9f\xe5\xaf\x06\x5b\x79\xd6\xa1\x77\x11\x9e\x72\xaa\x49\x14\x26\x66\x70\xd8\x85\xb1\x45\xf1\x62\xbd\x8a\x37\xdc\xbb\xd4\xe4\xab\x79\x58\xe2\x00\x76\xef\x5a\x79\x37\x08\x8b\xae\x0f\xee\x52\xbb\x22\xe4\xdb\x36\xc0\xe2\x90\xb0\x67\x7c\xff\x5b\x19\x9c\xaf\xd4\xb0\x82\xac\x6e\xf3\x59\x47\x25\x29\x5a\xae\xed\xfb\xfd\xe5\x15\x0c\xf0\xde\x5b\xb5\x16\x07\x57\x5e\xeb\xf5\xaa\xb5\x2a\x60\x7a\xb9\xb4\xd6\x96\xde\x97\xc5\xb3\x6a\x54\x8a\xb9\xb1\x8f\x2f\x70\xf4\x96\x48\x87\x6e\x3b\x79\x8e\x04\x84\x4e\x7f\xd7\xb5\xb3\x8a\x51\xc9\xe2\xba\x9b\xf7\xcb\x2b\xf1\x61\x55\x2b\x7d\x58\x5e\x49\x61\x68\xb5\xde\x8b\xd5\xea\x89\x77\xde\x4a\xc5\x2f\x05\x9e\x29\xec\xd2\x93\xfe\xda\xd1\xa4\x44\xac\x6a\x4b\xcf\x8d\x87\xc4\xe1\xd8\xac\xe4\x46\x8c\xe2\x1b\x36\x18\x0f\x85\x6d\x25\xb3\x33\x3b\x6b\x58\xfd\x9c\x8f\xe1\x7d\x04\x8b\xc4\x68\x77\x73\x3e\x86\x9d\x08\x26\xad\x99\x1f\x22\x98\xb7\x66\xbe\x8b\x60\xd6\x9a\xf9\x22\x82\x8b\xd6\xcc\xaf\x11\x04\xad\x99\x47\x11\x3c\x1b\xb7\x44\x9d\xb3\xe1\x4d\x64\x74\x77\x76\x58\x8e\xe8\xfc\xfb\xef\x9b\x96\x0d\x6c\x30\xf3\x92\x99\x0d\xb8\xe9\x75\xed\x53\xe1\x07\xad\x1e\xb1\x83\x43\xd3\xb1\xac\x0c\xd9\x10\x37\x5c\x72\xe2\x73\xf4\x05\x51\x1b\xd6\xed\x52\x4b\xac\x1c\x95\xb8\x11\xff\x23\xd7\xc2\xdc\xb4\x40\x44\xf1\xe0\x8d\xab\xc2\xa2\x17\xe2\x86\xe8\x6a\x0c\xcf\x23\xc8\xc5\x0b\x0c\x6e\x12\xec\x51\x7f\xe6\xc4\xc0\xe7\xe0\xe0\xac\xd9\x03\x91\x3d\x10\x3e\xde\x2f\x51\x06\x9f\x8c\xa8\xe4\xa1\x09\xbc\xaf\x2b\xce\xce\x18\x5b\x38\x0f\x1f\x9a\x54\x63\x75\xd4\x9f\xa6\x86\x2c\x84\x68\x02\x0b\x19\xb2\x19\x5e\x35\xef\x22\xcc\x99\x12\x8a\x9e\x3c\xc9\xad\x92\x9f\x14\x41\xc3\x71\x25\x0e\x37\x7d\x92\x8b\xe6\x72\x77\x39\xe1\x14\x7d\x8a\x50\xac\xe0\xea\xbb\xf4\x49\x3d\x3e\xbb\x0c\x96\xae\xec\xf5\xfc\x22\xba\x3a\x73\x09\xd0\x9a\x05\x84\x90\xdb\x35\x67\x77\xc4\x4a\x86\xb1\xbe\x0e\x4a\xdc\xb3\xa4\x52\xac\x3f\x18\x8f\xb2\xec\x89\x4f\x62\x16\xc6\x29\xee\xb1\xec\x6e\x4d\x0b\xc7\x1b\xf2\xb2\xb5\x72\x23\x34\xcb\x70\x94\x60\x31\xe9\xb4\x98\xf4\x3d\xd7\x4d\xe5\xf4\x4c\xb5\x8f\x8a\xda\x4f\x44\xed\x12\x60\xd2\x6e\xc0\x54\x20\x90\x2a\x08\x54\xad\x39\x63\x65\xd9\x9d\x72\x70\x2c\x9b\x48\xa5\x3d\x55\x5b\xcd\x4b\xec\xd6\xcf\x46\xa4\xa4\xbc\xd6\xab\x08\x4e\x29\x62\x76\x35\x7e\x58\x06\x1f\x4d\x1b\xfc\x2d\x45\x5d\xf1\x06\x98\x13\xa2\x5d\x0a\xd7\x4c\xbc\x4b\x89\xf8\x02\xf2\x63\x64\x67\x70\xdf\x38\x86\xb6\x78\x40\x9c\x48\xf7\xc4\xbf\xfd\x4b\x8f\xc6\xbc\x9f\x15\xe2\xf3\x7c\x8c\x84\x1d\x42\x33\x72\x04\x0b\xdc\xa5\x91\xf3\xce\x4c\x03\x99\x7a\xbd\xa9\xd7\xf7\xc9\x29\xff\x93\x2c\xc2\x98\xff\xdd\xb8\xe2\xff\x4e\xef\x1e\xb0\xa8\x1c\xb4\xad\xd4\x49\x42\xfb\x24\x8e\x96\x07\xe6\xf0\x09\xd2\x5e\xd9\x07\x83\x41\x77\x0c\x3f\x1d\x38\x81\x06\xed\x12\xc4\x5e\x88\xb6\x0d\xe3\x29\xa1\xd2\x65\x7f\x34\x1c\xf6\x2c\xa0\x26\x7b\xd1\x2f\x04\x19\x03\x62\xf8\xd5\xe8\xaa\x5a\xb3\xbf\x0c\x9a\xcc\x86\xf6\x6b\x63\x2f\x44\x93\xee\x61\x59\x80\x4d\x03\x7a\x5e\x0b\x14\x58\x44\x1d\x89\x3b\x06\xd4\x89\x00\x95\x4e\x0d\xb8\xd5\x1d\x85\x70\xd9\x34\x4d\xb8\x5f\xea\x31\xe8\x4f\x23\x7c\xd5\xe3\xff\xf4\x7d\x12\xa5\xf3\xb8\x57\x9f\xb9\x39\xc6\xc4\x41\x37\xa6\x5f\x2f\x89\x11\xd9\x0c\xa5\xb0\x5a\xb8\xc8\x67\xf5\xe9\x7c\x31\x2f\x48\x68\x5c\x90\x4e\x50\xfe\x5f\x07\xcb\xc6\xc6\xfc\x93\x61\xd9\x26\x9c\x92\x47\xa0\x3f\xa8\x3d\xca\x6b\x5f\x08\x69\xf9\x7d\x5b\xaa\x2d\x38\xdf\xb1\x04\x45\x34\xca\xde\xcc\x4b\xfa\x89\x34\xdf\xff\x6b\x56\xa6\x19\x7f\x64\xb5\x95\xa9\x9b\x6c\x7f\x21\xc8\xd7\x6f\x3e\x4b\x97\x47\x25\xa7\xbe\x31\xca\x74\x1e\xa0\x93\x9f\xf7\x94\x44\xbd\xf2\x0f\x0d\x1d\x43\x30\xc7\xa5\x0b\xae\xfc\x9d\x29\x9d\x8e\x3f\x69\xc5\xfe\x77\x95\xe4\xc2\x7c\xd3\x82\x34\xbc\x68\x7c\xf7\xe6\x09\xbc\xf8\x14\xd3\xff\x5d\x15\xe3\xde\x91\xc0\xb9\xd3\x4a\x75\x47\x6c\xaa\xb4\x3e\xc5\x38\x98\x78\xfe\xd9\x2a\x1c\x5c\x6a\x8c\x21\xd9\x1c\x97\x8c\xde\x87\x83\x76\xdd\x96\xf2\x2a\x96\x47\xf6\xb8\x17\x84\x93\xde\x7c\xb2\xde\x9b\xd3\xf5\x9e\x42\x1c\x2f\x0a\x4f\x63\x11\x62\x39\xe9\xfb\x38\x5e\x25\xe6\x9c\xe1\x10\x7a\x41\x90\xe5\xcf\xb0\x7f\x36\x21\x57\xa6\x00\x6f\xaf\xcc\x87\xd4\x78\x05\x96\x70\x65\x6e\x79\x11\xf5\xd7\x57\x01\x74\xf5\x46\x64\xba\x17\x18\x0f\xc6\xb8\x13\xe2\x26\xc6\xd4\xc4\x04\x4f\x8d\x33\xbe\x2b\xcb\x29\x6f\x1f\x1b\x0d\x06\x7c\x35\xd6\x93\x04\xe6\x1b\x97\xd9\x84\xae\x50\xe7\x29\xc7\xfb\xaf\xfb\x23\x6a\xcc\xff\x39\x41\xa6\xbd\xfb\x86\x20\x6b\x3c\x89\xbc\xd8\xb0\x27\x0c\x6b\xd5\x84\x55\xae\xef\xe3\x13\xad\xe5\xf8\x39\x92\x9a\x51\x7e\xd0\xa2\xb4\xc4\xda\x3d\xc2\xb4\xe0\xd2\x84\xc5\xbd\x09\x8b\xfb\xc9\xbc\x37\x39\xed\x4f\xbd\x00\x07\xf2\xb7\x88\xe2\xe0\xd1\xeb\xde\x9c\xf6\xd7\x7b\xf3\x49\x0d\xe5\x54\x13\x2b\x05\xa1\x4b\x13\x4c\xfb\x89\xb6\x79\x19\x39\x16\xc3\x57\xc6\xe0\xf3\xa6\xca\xfd\x39\xf9\xda\xff\xbe\x16\x2e\xf1\xe4\x2c\x64\x2b\x34\xa2\x09\xcf\x0a\xeb\x65\xa0\xff\x4e\x4b\x30\xc8\xef\x04\x31\xdf\x48\xc6\x48\x85\x8d\xbd\x64\x5c\x60\x3e\xc9\xfe\x3c\x15\x86\xbc\xcb\x49\xc6\x2a\xc7\x5a\x66\x43\x1a\x74\x3c\x7a\xf6\x42\x34\x37\x8d\x24\xf6\x2e\x9a\x11\xee\x4d\xe3\xc8\x8d\xa5\xdb\x90\x96\xb7\x14\x85\xf1\x59\x4f\x99\x74\x34\x1b\x8c\xf9\x6a\x98\x48\x55\x5e\xb7\x0d\xd4\x26\xf9\x09\x6f\xcf\x04\x86\x71\xd0\x16\x26\xc4\x43\xef\xba\x75\x52\x0d\x81\x74\xb3\xdc\x59\x6a\xd8\xd1\x6e\xc5\x21\x61\x19\xea\x1e\xba\xc0\x40\x39\x21\x31\xc8\xec\xf7\xcb\xae\x19\xd4\x6c\x71\x03\x6a\x22\xb6\xed\x5d\x34\x69\x85\x83\x57\xa1\xcb\x15\x8b\x38\xbd\x58\x8e\xdf\x0b\x4c\xfa\x6e\x5a\xeb\x72\xd3\x72\xff\xdb\x72\x2c\xd7\x2a\x88\xea\x15\x05\x5a\x77\x25\x20\x74\x39\x9b\x6b\x74\x86\x58\x93\x5f\xca\xa3\x1d\x26\x2d\x14\x5f\xb9\x8c\xe2\xa4\xdf\x0b\xa4\xe8\x78\x5a\x39\xe6\xea\x18\x1c\xd4\x74\x8a\xe3\x92\xf2\x9d\x08\xaf\xca\xec\x4d\x8c\x62\xdb\x89\xf9\x89\x29\x3c\xa0\x77\xcb\x99\x4a\x67\x4e\x91\xcc\x10\xb6\x37\xa9\x83\x33\xb5\xee\xe8\x85\xe9\x61\xe5\x1a\xed\x4b\xba\x7f\x6e\xdb\x10\x34\x69\x7f\x55\xde\x4d\x9f\xdc\x14\xd2\xdb\xaa\xc0\xfb\xbc\x10\x78\x0b\x49\xb7\x0c\xbd\x32\x18\x0f\x39\x44\x54\x99\x4f\x28\xb6\x9f\x30\x97\x01\x75\x63\x41\x0b\x17\x2d\x20\x25\x3e\x58\x67\xf8\x3a\x5d\x28\x87\x13\x0c\x98\xcf\x07\x39\xeb\x2e\x1f\x90\xcb\xb8\x56\xe3\x22\x70\x6f\x72\xa3\x61\xe7\x17\x10\xcc\x99\x33\xda\x80\x74\xe1\x6c\xfc\x02\xbc\x86\xf3\x68\x98\xc1\xbc\xa5\x65\x23\x7b\xea\x93\xa8\xe7\x93\xa8\xef\xa5\x8c\x7c\x6b\x50\x52\x4e\xa5\xe5\xf5\xc2\x4c\xa1\xcd\x4d\x75\x1e\x02\x24\x65\x51\x18\xe3\x7e\x18\x4f\x49\x0b\x09\x0a\xd1\x71\x02\xf7\x86\x26\x86\xcd\x44\xb1\x13\xa3\xc4\xd7\xf8\xa6\xb5\xca\xc0\x0c\xf7\x84\xfa\xd0\x46\x2b\x0e\xcd\xfa\x7f\xfe\xff\xab\x89\x68\x9b\xe2\xea\xd3\x56\xce\x6d\x1e\x88\x78\x02\x93\x16\x9c\xc9\xe0\xda\x48\x7c\x84\xb2\xad\xd6\xda\x14\x9a\xc3\x25\x3f\x04\x40\x5a\x63\x32\x30\x98\x04\x83\xbc\x23\x7b\xf3\x2c\x41\xf7\x46\xb6\x73\x92\x64\xe0\xbb\x51\xc0\x09\x60\xea\x8e\x13\x71\x4f\x2b\x3f\xd3\x95\xdb\x88\x85\xc3\x69\xcb\x72\xf2\x37\xb3\x54\xf9\x54\x2a\x89\x7c\x2c\xc7\x2a\xee\xb0\xe2\x41\xae\xea\xd9\x4e\x6f\x57\x31\x20\x31\xdb\x7c\xcb\x72\xd2\x7e\x92\x08\xea\x7d\x95\xa0\x7b\x43\x1b\x52\xdb\x7e\x52\xa9\x50\xcc\xa0\x68\x49\x0c\xab\x43\xdd\x9d\x0e\xea\x96\xfc\xe2\x75\xca\x14\x84\x1e\x2b\xe5\xf7\x7b\x23\xa5\x0c\x5f\x8a\x3d\x5f\x04\x7d\xd7\x88\xad\x54\xe1\x05\x14\xd5\x14\xce\xc4\xb8\xf5\x2f\x0e\xdd\xc4\x15\xf8\x66\x98\x99\x0d\x53\x57\xba\x0d\x86\xf3\x6a\x10\xe9\x26\x76\x53\x72\xd9\x8b\x49\xff\x34\x65\x0c\xd3\xa4\x72\x07\x14\x1a\xbe\x86\xed\x5c\xdc\x3e\x4e\xc5\xf2\xae\x42\x29\x4a\x37\x16\x4e\x77\x2c\x18\x9b\xa4\xf3\x2b\x31\xcb\xf3\x30\xee\x5f\x86\x01\x93\x5e\xac\xad\xf5\xe1\x70\x71\xf5\xe7\x85\x6a\x0e\xe3\x45\xca\xfa\xca\x11\xcc\xdd\x6f\xbf\xef\x88\x76\x76\xd2\x9f\x78\xb4\xaf\xb6\x90\x89\x58\x74\x8a\x88\x0a\xd9\x87\x49\xbc\x31\x0b\x90\x67\x48\x5e\x04\x46\xa9\x47\xe8\xa3\xcb\xc4\xfc\x4a\xff\x6d\xb7\xeb\x12\x88\xfa\x13\x16\x7f\x2f\xc1\x5f\xd0\x70\xee\xd1\x6b\xd3\xfc\x3f\x13\x34\x35\x24\x27\x4b\x5f\x6a\x38\x6d\x5d\x5b\x81\xb4\x76\xd3\xda\x7c\xfc\x27\xad\xe2\x1d\x7e\x79\xe8\xdd\xed\x06\x61\x6d\xa7\x09\x23\xf3\x9e\xc2\x0d\xe8\xe1\xc1\xe9\xc0\x34\xfb\x25\x70\x13\xfc\xbd\xba\x36\xc9\x6d\x3b\xf1\x12\xcc\x8f\xa8\x96\xb3\xe9\x32\x41\xff\x81\xe3\x0b\xd7\x5a\x50\x12\xa4\x82\x6e\x5a\xff\xb1\xd2\x39\x65\xa8\xf6\x0d\xa7\x96\x01\xfc\x76\x06\x27\x2d\x07\x99\xf1\x6e\x62\x62\x12\x7a\x13\x42\x03\x4c\xfb\x43\xd3\xb4\x9f\x57\x48\x4f\xc9\x73\x90\x51\xdc\x63\x5a\x2d\xa1\x90\x65\x3a\x81\x2f\x9b\x7c\x66\x6e\x63\xaf\xdc\x2c\x0b\x3d\xd6\x8a\xb9\x9f\xb2\x36\x77\x0a\xc9\x85\x65\xe9\x78\x2b\x15\x63\xfc\xde\x9d\xb8\x91\x4e\x18\x4c\x7d\xb4\x1f\xa1\x10\xcd\xa7\xc2\x85\xd2\x6a\xd3\x96\x23\x35\x4c\xbc\x29\x96\xfe\x1f\x1d\xa7\xd4\xdf\x36\x2d\x50\x66\xc3\x59\x50\xe7\x10\xf2\x15\x10\x9a\x3f\xcd\x65\xfa\xf3\xd1\xef\x34\xa9\x58\x08\xad\x34\xa9\xb7\x58\xda\xdc\x98\xc0\xaf\xbd\xd5\x1b\xdd\xcb\x95\x30\xdc\xa0\x33\xc4\x06\x61\xd0\x4c\x95\x1e\xc1\x0c\x42\x9e\x0e\x91\xde\xb7\x02\xc3\x10\xd0\xdf\x84\x7b\xc2\x45\x99\x61\xcb\x1d\x77\x5f\x9b\x3f\x7a\xce\x7d\x0f\xb0\xbb\x1f\xa1\x60\x8a\x42\x74\x25\x58\x71\xe9\xb2\x55\x5e\x96\x4b\x7e\x5b\xd5\x25\x59\x04\x05\xc8\x27\xea\x07\xb0\xcf\x59\x1a\x2f\x90\xf7\xc9\xab\xe6\x1e\x2f\x6e\xcc\xdd\xc2\x24\x45\x93\x13\x1c\x4d\x95\x34\x5d\xdc\x91\xee\x26\x96\x66\x35\x95\x9f\xe2\xd7\xb5\x88\x6b\x5a\xca\x85\x9e\x05\x27\xc2\x6f\xa0\x6d\xd8\x3a\xfc\xf2\xfc\xb4\x6d\x32\x37\x7e\x44\x12\x7c\x20\x7d\xc2\x3b\xfb\x7c\x17\x2e\xa6\xb6\x0d\x9c\x33\xf1\xc2\x18\xd3\xed\xc8\x4b\x12\xe7\x5c\xc5\x0c\x10\x2e\xa6\x93\x25\xcf\x3f\x6a\xa3\xf5\xb4\xe1\x90\x81\xf6\xcb\x90\x03\xfb\x88\x97\xde\xa2\xb8\x77\x4d\xd2\x5e\x92\xaa\x8f\x4b\x2f\x66\x3d\x46\x7a\xd2\xbd\x48\x8f\xcd\xc2\xa4\xa7\x50\x7b\xd3\xe2\x1c\x2e\x21\x4c\x0d\xa5\x5b\xa6\x68\x78\x11\xad\xd1\x9b\x8b\xbb\xd0\x1b\xe5\xf6\xc0\x34\x1f\x4e\x71\xb6\x3a\x10\xc6\x28\xf3\x6b\x30\xdc\xbd\x28\x4c\x34\x77\xc5\x93\xf3\x2d\xa5\x74\x9d\x44\xb6\xc8\x58\xf4\x87\xfc\xc6\xfd\xe8\x5b\x2f\xef\x52\x73\x87\xdf\xd9\x4d\x2f\x40\x6d\xdc\x7f\x0d\x86\x06\x0b\xf7\xb6\xc3\xaf\x71\xc0\x5d\x05\x60\xed\xc6\x41\x62\x15\x16\xb1\x46\xdf\x33\xaa\xa8\xb4\xeb\xe1\x85\xb5\xed\xa1\xe1\x30\x12\x6d\x2a\x1a\x5f\x34\x9b\xf1\xeb\x62\x03\x01\x4e\x02\x44\x07\x61\x60\xc8\x39\x0b\xcc\x9a\x14\xe8\x32\x00\x0a\xf7\x46\x26\x76\x7a\xf5\x87\x41\xe3\x9d\xea\x33\x1c\x07\x65\xf3\x51\x43\x73\x97\x21\x62\x9b\x1c\xe3\x9f\xaa\x51\xd8\xce\xb9\xf1\x59\xd0\x86\xc3\xc0\xe4\x64\xf1\xe3\x9d\x1c\xb7\x97\x5d\x72\x52\xb3\x3e\xb3\x58\xe3\xcc\x14\x6c\x40\x1f\xae\x99\x0a\xf3\x9c\xc1\xdb\xa0\xa6\x92\x98\x4c\x9b\x53\xf4\x0c\x69\x69\xc3\x40\x3e\xcb\x60\x77\xf9\xcb\x55\x97\x44\x99\x82\x08\x89\x73\xc8\x01\xc9\xd1\x03\xde\x06\x76\x06\x07\xad\xbb\x57\xd8\xed\xdf\x8f\x90\x75\x48\x34\x19\x4a\x7a\x53\x61\xae\x60\x3b\x21\xba\x30\x2d\x73\xb1\x91\x5b\x16\xdc\xa8\x3a\xbe\x15\x80\x02\xfc\xbe\xc4\x4e\x11\xf2\x1a\xa4\xdf\xd9\xed\xb6\x77\x2d\xaa\x82\x5a\x16\x31\xca\xd2\x00\x62\x30\xaa\xa1\xef\x47\x28\x52\x1e\x04\x1a\xfa\xd6\x5f\x10\x1e\x8c\x47\xf9\x89\x38\xe4\x6c\xd2\x66\x83\x0a\x7e\x8c\x10\x9e\xa2\xd8\x40\x32\x9d\xd5\xca\x76\x5f\x30\x27\x5e\x70\x8a\x7b\xe2\xdf\xfe\x22\x8c\x22\x72\xa9\x7e\xa8\xdd\xae\xe8\x94\x38\x6b\x19\x59\xf4\xe6\x2b\x3e\xf7\x9e\x2d\x13\x04\x2a\xe4\x42\x02\xd6\xe7\xed\x62\x32\xe6\x4d\x84\x84\x4c\x63\x82\x49\xc6\x62\x54\x9a\x30\x92\x83\x15\x69\xb8\xf1\x25\xbf\xed\x4d\xec\xeb\x72\x39\x44\xeb\x11\xf7\x4c\x39\x6b\x5d\x49\x64\x4a\x48\x0b\x8a\x05\x0a\xc5\xae\x39\x91\xcd\xbd\x49\x99\xbc\x1a\x9b\x9a\x35\x6e\xa8\xd8\xbb\xe8\xc5\xde\x45\x9f\x79\x93\xa4\xed\xe4\x13\xee\x05\x84\x58\x6a\x37\x40\x21\x3a\xf2\x2a\xeb\x11\xdb\x46\x3c\x6c\x6c\x83\xf8\x89\xc9\x5d\x9a\x0e\x1d\x53\x9c\x36\x07\x9c\x64\x9b\xdd\x2d\x81\xa0\x2e\x58\x9a\x12\xa8\x73\xed\x99\x17\x46\x29\x2d\x8e\xc0\xfb\x11\x62\xa6\x80\x39\x2c\xa8\x1d\x58\x39\x65\x87\x67\x2d\x74\xcf\xc8\x5c\xcc\x27\xeb\xbd\xcb\xfe\x2f\xc3\x7e\xd4\x13\x87\x7d\xdf\xf4\xb4\xb8\xd4\x45\xbc\x1f\xc0\x79\x39\x68\x47\x4d\x13\xdd\xb5\xa4\x1f\x5d\xe1\x30\x7e\x20\xbd\x94\x0b\x57\x30\x2d\x23\x9d\xb5\xd1\xca\xde\xc2\x1b\xca\x71\xb6\x8c\xf2\x99\x7a\x98\xda\x33\xee\x4c\x63\x2c\xa6\x7c\xc9\x9a\x9a\x0a\x6f\x10\xb6\x37\xbb\x58\xa3\x15\xf6\x64\xf4\x7d\x3a\x52\xa5\xd3\x24\xe8\xe5\x7e\xa9\xef\x2c\xb4\xb2\x3b\x39\xbc\x7f\xfd\x34\x4a\xc8\x70\x5c\x9d\x8d\xd3\xb3\xe0\x0c\x7d\x11\x3c\xc0\xdd\x26\xa6\x5a\xdf\x0f\x4c\x4a\x32\x2d\xca\x8a\x65\x69\x8a\x52\x82\x2f\x82\xce\x06\xab\xe9\xd3\x7d\xab\x5d\x01\x35\xea\x6c\x65\x19\xbc\x36\x29\x0b\xa9\x57\xc6\x62\x8f\x11\x02\x1f\xa7\xd0\x2e\xa3\xff\x56\x1e\xdf\x27\x51\xff\xa7\xa5\x95\x23\x44\x03\xd8\x26\xd2\x6b\x23\xc4\x11\x67\x7e\xb1\xf8\x37\x56\x0e\x83\x56\x39\x0a\xfe\xb4\x01\x50\xd1\x35\x53\x03\x30\xbf\x65\xdf\x6d\x04\xdf\xa3\xe3\xe6\x21\x1c\x80\xa5\x3c\x53\xc4\x5a\xd8\x00\xf7\xa7\xc8\x68\xf2\xc0\x36\x3d\x14\x07\x50\x5c\x40\x0b\x25\x16\xf5\xd6\x0a\xd6\xd4\xeb\x33\xea\x25\xb3\x3e\xb1\x20\xe2\xd3\xb4\x1d\xdf\x78\x2f\x30\x6a\xfd\x09\x9f\x4f\x81\xbb\xa2\xe0\xad\xfb\x02\xfc\x6a\xba\x12\x4b\xa0\xfc\x83\xf4\xb6\x5a\x69\xd4\x91\x89\x26\x37\x9e\xfb\xea\x56\x77\xca\x63\x83\xa5\xdd\x8c\x58\xa5\x80\xfb\x2d\xf3\xe3\xcc\x5e\x6f\x85\xb7\x83\xa9\x8f\x3e\xaf\x34\x39\x83\x46\x4f\x06\x3b\xed\x0a\x64\xea\x98\xc1\x5d\x9c\x41\x99\x12\xd5\xa9\xd4\x1e\xbf\x5b\xb6\xf2\x03\xb8\x8d\x1f\xb0\xe1\x5d\xa7\xda\xe1\x92\x57\x37\x4a\x2e\x7b\x16\x58\x73\xc6\x77\xe3\xca\xdb\x51\x5c\xb9\x2d\x50\xbb\xd8\xc4\xe9\x7d\x9c\xa2\xa9\x52\xba\xfb\x38\x45\x61\x64\x83\x49\xd7\x31\x6f\xb0\xf0\xff\x21\xf7\x65\x5b\x9b\x5e\xb5\x4d\x93\xfe\x60\xde\xe6\x6e\x1c\x2c\x1b\x62\x52\x6d\xce\x20\x86\x14\xb7\xe6\xf7\x77\xd1\x9f\x90\xa0\xbc\x03\x59\x36\x9e\xad\xdf\xa9\x65\x6d\x69\x17\x42\xbd\x15\xf9\x75\xe3\x85\x6b\xa5\x67\x2b\xb9\xf7\x7b\xde\x74\x2a\xe3\x3f\x4e\xae\x2b\x52\xb9\x15\x8d\xcd\x56\xa5\xda\xab\x9d\x79\xc6\x3b\xd1\x6a\x47\x8e\x60\xbf\xbc\xb9\x49\x32\x69\x1a\xe4\x77\xf6\x24\xdd\x0b\x7d\xf7\xab\x59\x1b\x56\x09\x75\xac\xd7\x01\xd2\x21\xda\x98\x0d\x23\xfb\x9f\x43\xbb\xf6\xc8\x95\x9f\x68\xc6\x03\x4a\x1e\x4c\x8b\x28\x4d\x2c\xbe\x51\x82\xc8\x70\x59\xe3\xb4\xf1\xc3\xf7\xd0\x21\x7e\x6d\x5b\x9d\x10\xbd\x34\xbc\x57\x1c\x05\x66\x9b\xc2\x15\x8e\x8b\x4e\xd5\x9d\xe5\xca\xd8\xf2\x69\x26\xc1\xa6\xc7\x09\x33\x41\x79\x61\x56\x03\x95\x41\xe5\x63\x11\x02\x7a\x4a\xe8\x1c\xd2\xba\xe5\x7b\xdc\x0c\xd1\x18\x57\x02\x57\x56\x54\x22\x76\x83\x90\xf5\x0a\xa7\x60\x23\xe7\xcd\x14\xc5\x42\x23\xda\x31\x15\x3f\xc4\x97\x95\xd2\x21\x7a\x3e\x05\x0c\x54\x89\x49\x85\x69\x32\x24\xfc\xcf\x68\x65\xc9\x46\xb8\x84\x50\x35\xfd\x04\x18\x11\xf3\x5d\x00\x7e\xe1\xbf\xd0\x57\xf2\x5b\xf0\x4b\x6e\x11\x1b\xb5\xde\x07\xc8\x2f\xb9\xdd\x6b\x3f\x28\x72\xe7\x30\x12\xfb\x5a\xce\x8a\x71\x71\x56\xa4\x91\x0d\x7e\xd9\x39\xa2\xb9\xed\x67\xbc\x6d\xed\x75\xab\xb3\x6d\xbf\x68\x9b\xc8\xb6\xb5\x83\xc5\x55\xe9\xe2\x8a\xa7\xce\x4e\x00\x64\x90\xbb\xfd\x03\x32\x90\xf7\x31\x23\xcc\x3f\x04\xc0\xc0\x07\x83\x8e\x88\x49\xcc\x2d\x11\xfb\x4b\x1b\x7f\x54\xc8\x2e\xed\xba\xa3\x53\x3e\xfc\x80\x92\x45\x40\x2e\x25\x0b\xde\xaa\x9d\xec\x2c\xa9\xf8\xcd\x8a\xf6\x7e\x4a\x13\x22\x23\x66\x5a\x0b\x12\x0a\xfe\xbf\x53\x75\xa8\x20\x0f\x3b\x09\xa2\x03\x2a\x7c\xe1\x1a\xc0\x52\xd9\x27\xd8\x74\x3d\x34\xdf\xa3\x32\x1b\xbe\xb6\xcb\x19\xeb\x91\x3b\x4a\x6a\x79\x09\x10\x97\x0e\xf2\x30\x1f\xe0\xbb\x21\xda\x86\x28\x40\xb1\x2d\xb4\xc1\x42\x34\x81\x20\x00\xca\x84\x6b\x4e\x6c\xdb\x90\x8a\x12\x9f\x6a\x05\x62\x99\x39\xee\xd0\xef\xbb\x08\x06\x1c\xf2\xf6\xe6\x51\x82\xd2\x3c\x28\xed\x45\x30\x48\x17\x22\xcd\x2f\xa7\x49\xc5\xbb\xcd\x9d\x44\xa8\xa6\x11\x68\x71\x98\xcc\x24\x28\x33\x11\xe9\xd0\xd9\x4b\x4a\x00\xec\x54\x8d\xd7\x97\xa8\xde\x9c\xf6\x1f\xf5\xf8\x97\x4f\xe6\x8b\x08\x33\xdc\x9f\xe3\x38\xed\x25\xb3\x1a\xdf\xa0\xdf\x1a\x7c\xf4\x52\xe8\xc7\x99\x76\x80\xcc\x1b\x7d\xb3\x46\xda\x82\x24\xa1\x64\x6a\x39\x5e\x51\x1c\x79\xca\x59\x7f\xa3\x39\x53\x6d\x75\x51\x93\x95\x63\x12\x63\x83\xc5\x85\x69\x23\xae\xa6\x8c\xa6\x03\x48\xf4\x05\xaa\xb4\x28\x99\x99\xd4\xc6\x52\x1f\xbd\x36\x7a\x7e\xf1\xd1\x7b\x53\xfa\x2c\xa8\xd2\xf8\x32\xcd\xa2\x35\x51\xed\x5d\x80\x1b\x84\xc9\x22\xf2\x64\x74\x40\x6b\x12\x11\xff\x6c\x55\xc0\x96\x94\x04\x47\xc3\xe1\x0f\x2b\x82\xf5\x9b\xcd\xfd\x72\x0a\x25\x10\xb1\xf2\xab\x4f\xc3\xd3\x99\x59\x95\xf2\x33\x7c\x11\x22\xae\xd8\x24\x19\xcf\xe0\x79\xd3\xd0\x41\xb2\x07\x7c\x77\x51\x11\x19\xf5\xb3\x51\x00\x6f\x7e\x93\xe3\x44\x28\x43\x2a\x8e\xdb\x47\x93\xc2\xfd\x8a\xaf\x81\x2d\xed\xcb\x4d\x2d\x9f\xfc\xc4\xd6\xb6\xef\xb8\xaf\x4d\x68\xb2\x47\xd0\xe8\x6f\xb5\x35\x97\x8b\xe6\xa6\x3e\x7a\x67\xda\x44\xea\x84\x1f\xf5\xbe\x6b\xcb\xdc\xf9\x94\x6b\x55\xa2\x2c\x31\xee\x79\xf4\x28\xa1\x86\xb2\x0d\xd6\x56\x14\x15\x3e\x68\x3a\x5b\xe6\x28\xf3\xa6\xf5\x69\x55\x3e\xa0\xe4\x41\x94\x6e\x6f\xf9\x31\x5b\x8e\x18\xb5\xf9\x35\x40\xd4\xe6\x5c\x6a\x20\x7c\xec\xe7\x11\xaf\x78\xbb\x9f\xfe\xd5\xea\x83\x4d\xef\x0c\x77\xf2\x0b\x23\xfa\xf1\x67\x1e\x65\x4b\xd4\x7f\x5a\x88\x0d\xbf\x73\x1c\x93\x94\x9a\x54\x68\x38\x81\x78\x65\x56\x89\xca\x59\x3f\x73\xa0\xf7\xcd\x15\x01\xb4\x82\xd6\x5e\x87\x86\xa5\x0c\x23\xfc\x5d\xe0\x9b\xe0\x28\xea\x27\x91\x97\xcc\xbe\x03\x7c\x79\xe0\xce\x26\x00\xdb\x8c\xe0\xbe\x51\xd3\xaf\x78\xff\xfa\x93\x66\xdd\x27\xdf\x3d\x6f\x33\xde\x7c\x36\xbf\xa1\xa9\xfd\xf3\x32\x42\x9f\x92\xaa\x06\x9d\x78\xf6\x23\x0b\xe7\xbe\xa7\xbd\x75\x0b\x2f\xfb\xe2\x36\xd3\xce\xc1\x8e\x47\x82\x67\x2d\xdb\x07\xff\x89\x86\x44\x4b\x0d\x76\xe5\x82\x89\xd3\xb7\x3f\x6c\xd3\xd3\xbe\x0b\x69\x6d\x98\xc8\x86\x79\x10\x94\x95\x4e\x14\xb3\xb1\xee\x5d\x1b\x69\xb3\xd7\xbd\x63\x3b\x0a\x3c\x3e\x89\xf4\x69\xf1\x7f\x7c\xdf\x37\x19\xfc\xae\x64\xf1\x5b\x90\x81\xb8\x1c\x60\xdd\xad\x46\x58\xd7\xb1\xd5\x57\x92\xba\xdd\xc9\x5c\x38\x7f\xf1\xc8\x05\x5a\x2d\xcf\x02\x01\x32\x40\x23\xe6\x65\x71\x66\xba\x04\xbc\xcf\x95\x22\x72\xa1\xa7\xd8\xe6\x26\x5f\x11\xdf\x68\x88\xc0\xb7\xe4\xfd\xce\x2d\x19\xa2\xc3\x6e\x09\xcc\x6e\xab\x3e\x6a\x4c\x2e\xa9\xb7\xdc\x9c\xa5\xb2\x84\x62\xbb\x5b\x8e\x41\x44\x67\x5c\xa8\xb7\x77\x79\x7e\x26\x81\x0c\x35\x6f\x84\x02\x5b\xb4\x07\x06\xaa\xa8\x45\x6d\x1a\xd0\x63\xea\xa3\x97\x11\xfa\x92\xa0\x73\xa3\x9e\xc7\x52\xca\xde\x2a\x91\xb8\x13\xf9\x9e\x87\x71\x9a\x7c\x3b\xdd\xde\xab\x5b\x3e\x16\x67\x55\xfb\x84\x35\x54\xbe\x69\xda\xdf\x39\xdf\x45\xf4\xaf\x98\x2e\xbf\x67\x2c\x56\x8b\x71\x12\x26\x79\x30\x4a\xa3\x7c\xb4\x44\xf8\x05\x99\xeb\xa1\x3c\x78\xb7\x6d\x99\x65\xa4\xb2\xa0\x95\x01\x71\x63\xbe\x15\x7c\xfe\xa7\x24\x0e\x35\x1d\x3d\x95\x48\xee\x26\xe5\xef\x9e\x05\x64\xa9\xcc\xbb\xb2\x0d\xaf\x3d\x84\x1b\x6a\xde\xc5\xcf\x13\x91\xed\x9b\x35\xbe\x01\x2f\x0c\x06\xdc\x52\xf6\x1c\xa2\xd3\x16\x43\xf6\x66\xc0\xed\x10\xf9\xcc\xac\xab\xb8\xc2\x55\x51\xea\x53\xc4\x22\xc8\xc1\x56\x2c\xe2\xb9\x57\xaf\x9e\x39\xd3\x7e\xcf\x43\x13\x78\x2e\xf5\x31\x21\xce\x19\xa9\x65\x37\xc8\xbf\xb9\x02\x35\x5d\x18\x4d\xfc\xf4\x43\x4e\x3c\xf0\xe2\x98\x30\x21\xfa\x4e\x6c\x18\xda\xff\x1c\x6e\x86\x88\x2d\xc4\x5a\x36\x95\x06\x54\xed\x4f\x01\x8a\x07\xa7\x38\xc6\xd4\x63\x84\xbe\xa3\x91\xa1\xcc\xab\xc0\xe8\xf2\xd0\xb4\x4b\xa5\x15\x3c\xec\xa3\x58\x13\xde\x2d\xe3\x59\xe3\x4d\x22\xdc\xcb\x81\x32\x6a\x91\x77\xdc\x0f\xa0\x3a\xab\xf6\x79\x18\xde\xb9\x3e\xc3\xc7\xc0\xb4\x89\x94\x67\x9e\xc5\xff\x25\x06\xf0\xe7\x77\x30\x80\xef\xf6\x2f\x78\xb7\x41\x2d\x31\x7e\x3f\xff\x6b\x8c\xdf\x49\x93\x47\x30\xbc\x3e\xe8\x78\xb6\x8e\x65\x75\xeb\x94\x94\x7d\xa8\x55\xde\x27\x5a\x9c\x88\x8a\xa9\x3e\x13\x2b\x60\x52\x68\x5d\x4d\xc5\xc4\x06\xbf\xfd\x74\xd3\x32\xfe\xd8\xbd\x47\x07\x2a\x36\xfc\x83\x07\xf7\xea\x92\x91\xdb\x5b\xa1\xc4\x68\x59\x8e\x25\x04\xdf\xdd\x97\xac\xf2\xf1\xd4\x10\x9c\x5b\x35\x09\x64\x21\x37\x7f\xdb\x21\x37\x7f\xdb\x90\x9b\xaf\x2c\x02\x6b\x88\x4c\x5b\xc8\x05\x59\x20\x0e\x8f\x7a\x0c\x7c\xdb\xe4\xc3\xce\xce\x20\x6d\x43\x0d\xa9\x21\xdf\x6c\x48\xf8\xb5\xd6\xf0\xf6\x5d\x5c\x7a\x53\x49\xbb\x1f\x45\x4a\x4e\x0f\x0e\xa4\xd3\x83\xad\x24\x83\xb1\x7e\x88\x21\xf5\x87\x18\x4e\xb5\x38\x90\x3d\xf5\x10\x53\x2d\x40\x64\x66\x52\xb1\xdb\xd0\x9e\x08\x68\xfe\x08\xa3\x2d\x14\xb7\x13\xe4\x15\x2e\x0c\xa8\x7a\x8e\x29\xe5\x8e\x6b\xb9\x55\x8f\x08\x6c\x93\x8f\x61\x4b\x7a\x0e\x78\x26\x3d\x07\xc4\x36\x67\x31\x25\x5e\xfb\xb5\xda\x26\xf7\x08\x7e\xe1\x1e\x81\x98\xdc\x23\x44\x01\x52\xd0\x94\xa2\x4e\xdc\x70\x97\x60\xf2\x94\x40\x74\x98\xc0\xc2\x7d\x7a\x1e\x3a\x50\x78\x4f\x20\x83\xf1\x68\x53\x53\x40\xa2\xbc\x48\x73\xd0\xab\xa9\x1d\x54\x3c\x25\xf0\x25\x99\xba\x6c\x73\x2b\x29\xcf\xad\xfb\x60\xf8\x13\x7c\x00\x28\xeb\xf8\xeb\xf6\x67\x97\x15\xed\xff\x7d\xf3\x53\x8b\x49\x78\xbc\x08\x50\x6a\x7e\xb0\x39\x34\x15\xf7\x7d\xb4\xdb\xb6\xb5\x53\x99\x67\xdc\xda\x7f\x17\xcf\x01\x2d\x3e\xf7\x0c\x3a\x81\x7f\xa2\xf7\x00\x9e\xd6\xc2\x83\x3c\xaf\xf0\xc2\x8c\xb3\x51\x7f\xae\x5f\x81\x7d\xce\x31\xf7\xce\xf0\x75\x6f\x4a\x68\x4f\x40\x39\x8c\x4f\xdb\xf5\xca\xff\x74\xc7\x06\x9d\x03\xf8\xeb\xfc\x1c\x1c\x26\xa8\x04\xe9\xd5\x78\x91\x52\xf9\x95\x64\x35\x61\xeb\xd9\x2d\x2e\xa4\x92\xea\x35\x9e\xe8\xef\x85\x68\x2f\x06\x02\x74\xc0\x2f\x21\xf6\xed\x2d\xc7\x0a\x02\xb1\x0d\xa9\xbb\x4d\x11\x11\x47\xb9\xbf\x59\xf6\x73\xe3\x54\x5c\xe0\xfc\x2b\x9d\xb9\xf0\xc3\x36\x5e\xf0\xc1\xac\x72\x76\x37\x1c\xba\xa4\xff\xf3\x0e\x5d\xd2\x05\xf8\x46\x55\xd1\xb1\xf9\x92\xe5\x2f\x8c\x3e\x47\x9b\x18\x60\x67\xe0\x2d\xba\x1d\xfa\xad\x6c\xf8\x25\xb2\x9b\x8a\xd1\x32\xfc\x06\xad\xe8\x78\xad\x28\xe7\x2e\x7b\x49\x1c\xf1\x2b\xc8\xc6\x6a\xca\x8f\x84\xc9\x3d\x6a\xda\xdd\x8d\x04\xa7\xc5\x4c\xe8\xdb\xa5\xfc\x2b\x0e\xb5\x63\xf6\xff\x2b\xcf\x5f\x2a\xcf\xff\x69\xe2\x0f\x03\xd3\xb3\xf5\xbf\xa7\x48\x7f\x85\xbb\xef\xbf\xab\xf4\x9e\xda\x19\x32\xdb\xb8\x2e\x31\x0e\xee\xb2\x64\x0c\x11\x5e\x08\x89\x58\x8b\x7e\x88\x0d\x49\x85\x2e\x29\x2f\xfd\x3a\x36\x4f\x2c\x94\xbe\xc2\xc0\x1c\x4b\xdc\x24\x84\x13\x7c\x0a\x13\x02\x4f\xcd\xba\x67\x66\xfd\x2d\x29\x9f\x53\xca\x24\xc4\xc8\x52\x57\x49\x1d\x2b\x19\x53\xb3\xba\x6e\xa0\x32\xad\x96\xac\x82\x36\xac\x6e\xd0\x20\x96\xa1\xae\xd0\xe8\x1e\xf2\x04\xb4\x40\x88\x4c\xdf\xf1\xaf\x54\xca\x1b\xef\x28\xec\x34\x17\xbe\x57\x92\x6b\x56\xa3\x3e\x3f\xa3\x28\x95\x7e\x37\x32\x1b\xa6\x8b\x2e\xf5\xe8\xef\x73\xfc\xda\x66\x05\x2c\x54\x46\xa2\xfe\xa8\xe7\x0b\xdf\x52\xb9\x83\x73\xfd\xd3\xe4\x8f\x7b\xc5\xdb\xcc\x32\x7f\xde\x42\x92\x56\xe9\xb5\x2f\xd8\x7c\x53\xd9\x57\x44\x68\x05\xde\x1b\x99\xa3\xc5\x8c\x7d\x93\x56\xd1\xcb\x48\xfa\x9c\xed\x54\x82\xbb\xdb\x3d\xa4\x31\xde\x20\xf4\x85\x66\xf0\x5d\xdf\x2f\x56\x6b\x3f\xc0\x89\x4f\xc3\x85\xd0\x43\x5a\xe1\x64\x5e\x21\x1e\x48\x8b\x92\x4d\xd4\x26\xfc\x60\x42\xf8\xc1\xbc\x89\x90\x76\x08\xb2\xf3\xd4\xa3\xdf\x67\xb6\xee\x7b\x34\xe0\xb4\xeb\x6e\x46\x30\xb5\x06\xfa\xd2\xa5\xcc\x0a\x4d\x2c\xb7\x08\x2f\xb5\x27\x12\x96\x36\x2a\x9c\x24\xb0\x29\xc4\x26\x82\xf2\x32\x42\x2f\x12\x49\xdd\x9a\x87\xc2\x1d\x4c\xe4\x45\x27\xf7\x93\x6f\xe8\xe4\xb9\x59\x00\x61\x44\x43\xb3\x19\xfe\xcb\x08\xbd\x4a\xb4\xba\xdf\x9b\xa0\xa4\x3b\x05\x38\xff\xac\x5b\xe5\x6b\xe9\x1e\x9a\x2e\x0a\x7b\x5e\x4b\xd9\xb9\xeb\xdf\xf0\xdc\xac\x4b\xce\xeb\xe4\x6f\x71\xba\x52\x9e\x00\x5f\xcd\x8e\x08\x57\x9b\x63\x3b\x12\x49\xb5\xd0\x65\xcb\xdd\x64\xba\xe5\x32\x9e\x78\x93\x92\x7d\x45\x07\x2c\x3f\x25\xb9\x4b\x03\x5c\x76\x69\xd0\x05\xff\x37\x1a\xfe\x0b\x44\x6c\xdb\x60\xd5\xdf\x2d\xf1\x6e\x0e\x5d\x3a\x28\xc0\x4a\xa1\x7f\x25\x3f\x05\x09\x4a\x16\x80\x07\x52\x1c\xbe\x17\x00\x05\x22\xdd\x12\xd4\x4c\xa5\x8d\xe6\x8a\x4d\xc3\x69\xed\xb5\xc0\xe8\xa3\x80\x93\xa1\xa0\x49\x86\xfe\x6d\x3d\xe3\xbd\x8e\x50\x88\xae\xff\xfd\x3d\xe3\xdd\x7d\x9c\x9d\x9e\xf1\x16\xad\x5a\x16\x5d\xc1\x4c\x24\xbf\xfa\x9d\xa6\x79\xeb\xe2\xd1\x4d\xb4\xd7\xc2\x87\x37\xda\x3a\x5e\x62\x5c\xf4\xad\x11\xb4\x5a\xed\xc5\x47\xc3\xef\x30\x18\xa7\xab\xc9\x09\x67\x6d\x4b\x50\x77\xc7\xf6\x3a\x42\x93\x29\x62\x52\xbd\xe3\x7f\x9d\xb2\x19\xa6\xb5\xc4\x29\xdb\x45\x27\x47\xfe\x9d\x86\x6d\x46\x35\xcb\x6e\xf6\x70\x1e\xad\x20\xf7\x68\x75\x41\x16\x2c\x5a\x5c\x90\xad\x74\x92\x84\x68\xc1\x8f\xe8\x1d\x0b\x84\x55\x92\xf0\x2f\xd5\x52\x48\xfa\x5b\xeb\x79\x4c\x94\xbd\xf4\x50\xc9\xf1\x5a\x7b\xad\xdd\x38\xa8\xd6\x51\x2e\xd8\xda\x6b\x48\x1f\x00\x41\xa5\x92\x8c\xaf\x1b\x74\xd6\x93\x2e\x03\x82\xde\xe4\x5a\x4d\xa6\x30\xd4\x6b\xaf\xa3\xcd\xf4\x64\x05\x65\x7d\xd7\x05\x02\x86\x45\x61\x3c\xad\x79\xb6\xeb\x18\x98\xb6\xc9\xb6\xc0\xa8\xc0\x60\xbc\xbd\x0a\x27\x3b\xda\xed\x64\xd9\x0d\x5c\x6b\x2f\x5b\xda\x10\x5b\x09\xf8\x61\x2f\x40\xc6\xa9\x5c\x86\x08\x0b\xb7\x71\x33\x81\x39\xc3\x16\xb7\x71\x59\xc9\xbc\x6f\xde\xfe\x34\xad\xa4\xf9\x25\xf7\x57\x9a\x07\x89\x5b\x1d\xef\x48\x1d\xaa\x27\x15\x85\xff\xa6\xc7\xa4\x4d\x0f\x5d\x2c\x00\x03\xe1\x63\x74\x8a\x1f\xa3\xba\x23\x85\x15\x1d\xbc\xdc\x8f\x94\x11\x6c\x06\xa7\x8b\xe5\xc1\x5d\x97\x6e\xf4\x98\xb0\x36\xc9\x84\x21\x61\xd2\xf2\x0c\x74\xd5\x3d\x0a\x6f\xd9\x28\xde\x63\x9a\x84\x24\xee\xed\xc5\xfc\x08\xf5\xcc\x97\xca\xd5\x4f\xbb\x3b\x9f\xeb\xc7\x6d\x67\x66\x32\x5f\xcd\x0b\x9b\xf5\x94\x7a\xb1\x3f\x73\xbe\x67\xd4\xaa\xbf\xd1\x72\xe7\x46\x9c\x3b\x18\x4c\x44\x8f\xdf\xc6\x7a\xff\x1b\xc1\x2d\x0d\xa3\x60\xc7\x63\xf8\x2f\x05\x9d\xee\xf4\xff\x13\xd0\x7b\x97\x60\xfa\x97\x43\x8f\x77\xfa\x77\x87\xde\x73\xa2\xe8\xce\x5f\x09\xbd\x53\xdd\xe9\xdf\x1d\x7a\x6f\xf1\x45\xf8\x57\x03\x8f\xaa\x3e\xff\xee\xb0\xfb\x1f\xc0\xbb\x8b\x6f\xc2\xba\x12\x1b\x65\x67\x70\xdd\x72\xfc\xcf\xbf\x41\xd2\xfa\xad\x70\x5e\xcd\xad\x4f\x10\x50\x9c\x24\xce\x6a\x0e\x84\x04\x7c\x3c\x59\xe5\x7b\x10\xe9\x5f\x3a\x25\xce\x1a\xdd\x65\x3e\x61\x3c\x25\xff\xb6\x93\x11\x57\x90\xbb\xcc\x46\xde\x4e\x56\x41\x55\x3b\x83\x93\xbf\x0b\x9a\x1e\x7a\xf3\x3b\x41\xc1\xe8\x6e\xe3\xdf\x65\x4d\x0f\x43\xff\xac\x77\xe7\x19\x85\xfe\xd9\xe1\xbf\xf3\xac\xde\xed\xed\xac\x3e\x9f\x33\xc4\x06\x69\x4d\xfa\xd0\x85\xa8\x97\xc6\x1b\xa9\x08\x49\x5b\x35\x6d\x36\x07\xa5\xfd\xde\x5b\xd7\x01\x4e\x66\xbd\x63\x71\xfd\xff\x9b\xdd\xb6\x04\x9a\xfd\x65\x87\x27\x5e\xee\x2f\xf4\x6f\xc0\x73\x14\xfb\xf3\xaf\x04\x5c\xdb\xfe\xfe\x9b\x01\xef\x08\x63\x9a\xac\x0a\x38\xe3\xab\x6e\x17\xe0\x42\xf4\x19\x4e\x16\x80\x07\x0b\x5c\x8f\x92\xf0\x37\x80\xcd\x36\x89\x63\x2c\x88\xd8\xbf\x16\x42\xd7\x1c\x42\x7e\xd1\xd9\x6a\x64\xb6\x14\x52\xfb\xef\x4b\x31\xbf\x7f\x2b\xca\xa1\xc7\x84\xf5\x7c\x12\x4f\xc3\xd3\x94\xae\xa4\x21\x69\x00\x71\x06\x67\x4b\x0d\xd2\xbe\x0d\xba\x42\x7a\x6a\x70\x4c\x6d\x04\xec\xc2\x04\x92\xc5\x77\x38\x98\x99\x78\xfe\x19\x5f\x93\x58\xd9\xd3\xfe\x9f\xe9\xcf\xd3\x9f\xa7\xbf\xae\xaa\xa7\x38\x25\x31\xeb\x4f\xbd\x79\x18\x29\xb7\x4e\x73\x12\x13\x61\x17\xb2\x92\x7f\x9d\x06\xb4\x2e\xff\xdc\xe7\xc1\x7c\xf1\x8e\xbf\x6d\xf1\x96\xbf\x18\xfd\x1d\xf9\x88\x77\x0b\x16\xfe\x95\x07\x22\x1b\xa4\xa2\xc7\x6f\x3b\x0e\x2f\x17\x88\x0d\xe6\x38\x99\x49\x58\x1b\x4a\x4c\x16\xc5\x4d\x7f\xaf\x76\x01\x54\x45\xce\x78\x11\x49\x03\x5a\xa8\x25\x5c\x19\xd9\x52\xf5\x50\xc4\x9b\xed\x8e\x4a\xa0\x50\xea\x78\x21\xfd\xc7\x7f\xf3\x3b\x07\x55\xef\x1c\x4f\x17\xee\x4d\xf4\xff\x52\x77\x3d\xcc\x71\xe2\xc8\xfe\xab\x10\xee\x2a\x91\x36\xed\xb1\x67\xef\xf6\xbd\x3a\x5c\x54\xca\x76\xec\xc4\x59\xdb\x49\x6c\x27\x9b\x64\x6b\x6b\x8e\x19\x60\x50\xcc\x00\x01\xe1\x3f\xeb\xf0\xdd\x5f\xe9\x1f\x08\x10\x63\xc6\x9b\x7b\xf5\x5e\xd5\x6e\x6c\x83\x68\xb5\x5a\xad\x56\x4b\xdd\xfa\x89\x24\x57\x8e\x6d\x43\xc2\xfd\x17\xbb\x82\xbd\xfa\xe1\xdf\xb6\x05\x63\xea\xa5\x54\xc4\x0a\xce\xf4\x22\xf5\x05\x72\xb2\x90\xfa\xbb\x82\x73\xad\x98\x8a\x3a\x89\x42\x12\x18\xbc\x82\xc3\xac\x73\xcb\xcf\x79\xd6\x17\xec\x99\xe1\xd9\x5e\xd6\x17\x31\x9c\x66\xee\xc0\x21\x73\xc1\x07\x15\xd5\xf3\xab\xe1\xf5\x7e\x30\x65\xc5\x08\x16\xcf\xd3\x92\x36\xa9\x24\xe7\x99\x10\xf9\x59\x4a\x8f\x98\x39\x6b\xbf\xdd\x97\x6f\xa5\x04\x8e\xd2\x7c\x75\xe8\x13\x2a\x0b\x75\x5f\x9d\x05\x37\x86\x37\x27\xa4\x30\x7d\xf0\x91\xd4\xa5\x65\x65\x67\xaa\x32\xde\x27\xed\x77\x7b\x59\xb7\xcf\xf7\x33\xd6\xe4\x83\xf5\x58\x19\xa7\x19\x33\x7d\x39\x7e\x61\x5b\xcd\x51\xd8\x0a\xc3\xb7\x35\xc9\x1f\xa6\xfc\x54\xed\xac\x47\x9d\xa9\x0a\x04\x1d\x64\x03\x21\xfa\x9e\xf5\x31\x42\x2c\x31\x52\xac\x13\x4d\xb3\xd0\xab\x14\xe5\x13\xf6\xd2\xf0\xee\xe3\x20\x9a\xa6\xf9\x5e\x86\x71\x0b\x12\x5c\x61\x38\x1a\xb0\xf7\x5f\xe0\x1b\x97\xe4\x61\x86\x2b\x38\x19\x28\x14\x0e\xb4\x71\xee\xe5\x96\xf8\xb1\x45\xd3\xe5\x32\x0e\xbc\x79\x1c\x6c\xad\x7c\xf5\x30\x26\xcb\x88\x36\x40\x36\xab\xf9\xd6\x2f\x56\x46\xb7\xfe\x61\x65\xdd\xd3\x11\x1b\xcd\xd0\x22\x9b\x68\x9e\x52\x9a\xae\x24\x06\x62\x76\x6b\x15\x69\x4c\x7c\x2b\x5f\xce\x3d\xb4\x03\x96\xf8\x6f\x32\xfd\xf9\x17\xfc\xa8\xf3\x36\x33\xb3\x91\x97\xf9\x29\x23\x66\xa5\x21\xbd\x60\x72\x99\xe7\x5e\x62\x3c\xd7\xf1\x2a\x45\xf6\xdf\x0c\xc9\xfb\xa6\xbd\x4d\x36\xe4\x57\x5e\xe2\x75\xcf\xac\x6f\xe8\x6e\x4b\x96\x12\xef\xda\xd0\xa8\xa3\xcc\x1c\x76\xef\x5f\x8d\xd7\x4e\xd2\xdb\xd0\xa8\xb4\xf3\xe2\xc6\xdd\x65\xc2\xdd\x04\x92\xc4\x24\x09\x8c\x00\x8b\x1b\xf4\xca\xd8\x13\x1a\xbc\x77\x1a\x10\xb8\xc4\x74\x79\xae\x71\xc9\xad\x61\x52\x8f\x19\xad\xe6\xfb\x91\xfa\xe5\xe0\xd8\x3c\x43\xe7\x4c\xaa\xe6\xc9\xd9\x60\x80\x6f\xb3\x3a\x75\x11\xef\xae\xb7\xe3\x2b\x5e\xb4\x79\xab\x72\x18\x0d\xb3\x0f\x41\x71\x06\x54\x64\x54\xb0\x79\x02\x34\x27\xa0\x3f\x7d\xc8\x8f\xbe\xf9\x0d\x7d\xf6\x16\xf7\xe6\xa8\x9e\xce\xf0\xf4\xd4\xe3\x18\x0a\xf4\xda\x87\x6f\x02\xda\x89\x4e\xa4\x0a\x49\x50\x6c\xa8\x89\x32\x12\xb8\x4f\x55\x53\x52\x13\xd9\x13\x79\x03\x8e\xee\xf9\xda\xb6\x99\xea\x65\x9a\x9d\x04\xd7\x41\xdc\x26\xd7\x77\x6c\x96\x59\x55\xc1\xdb\xc1\xc9\xca\x43\x65\x0a\x36\x9f\x42\xa0\xa7\x84\xa6\xd3\xbf\x6f\x53\x64\x17\xf4\x2e\x0e\x8a\x28\x08\x8c\x07\x14\x08\x4a\x17\x60\xc7\xa9\xe7\xdb\xb0\x48\x50\x8e\x2e\x08\x1b\xdc\xe6\x24\x1c\x56\x34\xc8\xf3\x34\x97\x65\x6f\x89\x3e\x53\x1e\x79\x24\x0e\x7c\x8b\xa6\x16\x23\x67\x1d\x5c\x5c\x58\x61\x9e\xae\x1c\x8b\xdf\x3c\x6d\x4a\x6c\xeb\x9c\x36\xa8\x30\xbc\x79\xdc\x02\xe4\x6d\x06\xfa\xb9\x16\x3b\x26\xf3\xed\x79\x9a\xd2\x82\xe6\x5e\xb6\xf5\xcf\xc9\xce\x64\x67\xcb\x8b\xb3\xc8\x9b\xfc\xd7\x96\x4f\x0a\xba\xbd\x28\x8a\xa6\xc0\x64\x45\x92\xc9\x82\x67\xe7\xdd\x9a\x80\x63\xcc\xf4\xf9\x9a\xce\xbb\x09\x8a\x74\x15\x6c\xfd\x73\xf2\xdf\x93\x1d\x4e\x55\x7f\xac\x11\xbe\x88\x8d\x0b\xae\x77\xa3\xb2\x52\xc7\x45\x24\xc6\xc1\xc3\x7a\x3e\x77\xae\xf9\x04\xf9\xcf\xee\xb9\xd3\x35\x1f\x6a\x67\xec\xf2\xc0\x1f\xb3\x6c\x35\xb8\x26\x63\x66\xa4\x13\x66\x4e\xb8\xb1\xda\x64\x9d\x25\xa7\x60\xe6\x43\x3c\x8c\x6e\x74\x9c\x8d\x3c\x72\x52\x61\x78\xf9\x18\x8d\x7c\xc3\xda\x10\x93\xb9\x19\x88\xa8\x93\xdb\x9e\x9b\xa0\x24\xe8\xa4\x56\xcf\x83\x8b\x0b\x46\x83\x4e\x98\x6a\xed\x09\xcd\x3a\xb8\xb8\xa8\x76\xa9\xe3\xa7\xf7\x39\xfb\x87\x84\xa8\xfe\xfa\x49\x1d\x17\x98\xe7\x81\x77\x65\x69\xd7\xc4\x49\x58\x89\xee\x9a\xac\x79\x3f\x5d\x7f\xf9\xdf\xda\x36\xff\xdf\xe9\xb7\xee\x5d\x43\x42\x0e\x79\x6d\x6c\xa5\x5c\x2a\xe3\x8d\x44\x04\xbd\xe3\x5e\xbe\x84\xd9\xa8\x3f\x62\x22\x56\x65\x79\xe8\x45\x09\x4b\x51\x57\x54\xab\x9b\x88\xc4\x01\x7a\x32\xd5\x4e\x08\x2a\x92\x53\xbe\x6a\xed\x15\x10\x2e\x8e\xf9\x70\x01\x7c\x58\xb3\xe4\x11\x49\xa3\x28\x87\x7b\x95\x3e\xe9\x10\x74\xd0\xea\x24\x82\x8e\x60\x51\x00\x9d\xd0\xe0\x96\x9f\x29\xab\x30\x7c\x34\xa5\x07\x0b\x94\x6d\x9d\x26\xfb\xc2\x39\x41\x41\x81\x02\x2d\x3d\xb3\xbe\x26\xdd\xa0\xb5\xf5\xd7\x81\xc6\x51\xaf\xb3\xce\x69\xc7\x50\xbd\x5e\xb4\x6e\x00\x7f\xef\x0d\xde\x9e\xba\xc8\xe1\x0e\x5d\x16\x18\x3e\x26\xe6\xeb\x3e\x4d\x22\xac\x30\xfc\xb6\xf6\xd0\xa8\x1a\x21\x8b\xd6\xea\xd9\xf7\xc5\x69\x19\x99\xdc\x2a\x12\x3b\x4b\x77\xa1\xa1\xe2\x79\xe8\x63\xc6\x0f\xc6\xd7\x0d\x4f\x5b\x5d\xf1\x0a\x4a\x48\x1b\xd9\xbd\x68\x7e\x77\x9a\x06\x37\x0f\x3b\xea\x5e\xf6\x55\x5d\x96\xbc\x64\x3d\xb3\x98\xcc\x76\x5e\xd8\xb6\x53\x7f\xcf\x9e\x56\xca\xe5\x10\x87\x21\x0c\x2d\x98\x6d\xd4\x82\x4f\x63\x8e\x86\xce\xb0\xde\xca\x3e\x93\x79\x81\x66\x78\x80\x4f\x91\x0b\x7d\xda\xbc\x51\x23\x71\x9d\x7a\x35\x3c\xd6\x95\x08\xd5\x3a\xa4\x95\xbc\x50\x3b\x0f\x8a\x82\x24\xcb\x7d\x05\xc0\x33\x92\x6c\x17\xb0\xa7\x43\xbb\xed\xaf\x19\x68\xa5\xb2\x24\xeb\xac\xd7\x83\xc8\x4c\x4a\xfa\x5f\x51\xf7\x50\x72\x1b\x03\x55\x48\x39\x60\xee\x2b\x77\x36\x9f\x3e\x55\x0f\xa6\xe2\x0a\xd2\x0a\xc4\x39\xd1\xaf\xc3\xc0\x87\xe2\xd2\x1d\x3d\x34\xfc\xe9\xd1\xd8\x86\x29\xab\x78\xbf\x06\x35\xf4\x28\x2c\x9e\xe7\x40\xd0\x4b\x58\x6c\xe5\x5b\x53\x10\x37\x5f\xc3\x9f\x26\xfb\x42\x9d\x30\xcd\xd1\xee\xae\xb2\x34\xa6\x49\x8f\x09\x2f\xaf\x76\xbb\xf3\x99\xc8\xb3\xfe\xfe\x9d\x0d\x0c\xfe\xa7\x9c\xc8\xf4\x27\xd2\x1a\x4b\xa6\x83\xdd\x3a\x0b\x7b\xca\x78\x5e\x88\x8f\x66\x3b\xbb\x0d\x96\x53\x22\xed\x31\xbe\xa7\xf2\xed\x14\x72\x37\x85\xc0\xd5\x4f\xfa\x77\x9c\x98\xde\x90\xdc\x65\x73\x18\x49\xca\xc0\xa2\x15\xa7\x2d\x60\x0c\x03\x01\x5d\xd8\xf0\x43\x5d\x2a\xa9\x07\x5c\x39\x5e\x3d\x84\xfa\x6a\xdb\xf8\xfb\x77\x89\x47\x65\xdb\x1c\x28\xa5\xee\x8a\x17\xd4\xf1\x72\xe4\xa1\x3f\x33\x28\x72\x36\x27\x16\x39\x73\xae\x74\x67\x9a\x43\xd0\x9b\xfa\x41\x09\xa0\x57\x83\xe2\xb5\x91\x11\xdf\xec\x92\x4f\x6b\x8b\x11\x3c\x9f\xfc\xfc\xcb\x4f\x17\x68\x2f\x47\x04\xbd\x52\x3b\x62\x3f\xa1\xe9\x56\xc0\xe1\xe9\xb3\xde\xfd\x0d\x0d\xae\x56\xa0\x91\x13\x5a\xb0\x97\x33\x51\xa5\x2e\x41\x5f\xe0\x36\x41\x73\x8a\x81\xa0\x99\x0f\x04\xc5\x14\xa6\x90\xf0\xa6\xf1\xa3\x07\x0b\x56\x36\xc7\x50\xba\x88\xa0\x3d\x58\x40\x82\xb7\x7f\xfe\xbe\x83\xb7\xa6\x1c\x81\x2c\xa5\x40\xd0\xd7\x8c\x19\x5c\x0c\x03\xd4\x16\x52\x50\x98\x63\x92\x7d\x65\x76\xab\x70\x2f\x90\x87\xb7\x2f\x50\x82\x21\x74\xff\x44\x83\xb7\x94\x0f\x74\x16\xfd\x29\xaf\x30\x4c\x7e\x81\x0b\x44\xd0\xeb\x0c\x52\x2e\x8d\x0a\x66\x18\x43\xec\x22\x46\x7c\x2b\x64\xf4\x3d\x0c\xbe\xaa\xab\xc1\xe3\xe2\x72\xf1\x60\x07\xbf\xd8\x71\xa6\xdb\xff\xf8\x09\xf9\xcf\x8b\xe7\x31\x93\xe3\xaf\x9b\xea\xc7\x8e\xa6\x1e\x53\xc7\x43\xef\x79\xd7\x00\x41\x9f\x65\x1f\x55\x18\xbe\x98\x9c\xd9\x75\x16\x91\x2a\x43\x5b\x38\x07\x39\xa2\x0d\xb6\x4f\x0d\x67\xc0\x94\xcd\x21\x28\xca\xc1\x66\x0b\x3d\xbd\x04\x55\x28\x73\x0e\x37\x15\xd3\x1d\xc8\x29\x22\xe8\x1d\xfc\x9a\xb5\x48\x81\xd9\x24\x49\x78\x54\xaa\xb0\x85\x72\x5c\xc1\x49\xc2\x1d\xeb\x42\x2e\x28\xfb\xe0\x76\xce\xb7\xda\x58\x57\xf0\x69\x94\xeb\x24\xc8\x3b\xaf\x3d\x44\xc5\x41\x71\xe1\x24\xfd\x7d\x9c\x93\xc4\xbf\x70\xbe\x7a\x0d\xf2\xdb\x3a\x07\x29\xf8\x11\xfe\xcf\x9e\xf4\x7f\xba\x90\x6b\x03\xbe\x0f\x8d\x1e\xe7\xfb\x30\x9a\x4e\xed\x26\xfc\xbd\xef\x26\x48\xc1\xe9\x9e\x8c\xec\xaa\x8e\xd1\x64\x96\x75\xc0\x95\x69\xb9\x87\x50\xeb\x84\xe6\xdc\xd4\xcf\x7a\xae\x0d\x67\xd0\xe4\x94\xad\xe3\x75\x94\x43\x53\xe2\xba\x2d\xa3\x18\x2d\x8d\x7c\x0a\xc5\x1c\xed\xcf\xf4\x54\xd9\xe0\xd6\x1c\xa5\x8b\xb2\x18\x49\x51\xa2\x68\x72\x32\xeb\x47\x8a\xa0\x7d\xde\x42\xda\x1c\x59\x49\x1b\x9e\xf3\x7f\xd1\x13\xd3\x9c\xc7\x23\x25\xf9\x5a\x5d\xbf\x64\xa8\xd7\xf9\x9a\xa7\xd8\xdd\x4d\x7e\xc0\x8f\xcb\x23\xf3\x16\xc0\x01\x85\xdf\x0a\x08\xe5\x79\xf7\x60\xf3\x61\x56\x5f\x01\x73\x14\x30\x15\xab\x65\x5e\x2f\xbd\x5d\x97\x69\xf6\xce\xe0\x3d\x88\xed\x9e\x90\xc4\x78\x23\x75\x59\x99\xf6\x73\xd2\x96\x1c\xf9\x56\xa7\xfa\x7e\x64\xff\xb4\xee\xb0\x71\x9e\xec\x68\x63\xc2\xb6\xa1\xb1\xfc\x43\x47\x7e\x75\x0b\x21\x1d\xbf\x0a\xc3\xbd\x8a\xae\xc6\x36\xf0\xbb\x95\x78\x40\x57\xcd\x1f\xa9\x76\x15\x0e\x86\xee\x65\x71\x4a\xa3\xa5\x99\x3c\x96\x66\xb2\x7b\x21\x18\xfe\xcf\xea\xbb\xd0\x49\xc5\x93\x66\xa0\x76\xb8\x9f\xf2\x23\xc5\x21\xa7\x53\xa3\x72\xfe\xca\x5c\xa1\x87\xae\xc4\x6a\xc9\x13\x8f\x59\xd8\xb7\x46\x53\x59\x77\xf3\xac\x23\x84\xfd\xb8\xcc\x95\x08\x5a\x33\xc9\x66\x4a\x35\xed\x90\xdd\xc8\xa2\xf6\xd4\xc3\x64\x4f\x05\xa6\xc5\x5d\xbb\xbb\x3c\xde\x5d\xe3\xa4\xd1\xe5\x18\x3a\x1a\xa2\xda\xd0\x9a\xe3\x73\x36\xc7\xeb\x9b\x25\xaa\x1b\x1c\xe9\x10\x32\x87\xee\x9b\x73\x82\x3c\x5c\x71\x90\xa5\xcd\x0c\x56\x12\xb9\x49\x0f\xba\xaf\x31\x46\x39\x94\xee\x02\x66\xee\xa2\xc6\xc5\x01\xd6\xe2\x1a\xdf\x03\x42\x6d\x05\x94\x42\x93\xfa\xc0\x5c\xda\x7a\x3b\x31\xee\xa7\x1a\xd4\x66\x8c\xd5\xe3\xbb\xf1\x38\x21\x96\x70\x2f\xe8\x3b\x3e\x28\x86\xfa\xf8\x1f\xf5\xbd\x4e\x9a\x6d\x94\x77\xaa\xd7\x94\x66\x70\xcf\x7c\x43\xe7\x65\xc2\xfd\xf8\xbd\x04\xf8\xba\x60\x1d\x9a\x97\x80\x05\x61\xce\xb1\x33\xab\x10\xee\xaa\x07\x6b\x90\xcc\xf4\xe0\x8d\xca\x5c\x82\x3e\x64\x10\x80\x87\x21\x72\x09\xfa\xc4\x7e\x9f\x8d\x19\x38\x4d\x2b\xf7\x09\xd4\xa2\x76\xb2\xa6\xc9\x11\x28\xbc\x12\x65\xc8\x7a\x8e\x22\x9f\x73\xcc\xb0\x2b\x9f\x6a\xd8\x9b\xa2\x80\xc4\x0c\xe3\xbd\xe6\x73\x85\x9a\x93\x47\xc8\x0c\xbc\xa6\x02\x59\xcb\x65\x1c\xd4\x18\x39\xc3\xea\x58\xf6\x74\x3e\xec\xea\xbc\x8e\xae\xe3\x9c\xa0\x98\xef\x8d\x0a\x6d\xd7\xea\x6a\xb0\x75\xfe\x72\x65\x35\x29\x53\x6d\x17\x01\xbd\xf4\xe6\x63\x4c\x4b\x09\xf7\xd4\x9b\x3b\x71\xdf\x9a\x9c\x16\xcb\xa3\x34\x3f\x52\x9d\x2b\x54\xe6\xda\x2d\xd0\x6f\x19\x84\x10\x00\xfb\x84\x69\x4e\xe6\x5e\xb3\xdf\x96\xec\xc7\x74\x9c\xee\xe8\x1a\xc3\x6a\xa7\xa1\x9a\xeb\x06\xbb\x54\x81\xf7\x2c\x71\x8b\xbd\x57\x52\xdf\x04\x77\x73\xb7\x40\x34\x6a\xb8\x9b\x31\xbd\x9e\x0b\xee\xe6\xa3\xb9\x6b\x74\xf8\x41\xae\xde\x9b\xb9\x3a\x6f\xb0\x99\x04\x63\x77\x6e\x81\x02\x8d\xb1\x45\x0b\xbe\x09\x2e\xdd\x3b\xc1\xe4\xdd\x68\x26\xb5\xef\x9d\xcb\x07\xf9\xfc\x55\xe3\xf3\x41\xe3\xdb\x1a\xe5\x6a\x10\xb7\x14\x84\x99\xe5\x34\x72\x0b\x14\x26\x70\x45\x80\xa0\x28\x01\x9b\x14\xe7\x6c\x4e\xb7\xe1\x8e\x5f\x51\xcb\x1e\x09\xac\xe4\xcb\xfa\x6f\x7e\xf3\x18\x7f\x80\x61\xd1\xf6\x43\x55\x8e\x85\x34\xc1\x5e\x1b\x33\x68\x91\xa0\x22\x94\x0b\x91\x2c\x48\x5a\x19\x75\x8b\x04\x79\xea\x5d\xd0\x85\x21\x4a\x50\x19\xf6\xd2\x2d\xd2\x44\x8f\xf4\xca\x51\xdb\x42\x87\xb0\x56\x65\x41\xad\x79\x60\xa5\x49\x60\xa5\xa1\xf5\x4c\xf0\xf3\x0c\xac\x67\xb2\xfa\x67\x56\x9a\x5b\xcf\x64\x7d\xcf\xac\x79\x49\xad\x1b\xaf\x78\x66\xb7\x43\xab\xcf\x26\x36\x1b\x94\x15\x94\xcc\xbe\x9e\x7b\xbf\xdb\xdf\x1d\xfb\x0f\x58\x24\x68\x11\x32\xa1\x24\x09\x2c\x22\x29\x9c\x42\x80\x55\x5c\x8a\xd5\x72\xab\xfc\x0f\xfd\x75\x91\xa0\x34\x54\x3d\x42\x7c\xd9\x1d\xe2\xcf\x1a\x82\xa3\x7e\x9a\x18\x81\xcf\x16\x09\x47\x02\xb4\x79\x30\xbc\x82\x8c\xfd\xc9\xbf\x57\xf8\x1c\xbc\x15\xb8\x69\x19\x87\x1d\xb1\xe1\xd4\xab\x1f\x0a\x5c\x91\xd6\xa3\x1a\x35\xa4\xf5\x74\x55\xc3\x71\x2c\x13\x94\x46\x2d\xb2\x3c\x19\xb2\x8c\xd8\x23\x26\xb0\xeb\xa4\xb3\x58\xaf\xcb\x74\x43\x71\x4c\x27\x3d\xf3\x27\xbe\x47\x3d\xbb\x3f\xdd\xd8\xf5\x9d\x8c\x3d\x6a\x82\x5c\x31\x8e\x9c\xa8\x7f\x99\xa0\x19\x63\x3b\xdc\xe4\xa3\x59\x84\x21\x36\x2e\xdf\x3e\x05\x23\xa2\xe5\x62\x34\xce\xa6\x0e\x4d\xd4\x09\xbb\x91\xe1\x72\x39\x6e\xd5\xa7\xfc\xcf\xb1\xdf\xd6\x66\x61\x36\x75\xfe\x1e\x20\x3a\x91\x0f\xb0\x01\xd4\x16\x57\xe0\x3f\xbe\x7d\xc4\x6f\x58\x24\xfe\x58\xfe\x34\x95\x57\x1f\x37\x40\x34\xa3\xd3\x09\xa4\xda\xd7\x14\x24\x32\xcd\xc8\xef\x9b\x01\x22\x08\xcc\x3d\x91\xaf\x24\xc1\x7a\x46\x52\x51\x23\x4a\xa3\xa1\xc0\x7b\x46\x52\x68\x86\xda\x6c\xea\x7c\x09\xb8\xdf\x19\x47\x40\xf5\x80\xa9\x29\x93\x9a\x75\x5c\x16\x0d\xee\x30\x92\x88\xef\x89\xdf\xe6\x60\x6f\x77\x73\x7d\xe8\xf0\x48\x33\x0c\xc2\x7c\x42\x7c\x83\xda\xec\xea\xbb\x18\x01\xbc\xf1\x10\x41\xdf\x3c\x0e\xcd\xce\x77\x8a\xa3\x68\x20\x76\x75\xb7\x40\x7e\x84\x72\x8c\x21\x79\x04\x83\x7d\xbb\xd2\xb0\xf2\xc6\x43\x1e\x3a\xf2\x98\xf3\x0a\x5e\xc4\xb9\xb8\x5e\x23\xa1\x1f\x22\x9c\x91\x92\x39\x61\x5c\x85\x91\x10\xcd\xea\x47\x30\xa5\xcd\xa6\x8d\x68\xde\x7b\xc8\x74\xbd\xce\x30\x4b\x85\x64\x69\x19\x0d\x5c\x9a\x9d\x1b\xa1\x8a\xf6\x7c\xbf\x0e\x09\x77\x37\xc4\x83\x56\xf8\xb7\x8e\x83\x0d\xc5\xa8\x4f\x42\x43\x5e\xb1\xbe\x11\x72\xa1\x06\xaa\x86\x8b\x04\x0b\x77\xe9\xa1\x40\x8e\x35\x69\x1c\xa1\x64\x0f\xd3\xd6\xcd\xfc\x2a\x1e\xea\xa1\x8f\x43\x18\xc5\x16\xdd\xca\x2b\x0c\x0b\x28\xf9\x05\x2e\xf6\xdb\xab\xee\xc9\xd8\xc4\xdd\xf7\xe4\x69\x03\xb9\x84\x54\xe7\x67\x25\x00\x26\x63\xc9\x09\x26\x7e\x99\x73\x70\x21\xc1\x8f\x3a\x17\xd6\x7b\x8e\xb4\xe0\x8d\xb6\xbe\x90\xcd\x74\x08\x3a\x0d\x21\x85\xa0\x31\x46\xa0\x08\x88\x77\x33\x68\x48\x76\x64\x75\x28\xcc\x11\x97\x54\x21\x24\x55\x0a\x49\x29\x62\x4a\x56\x5c\x80\xc5\xff\x53\x59\x89\x6e\x17\xd2\x28\x40\xa9\xc1\x06\x72\x7a\x29\x1f\x0b\x49\x85\x6b\x25\x15\xbb\x67\x1e\x0a\x31\xf8\x1b\x4a\xea\x39\x93\x54\x09\x71\x2d\x08\x5d\x58\x2f\xae\xa4\x94\x9c\xb6\x12\x8f\x68\xb0\x3f\xd8\xe0\xd0\xd4\xe0\x8f\x5e\x4c\x18\x99\x4b\xb2\x0a\x8c\x83\x55\x53\xbc\xb3\x10\x96\x5e\x4b\xf3\xea\x8a\xcf\x42\x78\x17\x1a\xa4\x63\xe4\xe5\x2c\x84\x33\x6f\x58\xfa\x07\xf5\xf4\x6f\xe2\xa7\xf6\x04\x44\xa3\x78\xd7\x04\xba\x7f\xd0\x69\xd8\x78\x6a\x67\x21\x5c\x84\x46\x5a\x92\x2f\xe9\x52\x18\xe9\x88\x77\x6d\x9e\x94\xc7\xd1\xe5\x68\x14\x9d\x9a\x9b\x0e\x15\x11\x9c\x6a\x65\xdc\x64\x2d\x30\xb8\x07\x2c\x2d\xdf\xdb\xcd\x34\x83\x8b\x79\x7e\x45\xf6\x7c\x0a\x9d\x2c\xac\x7e\xfa\xcc\x19\x73\x57\x9d\xc8\xf5\x50\xe8\x8b\x56\x1a\xaf\xf3\x6a\x62\xbb\x7c\x77\x59\xc9\x64\x0a\xca\xc5\xc5\x95\x5e\xd7\x5a\xc6\xa3\xae\xf4\xfe\x22\x2b\x42\xac\x7f\x85\x91\x96\x44\x3e\x72\x37\x7c\x13\x3e\xc4\x55\xdf\xba\x4c\xa4\xef\xfe\x03\x84\xf2\x78\x6e\x94\x58\x1e\xc7\x8b\x5a\xcc\x33\x65\xdc\xa0\x72\xb9\xec\x70\x12\x7e\xef\xf9\x46\x55\x72\x3c\xc0\xc8\x3d\xa3\x93\xb4\xa4\xcb\x94\x24\xcb\x77\x69\x4e\x91\x9d\x05\x79\x41\x0a\xfa\xb2\x95\x89\x6f\x1b\x77\x68\x2b\x0c\x77\x91\xf1\x0a\x1a\xe1\x48\xd4\x1b\xd1\xa9\xee\xda\x08\x73\xa2\xce\x55\x38\x62\xc3\xfb\x63\x88\xf2\x49\x98\xe6\x2b\xdc\x82\xcf\x58\x68\x13\x5f\x39\x76\xcb\x3f\x87\xfb\x7a\x59\xeb\xec\x93\x0d\x37\x6a\x8f\x63\xf4\x3a\x54\x1b\xb5\x51\x04\x89\xf9\x16\xa1\x79\x84\x4a\xcd\xce\x19\x73\xf1\x73\xb8\x8a\xe1\x33\x6d\x15\x34\xe6\x30\x57\x1b\x36\xea\x96\x20\xfb\x20\x2d\x63\x9f\x9f\x08\x2f\xca\xf9\x8a\x50\x8b\x46\x81\xc5\x24\x08\xea\xcc\x8a\x45\x0a\xfe\xfe\x2e\xa0\xd6\x35\x53\xf3\x89\x8d\x81\x95\x70\x5e\xd6\xd2\xee\x46\x6f\xc4\x97\xa2\x8b\x54\x32\x62\xca\x14\xb1\xe8\x4e\xce\xd4\x9d\x0d\xef\xf7\xb7\x76\x7a\x03\xfd\xae\x60\xed\x1c\x8e\xad\x76\xf6\x59\xfd\x68\xcc\x0e\x7d\x4b\x08\x32\xa0\x55\x48\xd6\xcf\x02\xb5\x55\x7d\x94\xa7\xab\x1a\xee\x74\x78\x47\x30\x17\xdb\x8b\x69\x3e\xa0\x05\x1e\xfa\x33\xe4\x77\xf9\x89\x9c\x3a\xae\x11\xe7\x01\x5e\x5b\xdd\x5e\xe2\xeb\x6e\x80\xa1\xd6\x7b\xde\x01\x1e\x7a\xab\xd3\x4e\x27\xb3\x9f\x31\xc8\xe0\xc3\x1e\x81\xa6\x91\x7b\xa4\xea\x87\x3b\xea\xb1\xb3\xbe\x6d\x1e\xba\x66\xea\x9b\x0e\xd8\x91\xe3\x18\x7d\x15\x8a\x8e\xdb\xbd\xcf\xeb\x30\x05\xba\xd3\x51\x81\xee\x1c\x44\x1b\x3f\x84\x48\xdd\x84\xa8\xb6\x72\xd3\x1c\x2e\xd9\x80\x38\x8e\xd1\xaf\x21\x5b\x17\x99\x16\xec\x79\x37\x37\xe1\x9a\xd4\xb2\x56\xee\xa4\x66\x2e\x3a\x4e\x70\x38\x8a\xc1\x3a\xce\xb3\x7e\x93\xf9\x38\x46\x9f\xc3\x56\xd0\xa6\x26\xf2\xd9\xab\xb3\xaf\x0b\x1f\x85\xac\xa1\xfa\xd4\x3f\xd0\x36\x03\x0f\x7c\x2c\x7b\x09\x1f\xa9\x3e\x29\xb2\xd8\xbb\xb3\x3c\x05\xa3\xbb\x27\xaf\xa9\x7b\xfc\x88\xe6\x14\x78\x40\xa1\x90\xa2\x1c\x13\x40\x69\xd8\x4b\x37\x4b\xae\x15\x5d\x4f\xd0\x32\x12\x7a\x27\x99\x7a\x40\xb7\xd9\x5c\x74\xb9\x3e\x22\x4a\x8d\xe9\x19\xea\x1c\x78\x4b\x65\xc7\x59\x90\xc2\x18\x6c\xd6\x86\xd7\xa8\x2c\x8b\x5c\x8f\xfb\xc8\xc0\x63\xae\xdd\xc3\x00\x75\x6d\xfb\x04\xcc\x10\xc3\x2a\x94\xe8\xa1\x55\xc4\x96\xa5\x10\x85\x6a\x40\xca\xc2\x2f\x83\x82\xe6\xe9\xdd\xc3\xc3\xbe\xd5\x4c\x73\x65\x27\x88\xe7\x9e\x10\xbf\xab\x28\xe6\x4a\x2c\x82\x4e\xe9\xef\xf6\x13\xfb\x0f\x30\xca\x70\x7d\xab\xda\x33\xa2\x87\x32\xd6\x40\x9e\x67\x71\x87\xb2\xd0\x34\xad\x2e\x26\xb3\x69\x7b\xf6\x48\xf4\x39\xc3\xe6\x93\xc5\xd0\x71\x12\x63\x70\xaf\x14\xc1\xbd\x41\x82\x10\x08\x8e\x5a\xbd\x36\x73\x4b\x6e\x35\xd9\x8f\x31\xb1\xab\x96\x1a\xcc\x34\xa3\xe2\x87\x10\x6e\x14\x9e\xca\x45\xe8\x72\xd1\x8d\x4c\xdd\x0c\x6f\x69\x51\xe3\x0e\xd2\xc6\x33\x45\x20\x3c\xce\xab\x5a\xfb\xfe\xaa\xe9\x48\xfa\xe3\xeb\x3f\xa0\xd0\x4f\xba\x75\xe8\xb3\x58\xe0\xdb\xfc\x58\x90\x36\x89\x25\xcd\x19\xab\x66\xbb\x6b\x53\xc7\xd2\xb9\x20\x28\xad\xad\x5a\x6b\x1a\xb9\x09\xc5\x5c\x11\x0c\xcd\x15\xda\x39\x0c\x0c\x9d\x08\xfb\x13\x11\xf1\xde\xcc\x21\xe4\x82\x6e\x2c\x6c\x47\x1c\xc7\x09\xa1\xda\xc1\xe0\xbf\x28\xec\xa9\xb2\x55\x1d\x85\xd9\x48\xc1\x1f\x20\xde\x1a\xfe\x6d\x87\x91\x63\xa7\x63\x3e\x20\xae\x22\x37\x44\x45\x02\xcb\x58\x46\xce\x24\x02\xa8\x1e\x9a\x4d\x4b\x3a\x17\x88\x40\x4d\xf8\xb6\x89\x48\xaa\x68\x61\x12\xa6\x32\x32\x78\x21\xc3\xbf\xab\x78\x20\xd6\xab\xf0\xd0\xf4\x67\x25\xf1\x6d\x98\xb3\xcf\x6f\x25\x4b\xd7\x9b\x7c\xce\x31\xc3\x78\x18\xf0\x22\x6a\x42\x96\x0d\x4c\x16\x7f\x75\xc5\x23\x84\xfb\x91\xeb\x23\x2f\x81\x48\xd1\x17\x18\xe2\x3a\xb5\x1a\x1a\xbb\xf7\xf0\x43\x11\xe4\xfa\xc3\x1a\xc8\x58\x7f\xa8\x00\x7a\x5b\xf1\x6d\xad\x18\x86\x3d\xd9\xc6\x2c\x6e\x58\x0d\xc9\xf2\xf3\xde\xe9\x49\x4b\x28\x1c\x27\xc7\x40\xe6\x98\x4b\x7b\x3f\xaa\x03\xa1\x35\x1e\x8e\x0d\x59\x82\x6e\x79\x43\xcf\x22\x57\xbc\x15\x21\xc3\xbd\x08\xc3\xf9\x50\xb4\x63\x93\x28\x83\x39\x6e\x5a\x89\x40\xc9\x89\x07\x01\x9c\x45\xed\xad\xfc\x1c\xde\xf0\x54\xef\x0a\xc3\xe1\x3a\x0b\x2c\xbd\x50\xb6\x2a\x10\x95\x34\xfb\xb1\x0f\x0d\x06\x5e\xde\xb9\x6f\xe0\x79\x84\xe1\x5c\x9b\x1b\x2a\xd7\x2e\xe7\x6c\x10\x1a\xfc\xd6\xa3\x18\x5d\xc6\xd2\xb5\xaf\x30\x9c\x0e\xc9\x8e\xdf\x3f\xcf\xaf\x5f\x9b\x7b\x45\xf0\xce\xa3\x11\xbf\x6d\xde\xcb\xc8\x87\x3c\x86\xb2\x99\x59\x4a\x7d\x66\x39\xf3\xae\xc9\xd2\xa3\xc1\x65\xaa\xe7\x5d\xc9\x29\x33\x76\x43\x94\x44\xf0\xa5\x80\x44\x03\x11\x98\xc1\x02\x52\x0c\x22\xe1\x0c\x32\xf6\x63\xcc\xb4\x9a\xc8\xb9\x84\xd1\x70\x7c\xe0\x47\x57\x9d\x3f\x63\x34\xc3\x32\x3f\x4b\xcd\xb5\x99\x5a\x95\xd5\xac\x69\x58\x05\xb6\xdc\x55\xe1\xfc\x5d\xbb\x21\xba\x8c\x20\x0b\x21\xd1\x11\x0b\x80\x7b\x26\x58\x24\xfc\xec\x88\xf4\x9f\x91\x1c\x6a\x54\x9c\xa5\xe4\xf1\x63\x8c\xa2\x9a\x47\x3d\xe3\xe6\x24\x86\x0c\xf7\x99\x15\x3a\x33\xc2\x7a\x26\x70\x2f\x6a\x78\x19\x77\x17\x55\x47\x31\xba\x8b\x9b\x6c\xa9\x9e\x28\x84\xf5\x17\x19\x45\x5c\x14\x77\xae\x87\x6e\x22\xb8\x0c\xd1\x1c\x37\xd2\x60\xc5\x98\x24\xae\x44\xfa\x4e\x36\x36\x7d\xa7\xe6\xec\x43\xcc\xe8\x69\xd4\x9c\x2b\x4d\x00\x6f\xcd\x02\x68\x21\x45\x08\x2e\x2f\x38\x97\x9b\xd4\xfc\x5b\x8c\x2e\xf4\xb5\xa6\x79\x45\x47\xd0\x2b\xd6\xf9\x5d\xa8\x09\xb6\xc8\xfb\x4c\xd1\xc5\xb0\x00\x15\xe2\x84\x60\xef\x76\x63\xf6\x5e\xc7\xe8\xd6\xb4\x14\x7e\x1f\xa2\x5b\x6c\xea\x38\x85\x00\xb5\x91\x62\x7c\x8d\x7b\x87\x06\x7c\x92\x07\x0b\xaa\x06\xeb\x20\xad\xa4\x37\xf9\xb6\x32\x4b\x71\x27\xa3\x9f\xdf\x36\xc8\x45\xb1\x2f\xf4\x69\xcf\x4d\xa4\x0f\x0d\x67\x2e\xcf\x92\x9d\xe7\x68\x1f\xd7\x99\xb2\xfb\x63\xb6\x78\x12\xe5\x49\x37\x8f\xf6\xa4\xf7\x74\x56\x75\xd7\x2c\x67\x69\x9a\x3d\xd4\xa0\x4e\xea\x5f\x7b\xa8\x59\x1e\x3a\x8c\x80\x73\x9f\xc0\xa2\xb5\x8c\xd8\x53\x86\x47\xb4\xf1\x5c\xd8\x35\x51\x54\xb3\x6c\x75\x93\xa5\x81\x3b\x17\x83\xe6\xfc\x31\x06\xae\x6d\xcb\x24\xbf\x5d\x3b\x76\x28\x0c\x98\x64\x44\x37\x61\x35\x2b\xd2\x92\x1d\x0a\x56\x0e\x1f\x67\xc9\x06\x8c\x56\x8b\xab\xc6\xa4\x9c\x0a\x5b\xd2\xe6\xaa\x31\x25\xa7\x82\x95\xd3\x4d\x59\x59\x6b\x3e\x5a\xac\xb0\xc1\x29\x58\x39\x70\x0b\x74\xd7\x65\x85\xbd\x16\x72\x39\x72\x0f\x04\x33\x07\x9b\x32\xc3\x68\x38\x47\xed\x4e\xda\xd7\x20\x20\x4e\x52\xcf\x1f\x77\x4a\x21\x81\x7b\x1d\x3b\xc2\x29\x4d\xc7\x88\x74\x24\x89\x8d\x48\xb7\x41\x28\x3a\xc4\xc7\x3b\xea\x09\xdc\xb7\x6d\x64\x9b\x12\xc7\x7a\x8b\x0c\x38\x46\xef\x99\xe7\x61\x46\x31\x1a\xc2\x0f\x3a\x8b\x51\x1f\x66\xa8\x0f\x63\x74\x6a\x2a\x66\xc6\x01\x3a\x1c\x2a\xda\x03\x22\x3a\x6f\x95\x34\x41\x22\x7d\x6b\xd3\x32\x61\xe1\xc5\xeb\x40\x84\xf6\xe3\x6e\xae\xe6\x41\x5c\x55\xf0\x6d\xd8\xa3\x7d\x43\xc1\xb6\x81\xa0\x32\x91\x5e\xb2\xdf\x89\xc6\x30\xb7\x9a\xca\x04\x9f\x37\x14\x9e\x4c\xf5\xc2\x59\x9e\xfa\x25\xa7\x2a\xd6\x3d\xac\x60\xea\x1e\x7a\x28\x79\x91\x4f\x32\x8f\x46\xe2\xc4\x4a\x44\x69\xe6\x6c\x6f\xc7\xe9\xc2\x8b\xa3\xb4\xa0\xce\xbf\x76\xfe\xf5\x8f\x6d\x1b\xc3\xc2\x6d\x17\xdc\xb6\xa1\x64\xbd\x9a\x1b\x92\x19\xa8\x5b\x1a\xaf\xfb\x6c\xc9\x71\x7d\xe7\x53\x36\x8d\x76\x04\xf4\xd9\xab\xb4\x40\x3d\x41\xa7\x11\x1c\x44\x8c\x81\x9b\x18\x85\x21\x46\xcb\x10\xa3\xdf\x42\x8c\xf2\x10\xa3\x12\xa3\x19\x46\xf3\x18\xa3\x86\x69\x8c\x52\x8c\x16\x18\xed\x13\xf1\x7f\xc0\x3d\xf8\x23\xb6\xac\x78\xbf\x80\x83\x08\xee\x49\x42\xa8\xf3\x2d\x02\xa1\xec\xce\x69\x04\xd7\xcc\xd6\xbc\xcc\xa0\x28\xe7\xf5\xd5\xc8\x85\x73\x87\x8e\x28\xae\x30\x0a\x12\x0c\x27\x91\x7b\x5f\xed\x92\x10\x9d\x44\x93\x53\x8f\x24\xae\xfc\xf9\xfd\xfb\x7d\x05\xd7\x29\xf1\xad\x9d\x27\xae\x7b\x14\x3d\x7d\x7a\x14\xa9\x32\x60\xb3\x7f\x6d\xf9\x1a\x83\xad\x04\x68\xbb\x2e\xbd\xcb\x82\x34\xb4\xfc\x20\x24\x49\xf0\xf4\xa9\xf8\x39\xf1\x56\x3e\x16\xbf\xa2\xdf\xff\x80\xde\x05\xb1\xd6\x49\x54\xe1\xdd\x20\x2e\x02\x8b\x84\xc8\x4e\xe7\x5f\x83\x05\xb5\x9f\x28\x62\xab\xd4\x2f\x63\xb9\x30\x39\x8e\x5c\x1a\x91\x62\x72\x18\xaf\x18\xd7\x35\x87\xc7\x11\x0e\xd3\x1c\xb1\x22\x6f\x23\x8b\x30\x92\xfc\x08\xb8\xf8\xe3\x38\xc2\x34\xca\xd3\x1b\x2b\x09\x6e\xac\xc3\x3c\x4f\x73\x64\x5f\x46\x41\x1e\x58\x5e\x1e\x58\xf4\x26\xb5\x0e\xe3\x95\xac\xa7\xb0\x16\x5e\x1c\x07\xbe\xf5\x6f\xfb\xf9\xdb\xe8\xb9\xfd\x6f\x2b\x4d\xc4\x15\x8c\x99\xb7\x0c\x9e\x58\xe7\x01\xeb\x0d\x95\x70\x4c\xa3\x60\x35\xb1\xf1\xee\x71\xf4\xfb\xdb\xe8\x0f\xf7\x84\xff\xa8\x78\x53\x14\x9f\xee\x49\x24\x1e\x08\xfa\x93\xe0\x36\x4b\x73\x5a\xb0\xc7\x78\xc2\xea\x42\xac\x24\xde\xfd\x9f\x00\x00\x00\xff\xff\x86\xa8\x62\x68\xa1\xeb\x02\x00") +var _uiAppScriptJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x77\xdb\x36\xb2\x38\x8e\xbf\x15\x9a\xbf\x5e\x15\x58\x8d\x15\x29\x49\x77\xef\xa5\x8c\xf8\xe4\xb1\x4d\x9b\x38\x69\x92\x36\xbb\xab\xf8\x2a\x34\x05\x49\xac\x29\x40\x01\x41\x39\x8e\xad\xf7\xfe\x3b\x78\x24\x48\x51\x76\xda\xed\xd9\xbb\x9f\x73\xbe\xfe\xc3\x22\x41\x3c\xcc\x0c\x06\x83\x01\x30\x33\x40\xf3\x8a\x65\x32\xe7\x0c\xe1\xab\xb8\x2a\x69\x54\x4a\x91\x67\x32\x1e\xbb\xf4\x48\x22\x89\xaf\xfc\x9b\x40\x02\x5f\x09\x2a\x2b\xc1\x22\x5f\x94\xfa\x24\x89\x04\x50\xbc\xdd\xda\x57\x31\x48\x45\x2e\x2f\xc9\x5d\x10\x03\x95\x9b\x48\x10\xdb\xa0\xae\xdf\x51\xb3\x4f\x62\xcd\xc6\x80\xe1\xed\x4e\x7b\xf7\x3a\xdb\xa3\xff\x62\x7b\x3e\x89\xb7\x41\x00\xae\x80\x68\x43\x71\xbf\x13\x0a\xf6\xe7\x43\xe1\x93\xb2\x5d\xc0\x20\xd3\xa0\xb5\x61\xfb\xae\x13\x36\xfe\x6f\x81\xcd\x27\x55\x5d\xe0\x42\x65\x00\x6e\x43\xfc\xd7\x4e\x88\xb3\xff\x2b\x88\x7d\xd2\xb4\x1b\x09\x98\x5a\x34\xda\x78\xfc\xad\x13\x8f\xea\x3f\x08\x0f\x9f\x94\xef\x43\x0d\x72\x87\x5c\x1b\xbb\xff\xee\xc4\x6e\xfa\x9f\x8d\x9d\x4f\x4a\xf7\x23\x0c\xa9\x47\xb9\x8d\xf3\xff\x74\xe2\x9c\x23\x09\x4a\x18\xba\x1a\xef\x12\x42\xa4\x29\x71\x2c\x75\x7e\x2d\x2b\x13\x89\x04\x46\x14\xd7\x05\x53\x53\x10\x6a\xf4\xef\x75\x16\x05\xe6\x0b\x23\x16\x94\x2f\x5d\x79\xa8\xa9\x75\x7f\x4f\x0d\xc0\xc3\x3a\x10\x0f\xaa\x99\xd7\xd5\x40\x4d\xe3\xef\xf6\x56\x04\x59\xab\x2a\x94\x05\xb5\x15\x61\x6d\x50\x77\xd0\x5f\x6f\xa8\x0f\xaa\xdd\x1a\x51\x15\x54\x3a\x6b\x56\x0a\x75\x27\xff\xed\xc6\x6a\x61\xda\x59\x31\x9a\x06\x75\xaf\xdb\x75\x43\xcd\x2f\xff\x7d\x4b\xed\x90\xef\xab\x1f\xe5\x78\xbb\x49\x45\xb4\x24\xc1\xbc\x1b\x4e\x50\x20\xf0\x55\x3e\x47\xf2\x68\x78\x7d\x2d\x1f\x90\xe7\x48\x60\x2c\x97\x82\x5f\x44\x8c\x5e\x44\x4f\x85\xe0\x02\xc5\xcf\xd9\x8c\x7e\x8e\xe2\xbe\xec\xc7\x51\x5e\x46\xbc\x92\x11\x9f\x47\x22\x65\x0b\x3a\x88\x1e\x2f\x69\x76\x1e\xc9\x25\x8d\x0a\xca\x16\x72\xa9\x3e\x5d\xf2\x4a\x44\xa9\x10\xe9\x65\x34\xcf\x45\x29\x23\x2e\x22\x35\xd9\x2f\xa8\x7c\x99\x5e\x9e\x51\xf5\xbe\xa0\xf2\x7d\x2e\x97\x4f\xe8\x3c\xad\x0a\x39\x88\xf1\xd8\x62\xcb\x34\x54\x8d\x09\x4c\x41\x39\xe7\x02\x29\x54\x28\x11\x83\x25\xcd\x17\x4b\x39\xa6\x0f\x86\x63\x7a\x78\x58\x7f\x63\x44\x3e\x78\xf0\xdd\x5f\xe8\x58\x0c\x0c\x30\xe5\x84\x9d\x1e\x11\x39\xc6\xac\xdf\x1f\xb3\x07\xc3\x5e\x0f\xc9\x43\x12\x7c\x3d\x1c\x9d\x62\x10\x44\x0c\x64\x7a\x56\xd0\x09\x3b\xad\x07\x9b\x49\x91\xa7\x8d\xe9\xaa\x31\xc4\x34\xd5\x9e\x23\x8a\x8f\x88\x3c\xa6\x49\x66\x3f\x37\x66\x0b\x53\x20\x9f\xa3\x21\x21\x04\x51\xf2\x02\x51\x8c\x2d\x02\x98\xfa\x46\x88\x18\xd3\xa2\xa4\x57\x06\x8b\x57\x48\x02\xc5\x35\xc0\xb4\x05\x30\xf5\xe0\x12\xdb\x84\x4f\xc0\x0e\x01\xda\x10\xf6\x20\x02\xa8\xc9\xf0\xf8\xe7\x64\x8a\x04\xbc\x4c\xe5\x72\x30\x2f\x38\x17\x48\x3f\x16\x7c\x81\x24\xbe\xe3\x9f\xbf\x60\x0c\x43\x90\xb8\x21\x59\x9d\xb0\xb0\x38\x05\x5d\xc3\x89\x62\x9a\x87\xaa\xdf\x11\x62\x87\x14\xff\x17\xfa\xd2\x1f\x61\x0c\x19\x19\x8e\xb3\x23\x6e\xb1\x18\x67\xfd\x3e\xe6\x93\xec\x94\x48\x44\xfb\x99\xeb\xf8\xab\x4c\x72\x91\xc4\x53\x5d\x3e\x06\x43\xa2\x64\x08\x1a\xb3\x84\x6f\xb7\xae\x99\x8a\x68\x00\xd7\xfc\x02\x7d\x01\x81\x21\x6c\x56\x7f\xc9\x68\x5e\x18\x00\xee\x54\x18\x43\x1e\x7c\x77\x30\xec\x87\x49\x63\x78\x38\x02\xda\xcf\xfe\x52\x19\x0a\xad\x72\x86\x68\x1f\x65\xfd\x11\xfe\x4b\x05\x4c\x55\xa9\x72\x3e\x47\xaa\x00\xee\xa3\xec\xc1\xf0\x38\x9f\x64\x87\xa3\xd3\x64\x78\x33\x36\xc2\x61\x03\xb6\x43\x93\x7c\xdb\x90\xc4\x9a\xac\xf1\xe4\x34\xd6\x43\x5e\xd5\x81\x6d\xb7\xfd\x3c\x76\xf8\x8b\x00\x9f\x2f\x18\x28\x99\x9c\x02\x23\xc3\xb1\x2a\x76\xe0\x8a\x8d\xb1\x50\xec\x21\x07\xd3\x21\x48\xf5\x33\x82\x7e\x9f\x11\x42\xbe\xf4\x7a\xa8\x44\x9c\xdc\x4c\x6e\xb1\x05\xaa\x06\x46\xa3\x25\x46\x86\x78\x9c\xcf\x11\x7b\x30\xc4\x57\xa6\xc3\x6f\xa9\x65\x50\xae\x8b\x3c\xa3\x68\xa8\xd4\xe6\x71\x89\xb8\x1e\x1e\x16\x0f\xd3\x03\x8e\xb7\x0f\x47\xba\x0f\xe8\x24\x3b\x35\xcc\x6c\xd3\xd5\x18\x28\x91\x4a\x56\x43\xc2\xf4\x3f\x9d\xd4\xa5\x4e\x9d\xdc\xa8\xec\xa8\x52\x05\x46\x84\x90\xaa\x51\xcd\xb1\x7d\x9d\x0c\x4f\x93\xaa\x35\x79\x19\x64\x28\x91\x4e\xb0\xe4\x73\xe4\x64\x04\x21\x84\x62\x3b\x2c\xbb\x91\xa5\xfd\x91\x45\x77\x72\xea\xbb\x75\x72\xba\x1d\x8b\xc1\xba\x2a\x97\x6a\xae\x14\x13\xea\x90\xd2\x49\xd2\x20\xc2\xc9\x73\xf5\xa8\xbf\xda\x82\x01\xd2\x88\xf7\x49\xf8\x69\xd2\x91\xcf\x88\xaf\x30\x5d\xd7\xcf\x6d\x62\x48\x00\xdf\xf5\xea\x8b\x1a\x36\xea\xf7\x77\xa2\xd4\x9e\xae\x1d\xe1\xf4\x6c\x5b\x0b\xf0\xaa\x28\x0e\x08\xa1\xc7\x34\xf9\x05\x09\x78\xad\x3e\x3a\x89\xd7\x9e\xa2\x6b\x31\xe2\x72\x34\xe5\xaf\x05\xfe\xe8\xcb\x31\xba\x9d\x67\x6d\x91\x52\xb3\x1c\xde\xe2\x26\xc9\x95\xee\xa1\x40\x1b\xd7\x30\x7f\x52\xd3\x9d\xe6\x68\x0b\xb2\x6d\x1d\x71\xf2\x42\x7d\xb2\x2c\xc3\x1b\xb0\x1c\x8e\x4e\x09\x05\xee\xbb\x85\xef\xf6\x49\xbf\x0f\xdc\x30\x51\x13\x09\xc7\x48\x21\x49\x0e\x47\x4a\x82\xa9\xe6\x1c\xfd\x78\x08\x37\xc3\x75\x53\xb6\x73\x6f\x6c\xf9\x39\x52\xf2\x89\x6f\x83\xbe\x68\x28\x30\x7e\x1a\x58\xa3\x1f\x07\x27\x79\xd1\x90\xee\xeb\xdd\xa9\xb6\x89\xf9\x98\x3e\x20\x66\xce\x95\x24\xec\xb5\xe3\x1f\x07\x8f\x39\x2b\x1d\xc2\x8a\xc3\x24\x4e\x74\x75\x3e\xc5\xe3\x27\xeb\x06\x97\x21\x17\xed\x11\x99\xb6\x09\xdb\xc9\xb5\x40\x6a\xc2\x86\xd5\x78\xab\x05\x00\xf2\x53\x66\x3d\xdb\xe3\x71\xad\x27\x0c\xc7\xec\xa8\x59\xc1\x98\x29\xe9\x53\x4f\xac\x0d\xf4\x24\xaa\x35\x04\x9c\x2c\x03\xbc\x58\x8d\x57\x30\xe3\x6e\x1a\x33\xee\x4a\x4f\x9a\xc3\x80\xd0\x2b\xa7\x18\xdc\x24\x58\xfe\x20\xe6\xec\x26\xcc\x39\x19\x8e\x79\x1b\x73\xde\xef\x63\xe6\x78\xbd\x85\xb9\x5a\x56\xd0\x3e\xf7\xf8\xf2\x53\x9c\xac\x02\xfc\xf9\x29\x0c\x09\xe1\xc7\x34\xa1\xfd\x5a\xaf\xe2\x4a\x30\x79\x79\x50\xe3\xbd\x68\x29\x44\xd4\x8d\x7a\x05\x9f\xe9\x15\xba\xdb\x2b\x82\x68\x28\x3c\xc5\x95\xac\x51\xda\x52\xd4\xec\xcf\xce\x92\x8b\xb6\x7e\xe4\xa0\x0a\x96\x4e\x67\x37\x43\xd5\xae\xf7\xf0\x70\xfc\x35\x20\x75\x17\x3b\xfb\x0a\x78\x2e\x77\xf5\x4c\xa5\x07\xf6\x89\xd2\x35\x31\x08\xfd\x2a\xdc\xeb\x05\x92\xf0\x4e\xaf\xed\x02\x06\x7b\x57\xab\xf6\x84\x18\xb5\xde\xb5\x33\xee\x96\xb8\xfb\xc5\xab\x13\xa4\xa4\x29\x60\x95\x62\x08\xdc\x4a\xd3\x57\xba\x3d\x60\xe4\x1d\x92\x87\x88\x3e\x18\x1e\xd7\xcc\x40\x8d\x62\xd4\x10\x05\x8e\xd2\x0e\x2a\x36\xbe\x49\x9f\x68\x8d\x84\x36\x1c\x14\xfb\x49\xca\xb7\x1a\x7c\xdc\x7a\x46\xdc\x51\x2c\x10\xf7\x30\x11\x16\xc8\x74\xaa\xb4\x3b\x86\xfb\x1a\x13\xde\xc6\x44\xc9\x57\x4f\xe9\x8b\xc6\x34\x26\xff\x74\x32\xfb\xa1\x66\xa1\xe8\x8f\x3a\xa8\x7e\xf1\xd5\x54\xa7\x1a\xa4\xa6\x54\xff\x13\x3a\x81\x76\x40\xe9\xfa\x64\x9f\xe0\x3a\x54\x5d\xc3\xbd\x5a\x46\xd8\x38\xd0\x0c\xa1\x22\xc3\x71\x75\xd4\x9c\x7a\xc7\x55\xbf\x8f\x33\xc5\xf8\xae\x58\x75\x1a\xcc\x8f\x93\xea\x94\x64\x7e\x16\xad\xbb\xe8\xbc\xd9\x45\x4d\xe9\xb9\xdb\x5f\x5d\x9f\xa5\xa5\xf8\x5b\xa3\xe9\x28\x42\x4e\x86\x4d\x05\xab\x4f\x27\xa3\x66\xca\x11\xf9\x52\xcb\x94\x76\x76\x57\xb3\x2a\xe5\x87\x43\xbb\x86\x3a\xd3\xf0\xb4\xd9\x68\x58\x61\xc6\x59\x96\x4a\x54\x97\xc6\xa0\xbf\xba\x49\x21\x5c\x20\x3f\xd7\x75\x28\x95\x43\x4d\x04\xba\x48\x53\x89\xd0\xb3\x41\x98\x3e\xe1\xa7\x7d\xc2\xc6\xba\x46\x37\xb3\x84\x2f\x8d\xe6\xdd\x84\xb3\x0d\x00\xdf\x3a\xc0\x6b\x78\x4c\x27\x3f\x34\xc4\xcc\x1e\x7c\xaf\x26\x6c\xf2\x58\xe7\x02\x55\x0f\x64\xd8\x57\xf1\x4b\x9d\x1c\x08\xb8\xb7\xad\x3e\x35\x75\xf7\x7a\x1d\x43\x6e\x22\x41\x68\xea\x8d\x0e\xea\x9c\xd7\xd7\xea\xcd\xe7\x54\x82\xd2\x3e\x87\x15\x48\xf2\x42\x69\x8e\x42\xeb\x67\xf0\x19\x49\x40\x8a\x07\x3e\xa9\xc4\x67\x4a\xa8\x62\x05\x15\x3c\x52\xe2\x57\x91\xd5\xcc\x01\x41\x65\x0f\x7c\x55\x9f\x91\xad\xac\xae\x41\x60\xac\xfb\x42\x90\x27\x9a\x7a\x1a\x47\x9b\xbf\x3f\xc2\xf5\x8e\x80\xe1\xbb\x67\xc8\xc0\x81\xf5\x4a\xac\x8b\xa7\x8e\x87\xc9\x48\xf5\x2c\x21\x84\x1d\x8f\x92\xe1\xd8\x00\xc6\x4e\x31\x48\xdd\x06\x57\x6d\xf0\xa0\x8d\x6d\xe7\xa0\xb8\xbe\xde\x3b\x12\x0c\x31\x1b\xfd\x67\xfb\x29\x3b\x22\xdf\x1f\xeb\xcf\xc9\x63\x3d\x81\x85\xfb\x71\x9f\x9b\xeb\xac\x96\x56\x29\x6b\x29\x2c\x40\x36\xa5\xb0\xc0\x8d\x94\x3e\x51\x62\x4e\xb6\xc4\x5c\xdd\xd0\x23\xcf\x17\xa2\x25\xed\xf1\x95\xac\x65\x4d\xd8\xcc\xd0\x34\x33\xae\xd5\xde\xe7\xa8\xce\xaa\x88\x3d\x1a\xb3\x23\xd9\x1e\x27\x5a\x5f\xec\x07\x79\x35\x99\x83\x8d\x27\x42\xb7\xba\x07\x1d\xba\xe5\x32\x9f\x4b\x64\xda\xb9\xa1\xce\x46\x15\xe1\xcb\x61\x08\xf2\xb8\x2e\x6b\xeb\x0d\x36\x12\x1e\xb6\xf5\xf8\x21\x18\x15\x49\x76\xa8\xbc\x7d\x52\x23\xd0\xfc\x5c\x2b\x65\x5d\xaa\x72\x3f\xd8\x35\x6b\x7e\x76\x32\xb3\x29\x1e\x5b\xc2\x1f\x05\x9b\x4f\x88\x1e\x8e\xf0\x9d\x2f\x58\x31\xa4\x47\xe2\xa4\xa5\x05\x51\x4f\xae\x63\x39\xa1\xa7\x89\x98\x50\x4f\x91\x60\x93\xee\x4d\xbd\x43\xd5\x2a\x41\x58\xb3\x0c\x09\x14\xd3\xa7\x75\xa9\x37\xae\x43\xdd\x94\xa6\x93\xed\xd4\xa8\x87\xdd\xf5\x35\xd5\x43\xa6\xd9\x79\xc7\xc3\xe4\x04\xf9\xc4\x9a\x13\x40\x21\x37\x7e\x13\x7c\x12\xf5\x27\xe0\x66\xc5\x56\x43\xf2\xd2\x2e\x1d\x8c\x92\x47\x86\x78\x7c\xd3\xea\xa8\x63\x71\x50\xeb\x3b\xed\x95\x50\x98\x09\x43\xb0\x5c\x79\xec\x48\x5d\xcf\x13\x2f\xbd\x08\xab\xf7\xc0\xbe\xc0\xcd\x5d\xaa\xb4\x51\x1e\x96\x64\xad\x2e\xbf\xbd\x78\x46\x86\xe3\x93\x9d\x0e\xc8\x70\x23\xe7\x7f\x7d\x21\x64\x38\xc6\x6f\x90\xad\x1f\xb8\xcb\x07\x5d\x65\x31\xbc\xa9\x17\x45\xb5\xb6\x60\x73\xef\x76\x8a\x2a\x91\xf5\xfb\xe3\x7a\xbf\x31\x83\xa9\x26\x5e\x8d\xda\xe1\x08\x86\x18\x72\x32\x1c\x67\x87\xd5\x21\x9a\xb6\x64\x8d\x12\xbe\xf8\x88\x8e\x8d\xc4\x4b\x49\x17\x58\x50\x92\x9a\xb2\x87\xcd\x1a\x20\x6d\xca\x5e\x35\x7b\xd9\x1c\x64\xda\x9c\xf5\xd3\x86\x1e\x96\x43\x89\x31\x4c\xeb\xa9\xd6\x21\x31\x27\xd3\x16\xbf\x42\x41\xe6\xe3\xe2\x68\xde\x2f\x0f\xf3\x71\xd1\xef\x63\x9f\x61\x52\x28\x89\x68\xdb\x99\x14\xa7\xaa\xc2\xfa\x53\x9f\x14\x0f\x86\xc7\x41\x8a\x96\xc0\xe3\xbc\x4f\xca\x16\xd8\x47\xa4\xec\xf5\x50\xd6\xef\x2b\x42\xa9\x4a\x3a\xf6\xa3\x9e\x22\x06\x5c\x1f\x91\xc0\x94\xb4\xe9\xab\xd4\x3d\xbd\x5d\xd8\xa6\x6f\xb3\xa0\xca\x36\xce\x8e\x6e\xe4\xae\x31\x76\x05\xba\x59\x44\x41\x59\xf5\xfb\x76\xe8\x4c\x18\xf0\x40\xa6\x7c\x0a\xf6\x4d\x9c\xb0\x6c\x4f\x62\x41\xf6\x67\x1d\xd9\x87\xc1\x77\xa5\x06\x5c\x99\x9d\xdc\x3d\xa3\xba\xa9\x6a\xcb\xd6\xc6\x56\x2d\x60\x83\x65\xbf\xe7\xdf\x40\x30\xd9\x02\x38\x3c\x27\x7c\x1e\x00\x17\xaa\x4e\xc7\x4d\x84\x92\x7a\xb2\x69\x0b\xba\x06\xae\xaf\xda\x53\x8d\x3e\x81\xf1\x47\x34\xc1\x7a\xc4\x1c\xc4\x50\x4f\xe3\x70\xbf\xe4\x75\x63\xbf\x44\x2b\x1f\xc7\x37\x6f\xf6\x4d\xe4\xe9\x36\xb9\x79\x93\x7d\xf2\xda\x6c\xe5\xe3\x60\x0f\x73\x74\x1a\x4c\x93\x4f\x1a\xad\x8a\x06\x31\x6e\xab\xfb\xc9\x6e\xdd\x8a\xb2\x61\xf5\xbf\x84\xd5\xdf\xdc\xd1\xf5\x7e\xab\xd2\x9f\x9a\x55\x82\xfa\xd7\x57\x1a\x4a\x58\xf9\xaf\x35\x0f\xd5\x62\x5d\xe5\xf4\xfa\xd8\x7b\x24\xf4\xe1\x4d\xd8\xf9\xef\x77\x05\xfd\x9e\x9d\x93\x70\x1f\xe4\x58\x4e\x44\x5f\xe9\x33\x7e\xbe\x4f\x74\x45\x7d\x64\x34\xcd\x61\xb2\xff\x80\x2a\x98\xd9\x7e\xd8\xe1\x3c\x3b\x71\xfe\x9c\xfc\x86\x64\xf7\x61\x94\x13\x80\x3b\x67\x52\x7e\xf3\xcb\x57\xff\x5b\xc7\xd1\xd4\xd7\x9c\x2c\x49\xbf\x84\x65\x78\x1b\x6c\x94\x35\x0f\x99\xb2\x1b\x0e\x99\x38\xc6\x50\x05\xdf\x33\x07\x1c\x4c\xc9\x70\x3c\x3d\x72\xef\xe3\xa9\x5a\xbe\x4e\xa6\xa7\xe4\x37\x7f\xc8\x34\xfd\x0b\x6f\x1c\x32\x4d\xfb\x23\xfc\x17\xae\x0f\x99\x2a\x95\xf3\x39\x52\x05\x70\x1f\x4d\x1f\x0c\x8f\xab\xc9\xf4\x77\x1c\x32\x65\x9e\x8f\xaa\xad\x3e\x05\xfe\x42\xee\xdd\x85\xef\xc9\x5d\xf8\xf9\x96\x9d\x74\x7d\x7a\x61\x5a\xa0\xab\xb5\xbc\x4c\x7e\x86\xb9\xe0\xab\x17\x79\x29\x93\x14\x24\xd7\x0f\x33\xc8\x59\x2e\xf3\xb4\xc8\xbf\xd0\x44\xa2\x0a\x43\xba\x5e\x53\x36\x4b\x24\x3a\xc7\xb0\xae\xca\x65\x22\xd1\x1c\x83\xa6\x6e\x22\xd0\x25\x86\x05\x95\x89\x44\x14\x43\x49\x65\x22\x10\xc7\xb0\x4a\xd7\x89\x44\x4b\x0c\x39\x9b\xd1\xcf\x74\xf6\x52\xbf\x6f\x30\xcc\x79\x31\x2b\x12\x81\x16\xe6\x51\x24\x02\x9d\xb9\x2d\x85\xe4\x39\x48\xfe\xe3\x5b\x0d\x7b\xf2\xab\x06\xcd\xbd\xfd\xb0\xdd\x22\x0c\x9b\x9b\x8e\xbb\x9d\xf0\xbc\x23\xae\x87\x3b\xa7\xcc\xee\xe3\x7f\x89\xd6\xb1\x6f\xc0\x54\x3b\xe7\xe3\x8f\x53\xc6\xb8\x8c\xd6\x54\xcc\xb9\x58\x45\x2b\x3e\x8b\x86\x83\xe8\x49\xbe\xc9\x4b\xbd\xbd\x78\x19\x7d\xa1\x82\x47\x54\xe5\x1e\xc4\x4e\xa1\x93\xff\x25\xec\x3a\x4e\x1e\x0f\x13\xa1\x56\x35\x0f\xc8\xd0\x6c\xa4\x26\x87\x1c\x1d\x4a\x38\x0c\x0e\x55\xb4\x4c\x1c\x26\xac\x75\xba\xec\x41\xf6\x03\x44\x04\x83\x25\xdc\xdc\xaf\xea\xe1\x77\x28\x5b\xb6\x32\xf5\x46\xe3\xf1\xa1\x4c\x64\xcb\xaa\xa4\xde\xc8\x1e\x64\x2b\x73\x46\x70\x34\x3c\x96\x89\x68\x19\x91\x74\xe4\x7b\xd0\xca\x57\xb6\x94\x7a\x93\x93\x82\x34\x35\xba\x57\x5d\x50\x24\x74\xe7\xbc\x29\xe4\xfb\x77\x93\xba\x9d\x7e\x43\xb0\x17\xcd\xce\x54\x0b\xfd\xce\x43\x90\x03\xd9\x38\xfb\xa8\x4b\x10\x42\x46\x77\x86\xd7\xd7\xea\xe1\x70\x74\x67\xd8\x38\xb1\xa8\x85\xd8\xb5\x6c\x6c\xf9\xd7\xe5\xff\xa2\x7b\xe0\xf5\xf3\x3b\xa3\xff\x1e\x36\x76\xbf\x6b\xf3\x1c\x97\xe5\x2f\xb2\xb1\x11\xed\x84\xba\x3e\xb8\xa5\xfa\xe0\x76\xec\x69\xf5\xae\x5a\x17\xf4\x2e\x12\xa6\x6c\xc6\x4b\x35\x96\xec\x5b\xa9\xe4\x47\xb8\x90\xb8\xfc\xba\xca\x4c\xe1\x4f\x42\x22\xf1\x17\xd1\xa7\x7f\xa1\xd8\xc8\xa3\x54\xa6\xec\xae\xee\x0a\x63\x42\xf2\x8e\x4c\xe2\x17\xef\x62\x88\x9f\xfe\x1c\x43\xfc\xfd\xbb\xd8\x1d\xbc\x5e\xcd\xf2\x8d\x19\xd5\x82\xae\x12\x89\x18\x86\x15\x57\x52\x80\x63\x58\xe7\x89\x45\x13\xa8\x79\x7a\x0a\x19\x2f\x13\x07\x3f\x94\x39\x4b\x1c\xf8\x20\x53\xfb\x22\x53\x06\xa9\xcf\xa7\x9e\x20\xf5\x39\xd5\x13\xa4\x3e\x6f\xaa\x33\x2b\x60\x13\x89\x6a\xc8\x31\xcc\xe8\x42\x50\x5a\x26\x1b\x50\x50\x96\xc9\x42\x0b\x8a\xd7\xbc\x48\x45\x72\x06\x92\x9b\xa7\x4b\x50\xb8\x27\x9e\x0a\x50\xf0\xc5\xa3\xb4\x54\x12\x2d\xc3\xc0\xe8\x22\x95\x34\xa9\x20\x3d\x2b\x93\x29\xac\x72\x96\x48\x94\x2b\xb1\xf5\x39\x91\x28\xc5\x90\x15\xe9\x6a\x9d\x08\x54\x62\xc8\xf8\x6a\x9d\x0a\x6a\x84\xde\x67\x2e\x12\x89\x0a\x0c\x8c\x2b\x49\x29\x45\xa5\x94\x75\x9a\x2c\x41\xcd\x1b\x39\x5b\x24\x7e\x12\x01\x3d\xe7\x25\xf5\xf4\x07\x82\x57\x6c\x66\x12\xf4\x23\x48\xfe\xac\xe0\xa9\x4c\xbc\x54\x0b\x58\x6d\x0b\x79\x79\x92\x9e\x24\xfa\x3f\xe4\xe5\x73\x36\x57\x72\x99\x26\x6b\x2d\x0a\x57\x9d\xa2\x50\x34\xb5\x36\x06\x9c\x4c\x4e\x21\x23\xd4\x9c\x54\x01\xc7\xe3\xac\xd7\x43\x8c\xf0\xc1\x9a\xaf\x11\xc6\x63\xac\x3e\xb2\xc1\x67\x60\x83\x4b\x93\xc1\x6d\xfb\x6c\x9b\x02\xd6\xd8\x81\x69\x2b\x81\xd1\x70\x88\xfd\x99\xa6\x3e\xbb\xbc\xfa\x9c\x48\xb8\x4c\xc4\x16\xc3\xc1\x70\x6c\x4f\x27\xdc\x34\x6d\x52\x62\x7e\xf6\x1b\xcd\x64\x7c\x40\xe4\xe5\x9a\xf2\x79\x64\x6d\x22\x5c\x2b\x31\xa9\x3f\xb4\x25\xf1\xb7\xef\xc4\x65\xce\x16\x91\xe4\xda\xdc\xe8\x23\x22\x04\x7f\x8c\x78\x6d\x71\x57\x0e\xa2\x77\x4b\x2a\x68\x94\x97\x11\xe3\xd1\x45\x7a\xa9\xf2\x9e\x33\x7e\x11\xe5\xf3\x3a\x57\x94\x0a\x1a\xc5\x72\x49\xa3\x32\x5d\xd1\x38\xca\x99\x36\x70\x7a\x5a\xac\xa2\x92\xb2\x92\x0e\xa2\x37\x34\x9d\x45\x2b\x2e\x68\x94\x9e\xf1\x4a\x46\x72\x99\x97\x51\x2a\xa3\xa5\x94\xeb\xe4\xce\x9d\x75\x9a\x9d\xa7\x0b\x3a\xa0\xc5\xea\xb0\x48\xd9\x62\xc0\xc5\xc2\x25\x96\x77\x5c\xea\x9d\x8c\x0b\x7a\xa7\x48\x25\x2d\xe5\x9d\x47\x69\x99\x67\xe5\xff\x8f\x90\xe8\x62\x99\x67\xcb\x68\x46\xcb\x4c\xe4\x67\xb4\x8c\x2e\x96\x97\x51\x2e\x15\xc8\xba\x15\x05\x74\xca\x66\xd1\xc5\x32\x95\x1a\xac\x33\x2a\x25\x15\xd1\x86\x0a\x3d\xdd\x5c\xe4\x45\x11\x15\x9c\x9f\x47\x45\x7e\x4e\x07\xdf\xba\x9e\x3a\x18\x6d\xed\x49\xb7\x9a\x72\xae\xaf\xed\x93\xa7\xfe\x48\xf7\x47\x94\xb3\x52\xa6\x2c\x53\x04\x7e\x92\x4a\x7f\x40\x23\x07\x0b\x2a\xdf\xe5\x2b\x8a\xb0\xde\x1a\xf4\x6f\xaa\xd4\x01\x8a\x95\x44\x8e\x15\x9d\x70\xcd\x56\x99\x26\x1c\x56\x19\x28\x92\x93\xec\x14\x84\xfa\xc7\xfa\x23\xe0\xb8\x6e\xd6\xf5\xbe\x02\x2f\x7e\xf3\xe8\x84\xcf\xe8\x94\x16\xab\xe9\x59\x95\x17\x32\x67\xb5\x4d\x4b\xaf\x17\xbf\x79\xf4\x54\x29\x24\xdd\xdf\xaf\xaf\x91\x24\x2f\x84\xdd\xb1\x15\x7a\x97\x23\x7e\x4b\x65\x23\x37\xa9\x6b\x53\xb9\x99\xcd\xcd\x4c\xee\x24\x09\x2c\x6f\xae\xea\x1d\x00\x09\x53\x22\xc6\xf6\x73\xe5\xa0\x31\xaf\x53\x6b\x70\x73\x65\x10\xad\x94\xb0\x9d\xaa\x7f\x6d\x44\x2b\x52\x0d\xa6\x23\x98\x92\xe9\x60\x3a\xda\x7a\xb3\x15\x55\xda\x57\xa3\x89\x60\xd5\xb2\x00\x12\x05\x45\x4e\x96\x03\xaf\xf7\x28\xb0\xd3\x46\x82\x39\x96\xc8\xad\xae\x79\x40\x48\xda\xdc\xb9\x3d\x18\x79\xe5\xb6\x24\xc3\x71\x79\xe4\xb2\x8e\xcb\x7e\xdf\x76\x52\x3e\x29\x4f\x21\x55\xff\x6e\xea\x24\xd5\x9b\x1a\x2e\x10\xe6\xa7\x9d\xf9\x8f\x32\x40\x5b\x1b\xeb\x16\x07\xc1\x24\x2d\x8e\x57\x89\x3c\x12\xc7\x9b\x64\xb1\xc3\xbd\x6f\xa5\xc8\xd9\xa2\xde\x73\xde\xa4\x45\x45\x5f\xcd\x11\x06\x4e\x44\xfd\xe6\x57\xa3\x84\x10\x7e\xbc\x4a\xe8\x11\x57\xd5\xe9\x7e\x08\xb9\xe1\xfa\xba\x69\x96\xa5\x99\x63\xdc\xc8\xe2\x39\x42\x04\x1c\x81\x32\xc2\x90\x9e\x80\xc5\x60\x3a\xc4\xf8\x80\x90\x95\x43\x21\x1b\x5b\xd3\x2c\x41\x44\xc0\x12\xd2\xb1\x84\xa9\xe7\x78\x95\x34\x9a\xf6\xe0\x4d\xf5\x14\x5e\x7f\xf0\x67\x9e\x7f\xc5\xf6\x88\x05\xaa\xe6\xa7\xbf\xe2\xc3\xa1\x3b\x6c\xaa\x1c\x14\x2b\x95\x52\x3d\x20\xa3\xaf\x80\xd7\xe4\xbc\xdb\xc8\x39\x52\x39\x47\xdd\x39\xef\x35\x72\xde\x55\x39\xef\x76\xe7\xbc\xdf\xc8\x79\x4f\xe5\xbc\xd7\x9d\xf3\xbb\x46\xce\xfb\x2a\xe7\xfd\xee\x9c\x7f\x6d\xe4\xfc\x4e\xe5\xfc\xae\x3b\xe7\xdf\x3a\xb4\x7a\x3d\x9f\xe7\xa5\x9a\xd8\x54\x4a\x12\x65\x46\xcf\xb7\x13\x7d\x24\x15\xf5\xcb\xe8\x22\x97\x4b\x33\x15\xc8\x65\xca\xa2\xbf\x46\xb4\xa0\x2b\xca\x64\x39\x88\x9b\x9e\x05\xab\xed\xd7\xb4\x51\xa7\xe4\x65\xc4\x59\x71\x19\xcd\xe8\x3c\x67\x74\xa6\xe6\xb1\x9c\xc9\x12\xa2\xb9\x52\x06\x4a\x88\x64\xbe\xa2\x25\x44\xd9\x32\x15\x25\x68\x4f\x1a\xb6\x28\x21\x2a\xf2\x52\x96\x11\x9f\xdb\xba\xd4\x8a\x2e\xd2\xec\x5e\x82\x9e\x38\x2c\xdc\x5d\x19\x14\xc8\xed\x75\x4f\x73\xa9\x69\xb4\xc6\x18\xa6\xc3\x44\xc2\x74\x94\x88\x6d\xcb\x39\xc2\xad\x57\xe8\x85\x1d\x81\xfb\x16\x21\xd1\x59\xbf\xdf\x32\x2c\xf5\x96\x40\xf5\x3a\x9c\x19\x11\xa2\x4d\x72\xe4\x84\x9d\x36\x3f\x08\xf3\x41\xa8\x0f\xbb\xbb\x4a\x79\x07\x02\x49\xd2\x0d\x7b\x5a\x4b\x1c\x43\xc8\x50\xcf\x70\xe3\xb2\xaf\x4f\x89\x3b\xcd\x33\x85\x5d\xd5\xe5\x66\xec\x5c\x62\x60\x84\x6a\x60\xcd\x10\x6f\x5b\x67\xb2\xc1\x74\x14\x64\xb6\x72\x80\x11\x16\xe8\xe8\x3a\x8f\x08\x37\xea\xcb\xc6\xc2\x26\x74\x66\xd8\x61\xad\x37\xa9\x66\x17\x1e\xa5\xd1\xc7\x27\xf4\xac\x5a\x0c\x32\x91\x96\xcb\x8f\x8a\x6c\x2b\x3e\xab\x0a\x1a\x7d\xd4\x26\xdd\x1f\xa3\xb8\x5f\x20\x81\xfb\xf1\x07\xf6\x6e\x49\xa3\x15\x2d\xcb\x74\x41\xa3\xb5\xe0\x9b\x7c\x46\x67\x6a\xfd\xaa\xd4\x8c\x8c\xcf\x68\x94\x56\x72\xc9\x45\x94\x97\xc9\x07\xf6\x81\x45\x51\x14\xc5\x7d\x1a\x1e\x3d\xcd\x5b\x0b\xbc\xd0\xbb\xe2\x5f\x80\x51\xb5\xf6\xce\x68\x3f\x65\x94\xa5\x55\x59\xc3\xf5\x31\x4b\x4b\xfa\x31\xa2\x9f\xd7\x82\x96\x5a\x03\x72\xf8\x0c\x3e\xb0\x57\x8c\x2a\x46\xd7\x6a\x92\x48\x59\xb6\xa4\x65\x44\x99\xc2\x4a\x0f\xdb\x34\xd2\x0d\x9a\x61\xb1\xa4\xd1\x9c\x17\x05\xbf\x50\x2a\xa4\x1e\x0f\xd1\x82\x2b\x15\x4b\xf0\x6a\xb1\x0c\x10\x9e\x21\xaa\xa9\xf5\x07\xe9\xc5\x70\x73\xa9\x1a\xec\x15\x97\x32\x15\x72\x50\xe4\x8c\x2a\x4e\xa1\x6c\xa6\x9f\x8f\x63\x95\x31\x67\x34\x8a\xfb\x61\x9e\x24\x3e\xa3\xf2\x82\x52\xf3\xb1\x6c\x7d\xed\xc7\x1a\x2d\x95\xe8\x2a\x6a\x2d\x82\xed\xe2\xd0\x72\xf9\xb8\xa5\x65\x7b\xcd\x30\x3e\x72\xa9\x0f\x62\x9d\xe9\x8c\xf3\x82\xa6\x8d\x3c\x91\x3c\x8e\xdf\x89\x8a\xc6\x49\xfc\x2c\x2d\x4a\x6a\x32\xb2\x6a\x75\x46\x45\x33\x5f\x3f\x8e\xf7\x4d\xd5\xb6\xb9\x6f\xe3\xbe\x5a\xd4\x1f\x0c\x71\x3f\xfe\xd6\x54\xe4\x87\xa4\xaf\xe8\xdb\xf8\x5b\x93\x6b\x84\xfb\xdf\xc6\xdf\x8e\x03\xd5\xd6\xd5\xa3\xde\xe3\x70\x49\xa1\x8a\xf7\x7a\x81\xaa\xea\x75\x03\x33\x45\x56\x67\xa6\x1d\x34\x84\xef\xb4\x32\x65\xc4\x5d\x6c\x6c\x80\xa7\x64\x72\xda\x16\x4b\xa6\xae\x03\x42\x58\xaf\x37\x35\x4b\x9c\x19\x52\x62\xca\x6f\xc3\xc6\x28\xee\x4f\x07\xbf\xf1\x9c\xa1\x18\x62\xdc\x8f\x71\x6c\xe7\xee\xb4\x3c\x8f\x03\x13\xa8\xf8\x48\xa6\xe5\xb9\xa5\xf0\x8e\x02\x68\xf3\xe8\xe4\x81\xdb\x8b\xd3\xac\xb8\x94\x7a\xd3\x57\x95\x3a\x9a\x51\xc5\x74\xe2\xc1\x6e\xc1\xfa\x93\xa9\xff\xb5\xe0\x19\x2d\xcb\x8e\x8c\x6b\xf3\x25\x51\x7c\x93\xcf\xfa\xb1\x2d\xd1\x54\x8c\xa7\x24\x9e\xa8\xc6\x95\xf8\xc2\x0d\x29\x17\xe6\x1b\xe3\x69\x9f\xc4\xe0\x33\x5a\x29\xe7\xc4\xdb\xb4\x1f\x9f\x1a\x62\x74\x08\x54\x95\xa6\x1b\xde\xab\xbf\xbb\x8c\x6f\xa9\x6c\x52\x44\xeb\xf4\x86\x22\x1d\xab\x89\x50\xa1\xeb\x5a\x4d\xec\xd4\xff\x24\xcf\xda\x0d\x08\xdd\xc0\x94\xc4\x71\xbd\x5f\xec\x55\x5d\xcf\x13\xdc\xd9\xb9\x28\x96\xe0\xa7\x18\x2a\x92\x4d\x86\xa7\x63\x45\x94\x28\xee\xa3\xf8\x4a\x2f\x26\xae\xaf\x63\xe4\x1e\x8e\xec\xc3\xb7\xf1\xb7\xe6\x21\x1b\xe8\x8d\xd1\x57\x73\x14\x47\x31\x3e\x1a\x1e\x67\x89\xe2\xa8\x4c\xf1\x11\x6e\xea\x8b\xfd\xe9\xb6\xc5\xeb\xc6\xfe\x6f\xcf\x8a\x2e\x3e\x52\x3d\x2c\xb9\x9d\xa4\xb1\xeb\x69\xa9\x16\xad\xd3\x0b\x7a\x36\x2d\x79\x76\x4e\xfd\x68\x3a\xba\xa0\x67\x26\xe5\x41\xac\xe7\xba\xae\xf1\x60\xc7\x00\xeb\xc7\x11\xd1\xa4\x6a\x8c\x05\xbd\xeb\xef\x0e\x0e\x8f\xe3\xab\x6d\x9c\xc4\x57\x51\x30\x3e\x22\x35\x40\xa2\x6d\xbc\x75\x6d\xe6\x4c\x52\xc1\xd2\x42\x29\x37\x55\x26\x2b\x41\x1f\xc4\x3b\xe6\xca\x6e\x10\x0b\xba\x2e\xd2\x8c\xa2\x3b\x1f\x3e\xdc\x59\x40\xfc\xe1\xc3\x87\x0f\x31\x0e\x52\x99\x49\x65\x8d\x44\x69\x12\x65\x23\x51\x98\x44\xd1\x48\xdc\x98\xc4\x4d\x23\x71\x68\x12\x87\xb5\xfb\x92\x38\xa6\xc1\xf7\x6f\xcd\xf7\x6f\x63\x9c\x84\xc9\xf1\x9d\x05\x7c\xfb\xe1\x43\xfc\xad\xd9\x5b\xdb\x90\xc3\x11\xac\xc8\x10\x16\x64\x04\x67\x64\x08\x97\x6e\x83\x7e\x72\x1a\xd7\x5b\xf1\x9f\x12\x01\xd9\x6a\x9d\x30\xd0\x5a\xd8\x30\x69\x28\x65\xc3\x78\x6b\xd2\xef\x26\x1c\xb2\xa5\x48\x32\xa8\xd6\xb3\x54\xd2\x64\x0a\x8b\x2a\x9f\x25\x55\xbd\x41\x9f\x62\xd0\x13\x5f\x52\x9a\xdf\xc7\x69\x49\x93\x39\x38\x6e\x48\x66\x7a\xef\x68\x41\x64\xed\xaf\x1d\x90\x5a\x38\x5c\x8d\x0d\xec\x74\xa8\xfe\x8d\xf0\x16\xc3\x19\x41\xa2\x51\x24\xb4\x62\x45\x1d\x3a\xa4\x50\x7a\x18\xdd\xaa\xb2\x7b\x0b\xea\x56\x40\xe0\x2d\xc6\x70\xb9\x03\x92\xdf\x07\xc3\xf0\x8e\x74\x6f\x90\x5d\x90\x8b\xeb\xeb\xab\xed\xf8\x62\x12\x1f\x5d\xc7\xa7\x7b\xab\x40\xaa\x0d\x40\x36\x3b\x9e\xc4\xd7\x0f\xf6\xe7\x56\x32\xa0\x99\xfb\x81\xca\xbd\x17\x0b\x81\xa4\xde\x9f\x6d\x14\x39\x3a\xba\xa9\x88\x44\x62\xb7\x48\xbf\x1f\x9f\x92\xd5\xc0\x74\xa5\x1e\x88\xe7\x64\xe5\xc7\x31\xbc\x25\x68\x33\xa8\x77\x01\x41\xbd\x9c\xa4\x27\xb0\x19\xd8\x4d\x44\x0c\x9f\x55\x16\xbb\x0d\x09\x1b\xb3\xe7\x88\xe1\x91\x4a\x75\xfb\x94\xb0\x31\x3b\x8f\x78\xbc\x19\x30\x2e\x61\x33\xf8\xcc\xc5\x38\xa4\x8c\xa2\xe3\x66\xc0\x45\x08\x5a\xaf\xa7\x13\x53\x0b\xd7\x43\xb2\x19\xac\xd2\xcf\x70\xa2\x6a\x5e\xe5\x0c\x36\x03\xbb\x74\xc2\x61\x55\x0f\x88\x2e\xb5\xa0\x0d\xc2\x98\xc4\xa2\x91\xf8\xc0\x64\x94\x8d\x8c\x26\x5f\x23\xed\x8e\x29\xcc\xe8\xa7\x30\x95\x98\x54\xfa\x69\xbc\x19\x28\x04\xd7\xb9\x86\xf2\x0d\xd9\x0c\xf4\x2e\x2e\x3c\x55\x70\xda\xed\x5f\xd8\x0c\xd2\xb3\x12\xc3\x4b\x5d\xcf\x22\x95\x74\xbc\x31\xfb\xc3\x1b\xb3\xbf\x6c\x7f\xd5\x4f\xa9\x51\xd3\xbb\xd4\x9b\x81\x49\x2b\x2d\xb6\x65\x88\xe8\xff\x9a\xf6\x3f\xaf\x43\xa8\xfe\x4b\x27\xae\xf8\x6c\xbc\x19\x08\xba\x0a\xf3\xdf\xb9\xa3\xbf\xcd\xf2\x4d\x03\x39\x9d\xa8\x97\x80\x4f\x9a\x5f\xfe\x62\xaa\xaa\x8a\x30\xf1\x50\x27\x96\xd5\x59\x83\x87\x4c\x3f\xcd\x54\xa3\x76\x23\x5c\x31\x82\xdb\x1e\x57\x68\x54\x82\x29\x74\xec\x26\xba\xa6\xd4\xe3\x5b\xc4\x41\xfc\x63\x55\xea\x89\x87\x9a\x6d\x0a\x25\x19\x12\x35\x2e\x3f\x39\x69\x76\xc2\xe5\x52\xe9\x71\x5b\x78\xf6\x3b\xeb\x92\x48\xd5\x86\x93\x4f\x5b\x0c\x2f\x3a\x86\xb9\x6d\x40\x97\xd2\xeb\xbb\xed\x16\x9e\xff\xce\x36\x5e\x20\xdb\x8a\x69\xe6\x55\xc7\xc0\x6c\xba\x6b\xec\xca\x31\x57\xb3\xfb\x44\x08\x61\x6e\x6b\xc8\xb5\xc6\x06\xd3\x61\x47\xda\xc8\x01\xa1\xc4\x9d\xce\x33\x1d\x82\x4e\xf7\x10\xfd\x48\x10\x6d\x81\x04\xac\xed\x89\xa7\x5b\xbe\x17\x00\x05\xd3\xbb\x09\x6b\x41\x76\x4f\x35\xca\xdb\x50\xf0\x0e\xc8\xb8\x83\xac\x99\x76\xd7\x41\xab\xd6\xcd\xdc\x42\xcb\x0d\xb4\xa0\xbf\x7b\xa8\xd9\x0e\xc8\xe0\x35\xa3\x06\xd0\xf7\xdb\x40\xc3\xf4\x5e\xc2\x5b\x90\xdf\x57\x00\x64\x6d\x88\xb2\x0e\xc8\xb3\x0e\xc8\x33\x07\x79\x33\xed\x9e\xc3\x46\xad\xaf\x33\x8b\x4d\x66\xb1\xc9\x0c\x36\xa0\xf3\x79\xac\x78\x07\x56\x90\x19\xbc\xaa\x26\x5e\xdf\x75\xe2\x05\xd3\xfb\x49\xd6\x42\xee\xbb\xc6\xee\xb2\x03\xb0\xea\x40\xae\xea\x40\xae\xea\x40\xae\x72\xc8\x35\xd3\xee\x3b\x84\xd5\x72\xbd\xb2\x08\x57\x16\xe1\xca\x22\x5c\x19\x84\x41\xe7\xf7\x88\x77\x1d\x27\x65\xbf\x63\xa3\xc5\x44\x9e\xf0\xae\xac\x97\xfa\x5c\xd2\x6e\x44\x53\xe3\x23\x93\x21\x69\x7c\x14\x3b\x7c\x63\xa6\xcd\xe2\x93\xd3\x1d\xb7\x57\xeb\xef\xd7\xb1\xe0\x10\x3b\xf1\x01\x42\x43\x98\x29\xa2\x7a\x6b\x18\x32\xe2\xac\x05\xc7\x99\x02\x88\x6b\x5f\x1f\x36\xc9\x4e\x83\x63\x2f\xbe\x13\x16\x20\xac\xab\x06\x4b\x38\xea\x9b\x57\xea\xb7\x7f\x34\x94\x7a\x87\xca\x2a\x50\x43\x8c\xed\x3e\x30\x50\x42\x03\xb0\xab\x46\xb8\x85\x75\x3d\xf0\x6b\x5b\x95\x5b\xda\xf3\xaf\xcc\x36\x6f\x8f\xe3\xd2\xb0\x79\x2d\x74\xda\x30\xb4\x76\xa4\xaa\x46\xc8\x86\x65\x38\xa0\x6b\xdf\x8d\xdf\x07\x8c\x7f\xe5\x16\xb6\xcc\xc0\x56\xee\xc0\xa6\xe5\xcc\x1e\x00\x81\x6b\x49\x55\xc3\x19\x1a\x9f\x6f\x9a\x43\xd4\x41\x3a\xfd\xd7\x20\xf5\xaf\x99\x5b\xec\x1a\xc0\xe7\xdd\x80\x6b\xb9\x72\x33\xf4\x90\x69\xa1\x55\x23\x11\x06\x88\x58\x34\xb4\xcf\x0a\x4d\x91\xc0\x83\x92\x8b\x60\x8e\xdb\x35\xac\x90\xda\x7c\xde\x28\x91\xb8\xe5\xf0\xf6\x15\x75\xd9\x98\x0a\x26\xb4\x84\xc1\xd2\xca\xab\xa7\x3f\xc7\xd6\xf4\x2b\x7e\xf1\xce\x3c\x1e\x8e\x92\xd1\xd6\x1a\x0b\x74\xae\x5f\x4e\xf2\x22\xb9\x84\xc7\x9c\x95\x49\x06\x99\xfa\xd1\x67\xec\x92\x1b\xd3\x9d\xa9\x3e\x9f\x37\xcf\x95\x37\xfa\x29\xb4\x8d\xd0\xdd\x44\xa0\x99\x7e\xba\x97\x50\xb4\xd6\x4f\xf7\x13\x86\x96\xfa\xe9\xbb\x84\xa3\x0d\x06\x85\xc0\xa3\xcb\x44\xa2\x85\x79\x7e\x9f\xcb\x65\x22\xd1\x19\x56\x8b\x19\x0c\xaf\x09\xfa\x71\xe0\xd2\xc1\x3c\x3e\xba\xc4\xf0\x64\x47\x4d\xd0\x27\x3b\xe6\xf4\xc6\x59\x98\x0c\xf1\xd1\xa8\xbd\xd5\x1b\x6e\x06\xd3\xd6\x66\xb0\x24\xf2\x70\x04\x42\x77\xf2\x76\x8b\xe1\x17\xd5\xb8\x02\x15\xf4\xcf\x7d\xf3\x73\xcf\xfc\xdc\xc5\xf0\xeb\x5e\x20\x6e\x69\xcb\x1e\xdb\x5a\xc5\xc5\x1f\xa4\x4b\x22\x83\xd6\xdf\x13\xd4\xbd\x8a\x39\xc8\xd1\xaf\xb5\x44\xaf\x93\xf5\x52\x48\x2f\xb9\xe0\xc7\x81\xee\x0a\x0c\x3f\x74\xe8\x43\x21\x90\x8c\xd0\x00\x48\xd6\xb1\x3b\xce\x89\x84\x8c\x38\xfd\x46\xc9\x77\x49\x38\x08\x92\x01\xd5\xc3\x40\x81\xfa\x1b\xd9\x05\x27\x4a\xd1\x0f\xb0\x6f\x19\xd6\x1f\x6d\x31\xa8\xca\xb6\xf0\xe5\x77\x96\x95\x7d\xe1\xcb\x7e\xbf\x6f\x9d\xd7\x4d\xa1\x68\x35\xa0\x9f\x90\x00\xe9\xc8\xf4\x73\x87\x52\xda\xd8\xd7\xda\xc2\x3f\x1a\x59\xec\xe6\xab\x1b\x50\xe1\xc1\xe1\xf1\x0b\x24\xac\xb6\x0b\x3f\x91\x9f\xf4\xda\xf5\xa7\x89\xca\x72\x4a\x7e\x1c\xa8\x91\xa3\xc9\xf9\x4f\xb2\x67\xec\xa7\xe8\x7d\x13\x65\xda\x3d\x37\xeb\x93\x72\xad\xb7\x6e\x31\x04\x03\x16\xa8\xc2\xe8\xef\x3b\xd5\x3b\x71\xd0\x55\xb3\x5e\x0f\x1f\x77\xcc\xfd\x74\xab\xd6\xf7\xe3\x00\x34\xb6\xdb\xd6\x37\x7b\x75\x6d\x59\x3b\xc6\x07\xda\xb2\xa6\x52\xb3\x31\xcd\x52\xbe\x3d\x90\x72\x5f\x87\x2a\x10\xbe\x51\x98\x87\x50\xe8\x3e\x14\xf2\xf7\x31\x50\xb7\xa6\xb3\x53\x31\x50\xd9\xd8\x16\x69\xa8\xed\x6d\x6a\xba\x91\xd4\x60\x8b\x4e\x84\x73\xc5\x7e\x66\xd2\xb6\x78\x07\xed\xd6\x14\x17\x12\x29\x0c\x38\x34\x4b\x53\x55\x26\x2c\x00\x4c\xef\x34\x74\xb3\x54\x43\xf2\x1c\x8b\x64\x87\xc3\x6e\xa5\x89\xdb\xc0\x61\xb2\x6b\x93\x46\xd5\x47\x65\x83\x70\x6a\x64\xf1\xbd\x9d\xc8\x24\xca\xd1\x3f\x41\x6a\xf3\x34\x0c\x99\xfc\x4a\x66\xb5\xe4\x05\xae\x97\x61\x5a\xd5\x0b\xf4\xc3\x80\x85\xc3\xc5\x5d\x07\x4e\x7c\xab\xfe\x67\xdb\xa4\x23\x3b\x0f\x48\x1b\x96\xc9\xb6\xdb\x3d\x03\xa1\xa3\x31\x4d\x83\x76\x17\xe9\xb1\x52\xc9\x86\x34\x17\x21\xd7\xec\x91\xbf\xe1\x64\xdc\xcd\x76\x9d\xe2\x61\x0f\x1e\x54\xe1\x01\x19\x51\x28\xf0\x46\x9f\x29\x62\xb6\x6c\x93\x5b\xa3\x33\xdb\x76\xee\xf4\xdd\x32\xe3\xd2\xb1\x41\x50\xec\x9d\x60\xa8\x9f\x71\x99\xd1\xae\xf6\x09\x87\xad\x62\xc2\xe9\x5e\xbe\xd2\xa3\xa5\x92\x8a\xb1\x42\xcc\x34\x93\xe5\xb2\x43\x4a\x79\x88\x45\x08\x71\x9b\xe0\x37\xee\x19\xc8\x64\xc6\xaf\x84\xfa\x57\x1b\x75\xdc\xad\xd5\x4e\x7c\x26\x68\x7a\x6e\xcf\xe7\x1c\xee\x76\xf5\x57\xa3\x6f\xcf\x68\x0e\xec\x47\xf7\x5d\x55\x39\xb2\x9b\x0e\xb6\x22\x31\xb6\x15\x6e\xcb\x8b\x5c\x66\x4b\xa4\xbf\x5d\x65\x69\x49\xa3\x51\xe2\xf2\xe8\xd7\xbb\xc9\x9e\xbe\x1c\x59\x7a\x76\x7d\x68\x7d\xd3\x9c\xbb\x35\xf5\xdd\x4b\xea\xa3\x24\x9f\x79\xd4\xc1\xa9\x7f\xa8\xa5\xf6\xb7\x4e\x40\xb6\x0e\xfb\xf1\xcc\x44\x1e\xdb\x0f\x92\x37\xe7\x09\x6b\x1c\x05\x06\x59\x9c\x34\xdb\xca\x48\x00\x57\x45\x3c\xf4\xad\x0a\xa6\x43\x28\xdb\x49\x81\x5d\xae\x61\xff\x11\xbd\x87\x1f\x0c\x5b\x22\xbf\xda\xc5\x36\xdb\x4d\xea\x90\x3f\x53\x95\x94\xa3\xa9\x04\x71\x78\x1f\x4a\x6d\x97\x92\xfc\x99\x75\xa7\x28\x97\x20\xfb\xa3\xa0\xfe\xad\x63\xb3\xed\xc5\x32\x2f\x28\x3a\xd8\x2f\x1a\x3a\x7b\xaa\x5d\x2a\x52\xd3\x7a\x7a\xc3\xb4\x9e\x4b\x18\xea\x19\x61\x8b\xa1\xec\x1a\xab\x3b\x52\xa6\x31\x66\x23\x39\x96\xa4\x63\x92\x94\x5b\xb5\x66\x3b\xd4\x4b\x36\x25\xbd\xe6\x72\x9f\x36\x1d\xa5\xa8\x6c\x4d\x62\x56\xb1\xb8\x09\x94\x03\x14\x98\xd5\x8f\x70\x5b\xe6\x75\xc8\x64\x25\x33\xb4\x7e\x6f\xa0\x62\x5a\xa6\x15\x37\x50\x66\xbe\x2b\xd0\xb6\x18\x66\x37\x94\xf8\x05\x24\xe4\xa8\x50\x14\xfd\x0d\x09\x7c\x38\xc2\x06\x93\xb5\x24\x68\x69\x0f\x1f\x60\xe9\x3c\x09\x97\xc6\xbc\x4c\xfd\x52\xb9\x4f\xdb\x36\x58\x0e\x41\xe2\xa3\x51\xaf\xe7\x70\x76\x75\x20\x81\xf1\xd1\x50\x6f\x7f\x2e\x07\x0b\x2a\xcd\xd4\x9e\x7c\x52\xa8\x2d\x75\xa3\x6a\x71\x0d\xcb\x81\x76\x48\xd9\x51\x53\x6e\x57\x4d\x73\x57\x85\xfa\xd2\x54\x49\x97\x7a\x89\x53\x00\xf3\xd5\xeb\x89\xd6\x24\x0b\x70\x9f\x97\x83\xda\x49\x05\x96\x6a\xe1\x06\xcb\x81\x71\x86\xc1\xb0\x91\x64\xe9\x4f\x89\x61\xa5\xde\x6a\xf7\x18\x58\xec\xe7\x99\x1c\xad\x14\xb2\xda\x27\xb7\xb9\xbd\x66\x07\x8b\xaa\xf4\x31\x9f\xd1\x2e\xeb\xef\xd5\x20\x5b\x0a\x64\x8e\x7e\x74\xeb\x8f\x97\xa9\x50\x99\x91\xc4\x78\x0b\x92\xef\x2b\x28\x07\x99\xcd\xf9\x50\xa2\xa1\xce\xfa\xcb\x7a\x4d\xc5\xfe\x46\xe4\xc0\x66\x79\x9c\x96\x14\x99\xda\x5f\xf0\x8b\xdb\x8a\xe8\x2c\x8d\x22\x59\x5a\xd0\xaf\x68\x2b\xc8\xb8\x53\xfc\xab\xda\xf5\x19\x5d\x71\xb3\x0d\x70\x26\x09\x5a\x98\x03\x7d\x85\x3e\x2c\x54\x6e\xf5\x84\xe1\xd2\x7c\x6a\x14\x86\x45\x0b\x18\x97\xe0\xbf\xe9\x54\x0c\xef\xba\x24\x8e\x61\xcb\x33\x89\x28\x6e\x0a\x78\x06\x67\xda\x6e\xe3\xc1\xa1\x1f\x0b\x3a\x49\x8d\x02\xb5\xa0\xbd\x90\x24\x47\xef\x24\x18\x84\xe2\x87\x31\x76\x8f\xff\x8c\x31\x86\xf3\xe6\xe7\xb4\xfe\xfc\x45\x7d\x7e\xdb\xfc\x3c\xac\x3f\xff\x8f\xfa\xfc\x59\x12\xb4\xe7\xfb\xdf\xd4\xf7\x0e\xc2\xbe\x55\xd0\x5e\x5f\xa7\xdd\x8d\xce\x63\x0c\xed\xcf\x01\xc8\xcf\xf4\xe7\x2d\x86\x47\xb2\xd3\x1b\x41\x36\x7d\x19\x9f\xa4\x92\xea\xb8\x78\x76\x80\x94\x27\xe9\x09\x0a\x2c\xce\xf1\xf1\x6b\x89\xe2\x5f\x98\xb6\x5b\x94\x3c\x5a\xa7\xa2\xa4\xd1\xb7\xda\x50\xec\xdb\x28\x2d\xa3\x34\x9a\xa5\x92\x0e\x74\x45\x65\xb4\xaa\x4a\x19\x9d\x51\x67\xc4\xff\xfc\xed\xab\xe8\xbf\xff\x3a\x1c\x45\x73\x2e\x56\xa9\x1c\xc4\x38\x79\xa2\xb7\x3b\xec\x86\x72\xfc\xb6\x62\x31\xc4\x2f\xb9\xfa\xff\xae\xa2\x31\xc4\xef\xe9\x4c\x3d\x2f\xab\x18\xe2\x67\x22\x8f\x21\x7e\x9b\xca\xf8\x14\x28\x99\xc4\x3f\xa6\x2a\xdf\x33\x7a\xa6\xca\xa4\x22\x86\xf8\xe1\x5a\xe8\xe7\xcb\x18\xe2\x1f\x75\x5d\x3f\x56\x85\x4a\xaf\x16\xaa\x24\x5d\xc7\x10\xbf\xca\x64\x0c\xf1\x09\xdf\xc4\x10\x3f\xa1\x59\xed\x4b\xa3\xd8\xd2\x9e\xc1\x4b\xb8\xa4\x69\x27\x97\x6b\x5b\xfc\x67\x55\x51\xfc\x83\xa6\x02\xe1\x2d\xac\x38\x93\xcb\x8e\x9c\x46\xe0\xd3\x89\x2e\xf0\x52\x65\x42\xf8\x74\xbb\x85\x59\x7a\xb9\xb7\x5e\x4d\x7d\xbc\x85\x25\xaf\xf6\x37\xfe\x03\xaf\x44\xa9\x5b\xce\x59\x25\xf7\x48\x18\xd5\xa6\xfe\xac\x73\x96\x34\xe3\x6c\xb6\x37\xe7\x5b\xfd\xd9\xd6\x59\x14\xf9\x2d\xd9\x5f\xd6\x79\x74\x19\xc9\x15\x6f\xec\xcd\x6e\x18\x67\xab\x77\x18\xf7\x65\x0c\x58\x4f\x53\xe8\xd5\xfc\x3d\xa5\xe7\x7b\xa9\x2a\x26\x96\x5c\x97\x9a\xa6\xda\x60\xe2\x61\x37\x7f\x8b\x9d\x73\x4a\x6d\xfd\x35\x2d\xab\x2c\xa3\x8a\xb7\xb4\xb1\x61\x22\xb7\xad\xd8\xf1\x1d\x45\xe6\x69\x5e\x74\xe5\xdf\x3d\x0a\x35\xf9\x59\x2a\xf3\x0d\x7d\x94\xb3\x59\xce\x16\x31\x64\x69\x51\x9c\xa5\xd9\x79\x22\x21\x4b\x59\x46\x0b\x1d\x11\x71\x7b\x9b\xcd\xaf\xaa\x29\x65\xb3\x77\x4b\xca\x1a\x75\xc8\xb4\x3c\x6f\x5b\x00\xef\x29\xce\x99\xb6\xf9\xbc\xb9\x78\xb5\x07\x0b\x41\x33\x9a\x6f\x68\x58\x78\xdb\x3a\x12\x6a\xba\xd3\x3b\xf3\x36\xc8\x67\xc9\x6a\xb0\xa8\xf2\x19\xc2\x20\x38\x97\x89\x84\x52\xaa\x0a\x14\xde\xb0\x4a\xf3\xe2\x8c\x7f\x0e\xfc\x5d\xa3\x35\x12\xb8\x15\x56\xbb\xe6\x10\x14\x5a\xdc\x52\x24\x90\x6a\x5a\x4d\xdb\x3b\x76\xc4\x72\x60\xeb\x36\x67\x02\x02\xc3\xba\x61\x07\x5d\x36\x14\x94\xa0\x62\x86\xaf\x52\xfd\x0d\x18\x12\xc8\x7a\xe9\x0d\x9b\x6d\xcc\xf7\xc2\x64\xd5\xa0\x81\x42\x75\xdc\xc9\x02\xc1\x89\x34\x1b\x18\x1e\xa8\x9f\x10\x06\x53\x96\x68\xf2\xd0\xbd\x10\x14\xb7\x40\x50\x9a\x21\xc7\x2b\x19\x5e\xf8\xd0\xaa\x0f\x6a\x19\x1f\x64\xca\x0a\x9a\x0a\x57\x98\xe1\xed\xb6\x1d\x80\xdb\x2a\xcf\xf2\x68\x53\xef\x8e\x6b\xa0\xcd\x01\x85\x37\xae\xf4\xc3\x4b\x07\xf6\xac\x93\xf5\x10\x6a\xa5\x39\xe6\x6e\x25\x3b\xa6\xd5\xc9\x57\x75\xfa\x0e\x49\x55\x57\x5a\x18\x34\x21\x3d\x44\x96\x5f\x51\x43\x8a\x18\x12\x4b\x58\x6b\x83\x23\xb3\x20\xad\x8d\x42\x3d\xb7\xeb\x56\xdb\x36\xd3\x36\x06\x2e\x23\xc2\x71\x98\xf3\xe7\x70\x87\x96\x66\x99\x3f\xb6\xad\xb4\x01\x61\x2e\x5c\x10\x86\x7e\x5f\xea\x00\x45\x91\x18\xe8\x31\x41\x6e\x19\xb0\xad\xaa\x40\xd0\x52\x26\xb6\xec\x16\x9a\xed\xa9\xa1\xad\x1a\x18\xef\x6f\x60\x57\xa0\xfc\xe1\x06\x0c\x47\xd8\x9c\xbd\x5e\xab\x01\xbd\xaf\xae\x3f\xf9\x23\x62\x03\x8e\x4b\x55\xed\x04\x06\xc4\x36\xb9\x4d\x47\x5b\x83\x23\xa4\x85\x43\x8b\x62\x0c\x5d\x55\x7a\x02\x77\x83\xe7\x08\xfc\x7f\x0a\x9e\x37\x21\x3d\xda\x1c\xcb\xfe\x28\x41\x5a\xfe\xb5\x62\xc2\xe2\xab\x33\x1f\x44\x77\x71\x7d\x8d\x82\xd1\xbd\x84\x21\x86\x05\x39\x18\x36\x8e\x85\xeb\x33\x56\xb5\x4a\x1d\x8e\xc5\xd1\x46\x7b\xdb\x9d\x79\xe6\x1b\x63\x23\x68\x74\x8c\xa3\x99\x3e\x48\xc1\x63\x79\xdc\xaa\x39\x59\x90\x83\x91\xb5\x90\x1c\xd1\xfb\xaa\xa1\x11\x9c\x91\x89\x57\x97\xec\x10\x4f\x04\xa8\x51\x9d\x50\x68\x8c\xcc\x84\x81\xe5\x01\xe3\x8d\x6c\x29\x6e\x8e\x1d\xed\x28\x4b\x2a\x28\xd7\xe9\x05\x4b\x72\x38\xcf\x8b\x22\x99\x43\x59\x50\xba\x4e\x0a\x28\x8d\xa9\x64\x89\x41\xa4\x17\x6f\x75\x9e\xa9\x7e\x54\xe9\xa9\x9e\xef\x4f\xba\xe7\xfb\x60\xf2\x8e\x3a\x0e\x14\x5a\x1b\xec\x83\x0b\x2e\xce\xa9\x68\x1c\x3d\xe4\x73\xb4\xe1\xf9\x2c\x1a\x1e\x74\x06\x1c\x78\xb7\xd4\x8e\x11\xb4\x1f\x7f\x74\x7e\x12\x33\x4e\xcb\x88\x71\x19\x31\x4a\x67\xd1\xbc\x48\x17\xe5\xe0\x03\x7b\x9c\x16\x45\xa4\x33\xda\x56\x10\x36\x8e\x0f\x8c\x47\xa9\x58\x54\xda\x4f\x49\xbb\x09\x5c\xf2\x2a\x2a\x97\xbc\x2a\x66\x4a\x57\x56\xc5\x4a\x2a\x0f\x6a\xb3\xd6\x0a\x49\xbd\xa0\x05\x39\x30\x56\xa5\x20\xb5\xc1\x7c\x26\xf2\xb5\x82\xba\xb4\x77\xd2\x74\x69\x24\x37\x12\xc1\x44\xea\xda\x21\x02\x0d\x88\xd0\x1d\x75\xe1\xa1\xa0\x1a\x6a\xe9\x7d\x7e\x4b\x46\xd3\xf3\x28\x8d\x4e\xe8\x86\x0a\xeb\xc1\xa1\xdd\x4b\x9e\x16\xab\xe3\xe8\x9d\xc8\xb3\xf3\x52\x52\x71\xf0\x81\x3d\x97\xda\x43\xb6\xd4\x2e\xb2\x51\xdc\x67\xfd\x58\x89\x53\xed\x73\xe5\xdc\xad\x34\x9d\x3e\xae\x05\x5f\x88\x74\xf5\x3e\x97\xcb\x67\x8a\xa8\x1f\xa3\xb3\x4a\x46\xcb\xb4\x8c\xe4\xe5\x9a\x46\x1f\x5f\x9b\xef\xa6\xcd\x8f\x83\x0f\xec\x97\x92\xfa\x52\x1f\xb5\xed\x35\x4d\x67\x51\xae\x2f\x45\x88\x66\x5c\xf7\xd1\x45\xca\xa4\xed\x23\x1b\x0e\x22\x23\x39\xfa\x89\x0e\x44\xc5\xf4\xc2\x51\xcf\x62\x4f\x85\xa8\x8d\x9d\x76\xf0\x67\x75\x9f\x0e\x06\x03\x6c\x1d\x63\x8a\xc2\xbb\xb6\xb0\xa8\x62\xf4\xf3\x9a\x66\x92\xce\x7c\x67\x0f\x3e\xb0\xe7\x91\x14\x39\x9d\x29\x82\x65\x9c\x6d\xa8\x90\x51\x2e\xd5\x5b\xca\xb4\x87\xb3\xa6\x1b\x68\x34\x85\xf3\xcf\xd1\x8e\xc7\x6b\xc1\xcf\x0a\xba\xd2\x9e\x2c\x71\x5f\x9b\x33\xb4\xb9\x03\x65\xc6\xec\xe6\x2b\x79\x84\x77\xbb\x33\x49\x7c\xd5\xd0\x29\xbd\xe5\xde\xc6\xc4\xac\xc6\xc0\x88\x8f\x5f\xe0\x14\x0a\xa8\x97\xd8\x5f\x18\xba\x52\xd0\x24\x0c\x36\x39\xbd\xe8\xdc\x28\x48\x73\xb6\x75\xf6\xd1\xfb\xce\x98\xb6\x18\x1a\xe0\x77\x55\x44\x1b\x0a\x4a\x15\x18\xe7\x84\x48\xd6\x77\xab\x3c\x94\x83\x86\x8c\xaa\x9b\xf6\x46\x71\xf6\x60\x0f\x8f\x99\xb6\x6b\x83\x0a\xd9\xf0\x73\x53\x6d\x1e\x02\x25\xa1\x2a\xe5\x0c\xa5\x30\x85\x12\x03\x47\x0f\x15\x9d\xb5\x24\xd4\xb1\xe4\x70\xcb\x25\xef\xa1\x1c\x58\xb9\x85\x4a\x25\xdb\xb5\x8d\x1a\xa4\xe4\x6a\x0b\x25\x59\xa3\xfd\x20\xf9\x7d\x6e\x39\x98\x0e\xc7\x15\x61\x28\x03\xee\x60\xd1\x0e\x6b\x39\xa1\x88\x3b\x58\x72\x0c\x22\x84\x85\xeb\x1d\x2d\x8e\x61\x4e\xa6\x28\x85\xac\x56\xf7\x8e\xaf\xd6\x5c\xc8\x32\x99\x6f\x93\xab\x6d\xb7\x13\x60\xd3\xb5\xe0\xc4\x41\x72\x32\x61\xa7\x63\x3e\xc8\xcb\x67\x5c\xd0\x7c\xc1\x7a\x3d\x84\x28\xa1\xc6\xb0\x95\x9d\x92\x38\x5b\xcd\x8c\x8d\xa2\x4c\x17\xc7\x9f\x11\xc3\xc9\x43\xc4\x40\x60\x0c\x52\x7d\x9f\x23\x0e\xa2\xeb\x92\x0c\x1b\x60\x24\x14\xe2\xde\x21\x90\x16\xf3\x5d\x8f\xbf\x14\x55\xc0\x40\x5a\x4b\x06\xe7\x84\x30\x1d\x8e\xed\xb1\x0a\x37\x67\x2a\x1a\xa0\xc4\x97\xc9\x80\x01\x1d\x64\xab\x59\xa9\x43\x9f\xaa\x0c\x65\x75\xb6\x93\x41\xf1\x9d\xcf\x30\xff\xec\xbf\x97\x61\x05\x3e\x9b\x09\xef\xc3\xc8\x95\x62\xeb\x44\x80\x02\x38\x31\xb2\x73\x0b\x5c\xc7\x77\x5c\x40\x46\xe4\x80\xb3\xa7\xf3\x39\xcd\x64\xa9\x1d\x83\x39\x7b\x4b\x8b\xf9\xcb\x72\x01\x53\xb2\x76\xf2\xbd\x1e\x46\x6c\xa0\xea\x21\x53\x98\xee\x8b\xac\xb2\x9f\x73\xa8\x5d\x02\x29\x1e\x02\x1a\x32\x45\xf7\x82\x62\xd6\xda\x13\x55\x05\x28\x9b\x29\x01\x42\x8b\xb9\xdb\xb9\xd6\x1d\xa1\xb7\xc1\xb7\x1d\x51\xeb\x1b\xd3\xaf\xe1\x16\xc5\xf9\x66\x9e\x6f\x80\xe6\xf7\x85\xa9\xde\x97\xaa\xdd\x19\x18\x50\x25\xa3\x0c\x35\x1f\xca\x81\x55\x1f\x80\x13\xf3\xad\x5e\xb1\xd8\x31\xa5\xd4\x82\xb6\x4d\xdc\x0d\xd3\xde\x95\x9a\x34\x92\xb8\xa0\xe9\x3c\x86\x25\x5f\xd1\x44\xda\xc5\xbc\x08\xe5\x62\x10\x4b\xc6\x96\x60\x7c\x46\x63\x70\x2e\x8c\x8d\xe5\x6f\xc3\x30\xcc\x66\x5f\xa5\xeb\x18\x64\xba\x58\x50\xa1\xd6\xd9\x82\xd2\xc6\x3a\xfb\xac\x65\xcf\xbc\x1d\x5f\xa2\x83\xa1\x8e\xdd\xa1\x94\x4c\x0c\x97\xe8\x60\xa4\x0d\xe6\xf4\x6b\xdb\xc9\xc9\xca\x29\xfd\xc6\x8e\xd9\x84\x9f\x26\x57\x8a\x21\x13\x73\xa3\x80\x62\x4a\xf3\xb8\x1d\x07\xa2\x47\x4e\xf8\xa9\xeb\xc8\xf9\x67\x73\xc0\xb4\x0d\x5d\x21\x2f\x6b\xe1\x69\x87\x90\x18\x28\x74\xec\x38\xd2\x44\x4b\x4c\xbf\x8a\x81\x22\x1e\x64\xe4\x1d\x92\xc0\x81\x81\x75\xe8\xf7\xdd\xa3\x98\x5f\xc7\xbb\x25\x17\x48\x42\xa6\xa3\xde\x62\x3b\x9c\x34\x2d\x93\x3a\xb6\x83\x18\x38\xba\x3a\x6b\xc0\xca\x6a\xe2\x97\xd6\x3a\x56\x03\x05\x26\x7c\x83\x6d\xc1\x54\xa5\xe8\x9c\x04\x4d\x1a\x1c\x06\x8a\xe0\x40\xe1\xca\xf6\x80\x18\x98\x07\xb3\xa0\x61\x0d\xa4\xdf\x75\xcf\x18\xa1\x8d\x2b\x1d\x8b\x31\x96\xc4\xd5\x62\x02\x56\x08\xb3\x2c\x70\xea\xfb\xd6\xb3\xb0\x3c\x3e\x99\x88\x53\x25\x20\x5e\xa6\xeb\x44\x3f\x97\xd5\xd9\xcb\x74\xad\xe8\x84\x5b\x71\xcb\xc3\xf0\xaa\x5a\x88\x76\x77\x23\xc8\x63\x64\x64\x0e\x71\x17\x3d\x58\x19\x84\x81\xe2\x04\x19\x41\x14\x7e\x53\xef\xb8\x71\x17\xd2\xb9\xbd\xdc\x46\x1a\x71\xde\xa5\xd3\x0a\x1a\x65\x29\x33\x4e\xef\x67\x34\xe2\x8c\x46\x6a\x9a\x88\x58\xba\xa2\x33\xe7\x09\x6c\x34\x13\x7d\xc3\x94\xd5\xb2\xb4\x36\xb6\xaa\x0a\x99\xaf\x0b\xda\xf0\x60\x7f\xdb\x90\x2a\x0a\x02\x38\x99\xc8\x53\xa2\x3a\x26\xd1\x82\x19\x2c\x9d\xde\x80\xd5\x85\x54\x77\x81\x9f\x5d\x92\x83\xe1\x16\x96\x8d\x9d\x9b\xcf\x8d\xbb\xe5\x68\xe3\x40\xaf\x61\x4c\x3a\x0e\x0d\x82\x33\xe0\xa4\x32\x56\x5d\x3a\x6a\x68\x7e\xe4\x6d\x8c\xf3\x7e\x1f\xb3\x49\x7e\xaa\xe6\xd1\x66\x1c\x88\x69\x4b\x9b\xce\xdc\x2a\xac\x75\x83\xa2\x61\x13\x94\x91\xcc\x47\x7c\xf4\x6e\x83\x4a\x62\x3d\x20\xc3\x5e\x2f\x73\x77\xf1\x08\x18\x19\x09\x97\x91\xc9\x29\x54\x44\x51\x64\xe0\xb1\x87\x29\x09\xb5\x09\x3d\xfc\x2d\x38\x3a\xa3\x9a\x23\xc8\x54\x93\xb1\x9e\x4d\x88\x40\x14\xc3\x95\x55\x96\xce\x68\xc2\xa0\x62\xf5\x1b\xdf\xee\xc4\x67\xde\xd3\x25\x6a\x2a\x04\xc3\xae\xc9\xd3\xaf\xee\x92\x87\x66\x33\x2d\x24\x56\xdb\x20\xdb\x5d\xdd\x65\xaf\x7d\xf2\x01\x97\xb3\x7e\x1f\x4f\x51\x39\xc9\xea\x8b\x18\x4a\xb3\xf9\xb5\x26\x53\x98\x11\x0e\x6c\xff\xfd\x5f\x73\x22\x60\xd9\x71\xdb\x97\xfd\xec\xec\xc2\x5b\xfb\x9b\xe5\x6e\x2f\xb6\x8c\xda\xe7\x6d\x46\xa2\x9a\x73\x90\xf4\xe6\xc3\xe1\x7e\xa3\xd7\x8e\x73\x54\x31\x28\x6c\x78\x7a\xb7\x7a\xa0\xdd\xab\x87\xb8\x8e\x94\xa4\xe6\xd9\xd6\x6a\x41\x2f\x6d\xf8\xdc\x2e\xa1\xac\x03\xbc\x19\x8b\x76\x14\x26\x6a\x09\xa0\x6d\x4e\xc7\x6b\x63\x7b\xba\x35\x81\x65\x26\xa7\x30\x27\x46\x80\x14\x6d\xd6\x9a\x11\x06\x6b\x52\xc1\xf2\x2b\x58\x6c\xb9\xcb\x62\x99\x62\x31\xbb\xf8\x56\x8d\x9d\x28\x05\xf6\xcd\x5e\x4b\x9e\x2d\x86\xa7\xfb\x3e\x76\x28\x03\xce\xd9\xce\xab\x03\xba\xad\x77\xfc\xe1\x7a\x6d\x22\x79\x99\x57\xa5\x31\x25\x12\xcd\x30\x50\x0d\xd8\xcb\x94\xa5\x0b\x2a\xca\xe4\x04\x78\x25\x17\x3c\x67\x8b\xd7\x5c\xc8\xe4\x2d\xe4\x2c\xe3\x2b\xf7\xfa\x08\x96\x72\x55\xbc\xe3\x76\xb9\x98\x64\x60\x85\x57\x42\xa1\xbd\xc4\x4c\x58\x18\x59\xb1\x02\x35\xf1\x25\x4b\x38\x4b\x65\xb6\x4c\x36\x36\x64\xe2\x42\x5b\x35\xc3\x1b\x49\x4e\xe4\x40\x7f\x82\xa7\x92\xbc\xf1\x4e\x96\xfa\x90\x1f\x5e\x4a\xf2\x52\x6a\xfb\xd1\x97\x72\x12\x1f\xec\xf5\x66\xdc\x17\xdd\xe3\x8d\x3e\x19\xdb\x1a\xf5\xf6\xb1\x6e\x6b\x95\xae\xe1\x53\xd0\xea\x33\x49\x3e\xb5\x5a\x7d\x21\x09\xb2\x39\xeb\x8e\x86\x13\xa3\xd2\x19\x12\x62\x78\xae\xeb\xf0\x34\x86\x57\xa6\x50\x9b\x18\x50\xa7\x35\xce\x25\x5b\xe6\xb3\xaf\xce\x3b\xcd\x67\x31\xfc\xb8\x6b\xe4\xd0\xf2\x02\x33\x45\xdb\x3e\x6b\xaf\xbb\xec\x14\x2d\x96\x6a\x68\x39\x27\xb3\x27\x1d\x27\xfb\x37\x35\xe0\x1c\xd9\x5e\xdb\x87\x6d\xd7\x71\xab\x6d\xe7\xd5\xb9\x6b\x06\xc3\x2f\xbf\x0f\x8f\x27\xb2\x76\x66\x0b\x9a\xfa\x75\xff\x21\xf5\xed\x4e\x6d\xa6\x01\xef\xbe\x76\x5c\x27\x8c\x7c\xa3\xdd\xce\x6b\xaf\x25\x72\x2f\xf6\x79\x68\x01\x7a\x2f\xff\x04\x9f\x36\x03\x07\x6f\x03\xe6\x5d\xd7\x82\x84\xbb\x1e\xd2\x9b\x1d\xd7\x5e\x4b\xe4\x5e\xec\xf3\x28\x78\x76\xd0\xff\x59\xae\x6d\x06\xbc\xac\x8d\x40\xd6\x46\xc0\xbb\xaf\x05\x09\xf7\x3c\x46\x5f\xe7\xbc\xf6\x5a\x6f\xd2\xdc\x73\xd8\x64\x01\x96\x59\x80\x65\x56\x63\xf9\x27\xbb\xba\x19\xc8\xab\x36\xb2\x55\x1b\xd9\xaa\x8d\xac\xf7\x65\x0b\x12\xee\x7b\xec\x7f\x9f\x27\xdb\x6b\x89\xdc\x8b\x7d\xbe\x17\x3c\xdf\x0d\x9e\x47\xc1\xb3\xa5\x08\x86\x1f\x7e\xf7\x68\xf4\xa3\xde\x0d\xcb\x2d\x86\xdf\x6e\x97\x1d\x2d\x17\xd5\x46\x45\xaa\x8a\x87\x7a\x4d\xaf\xa6\x74\x0c\x5f\x64\xb8\x64\xfd\xfe\x36\x10\xd5\x12\x56\x6f\x7d\xa3\x1c\x7d\x91\xf0\x5c\xd5\x08\x1e\xb6\x9f\x75\x65\xf3\x34\x2f\xe0\x1f\x37\x19\x2f\xfd\x26\xbb\xbc\x23\x7e\x96\xda\xf5\xc8\x39\x47\xd4\xb3\x00\x86\x9f\xf6\x5a\x9d\x69\x30\x3a\x2a\xfb\x47\xb3\xb2\x7f\x76\xc9\xb0\x5b\xaa\x68\xa6\xd3\xb0\x6a\x77\x6f\x32\xd6\xe6\xd5\xa6\x89\xbf\xef\x91\x4a\x7f\xb0\x95\x66\x3a\x0b\x5b\xaf\x2f\x5f\xc6\x5b\xb5\x3c\xab\x61\xe8\x96\x2d\x7f\x32\x04\xcd\x74\x1e\x42\x16\x5e\xeb\x8c\xb7\xc0\xdb\xf0\xed\x93\x0a\xff\x26\x08\x9b\xe9\x59\x08\x79\xf3\x26\x69\xbc\x85\xac\x0b\xfe\xf6\x26\x67\x30\xe8\x1a\xce\x0e\xff\x68\x2a\x37\x49\x8a\xfe\xb9\xcf\xc4\x71\xaf\xef\x83\x92\x3d\x7f\xd7\x43\x77\xa4\x07\xd7\x37\x37\xb2\xf0\x4f\x72\xbf\x4a\xe0\x43\x7d\x6c\x55\x85\x39\xfa\x27\x7c\x2f\xed\x55\x42\xda\x7b\x43\x90\x7f\xb4\xe2\x6c\x0c\x95\x46\x26\xc4\xfe\x06\xbb\x0a\x28\xa0\x85\xd2\xcf\x94\xee\x89\x62\x1d\xab\x08\x03\x13\xfb\x75\xa2\xd7\x26\xf8\xb5\xd7\x8b\xb8\xd8\x37\xcc\xa9\x40\x4c\x20\x8d\xa6\x74\x70\x67\xb7\xe6\xee\x96\x33\x5a\x34\xbc\xd6\xd2\x01\x6f\xe1\x46\x01\xf2\xc4\xe5\x52\xff\xb5\x1f\xc5\xde\x36\x03\xf0\xac\x38\x1c\x9f\xc8\x41\x53\xdf\x1f\x28\x9a\x90\xab\xf5\xf9\x22\x89\x1b\xf1\x5c\x63\xad\xbc\x27\x52\x80\x5f\xbb\x24\xdf\x48\xf0\x7b\xad\x89\x10\xb0\xb3\xfd\x50\x09\xe3\x27\x30\x15\x37\x85\xeb\xb5\x7b\xcc\xfd\x38\x89\xe2\x7e\x1d\xf3\x03\xe9\x2b\xe0\x98\x56\xf3\xeb\xad\x5b\x39\xe3\x95\x3c\x76\x0f\x83\x0b\x91\x4b\x8a\x28\x4e\x32\xce\x4a\x5e\x50\x1d\x1e\x9c\x36\x4c\x5d\xf4\xbe\x69\x7b\xa1\x28\xdd\x5e\xf9\x95\x09\x18\x43\xa1\xe0\x8b\xc4\x2c\x0b\x10\x86\xbc\x1b\x60\xba\x27\xd4\xff\xde\x78\xeb\x7d\xd1\xb9\xa7\x21\x27\xc3\xd3\x3a\xb0\xce\x0b\x14\x9c\xfa\x64\x4b\x61\xee\x86\x32\x5b\x1e\x23\xac\xad\x85\xbb\x2d\x91\x9a\xf5\x87\x31\x08\x7f\x1c\x58\xf7\x53\x24\xb1\x8d\x42\x14\xb7\x17\xe6\xde\x90\xac\x8d\x43\x8a\x76\xae\x4b\x2d\xd7\x45\x2e\x55\x1d\xc0\x48\xf3\xea\x47\x13\xc1\xd0\x02\x4e\x1b\x61\x91\x68\x47\xcb\xcd\x48\x7f\x41\xc5\x6a\x59\x65\x6a\xc1\x83\x79\x5e\x48\xbd\x21\xd8\x51\xc1\xbc\x19\x58\xce\x17\x17\x74\x43\x45\x49\x51\x57\x99\x0e\xaf\x78\x7f\x23\x8d\xb9\x30\x8e\x8d\xfb\x7d\x6e\x6f\xbf\x74\xa8\xf0\x53\xdc\xed\xab\xdf\xe1\x18\xdf\x75\x8b\x66\x40\x92\xee\x7a\xd6\x0d\x5a\xfc\x38\xf0\x7e\xc2\xc8\xd1\xa5\x71\xb1\xf0\xb2\x95\xdd\xf5\xb0\xb0\x28\xcb\xb6\x6b\x78\xd8\x85\x71\x3c\x96\x0f\x86\x63\x3c\xea\xc9\x5e\x0f\xd1\x3e\x51\x3c\xf6\xe0\x01\x19\x81\xe8\xd7\xaa\x13\xed\xb8\xd2\xd4\x77\xa6\xbf\xb7\x71\xaf\xc7\xb5\x3c\x1a\x1d\xc7\x71\x22\x82\x9b\x34\x5b\xdb\xe0\xfb\xb2\x1e\xca\xdd\x4b\x3e\x83\x9c\xc2\x67\x94\xed\xad\xde\x3d\xf9\x86\xd0\xa8\xf2\xbc\xb9\x28\x44\xf2\xd0\xdf\x41\x74\xe7\xae\xdf\x5c\x0f\x6e\xc0\x60\xaa\xcf\xfa\xb4\xbf\x41\xc3\x6b\xd6\x40\xf9\x6d\x9b\x30\xfd\x4d\x50\x5d\x23\xeb\xe7\x56\xd6\x56\xc6\x3e\x6d\xec\x1f\x06\x6c\x2d\x45\xbe\x42\xcd\x9d\xc0\xe0\xab\x8f\xb7\xf5\xbf\x1f\xca\xfe\x1d\x68\xb0\xfa\x49\x77\xce\x0f\x65\xff\x9b\x56\xce\x37\x0d\x71\x51\xf3\x9e\x6b\xdd\xb2\xa0\x2a\x7a\x67\x11\xf2\xe1\xd3\xbd\x05\x5d\x09\xf1\x81\x5d\x7f\x10\xd7\x1f\x58\xb3\xe0\xcb\x26\x8e\xa1\xd9\x7d\xe3\xce\xae\x46\xa6\xc0\xd4\xbd\x71\x13\x51\x5b\x42\x85\xa1\x36\xb4\xe7\xb8\x15\xa5\x13\x7a\x8a\x03\x07\x72\xfb\x30\x6a\x5c\x1c\x74\x4b\x5d\x07\xdd\x95\x75\x05\x78\x7e\xd5\x12\x6f\xf5\x76\xf5\x83\xc3\xd1\x8d\xf7\x02\x05\x59\xf7\xde\xe4\xe3\xee\x89\xf2\xf3\x4e\xaf\x27\x06\x45\x5a\xca\xe7\xbe\xac\xae\xca\xde\x67\xb4\x2b\xd9\x7f\x69\x4c\xb8\x7e\xa7\x7e\x8e\x68\xed\x2e\xa4\x37\x39\xc3\x2b\xa5\x75\x10\xfd\x31\x62\x21\x8c\x4a\xb1\x7f\x70\x38\xf2\x11\x37\x18\x06\xd6\xf7\xee\xbd\x0d\xb6\x08\x4f\x11\x7f\x0d\xef\x6e\xa8\x5b\x0f\x2f\xb5\x89\xde\xbb\x6b\xe4\xa9\x99\x26\xf3\x39\x8a\x87\x5a\x71\xed\xf5\xe2\xcf\xfa\xbc\x7a\x32\x3a\x35\x1d\xc6\xc8\xdd\x31\x3b\x12\xe3\x7e\x9f\x61\x13\xaf\x7d\x18\x1f\x11\x44\x75\x48\x5d\xdc\xeb\xd1\x23\x12\xff\x4f\x7c\x7d\x1d\x3f\x8c\x8f\x54\x79\xf5\xfe\x4c\xbd\xa7\xf5\xfb\x3c\xc6\x8d\xa6\xed\xf3\x13\x89\xb4\x01\xfe\x73\x26\x91\x84\xd1\x5f\xb1\xbe\x53\x92\x3e\xd0\xf5\xd1\xa3\x78\x18\xf7\x7a\xf1\xa1\x36\x66\xec\xf5\xe2\x7e\x1c\x5c\xb3\x6e\xea\xa9\x29\x38\x0a\x61\x74\xc0\xa9\x1a\xae\xaf\xe3\xff\x89\x8f\xe8\x57\x34\x3f\x0c\xc7\xd1\xfb\x60\x88\xbc\x96\x28\xce\xb4\x79\x93\x09\xe1\x6c\x0c\x5f\x4c\xbc\x4f\xef\x3b\x60\x8c\x60\x9e\x33\x19\xb7\xaf\x2d\xf2\xd7\x64\xba\x0b\x32\xef\x4c\x3e\x94\x9f\xcf\xf8\xe9\x9d\x81\xa4\xa5\x9e\x80\x6c\x43\xbf\xb9\x6e\x11\xa4\xef\xcf\xe7\x74\x30\xef\x63\xad\x82\x26\xbf\x35\x38\xf7\xb7\x3f\x02\x63\xa4\x23\xb9\x85\x40\x7e\xb9\x45\xd6\x34\x15\x87\xa0\xe0\xf7\xb7\x2a\x43\x56\xfd\xcb\x4b\x1d\x2b\x33\xa1\x2e\x74\x07\xc3\x50\x31\xfd\xcc\xeb\xc0\x82\x19\x06\x73\x2f\x9d\xde\xb7\xd6\x97\xf5\x4c\xed\x8e\x75\x8a\xc1\xe8\x2b\xd6\xa8\xce\xe8\x21\xc9\xdc\x5f\xf5\x53\xd4\x57\xfd\xcc\x30\x68\xb8\x13\x89\xd6\x18\x14\x28\xe6\x96\x20\x41\xd7\x34\x95\xe6\x86\x20\x77\xaf\xd0\x02\x43\x41\xe7\x52\x47\xfa\x00\x61\xae\xd5\x42\x97\x18\x66\x82\xaf\x5f\x98\x0f\xef\xcc\xdb\x1b\xfb\xf1\x02\xc3\x3a\x9d\x25\x42\xdf\x53\x94\xce\x74\x26\x81\x3e\xeb\x17\x93\x47\xa0\xb7\x6a\x31\x95\xaf\x92\x47\xfa\x47\x67\x79\xa8\x1f\x4d\x86\x13\xb8\xe0\x62\x56\x26\x6f\x40\x87\xde\x4d\x9e\x7a\x07\xaa\x97\xde\x2f\xea\x31\xa4\xec\x32\x91\xe8\x19\x86\xb4\x28\x12\x89\x9e\x6b\xe2\xc8\x34\xd7\xf4\x7b\x85\x41\x07\xeb\x2d\x6d\x9c\x92\xd7\x18\x28\x9b\xb9\xb7\x27\xee\x4a\x24\x95\xf5\x17\x0c\x92\x3f\x67\x32\xf9\xd5\x5f\x05\xf2\x83\xbb\x86\xe9\x4b\x7d\x35\xd3\xf7\x5a\x25\x4f\x05\xc9\x45\xed\x8a\x56\xea\x57\x93\x19\xe6\xf6\x45\xd7\x01\x85\x7d\x7b\xce\x24\xcc\x04\x41\xb9\x15\x5c\xb4\x84\xe6\xa3\x83\x0b\xc3\x5a\x17\xa9\xe1\x86\xa5\x4e\x70\x68\xc1\xc6\x54\x93\x16\x85\x2a\x97\xb2\x4b\x30\x8d\x2b\x82\x60\x58\xd9\x06\xad\x23\x95\xc9\xab\x09\xa8\xb2\x69\x8a\x62\x38\x33\xc9\x9e\xd6\x60\x5f\x54\x1f\xb8\x67\x0c\x97\x26\x97\xeb\x31\x30\xcf\x2a\x0f\x86\x77\xfe\x9b\x4a\xf6\x3d\x8f\xe1\x42\xb7\xef\x18\x03\xce\xf5\xab\x66\x19\x78\x6b\x81\xb1\x8d\x68\xe6\xc2\xf0\xd9\xa4\x1a\xb6\x53\xe9\x8a\x15\x31\x3c\x32\x54\x50\x1c\x0a\x0f\x4d\x16\xe3\x2a\x68\x1f\x34\xf2\x96\xc1\x75\x9a\xe6\x7b\xf5\xb4\x4a\xd7\x90\x0b\x7f\x3f\xd8\x89\xa3\x5e\x96\x4a\x78\x63\x69\x67\x9c\x2b\x73\x31\x30\xc3\x0b\xc3\x53\x97\xab\x84\x97\x5d\x4b\xf0\x28\x47\x4f\x05\x48\xad\xb6\xc0\x63\x9d\xd9\x8e\x56\xf8\xd4\xb5\xf0\xef\x8a\xda\xb2\x27\x14\xee\xfe\x30\x2e\xa9\xd9\xe9\x1f\xa9\x7f\x77\x21\x45\x9f\x84\xf6\x31\x65\x3a\x18\x7f\x33\xb0\xcb\xbd\xed\x16\xc3\xb3\x4e\xc8\x75\xb9\x7d\x5b\x13\xdd\xb1\x07\xf0\x4e\x98\x88\x17\xff\x6a\xd5\xfb\x83\xdb\xef\x6d\xf3\xf9\xbf\x8d\xb0\xcf\x3d\x61\xef\xb5\x09\x7b\x5f\x41\xf6\x4a\x90\x60\x2f\xce\x6e\x7b\xe9\x8b\x31\xed\xad\x21\x2d\x38\xb3\x26\x9c\xe6\x76\xd3\xca\x18\xf3\x69\x63\x97\x39\xc9\x83\x58\x03\xf3\x0e\xf7\xfc\x90\x50\xb9\x71\xff\xe6\x1a\xc8\x29\x36\xfb\x18\x05\x99\xab\x0a\x67\xea\x67\xa8\x9e\xd6\xf6\x69\x38\x0e\x3c\x9e\xd7\xfa\xda\x2f\x3f\x73\xd6\x89\xb5\xe3\xfb\x4d\x2d\x75\x75\x5b\xa1\xf2\x94\x88\xc1\x1a\x66\x16\x1e\xeb\x2a\x0d\x59\xd7\x11\x57\x61\xea\xa4\x3a\xff\x14\xeb\xc8\x16\x73\xa2\x89\x9e\x77\x45\xe7\x78\xa1\x8f\xa1\xa7\xa3\x64\xba\x85\x0a\x83\xc6\x73\x68\xf0\x1c\xd5\x0e\xc5\xbb\x01\x63\xac\x63\x4e\x9d\x85\x9a\x18\x48\xba\xa3\xf5\x7e\xe4\x0c\x0a\x1d\x6e\x49\x90\x1b\x76\x9e\xa7\xc2\x44\xc8\x47\x27\x02\x35\x59\x38\x7e\xee\x42\x25\x0b\x3a\x3b\x3c\x2b\xd2\xec\x3c\x92\x82\xd2\x28\x67\x9b\x54\xe4\x29\x93\xd1\x26\xe7\x45\x2a\xe9\x0c\x22\x7f\xd0\x1f\xef\x09\xf1\xd1\xaa\x5b\x5b\x88\x2f\xb8\xec\xca\x7f\x8e\x04\xee\x28\x72\xa7\x23\x2b\xfd\xca\x7c\xac\x23\xdf\x07\xf6\xba\xa0\x69\x49\x23\x41\xb5\x1d\x82\xb6\x48\x3e\xab\xb4\x05\xc3\xd1\x52\xca\x75\x99\xdc\xb9\xb3\xc8\xe5\xb2\x3a\x1b\x64\x7c\xd5\xba\x63\x29\x2f\xcb\x8a\x96\x0f\xe2\xdd\x70\x10\xe6\x4f\x6f\x08\xbe\x16\x9d\x01\x9a\xa4\x8b\xcc\xd1\x1d\x4c\x5c\xd4\x81\x36\xe2\x47\x8f\x14\xdd\x4d\xaa\x3d\xde\xaa\x57\x54\x2e\x1c\x82\xca\xf8\xe2\xab\x72\xb6\x23\x20\x1c\x8c\xb6\xf0\x64\x77\xd7\xb2\x2b\x52\xd8\x1e\xa9\xd3\x0c\x53\x26\xc7\x92\xe4\xe8\x89\xd0\x81\x1b\xa8\x12\xdc\x26\x66\x98\x96\xd7\xbf\xec\x36\x24\x93\x3f\xdc\xd4\x27\x67\x15\x9b\xa3\x13\x90\x26\x5e\xb4\x25\x9c\x36\xa4\x7b\xf1\x2e\x4e\x7c\xcc\xb2\x7b\x63\xa5\x4f\xe4\xac\xa2\x91\x34\x76\x76\x4f\x7f\xf6\x66\x76\x2f\x10\x1d\x4c\xef\x62\x1f\xbe\xc3\x97\xba\x1f\x94\xd2\xe3\xf8\xd7\x7d\x1b\xbc\xfe\x54\x2d\x47\xbf\x68\xe1\x6a\x40\xd9\x62\x78\xff\x67\x4a\xf5\xfd\xb3\xca\x58\x9a\x30\x35\x3a\x5a\xcd\xdd\x40\x96\xff\xe0\x5d\x18\x4f\x0c\x83\x6c\xe1\x37\x9f\xf4\xc8\x25\x7d\xa9\x93\x6c\xca\xf7\xdd\xac\x7b\x3b\xd7\xba\x95\xfc\x74\x58\xfb\xa7\xd3\x4f\x88\xc2\x17\x81\xaf\xaf\xed\xf3\x6f\xde\x60\xfa\x60\xb8\x85\x9f\x7d\xeb\x6f\xe8\x2c\xde\xc2\x3f\x9a\x6d\xdb\x7e\x96\x61\xef\x1a\x30\x5d\x0f\xfe\x66\xa2\xcb\xe8\xe2\x2e\xed\x8b\x4d\x3b\x69\x66\xfd\x59\xf8\x7e\x6e\x4b\xc0\xf8\x71\xca\xbe\x95\xd1\x2a\x3d\xa7\x51\x1a\xcd\x78\x75\x56\xd0\xc8\xc8\x3d\xc6\x67\xd4\xdc\xc8\xa3\xdf\x0f\x62\xbc\xdd\xc2\x4f\x5f\x01\x66\xb3\x71\x07\xd3\x0e\x48\x3b\xd0\xff\xf0\xb5\x60\xea\x50\xd2\xf9\xa6\x01\x68\x41\xcb\x32\x04\xf4\x9f\x9e\xbe\x2f\x7c\x8f\xff\x3d\x48\xb3\x49\xdf\xdc\x70\x18\xd3\xc5\x9d\xee\x60\x46\x52\xf2\x8d\x40\x7f\x17\x6a\x31\x45\x6e\x3a\x64\xf4\x75\xed\xf0\x4f\xcd\xc9\x30\xbd\xab\xa4\xfa\x3d\x25\xb2\xef\x27\x5c\x1f\x76\xd1\x9b\xc2\xdc\xdd\xc4\x8d\xbd\x9e\x26\x6a\x28\x13\x8f\xe7\x48\x28\x5e\xd4\x37\x4c\xe9\xcb\xa3\xf4\xbd\x50\xe6\xca\xa7\x44\x6e\x81\xfd\xe1\xd6\x4c\xd5\x3f\x09\x6b\x94\xd9\xd9\x80\x21\xd4\x16\x38\xed\x52\x30\x3b\x4e\x9a\x3a\x0e\x36\x3b\xce\x34\x3b\x8e\x33\x3b\x4e\x32\x7d\x52\xb5\x9b\x34\xdd\x4d\xca\x77\x93\xd2\xdd\xa4\xb2\x4e\xb2\xe8\x4b\xac\x35\x46\x4f\x68\xa0\xc6\x93\xc3\x25\x28\x55\x32\x85\x12\xe3\x7a\xb6\xdc\x42\x76\x0b\xd9\x3b\x85\xa3\xa5\xbb\x21\x6a\x72\x53\xcf\x6e\xa1\xfa\x17\x1a\xa8\xc7\x5e\x16\x8e\xbd\x17\x34\x9d\x2b\xe5\x28\xb6\x6d\xff\xbc\xaf\xed\x69\x77\xdb\x75\x98\x2e\xaa\xfe\x31\xf5\x8f\xab\x7f\x99\xfa\x57\xdd\xa0\x25\x78\x4b\xce\x46\x28\xaf\x7d\xcc\x69\x8d\x5c\xf0\x8d\x79\x8c\xdd\x0b\xf6\x76\xf2\xda\x7c\x25\x94\x65\x5a\x3c\xd5\x9f\xef\x77\x7d\xbe\x05\x8a\x3a\x72\x74\x3d\x2c\xef\x85\x2d\x19\x6c\xaa\xdb\xb0\xb1\xc0\xb6\xeb\xb9\xdf\xaa\x27\xbb\xb9\x9e\xfb\x9d\xf0\xdc\xdf\x85\x87\xdf\x5a\x4f\x07\x3c\xf7\x77\xe1\x61\x3e\x52\x58\x63\x66\xfa\x4f\x24\x5a\x87\x36\xa9\xef\xca\xfc\x0a\x52\x86\x25\x43\x62\xde\x52\xfe\xfe\x9e\xf2\x6d\xf8\x68\x67\xb8\xb5\xff\x24\xfa\x39\x65\xbb\xd1\xc9\xff\xca\xc0\xf9\x3f\x60\xd4\x3f\xc0\x03\xf7\xf6\xf0\xc0\xbd\xaf\xe4\x81\x7b\x7b\x78\xa0\x83\xc6\x62\xff\x40\xea\x5a\x06\xdd\xb8\xd6\xfa\xf7\xf2\xee\x57\xf3\xea\xbf\x8b\x82\xdb\xae\xd1\xf4\xff\x40\xcf\x6f\x1d\xbc\xff\x8f\x0d\xac\xdf\xc3\xb8\xff\xb1\x12\xd7\xc7\x61\xd4\xb1\x38\x6e\x51\x19\xfe\x43\xc5\xf3\xbf\xdc\x03\xff\x27\xf2\xae\xdd\x03\x3a\x18\xc8\x4d\x4a\xa2\xd3\xeb\x5c\x05\xff\xdf\x70\xf9\x3f\x1c\x2e\xbb\x11\x48\xb9\x71\xc4\xc2\xc8\x33\xce\x28\x78\xbe\xeb\x9e\x7d\xa2\x49\x31\xaf\x77\x83\x9c\xf7\x82\xe7\xfb\xee\xd9\x3c\xdc\xc7\xb7\x36\xdb\xaa\xde\x70\xe0\x28\x78\xee\x6e\x36\xc8\x10\x3e\x7f\x5d\xb3\x61\x65\xf7\x03\x28\xee\x07\x80\xdc\x0f\x12\x6d\xb3\x41\x9e\xf0\xf9\xbe\x7b\xfe\x9d\xcd\xb6\xaa\xbf\xdf\x4c\xec\x68\x36\xf8\x14\x3e\x77\x35\x1b\xac\x47\x2d\x82\xf5\xe3\x5d\xb8\x61\xb5\x6a\xb1\x83\x39\xca\x83\x0a\x5c\xe9\xbb\x75\x9e\xfb\x50\x51\x8f\x37\xbe\x19\x84\x7b\x75\x25\xb6\x4f\xc3\xfa\xef\xd5\x9f\xee\xda\x4a\x0d\x0c\x41\x0f\xef\x01\xd9\x34\x6f\xef\xcc\xde\x05\x41\x6e\x21\xdf\xb7\x2d\x64\xfc\x5a\x74\xb5\x75\xaa\x2b\xf8\xbd\x40\x19\x3e\x9e\x52\x94\xe1\x24\xdb\x62\x48\x6f\xde\x5c\x8a\x5e\x0b\xc4\xf0\xf5\xf5\x6b\x81\x38\x3e\xd6\xa8\xfd\xc3\x78\x36\xab\x7c\x54\xdb\xc9\x50\xc4\xb1\x5d\xab\xd7\xe5\xb7\x18\xca\x9b\x01\xe4\xb7\xec\x12\x98\x78\x2a\xc7\x29\x9a\xab\x7a\x55\xc1\x64\x8e\xd2\xba\x8d\x39\x2a\xa9\xf6\xa3\xd1\x4e\x34\xda\x83\x46\xbb\xcf\xa8\x7f\xf7\x4d\x8c\x56\xfa\x47\xbc\xa8\xf6\x6d\x1b\x1f\x04\x3e\x55\x4e\xf9\xdd\xb3\xb9\xdc\x19\x7d\xda\xc6\x9d\x36\x8e\x2f\x5d\x2e\x53\x26\xf8\x3c\x4c\xef\xee\x5c\xa6\x75\x2f\x0e\xef\x9b\xf2\x92\x32\xbc\x70\xca\x4a\xfc\xf0\xbe\xa9\x17\x61\xc6\xbb\xcd\x7d\x3a\x66\xcf\xfb\xcc\xef\x5d\xfb\x7b\xcf\xfe\xde\xc7\x49\x89\x7e\x14\x60\x9a\xba\xf3\x86\xce\xee\xd8\xca\x40\xc2\x39\xca\x30\x9c\xeb\xa0\x21\x26\xc0\x88\xab\x23\xb7\x4f\xf7\xa1\x20\xae\xfe\x19\xd1\xdd\xe4\xf0\x2e\x60\xea\x9b\xca\x31\xac\x49\x8a\xde\x0b\x9d\x9a\x63\x58\x92\xb5\xca\xb3\x51\x3f\xa3\x7a\xac\xe9\x2e\x5f\xc2\x06\x66\x40\xb5\xcd\xd2\x0d\xbd\x13\xd2\x7d\xe5\xe9\xbe\xf0\x74\x3f\xdb\x4b\xf7\x85\xa2\xfb\xaa\x8b\xee\x67\x3b\x74\x3f\x0b\xe8\xfe\x22\x4c\x1d\xb5\x7a\xe3\xac\x8b\xee\x23\x4b\xf7\x91\xa5\xfb\xc8\xd2\x7d\xb4\x43\xf7\x17\x9e\xfc\x86\xee\x0b\x45\xf7\x15\xc6\xdb\xae\x4d\xf1\x70\x9f\xdb\x6c\xdd\x75\xed\x8a\x7f\x23\xd0\x3f\x05\xde\xbf\x0b\x6e\xaf\xce\x5f\xa6\x1b\x1a\x9d\x99\xcd\x6f\x2e\x22\x56\x6f\x83\x97\x51\x6a\x0f\xf5\xd6\x3c\xd7\x06\x58\x5b\x0c\x05\xdd\xeb\xc3\xf4\xd5\x27\x4f\x16\x66\x67\x7e\x1c\x72\x80\xa0\xf6\x8e\x26\xd0\x6e\x8b\xa0\x0f\x96\x20\x47\x05\x35\x47\x54\xf7\xc2\x17\x33\xf4\x67\xfe\x66\x81\xb7\xe9\x8a\xc6\x5b\x58\xd3\xfa\x34\x64\xc5\x37\x2a\x69\xe9\x93\x9e\xb3\x92\x0a\x19\x6f\x61\xb3\x5f\x62\x84\x5b\xc6\x66\x58\xdf\x78\xc2\xc4\x03\x4e\xcc\x88\x40\x9f\xfc\xed\x28\xee\x72\xc5\x5a\xc4\x75\x08\xa3\x99\x09\x69\x4e\x3b\x0f\xcf\x97\xfa\xa3\xdb\x1c\x35\xce\x84\x20\x29\x48\x6a\x23\xcc\x54\xda\x85\x12\xa6\xea\xe7\x3e\x94\xea\xe7\x1e\x14\xe6\xee\xaa\x99\x76\xc0\x6c\x1e\xf3\x15\x8d\x33\xbe\xa7\x3f\x9b\xf0\x1d\x6b\x22\xd0\x0b\x54\xe1\x2e\xc8\xd7\x7b\x21\x5f\x53\x73\x54\x3f\xa7\x30\x83\x72\xdf\xf9\xff\xac\x46\x61\x06\x05\xe8\x81\xaf\x33\x8f\xfd\x31\xa3\x02\x61\x49\x18\x2a\x31\x6c\xc8\x52\x65\x58\xa9\x9f\x91\x03\x7d\x13\xc2\xac\x7b\x39\xd9\x7b\x9e\xd7\x6a\xae\x82\x55\xdd\x96\xed\xfc\xfd\x85\x1d\xb9\xf3\x66\xe1\xe6\x18\xda\x4b\x09\x2d\xc0\x82\x72\x7e\x89\xad\xf0\x5b\x10\x86\xa6\x0a\xbf\x85\x91\x4e\x8b\x3f\x0b\xbf\x12\xce\xfe\x38\x7e\xa6\xf0\xef\xc7\x4f\x97\xdb\x6e\xb7\xc0\x89\x1a\x26\x90\x69\x56\x83\xca\x5c\xf9\x66\xd1\xca\xf6\xa1\x15\x55\x5d\xf0\x46\x94\xa2\x6a\x47\x60\x65\x2a\x51\x49\x9e\x55\xd7\x80\xf5\xc6\x1b\x1b\xaa\x23\xb6\xbf\x40\x02\x63\x13\x2b\x7e\x41\x6f\xb8\x14\x60\x65\x94\x0b\x49\x5b\x17\xec\x34\x73\x3d\x17\xb0\xa2\xa0\xaf\x94\xc2\x18\xce\xe8\x9e\xbb\x6b\x76\x2f\x12\xf2\x46\x60\x06\xcc\x63\xdd\xa0\xf9\x96\xb0\x30\xce\xfd\x73\x01\x4c\x8d\x67\x0d\xc7\x25\xdd\x77\x7d\x54\x8e\xce\xe8\x3e\x30\x73\xf4\xab\xd0\x11\xf4\xb7\xf6\x42\x80\x77\x5f\x0f\xa7\x55\x5a\x4c\xf7\x8d\x4c\xf7\x0d\xc7\x6d\xe8\x3b\x18\xc2\x23\x54\xe1\xfd\xb7\xee\x54\x46\x3c\xd8\x9c\x19\xde\xee\x60\xde\x75\x1e\xef\xc4\xa1\xc1\xe8\x82\x7e\xed\x05\x50\xd6\xee\x7a\x1c\xf6\xb1\xbf\x09\xdb\x50\x46\xea\x2b\x8f\xe0\x7c\x77\x0e\x6b\xf3\xd1\x27\x4b\xcb\xb7\xbb\xb4\x0c\x31\xb8\xc1\x65\xf0\x9c\xba\x4e\xb1\x3f\x9f\xe9\x4d\x8e\x64\xb6\xdc\x8d\xe1\xbb\x7c\x20\x5f\x6d\x58\xb4\x49\x8b\x30\x92\x6f\x18\xfd\x4a\xdc\x18\xc9\xd7\x97\x36\xa1\x7c\xed\xa0\x67\xfc\x22\xd9\xdf\xba\xc4\x57\x32\x0c\x19\xf6\x24\x95\x74\xc0\xf8\x05\x32\x8e\x7b\x01\x4c\xd3\xda\x13\xed\x11\x25\x9f\xe9\x20\xfc\x06\x0f\xf7\xcf\xba\xfb\x6f\x12\xfa\x87\x74\x31\x76\xfd\x1d\x51\x9d\x3c\xf1\x90\x82\xb5\xd3\xd3\x9d\xcf\x9d\x13\x71\x45\x02\xbf\xea\x47\xea\x43\x8e\x5e\x48\x90\xc0\x31\x0e\x22\x8d\x7d\x91\x90\x41\xa5\xd0\x39\xd9\xa7\xe4\x48\x30\x0a\x0b\x70\x42\x0d\x20\xda\x5e\x85\xd7\x4e\x52\x1d\x73\xbe\x05\x66\xbf\x41\x95\xb9\x49\x4a\xe0\x64\x7f\x4e\x35\xef\x5b\x2f\xd9\x37\x9a\xaa\x8c\x5f\xc0\xd3\xfd\xc4\xd4\x60\x09\xa0\x36\x40\x55\xd9\x05\x1e\xf3\xde\xb4\x14\x27\x4d\x47\x4d\x19\x3a\x6a\xd2\x1b\xfc\x38\xad\xc7\x6b\xc7\x21\x7b\x8e\x9e\x2b\x12\x53\xe3\x26\x6e\x2e\x32\xdd\xc2\x1b\x73\x79\xfa\x4b\x1a\x78\xb2\xe6\x2b\x1a\x63\x78\xbc\x6f\x50\xda\x90\x5d\x65\x22\x61\x6d\x62\x88\xd3\xd2\x38\xf1\x7e\xa2\x44\x7b\x8b\x3f\xa6\x56\x25\xc2\xf0\xac\x45\x92\x70\x11\x0a\xd5\x5e\x72\xd1\x71\xc7\xd4\x77\xaf\x71\x4f\x95\xe6\xab\xe9\xdd\xbd\x84\x62\x83\xe9\xdd\x2d\x3c\x94\x83\xf3\xbc\x28\x34\xd2\x5b\x0c\xd3\x4e\xcb\x41\xcb\xc9\xfb\xdb\xe4\xb6\x4d\x3b\x4f\x51\x1d\x0d\x03\xeb\xe5\xa2\x6a\x45\x0d\xb8\x3f\x82\x4a\x87\x55\x21\xd3\x7c\x15\xa0\xc7\x6c\x03\x73\xa2\x64\xec\x89\xa6\x2c\xc3\x30\x23\x05\x7a\x25\x94\xde\x06\x15\xcc\x21\x1b\xf8\xae\x80\xfd\x0d\xb9\x0b\xd3\xa4\x0e\x3c\xb1\xc7\xa9\x79\x4d\x66\x0a\xdb\xa5\xfa\x19\xc1\x46\xfd\xdc\x6d\x8c\xc9\x6e\xa6\xd4\xbd\x3e\x07\x79\x93\x93\xb1\x95\x08\x6b\x58\xe2\x2d\x6c\x34\xe3\xbd\xd8\xcb\x65\x06\xb4\xa7\x1b\x2a\x2e\x5b\xbe\xe2\xcf\xf7\x2b\x12\x2f\x29\xca\xd1\x0b\xea\x2f\xbd\xbb\x25\xbc\x83\xce\xab\x05\x47\x07\xb4\xc6\x19\xdd\xdc\x39\xb3\xc5\x9d\xfe\xcd\xf9\x8a\xde\xe0\xdf\xfc\x89\x06\xfe\xcd\xcf\x68\xe0\xdf\xfc\x94\xc2\x4e\x2c\xaf\xe7\xd4\xd8\x05\xbf\xa2\xf0\x23\x25\x8f\xe4\x20\xb8\xe3\x01\x5e\xeb\x14\xfb\xf2\xc4\x7e\x66\x95\xa4\xf0\x8b\x7e\x59\xf2\x4a\xc0\xaf\xfa\xd1\x5f\xcb\x00\xef\xdd\x3b\xfc\x60\x4a\x70\x26\x97\xf0\x9b\x7e\xbe\xa4\xa9\x80\x2f\xfa\xd1\x5d\xf8\x00\xdf\xeb\x57\x73\x4d\x04\xfc\x4c\x09\xb2\x1f\x8d\x0b\x35\x68\x7f\xef\x2f\x54\x89\x0c\xc7\x63\x6f\x2b\x16\x6f\x31\xfc\xc3\xaf\xe6\x7e\x4c\x59\xbc\x85\x9f\x28\x41\x6e\x5d\x0b\x53\x31\x28\xf8\xa2\xf3\x4e\xec\x7c\xc7\x2a\xeb\x68\x46\x33\x3e\xa3\xe2\x41\xec\x08\x64\xaf\x7f\x58\x95\x8b\x46\x44\xc7\xf4\xd6\xa2\xe6\x1a\x88\x76\xb9\xf2\xb6\x72\x61\xe6\x79\x07\x43\xb6\xb3\x83\x7d\x6f\x04\x8f\x2c\x6e\x85\x8e\x55\x45\xe7\x25\x15\xb3\xdb\x9b\x8c\xe7\x39\x2d\x66\x31\xe8\x9f\x3d\x00\xac\xbf\xa2\x1a\xed\xbc\x12\x1b\x17\x9a\x3d\xd5\x6c\x6e\xc5\xe3\x9c\x5e\x1e\x6a\x2c\x62\x5f\xc1\xfe\xc0\x9b\xdd\x55\xac\xd2\xf5\xe1\x2a\x65\x97\xb1\xe6\x91\x1a\x92\x72\x37\x1e\xe7\x2d\x35\xf9\x70\xf9\x1e\x97\xee\xdb\x30\x2e\x6f\x45\x8b\x33\xfa\x6a\x1e\xd7\x90\xc8\x76\x38\x4a\x2f\x25\x14\x86\x13\x71\x7a\x43\xd4\x48\x93\x03\xe8\xe9\xae\x0f\x71\xb0\x34\x71\xb9\x80\x9d\xee\x3a\x08\x37\xb6\x85\xeb\x9c\xc0\x4f\x77\x3d\x84\x5b\x41\x46\xc2\xdc\x90\x85\xf9\x1f\x85\xf9\xa1\xda\x53\x02\xaa\xd3\x56\x18\xc1\xe0\x13\x4c\xf7\x96\x82\xe9\x69\xd3\x95\xb8\x59\x0e\xf2\x1b\x4a\x42\x7e\xda\xed\x5c\x6c\x22\x20\xf2\xf3\xae\x91\xf3\xb4\xad\xa3\x24\xf1\x5a\xe4\xab\x5c\xea\x5b\x51\x74\xcc\xd7\x20\x90\x6c\xe8\x48\xdc\x2e\xd6\x1a\x18\xe6\x8a\x85\x6d\xc3\xad\xb8\x5d\xa4\x35\x24\x77\x8a\xfc\x81\x56\x9e\xed\xa0\x6d\x78\xd2\x86\x18\x6f\xf2\xe4\xf3\x76\xe6\x6e\xe9\xf7\xaa\x19\x44\x31\x9e\xc6\x63\x39\xc6\x7e\x4b\x53\xa6\x0b\xbb\x39\x50\x53\xce\x2e\xfb\xe3\xa7\xda\x1f\x22\x67\x8b\x28\xee\x4b\x1d\x73\xb6\x8f\xe2\xa9\x3e\x34\x3c\x8e\xe3\x24\x8e\x52\x19\xc5\x7d\x81\xfb\xb1\x0e\x3e\xea\x82\xba\x2f\xb8\x4c\xa2\xb8\xff\x1a\xb9\x7b\x16\xcc\x46\x83\x41\x3e\x11\x7d\x12\x4f\x54\x7d\xfa\xbd\x1f\x9f\xc6\x20\x89\x34\x61\x5b\xcd\xdd\x0d\x26\xb8\xb3\xa6\xae\xce\x3d\x50\xb9\xf5\x7b\x67\x4e\x43\xa3\xa4\x76\xc0\xd6\x91\xf1\x34\xbd\x80\x91\xe1\x98\x1d\xd5\xd1\x15\xfa\x7d\x13\x70\xe2\x95\x89\xab\xe0\x14\xf2\xe7\x61\x48\x77\x1a\xcd\x79\x51\xf0\x0b\x85\xb7\xab\x28\xde\x87\xb8\x8d\xfa\xee\x42\x55\x7c\x60\xb1\x0b\x4e\xad\x3a\x23\xd9\xad\x3f\x8d\x3e\xaa\x4f\x1f\x23\x2b\x67\xf6\xd7\xac\x89\xbe\x2a\x17\xdb\x86\xdf\x77\x1d\x0c\xc0\xdd\x01\x20\x8f\xe3\x8a\xd9\xe8\xfc\x71\xf2\xe3\xdb\x57\x27\x03\xe3\x1b\x9b\xcf\x2f\xbb\xbc\xc1\x4d\x18\x71\x29\x2e\xaf\x28\xd1\xb9\xb5\xa3\xb0\x5a\x2f\x66\xa9\xe6\x89\x86\xe3\xed\xf7\xf9\x86\xb2\x48\x43\xbf\x49\x8b\x7c\x16\xa9\x22\x16\x36\x5a\x96\xe9\x82\xfa\xa8\xe1\xbf\xe8\xb5\xf9\x1e\x6f\xf1\x5f\xf5\x8b\x23\x38\xb7\x61\xc0\x64\xba\x30\xc1\xbb\x0c\xa3\x24\xaf\x25\x7a\xa5\xc3\x4d\x86\x2e\xdf\xaa\x92\x0e\x7e\x3d\xe3\xbc\xa6\xb0\x7a\xa1\x29\x8b\x09\x51\x6c\xca\xe7\x91\x38\x7e\x83\x04\x4e\x9e\xa2\x38\x8d\x1e\xa9\x9c\x3e\x6c\x78\xce\xfc\x6e\x57\xcc\xaa\xd5\x19\x15\xf1\x41\x5d\x4a\x15\x30\xbe\xce\x6a\x31\x78\x78\x77\x74\xff\x6f\xf7\xff\xfb\xde\x5f\xef\xff\xed\x48\xf4\x7a\xe2\xa8\x7e\xef\xf5\xd0\xf0\x5a\x68\x87\x79\xd3\xd4\x41\x5e\x3e\x53\x3a\xa0\x22\xe5\xf5\xb5\xf8\xaf\x51\xab\x2e\x95\xc9\xf2\x86\x76\x53\x6e\xc1\xd0\x09\xb9\x71\x68\xae\x43\xa2\xeb\x7e\xf5\x25\xed\x6b\xbb\xa4\xd0\x23\x31\x65\x99\x4a\x33\x8a\x9c\xfa\xd0\x8f\x63\x5b\xab\x49\xab\xab\xd5\x8a\x89\xdb\xeb\x73\xd7\xa9\x1c\xbf\xf1\xe3\x57\x95\x32\xca\x8b\x2b\x61\xa6\x7f\x57\xa4\xc6\xac\xc8\x4b\xa9\x4d\x1b\x0e\x50\x03\x0a\xed\x3e\xed\x3d\xda\x34\x10\x2f\x54\x56\x55\x61\x3d\x70\x4d\x7c\x54\x56\x47\x50\xd0\xd1\x50\xf4\xd9\x1f\x3f\x8f\x0f\x08\x41\x1b\xc5\x47\x03\x3b\x74\x40\xe8\x70\x31\x9a\x25\xdc\x5a\x00\x31\xd8\xe0\x31\x75\x31\x97\x37\x06\x03\xa8\x99\xf4\x0d\x72\xf2\x28\x55\x30\x7d\x1d\xb0\xcc\xa4\x35\xc0\xe5\x1e\x4c\xc8\xf4\xfd\x7c\x2e\x5c\x01\x30\xc2\xff\x30\xe4\x99\x92\x4e\x16\xea\x1a\x64\x73\x85\xe6\x8f\x6f\x4d\x13\x99\x8b\xd8\xbd\x4a\x2f\xcf\xc2\x5e\xb0\xc3\xaa\xdd\x96\x69\xe8\xf8\x85\xa3\x06\x4e\x3e\xe1\x86\x90\x35\x67\x18\x56\xc6\xfa\x21\x7a\xf6\x1b\xcd\x64\xc0\x5c\xbd\x9e\xe2\x81\x03\x42\x44\xaf\x57\x45\x39\x8b\xc4\xf1\x9e\x06\x27\x95\x45\xee\x78\x93\x3c\x46\x15\x6c\x0c\xdf\xb1\xc8\xd4\x69\x2f\xe2\x88\x74\x73\x75\x14\xeb\xaa\x1f\x7f\x0c\x47\xa9\x9e\x2d\xdc\x9d\x0a\xfa\xd5\x87\x0d\xd8\xe9\xad\xe3\xe9\x03\xdf\x1d\x7a\xd8\x45\x05\x67\x0b\x2a\x22\xdd\xc9\x83\xe8\x84\xd2\x59\xa4\xeb\x88\xe2\xfe\xd4\xce\x57\x52\x87\xd6\x4e\x05\x35\xa1\xb5\xe3\xbe\xab\xa1\x1f\x47\x94\x49\x91\xd3\x52\x0f\xdc\x7d\x58\x4e\x6b\x2c\x5f\xa2\x69\x8d\x65\xea\x79\x45\x63\x52\xab\xcb\xda\xe6\xc7\xd2\xb5\x16\x39\xd7\xd7\x6e\xc8\x5d\x5f\x77\xf0\x61\x83\x0d\x6d\x61\x77\xb3\x42\x4e\x9a\xd1\x36\x52\xdd\x2d\x37\xf2\x5d\xda\xe2\xbb\xc7\x28\x55\x7c\x67\xa2\x14\xfb\x38\x52\x29\x38\x5e\x19\xe7\x6e\x2c\x95\x90\x07\xa3\x28\xf7\x3c\x68\x35\x79\x3f\x01\xcf\x15\x27\x55\x2c\x83\x82\xf8\x86\xdd\x4c\x5c\x84\x33\x71\x1b\xcc\x62\xc2\x4e\x1d\xb7\x3a\xf0\x36\xe3\x39\x99\x7b\xc6\xad\x9b\x9f\xbb\x41\x6c\xd5\xff\xa4\x9e\x58\x3a\xb0\xf6\xfd\xa4\x52\xfd\x5d\x50\x1b\x7f\x0d\x14\xee\xd4\x24\x66\x64\x72\x0a\xeb\x00\x09\x17\x7f\xda\x9c\xc6\x59\xd7\x37\xd5\xd4\xda\xde\x76\x61\x11\x22\x84\x6c\x9a\x48\xcc\x4c\x98\x93\x0d\x86\xb5\x3e\x6e\x77\x88\x3c\x43\xb3\x0e\x7d\x41\xa9\x76\x6a\xe6\xf7\x17\x61\x98\x05\x71\x3d\xd0\xcd\xd7\x6d\x23\xa4\x87\xbd\x95\x43\x06\xb1\x50\x0e\xb4\x5b\xb1\x9e\x33\xb5\x19\x5d\x0d\xd2\x81\x3f\x1f\x0a\x67\x54\xdf\xd0\x2e\x44\xba\x45\x6d\x2d\xb6\x2a\x17\xe3\x60\xfe\xad\xa7\xd4\x70\x6a\x6b\xcc\x56\xbb\x33\xc6\xc1\xb0\x63\xe2\xb1\xb3\x8d\x6e\x44\x3f\x85\x53\x4a\x28\xb1\x43\xd9\xd7\x1e\x61\xb6\xae\xf7\x61\xef\xbb\xa7\xa6\xd0\xf3\xad\xea\x77\xdd\xaa\x7e\xea\xf5\x6e\x2a\xec\x94\x58\x57\x58\xbf\xd7\xf1\x77\x6e\x2e\x5c\x8f\x95\xba\xf1\x8a\x65\xa6\xed\x8a\x65\xbd\xde\x0f\x28\x18\x32\xbe\x78\xd9\xcd\xec\x51\xcd\xcb\xc6\xcb\xc7\xbe\xdc\x0c\x84\x65\x72\x5b\xc5\xbe\x06\xb7\x8d\x40\x2f\x7b\x82\xfe\x1c\xd4\xc1\x82\x6a\xbe\x0a\x22\xff\x28\xd5\x5b\x8f\x74\x35\xc7\xbe\x47\x52\x8f\x6f\x3d\xf3\xf9\xdc\x8e\x1f\x1a\x91\x5f\xc2\x30\x65\x4d\x75\x56\xe8\x9b\x37\x1a\x71\xc1\xc2\x10\x2f\xb2\x15\xc0\xa5\x5e\xf6\x5c\x6d\xdd\xe0\x95\xe1\xe0\xb5\x57\xd3\x88\x09\x1d\x4c\x87\xa7\xe6\x58\x41\xea\x2b\x7c\xdc\x08\x15\xee\x6c\x86\x32\x45\x9a\x44\xa2\xdf\x30\x88\x8a\xbd\x62\xee\x3e\x5a\xf4\x44\x27\x98\x78\x24\x86\x80\x27\x55\x51\x24\x85\x7d\x79\xed\xd6\x55\x49\x69\x53\x1e\x9b\xb0\x20\x3a\xe4\xcb\xdc\x95\x79\x66\xd6\x91\x68\xe6\x12\x9e\x9b\x55\x22\x5a\x63\x58\xa5\xeb\x91\x89\xd7\xb2\x4a\xd7\x77\x13\x81\x2e\xf4\xd3\xbd\x84\xa2\x73\xfd\x74\x3f\x61\xe8\xad\x7e\xfa\x2e\xe1\xe8\xb3\x7e\xfa\x6b\x92\xa1\x47\xfa\xe9\x6f\x49\x85\x1e\xea\xa7\xff\x4e\xa6\xe8\xc4\x35\xf0\x13\xbd\xfc\x55\x8d\x9a\xd7\x69\x2e\xca\x64\x13\x5c\x0a\x77\x86\xcd\xc5\x71\x29\xb8\x9b\xe4\x72\xd0\x7c\x93\x5c\x42\x3e\xa3\x4c\xe6\xf2\x32\xf9\x02\x86\x24\x1a\x59\x73\x31\xa6\x7e\xd7\xd3\x56\xb2\x1c\x48\x6e\x15\x16\x9b\xae\x63\xb1\xf8\x58\x3a\x36\xf1\x95\x9e\xd0\x92\xef\x81\x7e\xaa\xd2\x42\x55\xfb\xde\xdc\x47\xfd\x4f\x4a\x7e\xa2\x83\xba\x24\xfc\x9d\x12\xe4\x53\x4c\x15\xfe\xd5\xd4\x82\xe1\x9b\x30\x8f\x82\x4b\x65\x71\x00\x63\x90\x4c\x7f\x76\x09\xb0\xe7\x19\x83\x60\x75\xe3\x40\x4d\xa9\xba\x67\xc1\xbf\xf9\xae\x45\x56\xbe\x61\x0c\x4c\x97\xf5\x37\xe4\xe8\x37\x1d\x2f\x38\xd3\x8f\x2e\xec\x7b\xa5\xdf\x44\xc5\x60\xea\x9e\x1c\x4b\x41\x6a\x5a\x54\xfd\x05\xe6\xf7\x6f\xf6\xf7\xaf\x18\x4a\xff\xf1\x3b\x9b\x78\x1f\xc3\x5c\xd7\xa1\x58\x02\x0a\xf7\x78\x17\x66\xee\x71\x04\x6b\x53\x4a\x77\x62\xd7\x6e\x7e\x5e\xa3\xe8\xb9\x13\xac\x90\x35\x97\x54\x2f\x43\x32\x68\xde\xac\xe9\xa0\x79\x17\xc3\x86\xed\x3f\xd3\x7d\x0f\x4b\x66\x4f\xf1\x61\xa5\xe1\xea\x60\x42\x58\xb0\xee\x38\x2e\x5d\xc0\xe9\x89\x41\x07\x1d\x39\x0b\x41\x0b\xfa\xc4\x4c\x46\xb8\xb3\xbf\xb4\x31\x15\x86\xcb\x00\x94\xe0\xab\x9e\xdb\x30\xbc\xeb\xfe\x6a\x27\x36\x0c\x17\xac\xf3\x38\x99\x75\x07\xd1\x9b\x1c\x7e\xb8\xf3\xe1\xc3\xff\x7e\xf3\x97\xfe\xf1\x00\xe1\xeb\xc9\x87\xd3\xab\xed\xe9\x9d\x05\xc4\x1f\x3e\x7c\xd3\x8b\xdb\xb7\x97\xb8\xe5\x18\xbd\x88\xde\xd0\xc5\xd3\xcf\x6b\x24\x07\x25\xaf\x44\x46\x21\x5e\xe4\x71\xfb\x32\xb3\x8e\xec\x10\x2f\xe2\xf6\x25\x6c\x75\x46\xab\xcb\x0f\x56\x76\xd1\xdf\xba\x6e\x0c\x28\xbe\x92\x24\x7e\x58\x14\xb1\xbf\xe2\xeb\x78\x74\x67\x98\x68\x81\xe9\x85\xbc\x0e\xee\x06\x19\x19\x42\x45\x28\x4c\x49\x10\x4f\x0e\x72\x72\x38\x1a\x67\xfd\xfe\x91\xec\xf5\x74\xf8\x37\xfa\x99\x66\xa8\xc2\xb8\xd7\xcb\xcd\xd4\xe1\xb2\x06\x77\xc2\xa4\xfe\xc2\xd6\xc3\x11\x94\xc1\xc2\x2a\xc5\xe3\xf4\xc1\xd0\xca\xed\x39\x61\x93\xf4\x74\x5c\x4e\x0e\x0f\xd3\x53\xe2\xb7\x42\xe6\xc7\x9f\x92\x17\x68\x8e\xb7\x36\xac\xdc\x95\x46\x2e\x61\x93\xe1\x29\x94\xd5\x99\x7e\xa3\x65\x12\x46\x02\x2b\x6d\x40\xa9\x84\x99\x19\x1c\xcc\x72\x5c\x1b\xeb\xe6\x21\x8c\x7e\x42\xa8\x93\xc8\x14\xf6\x45\xaa\xcb\x51\xd7\xfd\x45\x46\x45\xcb\xfa\xfd\x07\x44\xd6\x31\x6e\xea\x19\xd3\xdf\x3d\xe9\x48\x70\x0f\x78\x40\x02\x86\xc7\xcc\x93\xa0\xaa\x73\xeb\xbb\xdf\x26\x87\x87\x2c\x20\x45\xa5\x49\x51\xd5\x57\xba\x39\x62\x88\x7d\x94\xe0\x8e\x12\x75\xbd\x3b\xf0\xdc\x3d\x0d\xe8\xb3\xdd\xcf\x1f\xe6\xb4\x77\x58\xc7\xdd\x75\x83\x40\x00\x6f\xdf\x0a\x0d\xe6\x4e\x4b\xb4\xb7\x36\x4c\x08\x19\xdd\x19\xd6\x01\x06\x6b\x98\xa9\x8d\xe3\x26\x30\x6e\xf0\x24\x05\x7b\x8b\x4f\xc8\x8f\x0d\xee\x1c\xcb\xc3\xc3\x90\x2d\x39\xc6\x63\x6c\x6f\x12\xe2\x36\x08\x68\x05\x96\x29\x30\x6e\x56\xe5\xf0\x6a\xe7\xc7\x18\xf6\xb3\x47\xe6\xcd\x3c\x04\x5d\xd0\xcf\x49\x06\x4a\x1f\x7b\xce\x4a\xca\x4a\xa3\x1f\x70\xa0\x65\x96\xae\x69\xc2\xc2\x80\x68\x15\x86\x79\xce\x66\x89\x40\x53\x1d\xe9\x4d\xd1\x31\xa1\x28\x77\xb1\xe0\x04\x4a\x8d\xa9\xc7\xb9\xbe\x9b\xed\x3c\x2f\x0a\x78\xcb\x88\xb6\x14\x29\x28\x35\x97\x8d\xac\xd3\x0b\x86\xe1\xf3\xae\x80\x6e\x9e\x8e\x76\xd8\x02\x51\x7b\x0e\x6e\xe3\x74\x6f\xb7\x18\x1e\xb1\xdb\x02\xf4\x77\xd9\x14\x99\x10\xfd\xda\xea\x5b\xe9\x57\x9d\x37\x7c\x44\x5a\xf5\xc2\xf0\xb0\x73\x1e\x90\xfa\xa0\xfc\x84\x91\x0b\x66\xa3\x8c\xbd\xd1\xcf\x96\x28\xf0\x54\xbf\x29\x62\xc1\x4b\x46\xd0\x05\xab\x03\xb0\xa9\xe7\x26\xb5\x41\x17\x5c\xd0\xcf\x18\x1e\xeb\x72\x86\xf6\xf0\x89\xdd\x14\xe4\xde\x0e\x22\x19\x0e\x22\x61\xc7\x0d\x75\x63\x83\x75\x23\x67\x89\xf2\x50\xbe\xe4\x6a\xe6\x72\x57\x98\x3c\xf3\xe6\xf1\x8a\xfd\xb7\xf0\x82\x11\xd4\x30\x2c\xe8\xb0\x57\xd8\x89\xe2\xd5\x65\xf3\xc6\x74\xbc\x72\x7d\x9b\x87\xb6\x4b\xbb\xbd\xce\xe7\xbf\xb7\xce\x8e\x4e\x7a\x26\x90\xb4\x5f\x9f\xef\xd5\x07\xac\xbd\x9c\xb0\x19\x5f\x75\x75\xb7\x3b\x6f\xa6\xb2\x33\x60\xc7\x8f\x8c\xbc\x62\x48\x52\x0c\xaf\xf7\x36\xf3\x8a\x21\x6b\xbe\xd1\xb6\x7a\xf0\x21\xcc\xe1\x49\x27\xab\xa5\xe8\x07\x78\xcd\xe0\x47\xa6\x15\x8c\x5f\x3a\x18\xde\x66\x7c\xc2\xb4\xf1\x8d\x84\x17\x0c\xb9\x68\xf3\x7b\x81\xb1\x16\x69\xbe\xed\x5b\x4c\x15\x74\x89\x05\x35\x97\x69\xd2\xdf\x53\xe8\xf2\x8f\x14\x7a\x7b\x43\xa1\x0e\xe3\x16\x53\xa8\x6d\x13\x19\x5e\x23\xa9\x95\x3d\x76\x4b\x6d\xfa\x12\xc9\x77\x5f\x55\x4b\xcb\xc2\x75\xaf\xa8\x79\xc5\x6c\x34\xb2\x57\xcc\xda\xad\x76\x69\x69\xdd\xd7\x51\x37\x78\xfe\xc6\x5b\x69\x9b\xfa\x97\x59\x66\xea\xbb\xc6\xf4\x7d\x98\x8d\xab\x97\x7a\xbd\xd0\x32\x90\x21\xcb\x00\x5e\xac\xa5\xb3\xd9\xd3\x0d\x65\x52\x2d\x74\x28\xa3\x02\x09\xc8\x1a\x40\x2b\x2d\x72\xc5\x37\x74\x37\xd7\xb6\x71\x6d\x22\xfb\x7a\x43\xc6\xb3\xd0\x70\xd1\xf4\xc5\x8c\x67\xe6\x36\xe4\x05\x95\x4f\x0b\xaa\x1e\x1f\x5d\x3e\x9f\x21\x89\xc7\x14\x59\x85\x91\x1d\x07\x16\x88\x02\x31\x8c\x13\x7b\x21\x8a\xb3\x2c\x3a\xe1\xf2\x19\xaf\xd8\xcc\x8e\x54\x63\x4a\xb3\x47\xb9\x45\x9d\xa6\x45\x72\x30\xe7\x59\x55\x22\x0c\xee\x56\xd4\x9d\xbb\x7b\x6f\xab\xe0\xac\xa8\xc4\x9e\xf2\xd5\xd7\x94\x2f\x33\xc1\x8b\xe2\x1d\x5f\x6f\xdb\x8a\xf1\xef\x28\x4b\x44\x27\x00\xe9\xef\x02\x80\xb8\xe7\x1f\xa8\x8e\xc8\xd9\x55\x63\xf9\xf5\x35\xbe\xa0\x73\xb9\xc5\x7b\xec\x5d\xbe\xa6\xf0\x1e\xa4\x8a\xdf\x07\x82\xc7\xea\x7d\x3e\x93\xcb\xce\x1a\x67\x2d\xc8\x44\xc3\x60\xab\xcb\x27\x47\x2d\x0e\x69\x7d\xba\x17\x89\xb0\x0d\xb3\xfb\xf5\x6b\x5e\xe6\x67\x05\xdd\xcd\x99\x15\x39\x65\x72\x6f\xce\xf7\xb9\x5c\x3e\xe2\x62\x46\x45\x19\x14\xe2\xf3\x79\x49\xbf\xaa\xd0\x43\x36\x7b\x99\x8a\x45\xce\x4a\x73\xa6\x41\x89\x50\xa3\xec\x91\x1a\x28\x39\x5b\x3c\xd6\xad\xbf\xa1\x99\x44\xc1\xf5\x07\x3a\x04\xab\x8e\xf8\x3e\x97\xdb\x8e\xab\x7d\xff\x04\xd2\x18\xa6\xfa\x2a\xda\xec\xcf\x7a\x13\x71\xbe\xaa\xd4\x1f\xa2\xce\x19\x97\x92\xaf\x0e\xe9\x40\xf2\xb5\xa2\x8e\x71\x60\xb9\x6a\xcb\xd2\x24\x10\x73\x5b\xe8\x10\xa3\x8d\x0c\x5b\xd8\x10\x8a\x82\x03\x75\x7f\x4e\xe3\x84\xe3\xb1\x7b\x48\x96\x18\x16\x7b\x32\x5f\xe4\x6c\xc6\x2f\x8e\xcd\x8f\xca\x78\x46\xba\xb2\x09\xfa\xa9\xa2\xa5\x7c\xc8\xf2\x55\xaa\x20\x78\x26\xd2\x15\x3d\xee\x4c\x4d\x9a\x66\xe0\xd8\xb9\xce\x5d\x71\xf6\xc4\x01\x24\xd0\x06\x03\x67\xef\x4d\xab\x3a\x04\xb4\x16\xa4\x09\x07\x25\x0f\x93\x0c\x16\x54\xbe\x75\x82\x25\xa9\xa0\x0c\x5f\xa5\x5a\x5f\xf8\x0c\x3a\xb4\x73\x59\xe7\xb0\x21\xa3\xe7\x18\x24\x7f\xa4\x29\x9f\xa4\x20\xb9\x09\xfb\x5c\xc0\x92\xda\x20\xd2\x6b\x0c\x17\x6a\x3c\xe8\x9d\x4c\xb3\x95\xf7\x2b\x23\xe8\x17\xa6\x45\x32\xfc\xc2\x8c\x6c\xc7\xf0\x9e\x91\x5f\xd8\xc0\x41\x0b\x3f\x98\x4c\x35\x36\x9d\x73\x36\xdb\xb9\x01\x5a\xd2\xcf\x32\x06\xf5\xbf\x61\xf5\xc2\x1b\x46\x9d\x9d\x9a\x45\x86\x9c\xcb\x46\xc7\x5d\xa5\xf5\x9a\x7c\x89\x04\x56\xab\xf0\x01\x4b\x57\xb4\x5c\xab\x75\x46\x46\xd8\x60\x9e\x9a\xeb\xc2\x27\xa7\x30\x25\x43\xb7\xb9\x4c\xc3\xcd\xe5\x5c\xdb\xa7\x8f\xa7\x7d\x92\x0f\x66\xb4\xcc\x28\x9b\xa5\x4c\x96\x8f\x79\xc5\xe4\xf5\xf5\x10\x2a\xb3\x7a\xcc\x31\x50\xbd\xf3\xec\xef\xb7\xed\x93\xca\x1d\x2d\x37\xee\xb9\x36\xc6\x87\xba\x65\xb5\x7a\x5c\xe6\xc5\x4c\x50\x96\x54\xe0\x41\x4b\x38\xb4\x5b\x4a\xa6\xdb\x9d\x8b\xf8\xff\x7c\xfc\xa6\xa3\x7f\x15\xc5\x73\x7a\x49\x67\x87\x7f\x16\xa2\xd3\x56\x5c\x63\xd3\x46\x56\x95\x92\xaf\x62\x5b\xf3\x12\x49\x6c\xf1\x5c\xf1\x19\x2d\xd4\x42\x6e\xb5\x2e\x12\xba\xdd\x73\xdf\x8c\x63\x39\x6d\x0b\x1f\x5c\x24\xae\x80\x4e\xc4\x2e\x40\xa3\x3e\x12\x5d\x64\xc1\x6d\x7b\xd3\x1d\x40\xe5\xb2\x62\xe7\xde\x38\x32\x15\x0b\xb5\xca\xd4\x89\x6a\x95\xa9\x9a\xb3\xd7\xd8\xef\xbb\x82\x7e\x6e\x4c\x14\xc3\x41\xe4\x47\x83\xd8\xbd\x62\x3e\xbc\xbd\xd7\x99\x2e\x76\x94\x75\xde\x48\x3b\x73\x51\x43\x6b\x9e\xd7\x66\x8d\x1d\x75\xd4\x57\xbb\x6d\xdb\xf7\xc3\xfb\xe3\x1a\xa0\xfb\x0e\x6c\x98\x3e\xb0\xd1\xfc\x7a\x4e\x2f\xc7\xf9\x1c\x71\x42\xc8\x4c\x5e\x5f\xab\xdf\xb5\xfd\x2d\xfc\x65\xec\x74\xc2\x4f\xf5\x0d\x50\xd9\x44\x2d\xf7\xd3\xe2\x27\x7a\x79\x4a\x98\x33\x0b\x99\xf0\x53\x92\x99\x00\x30\xb6\xaa\x79\x00\x47\xe5\x8b\xc3\xd4\x95\x71\x50\x4d\x9b\x23\x61\xaa\x46\x42\x35\xc9\xf5\x31\x52\xae\xed\xf8\x55\xda\x68\xab\x9b\xa8\x7c\x13\xb1\xe7\x60\xed\xb5\x8a\x85\xaf\xd7\xe7\xc8\x8a\xb4\x2c\x4f\xd2\x95\xcd\x71\x65\x76\x45\x55\x3d\x63\x5d\x99\xdf\xe2\x4b\x8f\x6d\xd9\x24\xed\xc7\x51\xdc\xb7\x6f\xa6\x2d\x9d\xd5\xd5\xdd\x38\xd2\xba\x32\xdc\x4f\x83\xc1\xb4\xcf\xfe\xf7\x9c\x5e\x26\x73\xd9\x61\x78\xd9\xb4\xf1\x55\xd9\xba\xec\x2c\xcf\x76\x72\xcd\x24\xd8\x4e\xe8\x2c\x70\xd9\x1a\x0c\xaa\xc8\xba\x2e\x22\x6c\x91\x2b\xf3\x13\x62\x20\xb7\xbb\x97\xc7\x37\xaa\x29\x76\x5b\xbe\xe2\x6b\x95\xbd\xd4\x43\xd7\x18\x0f\xd3\xb0\x9a\xc6\xfd\x40\x48\x0e\x6c\x76\xbd\xaa\xb3\xcf\xd7\xd7\x3e\x79\x50\x4a\xbe\x7e\x2d\xf8\x3a\x5d\xe8\x59\x3b\xcc\xd6\xfe\xd6\xeb\xd5\xc5\xd6\x82\x2a\x6d\xe4\x89\xf1\xb8\x6c\x94\x6a\x7e\xc2\xbd\xde\x4f\x74\xe0\xce\xc9\x3a\x4f\x78\x5b\xc6\xc6\xf5\x22\x5a\x0d\x96\x03\x35\x2e\x8e\x45\xf2\x0e\x09\x37\x12\xc0\x9e\xb4\xbb\x16\x21\x47\x33\xa6\x37\x28\x4c\xb2\xab\x77\xf7\xee\xf8\xda\x7a\xe0\x72\x4d\xad\x8e\x69\x84\x56\x7d\x38\xad\xe4\xd4\xf5\x35\x32\x0f\x44\x0e\xf4\x77\xa5\x10\xbc\xb5\x69\xde\xf0\xc2\x4a\xd4\x86\x0d\xa7\xce\xa0\x86\xbb\xf9\x38\x76\x99\x8c\xdd\xe0\xe5\x9a\x8e\xf1\x8e\x2d\x0d\x3b\x66\x64\xc2\xbc\xc7\xd5\x69\xc2\xcc\xfc\xe3\x12\xcc\x34\xa4\x6a\xb6\x9e\x6c\xd6\xaf\x29\x61\xb0\x4e\x85\x56\xa1\x9c\x5e\x85\xa6\xe4\x2d\xa2\xc0\x31\x1e\xd0\x62\x35\xd5\x1d\x31\x55\x25\xa7\x82\xce\x09\x87\xa9\x85\x5c\xa9\x1f\x0e\xe5\xa5\x1c\x64\x82\xa6\x92\xbe\xa3\x9f\xe5\x09\x9f\x51\x45\x1f\xfa\x59\x3a\x33\x3b\x35\xb7\x25\x9f\xd1\x54\x61\xe7\x38\xf7\xd8\x17\xb2\x2b\xee\x13\x4d\x1d\x3f\x17\x1b\xfb\x8c\xa4\x9d\xcb\xda\x6d\x80\x00\x69\xa6\xb0\x7a\xff\x3b\x53\x12\xd3\x4e\x99\x50\x91\xe1\xb8\x3a\xca\xdc\xa9\x7d\xd5\xef\xe3\xa9\xbd\x4a\xe1\xb1\xca\x83\xde\xa2\x6c\x52\x69\xb3\x1b\xa7\x59\x4f\xbd\xd9\x92\x9b\x8f\xff\x33\x61\x36\x1e\xa5\x6d\xb0\xed\x14\x5f\x1b\x8e\xad\xd6\xc5\x40\x50\x36\xa3\x02\xc9\x81\x9e\xe7\x7d\x91\xcf\x68\x1a\x00\x03\xa1\xfe\xf0\x79\x47\x51\x8a\x72\x16\xd5\xb1\x08\x26\xec\xd4\x59\xd0\x30\xc3\xfe\xd1\x5c\x26\x8f\x90\x04\x8e\x03\xe3\xe4\xa8\x90\x89\xb1\x9f\x6f\x26\xcf\x64\xf2\x66\x27\xef\x5a\x26\x4f\xdb\x89\xce\x6e\x46\x4e\xd8\xe9\x01\x21\xbc\xd7\xd3\x66\x14\xc4\x67\xf2\xf1\xbe\x75\x6a\x28\xbe\x1e\x35\xed\x36\x4a\x79\x59\xd0\x71\x03\x1d\x61\x8c\xa1\xc5\x84\x9d\xee\x98\xfb\xd7\xd3\xad\x62\xff\x65\xca\x66\x05\x15\xa5\x9e\x4a\xbd\x05\x64\x40\x92\x8c\xb0\x09\x3f\x05\x33\x63\xaa\x69\xb9\x3e\x88\xc2\xdd\x9b\x57\x1c\x32\x0c\xac\x9e\xd0\xfc\x04\xe8\x4b\x66\xf8\x2a\x23\x27\x48\x40\x85\xc7\x1d\x7b\x64\x75\x05\x76\x06\xcf\x06\x39\x9b\x73\x52\x6d\x9b\x30\x13\xd6\xf2\x49\x68\xec\x01\xfa\x4b\x08\xa8\x2e\xad\x77\x23\xed\xc1\x3c\x0b\x0c\xc8\xb4\x69\x97\xbb\x2e\x3b\x0c\x35\xc1\x9c\xec\x1c\x67\xbb\x52\x5e\xb4\x93\x10\xd6\x6e\x7b\xa1\x58\x57\xb9\x9a\x29\xa8\x1e\x17\xc6\x19\x1c\xa6\x44\x8e\xa7\x63\xa7\x0a\x4c\x9d\x48\x54\x30\x39\x54\x6a\x43\xcd\x14\x57\x24\x45\x15\x36\x04\x75\x35\x95\x24\x75\x03\xaa\x3c\x3c\x1c\xab\x3c\x93\xf2\x54\x65\x53\x8a\x8a\x91\x7e\xdb\xad\x3f\x2d\x34\xa4\x14\x40\x1b\x3e\x19\x8d\x8b\xce\xac\xad\xa1\x75\x1c\x9e\xd0\xd3\xb1\xef\x39\x76\xec\xfa\xfc\xa1\x94\x22\x3f\xab\xcc\x1d\x9b\x72\x50\x52\x19\xa4\x28\x1d\x70\xc7\x99\x63\x7f\xfd\x1d\xab\x14\xa3\xde\xd4\x1c\xb3\xdb\xee\xc9\x5b\xc4\x61\xa7\x6d\x93\xaa\xb7\x4f\xdb\xfe\x1a\x66\xbc\x4c\xfc\xfd\x9a\x9f\xac\xbe\x3a\xc4\x21\x31\x1e\xb7\x54\x0c\x73\x02\x24\x9c\xcf\xc9\x2c\x95\x69\x42\x61\xc6\x57\x27\xb5\xb2\x0e\xba\x93\x4f\x3a\xb5\xf7\x4f\xb5\x16\x9d\xcf\x91\x3c\x20\xc4\x87\x33\x32\x73\x2c\x64\x44\x98\x69\xcf\x2a\xaa\x99\xf3\xe1\xc8\x9a\xd3\x6f\xcd\x3a\x72\xa0\x16\x0e\xfa\xd8\x53\x3f\xe4\xf5\x9a\x2b\x25\x3b\xa6\x67\x39\x51\x4a\xad\x65\x91\xb4\xd7\xcb\x15\x97\xa4\xa4\x9a\xe4\xa7\xea\xcb\x24\xd7\xc3\x3a\xf5\x36\x8d\x3c\x9f\x21\xe1\xa6\x76\xf5\x83\xc7\xf6\x55\xb8\x99\xde\x5a\x95\x36\x68\x69\x27\x7e\xf3\x53\x2a\xaa\xea\x9a\xdc\x09\xf3\x83\x61\xaf\x47\xcd\xa4\xfd\x18\xc5\xeb\x43\xbb\x10\x62\x50\x62\xbc\x47\x59\x98\x7b\x1d\x01\x0a\x63\xe4\xa8\x1e\x67\xe4\x60\xa4\x8d\x37\xf5\x6c\x1f\x28\x0f\x6b\xab\x3c\xcc\xc8\xc1\x10\x76\x34\x88\xf9\xf1\x9c\x4c\xe6\xb0\xf6\x1a\xc4\xdc\x00\xb3\xf6\x1a\xc4\x9a\xac\x4d\x9d\xae\xfd\x25\x11\x3b\x8d\x2c\x6f\x6c\xa4\x38\x2e\xc8\xa4\x80\xa5\x6f\xa4\x30\x8d\x2c\x7d\x23\x4b\xb2\x34\x75\x5a\xc2\xcd\x7a\xbd\xb9\xa5\x90\x52\xe3\x9c\xa5\xb3\x66\xa3\x90\x5c\x82\xce\x44\x7a\xa1\xe8\x25\x30\x4e\x10\x9a\x1d\x3f\x43\x73\x28\x70\x32\x57\xab\x22\x7c\x7d\xdd\xa0\xad\x5d\xc7\x32\x28\xb0\xe9\x86\xe8\x13\x5a\xc3\x52\xb1\x61\x7f\xe4\xc9\xad\x35\x1c\x63\x47\x4a\x3f\x4b\x63\x48\xaa\x94\x9a\x80\x11\x1a\x30\x98\x1d\x19\x06\x36\x9b\x9b\x6d\x43\x1d\xc8\xab\x88\x81\x65\xaa\x52\xa5\xfd\xe0\xd6\x89\xb5\xbe\x71\x1b\x9e\x66\x38\x19\xc3\xdf\x17\xc8\x4e\xe8\x20\xec\xc4\x8e\x9b\x2c\xa5\x13\x55\xd1\x8d\xc3\xfa\xb9\x1f\x7c\x78\x57\xf7\xf9\x0f\x83\xf5\x55\x1b\x56\xa7\xf0\xe8\x1e\x52\xda\x8e\x86\x47\x3d\xec\xed\xa1\x06\x44\x63\x63\xc4\xbc\x0b\xca\xd8\x43\xba\xd9\x0f\xd4\xd8\x84\xfe\x32\x0d\x0e\x66\xf9\xdc\x9c\x27\x28\x51\xb1\xda\xdb\xbe\xdb\x86\x61\xb0\xf2\xec\x61\x57\xad\xfb\xa0\xdc\xde\x70\x79\xe7\x70\x4c\x8f\xbc\x5d\x2a\x35\xe6\xa6\x72\x42\x95\xbe\xa4\x6f\xdc\xbc\xc1\xd8\xf4\x45\x43\xd9\x69\x6a\x36\x52\xd5\xc3\x0f\x08\x99\xcb\x5e\x8f\xeb\xd5\x93\xf9\x9d\xd9\xdf\xb5\xc9\x11\xcc\x53\x19\x91\x46\x0b\x12\x4a\x0b\x52\xd2\xb5\xea\xf5\xac\x0a\xa7\xb4\xb7\xeb\x6b\x4a\x4c\x3d\x17\x28\x83\x0a\x5f\x5f\x23\x64\xaf\xa8\xc6\x7a\x9f\x00\x6b\x32\x34\xd2\xfc\xe4\x46\x8f\x77\x1c\x7e\x54\x6b\xc7\x71\xac\xad\x2f\x13\xaa\x77\x2f\xd4\xab\x69\xc4\x34\x36\x93\x86\x23\x87\xc9\x55\xb0\x5a\x9e\xf0\xd3\x60\x26\x35\xcb\x61\x3b\x27\x69\xb5\xe1\xca\xa8\xcf\x2f\x90\xc6\x47\xb8\x5d\x10\x8e\xc7\xd3\x5e\xaf\x09\xf3\x14\x6f\x1d\xd9\x72\x43\x0a\xfd\x23\x1b\xb8\xe5\x4a\xcb\xcc\xbd\xc3\x5d\xc4\x5a\xf7\xa7\x86\xf6\x08\xc1\x4a\x40\xcd\x79\xc1\xb2\x80\xbb\xe9\x6b\x4a\xea\xd5\xc1\x83\xe9\x71\x93\x6b\xd4\xf4\x7f\x58\xa4\xa5\x16\x42\xd5\xe1\x14\xe3\xa4\x3a\x9a\x36\x59\xd8\xac\x26\x54\x86\xac\xb6\xdd\xa9\xd5\xae\x9c\x30\x48\x49\x75\x34\x3d\xae\x92\x29\x94\x64\x38\x2e\x8f\xd2\x71\xa9\x7d\x16\xfa\xfd\xb1\x99\x75\xf8\xa4\x3c\x1d\x7f\x42\x73\xc8\x26\xe5\x29\x50\xc8\x31\xe4\x7d\x32\xef\xda\xf0\xdb\xb6\x6e\x78\xb5\x86\x61\xde\x93\x48\x9b\xd0\x5d\x6d\xdd\x76\x6b\x40\x81\x3c\xa4\x40\xea\x27\x68\x28\x49\xee\x1e\xe7\x64\x08\x05\x19\xc2\x8c\xb0\xf1\xfc\x28\xed\xf5\x8a\xa3\xd2\xea\x8a\x6b\x32\x9d\xcc\x4f\x61\x49\xf2\x49\x71\x6a\x22\xfd\xd9\xb0\x5e\x43\x58\x68\x47\x04\x38\x33\x41\xbe\x94\xde\x7d\x40\xc8\xca\x94\xbb\x24\xf3\xfe\xe8\x28\x85\x77\xa4\xe8\x8f\x8e\x4a\xf5\xf5\x12\xab\x0f\x17\xaa\xc2\xfe\xe8\x14\xce\xc9\x85\xaa\xe4\xad\xfa\x19\xc1\x67\xb2\x22\x84\x9c\xab\x7c\xef\x74\xbe\x47\xaa\x45\x95\xef\x21\x79\xa4\xf2\x9d\xa8\x9f\x11\xbc\x21\x1b\x42\xc8\x43\x5d\x5f\xaf\xf7\xae\xd7\x7b\xd3\xeb\x7d\xc6\x9f\xd0\x02\x4e\x80\x43\xbf\x3f\xc3\xf0\x23\xca\x80\xc3\x06\xce\xa0\x80\x0a\xc3\xac\x4f\x16\x9d\x3b\xcb\xaf\x6d\xbe\xb7\xa6\xd8\xac\x4f\xde\x76\xe6\x9b\xf7\xc9\x5d\x28\xfa\xe4\xae\x5f\x5f\xa8\x66\xf1\xac\xdf\xb7\x4d\xad\x5c\x53\x0e\x8c\xd9\x0d\xad\xce\xfb\x64\xd4\xac\xed\x52\x61\xe0\x80\x59\x78\x60\xba\x8b\x7f\x42\x6f\xe1\xcc\x61\x7a\x2b\xc8\xa3\xb1\x0b\x8c\x7c\x70\x79\x7d\x7d\xf0\xee\xfa\xfa\xfc\x80\x90\x87\x26\x42\xef\xb8\xd5\x66\x0b\x99\x1b\x41\x38\xf9\x6a\x10\xee\xda\xe8\xd8\x8a\x36\x21\xe0\xfb\xa8\xd3\x87\xa2\xdf\xd7\xf2\x40\xb1\xe2\x18\x5f\xcd\xfa\xfd\xf1\x82\x20\xc3\x88\x58\x71\x9a\x81\x5b\x73\xe2\xe2\x16\x5a\xf7\xbd\x64\x79\x3a\xd6\x4c\xfd\x94\x3c\xbd\xbe\x9e\x9c\x5a\x64\x91\xe1\x6b\xac\x43\x97\xe8\xc0\x25\x46\xcd\x7e\x8a\x15\x14\x63\xc4\xbd\x4e\x79\x7d\x5d\x05\xcf\x7e\x5e\x7b\xda\x9a\x6d\x05\xd5\xc7\x91\x4a\x2c\x5c\xad\xad\x71\x17\x87\x5c\x07\x48\x2b\x93\x0a\x28\x9b\x3d\xb7\x2f\x4f\xb7\xe1\xa6\xd8\x8f\x4d\x37\x7c\xab\x7e\xab\x25\x51\x73\x25\x6c\xa5\x5f\x45\x9c\x3b\xb8\x0e\xbd\x06\x1b\xbd\xa3\xcf\xac\x19\x19\x37\xab\x07\x2b\x8e\xc1\xda\x18\x5e\xb9\x8f\x94\x49\x71\x99\x54\x5b\xab\x38\xab\x56\x48\x65\xd6\xa7\x46\xf6\x99\x08\xa4\xc6\xab\x67\x6f\x59\x9d\x81\xc4\x3a\xff\xd8\x08\xfb\x50\x4d\xaf\x06\x1b\xb3\xff\x06\x53\xa8\xac\x0d\xa4\x7b\x20\xdc\xb4\x5c\x0d\x14\x9c\xfa\x1f\xf1\xe4\x9a\xd6\x6d\x6c\x2d\x55\xfa\x1b\x69\x09\xd3\xba\xc0\xba\x19\x9f\x76\x87\x5c\x19\xbe\x9a\x92\x40\xa6\xc7\xc0\x6d\x0f\xd7\x97\xe1\x1b\xfc\xa6\x21\x2d\x0c\x69\x5d\x91\x4e\xd2\x4e\xb7\x26\xb0\xa9\xa5\xff\x01\x21\x99\xa6\xd7\xeb\x06\xc0\x66\x01\x7d\x95\xb5\x29\xa5\x84\xf4\xf8\x13\x52\x53\x87\x21\x52\xa5\xf2\x1a\x1a\xb6\xc0\xf5\x64\xa9\x2c\x59\xb2\xad\x5a\x25\x59\xa0\xb7\x2d\xd7\x6c\x33\x2b\xfc\xe2\xd6\x9b\x30\x84\xdd\xd3\x23\xb5\x64\x6e\x3a\x58\x87\xd1\x1c\xdc\x70\x99\xea\x0d\x2a\xc8\xc9\xd4\x3a\x4e\xaa\xc5\x1d\x0f\x37\x10\xec\x42\xd2\xaf\xb0\x08\x21\x29\xd6\x50\x98\x95\xd9\x54\xf7\x2b\xb8\x5d\x04\x93\xd5\x8d\x0f\x9d\x79\x3a\xb0\xab\x5b\x22\x61\x3a\xf0\x4b\x5b\x52\x01\x9a\x13\x53\x7c\x60\xd1\xc7\xc1\xe2\xce\xc0\x3c\x87\xa1\x85\xb9\x59\xbf\xe3\xdf\x14\x5f\xed\xad\xdf\xae\x2a\x4d\x13\x35\xc7\x1c\x10\x52\xe2\xab\x72\xa0\x09\x6d\xb8\x52\xda\x99\xba\x74\x80\x8c\xe7\x37\x40\x62\x45\xdd\xfe\x76\xf3\x39\x62\xfd\x3e\x1c\x20\x43\x5e\xa5\xbd\x79\x0a\xe3\x07\x19\xf6\xba\x8d\x0f\x4f\x1f\x6e\x8e\xb7\x56\xad\x45\xc7\xaa\xb1\xb0\xab\xc6\x82\x14\x8d\xd5\x9f\x82\xb4\x30\xfd\xdc\x1f\x41\x06\xb2\x63\x4b\xba\xb1\xc7\x5c\x7b\x30\x06\xda\xc3\xda\xe9\x15\x0a\x9d\x12\x96\x64\x38\x5e\x1e\xcd\x9c\x1e\xb5\x54\xca\xcd\x8a\xf4\xfb\xbc\x8f\xd0\x86\xcc\x26\xcb\x53\xdc\x79\x76\xa9\xf7\x1f\x8e\x48\xde\xeb\xe5\x47\x64\xa5\x4d\xa8\x7f\x41\xeb\xc9\xf2\x14\x36\x96\x15\x57\x6a\x02\xda\x4b\x25\x4f\xa6\x31\x27\xab\xad\x7f\xd9\x59\x77\xfd\x51\x1c\xb8\x55\xd0\x0c\x0e\x6a\x5a\x58\x11\xde\x47\x9b\x7f\x3b\x32\x66\xe1\x1c\x6e\xcd\xc8\xa5\xe0\x17\xda\x45\xe3\xa9\x10\x5c\xa0\xb8\x5c\x9a\x6b\xcd\xe9\x86\x8a\x48\x8a\x54\xdf\x8c\x1c\x7d\x54\x25\x3f\x46\x5c\x44\x1f\x75\xc1\x8f\x36\x12\x70\x91\x9f\x53\x1d\x0b\x38\x0e\x45\xc7\xaf\x3b\xe7\xaf\x7a\xb1\xe0\xb6\x08\x64\x82\x6a\xe1\x02\xef\xb5\x05\x04\xde\x71\x1c\x6d\x2e\xa6\x44\xb8\x98\x6a\x6f\xc0\xd9\xd1\x01\x19\xf9\x01\x71\x60\x78\xcc\x09\x21\xb2\xd7\x43\x92\x64\xb5\x49\xe3\x8e\xfb\x60\xd7\x98\xf0\x6b\x3c\x7f\x05\xa2\x16\x40\x5a\xf2\x88\x7a\xe8\x59\xd6\x76\x0b\xcf\xc4\xef\xde\xcb\x30\x97\x2d\x88\x41\xba\xec\x8d\xb3\x19\xef\x87\xf3\x24\x95\x29\x1a\x82\x5b\x30\x76\x14\x6b\x1c\x63\xbd\xf7\x20\x79\x30\xdc\x50\x0e\x97\xb7\x43\x7d\x50\xbd\x3b\x2c\x8f\xbb\x12\xed\x36\x0f\x31\xf5\x26\x5d\x59\xfc\xc9\x94\x25\x87\x3b\x9e\xaa\xf1\xdd\xd6\x10\x87\x6b\x1e\x3d\x6e\x98\xad\xda\x84\x21\x70\x7b\xa2\xe6\xf0\x44\x6a\x07\x05\xfd\x5c\x87\xb7\x77\x35\xd9\x75\x51\x70\x10\x67\xdb\xef\x08\xa4\x22\x5b\x67\x32\x7a\xca\x09\xbb\x6d\xb7\x7a\x2b\xe0\x13\x17\x3f\xa1\x29\xc1\xcd\x81\xb8\xeb\x2e\x83\xb1\xaa\xa8\x09\xbe\xea\x29\x1b\x4c\xd0\xc8\xfa\x71\xbb\x1f\x32\xe7\x8b\x7b\x53\x25\x99\x99\x22\x54\xf7\x72\x3f\x4f\x85\x24\x35\x53\x9d\xbf\xf4\xd2\x6c\x6b\xd8\xaf\xe1\x21\x53\xe5\xf0\x70\xca\x9d\x22\x4b\x71\xf9\xda\xb8\x55\x41\x65\x79\xc7\x9f\xd3\xb4\x65\xc0\x1b\x1f\x19\x86\x45\x15\x3b\x67\xfc\x82\x45\x1a\x9e\x83\xc6\x30\xff\xad\x7d\x2c\x53\xa3\x06\x9c\xbc\xd5\x26\xd5\x4d\x4a\xe8\xa3\x8a\x5d\xce\xea\xf5\x50\x57\x72\x27\xf7\x62\x60\x66\xab\x43\xf6\x7a\xde\xcd\xc2\x90\x90\x83\xc4\xc0\x1b\x6e\xb8\x81\x5d\xb9\x63\x9a\xef\x11\x1d\xd4\x5a\xb3\xa2\xa0\xd4\x24\xa7\x9e\xe4\x41\x3c\x0d\x3a\xb0\xaa\x36\x64\x64\x38\xce\x8e\x9c\xfe\x3e\xce\x9c\x18\xaa\x08\x9f\x64\xa7\xfa\x5e\x6e\xdd\xf5\x90\x5b\xc5\x4c\xef\x5d\xcb\x74\x71\x6c\xb4\x82\xe4\x2d\x9a\x5a\xe5\xac\x21\x47\xa4\x6d\xe1\x11\x9d\x73\x41\x51\x0e\xe1\x6c\x32\xb1\xfa\xed\xa9\x97\x62\x9e\xa3\xf4\x81\x7d\xc8\xed\x0c\x43\xd3\xd7\xd8\x7a\xdf\xd7\xb2\x20\x94\xa9\xfe\x20\xd4\xd9\xb6\x3d\x13\xe9\x42\x9f\x88\x62\x3b\xb0\x64\x23\x2e\x82\xdd\x07\x99\xb0\x53\xcb\xe1\xb4\xd1\xb8\x47\x99\x6b\x94\xb9\x43\x99\x77\xa0\x5c\xfb\x7f\x05\xbc\xf4\xf3\xed\xc6\x71\x3e\xb1\xeb\x7a\x4e\xa3\x6c\x1a\x45\x53\x28\x45\x18\x8f\x03\xbf\xb3\x6f\x10\xd5\x1a\xd5\x14\x27\x54\xa2\x5c\x8d\x01\xa0\xd8\x26\x6d\x1b\x76\xac\xff\x40\x9e\x65\x7c\xe8\x09\x67\x0a\x0c\x4f\x65\x10\x17\x76\x25\xe1\x15\x85\x2b\x1d\x63\x91\xc2\x26\xa7\x17\xc9\xae\x69\x91\xd8\x42\xb5\x9e\xa5\x92\x26\x12\xed\x7e\xa5\x5b\x0c\x65\x75\x56\x66\x22\xb7\x76\x1f\xbb\x79\x9e\xc9\xed\x16\xa3\x00\xc2\x9f\x9a\x56\x55\x2d\x07\x9a\x50\x74\xd1\xfa\xfa\xe8\xbf\xa3\xf8\xdd\x92\x46\x1f\xe3\xbe\xe8\xc7\x1f\xa3\x15\x9f\x55\x05\x8d\x66\x9c\x96\x11\xe3\x32\x62\x94\xce\xa2\x79\x91\x2e\xca\xc1\x07\xf6\x9c\xe5\x32\x4f\x8b\xfc\x0b\x8d\x72\x1b\x19\x85\xf1\xc8\x3b\xde\xe9\x2b\xc6\x2f\x79\x15\x59\x55\xe1\x8c\x46\x69\x51\x44\x25\x95\x07\x71\xf3\xf8\xec\x9f\xdd\x90\xba\x35\x96\x8f\x16\xd5\xeb\xfd\x1d\x55\x24\x7e\x28\xa8\xae\x57\x8a\xcb\x9c\xe9\xeb\xc2\x4b\x46\xd3\xf3\x28\x8d\x4e\xb4\x36\xa2\xf7\x04\x8d\x60\x7a\x5a\xac\x8e\xa3\x77\x22\xcf\xce\x4b\x49\xc5\xc1\x07\xf6\x5c\x46\x05\xe7\xe7\x56\x23\xd1\x58\x0e\x56\x69\xce\xa2\xbc\x8c\xac\x8d\xab\xc1\xe4\xe3\x5a\xf0\x85\x48\x57\xef\x73\xb9\x7c\xa6\x10\xfe\xa8\x03\xaf\x2c\xd3\x32\x52\x6a\x40\xf4\xf1\xb5\xf9\x6e\xda\xfc\x38\xf8\xc0\x7e\x51\xfa\x8f\x2d\xf5\xd1\x47\x14\xcb\xe7\x1a\xd6\x19\xd7\xf4\xbb\x48\x99\xb4\xf4\x8b\xdd\xd2\x2b\xab\x8f\x6d\xd5\x1a\x29\x38\xae\xcd\x1a\x61\x8c\x29\xca\x06\xd3\x21\xb6\x0b\xb9\xf8\x9d\xc7\x3e\xaf\xfb\x41\xee\xf6\x9d\x89\x58\xa3\x04\xb4\xbf\x23\x5e\x01\xa0\xfa\x2f\x92\x22\xa7\x33\x55\x45\xc6\xd9\x86\x0a\xa9\xfa\xd1\x88\xf3\xa7\xc5\xca\xd0\x11\x34\xda\x41\x8c\xb1\xbc\x74\xa1\xc5\x6c\x00\x31\x05\xd5\xf8\xef\x48\x2d\x25\x83\x3e\xfd\xbb\xe9\x53\x33\x67\x88\x5e\x0f\x89\x41\xce\x18\x15\x3f\xbc\x7b\xf9\x82\x7c\x7b\x34\xcb\x37\x91\x3e\xd6\x27\xf1\x3a\x9d\xcd\x72\xb6\x38\x2c\xe8\x5c\x26\x23\xba\x1a\xc7\x0f\x8e\x96\x77\xdd\xd7\x39\x67\xf2\xf0\xc2\x98\xe8\x32\x2e\x56\x69\xa1\xbe\x9f\x3d\x78\xc5\xd7\xe5\xc1\xd1\x9d\xb3\x07\xd1\x5b\xbe\xa2\x3a\x28\x71\x74\x41\x99\x8c\x2e\x04\x57\x8f\x4b\xca\xa2\x52\xa6\x42\xc7\x80\xbb\xe4\x95\xd0\x28\xd9\xee\x19\x1c\xdd\x59\xde\x7d\x70\xb4\x16\xf4\x06\x20\xbe\xed\xcb\x7e\x7c\x74\x67\x2d\xe8\x83\xa3\x3b\xb3\x7c\xf3\x20\xc6\x50\x4f\x7e\xa1\xd7\xf1\x37\x81\x1e\x3b\xa0\xab\x33\x3a\x23\x4d\x7f\x21\xbd\xab\x24\x6a\xed\x65\x8c\x45\x63\x52\x17\x1d\x8a\xcd\x89\x92\xf8\xae\x63\x11\x43\xe6\x15\x28\x08\x0c\x72\x60\x84\x05\xc8\x41\x43\x2c\x80\x94\x48\x80\x1c\x28\x21\x83\xf1\x16\xc4\x60\x5e\x15\x45\x99\x09\x4a\x59\x57\xcc\xeb\x3d\x6d\x08\xf0\xee\x34\x67\x7c\x76\x79\x73\x7b\x8d\xac\x75\xdb\x35\x75\xa4\xdc\x3b\xbc\xdd\x7c\xe1\x34\x46\xea\x94\x45\xbf\x83\xa4\x84\x34\x86\x8a\xbc\x45\x59\x70\x35\x51\x73\x46\xab\x30\x08\x89\x2a\x10\x90\x35\x79\x50\xc8\x4e\x57\x66\xaf\xd1\x57\x56\x99\x3f\x79\x35\x7d\xf3\xf4\xe7\x5f\x9e\xbe\x7d\xd7\xb1\xd0\xf9\xa5\x1e\x37\x4a\xe1\x8f\x5c\xa8\x92\xc1\x07\xf6\xba\xa0\x69\x49\x23\x41\xd7\x5c\xd8\xab\x4e\x24\x8f\x8e\x96\x52\xae\xcb\xe4\xce\x9d\x45\x2e\x97\xd5\xd9\x20\xe3\xab\x3b\x3e\xde\xee\x26\x17\xb2\x4a\x8b\xc3\x19\x5f\xdd\xc9\xcb\xb2\xa2\xe5\x83\x81\x8b\xbb\xf7\xfa\xe9\xc9\x93\xe7\x27\xdf\xd7\xb0\x9c\x49\xc4\x15\xf2\xf1\xd3\xbf\xbf\x7b\xf3\xd0\xa7\x8f\xad\xa6\x82\x32\x0c\x39\x79\x89\xa6\x81\xfe\x24\x75\xb4\xba\x29\xe4\x6a\xc9\xa4\x77\x96\xa6\xc4\xad\x42\x9a\xb5\x84\x6b\x00\x25\x55\x03\x22\xd8\xbb\x41\x32\x68\x26\xc3\xb4\x76\xa0\x0b\x4d\xfa\xc3\x3c\xe6\xdc\xc8\x03\xde\x46\x09\x32\x12\xda\x62\x52\x19\x8e\x9c\x3d\xbc\x6a\x59\x64\xc6\x33\x7f\xce\xf3\x07\xd9\xf7\xff\xcf\xde\x9b\xa8\xb7\x8d\x63\x09\xa3\xaf\xa2\x70\xaa\x32\x60\xf9\x48\x91\x9c\x54\xaa\x8a\x69\xb6\xc7\xb1\x9d\xc4\x89\x9d\xcd\xce\x5a\x55\xc3\x4b\x91\x90\xc5\x98\x22\x64\x10\xf4\x12\x9b\xf3\x1a\xf7\x81\xee\x8b\xdd\x0f\x1b\x57\x90\x92\x93\xea\x9e\xe9\xff\x9f\xea\xfe\x62\x0a\x3b\x0e\x0e\x0e\x0e\x0e\xce\x82\x12\x3e\x2e\xbb\x85\xc5\x84\x21\x5c\xaf\x03\x44\x61\xb2\xfa\xb3\x9f\xa8\x8f\x57\x19\x93\x1b\xab\xb5\xcd\x0b\x69\xe0\x2d\x46\x4a\xaa\x9b\x99\x8f\x2e\xe8\x1a\x1d\x15\xb2\x93\xee\x11\x55\xec\xe8\x58\xc5\x6e\xa9\xdb\x8c\xae\xa2\x5e\x15\x12\x11\x73\xb8\xb4\x6b\xac\x18\xd1\xa5\x8f\xaf\x76\xb4\x52\x2f\xb2\x42\x3c\xcd\xf8\x46\x1d\xa6\x51\x88\xa7\x3e\x1d\x2a\x3f\x8a\xa9\x65\xff\x3e\xfe\xf3\x51\x72\xf7\x2e\x4a\x2a\xe6\x5f\x49\xcd\x52\xc7\xce\x69\x35\x04\x80\x66\x96\xec\xba\x89\x1d\x33\xba\x85\x2d\x86\x2d\x7c\xb8\xca\x77\x2e\x4d\x34\xb2\x26\xd1\xf0\xbb\xb3\x52\x19\x45\x65\xe6\x1e\x09\x9f\x60\x8f\x68\x8d\x90\xcc\xe4\xe1\x1a\xbb\x94\xa1\x19\x24\xc0\x8b\x40\xe8\x12\xe4\xd9\x23\x6f\x02\x4b\xf7\x08\x85\xe0\x37\x6b\x2d\x65\xad\x39\xaf\xb5\x04\x8f\xa1\x08\x96\x40\x6c\xe0\x45\xe1\xdc\x0d\x18\xf2\x20\x00\x1f\xa4\xc9\x86\x69\x03\xc5\xfc\x56\x37\xe7\xff\x9c\xf3\x73\xa5\xb2\x98\x01\x33\x88\xe7\xc1\x33\x35\x22\x1f\xd1\xd3\x5d\xb5\x44\xaf\x96\x58\x72\x79\x77\x02\xbe\xc0\xa5\xfc\x5e\xc4\x64\x53\x94\x21\x63\x92\x23\x06\x7e\xe3\x9d\x33\x57\x14\x55\x81\x95\x44\x39\x4e\x5e\x32\xce\x94\x78\xee\x7b\xe4\x41\x06\x11\xe7\x87\x33\x37\x81\x39\x2b\x6c\x2e\xab\x03\xce\xba\x48\x2e\xe5\x4d\xab\x17\x61\xf0\x46\x41\x4c\x52\x8c\xa4\xe5\x53\xe0\xca\x5d\x3f\x12\xd6\x37\xc3\xdf\xc6\x63\xc8\x74\x92\x34\xce\x19\xde\x7f\x38\x06\xcf\x95\x36\x49\x23\xb2\xc4\x09\xb2\x2c\xe0\xff\x17\x55\x5c\x5e\x45\x96\x74\x79\x49\x7e\x88\xbb\xd6\x46\xb0\x61\x01\x23\x4b\xd7\xda\xc8\xc4\xec\xbc\x91\x1e\x31\xc8\xd1\xcc\x19\xcc\xd9\x88\x45\x8c\x73\x00\x1a\x70\x83\xe1\xc0\xda\x10\x19\x9c\x10\x48\xdd\xc3\xd1\x42\x98\x78\xb9\xd6\xd8\x6a\x64\x28\xbe\x81\xe7\x28\xb7\x76\x47\xe2\x60\x7b\x54\xea\xd5\x8a\xd2\x55\x84\x89\x6c\xde\x48\x4b\x29\xd0\x3a\xc5\x57\x21\xb9\x48\xac\x9a\x01\x22\x1b\x2d\x30\xf3\x5f\xe0\xab\xbb\x77\x7f\xdd\x14\x0e\x26\x2e\xe6\x51\x30\xbf\x7b\x57\x01\x23\x26\x81\x50\xcf\x1b\x51\x1c\x13\x3f\x44\x36\xdc\xff\xb5\x5a\x0c\x25\x4a\x64\xa3\x6d\x5c\xdf\x2d\xad\x9c\x13\x99\xa6\xe2\x9e\x0d\x0f\xc6\xbd\x15\x77\xf9\xd8\xcc\x55\x73\x1b\xd4\x70\xda\xb3\xca\x12\x3e\x2e\xce\xed\x82\xd7\x93\x5d\xbd\xd0\x54\x51\x45\xb5\x6b\x52\xc3\xac\x36\xdd\x1c\xec\x0e\xc7\x2f\x19\x21\xa0\x82\xa9\x10\x55\xcc\x6c\x58\x4d\x2c\x01\xc4\x4d\x19\xa2\x36\x04\xae\xf5\x52\xf0\x99\x16\x64\xa5\x7a\x96\x57\xf5\x96\x93\xb7\xf6\x1f\x2d\xcc\x8a\x78\x13\xbe\x1b\xe9\xb8\x6f\x8f\xaa\x3a\x38\x27\x98\x16\x8d\x0b\x23\x88\xcc\xf1\x20\xb8\xe3\xba\xfe\xdd\xbb\x28\x62\xfa\x15\xac\x36\x4b\x4b\x6c\x7c\xe0\xb9\x4d\xe0\xf1\x2c\xdf\x86\x4a\x8b\x81\x10\x03\xd7\x4e\x32\x85\xa7\xe4\x1c\xd3\x59\x4c\x2e\xa0\x2f\xd3\xb5\xe6\x51\x18\xe2\xc4\xaa\x35\xca\x07\xd7\x5b\x2b\xe1\x40\xf3\x6d\x88\x84\x6f\x8c\x02\xc0\x51\x01\x60\xc5\x6e\x69\xd9\xa9\x6a\xda\xa9\x2a\x57\xbd\xf6\xb3\xb4\xd4\x58\xf2\x65\xd5\x2b\xad\x7e\x7e\x28\x8f\x99\x66\xfe\x31\xab\x1e\x7c\x3e\x6b\x5b\x88\xb5\x24\x7f\xb5\x89\xfc\xce\xfe\x54\xa2\x3f\xb8\x33\xae\xda\x24\x33\xa3\x7d\xbd\xf4\xfa\xa8\x77\xa9\x54\xa8\xba\x5a\xe2\x9b\x9b\x3b\x54\x6f\xd2\x9b\x9b\x5f\x37\x45\x86\xd8\x44\x55\x41\x8a\x25\x8f\x42\x69\x58\x2f\xab\x59\x17\x73\x8c\x2b\x29\xc2\x7d\x2c\xf3\xe9\x09\x66\x8f\xb4\xc9\xba\xf2\xc4\xca\xf9\x47\x0e\xef\xd8\xbf\xd2\x67\xee\x30\xc4\xcc\x8f\xe2\x54\x85\x62\xd1\x87\xf4\xdd\xbb\xfa\x36\x2f\x1e\x7d\xe4\xb5\xf9\x4e\x91\x96\xb8\x49\x45\xfc\x96\x9b\xb4\x7c\xdb\x3a\xbd\xb9\xe4\x07\x39\x51\x3d\x3a\xfe\x74\xb0\x67\x41\xcc\x5c\x6b\xef\xfd\xde\xcb\x63\x0b\x42\xe6\x5a\xdb\xc7\xc7\x6f\x2d\x58\xaa\x2f\xef\xe5\x11\x27\x93\x46\xb3\xd1\xb6\x29\xea\x75\x0e\xe7\xcc\xb5\x3c\x1c\x2f\x3e\x3c\x7c\x7c\x60\xc1\x82\xb9\x6f\xd0\x0b\x1b\x4e\xf8\xdf\xcf\x36\x4c\xcd\x2d\x7d\xab\x01\x6a\x8a\xd9\x71\xb4\xc0\x44\x9c\x54\x13\x7c\xff\xde\xc3\xb1\x9d\xc3\x15\x73\x7f\xb7\x82\x38\x0a\x4e\x2d\xb0\xc2\x69\xac\x3f\x17\x24\x4b\xd5\x9b\xa8\xfc\xce\x96\xfa\x4b\xd2\x6a\xf9\x8d\x13\xc6\xf7\xa3\xfc\x11\x63\x5f\x94\x67\x24\x0b\xe6\xe2\x0e\xaa\x7f\x08\xc5\x1d\xf9\x19\xf8\x49\x80\x63\xfd\x4b\xf5\x20\x02\x25\x62\xaa\x5a\x56\xbf\x44\x8f\xea\x9b\xe3\x40\xe5\x57\xc6\xca\x1f\x7a\x08\xea\xa7\x1e\x84\xfa\x59\xef\xa0\xe8\x3c\xa4\xfe\x89\x1e\x21\xff\x56\x7f\xe4\x38\xe5\x97\x6c\x95\x7f\xab\xce\xf9\xa7\x6e\x3d\xa4\x84\x8f\xee\x14\x5f\x65\xea\xaf\x1a\xfb\x29\xbe\x5a\x52\x9c\xa6\x16\x58\x51\xb2\x14\xe3\x0c\xe6\x7e\x72\xc2\x2b\x09\x2b\x5a\x0b\xac\x69\x9c\x51\xeb\x4f\x38\x66\xee\x15\x1b\x05\x24\x09\x7c\x86\xd4\x9e\x00\xbd\x5d\xf4\x41\x7a\x2d\x1e\xc3\x89\xb4\x96\x4d\x40\x4a\xb1\x1d\x0f\x16\xfe\xd2\x61\x28\xb5\x81\x24\x0e\x45\xc7\x36\x08\xda\xe4\x9c\xc3\x92\x92\x25\xa6\xec\xca\x61\xe8\xc4\x06\x5f\x6b\x4f\x4b\x0f\x81\x7e\xa9\x4c\xed\x50\x74\x25\xfc\x0b\xbe\x2e\x2b\x9c\xda\x10\xfb\x5f\xf9\x57\x2c\xbf\x36\x1d\x8a\x42\xf9\x79\xdf\xc1\x68\x69\x83\x78\xee\x13\xfa\xd0\x94\xdf\x3f\x95\x5c\xc1\x59\x30\x68\xca\x8d\x9c\x13\x06\x29\xf3\x59\x14\x28\x89\x91\xf3\x49\xda\x16\x7f\xe9\x70\x18\xf7\x2c\x19\x35\xdb\xd0\xea\x21\xcc\xce\xe1\xeb\xca\x6a\xf0\x0a\x8b\x92\x4f\x13\xf7\x99\xb0\x35\x94\x23\x85\x37\xe2\xb7\x98\x04\x7c\x2a\xbe\x37\xe1\x45\xe2\x22\xf5\x03\xae\x1b\xf4\xc0\xb9\x33\x81\x3a\x39\x70\xee\x4c\x72\x1b\x3e\x8b\xfa\x24\x81\x8f\x3d\x8e\xf3\x3e\x27\xc0\xe0\x45\x22\xe3\x4e\xfd\x20\x6a\x88\xe5\x01\x46\x44\x8f\x15\xa8\xc3\xb3\x64\x54\x59\x95\xda\x4f\x1b\x28\x71\xe5\xf4\x64\x59\x2c\x7e\x2e\xfc\x25\x24\xe2\x8b\x23\x05\x10\xf1\x29\xa4\xc8\x01\xe9\xf2\x79\xd3\x9a\x1e\x6b\xce\x4e\x84\xec\xf9\x92\xd8\x90\x11\xf7\x6b\x02\x1e\x71\x31\x81\x88\xb8\x09\x01\x9f\xb8\x84\x40\x4a\x5c\xe4\x13\x64\xf1\x03\xc4\xb2\x81\x7f\xa6\x58\xda\x31\xc8\x5f\x89\x7f\x6e\xd9\x36\xcc\x54\x39\x9f\xb2\x28\x88\xb1\xca\xf4\xf9\xcd\x49\x7d\xcf\x27\xbc\x5c\x4c\x5c\xf1\x63\xd3\xb2\x61\xa9\xbe\xef\x5b\x36\xcc\x55\xfd\xf9\x03\x5d\xfc\x67\xfd\xf1\x50\x7f\x60\x3f\xc4\xd4\x12\xfa\xb5\xb2\xf0\x8c\x10\xbe\x5f\x55\x5f\x61\x28\xb6\xa0\xfc\xb5\xf0\x23\x3d\xc2\x25\xaf\xb2\xd0\xed\xeb\xe2\x4b\x2a\x9c\x40\x9e\xe8\xf9\xc5\x24\x38\x3d\xcb\x08\xd3\xc3\x25\x31\xcf\x9e\xca\x21\x66\xb1\x65\xc3\x95\xfc\x8e\x23\xcb\x86\x63\x55\x2d\x8c\x55\xf1\x90\xe9\x8f\x50\x7d\xcc\xa2\x93\x8c\xe2\xf2\x47\xe0\x2f\x2b\x60\x0b\x23\x01\xb6\x0b\xd9\xa6\x6f\xd9\x70\xaa\x9a\xc4\x0b\x0d\x67\x46\x49\x72\xc2\x4b\x1d\xc9\x52\xe9\xc2\xe7\x34\x02\x2e\x55\x49\x3d\xd7\x20\x2a\x46\x7d\xa6\x9b\x9f\xe9\x8e\xfc\xe9\x54\x4f\x99\xc9\xd8\x61\xa2\x0a\x09\xc5\xf4\x1f\xab\xa6\xce\x7d\x5d\x28\xf5\x17\x4b\xf5\x79\x3a\xd5\x73\x49\xb3\x69\xf1\xa5\x73\x23\x5e\x7f\x5b\x8e\x8c\xe7\xbe\x54\x4d\x65\xc5\x0a\xd0\x53\xf5\x49\xb3\xa9\x46\x1e\xaa\xe1\x44\x75\x3b\xd3\x30\x2a\xbe\x88\xee\x65\xe9\x27\xbc\xf9\xb7\x7a\x75\xf4\xe8\x2e\x8a\xaf\x28\xd1\xd3\x0f\xb1\x5e\x84\x68\x71\xa2\xbf\x66\xfc\x24\xe4\x4d\xec\x15\x60\x9d\x62\x3d\x1d\xa5\xe6\xaf\x10\xc1\xa7\xbe\x06\xf9\x79\x14\x62\x3d\x06\x3f\x0b\xa3\x62\x3c\xc2\x9d\xa3\x06\x23\xf5\x03\x3d\xb3\xc0\x4f\xce\xfd\x12\xe7\xd8\x5c\x97\xf1\xa7\xb1\xe8\xfe\x50\x75\x5f\x5f\xfd\x80\xc4\x27\x94\x14\xa0\x0c\x88\x9e\x01\xab\xec\x33\xc6\x11\x5e\x7f\x73\x54\x2f\xfa\xe7\x0d\xef\x48\xc8\x33\x5e\xe2\x4c\x7d\xf3\xde\x9f\x14\x7b\x83\x2e\x0a\xe4\xc3\x71\x98\x62\x5d\x3f\xc6\xe2\xc4\x53\x3f\xfc\x29\x16\x98\x7e\x20\xdb\x90\xc7\x97\x0d\xfb\x6a\x61\x33\xc6\xc4\xa8\x5f\x69\x9c\xc3\x71\x09\xba\xd0\x67\xbe\x70\xee\xa9\xc0\xba\x64\xd5\x59\x91\xea\x8c\x39\xd1\xf2\x29\xf6\x79\x57\xcf\x55\x5b\xa7\xf8\xea\x04\xeb\x02\x24\x63\xb2\x67\xb9\x39\xc9\x49\x75\x33\xe3\x72\x9b\x6b\x3e\x50\xa3\xe3\x62\xe1\xd3\xab\xa2\x5c\x92\x45\xac\xd8\x40\xfc\xa7\x65\x03\x23\x36\xbc\x26\xe6\x63\xe4\x39\x01\xbe\x56\xfb\x32\xdc\xcb\x29\x12\xe2\xae\xdd\x9e\xc2\x94\x1f\xd7\xc2\xd3\x18\x71\x29\x81\xf7\xa4\xdb\x71\xda\x3b\x02\x0c\x58\x22\x63\x94\xc1\x87\x8e\x46\xdf\x13\xa8\x18\x92\x8b\xa6\x9f\xf5\x14\x8d\x42\x59\xe6\x4b\x4f\x19\x71\xc5\x97\xc5\xbe\xf6\x14\x4b\x69\x20\x0b\x3d\xed\x6b\xeb\x6a\xa9\x9a\x7a\xd3\x53\x4a\x05\x99\xe2\xc5\x3e\xf5\x14\x9b\xb3\x45\xfc\x84\x50\x59\xf0\x45\x5f\x41\x8a\x67\xb2\xd4\xe7\xbe\xb1\x89\xcb\x83\x2c\xf7\x71\xd5\x42\xfc\x80\xd5\x42\xfc\xd0\xd1\xe2\x47\xbe\x10\x73\x1c\x9c\x62\x05\x62\x16\x74\x17\x0c\xa3\x94\xef\x70\x55\x92\x1a\x4b\x7e\x20\x28\x42\x97\x14\xac\x81\x05\x11\xfa\x0c\xdb\x09\x44\xe8\x23\x3c\x4e\x80\xd9\x36\xc7\x33\x1c\xb8\x3f\x24\x90\x04\x6e\x84\xe6\x89\x60\x22\x77\x84\x53\x8d\x69\x62\x03\xe1\xa9\xe7\x49\x23\xba\x65\x31\xe5\x32\x1c\xa6\xce\x29\x86\xde\x88\x94\x99\xc3\x15\xbf\xb1\xde\xb6\x39\xb5\xa2\xad\xc6\x8e\x39\xaf\x10\xb8\x2f\x12\xf0\x02\xf7\x63\x02\x51\x07\x90\xbc\xa0\xe0\x7c\x83\x44\x6e\x2b\xbf\xa7\xa8\x60\x8e\x8b\x92\x69\xe0\xa2\x85\x96\x13\x67\x01\x5c\x37\x79\xb2\xb1\xd9\xa3\xa1\x6c\x4b\x73\xde\xca\x44\x9e\x04\x62\xd9\x67\x3d\xbd\x2b\x9e\x5d\x55\x08\x78\x05\x88\x7b\xca\x57\xef\x3d\x7a\xcc\xe1\xaa\xf2\xea\x6e\xa1\xcb\x2f\x7b\xca\xab\xeb\x98\x2e\x3a\x0f\xbe\x93\xc1\x7b\x9a\xd8\x70\x1e\xb8\x68\x1e\x48\xbe\x06\xf8\x47\x26\xc8\xfe\x22\x70\xdf\x24\x70\x12\xb8\x9f\x12\x98\x06\x5d\x31\x77\xcb\xa7\x79\xe1\x69\xfb\xdd\xdb\xfd\x1d\xb2\x58\x92\x44\xd8\x8a\x57\x44\x09\xc2\x53\x1f\xa3\x57\xba\xf8\x01\x92\x86\xb9\x8d\x0a\xed\x00\x46\x67\xdf\xe6\x1a\x4f\x8a\x3d\x12\x7c\x31\xf8\x78\x78\xf0\x8c\xb1\xe5\x5b\x79\x21\x7e\x44\x10\xe7\xc3\x21\x31\x88\xe0\x30\xa5\x9c\x04\x55\x66\x8a\x51\xd3\x31\x1e\x66\x17\x84\x9e\x8a\x27\x31\x4b\xf8\xc5\x33\xb6\xc4\xe4\xc5\xba\xbf\x2d\x75\xfb\xee\x69\xa6\x25\x11\xc4\xc8\x43\x09\xb0\x91\x7c\x89\x1b\x51\x9c\x2e\x49\x92\xe2\x63\xf2\x16\xa7\x59\xcc\xc1\x67\x8b\xa8\x50\x89\x94\x0d\x0b\x99\xe9\x9c\x84\xc0\x46\x19\x8d\x85\x6c\x47\x82\xb7\x04\x62\x6b\x54\x8f\xfd\xf0\x1d\x8d\xa5\xe3\x3f\x5e\x2b\x2f\xf5\x4f\x02\xde\xb7\x0d\x99\x18\x82\x7c\x51\xaa\x8c\x2d\x19\xf9\x53\x42\x85\x94\xa4\xee\x2a\x90\x2f\x59\x11\x2f\xf7\x4e\xe9\x4f\xd1\x24\xfa\x2d\x8e\xf7\x86\xec\x57\x4a\xae\x38\xa6\x64\x82\x81\xaa\x7b\x63\xa4\x23\x6f\x8c\xae\xa7\x57\x0c\xa7\x0e\x1b\x71\xa8\xe1\x10\xc4\xcf\x3d\xf5\x64\xe9\xb0\x11\x23\xcc\x8f\x73\xbb\xed\x2b\xaa\x69\x4b\x2e\xcc\x8c\x15\xba\x3c\x13\x37\x0b\xd1\x01\x50\xe1\x3b\x97\xd3\x6b\x0c\x74\x24\xef\x1c\xa9\x0d\x95\x65\xb8\x5a\x62\xe1\x8b\xb8\xbe\x38\x57\x4b\x0c\x6c\x74\x11\xb1\xf9\x0e\xc5\xc2\x3f\xbd\x1f\xa7\x2e\x6d\xa6\x80\xf5\x3c\x4b\x99\x92\x82\x49\xd4\x50\x80\x42\x4c\x27\x54\xb2\xbc\x71\xdb\x2f\x78\xa1\xa0\x59\xf1\x1a\xb7\xb7\x58\xb2\xab\xc7\x9c\x77\xac\x29\x3b\xf2\x49\x26\x21\x52\x72\x45\xe9\xb4\xbe\x56\xca\x00\x05\xed\x81\x6e\x78\x2c\x8e\x7e\xe1\x01\x13\xaa\xad\x09\x08\xc9\x16\x9f\x10\xba\xd8\xf5\x99\xdf\xd9\xb3\xf4\x1b\xdb\x72\xcc\x28\x85\x84\x29\x62\xb6\x8c\x7b\x92\x32\x9f\x65\xe9\xdf\x36\xc7\xe3\x9b\x9b\xfb\xe3\xf1\xdf\x5c\x9d\x54\x68\x83\x08\x4c\x74\x2b\xf0\xe6\x97\xe0\x36\x52\x1f\x89\x5a\xd2\x1d\x72\x6e\x17\x6f\x3b\xc5\x43\x94\x52\x35\x51\xc1\x9c\x2b\xef\x73\xc2\x6d\xa9\x83\xd6\xed\xe7\xb5\x7f\x25\xb7\x6d\x25\xe6\x31\xae\x59\x9a\x54\x63\x99\xca\xb9\x38\xd7\x32\x2e\x85\x9a\x1a\x28\xc9\x66\x91\xc0\xbb\xca\x41\x61\x9c\xc3\xc1\x72\x82\xd9\x76\x1c\xbf\x55\x43\x91\xeb\x93\x22\xdb\x86\x8c\xc6\x4e\x39\xc6\x77\x6f\x0f\x80\x0f\xbb\x92\x54\xf7\x5b\xa5\x9d\x9e\x32\x61\x4a\x70\xc7\xe0\xd1\x5c\xf8\x9d\x10\x0e\xba\xad\x3f\xe8\x1f\x9c\x27\x4f\x5c\x5c\x0f\xee\x55\xfa\xd3\x10\xde\x5d\x85\x06\xde\xab\x19\xb2\x9c\x81\x25\x56\x31\xf8\xfb\xb8\xd0\xfd\x13\x6f\xba\x02\xdb\xd0\x18\x02\x1b\xbc\x5a\x52\xb0\xb1\x69\x3f\xa2\xae\x08\x1f\x9f\x99\xce\xf1\x03\x54\xec\x12\xe5\x61\xdc\xdb\xb0\x40\x84\xb2\xf3\xc6\x8e\x67\x8b\xd8\xde\x65\xdc\x8f\x62\xaa\xd5\xc8\xae\xd5\x8d\xa9\x9d\xcf\x35\x29\x69\x4f\x70\xd7\x5a\x75\x5a\xdf\xe6\xad\x66\xda\x47\x12\x6d\x51\xed\x12\x07\x39\x47\xca\x84\xf2\x53\x5e\x0f\x0a\x5b\x0d\x83\xc2\xcf\x34\xbd\xbb\x7a\x03\xa2\xa8\xb7\x36\x54\x04\xef\xb7\xeb\x71\x51\x14\xce\xd6\x76\x2a\xc7\x5a\xaa\x01\x78\xcd\xc8\xb1\x9f\x9e\x3a\x0c\x25\x36\x48\xaa\x26\x09\x85\xc6\x3b\x27\x86\x85\xbf\x94\x34\x56\x86\x3d\x59\x64\x31\x8b\x96\x3e\x65\xce\x52\x45\x07\x79\x47\xa3\xc2\x39\x13\xff\xc6\xc2\xcf\xf9\x55\x27\xe3\x32\x28\xd8\x3b\x0a\xd7\xb2\x53\x27\x42\xd3\x60\x54\xf4\x24\x9c\x1b\xc9\x1c\xe1\x97\x16\x82\x96\xab\xef\x7a\x68\xd4\x6b\x79\x0a\x3a\xac\xd8\x42\x54\xec\x13\x2c\xf7\x46\xa2\xe6\xe6\x10\x50\xc4\xd5\x09\xa0\x41\x9c\x9d\xac\xd7\x1f\xb8\xa2\x93\xa5\x43\xf0\xe3\xa0\x3f\x3e\x76\x85\xe0\xd6\x83\x64\x5f\x04\xda\x93\x78\x49\xb8\x73\x38\xed\xe6\xf3\x64\x61\x49\x01\x1a\x6d\x4d\x83\x51\x01\x77\x1b\x8e\x02\x77\x1a\x8c\x8a\x45\x81\x4b\xf9\xdb\xb0\xac\xf0\xd8\xc8\x81\x5e\x06\xc8\xa0\x3a\x15\x21\x4f\xba\x9b\x12\x0c\x41\x6e\xe7\xb0\x1d\xb8\xa8\x5a\xb6\x6c\x61\x97\x21\xa6\xcb\xf1\xd1\x15\xd8\x62\x66\xd9\x8f\x03\xb0\xfc\xe5\x32\x8e\xe4\xcb\xee\xbd\x2f\x29\x49\x38\x2f\x4e\x13\x18\x8b\x88\xe5\x36\xbc\x0c\xdc\x8b\x00\xde\x06\xee\x55\x00\x7b\x41\xc3\xe9\x7a\xd5\x25\xde\xdb\x00\x69\x34\xb0\x5e\xbf\x3a\x3a\xb6\x0a\x5c\xa8\x06\x59\x17\xd4\x53\x62\x05\xd5\x58\xf1\x38\x40\xd8\x2e\x30\xe3\xac\x85\x19\x77\x26\x79\x8f\xc7\xf0\x6a\xbf\x4f\xf7\x56\x77\xfb\x32\xa8\xf4\x4b\xd7\xe8\xb7\x0a\x39\x45\xcb\x4b\x6a\x32\x0d\x46\x72\x0f\x8b\xc3\x1a\xce\x78\x85\xc3\x2e\xd4\x1c\x44\x28\xa0\xc0\x60\x2f\x50\xf7\xe1\x9d\xa0\xd7\x8d\xbe\x1c\xb5\x3a\xc1\x68\x31\x31\xbd\xab\xf2\x4e\xa0\x98\x0f\xcb\x12\x6f\xd7\xd8\x39\xaf\xc5\x53\x4d\xad\x96\xe9\x82\xb2\xb6\x0a\xd0\x58\x2a\xc8\xcf\xa3\x94\x11\x7a\x35\x3a\x21\x88\xd9\xb0\x86\x9a\x0e\x5d\xb7\x03\xdd\xf2\x32\x4b\xe7\x9c\x15\xc1\xe8\x3a\x07\xcb\x82\x66\x37\x01\xb2\xeb\x3d\xe0\xdb\xf6\xa0\x54\xfc\x6f\xd5\x49\xb2\x6e\x27\xc5\xb3\x71\x53\xdd\x62\x3d\x70\x91\x75\xfb\xe1\x97\x98\x86\x62\x87\xcb\xca\xbb\x61\xe7\x30\xee\x4c\xd6\xd2\xae\x0a\x94\xbf\xf4\x52\x23\xa2\x68\x49\xbf\xb3\xcd\x29\x9e\x39\x6c\xc4\xff\xc0\x9c\xa4\x8c\x7f\x93\x94\x89\xef\xc4\x5f\x60\xf5\x9b\x7f\xc2\x92\x12\x46\x02\xc2\x39\x2f\xfd\x09\x84\x46\x27\x51\xe2\xb0\x91\xfc\x80\x25\xa1\xcc\xe3\x05\x08\x65\xb0\xf4\xd9\x5c\x35\xa2\x3f\x21\xc5\x3e\x0d\xe6\xc2\xc9\x11\xff\x80\xb9\x9f\xf2\x5f\xfc\x0f\x64\x29\xa6\xaa\xbc\xfe\x84\xa5\x9f\xa6\x17\x84\x86\xa2\x0d\xf9\x59\xf3\x12\xab\x01\x3d\x9c\xdc\x71\xb5\xc6\x50\xe2\x9f\x47\x27\x3e\x23\x54\x34\xb3\x7d\xc2\x27\x5e\xb0\x6b\xc7\x54\x44\xcf\xb2\x8a\x18\x27\x27\x84\xef\x6f\xcc\x0e\x14\x68\x1c\x02\x12\xcc\xaf\x39\x73\x9a\x40\x81\xcb\x0e\x85\x2a\xd6\x39\x18\x4e\x2a\xb5\x02\x88\xd2\xfd\x84\x61\x9a\x60\xb6\x77\xb9\x8c\x09\xc5\x74\x32\xe1\x27\x2a\x67\x58\xcf\x02\x77\x27\xa8\x21\x2d\x3c\x11\x49\x45\xeb\x70\x20\x7e\x9f\x10\xd8\x57\x65\xf5\x18\xe0\x95\x48\xa8\x0c\x11\x9e\x07\xee\xf3\x40\xb8\x38\x7b\x1e\xfc\x6e\xdd\xfd\xbb\xf5\x67\x37\xb5\xfb\x6a\x3c\x77\x68\x2e\x22\x5c\x89\x1b\xc2\xeb\xc0\x6d\x9f\x28\x92\x8f\x33\x1e\x85\xfb\x4c\x85\x86\x10\x01\x90\x4b\x3a\xac\xc7\x02\x1f\x99\x08\x35\x21\xfc\xa1\xc0\x27\x86\x9a\x31\x2d\x64\x38\x8b\xee\x5e\x71\xe1\xb1\xae\x7a\xc7\x7b\x9e\x2d\x96\xc5\x25\xeb\x20\x90\x57\x16\x79\x0f\x7b\x89\x4b\xd3\x3c\x31\xe3\x08\xbd\x0e\xf8\x20\x6d\x78\xa2\x0a\x6a\xdd\x12\x12\x46\xb3\xab\xae\xc2\x67\xf5\xc2\xef\xa3\x34\x2a\x0d\xf3\x5e\xe9\x2e\xb5\x85\x94\x4a\xdf\x57\xe9\x9c\x3c\xbf\xab\xf3\x14\xf5\xa3\xaa\xa2\x65\x23\x2f\xaf\x5b\xa7\x2a\xc2\x82\x53\x01\x9e\x4e\x53\x1f\x13\xdb\xce\xe1\xbd\x09\x56\x6d\xb8\xfb\x72\x22\x58\xdc\x35\xf8\x7c\x3e\x31\xb1\x44\x36\x7c\x08\xdc\x97\x6c\x14\x63\x7f\x86\xac\x97\x72\x7b\xc8\xb7\x89\x67\x5d\x19\x5f\x3a\x79\x3b\xde\xb8\xc3\x60\x49\x96\x1f\x84\x69\x14\x95\x27\xd3\xd7\xc0\xfd\xc4\xd7\xfd\x4b\x00\xd5\x53\xff\xcc\xb6\xe1\xa9\x89\xd3\x2a\x98\xca\xf2\x6c\xcc\x73\x78\x13\xb8\xe8\x59\x80\x9e\x06\x9c\xc8\xf1\xe1\x89\xcf\xb1\xdd\xc3\x96\xca\x55\x2a\x98\xd2\x4f\x3d\x9d\xa9\xd5\xd7\x9d\xbd\xe8\x29\xca\x51\x4a\x97\xfb\x6c\xe4\x14\x9f\x05\xe8\x45\x20\x25\x94\x1f\x7b\x1a\x12\x68\xab\x5b\xfa\xa1\x0d\x55\x1d\xe0\x44\xab\x4d\x75\xa2\xfc\xc7\x40\x06\x26\x6a\xa3\xfc\x8b\x5a\x4e\x03\xc5\x3f\xd5\x32\xeb\x28\xfd\x46\xe7\x35\x50\xfa\xa9\x4a\x17\x7c\x4a\xd6\x07\xcf\x24\x62\x84\x16\xd3\xa3\x59\x67\xbc\x25\xa1\x02\x8d\x38\x85\x2b\xe9\x98\x81\x30\x40\x85\xe6\x94\x38\x7e\x56\xd0\x10\x25\x9f\xff\x10\x20\x96\x71\xd8\xb7\x45\xf7\xb4\xae\x50\xcd\xd9\xda\xa6\x14\xbf\x24\x5a\x19\x41\x35\x53\x2d\x2a\x95\xae\x95\x71\x16\xd5\x86\x10\x75\x6b\xac\xc4\xc8\x0a\xcb\x79\xfe\x33\x07\x1f\xe8\xc1\x1b\xef\x15\x12\xe2\xc0\x60\x25\xcc\xf3\x5b\xcc\x1d\xf3\xb9\xdb\x80\xb3\x15\xf1\xb9\x06\x2c\x33\xdd\xa3\x64\x6c\x2d\xc9\x79\xe7\x36\x24\xed\x66\x6a\xf8\xd5\x3c\x50\x1b\xcc\x30\xe9\x41\x4d\xad\xd5\xa9\x30\x33\xc8\x0c\x84\xd9\x78\xba\x1d\xac\x07\x33\x3d\xcf\x9d\x60\x64\x3a\xf8\xdb\x55\xb6\x7c\xf4\x99\x41\x92\xc1\x51\x82\x7c\xf4\x21\x01\x6b\x49\x96\xfc\x5e\x81\x2d\xc0\xf2\xa8\x2c\x72\x38\x3b\xa4\x9f\x71\x64\x1e\x3f\x22\x5e\x30\x20\x3d\xd5\xed\x1c\xb2\xcc\x35\x5d\x65\xa4\xe8\x2a\x19\x95\x24\x1b\x6a\x4f\x1d\x12\x1a\xa6\x90\x6a\x1c\xd4\x24\x7f\xc4\x9c\x90\x08\xcd\xc4\xdf\xff\x94\xa7\x97\xd2\x77\x95\xea\x8a\xa5\x44\xd7\x9b\xd4\x6c\xd8\x2a\x47\xd3\xbb\x40\x1c\x66\xe2\x60\xd3\xc7\x04\xe6\x87\x83\x72\x0f\x3b\x60\xc2\xd1\x89\x16\xa0\x9b\x5b\x7b\xd1\x71\x85\x16\x6d\x1d\x48\x52\x1c\x88\x9d\x55\x34\x7a\x31\x8f\x62\xcc\xcf\x12\xbd\x5e\x65\xe7\xc4\xb6\x73\x64\x77\xb3\x2f\x11\xda\x15\xa7\xa9\x2d\xd6\x26\xe0\xdc\xd2\x4b\x36\xc2\xb3\x19\x0e\xd8\xa1\x9f\xf8\x27\x98\xa6\xa3\xf2\xcc\x74\xaf\x97\xa7\x27\x8e\x55\xd8\xfe\x24\xe5\x69\x0a\x62\x97\x7e\x0d\x80\x24\x7b\xa2\x7a\xea\x64\x19\x90\xe4\x08\xc7\xb3\xc3\xf4\xc4\x79\x1f\x88\x40\x02\xd6\xec\xd2\x82\x60\x11\x1e\xfa\x4b\xe7\x87\x80\x6f\x3c\xfe\x85\xb3\x5c\xfa\x6c\xc9\x8c\xaf\x53\x52\x0d\xb6\xee\xcf\xa7\x12\xfa\x58\xbb\x1f\x1b\xd2\xbf\x65\xa5\x69\xe1\x70\x22\xfd\xc6\x94\x6e\x58\xc6\x8f\xbc\xbf\x65\x8f\x3c\x6d\xd4\x1b\xb9\xec\x77\x4f\x78\xb9\x89\xee\xb8\x6e\xf0\x3b\xdd\xf0\xfe\x6c\x57\x8f\x66\xe8\xe7\x9f\x37\x7f\x7b\x78\xc7\x45\x0f\xef\x3f\xf8\xf5\xd7\xbb\xc1\x28\x98\xfb\x74\x87\x84\x78\x5b\x84\x3a\xb4\xad\x3f\x84\xea\x6c\xb4\x45\x36\x36\x1c\xe1\x94\x84\xb8\x13\xbb\x70\x17\xe5\x6d\x6c\x00\xef\xa8\xa7\x0f\xb2\xb1\x51\x3a\x7b\x45\x74\x23\x13\xc9\xb5\x9b\x63\xcd\xbf\x69\x15\x89\xef\x57\xe8\x05\x78\x9b\xb5\x78\x09\x41\x25\xa2\x23\xfd\x7b\x21\xec\xb5\xf5\x75\xa2\x98\x9c\xab\x27\x87\x9b\x93\x2b\x68\x9a\x87\xb0\x12\xef\x22\x0a\x9b\xb6\x6d\x6f\xd1\x8d\x4d\x67\x38\x51\xf2\x77\xfc\x3b\x2d\x3c\x16\xf1\xc2\x89\x6d\x6f\x71\xc0\x08\xff\xb3\xc3\x4d\x87\x6e\x4c\x9c\xe1\xa4\x19\xfb\xa2\x10\xef\xc9\x05\xca\x8a\x2b\x0c\x55\x66\xa3\xc3\x89\xeb\xba\x5e\x0d\x62\x1c\x09\x2a\xbe\xe1\xd8\x96\xe7\x78\x1b\x85\x93\x8c\xe4\x6f\xd1\x23\xbd\x22\xd9\xef\xc9\x9f\x5b\xf5\xc5\xcb\xaa\xf3\xe3\x63\x14\xeb\x15\x6c\x6c\xd8\x7c\xe5\xdc\xcd\xe2\x73\x03\x08\xcf\x70\xcb\x4d\x85\x91\xf2\x9b\x24\xc7\xba\x18\x05\xf3\x22\xc0\x62\x94\x1e\x65\x53\x15\x82\x3a\x11\x56\x26\x3c\x61\x67\xee\x53\x47\xd8\xb4\xcd\xa2\x24\x2c\x4b\x10\x11\x07\x0d\xd9\x10\x65\x2e\xf2\xb2\x51\x2d\x17\xbc\x6c\x54\xd4\xb6\xc1\xcf\x5c\x9d\xa0\xf2\x53\xd3\x81\x30\x58\x8c\xf0\x19\x62\x20\x46\x85\xac\x0d\xcb\xb6\x6f\x6e\xea\x69\x43\x8b\x93\x8e\xd9\x1a\xb5\xc7\xa2\x64\xbc\x46\x49\x6c\xe8\x67\x4f\xd4\x0e\xd7\xa8\x3d\x12\x25\x97\xc6\x92\x47\x0c\x31\xfb\xe6\xe6\x42\xfe\x39\x95\x7f\x4c\xd5\xe7\x99\xe1\xda\x20\xac\x53\x8b\x20\x15\x3e\x8a\x32\x90\x39\xc2\x15\xe6\x28\x58\x2c\x51\x02\x63\xfb\x6f\xe3\xf2\x95\x84\xb9\x0c\xa8\x9b\x00\x76\x31\x3f\x76\xcf\x4d\xcd\xea\xe6\xe6\x45\x73\xd5\x79\xf1\x03\x6a\xeb\x35\x47\x2b\x47\xfc\x16\xdd\x2e\xf9\x5e\xc6\x36\x0c\x27\xf6\xd6\xae\xc8\x13\x25\x72\x1b\x16\x5d\xec\x85\xa8\x17\x8b\x2e\xd4\x78\xf1\x19\xc2\xbc\x05\xbb\x22\x7d\xd5\x0f\x5f\xa2\x74\x9a\x49\x2b\x5a\xe2\xaa\x91\xf0\xee\xb0\x93\xd4\xc6\x27\x4a\xce\x32\x69\xa2\xc7\x0b\x94\xa9\x47\xac\x4c\x7d\xcd\x10\xb1\x1d\x1f\x9d\x17\xc9\x8e\x48\xca\x6d\x38\xe9\x1d\x72\xa8\x86\x5c\xed\x53\x0c\x7b\x2b\x42\x0b\x99\xe7\x88\x2f\x01\xc0\x23\x65\xf8\x2b\x34\x69\xa7\x99\x8b\x88\x51\xf6\x5f\xde\xc8\x84\x7a\x9e\xc3\x40\x46\xb2\x52\x71\x3e\x13\xce\xd5\x06\x24\x51\x4a\xd4\x94\x5c\x38\x04\x02\x12\x3b\x41\xaf\x94\xff\xb5\x4f\x53\x4c\xcb\xfb\xd4\xd5\x0a\x1e\xed\x71\x4b\xb2\x79\xbc\xa2\xc6\x53\x42\x9a\x55\x2e\x56\xf1\x93\x7a\x8e\x58\x87\x96\x56\x53\xc5\x2a\x7a\x57\x31\xe3\x91\xfc\x28\x26\xce\xc4\xc4\xf1\x88\x92\x0b\x31\x79\x3c\x0a\x48\xcc\xbb\x3c\x5d\xc9\xc2\x4e\xb3\x96\x01\x65\xe2\x52\x20\x22\x9a\x10\x52\xb6\xfb\x7c\xfa\xa5\xaf\xf5\x82\x99\xb8\xca\x44\xe8\x51\xfe\xcf\xc4\x2e\xdc\xc0\x78\x13\xc8\x5c\x1f\x1d\x51\x48\xf4\xb8\x03\xfd\x91\xa8\x99\x55\x38\x92\xe3\x0c\xa4\x57\x0a\x22\x83\x4a\x4a\xa6\xf9\xc8\x48\x14\x22\x74\x9a\xc1\x95\x50\xc7\xba\x34\xed\xcf\x62\x73\x53\x18\xdb\x7f\x1f\x4e\xca\xa1\x9e\x64\x72\xbf\x56\x76\xf0\x11\x93\x8c\x0f\x71\x45\xb6\xd8\xa5\x81\x4b\xc4\x84\xf7\x28\x6d\x7b\x2b\x20\xca\x4f\x81\xf0\x0e\x50\x45\xf2\x0c\x98\xd8\x36\x99\xed\x90\xdc\x86\xc7\x6b\x90\xbe\x4b\x41\xbb\xb6\xd7\x26\xc6\x2f\x4d\xd3\xad\x96\xa7\x62\xa3\xe9\x5d\xcb\x27\x56\x21\x42\x8f\xe5\xec\x1b\x9b\x7e\x59\x49\xdd\xe5\xa7\x3d\xdf\xe7\x54\x6d\xfd\x4b\x06\x6c\x63\x53\x44\x17\x82\xb7\x5d\xb8\x5e\xc3\x9e\x5a\x10\x51\xbd\xd0\x9c\x07\x47\x3e\xef\x28\x29\x71\x80\xa3\x69\x32\x12\xa2\x55\x1b\x24\x3c\x85\x13\x59\x6f\x02\x3e\xff\xb3\xd9\x80\xae\x24\x21\x57\x19\x08\x6b\xb6\x84\x53\x91\xe3\xac\x1d\x44\x56\x6f\x1f\xa2\xf7\x4d\xa6\x37\x4c\xd2\xdc\x30\x32\x16\x31\xbe\x94\x1b\xc7\x13\x9b\xc6\xcf\x25\xea\xed\x75\x53\x7e\xb1\x2f\x7a\x76\x0e\x76\x13\x79\xf3\xab\xee\x1a\xdc\xde\x35\xe2\x1d\x97\xea\x2d\x83\xe5\x96\xe1\xf8\x8f\x02\x59\x55\x50\x0f\xe1\x39\xb2\x5e\x57\x6d\x16\x51\x3f\x13\xfb\x25\x2b\xf6\x1e\x67\x9f\xbc\x31\xf8\xfc\xcf\xa4\x06\xc1\x40\x40\xdc\xe7\xff\xda\x77\xef\xaa\x24\x0e\x7e\x9f\xff\xab\x60\xeb\x49\xf2\x2c\xbe\x7c\x09\x89\xc3\xba\xa4\xa3\x8a\x73\x3e\xda\xcb\xba\x1e\xca\x68\x6e\xab\xb8\x54\xa6\x9b\xcc\xd4\x74\x67\x46\x63\x30\x48\x50\xf9\x04\x65\x7c\x2c\x1b\x76\xbe\x8d\x92\xa9\x9b\xb8\x16\x4e\xaa\x25\x51\xaa\x21\x62\xb6\x42\xb3\x23\xe1\x50\x74\xc4\x28\x84\x98\x53\xf4\x2c\x12\x45\xe7\x67\x9d\x1b\x40\xc6\xef\x82\x27\xff\x24\x9c\xc1\x75\x4a\x3b\x96\x51\xc0\x1b\xb3\x0b\x2a\xb3\x13\x7b\x2b\x10\xb3\xab\x63\x4f\x20\xa9\x6d\x31\xc5\x83\xcc\x3d\xc8\x84\xb4\xfd\x20\xfb\xdd\xba\x71\xbb\xa5\xed\x3e\x7a\x92\xc1\x99\x3c\xcf\x73\x1b\x50\x51\xd3\xfe\xdd\xba\x19\xad\xa8\x77\xa5\xaa\x89\x39\xec\xff\x25\x6b\xaa\xf7\x4a\xb1\xa8\xc7\x99\x5e\x46\xb5\xae\x8d\x75\x16\xf3\x7d\x65\x24\xbd\x46\xe4\x94\xfb\x4e\x8e\x3b\x87\xe7\x5d\x83\xd6\xe4\x87\x6a\xf2\x33\xd6\xe4\x67\x52\xd0\x9d\xaa\xd0\x98\x53\x9e\x89\xa0\x3c\x93\x1c\x64\x24\xb5\x8a\x0e\x53\x63\x56\xbb\x6a\x46\x9c\x44\x5f\xf3\x9a\x7c\x26\xc5\x79\x2f\x7e\xf0\x0d\x5d\x0c\x41\xfb\xb3\x11\xb3\x2e\xa9\x9e\x28\x26\x7e\x08\x20\xbc\xce\x5c\x94\x18\xd8\xae\x52\x43\x86\x5c\x38\x4c\x74\x41\x75\xdb\xb8\x6c\xbb\x68\x98\xe4\xcd\x88\xe6\xd5\xdb\x6a\xb5\x91\x10\x17\x72\x36\x7e\x53\xb5\x6d\xd8\xed\x16\xa7\xae\xe4\x51\x4a\x32\x1e\xb8\x11\xba\xc8\x1a\xaa\xcf\x3e\x7a\x9d\xd5\x8e\x1b\x66\x4b\x59\x0f\x08\x07\x2c\x58\x11\xdc\x06\xc4\xb3\x0a\x1e\x09\x8a\x2a\x5a\x26\x92\xd2\xda\xc2\x97\x6e\x0f\x67\xf9\xc4\x8f\xe2\x92\xaf\x7c\x77\x2b\x2c\xbb\xca\x60\x37\x13\xef\xaf\x02\xd3\xde\x67\x85\x02\x89\xd0\x23\x88\x92\x93\xf7\x3e\x8d\x84\xd5\x49\x0e\x1f\x7a\xe4\x82\x45\xf9\x17\xf8\xea\x82\xd0\xf2\xe5\xe1\x59\x07\x5b\xf5\x36\x83\x0f\x99\xb4\x39\x58\xa7\xd9\xa3\xab\xc5\x94\x94\x72\xc7\xaf\xdd\xad\x7e\x91\xad\x3e\x6d\x4f\x65\x2f\x09\xad\x1c\xde\x64\x6e\x15\x1a\x0d\x26\x68\x9b\x22\xa6\x39\x46\x60\x8a\x81\xb0\xb7\xcc\xc7\x3f\x53\x1b\xfd\xa9\xe8\xd2\x86\x4f\x45\x9f\x8f\xfd\xf0\x2d\x5e\x62\x9f\x59\x39\xbc\x30\x4b\x0f\xf5\x85\xb1\xe0\x20\x19\xbf\x1e\x4e\x6a\x27\x2f\x65\x08\x73\xf6\x43\x45\x2b\xa3\x9c\x3b\xbe\x2e\x4e\xeb\x3b\xeb\xf3\xc7\xc5\xa5\x4e\xe2\x66\x50\x3d\x98\x25\xa2\x8a\xe3\xd9\xae\xb5\xf4\x29\x83\xc0\xe6\xb7\xd4\xe1\x04\xa8\x2b\x82\x32\xd6\x90\x9d\x14\x1a\x8a\x90\xb8\x41\xce\xb1\xef\x73\xff\x5c\x57\x4c\xe3\xba\x32\xe0\xda\x35\xb7\x7f\xd0\x3c\xa9\x04\xe0\x56\x0d\x72\x4e\x09\x13\x25\x47\xc9\x4c\x00\xc9\xda\x6d\x67\x46\x80\x64\x6b\x03\x24\x13\x00\xf9\xd8\x79\xe0\x88\xc3\xa1\xd4\xb7\x99\x66\xc8\xda\xbb\xf4\x03\x16\x5f\x55\x88\xb0\x01\x4d\x53\xf4\x42\x1d\x2d\xb8\xf6\x22\xc8\xec\xdc\xf4\x62\x91\xa2\xcf\x5d\xc5\x85\xd9\x4a\xe6\x66\x1d\x1a\x70\xe0\xad\x87\xa4\x9d\x5c\x71\x71\x9b\x4c\xf4\xb1\x44\x0a\xfa\x1d\x88\xc3\x28\x13\x34\xda\xcb\x75\xa4\x20\x71\x49\xa0\xe2\x62\x54\x2c\x50\x5a\x15\x43\xe8\x65\xf8\x96\x2e\x2a\x0d\x6e\xda\xf6\x75\x75\x19\x31\x24\x6e\xb2\x31\x01\xe2\x12\x08\xdc\x00\x32\x37\xdb\x98\x80\xe7\x4e\xa4\x4b\xe8\x66\xd1\xb4\x5a\x10\x3c\xd7\xdb\x98\x88\x27\x3d\x6f\x2d\x58\xae\x9a\xea\xb5\x74\x5a\x7d\xfb\x29\x96\x7b\xa6\xb9\x1b\x5a\x4b\x34\x53\x1b\xe3\x53\x06\x33\xe1\x0b\xfd\x1f\x0b\x19\xea\x75\xec\x82\x2e\xf4\xc7\x6d\xf4\x57\x7e\x4f\x75\x85\x25\xfa\x41\xdf\x6a\x8a\x3b\x7e\xf5\xc6\xa7\xae\x5f\xe5\x79\x5d\x39\x95\x1b\x3b\xa5\xd5\x32\xf3\xbe\xbd\x65\xbe\xa9\x70\x7b\xba\x5a\xc6\x98\xa1\x08\x51\x4f\xb0\x76\xe2\xa5\xce\xab\x9c\x18\x4f\x62\x22\x0e\x0c\xe2\x35\x4f\x28\xa5\xf0\x00\x9c\x6c\xe8\x01\xb9\x54\x74\x4b\x5c\x5a\xc8\x3c\xc4\x73\xb0\x18\x5c\xe6\xd2\x62\x78\x9e\xf8\x8e\x81\xe3\xdc\x25\x67\x2b\x04\xea\x6d\xf3\x2f\x6c\x2b\xf4\xd3\xe2\x87\xb4\x42\x88\x67\x6e\x5a\x11\x3b\x48\x8e\xd6\x6b\xef\xbc\x99\x46\xcb\xa0\x40\xcb\x4c\xa0\x65\x22\xd1\x72\x03\xcd\x86\xc4\x56\xf1\xd9\x63\xd1\x26\x84\xee\x8c\x22\x21\xb0\x21\x10\x43\xe9\x29\x58\x0f\x23\x94\xcb\xbf\x18\x05\xd4\x4f\xe7\x3b\x7e\x8a\x51\x21\x40\xbb\x16\xae\x16\x9c\xeb\x38\x4a\xb0\xf3\xcb\xfd\xfb\xbc\x97\x6c\x91\x38\xbf\xe5\x80\x93\x50\xa7\x3f\xf8\x59\xa7\x4f\x1e\xe6\x39\x84\xb6\x72\xc9\x29\x5b\x19\xcd\x38\xa8\xff\x9f\xc1\x52\xfc\x1a\xa4\x18\x2f\x84\xd7\xb9\xb9\x7f\x8e\x07\xfe\x60\x9a\x9d\xb4\x1c\xd3\xf9\xc9\xe0\xe8\x68\x67\x67\xaf\xcf\x39\x1d\x23\x24\x4e\xef\xc9\x46\x2b\x8e\xe9\xe4\x3d\x28\xe4\x13\x6f\x41\x2f\x5e\x09\xbd\x58\x42\xcf\x86\xa0\x8a\x2b\xfb\x09\xc7\x94\xcc\x73\xd1\x3f\x0a\x55\x5e\x7e\x1f\xaa\x04\x7f\x19\xaa\xc4\x7f\x0d\xaa\x3c\xbc\xff\xab\x11\x55\x1e\xfe\x3c\xee\x45\x95\x28\xf9\x57\x43\x94\x4e\x6e\xfa\xb1\x1f\xbe\x4a\xf0\xab\x59\x79\x5b\xf0\xbc\x95\x4f\x19\x32\x4e\x84\x7c\xa1\x4e\xda\xec\x66\xe6\x21\x2a\xde\xed\x80\x69\x36\x95\x73\x1b\xfc\xa2\xc3\xea\x92\x25\xd2\x10\x6d\x0a\xbf\x6a\x52\xf2\x28\xd1\x53\xdd\x2f\xed\x9b\x1b\x9d\x2c\x04\x76\xea\xa6\x69\x97\x35\xe5\xc3\x89\x99\xf7\xa2\x39\x08\xf9\xc6\x44\xb0\x5f\x91\xb7\xfe\x6d\xc8\x47\x9e\x07\xb4\xcd\x24\x81\x6f\x6a\xa4\xb8\x5c\xc8\x33\x4b\x5f\x4c\xd2\x9e\xb2\xdb\xec\x00\xfb\xa5\xa2\x3f\xcc\x3c\x37\xf5\xd0\xd8\x86\x58\x7c\x4c\x6c\x08\x4d\xb5\xef\x8c\x73\x58\x7a\xae\x3c\x38\x66\x9e\x49\xc2\x55\x97\xdf\x0e\x0c\x4f\x64\x7f\x24\xa6\x44\x6a\xd9\x3d\xea\xe7\x94\x5f\x96\xe7\x9d\x67\x99\x90\xae\x2c\x3d\x2d\x95\x39\xf7\xdc\x73\x4f\x88\x73\xce\xbd\xdf\xad\x9b\xa1\xf5\xa7\x3b\xf7\x64\x78\x38\xcf\xed\xbb\xf2\x0f\x22\xaf\xa1\xc9\x13\xa1\x9d\x8a\x01\x4f\xc5\x81\x21\x5a\x78\xa0\xeb\xd7\xab\x04\xf2\x9a\x6d\xe7\x10\x21\x21\x4e\x1a\x59\x7f\x76\x7c\x8a\x37\xa0\xaf\x19\x4a\x6c\xa9\x82\xd0\xd2\x16\x8a\x90\x9e\x01\x2f\xc6\x6c\x78\x95\x71\x1c\x27\xb6\x6d\x52\x1b\xb2\xe1\xa4\x6b\x7e\xf2\x3a\x63\x9c\xc8\xc9\xca\x89\x94\xd4\x74\xce\xd1\xd2\x00\xa4\x62\x94\xf5\x01\x27\x7c\x5a\x20\x60\x18\x70\x82\xf9\x9d\x13\x14\x8f\x65\xdf\x30\xc3\xe9\xea\xa5\xca\xdc\xfa\x4a\x97\x08\x5d\x0c\x28\x97\x23\xb4\xbf\x17\x1a\x46\x14\xe3\xe0\x69\x43\x27\x33\xc0\x60\xbd\x52\xb9\x0d\x57\xdf\x8d\xeb\x4a\x61\x91\x54\x15\x16\x9f\x10\x3a\x95\x4e\xe5\x9c\x35\x31\xa8\x3a\x32\xa5\xa3\xf8\x4a\xc8\xc0\x4a\x9f\x71\x2b\xd7\xa8\xde\x46\x43\x97\xd1\x0c\xf0\xca\x27\x2d\xf7\x18\xac\xda\xb8\xb5\x9e\xec\x3c\x37\xae\x8b\x09\x6b\x2b\x15\x3b\x36\xe7\xb1\x67\x94\x48\xa8\x59\x1c\x56\x4e\x82\xca\x22\x71\x24\xd3\xe4\x96\x19\xb1\x67\xee\xf1\x41\x60\x1b\xd4\xeb\xf7\xc4\xde\x2a\x87\x53\xbe\x27\x38\x29\x3a\x2e\x66\xce\x2f\x77\xa6\x69\xc9\xb6\xa8\x0d\xd5\xc2\x1b\xdd\x85\xc5\xc8\x7c\x75\x60\xd4\x6b\x19\x80\x90\x2b\xa5\xc0\x0b\xaf\x4b\xea\x69\xd0\x50\x7b\x2b\x1c\x97\x7a\x13\xfe\x41\xed\xfc\x51\x43\x89\x0c\x17\x9a\x6a\x0a\x62\xef\x32\x54\xf1\xa5\x2e\x18\x9b\x81\x3f\x10\x26\x5a\x43\xce\x65\x0d\x02\xb2\x10\xbe\x23\x85\x23\x74\x36\xc7\xd2\xad\xf8\x80\x91\x53\x9c\x0c\x02\x3f\x49\x08\x1b\x4c\xa5\xeb\x75\xbc\x58\xb2\xab\x81\x34\xea\xbc\x23\x8d\x40\x1b\x7d\x4f\xbe\xb3\x6f\x9c\x84\x6b\xf5\xdc\x50\xd6\x2f\x4f\x64\x75\x8c\x62\xc9\xe8\x8c\xbc\xb1\x7d\xf7\x6e\x25\x71\xa2\x12\x2b\x34\xbc\x38\x7d\x24\xea\x8a\x35\x13\xa6\x6f\x30\xb1\x3b\x2c\xb1\x24\x0b\xbf\xf4\x03\x9c\x3e\xea\xdd\x74\x1c\x79\x46\x02\x9e\x9c\x47\x87\x19\xba\xf2\x80\x8e\x70\x12\x0a\x5b\xf3\x88\xe1\x05\xd0\x51\x8a\x97\x3e\xf5\x19\xa1\x40\x47\x8c\xfa\x51\x1c\x25\x27\xa2\xe7\x53\xcf\xed\xb6\x81\xac\xb2\x82\x5e\xa9\xd5\x42\x4a\x99\x85\x57\x11\xcf\xb4\x9e\x43\x69\x17\xd3\x8a\xe5\x23\x42\x5e\x6d\x46\x89\x1e\x80\xba\x74\x63\x02\xd8\xc5\x1b\x13\x48\xdc\x9a\xe8\xa1\x10\x3a\x00\x75\x3d\xb3\x74\x82\x73\x7d\x47\x26\xae\xd6\xc0\xfb\x95\x3a\x9c\x10\xb8\x44\x3c\x88\xaa\x2b\x93\xe7\x12\xc1\x93\xa6\x2e\xd1\x57\xa6\x99\xb2\x4e\x4e\x18\xc4\x9c\x97\x55\x57\xa6\xa5\x86\x4a\x0a\x59\x09\x95\x65\x4b\x68\xf5\x5e\x08\x53\xa5\x8f\x63\x5d\x64\xd3\xde\x0a\xd1\x29\x3f\xcf\xd2\x8d\x09\x78\x1b\x13\x98\x40\x06\x22\x5e\xb3\x4a\x5f\x82\x07\xbc\xaf\x78\x43\xe7\xc0\xb9\xd4\x74\x48\x61\xae\x47\x96\x55\x4e\xc7\xfd\x04\xce\x01\xab\x07\x56\xd1\xa7\xbc\x54\x9c\xc3\x5c\x92\x81\xcb\xe2\x16\x59\x1e\x2a\x39\x3c\x36\x10\x07\xd5\xe6\x85\x87\xd4\x3d\xca\xfa\xdd\x82\x02\x8d\x1c\x0b\x2c\x71\x8b\xb2\xfe\xb4\x40\x62\xa9\xc3\x80\x23\x9b\x43\x41\x23\x98\x73\xe9\xf5\xd9\x37\x56\x9a\xbe\x36\x36\x9d\xaf\x6c\xda\x86\xed\xb5\x86\x8e\x8c\xed\xdb\xdf\x3a\x74\xed\x06\x38\x49\x70\x2a\x7c\x4a\xec\x48\x1a\x73\x1b\x63\xc4\x97\xbd\x55\xdb\x8f\xb6\x11\x7a\x4c\xc1\x72\xad\x52\xe1\x89\x9f\x0a\x85\xb0\xec\xee\xdd\xe2\xa7\x22\x90\x77\xef\xaa\x6b\x9b\x24\x49\x32\x71\xcb\x47\xaf\xfa\xc7\x55\x3d\x07\xca\xf1\x9c\x2a\xdb\x05\xf5\x21\x54\x8e\x6d\xe7\x2c\xb7\xe1\xa5\xf1\x8e\x75\x81\x51\x84\x18\x83\x6d\x7e\x5e\xf1\x81\xdf\xb5\x20\x42\x17\x14\x26\xda\x4f\xd1\x5b\xcf\xa0\x3b\x2e\xcb\xde\xb3\x80\x35\x26\xa9\x1d\x7f\x58\x5a\x53\x7a\x8b\x8e\xe4\x75\x6f\xaf\xde\x4e\x95\x64\x51\x97\x3d\xaa\xea\x57\x57\x8f\x8d\xb3\x47\x35\x41\x3c\x1e\x65\xc9\x79\x94\x46\x0c\x87\x9d\x17\xde\x03\x84\x47\xc2\x83\x91\x3c\x94\x64\x01\x6f\x5c\xc0\x39\x69\x1e\x4d\x95\x0a\x4c\x68\x5e\xe7\x39\x1c\xf6\x10\xa7\x3d\x0f\x89\x47\xd9\x6b\x35\x92\xba\xa1\xaf\x1e\x9f\xf3\xd6\xe3\xdc\x82\xf0\x30\x97\x3a\x3a\x7c\xf3\xb1\x64\x40\x77\x7a\xee\x6b\x87\x9c\x4f\x50\x8b\x40\x85\x71\x20\x5f\x3d\x7e\x78\x08\xab\x41\x51\xff\xac\x7b\x3b\xa9\x06\x68\x69\x76\xd8\xac\xbc\x42\xd9\x4c\x8f\x1f\x8f\xd4\x57\x65\x4e\x15\xf8\x17\x33\x1b\xc9\x0f\x35\x41\x56\x00\x53\x70\xe4\x4f\xfa\x18\xbb\xa2\x2b\x56\xe9\x82\x36\x41\x26\xcc\x8c\x0f\x7a\x6e\xec\x75\xa5\x3d\xd8\x37\x62\xfa\x81\x67\xd0\xb0\xa0\xeb\xa1\x54\x65\x7d\x2b\xc2\x93\xda\xe3\x17\x01\x66\x6f\xd5\xb9\xc0\x14\x3d\xf1\x1a\x6c\x34\x11\xef\x4e\x1a\xae\xb9\x50\x3b\x80\x02\x80\x1a\x70\x4d\xe6\xb0\xce\x78\xe7\xf0\xaa\x13\x79\xaa\x93\x64\x85\xf4\xfe\x7b\x26\x29\xc2\x92\x90\x86\x07\x15\xa5\x48\xf2\xd7\x4c\x57\x86\xfa\x59\x35\x69\x1b\x9e\x7b\x6e\x84\x5e\x79\x60\x1d\x1d\xbf\xdd\x7f\xf9\xd4\x82\x5d\x66\xc3\x6b\x21\x71\xe1\xa9\x2f\xdf\x1d\x3e\xde\x7b\x6b\x41\x4c\x79\xaa\x50\x3b\x79\xf4\xda\xfb\xdd\xfa\xdb\x3d\x93\x81\x68\x09\x99\x42\x99\xa0\x01\xbb\xe2\xac\x26\x4c\x3d\xcc\x49\x61\x99\x38\x9f\x05\x80\x76\xbb\x9e\x4b\x8c\x4d\x96\xfa\x09\x25\x1b\xf0\x19\xce\x3c\x94\xe8\x55\xc7\x35\x9a\x92\x18\x76\x5f\xd2\xde\x7d\x49\x63\xf7\xe9\x7b\xc4\x3b\xcf\x35\x4e\xa8\xbe\x40\xac\x7d\x19\x7b\x84\x5e\x7b\xae\x02\xe0\xef\xd6\xdf\xb6\xfe\x51\xd0\x7b\xdf\xb3\xa1\xdf\x64\x98\x5e\x35\x76\xf5\x87\x4e\xa4\x7f\xef\x75\xea\x1a\x4a\xd8\x3c\x32\x4d\x5d\xa0\x6b\x09\xe4\x2a\x68\x09\xa8\x35\x41\x14\x45\xe8\x1d\x05\x06\xc4\xee\x12\x2b\x3d\x33\x52\x9b\x08\x7d\xe0\x44\xf8\xd8\xce\xe1\x8b\xe7\x9e\x37\x8d\xe0\x0c\x86\x1a\xd6\x73\x3f\xc9\x7c\x7a\x25\xdc\xee\xdd\x9f\x80\xb7\xe9\xdc\x9f\xe4\xed\xbb\xa5\xa9\xea\x13\x3c\xa5\x45\xdd\xcd\x5f\x79\xdd\xcd\xdf\xd6\xac\x7b\xc8\x8f\x85\x6f\xe9\x74\x7b\x49\x85\x46\xcb\xc4\xb9\x3f\x16\x15\xc7\x6b\xf7\xf8\x4d\x93\x7c\x9e\x25\xf8\x5b\xba\x7b\x9e\xc5\xdf\xd4\xdf\x76\x76\x92\xa5\xec\x5b\x6a\x1e\xe1\x25\xc3\x8b\xa9\x40\xde\x5b\x0f\xf7\x55\xc0\x48\x51\xf5\x76\xfd\xbe\x24\xe7\xdf\xdc\xed\x2e\x0e\x2a\x75\x0d\xfd\x2a\x31\x45\xf1\x9f\x0d\x5f\x4d\x9c\xa1\x38\x0c\x85\x6a\xd4\xef\xd6\x8f\xd6\x9f\xc0\xe0\xc1\x98\x53\x77\x6c\xc8\x99\x88\x9c\xa4\xf1\x44\x60\x68\xc1\x24\x63\xc1\x06\xfb\xd1\xf6\x70\x4b\xe3\x3d\xc9\x9f\x26\x8a\x3f\xbd\x33\x2e\xb9\x42\x9d\xa3\xb9\x42\xf1\xe2\x31\xd1\x49\xde\xd8\xae\xd5\x2f\x79\xf4\x3a\x43\x59\xa6\xdb\xfa\x41\xa0\x66\xdc\xd7\xae\x2f\x3b\x1a\x57\x1b\x50\x7d\xdd\xa2\xd9\xde\xa2\x93\xa2\x68\xf3\x6f\xd3\x32\xf0\xce\x24\x87\xa7\x5d\xe7\x59\x84\x96\x0c\xe8\x70\x02\x5f\xbc\x82\x11\xd0\x66\x8f\x4a\x05\xe0\xab\x87\x98\xbd\x25\x25\x2d\x9b\x8e\xfc\x3b\x71\xc6\xb9\x0d\x6f\xd6\x78\xbb\x1a\x46\xe8\xa9\x7c\xa1\x90\xcf\x4d\x15\x4b\x9c\xbf\x8f\x6d\xbb\xf3\xde\x43\xa5\x1a\xcf\xa3\xaa\x3c\x22\x11\xb8\xf9\xc9\x48\x95\xe5\x28\xef\x3f\x7c\xe8\xdc\x7f\xf8\x73\x0e\x2f\x3c\x93\x37\xa1\x8a\x32\xcd\x9d\x42\x9d\x86\x56\x06\x32\xc0\x4a\xe4\xc4\x80\x88\x4e\x03\xf7\x13\x67\xf5\x1f\x31\x37\x01\xea\x12\xc0\x6e\x87\x91\xc9\x20\x42\x3b\x30\x86\x57\x0c\xc5\x94\x1f\x86\xfc\xfc\xf8\x5c\xdc\xf4\xb7\x67\x0c\x53\x2b\x87\x8f\xe5\x0b\xb2\x08\x80\x6a\xe5\xf0\x83\x09\x88\xcc\xa9\x0c\x55\xd5\x2e\x9c\xa6\xd9\xd7\x1c\xae\x72\x5c\x35\xd3\xa6\xbf\x8f\xed\x6b\xe6\x7e\xf6\x4a\x80\x3d\x0a\x48\xc2\xa2\x24\xc3\x03\x96\xd7\xf4\xb9\x60\x5c\xb0\xb4\x35\xa8\x6f\x4c\x40\x2c\xae\xd3\xbd\x24\xb9\x5a\xd9\x8d\x62\x04\x77\xea\xe6\x55\x2b\x16\x55\x54\xdb\x10\x4b\xfb\x51\x0c\x75\xa8\xd6\xd6\x06\x16\x99\xbc\x4c\x8c\x52\x1c\x90\x24\x04\xec\xb2\xd1\x22\x4a\x32\x86\x85\xea\xec\x9c\x64\xb4\x61\x8b\xb5\xf9\xa0\x50\x45\xc3\x1b\xc2\x1e\x64\xbc\xf5\x9a\x21\x8b\x17\x1d\x44\xe9\x80\x64\x6c\x40\x66\x03\x2a\x0c\x90\x6d\xa7\x3a\xea\x9b\x1b\xfd\x6b\xf3\xc1\x5a\xd5\x70\xad\x1a\x86\x9f\x7f\xd3\xd5\xe4\x18\x3b\x2b\xd2\x5a\x45\x5a\xa9\x28\xe7\x69\xa8\x28\x6c\xbf\x72\xa0\x91\xd9\x74\x44\xe0\xf1\x68\x41\x12\x36\x87\x49\xa5\xed\x22\x6d\xb3\x18\x1a\xff\xdd\x39\x32\x36\x0a\xfd\xab\x46\x0b\x3c\x45\x6e\xe1\xd1\x15\xf6\x29\xa8\x36\x6d\xdd\x62\xe8\x5f\x19\xda\x63\x91\x18\x30\x8e\x5a\x21\xf0\x70\x8b\x10\xa9\xe7\x16\xa6\x5e\x5a\x36\x8a\xd7\x11\x2a\x5f\x4d\x86\x15\xa7\x26\x17\xbf\x5b\x1b\x1b\xe2\xe0\xa0\xad\xf7\x10\x21\x24\x49\x5c\x1f\xed\x25\x70\x96\xa0\x89\x0d\x87\x09\xb2\xd0\xef\xc3\x8d\x3f\x6d\xf4\xc7\x1f\xe1\x1f\x7f\x84\xb6\xb3\xa5\xbf\x2c\xf1\x40\x07\x96\x25\x5e\x20\x89\xcb\x39\x76\x03\x70\x45\x14\xbb\x85\x8c\x94\x2c\x54\x88\x03\x17\x89\x66\x3f\xdf\xa0\xdf\x37\x86\x7f\xfe\xf1\x47\x78\xbd\x99\x3b\x5b\xf2\xaf\x6d\x6f\x59\x36\x10\xbb\x79\x34\x05\x75\xf9\x50\xa0\x85\xf7\x77\xef\x16\xc4\x36\x50\x92\xec\x76\xc1\xf2\x48\xaa\x97\x9d\xd4\x8d\xd5\xeb\x35\xaa\xe7\x50\xbb\xde\xa4\xd2\x93\x3c\x65\xaa\x59\x93\x56\xd6\xc4\x70\x99\xac\xee\xeb\x17\x1e\x8a\x10\x86\xa0\x90\xc6\x43\x65\x88\xfa\x06\xf8\xc2\x43\xf5\x01\x08\xf9\x7c\xfb\xc0\xfb\xab\xfa\x1b\xe7\xad\x23\xb2\x79\x34\x1a\x9a\x1e\xcb\xaa\x39\x24\x46\x5a\xd4\x7c\x0b\xa9\x4b\xb4\xc6\x8f\xb4\x03\xd4\xb7\x55\x1c\xfc\x1d\x46\x7f\x5a\xa6\x43\xc3\x1a\x8f\xac\x5c\x79\x62\x4d\xdc\xe2\x04\x99\x51\x84\xed\xf2\xc5\xf5\x31\x9a\xe0\xfb\x3f\x25\x76\x0e\x24\x72\xa3\x1a\x7a\x97\x3b\xc2\xe2\x88\x7d\xfd\x20\xb7\xb7\x86\x5b\x16\x34\xd3\x37\x7b\xd2\x6b\xa9\xc7\x1d\x85\x9c\x5b\xa6\xd7\x53\x7f\x1f\x81\xd8\x29\x13\x68\x65\x7d\xbe\x31\x6c\xa3\x2d\x0b\x2c\x34\xfa\x89\xef\xa6\xf2\x3f\x08\xd6\xa1\x26\x0a\x66\x02\x43\x76\x80\x2a\x47\x83\xc9\x7a\xfb\x9b\x44\x88\xda\x0d\xb1\x67\x52\xdf\x92\x49\x6b\x93\x26\xf5\x4d\x5a\x4f\xec\x49\xef\xcf\x5a\x99\xbb\x4e\x81\x35\xcb\xac\x5f\xcc\xc0\x1e\x77\x97\x34\xf2\xd2\x82\xa5\x2c\x28\x52\x7f\x7d\x09\x68\x71\xcc\x54\xc2\x3e\x0b\x97\xaf\xb6\x43\x23\x74\xcd\x4f\x24\x87\x53\x02\xa5\xf0\x04\xd6\xd8\xb2\x41\x1c\x50\x95\xe4\x89\xc8\x99\x58\x36\x84\xfe\x55\x3d\xbd\xcc\xe2\x67\x7d\x2b\x6f\x52\xb6\x29\xce\x74\x53\x81\xb2\x8c\x3c\xbe\x3b\xca\x54\x9b\x8a\xe3\x48\x95\x4d\x22\xd4\x05\x82\xb1\x5d\x98\x02\x77\x17\x12\xe5\x72\x61\x21\x64\x65\xc9\x69\x42\x2e\x92\x81\xf4\x83\x6e\xe7\x90\x75\xb0\x0b\xe2\x91\x74\x6c\x6f\x59\x96\x3e\xf7\x61\xc2\x59\x92\xad\xca\xbe\x1c\x8d\xc7\x2a\x6c\x46\xa5\x4c\xbb\x90\x2e\x53\x4d\x2c\xc2\x6d\x78\x26\x0a\xca\xf3\x9a\x6a\xd2\xad\xde\xc7\xbc\x77\xda\xd7\x75\xb3\x00\xbe\xdf\x2c\x20\xf2\x69\x0e\x51\x1f\xd3\x64\xe8\x5a\x4f\xe9\x54\x70\x30\x7e\xe7\x29\x30\x56\xaf\x20\x77\xef\xaa\x2f\xad\x93\x6f\x7d\xb6\xea\x0f\x1b\x25\xbf\xf8\xf7\xe1\x64\x8b\x33\x38\xd6\xd0\x7a\xd4\xe2\x69\x92\x0a\x5d\x8c\x22\xb4\xc7\xcf\x00\xfe\x21\x7d\xa5\xd9\x39\xa4\xc6\x99\xc8\x50\x14\x56\x43\x3c\xeb\x45\x48\x32\x6c\x86\xeb\xb5\x35\x34\x04\x86\x88\x22\xcd\x2e\xde\xaa\x46\xe8\x5f\x99\xca\x1f\x77\x95\xe7\xdb\xcc\x54\xc1\xe9\x1c\x92\xd8\x78\xb7\xaa\x22\xf7\x96\x49\x63\x48\x36\x58\x6c\x3f\x43\x11\x9f\x17\x51\x36\x47\x3d\x12\x92\xdc\xce\x61\x16\xb9\x92\x00\x8d\x15\xc5\x99\x08\xfa\x32\x91\xa4\x64\xac\x49\xc6\x58\xd3\x85\x71\x6d\xe7\x8f\xf5\xee\xee\xe3\x41\x62\xf3\x7d\x48\xd6\xd4\x18\x74\xff\x21\xfe\xf9\x27\x8e\x6a\x1b\x0f\xf1\x83\x9f\xc4\x1b\x17\x84\xf5\x8a\x5a\xea\xa1\x99\x7a\xc1\xc9\x4f\x7e\xfb\x45\x1a\xcc\xab\x76\xbf\x0a\xe7\x40\x4f\xbd\x02\x71\x22\x14\x33\x98\x94\x1c\xbf\x0d\x58\x1c\xa3\x9f\x3c\x99\x25\xcb\x6d\x4c\x60\xf2\xdb\xc3\xdf\x0c\xd2\x9e\x5f\x1f\x3e\xc0\x3f\xff\xf4\x15\x99\x56\x4f\xe6\xa1\x4f\x45\x6f\x43\x13\x5a\xa8\x52\xa6\xfb\xc7\xb0\x0b\xf7\x7e\xdd\xfc\x15\xff\x3c\x14\x40\x91\xe8\xd6\x2e\x72\xff\xe7\x07\xf8\xc1\x90\x43\xab\xb8\x50\xb6\xca\x3c\xc4\x0f\x86\x9c\xed\x2a\x6e\x9f\xad\x12\x71\x84\xba\x70\x44\x2f\xcd\x78\x88\xbe\xa2\x84\x8f\xb5\x8a\x75\xb9\x7c\x82\xe9\x85\xb6\xd0\x54\xaa\x83\x9b\xaf\x97\x82\x82\xc8\xbd\x3d\xb8\xbf\x22\xd2\x0d\x64\x01\xcf\xe1\xc4\x50\xa0\x17\x96\xfd\x50\xec\x87\xe0\x70\xf2\xd3\x1a\x40\xe4\x10\xdc\xa8\x41\x30\x87\xa5\x69\x63\x94\x56\x37\x9c\xce\x7e\xf6\x9c\x8f\x9e\x00\x61\x29\x94\xc4\xf7\xe5\xbb\x71\x21\x50\xa1\x15\x15\xfa\xa4\x52\xf4\x1e\x9f\xf3\xcd\x18\x36\x1f\xc8\xbb\x61\x91\xfe\x10\x3f\xb8\x19\xc3\xc3\xb1\x2d\xad\x4f\x75\xf2\x04\xdf\x57\xc9\x99\xeb\xa3\x1f\x3c\xf8\xec\xa9\xf5\xba\x27\xc0\x7b\x33\xb6\x41\xd9\xea\xa7\xc2\x56\x1f\x66\xae\x8f\xde\x78\xe0\xc1\x04\xd2\x8d\x89\x0d\xb1\x3b\x53\x76\x19\x35\xdb\x3b\xe5\x4c\x7d\x16\xc1\xb5\x22\x1c\x81\x26\x2c\x44\x12\x9a\x44\x50\x9d\x50\xd1\xa0\x18\x04\x49\xf2\x6a\xb4\x06\x2b\x85\xfe\xa5\x5b\x0c\x07\xe6\x55\xc0\x88\x44\x1b\xce\xa5\x20\x77\xce\x99\x03\x31\x8b\x8f\x9e\xd8\xdb\xb0\xdc\x98\xd8\x4e\x3d\x85\xcf\xe7\x5c\xce\xe7\x9c\xcf\xe7\xa4\x32\x1f\x3e\x9b\x13\x39\x9b\x13\x9e\x57\x01\xd5\xbc\x02\x2a\x52\x4d\x2e\x01\x9b\x54\x93\xcb\x75\xf8\x07\xc0\x04\xe6\x91\x8b\xfa\x0c\xc6\xd4\x2d\x51\x54\x67\xaa\x35\x2a\xda\xc6\xba\xa3\xa2\xe3\xca\x50\xca\x5e\x32\x4d\xe5\xbd\x3c\xb7\xf5\x11\x7d\x94\x89\x00\xd4\xe7\x91\x8b\xba\x5e\x8f\x8e\xe7\x99\xd5\x2d\xdd\x7f\x42\xa3\x9e\xdc\x23\x61\xc2\xd4\xca\x9d\x47\x9d\x35\x0e\x49\xd2\xd3\xde\x71\x86\x7b\x72\x3f\xe0\xd0\xea\x78\x4b\x68\x6b\x23\xdc\x29\x7e\xda\xd7\x52\x96\x59\x73\x54\x77\x4c\x6a\xba\xff\x4d\xc5\xcb\x59\x6f\x36\x41\xd6\xf6\x94\x88\x48\x73\x4d\x7d\x56\x93\x16\x67\xd9\x97\x76\x5e\xa9\x63\x09\x0e\x55\x84\x87\xe8\x1c\xb7\xdb\x6a\x0d\xea\xed\x3a\xed\x0c\x55\xf0\xba\xd6\x38\xbe\x12\x44\xdb\xe4\xaf\x3a\xcd\xde\xd9\x94\x4f\x95\x2f\x49\xd3\x17\x27\x41\xd6\xd4\x0f\x4f\x0c\x73\xb0\xe1\xd8\x54\xfa\x02\x8b\x20\x94\xeb\x15\xfe\x92\x2d\xa6\x84\x51\xe1\x51\xb7\x55\xa3\x03\xba\x41\x8c\x7d\x3a\x8b\x2e\xbb\xa1\x2a\x27\x1c\xa1\x97\xc6\x95\x56\x3a\xc6\x8b\xc8\x45\xc6\x31\xcd\x08\x5d\x0c\x75\xa0\xc2\xf5\xa6\x41\xc9\x85\xa1\xac\x0d\x27\x51\x77\x80\x8b\xa8\xa5\x8a\x6c\x9e\x2d\x89\x87\x97\xe9\xf0\xa1\x61\xb6\x6c\x7d\x8c\xec\x69\xc5\x80\x38\x76\xd7\x3c\x03\x92\x30\x3f\x4a\x30\x1d\xce\xe2\x2c\x0a\xd7\x86\x4f\x51\xcf\x54\xc3\x47\x3e\x01\x2b\x8e\x92\xd3\xe6\xed\x63\x57\x44\x39\xbd\x8a\x71\x3a\xc7\x98\x99\x10\xff\x05\x41\x96\x36\xcd\x5a\xf8\x97\x41\x98\x8c\xa6\x84\xb0\x94\x51\x7f\xc9\x7f\x04\x64\x71\xaf\x48\xb8\x77\x7f\x74\x7f\xf4\xf0\x5e\x90\xa6\x65\x1a\x67\x39\x46\x81\x88\x24\xd9\xbf\x7d\xd4\x8f\x03\x3c\x63\xfc\xe7\x34\x2a\x5e\x60\x08\x63\x64\x61\xe5\x70\x55\x24\xbd\x8d\x4e\xe6\x9c\x78\x1e\x17\x29\xc7\x64\x69\xe5\x70\x11\xf5\xfb\xcc\x18\x18\x56\x8f\x06\x7d\x8a\x01\x92\xd1\xb7\x96\x64\x49\xce\x31\x1d\xcc\xfc\x50\x3e\x80\xdf\x59\xf9\xa8\xab\x6a\x46\x89\xa5\x8c\xad\xd6\x2a\xce\xc8\x52\x94\x57\xb7\xff\xe3\xc8\x5e\xb3\x22\x15\x20\xa9\x54\xbd\x5a\xbb\xea\x54\x02\xb8\x52\x77\xba\x76\xdd\x98\x2f\x57\xa5\xe6\x49\xbd\x66\x79\xca\x98\x9e\x8f\x83\x8a\x5c\x14\xc3\xea\xce\xc2\x28\x5d\xc6\x4a\x73\x41\x06\x0c\x6e\x1f\x69\x06\x15\x91\xd6\x59\x60\xdc\xc1\x3e\x35\x12\x99\x2e\x1a\xaf\x6a\x56\x0e\x4a\x19\xe9\x20\x69\xbe\xce\x32\xed\xb2\x64\x69\xea\x55\x21\xd6\x50\x86\x0c\x5d\x79\x8c\x11\xa1\xf5\xd8\xde\xe3\xce\x79\x94\xa3\xf5\xa9\x95\xee\x35\x90\x91\xc6\x56\xf6\x4b\x56\x1f\x6e\x82\xa6\x45\xe8\x59\x97\x06\xb3\x72\x84\x76\x66\x6f\x31\x87\xe6\x36\x9c\x75\xea\x3a\xb3\xad\x03\x44\xa5\xc2\x6c\x8f\x63\xa7\xee\x42\x4d\x05\x30\xd4\x7c\x28\xc7\x23\x6f\xec\x08\x37\x24\x5d\x7e\xa1\x0c\xc8\xa7\xdf\xb9\xd5\xea\xea\xac\xaa\xe0\xb9\x26\x2c\x6d\xa7\x29\x99\xea\x01\x8a\x10\x2b\x04\xa1\x49\x4d\x41\x98\x31\x74\xdc\x35\x21\xc3\x98\x94\xce\x71\xe9\xdd\xbf\x6d\x76\xb2\x75\xe6\x18\x4d\x42\xb6\xce\x9c\x03\x64\x68\x52\x19\x6a\x48\xa5\x41\x31\xb4\x3e\xb5\xf4\xaa\xce\x57\xe5\x79\x9d\x41\x84\xf6\x05\x3c\xa5\x02\xea\xa9\x49\x20\xd6\xd8\x20\x39\x1c\x75\x9e\xe5\xd7\x41\x4c\x52\x7c\xa8\xc2\xb5\xf1\xb6\x19\xd0\x51\x35\xd1\x86\xe2\x04\xdc\x89\xfd\x34\x75\xa4\xa5\x76\x99\xa0\xe2\xe6\x88\xca\x9e\x0c\x3b\xa3\x62\x0b\xda\x32\x90\x4e\x35\x43\x05\x5d\x14\xc1\xcd\x6b\x19\x32\xc9\xee\xd4\x2c\xf8\xb6\xc3\x65\x41\x42\x3f\x1e\x4e\xfd\xe0\x34\xa4\x64\x39\x50\x27\xc6\xa9\x7c\x9a\x5d\xb5\xf1\x6a\xf4\x29\xb7\xe1\xb2\x43\xf8\x68\xa4\x03\xb2\xe7\x22\x8a\x7b\x3f\x11\x68\x29\x2a\xda\x39\x3c\xbe\x7d\x6f\x2a\xc0\xf6\xed\xfb\xda\xee\xe8\x6b\xdf\xcc\xc3\x92\x14\x9b\x18\x9a\x65\x60\x12\x64\x18\x2e\x29\x06\xf6\xd7\xce\xe1\x65\xd4\xf5\x92\xa5\x0e\xc0\x33\xed\x1b\x47\xd0\xba\xf3\xa8\x8b\x04\x4b\x60\xe8\x90\xfa\x2b\xc0\xe1\xa3\x8b\x08\xce\x23\xd8\x8e\x3a\x78\xd2\x1d\x9e\xdb\xc1\x68\xbe\x35\x8a\xf7\xa3\x8a\x7c\x5f\x0c\xb1\x71\x92\x51\x37\x42\x4f\xcc\x2f\x71\xf5\x9d\x95\x57\x0c\x10\x5a\x0f\xae\x5b\x95\xd1\x38\x2d\x20\x50\xd3\x59\xc6\xcf\xb1\x95\x87\xd8\xfa\xfb\xea\xfb\xb9\x35\x05\x49\x23\xff\x72\x3b\x9e\x85\x6e\x29\xae\xc5\xb1\x12\x92\x60\x03\xf3\xf2\x8d\xbc\x8b\x44\xa6\x30\xf2\x63\x72\xb2\xc6\x5d\xb8\xa7\x8d\x6e\x8e\xa0\x85\x1f\xfd\x6f\xec\xf5\x0e\xce\xa3\x66\x7b\x95\xa7\x17\xa3\x6e\x70\x84\x5e\x46\x80\x6b\x44\x1e\x70\x41\xb2\xdb\xef\x01\x6a\x87\x3c\xe6\x95\x24\xfd\xee\x2c\x73\xc9\xcb\x28\x52\x6e\xe0\x55\x51\x9b\x85\x5c\x47\x54\x71\x64\x94\x90\xda\x39\xec\xad\xb8\x94\xd4\x4f\x37\xd6\x3a\xc9\xf4\xd1\x55\xc4\x51\x54\x07\x53\xbf\x63\xbf\x28\x7d\x8b\x4f\xf0\xa5\xc3\x40\x44\xb4\xa2\x4a\x39\x5d\xfa\xf5\x3b\xec\x3e\x6a\x99\xc3\x20\xed\xb5\xc9\x0a\xcb\x12\x9d\xda\xe3\x47\x59\x10\x88\xf8\xc2\xda\x7d\xc6\x8e\x89\x78\xab\xc2\x4f\xfc\x28\xce\x28\xd6\x85\xe1\xac\xb8\xd5\x1d\x10\x3f\xe4\xc8\x95\xc3\x93\x22\x6d\x3f\x89\x58\xe4\xc7\x56\x0e\x07\x51\x8f\x3d\xa6\xea\x41\x58\xad\x8a\x20\x08\xa9\xc3\x20\xf6\xa7\x38\xe6\x20\x4d\xa3\x18\x27\x01\xde\x0f\x1d\x2c\xc2\x66\xcd\xa3\xa9\xd4\xee\x07\x61\x05\x97\x6e\x33\x87\xc0\x09\x4e\xb0\x30\x83\x7b\x47\x63\x27\x80\x28\x94\xe1\x29\xf7\xbb\x8e\x80\x6b\x19\x3b\x0c\xa8\x00\xbc\x00\xd0\xab\x6e\x40\x47\x93\x5f\x13\x87\xc1\x8c\xd0\x85\xcf\xda\xe0\xd4\xda\x56\xb5\x68\x3c\x7e\x69\xd6\x3e\x51\x01\x80\xf1\xb4\x48\xda\x54\xe1\x77\x7c\x5a\x24\xdd\x97\x49\xdb\xcb\x32\xe9\x81\x2e\x55\x46\xe8\xf9\xf9\x91\x0a\xf6\x53\x36\xff\x50\x27\x95\x46\xf0\xbf\xa8\xb6\xb2\x93\x22\xe9\x57\x15\xd7\x18\x97\x41\x82\x7e\x53\x26\xf4\x41\x19\xe4\x67\x32\x56\x11\x83\xc8\x79\x99\x36\x69\xaa\x85\x4d\x36\x39\x08\x9e\x77\xbf\x85\xd7\xb4\x91\xa1\x34\x24\x6e\x68\x33\xc3\x58\x7b\xef\x68\x28\x40\xc3\xd8\xce\xe1\x75\x7b\xf1\x4c\xe1\x9c\xab\x90\xbe\x6f\x00\xf5\x73\xbe\xd9\xb7\x36\x7f\x73\x36\x7f\x35\x00\x7d\xd2\x86\xfa\xfd\x71\x1b\xec\xba\x5c\x15\xee\xba\x9c\x00\x7c\x0b\xde\xba\x46\x15\xe0\xba\x46\x15\xe2\xba\x5c\x15\xe2\xf7\xc7\x4d\x88\xdf\x17\x1e\xc7\x76\x8d\x10\xbf\x44\x4f\xb1\xd4\x0e\x78\x67\xcc\xff\x8a\xd1\x91\xcc\x7f\x5f\xcf\x37\xe1\xed\x21\x69\xe1\xed\x71\x86\x9b\x78\xfb\x01\x87\x4d\xbc\x3d\x9e\x67\x4d\xbc\x7d\x42\xa3\x26\xde\x1e\xf9\xac\x82\xb7\x8d\x49\xfe\x92\xe7\xf0\x21\x72\x2f\xd1\xc4\x86\x67\x91\x3b\xc1\xf7\x7f\xfa\x10\xc1\x97\xc8\x7d\x38\xfe\xe9\x59\x04\x5f\xc5\xc7\x97\x08\x9e\x46\xee\xe6\x83\x9f\xbe\x46\xf0\x26\x72\x7f\xf9\xe9\x69\x04\x9f\x0c\x5b\x57\x9e\x59\xcf\x39\x64\x86\xcf\xb1\x70\x78\xed\xbe\x16\xbf\x5e\x8b\x5f\xc4\xdd\x15\xbf\x76\xc5\xaf\xc0\x7d\x27\x7e\xbd\x13\xbf\x32\x17\xed\x46\x22\x33\x42\xd4\x1e\x06\x3f\x7d\x8d\x86\xe4\xa7\x2f\xd1\x30\xf9\xe9\x59\x34\xc4\x3f\x7d\x88\xec\x7b\x4f\xa3\x9b\x31\x78\xd5\x30\x2b\x85\xde\x70\x26\x75\x76\x95\x94\x61\x0f\x65\x3d\xba\x71\x87\x88\xdd\xfb\xe5\x46\xb2\x56\x87\xd5\x6d\xf0\x8b\x5d\x84\x6d\x36\x54\xcb\x78\x25\x5e\xa7\xa8\x91\xc1\x2f\x22\x18\x86\xee\xea\x02\xe3\x53\xc7\x13\x2f\x46\xfe\x15\xff\x50\x8f\xe8\x41\xeb\x79\x25\x69\x3c\xe2\xd4\x8f\xaa\xba\x6b\x89\x77\x11\xbf\x12\x77\x5c\xf5\x37\x68\x6e\x03\xfe\x89\xc2\x6e\x84\x12\xa1\xae\x6d\xc3\x0b\xb3\xb2\x87\x69\x23\x1f\x96\xa3\x28\x70\xe4\x43\xa4\x77\x51\x2d\xf9\x99\x4a\x3e\x14\x53\x29\x92\xbf\xa8\xe4\x67\x24\x2b\xb7\xf3\x57\x95\xb8\x5b\xd9\xce\x4f\x23\x8d\xc7\xf8\xb4\x0c\x70\x16\x15\x08\xd9\x62\x78\x06\x1f\xa2\x9f\x70\xf5\xbd\x74\xe3\x19\x4f\x50\xdf\x5f\x64\x26\x1f\xcb\xc6\x57\xfe\xcd\x21\xbd\xf1\x94\x7f\x85\xfe\xd5\xc6\x1b\xfe\xc1\xd7\x23\xcf\xe1\xb3\x71\x8b\x7e\x8a\xd0\x8b\x48\x85\x87\x8b\x56\x86\x70\x10\x4b\xcb\xc4\xba\x52\xb9\xa8\x58\x2f\x6a\xa2\x17\x95\xd4\x16\xb5\x3f\x8a\xc3\x2e\x8e\x99\x5f\x9e\xff\x3f\x14\xe7\xb7\x02\x6f\x0e\xcc\x2f\x93\xca\x45\xca\x81\xfa\x9d\xfe\xba\x11\x9a\xfc\x7c\xff\x27\x44\x37\x8a\x50\x02\x42\x63\x7a\x78\xdf\xf9\xcd\xb6\x37\x36\xed\x7b\x3f\xdf\x8c\xed\x0d\x3c\x9c\x00\x71\xd9\xb0\x52\xe8\x6f\x93\xad\x89\x23\x1e\x83\x55\x22\x51\xaf\xcf\xc4\x21\xc3\xfb\xbf\xfd\x66\xdf\x7b\x30\x1e\xdf\x8c\x21\x73\xc9\xf0\xc1\x78\xfc\x53\xa0\x97\x68\xf2\xe0\xe1\xf8\xb7\x5f\x7e\x0a\x36\xd0\xfd\x87\x3f\xff\x94\x6d\xa0\xec\xde\x83\x9b\xb1\x3d\x44\xd9\xbd\x09\xaf\x61\x6f\x24\xf6\xf0\x97\xc9\x6f\x0f\x1e\xfe\xca\xf1\xd4\xef\xe1\x48\xa4\x67\x88\x57\x91\xf0\x5f\x52\x79\x04\xff\xdb\x78\x8b\x5f\x78\x67\xae\x8f\xde\xc2\x04\x22\xf4\x3a\x02\x11\x3c\x11\xdb\x10\xbb\x3e\xa2\x3e\xa4\xe0\xc1\xac\xb8\xae\xbd\x88\xd0\xc7\x08\x5d\x57\xd7\x82\x57\x1d\xc3\x6f\xbf\xfd\x06\x59\xa1\xdf\x26\xd3\x7e\xfe\x0d\x82\x42\x2d\xae\x48\x22\x4a\x91\x4e\x26\x6c\xde\x87\x44\x2a\xdd\xc5\x20\xf0\x60\x2c\x2d\xa4\x13\xdf\x84\x57\x21\xc2\x3e\x7c\xe1\x94\x0d\x9e\x89\x7f\x3f\x88\x7f\x05\xad\x03\x41\xff\x40\xd0\x44\x78\xae\x4e\x10\xe2\x1b\xb6\x6b\xe2\x97\x17\x50\xa4\x4f\x9b\x21\xb5\xef\x7d\x89\x6e\xc6\x39\x04\xbe\xdb\xe1\xdd\x7e\x35\xb5\xa0\x9c\x9e\xef\x46\x42\x37\x37\xb7\x21\xf3\x7b\xec\xb4\x3f\x47\xf0\x43\x04\xc4\xe7\x24\x99\xf8\xda\xbf\x33\x7c\x89\x6c\xf0\x7c\xf7\x55\x04\x91\xef\xbe\x8f\xc0\x37\xb4\xa1\x0c\x73\x7c\x79\x0c\x44\x7e\x4b\x61\x2e\x01\xcc\x17\xf7\x97\x8d\x64\x88\x9d\x64\x88\x73\x1b\xbe\x62\x34\xb6\x6d\x48\xfd\x66\xf4\x33\xc6\x8f\xa1\x77\x18\xf9\xbe\xbd\xb1\x2b\xfe\xd4\x4c\x26\xbe\x88\x24\xa9\xc0\xb3\x35\x1e\x22\x36\x9c\x3c\x78\x30\xb6\x9d\xf1\x90\xf1\xfb\xf2\xcc\x77\x89\x0f\xb1\x09\xce\x62\x8a\xcc\x07\xb6\x91\xfa\x3f\x65\x3e\xf0\x66\xb0\x3b\xf3\x51\x2b\x18\x4c\xea\xdb\x5b\x1c\x23\x24\x48\xf0\x30\xf5\x39\x2c\x20\xf4\x5d\xe4\xa3\x55\x8c\xf6\x20\xf6\x91\x40\x8c\x7a\x2e\x87\xa5\xd0\xaf\xf8\x84\x61\x62\x83\x64\x7a\xaf\x43\xff\xea\x68\x4e\x68\x3d\x6e\xe0\x0a\xc6\x41\x7c\xb7\x78\x07\xf1\xdd\x62\x1f\xc4\x77\x8b\x83\x10\xdf\x2d\x26\x42\x7c\xb7\xf8\x08\xf1\xdd\x60\x25\xa4\x3e\x00\x07\xc8\xd5\x4b\xce\xe8\xdf\x72\xf0\xa1\x7f\x65\x1e\x7f\x5a\xe6\x34\xe6\x90\x54\xf3\x1a\x33\xa1\x95\xac\xc6\x74\xca\x8c\xc6\x8c\x32\x2a\xb2\xda\xd3\xe2\xc9\x79\x2e\x15\x27\xd6\x5b\x99\x0a\x83\x2c\xbe\x5b\x2c\xb2\xf8\x6e\xf1\xc6\xe2\xbb\xc5\x1d\x8b\xef\x16\x7f\x2c\xbe\x5b\x1c\xb2\xf8\x6e\x5d\x4e\xc4\x77\xeb\x7e\x22\xbe\x5b\x1c\xb3\xf8\x6e\xf1\xcc\xe2\xbb\xc5\x35\x8b\xef\x26\xc0\x76\x71\x50\x40\x6b\x2d\x4c\x68\x00\x4b\x98\x09\x1b\x01\x46\x2b\x59\x0d\xa8\x05\x73\x33\xdc\xa2\xf8\x36\x90\xc3\x66\xd0\x5d\x99\x61\x97\xa5\xcc\x0c\x3e\x65\x5a\x6b\x04\x22\x29\x73\x1a\x80\x54\x95\xda\xd0\x94\x19\x72\x6b\xbd\x9a\x1d\x72\xb8\x7e\x88\xd8\xfc\x28\x9b\xcd\xa2\x4b\x67\x45\x9c\xd3\xf2\x02\x27\xa1\x3d\x98\xe8\x96\x27\x7a\xf8\x83\xcd\x22\x6d\xb3\x92\x58\xa4\x25\xa1\x4e\x2a\xd3\xca\xc4\xfb\x3a\xed\x3e\x2d\xca\x15\x69\x9b\x65\xe2\xfd\xa2\x93\xfb\xa2\x93\x96\x1b\x38\xfd\xd4\x79\xca\x4f\x0c\x8b\xcd\xad\x2a\x6f\x3d\x60\x5b\x3e\xba\xa2\xf0\xa0\xe2\x9b\x12\xb0\x2d\xf5\x9f\x94\x90\xe0\x5a\x04\x46\xb5\x7e\x1c\x2e\xee\xfd\x38\x0c\xef\xfd\xf8\xc9\x82\x98\x24\x27\xbb\x32\x75\x1b\x06\x3f\x3e\x1e\xfc\x18\xc2\x80\x67\xb0\x68\x21\x8a\x3e\x73\x7e\x3c\x1c\xfc\xb8\x94\x25\x8f\x2b\x89\xce\x8f\x47\x22\x9d\xb7\xa9\xd3\x75\xbb\x83\x1f\x87\xfb\xba\xde\x2c\xa2\x29\xdb\xe5\x0b\xc3\x19\x5b\xe7\x8d\xe0\xe5\x97\x26\xce\xc0\xf4\x42\x75\xef\xe1\xb8\x71\xa7\x60\xf0\x70\x6c\xe7\x39\xcc\xfd\x2e\x49\xba\xe1\x55\x49\x80\x86\x1f\x2d\xa7\x48\x3e\x2a\xc1\xb9\x91\x37\xa9\xda\x9d\x54\xab\x6e\x02\x13\x60\xe7\x1d\x2f\x8c\x35\x5b\xa2\x84\x4d\x1b\xc6\xf6\xd6\x64\xd3\xa9\x27\xe6\x70\xd2\x1e\xb8\x44\xc9\xa5\x8f\xf6\x84\x7f\x57\x19\x06\x45\xc6\xe9\x9a\xb4\x15\xc8\x2b\xe6\x85\x85\x9a\x79\x55\xa7\x1c\x9d\xfb\x95\x00\x53\x9c\x35\xab\x1a\xd4\x35\xb3\x85\x5b\x84\xdc\x86\xa9\x71\x5a\x11\x7a\x02\xc7\x22\xcc\xc3\x95\xdf\x13\x9a\x55\x98\xd8\x0d\x2c\x98\xfa\xe8\x13\x4a\x2a\xb6\x36\xb6\x6d\xeb\x7b\x15\x51\xd4\xec\x53\x71\xb9\xf1\xd1\xdc\x2f\x11\x96\x0f\xe6\x0b\xe6\xeb\x23\x77\x7f\x35\xc8\xf9\x29\x5f\x02\x51\x7c\xb3\x5d\x5c\x95\x5f\x54\xca\xd7\xa7\xe8\xf9\xe8\x59\xb5\xa4\x67\x2e\x3a\x30\x14\x1d\x96\x45\x4f\x51\x33\xf3\x71\x91\xc7\x46\x9c\x33\x19\x15\x24\x5d\x95\x93\xc5\xfe\xb3\x2c\xb7\xa0\xa8\xa3\xa8\x2a\x3b\x35\x36\x29\xce\xd4\x7a\x9b\xd3\xae\x36\xab\x65\x55\xe1\xb0\x13\x32\x1f\x2a\x4d\x0e\xc3\xca\x54\x6b\x19\xff\x51\x6d\x40\xf5\x65\x22\xb5\x70\x67\x52\x6b\x11\x77\x82\xb9\x5a\xea\x3f\xf0\xba\xad\x8f\x6b\xf5\xb6\x9b\xa0\x52\x8c\x15\x7a\x5f\x85\xd3\xb6\x01\x4e\xf5\x82\xaa\xa4\x6f\x68\x4e\xc2\xb2\xd6\x9e\x6f\x6e\xaf\x5a\x52\x15\x7d\xd6\x09\xf5\x77\x55\xe0\x3e\xab\x40\xbd\x9a\x71\xda\x09\xbc\x6a\xa9\xfd\xce\x4e\x16\xbe\x6a\x4e\x77\xb4\x5f\xe9\xa8\x99\x19\x77\x76\xd6\x2c\x59\x0a\x0e\x25\x19\x12\x99\x9c\xb0\xfd\x6d\xbc\x65\x6d\x1f\x5a\x8e\xf5\xfa\x50\x1d\xdf\xaf\xfb\x8a\xfa\x0b\xcb\xb1\x96\x0b\xcd\x7c\x74\x4e\x63\xb7\x32\xd9\xa3\xce\x52\xaf\x2b\xa5\x0e\xea\xf4\xe5\x7e\xb5\xdc\xf3\x4a\xb9\x1f\x8b\x72\x44\x26\x7c\xad\x34\x7f\xe2\x4b\x93\x61\x99\xe3\x34\xb3\x1c\xab\x6d\x98\x6c\x49\xf5\x3a\xdf\x3d\x4c\x90\xf5\x23\xba\xba\xf9\x74\xb3\xb8\xf1\x16\x37\xc3\xc5\xcd\xe3\x9b\xff\x7c\x7c\x33\xbd\xf9\xcf\xe9\x4d\x78\x33\x0c\x6f\x86\xff\x11\xde\xe0\x9b\xff\xc0\x37\xdb\x37\xff\xb9\x7d\xe3\xdf\xfc\xa7\x7f\xf3\xec\x66\xf8\xec\xe6\xf4\x66\xff\x66\xb8\x7f\x13\xdf\x2c\x6f\x5e\xdf\x1c\xde\x1c\xdd\xfc\x78\x73\x70\xf3\xf5\xc6\xf9\x6a\x5b\x36\x5c\xf4\xd1\xdf\x99\x8f\x92\x82\x13\x10\x56\xa9\x4f\x12\x38\xf6\xc1\x47\x57\xf2\x4a\x15\xa1\xc0\x07\x32\xa4\xc2\x71\xa9\x08\xdf\x76\x6a\x12\x93\x14\x2d\x5c\xf0\x6a\x33\x9f\x2f\x98\x0a\xf7\x76\xb4\xba\xfc\x58\x97\xbd\xf4\x5d\x14\xa1\x53\x1f\x42\x1f\xac\x1f\x3f\x0d\x7f\x5c\x0c\x7f\x0c\x8f\x7f\x54\x6c\xc3\xe8\xc7\x83\x1f\x9d\xaf\xc2\x30\xbb\xa7\x88\xd1\x90\x56\xbf\x92\x5b\x96\x08\xca\x68\x1d\xcd\x49\x16\x87\x03\xe5\x59\x54\x78\x15\x15\xce\xdd\x9f\x31\xb8\x42\xd6\x07\x4a\x92\x93\xc1\xfe\xd1\xab\x5f\x1f\x8e\x27\x03\xc9\x04\x89\x6e\xdf\x19\xe3\x70\x1f\xa1\x50\xc9\xbb\x82\x48\xbb\x76\x78\x6c\x3c\x15\xd3\x08\x2d\x23\xf4\x58\x16\x82\x6d\x63\x19\x1f\x1d\xa9\xc9\xa9\x39\x59\xfc\xf6\x2e\x9a\x7f\xb9\xa2\x82\x82\x46\x59\xe1\x6d\xc7\xd9\xac\x4f\xf5\x97\x42\xf2\x50\xb1\x6e\x1b\x58\xb0\xed\xab\xe1\xed\xad\x31\x85\x43\xdf\x5d\xfd\x14\xad\x5d\xf0\xfc\xfc\xf3\xc3\xdf\x36\x1f\xe2\xfb\x6b\xbe\x89\x87\xa2\x9a\x30\x3d\x58\xb3\x86\xf2\x65\xf4\x70\xed\x0a\x52\xf9\xf0\x21\x7e\xb0\x66\xf9\x54\x94\x9f\xd4\xa7\x50\xe8\x1a\xc2\x8e\xef\x56\xfc\xc8\x0a\xef\xeb\x5d\x02\xa3\x9f\x68\x6e\x03\xf1\x20\xf2\x50\xd3\xf2\x58\x8b\x95\x8b\xd5\x2a\x5a\x7c\x95\x49\x63\x3f\xe9\x4f\xd6\x1b\xcb\x15\xb0\x6d\xbb\x74\x85\xdc\xab\x23\x42\xed\xdc\x46\x15\x17\xf4\xb6\x0d\x67\xbe\x6b\xe0\x5d\x6b\x01\x53\xb7\x0e\xd0\x94\xa2\xed\x04\xf9\x06\x2d\xbb\xaa\x9b\x39\x6f\x02\xc4\xa5\x20\xa3\x10\x42\x56\x8d\x12\x65\x00\xa6\x8c\xe3\x79\x2f\xb9\x19\x73\x7e\x37\xa8\x98\x88\x06\x50\xbd\xb3\x88\x22\x55\x24\x15\x3c\xae\x1c\x7f\xe3\xd1\x20\xb1\x2b\x56\x14\xb5\x85\x13\xeb\xf6\x18\x51\x0d\x30\xdb\x39\xcb\xe1\x49\x6d\xb9\xd4\xa7\x2b\xe1\x1c\xa1\x0f\x9d\x6b\x27\x84\x7d\x63\x01\xf5\x8f\x19\x87\xfa\x8e\x6f\xdb\xf0\x26\xb3\xe1\xa0\x63\xbf\x55\xc9\x4a\x98\x51\xf1\x2e\x5c\xa5\x2b\xcf\x33\x78\xe2\x0b\x53\x74\xd8\xf7\xdd\x7d\x5f\x38\xe9\xdf\xf7\x7f\xb7\x6e\x1c\xeb\x4f\x77\x8a\xe2\xa4\x4b\x92\x48\x11\xb3\x73\x7e\xc8\xf2\x85\x78\x65\x12\xc4\x45\x28\xd4\xfe\x3a\xb7\x22\x74\x2c\xdd\x7b\x3a\xac\x7d\x3d\xe0\xa5\xfc\x65\x74\xef\x7c\x62\xd9\x39\x3c\xe7\xc0\x49\x12\x03\x66\x5e\x56\x24\x8e\xca\x29\xa0\x52\xba\x09\x12\x89\x96\x0e\xa9\x79\x1e\xd8\x29\x68\x6d\x88\x03\x12\xe2\x01\xbf\x23\x0e\xac\xc6\xed\xa2\x28\xee\x0c\x2c\xe9\xf2\x40\x50\x98\xe3\xc4\x86\xd7\x7e\xbf\xcb\xf6\xb7\x01\xba\x5e\x60\x36\x27\xa1\xc3\x94\xd6\x42\xea\x50\xc8\x68\x5c\x2a\x2f\x48\xf3\x70\xe7\x71\x80\x88\x2d\x2e\xa9\x24\x63\xce\x19\x5c\x44\x6c\xbe\x43\x71\x88\x13\x16\xf9\x71\xea\xdc\x99\x08\xdd\xa5\xdd\xee\x4b\x22\x7a\xed\x83\xb5\xbb\x77\xb0\x77\xbc\x67\xd5\x43\x51\xc0\xcb\x40\x4a\x71\xdf\xf5\x1c\x79\xb2\xfe\xeb\x57\x47\xc7\xcd\xda\xea\x0c\x7c\xbf\xa2\xeb\xa7\x7b\xad\x9a\xba\xdf\x0f\x46\xf4\x7b\xc5\x50\x84\xbc\x04\x22\x34\x4f\xc0\x92\xd6\xdf\x02\xac\x02\xdf\x9e\x99\x70\xc6\xfc\xa6\x75\x2c\xa1\x56\x4a\x03\xe5\xef\x01\xbe\x0c\x30\x0e\x0b\xd1\xe7\x4b\xcc\x2e\x08\x3d\xdd\x13\x1d\x15\x62\x18\x99\xa8\x8c\xcf\xd5\x35\xc8\x0f\x8f\x98\xcf\xb2\xd4\x32\xbc\x51\xf1\x9b\x61\x95\x0c\xe0\x51\x2a\xca\x8e\x38\x06\x35\xcf\xac\x22\x73\xa1\xd4\x32\x39\x2c\x90\x52\xc8\xb1\x8b\xde\x5e\xfb\x57\x31\xf1\x43\x83\xbf\x18\xeb\x5d\xe9\x3f\x40\x99\xe5\xe0\xc1\x8c\x92\xc5\xc0\x5f\x46\x05\x42\x76\x8b\x56\xac\x43\x3f\xe6\xfb\x19\x87\x03\x8e\x75\xba\x42\x9e\xc3\x17\xdf\x3d\x0c\x4c\xf1\x7f\x1a\x51\x72\xd4\x16\xda\x89\xd0\x33\x5f\x11\x77\xe7\x30\x92\x5f\xb9\x0d\x5f\x3b\x1f\x02\xb4\xc2\x71\xa1\xfb\xd2\x54\x38\xee\x51\x55\x56\xab\x8c\xab\xab\xac\x9b\xd1\x93\x3c\x8c\x10\x93\x8e\x85\xf5\xd5\x41\x29\xc2\xe8\x02\x4f\xd4\xfb\xa3\x56\x9a\xd1\xe9\x67\x51\x13\x5e\x3b\x91\x6c\x48\xe8\x02\x3d\xf5\x5d\xec\x21\xe1\x24\xdf\x86\x37\x46\xcc\x3d\xad\xc5\xfb\xaf\x47\x46\xf1\x44\xb4\x94\x23\xe9\xf8\xe8\x93\xf1\x14\x8b\xd0\x7e\x06\x97\x14\x59\x56\x49\xaa\x0d\x81\x02\x0a\xb2\x5f\x3f\x01\x3a\x36\x61\xdd\xc7\x90\x9c\x48\x67\xac\xca\x32\x8e\xcb\x1f\x96\xdd\x5d\xf8\xce\xd8\x18\xc0\x22\x42\xd8\x83\xd8\x14\x4e\xe6\x4e\x71\xa0\x97\x5e\xed\xeb\x3d\xb5\x15\xc2\xf8\x66\x7f\xc1\x89\xfa\xf7\xc4\xa8\x61\xb2\xf1\xcf\xbe\xc1\xd3\x0a\x35\xea\x83\x07\x6d\x6f\xb1\x96\x1f\x63\xca\x12\x7f\x81\xad\xe6\x30\x9d\x08\x7d\x04\xe3\x52\x76\x72\x36\xda\x49\xdb\xdf\xc6\xfc\x54\x86\x6d\x2a\xc4\x6d\xca\xa5\x35\x58\x80\x15\xa3\xf4\xd1\x88\x62\x6f\x10\xb3\xb7\x0e\x38\x8a\x68\x4b\x92\xb5\xc7\x6a\x0b\x5d\x76\xe9\x5e\x01\x2c\x49\x4d\x7f\x30\x53\xd3\x42\xe2\x2d\x35\xcf\xdb\x9e\xb2\xcf\x1c\x96\x03\x4b\x4d\x58\xbc\x8f\x8c\xda\xee\x6b\xa2\x27\xd4\xce\x77\xd7\xb2\xe1\x28\x10\xa2\x4c\x3b\x07\x9a\x9a\x56\x51\xd8\xd7\x32\x06\x27\x88\xa5\x4d\x8d\x58\x23\x4f\x2c\x55\xda\x24\xb7\x7e\x80\xce\x29\x3a\x15\xae\x75\xee\x4c\x38\x59\x9e\x93\x8b\x23\x55\x40\x9e\xe7\x6b\xaa\xc3\x2a\xc5\xb8\xce\x46\x0b\xd5\xb9\x5b\xb4\x3a\x8b\x62\xa6\xbc\x5c\xfe\xc0\x4f\x07\x86\x2f\xd9\xda\x66\x4e\x38\xc0\xd1\x79\xb5\xb6\x4e\x59\xb7\x05\x69\x78\x28\x0d\x1c\xc4\xb7\xf1\x0e\xd1\x78\xca\xfd\x82\x12\x5b\xba\xa9\x5b\x7f\xc5\x2d\xe1\x41\xe9\x52\x3a\x74\x4f\x6c\xdb\xb1\xac\x1c\x70\xea\x5e\x8b\xe8\x0e\x67\x20\x3a\x77\xce\x40\x4f\xc0\x39\x83\xea\x32\xa9\x9f\xa5\x6e\xe2\x59\x0e\x49\xda\xcb\x80\xc9\x96\x99\x6a\x99\x96\x2d\xe3\x7a\xcb\x49\xa3\x65\xa1\x49\x4a\xd2\x4e\x66\xe9\xfa\x14\x5f\x39\x0c\xc8\xb2\xa6\x46\x0a\x41\x5a\xd8\xe3\xe1\x13\x7c\x79\xe8\xb3\x60\x6e\xe5\x90\x15\xc9\x7b\x67\x56\x0e\x5e\xba\xc6\xd5\xd4\xfd\x2f\xb1\x22\x41\xba\xe6\x22\xde\xf9\xaf\x2a\x19\x78\x49\x58\x75\x04\x6b\xb6\xe1\x8a\x26\xb2\xb5\xbb\x74\x1b\x5d\xf2\xd9\x99\x70\x07\x22\xe3\x7e\x6e\x33\xfa\x78\x74\x8a\xaf\x6a\x82\x7f\xe1\xe7\x2e\x42\xfb\xb0\x9d\xc0\x27\x74\x7b\x1a\x5c\xdc\x2e\x01\x8f\xc8\x12\x1e\x27\x92\x06\x7b\xa9\x2d\x2f\xa7\xba\xa7\x7f\xb7\xfe\xbd\x76\x91\x13\x8b\xca\x53\xe5\x2e\xf6\xfb\x26\x50\x44\x4a\x10\x27\x8a\x65\x39\xd5\x09\xac\xbd\x37\xae\xf5\xde\x00\x71\x01\xf9\x0c\x51\x0a\x98\x0f\xd2\xca\xf9\xad\x27\x4d\x5d\x33\x43\x50\xe7\x0d\x48\x6a\x83\x8f\x8e\x3c\x78\xe3\xf3\xff\x3f\x4f\x6c\xfb\x1b\x6f\xf2\xcf\xca\x9b\xbc\x80\x96\xd9\xbe\xc7\x74\x49\xad\xb7\x76\x2c\x84\x02\x87\xd2\xb5\x28\x7c\x12\x32\x9c\x4a\x4a\xae\xae\xfd\x12\xd4\x30\x4b\xbb\x6f\xbe\xc7\x7c\xc1\x1e\x7b\xf0\xc2\x87\x34\x55\xf7\xda\x38\xed\xbc\x58\x3c\xcf\x60\x96\xca\xc3\x2f\x34\xb5\xba\x6a\xd4\x2f\x7c\x9b\xf7\x23\xfe\xf2\xae\x96\xbd\x5d\x85\xaa\xab\x79\xea\x86\xc8\x4f\xe0\x20\x82\xd6\x2d\x55\x55\x09\x12\x71\x62\xd4\x6e\x4a\xbc\xea\x92\xa7\xf3\x9b\x50\x45\x45\xdb\x82\x45\x82\x8e\x13\x85\xad\x3c\x53\x6a\x6c\x17\xe9\xb2\xd6\x79\x33\x34\x96\x25\xaf\x1d\x06\x47\x43\xc5\xb1\xf8\xf8\xca\x94\x3b\x6e\x71\x13\xb9\xb8\xea\xf2\xee\xc3\xa4\x43\xf2\x70\xa7\x2a\xc6\x39\xfb\x86\x31\x15\xc7\xea\x2d\x07\xa5\x81\xa2\x75\xd4\x2d\x78\xee\xeb\xb4\x52\x59\xfd\xed\x81\x25\xa7\x70\xce\xf1\x80\xe7\x85\x3e\xf3\x2d\x39\xa3\x90\x99\x02\x3a\xf6\x0a\x35\x90\x7c\x38\xb5\xe1\x24\x41\x73\xb1\x37\x16\x69\xa7\x97\xe2\x4b\x29\xe3\xe8\xb6\xe6\x2a\x78\xea\xe2\xca\x26\x38\xbb\xd4\x02\x9a\x22\x6a\x72\xf0\xae\xb7\xed\x17\x1f\x45\xe8\xbd\x0f\x18\xce\x53\x39\x1e\x23\x8a\xea\x62\x55\x9a\x63\xdd\xd3\x47\x61\x6a\x69\x80\x49\xa0\x9c\xf0\xb5\x0b\x8d\x88\x1b\xa1\xfd\x08\x18\xec\x24\x52\x86\x2b\xd1\xd2\xce\x61\x6a\x64\x0f\x85\xb7\x79\x0a\xfb\x26\xf0\x76\xd1\xc5\x2a\x22\x81\x35\xf3\xe3\x14\x5b\x70\x2e\x19\x67\xde\xd3\x15\x5f\xc0\x5d\x0f\x92\x14\x22\x24\x02\x29\x6c\xfd\x5d\xec\xdd\xdb\x7d\xef\x7b\x48\x03\xd9\x86\x67\x1e\xd2\x0c\x98\x2d\x7f\x29\x4f\x0c\xf2\x47\xc1\x5f\xd9\x36\x4c\x53\x54\x72\x95\xea\x77\xc9\x11\x72\x44\x38\x56\x03\x34\xbd\xc4\xa3\x24\x05\x06\x67\xf2\x7f\xe2\x22\x50\x1f\x91\x6a\xb9\x35\x26\x1b\x2e\x78\xab\x45\xdc\x88\x66\xe1\xe7\x9e\x0d\xa7\xbd\x25\xaa\x59\xcf\x3d\x91\x8b\xc3\x88\x89\xb6\x8f\xba\x47\xdc\xa4\x52\x11\x7a\x02\xb1\xa2\x73\xab\x7b\x2b\xe6\x95\xe0\x8b\xd6\x94\x6c\xb8\xec\x40\x9a\xb5\x0f\xcc\x7f\xbb\xa7\xfb\xbc\x97\xe0\x8b\x2d\xd9\xb6\x6b\xf1\x6b\x84\x9f\xae\x3a\xf1\x7c\x44\x52\x21\x09\x81\x4c\xfc\x9d\xf0\x5b\x87\xc4\xe6\xc7\xa9\x2b\x26\x24\x89\x95\x0d\xdb\xa9\x7b\x2d\xdf\xfe\x69\x5a\xdd\x88\x30\xf5\x83\x53\x11\x02\xea\x35\xc5\x69\x8a\x43\xe7\xce\x04\x54\xc1\x63\xce\x76\x72\xee\xf6\x65\x6a\xf2\xe6\xad\x98\xc8\xa2\x55\xd6\x6e\x8b\xd6\x9a\xc2\x15\xf1\xf1\x4b\x42\x96\x56\x6e\xc3\x5b\xd3\x66\x57\x65\xde\x09\x47\x43\x87\x65\x0b\x85\x29\xd1\x5e\x4f\x2d\xd1\x77\x94\x9c\x3c\xd6\x83\x29\x6a\x1d\xb6\xe9\x5b\xad\xe6\x2e\x8e\x31\xc3\x4f\xc4\x12\xa8\x5e\xab\xf6\xd8\xb9\x0d\x3b\x2b\x5a\xd8\x0e\xc3\xbe\xea\x67\xa9\x7b\x1d\x47\x29\x73\x9e\x27\x30\x8b\x70\x1c\x2a\x08\xcb\x1f\xf5\x75\x51\x8a\x1a\xb5\xb4\x19\x09\x32\xb5\x44\x14\xa7\x59\xcc\xd2\x67\xe4\x1c\x53\x99\x62\x5e\xc8\xab\x29\x3e\xc2\xb1\x90\xbc\x89\x31\x09\xc1\x7c\xba\x96\xdb\x25\x31\x52\x56\x19\x28\xd5\xe3\xc4\xc5\xe8\x92\x76\xb7\xa4\x18\x66\xd0\x1c\x65\x66\x1a\x90\x67\xc0\x8a\x83\x95\x58\xf1\x44\x8f\xaa\x58\xdd\xfd\x9e\x3a\x6f\x6b\xe3\x28\xaa\xbc\xea\xa9\xf2\x84\x4f\xa2\x28\xf9\xfc\x9b\x10\xee\x75\x4f\x2d\x09\x84\xa2\xe8\xee\x9a\xb8\x89\xe3\xb0\x81\x54\xef\xd6\xc1\xc9\x76\xb5\xf7\xa9\x7b\x5d\x9c\x9e\xab\x31\xaf\x8a\xad\xa9\x5a\xbf\xb7\xf5\x1b\xee\xdb\xa2\x35\x13\x7e\xe6\xf0\x21\x5d\x69\xad\x50\x0e\x88\x15\xc3\xa0\x95\xce\x71\xbb\xef\xa4\xd1\x37\x69\x76\x1d\x18\xf0\xeb\x59\x71\x79\x7d\x1c\x67\x54\x57\x96\x60\xca\xe1\xcb\xed\x31\xe9\xeb\xfa\x2b\xfd\xb4\x0f\xe9\x04\xf1\x78\x7c\xf5\xb6\x14\x87\xc8\x4a\x6f\xca\xcb\x77\x18\xb1\x62\xb6\x56\x0e\x9f\x56\x6e\x95\x56\x63\x2f\x7a\xe7\xa7\x9a\x7e\x82\x39\xf8\xcb\x19\x7e\x5e\xbd\x7a\x92\x19\x11\x96\x92\xb2\x91\xc7\x3e\x75\xa8\x14\x5b\xf0\x4f\x0c\xf2\x78\xe3\xdf\x09\x30\x7f\xea\x10\xf0\x03\x16\x9d\xe3\xfd\x55\x66\x27\x47\x98\x1d\xfb\xd3\xd2\xee\xe4\x63\x2f\xbc\xd9\xb6\x68\xb5\x18\xfb\x0f\x3d\xa5\x8f\xc9\xc9\x49\x8c\xf7\x2b\x12\x31\x59\x87\xcd\x56\xd5\x39\x2a\x25\x73\xb2\x0a\xed\xa9\x72\x98\x9e\x3c\x21\xf4\xa9\x02\x45\x51\x05\xaf\xac\xf2\x44\x83\xac\xa8\x93\xac\xac\xf3\xb6\x84\x7f\x51\x8b\xcc\x8a\xb0\x97\x7c\x65\xb7\x25\xe3\x98\x43\xd0\xd3\x9a\x2c\xd4\xc4\x84\xac\x68\x49\x4c\x87\xaf\x4b\x0e\x5e\xd9\xbc\x18\xb0\x4c\xf5\x67\xae\xc6\x8a\x27\x51\x0d\x2d\xde\xa7\x25\x5e\x9c\xa5\x15\xc4\xd8\x4e\x05\x66\x78\xb3\x12\x35\xce\x72\x48\x67\x2b\xad\x11\xd5\x9a\xeb\x17\x31\x59\x5b\xab\x3c\xe1\xa4\xfa\x76\x62\x2d\xd5\xef\xa6\xaa\x10\xbe\x5c\x46\x7c\x5b\xe7\x39\xcc\x66\xae\x8f\xf6\x22\xb8\x33\x01\xcb\x02\xcb\xb2\x21\x9e\xb9\x6b\x9c\x9a\x51\xe8\x30\x08\x28\xf6\xc5\x3d\xd0\xa1\xa0\x82\xef\x72\xda\xa5\x6d\x90\x13\xc0\x49\x28\x8d\x91\xa5\x33\xc5\x70\x9b\x39\x01\x14\x9c\x54\x06\x92\x6f\x93\x67\x63\x68\x5c\x21\x5e\x02\x8b\xf5\x58\x16\xa0\xdf\xd3\xc3\x87\xf9\xcc\xe5\x23\xb1\xac\xca\x50\xf8\x0f\x35\x16\x4e\xc4\xf5\x60\xc6\x7a\x30\xe3\xca\x60\xc6\xd0\x64\x16\xb5\x63\xa4\x59\xcb\x83\x80\x1a\xab\x1a\xd1\x72\x96\xe7\x70\x5e\x0c\x49\x43\x3e\x87\x45\x91\xa6\x56\x2a\x87\x93\x99\x7b\xad\xd9\x5f\x8e\x20\x2d\x2c\x58\xcc\x04\x75\xdf\x21\xc9\x2c\xa2\x0b\x21\x4c\xd8\x15\xde\x10\x38\x4e\x4c\x67\x3d\x5c\x69\xd1\x2c\x13\x0d\xf1\x65\xc8\x12\xc5\x82\xf6\x44\x4d\xac\x54\x2b\x07\x43\x45\x13\xb8\x6b\x28\xc9\xad\x28\xd7\xd5\x37\xec\xf8\xe3\xfa\xde\x3d\xd2\xb7\x94\x1c\x2e\x7a\x5a\xd3\xc5\x44\x9d\xa2\xad\xd3\xd9\x2a\x46\x23\x65\x94\x5c\xa9\xca\x0d\xa6\xe1\x68\x45\x65\x05\x9d\xde\x36\x2e\xcb\x45\xe7\x6b\x5e\x92\x87\x0e\xf0\x72\xd6\xe1\xf1\x1a\x4b\xed\x30\xdd\x16\xed\x6a\x0a\xf7\xae\xd4\x5b\x2c\x5e\xaf\x8b\x95\xda\xfe\x0b\x26\xfb\xb2\x67\x7d\xf6\x93\x88\xa9\x5a\xef\x23\x7c\x51\xac\xd0\xdb\x55\x14\x59\x90\xdd\xf4\x35\xc5\xe7\xd5\x6a\x7b\xab\x51\xa1\x49\xc9\x0f\x4d\x55\x06\x3b\x14\x4d\x85\x58\xb3\x47\x95\x4f\x45\xc4\xd9\x99\x75\xfa\x41\x50\x41\x13\xe1\xdc\x8f\xa3\x50\x2c\xc2\x91\xa0\x0f\xfd\x0e\x26\xf6\x13\x51\xbe\x5c\x84\xb3\x02\xf5\xdf\x8b\x8c\x1c\x9e\xcc\xfa\xde\x00\x6b\x0a\x33\x67\x33\x67\x67\xa6\xde\xf8\xe1\xa0\x6b\x39\x4b\x97\xb6\x14\xae\x9b\xc3\x7d\x32\x43\x0c\x51\x15\x47\x52\xc6\x7f\xdc\x9f\xb5\x7d\x56\xbc\x32\x02\xbf\x0b\x06\xfb\x9c\x46\x3e\x5f\x77\x3c\x5d\x4d\xf0\xb1\xbc\xee\x03\x86\x74\x5c\xf1\x8a\x43\x80\x7f\xd9\xea\x91\x47\x24\xa8\xc0\x98\xda\x9d\x08\x1d\xa9\x2f\x7e\x15\xe9\x6b\x73\x10\xa1\x7d\x93\x94\x45\x9c\x95\x0c\xa8\x78\xfb\xd0\xcd\xd7\xbc\xcb\x14\x2a\x2f\x64\x59\x3d\xb6\xf7\xce\x0a\x8d\x86\x03\x11\x1a\x46\xa4\x56\xde\x7d\x2a\xb9\x6d\x15\x91\x33\xe1\xd7\x25\x87\x77\xb3\xfe\xb7\x99\xf7\xac\x3f\xe4\x73\x55\xa2\x49\xa5\x73\xcd\xf7\x0c\xf6\x22\x84\x35\x60\x6c\x38\x9c\x21\x2c\x00\xa9\x81\xb7\x5b\x04\xe4\xd5\xf8\x61\xe7\xf0\x9e\x9f\xbc\x0a\xaa\x77\x26\xa0\x97\x80\x33\x10\x05\xf8\x2d\xcb\xce\xe1\x83\xe1\x88\x56\x05\xf5\x31\xad\x7e\x16\x47\xb5\xfa\xad\xce\x6b\xf5\x4b\x2b\xbc\xe9\xdf\x26\x29\x4f\x0e\xcf\x66\xdd\x3a\x53\x05\xbe\x7d\x98\xc1\x75\xb5\xb3\x3d\x5f\x04\x41\x28\xfb\xe3\x09\x1b\xbf\x6c\xe2\x9f\xed\x7a\xbf\xea\x89\xeb\xcc\x47\x32\xd3\xae\xcf\x89\x55\x46\xf5\x06\xd1\x66\x34\xdf\xf7\x2d\x9e\xc2\x11\x4f\xe4\x66\xe1\x2d\xbc\x9e\xc1\xee\x4c\x0a\x6f\xa9\xdc\x91\x5f\x56\xef\x82\x08\x1d\xcc\xe0\x70\x06\xf5\xad\xa0\x10\xd5\xb8\x0d\xbe\xb6\xf7\x67\xa7\xc7\x3e\xa1\xb3\xc7\x27\x71\xe9\x23\x6a\x8b\xa0\xfe\x8a\x12\xe1\x8a\xd3\xc0\x22\x65\x52\x73\x7b\xae\x1c\xf2\xd5\x5f\xa6\xb5\xc3\xbe\x44\x07\xfa\xda\xf1\x93\x7f\x17\x24\x38\x4a\x06\x6c\x8e\x07\x4b\x3f\x65\x92\x10\x27\xb6\x8e\x2d\xc7\x5b\xca\x6d\x78\x6a\x04\x07\x60\x97\x8e\xf4\xea\x3e\x2a\xb9\x55\x3a\x8a\xc2\xca\x72\x95\x80\x2a\xd2\x4a\x84\xac\x64\xca\x94\x0a\x72\x8a\xbc\x4b\x1f\x70\x81\x30\x22\xe5\xeb\xac\x88\x5a\x0d\x74\x24\x73\x2a\xc8\x23\xca\x1c\xf8\x40\x47\x3a\xa9\x82\x2b\x11\xfa\x0c\x5f\x78\x6f\x3a\xc5\xe6\x57\xe1\xd5\xb3\x83\xc4\xd5\x5d\x75\x4f\x54\x90\x41\xc3\x1c\x65\x7a\x6b\x7a\x1d\xdb\x21\xe9\xdc\x09\xc9\x50\x3c\x7c\xd6\x26\xf3\xba\x39\x99\x4f\x6b\x2f\xd5\xe0\x15\x43\x31\xfa\xc0\xa0\xa6\x29\xd0\xb8\x82\x97\x5b\x79\x3e\x83\x72\xce\x6a\x66\xac\x1c\x0c\xae\x00\xa2\xe6\x1c\x49\x4d\x2e\x10\xfb\xea\xb0\x02\x0a\xbd\x86\x3e\xfa\x00\xef\x66\x9c\xf6\x55\x36\xac\x5d\x9d\x96\xaa\xa6\xdb\xd7\x15\x2f\xfd\x12\x11\x22\xf4\x75\x56\xbc\x4f\xeb\xa5\xaa\x10\xd1\x17\x33\xf7\x7a\x46\xe8\xc2\xf9\x30\xab\xf8\x74\xaa\x72\x8b\x39\x7c\xee\xe3\x09\x45\x65\x56\xa9\x4b\x75\x55\xa9\xe2\xb0\xca\xbf\xd4\x2d\x6f\x71\x05\x06\x54\x2f\x71\xbd\x7e\xbc\x94\x4f\x29\x45\x86\x0a\x02\xd4\xcf\xa1\x2a\x36\x6e\x47\x8c\xab\x22\x0c\x59\x93\xf3\x2b\xe5\x21\xdd\x87\x81\x16\x94\x61\xad\x56\xf2\x84\x92\x85\x92\x66\xa7\xdb\x49\x78\x1c\x2d\xaa\x3c\x2e\x78\x9b\x72\xcc\x2c\xee\x67\x96\xcd\x0d\x36\x0e\x5d\x1a\xf7\x88\xc6\x2a\x37\x9f\x52\x7c\xd2\x53\xa1\x87\x55\x4e\x62\xb7\x94\xdd\xf2\x1c\xdd\x6e\x0e\xa4\xc8\x92\x50\x2e\x73\x82\x9e\xbe\x2a\x32\xe9\x52\x4c\xb2\x02\x22\xb5\xd7\x0d\xb1\xfa\x0d\x68\x78\x3d\x1d\xbe\x97\xec\xa0\xae\xfe\x9e\xa3\x51\xd1\x73\x74\x9b\x9e\x2b\x55\x4b\xe6\x67\xfd\x9e\x5f\xfa\x8b\xb2\xe3\xf4\x36\x1d\x97\x35\x8b\x7e\x67\xb1\xdb\xe8\x65\x47\x6e\x3b\x2b\x87\x78\x25\xf8\x75\x59\x3d\x9a\xb0\xdd\x9a\xde\xd0\x56\x0e\xcb\xd5\xed\x15\xa5\x75\x8b\xf3\x56\x8b\x62\x3b\xe4\x70\xbe\xb2\xb1\x5d\x45\x21\x8a\xb6\x16\x2b\xab\xec\x09\xea\x52\x54\x38\x59\x59\xe1\xa8\xd0\x1f\x50\x55\xa6\x3d\x55\xe4\x83\x42\xed\x9d\x2a\xcf\xe1\xaa\x98\xe1\x76\x18\xea\xcc\x1c\x8e\x63\xa3\x91\x9b\x6e\x90\x5f\x84\x4f\x1c\x06\xd9\x52\x98\xa7\x53\x38\xc7\x34\x8d\x48\xb2\x9f\xcc\x08\x3f\x6a\xe2\x2c\x65\x98\x4a\x65\x74\x29\x2e\xb9\x88\xdd\x15\xc2\xe4\x29\xf5\x93\x60\xee\x30\x98\x66\x51\x1c\x0a\x5b\x78\x2a\xbf\xdf\xa5\x42\xf5\xed\x84\xbc\x97\xbd\x38\x09\xf0\x5d\x2c\x3e\x89\xee\x5a\xca\x93\x4f\xe3\x6e\x42\xa7\x28\xb0\x92\x5e\x51\x58\x62\x71\x30\x0a\x31\x47\x27\x1e\xab\x4a\x7e\x18\x52\x9c\x2a\x6f\x89\x97\xb1\x7b\x2d\x5b\x11\xf3\xe5\x67\xd3\xe3\xb8\x7a\x45\x94\x13\x17\x77\xfc\x1c\xb6\x7b\xd6\x84\x13\x49\xad\x5d\x22\xd7\xe3\xa5\xa9\xb4\xc9\x1c\xde\xa0\xc4\x5a\x24\x25\xed\x24\xd2\x4e\x0a\xda\x49\x59\x3b\xc9\x6b\x27\x45\xed\x24\xbf\x9d\x94\xb6\x93\x66\xed\xa4\xb8\x29\xd5\x39\x90\x8f\x90\x69\x29\x27\x29\xdd\x3c\x3e\xe1\x87\x3c\x96\x07\xbb\x28\x97\x00\x25\xd2\x5d\x99\x14\xde\x39\x81\x5e\xde\x0c\xa6\x7e\x8a\x5f\xfb\x6c\xee\x78\xe0\x2f\xa3\x77\x34\x76\x22\x88\xa3\x29\xff\xf0\xa1\x08\x6b\xb0\x73\x74\xe4\xa4\x30\x23\x09\xdb\xbe\xc0\x29\x59\x60\x9e\x30\x03\x75\xeb\x14\x14\x81\x50\x27\xae\x07\x23\x83\xb7\x3d\x6b\x7a\x84\xd9\x6e\xad\x76\x29\xb0\xe9\x3b\xed\x6a\x23\x38\x20\x7e\x58\x15\xdb\xf4\x54\x7c\x5c\x99\x49\xa3\xda\x4e\x5c\xea\x75\x86\x11\xc5\x01\x2b\x1e\x01\xce\x8a\xac\x97\xfe\x79\x74\xc2\x09\x1b\x51\x98\x98\xc3\x93\x3e\x8c\x2d\x8b\x97\xeb\x55\xf4\x78\x70\x9b\x9a\x7c\x35\x5f\x56\x0e\xe9\xfd\xdb\x56\xde\x0b\xa3\xb2\xeb\x57\xb7\xa9\x5d\x13\xbf\x3d\x37\xc0\xe2\x25\x61\x4f\x48\x26\xdc\x98\xbd\x5e\xab\x61\x05\xd9\xe2\x75\xb7\xa7\x92\x14\xfa\x36\xf6\xfd\xbb\xd5\x15\x0c\xf0\x7e\xbf\x6e\x2d\x0e\xae\xa2\xd6\x87\x75\x6b\xd5\xc0\xf4\x6c\x65\xad\x6d\xbd\x2f\x8b\x3a\x5f\xe2\x4a\x5c\x8f\x03\x7c\x8e\xe3\xb7\x44\x3a\x8d\xfb\x5a\xe4\x48\x40\xe8\xf4\xa7\x7d\x3b\xab\x1c\x95\x2c\x5e\x3c\x96\xae\xae\xc4\x87\x55\xaf\xf4\x69\x75\x25\x85\xa1\xf5\x7a\x2f\xd6\xab\x27\x9e\x6d\x6b\x15\x3f\x97\x78\xa6\xb0\x4b\x4f\xfa\xe3\x2a\xae\x36\xad\xb7\xf4\x83\xf1\x90\x38\xf0\xcc\x3a\x6b\xc4\x28\x58\x61\x23\x6f\x2c\xec\x37\x99\x9d\xdb\x79\xcb\x88\x67\xd7\x83\x37\x31\x1c\xa7\x46\x33\x9a\x5d\x0f\xbe\xc6\xf0\xb8\x33\xf3\x53\x0c\x47\x9d\x99\x4f\x63\xb8\xe8\xcc\x7c\x11\xc3\x69\x67\xe6\xc7\x18\xae\x3a\x33\xbf\xc4\xf0\xce\xeb\x88\x6c\x67\x03\x0b\x8d\x2e\xd5\x5e\x56\xa3\x46\xff\xf1\xc7\x96\x65\x03\x1b\xcd\xfd\x74\x2e\x7c\xab\x95\xa2\x4c\xe9\xd9\xed\x53\xe9\x6b\xad\x19\x15\x84\x43\xd3\xb1\xac\x1c\xd9\x90\xb4\xdc\x7e\xe2\x33\xf4\x05\x51\x1b\x36\xed\x4a\x4b\xac\x1a\xf9\xb8\x15\x63\xa4\x50\xaa\xdc\xb2\x40\x44\x0a\xe1\x8d\xab\xc2\xa2\x17\xe1\xea\xc5\x83\x1f\x62\x28\x24\x00\x0c\xae\x53\xec\xd3\x60\xee\x24\xc0\xe7\xe0\xe0\xbc\xdd\x03\x91\x3d\x10\x3e\xde\xcf\x71\x0e\x34\x34\x9b\xc0\x4f\xe1\x7d\x53\x0f\x76\xce\xd8\xd2\xb9\x77\xcf\xa4\xe9\xaa\x23\x0b\xb5\x15\x5e\x21\x42\x53\x58\xca\xb0\xd0\x80\xc3\x16\x9b\xc5\x9c\x19\xa1\xe8\xd1\xa3\xc2\xf2\xf9\x51\x19\x98\x1c\xd7\x62\x7d\xd3\x47\x85\xf4\xac\x70\xc9\x13\xcd\x10\x0d\x51\xa2\xe0\x1a\xb8\xf4\x51\x33\x06\xbc\x0c\xc8\xae\x6c\x02\x83\x32\x82\x3b\x73\x09\xd0\x86\x41\x83\x10\xad\xb5\x67\xf7\x9a\x55\x8c\x6f\x03\x1d\xf8\x78\x60\x49\x1d\xd7\x60\xe4\x4d\xf2\xfc\x51\x40\x12\x16\x25\x19\x1e\xb0\xfc\x76\x4d\x4b\x6f\x37\xe2\x3e\xb4\x76\x23\x34\xcf\x71\x9c\x62\x31\xe9\xac\x9c\xf4\x1d\xd7\xcd\xe4\xf4\x4c\xb5\x5f\x97\xb5\x1f\x89\xda\x15\xc0\x64\xfd\x80\xa9\x41\x20\x53\x10\xa8\x5b\x8c\x26\xca\x7a\x3c\xe3\xe0\x58\x35\x91\x5a\x7b\xaa\xb6\x9a\x97\xd8\xad\x89\x11\x29\x29\xaf\x85\x43\x38\xa1\x88\xd9\xf5\x18\x65\x39\x10\xd3\x06\x7f\x4b\x51\x5f\x4c\x03\xe6\x44\x68\x8f\xc2\x15\x13\x2f\x46\x22\x86\x81\xfc\x98\xd8\x39\x04\xc6\x31\x74\xc5\x1c\xe2\x44\x7a\x20\xfe\x1d\x5e\xf8\x34\xe1\xfd\xac\x11\x03\x88\x84\xc2\xac\xa0\x1d\x9d\x22\x0b\xdd\x95\xd1\xf9\x1e\x9b\x06\x32\xf3\x07\x33\x7f\x18\x90\x13\xfe\x27\x5d\x46\x09\xff\x7b\xff\x92\xff\x3b\xbb\x7d\x50\xa4\x6a\x60\xb8\x4a\x27\x29\x1d\x92\x24\x5e\x1d\xfc\x23\x22\x48\x1b\xb1\x8e\x46\xa3\xfe\x38\x81\x45\x70\x86\xb0\x5b\xc8\x37\x88\xd0\x81\x61\x3c\x15\x54\xba\x18\x4e\xc6\xe3\x81\x05\xd4\x64\xfe\xf9\x86\x20\x53\xd0\x8d\x59\x50\x8f\xe0\xaa\x15\xf5\xab\xa0\xe9\xd5\x21\x18\x44\xe8\xa2\x7f\x58\x16\x60\xd3\x80\x5e\x34\x82\x11\x96\x91\x4d\x92\x9e\x01\xf5\x22\x40\xad\x53\x03\x6e\xf5\x47\x3a\x5c\x35\x4d\x13\xee\x57\x7a\x0c\x87\xb3\x18\x5f\x0e\xf8\x3f\xc3\x80\xc4\xd9\x22\x19\x34\x67\x6e\x8e\x63\xf1\xa4\x1f\xd3\x4f\x57\xc4\xa1\x6c\x87\x6b\x58\x2f\x24\xe5\xab\xe6\x74\xde\x98\x17\x64\x66\x5c\x90\x5e\x50\xfe\x5f\x07\xcb\xd6\xc6\xfc\x8b\x61\xd9\x25\x3c\x92\x47\x60\x30\x6a\x3c\x97\x6b\x4b\xfc\xac\xfa\xf2\x2c\x15\x0a\x9c\xef\x58\x82\x32\xe2\xe5\x60\xee\xa7\xc3\x54\x9a\xf6\xff\x73\x56\xa6\x1d\xe3\x64\xbd\x95\x69\x5a\x60\xbf\x21\x28\xd0\xcf\x32\x2b\x97\x47\x47\x5c\x09\x8c\x91\xac\x8b\x20\xa0\xfc\xbc\xa7\x24\x1e\x54\x7f\x68\xe8\x18\x02\x46\xae\x5c\x70\xb3\x63\x84\xef\x5c\xb1\xff\x5d\x25\xb9\x30\xdf\xb4\x20\x2d\x4f\x1d\xdf\xbd\x79\x42\x3f\x39\xc1\xf4\x7f\x57\xc5\xb8\x77\x24\x70\x6e\xb5\x52\xfd\x51\xa1\x6a\xad\xcf\x30\x0e\xa7\x7e\x70\xba\x0e\x07\x97\x19\xe3\x54\xb6\xc7\x25\x9d\x90\x44\x61\xb7\xd6\x49\x75\x15\xab\x23\x7b\x38\x08\xa3\xe9\x60\x31\xdd\x1c\x2c\xe8\xe6\x40\x21\x8e\x1f\x47\x27\x89\x08\xe3\x9c\x0e\x03\x9c\xac\x13\xd7\xce\x70\x08\x3d\x25\xc8\x0a\xe6\x38\x38\x9d\x92\x4b\x53\x10\xb9\x1f\xcc\x87\x54\xba\x06\x4b\xb8\x36\xb7\xbc\x8c\x87\x9b\xeb\x00\xba\x7e\x23\x32\xdd\x0b\x8c\x07\xa3\xdf\x0b\x71\x13\x63\x6a\x62\x82\x97\xc6\x19\xdf\x96\xe5\x94\xb7\x8f\xfb\x2d\x06\x7c\x3d\xd6\x33\xed\xb8\x71\x99\x2d\xe2\x4a\x8d\x1b\x5a\x51\xae\x69\xfa\x3c\x6a\xcd\xff\x05\x41\xa6\xbd\xfb\x99\x20\xcb\x9b\xc6\x7e\x62\xd8\x13\x86\xb5\x6a\xc3\xaa\x50\xc9\x89\x88\xd6\x3f\x4c\x42\xa9\xb3\x34\x6b\x4b\x3d\xb4\xac\xa3\x7d\x35\xc5\x5a\x02\x64\xc4\xa5\x29\x4b\x06\x53\x96\x0c\xd3\xc5\x60\x7a\x32\x9c\xf9\x21\x0e\xe5\x6f\x11\x29\xc2\xa7\x57\x83\x05\x1d\x6e\x0e\x16\xd3\x06\xca\xa9\x26\xd6\x0a\x74\x97\xa5\x98\x0e\x53\x6d\xc2\x32\x71\x2c\x86\x2f\x8d\x01\xee\x4d\x95\x87\x0b\xf2\x75\xf8\x7d\x2d\x5c\xe0\xe9\x69\xc4\xd6\x68\x44\x13\x9e\x35\xd6\xcb\x40\xff\x9d\x8e\x80\x93\xdf\x09\x62\xbe\x91\x8c\xd1\x10\x5b\x7b\xc9\xb8\xc0\x7c\x92\xc3\x45\x26\xec\x72\x57\x93\x8c\x75\x8e\xb5\xdc\x86\x38\xec\x79\xcc\x1d\x44\xe8\xca\x34\x92\xc4\x3f\x6f\x47\xd1\x37\x8d\xa3\xb0\x7d\xee\x42\x5a\xde\x52\x1c\x25\xa7\x03\x65\xa1\xd1\x6e\x30\xe1\xab\x61\x22\x55\x45\xdd\x2e\x50\x9b\xe4\x27\xbc\x3d\x13\x18\xc2\xb0\x2b\x14\x89\x8f\xde\xf5\x6b\x8b\x1a\x82\xf5\xe6\x85\x43\xd6\x65\x4f\xbb\x35\xa7\x87\x55\xa8\xfb\xe8\x1c\x03\xe5\x84\xc4\x20\xb3\x3f\xa8\x7a\x5a\xd0\x7b\xb7\x05\x35\x11\x3f\xf7\x36\x3a\xae\xc2\x89\xac\x50\xb7\x4a\x44\x2c\x60\x2c\xc7\x3f\x37\x89\xce\x98\x56\x8c\xdc\xb2\xdc\xff\xb2\x1c\xcb\xb5\x4a\xa2\x7a\x49\x81\x36\x3d\x03\x08\x2d\xcb\xf6\x1a\x9d\x22\xd6\xe6\x97\x8a\x88\x8a\xe7\x1d\x14\x5f\x79\x80\xe2\xa4\x7f\x1e\x4a\xd1\xf1\xa2\x76\xcc\x35\x31\x38\x6c\x68\xfb\x26\x15\xfd\x38\x11\xc2\x95\xd9\x5b\x18\x25\xb6\x93\xe4\xb6\x9c\xfc\x49\xbf\x9c\xa9\x72\xe6\x94\xc9\x0c\x61\x7b\x8b\x3a\x38\x97\x70\x8b\xd0\x33\xd3\xc3\xca\x15\x3a\x90\x74\xff\xcc\xb6\x61\xda\xa6\xfd\x75\x79\x37\x7d\x74\x5d\x4a\x6f\xeb\x02\xef\xb3\x52\xe0\x2d\x24\xdd\x32\xbc\xcb\xc8\x1b\x73\x88\xa8\x32\x9f\x50\x62\x3f\x62\x2e\x03\xea\x26\x82\x16\x5e\x75\x80\xd4\x0b\xc0\x3a\xc5\x57\xd9\x52\xf9\x8f\x60\x90\x04\xc2\x1b\x42\x7f\xf9\x90\x5c\x24\x8d\x1a\x17\xa1\x7b\x5d\xd8\x00\x3b\xbf\x82\x60\xce\x9c\xc9\x7d\xc8\x96\xce\xfd\x5f\x81\xd7\x70\x1e\x8c\x73\x38\xbd\x8d\x00\x35\x20\xf1\x20\x20\xf1\xd0\xcf\x18\xf9\xd6\xc0\xa7\x9c\x4a\xcb\xeb\x85\x99\x42\x9b\x9b\xea\x3d\x04\x48\xc6\xe2\x28\xc1\xc3\x28\x99\x91\x0e\x12\x14\xa1\xc3\x14\xee\x8c\x4d\x0c\x9b\x89\xc9\x4b\x8d\x12\x5f\x13\x33\xb9\xd6\xc0\x0c\xf7\x84\xe6\xd0\x26\x6b\x0e\xcd\xfa\xff\xfe\xdf\x35\x45\xb4\x2d\x71\xf5\x51\x27\xe7\x76\x1a\x8a\x98\x05\x97\x1d\x38\x93\xc3\x63\x23\xf1\x11\xfa\xb0\x5a\xb1\x52\x28\xf7\x56\xdc\x0a\x00\xe9\x8c\xfb\xc0\xe0\x32\x1c\x15\x1d\xd9\x5b\x7b\x29\xba\x33\xb1\x9d\x97\x69\x0e\x81\x7b\x12\x72\x02\x98\xb9\xcb\x54\xdc\xd3\xaa\xcf\x74\xd5\x36\x12\xe1\xd4\xda\xb2\x9c\xe2\xcd\x2c\x53\x2e\x92\x2a\x22\x1f\xcb\xb1\xca\x3b\xac\x78\x90\xab\x3b\xaa\xd3\xdb\x55\x0c\x48\xcc\xb6\xd8\xb2\x9c\xb4\xbf\x4c\x05\xf5\xde\x49\xd1\x9d\xb1\x0d\x99\x6d\x3f\xaa\x55\x28\x67\x50\xb6\x24\x86\xd5\xa3\x91\x4e\x47\x4d\xc3\x7c\xf1\x3a\x65\x0a\x74\x8f\x95\x7e\xfa\x9d\x89\xd2\x57\xaf\xc4\xb7\x2f\x03\xcb\x6b\xc4\x56\xda\xea\x02\x8a\x6a\x0a\x7b\x62\xdc\xfa\x17\x87\x6e\xea\x0a\x7c\x33\xcc\xcc\x86\x99\x2b\x5d\x13\xc3\x59\x3d\x50\x75\x1b\xbb\x29\xb9\x18\x24\x64\x78\x92\x31\x86\x69\x5a\xbb\x03\x0a\x25\x5c\xc3\x76\x2e\x6f\x1f\x47\x62\x79\xd7\xa1\x14\x95\x1b\x0b\xa7\x3b\x16\x78\x26\xe9\xfc\x5a\xcc\xf2\x22\x4a\x86\x17\x51\xc8\xa4\xa7\x6c\x6b\x73\x3c\x5e\x5e\xfe\x75\xe1\xa0\xa3\x64\x99\xb1\xa1\xf2\xeb\x72\xfb\xdb\xef\x33\xa2\x7d\x97\x0c\xa7\x3e\x1d\xaa\x2d\x64\x22\x16\xbd\x22\xa2\x52\xf6\x61\x12\x6f\x1c\x87\xc8\x37\x24\x5f\x85\x46\xa9\xc7\x2c\x40\x6f\x53\xf3\x2b\xfd\xb7\xdd\xae\x2b\x20\x1a\x4e\x59\xf2\xbd\x04\x7f\x49\xa3\x85\x4f\xaf\x4c\xf3\x67\x01\x9a\x99\x64\x05\xab\x5f\x6a\x08\xb2\x36\xd6\x20\xad\xfd\xb4\xb6\x18\xff\x51\xa7\x78\x87\x5f\x1e\x06\xb7\xbb\x41\x58\x3b\x59\xca\xc8\x62\xa0\x70\x03\x06\x78\x74\x32\x32\xcd\x7e\x05\xdc\x04\x7f\xaf\xae\x4d\x72\xdb\x4e\xfd\x14\xf3\x23\xaa\xe3\x6c\x7a\x9b\xa2\x7f\xc7\xc9\xb9\x6b\x2d\x29\x09\x33\x41\x37\xad\x7f\x5f\xeb\x9c\x32\x54\xfb\x86\x53\xcb\x00\x7e\x3b\x87\xed\x8e\x83\xcc\x78\x37\x31\x31\x09\x83\x29\xa1\x21\xa6\xc3\xb1\x69\xda\x2f\x6a\xa4\xa7\xe2\x08\xc8\x28\xee\x31\xad\x96\x50\xc8\x32\x9d\xc0\x2f\xdb\x7c\x66\x61\x32\xaf\x5c\x39\x0b\x6b\xed\x9a\x21\x9e\x32\x1e\x77\x4a\xc9\x85\x65\xe9\x98\x2e\x35\xdb\xfa\xc1\xad\xb8\x91\x5e\x18\x2c\x03\xf4\x2e\x46\x11\x3a\x9a\x09\x8f\x48\xeb\x4d\x5b\x8e\xd4\x30\xf1\xb6\x58\xfa\xbf\x75\x9c\x52\xc5\xda\xb4\x40\xb9\x0d\x6f\x4d\x9c\x4e\x53\xba\xd5\x7d\xeb\x2c\x2e\x58\xea\x42\x95\xe7\xc0\x4a\x13\x1c\x21\x0e\xd3\x0b\x2a\x14\x89\xda\xab\xfe\xd7\x63\xf3\xa5\xd9\xd3\x9b\x01\x32\x6f\xb1\xb4\xad\x31\xad\x61\xaf\xcb\xb9\xca\x36\x31\x28\x1e\xb1\x51\x14\xb6\x53\xa5\x97\x30\x83\xa4\xa8\x47\x2e\xf8\xad\x20\x58\x43\x6a\xca\x11\x58\xb8\x2d\x33\xec\xdb\xbd\xfe\xbb\x77\x90\x3a\x59\x0a\xd8\x7d\x17\xa3\x2b\x61\x6a\x26\xf8\x79\xe9\xc6\x55\x22\x44\xc5\x97\xab\x46\x0c\xdb\xae\x4c\x74\x16\xc2\x01\x1f\xe4\x5c\x09\x23\x0f\xdb\x84\xa2\x28\xbb\x42\x22\xa5\x08\x7b\x8a\xe3\x99\x12\xc9\x8b\x8b\xd6\xed\x64\xdb\xac\xa1\x37\x54\xfe\xda\x16\x01\x58\x2b\xb9\x30\xb0\xe0\x25\x4f\x14\xff\x99\x24\x3a\x3b\x5d\x93\xb9\x0e\x62\x92\xe2\x43\xe9\xbc\xde\x39\xe0\x5b\xf9\x78\x66\xdb\xc0\xd9\x1b\x3f\x4a\x30\xdd\x89\xfd\x34\x75\xce\x54\x70\x03\xe1\x76\x7a\xb9\xe2\x0d\x49\x6d\xaf\x81\x36\x10\x32\x1c\x20\x32\x36\xc2\x01\xe2\xa5\xb7\x29\x1e\x5c\x91\x6c\x90\x66\xea\xe3\xc2\x4f\xd8\x80\x91\x81\x74\x39\x32\x60\xf3\x28\x1d\x28\xd4\xde\xb2\x38\x9b\x4c\x08\x53\x43\xe9\x17\x4c\x1a\x9e\x55\x1b\x44\xeb\xf4\x36\x44\x4b\x79\x35\x30\xcd\x47\xd8\xe3\xf7\x20\x4c\x4b\x70\xb8\x16\xcf\xbc\x24\x69\xa4\x2c\x63\x26\xd2\xbb\x66\x14\xf4\xf3\xcc\x15\x28\xb4\xee\x04\x83\x38\x4a\x35\x03\xc8\x93\x8b\x0d\x3b\x58\x0e\xc7\x83\xc5\x74\xf8\x60\x0d\x89\xbe\x99\xfd\x96\xda\x44\x8b\xe9\xd0\xf8\x2a\xd5\x75\x23\x69\x30\xbc\x06\x7b\xf8\xae\x03\xb9\x75\xe8\x1e\x86\x60\xed\x25\x61\x6a\x95\x86\xb4\x46\xf7\x36\xaa\xa8\x34\x07\xe2\x85\xb5\xc9\xa2\xe1\x80\x14\x6d\xaa\x83\xa2\x6c\x36\xe7\x57\xd8\x16\xc0\xb7\x43\x44\x47\x51\x68\xc8\x79\x1b\x1a\x1f\xce\x22\xf4\x32\x04\x0a\x77\x26\x26\x16\x7f\xfd\xc7\x4a\xe3\x3d\xef\x33\xec\x85\x55\xab\x53\xd3\xa8\x22\xc4\xb6\x84\xf0\x54\x8d\xc2\x76\xce\x8c\x4f\x95\x36\x3c\x09\x1b\x3a\x89\x8b\x59\xbb\xbd\x73\x43\xda\xb2\x65\xbb\x9e\xe7\x70\x60\x92\x4e\xca\x88\x60\x49\x11\x76\xb1\x2f\x28\x84\x81\xeb\x14\x9e\xf4\x83\x10\x59\x2f\x89\xa6\x13\xe9\x60\x26\x8c\x12\x6c\x27\x42\xe7\x81\x01\x70\xe5\x5e\xe8\x00\xe1\x9a\xbc\x86\x3c\x55\x23\x74\x16\x82\x12\xa0\x1e\x20\x9e\x6a\xdb\xc0\x71\x45\x88\x64\x5b\xde\x80\x3b\x1c\x45\xb0\x91\x1e\x7d\xfe\xbd\xbe\xb0\xcd\xcd\x33\x7f\x9a\x4b\xff\xd8\x44\x45\xb9\x51\xbb\xe4\x89\x1f\xc5\x19\x2d\x37\x54\x10\x22\x62\x0a\x3b\x92\x85\x1c\x39\xf7\x7b\x1e\x52\x53\x14\x87\x80\xc1\xa8\x48\xff\x2e\x46\x53\xe5\x9d\xa0\xa5\x31\x5e\x38\xa4\x18\x73\x9e\x6c\xab\x45\x7c\x49\x88\xd2\x99\x08\xea\xd7\x5c\xad\xe6\x46\xe9\x28\xdb\x7f\x39\x9e\xfa\xe1\x09\x1e\x88\x7f\x87\xcb\x28\x8e\xc9\x85\xfa\xa1\x00\xa0\xe8\x99\x38\xe2\x19\x59\x0e\x16\x6b\x3e\x55\x9f\xae\x12\x62\xaa\x7d\x81\x84\x7b\xdf\x57\x5d\xef\x9f\x3d\x91\x56\x22\x34\xed\x78\x0e\x1a\x24\xfe\xf9\x90\xf9\xd3\xb4\x83\xb6\xd7\xd1\xbc\xed\x1a\xc4\x47\xfb\x21\x30\xc0\x23\xe1\x1f\x0a\x30\x47\x1f\x3b\x57\x51\x2d\x9c\xef\xec\x37\x92\x8d\x8f\x39\x7d\x11\x73\x7f\xde\x2d\xde\x64\xfe\x54\x48\x36\xf5\xee\x30\xc9\xc6\x8c\xca\x2e\x46\x92\xd9\x31\xa8\x66\x5d\xa3\x06\x46\xd7\x5b\xe6\xa7\xd5\xf2\xa3\x4e\xae\xe2\x89\xf2\x99\xbb\x96\xa8\xdb\x23\x1d\x1b\xeb\x4a\x6d\xac\xc7\xfc\x20\x2a\xfc\x73\x99\x9c\x4b\xb7\x9b\xf5\xd1\x49\x00\xaf\x42\x41\x8b\x0d\x62\x1b\xb4\x08\xe0\x80\x1f\x28\x66\xd7\x51\xcd\x6a\xc5\xd1\x01\xaf\x3b\x64\x04\xc6\x57\xd4\xc5\x74\x73\x70\x31\xfc\x75\x3c\x8c\x07\x82\x9b\x18\x9a\xde\x53\x57\xba\xb9\x9f\x85\x70\x56\x0d\x3c\xd2\x50\xbf\x77\x2d\xe9\x0b\x98\x43\x8a\x8d\xa4\xa7\x75\xfe\xbd\xdb\x31\xd2\x13\xd3\x48\xf9\xd1\x31\x58\xfa\x63\x39\xce\x8e\x51\xbe\x56\xaf\x71\xef\x8c\x68\x6d\x0c\x72\x55\x9c\x74\x6d\xf5\x8c\x37\x08\x8b\x10\x6a\x9d\xbc\xd7\x1a\x08\x7d\xfe\x7d\x8a\x61\x95\xc3\x35\x1c\x14\xbe\xb5\x6f\x2d\xa9\xb3\x7b\x59\xc8\x7f\xfc\x34\x2a\xc8\x70\x54\x9f\x8d\x33\xb0\xe0\x14\x7d\x11\xe7\xc6\xed\x26\xa6\x5a\xdf\x0d\x4d\x77\xdc\x2e\x0d\xcd\x8a\x08\xa9\x19\xbe\x2a\x0b\xd7\x53\x22\xfc\x56\x63\x0a\x6a\x54\x54\xcb\x73\x78\x6f\x3a\xd8\xd5\xd3\x6a\xb9\xc7\x3c\x02\x41\x0c\xdd\x0f\x13\xdf\xfa\x2a\x19\x90\x78\xf8\xf3\xca\xca\x31\xf2\x42\x38\x20\xd2\xf3\x24\xa4\x31\xe7\xae\x7d\xf1\x6f\xa2\xfc\x17\xad\x43\x47\xff\xb2\x01\x44\xa2\x6b\x4f\x0d\xc0\xfc\x80\x7f\xbb\x11\x7c\x8f\x62\x9f\x8f\xa2\x10\x2c\xe5\x31\x23\xd1\xc2\x11\xc8\x62\x64\xb4\xf3\x60\x5b\x3e\xf2\x43\x28\x2f\xcc\xa5\xe6\x8e\x7a\x60\x06\x6b\xe6\x0f\x19\xf5\xd3\xf9\x90\x58\x30\x15\xed\x38\x91\xf1\xe2\x61\x54\x75\x14\xb1\x01\x43\x77\x4d\x69\x63\xff\x85\x3d\x89\xd7\x3a\x4f\x95\xdf\x92\xc1\x76\x27\x8d\x7a\x66\xa2\xc9\xad\x37\xce\xa6\xa9\xa1\xf2\x24\x61\x69\xf7\x27\x56\x8e\x2a\xd2\x23\xe3\xfc\x38\x97\x38\x58\xe3\xc1\x64\x19\x20\xb2\xd6\xe4\x0c\x6a\x4c\x39\x7c\xe9\xd6\x9a\x5b\x27\xca\x5e\x95\x12\x35\xa9\xd4\x3b\x7e\x79\xed\xbc\x22\xe0\xee\x2b\xc2\xd7\x5e\x5d\xcb\x15\x4f\x8d\x94\x5c\x0c\x2c\xb0\x16\x8c\xef\xc6\xb5\xb7\xa3\xb8\xd3\x5b\xa0\x76\xb1\x31\x2e\x4b\x8c\x4e\x62\x15\x2e\x39\x46\xf3\x98\x5f\xd1\xda\x8b\x51\x34\x58\xfa\x25\x91\xfb\xb2\xab\xcd\xf3\x7a\x9b\x26\xa5\xc9\xa2\xcd\xbd\x24\x5c\x35\xc4\x45\xbd\xb9\xf6\x92\xcb\x6b\xf9\xd3\xdb\x28\x8d\x48\x50\xde\x82\x2c\x1b\xcf\xd6\xef\x54\x2d\xb7\xb4\x6b\xa3\xc1\x9a\xcc\xae\xf1\xa6\xb6\xd6\x5b\x9d\xdc\xfb\x03\x7f\x36\x93\x81\x35\xa7\x57\x35\x29\xe2\xba\x16\x76\x6b\x52\xed\xf5\xce\x3c\xe3\x85\x62\xbd\x23\x47\xb0\x5f\xfe\xc2\x24\x49\x35\x0d\xf2\x3b\x7b\x92\x6e\x8f\xbe\xfb\xa9\xb0\x0b\xab\x84\x0e\xda\xfb\x10\xe9\x30\x73\xcc\x86\x89\xfd\xf7\xb1\xdd\x78\xd9\x2b\x4e\x34\xe3\x01\x25\x0f\xa6\x65\x9c\xa5\x16\xdf\x28\x57\xb1\xe1\xa6\xc3\x69\xe3\x9b\xef\xa1\x43\xfc\xa6\xb8\x3e\x21\xfa\x60\x78\x5f\x79\x16\x1a\x75\xc8\xd7\x39\x2e\x7a\xf5\x95\xd6\x7b\x4b\x79\x8b\x53\x6c\x7a\x4c\x31\x13\x94\x4f\x66\xdd\x57\x25\x9b\x13\xb1\xb5\x67\x84\x2e\x20\x6b\x9a\xfb\x27\xed\x30\x93\x49\x2d\xf8\x66\x4d\xa6\xbd\x17\x46\x6c\x50\x3a\x2b\x9b\x38\x34\x46\x89\x50\x03\x37\x8a\xc0\x5f\xe2\x8b\x5a\xe9\x08\xb1\x18\x30\x50\x25\x87\x15\xf6\xd8\x90\xf2\x3f\x93\xb5\xc5\x02\xb3\x15\x84\xaa\xed\x1c\xc1\x88\x98\x5f\x43\x08\x4a\xbf\x8a\x81\x12\x10\x43\x50\x71\xd7\xd8\xaa\xf5\x34\x44\x41\xc5\x1d\x60\xf7\x41\x51\x78\xc4\x91\xd8\xd7\x71\x56\x2c\xcb\xb3\x22\x8c\x6d\x08\xaa\x4e\x1b\xcd\x6d\xbf\xe2\x6d\x6b\x6f\x60\xbd\x6d\xc7\x65\xdb\x33\xd9\xb6\x76\xfc\xb8\x2e\x5d\x5c\xf3\xd4\xf9\x12\x02\x19\x15\xee\x08\x81\x8c\xe4\x7d\xcc\x08\xf3\x37\x21\x30\x08\xc0\xa0\x18\x63\x92\xa3\x4b\xc4\x7e\xd1\xc5\x1f\x29\x89\xe9\x01\x67\x6a\xb7\xda\xc3\x0f\x29\x59\x86\xe4\x42\xb2\xe0\x9d\x2a\xd9\x86\x97\x97\x5a\xc5\x6f\xb6\x2e\x08\x32\x9a\x12\x19\xf5\xd3\x5a\x92\x48\xf0\xff\xeb\xbc\xfd\x2c\x03\xf4\x34\x45\x74\x44\x85\x6b\x5e\x03\x58\x6a\xfb\x04\x9b\xae\x87\xe6\x7b\x54\x6e\xc3\xe7\x6e\x21\x5d\x33\xfa\x48\x45\x17\x31\x05\xe2\xd2\x51\x11\xaa\x04\x02\x37\x42\x3b\x70\x12\xa2\xc4\x16\xa2\xf0\x08\x4d\x61\x1a\x02\x65\xc2\x65\x28\xb6\x6d\xc8\x44\x89\x4f\x8d\x02\x89\xcc\xf4\x7a\x94\x1a\x2f\xc2\x11\x87\xbc\xbd\xf5\x35\x45\x59\x11\x58\xf7\x22\x1c\x65\x4b\x91\x16\x54\xd3\xa4\xb6\xe1\xd6\xd3\x54\x08\xe8\x49\xb7\x58\x5e\x80\x32\x17\xd1\x1a\x9d\x0f\x69\x05\x80\xbd\xf6\x00\xfa\x12\x35\x58\xd0\xe1\x83\x01\xff\x0a\xc8\x62\x19\x63\x86\x87\x0b\x9c\x64\x83\x74\xde\xe0\x1b\x54\x1b\x61\x80\xbe\x08\xa5\x40\xd3\x1e\x96\x79\x93\x6f\x56\xc3\xab\x3f\x29\x52\x1c\xfb\x2a\xe0\x40\xab\x39\x53\x6d\x75\x51\x93\x95\x13\x92\x60\x83\x99\x89\x69\x23\xae\xa7\x81\xa7\x83\x60\x0c\x05\xaa\x74\x68\xd6\x99\x74\xe5\xfc\x00\x3d\x33\xd1\x8b\x59\x80\x3e\x99\xd2\x8f\xc3\x3a\x8d\xaf\xd2\x2c\xda\x90\x0e\xdf\x06\xb8\x61\x94\x2e\x63\x5f\x46\x38\xb4\xa6\x31\x09\x4e\xd7\x05\x6c\x45\x33\x72\x32\x1e\xff\xb8\x26\x58\xbf\xd9\xc6\xb1\xa0\x50\x02\x11\x6b\xbf\x86\x34\x3a\x99\x9b\xf5\x47\x3f\xc3\x0b\x21\xe2\x4a\x4c\x62\xe5\x1c\x3e\xb6\xad\x3b\x24\x7b\xc0\x77\x17\x15\x2f\x5a\xa6\x67\xb5\xc1\x81\x29\x88\xb9\x54\xda\xc8\x91\x8a\x45\xf7\xd1\x64\x65\xb0\xd6\x53\x18\x85\x8e\xf6\xe5\xa6\x46\xd2\xab\xae\x10\xfa\xdd\x72\x5f\x9b\xd0\xe4\x35\x41\x93\x7f\xa9\xad\xb9\x5a\x34\xb7\x0c\xd0\x1b\xd3\x26\x52\x27\xfc\x64\xf0\x5d\x5b\xe6\xd6\xa7\x5c\xa7\xe6\x68\x85\x71\x2f\x22\x60\x09\xb5\x99\x1d\xb0\xb6\xe3\xb8\x74\xbc\xd3\xdb\x32\x47\x99\x1f\x3a\x15\x39\xe4\x1b\x48\x11\x08\xea\xe6\x86\x1f\xb3\xd5\xa8\x57\x5b\x9f\x43\x44\x6d\x27\x42\x1f\x43\xe1\xf2\xbf\x88\xda\x25\xcc\x88\x96\xff\x60\x9d\xc9\xb6\x4b\x8a\x5b\x39\xc3\x11\xfd\x04\x73\x9f\xb2\x15\xea\x4a\x5d\xc4\x86\x20\xeb\x88\x64\xd4\xa4\xf2\x23\xa2\xbe\x2f\x8d\x2a\x5c\x05\xeb\x67\x0e\x56\xbf\xb5\x26\x80\xd6\x50\x55\xec\x51\x2b\x95\xa1\x90\xbf\x0b\x7c\x53\x1c\xc7\xc3\x34\xf6\xd3\xf9\x77\x80\xaf\x08\x3e\xda\x06\x60\x97\xe5\xdf\x37\xea\x23\x96\xef\x5f\x7f\xd1\xac\x87\xe4\xbb\xe7\x6d\xc6\x1b\x6c\xc4\x1b\x4d\xad\x9f\xc5\x08\x37\x34\xfe\xc4\xb3\x1f\x59\x3a\x59\x5a\x04\x33\xf0\x26\xb9\xb4\xe7\x33\xb6\x25\x38\x58\x6f\x22\x78\xd6\xaa\x51\xf4\x5f\x68\x3d\xb5\xd2\x4a\x59\x2e\x98\x38\x7d\x87\xe3\x2e\xe5\xf4\xdb\x90\xd6\x96\x5d\x70\x54\xc4\x64\x59\xeb\x44\x31\x5b\x28\xdf\xb6\x91\x2e\x23\xe5\x5b\xb6\xa3\xc0\x13\x90\x58\x9f\x16\xff\x16\x04\x06\x65\xb8\x35\xcd\x9c\x4b\x32\x90\x54\x83\xc4\xbb\xf5\x28\xf1\x3a\x3e\xfc\x5a\x52\xb7\x5b\xd9\x48\x17\x2f\x1e\x85\x40\xab\x43\xd0\xb3\x44\x06\x68\x24\xbc\x2c\xce\x4d\x97\x80\x2f\x85\x46\x41\x21\xf4\x14\xdb\xdc\xe4\x20\xe3\x1b\xad\x2f\xf8\x96\x24\xbd\x5b\x32\x42\x87\xfd\x12\x98\xb3\x4e\xfd\xd9\x84\x5c\x50\x7f\x0d\x1b\x9e\xea\x12\x8a\xed\x6e\x39\x06\x11\x9d\x71\xa1\x76\x6e\xf3\xfc\x9c\x86\x32\x5c\xbe\x11\x0a\xc1\xb2\x3b\x4e\x91\x16\x2d\x08\x5d\xb0\x2d\x03\x7a\x2c\x03\xf4\x2c\x46\x1f\x53\x74\x66\x54\x54\x5a\x49\xd9\x3b\x25\x12\xb7\x22\xdf\x8b\x28\xc9\xd2\x6f\xa7\xdb\xfb\x4d\x73\xcf\xf2\xac\xea\x9e\xb0\x86\xca\x37\x4d\xfb\x3b\xe7\xbb\x8c\xff\x11\xd3\xcd\x6d\xc8\xba\x0f\x96\x5a\xec\x95\x28\x2d\x02\x6a\x1a\xe5\xa3\x15\xc2\x2f\xc8\xdc\x00\x15\x01\xc8\x6d\xcb\x2c\x23\x95\x05\xad\x1c\x88\x9b\xf0\xad\x10\xf0\x3f\x15\x71\xa8\xe9\xe8\xa9\x45\xa3\x37\x29\xab\x0f\x2c\x20\xab\xdd\x0d\x55\x1b\xda\xf6\x11\x6e\xa9\xa5\x97\x3f\x5f\x8a\xec\xc0\xac\xa1\x0e\xde\xb2\x53\x2f\x34\x42\x27\x1d\xd6\xfb\xed\xa0\xe1\x11\x0a\xd8\x37\x6b\x4d\x4a\x7d\x8a\x44\x04\x5f\xd8\x4e\xa4\xa2\x64\xed\xea\x59\x30\xed\x77\x7c\x34\x85\xa7\x40\x85\xc9\x6e\x52\x30\x52\x7d\x37\xc8\xff\x55\xf8\x6e\x36\x9d\x2d\x8d\x66\x92\xfa\x5d\x28\x19\xf9\x49\x42\x98\x90\xa4\xa7\x36\x8c\xed\xbf\x8f\xb7\x22\x14\x2c\x05\x6a\xb4\x75\x10\x54\x6d\xb6\x44\xc9\xe8\x04\x27\x98\xfa\x8c\xd0\x77\x34\x36\x94\xa1\x4b\xa3\xdb\x48\x13\x5c\xa5\x27\x01\x38\x40\x89\xa6\xe3\x7b\xc6\xa3\xcb\x9f\xc6\x78\x50\x00\x65\xd2\x21\x3e\x21\x4b\xa8\xcf\xaa\x7b\x1e\x86\x67\xb3\xcf\x90\x2c\x4d\x7b\x52\xd2\x9f\xa8\xe3\x72\xf9\x7f\x9c\x13\x81\xdd\x5b\x38\x11\xe8\xf7\xd1\x78\xbb\x41\xad\x70\x20\xb0\xfb\xcf\x71\x20\xe0\xb7\x59\x0e\xc3\x63\x86\x0e\xf1\xeb\x58\x56\xbf\x8a\x4a\xd5\x0f\x5d\xed\xb9\xa3\xc3\x11\xab\x98\xea\x3b\xb1\x02\xeb\xd9\xb3\x99\x34\x56\x6c\x48\xbb\x0f\x4b\xfd\x64\x90\xb8\x77\xe8\x48\x85\xcb\xbf\x7b\xf7\x4e\x53\xd0\x72\x73\x23\x74\x22\x2d\xcb\xb1\x84\x1c\xbd\xff\xce\x56\x3d\xed\x5a\x72\x78\xab\x21\xd0\x2c\xc5\xf0\xfb\x3d\x62\xf8\xfd\x96\x18\x7e\x6d\x89\x5a\x4b\x02\xdb\x41\x2e\xfc\x25\xe2\xf0\xb8\x9a\xe2\x23\xf5\xb8\x22\x34\x28\x6c\x93\x1f\x40\x3b\x87\x59\x17\x6a\x50\x48\x5c\x6c\x68\x48\xf8\x06\xd7\xf0\x0e\x5c\x5c\x79\xa2\xc9\xfa\xdf\x58\x2a\x8e\x23\x9e\x4b\xc7\x11\x4f\xd2\x1c\x3c\xfd\xae\x43\x9a\xef\x3a\x9c\x6a\x71\x20\xfb\xea\x5d\xa7\x5e\x80\xc8\xcc\xb4\x16\xa7\x52\x7b\x73\xa0\xc5\x9b\x8e\x36\xcb\x7c\x9d\x22\xbf\x74\x03\x41\xd5\xeb\x4e\x25\xd7\x6b\xe4\xd6\xbd\x4a\xb0\x2d\x3e\x86\x27\xd2\xfb\xc2\x3b\xe9\x7d\x21\x11\x0a\xed\x12\xaf\x83\x46\x6d\x93\x8b\x89\xa0\x74\x31\x41\x4c\x2e\x26\x4e\x42\xa4\xa0\x29\x25\xa7\xb8\xe5\x72\xc2\xe4\x6d\x82\xe8\x68\x88\xa5\x0b\xfa\x22\x42\xa2\xf0\x40\x41\x46\xde\x64\x4b\x53\x40\xa2\x3c\x71\x73\xd0\xab\xa9\x3d\xaf\x79\x9b\xe0\x4b\x32\x73\xd9\xd6\x93\xb4\x3a\xb7\xfe\x83\xe1\x2f\xf0\xa3\xa0\x3c\x0c\x5c\x75\xbf\xe2\xac\xe9\x43\x21\x30\xbf\xdc\x98\x64\xd1\x57\x21\xca\xcc\xef\x3f\x07\xc6\x30\x08\x01\x7a\xd5\xb5\xb5\x7d\x99\x67\xdc\xda\xff\x2a\xde\x17\x3a\xfc\x16\xce\xfe\x3a\x19\x80\xf9\x0e\x14\x77\xf0\x20\x4f\x6b\xac\x35\xe3\x6c\xd4\x5f\xeb\x9b\xe1\x80\x33\xe0\x83\x53\x7c\x35\x98\x11\x3a\x10\x50\x8e\x92\x93\x6e\x35\xf5\xbf\xdc\x39\x44\xef\x00\xfe\x79\xbe\x22\x0e\x52\x54\x81\xf4\x7a\xbc\x48\xa5\xfc\x5a\xa2\x9f\xb0\xf3\xec\x16\xf7\x5b\x49\xf5\x5a\x2f\xfe\x77\x22\xb4\x9f\x00\x01\x3a\xe2\x97\x12\xfb\xe6\x86\x63\x05\x81\xc4\x86\xcc\xdd\xa1\x88\x88\xa3\x3c\xd8\xaa\xfa\x0a\x72\x6a\x6e\x84\xfe\x91\x0e\x71\x84\x41\xd2\x92\x0f\x66\x9d\xb3\xbb\xe5\x14\x27\xfb\xef\x77\x8a\x33\x5b\x42\x60\xd6\x3c\x35\x5f\xb2\xd2\xa5\xd1\x6f\x6b\x1b\x03\xec\x1c\x96\xcb\x7e\xa7\x88\x6b\x1b\x61\x89\xec\xb6\x9e\xb5\x0c\x61\x42\x6b\x2a\x63\x6b\x8a\xcd\xab\x9e\x26\x27\xfc\x0a\x72\x7f\x3d\x5d\x4a\xc2\xe4\x1e\x35\xed\xee\x56\x82\xd3\x61\x75\xf4\xed\x8f\x06\xeb\x0e\xb5\x7b\xf6\xff\xfb\x3c\xb0\xf2\x79\xe0\xe7\x69\x30\x0e\x4d\xaf\xe0\xff\x33\x5f\x08\xd6\xb8\xfb\xfe\x4f\x7d\x0c\xa0\x76\x8e\xcc\xb6\xb6\x46\x13\xd1\x52\x2a\xd5\x6f\x20\xea\x2d\x85\x80\xad\x43\xdd\xc4\x86\x79\x8d\x2e\xa9\x48\x07\x3a\xbe\x51\x22\x74\xc8\x96\xa1\x39\x52\xba\x49\xa6\x27\xf8\x14\x26\xe4\xa7\x9a\x75\xcf\xcd\xea\x60\x52\xdc\xa7\x74\x53\x88\x91\xa5\xae\x93\xba\x86\xa9\x7a\x1d\x24\xca\x70\x5d\xb2\x0a\xda\x6c\xbd\x45\x83\x58\x8e\xfa\x02\xbf\xfb\x68\x29\xa0\x05\x42\x02\xfb\x8e\x7f\x65\x52\x7c\x79\x4b\xd9\xa9\xb9\xf0\x9d\x8a\x98\xb4\x1e\xdc\xfa\x09\x45\x99\x74\x3b\x92\xdb\x70\xbe\xec\xd3\xb6\xfe\x3e\xe7\xb9\x5d\x16\xb9\x42\x03\x25\x1e\x4e\x06\x81\xf0\xcf\x55\x38\x89\xd7\x3f\x4d\x3e\xcd\xd7\xbc\xcd\xac\xf2\x89\x2e\x24\x69\xb5\x5e\x87\x82\xcd\x37\x95\xfd\x81\x08\x25\xc3\x3b\x13\x73\xc4\x9d\x34\x30\x29\x29\x3d\x8b\xa5\xdf\xde\x5e\x9d\xba\xdb\xdd\x43\x5a\xe3\x0d\xa3\x40\x28\x1a\xdf\xfa\x39\x64\xad\xf6\x43\x9c\x06\x34\x5a\x0a\x99\xf6\x1a\x27\xf3\x1a\x31\x55\x3a\x74\x76\x16\x5d\xc2\x0f\x26\x84\x1f\xcc\x9f\x0a\x69\x87\x20\x3b\x8f\x7d\xfa\x7d\x26\xe4\x81\x4f\x43\x4e\xbb\x6e\x67\x53\xd3\x68\x60\x28\x3d\xea\xac\xd1\xc4\x6a\x43\xfb\x4a\x7b\x22\x61\x65\xa3\xc2\x4d\x83\x37\x83\xc4\x44\x50\x9e\xc5\xe8\x73\x2a\xa9\x5b\xfb\x50\xb8\x85\xb9\xba\xe8\x24\xfb\x96\x4e\x9e\x9a\x05\x10\x46\x34\x34\x9b\xc4\x3f\x8b\x51\x32\xd3\xda\x83\x3f\x84\x15\x55\x2c\xc0\xc5\x67\xd3\x42\x5e\x8b\x00\xd0\xf9\xb2\x34\x0f\xb6\x94\xe5\xbb\xfe\x0d\xcc\xe4\xdc\x50\xd6\x29\x9e\xf6\x74\xa5\x22\x01\x7e\x30\x3b\x73\x5c\x6f\x8e\xdd\x48\x24\xb5\x4c\x57\x2d\x77\x9b\xe9\x96\xcb\x78\xec\x4f\x2b\xe6\x1a\x3d\xb0\xc4\xa5\x7b\x01\x5c\x75\x2f\xd0\x07\x7f\xaa\xea\x84\x4b\x44\x6c\xbb\xee\x36\x67\x0d\x89\x77\x7b\xe8\xd2\x53\x08\x56\xf6\x01\x8f\x0a\xb7\x7d\x41\xb7\x71\x63\x8a\xe6\x4b\xc0\x23\x29\x0e\xdf\x0f\x81\x02\x91\x51\x22\x1b\x96\xd7\x46\xeb\xc7\xb6\x1d\x76\x10\x22\x51\x3b\x37\xcc\x46\x90\xa1\x93\x36\x19\xfa\x1f\xeb\x5d\xf0\x43\x8c\x22\xb4\xfd\x3f\xdf\xbb\xe0\xed\xc7\xd9\xeb\x5d\x70\xda\xa9\xb4\xd1\x17\x10\x46\xf2\xab\xdf\x69\xe9\xb7\x29\x1e\xdd\x44\x7b\x1d\x7c\x78\xab\xad\xed\x15\xb6\x4a\xdf\x1a\x85\xac\xd3\xfc\x7c\x32\xfe\x0e\xfb\x73\xba\x9e\x9c\xf0\xaa\x6b\x09\x9a\xde\xe8\x3e\xc4\xe8\xf1\x4c\xf9\x53\xfa\x5f\x9f\x74\xdf\xe0\x93\xee\xb8\x97\x23\xff\x4e\x3b\x39\xa3\xd6\x66\x3f\x7b\xb8\x88\xd7\x90\x7b\x74\xba\x4c\x3b\x59\x76\xb8\x4c\x5b\xeb\x24\x89\xd0\x94\x1f\xd1\xbb\x16\x08\x23\x27\xe1\xa3\xab\xa3\x90\xf4\x0f\x37\xf0\x99\x28\xfb\xd6\x47\x15\x47\x71\xdd\xb5\xf6\x92\xb0\x5e\x47\xb9\x8c\xeb\xae\x21\x5d\x0a\x84\xb5\x4a\x32\x46\x71\xd8\x5b\x4f\x7a\x20\x08\x07\xd3\x2b\x35\x99\xd2\xee\xaf\xbb\x8e\xb6\xfa\x93\x15\x94\x31\x5f\x1f\x08\x18\x16\x85\xd3\x59\xc3\x13\x5f\xcf\xc0\xb4\x89\xb7\x05\x46\x05\x06\xe3\xed\x55\xf8\xec\xd1\x5e\x37\xab\x6e\xeb\x3a\x7b\xd9\xd6\x76\xdd\x4a\xc0\x0f\xef\x9a\xe1\x61\x35\x26\x45\x08\x0b\x37\x77\x57\x02\x73\xc6\x1d\x6e\xee\xf2\x8a\xb5\xe0\x45\xf7\xd3\xb4\x92\xe6\x57\x5c\x51\x69\x1e\x24\xe9\xf4\xe3\x23\x55\xb2\x1e\xd5\xec\x07\xda\x3e\x94\xb6\x7c\x74\xbc\x04\x0c\x84\x8f\xd1\x29\x7f\x4c\x9a\x7e\x19\xd6\xf4\x17\x13\x84\xca\xa6\x36\x87\xd3\xe5\xea\x00\xb9\x2b\x37\x7a\x42\x58\x97\x64\xc2\x90\x70\xd4\xf1\x0c\xf4\xb2\x7f\x14\xf1\xaa\x51\xbc\xc7\x34\x8d\x48\x32\xd8\x4f\xf8\x11\xea\x9b\x2f\x95\xeb\x9f\x76\xb7\x3e\xd7\xb7\xbb\xce\xcc\x74\xb1\x9e\x37\x38\xeb\x31\xf5\x93\x60\xee\x7c\xcf\xa8\x55\x7f\x93\x35\x7c\x25\x11\xc4\x46\x53\xd1\xe3\xb7\xb1\xde\xff\x83\xe0\x96\x45\x71\xb8\xeb\x33\xfc\x4f\x05\x9d\xee\xf4\xff\x08\xe8\xbd\x4b\x31\xfd\xa7\x43\x8f\x77\xfa\xaf\x0e\xbd\xa7\x44\xd1\x9d\x7f\x26\xf4\x4e\x74\xa7\xff\xea\xd0\x7b\x8b\xcf\xa3\x7f\x36\xf0\xa8\xea\xf3\x5f\x1d\x76\xff\x0d\x78\x77\xfe\x4d\x58\x57\x61\xa3\xec\x1c\x2e\x3b\x8e\xff\xab\x6f\x90\xb4\x7e\x2b\x9c\xd7\x76\xa9\xe3\xac\xe9\x8c\x88\x03\xc7\xe8\x16\xe1\xfb\x9c\x35\xff\x75\x93\xd9\x0e\x43\x8a\xd3\xf4\x36\xf3\xf1\x65\x95\xb5\xae\x53\x39\x3c\x36\x9b\xfc\x44\x33\xd4\x30\xd8\x34\xc7\x17\xfd\x5e\xe6\x6f\x27\xce\x52\x86\xe9\xe0\x48\x5c\x44\xfe\xc5\xf8\x3e\x81\x69\xff\xb4\x6d\x8c\x57\x3b\x42\xfc\x17\xa0\x7e\x72\xa1\xff\x59\x50\x6b\x8b\x2b\xe8\x3a\x4a\x14\xc2\x49\xb4\x50\x38\xb8\x33\x5e\x57\x55\x41\xf8\x95\xd6\x72\x20\x5e\x47\x85\x2b\x94\x57\x6c\xb0\x28\xf6\xc3\x2b\xcb\xbe\x55\x73\xda\xfb\xa7\xa1\xb9\x14\x33\x16\x0b\xcf\xa0\xeb\x84\x84\x35\x61\x93\x6c\xe9\x76\x82\xc6\x7f\x01\x04\x7b\x8d\x31\x5d\x1b\xbf\x8c\x6f\x70\x7d\xf8\x15\xa1\xcf\x70\xb9\x04\x3c\x5a\xe2\xa6\x0f\xfe\xee\x03\xb4\x8c\x8d\xfc\xdd\xf4\xf2\x10\xa7\xf3\xff\x0e\x62\xf9\xfd\xe4\x4b\x0e\x3d\x21\x6c\x10\x90\x64\x16\x9d\x64\x74\x2d\x35\x2d\xe3\xa1\xb5\xbd\xd2\x2a\xe6\x1b\x4f\x23\x31\xb2\x35\x01\xbb\x30\x81\x64\xf9\x1d\x4e\x33\xa6\x7e\x70\xca\xd7\x24\x51\x36\x82\xff\x36\xfb\x65\xf6\xcb\xec\xb7\xff\x9f\xba\x6b\x71\x8e\x13\x47\xfa\xff\x0a\xe1\xae\x12\x69\xd3\x9e\x78\xf6\x76\xbf\xaf\x0e\x17\x95\xf2\x33\x9b\xc4\x76\xb2\x7e\xe5\xb1\xb5\x35\xc7\x80\x30\x24\x0c\x60\xd0\xf8\x11\x87\xff\xfd\x2b\xbd\x40\x80\x18\x33\xde\xdc\xd5\x77\x55\xbb\xb1\x0d\xa2\xd5\x6a\xb5\x5a\x2d\x75\xeb\xa7\xb1\xc9\x52\x61\x96\xd2\x8d\xd0\x5b\xc4\x89\x84\xaa\x59\x64\x69\xc6\x93\xd3\x47\x61\x86\xf4\xa4\x75\xfb\x63\x63\x14\x75\xe7\x1d\x3f\xae\xf3\x1e\xde\xb6\xfe\x6f\x74\x21\xce\x73\x1a\xff\x27\x9d\x08\x3a\x59\xf2\x1a\x1f\x67\xe5\x77\x72\x44\x27\xbe\x70\xd9\x4e\x7b\xd3\x87\x2c\x74\x9a\x37\x2b\x8e\xd7\x69\x68\x42\x76\xda\xe6\x74\xf8\x60\x33\x2e\x38\x70\x05\x27\x03\xa8\x22\xbc\x56\x46\x76\x35\xd8\xba\xd4\xaa\xe3\x5c\xc0\x62\x3f\x7a\xbf\xb5\x90\xfb\xad\xfb\xb9\x7b\x9f\xc4\xe9\x57\xc7\xb6\x21\xe5\x6e\x9f\x5d\xc1\x51\xfd\xf0\x6f\x2f\x04\x63\xea\xa5\xd4\xc5\x0a\x76\xf5\x22\xf5\x3d\x5e\xb2\x90\xfa\xbb\x82\x2b\xad\x98\xda\xfd\x16\x85\x24\xde\x71\x05\x07\x79\xe7\xc2\x96\xab\xbc\x2f\xd8\x5d\xc3\xb3\xa3\xbc\x2f\x62\x38\xcc\xdd\x81\xb3\xb3\x82\x0f\x2a\xaa\xe7\xd7\x7c\xeb\xfd\x60\x8a\xce\x0b\x16\x4f\xb2\x25\x6d\x42\xda\x57\xb9\x10\xf9\x71\x46\x0f\x98\x45\x6b\xbf\xdd\x97\x6f\xa5\x04\x0e\xb2\x62\xb1\x1f\xc4\x54\x16\xea\xbe\x3a\x26\x37\x86\x37\x87\x71\x69\xfa\xe0\x22\xae\x4b\xcb\xca\x76\x55\x65\xbc\x4f\xda\xef\x8e\xf2\x6e\x9f\xef\xe7\xfc\x2e\x94\xd5\x10\x00\x87\x39\xb3\x7e\x05\x7e\x69\x5b\xcd\x91\xbc\x0a\xc3\xbb\x15\x41\x68\x53\x9e\x9c\x96\x73\x5e\x67\xcc\x41\x8c\x5e\xe7\x03\xa1\xc2\x9e\x01\x5a\xfb\xce\xf8\xb7\x19\x2a\x26\xec\xa5\xe1\xdd\x97\x41\x90\x40\x33\xdc\xfc\xb8\xe5\x08\xbf\x05\x64\xc0\xe4\x7f\x86\x77\x5c\x92\x07\x39\xae\xe0\xfd\x40\xa1\x68\xa0\x8d\x73\xaf\xb0\xc4\x8f\x0d\x9a\x5d\x5e\x26\xc4\x9b\x27\x64\x63\x11\xa8\x87\x49\x7c\x19\xd1\x06\x9f\x63\x31\xdf\xf8\xd5\xca\xe9\xc6\x3f\xac\xbc\x9b\xa5\xbd\xd6\x24\x2d\xb2\x1a\xe6\x19\xa5\xd9\x42\x42\xbb\xe5\xb7\x56\x99\x25\x71\x60\x15\x97\x73\x0f\x6d\x82\x25\xfe\x9b\x4c\x7f\xfe\x15\x3f\x2a\xef\xbf\x34\xdb\x79\x19\x27\x1f\x31\x31\x0d\xe9\x05\x93\xcb\xbc\xf0\x52\x63\x7e\xf9\xdb\x0c\xd9\x7f\x1b\x71\x76\x5c\x21\x31\x2f\xbc\xd4\xeb\x9e\x9d\x5d\xd3\xd5\x96\x2c\xa5\xde\xb5\xa1\x51\x6f\x72\x73\xf8\xaf\x7f\xa5\x58\x3b\x59\x68\x4d\xa3\xd2\xce\xcf\x19\x77\x45\x03\xf7\x14\xe2\x34\x89\x53\x62\xc4\x8d\x5b\xa3\x57\xc6\x66\x8a\xf3\xde\x69\xb0\xad\x52\xd3\x45\xa8\xc6\x4d\x0a\x0d\x6a\x77\xcc\x68\x35\xe5\x40\x19\xcf\x2c\xef\x99\x67\xe8\x82\x49\xd5\x3c\x39\x1b\x0c\xf0\x49\x5e\xa7\x50\xe1\xad\xd5\x76\xfc\x86\x17\x6d\xde\xaa\x5c\x2a\xc3\xec\x13\xa3\x45\x0e\x54\x44\x76\xd9\x3c\x01\x9a\x13\xd0\x9f\x3e\xd4\x31\xcb\xa0\xa1\xcf\xde\xe2\xde\x1c\xd5\xd7\x19\x34\xcb\xe0\x22\x81\x12\x7d\x0a\xe0\x4a\x20\xd6\xd0\x89\x54\x21\x89\xf5\x0b\x35\x51\x46\x02\xf7\xa9\x6a\x4a\x6a\x22\x7b\x28\x2f\xf6\xd0\x9d\x5f\xdb\x36\x53\x3d\xcb\xf2\x43\x72\x4d\x92\x36\xb9\xbe\x63\xf3\x35\xaf\x2a\x38\x1f\x9c\xac\x3c\xe4\x65\x60\xf3\x29\x04\x7a\x4a\x68\x3a\x85\xb8\x97\x21\xbb\xa4\x77\x09\x29\x23\x42\x8c\x89\xd2\x31\x9a\xf9\x60\x27\x99\x17\xd8\xe0\xa7\xa8\x40\x47\x31\x1b\xdc\xe6\x64\x00\x56\x94\x14\x45\x56\xc8\xb2\xbb\xb1\x3e\x53\x1e\x78\x71\x42\x02\x8b\x66\x16\x23\x67\xed\x9e\x9e\x5a\x61\x91\x2d\x1c\x8b\xdf\x22\x6c\x4a\xb0\xe9\x64\x3d\x57\x18\x2e\x1e\xb7\x06\x39\xcf\x41\xcf\xaf\xb7\x93\x78\xfe\x62\x9e\x65\xb4\xa4\x85\x97\x6f\xfc\x32\xd9\x9c\x6c\x6e\x78\x49\x1e\x79\x93\xff\xd9\x08\xe2\x92\xbe\xf0\xcb\xb2\x29\x30\x59\xc4\xe9\xc4\xe7\x59\x42\x47\x26\x00\x0b\x33\x7d\xbe\xac\xf3\x6e\x48\x99\x2d\xc8\xc6\x2f\x93\xff\x9d\x6c\x72\xaa\xfa\x63\x8d\xf0\xbe\xe1\xc2\x09\x5c\xc1\x87\x51\xd9\x71\xe3\x36\xf0\xc7\x41\x9e\x78\x41\xa0\x76\xae\xec\x5f\xba\xe7\xdf\x56\x7c\xa8\x9d\xf5\x29\x48\x30\x66\xe5\x6a\x70\x4d\xc6\xcc\x48\xef\x99\x39\xe1\xc6\x6a\x9d\xa5\x96\x9c\x82\x99\x0f\xf1\xf0\x75\x63\x7b\xf9\xc8\xd4\xf7\x0a\xc3\x6f\x8f\xd1\xc8\x0b\xd6\x86\x24\x9e\x9b\x01\x51\x3a\x39\xb6\x85\xe9\x48\x3b\x9d\xd4\xea\xb9\x7b\x7a\x0a\xfc\x7a\x65\xa6\x5a\xdb\x42\xb3\x76\x4f\x4f\xab\x2d\xea\x04\xd9\x7d\xc1\xfe\x89\x43\x54\x7f\xfd\xa4\x0e\x0c\xcc\x0b\xe2\x7d\xb5\xb4\xdb\xaf\xe4\xf1\xf6\xee\x9a\xac\x79\x3f\x5d\x79\x73\xc9\xea\x36\xff\xff\xe9\xb7\xee\x15\x2a\x42\x0e\x45\x6d\x6c\xa5\x5c\x2a\xe3\x45\x2b\x31\xfa\xc0\xbd\x7c\x79\xdc\xbf\xfe\x88\x89\x58\x95\xe5\xb1\x17\x25\x2c\x45\x5d\x51\xad\x6e\xa2\x38\x21\xe8\xc9\x54\x3b\xa9\xa4\x48\x4e\xf9\xaa\xb5\x5f\x80\xbb\x38\xe6\x24\x67\xf8\xb2\x62\xc9\x23\x92\xd7\x50\x01\xf7\x2a\x8d\xcb\xe9\x5f\x7e\x79\x00\x49\x09\x74\x42\xc9\x2d\x3f\xdb\x52\x61\xf8\x66\x4a\x53\x14\xe0\xc1\x3a\x4d\xf6\x85\x73\x88\xbc\x12\x11\x2d\x4d\xac\xbe\xad\xda\xa0\xb5\xf5\xd7\x44\xe3\xa8\xd7\x59\x27\xb4\x63\xa8\x3e\xfb\xad\x8b\x98\x8b\x12\xa5\x03\x33\x90\x5f\xc0\x1d\x3a\x2e\x31\x5c\xa4\xe6\x2b\x00\x4d\x22\xac\x30\xbc\x5a\x79\x78\x4d\x8d\x10\xbf\xb5\x7a\x0e\x02\x91\xb5\x2f\x93\xec\x44\x82\xd9\xd2\xf5\x35\xb0\x2f\x0f\x7d\xcb\xf9\x01\xdd\xba\xe1\x59\xab\x2b\x5e\xc1\x12\xb2\x46\x76\x2f\x9b\xdf\x9d\xa6\xc1\xcd\xc3\x8e\xba\x2f\xfb\xaa\x2e\x4b\x9e\xb1\x9e\xf1\x27\xb3\xcd\x97\xb6\xed\xd4\xdf\xb3\xa7\x95\x72\x39\x44\x52\xb6\xa1\x05\xb3\xb5\x5a\xf0\x71\xcc\x11\xb5\x19\xd6\x5b\xd9\x67\x32\x2e\xd1\x0c\x0f\xf0\x29\x72\x32\x8f\x9a\x37\x6a\x24\xae\x52\xaf\x86\xc7\xba\x12\xa1\x5a\xfb\xb4\x92\x17\x11\x17\xa4\x2c\xe3\xf4\x72\x47\x01\x81\x8c\x24\xdb\x05\x0e\xe9\xd0\x6e\xfb\x6b\x06\x5a\x99\x2c\xc9\x3a\xeb\xf7\x41\x84\x18\x25\xfd\x2f\xa8\x7b\x38\xb2\x0d\xed\xf8\x44\x06\x97\x66\x9b\xc2\x53\x7e\xfa\x54\x3d\x98\x8a\x9b\x15\xc5\x8d\xb7\x18\x3e\x0d\xe3\xb9\x89\xbb\x44\xf4\xd8\xf0\xe3\x2f\xba\xcd\x58\xc5\x3b\x35\x56\x9b\x47\xc1\x7f\x5e\x40\x8c\xf6\xc0\xdf\x28\x36\xa6\x1c\xd7\xbb\xc2\xf0\xd6\x64\x5f\xa8\x13\x66\x05\xda\xda\x52\x96\xc6\x34\xe9\x31\xe1\x15\xd5\x56\x77\x3e\x13\xf9\x9e\xdf\xbf\xb3\x81\xc1\xff\x94\x13\x99\xfe\x44\x5a\x63\xc9\x34\xd9\xaa\xb3\x41\xa7\x8c\x67\x5f\x7c\x34\xdb\xdc\x6a\x30\x65\x52\x69\x8f\xf1\x3d\x95\x6f\xa7\x50\xb8\x19\x10\x57\x3f\x71\xdc\x1e\x92\x7e\x6f\x48\x6e\xb1\x39\x2c\x4e\x97\xc4\xa2\x15\xa7\x2d\xe0\xd4\x88\x80\x50\x6b\xf8\xa1\x2e\x95\xd4\x09\x57\x8e\xcf\x0f\x81\x59\xda\x36\xfe\xfe\x5d\xe2\xe2\xd8\x36\x07\x6c\xa8\xbb\xe2\x25\x75\xbc\x02\x79\xe8\x6d\x0e\x65\xc1\xe6\xc4\xb2\x60\xce\x95\xee\x4c\xb3\x7e\xf8\x68\xea\x07\x25\x80\x5e\x0d\x8a\xd7\x46\x46\x7c\xb3\x4b\x3e\xad\x2d\x06\x79\x3e\xf9\xf9\xd7\x9f\x4e\xd1\x76\x81\x62\xf4\x59\xed\x88\xfd\x84\xa6\x1b\x84\xa3\x79\xe7\x3d\x58\xfa\x06\xdf\x87\x68\xe4\x84\x16\x6c\x17\x4c\x54\x99\xcb\xe3\x77\x29\x9a\x53\x0c\x31\x0a\x02\x88\x51\x42\x61\x0a\x29\x6f\x1a\x4f\x81\xf6\x59\xd9\x02\xc3\xd2\x45\x31\xda\x06\x1f\x52\xfc\xe2\xe7\xef\x9b\x78\x63\xca\x91\x90\x32\x0a\x31\xfa\x94\x33\x83\x8b\x61\x80\x9a\x2f\x05\x85\x39\x36\xd2\x17\x66\xb7\x4a\xf7\x14\x79\xf8\xc5\x29\x4a\x31\x84\xee\x37\xd4\xbd\xa4\xf7\xa1\xd1\x41\x7f\x2a\x2a\x0c\x93\x5f\xe1\x14\xc5\xe8\xf7\x1c\x32\x2e\x8d\x0a\x66\x18\x43\xe2\x22\x46\x7c\x23\x64\xf4\x3d\x0c\x81\xaa\xab\xc1\x05\xe2\x72\xf1\x60\x13\xbf\xdc\x74\xa6\x2f\xfe\xf1\x13\x0a\x9e\x97\xcf\x13\x8e\x5e\x1e\xad\xa9\x1f\x9b\x9a\x7a\x4c\x1d\x0f\x7d\xe4\x5d\x03\x31\xfa\xbb\xec\xa3\x0a\x43\x11\x19\x9c\xd9\x55\x16\x91\x2a\x43\x5b\x3a\xbb\x05\xa2\x0d\xc6\x48\x7d\xac\x9a\x29\x9b\x13\xa3\xa8\x00\x9b\x2d\xf4\xf4\x12\x54\xa1\x5d\x39\xdc\x54\x4c\x37\xa1\xa0\x28\x46\xef\x81\x46\x2d\x52\x60\x36\x49\x12\xf5\x91\x2a\x8c\x93\x02\x57\x70\x98\x72\xc7\xba\x94\x0b\xca\x3e\xc8\x96\x73\x55\x1b\xeb\x0a\xc8\x0a\x19\x36\x6e\x8e\x20\xef\x7c\xf6\x10\x15\x07\x56\x85\x93\x94\x46\xa3\x9c\x24\xfe\x85\xf3\xd1\x6b\x10\xa8\x56\x39\x48\xe4\x47\xf8\x3f\x07\xd2\xff\xe9\x42\x3f\x0d\xf8\x3e\x59\xf4\x38\xdf\x87\xd1\x74\x6a\x37\x21\x8d\x7a\x6e\x82\x14\x9c\xee\xc9\xc8\xae\xea\x18\x4d\x66\x59\x07\x5c\x99\x96\x7b\x08\xb5\x4e\x68\xce\x4d\xfd\xac\xe7\xda\x70\x06\x4d\x4e\xd9\x2a\x5e\x47\x39\x34\x4b\x5c\xb7\x65\x14\xa3\x4b\x23\x9f\x42\x31\x47\xfb\x33\x3d\x55\x36\xb8\x35\x07\x99\xbf\x2c\x47\x52\x94\x68\x7e\x9c\xcc\xea\x91\x22\x68\x9f\xb4\x10\xff\x46\x56\xd2\x86\x09\xfc\x0f\x7a\x62\x9a\xf3\x78\xa0\x24\x5f\xab\x6b\x11\xa1\x5e\xe7\x6b\x9e\x62\x77\x37\xf9\x01\x3f\xce\x37\x59\x4d\x2b\x46\xbb\x14\xde\x96\x70\x29\x8f\x55\x2f\xd7\x1f\x66\xf5\xcd\x16\x07\x84\xa9\x58\x2d\x73\xfd\xde\x79\x5f\x39\x3b\x26\xf8\xe2\x76\x4f\x48\x62\xbc\x91\xba\xac\x4c\xfb\x39\x59\x4b\x8e\x7c\xab\x53\x7d\x3f\xb2\x7f\x5a\x57\x73\x38\x4f\x36\xb5\x31\x61\xdb\xd0\x58\xfe\xa1\xa3\x87\xba\x85\x90\x8e\x5f\x85\xe1\x5e\x45\x57\x13\x1b\xf8\x95\x31\x3c\xa0\xab\xe6\x8f\x4c\xbb\xe1\x03\x43\xf7\x0e\x2c\xa5\xd1\xd2\x4c\x7e\x90\x66\xb2\x7b\xcf\x11\xfe\xf7\xea\xbb\xd0\x49\xc5\x93\x66\xa0\x36\xb9\x9f\xf2\x23\xc5\x21\xa7\x53\xa3\x72\xd2\x08\x96\x66\x3c\x15\xed\xa6\x9f\x96\x3c\xf1\x98\x85\x7d\x6b\x34\x2d\xeb\x6e\x9e\x75\x84\xb0\x93\x2c\x0b\x25\x82\xd6\x4c\xb2\x9e\x52\x4d\x3b\x64\xd7\xb2\xa8\x3d\xf5\x30\xd9\x53\x71\xb6\xfe\xae\xdd\x5d\x1e\xef\xae\x71\xd2\xe8\x72\x0c\x1d\x0d\x51\x6d\x68\xcd\xf1\x05\x9b\xe3\xf5\xcd\x12\xd5\x0d\x8e\x74\x08\x99\x43\x77\xe5\x1c\x22\x0f\x57\x1c\xec\x65\x3d\x83\x35\x8b\xdc\xb4\x07\x21\xd6\x18\xa3\x02\x96\xae\x0f\x33\xd7\xaf\xf1\x39\x80\xb5\xb8\xc6\x19\x80\x50\x5b\x01\x65\xd0\xa4\x3e\x30\x97\xb6\xde\x4e\x4c\xfa\xa9\x06\xb5\x19\x63\xf5\x04\x6e\x32\x4e\x88\x4b\xb8\x97\x57\xc2\x07\xa0\x18\xea\xe3\x10\xd4\xd7\xd5\x68\xb6\x51\x5e\x15\x5d\x53\x9a\xc1\x3d\xf3\x0d\x9d\xbd\x94\xfb\xf1\xdb\x29\xf0\x75\xc1\x2a\x54\x21\x01\x4f\xc0\x9c\x63\x67\x56\x21\xdc\x55\x0f\xd6\x20\x99\xe9\xc1\x1b\x95\xbb\x31\xfa\x92\x03\x01\x0f\x43\xe4\xc6\x88\x44\x40\x60\x36\x66\xe0\x34\xad\xbc\x8a\xa1\x16\xb5\x93\x37\x4d\x8e\x40\xe1\x26\x28\x43\xd6\x73\x14\xf9\x9c\x63\x86\x7f\xf0\x6b\xf8\x8d\x45\x09\xa9\x19\x4e\x78\xc5\xe7\x0a\xbd\xc3\x8f\x90\x19\x00\x4a\x05\xb2\x2e\x2f\x13\x52\x63\x75\x0c\xab\xe3\xb2\xa7\xf3\x61\x57\xe7\x75\x94\x0f\xe7\x10\x25\x7c\x6f\x54\x68\xbb\x56\x57\x83\xf1\xf1\x97\x2b\xab\x49\x99\x6a\x3b\x25\xf4\xcc\x9b\x8f\x31\x2d\x4b\xb8\xa7\xde\xdc\x49\xfa\xd6\xe4\xa8\xbc\x3c\xc8\x8a\x03\xd5\xb9\x42\x65\xae\xdd\x12\xbd\xca\x21\x04\x02\xec\x13\xa6\x39\xb9\x7b\xcd\x7e\xbb\x64\x3f\xa6\xe3\x74\x47\xd7\x18\x56\xfb\x2c\x54\x73\xdd\x60\x97\x2a\x10\x91\x4b\xdc\x62\xef\x95\xd4\x37\xc1\xdd\xdc\x2d\x51\x16\x35\xdc\xcd\x98\x5e\xcf\x05\x77\xf3\xd1\xdc\x35\x3a\xfc\x20\x57\x85\x99\xab\x93\x06\x23\x46\x30\x76\xe7\x96\x68\xa9\x31\xe6\xb7\x60\x64\xe0\xcc\xbd\x13\x4c\xde\x8d\x66\x52\xfb\xde\x39\x7b\x90\xcf\x54\xe3\xf3\x41\xe3\xdb\x1a\xe5\x6a\x10\xb7\x14\x84\x99\xe5\x38\x72\x4b\x14\xa6\xb0\x1f\x43\x8c\xa2\x14\xec\xb8\x3c\x61\x73\xba\x0d\x77\xfc\xe6\x4d\xf6\x48\x60\xb6\x9e\xd5\x7f\xf3\x0b\x95\xf8\x03\x0c\x5e\xdb\x0f\x55\x39\x16\xd2\x04\x7b\x6d\xec\x12\x3f\x45\x8b\x50\x2e\x44\x72\x92\xb6\x32\xea\xfc\x14\x5d\xab\x77\xa4\x03\x87\xe2\xa7\x28\x0f\x7b\xe9\x16\x59\xaa\x47\x7a\xe5\xa8\x6d\x9d\x52\xb7\x16\xcb\x92\x5a\x73\x62\x65\x29\xb1\xb2\xd0\x7a\x26\xf8\x79\x06\xd6\x33\x59\xfd\x33\x2b\x2b\xac\x67\xb2\xbe\x67\xd6\x7c\x49\xad\x1b\xaf\x7c\x66\xb7\x43\xab\xcf\x26\x36\x1b\x94\x15\x94\xcc\xbe\xbe\xf6\xfe\xb0\xbf\x3b\xf6\x9f\xe0\xa7\x28\x08\x99\x50\xd2\x14\xbc\x48\x0a\xa7\x14\x87\xe6\xcf\xf8\x6a\x39\x6c\x95\xff\xa1\xbf\xfa\x29\x4a\x42\xd5\x23\x71\x20\xbb\x43\xfc\x59\x43\x01\xd4\x4f\x53\x23\x00\x93\x9f\x72\x44\x32\x9b\x07\xc3\x2b\xc8\xd9\x9f\xfc\x7b\x85\x13\xc0\x5b\x81\x9b\x96\x71\xf8\x03\x1b\xde\x78\xf5\x43\x81\x6f\xd0\x7a\x54\xa3\x17\xb4\x9e\x2e\x6a\x58\x80\xcb\x14\xc5\x51\x8b\x2c\x4f\x86\x2c\x23\x8c\x21\x61\x02\xbb\x4e\x3b\x8b\xf5\xba\x4c\x37\x14\xc7\x74\x32\x30\x7f\x12\x78\xd4\xb3\xfb\xd3\x8d\x5d\x5f\x35\xd7\xa3\x26\xc8\xe5\xe3\xc8\x89\xfa\x2f\x53\x14\x32\xb6\xa3\x75\x3e\x0a\x23\x0c\xd7\xc6\xe5\xdb\x47\x32\x22\x5a\x2e\x46\xe3\x6c\xea\xd0\x54\x1d\x48\x1b\x19\x2e\x97\xe3\x56\x7d\xca\xff\x1c\xfb\x6d\x6d\x16\x66\x53\xe7\xef\x04\xd1\x89\x7c\x60\x3c\x51\x52\xc1\xe2\xf1\xed\x8b\x83\x86\xc5\x38\x18\xcb\x9f\xa6\xf2\xea\xe3\x06\x10\x63\x74\x3a\x81\x54\xfb\x9a\x82\x44\xc8\x18\xf9\x7d\x33\x40\x04\x81\x1d\x4f\xe4\x2b\x49\xd0\x90\x91\x54\xd4\x88\xd2\x68\x28\x10\x91\x91\x14\x9a\xa1\xc6\x5c\x10\xc2\xfd\xce\xeb\x08\xa8\x1e\x30\x35\x65\x52\xb3\x8e\xbb\x1c\xde\x61\x4c\x22\xbe\x27\x7e\x5b\x80\xfd\xa2\x9b\xeb\x43\x87\x47\x9a\x61\x10\x16\x93\x38\x30\xa8\xcd\x96\xbe\x8b\x41\xe0\x8b\x87\x62\xb4\xe7\x71\x88\x68\xbe\x53\x3c\xef\x6f\x9d\x8a\xd8\xd5\xb6\x8f\x16\x11\x2a\x30\x86\xf4\x11\x0c\xf6\xed\x4a\xc3\xca\x17\x0f\x79\xe8\xdc\x63\xce\x2b\x04\x11\xe7\xe2\x6e\x58\x42\x3f\x46\x38\x23\x25\x73\xc1\xb8\x8a\x22\x21\x9a\xb3\x1f\xc1\x94\x36\x9b\x36\xa2\x29\x4a\x64\xba\xe6\x63\x98\xa5\x5c\xb2\x74\x13\x0d\xdc\x05\x5c\x18\x21\x53\xb6\x83\xa0\x0e\x09\x77\x37\xc4\x49\x2b\xfc\x5b\xc7\xc1\x86\x62\xd4\x17\xa1\x21\xaf\x58\xdf\x08\x39\x55\x03\x55\xc3\x67\x01\xdf\xbd\xf5\x10\x91\x63\x4d\x1a\x47\x58\xb2\x87\x59\xeb\xc2\x71\x15\x0f\xf5\xd0\xc5\x10\x56\xaa\x45\x37\x8a\x0a\x83\x0f\x4b\x7e\x91\x84\xfd\xee\x6b\xf7\x68\x6c\xea\x5e\x79\xf2\xb4\x81\x5c\x42\xaa\x03\xb4\x12\x88\x8f\xb1\xe4\x90\x49\xb0\x2c\x38\xc8\x89\xe0\x47\x1d\x0d\xeb\x3d\x47\x5a\xf0\x46\x5b\x5f\xc8\x66\x3a\x31\x7a\x13\x42\x06\xa4\x31\x46\xa0\x08\x88\x77\x33\x68\x48\x76\x64\xb5\x2f\xcc\x11\x97\x54\x29\x24\xb5\x14\x92\x52\xc4\x94\xac\xb8\x00\xcb\xff\x52\x59\x89\x6e\x17\xd2\x28\x41\xa9\xc1\x1a\x72\xda\x93\x8f\x85\xa4\xc2\x95\x92\x4a\xdc\x43\x0f\x85\x18\x82\x35\x25\xf5\x9c\x49\x6a\x09\x49\x2d\x08\x5d\x58\x2f\xf7\xa5\x94\x9c\xb6\x12\x8f\x68\x70\x30\xd8\xe0\xd0\xd4\xe0\x0b\x2f\x89\x19\x99\xb3\x78\x41\x8c\x83\x55\x53\xbc\xc3\x10\x6e\xbd\x96\xe6\xd5\x15\x1f\x86\xf0\x2d\x34\x48\xc7\xc8\xcb\x61\x08\x87\xde\xb0\xf4\x77\xeb\xe9\xdf\xc4\x4f\xed\x09\x88\x46\xf1\xae\x21\xba\x7f\xd0\x69\xd8\x78\x6a\x87\x21\x1c\x85\x46\x5a\x92\x2f\xe9\x52\x18\xe9\x88\x77\x6d\x9e\x94\xc7\xd1\xe5\x68\x14\x9d\x9a\x9b\x0e\x15\x11\x9c\x6a\x65\xdc\xe4\x2d\x50\xaa\x07\x2c\x2d\xdf\xdb\xcd\x35\x83\x8b\x79\x7e\x45\xfe\x7c\x0a\x9d\x2c\xac\x7e\xfa\xcc\x31\x73\x57\x9d\xc8\xf5\xd0\x22\x10\xad\x34\x5e\x2b\xd4\xc4\x76\xf9\xee\xb2\x92\xc9\x14\x94\x8b\x8b\x2b\xbd\xae\x95\x8c\x47\x5d\xe9\xfd\x45\x56\x84\x58\xff\x0a\x23\x2d\x89\x5c\x70\x37\x7c\x1d\x3e\xc4\x0d\xc6\xba\x4c\xa4\xef\xfe\x03\x84\xf2\x58\x6e\x94\x75\x59\x93\x05\xb5\x86\x67\x3a\xb8\x46\x9d\x72\xb5\xe1\xa4\xfc\x16\xe7\xb5\xaa\xac\x2a\x0c\x5f\x23\xf7\x98\x4e\xb2\x25\xbd\xcc\xe2\xf4\xf2\x7d\x56\x50\x64\xe7\xa4\x28\xe3\x92\xee\xb5\x12\xf0\x6d\xe3\xc6\x6c\x85\xe1\x34\x32\xde\x80\x21\xfc\x87\x7a\xff\x39\xd3\x3d\x1a\x61\x45\xd4\x71\x0a\x47\xec\x73\x7f\x0a\x51\x31\x09\xb3\x62\x81\x5b\xb0\x19\xbe\x36\xdf\x2d\xc7\xee\xf4\x17\x70\x5f\xaf\x66\x9d\xab\x78\xcd\xfd\xd9\x8b\x04\x7d\xae\xf7\x67\xe7\x11\xa4\xe6\x4b\x4c\xbe\x46\x68\xa9\x99\x37\x93\xd7\x98\x15\x70\x92\xc0\x27\xda\x2a\x68\x4c\x5d\xae\xd6\x6c\xd4\x6e\x8c\xec\xdd\x6c\x99\x04\xfc\x2c\x78\xb9\x9c\x2f\x62\x6a\xd1\x88\x58\x4c\x82\xa0\x8e\xaa\x58\x71\xc9\xdf\xdf\x11\x6a\x5d\x33\xed\x9e\xd8\x18\x58\x09\xe7\x55\x2d\xed\x6e\xd0\x46\x7c\x29\xba\x48\xe5\x20\x66\x4c\x11\xcb\xee\x9c\x4c\xdd\xd9\xf0\x36\x7f\x6b\x83\x97\xc0\xd0\xd5\xf2\x72\x43\x9f\xd5\x8f\xc6\x6c\xcc\xb7\x84\x20\xe3\x58\xa5\x64\xfd\x98\xa8\x1d\xea\x83\x22\x5b\xd4\x68\x8b\xc3\x1b\x81\x85\xd8\x55\xcc\x8a\x01\x2d\xf0\xd0\xdf\x43\x7e\x95\x98\x48\xa5\xe3\x1a\x71\x42\xf0\xca\xea\xb6\xd3\x40\x9f\xfd\x0d\xb5\xde\xf3\x0e\xf0\xd0\x6f\x3a\xed\x6c\x32\xfb\x19\x83\x8c\x39\x1c\xc4\xd0\x34\xf2\x20\xae\xfa\x51\x8e\x7a\xec\xac\x6e\x9b\x87\xee\x98\xfa\x66\x03\x76\xe4\x22\x41\x1f\x85\xa2\xe3\x76\xef\xf3\x3a\x4c\xf1\xed\x6c\x54\x7c\xbb\x00\xd1\xc6\xdf\x43\xa4\x2e\x62\x53\x3b\xb8\x59\x01\x67\x6c\x40\x5c\x24\x28\x4d\xd8\x72\xc8\xb4\x4e\x2f\xba\x29\x09\xd7\x71\x2d\x6b\xe5\x45\x6a\xe6\xa2\xe3\xfb\x86\xa3\x18\xac\xc3\x3b\xab\xf7\x96\x2f\x12\x44\x92\x56\xac\xa6\xb1\xa6\x65\x9d\x74\x7d\x1d\xa0\x90\x35\x54\x9f\xf1\x07\xda\x66\xe0\x81\x8f\x65\x2f\xe5\x23\x35\x88\xcb\x3c\xf1\xee\x2c\x4f\xa1\x78\x6e\xcb\x5b\xb2\x1e\x3f\xa2\x39\x05\x1e\x47\x28\xa5\x28\xc7\xc4\x4d\x1a\xf6\xb2\xf5\x72\x6a\x45\xd7\xc7\xe8\x26\x12\x7a\x27\x99\x7a\x40\xb7\xd9\x5c\x74\x1b\xb9\x86\x64\xbe\x8f\xcd\xe4\x42\xd6\xcb\x7f\x35\x0e\x6b\x71\x4e\x8e\x54\xa6\x2b\x25\xd4\x19\xba\x0a\x89\xd4\xd8\x0a\x76\xa2\xce\x71\xf1\x45\xd8\xb7\xf3\xd7\x86\x67\x79\x6f\xa5\x5d\x55\xb0\x3d\xb4\x4d\x13\xa3\xdb\x88\xdf\xe7\xa2\x2c\x20\xf5\xe6\x4e\xa1\x04\x55\x3a\x04\xfc\x6c\x99\x52\xe7\x0b\x22\x7c\xd6\x3e\x5e\x1d\x32\xa6\xc6\xfc\x15\x75\x50\xbe\x35\xb8\xc7\xd9\x5a\xe6\xf2\x7e\xf3\xcc\xa9\x0b\x9f\x61\x3b\x42\x14\xc3\x4e\x84\x2b\xf0\x9b\xb1\x6e\x34\x58\xa3\xd2\x55\x0a\x3d\x80\x26\x23\xb8\x85\x06\xac\xdf\xc8\xe5\x2a\x06\x33\x66\xac\x8a\xc9\x7a\xe8\x2c\x62\xeb\x7b\xb8\x09\x95\x89\x93\x85\xf7\x48\x49\x8b\xec\xee\x61\x43\xda\x12\x87\xb9\xb2\x43\xc4\x93\x78\xe2\xa0\xdb\x74\x73\x25\x56\x8c\x8e\xe8\x1f\xf6\x13\xfb\x4f\x30\xca\x7a\x75\xab\xda\x7a\xe6\xa1\x4b\xd6\x40\x9e\xb0\x72\x87\xce\x42\x93\xa3\xe2\x4f\x66\xd3\xf6\x7c\x9c\xea\xb3\xb0\xcd\xa7\xdf\xa1\x73\x39\xc6\x28\xe9\x52\x44\x49\x07\x09\x02\x11\x1c\xb5\x7a\x6d\xe6\x2e\xf9\x3c\xc4\x7e\x8c\x09\x02\xb6\xd4\x60\xa6\x99\xe9\xbb\x10\xc2\xb5\xe2\x7c\x85\x88\x01\xfb\xdd\x10\xdf\xc9\xf0\xde\x20\x35\x6e\xc5\xad\x3d\xf7\x12\xe1\xc3\xef\xd7\xda\xf7\x57\x8d\x71\xda\x8f\x63\xff\x1b\x14\xfa\x49\xb7\x0e\xdd\x2f\x20\x81\xcd\xcf\x57\x69\x6e\x41\xda\x1c\x56\x6b\xf6\x0d\xd7\x75\xd5\x9d\xa3\x18\x65\xf5\x3c\xd1\x9a\x98\x4f\x42\x31\xfb\x92\xa1\xd9\x57\x3b\xd0\x82\xa1\x93\xaa\xf0\x44\xa4\x0e\xac\xe7\x62\x73\x41\x37\x73\x56\x47\x1c\xaf\xd3\x98\x6a\x27\xac\xff\xa2\xb0\xa7\xca\x56\x75\x14\x66\x2d\x05\x7f\x80\x78\x6b\xf8\xb7\x5d\x70\x0e\x86\x8d\xf9\x80\xd8\x67\x0b\xcf\x24\x85\xd3\x64\x20\xc0\x2d\x51\x11\x65\xf4\xf4\x48\x86\xc8\xbf\x0e\x15\x57\xd1\xc9\xe6\x09\x07\xfc\xe2\x91\xce\x7d\x1e\xe9\xdc\x8d\xdc\x00\x79\x29\xdc\x28\x12\x02\x93\x59\xff\xa4\x86\x1a\xee\x3d\x3c\x2f\x49\xa1\x3f\xac\x81\x61\xf5\x87\x0a\xf0\xb4\x15\xa7\xd7\x8a\x61\xb8\x8a\xdc\x10\x95\x29\x9c\x29\x1e\x04\xa6\xce\xa7\xed\xa3\x43\xfd\x23\x01\xf9\x63\x20\xf3\x3a\x0d\x33\x1b\x76\xa3\x3a\xc8\xac\x43\xfb\xd8\x90\xa7\xe8\x88\xb7\xf5\x20\x72\x45\x01\x11\xfd\xbc\x8a\x30\x1c\xae\xf0\x08\x46\x07\x4c\xcc\x21\xe0\x4a\xc4\x7c\x2e\x3c\x20\x70\x10\xb5\xa3\x12\x05\x7c\xf1\x50\xca\x83\x11\xaf\x57\xd9\x40\xe9\x59\xb3\x95\x8e\xa8\xa4\xd9\x5a\x7e\x48\x1d\x05\x40\xe1\x7d\x83\x34\x24\x4c\xd7\xca\x34\x57\xb9\x1e\x3b\x64\xc3\xc0\xe0\x6b\xec\x25\x68\x3b\x91\xcb\x95\x0a\xc3\xbb\x21\xd9\xf1\x2b\xbd\xf9\x8d\x56\x73\xaf\x24\xef\x3d\x1a\xf1\x0b\xbc\xbd\x3c\x3e\x2f\x12\x58\x36\xb6\x7d\xa9\xdb\xf6\x63\xef\x3a\xbe\xf4\x28\x39\xcb\xf4\x14\x32\x39\x69\x25\x6e\x88\x66\x11\x64\x21\xa4\x1a\x1e\xc2\x0c\x7c\xc8\x30\x88\xdc\x39\xc8\xd9\x8f\x31\x13\x5b\x2a\xad\x39\xa3\xe1\x04\xc0\x4f\xe1\x3a\x1f\x13\x34\xc3\x32\xd5\x4c\xcd\x76\xb9\x5a\x69\xd6\xac\x69\xb0\x0b\xb6\xdc\x29\xe2\xfc\x5d\xbb\x21\x3a\x8e\xe0\x8c\xf1\xa7\x81\x2f\x00\xf7\x0d\xb0\xc8\x5d\xda\x14\x99\x4c\x23\x39\xd4\xa8\x38\x97\x92\xc7\xdf\x13\x14\xd5\x3c\xea\xc9\x43\xe7\x09\xe4\xb8\xcf\xac\xd0\x99\x11\xf6\x2b\x85\x7b\x51\xc3\xb7\xa4\xbb\x50\xdc\x4b\xd0\x4e\xd2\x24\x7e\xf5\x44\x21\xec\xaf\x48\x8e\xe2\xa2\xb8\x73\x3d\x74\x12\xc1\x71\x88\xe6\xb8\x91\x06\x2b\xc6\x24\xf1\x55\x64\x22\xe5\x63\x33\x91\x6a\xce\x5e\x25\x8c\x9e\x46\xcd\xf9\xaa\x09\xe0\x83\x59\x00\x2d\xd0\x0b\xc1\xe5\x29\xe7\x72\x9d\x9a\x3f\x25\xe8\x54\x5f\x3f\x9b\x57\xa9\x31\xa2\x09\xa4\x3d\xd4\x0c\xb6\x70\xfd\x44\xd1\xe9\xb0\x00\x15\x78\x86\x60\xef\x76\x6d\xf6\xde\x26\xe8\xd6\xb4\xbc\x2f\xd8\x73\x53\xc7\x29\x30\xab\xb5\x14\xe3\x73\xd2\x3b\xff\x10\xc4\x05\xf1\xa9\x1a\xac\x83\xb4\xd2\xde\xf4\xd7\x4a\x92\xc5\x9d\xc3\x09\xfc\x02\x37\x2e\x8a\x1d\xa1\x4f\xdb\x6e\x2a\xbd\x58\x38\x76\xf9\xf2\x72\x5e\xa0\x1d\x5c\x27\xfd\xee\x8c\xd9\xb6\x4a\x95\x2f\xdb\x3c\xda\x96\xfe\xcb\x71\xd5\x5d\x35\x1c\x67\x59\xfe\x50\x83\x3a\x59\x8c\xed\xa1\x66\x79\xe8\x75\x04\x9c\xfb\x14\xfc\x96\x23\xbf\xad\x0c\x8f\x68\xe3\x89\xb0\x6b\xa2\xa8\x66\xd9\xea\x26\x4b\x03\x77\x22\x06\xcd\xc9\x63\x0c\x5c\xdb\x96\x49\x7e\xbb\x76\x6c\x5f\x18\x30\xc9\x88\x6e\xc2\x6a\x56\xa4\x25\xdb\x17\xac\xec\x3f\xce\x92\x0d\x18\xad\x16\x57\x8d\x49\x39\x12\xb6\xa4\xcd\x55\x63\x4a\x8e\x04\x2b\x47\xeb\xb2\xb2\xd2\x7c\xb4\x58\x61\x83\x53\xb0\xb2\xeb\x96\xe8\xb4\xcb\x0a\x7b\x2d\xe4\x72\xe0\xee\x0a\x66\x76\xd7\x65\x86\xd1\x70\x0e\xda\x9d\xb4\xa3\xa1\x59\x1c\x66\x5e\x30\xee\xc0\x45\x0a\xf7\x3a\x0c\x86\xb3\x34\x9d\x88\xd2\x41\x31\xd6\x22\xdd\xc6\xd3\xe8\x10\x1f\xef\x2a\xa7\x70\xdf\xb6\x91\x6d\x4a\xcc\xb1\x78\x13\x99\x20\x99\x02\x44\xb1\x19\x90\x69\x08\x0a\xe9\x20\x41\x7d\xc4\xa4\x3e\x22\xd3\x3b\x53\x31\x33\xa4\xd1\xeb\xa1\xa2\x3d\x4c\xa5\xc3\x56\x49\x13\xba\xd3\xfb\x36\x2d\x03\xaa\xd4\x55\xb2\x0a\x0f\x69\x37\xe9\xa6\x9d\xbe\x49\xaa\x0a\xde\x0f\x7b\xb4\x6f\x28\xd8\x36\xc4\x68\x99\x4a\x47\x39\xe8\x44\x98\x98\x67\x4d\x65\xae\xd2\x1b\x0a\x4f\xa6\x7a\xe1\xbc\xc8\x82\x25\xa7\x2a\x32\x70\x59\xc1\xcc\x7d\xe7\xa1\xf4\x65\x31\xc9\x3d\x1a\x89\xc3\x37\x11\xa5\xb9\xf3\xe2\x45\x92\xf9\x5e\x12\x65\x25\x75\xfe\xb9\xf9\xcf\x7f\xbc\xb0\x31\xf8\x6e\xbb\xe0\x0b\x9b\xb9\x82\xe2\x36\xad\x7e\x64\x63\x69\xbc\x41\xb1\x25\xc7\xd5\x9d\x4f\xd9\x34\xda\x11\x10\x29\x2b\x2d\xe7\x20\x46\xef\x22\x78\x13\x31\x06\x8e\x13\x74\x19\x62\x74\x1b\x62\xf4\x36\xc4\xc8\x0b\x31\x5a\x62\x34\xc3\xe8\x36\xc1\xa8\x61\x1a\xa3\x0c\x23\x1f\xa3\xab\x58\xfc\x4f\xb8\x07\xbf\xc7\x96\x15\xc5\x12\xde\x44\x70\x1f\xa7\x31\x75\xde\x47\x20\x94\xdd\x79\x17\xc1\x35\xb3\x35\xbf\xe5\x50\x2e\xe7\xf5\x6d\xb3\xa5\x73\x87\x0e\x28\xae\x30\x22\x29\x86\xf3\xc8\xbd\xaf\xb6\xe2\x10\x9d\x47\x93\x23\x2f\x4e\x5d\xf9\xf3\xfb\xf7\xfb\x0a\xae\xb3\x38\xb0\x36\x9f\xb8\xee\x5e\xf4\xf4\xe9\x5e\xa4\xca\x80\xcd\xfe\xb5\xe5\x6b\x0c\xb6\x12\xa0\xed\xba\xf4\x2e\x27\x59\x68\x05\x24\x8c\x53\xf2\xf4\xa9\xf8\x39\xf1\x16\x01\x16\xbf\xa2\x3f\xfe\xec\x5f\x74\x6f\x9d\x47\x15\xde\x22\x49\x49\xac\x38\x44\x76\x36\xff\x42\x7c\x6a\x3f\x51\xc4\x16\x59\xb0\x4c\xe4\xc2\xe4\x22\x72\x69\x14\x97\x93\xfd\x64\xc1\xb8\xae\x39\xbc\x88\x70\x98\x15\x88\x15\xf9\x10\x59\x31\x23\xc9\x4f\xb3\x8b\x3f\x2e\x22\x4c\xa3\x22\xbb\xb1\x52\x72\x63\xed\x17\x45\x56\x20\xfb\x2c\x22\x05\xb1\xbc\x82\x58\xf4\x26\xb3\xf6\x93\x85\xac\xa7\xb4\x7c\x2f\x49\x48\x60\xfd\xcb\x7e\xfe\x21\x7a\x6e\xff\xcb\xca\x52\x71\xab\x5d\xee\x5d\x92\x27\xd6\x09\x61\xbd\xa1\x72\xa7\x69\x44\x16\x13\x1b\x6f\x5d\x44\x7f\x7c\x88\xfe\x74\xcf\xf9\x8f\x8a\x37\x45\xf1\xe9\x9e\x47\xe2\x81\xa0\x3f\x21\xb7\x79\x56\xd0\x92\x3d\xc6\x13\x56\x17\x62\x25\xf1\xd6\xff\x05\x00\x00\xff\xff\x74\xa0\x08\xe0\xce\xea\x02\x00") func uiAppScriptJsBytes() ([]byte, error) { return bindataRead( @@ -95,7 +95,7 @@ func uiAppScriptJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "ui/app/script.js", size: 191393, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "ui/app/script.js", size: 191182, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -392,19 +392,19 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "ui/app/script.js": uiAppScriptJs, - "ui/app/index.html": uiAppIndexHtml, - "ui/app/favicon.ico": uiAppFaviconIco, - "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css": uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss, + "ui/app/script.js": uiAppScriptJs, + "ui/app/index.html": uiAppIndexHtml, + "ui/app/favicon.ico": uiAppFaviconIco, + "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css": uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss, "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css.map": uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMap, - "ui/app/lib/font-awesome-4.7.0/css/font-awesome.css": uiAppLibFontAwesome470CssFontAwesomeCss, - "ui/app/lib/font-awesome-4.7.0/css/font-awesome.min.css": uiAppLibFontAwesome470CssFontAwesomeMinCss, - "ui/app/lib/font-awesome-4.7.0/fonts/FontAwesome.otf": uiAppLibFontAwesome470FontsFontawesomeOtf, - "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.eot": uiAppLibFontAwesome470FontsFontawesomeWebfontEot, - "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.svg": uiAppLibFontAwesome470FontsFontawesomeWebfontSvg, - "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf": uiAppLibFontAwesome470FontsFontawesomeWebfontTtf, - "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff": uiAppLibFontAwesome470FontsFontawesomeWebfontWoff, - "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2": uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2, + "ui/app/lib/font-awesome-4.7.0/css/font-awesome.css": uiAppLibFontAwesome470CssFontAwesomeCss, + "ui/app/lib/font-awesome-4.7.0/css/font-awesome.min.css": uiAppLibFontAwesome470CssFontAwesomeMinCss, + "ui/app/lib/font-awesome-4.7.0/fonts/FontAwesome.otf": uiAppLibFontAwesome470FontsFontawesomeOtf, + "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.eot": uiAppLibFontAwesome470FontsFontawesomeWebfontEot, + "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.svg": uiAppLibFontAwesome470FontsFontawesomeWebfontSvg, + "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf": uiAppLibFontAwesome470FontsFontawesomeWebfontTtf, + "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff": uiAppLibFontAwesome470FontsFontawesomeWebfontWoff, + "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2": uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2, } // AssetDir returns the file names below a certain @@ -446,29 +446,30 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "ui": &bintree{nil, map[string]*bintree{ "app": &bintree{nil, map[string]*bintree{ "favicon.ico": &bintree{uiAppFaviconIco, map[string]*bintree{}}, - "index.html": &bintree{uiAppIndexHtml, map[string]*bintree{}}, + "index.html": &bintree{uiAppIndexHtml, map[string]*bintree{}}, "lib": &bintree{nil, map[string]*bintree{ "bootstrap-4.0.0-alpha.6-dist": &bintree{nil, map[string]*bintree{ "css": &bintree{nil, map[string]*bintree{ - "bootstrap.min.css": &bintree{uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss, map[string]*bintree{}}, + "bootstrap.min.css": &bintree{uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss, map[string]*bintree{}}, "bootstrap.min.css.map": &bintree{uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMap, map[string]*bintree{}}, }}, }}, "font-awesome-4.7.0": &bintree{nil, map[string]*bintree{ "css": &bintree{nil, map[string]*bintree{ - "font-awesome.css": &bintree{uiAppLibFontAwesome470CssFontAwesomeCss, map[string]*bintree{}}, + "font-awesome.css": &bintree{uiAppLibFontAwesome470CssFontAwesomeCss, map[string]*bintree{}}, "font-awesome.min.css": &bintree{uiAppLibFontAwesome470CssFontAwesomeMinCss, map[string]*bintree{}}, }}, "fonts": &bintree{nil, map[string]*bintree{ - "FontAwesome.otf": &bintree{uiAppLibFontAwesome470FontsFontawesomeOtf, map[string]*bintree{}}, - "fontawesome-webfont.eot": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontEot, map[string]*bintree{}}, - "fontawesome-webfont.svg": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontSvg, map[string]*bintree{}}, - "fontawesome-webfont.ttf": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontTtf, map[string]*bintree{}}, - "fontawesome-webfont.woff": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontWoff, map[string]*bintree{}}, + "FontAwesome.otf": &bintree{uiAppLibFontAwesome470FontsFontawesomeOtf, map[string]*bintree{}}, + "fontawesome-webfont.eot": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontEot, map[string]*bintree{}}, + "fontawesome-webfont.svg": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontSvg, map[string]*bintree{}}, + "fontawesome-webfont.ttf": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontTtf, map[string]*bintree{}}, + "fontawesome-webfont.woff": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontWoff, map[string]*bintree{}}, "fontawesome-webfont.woff2": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2, map[string]*bintree{}}, }}, }}, @@ -524,4 +525,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/vendor/github.com/prometheus/alertmanager/ui/web.go b/vendor/github.com/prometheus/alertmanager/ui/web.go index 140c20b7f3b..049ef335a1d 100644 --- a/vendor/github.com/prometheus/alertmanager/ui/web.go +++ b/vendor/github.com/prometheus/alertmanager/ui/web.go @@ -14,21 +14,15 @@ package ui import ( - "bufio" "bytes" "fmt" "io" - "net" "net/http" _ "net/http/pprof" // Comment this line to disable pprof endpoint. "path/filepath" - "strconv" - "strings" - "time" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" - "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/route" ) @@ -55,30 +49,28 @@ func serveAsset(w http.ResponseWriter, req *http.Request, fp string, logger log. // Register registers handlers to serve files for the web interface. func Register(r *route.Router, reloadCh chan<- chan error, logger log.Logger) { - ihf := InstrumentHandlerFunc - r.Get("/metrics", promhttp.Handler().ServeHTTP) - r.Get("/", ihf("index", func(w http.ResponseWriter, req *http.Request) { + r.Get("/", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { serveAsset(w, req, "ui/app/index.html", logger) })) - r.Get("/script.js", ihf("app", func(w http.ResponseWriter, req *http.Request) { + r.Get("/script.js", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { serveAsset(w, req, "ui/app/script.js", logger) })) - r.Get("/favicon.ico", ihf("app", func(w http.ResponseWriter, req *http.Request) { + r.Get("/favicon.ico", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { serveAsset(w, req, "ui/app/favicon.ico", logger) })) - r.Get("/lib/*filepath", ihf("lib_files", + r.Get("/lib/*filepath", http.HandlerFunc( func(w http.ResponseWriter, req *http.Request) { fp := route.Param(req.Context(), "filepath") serveAsset(w, req, filepath.Join("ui/app/lib", fp), logger) }, )) - r.Post("/-/reload", func(w http.ResponseWriter, req *http.Request) { + r.Post("/-/reload", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { errc := make(chan error) defer close(errc) @@ -86,331 +78,17 @@ func Register(r *route.Router, reloadCh chan<- chan error, logger log.Logger) { if err := <-errc; err != nil { http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError) } - }) + })) - r.Get("/-/healthy", func(w http.ResponseWriter, _ *http.Request) { + r.Get("/-/healthy", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "OK") + })) + r.Get("/-/ready", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "OK") - }) + })) r.Get("/debug/*subpath", http.DefaultServeMux.ServeHTTP) r.Post("/debug/*subpath", http.DefaultServeMux.ServeHTTP) } - -// InstrumentHandlerFunc wraps the given function for instrumentation. It -// otherwise works in the same way as InstrumentHandler (and shares the same -// issues). -// -// Deprecated: InstrumentHandlerFunc has several issues: -// -// - It uses Summaries rather than Histograms. Summaries are not useful if -// aggregation across multiple instances is required. -// -// - It uses microseconds as unit, which is deprecated and should be replaced by -// seconds. -// -// - The size of the request is calculated in a separate goroutine. Since this -// calculator requires access to the request header, it creates a race with -// any writes to the header performed during request handling. -// httputil.ReverseProxy is a prominent example for a handler -// performing such writes. -// -// Upcoming versions of this package will provide ways of instrumenting HTTP -// handlers that are more flexible and have fewer issues. Please prefer direct -// instrumentation in the meantime. -func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - return InstrumentHandlerFuncWithOpts( - prometheus.SummaryOpts{ - Subsystem: "http", - ConstLabels: prometheus.Labels{"handler": handlerName}, - }, - handlerFunc, - ) -} - -// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares -// the same issues) but provides more flexibility (at the cost of a more complex -// call syntax). See InstrumentHandlerWithOpts for details how the provided -// SummaryOpts are used. -// -// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons -// as InstrumentHandlerFunc is. -func InstrumentHandlerFuncWithOpts(opts prometheus.SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - reqCnt := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: opts.Namespace, - Subsystem: opts.Subsystem, - Name: "requests_total", - Help: "Total number of HTTP requests made.", - ConstLabels: opts.ConstLabels, - }, - instLabels, - ) - - opts.Name = "request_duration_microseconds" - opts.Help = "The HTTP request latencies in microseconds." - reqDur := prometheus.NewSummary(opts) - - opts.Name = "request_size_bytes" - opts.Help = "The HTTP request sizes in bytes." - reqSz := prometheus.NewSummary(opts) - - opts.Name = "response_size_bytes" - opts.Help = "The HTTP response sizes in bytes." - resSz := prometheus.NewSummary(opts) - - regReqCnt := MustRegisterOrGet(reqCnt).(*prometheus.CounterVec) - regReqDur := MustRegisterOrGet(reqDur).(prometheus.Summary) - regReqSz := MustRegisterOrGet(reqSz).(prometheus.Summary) - regResSz := MustRegisterOrGet(resSz).(prometheus.Summary) - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - now := time.Now() - - delegate := &responseWriterDelegator{ResponseWriter: w} - out := make(chan int) - urlLen := 0 - if r.URL != nil { - urlLen = len(r.URL.String()) - } - go computeApproximateRequestSize(r, out, urlLen) - - _, cn := w.(http.CloseNotifier) - _, fl := w.(http.Flusher) - _, hj := w.(http.Hijacker) - _, rf := w.(io.ReaderFrom) - var rw http.ResponseWriter - if cn && fl && hj && rf { - rw = &fancyResponseWriterDelegator{delegate} - } else { - rw = delegate - } - handlerFunc(rw, r) - - elapsed := float64(time.Since(now)) / float64(time.Microsecond) - - method := sanitizeMethod(r.Method) - code := sanitizeCode(delegate.status) - regReqCnt.WithLabelValues(method, code).Inc() - regReqDur.Observe(elapsed) - regResSz.Observe(float64(delegate.written)) - regReqSz.Observe(float64(<-out)) - }) -} - -func computeApproximateRequestSize(r *http.Request, out chan int, s int) { - s += len(r.Method) - s += len(r.Proto) - for name, values := range r.Header { - s += len(name) - for _, value := range values { - s += len(value) - } - } - s += len(r.Host) - - // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. - - if r.ContentLength != -1 { - s += int(r.ContentLength) - } - out <- s -} - -func sanitizeMethod(m string) string { - switch m { - case "GET", "get": - return "get" - case "PUT", "put": - return "put" - case "HEAD", "head": - return "head" - case "POST", "post": - return "post" - case "DELETE", "delete": - return "delete" - case "CONNECT", "connect": - return "connect" - case "OPTIONS", "options": - return "options" - case "NOTIFY", "notify": - return "notify" - default: - return strings.ToLower(m) - } -} - -var instLabels = []string{"method", "code"} - -type responseWriterDelegator struct { - http.ResponseWriter - - handler, method string - status int - written int64 - wroteHeader bool -} - -func (r *responseWriterDelegator) WriteHeader(code int) { - r.status = code - r.wroteHeader = true - r.ResponseWriter.WriteHeader(code) -} - -func (r *responseWriterDelegator) Write(b []byte) (int, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.Write(b) - r.written += int64(n) - return n, err -} - -type fancyResponseWriterDelegator struct { - *responseWriterDelegator -} - -func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool { - return f.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - -func (f *fancyResponseWriterDelegator) Flush() { - f.ResponseWriter.(http.Flusher).Flush() -} - -func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return f.ResponseWriter.(http.Hijacker).Hijack() -} - -func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) { - if !f.wroteHeader { - f.WriteHeader(http.StatusOK) - } - n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r) - f.written += n - return n, err -} - -func sanitizeCode(s int) string { - switch s { - case 100: - return "100" - case 101: - return "101" - - case 200: - return "200" - case 201: - return "201" - case 202: - return "202" - case 203: - return "203" - case 204: - return "204" - case 205: - return "205" - case 206: - return "206" - - case 300: - return "300" - case 301: - return "301" - case 302: - return "302" - case 304: - return "304" - case 305: - return "305" - case 307: - return "307" - - case 400: - return "400" - case 401: - return "401" - case 402: - return "402" - case 403: - return "403" - case 404: - return "404" - case 405: - return "405" - case 406: - return "406" - case 407: - return "407" - case 408: - return "408" - case 409: - return "409" - case 410: - return "410" - case 411: - return "411" - case 412: - return "412" - case 413: - return "413" - case 414: - return "414" - case 415: - return "415" - case 416: - return "416" - case 417: - return "417" - case 418: - return "418" - - case 500: - return "500" - case 501: - return "501" - case 502: - return "502" - case 503: - return "503" - case 504: - return "504" - case 505: - return "505" - - case 428: - return "428" - case 429: - return "429" - case 431: - return "431" - case 511: - return "511" - - default: - return strconv.Itoa(s) - } -} - -// RegisterOrGet registers the provided Collector with the DefaultRegisterer and -// returns the Collector, unless an equal Collector was registered before, in -// which case that Collector is returned. -func RegisterOrGet(c prometheus.Collector) (prometheus.Collector, error) { - if err := prometheus.Register(c); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - return are.ExistingCollector, nil - } - return nil, err - } - return c, nil -} - -// MustRegisterOrGet behaves like RegisterOrGet but panics instead of returning -// an error. -func MustRegisterOrGet(c prometheus.Collector) prometheus.Collector { - c, err := RegisterOrGet(c) - if err != nil { - panic(err) - } - return c -} diff --git a/vendor/github.com/sean-/seed/.gitignore b/vendor/github.com/sean-/seed/.gitignore new file mode 100644 index 00000000000..daf913b1b34 --- /dev/null +++ b/vendor/github.com/sean-/seed/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/sean-/seed/LICENSE b/vendor/github.com/sean-/seed/LICENSE new file mode 100644 index 00000000000..33d326a371b --- /dev/null +++ b/vendor/github.com/sean-/seed/LICENSE @@ -0,0 +1,54 @@ +MIT License + +Copyright (c) 2017 Sean Chittenden +Copyright (c) 2016 Alex Dadgar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +===== + +Bits of Go-lang's `once.Do()` were cribbed and reused here, too. + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/sean-/seed/README.md b/vendor/github.com/sean-/seed/README.md new file mode 100644 index 00000000000..0137564f0c5 --- /dev/null +++ b/vendor/github.com/sean-/seed/README.md @@ -0,0 +1,44 @@ +# `seed` - Quickly Seed Go's Random Number Generator + +Boiler-plate to securely [seed](https://en.wikipedia.org/wiki/Random_seed) Go's +random number generator (if possible). This library isn't anything fancy, it's +just a canonical way of seeding Go's random number generator. Cribbed from +[`Nomad`](https://github.com/hashicorp/nomad/commit/f89a993ec6b91636a3384dd568898245fbc273a1) +before it was moved into +[`Consul`](https://github.com/hashicorp/consul/commit/d695bcaae6e31ee307c11fdf55bb0bf46ea9fcf4) +and made into a helper function, and now further modularized to be a super +lightweight and reusable library. + +Time is better than +[Go's default seed of `1`](https://golang.org/pkg/math/rand/#Seed), but friends +don't let friends use time as a seed to a random number generator. Use +`seed.MustInit()` instead. + +`seed.Init()` is an idempotent and reentrant call that will return an error if +it can't seed the value the first time it is called. `Init()` is reentrant. + +`seed.MustInit()` is idempotent and reentrant call that will `panic()` if it +can't seed the value the first time it is called. `MustInit()` is reentrant. + +## Usage + +``` +package mypackage + +import ( + "github.com/sean-/seed" +) + +// MustInit will panic() if it is unable to set a high-entropy random seed: +func init() { + seed.MustInit() +} + +// Or if you want to not panic() and can actually handle this error: +func init() { + if secure, err := !seed.Init(); !secure { + // Handle the error + //panic(fmt.Sprintf("Unable to securely seed Go's RNG: %v", err)) + } +} +``` diff --git a/vendor/github.com/sean-/seed/init.go b/vendor/github.com/sean-/seed/init.go new file mode 100644 index 00000000000..248d6b636c7 --- /dev/null +++ b/vendor/github.com/sean-/seed/init.go @@ -0,0 +1,84 @@ +package seed + +import ( + crand "crypto/rand" + "fmt" + "math" + "math/big" + "math/rand" + "sync" + "sync/atomic" + "time" +) + +var ( + m sync.Mutex + secure int32 + seeded int32 +) + +func cryptoSeed() error { + defer atomic.StoreInt32(&seeded, 1) + + var err error + var n *big.Int + n, err = crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) + if err != nil { + rand.Seed(time.Now().UTC().UnixNano()) + return err + } + rand.Seed(n.Int64()) + atomic.StoreInt32(&secure, 1) + return nil +} + +// Init provides best-effort seeding (which is better than running with Go's +// default seed of 1). If `/dev/urandom` is available, Init() will seed Go's +// runtime with entropy from `/dev/urandom` and return true because the runtime +// was securely seeded. If Init() has already initialized the random number or +// it had failed to securely initialize the random number generation, Init() +// will return false. See MustInit(). +func Init() (seededSecurely bool, err error) { + if atomic.LoadInt32(&seeded) == 1 { + return false, nil + } + + // Slow-path + m.Lock() + defer m.Unlock() + + if err := cryptoSeed(); err != nil { + return false, err + } + + return true, nil +} + +// MustInit provides guaranteed secure seeding. If `/dev/urandom` is not +// available, MustInit will panic() with an error indicating why reading from +// `/dev/urandom` failed. MustInit() will upgrade the seed if for some reason a +// call to Init() failed in the past. +func MustInit() { + if atomic.LoadInt32(&secure) == 1 { + return + } + + // Slow-path + m.Lock() + defer m.Unlock() + + if err := cryptoSeed(); err != nil { + panic(fmt.Sprintf("Unable to seed the random number generator: %v", err)) + } +} + +// Secure returns true if a cryptographically secure seed was used to +// initialize rand. +func Secure() bool { + return atomic.LoadInt32(&secure) == 1 +} + +// Seeded returns true if Init has seeded the random number generator. +func Seeded() bool { + return atomic.LoadInt32(&seeded) == 1 +} diff --git a/vendor/github.com/weaveworks/mesh/LICENSE b/vendor/github.com/weaveworks/mesh/LICENSE deleted file mode 100644 index 8dada3edaf5..00000000000 --- a/vendor/github.com/weaveworks/mesh/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/weaveworks/mesh/README.md b/vendor/github.com/weaveworks/mesh/README.md deleted file mode 100644 index 856768fc846..00000000000 --- a/vendor/github.com/weaveworks/mesh/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# mesh [![GoDoc](https://godoc.org/github.com/weaveworks/mesh?status.svg)](https://godoc.org/github.com/weaveworks/mesh) [![Circle CI](https://circleci.com/gh/weaveworks/mesh.svg?style=svg)](https://circleci.com/gh/weaveworks/mesh) - -Mesh is a tool for building distributed applications. - -Mesh implements a [gossip protocol](https://en.wikipedia.org/wiki/Gossip_protocol) -that provide membership, unicast, and broadcast functionality -with [eventually-consistent semantics](https://en.wikipedia.org/wiki/Eventual_consistency). -In CAP terms, it is AP: highly-available and partition-tolerant. - -Mesh works in a wide variety of network setups, including thru NAT and firewalls, and across clouds and datacenters. -It works in situations where there is only partial connectivity, - i.e. data is transparently routed across multiple hops when there is no direct connection between peers. -It copes with partitions and partial network failure. -It can be easily bootstrapped, typically only requiring knowledge of a single existing peer in the mesh to join. -It has built-in shared-secret authentication and encryption. -It scales to on the order of 100 peers, and has no dependencies. - -## Using - -Mesh is currently distributed as a Go package. -See [the API documentation](https://godoc.org/github.com/weaveworks/mesh). - -We plan to offer Mesh as a standalone service + an easy-to-use API. -We will support multiple deployment scenarios, including - as a standalone binary, - as a container, - as an ambassador or [sidecar](http://blog.kubernetes.io/2015/06/the-distributed-system-toolkit-patterns.html) component to an existing container, - and as an infrastructure service in popular platforms. - -## Developing - -Mesh builds with the standard Go tooling. You will need to put the -repository in Go's expected directory structure; i.e., -`$GOPATH/src/github.com/weaveworks/mesh`. - -### Building - -If necessary, you may fetch the latest version of all of the dependencies into your GOPATH via - -`go get -d -u -t ./...` - -Build the code with the usual - -`go install ./...` - -### Testing - -Assuming you've fetched dependencies as above, - -`go test ./...` - -### Dependencies - -Mesh is a library, designed to be imported into a binary package. -Vendoring is currently the best way for binary package authors to ensure reliable, reproducible builds. -Therefore, we strongly recommend our users use vendoring for all of their dependencies, including Mesh. -To avoid compatibility and availability issues, Mesh doesn't vendor its own dependencies, and doesn't recommend use of third-party import proxies. - -There are several tools to make vendoring easier, including - [gb](https://getgb.io), - [gvt](https://github.com/filosottile/gvt), - [glide](https://github.com/Masterminds/glide), and - [govendor](https://github.com/kardianos/govendor). - -### Workflow - -Mesh follows a typical PR workflow. -All contributions should be made as pull requests that satisfy the guidelines, below. - -### Guidelines - -- All code must abide [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) -- Names should abide [What's in a name](https://talks.golang.org/2014/names.slide#1) -- Code must build on both Linux and Darwin, via plain `go build` -- Code should have appropriate test coverage, invoked via plain `go test` - -In addition, several mechanical checks are enforced. -See [the lint script](/lint) for details. - diff --git a/vendor/github.com/weaveworks/mesh/circle.yml b/vendor/github.com/weaveworks/mesh/circle.yml deleted file mode 100644 index 6f4df805041..00000000000 --- a/vendor/github.com/weaveworks/mesh/circle.yml +++ /dev/null @@ -1,4 +0,0 @@ -test: - pre: - - ./lint - diff --git a/vendor/github.com/weaveworks/mesh/connection.go b/vendor/github.com/weaveworks/mesh/connection.go deleted file mode 100644 index 545f98bd2c7..00000000000 --- a/vendor/github.com/weaveworks/mesh/connection.go +++ /dev/null @@ -1,500 +0,0 @@ -package mesh - -import ( - "fmt" - "net" - "strconv" - "time" -) - -// Connection describes a link between peers. -// It may be in any state, not necessarily established. -type Connection interface { - Remote() *Peer - - getLocal() *Peer - remoteTCPAddress() string - isOutbound() bool - isEstablished() bool -} - -type ourConnection interface { - Connection - - breakTie(ourConnection) connectionTieBreak - shutdown(error) - logf(format string, args ...interface{}) -} - -// A local representation of the remote side of a connection. -// Limited capabilities compared to LocalConnection. -type remoteConnection struct { - local *Peer - remote *Peer - remoteTCPAddr string - outbound bool - established bool -} - -func newRemoteConnection(from, to *Peer, tcpAddr string, outbound bool, established bool) *remoteConnection { - return &remoteConnection{ - local: from, - remote: to, - remoteTCPAddr: tcpAddr, - outbound: outbound, - established: established, - } -} - -func (conn *remoteConnection) Remote() *Peer { return conn.remote } - -func (conn *remoteConnection) getLocal() *Peer { return conn.local } - -func (conn *remoteConnection) remoteTCPAddress() string { return conn.remoteTCPAddr } - -func (conn *remoteConnection) isOutbound() bool { return conn.outbound } - -func (conn *remoteConnection) isEstablished() bool { return conn.established } - -// LocalConnection is the local (our) side of a connection. -// It implements ProtocolSender, and manages per-channel GossipSenders. -type LocalConnection struct { - OverlayConn OverlayConnection - - remoteConnection - tcpConn *net.TCPConn - trustRemote bool // is remote on a trusted subnet? - trustedByRemote bool // does remote trust us? - version byte - tcpSender tcpSender - sessionKey *[32]byte - heartbeatTCP *time.Ticker - router *Router - uid uint64 - actionChan chan<- connectionAction - errorChan chan<- error - finished <-chan struct{} // closed to signal that actorLoop has finished - senders *gossipSenders - logger Logger -} - -// If the connection is successful, it will end up in the local peer's -// connections map. -func startLocalConnection(connRemote *remoteConnection, tcpConn *net.TCPConn, router *Router, acceptNewPeer bool, logger Logger) { - if connRemote.local != router.Ourself.Peer { - panic("attempt to create local connection from a peer which is not ourself") - } - actionChan := make(chan connectionAction, ChannelSize) - errorChan := make(chan error, 1) - finished := make(chan struct{}) - conn := &LocalConnection{ - remoteConnection: *connRemote, // NB, we're taking a copy of connRemote here. - router: router, - tcpConn: tcpConn, - trustRemote: router.trusts(connRemote), - uid: randUint64(), - actionChan: actionChan, - errorChan: errorChan, - finished: finished, - logger: logger, - } - conn.senders = newGossipSenders(conn, finished) - go conn.run(actionChan, errorChan, finished, acceptNewPeer) -} - -func (conn *LocalConnection) logf(format string, args ...interface{}) { - format = "->[" + conn.remoteTCPAddr + "|" + conn.remote.String() + "]: " + format - conn.logger.Printf(format, args...) -} - -func (conn *LocalConnection) breakTie(dupConn ourConnection) connectionTieBreak { - dupConnLocal := dupConn.(*LocalConnection) - // conn.uid is used as the tie breaker here, in the knowledge that - // both sides will make the same decision. - if conn.uid < dupConnLocal.uid { - return tieBreakWon - } else if dupConnLocal.uid < conn.uid { - return tieBreakLost - } - return tieBreakTied -} - -// Established returns true if the connection is established. -// TODO(pb): data race? -func (conn *LocalConnection) isEstablished() bool { - return conn.established -} - -// SendProtocolMsg implements ProtocolSender. -func (conn *LocalConnection) SendProtocolMsg(m protocolMsg) error { - if err := conn.sendProtocolMsg(m); err != nil { - conn.shutdown(err) - return err - } - return nil -} - -func (conn *LocalConnection) gossipSenders() *gossipSenders { - return conn.senders -} - -// ACTOR methods - -// NB: The conn.* fields are only written by the connection actor -// process, which is the caller of the ConnectionAction funs. Hence we -// do not need locks for reading, and only need write locks for fields -// read by other processes. - -// Non-blocking. -func (conn *LocalConnection) shutdown(err error) { - // err should always be a real error, even if only io.EOF - if err == nil { - panic("nil error") - } - - select { - case conn.errorChan <- err: - default: - } -} - -// Send an actor request to the actorLoop, but don't block if actorLoop has -// exited. See http://blog.golang.org/pipelines for pattern. -func (conn *LocalConnection) sendAction(action connectionAction) { - select { - case conn.actionChan <- action: - case <-conn.finished: - } -} - -// ACTOR server - -func (conn *LocalConnection) run(actionChan <-chan connectionAction, errorChan <-chan error, finished chan<- struct{}, acceptNewPeer bool) { - var err error // important to use this var and not create another one with 'err :=' - defer func() { conn.teardown(err) }() - defer close(finished) - - if err = conn.tcpConn.SetLinger(0); err != nil { - return - } - - intro, err := protocolIntroParams{ - MinVersion: conn.router.ProtocolMinVersion, - MaxVersion: ProtocolMaxVersion, - Features: conn.makeFeatures(), - Conn: conn.tcpConn, - Password: conn.router.Password, - Outbound: conn.outbound, - }.doIntro() - if err != nil { - return - } - - conn.sessionKey = intro.SessionKey - conn.tcpSender = intro.Sender - conn.version = intro.Version - - remote, err := conn.parseFeatures(intro.Features) - if err != nil { - return - } - - if err = conn.registerRemote(remote, acceptNewPeer); err != nil { - return - } - isRestartedPeer := conn.Remote().UID != remote.UID - - conn.logf("connection ready; using protocol version %v", conn.version) - - // only use negotiated session key for untrusted connections - var sessionKey *[32]byte - if conn.untrusted() { - sessionKey = conn.sessionKey - } - - params := OverlayConnectionParams{ - RemotePeer: conn.remote, - LocalAddr: conn.tcpConn.LocalAddr().(*net.TCPAddr), - RemoteAddr: conn.tcpConn.RemoteAddr().(*net.TCPAddr), - Outbound: conn.outbound, - ConnUID: conn.uid, - SessionKey: sessionKey, - SendControlMessage: conn.sendOverlayControlMessage, - Features: intro.Features, - } - if conn.OverlayConn, err = conn.router.Overlay.PrepareConnection(params); err != nil { - return - } - - // As soon as we do AddConnection, the new connection becomes - // visible to the packet routing logic. So AddConnection must - // come after PrepareConnection - if err = conn.router.Ourself.doAddConnection(conn, isRestartedPeer); err != nil { - return - } - conn.router.ConnectionMaker.connectionCreated(conn) - - // OverlayConnection confirmation comes after AddConnection, - // because only after that completes do we know the connection is - // valid: in particular that it is not a duplicate connection to - // the same peer. Overlay communication on a duplicate connection - // can cause problems such as tripping up overlay crypto at the - // other end due to data being decoded by the other connection. It - // is also generally wasteful to engage in any interaction with - // the remote on a connection that turns out to be invalid. - conn.OverlayConn.Confirm() - - // receiveTCP must follow also AddConnection. In the absence - // of any indirect connectivity to the remote peer, the first - // we hear about it (and any peers reachable from it) is - // through topology gossip it sends us on the connection. We - // must ensure that the connection has been added to Ourself - // prior to processing any such gossip, otherwise we risk - // immediately gc'ing part of that newly received portion of - // the topology (though not the remote peer itself, since that - // will have a positive ref count), leaving behind dangling - // references to peers. Hence we must invoke AddConnection, - // which is *synchronous*, first. - conn.heartbeatTCP = time.NewTicker(tcpHeartbeat) - go conn.receiveTCP(intro.Receiver) - - // AddConnection must precede actorLoop. More precisely, it - // must precede shutdown, since that invokes DeleteConnection - // and is invoked on termination of this entire - // function. Essentially this boils down to a prohibition on - // running AddConnection in a separate goroutine, at least not - // without some synchronisation. Which in turn requires the - // launching of the receiveTCP goroutine to precede actorLoop. - err = conn.actorLoop(actionChan, errorChan) -} - -func (conn *LocalConnection) makeFeatures() map[string]string { - features := map[string]string{ - "PeerNameFlavour": PeerNameFlavour, - "Name": conn.local.Name.String(), - "NickName": conn.local.NickName, - "ShortID": fmt.Sprint(conn.local.ShortID), - "UID": fmt.Sprint(conn.local.UID), - "ConnID": fmt.Sprint(conn.uid), - "Trusted": fmt.Sprint(conn.trustRemote), - } - conn.router.Overlay.AddFeaturesTo(features) - return features -} - -func (conn *LocalConnection) parseFeatures(features map[string]string) (*Peer, error) { - if err := mustHave(features, []string{"PeerNameFlavour", "Name", "NickName", "UID", "ConnID"}); err != nil { - return nil, err - } - - remotePeerNameFlavour := features["PeerNameFlavour"] - if remotePeerNameFlavour != PeerNameFlavour { - return nil, fmt.Errorf("Peer name flavour mismatch (ours: '%s', theirs: '%s')", PeerNameFlavour, remotePeerNameFlavour) - } - - name, err := PeerNameFromString(features["Name"]) - if err != nil { - return nil, err - } - - nickName := features["NickName"] - - var shortID uint64 - var hasShortID bool - if shortIDStr, ok := features["ShortID"]; ok { - hasShortID = true - shortID, err = strconv.ParseUint(shortIDStr, 10, peerShortIDBits) - if err != nil { - return nil, err - } - } - - var trusted bool - if trustedStr, ok := features["Trusted"]; ok { - trusted, err = strconv.ParseBool(trustedStr) - if err != nil { - return nil, err - } - } - conn.trustedByRemote = trusted - - uid, err := parsePeerUID(features["UID"]) - if err != nil { - return nil, err - } - - remoteConnID, err := strconv.ParseUint(features["ConnID"], 10, 64) - if err != nil { - return nil, err - } - - conn.uid ^= remoteConnID - peer := newPeer(name, nickName, uid, 0, PeerShortID(shortID)) - peer.HasShortID = hasShortID - return peer, nil -} - -func (conn *LocalConnection) registerRemote(remote *Peer, acceptNewPeer bool) error { - if acceptNewPeer { - conn.remote = conn.router.Peers.fetchWithDefault(remote) - } else { - conn.remote = conn.router.Peers.fetchAndAddRef(remote.Name) - if conn.remote == nil { - return fmt.Errorf("Found unknown remote name: %s at %s", remote.Name, conn.remoteTCPAddr) - } - } - - if remote.Name == conn.local.Name && remote.UID != conn.local.UID { - return &peerNameCollisionError{conn.local, remote} - } - if conn.remote == conn.local { - return errConnectToSelf - } - - return nil -} - -func (conn *LocalConnection) actorLoop(actionChan <-chan connectionAction, errorChan <-chan error) (err error) { - fwdErrorChan := conn.OverlayConn.ErrorChannel() - fwdEstablishedChan := conn.OverlayConn.EstablishedChannel() - - for err == nil { - select { - case err = <-errorChan: - case err = <-fwdErrorChan: - default: - select { - case action := <-actionChan: - err = action() - case <-conn.heartbeatTCP.C: - err = conn.sendSimpleProtocolMsg(ProtocolHeartbeat) - case <-fwdEstablishedChan: - conn.established = true - fwdEstablishedChan = nil - conn.router.Ourself.doConnectionEstablished(conn) - case err = <-errorChan: - case err = <-fwdErrorChan: - } - } - } - - return -} - -func (conn *LocalConnection) teardown(err error) { - if conn.remote == nil { - conn.logger.Printf("->[%s] connection shutting down due to error during handshake: %v", conn.remoteTCPAddr, err) - } else { - conn.logf("connection shutting down due to error: %v", err) - } - - if conn.tcpConn != nil { - if closeErr := conn.tcpConn.Close(); closeErr != nil { - conn.logger.Printf("warning: %v", closeErr) - } - } - - if conn.remote != nil { - conn.router.Peers.dereference(conn.remote) - conn.router.Ourself.doDeleteConnection(conn) - } - - if conn.heartbeatTCP != nil { - conn.heartbeatTCP.Stop() - } - - if conn.OverlayConn != nil { - conn.OverlayConn.Stop() - } - - conn.router.ConnectionMaker.connectionTerminated(conn, err) -} - -func (conn *LocalConnection) sendOverlayControlMessage(tag byte, msg []byte) error { - return conn.sendProtocolMsg(protocolMsg{protocolTag(tag), msg}) -} - -// Helpers - -func (conn *LocalConnection) sendSimpleProtocolMsg(tag protocolTag) error { - return conn.sendProtocolMsg(protocolMsg{tag: tag}) -} - -func (conn *LocalConnection) sendProtocolMsg(m protocolMsg) error { - return conn.tcpSender.Send(append([]byte{byte(m.tag)}, m.msg...)) -} - -func (conn *LocalConnection) receiveTCP(receiver tcpReceiver) { - var err error - for { - if err = conn.extendReadDeadline(); err != nil { - break - } - var msg []byte - if msg, err = receiver.Receive(); err != nil { - break - } - if len(msg) < 1 { - conn.logf("ignoring blank msg") - continue - } - if err = conn.handleProtocolMsg(protocolTag(msg[0]), msg[1:]); err != nil { - break - } - } - conn.shutdown(err) -} - -func (conn *LocalConnection) handleProtocolMsg(tag protocolTag, payload []byte) error { - switch tag { - case ProtocolHeartbeat: - case ProtocolReserved1, ProtocolReserved2, ProtocolReserved3, ProtocolOverlayControlMsg: - conn.OverlayConn.ControlMessage(byte(tag), payload) - case ProtocolGossipUnicast, ProtocolGossipBroadcast, ProtocolGossip: - return conn.router.handleGossip(tag, payload) - default: - conn.logf("ignoring unknown protocol tag: %v", tag) - } - return nil -} - -func (conn *LocalConnection) extendReadDeadline() error { - return conn.tcpConn.SetReadDeadline(time.Now().Add(tcpHeartbeat * 2)) -} - -// Untrusted returns true if either we don't trust our remote, or are not -// trusted by our remote. -func (conn *LocalConnection) untrusted() bool { - return !conn.trustRemote || !conn.trustedByRemote -} - -type connectionTieBreak int - -const ( - tieBreakWon connectionTieBreak = iota - tieBreakLost - tieBreakTied -) - -var errConnectToSelf = fmt.Errorf("cannot connect to ourself") - -type peerNameCollisionError struct { - local, remote *Peer -} - -func (err *peerNameCollisionError) Error() string { - return fmt.Sprintf("local %q and remote %q peer names collision", err.local, err.remote) -} - -// The actor closure used by LocalConnection. If an action returns an error, -// it will terminate the actor loop, which terminates the connection in turn. -type connectionAction func() error - -func mustHave(features map[string]string, keys []string) error { - for _, key := range keys { - if _, ok := features[key]; !ok { - return fmt.Errorf("field %s is missing", key) - } - } - return nil -} diff --git a/vendor/github.com/weaveworks/mesh/connection_maker.go b/vendor/github.com/weaveworks/mesh/connection_maker.go deleted file mode 100644 index 849161b0ad1..00000000000 --- a/vendor/github.com/weaveworks/mesh/connection_maker.go +++ /dev/null @@ -1,399 +0,0 @@ -package mesh - -import ( - "fmt" - "math/rand" - "net" - "time" - "unicode" -) - -const ( - initialInterval = 2 * time.Second - maxInterval = 6 * time.Minute - resetAfter = 1 * time.Minute -) - -type peerAddrs map[string]*net.TCPAddr - -// ConnectionMaker initiates and manages connections to peers. -type connectionMaker struct { - ourself *localPeer - peers *Peers - localAddr string - port int - discovery bool - targets map[string]*target - connections map[Connection]struct{} - directPeers peerAddrs - terminationCount int - actionChan chan<- connectionMakerAction - logger Logger -} - -// TargetState describes the connection state of a remote target. -type targetState int - -const ( - targetWaiting targetState = iota - targetAttempting - targetConnected - targetSuspended -) - -// Information about an address where we may find a peer. -type target struct { - state targetState - lastError error // reason for disconnection last time - tryAfter time.Time // next time to try this address - tryInterval time.Duration // retry delay on next failure -} - -// The actor closure used by ConnectionMaker. If an action returns true, the -// ConnectionMaker will check the state of its targets, and reconnect to -// relevant candidates. -type connectionMakerAction func() bool - -// newConnectionMaker returns a usable ConnectionMaker, seeded with -// peers, making outbound connections from localAddr, and listening on -// port. If discovery is true, ConnectionMaker will attempt to -// initiate new connections with peers it's not directly connected to. -func newConnectionMaker(ourself *localPeer, peers *Peers, localAddr string, port int, discovery bool, logger Logger) *connectionMaker { - actionChan := make(chan connectionMakerAction, ChannelSize) - cm := &connectionMaker{ - ourself: ourself, - peers: peers, - localAddr: localAddr, - port: port, - discovery: discovery, - directPeers: peerAddrs{}, - targets: make(map[string]*target), - connections: make(map[Connection]struct{}), - actionChan: actionChan, - logger: logger, - } - go cm.queryLoop(actionChan) - return cm -} - -// InitiateConnections creates new connections to the provided peers, -// specified in host:port format. If replace is true, any existing direct -// peers are forgotten. -// -// TODO(pb): Weave Net invokes router.ConnectionMaker.InitiateConnections; -// it may be better to provide that on Router directly. -func (cm *connectionMaker) InitiateConnections(peers []string, replace bool) []error { - errors := []error{} - addrs := peerAddrs{} - for _, peer := range peers { - host, port, err := net.SplitHostPort(peer) - if err != nil { - host = peer - port = "0" // we use that as an indication that "no port was supplied" - } - if host == "" || !isAlnum(port) { - errors = append(errors, fmt.Errorf("invalid peer name %q, should be host[:port]", peer)) - } else if addr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%s", host, port)); err != nil { - errors = append(errors, err) - } else { - addrs[peer] = addr - } - } - cm.actionChan <- func() bool { - if replace { - cm.directPeers = peerAddrs{} - } - for peer, addr := range addrs { - cm.directPeers[peer] = addr - // curtail any existing reconnect interval - if target, found := cm.targets[cm.completeAddr(*addr)]; found { - target.nextTryNow() - } - } - return true - } - return errors -} - -func isAlnum(s string) bool { - for _, c := range s { - if !unicode.In(c, unicode.Letter, unicode.Digit) { - return false - } - } - return true -} - -// ForgetConnections removes direct connections to the provided peers, -// specified in host:port format. -// -// TODO(pb): Weave Net invokes router.ConnectionMaker.ForgetConnections; -// it may be better to provide that on Router directly. -func (cm *connectionMaker) ForgetConnections(peers []string) { - cm.actionChan <- func() bool { - for _, peer := range peers { - delete(cm.directPeers, peer) - } - return true - } -} - -// Targets takes a snapshot of the targets (direct peers), -// either just the ones we are still trying, or all of them. -// Note these are the same things that InitiateConnections and ForgetConnections talks about, -// but a method to retrieve 'Connections' would obviously return the current connections. -func (cm *connectionMaker) Targets(activeOnly bool) []string { - resultChan := make(chan []string, 0) - cm.actionChan <- func() bool { - var slice []string - for peer, addr := range cm.directPeers { - if activeOnly { - if target, ok := cm.targets[cm.completeAddr(*addr)]; ok && target.tryAfter.IsZero() { - continue - } - } - slice = append(slice, peer) - } - resultChan <- slice - return false - } - return <-resultChan -} - -// connectionAborted marks the target identified by address as broken, and -// puts it in the TargetWaiting state. -func (cm *connectionMaker) connectionAborted(address string, err error) { - cm.actionChan <- func() bool { - target := cm.targets[address] - target.state = targetWaiting - target.lastError = err - target.nextTryLater() - return true - } -} - -// connectionCreated registers the passed connection, and marks the target -// identified by conn.RemoteTCPAddr() as established, and puts it in the -// TargetConnected state. -func (cm *connectionMaker) connectionCreated(conn Connection) { - cm.actionChan <- func() bool { - cm.connections[conn] = struct{}{} - if conn.isOutbound() { - target := cm.targets[conn.remoteTCPAddress()] - target.state = targetConnected - } - return false - } -} - -// connectionTerminated unregisters the passed connection, and marks the -// target identified by conn.RemoteTCPAddr() as Waiting. -func (cm *connectionMaker) connectionTerminated(conn Connection, err error) { - cm.actionChan <- func() bool { - if err != errConnectToSelf { - cm.terminationCount++ - } - delete(cm.connections, conn) - if conn.isOutbound() { - target := cm.targets[conn.remoteTCPAddress()] - target.state = targetWaiting - target.lastError = err - _, peerNameCollision := err.(*peerNameCollisionError) - switch { - case peerNameCollision || err == errConnectToSelf: - target.nextTryNever() - case time.Now().After(target.tryAfter.Add(resetAfter)): - target.nextTryNow() - default: - target.nextTryLater() - } - } - return true - } -} - -// refresh sends a no-op action into the ConnectionMaker, purely so that the -// ConnectionMaker will check the state of its targets and reconnect to -// relevant candidates. -func (cm *connectionMaker) refresh() { - cm.actionChan <- func() bool { return true } -} - -func (cm *connectionMaker) queryLoop(actionChan <-chan connectionMakerAction) { - timer := time.NewTimer(maxDuration) - run := func() { timer.Reset(cm.checkStateAndAttemptConnections()) } - for { - select { - case action := <-actionChan: - if action() { - run() - } - case <-timer.C: - run() - } - } -} - -func (cm *connectionMaker) completeAddr(addr net.TCPAddr) string { - if addr.Port == 0 { - addr.Port = cm.port - } - return addr.String() -} - -func (cm *connectionMaker) checkStateAndAttemptConnections() time.Duration { - var ( - validTarget = make(map[string]struct{}) - directTarget = make(map[string]struct{}) - ) - ourConnectedPeers, ourConnectedTargets, ourInboundIPs := cm.ourConnections() - - addTarget := func(address string) { - if _, connected := ourConnectedTargets[address]; connected { - return - } - validTarget[address] = struct{}{} - if _, found := cm.targets[address]; found { - return - } - tgt := &target{state: targetWaiting} - tgt.nextTryNow() - cm.targets[address] = tgt - } - - // Add direct targets that are not connected - for _, addr := range cm.directPeers { - attempt := true - if addr.Port == 0 { - // If a peer was specified w/o a port, then we do not - // attempt to connect to it if we have any inbound - // connections from that IP. - if _, connected := ourInboundIPs[addr.IP.String()]; connected { - attempt = false - } - } - address := cm.completeAddr(*addr) - directTarget[address] = struct{}{} - if attempt { - addTarget(address) - } - } - - // Add targets for peers that someone else is connected to, but we - // aren't - if cm.discovery { - cm.addPeerTargets(ourConnectedPeers, addTarget) - } - - return cm.connectToTargets(validTarget, directTarget) -} - -func (cm *connectionMaker) ourConnections() (peerNameSet, map[string]struct{}, map[string]struct{}) { - var ( - ourConnectedPeers = make(peerNameSet) - ourConnectedTargets = make(map[string]struct{}) - ourInboundIPs = make(map[string]struct{}) - ) - for conn := range cm.connections { - address := conn.remoteTCPAddress() - ourConnectedPeers[conn.Remote().Name] = struct{}{} - ourConnectedTargets[address] = struct{}{} - if conn.isOutbound() { - continue - } - if ip, _, err := net.SplitHostPort(address); err == nil { // should always succeed - ourInboundIPs[ip] = struct{}{} - } - } - return ourConnectedPeers, ourConnectedTargets, ourInboundIPs -} - -func (cm *connectionMaker) addPeerTargets(ourConnectedPeers peerNameSet, addTarget func(string)) { - cm.peers.forEach(func(peer *Peer) { - if peer == cm.ourself.Peer { - return - } - // Modifying peer.connections requires a write lock on Peers, - // and since we are holding a read lock (due to the ForEach), - // access without locking the peer is safe. - for otherPeer, conn := range peer.connections { - if otherPeer == cm.ourself.Name { - continue - } - if _, connected := ourConnectedPeers[otherPeer]; connected { - continue - } - address := conn.remoteTCPAddress() - if conn.isOutbound() { - addTarget(address) - } else if ip, _, err := net.SplitHostPort(address); err == nil { - // There is no point connecting to the (likely - // ephemeral) remote port of an inbound connection - // that some peer has. Let's try to connect on the - // weave port instead. - addTarget(fmt.Sprintf("%s:%d", ip, cm.port)) - } - } - }) -} - -func (cm *connectionMaker) connectToTargets(validTarget map[string]struct{}, directTarget map[string]struct{}) time.Duration { - now := time.Now() // make sure we catch items just added - after := maxDuration - for address, target := range cm.targets { - if target.state != targetWaiting && target.state != targetSuspended { - continue - } - if _, valid := validTarget[address]; !valid { - // Not valid: suspend reconnects if direct peer, - // otherwise forget this target entirely - if _, direct := directTarget[address]; direct { - target.state = targetSuspended - } else { - delete(cm.targets, address) - } - continue - } - if target.tryAfter.IsZero() { - continue - } - target.state = targetWaiting - switch duration := target.tryAfter.Sub(now); { - case duration <= 0: - target.state = targetAttempting - _, isCmdLineTarget := directTarget[address] - go cm.attemptConnection(address, isCmdLineTarget) - case duration < after: - after = duration - } - } - return after -} - -func (cm *connectionMaker) attemptConnection(address string, acceptNewPeer bool) { - cm.logger.Printf("->[%s] attempting connection", address) - if err := cm.ourself.createConnection(cm.localAddr, address, acceptNewPeer, cm.logger); err != nil { - cm.logger.Printf("->[%s] error during connection attempt: %v", address, err) - cm.connectionAborted(address, err) - } -} - -func (t *target) nextTryNever() { - t.tryAfter = time.Time{} - t.tryInterval = maxInterval -} - -func (t *target) nextTryNow() { - t.tryAfter = time.Now() - t.tryInterval = initialInterval -} - -// The delay at the nth retry is a random value in the range -// [i-i/2,i+i/2], where i = InitialInterval * 1.5^(n-1). -func (t *target) nextTryLater() { - t.tryAfter = time.Now().Add(t.tryInterval/2 + time.Duration(rand.Int63n(int64(t.tryInterval)))) - t.tryInterval = t.tryInterval * 3 / 2 - if t.tryInterval > maxInterval { - t.tryInterval = maxInterval - } -} diff --git a/vendor/github.com/weaveworks/mesh/gossip.go b/vendor/github.com/weaveworks/mesh/gossip.go deleted file mode 100644 index fe90d13316f..00000000000 --- a/vendor/github.com/weaveworks/mesh/gossip.go +++ /dev/null @@ -1,269 +0,0 @@ -package mesh - -import "sync" - -// Gossip is the sending interface. -// -// TODO(pb): rename to e.g. Sender -type Gossip interface { - // GossipUnicast emits a single message to a peer in the mesh. - // - // TODO(pb): rename to Unicast? - // - // Unicast takes []byte instead of GossipData because "to date there has - // been no compelling reason [in practice] to do merging on unicast." - // But there may be some motivation to have unicast Mergeable; see - // https://github.com/weaveworks/weave/issues/1764 - // - // TODO(pb): for uniformity of interface, rather take GossipData? - GossipUnicast(dst PeerName, msg []byte) error - - // GossipBroadcast emits a message to all peers in the mesh. - // - // TODO(pb): rename to Broadcast? - GossipBroadcast(update GossipData) -} - -// Gossiper is the receiving interface. -// -// TODO(pb): rename to e.g. Receiver -type Gossiper interface { - // OnGossipUnicast merges received data into state. - // - // TODO(pb): rename to e.g. OnUnicast - OnGossipUnicast(src PeerName, msg []byte) error - - // OnGossipBroadcast merges received data into state and returns a - // representation of the received data (typically a delta) for further - // propagation. - // - // TODO(pb): rename to e.g. OnBroadcast - OnGossipBroadcast(src PeerName, update []byte) (received GossipData, err error) - - // Gossip returns the state of everything we know; gets called periodically. - Gossip() (complete GossipData) - - // OnGossip merges received data into state and returns "everything new - // I've just learnt", or nil if nothing in the received data was new. - OnGossip(msg []byte) (delta GossipData, err error) -} - -// GossipData is a merge-able dataset. -// Think: log-structured data. -type GossipData interface { - // Encode encodes the data into multiple byte-slices. - Encode() [][]byte - - // Merge combines another GossipData into this one and returns the result. - // - // TODO(pb): does it need to be leave the original unmodified? - Merge(GossipData) GossipData -} - -// GossipSender accumulates GossipData that needs to be sent to one -// destination, and sends it when possible. GossipSender is one-to-one with a -// channel. -type gossipSender struct { - sync.Mutex - makeMsg func(msg []byte) protocolMsg - makeBroadcastMsg func(srcName PeerName, msg []byte) protocolMsg - sender protocolSender - gossip GossipData - broadcasts map[PeerName]GossipData - more chan<- struct{} - flush chan<- chan<- bool // for testing -} - -// NewGossipSender constructs a usable GossipSender. -func newGossipSender( - makeMsg func(msg []byte) protocolMsg, - makeBroadcastMsg func(srcName PeerName, msg []byte) protocolMsg, - sender protocolSender, - stop <-chan struct{}, -) *gossipSender { - more := make(chan struct{}, 1) - flush := make(chan chan<- bool) - s := &gossipSender{ - makeMsg: makeMsg, - makeBroadcastMsg: makeBroadcastMsg, - sender: sender, - broadcasts: make(map[PeerName]GossipData), - more: more, - flush: flush, - } - go s.run(stop, more, flush) - return s -} - -func (s *gossipSender) run(stop <-chan struct{}, more <-chan struct{}, flush <-chan chan<- bool) { - sent := false - for { - select { - case <-stop: - return - case <-more: - sentSomething, err := s.deliver(stop) - if err != nil { - return - } - sent = sent || sentSomething - case ch := <-flush: // for testing - // send anything pending, then reply back whether we sent - // anything since previous flush - select { - case <-more: - sentSomething, err := s.deliver(stop) - if err != nil { - return - } - sent = sent || sentSomething - default: - } - ch <- sent - sent = false - } - } -} - -func (s *gossipSender) deliver(stop <-chan struct{}) (bool, error) { - sent := false - // We must not hold our lock when sending, since that would block - // the callers of Send/Broadcast while we are stuck waiting for - // network congestion to clear. So we pick and send one piece of - // data at a time, only holding the lock during the picking. - for { - select { - case <-stop: - return sent, nil - default: - } - data, makeProtocolMsg := s.pick() - if data == nil { - return sent, nil - } - for _, msg := range data.Encode() { - if err := s.sender.SendProtocolMsg(makeProtocolMsg(msg)); err != nil { - return sent, err - } - } - sent = true - } -} - -func (s *gossipSender) pick() (data GossipData, makeProtocolMsg func(msg []byte) protocolMsg) { - s.Lock() - defer s.Unlock() - switch { - case s.gossip != nil: // usually more important than broadcasts - data = s.gossip - makeProtocolMsg = s.makeMsg - s.gossip = nil - case len(s.broadcasts) > 0: - for srcName, d := range s.broadcasts { - data = d - makeProtocolMsg = func(msg []byte) protocolMsg { return s.makeBroadcastMsg(srcName, msg) } - delete(s.broadcasts, srcName) - break - } - } - return -} - -// Send accumulates the GossipData and will send it eventually. -// Send and Broadcast accumulate into different buckets. -func (s *gossipSender) Send(data GossipData) { - s.Lock() - defer s.Unlock() - if s.empty() { - defer s.prod() - } - if s.gossip == nil { - s.gossip = data - } else { - s.gossip = s.gossip.Merge(data) - } -} - -// Broadcast accumulates the GossipData under the given srcName and will send -// it eventually. Send and Broadcast accumulate into different buckets. -func (s *gossipSender) Broadcast(srcName PeerName, data GossipData) { - s.Lock() - defer s.Unlock() - if s.empty() { - defer s.prod() - } - d, found := s.broadcasts[srcName] - if !found { - s.broadcasts[srcName] = data - } else { - s.broadcasts[srcName] = d.Merge(data) - } -} - -func (s *gossipSender) empty() bool { return s.gossip == nil && len(s.broadcasts) == 0 } - -func (s *gossipSender) prod() { - select { - case s.more <- struct{}{}: - default: - } -} - -// Flush sends all pending data, and returns true if anything was sent since -// the previous flush. For testing. -func (s *gossipSender) Flush() bool { - ch := make(chan bool) - s.flush <- ch - return <-ch -} - -// gossipSenders wraps a ProtocolSender (e.g. a LocalConnection) and yields -// per-channel GossipSenders. -// TODO(pb): may be able to remove this and use makeGossipSender directly -type gossipSenders struct { - sync.Mutex - sender protocolSender - stop <-chan struct{} - senders map[string]*gossipSender -} - -// NewGossipSenders returns a usable GossipSenders leveraging the ProtocolSender. -// TODO(pb): is stop chan the best way to do that? -func newGossipSenders(sender protocolSender, stop <-chan struct{}) *gossipSenders { - return &gossipSenders{ - sender: sender, - stop: stop, - senders: make(map[string]*gossipSender), - } -} - -// Sender yields the GossipSender for the named channel. -// It will use the factory function if no sender yet exists. -func (gs *gossipSenders) Sender(channelName string, makeGossipSender func(sender protocolSender, stop <-chan struct{}) *gossipSender) *gossipSender { - gs.Lock() - defer gs.Unlock() - s, found := gs.senders[channelName] - if !found { - s = makeGossipSender(gs.sender, gs.stop) - gs.senders[channelName] = s - } - return s -} - -// Flush flushes all managed senders. Used for testing. -func (gs *gossipSenders) Flush() bool { - sent := false - gs.Lock() - defer gs.Unlock() - for _, sender := range gs.senders { - sent = sender.Flush() || sent - } - return sent -} - -// GossipChannels is an index of channel name to gossip channel. -type gossipChannels map[string]*gossipChannel - -type gossipConnection interface { - gossipSenders() *gossipSenders -} diff --git a/vendor/github.com/weaveworks/mesh/gossip_channel.go b/vendor/github.com/weaveworks/mesh/gossip_channel.go deleted file mode 100644 index 2ff512e76fc..00000000000 --- a/vendor/github.com/weaveworks/mesh/gossip_channel.go +++ /dev/null @@ -1,152 +0,0 @@ -package mesh - -import ( - "bytes" - "encoding/gob" - "fmt" -) - -// gossipChannel is a logical communication channel within a physical mesh. -type gossipChannel struct { - name string - ourself *localPeer - routes *routes - gossiper Gossiper - logger Logger -} - -// newGossipChannel returns a named, usable channel. -// It delegates receiving duties to the passed Gossiper. -func newGossipChannel(channelName string, ourself *localPeer, r *routes, g Gossiper, logger Logger) *gossipChannel { - return &gossipChannel{ - name: channelName, - ourself: ourself, - routes: r, - gossiper: g, - logger: logger, - } -} - -func (c *gossipChannel) deliverUnicast(srcName PeerName, origPayload []byte, dec *gob.Decoder) error { - var destName PeerName - if err := dec.Decode(&destName); err != nil { - return err - } - if c.ourself.Name == destName { - var payload []byte - if err := dec.Decode(&payload); err != nil { - return err - } - return c.gossiper.OnGossipUnicast(srcName, payload) - } - if err := c.relayUnicast(destName, origPayload); err != nil { - c.logf("%v", err) - } - return nil -} - -func (c *gossipChannel) deliverBroadcast(srcName PeerName, _ []byte, dec *gob.Decoder) error { - var payload []byte - if err := dec.Decode(&payload); err != nil { - return err - } - data, err := c.gossiper.OnGossipBroadcast(srcName, payload) - if err != nil || data == nil { - return err - } - c.relayBroadcast(srcName, data) - return nil -} - -func (c *gossipChannel) deliver(srcName PeerName, _ []byte, dec *gob.Decoder) error { - var payload []byte - if err := dec.Decode(&payload); err != nil { - return err - } - update, err := c.gossiper.OnGossip(payload) - if err != nil || update == nil { - return err - } - c.relay(srcName, update) - return nil -} - -// GossipUnicast implements Gossip, relaying msg to dst, which must be a -// member of the channel. -func (c *gossipChannel) GossipUnicast(dstPeerName PeerName, msg []byte) error { - return c.relayUnicast(dstPeerName, gobEncode(c.name, c.ourself.Name, dstPeerName, msg)) -} - -// GossipBroadcast implements Gossip, relaying update to all members of the -// channel. -func (c *gossipChannel) GossipBroadcast(update GossipData) { - c.relayBroadcast(c.ourself.Name, update) -} - -// Send relays data into the channel topology via random neighbours. -func (c *gossipChannel) Send(data GossipData) { - c.relay(c.ourself.Name, data) -} - -// SendDown relays data into the channel topology via conn. -func (c *gossipChannel) SendDown(conn Connection, data GossipData) { - c.senderFor(conn).Send(data) -} - -func (c *gossipChannel) relayUnicast(dstPeerName PeerName, buf []byte) (err error) { - if relayPeerName, found := c.routes.UnicastAll(dstPeerName); !found { - err = fmt.Errorf("unknown relay destination: %s", dstPeerName) - } else if conn, found := c.ourself.ConnectionTo(relayPeerName); !found { - err = fmt.Errorf("unable to find connection to relay peer %s", relayPeerName) - } else { - err = conn.(protocolSender).SendProtocolMsg(protocolMsg{ProtocolGossipUnicast, buf}) - } - return err -} - -func (c *gossipChannel) relayBroadcast(srcName PeerName, update GossipData) { - c.routes.ensureRecalculated() - for _, conn := range c.ourself.ConnectionsTo(c.routes.BroadcastAll(srcName)) { - c.senderFor(conn).Broadcast(srcName, update) - } -} - -func (c *gossipChannel) relay(srcName PeerName, data GossipData) { - c.routes.ensureRecalculated() - for _, conn := range c.ourself.ConnectionsTo(c.routes.randomNeighbours(srcName)) { - c.senderFor(conn).Send(data) - } -} - -func (c *gossipChannel) senderFor(conn Connection) *gossipSender { - return conn.(gossipConnection).gossipSenders().Sender(c.name, c.makeGossipSender) -} - -func (c *gossipChannel) makeGossipSender(sender protocolSender, stop <-chan struct{}) *gossipSender { - return newGossipSender(c.makeMsg, c.makeBroadcastMsg, sender, stop) -} - -func (c *gossipChannel) makeMsg(msg []byte) protocolMsg { - return protocolMsg{ProtocolGossip, gobEncode(c.name, c.ourself.Name, msg)} -} - -func (c *gossipChannel) makeBroadcastMsg(srcName PeerName, msg []byte) protocolMsg { - return protocolMsg{ProtocolGossipBroadcast, gobEncode(c.name, srcName, msg)} -} - -func (c *gossipChannel) logf(format string, args ...interface{}) { - format = "[gossip " + c.name + "]: " + format - c.logger.Printf(format, args...) -} - -// GobEncode gob-encodes each item and returns the resulting byte slice. -func gobEncode(items ...interface{}) []byte { - buf := new(bytes.Buffer) - enc := gob.NewEncoder(buf) - for _, i := range items { - if err := enc.Encode(i); err != nil { - panic(err) - } - } - return buf.Bytes() -} diff --git a/vendor/github.com/weaveworks/mesh/lint b/vendor/github.com/weaveworks/mesh/lint deleted file mode 100644 index 0b595ded0c0..00000000000 --- a/vendor/github.com/weaveworks/mesh/lint +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -if [ ! $(command -v gometalinter) ] -then - go get github.com/alecthomas/gometalinter - gometalinter --install --vendor -fi - -gometalinter \ - --exclude='error return value not checked.*(Close|Log|Print).*\(errcheck\)$' \ - --exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$' \ - --exclude='duplicate of.*_test.go.*\(dupl\)$' \ - --disable=aligncheck \ - --disable=gotype \ - --disable=gas \ - --cyclo-over=20 \ - --tests \ - --deadline=10s diff --git a/vendor/github.com/weaveworks/mesh/local_peer.go b/vendor/github.com/weaveworks/mesh/local_peer.go deleted file mode 100644 index 9e99aecf324..00000000000 --- a/vendor/github.com/weaveworks/mesh/local_peer.go +++ /dev/null @@ -1,296 +0,0 @@ -package mesh - -import ( - "encoding/gob" - "fmt" - "net" - "sync" - "time" -) - -// localPeer is the only "active" peer in the mesh. It extends Peer with -// additional behaviors, mostly to retrieve and manage connection state. -type localPeer struct { - sync.RWMutex - *Peer - router *Router - actionChan chan<- localPeerAction -} - -// The actor closure used by localPeer. -type localPeerAction func() - -// newLocalPeer returns a usable LocalPeer. -func newLocalPeer(name PeerName, nickName string, router *Router) *localPeer { - actionChan := make(chan localPeerAction, ChannelSize) - peer := &localPeer{ - Peer: newPeer(name, nickName, randomPeerUID(), 0, randomPeerShortID()), - router: router, - actionChan: actionChan, - } - go peer.actorLoop(actionChan) - return peer -} - -// Connections returns all the connections that the local peer is aware of. -func (peer *localPeer) getConnections() connectionSet { - connections := make(connectionSet) - peer.RLock() - defer peer.RUnlock() - for _, conn := range peer.connections { - connections[conn] = struct{}{} - } - return connections -} - -// ConnectionTo returns the connection to the named peer, if any. -// -// TODO(pb): Weave Net invokes router.Ourself.ConnectionTo; -// it may be better to provide that on Router directly. -func (peer *localPeer) ConnectionTo(name PeerName) (Connection, bool) { - peer.RLock() - defer peer.RUnlock() - conn, found := peer.connections[name] - return conn, found // yes, you really can't inline that. FFS. -} - -// ConnectionsTo returns all known connections to the named peers. -// -// TODO(pb): Weave Net invokes router.Ourself.ConnectionsTo; -// it may be better to provide that on Router directly. -func (peer *localPeer) ConnectionsTo(names []PeerName) []Connection { - if len(names) == 0 { - return nil - } - conns := make([]Connection, 0, len(names)) - peer.RLock() - defer peer.RUnlock() - for _, name := range names { - conn, found := peer.connections[name] - // Again, !found could just be due to a race. - if found { - conns = append(conns, conn) - } - } - return conns -} - -// createConnection creates a new connection, originating from -// localAddr, to peerAddr. If acceptNewPeer is false, peerAddr must -// already be a member of the mesh. -func (peer *localPeer) createConnection(localAddr string, peerAddr string, acceptNewPeer bool, logger Logger) error { - if err := peer.checkConnectionLimit(); err != nil { - return err - } - localTCPAddr, err := net.ResolveTCPAddr("tcp4", localAddr) - if err != nil { - return err - } - remoteTCPAddr, err := net.ResolveTCPAddr("tcp4", peerAddr) - if err != nil { - return err - } - tcpConn, err := net.DialTCP("tcp4", localTCPAddr, remoteTCPAddr) - if err != nil { - return err - } - connRemote := newRemoteConnection(peer.Peer, nil, peerAddr, true, false) - startLocalConnection(connRemote, tcpConn, peer.router, acceptNewPeer, logger) - return nil -} - -// ACTOR client API - -// Synchronous. -func (peer *localPeer) doAddConnection(conn ourConnection, isRestartedPeer bool) error { - resultChan := make(chan error) - peer.actionChan <- func() { - resultChan <- peer.handleAddConnection(conn, isRestartedPeer) - } - return <-resultChan -} - -// Asynchronous. -func (peer *localPeer) doConnectionEstablished(conn ourConnection) { - peer.actionChan <- func() { - peer.handleConnectionEstablished(conn) - } -} - -// Synchronous. -func (peer *localPeer) doDeleteConnection(conn ourConnection) { - resultChan := make(chan interface{}) - peer.actionChan <- func() { - peer.handleDeleteConnection(conn) - resultChan <- nil - } - <-resultChan -} - -func (peer *localPeer) encode(enc *gob.Encoder) { - peer.RLock() - defer peer.RUnlock() - peer.Peer.encode(enc) -} - -// ACTOR server - -func (peer *localPeer) actorLoop(actionChan <-chan localPeerAction) { - gossipTimer := time.Tick(gossipInterval) - for { - select { - case action := <-actionChan: - action() - case <-gossipTimer: - peer.router.sendAllGossip() - } - } -} - -func (peer *localPeer) handleAddConnection(conn ourConnection, isRestartedPeer bool) error { - if peer.Peer != conn.getLocal() { - panic("Attempt made to add connection to peer where peer is not the source of connection") - } - if conn.Remote() == nil { - panic("Attempt made to add connection to peer with unknown remote peer") - } - toName := conn.Remote().Name - dupErr := fmt.Errorf("Multiple connections to %s added to %s", conn.Remote(), peer.String()) - // deliberately non symmetrical - if dupConn, found := peer.connections[toName]; found { - if dupConn == conn { - return nil - } - dupOurConn := dupConn.(ourConnection) - switch conn.breakTie(dupOurConn) { - case tieBreakWon: - dupOurConn.shutdown(dupErr) - peer.handleDeleteConnection(dupOurConn) - case tieBreakLost: - return dupErr - case tieBreakTied: - // oh good grief. Sod it, just kill both of them. - dupOurConn.shutdown(dupErr) - peer.handleDeleteConnection(dupOurConn) - return dupErr - } - } - if err := peer.checkConnectionLimit(); err != nil { - return err - } - _, isConnectedPeer := peer.router.Routes.Unicast(toName) - peer.addConnection(conn) - switch { - case isRestartedPeer: - conn.logf("connection added (restarted peer)") - peer.router.sendAllGossipDown(conn) - case isConnectedPeer: - conn.logf("connection added") - default: - conn.logf("connection added (new peer)") - peer.router.sendAllGossipDown(conn) - } - - peer.router.Routes.recalculate() - peer.broadcastPeerUpdate(conn.Remote()) - - return nil -} - -func (peer *localPeer) handleConnectionEstablished(conn ourConnection) { - if peer.Peer != conn.getLocal() { - panic("Peer informed of active connection where peer is not the source of connection") - } - if dupConn, found := peer.connections[conn.Remote().Name]; !found || conn != dupConn { - conn.shutdown(fmt.Errorf("Cannot set unknown connection active")) - return - } - peer.connectionEstablished(conn) - conn.logf("connection fully established") - - peer.router.Routes.recalculate() - peer.broadcastPeerUpdate() -} - -func (peer *localPeer) handleDeleteConnection(conn ourConnection) { - if peer.Peer != conn.getLocal() { - panic("Attempt made to delete connection from peer where peer is not the source of connection") - } - if conn.Remote() == nil { - panic("Attempt made to delete connection to peer with unknown remote peer") - } - toName := conn.Remote().Name - if connFound, found := peer.connections[toName]; !found || connFound != conn { - return - } - peer.deleteConnection(conn) - conn.logf("connection deleted") - // Must do garbage collection first to ensure we don't send out an - // update with unreachable peers (can cause looping) - peer.router.Peers.GarbageCollect() - peer.router.Routes.recalculate() - peer.broadcastPeerUpdate() -} - -// helpers - -func (peer *localPeer) broadcastPeerUpdate(peers ...*Peer) { - // Some tests run without a router. This should be fixed so - // that the relevant part of Router can be easily run in the - // context of a test, but that will involve significant - // reworking of tests. - if peer.router != nil { - peer.router.broadcastTopologyUpdate(append(peers, peer.Peer)) - } -} - -func (peer *localPeer) checkConnectionLimit() error { - limit := peer.router.ConnLimit - if 0 != limit && peer.connectionCount() >= limit { - return fmt.Errorf("Connection limit reached (%v)", limit) - } - return nil -} - -func (peer *localPeer) addConnection(conn Connection) { - peer.Lock() - defer peer.Unlock() - peer.connections[conn.Remote().Name] = conn - peer.Version++ -} - -func (peer *localPeer) deleteConnection(conn Connection) { - peer.Lock() - defer peer.Unlock() - delete(peer.connections, conn.Remote().Name) - peer.Version++ -} - -func (peer *localPeer) connectionEstablished(conn Connection) { - peer.Lock() - defer peer.Unlock() - peer.Version++ -} - -func (peer *localPeer) connectionCount() int { - peer.RLock() - defer peer.RUnlock() - return len(peer.connections) -} - -func (peer *localPeer) setShortID(shortID PeerShortID) { - peer.Lock() - defer peer.Unlock() - peer.ShortID = shortID - peer.Version++ -} - -func (peer *localPeer) setVersionBeyond(version uint64) bool { - peer.Lock() - defer peer.Unlock() - if version >= peer.Version { - peer.Version = version + 1 - return true - } - return false -} diff --git a/vendor/github.com/weaveworks/mesh/logger.go b/vendor/github.com/weaveworks/mesh/logger.go deleted file mode 100644 index 3b250eb9943..00000000000 --- a/vendor/github.com/weaveworks/mesh/logger.go +++ /dev/null @@ -1,6 +0,0 @@ -package mesh - -// Logger is a simple interface used by mesh to do logging. -type Logger interface { - Printf(format string, args ...interface{}) -} diff --git a/vendor/github.com/weaveworks/mesh/overlay.go b/vendor/github.com/weaveworks/mesh/overlay.go deleted file mode 100644 index b7ad0e72cf6..00000000000 --- a/vendor/github.com/weaveworks/mesh/overlay.go +++ /dev/null @@ -1,123 +0,0 @@ -package mesh - -import ( - "net" -) - -// Overlay yields OverlayConnections. -type Overlay interface { - // Enhance a features map with overlay-related features. - AddFeaturesTo(map[string]string) - - // Prepare on overlay connection. The connection should remain - // passive until it has been Confirm()ed. - PrepareConnection(OverlayConnectionParams) (OverlayConnection, error) - - // Obtain diagnostic information specific to the overlay. - Diagnostics() interface{} - - // Stop the overlay. - Stop() -} - -// OverlayConnectionParams are used to set up overlay connections. -type OverlayConnectionParams struct { - RemotePeer *Peer - - // The local address of the corresponding TCP connection. Used to - // derive the local IP address for sending. May differ for - // different overlay connections. - LocalAddr *net.TCPAddr - - // The remote address of the corresponding TCP connection. Used to - // determine the address to send to, but only if the TCP - // connection is outbound. Otherwise the Overlay needs to discover - // it (e.g. from incoming datagrams). - RemoteAddr *net.TCPAddr - - // Is the corresponding TCP connection outbound? - Outbound bool - - // Unique identifier for this connection - ConnUID uint64 - - // Session key, if connection is encrypted; nil otherwise. - // - // NB: overlay connections must take care not to use nonces which - // may collide with those of the main connection. These nonces are - // 192 bits, with the top most bit unspecified, the next bit set - // to 1, followed by 126 zero bits, and a message sequence number - // in the lowest 64 bits. - SessionKey *[32]byte - - // Function to send a control message to the counterpart - // overlay connection. - SendControlMessage func(tag byte, msg []byte) error - - // Features passed at connection initiation - Features map[string]string -} - -// OverlayConnection describes all of the machinery to manage overlay -// connectivity to a particular peer. -type OverlayConnection interface { - // Confirm that the connection is really wanted, and so the - // Overlay should begin heartbeats etc. to verify the operation of - // the overlay connection. - Confirm() - - // EstablishedChannel returns a channel that will be closed when the - // overlay connection is established, i.e. its operation has been - // confirmed. - EstablishedChannel() <-chan struct{} - - // ErrorChannel returns a channel that forwards errors from the overlay - // connection. The overlay connection is not expected to be operational - // after the first error, so the channel only needs to buffer a single - // error. - ErrorChannel() <-chan error - - // Stop terminates the connection. - Stop() - - // ControlMessage handles a message from the remote peer. 'tag' exists for - // compatibility, and should always be ProtocolOverlayControlMessage for - // non-sleeve overlays. - ControlMessage(tag byte, msg []byte) - - // Attrs returns the user-facing overlay name plus any other - // data that users may wish to check or monitor - Attrs() map[string]interface{} -} - -// NullOverlay implements Overlay and OverlayConnection with no-ops. -type NullOverlay struct{} - -// AddFeaturesTo implements Overlay. -func (NullOverlay) AddFeaturesTo(map[string]string) {} - -// PrepareConnection implements Overlay. -func (NullOverlay) PrepareConnection(OverlayConnectionParams) (OverlayConnection, error) { - return NullOverlay{}, nil -} - -// Diagnostics implements Overlay. -func (NullOverlay) Diagnostics() interface{} { return nil } - -// Confirm implements OverlayConnection. -func (NullOverlay) Confirm() {} - -// EstablishedChannel implements OverlayConnection. -func (NullOverlay) EstablishedChannel() <-chan struct{} { return nil } - -// ErrorChannel implements OverlayConnection. -func (NullOverlay) ErrorChannel() <-chan error { return nil } - -// Stop implements OverlayConnection. -func (NullOverlay) Stop() {} - -// ControlMessage implements OverlayConnection. -func (NullOverlay) ControlMessage(byte, []byte) {} - -// Attrs implements OverlayConnection. -func (NullOverlay) Attrs() map[string]interface{} { return nil } diff --git a/vendor/github.com/weaveworks/mesh/peer.go b/vendor/github.com/weaveworks/mesh/peer.go deleted file mode 100644 index 22b4138b02a..00000000000 --- a/vendor/github.com/weaveworks/mesh/peer.go +++ /dev/null @@ -1,200 +0,0 @@ -package mesh - -import ( - "crypto/rand" - "encoding/binary" - "fmt" - "sort" - "strconv" -) - -// Peer is a local representation of a peer, including connections to other -// peers. By itself, it is a remote peer. -type Peer struct { - Name PeerName - peerSummary - localRefCount uint64 // maintained by Peers - connections map[PeerName]Connection -} - -type peerSummary struct { - NameByte []byte - NickName string - UID PeerUID - Version uint64 - ShortID PeerShortID - HasShortID bool -} - -// PeerDescription collects information about peers that is useful to clients. -type PeerDescription struct { - Name PeerName - NickName string - UID PeerUID - Self bool - NumConnections int -} - -type connectionSet map[Connection]struct{} - -func newPeerFromSummary(summary peerSummary) *Peer { - return &Peer{ - Name: PeerNameFromBin(summary.NameByte), - peerSummary: summary, - connections: make(map[PeerName]Connection), - } -} - -func newPeer(name PeerName, nickName string, uid PeerUID, version uint64, shortID PeerShortID) *Peer { - return newPeerFromSummary(peerSummary{ - NameByte: name.bytes(), - NickName: nickName, - UID: uid, - Version: version, - ShortID: shortID, - HasShortID: true, - }) -} - -func newPeerPlaceholder(name PeerName) *Peer { - return newPeerFromSummary(peerSummary{NameByte: name.bytes()}) -} - -// String returns the peer name and nickname. -func (peer *Peer) String() string { - return fmt.Sprint(peer.Name, "(", peer.NickName, ")") -} - -// Routes calculates the routing table from this peer to all peers reachable -// from it, returning a "next hop" map of PeerNameX -> PeerNameY, which says -// "in order to send a message to X, the peer should send the message to its -// neighbour Y". -// -// Because currently we do not have weightings on the connections between -// peers, there is no need to use a minimum spanning tree algorithm. Instead -// we employ the simpler and cheaper breadth-first widening. The computation -// is deterministic, which ensures that when it is performed on the same data -// by different peers, they get the same result. This is important since -// otherwise we risk message loss or routing cycles. -// -// When the 'establishedAndSymmetric' flag is set, only connections that are -// marked as 'established' and are symmetric (i.e. where both sides indicate -// they have a connection to the other) are considered. -// -// When a non-nil stopAt peer is supplied, the widening stops when it reaches -// that peer. The boolean return indicates whether that has happened. -// -// NB: This function should generally be invoked while holding a read lock on -// Peers and LocalPeer. -func (peer *Peer) routes(stopAt *Peer, establishedAndSymmetric bool) (bool, map[PeerName]PeerName) { - routes := make(unicastRoutes) - routes[peer.Name] = UnknownPeerName - nextWorklist := []*Peer{peer} - for len(nextWorklist) > 0 { - worklist := nextWorklist - sort.Sort(listOfPeers(worklist)) - nextWorklist = []*Peer{} - for _, curPeer := range worklist { - if curPeer == stopAt { - return true, routes - } - curPeer.forEachConnectedPeer(establishedAndSymmetric, routes, - func(remotePeer *Peer) { - nextWorklist = append(nextWorklist, remotePeer) - remoteName := remotePeer.Name - // We now know how to get to remoteName: the same - // way we get to curPeer. Except, if curPeer is - // the starting peer in which case we know we can - // reach remoteName directly. - if curPeer == peer { - routes[remoteName] = remoteName - } else { - routes[remoteName] = routes[curPeer.Name] - } - }) - } - } - return false, routes -} - -// Apply f to all peers reachable by peer. If establishedAndSymmetric is true, -// only peers with established bidirectional connections will be selected. The -// exclude maps is treated as a set of remote peers to blacklist. -func (peer *Peer) forEachConnectedPeer(establishedAndSymmetric bool, exclude map[PeerName]PeerName, f func(*Peer)) { - for remoteName, conn := range peer.connections { - if establishedAndSymmetric && !conn.isEstablished() { - continue - } - if _, found := exclude[remoteName]; found { - continue - } - remotePeer := conn.Remote() - if remoteConn, found := remotePeer.connections[peer.Name]; !establishedAndSymmetric || (found && remoteConn.isEstablished()) { - f(remotePeer) - } - } -} - -// PeerUID uniquely identifies a peer in a mesh. -type PeerUID uint64 - -// ParsePeerUID parses a decimal peer UID from a string. -func parsePeerUID(s string) (PeerUID, error) { - uid, err := strconv.ParseUint(s, 10, 64) - return PeerUID(uid), err -} - -func randomPeerUID() PeerUID { - for { - uid := randUint64() - if uid != 0 { // uid 0 is reserved for peer placeholder - return PeerUID(uid) - } - } -} - -// PeerShortID exists for the sake of fast datapath. They are 12 bits, -// randomly assigned, but we detect and recover from collisions. This -// does limit us to 4096 peers, but that should be sufficient for a -// while. -type PeerShortID uint16 - -const peerShortIDBits = 12 - -func randomPeerShortID() PeerShortID { - return PeerShortID(randUint16() & (1<> 1 - - // UnknownPeerName is used as a sentinel value. - UnknownPeerName = PeerName("") -) - -// PeerNameFromUserInput parses PeerName from a user-provided string. -func PeerNameFromUserInput(userInput string) (PeerName, error) { - // fixed-length identity - nameByteAry := sha256.Sum256([]byte(userInput)) - return PeerNameFromBin(nameByteAry[:NameSize]), nil -} - -// PeerNameFromString parses PeerName from a generic string. -func PeerNameFromString(nameStr string) (PeerName, error) { - if _, err := hex.DecodeString(nameStr); err != nil { - return UnknownPeerName, err - } - return PeerName(nameStr), nil -} - -// PeerNameFromBin parses PeerName from a byte slice. -func PeerNameFromBin(nameByte []byte) PeerName { - return PeerName(hex.EncodeToString(nameByte)) -} - -// Bin encodes PeerName as a byte slice. -func (name PeerName) Bin() []byte { - res, err := hex.DecodeString(string(name)) - checkFatal(err) - return res -} - -// String encodes PeerName as a string. -func (name PeerName) String() string { - return string(name) -} diff --git a/vendor/github.com/weaveworks/mesh/peer_name_mac.go b/vendor/github.com/weaveworks/mesh/peer_name_mac.go deleted file mode 100644 index 9524c1daaba..00000000000 --- a/vendor/github.com/weaveworks/mesh/peer_name_mac.go +++ /dev/null @@ -1,110 +0,0 @@ -// +build peer_name_mac !peer_name_alternative - -package mesh - -// The !peer_name_alternative effectively makes this the default, -// i.e. to choose an alternative, run -// -// go build -tags 'peer_name_alternative peer_name_hash' -// -// Let peer names be MACs... -// -// MACs need to be unique across our network, or bad things will -// happen anyway. So they make pretty good candidates for peer -// names. And doing so is pretty efficient both computationally and -// network overhead wise. -// -// Note that we do not mandate *what* MAC should be used as the peer -// name. In particular it doesn't actually have to be the MAC of, say, -// the network interface the peer is sniffing on. - -import ( - "fmt" - "net" -) - -// PeerName is used as a map key. Since net.HardwareAddr isn't suitable for -// that - it's a slice, and slices can't be map keys - we convert that to/from -// uint64. -type PeerName uint64 - -const ( - // PeerNameFlavour is the type of peer names we use. - PeerNameFlavour = "mac" - - // NameSize is the number of bytes in a peer name. - NameSize = 6 - - // UnknownPeerName is used as a sentinel value. - UnknownPeerName = PeerName(0) -) - -// PeerNameFromUserInput parses PeerName from a user-provided string. -func PeerNameFromUserInput(userInput string) (PeerName, error) { - return PeerNameFromString(userInput) -} - -// PeerNameFromString parses PeerName from a generic string. -func PeerNameFromString(nameStr string) (PeerName, error) { - var a, b, c, d, e, f uint64 - - match := func(format string, args ...interface{}) bool { - a, b, c, d, e, f = 0, 0, 0, 0, 0, 0 - n, err := fmt.Sscanf(nameStr+"\000", format+"\000", args...) - return err == nil && n == len(args) - } - - switch { - case match("%2x:%2x:%2x:%2x:%2x:%2x", &a, &b, &c, &d, &e, &f): - case match("::%2x:%2x:%2x:%2x", &c, &d, &e, &f): - case match("%2x::%2x:%2x:%2x", &a, &d, &e, &f): - case match("%2x:%2x::%2x:%2x", &a, &b, &e, &f): - case match("%2x:%2x:%2x::%2x", &a, &b, &c, &f): - case match("%2x:%2x:%2x:%2x::", &a, &b, &c, &d): - case match("::%2x:%2x:%2x", &d, &e, &f): - case match("%2x::%2x:%2x", &a, &e, &f): - case match("%2x:%2x::%2x", &a, &b, &f): - case match("%2x:%2x:%2x::", &a, &b, &c): - case match("::%2x:%2x", &e, &f): - case match("%2x::%2x", &a, &f): - case match("%2x:%2x::", &a, &b): - case match("::%2x", &f): - case match("%2x::", &a): - default: - return UnknownPeerName, fmt.Errorf("invalid peer name format: %q", nameStr) - } - - return PeerName(a<<40 | b<<32 | c<<24 | d<<16 | e<<8 | f), nil -} - -// PeerNameFromBin parses PeerName from a byte slice. -func PeerNameFromBin(nameByte []byte) PeerName { - return PeerName(macint(net.HardwareAddr(nameByte))) -} - -// Bin encodes PeerName as a byte slice. -func (name PeerName) bytes() []byte { - return intmac(uint64(name)) -} - -// String encodes PeerName as a string. -func (name PeerName) String() string { - return intmac(uint64(name)).String() -} - -func macint(mac net.HardwareAddr) (r uint64) { - for _, b := range mac { - r <<= 8 - r |= uint64(b) - } - return -} - -func intmac(key uint64) (r net.HardwareAddr) { - r = make([]byte, 6) - for i := 5; i >= 0; i-- { - r[i] = byte(key) - key >>= 8 - } - return -} diff --git a/vendor/github.com/weaveworks/mesh/peers.go b/vendor/github.com/weaveworks/mesh/peers.go deleted file mode 100644 index 1190450eb69..00000000000 --- a/vendor/github.com/weaveworks/mesh/peers.go +++ /dev/null @@ -1,560 +0,0 @@ -package mesh - -import ( - "bytes" - "encoding/gob" - "io" - "math/rand" - "sync" -) - -// Peers collects all of the known peers in the mesh, including ourself. -type Peers struct { - sync.RWMutex - ourself *localPeer - byName map[PeerName]*Peer - byShortID map[PeerShortID]shortIDPeers - onGC []func(*Peer) - - // Called when the mapping from short IDs to peers changes - onInvalidateShortIDs []func() -} - -type shortIDPeers struct { - // If we know about a single peer with the short ID, this is - // that peer. If there is a collision, this is the peer with - // the lowest Name. - peer *Peer - - // In case of a collision, this holds the other peers. - others []*Peer -} - -type peerNameSet map[PeerName]struct{} - -type connectionSummary struct { - NameByte []byte - RemoteTCPAddr string - Outbound bool - Established bool -} - -// Due to changes to Peers that need to be sent out -// once the Peers is unlocked. -type peersPendingNotifications struct { - // Peers that have been GCed - removed []*Peer - - // The mapping from short IDs to peers changed - invalidateShortIDs bool - - // The local short ID needs reassigning due to a collision - reassignLocalShortID bool - - // The local peer was modified - localPeerModified bool -} - -func newPeers(ourself *localPeer) *Peers { - peers := &Peers{ - ourself: ourself, - byName: make(map[PeerName]*Peer), - byShortID: make(map[PeerShortID]shortIDPeers), - } - peers.fetchWithDefault(ourself.Peer) - return peers -} - -// Descriptions returns descriptions for all known peers. -func (peers *Peers) Descriptions() []PeerDescription { - peers.RLock() - defer peers.RUnlock() - descriptions := make([]PeerDescription, 0, len(peers.byName)) - for _, peer := range peers.byName { - descriptions = append(descriptions, PeerDescription{ - Name: peer.Name, - NickName: peer.peerSummary.NickName, - UID: peer.UID, - Self: peer.Name == peers.ourself.Name, - NumConnections: len(peer.connections), - }) - } - return descriptions -} - -// OnGC adds a new function to be set of functions that will be executed on -// all subsequent GC runs, receiving the GC'd peer. -func (peers *Peers) OnGC(callback func(*Peer)) { - peers.Lock() - defer peers.Unlock() - - // Although the array underlying peers.onGC might be accessed - // without holding the lock in unlockAndNotify, we don't - // support removing callbacks, so a simple append here is - // safe. - peers.onGC = append(peers.onGC, callback) -} - -// OnInvalidateShortIDs adds a new function to a set of functions that will be -// executed on all subsequent GC runs, when the mapping from short IDs to -// peers has changed. -func (peers *Peers) OnInvalidateShortIDs(callback func()) { - peers.Lock() - defer peers.Unlock() - - // Safe, as in OnGC - peers.onInvalidateShortIDs = append(peers.onInvalidateShortIDs, callback) -} - -func (peers *Peers) unlockAndNotify(pending *peersPendingNotifications) { - broadcastLocalPeer := (pending.reassignLocalShortID && peers.reassignLocalShortID(pending)) || pending.localPeerModified - onGC := peers.onGC - onInvalidateShortIDs := peers.onInvalidateShortIDs - peers.Unlock() - - if pending.removed != nil { - for _, callback := range onGC { - for _, peer := range pending.removed { - callback(peer) - } - } - } - - if pending.invalidateShortIDs { - for _, callback := range onInvalidateShortIDs { - callback() - } - } - - if broadcastLocalPeer { - peers.ourself.broadcastPeerUpdate() - } -} - -func (peers *Peers) addByShortID(peer *Peer, pending *peersPendingNotifications) { - if !peer.HasShortID { - return - } - - entry, ok := peers.byShortID[peer.ShortID] - if !ok { - entry = shortIDPeers{peer: peer} - } else if entry.peer == nil { - // This short ID is free, but was used in the past. - // Because we are reusing it, it's an invalidation - // event. - entry.peer = peer - pending.invalidateShortIDs = true - } else if peer.Name < entry.peer.Name { - // Short ID collision, this peer becomes the principal - // peer for the short ID, bumping the previous one - // into others. - - if entry.peer == peers.ourself.Peer { - // The bumped peer is peers.ourself, so we - // need to look for a new short ID. - pending.reassignLocalShortID = true - } - - entry.others = append(entry.others, entry.peer) - entry.peer = peer - pending.invalidateShortIDs = true - } else { - // Short ID collision, this peer is secondary - entry.others = append(entry.others, peer) - } - - peers.byShortID[peer.ShortID] = entry -} - -func (peers *Peers) deleteByShortID(peer *Peer, pending *peersPendingNotifications) { - if !peer.HasShortID { - return - } - - entry := peers.byShortID[peer.ShortID] - var otherIndex int - - if peer != entry.peer { - // peer is secondary, find its index in others - otherIndex = -1 - - for i, other := range entry.others { - if peer == other { - otherIndex = i - break - } - } - - if otherIndex < 0 { - return - } - } else if len(entry.others) != 0 { - // need to find the peer with the lowest name to - // become the new principal one - otherIndex = 0 - minName := entry.others[0].Name - - for i := 1; i < len(entry.others); i++ { - otherName := entry.others[i].Name - if otherName < minName { - minName = otherName - otherIndex = i - } - } - - entry.peer = entry.others[otherIndex] - pending.invalidateShortIDs = true - } else { - // This is the last peer with the short ID. We clear - // the entry, don't delete it, in order to detect when - // it gets re-used. - peers.byShortID[peer.ShortID] = shortIDPeers{} - return - } - - entry.others[otherIndex] = entry.others[len(entry.others)-1] - entry.others = entry.others[:len(entry.others)-1] - peers.byShortID[peer.ShortID] = entry -} - -func (peers *Peers) reassignLocalShortID(pending *peersPendingNotifications) bool { - newShortID, ok := peers.chooseShortID() - if ok { - peers.setLocalShortID(newShortID, pending) - return true - } - - // Otherwise we'll try again later on in garbageColleect - return false -} - -func (peers *Peers) setLocalShortID(newShortID PeerShortID, pending *peersPendingNotifications) { - peers.deleteByShortID(peers.ourself.Peer, pending) - peers.ourself.setShortID(newShortID) - peers.addByShortID(peers.ourself.Peer, pending) -} - -// Choose an available short ID at random. -func (peers *Peers) chooseShortID() (PeerShortID, bool) { - rng := rand.New(rand.NewSource(int64(randUint64()))) - - // First, just try picking some short IDs at random, and - // seeing if they are available: - for i := 0; i < 10; i++ { - shortID := PeerShortID(rng.Intn(1 << peerShortIDBits)) - if peers.byShortID[shortID].peer == nil { - return shortID, true - } - } - - // Looks like most short IDs are used. So count the number of - // unused ones, and pick one at random. - available := int(1 << peerShortIDBits) - for _, entry := range peers.byShortID { - if entry.peer != nil { - available-- - } - } - - if available == 0 { - // All short IDs are used. - return 0, false - } - - n := rng.Intn(available) - var i PeerShortID - for { - if peers.byShortID[i].peer == nil { - if n == 0 { - return i, true - } - - n-- - } - - i++ - } -} - -// fetchWithDefault will use reference fields of the passed peer object to -// look up and return an existing, matching peer. If no matching peer is -// found, the passed peer is saved and returned. -func (peers *Peers) fetchWithDefault(peer *Peer) *Peer { - peers.Lock() - var pending peersPendingNotifications - defer peers.unlockAndNotify(&pending) - - if existingPeer, found := peers.byName[peer.Name]; found { - existingPeer.localRefCount++ - return existingPeer - } - - peers.byName[peer.Name] = peer - peers.addByShortID(peer, &pending) - peer.localRefCount++ - return peer -} - -// Fetch returns a peer matching the passed name, without incrementing its -// refcount. If no matching peer is found, Fetch returns nil. -func (peers *Peers) Fetch(name PeerName) *Peer { - peers.RLock() - defer peers.RUnlock() - return peers.byName[name] -} - -// Like fetch, but increments local refcount. -func (peers *Peers) fetchAndAddRef(name PeerName) *Peer { - peers.Lock() - defer peers.Unlock() - peer := peers.byName[name] - if peer != nil { - peer.localRefCount++ - } - return peer -} - -// FetchByShortID returns a peer matching the passed short ID. -// If no matching peer is found, FetchByShortID returns nil. -func (peers *Peers) FetchByShortID(shortID PeerShortID) *Peer { - peers.RLock() - defer peers.RUnlock() - return peers.byShortID[shortID].peer -} - -// Dereference decrements the refcount of the matching peer. -// TODO(pb): this is an awkward way to use the mutex; consider refactoring -func (peers *Peers) dereference(peer *Peer) { - peers.Lock() - defer peers.Unlock() - peer.localRefCount-- -} - -func (peers *Peers) forEach(fun func(*Peer)) { - peers.RLock() - defer peers.RUnlock() - for _, peer := range peers.byName { - fun(peer) - } -} - -// Merge an incoming update with our own topology. -// -// We add peers hitherto unknown to us, and update peers for which the -// update contains a more recent version than known to us. The return -// value is a) a representation of the received update, and b) an -// "improved" update containing just these new/updated elements. -func (peers *Peers) applyUpdate(update []byte) (peerNameSet, peerNameSet, error) { - peers.Lock() - var pending peersPendingNotifications - defer peers.unlockAndNotify(&pending) - - newPeers, decodedUpdate, decodedConns, err := peers.decodeUpdate(update) - if err != nil { - return nil, nil, err - } - - // Add new peers - for name, newPeer := range newPeers { - peers.byName[name] = newPeer - peers.addByShortID(newPeer, &pending) - } - - // Now apply the updates - newUpdate := peers.applyDecodedUpdate(decodedUpdate, decodedConns, &pending) - peers.garbageCollect(&pending) - for _, peerRemoved := range pending.removed { - delete(newUpdate, peerRemoved.Name) - } - - updateNames := make(peerNameSet) - for _, peer := range decodedUpdate { - updateNames[peer.Name] = struct{}{} - } - - return updateNames, newUpdate, nil -} - -func (peers *Peers) names() peerNameSet { - peers.RLock() - defer peers.RUnlock() - - names := make(peerNameSet) - for name := range peers.byName { - names[name] = struct{}{} - } - return names -} - -func (peers *Peers) encodePeers(names peerNameSet) []byte { - buf := new(bytes.Buffer) - enc := gob.NewEncoder(buf) - peers.RLock() - defer peers.RUnlock() - for name := range names { - if peer, found := peers.byName[name]; found { - if peer == peers.ourself.Peer { - peers.ourself.encode(enc) - } else { - peer.encode(enc) - } - } - } - return buf.Bytes() -} - -// GarbageCollect takes a lock, triggers a GC, and invokes the accumulated GC -// callbacks. -func (peers *Peers) GarbageCollect() { - peers.Lock() - var pending peersPendingNotifications - defer peers.unlockAndNotify(&pending) - - peers.garbageCollect(&pending) -} - -func (peers *Peers) garbageCollect(pending *peersPendingNotifications) { - peers.ourself.RLock() - _, reached := peers.ourself.routes(nil, false) - peers.ourself.RUnlock() - - for name, peer := range peers.byName { - if _, found := reached[peer.Name]; !found && peer.localRefCount == 0 { - delete(peers.byName, name) - peers.deleteByShortID(peer, pending) - pending.removed = append(pending.removed, peer) - } - } - - if len(pending.removed) > 0 && peers.byShortID[peers.ourself.ShortID].peer != peers.ourself.Peer { - // The local peer doesn't own its short ID. Garbage - // collection might have freed some up, so try to - // reassign. - pending.reassignLocalShortID = true - } -} - -func (peers *Peers) decodeUpdate(update []byte) (newPeers map[PeerName]*Peer, decodedUpdate []*Peer, decodedConns [][]connectionSummary, err error) { - newPeers = make(map[PeerName]*Peer) - decodedUpdate = []*Peer{} - decodedConns = [][]connectionSummary{} - - decoder := gob.NewDecoder(bytes.NewReader(update)) - - for { - summary, connSummaries, decErr := decodePeer(decoder) - if decErr == io.EOF { - break - } else if decErr != nil { - err = decErr - return - } - newPeer := newPeerFromSummary(summary) - decodedUpdate = append(decodedUpdate, newPeer) - decodedConns = append(decodedConns, connSummaries) - if _, found := peers.byName[newPeer.Name]; !found { - newPeers[newPeer.Name] = newPeer - } - } - - for _, connSummaries := range decodedConns { - for _, connSummary := range connSummaries { - remoteName := PeerNameFromBin(connSummary.NameByte) - if _, found := newPeers[remoteName]; found { - continue - } - if _, found := peers.byName[remoteName]; found { - continue - } - // Update refers to a peer which we have no knowledge of. - newPeers[remoteName] = newPeerPlaceholder(remoteName) - } - } - return -} - -func (peers *Peers) applyDecodedUpdate(decodedUpdate []*Peer, decodedConns [][]connectionSummary, pending *peersPendingNotifications) peerNameSet { - newUpdate := make(peerNameSet) - for idx, newPeer := range decodedUpdate { - connSummaries := decodedConns[idx] - name := newPeer.Name - // guaranteed to find peer in the peers.byName - switch peer := peers.byName[name]; peer { - case peers.ourself.Peer: - if newPeer.UID != peer.UID { - // The update contains information about an old - // incarnation of ourselves. We increase our version - // number beyond that which we received, so our - // information supersedes the old one when it is - // received by other peers. - pending.localPeerModified = peers.ourself.setVersionBeyond(newPeer.Version) - } - case newPeer: - peer.connections = makeConnsMap(peer, connSummaries, peers.byName) - newUpdate[name] = struct{}{} - default: // existing peer - if newPeer.Version < peer.Version || - (newPeer.Version == peer.Version && - (newPeer.UID < peer.UID || - (newPeer.UID == peer.UID && - (!newPeer.HasShortID || peer.HasShortID)))) { - continue - } - peer.Version = newPeer.Version - peer.UID = newPeer.UID - peer.NickName = newPeer.NickName - peer.connections = makeConnsMap(peer, connSummaries, peers.byName) - - if newPeer.ShortID != peer.ShortID || newPeer.HasShortID != peer.HasShortID { - peers.deleteByShortID(peer, pending) - peer.ShortID = newPeer.ShortID - peer.HasShortID = newPeer.HasShortID - peers.addByShortID(peer, pending) - } - newUpdate[name] = struct{}{} - } - } - return newUpdate -} - -func (peer *Peer) encode(enc *gob.Encoder) { - if err := enc.Encode(peer.peerSummary); err != nil { - panic(err) - } - - connSummaries := []connectionSummary{} - for _, conn := range peer.connections { - connSummaries = append(connSummaries, connectionSummary{ - conn.Remote().NameByte, - conn.remoteTCPAddress(), - conn.isOutbound(), - conn.isEstablished(), - }) - } - - if err := enc.Encode(connSummaries); err != nil { - panic(err) - } -} - -func decodePeer(dec *gob.Decoder) (ps peerSummary, connSummaries []connectionSummary, err error) { - if err = dec.Decode(&ps); err != nil { - return - } - if err = dec.Decode(&connSummaries); err != nil { - return - } - return -} - -func makeConnsMap(peer *Peer, connSummaries []connectionSummary, byName map[PeerName]*Peer) map[PeerName]Connection { - conns := make(map[PeerName]Connection) - for _, connSummary := range connSummaries { - name := PeerNameFromBin(connSummary.NameByte) - remotePeer := byName[name] - conn := newRemoteConnection(peer, remotePeer, connSummary.RemoteTCPAddr, connSummary.Outbound, connSummary.Established) - conns[name] = conn - } - return conns -} diff --git a/vendor/github.com/weaveworks/mesh/protocol.go b/vendor/github.com/weaveworks/mesh/protocol.go deleted file mode 100644 index f0c8c8a99d8..00000000000 --- a/vendor/github.com/weaveworks/mesh/protocol.go +++ /dev/null @@ -1,364 +0,0 @@ -package mesh - -import ( - "bytes" - "encoding/gob" - "encoding/hex" - "fmt" - "io" - "time" -) - -const ( - // Protocol identifies a sort of major version of the protocol. - Protocol = "weave" - - // ProtocolMinVersion establishes the lowest protocol version among peers - // that we're willing to try to communicate with. - ProtocolMinVersion = 1 - - // ProtocolMaxVersion establishes the highest protocol version among peers - // that we're willing to try to communicate with. - ProtocolMaxVersion = 2 -) - -var ( - protocolBytes = []byte(Protocol) - - // How long we wait for the handshake phase of protocol negotiation. - headerTimeout = 10 * time.Second - - // See filterV1Features. - protocolV1Features = []string{ - "ConnID", - "Name", - "NickName", - "PeerNameFlavour", - "UID", - } - - errExpectedCrypto = fmt.Errorf("password specified, but peer requested an unencrypted connection") - errExpectedNoCrypto = fmt.Errorf("no password specificed, but peer requested an encrypted connection") -) - -type protocolIntroConn interface { - io.ReadWriter - - // net.Conn's deadline methods - SetDeadline(t time.Time) error - SetReadDeadline(t time.Time) error - SetWriteDeadline(t time.Time) error -} - -// The params necessary to negotiate a protocol intro with a remote peer. -type protocolIntroParams struct { - MinVersion byte - MaxVersion byte - Features map[string]string - Conn protocolIntroConn - Password []byte - Outbound bool -} - -// The results from a successful protocol intro. -type protocolIntroResults struct { - Features map[string]string - Receiver tcpReceiver - Sender tcpSender - SessionKey *[32]byte - Version byte -} - -// DoIntro executes the protocol introduction. -func (params protocolIntroParams) doIntro() (res protocolIntroResults, err error) { - if err = params.Conn.SetDeadline(time.Now().Add(headerTimeout)); err != nil { - return - } - - if res.Version, err = params.exchangeProtocolHeader(); err != nil { - return - } - - var pubKey, privKey *[32]byte - if params.Password != nil { - if pubKey, privKey, err = generateKeyPair(); err != nil { - return - } - } - - if err = params.Conn.SetWriteDeadline(time.Time{}); err != nil { - return - } - if err = params.Conn.SetReadDeadline(time.Now().Add(tcpHeartbeat * 2)); err != nil { - return - } - - switch res.Version { - case 1: - err = res.doIntroV1(params, pubKey, privKey) - case 2: - err = res.doIntroV2(params, pubKey, privKey) - default: - panic("unhandled protocol version") - } - - return -} - -func (params protocolIntroParams) exchangeProtocolHeader() (byte, error) { - // Write in a separate goroutine to avoid the possibility of - // deadlock. The result channel is of size 1 so that the - // goroutine does not linger even if we encounter an error on - // the read side. - sendHeader := append(protocolBytes, params.MinVersion, params.MaxVersion) - writeDone := make(chan error, 1) - go func() { - _, err := params.Conn.Write(sendHeader) - writeDone <- err - }() - - header := make([]byte, len(protocolBytes)+2) - if n, err := io.ReadFull(params.Conn, header); err != nil && n == 0 { - return 0, fmt.Errorf("failed to receive remote protocol header: %s", err) - } else if err != nil { - return 0, fmt.Errorf("received incomplete remote protocol header (%d octets instead of %d): %v; error: %s", - n, len(header), header[:n], err) - } - - if !bytes.Equal(protocolBytes, header[:len(protocolBytes)]) { - return 0, fmt.Errorf("remote protocol header not recognised: %v", header[:len(protocolBytes)]) - } - - theirMinVersion := header[len(protocolBytes)] - minVersion := theirMinVersion - if params.MinVersion > minVersion { - minVersion = params.MinVersion - } - - theirMaxVersion := header[len(protocolBytes)+1] - maxVersion := theirMaxVersion - if maxVersion > params.MaxVersion { - maxVersion = params.MaxVersion - } - - if minVersion > maxVersion { - return 0, fmt.Errorf("remote version range [%d,%d] is incompatible with ours [%d,%d]", - theirMinVersion, theirMaxVersion, - params.MinVersion, params.MaxVersion) - } - - if err := <-writeDone; err != nil { - return 0, err - } - - return maxVersion, nil -} - -// The V1 procotol consists of the protocol identification/version -// header, followed by a stream of gobified values. The first value -// is the encoded features map (never encrypted). The subsequent -// values are the messages on the connection (encrypted for an -// encrypted connection). For an encrypted connection, the public key -// is passed in the "PublicKey" feature as a string of hex digits. -func (res *protocolIntroResults) doIntroV1(params protocolIntroParams, pubKey, privKey *[32]byte) error { - features := filterV1Features(params.Features) - if pubKey != nil { - features["PublicKey"] = hex.EncodeToString(pubKey[:]) - } - - enc := gob.NewEncoder(params.Conn) - dec := gob.NewDecoder(params.Conn) - - // Encode in a separate goroutine to avoid the possibility of - // deadlock. The result channel is of size 1 so that the - // goroutine does not linger even if we encounter an error on - // the read side. - encodeDone := make(chan error, 1) - go func() { - encodeDone <- enc.Encode(features) - }() - - if err := dec.Decode(&res.Features); err != nil { - return err - } - - if err := <-encodeDone; err != nil { - return err - } - - res.Sender = newGobTCPSender(enc) - res.Receiver = newGobTCPReceiver(dec) - - if pubKey == nil { - if _, present := res.Features["PublicKey"]; present { - return errExpectedNoCrypto - } - } else { - remotePubKeyStr, ok := res.Features["PublicKey"] - if !ok { - return errExpectedCrypto - } - - remotePubKey, err := hex.DecodeString(remotePubKeyStr) - if err != nil { - return err - } - - res.setupCrypto(params, remotePubKey, privKey) - } - - res.Features = filterV1Features(res.Features) - return nil -} - -// In the V1 protocol, the intro fields are sent unencrypted. So we -// restrict them to an established subset of fields that are assumed -// to be safe. -func filterV1Features(intro map[string]string) map[string]string { - safe := make(map[string]string) - for _, k := range protocolV1Features { - if val, ok := intro[k]; ok { - safe[k] = val - } - } - - return safe -} - -// The V2 procotol consists of the protocol identification/version -// header, followed by: -// -// - A single "encryption flag" byte: 0 for no encryption, 1 for -// encryption. -// -// - When the connection is encrypted, 32 bytes follow containing the -// public key. -// -// - Then a stream of length-prefixed messages, which are encrypted -// for an encrypted connection. -// -// The first message contains the encoded features map (so in contrast -// to V1, it will be encrypted on an encrypted connection). -func (res *protocolIntroResults) doIntroV2(params protocolIntroParams, pubKey, privKey *[32]byte) error { - // Public key exchange - var wbuf []byte - if pubKey == nil { - wbuf = []byte{0} - } else { - wbuf = make([]byte, 1+len(*pubKey)) - wbuf[0] = 1 - copy(wbuf[1:], (*pubKey)[:]) - } - - // Write in a separate goroutine to avoid the possibility of - // deadlock. The result channel is of size 1 so that the - // goroutine does not linger even if we encounter an error on - // the read side. - writeDone := make(chan error, 1) - go func() { - _, err := params.Conn.Write(wbuf) - writeDone <- err - }() - - rbuf := make([]byte, 1) - if _, err := io.ReadFull(params.Conn, rbuf); err != nil { - return err - } - - switch rbuf[0] { - case 0: - if pubKey != nil { - return errExpectedCrypto - } - - res.Sender = newLengthPrefixTCPSender(params.Conn) - res.Receiver = newLengthPrefixTCPReceiver(params.Conn) - - case 1: - if pubKey == nil { - return errExpectedNoCrypto - } - - rbuf = make([]byte, len(pubKey)) - if _, err := io.ReadFull(params.Conn, rbuf); err != nil { - return err - } - - res.Sender = newLengthPrefixTCPSender(params.Conn) - res.Receiver = newLengthPrefixTCPReceiver(params.Conn) - res.setupCrypto(params, rbuf, privKey) - - default: - return fmt.Errorf("Bad encryption flag %d", rbuf[0]) - } - - if err := <-writeDone; err != nil { - return err - } - - // Features exchange - go func() { - buf := new(bytes.Buffer) - if err := gob.NewEncoder(buf).Encode(¶ms.Features); err != nil { - writeDone <- err - return - } - - writeDone <- res.Sender.Send(buf.Bytes()) - }() - - rbuf, err := res.Receiver.Receive() - if err != nil { - return err - } - - if err := gob.NewDecoder(bytes.NewReader(rbuf)).Decode(&res.Features); err != nil { - return err - } - - if err := <-writeDone; err != nil { - return err - } - - return nil -} - -func (res *protocolIntroResults) setupCrypto(params protocolIntroParams, remotePubKey []byte, privKey *[32]byte) { - var remotePubKeyArr [32]byte - copy(remotePubKeyArr[:], remotePubKey) - res.SessionKey = formSessionKey(&remotePubKeyArr, privKey, params.Password) - res.Sender = newEncryptedTCPSender(res.Sender, res.SessionKey, params.Outbound) - res.Receiver = newEncryptedTCPReceiver(res.Receiver, res.SessionKey, params.Outbound) -} - -// ProtocolTag identifies the type of msg encoded in a ProtocolMsg. -type protocolTag byte - -const ( - // ProtocolHeartbeat identifies a heartbeat msg. - ProtocolHeartbeat = iota - // ProtocolReserved1 is a legacy overly control message. - ProtocolReserved1 - // ProtocolReserved2 is a legacy overly control message. - ProtocolReserved2 - // ProtocolReserved3 is a legacy overly control message. - ProtocolReserved3 - // ProtocolGossip identifies a pure gossip msg. - ProtocolGossip - // ProtocolGossipUnicast identifies a gossip (unicast) msg. - ProtocolGossipUnicast - // ProtocolGossipBroadcast identifies a gossip (broadcast) msg. - ProtocolGossipBroadcast - // ProtocolOverlayControlMsg identifies a control msg. - ProtocolOverlayControlMsg -) - -// ProtocolMsg combines a tag and encoded msg. -type protocolMsg struct { - tag protocolTag - msg []byte -} - -type protocolSender interface { - SendProtocolMsg(m protocolMsg) error -} diff --git a/vendor/github.com/weaveworks/mesh/protocol_crypto.go b/vendor/github.com/weaveworks/mesh/protocol_crypto.go deleted file mode 100644 index c34d9ada55b..00000000000 --- a/vendor/github.com/weaveworks/mesh/protocol_crypto.go +++ /dev/null @@ -1,205 +0,0 @@ -package mesh - -import ( - "crypto/rand" - "crypto/sha256" - "encoding/binary" - "encoding/gob" - "fmt" - "io" - "sync" - - "golang.org/x/crypto/nacl/box" - "golang.org/x/crypto/nacl/secretbox" -) - -// MaxTCPMsgSize is the hard limit on sends and receives. Larger messages will -// result in errors. This applies to the LengthPrefixTCP{Sender,Receiver} i.e. -// V2 of the protocol. -const maxTCPMsgSize = 10 * 1024 * 1024 - -// GenerateKeyPair is used during encrypted protocol introduction. -func generateKeyPair() (publicKey, privateKey *[32]byte, err error) { - return box.GenerateKey(rand.Reader) -} - -// FormSessionKey is used during encrypted protocol introduction. -func formSessionKey(remotePublicKey, localPrivateKey *[32]byte, secretKey []byte) *[32]byte { - var sharedKey [32]byte - box.Precompute(&sharedKey, remotePublicKey, localPrivateKey) - sharedKeySlice := sharedKey[:] - sharedKeySlice = append(sharedKeySlice, secretKey...) - sessionKey := sha256.Sum256(sharedKeySlice) - return &sessionKey -} - -// TCP Senders/Receivers - -// TCPCryptoState stores session key, nonce, and sequence state. -// -// The lowest 64 bits of the nonce contain the message sequence number. The -// top most bit indicates the connection polarity at the sender - '1' for -// outbound; the next indicates protocol type - '1' for TCP. The remaining 126 -// bits are zero. The polarity is needed so that the two ends of a connection -// do not use the same nonces; the protocol type so that the TCP connection -// nonces are distinct from nonces used by overlay connections, if they share -// the session key. This is a requirement of the NaCl Security Model; see -// http://nacl.cr.yp.to/box.html. -type tcpCryptoState struct { - sessionKey *[32]byte - nonce [24]byte - seqNo uint64 -} - -// NewTCPCryptoState returns a valid TCPCryptoState. -func newTCPCryptoState(sessionKey *[32]byte, outbound bool) *tcpCryptoState { - s := &tcpCryptoState{sessionKey: sessionKey} - if outbound { - s.nonce[0] |= (1 << 7) - } - s.nonce[0] |= (1 << 6) - return s -} - -func (s *tcpCryptoState) advance() { - s.seqNo++ - binary.BigEndian.PutUint64(s.nonce[16:24], s.seqNo) -} - -// TCPSender describes anything that can send byte buffers. -// It abstracts over the different protocol version senders. -type tcpSender interface { - Send([]byte) error -} - -// GobTCPSender implements TCPSender and is used in the V1 protocol. -type gobTCPSender struct { - encoder *gob.Encoder -} - -func newGobTCPSender(encoder *gob.Encoder) *gobTCPSender { - return &gobTCPSender{encoder: encoder} -} - -// Send implements TCPSender by encoding the msg. -func (sender *gobTCPSender) Send(msg []byte) error { - return sender.encoder.Encode(msg) -} - -// LengthPrefixTCPSender implements TCPSender and is used in the V2 protocol. -type lengthPrefixTCPSender struct { - writer io.Writer -} - -func newLengthPrefixTCPSender(writer io.Writer) *lengthPrefixTCPSender { - return &lengthPrefixTCPSender{writer: writer} -} - -// Send implements TCPSender by writing the size of the msg as a big-endian -// uint32 before the msg. msgs larger than MaxTCPMsgSize are rejected. -func (sender *lengthPrefixTCPSender) Send(msg []byte) error { - l := len(msg) - if l > maxTCPMsgSize { - return fmt.Errorf("outgoing message exceeds maximum size: %d > %d", l, maxTCPMsgSize) - } - // We copy the message so we can send it in a single Write - // operation, thus making this thread-safe without locking. - prefixedMsg := make([]byte, 4+l) - binary.BigEndian.PutUint32(prefixedMsg, uint32(l)) - copy(prefixedMsg[4:], msg) - _, err := sender.writer.Write(prefixedMsg) - return err -} - -// Implement TCPSender by wrapping an existing TCPSender with tcpCryptoState. -type encryptedTCPSender struct { - sync.RWMutex - sender tcpSender - state *tcpCryptoState -} - -func newEncryptedTCPSender(sender tcpSender, sessionKey *[32]byte, outbound bool) *encryptedTCPSender { - return &encryptedTCPSender{sender: sender, state: newTCPCryptoState(sessionKey, outbound)} -} - -// Send implements TCPSender by sealing and sending the msg as-is. -func (sender *encryptedTCPSender) Send(msg []byte) error { - sender.Lock() - defer sender.Unlock() - encodedMsg := secretbox.Seal(nil, msg, &sender.state.nonce, sender.state.sessionKey) - sender.state.advance() - return sender.sender.Send(encodedMsg) -} - -// tcpReceiver describes anything that can receive byte buffers. -// It abstracts over the different protocol version receivers. -type tcpReceiver interface { - Receive() ([]byte, error) -} - -// gobTCPReceiver implements TCPReceiver and is used in the V1 protocol. -type gobTCPReceiver struct { - decoder *gob.Decoder -} - -func newGobTCPReceiver(decoder *gob.Decoder) *gobTCPReceiver { - return &gobTCPReceiver{decoder: decoder} -} - -// Receive implements TCPReciever by Gob decoding into a byte slice directly. -func (receiver *gobTCPReceiver) Receive() ([]byte, error) { - var msg []byte - err := receiver.decoder.Decode(&msg) - return msg, err -} - -// lengthPrefixTCPReceiver implements TCPReceiver, used in the V2 protocol. -type lengthPrefixTCPReceiver struct { - reader io.Reader -} - -func newLengthPrefixTCPReceiver(reader io.Reader) *lengthPrefixTCPReceiver { - return &lengthPrefixTCPReceiver{reader: reader} -} - -// Receive implements TCPReceiver by making a length-limited read into a byte buffer. -func (receiver *lengthPrefixTCPReceiver) Receive() ([]byte, error) { - lenPrefix := make([]byte, 4) - if _, err := io.ReadFull(receiver.reader, lenPrefix); err != nil { - return nil, err - } - l := binary.BigEndian.Uint32(lenPrefix) - if l > maxTCPMsgSize { - return nil, fmt.Errorf("incoming message exceeds maximum size: %d > %d", l, maxTCPMsgSize) - } - msg := make([]byte, l) - _, err := io.ReadFull(receiver.reader, msg) - return msg, err -} - -// encryptedTCPReceiver implements TCPReceiver by wrapping a TCPReceiver with TCPCryptoState. -type encryptedTCPReceiver struct { - receiver tcpReceiver - state *tcpCryptoState -} - -func newEncryptedTCPReceiver(receiver tcpReceiver, sessionKey *[32]byte, outbound bool) *encryptedTCPReceiver { - return &encryptedTCPReceiver{receiver: receiver, state: newTCPCryptoState(sessionKey, !outbound)} -} - -// Receive implements TCPReceiver by reading from the wrapped TCPReceiver and -// unboxing the encrypted message, returning the decoded message. -func (receiver *encryptedTCPReceiver) Receive() ([]byte, error) { - msg, err := receiver.receiver.Receive() - if err != nil { - return nil, err - } - - decodedMsg, success := secretbox.Open(nil, msg, &receiver.state.nonce, receiver.state.sessionKey) - if !success { - return nil, fmt.Errorf("Unable to decrypt TCP msg") - } - - receiver.state.advance() - return decodedMsg, nil -} diff --git a/vendor/github.com/weaveworks/mesh/router.go b/vendor/github.com/weaveworks/mesh/router.go deleted file mode 100644 index 6b4dec48b50..00000000000 --- a/vendor/github.com/weaveworks/mesh/router.go +++ /dev/null @@ -1,309 +0,0 @@ -package mesh - -import ( - "bytes" - "encoding/gob" - "fmt" - "math" - "net" - "sync" - "time" -) - -var ( - // Port is the port used for all mesh communication. - Port = 6783 - - // ChannelSize is the buffer size used by so-called actor goroutines - // throughout mesh. - ChannelSize = 16 -) - -const ( - tcpHeartbeat = 30 * time.Second - gossipInterval = 30 * time.Second - maxDuration = time.Duration(math.MaxInt64) - acceptMaxTokens = 100 - acceptTokenDelay = 100 * time.Millisecond // [2] -) - -// Config defines dimensions of configuration for the router. -// TODO(pb): provide usable defaults in NewRouter -type Config struct { - Host string - Port int - ProtocolMinVersion byte - Password []byte - ConnLimit int - PeerDiscovery bool - TrustedSubnets []*net.IPNet -} - -// Router manages communication between this peer and the rest of the mesh. -// Router implements Gossiper. -type Router struct { - Config - Overlay Overlay - Ourself *localPeer - Peers *Peers - Routes *routes - ConnectionMaker *connectionMaker - gossipLock sync.RWMutex - gossipChannels gossipChannels - topologyGossip Gossip - acceptLimiter *tokenBucket - logger Logger -} - -// NewRouter returns a new router. It must be started. -func NewRouter(config Config, name PeerName, nickName string, overlay Overlay, logger Logger) *Router { - router := &Router{Config: config, gossipChannels: make(gossipChannels)} - - if overlay == nil { - overlay = NullOverlay{} - } - - router.Overlay = overlay - router.Ourself = newLocalPeer(name, nickName, router) - router.Peers = newPeers(router.Ourself) - router.Peers.OnGC(func(peer *Peer) { - logger.Printf("Removed unreachable peer %s", peer) - }) - router.Routes = newRoutes(router.Ourself, router.Peers) - router.ConnectionMaker = newConnectionMaker(router.Ourself, router.Peers, net.JoinHostPort(router.Host, "0"), router.Port, router.PeerDiscovery, logger) - router.logger = logger - router.topologyGossip = router.NewGossip("topology", router) - router.acceptLimiter = newTokenBucket(acceptMaxTokens, acceptTokenDelay) - - return router -} - -// Start listening for TCP connections. This is separate from NewRouter so -// that gossipers can register before we start forming connections. -func (router *Router) Start() { - router.listenTCP() -} - -// Stop shuts down the router. -func (router *Router) Stop() error { - router.Overlay.Stop() - // TODO: perform more graceful shutdown... - return nil -} - -func (router *Router) usingPassword() bool { - return router.Password != nil -} - -func (router *Router) listenTCP() { - localAddr, err := net.ResolveTCPAddr("tcp4", net.JoinHostPort(router.Host, fmt.Sprint(router.Port))) - if err != nil { - panic(err) - } - ln, err := net.ListenTCP("tcp4", localAddr) - if err != nil { - panic(err) - } - go func() { - defer ln.Close() - for { - tcpConn, err := ln.AcceptTCP() - if err != nil { - router.logger.Printf("%v", err) - continue - } - router.acceptTCP(tcpConn) - router.acceptLimiter.wait() - } - }() -} - -func (router *Router) acceptTCP(tcpConn *net.TCPConn) { - remoteAddrStr := tcpConn.RemoteAddr().String() - router.logger.Printf("->[%s] connection accepted", remoteAddrStr) - connRemote := newRemoteConnection(router.Ourself.Peer, nil, remoteAddrStr, false, false) - startLocalConnection(connRemote, tcpConn, router, true, router.logger) -} - -// NewGossip returns a usable GossipChannel from the router. -// -// TODO(pb): rename? -func (router *Router) NewGossip(channelName string, g Gossiper) Gossip { - channel := newGossipChannel(channelName, router.Ourself, router.Routes, g, router.logger) - router.gossipLock.Lock() - defer router.gossipLock.Unlock() - if _, found := router.gossipChannels[channelName]; found { - panic(fmt.Sprintf("[gossip] duplicate channel %s", channelName)) - } - router.gossipChannels[channelName] = channel - return channel -} - -func (router *Router) gossipChannel(channelName string) *gossipChannel { - router.gossipLock.RLock() - channel, found := router.gossipChannels[channelName] - router.gossipLock.RUnlock() - if found { - return channel - } - router.gossipLock.Lock() - defer router.gossipLock.Unlock() - if channel, found = router.gossipChannels[channelName]; found { - return channel - } - channel = newGossipChannel(channelName, router.Ourself, router.Routes, &surrogateGossiper{}, router.logger) - channel.logf("created surrogate channel") - router.gossipChannels[channelName] = channel - return channel -} - -func (router *Router) gossipChannelSet() map[*gossipChannel]struct{} { - channels := make(map[*gossipChannel]struct{}) - router.gossipLock.RLock() - defer router.gossipLock.RUnlock() - for _, channel := range router.gossipChannels { - channels[channel] = struct{}{} - } - return channels -} - -func (router *Router) handleGossip(tag protocolTag, payload []byte) error { - decoder := gob.NewDecoder(bytes.NewReader(payload)) - var channelName string - if err := decoder.Decode(&channelName); err != nil { - return err - } - channel := router.gossipChannel(channelName) - var srcName PeerName - if err := decoder.Decode(&srcName); err != nil { - return err - } - switch tag { - case ProtocolGossipUnicast: - return channel.deliverUnicast(srcName, payload, decoder) - case ProtocolGossipBroadcast: - return channel.deliverBroadcast(srcName, payload, decoder) - case ProtocolGossip: - return channel.deliver(srcName, payload, decoder) - } - return nil -} - -// Relay all pending gossip data for each channel via random neighbours. -func (router *Router) sendAllGossip() { - for channel := range router.gossipChannelSet() { - if gossip := channel.gossiper.Gossip(); gossip != nil { - channel.Send(gossip) - } - } -} - -// Relay all pending gossip data for each channel via conn. -func (router *Router) sendAllGossipDown(conn Connection) { - for channel := range router.gossipChannelSet() { - if gossip := channel.gossiper.Gossip(); gossip != nil { - channel.SendDown(conn, gossip) - } - } -} - -// for testing -func (router *Router) sendPendingGossip() bool { - sentSomething := false - for conn := range router.Ourself.getConnections() { - sentSomething = conn.(gossipConnection).gossipSenders().Flush() || sentSomething - } - return sentSomething -} - -// BroadcastTopologyUpdate is invoked whenever there is a change to the mesh -// topology, and broadcasts the new set of peers to the mesh. -func (router *Router) broadcastTopologyUpdate(update []*Peer) { - names := make(peerNameSet) - for _, p := range update { - names[p.Name] = struct{}{} - } - router.topologyGossip.GossipBroadcast(&topologyGossipData{peers: router.Peers, update: names}) -} - -// OnGossipUnicast implements Gossiper, but always returns an error, as a -// router should only receive gossip broadcasts of TopologyGossipData. -func (router *Router) OnGossipUnicast(sender PeerName, msg []byte) error { - return fmt.Errorf("unexpected topology gossip unicast: %v", msg) -} - -// OnGossipBroadcast receives broadcasts of TopologyGossipData. -// It returns the received update unchanged. -func (router *Router) OnGossipBroadcast(_ PeerName, update []byte) (GossipData, error) { - origUpdate, _, err := router.applyTopologyUpdate(update) - if err != nil || len(origUpdate) == 0 { - return nil, err - } - return &topologyGossipData{peers: router.Peers, update: origUpdate}, nil -} - -// Gossip yields the current topology as GossipData. -func (router *Router) Gossip() GossipData { - return &topologyGossipData{peers: router.Peers, update: router.Peers.names()} -} - -// OnGossip receives broadcasts of TopologyGossipData. -// It returns an "improved" version of the received update. -// See peers.ApplyUpdate. -func (router *Router) OnGossip(update []byte) (GossipData, error) { - _, newUpdate, err := router.applyTopologyUpdate(update) - if err != nil || len(newUpdate) == 0 { - return nil, err - } - return &topologyGossipData{peers: router.Peers, update: newUpdate}, nil -} - -func (router *Router) applyTopologyUpdate(update []byte) (peerNameSet, peerNameSet, error) { - origUpdate, newUpdate, err := router.Peers.applyUpdate(update) - if err != nil { - return nil, nil, err - } - if len(newUpdate) > 0 { - router.ConnectionMaker.refresh() - router.Routes.recalculate() - } - return origUpdate, newUpdate, nil -} - -func (router *Router) trusts(remote *remoteConnection) bool { - if tcpAddr, err := net.ResolveTCPAddr("tcp4", remote.remoteTCPAddr); err == nil { - for _, trustedSubnet := range router.TrustedSubnets { - if trustedSubnet.Contains(tcpAddr.IP) { - return true - } - } - } else { - // Should not happen as remoteTCPAddr was obtained from TCPConn - router.logger.Printf("Unable to parse remote TCP addr: %s", err) - } - return false -} - -// The set of peers in the mesh network. -// Gossiped just like anything else. -type topologyGossipData struct { - peers *Peers - update peerNameSet -} - -// Merge implements GossipData. -func (d *topologyGossipData) Merge(other GossipData) GossipData { - names := make(peerNameSet) - for name := range d.update { - names[name] = struct{}{} - } - for name := range other.(*topologyGossipData).update { - names[name] = struct{}{} - } - return &topologyGossipData{peers: d.peers, update: names} -} - -// Encode implements GossipData. -func (d *topologyGossipData) Encode() [][]byte { - return [][]byte{d.peers.encodePeers(d.update)} -} diff --git a/vendor/github.com/weaveworks/mesh/routes.go b/vendor/github.com/weaveworks/mesh/routes.go deleted file mode 100644 index 10ff3152eda..00000000000 --- a/vendor/github.com/weaveworks/mesh/routes.go +++ /dev/null @@ -1,263 +0,0 @@ -package mesh - -import ( - "math" - "sync" -) - -type unicastRoutes map[PeerName]PeerName -type broadcastRoutes map[PeerName][]PeerName - -// routes aggregates unicast and broadcast routes for our peer. -type routes struct { - sync.RWMutex - ourself *localPeer - peers *Peers - onChange []func() - unicast unicastRoutes - unicastAll unicastRoutes // [1] - broadcast broadcastRoutes - broadcastAll broadcastRoutes // [1] - recalc chan<- *struct{} - wait chan<- chan struct{} - action chan<- func() - // [1] based on *all* connections, not just established & - // symmetric ones -} - -// newRoutes returns a usable Routes based on the LocalPeer and existing Peers. -func newRoutes(ourself *localPeer, peers *Peers) *routes { - recalculate := make(chan *struct{}, 1) - wait := make(chan chan struct{}) - action := make(chan func()) - r := &routes{ - ourself: ourself, - peers: peers, - unicast: unicastRoutes{ourself.Name: UnknownPeerName}, - unicastAll: unicastRoutes{ourself.Name: UnknownPeerName}, - broadcast: broadcastRoutes{ourself.Name: []PeerName{}}, - broadcastAll: broadcastRoutes{ourself.Name: []PeerName{}}, - recalc: recalculate, - wait: wait, - action: action, - } - go r.run(recalculate, wait, action) - return r -} - -// OnChange appends callback to the functions that will be called whenever the -// routes are recalculated. -func (r *routes) OnChange(callback func()) { - r.Lock() - defer r.Unlock() - r.onChange = append(r.onChange, callback) -} - -// PeerNames returns the peers that are accountd for in the r. -func (r *routes) PeerNames() peerNameSet { - return r.peers.names() -} - -// Unicast returns the next hop on the unicast route to the named peer, -// based on established and symmetric connections. -func (r *routes) Unicast(name PeerName) (PeerName, bool) { - r.RLock() - defer r.RUnlock() - hop, found := r.unicast[name] - return hop, found -} - -// UnicastAll returns the next hop on the unicast route to the named peer, -// based on all connections. -func (r *routes) UnicastAll(name PeerName) (PeerName, bool) { - r.RLock() - defer r.RUnlock() - hop, found := r.unicastAll[name] - return hop, found -} - -// Broadcast returns the set of peer names that should be notified -// when we receive a broadcast message originating from the named peer -// based on established and symmetric connections. -func (r *routes) Broadcast(name PeerName) []PeerName { - return r.lookupOrCalculate(name, &r.broadcast, true) -} - -// BroadcastAll returns the set of peer names that should be notified -// when we receive a broadcast message originating from the named peer -// based on all connections. -func (r *routes) BroadcastAll(name PeerName) []PeerName { - return r.lookupOrCalculate(name, &r.broadcastAll, false) -} - -func (r *routes) lookupOrCalculate(name PeerName, broadcast *broadcastRoutes, establishedAndSymmetric bool) []PeerName { - r.RLock() - hops, found := (*broadcast)[name] - r.RUnlock() - if found { - return hops - } - res := make(chan []PeerName) - r.action <- func() { - r.RLock() - hops, found := (*broadcast)[name] - r.RUnlock() - if found { - res <- hops - return - } - r.peers.RLock() - r.ourself.RLock() - hops = r.calculateBroadcast(name, establishedAndSymmetric) - r.ourself.RUnlock() - r.peers.RUnlock() - res <- hops - r.Lock() - (*broadcast)[name] = hops - r.Unlock() - } - return <-res -} - -// RandomNeighbours chooses min(log2(n_peers), n_neighbouring_peers) -// neighbours, with a random distribution that is topology-sensitive, -// favouring neighbours at the end of "bottleneck links". We determine the -// latter based on the unicast routing table. If a neighbour appears as the -// value more frequently than others - meaning that we reach a higher -// proportion of peers via that neighbour than other neighbours - then it is -// chosen with a higher probability. -// -// Note that we choose log2(n_peers) *neighbours*, not peers. Consequently, on -// sparsely connected peers this function returns a higher proportion of -// neighbours than elsewhere. In extremis, on peers with fewer than -// log2(n_peers) neighbours, all neighbours are returned. -func (r *routes) randomNeighbours(except PeerName) []PeerName { - destinations := make(peerNameSet) - r.RLock() - defer r.RUnlock() - count := int(math.Log2(float64(len(r.unicastAll)))) - // depends on go's random map iteration - for _, dst := range r.unicastAll { - if dst != UnknownPeerName && dst != except { - destinations[dst] = struct{}{} - if len(destinations) >= count { - break - } - } - } - res := make([]PeerName, 0, len(destinations)) - for dst := range destinations { - res = append(res, dst) - } - return res -} - -// Recalculate requests recalculation of the routing table. This is async but -// can effectively be made synchronous with a subsequent call to -// EnsureRecalculated. -func (r *routes) recalculate() { - // The use of a 1-capacity channel in combination with the - // non-blocking send is an optimisation that results in multiple - // requests being coalesced. - select { - case r.recalc <- nil: - default: - } -} - -// EnsureRecalculated waits for any preceding Recalculate requests to finish. -func (r *routes) ensureRecalculated() { - done := make(chan struct{}) - r.wait <- done - <-done -} - -func (r *routes) run(recalculate <-chan *struct{}, wait <-chan chan struct{}, action <-chan func()) { - for { - select { - case <-recalculate: - r.calculate() - case done := <-wait: - select { - case <-recalculate: - r.calculate() - default: - } - close(done) - case f := <-action: - f() - } - } -} - -func (r *routes) calculate() { - r.peers.RLock() - r.ourself.RLock() - var ( - unicast = r.calculateUnicast(true) - unicastAll = r.calculateUnicast(false) - broadcast = make(broadcastRoutes) - broadcastAll = make(broadcastRoutes) - ) - broadcast[r.ourself.Name] = r.calculateBroadcast(r.ourself.Name, true) - broadcastAll[r.ourself.Name] = r.calculateBroadcast(r.ourself.Name, false) - r.ourself.RUnlock() - r.peers.RUnlock() - - r.Lock() - r.unicast = unicast - r.unicastAll = unicastAll - r.broadcast = broadcast - r.broadcastAll = broadcastAll - onChange := r.onChange - r.Unlock() - - for _, callback := range onChange { - callback() - } -} - -// Calculate all the routes for the question: if *we* want to send a -// packet to Peer X, what is the next hop? -// -// When we sniff a packet, we determine the destination peer -// ourself. Consequently, we can relay the packet via any -// arbitrary peers - the intermediate peers do not have to have -// any knowledge of the MAC address at all. Thus there's no need -// to exchange knowledge of MAC addresses, nor any constraints on -// the routes that we construct. -func (r *routes) calculateUnicast(establishedAndSymmetric bool) unicastRoutes { - _, unicast := r.ourself.routes(nil, establishedAndSymmetric) - return unicast -} - -// Calculate the route to answer the question: if we receive a -// broadcast originally from Peer X, which peers should we pass the -// frames on to? -// -// When the topology is stable, and thus all peers perform route -// calculations based on the same data, the algorithm ensures that -// broadcasts reach every peer exactly once. -// -// This is largely due to properties of the Peer.Routes algorithm. In -// particular: -// -// ForAll X,Y,Z in Peers. -// X.Routes(Y) <= X.Routes(Z) \/ -// X.Routes(Z) <= X.Routes(Y) -// ForAll X,Y,Z in Peers. -// Y =/= Z /\ X.Routes(Y) <= X.Routes(Z) => -// X.Routes(Y) u [P | Y.HasSymmetricConnectionTo(P)] <= X.Routes(Z) -// where <= is the subset relationship on keys of the returned map. -func (r *routes) calculateBroadcast(name PeerName, establishedAndSymmetric bool) []PeerName { - hops := []PeerName{} - peer, found := r.peers.byName[name] - if !found { - return hops - } - if found, reached := peer.routes(r.ourself.Peer, establishedAndSymmetric); found { - r.ourself.forEachConnectedPeer(establishedAndSymmetric, reached, - func(remotePeer *Peer) { hops = append(hops, remotePeer.Name) }) - } - return hops -} diff --git a/vendor/github.com/weaveworks/mesh/status.go b/vendor/github.com/weaveworks/mesh/status.go deleted file mode 100644 index bfe250b5e07..00000000000 --- a/vendor/github.com/weaveworks/mesh/status.go +++ /dev/null @@ -1,223 +0,0 @@ -package mesh - -import ( - "fmt" - "net" -) - -// Status is our current state as a peer, as taken from a router. -// This is designed to be used as diagnostic information. -type Status struct { - Protocol string - ProtocolMinVersion int - ProtocolMaxVersion int - Encryption bool - PeerDiscovery bool - Name string - NickName string - Port int - Peers []PeerStatus - UnicastRoutes []unicastRouteStatus - BroadcastRoutes []broadcastRouteStatus - Connections []LocalConnectionStatus - TerminationCount int - Targets []string - OverlayDiagnostics interface{} - TrustedSubnets []string -} - -// NewStatus returns a Status object, taken as a snapshot from the router. -func NewStatus(router *Router) *Status { - return &Status{ - Protocol: Protocol, - ProtocolMinVersion: ProtocolMinVersion, - ProtocolMaxVersion: ProtocolMaxVersion, - Encryption: router.usingPassword(), - PeerDiscovery: router.PeerDiscovery, - Name: router.Ourself.Name.String(), - NickName: router.Ourself.NickName, - Port: router.Port, - Peers: makePeerStatusSlice(router.Peers), - UnicastRoutes: makeUnicastRouteStatusSlice(router.Routes), - BroadcastRoutes: makeBroadcastRouteStatusSlice(router.Routes), - Connections: makeLocalConnectionStatusSlice(router.ConnectionMaker), - TerminationCount: router.ConnectionMaker.terminationCount, - Targets: router.ConnectionMaker.Targets(false), - OverlayDiagnostics: router.Overlay.Diagnostics(), - TrustedSubnets: makeTrustedSubnetsSlice(router.TrustedSubnets), - } -} - -// PeerStatus is the current state of a peer in the mesh. -type PeerStatus struct { - Name string - NickName string - UID PeerUID - ShortID PeerShortID - Version uint64 - Connections []connectionStatus -} - -// makePeerStatusSlice takes a snapshot of the state of peers. -func makePeerStatusSlice(peers *Peers) []PeerStatus { - var slice []PeerStatus - - peers.forEach(func(peer *Peer) { - var connections []connectionStatus - if peer == peers.ourself.Peer { - for conn := range peers.ourself.getConnections() { - connections = append(connections, makeConnectionStatus(conn)) - } - } else { - // Modifying peer.connections requires a write lock on - // Peers, and since we are holding a read lock (due to the - // ForEach), access without locking the peer is safe. - for _, conn := range peer.connections { - connections = append(connections, makeConnectionStatus(conn)) - } - } - slice = append(slice, PeerStatus{ - peer.Name.String(), - peer.NickName, - peer.UID, - peer.ShortID, - peer.Version, - connections, - }) - }) - - return slice -} - -type connectionStatus struct { - Name string - NickName string - Address string - Outbound bool - Established bool -} - -func makeConnectionStatus(c Connection) connectionStatus { - return connectionStatus{ - Name: c.Remote().Name.String(), - NickName: c.Remote().NickName, - Address: c.remoteTCPAddress(), - Outbound: c.isOutbound(), - Established: c.isEstablished(), - } -} - -// unicastRouteStatus is the current state of an established unicast route. -type unicastRouteStatus struct { - Dest, Via string -} - -// makeUnicastRouteStatusSlice takes a snapshot of the unicast routes in routes. -func makeUnicastRouteStatusSlice(r *routes) []unicastRouteStatus { - r.RLock() - defer r.RUnlock() - - var slice []unicastRouteStatus - for dest, via := range r.unicast { - slice = append(slice, unicastRouteStatus{dest.String(), via.String()}) - } - return slice -} - -// BroadcastRouteStatus is the current state of an established broadcast route. -type broadcastRouteStatus struct { - Source string - Via []string -} - -// makeBroadcastRouteStatusSlice takes a snapshot of the broadcast routes in routes. -func makeBroadcastRouteStatusSlice(r *routes) []broadcastRouteStatus { - r.RLock() - defer r.RUnlock() - - var slice []broadcastRouteStatus - for source, via := range r.broadcast { - var hops []string - for _, hop := range via { - hops = append(hops, hop.String()) - } - slice = append(slice, broadcastRouteStatus{source.String(), hops}) - } - return slice -} - -// LocalConnectionStatus is the current state of a physical connection to a peer. -type LocalConnectionStatus struct { - Address string - Outbound bool - State string - Info string - Attrs map[string]interface{} -} - -// makeLocalConnectionStatusSlice takes a snapshot of the active local -// connections in the ConnectionMaker. -func makeLocalConnectionStatusSlice(cm *connectionMaker) []LocalConnectionStatus { - resultChan := make(chan []LocalConnectionStatus, 0) - cm.actionChan <- func() bool { - var slice []LocalConnectionStatus - for conn := range cm.connections { - state := "pending" - if conn.isEstablished() { - state = "established" - } - lc, _ := conn.(*LocalConnection) - attrs := lc.OverlayConn.Attrs() - name, ok := attrs["name"] - if !ok { - name = "none" - } - info := fmt.Sprintf("%-6v %v", name, conn.Remote()) - if lc.router.usingPassword() { - if lc.untrusted() { - info = fmt.Sprintf("%-11v %v", "encrypted", info) - } else { - info = fmt.Sprintf("%-11v %v", "unencrypted", info) - } - } - slice = append(slice, LocalConnectionStatus{conn.remoteTCPAddress(), conn.isOutbound(), state, info, attrs}) - } - for address, target := range cm.targets { - add := func(state, info string) { - slice = append(slice, LocalConnectionStatus{address, true, state, info, nil}) - } - switch target.state { - case targetWaiting: - until := "never" - if !target.tryAfter.IsZero() { - until = target.tryAfter.String() - } - if target.lastError == nil { // shouldn't happen - add("waiting", "until: "+until) - } else { - add("failed", target.lastError.Error()+", retry: "+until) - } - case targetAttempting: - if target.lastError == nil { - add("connecting", "") - } else { - add("retrying", target.lastError.Error()) - } - case targetConnected: - case targetSuspended: - } - } - resultChan <- slice - return false - } - return <-resultChan -} - -// makeTrustedSubnetsSlice makes a human-readable copy of the trustedSubnets. -func makeTrustedSubnetsSlice(trustedSubnets []*net.IPNet) []string { - trustedSubnetStrs := []string{} - for _, trustedSubnet := range trustedSubnets { - trustedSubnetStrs = append(trustedSubnetStrs, trustedSubnet.String()) - } - return trustedSubnetStrs -} diff --git a/vendor/github.com/weaveworks/mesh/surrogate_gossiper.go b/vendor/github.com/weaveworks/mesh/surrogate_gossiper.go deleted file mode 100644 index 89ea9e1b94a..00000000000 --- a/vendor/github.com/weaveworks/mesh/surrogate_gossiper.go +++ /dev/null @@ -1,94 +0,0 @@ -package mesh - -import ( - "bytes" - "hash/fnv" - "sync" - "time" -) - -// surrogateGossiper ignores unicasts and relays broadcasts and gossips. -type surrogateGossiper struct { - sync.Mutex - prevUpdates []prevUpdate -} - -type prevUpdate struct { - update []byte - hash uint64 - t time.Time -} - -var _ Gossiper = &surrogateGossiper{} - -// Hook to mock time for testing -var now = func() time.Time { return time.Now() } - -// OnGossipUnicast implements Gossiper. -func (*surrogateGossiper) OnGossipUnicast(sender PeerName, msg []byte) error { - return nil -} - -// OnGossipBroadcast implements Gossiper. -func (*surrogateGossiper) OnGossipBroadcast(_ PeerName, update []byte) (GossipData, error) { - return newSurrogateGossipData(update), nil -} - -// Gossip implements Gossiper. -func (*surrogateGossiper) Gossip() GossipData { - return nil -} - -// OnGossip should return "everything new I've just learnt". -// surrogateGossiper doesn't understand the content of messages, but it can eliminate simple duplicates -func (s *surrogateGossiper) OnGossip(update []byte) (GossipData, error) { - hash := fnv.New64a() - _, _ = hash.Write(update) - updateHash := hash.Sum64() - s.Lock() - defer s.Unlock() - for _, p := range s.prevUpdates { - if updateHash == p.hash && bytes.Equal(update, p.update) { - return nil, nil - } - } - // Delete anything that's older than the gossip interval, so we don't grow forever - // (this time limit is arbitrary; surrogateGossiper should pass on new gossip immediately - // so there should be no reason for a duplicate to show up after a long time) - updateTime := now() - deleteBefore := updateTime.Add(-gossipInterval) - keepFrom := len(s.prevUpdates) - for i, p := range s.prevUpdates { - if p.t.After(deleteBefore) { - keepFrom = i - break - } - } - s.prevUpdates = append(s.prevUpdates[keepFrom:], prevUpdate{update, updateHash, updateTime}) - return newSurrogateGossipData(update), nil -} - -// surrogateGossipData is a simple in-memory GossipData. -type surrogateGossipData struct { - messages [][]byte -} - -var _ GossipData = &surrogateGossipData{} - -func newSurrogateGossipData(msg []byte) *surrogateGossipData { - return &surrogateGossipData{messages: [][]byte{msg}} -} - -// Encode implements GossipData. -func (d *surrogateGossipData) Encode() [][]byte { - return d.messages -} - -// Merge implements GossipData. -func (d *surrogateGossipData) Merge(other GossipData) GossipData { - o := other.(*surrogateGossipData) - messages := make([][]byte, 0, len(d.messages)+len(o.messages)) - messages = append(messages, d.messages...) - messages = append(messages, o.messages...) - return &surrogateGossipData{messages: messages} -} diff --git a/vendor/github.com/weaveworks/mesh/token_bucket.go b/vendor/github.com/weaveworks/mesh/token_bucket.go deleted file mode 100644 index 2015f47ec90..00000000000 --- a/vendor/github.com/weaveworks/mesh/token_bucket.go +++ /dev/null @@ -1,48 +0,0 @@ -package mesh - -import ( - "time" -) - -// TokenBucket acts as a rate-limiter. -// It is not safe for concurrent use by multiple goroutines. -type tokenBucket struct { - capacity int64 // Maximum capacity of bucket - tokenInterval time.Duration // Token replenishment rate - refillDuration time.Duration // Time to refill from empty - earliestUnspentToken time.Time -} - -// newTokenBucket returns a bucket containing capacity tokens, refilled at a -// rate of one token per tokenInterval. -func newTokenBucket(capacity int64, tokenInterval time.Duration) *tokenBucket { - tb := tokenBucket{ - capacity: capacity, - tokenInterval: tokenInterval, - refillDuration: tokenInterval * time.Duration(capacity)} - - tb.earliestUnspentToken = tb.capacityToken() - - return &tb -} - -// Blocks until there is a token available. -// Not safe for concurrent use by multiple goroutines. -func (tb *tokenBucket) wait() { - // If earliest unspent token is in the future, sleep until then - time.Sleep(tb.earliestUnspentToken.Sub(time.Now())) - - // Alternatively, enforce bucket capacity if necessary - capacityToken := tb.capacityToken() - if tb.earliestUnspentToken.Before(capacityToken) { - tb.earliestUnspentToken = capacityToken - } - - // 'Remove' a token from the bucket - tb.earliestUnspentToken = tb.earliestUnspentToken.Add(tb.tokenInterval) -} - -// Determine the historic token timestamp representing a full bucket -func (tb *tokenBucket) capacityToken() time.Time { - return time.Now().Add(-tb.refillDuration).Truncate(tb.tokenInterval) -} diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.h b/vendor/golang.org/x/crypto/curve25519/const_amd64.h deleted file mode 100644 index b3f74162f60..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/const_amd64.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -#define REDMASK51 0x0007FFFFFFFFFFFF diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s deleted file mode 100644 index ee7b4bd5f8e..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/const_amd64.s +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -// These constants cannot be encoded in non-MOVQ immediates. -// We access them directly from memory instead. - -DATA ·_121666_213(SB)/8, $996687872 -GLOBL ·_121666_213(SB), 8, $8 - -DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA -GLOBL ·_2P0(SB), 8, $8 - -DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE -GLOBL ·_2P1234(SB), 8, $8 diff --git a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s deleted file mode 100644 index cd793a5b5f2..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -// func cswap(inout *[4][5]uint64, v uint64) -TEXT ·cswap(SB),7,$0 - MOVQ inout+0(FP),DI - MOVQ v+8(FP),SI - - SUBQ $1, SI - NOTQ SI - MOVQ SI, X15 - PSHUFD $0x44, X15, X15 - - MOVOU 0(DI), X0 - MOVOU 16(DI), X2 - MOVOU 32(DI), X4 - MOVOU 48(DI), X6 - MOVOU 64(DI), X8 - MOVOU 80(DI), X1 - MOVOU 96(DI), X3 - MOVOU 112(DI), X5 - MOVOU 128(DI), X7 - MOVOU 144(DI), X9 - - MOVO X1, X10 - MOVO X3, X11 - MOVO X5, X12 - MOVO X7, X13 - MOVO X9, X14 - - PXOR X0, X10 - PXOR X2, X11 - PXOR X4, X12 - PXOR X6, X13 - PXOR X8, X14 - PAND X15, X10 - PAND X15, X11 - PAND X15, X12 - PAND X15, X13 - PAND X15, X14 - PXOR X10, X0 - PXOR X10, X1 - PXOR X11, X2 - PXOR X11, X3 - PXOR X12, X4 - PXOR X12, X5 - PXOR X13, X6 - PXOR X13, X7 - PXOR X14, X8 - PXOR X14, X9 - - MOVOU X0, 0(DI) - MOVOU X2, 16(DI) - MOVOU X4, 32(DI) - MOVOU X6, 48(DI) - MOVOU X8, 64(DI) - MOVOU X1, 80(DI) - MOVOU X3, 96(DI) - MOVOU X5, 112(DI) - MOVOU X7, 128(DI) - MOVOU X9, 144(DI) - RET diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go deleted file mode 100644 index 75f24babb69..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/curve25519.go +++ /dev/null @@ -1,834 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// We have an implementation in amd64 assembly so this code is only run on -// non-amd64 platforms. The amd64 assembly does not support gccgo. -// +build !amd64 gccgo appengine - -package curve25519 - -import ( - "encoding/binary" -) - -// This code is a port of the public domain, "ref10" implementation of -// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. - -// fieldElement represents an element of the field GF(2^255 - 19). An element -// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -// context. -type fieldElement [10]int32 - -func feZero(fe *fieldElement) { - for i := range fe { - fe[i] = 0 - } -} - -func feOne(fe *fieldElement) { - feZero(fe) - fe[0] = 1 -} - -func feAdd(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] + b[i] - } -} - -func feSub(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] - b[i] - } -} - -func feCopy(dst, src *fieldElement) { - for i := range dst { - dst[i] = src[i] - } -} - -// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. -// -// Preconditions: b in {0,1}. -func feCSwap(f, g *fieldElement, b int32) { - b = -b - for i := range f { - t := b & (f[i] ^ g[i]) - f[i] ^= t - g[i] ^= t - } -} - -// load3 reads a 24-bit, little-endian value from in. -func load3(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r -} - -// load4 reads a 32-bit, little-endian value from in. -func load4(in []byte) int64 { - return int64(binary.LittleEndian.Uint32(in)) -} - -func feFromBytes(dst *fieldElement, src *[32]byte) { - h0 := load4(src[:]) - h1 := load3(src[4:]) << 6 - h2 := load3(src[7:]) << 5 - h3 := load3(src[10:]) << 3 - h4 := load3(src[13:]) << 2 - h5 := load4(src[16:]) - h6 := load3(src[20:]) << 7 - h7 := load3(src[23:]) << 5 - h8 := load3(src[26:]) << 4 - h9 := (load3(src[29:]) & 0x7fffff) << 2 - - var carry [10]int64 - carry[9] = (h9 + 1<<24) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + 1<<24) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + 1<<24) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + 1<<24) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + 1<<24) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + 1<<25) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + 1<<25) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + 1<<25) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + 1<<25) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + 1<<25) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - dst[0] = int32(h0) - dst[1] = int32(h1) - dst[2] = int32(h2) - dst[3] = int32(h3) - dst[4] = int32(h4) - dst[5] = int32(h5) - dst[6] = int32(h6) - dst[7] = int32(h7) - dst[8] = int32(h8) - dst[9] = int32(h9) -} - -// feToBytes marshals h to s. -// Preconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0> 25 - q = (h[0] + q) >> 26 - q = (h[1] + q) >> 25 - q = (h[2] + q) >> 26 - q = (h[3] + q) >> 25 - q = (h[4] + q) >> 26 - q = (h[5] + q) >> 25 - q = (h[6] + q) >> 26 - q = (h[7] + q) >> 25 - q = (h[8] + q) >> 26 - q = (h[9] + q) >> 25 - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h[0] += 19 * q - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - carry[0] = h[0] >> 26 - h[1] += carry[0] - h[0] -= carry[0] << 26 - carry[1] = h[1] >> 25 - h[2] += carry[1] - h[1] -= carry[1] << 25 - carry[2] = h[2] >> 26 - h[3] += carry[2] - h[2] -= carry[2] << 26 - carry[3] = h[3] >> 25 - h[4] += carry[3] - h[3] -= carry[3] << 25 - carry[4] = h[4] >> 26 - h[5] += carry[4] - h[4] -= carry[4] << 26 - carry[5] = h[5] >> 25 - h[6] += carry[5] - h[5] -= carry[5] << 25 - carry[6] = h[6] >> 26 - h[7] += carry[6] - h[6] -= carry[6] << 26 - carry[7] = h[7] >> 25 - h[8] += carry[7] - h[7] -= carry[7] << 25 - carry[8] = h[8] >> 26 - h[9] += carry[8] - h[8] -= carry[8] << 26 - carry[9] = h[9] >> 25 - h[9] -= carry[9] << 25 - // h10 = carry9 - - // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h[0]+...+2^230 h[9]. - - s[0] = byte(h[0] >> 0) - s[1] = byte(h[0] >> 8) - s[2] = byte(h[0] >> 16) - s[3] = byte((h[0] >> 24) | (h[1] << 2)) - s[4] = byte(h[1] >> 6) - s[5] = byte(h[1] >> 14) - s[6] = byte((h[1] >> 22) | (h[2] << 3)) - s[7] = byte(h[2] >> 5) - s[8] = byte(h[2] >> 13) - s[9] = byte((h[2] >> 21) | (h[3] << 5)) - s[10] = byte(h[3] >> 3) - s[11] = byte(h[3] >> 11) - s[12] = byte((h[3] >> 19) | (h[4] << 6)) - s[13] = byte(h[4] >> 2) - s[14] = byte(h[4] >> 10) - s[15] = byte(h[4] >> 18) - s[16] = byte(h[5] >> 0) - s[17] = byte(h[5] >> 8) - s[18] = byte(h[5] >> 16) - s[19] = byte((h[5] >> 24) | (h[6] << 1)) - s[20] = byte(h[6] >> 7) - s[21] = byte(h[6] >> 15) - s[22] = byte((h[6] >> 23) | (h[7] << 3)) - s[23] = byte(h[7] >> 5) - s[24] = byte(h[7] >> 13) - s[25] = byte((h[7] >> 21) | (h[8] << 4)) - s[26] = byte(h[8] >> 4) - s[27] = byte(h[8] >> 12) - s[28] = byte((h[8] >> 20) | (h[9] << 6)) - s[29] = byte(h[9] >> 2) - s[30] = byte(h[9] >> 10) - s[31] = byte(h[9] >> 18) -} - -// feMul calculates h = f * g -// Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Notes on implementation strategy: -// -// Using schoolbook multiplication. -// Karatsuba would save a little in some cost models. -// -// Most multiplications by 2 and 19 are 32-bit precomputations; -// cheaper than 64-bit postcomputations. -// -// There is one remaining multiplication by 19 in the carry chain; -// one *19 precomputation can be merged into this, -// but the resulting data flow is considerably less clean. -// -// There are 12 carries below. -// 10 of them are 2-way parallelizable and vectorizable. -// Can get away with 11 carries, but then data flow is much deeper. -// -// With tighter constraints on inputs can squeeze carries into int32. -func feMul(h, f, g *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - g0 := g[0] - g1 := g[1] - g2 := g[2] - g3 := g[3] - g4 := g[4] - g5 := g[5] - g6 := g[6] - g7 := g[7] - g8 := g[8] - g9 := g[9] - g1_19 := 19 * g1 // 1.4*2^29 - g2_19 := 19 * g2 // 1.4*2^30; still ok - g3_19 := 19 * g3 - g4_19 := 19 * g4 - g5_19 := 19 * g5 - g6_19 := 19 * g6 - g7_19 := 19 * g7 - g8_19 := 19 * g8 - g9_19 := 19 * g9 - f1_2 := 2 * f1 - f3_2 := 2 * f3 - f5_2 := 2 * f5 - f7_2 := 2 * f7 - f9_2 := 2 * f9 - f0g0 := int64(f0) * int64(g0) - f0g1 := int64(f0) * int64(g1) - f0g2 := int64(f0) * int64(g2) - f0g3 := int64(f0) * int64(g3) - f0g4 := int64(f0) * int64(g4) - f0g5 := int64(f0) * int64(g5) - f0g6 := int64(f0) * int64(g6) - f0g7 := int64(f0) * int64(g7) - f0g8 := int64(f0) * int64(g8) - f0g9 := int64(f0) * int64(g9) - f1g0 := int64(f1) * int64(g0) - f1g1_2 := int64(f1_2) * int64(g1) - f1g2 := int64(f1) * int64(g2) - f1g3_2 := int64(f1_2) * int64(g3) - f1g4 := int64(f1) * int64(g4) - f1g5_2 := int64(f1_2) * int64(g5) - f1g6 := int64(f1) * int64(g6) - f1g7_2 := int64(f1_2) * int64(g7) - f1g8 := int64(f1) * int64(g8) - f1g9_38 := int64(f1_2) * int64(g9_19) - f2g0 := int64(f2) * int64(g0) - f2g1 := int64(f2) * int64(g1) - f2g2 := int64(f2) * int64(g2) - f2g3 := int64(f2) * int64(g3) - f2g4 := int64(f2) * int64(g4) - f2g5 := int64(f2) * int64(g5) - f2g6 := int64(f2) * int64(g6) - f2g7 := int64(f2) * int64(g7) - f2g8_19 := int64(f2) * int64(g8_19) - f2g9_19 := int64(f2) * int64(g9_19) - f3g0 := int64(f3) * int64(g0) - f3g1_2 := int64(f3_2) * int64(g1) - f3g2 := int64(f3) * int64(g2) - f3g3_2 := int64(f3_2) * int64(g3) - f3g4 := int64(f3) * int64(g4) - f3g5_2 := int64(f3_2) * int64(g5) - f3g6 := int64(f3) * int64(g6) - f3g7_38 := int64(f3_2) * int64(g7_19) - f3g8_19 := int64(f3) * int64(g8_19) - f3g9_38 := int64(f3_2) * int64(g9_19) - f4g0 := int64(f4) * int64(g0) - f4g1 := int64(f4) * int64(g1) - f4g2 := int64(f4) * int64(g2) - f4g3 := int64(f4) * int64(g3) - f4g4 := int64(f4) * int64(g4) - f4g5 := int64(f4) * int64(g5) - f4g6_19 := int64(f4) * int64(g6_19) - f4g7_19 := int64(f4) * int64(g7_19) - f4g8_19 := int64(f4) * int64(g8_19) - f4g9_19 := int64(f4) * int64(g9_19) - f5g0 := int64(f5) * int64(g0) - f5g1_2 := int64(f5_2) * int64(g1) - f5g2 := int64(f5) * int64(g2) - f5g3_2 := int64(f5_2) * int64(g3) - f5g4 := int64(f5) * int64(g4) - f5g5_38 := int64(f5_2) * int64(g5_19) - f5g6_19 := int64(f5) * int64(g6_19) - f5g7_38 := int64(f5_2) * int64(g7_19) - f5g8_19 := int64(f5) * int64(g8_19) - f5g9_38 := int64(f5_2) * int64(g9_19) - f6g0 := int64(f6) * int64(g0) - f6g1 := int64(f6) * int64(g1) - f6g2 := int64(f6) * int64(g2) - f6g3 := int64(f6) * int64(g3) - f6g4_19 := int64(f6) * int64(g4_19) - f6g5_19 := int64(f6) * int64(g5_19) - f6g6_19 := int64(f6) * int64(g6_19) - f6g7_19 := int64(f6) * int64(g7_19) - f6g8_19 := int64(f6) * int64(g8_19) - f6g9_19 := int64(f6) * int64(g9_19) - f7g0 := int64(f7) * int64(g0) - f7g1_2 := int64(f7_2) * int64(g1) - f7g2 := int64(f7) * int64(g2) - f7g3_38 := int64(f7_2) * int64(g3_19) - f7g4_19 := int64(f7) * int64(g4_19) - f7g5_38 := int64(f7_2) * int64(g5_19) - f7g6_19 := int64(f7) * int64(g6_19) - f7g7_38 := int64(f7_2) * int64(g7_19) - f7g8_19 := int64(f7) * int64(g8_19) - f7g9_38 := int64(f7_2) * int64(g9_19) - f8g0 := int64(f8) * int64(g0) - f8g1 := int64(f8) * int64(g1) - f8g2_19 := int64(f8) * int64(g2_19) - f8g3_19 := int64(f8) * int64(g3_19) - f8g4_19 := int64(f8) * int64(g4_19) - f8g5_19 := int64(f8) * int64(g5_19) - f8g6_19 := int64(f8) * int64(g6_19) - f8g7_19 := int64(f8) * int64(g7_19) - f8g8_19 := int64(f8) * int64(g8_19) - f8g9_19 := int64(f8) * int64(g9_19) - f9g0 := int64(f9) * int64(g0) - f9g1_38 := int64(f9_2) * int64(g1_19) - f9g2_19 := int64(f9) * int64(g2_19) - f9g3_38 := int64(f9_2) * int64(g3_19) - f9g4_19 := int64(f9) * int64(g4_19) - f9g5_38 := int64(f9_2) * int64(g5_19) - f9g6_19 := int64(f9) * int64(g6_19) - f9g7_38 := int64(f9_2) * int64(g7_19) - f9g8_19 := int64(f9) * int64(g8_19) - f9g9_38 := int64(f9_2) * int64(g9_19) - h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 - h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 - h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 - h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 - h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 - h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 - h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 - h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 - h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 - h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 - var carry [10]int64 - - // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - // |h0| <= 2^25 - // |h4| <= 2^25 - // |h1| <= 1.51*2^58 - // |h5| <= 1.51*2^58 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - // |h1| <= 2^24; from now on fits into int32 - // |h5| <= 2^24; from now on fits into int32 - // |h2| <= 1.21*2^59 - // |h6| <= 1.21*2^59 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - // |h2| <= 2^25; from now on fits into int32 unchanged - // |h6| <= 2^25; from now on fits into int32 unchanged - // |h3| <= 1.51*2^58 - // |h7| <= 1.51*2^58 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - // |h3| <= 2^24; from now on fits into int32 unchanged - // |h7| <= 2^24; from now on fits into int32 unchanged - // |h4| <= 1.52*2^33 - // |h8| <= 1.52*2^33 - - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - // |h4| <= 2^25; from now on fits into int32 unchanged - // |h8| <= 2^25; from now on fits into int32 unchanged - // |h5| <= 1.01*2^24 - // |h9| <= 1.51*2^58 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - // |h9| <= 2^24; from now on fits into int32 unchanged - // |h0| <= 1.8*2^37 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - // |h0| <= 2^25; from now on fits into int32 unchanged - // |h1| <= 1.01*2^24 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// feSquare calculates h = f*f. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feSquare(h, f *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - f0_2 := 2 * f0 - f1_2 := 2 * f1 - f2_2 := 2 * f2 - f3_2 := 2 * f3 - f4_2 := 2 * f4 - f5_2 := 2 * f5 - f6_2 := 2 * f6 - f7_2 := 2 * f7 - f5_38 := 38 * f5 // 1.31*2^30 - f6_19 := 19 * f6 // 1.31*2^30 - f7_38 := 38 * f7 // 1.31*2^30 - f8_19 := 19 * f8 // 1.31*2^30 - f9_38 := 38 * f9 // 1.31*2^30 - f0f0 := int64(f0) * int64(f0) - f0f1_2 := int64(f0_2) * int64(f1) - f0f2_2 := int64(f0_2) * int64(f2) - f0f3_2 := int64(f0_2) * int64(f3) - f0f4_2 := int64(f0_2) * int64(f4) - f0f5_2 := int64(f0_2) * int64(f5) - f0f6_2 := int64(f0_2) * int64(f6) - f0f7_2 := int64(f0_2) * int64(f7) - f0f8_2 := int64(f0_2) * int64(f8) - f0f9_2 := int64(f0_2) * int64(f9) - f1f1_2 := int64(f1_2) * int64(f1) - f1f2_2 := int64(f1_2) * int64(f2) - f1f3_4 := int64(f1_2) * int64(f3_2) - f1f4_2 := int64(f1_2) * int64(f4) - f1f5_4 := int64(f1_2) * int64(f5_2) - f1f6_2 := int64(f1_2) * int64(f6) - f1f7_4 := int64(f1_2) * int64(f7_2) - f1f8_2 := int64(f1_2) * int64(f8) - f1f9_76 := int64(f1_2) * int64(f9_38) - f2f2 := int64(f2) * int64(f2) - f2f3_2 := int64(f2_2) * int64(f3) - f2f4_2 := int64(f2_2) * int64(f4) - f2f5_2 := int64(f2_2) * int64(f5) - f2f6_2 := int64(f2_2) * int64(f6) - f2f7_2 := int64(f2_2) * int64(f7) - f2f8_38 := int64(f2_2) * int64(f8_19) - f2f9_38 := int64(f2) * int64(f9_38) - f3f3_2 := int64(f3_2) * int64(f3) - f3f4_2 := int64(f3_2) * int64(f4) - f3f5_4 := int64(f3_2) * int64(f5_2) - f3f6_2 := int64(f3_2) * int64(f6) - f3f7_76 := int64(f3_2) * int64(f7_38) - f3f8_38 := int64(f3_2) * int64(f8_19) - f3f9_76 := int64(f3_2) * int64(f9_38) - f4f4 := int64(f4) * int64(f4) - f4f5_2 := int64(f4_2) * int64(f5) - f4f6_38 := int64(f4_2) * int64(f6_19) - f4f7_38 := int64(f4) * int64(f7_38) - f4f8_38 := int64(f4_2) * int64(f8_19) - f4f9_38 := int64(f4) * int64(f9_38) - f5f5_38 := int64(f5) * int64(f5_38) - f5f6_38 := int64(f5_2) * int64(f6_19) - f5f7_76 := int64(f5_2) * int64(f7_38) - f5f8_38 := int64(f5_2) * int64(f8_19) - f5f9_76 := int64(f5_2) * int64(f9_38) - f6f6_19 := int64(f6) * int64(f6_19) - f6f7_38 := int64(f6) * int64(f7_38) - f6f8_38 := int64(f6_2) * int64(f8_19) - f6f9_38 := int64(f6) * int64(f9_38) - f7f7_38 := int64(f7) * int64(f7_38) - f7f8_38 := int64(f7_2) * int64(f8_19) - f7f9_76 := int64(f7_2) * int64(f9_38) - f8f8_19 := int64(f8) * int64(f8_19) - f8f9_38 := int64(f8) * int64(f9_38) - f9f9_38 := int64(f9) * int64(f9_38) - h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 - h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 - h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 - h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 - h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 - h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 - h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 - h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 - h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 - h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 - var carry [10]int64 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// feMul121666 calculates h = f * 121666. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feMul121666(h, f *fieldElement) { - h0 := int64(f[0]) * 121666 - h1 := int64(f[1]) * 121666 - h2 := int64(f[2]) * 121666 - h3 := int64(f[3]) * 121666 - h4 := int64(f[4]) * 121666 - h5 := int64(f[5]) * 121666 - h6 := int64(f[6]) * 121666 - h7 := int64(f[7]) * 121666 - h8 := int64(f[8]) * 121666 - h9 := int64(f[9]) * 121666 - var carry [10]int64 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// feInvert sets out = z^-1. -func feInvert(out, z *fieldElement) { - var t0, t1, t2, t3 fieldElement - var i int - - feSquare(&t0, z) - for i = 1; i < 1; i++ { - feSquare(&t0, &t0) - } - feSquare(&t1, &t0) - for i = 1; i < 2; i++ { - feSquare(&t1, &t1) - } - feMul(&t1, z, &t1) - feMul(&t0, &t0, &t1) - feSquare(&t2, &t0) - for i = 1; i < 1; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t1, &t2) - feSquare(&t2, &t1) - for i = 1; i < 5; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) - } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 20; i++ { - feSquare(&t3, &t3) - } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) - } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 100; i++ { - feSquare(&t3, &t3) - } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t1, &t1) - for i = 1; i < 5; i++ { - feSquare(&t1, &t1) - } - feMul(out, &t1, &t0) -} - -func scalarMult(out, in, base *[32]byte) { - var e [32]byte - - copy(e[:], in[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement - feFromBytes(&x1, base) - feOne(&x2) - feCopy(&x3, &x1) - feOne(&z3) - - swap := int32(0) - for pos := 254; pos >= 0; pos-- { - b := e[pos/8] >> uint(pos&7) - b &= 1 - swap ^= int32(b) - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - swap = int32(b) - - feSub(&tmp0, &x3, &z3) - feSub(&tmp1, &x2, &z2) - feAdd(&x2, &x2, &z2) - feAdd(&z2, &x3, &z3) - feMul(&z3, &tmp0, &x2) - feMul(&z2, &z2, &tmp1) - feSquare(&tmp0, &tmp1) - feSquare(&tmp1, &x2) - feAdd(&x3, &z3, &z2) - feSub(&z2, &z3, &z2) - feMul(&x2, &tmp1, &tmp0) - feSub(&tmp1, &tmp1, &tmp0) - feSquare(&z2, &z2) - feMul121666(&z3, &tmp1) - feSquare(&x3, &x3) - feAdd(&tmp0, &tmp0, &z3) - feMul(&z3, &x1, &z2) - feMul(&z2, &tmp1, &tmp0) - } - - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - - feInvert(&z2, &z2) - feMul(&x2, &x2, &z2) - feToBytes(out, &x2) -} diff --git a/vendor/golang.org/x/crypto/curve25519/doc.go b/vendor/golang.org/x/crypto/curve25519/doc.go deleted file mode 100644 index da9b10d9c1f..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/doc.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package curve25519 provides an implementation of scalar multiplication on -// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html -package curve25519 // import "golang.org/x/crypto/curve25519" - -// basePoint is the x coordinate of the generator of the curve. -var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -// ScalarMult sets dst to the product in*base where dst and base are the x -// coordinates of group points and all values are in little-endian form. -func ScalarMult(dst, in, base *[32]byte) { - scalarMult(dst, in, base) -} - -// ScalarBaseMult sets dst to the product in*base where dst and base are the x -// coordinates of group points, base is the standard generator and all values -// are in little-endian form. -func ScalarBaseMult(dst, in *[32]byte) { - ScalarMult(dst, in, &basePoint) -} diff --git a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s deleted file mode 100644 index 390816106ee..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func freeze(inout *[5]uint64) -TEXT ·freeze(SB),7,$0-8 - MOVQ inout+0(FP), DI - - MOVQ 0(DI),SI - MOVQ 8(DI),DX - MOVQ 16(DI),CX - MOVQ 24(DI),R8 - MOVQ 32(DI),R9 - MOVQ $REDMASK51,AX - MOVQ AX,R10 - SUBQ $18,R10 - MOVQ $3,R11 -REDUCELOOP: - MOVQ SI,R12 - SHRQ $51,R12 - ANDQ AX,SI - ADDQ R12,DX - MOVQ DX,R12 - SHRQ $51,R12 - ANDQ AX,DX - ADDQ R12,CX - MOVQ CX,R12 - SHRQ $51,R12 - ANDQ AX,CX - ADDQ R12,R8 - MOVQ R8,R12 - SHRQ $51,R12 - ANDQ AX,R8 - ADDQ R12,R9 - MOVQ R9,R12 - SHRQ $51,R12 - ANDQ AX,R9 - IMUL3Q $19,R12,R12 - ADDQ R12,SI - SUBQ $1,R11 - JA REDUCELOOP - MOVQ $1,R12 - CMPQ R10,SI - CMOVQLT R11,R12 - CMPQ AX,DX - CMOVQNE R11,R12 - CMPQ AX,CX - CMOVQNE R11,R12 - CMPQ AX,R8 - CMOVQNE R11,R12 - CMPQ AX,R9 - CMOVQNE R11,R12 - NEGQ R12 - ANDQ R12,AX - ANDQ R12,R10 - SUBQ R10,SI - SUBQ AX,DX - SUBQ AX,CX - SUBQ AX,R8 - SUBQ AX,R9 - MOVQ SI,0(DI) - MOVQ DX,8(DI) - MOVQ CX,16(DI) - MOVQ R8,24(DI) - MOVQ R9,32(DI) - RET diff --git a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s deleted file mode 100644 index e0ac30c70f1..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s +++ /dev/null @@ -1,1377 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func ladderstep(inout *[5][5]uint64) -TEXT ·ladderstep(SB),0,$296-8 - MOVQ inout+0(FP),DI - - MOVQ 40(DI),SI - MOVQ 48(DI),DX - MOVQ 56(DI),CX - MOVQ 64(DI),R8 - MOVQ 72(DI),R9 - MOVQ SI,AX - MOVQ DX,R10 - MOVQ CX,R11 - MOVQ R8,R12 - MOVQ R9,R13 - ADDQ ·_2P0(SB),AX - ADDQ ·_2P1234(SB),R10 - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 80(DI),SI - ADDQ 88(DI),DX - ADDQ 96(DI),CX - ADDQ 104(DI),R8 - ADDQ 112(DI),R9 - SUBQ 80(DI),AX - SUBQ 88(DI),R10 - SUBQ 96(DI),R11 - SUBQ 104(DI),R12 - SUBQ 112(DI),R13 - MOVQ SI,0(SP) - MOVQ DX,8(SP) - MOVQ CX,16(SP) - MOVQ R8,24(SP) - MOVQ R9,32(SP) - MOVQ AX,40(SP) - MOVQ R10,48(SP) - MOVQ R11,56(SP) - MOVQ R12,64(SP) - MOVQ R13,72(SP) - MOVQ 40(SP),AX - MULQ 40(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 48(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 56(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 64(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 72(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 48(SP),AX - MULQ 48(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 48(SP),AX - SHLQ $1,AX - MULQ 56(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 48(SP),AX - SHLQ $1,AX - MULQ 64(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 48(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 56(SP),AX - MULQ 56(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 56(SP),DX - IMUL3Q $38,DX,AX - MULQ 64(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 56(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 64(SP),DX - IMUL3Q $19,DX,AX - MULQ 64(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 64(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 72(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,80(SP) - MOVQ R8,88(SP) - MOVQ R9,96(SP) - MOVQ AX,104(SP) - MOVQ R10,112(SP) - MOVQ 0(SP),AX - MULQ 0(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 8(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 16(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 24(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 32(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 8(SP),AX - MULQ 8(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - SHLQ $1,AX - MULQ 16(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SP),AX - SHLQ $1,AX - MULQ 24(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 16(SP),AX - MULQ 16(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 16(SP),DX - IMUL3Q $38,DX,AX - MULQ 24(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 16(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 24(SP),DX - IMUL3Q $19,DX,AX - MULQ 24(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 24(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 32(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,120(SP) - MOVQ R8,128(SP) - MOVQ R9,136(SP) - MOVQ AX,144(SP) - MOVQ R10,152(SP) - MOVQ SI,SI - MOVQ R8,DX - MOVQ R9,CX - MOVQ AX,R8 - MOVQ R10,R9 - ADDQ ·_2P0(SB),SI - ADDQ ·_2P1234(SB),DX - ADDQ ·_2P1234(SB),CX - ADDQ ·_2P1234(SB),R8 - ADDQ ·_2P1234(SB),R9 - SUBQ 80(SP),SI - SUBQ 88(SP),DX - SUBQ 96(SP),CX - SUBQ 104(SP),R8 - SUBQ 112(SP),R9 - MOVQ SI,160(SP) - MOVQ DX,168(SP) - MOVQ CX,176(SP) - MOVQ R8,184(SP) - MOVQ R9,192(SP) - MOVQ 120(DI),SI - MOVQ 128(DI),DX - MOVQ 136(DI),CX - MOVQ 144(DI),R8 - MOVQ 152(DI),R9 - MOVQ SI,AX - MOVQ DX,R10 - MOVQ CX,R11 - MOVQ R8,R12 - MOVQ R9,R13 - ADDQ ·_2P0(SB),AX - ADDQ ·_2P1234(SB),R10 - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 160(DI),SI - ADDQ 168(DI),DX - ADDQ 176(DI),CX - ADDQ 184(DI),R8 - ADDQ 192(DI),R9 - SUBQ 160(DI),AX - SUBQ 168(DI),R10 - SUBQ 176(DI),R11 - SUBQ 184(DI),R12 - SUBQ 192(DI),R13 - MOVQ SI,200(SP) - MOVQ DX,208(SP) - MOVQ CX,216(SP) - MOVQ R8,224(SP) - MOVQ R9,232(SP) - MOVQ AX,240(SP) - MOVQ R10,248(SP) - MOVQ R11,256(SP) - MOVQ R12,264(SP) - MOVQ R13,272(SP) - MOVQ 224(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,280(SP) - MULQ 56(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 232(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,288(SP) - MULQ 48(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 200(SP),AX - MULQ 40(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 200(SP),AX - MULQ 48(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 200(SP),AX - MULQ 56(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 200(SP),AX - MULQ 64(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 200(SP),AX - MULQ 72(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 208(SP),AX - MULQ 40(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 208(SP),AX - MULQ 48(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 208(SP),AX - MULQ 56(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 208(SP),AX - MULQ 64(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 208(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 216(SP),AX - MULQ 40(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 216(SP),AX - MULQ 48(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 216(SP),AX - MULQ 56(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 216(SP),DX - IMUL3Q $19,DX,AX - MULQ 64(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 216(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 224(SP),AX - MULQ 40(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 224(SP),AX - MULQ 48(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 280(SP),AX - MULQ 64(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 280(SP),AX - MULQ 72(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 232(SP),AX - MULQ 40(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 288(SP),AX - MULQ 56(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 288(SP),AX - MULQ 64(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 288(SP),AX - MULQ 72(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,40(SP) - MOVQ R8,48(SP) - MOVQ R9,56(SP) - MOVQ AX,64(SP) - MOVQ R10,72(SP) - MOVQ 264(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,200(SP) - MULQ 16(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 272(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,208(SP) - MULQ 8(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 240(SP),AX - MULQ 0(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 240(SP),AX - MULQ 8(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 240(SP),AX - MULQ 16(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 240(SP),AX - MULQ 24(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 240(SP),AX - MULQ 32(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 248(SP),AX - MULQ 0(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 248(SP),AX - MULQ 8(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 248(SP),AX - MULQ 16(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 248(SP),AX - MULQ 24(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 248(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 256(SP),AX - MULQ 0(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 256(SP),AX - MULQ 8(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 256(SP),AX - MULQ 16(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 256(SP),DX - IMUL3Q $19,DX,AX - MULQ 24(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 256(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 264(SP),AX - MULQ 0(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 264(SP),AX - MULQ 8(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 200(SP),AX - MULQ 24(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 200(SP),AX - MULQ 32(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 272(SP),AX - MULQ 0(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 208(SP),AX - MULQ 16(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 208(SP),AX - MULQ 24(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 208(SP),AX - MULQ 32(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,DX - MOVQ R8,CX - MOVQ R9,R11 - MOVQ AX,R12 - MOVQ R10,R13 - ADDQ ·_2P0(SB),DX - ADDQ ·_2P1234(SB),CX - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 40(SP),SI - ADDQ 48(SP),R8 - ADDQ 56(SP),R9 - ADDQ 64(SP),AX - ADDQ 72(SP),R10 - SUBQ 40(SP),DX - SUBQ 48(SP),CX - SUBQ 56(SP),R11 - SUBQ 64(SP),R12 - SUBQ 72(SP),R13 - MOVQ SI,120(DI) - MOVQ R8,128(DI) - MOVQ R9,136(DI) - MOVQ AX,144(DI) - MOVQ R10,152(DI) - MOVQ DX,160(DI) - MOVQ CX,168(DI) - MOVQ R11,176(DI) - MOVQ R12,184(DI) - MOVQ R13,192(DI) - MOVQ 120(DI),AX - MULQ 120(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 128(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 136(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 144(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 152(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 128(DI),AX - MULQ 128(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 128(DI),AX - SHLQ $1,AX - MULQ 136(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 128(DI),AX - SHLQ $1,AX - MULQ 144(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 128(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(DI),AX - MULQ 136(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 136(DI),DX - IMUL3Q $38,DX,AX - MULQ 144(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(DI),DX - IMUL3Q $19,DX,AX - MULQ 144(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 152(DI),DX - IMUL3Q $19,DX,AX - MULQ 152(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,120(DI) - MOVQ R8,128(DI) - MOVQ R9,136(DI) - MOVQ AX,144(DI) - MOVQ R10,152(DI) - MOVQ 160(DI),AX - MULQ 160(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 168(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 176(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 184(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 192(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 168(DI),AX - MULQ 168(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 168(DI),AX - SHLQ $1,AX - MULQ 176(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 168(DI),AX - SHLQ $1,AX - MULQ 184(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 168(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),AX - MULQ 176(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 176(DI),DX - IMUL3Q $38,DX,AX - MULQ 184(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),DX - IMUL3Q $19,DX,AX - MULQ 184(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 192(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,160(DI) - MOVQ R8,168(DI) - MOVQ R9,176(DI) - MOVQ AX,184(DI) - MOVQ R10,192(DI) - MOVQ 184(DI),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 16(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 192(DI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 8(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 160(DI),AX - MULQ 0(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 160(DI),AX - MULQ 8(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 160(DI),AX - MULQ 16(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 160(DI),AX - MULQ 24(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 160(DI),AX - MULQ 32(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 168(DI),AX - MULQ 0(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 168(DI),AX - MULQ 8(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 168(DI),AX - MULQ 16(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 168(DI),AX - MULQ 24(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 168(DI),DX - IMUL3Q $19,DX,AX - MULQ 32(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),AX - MULQ 0(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 176(DI),AX - MULQ 8(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 176(DI),AX - MULQ 16(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 176(DI),DX - IMUL3Q $19,DX,AX - MULQ 24(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),DX - IMUL3Q $19,DX,AX - MULQ 32(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),AX - MULQ 0(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 184(DI),AX - MULQ 8(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 24(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 32(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 192(DI),AX - MULQ 0(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 16(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 24(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 32(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,160(DI) - MOVQ R8,168(DI) - MOVQ R9,176(DI) - MOVQ AX,184(DI) - MOVQ R10,192(DI) - MOVQ 144(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 96(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 152(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 88(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 120(SP),AX - MULQ 80(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 120(SP),AX - MULQ 88(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 120(SP),AX - MULQ 96(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 120(SP),AX - MULQ 104(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 120(SP),AX - MULQ 112(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 128(SP),AX - MULQ 80(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 128(SP),AX - MULQ 88(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 128(SP),AX - MULQ 96(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 128(SP),AX - MULQ 104(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 128(SP),DX - IMUL3Q $19,DX,AX - MULQ 112(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(SP),AX - MULQ 80(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 136(SP),AX - MULQ 88(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 136(SP),AX - MULQ 96(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 136(SP),DX - IMUL3Q $19,DX,AX - MULQ 104(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(SP),DX - IMUL3Q $19,DX,AX - MULQ 112(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(SP),AX - MULQ 80(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 144(SP),AX - MULQ 88(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 104(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 112(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 152(SP),AX - MULQ 80(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 96(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 104(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 112(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,40(DI) - MOVQ R8,48(DI) - MOVQ R9,56(DI) - MOVQ AX,64(DI) - MOVQ R10,72(DI) - MOVQ 160(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - MOVQ AX,SI - MOVQ DX,CX - MOVQ 168(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,CX - MOVQ DX,R8 - MOVQ 176(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R8 - MOVQ DX,R9 - MOVQ 184(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R9 - MOVQ DX,R10 - MOVQ 192(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R10 - IMUL3Q $19,DX,DX - ADDQ DX,SI - ADDQ 80(SP),SI - ADDQ 88(SP),CX - ADDQ 96(SP),R8 - ADDQ 104(SP),R9 - ADDQ 112(SP),R10 - MOVQ SI,80(DI) - MOVQ CX,88(DI) - MOVQ R8,96(DI) - MOVQ R9,104(DI) - MOVQ R10,112(DI) - MOVQ 104(DI),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 176(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 112(DI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 168(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 80(DI),AX - MULQ 160(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 80(DI),AX - MULQ 168(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 80(DI),AX - MULQ 176(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 80(DI),AX - MULQ 184(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 80(DI),AX - MULQ 192(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 88(DI),AX - MULQ 160(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 88(DI),AX - MULQ 168(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 88(DI),AX - MULQ 176(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 88(DI),AX - MULQ 184(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 88(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 96(DI),AX - MULQ 160(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 96(DI),AX - MULQ 168(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 96(DI),AX - MULQ 176(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 96(DI),DX - IMUL3Q $19,DX,AX - MULQ 184(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 96(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 104(DI),AX - MULQ 160(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 104(DI),AX - MULQ 168(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 184(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 192(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 112(DI),AX - MULQ 160(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 176(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 184(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 192(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,80(DI) - MOVQ R8,88(DI) - MOVQ R9,96(DI) - MOVQ AX,104(DI) - MOVQ R10,112(DI) - RET diff --git a/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go deleted file mode 100644 index 5822bd53383..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -package curve25519 - -// These functions are implemented in the .s files. The names of the functions -// in the rest of the file are also taken from the SUPERCOP sources to help -// people following along. - -//go:noescape - -func cswap(inout *[5]uint64, v uint64) - -//go:noescape - -func ladderstep(inout *[5][5]uint64) - -//go:noescape - -func freeze(inout *[5]uint64) - -//go:noescape - -func mul(dest, a, b *[5]uint64) - -//go:noescape - -func square(out, in *[5]uint64) - -// mladder uses a Montgomery ladder to calculate (xr/zr) *= s. -func mladder(xr, zr *[5]uint64, s *[32]byte) { - var work [5][5]uint64 - - work[0] = *xr - setint(&work[1], 1) - setint(&work[2], 0) - work[3] = *xr - setint(&work[4], 1) - - j := uint(6) - var prevbit byte - - for i := 31; i >= 0; i-- { - for j < 8 { - bit := ((*s)[i] >> j) & 1 - swap := bit ^ prevbit - prevbit = bit - cswap(&work[1], uint64(swap)) - ladderstep(&work) - j-- - } - j = 7 - } - - *xr = work[1] - *zr = work[2] -} - -func scalarMult(out, in, base *[32]byte) { - var e [32]byte - copy(e[:], (*in)[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var t, z [5]uint64 - unpack(&t, base) - mladder(&t, &z, &e) - invert(&z, &z) - mul(&t, &t, &z) - pack(out, &t) -} - -func setint(r *[5]uint64, v uint64) { - r[0] = v - r[1] = 0 - r[2] = 0 - r[3] = 0 - r[4] = 0 -} - -// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian -// order. -func unpack(r *[5]uint64, x *[32]byte) { - r[0] = uint64(x[0]) | - uint64(x[1])<<8 | - uint64(x[2])<<16 | - uint64(x[3])<<24 | - uint64(x[4])<<32 | - uint64(x[5])<<40 | - uint64(x[6]&7)<<48 - - r[1] = uint64(x[6])>>3 | - uint64(x[7])<<5 | - uint64(x[8])<<13 | - uint64(x[9])<<21 | - uint64(x[10])<<29 | - uint64(x[11])<<37 | - uint64(x[12]&63)<<45 - - r[2] = uint64(x[12])>>6 | - uint64(x[13])<<2 | - uint64(x[14])<<10 | - uint64(x[15])<<18 | - uint64(x[16])<<26 | - uint64(x[17])<<34 | - uint64(x[18])<<42 | - uint64(x[19]&1)<<50 - - r[3] = uint64(x[19])>>1 | - uint64(x[20])<<7 | - uint64(x[21])<<15 | - uint64(x[22])<<23 | - uint64(x[23])<<31 | - uint64(x[24])<<39 | - uint64(x[25]&15)<<47 - - r[4] = uint64(x[25])>>4 | - uint64(x[26])<<4 | - uint64(x[27])<<12 | - uint64(x[28])<<20 | - uint64(x[29])<<28 | - uint64(x[30])<<36 | - uint64(x[31]&127)<<44 -} - -// pack sets out = x where out is the usual, little-endian form of the 5, -// 51-bit limbs in x. -func pack(out *[32]byte, x *[5]uint64) { - t := *x - freeze(&t) - - out[0] = byte(t[0]) - out[1] = byte(t[0] >> 8) - out[2] = byte(t[0] >> 16) - out[3] = byte(t[0] >> 24) - out[4] = byte(t[0] >> 32) - out[5] = byte(t[0] >> 40) - out[6] = byte(t[0] >> 48) - - out[6] ^= byte(t[1]<<3) & 0xf8 - out[7] = byte(t[1] >> 5) - out[8] = byte(t[1] >> 13) - out[9] = byte(t[1] >> 21) - out[10] = byte(t[1] >> 29) - out[11] = byte(t[1] >> 37) - out[12] = byte(t[1] >> 45) - - out[12] ^= byte(t[2]<<6) & 0xc0 - out[13] = byte(t[2] >> 2) - out[14] = byte(t[2] >> 10) - out[15] = byte(t[2] >> 18) - out[16] = byte(t[2] >> 26) - out[17] = byte(t[2] >> 34) - out[18] = byte(t[2] >> 42) - out[19] = byte(t[2] >> 50) - - out[19] ^= byte(t[3]<<1) & 0xfe - out[20] = byte(t[3] >> 7) - out[21] = byte(t[3] >> 15) - out[22] = byte(t[3] >> 23) - out[23] = byte(t[3] >> 31) - out[24] = byte(t[3] >> 39) - out[25] = byte(t[3] >> 47) - - out[25] ^= byte(t[4]<<4) & 0xf0 - out[26] = byte(t[4] >> 4) - out[27] = byte(t[4] >> 12) - out[28] = byte(t[4] >> 20) - out[29] = byte(t[4] >> 28) - out[30] = byte(t[4] >> 36) - out[31] = byte(t[4] >> 44) -} - -// invert calculates r = x^-1 mod p using Fermat's little theorem. -func invert(r *[5]uint64, x *[5]uint64) { - var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 - - square(&z2, x) /* 2 */ - square(&t, &z2) /* 4 */ - square(&t, &t) /* 8 */ - mul(&z9, &t, x) /* 9 */ - mul(&z11, &z9, &z2) /* 11 */ - square(&t, &z11) /* 22 */ - mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ - - square(&t, &z2_5_0) /* 2^6 - 2^1 */ - for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ - square(&t, &t) - } - mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ - - square(&t, &z2_10_0) /* 2^11 - 2^1 */ - for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ - square(&t, &t) - } - mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ - - square(&t, &z2_20_0) /* 2^21 - 2^1 */ - for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ - square(&t, &t) - } - mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ - - square(&t, &t) /* 2^41 - 2^1 */ - for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ - square(&t, &t) - } - mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ - - square(&t, &z2_50_0) /* 2^51 - 2^1 */ - for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ - square(&t, &t) - } - mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ - - square(&t, &z2_100_0) /* 2^101 - 2^1 */ - for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ - square(&t, &t) - } - mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ - - square(&t, &t) /* 2^201 - 2^1 */ - for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ - square(&t, &t) - } - mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ - - square(&t, &t) /* 2^251 - 2^1 */ - square(&t, &t) /* 2^252 - 2^2 */ - square(&t, &t) /* 2^253 - 2^3 */ - - square(&t, &t) /* 2^254 - 2^4 */ - - square(&t, &t) /* 2^255 - 2^5 */ - mul(r, &t, &z11) /* 2^255 - 21 */ -} diff --git a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s deleted file mode 100644 index 1f76d1a3f59..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func mul(dest, a, b *[5]uint64) -TEXT ·mul(SB),0,$16-24 - MOVQ dest+0(FP), DI - MOVQ a+8(FP), SI - MOVQ b+16(FP), DX - - MOVQ DX,CX - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,0(SP) - MULQ 16(CX) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 8(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 0(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 8(CX) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 0(SI),AX - MULQ 16(CX) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 0(SI),AX - MULQ 24(CX) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 0(SI),AX - MULQ 32(CX) - MOVQ AX,BX - MOVQ DX,BP - MOVQ 8(SI),AX - MULQ 0(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SI),AX - MULQ 8(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SI),AX - MULQ 16(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SI),AX - MULQ 24(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),AX - MULQ 0(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 16(SI),AX - MULQ 8(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 16(SI),AX - MULQ 16(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 24(SI),AX - MULQ 0(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 24(SI),AX - MULQ 8(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 0(SP),AX - MULQ 24(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 0(SP),AX - MULQ 32(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 32(SI),AX - MULQ 0(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SP),AX - MULQ 16(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 24(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SP),AX - MULQ 32(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ $REDMASK51,SI - SHLQ $13,R8,R9 - ANDQ SI,R8 - SHLQ $13,R10,R11 - ANDQ SI,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ SI,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ SI,R14 - ADDQ R13,R14 - SHLQ $13,BX,BP - ANDQ SI,BX - ADDQ R15,BX - IMUL3Q $19,BP,DX - ADDQ DX,R8 - MOVQ R8,DX - SHRQ $51,DX - ADDQ R10,DX - MOVQ DX,CX - SHRQ $51,DX - ANDQ SI,R8 - ADDQ R12,DX - MOVQ DX,R9 - SHRQ $51,DX - ANDQ SI,CX - ADDQ R14,DX - MOVQ DX,AX - SHRQ $51,DX - ANDQ SI,R9 - ADDQ BX,DX - MOVQ DX,R10 - SHRQ $51,DX - ANDQ SI,AX - IMUL3Q $19,DX,DX - ADDQ DX,R8 - ANDQ SI,R10 - MOVQ R8,0(DI) - MOVQ CX,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET diff --git a/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s deleted file mode 100644 index 07511a45af2..00000000000 --- a/vendor/golang.org/x/crypto/curve25519/square_amd64.s +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func square(out, in *[5]uint64) -TEXT ·square(SB),7,$0-16 - MOVQ out+0(FP), DI - MOVQ in+8(FP), SI - - MOVQ 0(SI),AX - MULQ 0(SI) - MOVQ AX,CX - MOVQ DX,R8 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 8(SI) - MOVQ AX,R9 - MOVQ DX,R10 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 16(SI) - MOVQ AX,R11 - MOVQ DX,R12 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 24(SI) - MOVQ AX,R13 - MOVQ DX,R14 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 32(SI) - MOVQ AX,R15 - MOVQ DX,BX - MOVQ 8(SI),AX - MULQ 8(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 16(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 24(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 8(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),AX - MULQ 16(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 24(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ $REDMASK51,SI - SHLQ $13,CX,R8 - ANDQ SI,CX - SHLQ $13,R9,R10 - ANDQ SI,R9 - ADDQ R8,R9 - SHLQ $13,R11,R12 - ANDQ SI,R11 - ADDQ R10,R11 - SHLQ $13,R13,R14 - ANDQ SI,R13 - ADDQ R12,R13 - SHLQ $13,R15,BX - ANDQ SI,R15 - ADDQ R14,R15 - IMUL3Q $19,BX,DX - ADDQ DX,CX - MOVQ CX,DX - SHRQ $51,DX - ADDQ R9,DX - ANDQ SI,CX - MOVQ DX,R8 - SHRQ $51,DX - ADDQ R11,DX - ANDQ SI,R8 - MOVQ DX,R9 - SHRQ $51,DX - ADDQ R13,DX - ANDQ SI,R9 - MOVQ DX,AX - SHRQ $51,DX - ADDQ R15,DX - ANDQ SI,AX - MOVQ DX,R10 - SHRQ $51,DX - IMUL3Q $19,DX,DX - ADDQ DX,CX - ANDQ SI,R10 - MOVQ CX,0(DI) - MOVQ R8,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go deleted file mode 100644 index f38797bfa1b..00000000000 --- a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !appengine - -// Package subtle implements functions that are often useful in cryptographic -// code but require careful thought to use correctly. -package subtle // import "golang.org/x/crypto/internal/subtle" - -import "unsafe" - -// AnyOverlap reports whether x and y share memory at any (not necessarily -// corresponding) index. The memory beyond the slice length is ignored. -func AnyOverlap(x, y []byte) bool { - return len(x) > 0 && len(y) > 0 && - uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && - uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) -} - -// InexactOverlap reports whether x and y share memory at any non-corresponding -// index. The memory beyond the slice length is ignored. Note that x and y can -// have different lengths and still not have any inexact overlap. -// -// InexactOverlap can be used to implement the requirements of the crypto/cipher -// AEAD, Block, BlockMode and Stream interfaces. -func InexactOverlap(x, y []byte) bool { - if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { - return false - } - return AnyOverlap(x, y) -} diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go deleted file mode 100644 index 0cc4a8a642c..00000000000 --- a/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build appengine - -// Package subtle implements functions that are often useful in cryptographic -// code but require careful thought to use correctly. -package subtle // import "golang.org/x/crypto/internal/subtle" - -// This is the Google App Engine standard variant based on reflect -// because the unsafe package and cgo are disallowed. - -import "reflect" - -// AnyOverlap reports whether x and y share memory at any (not necessarily -// corresponding) index. The memory beyond the slice length is ignored. -func AnyOverlap(x, y []byte) bool { - return len(x) > 0 && len(y) > 0 && - reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && - reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() -} - -// InexactOverlap reports whether x and y share memory at any non-corresponding -// index. The memory beyond the slice length is ignored. Note that x and y can -// have different lengths and still not have any inexact overlap. -// -// InexactOverlap can be used to implement the requirements of the crypto/cipher -// AEAD, Block, BlockMode and Stream interfaces. -func InexactOverlap(x, y []byte) bool { - if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { - return false - } - return AnyOverlap(x, y) -} diff --git a/vendor/golang.org/x/crypto/nacl/box/box.go b/vendor/golang.org/x/crypto/nacl/box/box.go deleted file mode 100644 index 31b697be441..00000000000 --- a/vendor/golang.org/x/crypto/nacl/box/box.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package box authenticates and encrypts small messages using public-key cryptography. - -Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate -messages. The length of messages is not hidden. - -It is the caller's responsibility to ensure the uniqueness of nonces—for -example, by using nonce 1 for the first message, nonce 2 for the second -message, etc. Nonces are long enough that randomly generated nonces have -negligible risk of collision. - -Messages should be small because: - -1. The whole message needs to be held in memory to be processed. - -2. Using large messages pressures implementations on small machines to decrypt -and process plaintext before authenticating it. This is very dangerous, and -this API does not allow it, but a protocol that uses excessive message sizes -might present some implementations with no other choice. - -3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. - -4. Performance may be improved by working with messages that fit into data caches. - -Thus large amounts of data should be chunked so that each message is small. -(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable -chunk size. - -This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html. -*/ -package box // import "golang.org/x/crypto/nacl/box" - -import ( - "io" - - "golang.org/x/crypto/curve25519" - "golang.org/x/crypto/nacl/secretbox" - "golang.org/x/crypto/salsa20/salsa" -) - -// Overhead is the number of bytes of overhead when boxing a message. -const Overhead = secretbox.Overhead - -// GenerateKey generates a new public/private key pair suitable for use with -// Seal and Open. -func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { - publicKey = new([32]byte) - privateKey = new([32]byte) - _, err = io.ReadFull(rand, privateKey[:]) - if err != nil { - publicKey = nil - privateKey = nil - return - } - - curve25519.ScalarBaseMult(publicKey, privateKey) - return -} - -var zeros [16]byte - -// Precompute calculates the shared key between peersPublicKey and privateKey -// and writes it to sharedKey. The shared key can be used with -// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing -// when using the same pair of keys repeatedly. -func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { - curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) - salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) -} - -// Seal appends an encrypted and authenticated copy of message to out, which -// will be Overhead bytes longer than the original and must not overlap it. The -// nonce must be unique for each distinct message for a given pair of keys. -func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { - var sharedKey [32]byte - Precompute(&sharedKey, peersPublicKey, privateKey) - return secretbox.Seal(out, message, nonce, &sharedKey) -} - -// SealAfterPrecomputation performs the same actions as Seal, but takes a -// shared key as generated by Precompute. -func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { - return secretbox.Seal(out, message, nonce, sharedKey) -} - -// Open authenticates and decrypts a box produced by Seal and appends the -// message to out, which must not overlap box. The output will be Overhead -// bytes smaller than box. -func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { - var sharedKey [32]byte - Precompute(&sharedKey, peersPublicKey, privateKey) - return secretbox.Open(out, box, nonce, &sharedKey) -} - -// OpenAfterPrecomputation performs the same actions as Open, but takes a -// shared key as generated by Precompute. -func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { - return secretbox.Open(out, box, nonce, sharedKey) -} diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go deleted file mode 100644 index a98d1bd45cd..00000000000 --- a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package secretbox encrypts and authenticates small messages. - -Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with -secret-key cryptography. The length of messages is not hidden. - -It is the caller's responsibility to ensure the uniqueness of nonces—for -example, by using nonce 1 for the first message, nonce 2 for the second -message, etc. Nonces are long enough that randomly generated nonces have -negligible risk of collision. - -Messages should be small because: - -1. The whole message needs to be held in memory to be processed. - -2. Using large messages pressures implementations on small machines to decrypt -and process plaintext before authenticating it. This is very dangerous, and -this API does not allow it, but a protocol that uses excessive message sizes -might present some implementations with no other choice. - -3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. - -4. Performance may be improved by working with messages that fit into data caches. - -Thus large amounts of data should be chunked so that each message is small. -(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable -chunk size. - -This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. -*/ -package secretbox // import "golang.org/x/crypto/nacl/secretbox" - -import ( - "golang.org/x/crypto/internal/subtle" - "golang.org/x/crypto/poly1305" - "golang.org/x/crypto/salsa20/salsa" -) - -// Overhead is the number of bytes of overhead when boxing a message. -const Overhead = poly1305.TagSize - -// setup produces a sub-key and Salsa20 counter given a nonce and key. -func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { - // We use XSalsa20 for encryption so first we need to generate a - // key and nonce with HSalsa20. - var hNonce [16]byte - copy(hNonce[:], nonce[:]) - salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) - - // The final 8 bytes of the original nonce form the new nonce. - copy(counter[:], nonce[16:]) -} - -// sliceForAppend takes a slice and a requested number of bytes. It returns a -// slice with the contents of the given slice followed by that many bytes and a -// second slice that aliases into it and contains only the extra bytes. If the -// original slice has sufficient capacity then no allocation is performed. -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -// Seal appends an encrypted and authenticated copy of message to out, which -// must not overlap message. The key and nonce pair must be unique for each -// distinct message and the output will be Overhead bytes longer than message. -func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { - var subKey [32]byte - var counter [16]byte - setup(&subKey, &counter, nonce, key) - - // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since - // Salsa20 works with 64-byte blocks, we also generate 32 bytes of - // keystream as a side effect. - var firstBlock [64]byte - salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) - - var poly1305Key [32]byte - copy(poly1305Key[:], firstBlock[:]) - - ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) - if subtle.AnyOverlap(out, message) { - panic("nacl: invalid buffer overlap") - } - - // We XOR up to 32 bytes of message with the keystream generated from - // the first block. - firstMessageBlock := message - if len(firstMessageBlock) > 32 { - firstMessageBlock = firstMessageBlock[:32] - } - - tagOut := out - out = out[poly1305.TagSize:] - for i, x := range firstMessageBlock { - out[i] = firstBlock[32+i] ^ x - } - message = message[len(firstMessageBlock):] - ciphertext := out - out = out[len(firstMessageBlock):] - - // Now encrypt the rest. - counter[8] = 1 - salsa.XORKeyStream(out, message, &counter, &subKey) - - var tag [poly1305.TagSize]byte - poly1305.Sum(&tag, ciphertext, &poly1305Key) - copy(tagOut, tag[:]) - - return ret -} - -// Open authenticates and decrypts a box produced by Seal and appends the -// message to out, which must not overlap box. The output will be Overhead -// bytes smaller than box. -func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { - if len(box) < Overhead { - return nil, false - } - - var subKey [32]byte - var counter [16]byte - setup(&subKey, &counter, nonce, key) - - // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since - // Salsa20 works with 64-byte blocks, we also generate 32 bytes of - // keystream as a side effect. - var firstBlock [64]byte - salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) - - var poly1305Key [32]byte - copy(poly1305Key[:], firstBlock[:]) - var tag [poly1305.TagSize]byte - copy(tag[:], box) - - if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { - return nil, false - } - - ret, out := sliceForAppend(out, len(box)-Overhead) - if subtle.AnyOverlap(out, box) { - panic("nacl: invalid buffer overlap") - } - - // We XOR up to 32 bytes of box with the keystream generated from - // the first block. - box = box[Overhead:] - firstMessageBlock := box - if len(firstMessageBlock) > 32 { - firstMessageBlock = firstMessageBlock[:32] - } - for i, x := range firstMessageBlock { - out[i] = firstBlock[32+i] ^ x - } - - box = box[len(firstMessageBlock):] - out = out[len(firstMessageBlock):] - - // Now decrypt the rest. - counter[8] = 1 - salsa.XORKeyStream(out, box, &counter, &subKey) - - return ret, true -} diff --git a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/poly1305/mac_noasm.go deleted file mode 100644 index 8387d29998f..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !amd64 gccgo appengine - -package poly1305 - -type mac struct{ macGeneric } - -func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} } diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/poly1305/poly1305.go deleted file mode 100644 index d076a562351..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/poly1305.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package poly1305 implements Poly1305 one-time message authentication code as -// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. -// -// Poly1305 is a fast, one-time authentication function. It is infeasible for an -// attacker to generate an authenticator for a message without the key. However, a -// key must only be used for a single message. Authenticating two different -// messages with the same key allows an attacker to forge authenticators for other -// messages with the same key. -// -// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was -// used with a fixed key in order to generate one-time keys from an nonce. -// However, in this package AES isn't used and the one-time key is specified -// directly. -package poly1305 // import "golang.org/x/crypto/poly1305" - -import "crypto/subtle" - -// TagSize is the size, in bytes, of a poly1305 authenticator. -const TagSize = 16 - -// Verify returns true if mac is a valid authenticator for m with the given -// key. -func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { - var tmp [16]byte - Sum(&tmp, m, key) - return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 -} - -// New returns a new MAC computing an authentication -// tag of all data written to it with the given key. -// This allows writing the message progressively instead -// of passing it as a single slice. Common users should use -// the Sum function instead. -// -// The key must be unique for each message, as authenticating -// two different messages with the same key allows an attacker -// to forge messages at will. -func New(key *[32]byte) *MAC { - return &MAC{ - mac: newMAC(key), - finalized: false, - } -} - -// MAC is an io.Writer computing an authentication tag -// of the data written to it. -// -// MAC cannot be used like common hash.Hash implementations, -// because using a poly1305 key twice breaks its security. -// Therefore writing data to a running MAC after calling -// Sum causes it to panic. -type MAC struct { - mac // platform-dependent implementation - - finalized bool -} - -// Size returns the number of bytes Sum will return. -func (h *MAC) Size() int { return TagSize } - -// Write adds more data to the running message authentication code. -// It never returns an error. -// -// It must not be called after the first call of Sum. -func (h *MAC) Write(p []byte) (n int, err error) { - if h.finalized { - panic("poly1305: write to MAC after Sum") - } - return h.mac.Write(p) -} - -// Sum computes the authenticator of all data written to the -// message authentication code. -func (h *MAC) Sum(b []byte) []byte { - var mac [TagSize]byte - h.mac.Sum(&mac) - h.finalized = true - return append(b, mac[:]...) -} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go deleted file mode 100644 index 2dbf42aa537..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -package poly1305 - -//go:noescape -func initialize(state *[7]uint64, key *[32]byte) - -//go:noescape -func update(state *[7]uint64, msg []byte) - -//go:noescape -func finalize(tag *[TagSize]byte, state *[7]uint64) - -// Sum generates an authenticator for m using a one-time key and puts the -// 16-byte result into out. Authenticating two different messages with the same -// key allows an attacker to forge messages at will. -func Sum(out *[16]byte, m []byte, key *[32]byte) { - h := newMAC(key) - h.Write(m) - h.Sum(out) -} - -func newMAC(key *[32]byte) (h mac) { - initialize(&h.state, key) - return -} - -type mac struct { - state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 } - - buffer [TagSize]byte - offset int -} - -func (h *mac) Write(p []byte) (n int, err error) { - n = len(p) - if h.offset > 0 { - remaining := TagSize - h.offset - if n < remaining { - h.offset += copy(h.buffer[h.offset:], p) - return n, nil - } - copy(h.buffer[h.offset:], p[:remaining]) - p = p[remaining:] - h.offset = 0 - update(&h.state, h.buffer[:]) - } - if nn := len(p) - (len(p) % TagSize); nn > 0 { - update(&h.state, p[:nn]) - p = p[nn:] - } - if len(p) > 0 { - h.offset += copy(h.buffer[h.offset:], p) - } - return n, nil -} - -func (h *mac) Sum(out *[16]byte) { - state := h.state - if h.offset > 0 { - update(&state, h.buffer[:h.offset]) - } - finalize(out, &state) -} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/poly1305/sum_amd64.s deleted file mode 100644 index 7d600f13cc8..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -#include "textflag.h" - -#define POLY1305_ADD(msg, h0, h1, h2) \ - ADDQ 0(msg), h0; \ - ADCQ 8(msg), h1; \ - ADCQ $1, h2; \ - LEAQ 16(msg), msg - -#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ - MOVQ r0, AX; \ - MULQ h0; \ - MOVQ AX, t0; \ - MOVQ DX, t1; \ - MOVQ r0, AX; \ - MULQ h1; \ - ADDQ AX, t1; \ - ADCQ $0, DX; \ - MOVQ r0, t2; \ - IMULQ h2, t2; \ - ADDQ DX, t2; \ - \ - MOVQ r1, AX; \ - MULQ h0; \ - ADDQ AX, t1; \ - ADCQ $0, DX; \ - MOVQ DX, h0; \ - MOVQ r1, t3; \ - IMULQ h2, t3; \ - MOVQ r1, AX; \ - MULQ h1; \ - ADDQ AX, t2; \ - ADCQ DX, t3; \ - ADDQ h0, t2; \ - ADCQ $0, t3; \ - \ - MOVQ t0, h0; \ - MOVQ t1, h1; \ - MOVQ t2, h2; \ - ANDQ $3, h2; \ - MOVQ t2, t0; \ - ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ - ADDQ t0, h0; \ - ADCQ t3, h1; \ - ADCQ $0, h2; \ - SHRQ $2, t3, t2; \ - SHRQ $2, t3; \ - ADDQ t2, h0; \ - ADCQ t3, h1; \ - ADCQ $0, h2 - -DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -GLOBL ·poly1305Mask<>(SB), RODATA, $16 - -// func update(state *[7]uint64, msg []byte) -TEXT ·update(SB), $0-32 - MOVQ state+0(FP), DI - MOVQ msg_base+8(FP), SI - MOVQ msg_len+16(FP), R15 - - MOVQ 0(DI), R8 // h0 - MOVQ 8(DI), R9 // h1 - MOVQ 16(DI), R10 // h2 - MOVQ 24(DI), R11 // r0 - MOVQ 32(DI), R12 // r1 - - CMPQ R15, $16 - JB bytes_between_0_and_15 - -loop: - POLY1305_ADD(SI, R8, R9, R10) - -multiply: - POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) - SUBQ $16, R15 - CMPQ R15, $16 - JAE loop - -bytes_between_0_and_15: - TESTQ R15, R15 - JZ done - MOVQ $1, BX - XORQ CX, CX - XORQ R13, R13 - ADDQ R15, SI - -flush_buffer: - SHLQ $8, BX, CX - SHLQ $8, BX - MOVB -1(SI), R13 - XORQ R13, BX - DECQ SI - DECQ R15 - JNZ flush_buffer - - ADDQ BX, R8 - ADCQ CX, R9 - ADCQ $0, R10 - MOVQ $16, R15 - JMP multiply - -done: - MOVQ R8, 0(DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - RET - -// func initialize(state *[7]uint64, key *[32]byte) -TEXT ·initialize(SB), $0-16 - MOVQ state+0(FP), DI - MOVQ key+8(FP), SI - - // state[0...7] is initialized with zero - MOVOU 0(SI), X0 - MOVOU 16(SI), X1 - MOVOU ·poly1305Mask<>(SB), X2 - PAND X2, X0 - MOVOU X0, 24(DI) - MOVOU X1, 40(DI) - RET - -// func finalize(tag *[TagSize]byte, state *[7]uint64) -TEXT ·finalize(SB), $0-16 - MOVQ tag+0(FP), DI - MOVQ state+8(FP), SI - - MOVQ 0(SI), AX - MOVQ 8(SI), BX - MOVQ 16(SI), CX - MOVQ AX, R8 - MOVQ BX, R9 - SUBQ $0xFFFFFFFFFFFFFFFB, AX - SBBQ $0xFFFFFFFFFFFFFFFF, BX - SBBQ $3, CX - CMOVQCS R8, AX - CMOVQCS R9, BX - ADDQ 40(SI), AX - ADCQ 48(SI), BX - - MOVQ AX, 0(DI) - MOVQ BX, 8(DI) - RET diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.go b/vendor/golang.org/x/crypto/poly1305/sum_arm.go deleted file mode 100644 index 5dc321c2f39..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_arm.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build arm,!gccgo,!appengine,!nacl - -package poly1305 - -// This function is implemented in sum_arm.s -//go:noescape -func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte) - -// Sum generates an authenticator for m using a one-time key and puts the -// 16-byte result into out. Authenticating two different messages with the same -// key allows an attacker to forge messages at will. -func Sum(out *[16]byte, m []byte, key *[32]byte) { - var mPtr *byte - if len(m) > 0 { - mPtr = &m[0] - } - poly1305_auth_armv6(out, mPtr, uint32(len(m)), key) -} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.s b/vendor/golang.org/x/crypto/poly1305/sum_arm.s deleted file mode 100644 index f70b4ac4845..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_arm.s +++ /dev/null @@ -1,427 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build arm,!gccgo,!appengine,!nacl - -#include "textflag.h" - -// This code was translated into a form compatible with 5a from the public -// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. - -DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff -DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 -DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff -DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff -DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff -GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20 - -// Warning: the linker may use R11 to synthesize certain instructions. Please -// take care and verify that no synthetic instructions use it. - -TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0 - // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It - // might look like it's only 60 bytes of space but the final four bytes - // will be written by another function.) We need to skip over four - // bytes of stack because that's saving the value of 'g'. - ADD $4, R13, R8 - MOVM.IB [R4-R7], (R8) - MOVM.IA.W (R1), [R2-R5] - MOVW $·poly1305_init_constants_armv6<>(SB), R7 - MOVW R2, R8 - MOVW R2>>26, R9 - MOVW R3>>20, g - MOVW R4>>14, R11 - MOVW R5>>8, R12 - ORR R3<<6, R9, R9 - ORR R4<<12, g, g - ORR R5<<18, R11, R11 - MOVM.IA (R7), [R2-R6] - AND R8, R2, R2 - AND R9, R3, R3 - AND g, R4, R4 - AND R11, R5, R5 - AND R12, R6, R6 - MOVM.IA.W [R2-R6], (R0) - EOR R2, R2, R2 - EOR R3, R3, R3 - EOR R4, R4, R4 - EOR R5, R5, R5 - EOR R6, R6, R6 - MOVM.IA.W [R2-R6], (R0) - MOVM.IA.W (R1), [R2-R5] - MOVM.IA [R2-R6], (R0) - ADD $20, R13, R0 - MOVM.DA (R0), [R4-R7] - RET - -#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \ - MOVBU (offset+0)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+0)(Rdst); \ - MOVBU (offset+1)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+1)(Rdst); \ - MOVBU (offset+2)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+2)(Rdst); \ - MOVBU (offset+3)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+3)(Rdst) - -TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0 - // Needs 24 bytes of stack for saved registers and then 88 bytes of - // scratch space after that. We assume that 24 bytes at (R13) have - // already been used: four bytes for the link register saved in the - // prelude of poly1305_auth_armv6, four bytes for saving the value of g - // in that function and 16 bytes of scratch space used around - // poly1305_finish_ext_armv6_skip1. - ADD $24, R13, R12 - MOVM.IB [R4-R8, R14], (R12) - MOVW R0, 88(R13) - MOVW R1, 92(R13) - MOVW R2, 96(R13) - MOVW R1, R14 - MOVW R2, R12 - MOVW 56(R0), R8 - WORD $0xe1180008 // TST R8, R8 not working see issue 5921 - EOR R6, R6, R6 - MOVW.EQ $(1<<24), R6 - MOVW R6, 84(R13) - ADD $116, R13, g - MOVM.IA (R0), [R0-R9] - MOVM.IA [R0-R4], (g) - CMP $16, R12 - BLO poly1305_blocks_armv6_done - -poly1305_blocks_armv6_mainloop: - WORD $0xe31e0003 // TST R14, #3 not working see issue 5921 - BEQ poly1305_blocks_armv6_mainloop_aligned - ADD $100, R13, g - MOVW_UNALIGNED(R14, g, R0, 0) - MOVW_UNALIGNED(R14, g, R0, 4) - MOVW_UNALIGNED(R14, g, R0, 8) - MOVW_UNALIGNED(R14, g, R0, 12) - MOVM.IA (g), [R0-R3] - ADD $16, R14 - B poly1305_blocks_armv6_mainloop_loaded - -poly1305_blocks_armv6_mainloop_aligned: - MOVM.IA.W (R14), [R0-R3] - -poly1305_blocks_armv6_mainloop_loaded: - MOVW R0>>26, g - MOVW R1>>20, R11 - MOVW R2>>14, R12 - MOVW R14, 92(R13) - MOVW R3>>8, R4 - ORR R1<<6, g, g - ORR R2<<12, R11, R11 - ORR R3<<18, R12, R12 - BIC $0xfc000000, R0, R0 - BIC $0xfc000000, g, g - MOVW 84(R13), R3 - BIC $0xfc000000, R11, R11 - BIC $0xfc000000, R12, R12 - ADD R0, R5, R5 - ADD g, R6, R6 - ORR R3, R4, R4 - ADD R11, R7, R7 - ADD $116, R13, R14 - ADD R12, R8, R8 - ADD R4, R9, R9 - MOVM.IA (R14), [R0-R4] - MULLU R4, R5, (R11, g) - MULLU R3, R5, (R14, R12) - MULALU R3, R6, (R11, g) - MULALU R2, R6, (R14, R12) - MULALU R2, R7, (R11, g) - MULALU R1, R7, (R14, R12) - ADD R4<<2, R4, R4 - ADD R3<<2, R3, R3 - MULALU R1, R8, (R11, g) - MULALU R0, R8, (R14, R12) - MULALU R0, R9, (R11, g) - MULALU R4, R9, (R14, R12) - MOVW g, 76(R13) - MOVW R11, 80(R13) - MOVW R12, 68(R13) - MOVW R14, 72(R13) - MULLU R2, R5, (R11, g) - MULLU R1, R5, (R14, R12) - MULALU R1, R6, (R11, g) - MULALU R0, R6, (R14, R12) - MULALU R0, R7, (R11, g) - MULALU R4, R7, (R14, R12) - ADD R2<<2, R2, R2 - ADD R1<<2, R1, R1 - MULALU R4, R8, (R11, g) - MULALU R3, R8, (R14, R12) - MULALU R3, R9, (R11, g) - MULALU R2, R9, (R14, R12) - MOVW g, 60(R13) - MOVW R11, 64(R13) - MOVW R12, 52(R13) - MOVW R14, 56(R13) - MULLU R0, R5, (R11, g) - MULALU R4, R6, (R11, g) - MULALU R3, R7, (R11, g) - MULALU R2, R8, (R11, g) - MULALU R1, R9, (R11, g) - ADD $52, R13, R0 - MOVM.IA (R0), [R0-R7] - MOVW g>>26, R12 - MOVW R4>>26, R14 - ORR R11<<6, R12, R12 - ORR R5<<6, R14, R14 - BIC $0xfc000000, g, g - BIC $0xfc000000, R4, R4 - ADD.S R12, R0, R0 - ADC $0, R1, R1 - ADD.S R14, R6, R6 - ADC $0, R7, R7 - MOVW R0>>26, R12 - MOVW R6>>26, R14 - ORR R1<<6, R12, R12 - ORR R7<<6, R14, R14 - BIC $0xfc000000, R0, R0 - BIC $0xfc000000, R6, R6 - ADD R14<<2, R14, R14 - ADD.S R12, R2, R2 - ADC $0, R3, R3 - ADD R14, g, g - MOVW R2>>26, R12 - MOVW g>>26, R14 - ORR R3<<6, R12, R12 - BIC $0xfc000000, g, R5 - BIC $0xfc000000, R2, R7 - ADD R12, R4, R4 - ADD R14, R0, R0 - MOVW R4>>26, R12 - BIC $0xfc000000, R4, R8 - ADD R12, R6, R9 - MOVW 96(R13), R12 - MOVW 92(R13), R14 - MOVW R0, R6 - CMP $32, R12 - SUB $16, R12, R12 - MOVW R12, 96(R13) - BHS poly1305_blocks_armv6_mainloop - -poly1305_blocks_armv6_done: - MOVW 88(R13), R12 - MOVW R5, 20(R12) - MOVW R6, 24(R12) - MOVW R7, 28(R12) - MOVW R8, 32(R12) - MOVW R9, 36(R12) - ADD $48, R13, R0 - MOVM.DA (R0), [R4-R8, R14] - RET - -#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \ - MOVBU.P 1(Rsrc), Rtmp; \ - MOVBU.P Rtmp, 1(Rdst); \ - MOVBU.P 1(Rsrc), Rtmp; \ - MOVBU.P Rtmp, 1(Rdst) - -#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \ - MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \ - MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) - -// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key) -TEXT ·poly1305_auth_armv6(SB), $196-16 - // The value 196, just above, is the sum of 64 (the size of the context - // structure) and 132 (the amount of stack needed). - // - // At this point, the stack pointer (R13) has been moved down. It - // points to the saved link register and there's 196 bytes of free - // space above it. - // - // The stack for this function looks like: - // - // +--------------------- - // | - // | 64 bytes of context structure - // | - // +--------------------- - // | - // | 112 bytes for poly1305_blocks_armv6 - // | - // +--------------------- - // | 16 bytes of final block, constructed at - // | poly1305_finish_ext_armv6_skip8 - // +--------------------- - // | four bytes of saved 'g' - // +--------------------- - // | lr, saved by prelude <- R13 points here - // +--------------------- - MOVW g, 4(R13) - - MOVW out+0(FP), R4 - MOVW m+4(FP), R5 - MOVW mlen+8(FP), R6 - MOVW key+12(FP), R7 - - ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112 - MOVW R7, R1 - - // poly1305_init_ext_armv6 will write to the stack from R13+4, but - // that's ok because none of the other values have been written yet. - BL poly1305_init_ext_armv6<>(SB) - BIC.S $15, R6, R2 - BEQ poly1305_auth_armv6_noblocks - ADD $136, R13, R0 - MOVW R5, R1 - ADD R2, R5, R5 - SUB R2, R6, R6 - BL poly1305_blocks_armv6<>(SB) - -poly1305_auth_armv6_noblocks: - ADD $136, R13, R0 - MOVW R5, R1 - MOVW R6, R2 - MOVW R4, R3 - - MOVW R0, R5 - MOVW R1, R6 - MOVW R2, R7 - MOVW R3, R8 - AND.S R2, R2, R2 - BEQ poly1305_finish_ext_armv6_noremaining - EOR R0, R0 - ADD $8, R13, R9 // 8 = offset to 16 byte scratch space - MOVW R0, (R9) - MOVW R0, 4(R9) - MOVW R0, 8(R9) - MOVW R0, 12(R9) - WORD $0xe3110003 // TST R1, #3 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_aligned - WORD $0xe3120008 // TST R2, #8 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip8 - MOVWP_UNALIGNED(R1, R9, g) - MOVWP_UNALIGNED(R1, R9, g) - -poly1305_finish_ext_armv6_skip8: - WORD $0xe3120004 // TST $4, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip4 - MOVWP_UNALIGNED(R1, R9, g) - -poly1305_finish_ext_armv6_skip4: - WORD $0xe3120002 // TST $2, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip2 - MOVHUP_UNALIGNED(R1, R9, g) - B poly1305_finish_ext_armv6_skip2 - -poly1305_finish_ext_armv6_aligned: - WORD $0xe3120008 // TST R2, #8 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip8_aligned - MOVM.IA.W (R1), [g-R11] - MOVM.IA.W [g-R11], (R9) - -poly1305_finish_ext_armv6_skip8_aligned: - WORD $0xe3120004 // TST $4, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip4_aligned - MOVW.P 4(R1), g - MOVW.P g, 4(R9) - -poly1305_finish_ext_armv6_skip4_aligned: - WORD $0xe3120002 // TST $2, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip2 - MOVHU.P 2(R1), g - MOVH.P g, 2(R9) - -poly1305_finish_ext_armv6_skip2: - WORD $0xe3120001 // TST $1, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip1 - MOVBU.P 1(R1), g - MOVBU.P g, 1(R9) - -poly1305_finish_ext_armv6_skip1: - MOVW $1, R11 - MOVBU R11, 0(R9) - MOVW R11, 56(R5) - MOVW R5, R0 - ADD $8, R13, R1 - MOVW $16, R2 - BL poly1305_blocks_armv6<>(SB) - -poly1305_finish_ext_armv6_noremaining: - MOVW 20(R5), R0 - MOVW 24(R5), R1 - MOVW 28(R5), R2 - MOVW 32(R5), R3 - MOVW 36(R5), R4 - MOVW R4>>26, R12 - BIC $0xfc000000, R4, R4 - ADD R12<<2, R12, R12 - ADD R12, R0, R0 - MOVW R0>>26, R12 - BIC $0xfc000000, R0, R0 - ADD R12, R1, R1 - MOVW R1>>26, R12 - BIC $0xfc000000, R1, R1 - ADD R12, R2, R2 - MOVW R2>>26, R12 - BIC $0xfc000000, R2, R2 - ADD R12, R3, R3 - MOVW R3>>26, R12 - BIC $0xfc000000, R3, R3 - ADD R12, R4, R4 - ADD $5, R0, R6 - MOVW R6>>26, R12 - BIC $0xfc000000, R6, R6 - ADD R12, R1, R7 - MOVW R7>>26, R12 - BIC $0xfc000000, R7, R7 - ADD R12, R2, g - MOVW g>>26, R12 - BIC $0xfc000000, g, g - ADD R12, R3, R11 - MOVW $-(1<<26), R12 - ADD R11>>26, R12, R12 - BIC $0xfc000000, R11, R11 - ADD R12, R4, R9 - MOVW R9>>31, R12 - SUB $1, R12 - AND R12, R6, R6 - AND R12, R7, R7 - AND R12, g, g - AND R12, R11, R11 - AND R12, R9, R9 - MVN R12, R12 - AND R12, R0, R0 - AND R12, R1, R1 - AND R12, R2, R2 - AND R12, R3, R3 - AND R12, R4, R4 - ORR R6, R0, R0 - ORR R7, R1, R1 - ORR g, R2, R2 - ORR R11, R3, R3 - ORR R9, R4, R4 - ORR R1<<26, R0, R0 - MOVW R1>>6, R1 - ORR R2<<20, R1, R1 - MOVW R2>>12, R2 - ORR R3<<14, R2, R2 - MOVW R3>>18, R3 - ORR R4<<8, R3, R3 - MOVW 40(R5), R6 - MOVW 44(R5), R7 - MOVW 48(R5), g - MOVW 52(R5), R11 - ADD.S R6, R0, R0 - ADC.S R7, R1, R1 - ADC.S g, R2, R2 - ADC.S R11, R3, R3 - MOVM.IA [R0-R3], (R8) - MOVW R5, R12 - EOR R0, R0, R0 - EOR R1, R1, R1 - EOR R2, R2, R2 - EOR R3, R3, R3 - EOR R4, R4, R4 - EOR R5, R5, R5 - EOR R6, R6, R6 - EOR R7, R7, R7 - MOVM.IA.W [R0-R7], (R12) - MOVM.IA [R0-R7], (R12) - MOVW 4(R13), g - RET diff --git a/vendor/golang.org/x/crypto/poly1305/sum_generic.go b/vendor/golang.org/x/crypto/poly1305/sum_generic.go deleted file mode 100644 index bab76ef0d83..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_generic.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package poly1305 - -import "encoding/binary" - -const ( - msgBlock = uint32(1 << 24) - finalBlock = uint32(0) -) - -// sumGeneric generates an authenticator for msg using a one-time key and -// puts the 16-byte result into out. This is the generic implementation of -// Sum and should be called if no assembly implementation is available. -func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { - h := newMACGeneric(key) - h.Write(msg) - h.Sum(out) -} - -func newMACGeneric(key *[32]byte) (h macGeneric) { - h.r[0] = binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff - h.r[1] = (binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03 - h.r[2] = (binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff - h.r[3] = (binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff - h.r[4] = (binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff - - h.s[0] = binary.LittleEndian.Uint32(key[16:]) - h.s[1] = binary.LittleEndian.Uint32(key[20:]) - h.s[2] = binary.LittleEndian.Uint32(key[24:]) - h.s[3] = binary.LittleEndian.Uint32(key[28:]) - return -} - -type macGeneric struct { - h, r [5]uint32 - s [4]uint32 - - buffer [TagSize]byte - offset int -} - -func (h *macGeneric) Write(p []byte) (n int, err error) { - n = len(p) - if h.offset > 0 { - remaining := TagSize - h.offset - if n < remaining { - h.offset += copy(h.buffer[h.offset:], p) - return n, nil - } - copy(h.buffer[h.offset:], p[:remaining]) - p = p[remaining:] - h.offset = 0 - updateGeneric(h.buffer[:], msgBlock, &(h.h), &(h.r)) - } - if nn := len(p) - (len(p) % TagSize); nn > 0 { - updateGeneric(p, msgBlock, &(h.h), &(h.r)) - p = p[nn:] - } - if len(p) > 0 { - h.offset += copy(h.buffer[h.offset:], p) - } - return n, nil -} - -func (h *macGeneric) Sum(out *[16]byte) { - H, R := h.h, h.r - if h.offset > 0 { - var buffer [TagSize]byte - copy(buffer[:], h.buffer[:h.offset]) - buffer[h.offset] = 1 // invariant: h.offset < TagSize - updateGeneric(buffer[:], finalBlock, &H, &R) - } - finalizeGeneric(out, &H, &(h.s)) -} - -func updateGeneric(msg []byte, flag uint32, h, r *[5]uint32) { - h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4] - r0, r1, r2, r3, r4 := uint64(r[0]), uint64(r[1]), uint64(r[2]), uint64(r[3]), uint64(r[4]) - R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5 - - for len(msg) >= TagSize { - // h += msg - h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff - h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff - h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff - h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff - h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | flag - - // h *= r - d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1) - d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2) - d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3) - d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4) - d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0) - - // h %= p - h0 = uint32(d0) & 0x3ffffff - h1 = uint32(d1) & 0x3ffffff - h2 = uint32(d2) & 0x3ffffff - h3 = uint32(d3) & 0x3ffffff - h4 = uint32(d4) & 0x3ffffff - - h0 += uint32(d4>>26) * 5 - h1 += h0 >> 26 - h0 = h0 & 0x3ffffff - - msg = msg[TagSize:] - } - - h[0], h[1], h[2], h[3], h[4] = h0, h1, h2, h3, h4 -} - -func finalizeGeneric(out *[TagSize]byte, h *[5]uint32, s *[4]uint32) { - h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4] - - // h %= p reduction - h2 += h1 >> 26 - h1 &= 0x3ffffff - h3 += h2 >> 26 - h2 &= 0x3ffffff - h4 += h3 >> 26 - h3 &= 0x3ffffff - h0 += 5 * (h4 >> 26) - h4 &= 0x3ffffff - h1 += h0 >> 26 - h0 &= 0x3ffffff - - // h - p - t0 := h0 + 5 - t1 := h1 + (t0 >> 26) - t2 := h2 + (t1 >> 26) - t3 := h3 + (t2 >> 26) - t4 := h4 + (t3 >> 26) - (1 << 26) - t0 &= 0x3ffffff - t1 &= 0x3ffffff - t2 &= 0x3ffffff - t3 &= 0x3ffffff - - // select h if h < p else h - p - t_mask := (t4 >> 31) - 1 - h_mask := ^t_mask - h0 = (h0 & h_mask) | (t0 & t_mask) - h1 = (h1 & h_mask) | (t1 & t_mask) - h2 = (h2 & h_mask) | (t2 & t_mask) - h3 = (h3 & h_mask) | (t3 & t_mask) - h4 = (h4 & h_mask) | (t4 & t_mask) - - // h %= 2^128 - h0 |= h1 << 26 - h1 = ((h1 >> 6) | (h2 << 20)) - h2 = ((h2 >> 12) | (h3 << 14)) - h3 = ((h3 >> 18) | (h4 << 8)) - - // s: the s part of the key - // tag = (h + s) % (2^128) - t := uint64(h0) + uint64(s[0]) - h0 = uint32(t) - t = uint64(h1) + uint64(s[1]) + (t >> 32) - h1 = uint32(t) - t = uint64(h2) + uint64(s[2]) + (t >> 32) - h2 = uint32(t) - t = uint64(h3) + uint64(s[3]) + (t >> 32) - h3 = uint32(t) - - binary.LittleEndian.PutUint32(out[0:], h0) - binary.LittleEndian.PutUint32(out[4:], h1) - binary.LittleEndian.PutUint32(out[8:], h2) - binary.LittleEndian.PutUint32(out[12:], h3) -} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go deleted file mode 100644 index fcdef46ab6e..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl - -package poly1305 - -// Sum generates an authenticator for msg using a one-time key and puts the -// 16-byte result into out. Authenticating two different messages with the same -// key allows an attacker to forge messages at will. -func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) { - h := newMAC(key) - h.Write(msg) - h.Sum(out) -} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/poly1305/sum_s390x.go deleted file mode 100644 index ec99e07e9fb..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build s390x,go1.11,!gccgo,!appengine - -package poly1305 - -import ( - "golang.org/x/sys/cpu" -) - -// poly1305vx is an assembly implementation of Poly1305 that uses vector -// instructions. It must only be called if the vector facility (vx) is -// available. -//go:noescape -func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte) - -// poly1305vmsl is an assembly implementation of Poly1305 that uses vector -// instructions, including VMSL. It must only be called if the vector facility (vx) is -// available and if VMSL is supported. -//go:noescape -func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte) - -// Sum generates an authenticator for m using a one-time key and puts the -// 16-byte result into out. Authenticating two different messages with the same -// key allows an attacker to forge messages at will. -func Sum(out *[16]byte, m []byte, key *[32]byte) { - if cpu.S390X.HasVX { - var mPtr *byte - if len(m) > 0 { - mPtr = &m[0] - } - if cpu.S390X.HasVXE && len(m) > 256 { - poly1305vmsl(out, mPtr, uint64(len(m)), key) - } else { - poly1305vx(out, mPtr, uint64(len(m)), key) - } - } else { - sumGeneric(out, m, key) - } -} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s b/vendor/golang.org/x/crypto/poly1305/sum_s390x.s deleted file mode 100644 index ca5a309d867..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build s390x,go1.11,!gccgo,!appengine - -#include "textflag.h" - -// Implementation of Poly1305 using the vector facility (vx). - -// constants -#define MOD26 V0 -#define EX0 V1 -#define EX1 V2 -#define EX2 V3 - -// temporaries -#define T_0 V4 -#define T_1 V5 -#define T_2 V6 -#define T_3 V7 -#define T_4 V8 - -// key (r) -#define R_0 V9 -#define R_1 V10 -#define R_2 V11 -#define R_3 V12 -#define R_4 V13 -#define R5_1 V14 -#define R5_2 V15 -#define R5_3 V16 -#define R5_4 V17 -#define RSAVE_0 R5 -#define RSAVE_1 R6 -#define RSAVE_2 R7 -#define RSAVE_3 R8 -#define RSAVE_4 R9 -#define R5SAVE_1 V28 -#define R5SAVE_2 V29 -#define R5SAVE_3 V30 -#define R5SAVE_4 V31 - -// message block -#define F_0 V18 -#define F_1 V19 -#define F_2 V20 -#define F_3 V21 -#define F_4 V22 - -// accumulator -#define H_0 V23 -#define H_1 V24 -#define H_2 V25 -#define H_3 V26 -#define H_4 V27 - -GLOBL ·keyMask<>(SB), RODATA, $16 -DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f -DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f - -GLOBL ·bswapMask<>(SB), RODATA, $16 -DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908 -DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100 - -GLOBL ·constants<>(SB), RODATA, $64 -// MOD26 -DATA ·constants<>+0(SB)/8, $0x3ffffff -DATA ·constants<>+8(SB)/8, $0x3ffffff -// EX0 -DATA ·constants<>+16(SB)/8, $0x0006050403020100 -DATA ·constants<>+24(SB)/8, $0x1016151413121110 -// EX1 -DATA ·constants<>+32(SB)/8, $0x060c0b0a09080706 -DATA ·constants<>+40(SB)/8, $0x161c1b1a19181716 -// EX2 -DATA ·constants<>+48(SB)/8, $0x0d0d0d0d0d0f0e0d -DATA ·constants<>+56(SB)/8, $0x1d1d1d1d1d1f1e1d - -// h = (f*g) % (2**130-5) [partial reduction] -#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ - VMLOF f0, g0, h0 \ - VMLOF f0, g1, h1 \ - VMLOF f0, g2, h2 \ - VMLOF f0, g3, h3 \ - VMLOF f0, g4, h4 \ - VMLOF f1, g54, T_0 \ - VMLOF f1, g0, T_1 \ - VMLOF f1, g1, T_2 \ - VMLOF f1, g2, T_3 \ - VMLOF f1, g3, T_4 \ - VMALOF f2, g53, h0, h0 \ - VMALOF f2, g54, h1, h1 \ - VMALOF f2, g0, h2, h2 \ - VMALOF f2, g1, h3, h3 \ - VMALOF f2, g2, h4, h4 \ - VMALOF f3, g52, T_0, T_0 \ - VMALOF f3, g53, T_1, T_1 \ - VMALOF f3, g54, T_2, T_2 \ - VMALOF f3, g0, T_3, T_3 \ - VMALOF f3, g1, T_4, T_4 \ - VMALOF f4, g51, h0, h0 \ - VMALOF f4, g52, h1, h1 \ - VMALOF f4, g53, h2, h2 \ - VMALOF f4, g54, h3, h3 \ - VMALOF f4, g0, h4, h4 \ - VAG T_0, h0, h0 \ - VAG T_1, h1, h1 \ - VAG T_2, h2, h2 \ - VAG T_3, h3, h3 \ - VAG T_4, h4, h4 - -// carry h0->h1 h3->h4, h1->h2 h4->h0, h0->h1 h2->h3, h3->h4 -#define REDUCE(h0, h1, h2, h3, h4) \ - VESRLG $26, h0, T_0 \ - VESRLG $26, h3, T_1 \ - VN MOD26, h0, h0 \ - VN MOD26, h3, h3 \ - VAG T_0, h1, h1 \ - VAG T_1, h4, h4 \ - VESRLG $26, h1, T_2 \ - VESRLG $26, h4, T_3 \ - VN MOD26, h1, h1 \ - VN MOD26, h4, h4 \ - VESLG $2, T_3, T_4 \ - VAG T_3, T_4, T_4 \ - VAG T_2, h2, h2 \ - VAG T_4, h0, h0 \ - VESRLG $26, h2, T_0 \ - VESRLG $26, h0, T_1 \ - VN MOD26, h2, h2 \ - VN MOD26, h0, h0 \ - VAG T_0, h3, h3 \ - VAG T_1, h1, h1 \ - VESRLG $26, h3, T_2 \ - VN MOD26, h3, h3 \ - VAG T_2, h4, h4 - -// expand in0 into d[0] and in1 into d[1] -#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ - VGBM $0x0707, d1 \ // d1=tmp - VPERM in0, in1, EX2, d4 \ - VPERM in0, in1, EX0, d0 \ - VPERM in0, in1, EX1, d2 \ - VN d1, d4, d4 \ - VESRLG $26, d0, d1 \ - VESRLG $30, d2, d3 \ - VESRLG $4, d2, d2 \ - VN MOD26, d0, d0 \ - VN MOD26, d1, d1 \ - VN MOD26, d2, d2 \ - VN MOD26, d3, d3 - -// pack h4:h0 into h1:h0 (no carry) -#define PACK(h0, h1, h2, h3, h4) \ - VESLG $26, h1, h1 \ - VESLG $26, h3, h3 \ - VO h0, h1, h0 \ - VO h2, h3, h2 \ - VESLG $4, h2, h2 \ - VLEIB $7, $48, h1 \ - VSLB h1, h2, h2 \ - VO h0, h2, h0 \ - VLEIB $7, $104, h1 \ - VSLB h1, h4, h3 \ - VO h3, h0, h0 \ - VLEIB $7, $24, h1 \ - VSRLB h1, h4, h1 - -// if h > 2**130-5 then h -= 2**130-5 -#define MOD(h0, h1, t0, t1, t2) \ - VZERO t0 \ - VLEIG $1, $5, t0 \ - VACCQ h0, t0, t1 \ - VAQ h0, t0, t0 \ - VONE t2 \ - VLEIG $1, $-4, t2 \ - VAQ t2, t1, t1 \ - VACCQ h1, t1, t1 \ - VONE t2 \ - VAQ t2, t1, t1 \ - VN h0, t1, t2 \ - VNC t0, t1, t1 \ - VO t1, t2, h0 - -// func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]key) -TEXT ·poly1305vx(SB), $0-32 - // This code processes up to 2 blocks (32 bytes) per iteration - // using the algorithm described in: - // NEON crypto, Daniel J. Bernstein & Peter Schwabe - // https://cryptojedi.org/papers/neoncrypto-20120320.pdf - LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key - - // load MOD26, EX0, EX1 and EX2 - MOVD $·constants<>(SB), R5 - VLM (R5), MOD26, EX2 - - // setup r - VL (R4), T_0 - MOVD $·keyMask<>(SB), R6 - VL (R6), T_1 - VN T_0, T_1, T_0 - EXPAND(T_0, T_0, R_0, R_1, R_2, R_3, R_4) - - // setup r*5 - VLEIG $0, $5, T_0 - VLEIG $1, $5, T_0 - - // store r (for final block) - VMLOF T_0, R_1, R5SAVE_1 - VMLOF T_0, R_2, R5SAVE_2 - VMLOF T_0, R_3, R5SAVE_3 - VMLOF T_0, R_4, R5SAVE_4 - VLGVG $0, R_0, RSAVE_0 - VLGVG $0, R_1, RSAVE_1 - VLGVG $0, R_2, RSAVE_2 - VLGVG $0, R_3, RSAVE_3 - VLGVG $0, R_4, RSAVE_4 - - // skip r**2 calculation - CMPBLE R3, $16, skip - - // calculate r**2 - MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5SAVE_1, R5SAVE_2, R5SAVE_3, R5SAVE_4, H_0, H_1, H_2, H_3, H_4) - REDUCE(H_0, H_1, H_2, H_3, H_4) - VLEIG $0, $5, T_0 - VLEIG $1, $5, T_0 - VMLOF T_0, H_1, R5_1 - VMLOF T_0, H_2, R5_2 - VMLOF T_0, H_3, R5_3 - VMLOF T_0, H_4, R5_4 - VLR H_0, R_0 - VLR H_1, R_1 - VLR H_2, R_2 - VLR H_3, R_3 - VLR H_4, R_4 - - // initialize h - VZERO H_0 - VZERO H_1 - VZERO H_2 - VZERO H_3 - VZERO H_4 - -loop: - CMPBLE R3, $32, b2 - VLM (R2), T_0, T_1 - SUB $32, R3 - MOVD $32(R2), R2 - EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) - VLEIB $4, $1, F_4 - VLEIB $12, $1, F_4 - -multiply: - VAG H_0, F_0, F_0 - VAG H_1, F_1, F_1 - VAG H_2, F_2, F_2 - VAG H_3, F_3, F_3 - VAG H_4, F_4, F_4 - MULTIPLY(F_0, F_1, F_2, F_3, F_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4) - REDUCE(H_0, H_1, H_2, H_3, H_4) - CMPBNE R3, $0, loop - -finish: - // sum vectors - VZERO T_0 - VSUMQG H_0, T_0, H_0 - VSUMQG H_1, T_0, H_1 - VSUMQG H_2, T_0, H_2 - VSUMQG H_3, T_0, H_3 - VSUMQG H_4, T_0, H_4 - - // h may be >= 2*(2**130-5) so we need to reduce it again - REDUCE(H_0, H_1, H_2, H_3, H_4) - - // carry h1->h4 - VESRLG $26, H_1, T_1 - VN MOD26, H_1, H_1 - VAQ T_1, H_2, H_2 - VESRLG $26, H_2, T_2 - VN MOD26, H_2, H_2 - VAQ T_2, H_3, H_3 - VESRLG $26, H_3, T_3 - VN MOD26, H_3, H_3 - VAQ T_3, H_4, H_4 - - // h is now < 2*(2**130-5) - // pack h into h1 (hi) and h0 (lo) - PACK(H_0, H_1, H_2, H_3, H_4) - - // if h > 2**130-5 then h -= 2**130-5 - MOD(H_0, H_1, T_0, T_1, T_2) - - // h += s - MOVD $·bswapMask<>(SB), R5 - VL (R5), T_1 - VL 16(R4), T_0 - VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big) - VAQ T_0, H_0, H_0 - VPERM H_0, H_0, T_1, H_0 // reverse bytes (to little) - VST H_0, (R1) - - RET - -b2: - CMPBLE R3, $16, b1 - - // 2 blocks remaining - SUB $17, R3 - VL (R2), T_0 - VLL R3, 16(R2), T_1 - ADD $1, R3 - MOVBZ $1, R0 - CMPBEQ R3, $16, 2(PC) - VLVGB R3, R0, T_1 - EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) - CMPBNE R3, $16, 2(PC) - VLEIB $12, $1, F_4 - VLEIB $4, $1, F_4 - - // setup [r²,r] - VLVGG $1, RSAVE_0, R_0 - VLVGG $1, RSAVE_1, R_1 - VLVGG $1, RSAVE_2, R_2 - VLVGG $1, RSAVE_3, R_3 - VLVGG $1, RSAVE_4, R_4 - VPDI $0, R5_1, R5SAVE_1, R5_1 - VPDI $0, R5_2, R5SAVE_2, R5_2 - VPDI $0, R5_3, R5SAVE_3, R5_3 - VPDI $0, R5_4, R5SAVE_4, R5_4 - - MOVD $0, R3 - BR multiply - -skip: - VZERO H_0 - VZERO H_1 - VZERO H_2 - VZERO H_3 - VZERO H_4 - - CMPBEQ R3, $0, finish - -b1: - // 1 block remaining - SUB $1, R3 - VLL R3, (R2), T_0 - ADD $1, R3 - MOVBZ $1, R0 - CMPBEQ R3, $16, 2(PC) - VLVGB R3, R0, T_0 - VZERO T_1 - EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4) - CMPBNE R3, $16, 2(PC) - VLEIB $4, $1, F_4 - VLEIG $1, $1, R_0 - VZERO R_1 - VZERO R_2 - VZERO R_3 - VZERO R_4 - VZERO R5_1 - VZERO R5_2 - VZERO R5_3 - VZERO R5_4 - - // setup [r, 1] - VLVGG $0, RSAVE_0, R_0 - VLVGG $0, RSAVE_1, R_1 - VLVGG $0, RSAVE_2, R_2 - VLVGG $0, RSAVE_3, R_3 - VLVGG $0, RSAVE_4, R_4 - VPDI $0, R5SAVE_1, R5_1, R5_1 - VPDI $0, R5SAVE_2, R5_2, R5_2 - VPDI $0, R5SAVE_3, R5_3, R5_3 - VPDI $0, R5SAVE_4, R5_4, R5_4 - - MOVD $0, R3 - BR multiply diff --git a/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s b/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s deleted file mode 100644 index e60bbc1d7f8..00000000000 --- a/vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s +++ /dev/null @@ -1,909 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build s390x,go1.11,!gccgo,!appengine - -#include "textflag.h" - -// Implementation of Poly1305 using the vector facility (vx) and the VMSL instruction. - -// constants -#define EX0 V1 -#define EX1 V2 -#define EX2 V3 - -// temporaries -#define T_0 V4 -#define T_1 V5 -#define T_2 V6 -#define T_3 V7 -#define T_4 V8 -#define T_5 V9 -#define T_6 V10 -#define T_7 V11 -#define T_8 V12 -#define T_9 V13 -#define T_10 V14 - -// r**2 & r**4 -#define R_0 V15 -#define R_1 V16 -#define R_2 V17 -#define R5_1 V18 -#define R5_2 V19 -// key (r) -#define RSAVE_0 R7 -#define RSAVE_1 R8 -#define RSAVE_2 R9 -#define R5SAVE_1 R10 -#define R5SAVE_2 R11 - -// message block -#define M0 V20 -#define M1 V21 -#define M2 V22 -#define M3 V23 -#define M4 V24 -#define M5 V25 - -// accumulator -#define H0_0 V26 -#define H1_0 V27 -#define H2_0 V28 -#define H0_1 V29 -#define H1_1 V30 -#define H2_1 V31 - -GLOBL ·keyMask<>(SB), RODATA, $16 -DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f -DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f - -GLOBL ·bswapMask<>(SB), RODATA, $16 -DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908 -DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100 - -GLOBL ·constants<>(SB), RODATA, $48 -// EX0 -DATA ·constants<>+0(SB)/8, $0x18191a1b1c1d1e1f -DATA ·constants<>+8(SB)/8, $0x0000050403020100 -// EX1 -DATA ·constants<>+16(SB)/8, $0x18191a1b1c1d1e1f -DATA ·constants<>+24(SB)/8, $0x00000a0908070605 -// EX2 -DATA ·constants<>+32(SB)/8, $0x18191a1b1c1d1e1f -DATA ·constants<>+40(SB)/8, $0x0000000f0e0d0c0b - -GLOBL ·c<>(SB), RODATA, $48 -// EX0 -DATA ·c<>+0(SB)/8, $0x0000050403020100 -DATA ·c<>+8(SB)/8, $0x0000151413121110 -// EX1 -DATA ·c<>+16(SB)/8, $0x00000a0908070605 -DATA ·c<>+24(SB)/8, $0x00001a1918171615 -// EX2 -DATA ·c<>+32(SB)/8, $0x0000000f0e0d0c0b -DATA ·c<>+40(SB)/8, $0x0000001f1e1d1c1b - -GLOBL ·reduce<>(SB), RODATA, $32 -// 44 bit -DATA ·reduce<>+0(SB)/8, $0x0 -DATA ·reduce<>+8(SB)/8, $0xfffffffffff -// 42 bit -DATA ·reduce<>+16(SB)/8, $0x0 -DATA ·reduce<>+24(SB)/8, $0x3ffffffffff - -// h = (f*g) % (2**130-5) [partial reduction] -// uses T_0...T_9 temporary registers -// input: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2 -// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 -// output: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2 -#define MULTIPLY(m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ - \ // Eliminate the dependency for the last 2 VMSLs - VMSLG m02_0, r_2, m4_2, m4_2 \ - VMSLG m13_0, r_2, m5_2, m5_2 \ // 8 VMSLs pipelined - VMSLG m02_0, r_0, m4_0, m4_0 \ - VMSLG m02_1, r5_2, V0, T_0 \ - VMSLG m02_0, r_1, m4_1, m4_1 \ - VMSLG m02_1, r_0, V0, T_1 \ - VMSLG m02_1, r_1, V0, T_2 \ - VMSLG m02_2, r5_1, V0, T_3 \ - VMSLG m02_2, r5_2, V0, T_4 \ - VMSLG m13_0, r_0, m5_0, m5_0 \ - VMSLG m13_1, r5_2, V0, T_5 \ - VMSLG m13_0, r_1, m5_1, m5_1 \ - VMSLG m13_1, r_0, V0, T_6 \ - VMSLG m13_1, r_1, V0, T_7 \ - VMSLG m13_2, r5_1, V0, T_8 \ - VMSLG m13_2, r5_2, V0, T_9 \ - VMSLG m02_2, r_0, m4_2, m4_2 \ - VMSLG m13_2, r_0, m5_2, m5_2 \ - VAQ m4_0, T_0, m02_0 \ - VAQ m4_1, T_1, m02_1 \ - VAQ m5_0, T_5, m13_0 \ - VAQ m5_1, T_6, m13_1 \ - VAQ m02_0, T_3, m02_0 \ - VAQ m02_1, T_4, m02_1 \ - VAQ m13_0, T_8, m13_0 \ - VAQ m13_1, T_9, m13_1 \ - VAQ m4_2, T_2, m02_2 \ - VAQ m5_2, T_7, m13_2 \ - -// SQUARE uses three limbs of r and r_2*5 to output square of r -// uses T_1, T_5 and T_7 temporary registers -// input: r_0, r_1, r_2, r5_2 -// temp: TEMP0, TEMP1, TEMP2 -// output: p0, p1, p2 -#define SQUARE(r_0, r_1, r_2, r5_2, p0, p1, p2, TEMP0, TEMP1, TEMP2) \ - VMSLG r_0, r_0, p0, p0 \ - VMSLG r_1, r5_2, V0, TEMP0 \ - VMSLG r_2, r5_2, p1, p1 \ - VMSLG r_0, r_1, V0, TEMP1 \ - VMSLG r_1, r_1, p2, p2 \ - VMSLG r_0, r_2, V0, TEMP2 \ - VAQ TEMP0, p0, p0 \ - VAQ TEMP1, p1, p1 \ - VAQ TEMP2, p2, p2 \ - VAQ TEMP0, p0, p0 \ - VAQ TEMP1, p1, p1 \ - VAQ TEMP2, p2, p2 \ - -// carry h0->h1->h2->h0 || h3->h4->h5->h3 -// uses T_2, T_4, T_5, T_7, T_8, T_9 -// t6, t7, t8, t9, t10, t11 -// input: h0, h1, h2, h3, h4, h5 -// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11 -// output: h0, h1, h2, h3, h4, h5 -#define REDUCE(h0, h1, h2, h3, h4, h5, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \ - VLM (R12), t6, t7 \ // 44 and 42 bit clear mask - VLEIB $7, $0x28, t10 \ // 5 byte shift mask - VREPIB $4, t8 \ // 4 bit shift mask - VREPIB $2, t11 \ // 2 bit shift mask - VSRLB t10, h0, t0 \ // h0 byte shift - VSRLB t10, h1, t1 \ // h1 byte shift - VSRLB t10, h2, t2 \ // h2 byte shift - VSRLB t10, h3, t3 \ // h3 byte shift - VSRLB t10, h4, t4 \ // h4 byte shift - VSRLB t10, h5, t5 \ // h5 byte shift - VSRL t8, t0, t0 \ // h0 bit shift - VSRL t8, t1, t1 \ // h2 bit shift - VSRL t11, t2, t2 \ // h2 bit shift - VSRL t8, t3, t3 \ // h3 bit shift - VSRL t8, t4, t4 \ // h4 bit shift - VESLG $2, t2, t9 \ // h2 carry x5 - VSRL t11, t5, t5 \ // h5 bit shift - VN t6, h0, h0 \ // h0 clear carry - VAQ t2, t9, t2 \ // h2 carry x5 - VESLG $2, t5, t9 \ // h5 carry x5 - VN t6, h1, h1 \ // h1 clear carry - VN t7, h2, h2 \ // h2 clear carry - VAQ t5, t9, t5 \ // h5 carry x5 - VN t6, h3, h3 \ // h3 clear carry - VN t6, h4, h4 \ // h4 clear carry - VN t7, h5, h5 \ // h5 clear carry - VAQ t0, h1, h1 \ // h0->h1 - VAQ t3, h4, h4 \ // h3->h4 - VAQ t1, h2, h2 \ // h1->h2 - VAQ t4, h5, h5 \ // h4->h5 - VAQ t2, h0, h0 \ // h2->h0 - VAQ t5, h3, h3 \ // h5->h3 - VREPG $1, t6, t6 \ // 44 and 42 bit masks across both halves - VREPG $1, t7, t7 \ - VSLDB $8, h0, h0, h0 \ // set up [h0/1/2, h3/4/5] - VSLDB $8, h1, h1, h1 \ - VSLDB $8, h2, h2, h2 \ - VO h0, h3, h3 \ - VO h1, h4, h4 \ - VO h2, h5, h5 \ - VESRLG $44, h3, t0 \ // 44 bit shift right - VESRLG $44, h4, t1 \ - VESRLG $42, h5, t2 \ - VN t6, h3, h3 \ // clear carry bits - VN t6, h4, h4 \ - VN t7, h5, h5 \ - VESLG $2, t2, t9 \ // multiply carry by 5 - VAQ t9, t2, t2 \ - VAQ t0, h4, h4 \ - VAQ t1, h5, h5 \ - VAQ t2, h3, h3 \ - -// carry h0->h1->h2->h0 -// input: h0, h1, h2 -// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8 -// output: h0, h1, h2 -#define REDUCE2(h0, h1, h2, t0, t1, t2, t3, t4, t5, t6, t7, t8) \ - VLEIB $7, $0x28, t3 \ // 5 byte shift mask - VREPIB $4, t4 \ // 4 bit shift mask - VREPIB $2, t7 \ // 2 bit shift mask - VGBM $0x003F, t5 \ // mask to clear carry bits - VSRLB t3, h0, t0 \ - VSRLB t3, h1, t1 \ - VSRLB t3, h2, t2 \ - VESRLG $4, t5, t5 \ // 44 bit clear mask - VSRL t4, t0, t0 \ - VSRL t4, t1, t1 \ - VSRL t7, t2, t2 \ - VESRLG $2, t5, t6 \ // 42 bit clear mask - VESLG $2, t2, t8 \ - VAQ t8, t2, t2 \ - VN t5, h0, h0 \ - VN t5, h1, h1 \ - VN t6, h2, h2 \ - VAQ t0, h1, h1 \ - VAQ t1, h2, h2 \ - VAQ t2, h0, h0 \ - VSRLB t3, h0, t0 \ - VSRLB t3, h1, t1 \ - VSRLB t3, h2, t2 \ - VSRL t4, t0, t0 \ - VSRL t4, t1, t1 \ - VSRL t7, t2, t2 \ - VN t5, h0, h0 \ - VN t5, h1, h1 \ - VESLG $2, t2, t8 \ - VN t6, h2, h2 \ - VAQ t0, h1, h1 \ - VAQ t8, t2, t2 \ - VAQ t1, h2, h2 \ - VAQ t2, h0, h0 \ - -// expands two message blocks into the lower halfs of the d registers -// moves the contents of the d registers into upper halfs -// input: in1, in2, d0, d1, d2, d3, d4, d5 -// temp: TEMP0, TEMP1, TEMP2, TEMP3 -// output: d0, d1, d2, d3, d4, d5 -#define EXPACC(in1, in2, d0, d1, d2, d3, d4, d5, TEMP0, TEMP1, TEMP2, TEMP3) \ - VGBM $0xff3f, TEMP0 \ - VGBM $0xff1f, TEMP1 \ - VESLG $4, d1, TEMP2 \ - VESLG $4, d4, TEMP3 \ - VESRLG $4, TEMP0, TEMP0 \ - VPERM in1, d0, EX0, d0 \ - VPERM in2, d3, EX0, d3 \ - VPERM in1, d2, EX2, d2 \ - VPERM in2, d5, EX2, d5 \ - VPERM in1, TEMP2, EX1, d1 \ - VPERM in2, TEMP3, EX1, d4 \ - VN TEMP0, d0, d0 \ - VN TEMP0, d3, d3 \ - VESRLG $4, d1, d1 \ - VESRLG $4, d4, d4 \ - VN TEMP1, d2, d2 \ - VN TEMP1, d5, d5 \ - VN TEMP0, d1, d1 \ - VN TEMP0, d4, d4 \ - -// expands one message block into the lower halfs of the d registers -// moves the contents of the d registers into upper halfs -// input: in, d0, d1, d2 -// temp: TEMP0, TEMP1, TEMP2 -// output: d0, d1, d2 -#define EXPACC2(in, d0, d1, d2, TEMP0, TEMP1, TEMP2) \ - VGBM $0xff3f, TEMP0 \ - VESLG $4, d1, TEMP2 \ - VGBM $0xff1f, TEMP1 \ - VPERM in, d0, EX0, d0 \ - VESRLG $4, TEMP0, TEMP0 \ - VPERM in, d2, EX2, d2 \ - VPERM in, TEMP2, EX1, d1 \ - VN TEMP0, d0, d0 \ - VN TEMP1, d2, d2 \ - VESRLG $4, d1, d1 \ - VN TEMP0, d1, d1 \ - -// pack h2:h0 into h1:h0 (no carry) -// input: h0, h1, h2 -// output: h0, h1, h2 -#define PACK(h0, h1, h2) \ - VMRLG h1, h2, h2 \ // copy h1 to upper half h2 - VESLG $44, h1, h1 \ // shift limb 1 44 bits, leaving 20 - VO h0, h1, h0 \ // combine h0 with 20 bits from limb 1 - VESRLG $20, h2, h1 \ // put top 24 bits of limb 1 into h1 - VLEIG $1, $0, h1 \ // clear h2 stuff from lower half of h1 - VO h0, h1, h0 \ // h0 now has 88 bits (limb 0 and 1) - VLEIG $0, $0, h2 \ // clear upper half of h2 - VESRLG $40, h2, h1 \ // h1 now has upper two bits of result - VLEIB $7, $88, h1 \ // for byte shift (11 bytes) - VSLB h1, h2, h2 \ // shift h2 11 bytes to the left - VO h0, h2, h0 \ // combine h0 with 20 bits from limb 1 - VLEIG $0, $0, h1 \ // clear upper half of h1 - -// if h > 2**130-5 then h -= 2**130-5 -// input: h0, h1 -// temp: t0, t1, t2 -// output: h0 -#define MOD(h0, h1, t0, t1, t2) \ - VZERO t0 \ - VLEIG $1, $5, t0 \ - VACCQ h0, t0, t1 \ - VAQ h0, t0, t0 \ - VONE t2 \ - VLEIG $1, $-4, t2 \ - VAQ t2, t1, t1 \ - VACCQ h1, t1, t1 \ - VONE t2 \ - VAQ t2, t1, t1 \ - VN h0, t1, t2 \ - VNC t0, t1, t1 \ - VO t1, t2, h0 \ - -// func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]key) -TEXT ·poly1305vmsl(SB), $0-32 - // This code processes 6 + up to 4 blocks (32 bytes) per iteration - // using the algorithm described in: - // NEON crypto, Daniel J. Bernstein & Peter Schwabe - // https://cryptojedi.org/papers/neoncrypto-20120320.pdf - // And as moddified for VMSL as described in - // Accelerating Poly1305 Cryptographic Message Authentication on the z14 - // O'Farrell et al, CASCON 2017, p48-55 - // https://ibm.ent.box.com/s/jf9gedj0e9d2vjctfyh186shaztavnht - - LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key - VZERO V0 // c - - // load EX0, EX1 and EX2 - MOVD $·constants<>(SB), R5 - VLM (R5), EX0, EX2 // c - - // setup r - VL (R4), T_0 - MOVD $·keyMask<>(SB), R6 - VL (R6), T_1 - VN T_0, T_1, T_0 - VZERO T_2 // limbs for r - VZERO T_3 - VZERO T_4 - EXPACC2(T_0, T_2, T_3, T_4, T_1, T_5, T_7) - - // T_2, T_3, T_4: [0, r] - - // setup r*20 - VLEIG $0, $0, T_0 - VLEIG $1, $20, T_0 // T_0: [0, 20] - VZERO T_5 - VZERO T_6 - VMSLG T_0, T_3, T_5, T_5 - VMSLG T_0, T_4, T_6, T_6 - - // store r for final block in GR - VLGVG $1, T_2, RSAVE_0 // c - VLGVG $1, T_3, RSAVE_1 // c - VLGVG $1, T_4, RSAVE_2 // c - VLGVG $1, T_5, R5SAVE_1 // c - VLGVG $1, T_6, R5SAVE_2 // c - - // initialize h - VZERO H0_0 - VZERO H1_0 - VZERO H2_0 - VZERO H0_1 - VZERO H1_1 - VZERO H2_1 - - // initialize pointer for reduce constants - MOVD $·reduce<>(SB), R12 - - // calculate r**2 and 20*(r**2) - VZERO R_0 - VZERO R_1 - VZERO R_2 - SQUARE(T_2, T_3, T_4, T_6, R_0, R_1, R_2, T_1, T_5, T_7) - REDUCE2(R_0, R_1, R_2, M0, M1, M2, M3, M4, R5_1, R5_2, M5, T_1) - VZERO R5_1 - VZERO R5_2 - VMSLG T_0, R_1, R5_1, R5_1 - VMSLG T_0, R_2, R5_2, R5_2 - - // skip r**4 calculation if 3 blocks or less - CMPBLE R3, $48, b4 - - // calculate r**4 and 20*(r**4) - VZERO T_8 - VZERO T_9 - VZERO T_10 - SQUARE(R_0, R_1, R_2, R5_2, T_8, T_9, T_10, T_1, T_5, T_7) - REDUCE2(T_8, T_9, T_10, M0, M1, M2, M3, M4, T_2, T_3, M5, T_1) - VZERO T_2 - VZERO T_3 - VMSLG T_0, T_9, T_2, T_2 - VMSLG T_0, T_10, T_3, T_3 - - // put r**2 to the right and r**4 to the left of R_0, R_1, R_2 - VSLDB $8, T_8, T_8, T_8 - VSLDB $8, T_9, T_9, T_9 - VSLDB $8, T_10, T_10, T_10 - VSLDB $8, T_2, T_2, T_2 - VSLDB $8, T_3, T_3, T_3 - - VO T_8, R_0, R_0 - VO T_9, R_1, R_1 - VO T_10, R_2, R_2 - VO T_2, R5_1, R5_1 - VO T_3, R5_2, R5_2 - - CMPBLE R3, $80, load // less than or equal to 5 blocks in message - - // 6(or 5+1) blocks - SUB $81, R3 - VLM (R2), M0, M4 - VLL R3, 80(R2), M5 - ADD $1, R3 - MOVBZ $1, R0 - CMPBGE R3, $16, 2(PC) - VLVGB R3, R0, M5 - MOVD $96(R2), R2 - EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) - EXPACC(M2, M3, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) - VLEIB $2, $1, H2_0 - VLEIB $2, $1, H2_1 - VLEIB $10, $1, H2_0 - VLEIB $10, $1, H2_1 - - VZERO M0 - VZERO M1 - VZERO M2 - VZERO M3 - VZERO T_4 - VZERO T_10 - EXPACC(M4, M5, M0, M1, M2, M3, T_4, T_10, T_0, T_1, T_2, T_3) - VLR T_4, M4 - VLEIB $10, $1, M2 - CMPBLT R3, $16, 2(PC) - VLEIB $10, $1, T_10 - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9) - VMRHG V0, H0_1, H0_0 - VMRHG V0, H1_1, H1_0 - VMRHG V0, H2_1, H2_0 - VMRLG V0, H0_1, H0_1 - VMRLG V0, H1_1, H1_1 - VMRLG V0, H2_1, H2_1 - - SUB $16, R3 - CMPBLE R3, $0, square - -load: - // load EX0, EX1 and EX2 - MOVD $·c<>(SB), R5 - VLM (R5), EX0, EX2 - -loop: - CMPBLE R3, $64, add // b4 // last 4 or less blocks left - - // next 4 full blocks - VLM (R2), M2, M5 - SUB $64, R3 - MOVD $64(R2), R2 - REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, T_0, T_1, T_3, T_4, T_5, T_2, T_7, T_8, T_9) - - // expacc in-lined to create [m2, m3] limbs - VGBM $0x3f3f, T_0 // 44 bit clear mask - VGBM $0x1f1f, T_1 // 40 bit clear mask - VPERM M2, M3, EX0, T_3 - VESRLG $4, T_0, T_0 // 44 bit clear mask ready - VPERM M2, M3, EX1, T_4 - VPERM M2, M3, EX2, T_5 - VN T_0, T_3, T_3 - VESRLG $4, T_4, T_4 - VN T_1, T_5, T_5 - VN T_0, T_4, T_4 - VMRHG H0_1, T_3, H0_0 - VMRHG H1_1, T_4, H1_0 - VMRHG H2_1, T_5, H2_0 - VMRLG H0_1, T_3, H0_1 - VMRLG H1_1, T_4, H1_1 - VMRLG H2_1, T_5, H2_1 - VLEIB $10, $1, H2_0 - VLEIB $10, $1, H2_1 - VPERM M4, M5, EX0, T_3 - VPERM M4, M5, EX1, T_4 - VPERM M4, M5, EX2, T_5 - VN T_0, T_3, T_3 - VESRLG $4, T_4, T_4 - VN T_1, T_5, T_5 - VN T_0, T_4, T_4 - VMRHG V0, T_3, M0 - VMRHG V0, T_4, M1 - VMRHG V0, T_5, M2 - VMRLG V0, T_3, M3 - VMRLG V0, T_4, M4 - VMRLG V0, T_5, M5 - VLEIB $10, $1, M2 - VLEIB $10, $1, M5 - - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - CMPBNE R3, $0, loop - REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) - VMRHG V0, H0_1, H0_0 - VMRHG V0, H1_1, H1_0 - VMRHG V0, H2_1, H2_0 - VMRLG V0, H0_1, H0_1 - VMRLG V0, H1_1, H1_1 - VMRLG V0, H2_1, H2_1 - - // load EX0, EX1, EX2 - MOVD $·constants<>(SB), R5 - VLM (R5), EX0, EX2 - - // sum vectors - VAQ H0_0, H0_1, H0_0 - VAQ H1_0, H1_1, H1_0 - VAQ H2_0, H2_1, H2_0 - - // h may be >= 2*(2**130-5) so we need to reduce it again - // M0...M4 are used as temps here - REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) - -next: // carry h1->h2 - VLEIB $7, $0x28, T_1 - VREPIB $4, T_2 - VGBM $0x003F, T_3 - VESRLG $4, T_3 - - // byte shift - VSRLB T_1, H1_0, T_4 - - // bit shift - VSRL T_2, T_4, T_4 - - // clear h1 carry bits - VN T_3, H1_0, H1_0 - - // add carry - VAQ T_4, H2_0, H2_0 - - // h is now < 2*(2**130-5) - // pack h into h1 (hi) and h0 (lo) - PACK(H0_0, H1_0, H2_0) - - // if h > 2**130-5 then h -= 2**130-5 - MOD(H0_0, H1_0, T_0, T_1, T_2) - - // h += s - MOVD $·bswapMask<>(SB), R5 - VL (R5), T_1 - VL 16(R4), T_0 - VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big) - VAQ T_0, H0_0, H0_0 - VPERM H0_0, H0_0, T_1, H0_0 // reverse bytes (to little) - VST H0_0, (R1) - RET - -add: - // load EX0, EX1, EX2 - MOVD $·constants<>(SB), R5 - VLM (R5), EX0, EX2 - - REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) - VMRHG V0, H0_1, H0_0 - VMRHG V0, H1_1, H1_0 - VMRHG V0, H2_1, H2_0 - VMRLG V0, H0_1, H0_1 - VMRLG V0, H1_1, H1_1 - VMRLG V0, H2_1, H2_1 - CMPBLE R3, $64, b4 - -b4: - CMPBLE R3, $48, b3 // 3 blocks or less - - // 4(3+1) blocks remaining - SUB $49, R3 - VLM (R2), M0, M2 - VLL R3, 48(R2), M3 - ADD $1, R3 - MOVBZ $1, R0 - CMPBEQ R3, $16, 2(PC) - VLVGB R3, R0, M3 - MOVD $64(R2), R2 - EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3) - VLEIB $10, $1, H2_0 - VLEIB $10, $1, H2_1 - VZERO M0 - VZERO M1 - VZERO M4 - VZERO M5 - VZERO T_4 - VZERO T_10 - EXPACC(M2, M3, M0, M1, M4, M5, T_4, T_10, T_0, T_1, T_2, T_3) - VLR T_4, M2 - VLEIB $10, $1, M4 - CMPBNE R3, $16, 2(PC) - VLEIB $10, $1, T_10 - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M4, M5, M2, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9) - VMRHG V0, H0_1, H0_0 - VMRHG V0, H1_1, H1_0 - VMRHG V0, H2_1, H2_0 - VMRLG V0, H0_1, H0_1 - VMRLG V0, H1_1, H1_1 - VMRLG V0, H2_1, H2_1 - SUB $16, R3 - CMPBLE R3, $0, square // this condition must always hold true! - -b3: - CMPBLE R3, $32, b2 - - // 3 blocks remaining - - // setup [r²,r] - VSLDB $8, R_0, R_0, R_0 - VSLDB $8, R_1, R_1, R_1 - VSLDB $8, R_2, R_2, R_2 - VSLDB $8, R5_1, R5_1, R5_1 - VSLDB $8, R5_2, R5_2, R5_2 - - VLVGG $1, RSAVE_0, R_0 - VLVGG $1, RSAVE_1, R_1 - VLVGG $1, RSAVE_2, R_2 - VLVGG $1, R5SAVE_1, R5_1 - VLVGG $1, R5SAVE_2, R5_2 - - // setup [h0, h1] - VSLDB $8, H0_0, H0_0, H0_0 - VSLDB $8, H1_0, H1_0, H1_0 - VSLDB $8, H2_0, H2_0, H2_0 - VO H0_1, H0_0, H0_0 - VO H1_1, H1_0, H1_0 - VO H2_1, H2_0, H2_0 - VZERO H0_1 - VZERO H1_1 - VZERO H2_1 - - VZERO M0 - VZERO M1 - VZERO M2 - VZERO M3 - VZERO M4 - VZERO M5 - - // H*[r**2, r] - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, T_10, M5) - - SUB $33, R3 - VLM (R2), M0, M1 - VLL R3, 32(R2), M2 - ADD $1, R3 - MOVBZ $1, R0 - CMPBEQ R3, $16, 2(PC) - VLVGB R3, R0, M2 - - // H += m0 - VZERO T_1 - VZERO T_2 - VZERO T_3 - EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6) - VLEIB $10, $1, T_3 - VAG H0_0, T_1, H0_0 - VAG H1_0, T_2, H1_0 - VAG H2_0, T_3, H2_0 - - VZERO M0 - VZERO M3 - VZERO M4 - VZERO M5 - VZERO T_10 - - // (H+m0)*r - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M3, M4, M5, V0, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_10, H0_1, H1_1, H2_1, T_9) - - // H += m1 - VZERO V0 - VZERO T_1 - VZERO T_2 - VZERO T_3 - EXPACC2(M1, T_1, T_2, T_3, T_4, T_5, T_6) - VLEIB $10, $1, T_3 - VAQ H0_0, T_1, H0_0 - VAQ H1_0, T_2, H1_0 - VAQ H2_0, T_3, H2_0 - REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10) - - // [H, m2] * [r**2, r] - EXPACC2(M2, H0_0, H1_0, H2_0, T_1, T_2, T_3) - CMPBNE R3, $16, 2(PC) - VLEIB $10, $1, H2_0 - VZERO M0 - VZERO M1 - VZERO M2 - VZERO M3 - VZERO M4 - VZERO M5 - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, M5, T_10) - SUB $16, R3 - CMPBLE R3, $0, next // this condition must always hold true! - -b2: - CMPBLE R3, $16, b1 - - // 2 blocks remaining - - // setup [r²,r] - VSLDB $8, R_0, R_0, R_0 - VSLDB $8, R_1, R_1, R_1 - VSLDB $8, R_2, R_2, R_2 - VSLDB $8, R5_1, R5_1, R5_1 - VSLDB $8, R5_2, R5_2, R5_2 - - VLVGG $1, RSAVE_0, R_0 - VLVGG $1, RSAVE_1, R_1 - VLVGG $1, RSAVE_2, R_2 - VLVGG $1, R5SAVE_1, R5_1 - VLVGG $1, R5SAVE_2, R5_2 - - // setup [h0, h1] - VSLDB $8, H0_0, H0_0, H0_0 - VSLDB $8, H1_0, H1_0, H1_0 - VSLDB $8, H2_0, H2_0, H2_0 - VO H0_1, H0_0, H0_0 - VO H1_1, H1_0, H1_0 - VO H2_1, H2_0, H2_0 - VZERO H0_1 - VZERO H1_1 - VZERO H2_1 - - VZERO M0 - VZERO M1 - VZERO M2 - VZERO M3 - VZERO M4 - VZERO M5 - - // H*[r**2, r] - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9) - VMRHG V0, H0_1, H0_0 - VMRHG V0, H1_1, H1_0 - VMRHG V0, H2_1, H2_0 - VMRLG V0, H0_1, H0_1 - VMRLG V0, H1_1, H1_1 - VMRLG V0, H2_1, H2_1 - - // move h to the left and 0s at the right - VSLDB $8, H0_0, H0_0, H0_0 - VSLDB $8, H1_0, H1_0, H1_0 - VSLDB $8, H2_0, H2_0, H2_0 - - // get message blocks and append 1 to start - SUB $17, R3 - VL (R2), M0 - VLL R3, 16(R2), M1 - ADD $1, R3 - MOVBZ $1, R0 - CMPBEQ R3, $16, 2(PC) - VLVGB R3, R0, M1 - VZERO T_6 - VZERO T_7 - VZERO T_8 - EXPACC2(M0, T_6, T_7, T_8, T_1, T_2, T_3) - EXPACC2(M1, T_6, T_7, T_8, T_1, T_2, T_3) - VLEIB $2, $1, T_8 - CMPBNE R3, $16, 2(PC) - VLEIB $10, $1, T_8 - - // add [m0, m1] to h - VAG H0_0, T_6, H0_0 - VAG H1_0, T_7, H1_0 - VAG H2_0, T_8, H2_0 - - VZERO M2 - VZERO M3 - VZERO M4 - VZERO M5 - VZERO T_10 - VZERO M0 - - // at this point R_0 .. R5_2 look like [r**2, r] - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M2, M3, M4, M5, T_10, M0, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE2(H0_0, H1_0, H2_0, M2, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10) - SUB $16, R3, R3 - CMPBLE R3, $0, next - -b1: - CMPBLE R3, $0, next - - // 1 block remaining - - // setup [r²,r] - VSLDB $8, R_0, R_0, R_0 - VSLDB $8, R_1, R_1, R_1 - VSLDB $8, R_2, R_2, R_2 - VSLDB $8, R5_1, R5_1, R5_1 - VSLDB $8, R5_2, R5_2, R5_2 - - VLVGG $1, RSAVE_0, R_0 - VLVGG $1, RSAVE_1, R_1 - VLVGG $1, RSAVE_2, R_2 - VLVGG $1, R5SAVE_1, R5_1 - VLVGG $1, R5SAVE_2, R5_2 - - // setup [h0, h1] - VSLDB $8, H0_0, H0_0, H0_0 - VSLDB $8, H1_0, H1_0, H1_0 - VSLDB $8, H2_0, H2_0, H2_0 - VO H0_1, H0_0, H0_0 - VO H1_1, H1_0, H1_0 - VO H2_1, H2_0, H2_0 - VZERO H0_1 - VZERO H1_1 - VZERO H2_1 - - VZERO M0 - VZERO M1 - VZERO M2 - VZERO M3 - VZERO M4 - VZERO M5 - - // H*[r**2, r] - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) - - // set up [0, m0] limbs - SUB $1, R3 - VLL R3, (R2), M0 - ADD $1, R3 - MOVBZ $1, R0 - CMPBEQ R3, $16, 2(PC) - VLVGB R3, R0, M0 - VZERO T_1 - VZERO T_2 - VZERO T_3 - EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)// limbs: [0, m] - CMPBNE R3, $16, 2(PC) - VLEIB $10, $1, T_3 - - // h+m0 - VAQ H0_0, T_1, H0_0 - VAQ H1_0, T_2, H1_0 - VAQ H2_0, T_3, H2_0 - - VZERO M0 - VZERO M1 - VZERO M2 - VZERO M3 - VZERO M4 - VZERO M5 - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) - - BR next - -square: - // setup [r²,r] - VSLDB $8, R_0, R_0, R_0 - VSLDB $8, R_1, R_1, R_1 - VSLDB $8, R_2, R_2, R_2 - VSLDB $8, R5_1, R5_1, R5_1 - VSLDB $8, R5_2, R5_2, R5_2 - - VLVGG $1, RSAVE_0, R_0 - VLVGG $1, RSAVE_1, R_1 - VLVGG $1, RSAVE_2, R_2 - VLVGG $1, R5SAVE_1, R5_1 - VLVGG $1, R5SAVE_2, R5_2 - - // setup [h0, h1] - VSLDB $8, H0_0, H0_0, H0_0 - VSLDB $8, H1_0, H1_0, H1_0 - VSLDB $8, H2_0, H2_0, H2_0 - VO H0_1, H0_0, H0_0 - VO H1_1, H1_0, H1_0 - VO H2_1, H2_0, H2_0 - VZERO H0_1 - VZERO H1_1 - VZERO H2_1 - - VZERO M0 - VZERO M1 - VZERO M2 - VZERO M3 - VZERO M4 - VZERO M5 - - // (h0*r**2) + (h1*r) - MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9) - REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5) - BR next diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go deleted file mode 100644 index 4c96147c86b..00000000000 --- a/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package salsa provides low-level access to functions in the Salsa family. -package salsa // import "golang.org/x/crypto/salsa20/salsa" - -// Sigma is the Salsa20 constant for 256-bit keys. -var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} - -// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte -// key k, and 16-byte constant c, and puts the result into the 32-byte array -// out. -func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { - x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 - x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 - x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 - x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 - x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 - x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 - x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 - x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 - x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 - x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 - x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 - x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 - x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 - x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 - x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 - x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 - - for i := 0; i < 20; i += 2 { - u := x0 + x12 - x4 ^= u<<7 | u>>(32-7) - u = x4 + x0 - x8 ^= u<<9 | u>>(32-9) - u = x8 + x4 - x12 ^= u<<13 | u>>(32-13) - u = x12 + x8 - x0 ^= u<<18 | u>>(32-18) - - u = x5 + x1 - x9 ^= u<<7 | u>>(32-7) - u = x9 + x5 - x13 ^= u<<9 | u>>(32-9) - u = x13 + x9 - x1 ^= u<<13 | u>>(32-13) - u = x1 + x13 - x5 ^= u<<18 | u>>(32-18) - - u = x10 + x6 - x14 ^= u<<7 | u>>(32-7) - u = x14 + x10 - x2 ^= u<<9 | u>>(32-9) - u = x2 + x14 - x6 ^= u<<13 | u>>(32-13) - u = x6 + x2 - x10 ^= u<<18 | u>>(32-18) - - u = x15 + x11 - x3 ^= u<<7 | u>>(32-7) - u = x3 + x15 - x7 ^= u<<9 | u>>(32-9) - u = x7 + x3 - x11 ^= u<<13 | u>>(32-13) - u = x11 + x7 - x15 ^= u<<18 | u>>(32-18) - - u = x0 + x3 - x1 ^= u<<7 | u>>(32-7) - u = x1 + x0 - x2 ^= u<<9 | u>>(32-9) - u = x2 + x1 - x3 ^= u<<13 | u>>(32-13) - u = x3 + x2 - x0 ^= u<<18 | u>>(32-18) - - u = x5 + x4 - x6 ^= u<<7 | u>>(32-7) - u = x6 + x5 - x7 ^= u<<9 | u>>(32-9) - u = x7 + x6 - x4 ^= u<<13 | u>>(32-13) - u = x4 + x7 - x5 ^= u<<18 | u>>(32-18) - - u = x10 + x9 - x11 ^= u<<7 | u>>(32-7) - u = x11 + x10 - x8 ^= u<<9 | u>>(32-9) - u = x8 + x11 - x9 ^= u<<13 | u>>(32-13) - u = x9 + x8 - x10 ^= u<<18 | u>>(32-18) - - u = x15 + x14 - x12 ^= u<<7 | u>>(32-7) - u = x12 + x15 - x13 ^= u<<9 | u>>(32-9) - u = x13 + x12 - x14 ^= u<<13 | u>>(32-13) - u = x14 + x13 - x15 ^= u<<18 | u>>(32-18) - } - out[0] = byte(x0) - out[1] = byte(x0 >> 8) - out[2] = byte(x0 >> 16) - out[3] = byte(x0 >> 24) - - out[4] = byte(x5) - out[5] = byte(x5 >> 8) - out[6] = byte(x5 >> 16) - out[7] = byte(x5 >> 24) - - out[8] = byte(x10) - out[9] = byte(x10 >> 8) - out[10] = byte(x10 >> 16) - out[11] = byte(x10 >> 24) - - out[12] = byte(x15) - out[13] = byte(x15 >> 8) - out[14] = byte(x15 >> 16) - out[15] = byte(x15 >> 24) - - out[16] = byte(x6) - out[17] = byte(x6 >> 8) - out[18] = byte(x6 >> 16) - out[19] = byte(x6 >> 24) - - out[20] = byte(x7) - out[21] = byte(x7 >> 8) - out[22] = byte(x7 >> 16) - out[23] = byte(x7 >> 24) - - out[24] = byte(x8) - out[25] = byte(x8 >> 8) - out[26] = byte(x8 >> 16) - out[27] = byte(x8 >> 24) - - out[28] = byte(x9) - out[29] = byte(x9 >> 8) - out[30] = byte(x9 >> 16) - out[31] = byte(x9 >> 24) -} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go deleted file mode 100644 index 9bfc0927ce8..00000000000 --- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package salsa - -// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts -// the result into the 64-byte array out. The input and output may be the same array. -func Core208(out *[64]byte, in *[64]byte) { - j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 - j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 - j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 - j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 - j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24 - j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24 - j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24 - j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24 - j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24 - j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24 - j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24 - j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24 - j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24 - j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24 - j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24 - j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24 - - x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 - x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 - - for i := 0; i < 8; i += 2 { - u := x0 + x12 - x4 ^= u<<7 | u>>(32-7) - u = x4 + x0 - x8 ^= u<<9 | u>>(32-9) - u = x8 + x4 - x12 ^= u<<13 | u>>(32-13) - u = x12 + x8 - x0 ^= u<<18 | u>>(32-18) - - u = x5 + x1 - x9 ^= u<<7 | u>>(32-7) - u = x9 + x5 - x13 ^= u<<9 | u>>(32-9) - u = x13 + x9 - x1 ^= u<<13 | u>>(32-13) - u = x1 + x13 - x5 ^= u<<18 | u>>(32-18) - - u = x10 + x6 - x14 ^= u<<7 | u>>(32-7) - u = x14 + x10 - x2 ^= u<<9 | u>>(32-9) - u = x2 + x14 - x6 ^= u<<13 | u>>(32-13) - u = x6 + x2 - x10 ^= u<<18 | u>>(32-18) - - u = x15 + x11 - x3 ^= u<<7 | u>>(32-7) - u = x3 + x15 - x7 ^= u<<9 | u>>(32-9) - u = x7 + x3 - x11 ^= u<<13 | u>>(32-13) - u = x11 + x7 - x15 ^= u<<18 | u>>(32-18) - - u = x0 + x3 - x1 ^= u<<7 | u>>(32-7) - u = x1 + x0 - x2 ^= u<<9 | u>>(32-9) - u = x2 + x1 - x3 ^= u<<13 | u>>(32-13) - u = x3 + x2 - x0 ^= u<<18 | u>>(32-18) - - u = x5 + x4 - x6 ^= u<<7 | u>>(32-7) - u = x6 + x5 - x7 ^= u<<9 | u>>(32-9) - u = x7 + x6 - x4 ^= u<<13 | u>>(32-13) - u = x4 + x7 - x5 ^= u<<18 | u>>(32-18) - - u = x10 + x9 - x11 ^= u<<7 | u>>(32-7) - u = x11 + x10 - x8 ^= u<<9 | u>>(32-9) - u = x8 + x11 - x9 ^= u<<13 | u>>(32-13) - u = x9 + x8 - x10 ^= u<<18 | u>>(32-18) - - u = x15 + x14 - x12 ^= u<<7 | u>>(32-7) - u = x12 + x15 - x13 ^= u<<9 | u>>(32-9) - u = x13 + x12 - x14 ^= u<<13 | u>>(32-13) - u = x14 + x13 - x15 ^= u<<18 | u>>(32-18) - } - x0 += j0 - x1 += j1 - x2 += j2 - x3 += j3 - x4 += j4 - x5 += j5 - x6 += j6 - x7 += j7 - x8 += j8 - x9 += j9 - x10 += j10 - x11 += j11 - x12 += j12 - x13 += j13 - x14 += j14 - x15 += j15 - - out[0] = byte(x0) - out[1] = byte(x0 >> 8) - out[2] = byte(x0 >> 16) - out[3] = byte(x0 >> 24) - - out[4] = byte(x1) - out[5] = byte(x1 >> 8) - out[6] = byte(x1 >> 16) - out[7] = byte(x1 >> 24) - - out[8] = byte(x2) - out[9] = byte(x2 >> 8) - out[10] = byte(x2 >> 16) - out[11] = byte(x2 >> 24) - - out[12] = byte(x3) - out[13] = byte(x3 >> 8) - out[14] = byte(x3 >> 16) - out[15] = byte(x3 >> 24) - - out[16] = byte(x4) - out[17] = byte(x4 >> 8) - out[18] = byte(x4 >> 16) - out[19] = byte(x4 >> 24) - - out[20] = byte(x5) - out[21] = byte(x5 >> 8) - out[22] = byte(x5 >> 16) - out[23] = byte(x5 >> 24) - - out[24] = byte(x6) - out[25] = byte(x6 >> 8) - out[26] = byte(x6 >> 16) - out[27] = byte(x6 >> 24) - - out[28] = byte(x7) - out[29] = byte(x7 >> 8) - out[30] = byte(x7 >> 16) - out[31] = byte(x7 >> 24) - - out[32] = byte(x8) - out[33] = byte(x8 >> 8) - out[34] = byte(x8 >> 16) - out[35] = byte(x8 >> 24) - - out[36] = byte(x9) - out[37] = byte(x9 >> 8) - out[38] = byte(x9 >> 16) - out[39] = byte(x9 >> 24) - - out[40] = byte(x10) - out[41] = byte(x10 >> 8) - out[42] = byte(x10 >> 16) - out[43] = byte(x10 >> 24) - - out[44] = byte(x11) - out[45] = byte(x11 >> 8) - out[46] = byte(x11 >> 16) - out[47] = byte(x11 >> 24) - - out[48] = byte(x12) - out[49] = byte(x12 >> 8) - out[50] = byte(x12 >> 16) - out[51] = byte(x12 >> 24) - - out[52] = byte(x13) - out[53] = byte(x13 >> 8) - out[54] = byte(x13 >> 16) - out[55] = byte(x13 >> 24) - - out[56] = byte(x14) - out[57] = byte(x14 >> 8) - out[58] = byte(x14 >> 16) - out[59] = byte(x14 >> 24) - - out[60] = byte(x15) - out[61] = byte(x15 >> 8) - out[62] = byte(x15 >> 16) - out[63] = byte(x15 >> 24) -} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go deleted file mode 100644 index 656e8df942b..00000000000 --- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!appengine,!gccgo - -package salsa - -//go:noescape - -// salsa2020XORKeyStream is implemented in salsa20_amd64.s. -func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) - -// XORKeyStream crypts bytes from in to out using the given key and counters. -// In and out must overlap entirely or not at all. Counter -// contains the raw salsa20 counter bytes (both nonce and block counter). -func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { - if len(in) == 0 { - return - } - _ = out[len(in)-1] - salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0]) -} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s deleted file mode 100644 index 18085d2e8c6..00000000000 --- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s +++ /dev/null @@ -1,883 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!appengine,!gccgo - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) -// This needs up to 64 bytes at 360(SP); hence the non-obvious frame size. -TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVQ out+0(FP),DI - MOVQ in+8(FP),SI - MOVQ n+16(FP),DX - MOVQ nonce+24(FP),CX - MOVQ key+32(FP),R8 - - MOVQ SP,R12 - MOVQ SP,R9 - ADDQ $31, R9 - ANDQ $~31, R9 - MOVQ R9, SP - - MOVQ DX,R9 - MOVQ CX,DX - MOVQ R8,R10 - CMPQ R9,$0 - JBE DONE - START: - MOVL 20(R10),CX - MOVL 0(R10),R8 - MOVL 0(DX),AX - MOVL 16(R10),R11 - MOVL CX,0(SP) - MOVL R8, 4 (SP) - MOVL AX, 8 (SP) - MOVL R11, 12 (SP) - MOVL 8(DX),CX - MOVL 24(R10),R8 - MOVL 4(R10),AX - MOVL 4(DX),R11 - MOVL CX,16(SP) - MOVL R8, 20 (SP) - MOVL AX, 24 (SP) - MOVL R11, 28 (SP) - MOVL 12(DX),CX - MOVL 12(R10),DX - MOVL 28(R10),R8 - MOVL 8(R10),AX - MOVL DX,32(SP) - MOVL CX, 36 (SP) - MOVL R8, 40 (SP) - MOVL AX, 44 (SP) - MOVQ $1634760805,DX - MOVQ $857760878,CX - MOVQ $2036477234,R8 - MOVQ $1797285236,AX - MOVL DX,48(SP) - MOVL CX, 52 (SP) - MOVL R8, 56 (SP) - MOVL AX, 60 (SP) - CMPQ R9,$256 - JB BYTESBETWEEN1AND255 - MOVOA 48(SP),X0 - PSHUFL $0X55,X0,X1 - PSHUFL $0XAA,X0,X2 - PSHUFL $0XFF,X0,X3 - PSHUFL $0X00,X0,X0 - MOVOA X1,64(SP) - MOVOA X2,80(SP) - MOVOA X3,96(SP) - MOVOA X0,112(SP) - MOVOA 0(SP),X0 - PSHUFL $0XAA,X0,X1 - PSHUFL $0XFF,X0,X2 - PSHUFL $0X00,X0,X3 - PSHUFL $0X55,X0,X0 - MOVOA X1,128(SP) - MOVOA X2,144(SP) - MOVOA X3,160(SP) - MOVOA X0,176(SP) - MOVOA 16(SP),X0 - PSHUFL $0XFF,X0,X1 - PSHUFL $0X55,X0,X2 - PSHUFL $0XAA,X0,X0 - MOVOA X1,192(SP) - MOVOA X2,208(SP) - MOVOA X0,224(SP) - MOVOA 32(SP),X0 - PSHUFL $0X00,X0,X1 - PSHUFL $0XAA,X0,X2 - PSHUFL $0XFF,X0,X0 - MOVOA X1,240(SP) - MOVOA X2,256(SP) - MOVOA X0,272(SP) - BYTESATLEAST256: - MOVL 16(SP),DX - MOVL 36 (SP),CX - MOVL DX,288(SP) - MOVL CX,304(SP) - SHLQ $32,CX - ADDQ CX,DX - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX, 292 (SP) - MOVL CX, 308 (SP) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX, 296 (SP) - MOVL CX, 312 (SP) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX, 300 (SP) - MOVL CX, 316 (SP) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX,16(SP) - MOVL CX, 36 (SP) - MOVQ R9,352(SP) - MOVQ $20,DX - MOVOA 64(SP),X0 - MOVOA 80(SP),X1 - MOVOA 96(SP),X2 - MOVOA 256(SP),X3 - MOVOA 272(SP),X4 - MOVOA 128(SP),X5 - MOVOA 144(SP),X6 - MOVOA 176(SP),X7 - MOVOA 192(SP),X8 - MOVOA 208(SP),X9 - MOVOA 224(SP),X10 - MOVOA 304(SP),X11 - MOVOA 112(SP),X12 - MOVOA 160(SP),X13 - MOVOA 240(SP),X14 - MOVOA 288(SP),X15 - MAINLOOP1: - MOVOA X1,320(SP) - MOVOA X2,336(SP) - MOVOA X13,X1 - PADDL X12,X1 - MOVOA X1,X2 - PSLLL $7,X1 - PXOR X1,X14 - PSRLL $25,X2 - PXOR X2,X14 - MOVOA X7,X1 - PADDL X0,X1 - MOVOA X1,X2 - PSLLL $7,X1 - PXOR X1,X11 - PSRLL $25,X2 - PXOR X2,X11 - MOVOA X12,X1 - PADDL X14,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X15 - PSRLL $23,X2 - PXOR X2,X15 - MOVOA X0,X1 - PADDL X11,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X9 - PSRLL $23,X2 - PXOR X2,X9 - MOVOA X14,X1 - PADDL X15,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X13 - PSRLL $19,X2 - PXOR X2,X13 - MOVOA X11,X1 - PADDL X9,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X7 - PSRLL $19,X2 - PXOR X2,X7 - MOVOA X15,X1 - PADDL X13,X1 - MOVOA X1,X2 - PSLLL $18,X1 - PXOR X1,X12 - PSRLL $14,X2 - PXOR X2,X12 - MOVOA 320(SP),X1 - MOVOA X12,320(SP) - MOVOA X9,X2 - PADDL X7,X2 - MOVOA X2,X12 - PSLLL $18,X2 - PXOR X2,X0 - PSRLL $14,X12 - PXOR X12,X0 - MOVOA X5,X2 - PADDL X1,X2 - MOVOA X2,X12 - PSLLL $7,X2 - PXOR X2,X3 - PSRLL $25,X12 - PXOR X12,X3 - MOVOA 336(SP),X2 - MOVOA X0,336(SP) - MOVOA X6,X0 - PADDL X2,X0 - MOVOA X0,X12 - PSLLL $7,X0 - PXOR X0,X4 - PSRLL $25,X12 - PXOR X12,X4 - MOVOA X1,X0 - PADDL X3,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X10 - PSRLL $23,X12 - PXOR X12,X10 - MOVOA X2,X0 - PADDL X4,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X8 - PSRLL $23,X12 - PXOR X12,X8 - MOVOA X3,X0 - PADDL X10,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X5 - PSRLL $19,X12 - PXOR X12,X5 - MOVOA X4,X0 - PADDL X8,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X6 - PSRLL $19,X12 - PXOR X12,X6 - MOVOA X10,X0 - PADDL X5,X0 - MOVOA X0,X12 - PSLLL $18,X0 - PXOR X0,X1 - PSRLL $14,X12 - PXOR X12,X1 - MOVOA 320(SP),X0 - MOVOA X1,320(SP) - MOVOA X4,X1 - PADDL X0,X1 - MOVOA X1,X12 - PSLLL $7,X1 - PXOR X1,X7 - PSRLL $25,X12 - PXOR X12,X7 - MOVOA X8,X1 - PADDL X6,X1 - MOVOA X1,X12 - PSLLL $18,X1 - PXOR X1,X2 - PSRLL $14,X12 - PXOR X12,X2 - MOVOA 336(SP),X12 - MOVOA X2,336(SP) - MOVOA X14,X1 - PADDL X12,X1 - MOVOA X1,X2 - PSLLL $7,X1 - PXOR X1,X5 - PSRLL $25,X2 - PXOR X2,X5 - MOVOA X0,X1 - PADDL X7,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X10 - PSRLL $23,X2 - PXOR X2,X10 - MOVOA X12,X1 - PADDL X5,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X8 - PSRLL $23,X2 - PXOR X2,X8 - MOVOA X7,X1 - PADDL X10,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X4 - PSRLL $19,X2 - PXOR X2,X4 - MOVOA X5,X1 - PADDL X8,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X14 - PSRLL $19,X2 - PXOR X2,X14 - MOVOA X10,X1 - PADDL X4,X1 - MOVOA X1,X2 - PSLLL $18,X1 - PXOR X1,X0 - PSRLL $14,X2 - PXOR X2,X0 - MOVOA 320(SP),X1 - MOVOA X0,320(SP) - MOVOA X8,X0 - PADDL X14,X0 - MOVOA X0,X2 - PSLLL $18,X0 - PXOR X0,X12 - PSRLL $14,X2 - PXOR X2,X12 - MOVOA X11,X0 - PADDL X1,X0 - MOVOA X0,X2 - PSLLL $7,X0 - PXOR X0,X6 - PSRLL $25,X2 - PXOR X2,X6 - MOVOA 336(SP),X2 - MOVOA X12,336(SP) - MOVOA X3,X0 - PADDL X2,X0 - MOVOA X0,X12 - PSLLL $7,X0 - PXOR X0,X13 - PSRLL $25,X12 - PXOR X12,X13 - MOVOA X1,X0 - PADDL X6,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X15 - PSRLL $23,X12 - PXOR X12,X15 - MOVOA X2,X0 - PADDL X13,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X9 - PSRLL $23,X12 - PXOR X12,X9 - MOVOA X6,X0 - PADDL X15,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X11 - PSRLL $19,X12 - PXOR X12,X11 - MOVOA X13,X0 - PADDL X9,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X3 - PSRLL $19,X12 - PXOR X12,X3 - MOVOA X15,X0 - PADDL X11,X0 - MOVOA X0,X12 - PSLLL $18,X0 - PXOR X0,X1 - PSRLL $14,X12 - PXOR X12,X1 - MOVOA X9,X0 - PADDL X3,X0 - MOVOA X0,X12 - PSLLL $18,X0 - PXOR X0,X2 - PSRLL $14,X12 - PXOR X12,X2 - MOVOA 320(SP),X12 - MOVOA 336(SP),X0 - SUBQ $2,DX - JA MAINLOOP1 - PADDL 112(SP),X12 - PADDL 176(SP),X7 - PADDL 224(SP),X10 - PADDL 272(SP),X4 - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - PSHUFL $0X39,X12,X12 - PSHUFL $0X39,X7,X7 - PSHUFL $0X39,X10,X10 - PSHUFL $0X39,X4,X4 - XORL 0(SI),DX - XORL 4(SI),CX - XORL 8(SI),R8 - XORL 12(SI),R9 - MOVL DX,0(DI) - MOVL CX,4(DI) - MOVL R8,8(DI) - MOVL R9,12(DI) - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - PSHUFL $0X39,X12,X12 - PSHUFL $0X39,X7,X7 - PSHUFL $0X39,X10,X10 - PSHUFL $0X39,X4,X4 - XORL 64(SI),DX - XORL 68(SI),CX - XORL 72(SI),R8 - XORL 76(SI),R9 - MOVL DX,64(DI) - MOVL CX,68(DI) - MOVL R8,72(DI) - MOVL R9,76(DI) - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - PSHUFL $0X39,X12,X12 - PSHUFL $0X39,X7,X7 - PSHUFL $0X39,X10,X10 - PSHUFL $0X39,X4,X4 - XORL 128(SI),DX - XORL 132(SI),CX - XORL 136(SI),R8 - XORL 140(SI),R9 - MOVL DX,128(DI) - MOVL CX,132(DI) - MOVL R8,136(DI) - MOVL R9,140(DI) - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - XORL 192(SI),DX - XORL 196(SI),CX - XORL 200(SI),R8 - XORL 204(SI),R9 - MOVL DX,192(DI) - MOVL CX,196(DI) - MOVL R8,200(DI) - MOVL R9,204(DI) - PADDL 240(SP),X14 - PADDL 64(SP),X0 - PADDL 128(SP),X5 - PADDL 192(SP),X8 - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - PSHUFL $0X39,X14,X14 - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X5,X5 - PSHUFL $0X39,X8,X8 - XORL 16(SI),DX - XORL 20(SI),CX - XORL 24(SI),R8 - XORL 28(SI),R9 - MOVL DX,16(DI) - MOVL CX,20(DI) - MOVL R8,24(DI) - MOVL R9,28(DI) - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - PSHUFL $0X39,X14,X14 - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X5,X5 - PSHUFL $0X39,X8,X8 - XORL 80(SI),DX - XORL 84(SI),CX - XORL 88(SI),R8 - XORL 92(SI),R9 - MOVL DX,80(DI) - MOVL CX,84(DI) - MOVL R8,88(DI) - MOVL R9,92(DI) - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - PSHUFL $0X39,X14,X14 - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X5,X5 - PSHUFL $0X39,X8,X8 - XORL 144(SI),DX - XORL 148(SI),CX - XORL 152(SI),R8 - XORL 156(SI),R9 - MOVL DX,144(DI) - MOVL CX,148(DI) - MOVL R8,152(DI) - MOVL R9,156(DI) - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - XORL 208(SI),DX - XORL 212(SI),CX - XORL 216(SI),R8 - XORL 220(SI),R9 - MOVL DX,208(DI) - MOVL CX,212(DI) - MOVL R8,216(DI) - MOVL R9,220(DI) - PADDL 288(SP),X15 - PADDL 304(SP),X11 - PADDL 80(SP),X1 - PADDL 144(SP),X6 - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - PSHUFL $0X39,X15,X15 - PSHUFL $0X39,X11,X11 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X6,X6 - XORL 32(SI),DX - XORL 36(SI),CX - XORL 40(SI),R8 - XORL 44(SI),R9 - MOVL DX,32(DI) - MOVL CX,36(DI) - MOVL R8,40(DI) - MOVL R9,44(DI) - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - PSHUFL $0X39,X15,X15 - PSHUFL $0X39,X11,X11 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X6,X6 - XORL 96(SI),DX - XORL 100(SI),CX - XORL 104(SI),R8 - XORL 108(SI),R9 - MOVL DX,96(DI) - MOVL CX,100(DI) - MOVL R8,104(DI) - MOVL R9,108(DI) - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - PSHUFL $0X39,X15,X15 - PSHUFL $0X39,X11,X11 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X6,X6 - XORL 160(SI),DX - XORL 164(SI),CX - XORL 168(SI),R8 - XORL 172(SI),R9 - MOVL DX,160(DI) - MOVL CX,164(DI) - MOVL R8,168(DI) - MOVL R9,172(DI) - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - XORL 224(SI),DX - XORL 228(SI),CX - XORL 232(SI),R8 - XORL 236(SI),R9 - MOVL DX,224(DI) - MOVL CX,228(DI) - MOVL R8,232(DI) - MOVL R9,236(DI) - PADDL 160(SP),X13 - PADDL 208(SP),X9 - PADDL 256(SP),X3 - PADDL 96(SP),X2 - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - PSHUFL $0X39,X13,X13 - PSHUFL $0X39,X9,X9 - PSHUFL $0X39,X3,X3 - PSHUFL $0X39,X2,X2 - XORL 48(SI),DX - XORL 52(SI),CX - XORL 56(SI),R8 - XORL 60(SI),R9 - MOVL DX,48(DI) - MOVL CX,52(DI) - MOVL R8,56(DI) - MOVL R9,60(DI) - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - PSHUFL $0X39,X13,X13 - PSHUFL $0X39,X9,X9 - PSHUFL $0X39,X3,X3 - PSHUFL $0X39,X2,X2 - XORL 112(SI),DX - XORL 116(SI),CX - XORL 120(SI),R8 - XORL 124(SI),R9 - MOVL DX,112(DI) - MOVL CX,116(DI) - MOVL R8,120(DI) - MOVL R9,124(DI) - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - PSHUFL $0X39,X13,X13 - PSHUFL $0X39,X9,X9 - PSHUFL $0X39,X3,X3 - PSHUFL $0X39,X2,X2 - XORL 176(SI),DX - XORL 180(SI),CX - XORL 184(SI),R8 - XORL 188(SI),R9 - MOVL DX,176(DI) - MOVL CX,180(DI) - MOVL R8,184(DI) - MOVL R9,188(DI) - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - XORL 240(SI),DX - XORL 244(SI),CX - XORL 248(SI),R8 - XORL 252(SI),R9 - MOVL DX,240(DI) - MOVL CX,244(DI) - MOVL R8,248(DI) - MOVL R9,252(DI) - MOVQ 352(SP),R9 - SUBQ $256,R9 - ADDQ $256,SI - ADDQ $256,DI - CMPQ R9,$256 - JAE BYTESATLEAST256 - CMPQ R9,$0 - JBE DONE - BYTESBETWEEN1AND255: - CMPQ R9,$64 - JAE NOCOPY - MOVQ DI,DX - LEAQ 360(SP),DI - MOVQ R9,CX - REP; MOVSB - LEAQ 360(SP),DI - LEAQ 360(SP),SI - NOCOPY: - MOVQ R9,352(SP) - MOVOA 48(SP),X0 - MOVOA 0(SP),X1 - MOVOA 16(SP),X2 - MOVOA 32(SP),X3 - MOVOA X1,X4 - MOVQ $20,CX - MAINLOOP2: - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X3 - PXOR X6,X3 - PADDL X3,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X3,X3 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X1 - PSHUFL $0X4E,X2,X2 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X1,X1 - PXOR X6,X0 - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X1 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X1,X1 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X3 - PSHUFL $0X4E,X2,X2 - PXOR X6,X3 - PADDL X3,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X3,X3 - PXOR X6,X0 - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X3 - PXOR X6,X3 - PADDL X3,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X3,X3 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X1 - PSHUFL $0X4E,X2,X2 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X1,X1 - PXOR X6,X0 - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X1 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X1,X1 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X3 - PSHUFL $0X4E,X2,X2 - PXOR X6,X3 - SUBQ $4,CX - PADDL X3,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PXOR X7,X7 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X3,X3 - PXOR X6,X0 - JA MAINLOOP2 - PADDL 48(SP),X0 - PADDL 0(SP),X1 - PADDL 16(SP),X2 - PADDL 32(SP),X3 - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X2,X2 - PSHUFL $0X39,X3,X3 - XORL 0(SI),CX - XORL 48(SI),R8 - XORL 32(SI),R9 - XORL 16(SI),AX - MOVL CX,0(DI) - MOVL R8,48(DI) - MOVL R9,32(DI) - MOVL AX,16(DI) - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X2,X2 - PSHUFL $0X39,X3,X3 - XORL 20(SI),CX - XORL 4(SI),R8 - XORL 52(SI),R9 - XORL 36(SI),AX - MOVL CX,20(DI) - MOVL R8,4(DI) - MOVL R9,52(DI) - MOVL AX,36(DI) - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X2,X2 - PSHUFL $0X39,X3,X3 - XORL 40(SI),CX - XORL 24(SI),R8 - XORL 8(SI),R9 - XORL 56(SI),AX - MOVL CX,40(DI) - MOVL R8,24(DI) - MOVL R9,8(DI) - MOVL AX,56(DI) - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - XORL 60(SI),CX - XORL 44(SI),R8 - XORL 28(SI),R9 - XORL 12(SI),AX - MOVL CX,60(DI) - MOVL R8,44(DI) - MOVL R9,28(DI) - MOVL AX,12(DI) - MOVQ 352(SP),R9 - MOVL 16(SP),CX - MOVL 36 (SP),R8 - ADDQ $1,CX - SHLQ $32,R8 - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $32,R8 - MOVL CX,16(SP) - MOVL R8, 36 (SP) - CMPQ R9,$64 - JA BYTESATLEAST65 - JAE BYTESATLEAST64 - MOVQ DI,SI - MOVQ DX,DI - MOVQ R9,CX - REP; MOVSB - BYTESATLEAST64: - DONE: - MOVQ R12,SP - RET - BYTESATLEAST65: - SUBQ $64,R9 - ADDQ $64,DI - ADDQ $64,SI - JMP BYTESBETWEEN1AND255 diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go deleted file mode 100644 index 8a46bd2b3af..00000000000 --- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !amd64 appengine gccgo - -package salsa - -// XORKeyStream crypts bytes from in to out using the given key and counters. -// In and out must overlap entirely or not at all. Counter -// contains the raw salsa20 counter bytes (both nonce and block counter). -func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { - genericXORKeyStream(out, in, counter, key) -} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go deleted file mode 100644 index 68169c6d681..00000000000 --- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package salsa - -const rounds = 20 - -// core applies the Salsa20 core function to 16-byte input in, 32-byte key k, -// and 16-byte constant c, and puts the result into 64-byte array out. -func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { - j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 - j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 - j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 - j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 - j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 - j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 - j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 - j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 - j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 - j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 - j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 - j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 - j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 - j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 - j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 - j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 - - x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 - x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 - - for i := 0; i < rounds; i += 2 { - u := x0 + x12 - x4 ^= u<<7 | u>>(32-7) - u = x4 + x0 - x8 ^= u<<9 | u>>(32-9) - u = x8 + x4 - x12 ^= u<<13 | u>>(32-13) - u = x12 + x8 - x0 ^= u<<18 | u>>(32-18) - - u = x5 + x1 - x9 ^= u<<7 | u>>(32-7) - u = x9 + x5 - x13 ^= u<<9 | u>>(32-9) - u = x13 + x9 - x1 ^= u<<13 | u>>(32-13) - u = x1 + x13 - x5 ^= u<<18 | u>>(32-18) - - u = x10 + x6 - x14 ^= u<<7 | u>>(32-7) - u = x14 + x10 - x2 ^= u<<9 | u>>(32-9) - u = x2 + x14 - x6 ^= u<<13 | u>>(32-13) - u = x6 + x2 - x10 ^= u<<18 | u>>(32-18) - - u = x15 + x11 - x3 ^= u<<7 | u>>(32-7) - u = x3 + x15 - x7 ^= u<<9 | u>>(32-9) - u = x7 + x3 - x11 ^= u<<13 | u>>(32-13) - u = x11 + x7 - x15 ^= u<<18 | u>>(32-18) - - u = x0 + x3 - x1 ^= u<<7 | u>>(32-7) - u = x1 + x0 - x2 ^= u<<9 | u>>(32-9) - u = x2 + x1 - x3 ^= u<<13 | u>>(32-13) - u = x3 + x2 - x0 ^= u<<18 | u>>(32-18) - - u = x5 + x4 - x6 ^= u<<7 | u>>(32-7) - u = x6 + x5 - x7 ^= u<<9 | u>>(32-9) - u = x7 + x6 - x4 ^= u<<13 | u>>(32-13) - u = x4 + x7 - x5 ^= u<<18 | u>>(32-18) - - u = x10 + x9 - x11 ^= u<<7 | u>>(32-7) - u = x11 + x10 - x8 ^= u<<9 | u>>(32-9) - u = x8 + x11 - x9 ^= u<<13 | u>>(32-13) - u = x9 + x8 - x10 ^= u<<18 | u>>(32-18) - - u = x15 + x14 - x12 ^= u<<7 | u>>(32-7) - u = x12 + x15 - x13 ^= u<<9 | u>>(32-9) - u = x13 + x12 - x14 ^= u<<13 | u>>(32-13) - u = x14 + x13 - x15 ^= u<<18 | u>>(32-18) - } - x0 += j0 - x1 += j1 - x2 += j2 - x3 += j3 - x4 += j4 - x5 += j5 - x6 += j6 - x7 += j7 - x8 += j8 - x9 += j9 - x10 += j10 - x11 += j11 - x12 += j12 - x13 += j13 - x14 += j14 - x15 += j15 - - out[0] = byte(x0) - out[1] = byte(x0 >> 8) - out[2] = byte(x0 >> 16) - out[3] = byte(x0 >> 24) - - out[4] = byte(x1) - out[5] = byte(x1 >> 8) - out[6] = byte(x1 >> 16) - out[7] = byte(x1 >> 24) - - out[8] = byte(x2) - out[9] = byte(x2 >> 8) - out[10] = byte(x2 >> 16) - out[11] = byte(x2 >> 24) - - out[12] = byte(x3) - out[13] = byte(x3 >> 8) - out[14] = byte(x3 >> 16) - out[15] = byte(x3 >> 24) - - out[16] = byte(x4) - out[17] = byte(x4 >> 8) - out[18] = byte(x4 >> 16) - out[19] = byte(x4 >> 24) - - out[20] = byte(x5) - out[21] = byte(x5 >> 8) - out[22] = byte(x5 >> 16) - out[23] = byte(x5 >> 24) - - out[24] = byte(x6) - out[25] = byte(x6 >> 8) - out[26] = byte(x6 >> 16) - out[27] = byte(x6 >> 24) - - out[28] = byte(x7) - out[29] = byte(x7 >> 8) - out[30] = byte(x7 >> 16) - out[31] = byte(x7 >> 24) - - out[32] = byte(x8) - out[33] = byte(x8 >> 8) - out[34] = byte(x8 >> 16) - out[35] = byte(x8 >> 24) - - out[36] = byte(x9) - out[37] = byte(x9 >> 8) - out[38] = byte(x9 >> 16) - out[39] = byte(x9 >> 24) - - out[40] = byte(x10) - out[41] = byte(x10 >> 8) - out[42] = byte(x10 >> 16) - out[43] = byte(x10 >> 24) - - out[44] = byte(x11) - out[45] = byte(x11 >> 8) - out[46] = byte(x11 >> 16) - out[47] = byte(x11 >> 24) - - out[48] = byte(x12) - out[49] = byte(x12 >> 8) - out[50] = byte(x12 >> 16) - out[51] = byte(x12 >> 24) - - out[52] = byte(x13) - out[53] = byte(x13 >> 8) - out[54] = byte(x13 >> 16) - out[55] = byte(x13 >> 24) - - out[56] = byte(x14) - out[57] = byte(x14 >> 8) - out[58] = byte(x14 >> 16) - out[59] = byte(x14 >> 24) - - out[60] = byte(x15) - out[61] = byte(x15 >> 8) - out[62] = byte(x15 >> 16) - out[63] = byte(x15 >> 24) -} - -// genericXORKeyStream is the generic implementation of XORKeyStream to be used -// when no assembly implementation is available. -func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { - var block [64]byte - var counterCopy [16]byte - copy(counterCopy[:], counter[:]) - - for len(in) >= 64 { - core(&block, &counterCopy, key, &Sigma) - for i, x := range block { - out[i] = in[i] ^ x - } - u := uint32(1) - for i := 8; i < 16; i++ { - u += uint32(counterCopy[i]) - counterCopy[i] = byte(u) - u >>= 8 - } - in = in[64:] - out = out[64:] - } - - if len(in) > 0 { - core(&block, &counterCopy, key, &Sigma) - for i, v := range in { - out[i] = v ^ block[i] - } - } -} diff --git a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s deleted file mode 100644 index 06f84b85558..00000000000 --- a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go -// - -TEXT ·syscall6(SB),NOSPLIT,$0-88 - JMP syscall·syscall6(SB) - -TEXT ·rawSyscall6(SB),NOSPLIT,$0-88 - JMP syscall·rawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/cpu/byteorder.go b/vendor/golang.org/x/sys/cpu/byteorder.go deleted file mode 100644 index da6b9e4363d..00000000000 --- a/vendor/golang.org/x/sys/cpu/byteorder.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "encoding/binary" - "runtime" -) - -// hostByteOrder returns binary.LittleEndian on little-endian machines and -// binary.BigEndian on big-endian machines. -func hostByteOrder() binary.ByteOrder { - switch runtime.GOARCH { - case "386", "amd64", "amd64p32", - "arm", "arm64", - "mipsle", "mips64le", "mips64p32le", - "ppc64le", - "riscv", "riscv64": - return binary.LittleEndian - case "armbe", "arm64be", - "mips", "mips64", "mips64p32", - "ppc", "ppc64", - "s390", "s390x", - "sparc", "sparc64": - return binary.BigEndian - } - panic("unknown architecture") -} diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go deleted file mode 100644 index 679e78c2cef..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package cpu implements processor feature detection for -// various CPU architectures. -package cpu - -// Initialized reports whether the CPU features were initialized. -// -// For some GOOS/GOARCH combinations initialization of the CPU features depends -// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm -// Initialized will report false if reading the file fails. -var Initialized bool - -// CacheLinePad is used to pad structs to avoid false sharing. -type CacheLinePad struct{ _ [cacheLineSize]byte } - -// X86 contains the supported CPU features of the -// current X86/AMD64 platform. If the current platform -// is not X86/AMD64 then all feature flags are false. -// -// X86 is padded to avoid false sharing. Further the HasAVX -// and HasAVX2 are only set if the OS supports XMM and YMM -// registers in addition to the CPUID feature bit being set. -var X86 struct { - _ CacheLinePad - HasAES bool // AES hardware implementation (AES NI) - HasADX bool // Multi-precision add-carry instruction extensions - HasAVX bool // Advanced vector extension - HasAVX2 bool // Advanced vector extension 2 - HasBMI1 bool // Bit manipulation instruction set 1 - HasBMI2 bool // Bit manipulation instruction set 2 - HasERMS bool // Enhanced REP for MOVSB and STOSB - HasFMA bool // Fused-multiply-add instructions - HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. - HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM - HasPOPCNT bool // Hamming weight instruction POPCNT. - HasRDRAND bool // RDRAND instruction (on-chip random number generator) - HasRDSEED bool // RDSEED instruction (on-chip random number generator) - HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) - HasSSE3 bool // Streaming SIMD extension 3 - HasSSSE3 bool // Supplemental streaming SIMD extension 3 - HasSSE41 bool // Streaming SIMD extension 4 and 4.1 - HasSSE42 bool // Streaming SIMD extension 4 and 4.2 - _ CacheLinePad -} - -// ARM64 contains the supported CPU features of the -// current ARMv8(aarch64) platform. If the current platform -// is not arm64 then all feature flags are false. -var ARM64 struct { - _ CacheLinePad - HasFP bool // Floating-point instruction set (always available) - HasASIMD bool // Advanced SIMD (always available) - HasEVTSTRM bool // Event stream support - HasAES bool // AES hardware implementation - HasPMULL bool // Polynomial multiplication instruction set - HasSHA1 bool // SHA1 hardware implementation - HasSHA2 bool // SHA2 hardware implementation - HasCRC32 bool // CRC32 hardware implementation - HasATOMICS bool // Atomic memory operation instruction set - HasFPHP bool // Half precision floating-point instruction set - HasASIMDHP bool // Advanced SIMD half precision instruction set - HasCPUID bool // CPUID identification scheme registers - HasASIMDRDM bool // Rounding double multiply add/subtract instruction set - HasJSCVT bool // Javascript conversion from floating-point to integer - HasFCMA bool // Floating-point multiplication and addition of complex numbers - HasLRCPC bool // Release Consistent processor consistent support - HasDCPOP bool // Persistent memory support - HasSHA3 bool // SHA3 hardware implementation - HasSM3 bool // SM3 hardware implementation - HasSM4 bool // SM4 hardware implementation - HasASIMDDP bool // Advanced SIMD double precision instruction set - HasSHA512 bool // SHA512 hardware implementation - HasSVE bool // Scalable Vector Extensions - HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 - _ CacheLinePad -} - -// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. -// If the current platform is not ppc64/ppc64le then all feature flags are false. -// -// For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, -// since there are no optional categories. There are some exceptions that also -// require kernel support to work (DARN, SCV), so there are feature bits for -// those as well. The minimum processor requirement is POWER8 (ISA 2.07). -// The struct is padded to avoid false sharing. -var PPC64 struct { - _ CacheLinePad - HasDARN bool // Hardware random number generator (requires kernel enablement) - HasSCV bool // Syscall vectored (requires kernel enablement) - IsPOWER8 bool // ISA v2.07 (POWER8) - IsPOWER9 bool // ISA v3.00 (POWER9) - _ CacheLinePad -} - -// S390X contains the supported CPU features of the current IBM Z -// (s390x) platform. If the current platform is not IBM Z then all -// feature flags are false. -// -// S390X is padded to avoid false sharing. Further HasVX is only set -// if the OS supports vector registers in addition to the STFLE -// feature bit being set. -var S390X struct { - _ CacheLinePad - HasZARCH bool // z/Architecture mode is active [mandatory] - HasSTFLE bool // store facility list extended - HasLDISP bool // long (20-bit) displacements - HasEIMM bool // 32-bit immediates - HasDFP bool // decimal floating point - HasETF3EH bool // ETF-3 enhanced - HasMSA bool // message security assist (CPACF) - HasAES bool // KM-AES{128,192,256} functions - HasAESCBC bool // KMC-AES{128,192,256} functions - HasAESCTR bool // KMCTR-AES{128,192,256} functions - HasAESGCM bool // KMA-GCM-AES{128,192,256} functions - HasGHASH bool // KIMD-GHASH function - HasSHA1 bool // K{I,L}MD-SHA-1 functions - HasSHA256 bool // K{I,L}MD-SHA-256 functions - HasSHA512 bool // K{I,L}MD-SHA-512 functions - HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions - HasVX bool // vector facility - HasVXE bool // vector-enhancements facility 1 - _ CacheLinePad -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go b/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go deleted file mode 100644 index be602722472..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix,ppc64 - -package cpu - -const cacheLineSize = 128 - -const ( - // getsystemcfg constants - _SC_IMPL = 2 - _IMPL_POWER8 = 0x10000 - _IMPL_POWER9 = 0x20000 -) - -func init() { - impl := getsystemcfg(_SC_IMPL) - if impl&_IMPL_POWER8 != 0 { - PPC64.IsPOWER8 = true - } - if impl&_IMPL_POWER9 != 0 { - PPC64.IsPOWER9 = true - } - - Initialized = true -} - -func getsystemcfg(label int) (n uint64) { - r0, _ := callgetsystemcfg(label) - n = uint64(r0) - return -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go deleted file mode 100644 index 7f2348b7d4b..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_arm.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const cacheLineSize = 32 - -func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go deleted file mode 100644 index 568bcd031aa..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -package cpu - -// haveAsmFunctions reports whether the other functions in this file can -// be safely called. -func haveAsmFunctions() bool { return true } - -// The following feature detection functions are defined in cpu_s390x.s. -// They are likely to be expensive to call so the results should be cached. -func stfle() facilityList -func kmQuery() queryResult -func kmcQuery() queryResult -func kmctrQuery() queryResult -func kmaQuery() queryResult -func kimdQuery() queryResult -func klmdQuery() queryResult diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go deleted file mode 100644 index f7cb46971cb..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build 386 amd64 amd64p32 -// +build !gccgo - -package cpu - -// cpuid is implemented in cpu_x86.s for gc compiler -// and in cpu_gccgo.c for gccgo. -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) - -// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler -// and in cpu_gccgo.c for gccgo. -func xgetbv() (eax, edx uint32) diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo.c b/vendor/golang.org/x/sys/cpu/cpu_gccgo.c deleted file mode 100644 index e363c7d1319..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo.c +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build 386 amd64 amd64p32 -// +build gccgo - -#include -#include - -// Need to wrap __get_cpuid_count because it's declared as static. -int -gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, - uint32_t *eax, uint32_t *ebx, - uint32_t *ecx, uint32_t *edx) -{ - return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); -} - -// xgetbv reads the contents of an XCR (Extended Control Register) -// specified in the ECX register into registers EDX:EAX. -// Currently, the only supported value for XCR is 0. -// -// TODO: Replace with a better alternative: -// -// #include -// -// #pragma GCC target("xsave") -// -// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { -// unsigned long long x = _xgetbv(0); -// *eax = x & 0xffffffff; -// *edx = (x >> 32) & 0xffffffff; -// } -// -// Note that _xgetbv is defined starting with GCC 8. -void -gccgoXgetbv(uint32_t *eax, uint32_t *edx) -{ - __asm(" xorl %%ecx, %%ecx\n" - " xgetbv" - : "=a"(*eax), "=d"(*edx)); -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo.go deleted file mode 100644 index ba49b91bd39..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build 386 amd64 amd64p32 -// +build gccgo - -package cpu - -//extern gccgoGetCpuidCount -func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) - -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { - var a, b, c, d uint32 - gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) - return a, b, c, d -} - -//extern gccgoXgetbv -func gccgoXgetbv(eax, edx *uint32) - -func xgetbv() (eax, edx uint32) { - var a, d uint32 - gccgoXgetbv(&a, &d) - return a, d -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go deleted file mode 100644 index aa986f77825..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build gccgo - -package cpu - -// haveAsmFunctions reports whether the other functions in this file can -// be safely called. -func haveAsmFunctions() bool { return false } - -// TODO(mundaym): the following feature detection functions are currently -// stubs. See https://golang.org/cl/162887 for how to fix this. -// They are likely to be expensive to call so the results should be cached. -func stfle() facilityList { panic("not implemented for gccgo") } -func kmQuery() queryResult { panic("not implemented for gccgo") } -func kmcQuery() queryResult { panic("not implemented for gccgo") } -func kmctrQuery() queryResult { panic("not implemented for gccgo") } -func kmaQuery() queryResult { panic("not implemented for gccgo") } -func kimdQuery() queryResult { panic("not implemented for gccgo") } -func klmdQuery() queryResult { panic("not implemented for gccgo") } diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux.go b/vendor/golang.org/x/sys/cpu/cpu_linux.go deleted file mode 100644 index 76b5f507faf..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//+build !amd64,!amd64p32,!386 - -package cpu - -import ( - "io/ioutil" -) - -const ( - _AT_HWCAP = 16 - _AT_HWCAP2 = 26 - - procAuxv = "/proc/self/auxv" - - uintSize = int(32 << (^uint(0) >> 63)) -) - -// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2 -// These are initialized in cpu_$GOARCH.go -// and should not be changed after they are initialized. -var hwCap uint -var hwCap2 uint - -func init() { - buf, err := ioutil.ReadFile(procAuxv) - if err != nil { - // e.g. on android /proc/self/auxv is not accessible, so silently - // ignore the error and leave Initialized = false - return - } - - bo := hostByteOrder() - for len(buf) >= 2*(uintSize/8) { - var tag, val uint - switch uintSize { - case 32: - tag = uint(bo.Uint32(buf[0:])) - val = uint(bo.Uint32(buf[4:])) - buf = buf[8:] - case 64: - tag = uint(bo.Uint64(buf[0:])) - val = uint(bo.Uint64(buf[8:])) - buf = buf[16:] - } - switch tag { - case _AT_HWCAP: - hwCap = val - case _AT_HWCAP2: - hwCap2 = val - } - } - doinit() - - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go deleted file mode 100644 index fa7fb1bd7b2..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const cacheLineSize = 64 - -// HWCAP/HWCAP2 bits. These are exposed by Linux. -const ( - hwcap_FP = 1 << 0 - hwcap_ASIMD = 1 << 1 - hwcap_EVTSTRM = 1 << 2 - hwcap_AES = 1 << 3 - hwcap_PMULL = 1 << 4 - hwcap_SHA1 = 1 << 5 - hwcap_SHA2 = 1 << 6 - hwcap_CRC32 = 1 << 7 - hwcap_ATOMICS = 1 << 8 - hwcap_FPHP = 1 << 9 - hwcap_ASIMDHP = 1 << 10 - hwcap_CPUID = 1 << 11 - hwcap_ASIMDRDM = 1 << 12 - hwcap_JSCVT = 1 << 13 - hwcap_FCMA = 1 << 14 - hwcap_LRCPC = 1 << 15 - hwcap_DCPOP = 1 << 16 - hwcap_SHA3 = 1 << 17 - hwcap_SM3 = 1 << 18 - hwcap_SM4 = 1 << 19 - hwcap_ASIMDDP = 1 << 20 - hwcap_SHA512 = 1 << 21 - hwcap_SVE = 1 << 22 - hwcap_ASIMDFHM = 1 << 23 -) - -func doinit() { - // HWCAP feature bits - ARM64.HasFP = isSet(hwCap, hwcap_FP) - ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD) - ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) - ARM64.HasAES = isSet(hwCap, hwcap_AES) - ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL) - ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1) - ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2) - ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32) - ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS) - ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP) - ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP) - ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID) - ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM) - ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT) - ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA) - ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC) - ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP) - ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3) - ARM64.HasSM3 = isSet(hwCap, hwcap_SM3) - ARM64.HasSM4 = isSet(hwCap, hwcap_SM4) - ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP) - ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) - ARM64.HasSVE = isSet(hwCap, hwcap_SVE) - ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go deleted file mode 100644 index 6c8d975d40a..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux -// +build ppc64 ppc64le - -package cpu - -const cacheLineSize = 128 - -// HWCAP/HWCAP2 bits. These are exposed by the kernel. -const ( - // ISA Level - _PPC_FEATURE2_ARCH_2_07 = 0x80000000 - _PPC_FEATURE2_ARCH_3_00 = 0x00800000 - - // CPU features - _PPC_FEATURE2_DARN = 0x00200000 - _PPC_FEATURE2_SCV = 0x00100000 -) - -func doinit() { - // HWCAP2 feature bits - PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) - PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) - PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) - PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go deleted file mode 100644 index d579eaef404..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const cacheLineSize = 256 - -const ( - // bit mask values from /usr/include/bits/hwcap.h - hwcap_ZARCH = 2 - hwcap_STFLE = 4 - hwcap_MSA = 8 - hwcap_LDISP = 16 - hwcap_EIMM = 32 - hwcap_DFP = 64 - hwcap_ETF3EH = 256 - hwcap_VX = 2048 - hwcap_VXE = 8192 -) - -// bitIsSet reports whether the bit at index is set. The bit index -// is in big endian order, so bit index 0 is the leftmost bit. -func bitIsSet(bits []uint64, index uint) bool { - return bits[index/64]&((1<<63)>>(index%64)) != 0 -} - -// function is the code for the named cryptographic function. -type function uint8 - -const ( - // KM{,A,C,CTR} function codes - aes128 function = 18 // AES-128 - aes192 function = 19 // AES-192 - aes256 function = 20 // AES-256 - - // K{I,L}MD function codes - sha1 function = 1 // SHA-1 - sha256 function = 2 // SHA-256 - sha512 function = 3 // SHA-512 - sha3_224 function = 32 // SHA3-224 - sha3_256 function = 33 // SHA3-256 - sha3_384 function = 34 // SHA3-384 - sha3_512 function = 35 // SHA3-512 - shake128 function = 36 // SHAKE-128 - shake256 function = 37 // SHAKE-256 - - // KLMD function codes - ghash function = 65 // GHASH -) - -// queryResult contains the result of a Query function -// call. Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type queryResult struct { - bits [2]uint64 -} - -// Has reports whether the given functions are present. -func (q *queryResult) Has(fns ...function) bool { - if len(fns) == 0 { - panic("no function codes provided") - } - for _, f := range fns { - if !bitIsSet(q.bits[:], uint(f)) { - return false - } - } - return true -} - -// facility is a bit index for the named facility. -type facility uint8 - -const ( - // cryptography facilities - msa4 facility = 77 // message-security-assist extension 4 - msa8 facility = 146 // message-security-assist extension 8 -) - -// facilityList contains the result of an STFLE call. -// Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type facilityList struct { - bits [4]uint64 -} - -// Has reports whether the given facilities are present. -func (s *facilityList) Has(fs ...facility) bool { - if len(fs) == 0 { - panic("no facility bits provided") - } - for _, f := range fs { - if !bitIsSet(s.bits[:], uint(f)) { - return false - } - } - return true -} - -func doinit() { - // test HWCAP bit vector - has := func(featureMask uint) bool { - return hwCap&featureMask == featureMask - } - - // mandatory - S390X.HasZARCH = has(hwcap_ZARCH) - - // optional - S390X.HasSTFLE = has(hwcap_STFLE) - S390X.HasLDISP = has(hwcap_LDISP) - S390X.HasEIMM = has(hwcap_EIMM) - S390X.HasETF3EH = has(hwcap_ETF3EH) - S390X.HasDFP = has(hwcap_DFP) - S390X.HasMSA = has(hwcap_MSA) - S390X.HasVX = has(hwcap_VX) - if S390X.HasVX { - S390X.HasVXE = has(hwcap_VXE) - } - - // We need implementations of stfle, km and so on - // to detect cryptographic features. - if !haveAsmFunctions() { - return - } - - // optional cryptographic functions - if S390X.HasMSA { - aes := []function{aes128, aes192, aes256} - - // cipher message - km, kmc := kmQuery(), kmcQuery() - S390X.HasAES = km.Has(aes...) - S390X.HasAESCBC = kmc.Has(aes...) - if S390X.HasSTFLE { - facilities := stfle() - if facilities.Has(msa4) { - kmctr := kmctrQuery() - S390X.HasAESCTR = kmctr.Has(aes...) - } - if facilities.Has(msa8) { - kma := kmaQuery() - S390X.HasAESGCM = kma.Has(aes...) - } - } - - // compute message digest - kimd := kimdQuery() // intermediate (no padding) - klmd := klmdQuery() // last (padding) - S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) - S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) - S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) - S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist - sha3 := []function{ - sha3_224, sha3_256, sha3_384, sha3_512, - shake128, shake256, - } - S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) - } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go deleted file mode 100644 index f55e0c82c73..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build mips64 mips64le - -package cpu - -const cacheLineSize = 32 - -func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go deleted file mode 100644 index cda87b1a1b1..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build mips mipsle - -package cpu - -const cacheLineSize = 32 - -func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go deleted file mode 100644 index dd1e76dc921..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !linux,arm64 - -package cpu - -const cacheLineSize = 64 - -func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/vendor/golang.org/x/sys/cpu/cpu_s390x.s deleted file mode 100644 index e5037d92e06..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_s390x.s +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// func stfle() facilityList -TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32 - MOVD $ret+0(FP), R1 - MOVD $3, R0 // last doubleword index to store - XC $32, (R1), (R1) // clear 4 doublewords (32 bytes) - WORD $0xb2b01000 // store facility list extended (STFLE) - RET - -// func kmQuery() queryResult -TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KM-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92E0024 // cipher message (KM) - RET - -// func kmcQuery() queryResult -TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMC-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92F0024 // cipher message with chaining (KMC) - RET - -// func kmctrQuery() queryResult -TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMCTR-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92D4024 // cipher message with counter (KMCTR) - RET - -// func kmaQuery() queryResult -TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMA-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xb9296024 // cipher message with authentication (KMA) - RET - -// func kimdQuery() queryResult -TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KIMD-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB93E0024 // compute intermediate message digest (KIMD) - RET - -// func klmdQuery() queryResult -TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KLMD-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB93F0024 // compute last message digest (KLMD) - RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_wasm.go b/vendor/golang.org/x/sys/cpu/cpu_wasm.go deleted file mode 100644 index bd9bbda0c08..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_wasm.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build wasm - -package cpu - -// We're compiling the cpu package for an unknown (software-abstracted) CPU. -// Make CacheLinePad an empty struct and hope that the usual struct alignment -// rules are good enough. - -const cacheLineSize = 0 - -func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go deleted file mode 100644 index d70d317f5a4..00000000000 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build 386 amd64 amd64p32 - -package cpu - -const cacheLineSize = 64 - -func init() { - Initialized = true - - maxID, _, _, _ := cpuid(0, 0) - - if maxID < 1 { - return - } - - _, _, ecx1, edx1 := cpuid(1, 0) - X86.HasSSE2 = isSet(26, edx1) - - X86.HasSSE3 = isSet(0, ecx1) - X86.HasPCLMULQDQ = isSet(1, ecx1) - X86.HasSSSE3 = isSet(9, ecx1) - X86.HasFMA = isSet(12, ecx1) - X86.HasSSE41 = isSet(19, ecx1) - X86.HasSSE42 = isSet(20, ecx1) - X86.HasPOPCNT = isSet(23, ecx1) - X86.HasAES = isSet(25, ecx1) - X86.HasOSXSAVE = isSet(27, ecx1) - X86.HasRDRAND = isSet(30, ecx1) - - osSupportsAVX := false - // For XGETBV, OSXSAVE bit is required and sufficient. - if X86.HasOSXSAVE { - eax, _ := xgetbv() - // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(1, eax) && isSet(2, eax) - } - - X86.HasAVX = isSet(28, ecx1) && osSupportsAVX - - if maxID < 7 { - return - } - - _, ebx7, _, _ := cpuid(7, 0) - X86.HasBMI1 = isSet(3, ebx7) - X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX - X86.HasBMI2 = isSet(8, ebx7) - X86.HasERMS = isSet(9, ebx7) - X86.HasRDSEED = isSet(18, ebx7) - X86.HasADX = isSet(19, ebx7) -} - -func isSet(bitpos uint, value uint32) bool { - return value&(1< Date: Thu, 8 Aug 2019 10:43:06 +0000 Subject: [PATCH 3/4] Add feature and flag changes to CHANGELOG Signed-off-by: Bryan Boreham --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e75c17b4db4..2048cfb2ca0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## master / unreleased +* [FEATURE] You can now specify `http_config` on alert receivers #929 +* [CHANGE] Flags changed due to changes upstream in Prometheus Alertmanager #929: + * `alertmanager.mesh.listen-address` is now `cluster.listen-address` + * `alertmanager.mesh.peer.host` and `alertmanager.mesh.peer.service` can be replaced by `cluster.peer` + * `alertmanager.mesh.hardware-address`, `alertmanager.mesh.nickname`, `alertmanager.mesh.password`, and `alertmanager.mesh.peer.refresh-interval` all disappear. * [CHANGE] Retention period should now be a multiple of periodic table duration #1564 * [FEATURE] Add option to use jump hashing to load balance requests to memcached #1554 * [FEATURE] Add status page for HA tracker to distributors #1546 From f547d62f3f494af28b1044b9ae55f5cb1b55ea89 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Tue, 13 Aug 2019 10:31:05 +0000 Subject: [PATCH 4/4] Remove command-line options for Alertmanager cluster params Don't expect any of these will need to be configured. Signed-off-by: Bryan Boreham --- pkg/alertmanager/multitenant.go | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/pkg/alertmanager/multitenant.go b/pkg/alertmanager/multitenant.go index e1735d75eb5..6d5c371b573 100644 --- a/pkg/alertmanager/multitenant.go +++ b/pkg/alertmanager/multitenant.go @@ -113,13 +113,6 @@ type MultitenantAlertmanagerConfig struct { clusterAdvertiseAddr string peers flagext.StringSlice peerTimeout time.Duration - gossipInterval time.Duration - pushPullInterval time.Duration - tcpTimeout time.Duration - probeTimeout time.Duration - probeInterval time.Duration - reconnectInterval time.Duration - peerReconnectTimeout time.Duration FallbackConfigFile string AutoWebhookRoot string @@ -144,14 +137,6 @@ func (cfg *MultitenantAlertmanagerConfig) RegisterFlags(f *flag.FlagSet) { flag.StringVar(&cfg.clusterAdvertiseAddr, "cluster.advertise-address", "", "Explicit address to advertise in cluster.") flag.Var(&cfg.peers, "cluster.peer", "Initial peers (may be repeated).") flag.DurationVar(&cfg.peerTimeout, "cluster.peer-timeout", time.Second*15, "Time to wait between peers to send notifications.") - flag.DurationVar(&cfg.gossipInterval, "cluster.gossip-interval", cluster.DefaultGossipInterval, "Interval between sending gossip messages. By lowering this value (more frequent) gossip messages are propagated across the cluster more quickly at the expense of increased bandwidth.") - flag.DurationVar(&cfg.pushPullInterval, "cluster.pushpull-interval", cluster.DefaultPushPullInterval, "Interval for gossip state syncs. Setting this interval lower (more frequent) will increase convergence speeds across larger clusters at the expense of increased bandwidth usage.") - flag.DurationVar(&cfg.tcpTimeout, "cluster.tcp-timeout", cluster.DefaultTcpTimeout, "Timeout for establishing a stream connection with a remote node for a full state sync, and for stream read and write operations.") - flag.DurationVar(&cfg.probeTimeout, "cluster.probe-timeout", cluster.DefaultProbeTimeout, "Timeout to wait for an ack from a probed node before assuming it is unhealthy. This should be set to 99-percentile of RTT (round-trip time) on your network.") - flag.DurationVar(&cfg.probeInterval, "cluster.probe-interval", cluster.DefaultProbeInterval, "Interval between random node probes. Setting this lower (more frequent) will cause the cluster to detect failed nodes more quickly at the expense of increased bandwidth usage.") - flag.DurationVar(&cfg.reconnectInterval, "cluster.reconnect-interval", cluster.DefaultReconnectInterval, "Interval between attempting to reconnect to lost peers.") - flag.DurationVar(&cfg.peerReconnectTimeout, "cluster.reconnect-timeout", cluster.DefaultReconnectTimeout, "Length of time to attempt to reconnect to a lost peer.") - } // A MultitenantAlertmanager manages Alertmanager instances for multiple @@ -214,21 +199,21 @@ func NewMultitenantAlertmanager(cfg *MultitenantAlertmanagerConfig, cfgCfg confi cfg.clusterAdvertiseAddr, cfg.peers, true, - cfg.pushPullInterval, - cfg.gossipInterval, - cfg.tcpTimeout, - cfg.probeTimeout, - cfg.probeInterval, + cluster.DefaultPushPullInterval, + cluster.DefaultGossipInterval, + cluster.DefaultTcpTimeout, + cluster.DefaultProbeTimeout, + cluster.DefaultProbeInterval, ) if err != nil { level.Error(util.Logger).Log("msg", "unable to initialize gossip mesh", "err", err) os.Exit(1) } - err = peer.Join(cfg.reconnectInterval, cfg.peerReconnectTimeout) + err = peer.Join(cluster.DefaultReconnectInterval, cluster.DefaultReconnectTimeout) if err != nil { level.Warn(util.Logger).Log("msg", "unable to join gossip mesh", "err", err) } - go peer.Settle(context.Background(), cfg.gossipInterval*10) + go peer.Settle(context.Background(), cluster.DefaultGossipInterval) } am := &MultitenantAlertmanager{