From f5bc9e892a70b64bad040d4493a09cd5f2172486 Mon Sep 17 00:00:00 2001 From: Roland Bracewell Shoemaker Date: Wed, 28 Jun 2017 06:44:58 -0700 Subject: [PATCH] Update github.com/google/safebrowsing and block on database health (#2837) Update github.com/google/safebrowsing and block on database health before starting VA before starting `boulder-va`. ``` $ go test . ok github.com/google/safebrowsing 4.510s $ go test . ok github.com/golang/protobuf/ptypes 0.002s ``` Fixes #2742. --- Godeps/Godeps.json | 8 +- cmd/boulder-va/gsb.go | 8 + .../protobuf/ptypes/duration/duration.pb.go | 114 ++++ .../protobuf/ptypes/duration/duration.proto | 98 ++++ .../google/safebrowsing/.travis.yml | 6 +- vendor/github.com/google/safebrowsing/api.go | 7 +- .../github.com/google/safebrowsing/cache.go | 7 +- .../google/safebrowsing/database.go | 122 +++- .../safebrowsing_proto/safebrowsing.pb.go | 532 +++++++++++++----- .../safebrowsing_proto/safebrowsing.proto | 31 +- .../google/safebrowsing/safebrowser.go | 68 ++- vendor/github.com/google/safebrowsing/urls.go | 8 +- 12 files changed, 793 insertions(+), 216 deletions(-) create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.proto diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 8bbcfd078..6578b2d6f 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -114,6 +114,10 @@ "ImportPath": "github.com/golang/protobuf/proto", "Rev": "c9c7427a2a70d2eb3bafa0ab2dc163e45f143317" }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/duration", + "Rev": "c9c7427a2a70d2eb3bafa0ab2dc163e45f143317" + }, { "ImportPath": "github.com/google/certificate-transparency-go", "Rev": "0dac42a6ed448ba220ee315abfaa6d26fd5fc9bb" @@ -144,11 +148,11 @@ }, { "ImportPath": "github.com/google/safebrowsing", - "Rev": "fc74adc270b82ff5a2f288fa84e40213eae713c5" + "Rev": "a8c029efb52bae66853e05241150ab338e98fbc7" }, { "ImportPath": "github.com/google/safebrowsing/internal/safebrowsing_proto", - "Rev": "fc74adc270b82ff5a2f288fa84e40213eae713c5" + "Rev": "a8c029efb52bae66853e05241150ab338e98fbc7" }, { "ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus", diff --git a/cmd/boulder-va/gsb.go b/cmd/boulder-va/gsb.go index 325dfc41d..6e4ae9bca 100644 --- a/cmd/boulder-va/gsb.go +++ b/cmd/boulder-va/gsb.go @@ -3,9 +3,11 @@ package main import ( + "context" "errors" "os" "path/filepath" + "time" safebrowsingv4 "github.com/google/safebrowsing" "github.com/letsencrypt/boulder/cmd" @@ -119,6 +121,12 @@ func newGoogleSafeBrowsingV4(gsb *cmd.GoogleSafeBrowsingConfig, logger blog.Logg if err != nil { return nil, err } + ctx, cancel := context.WithTimeout(context.Background(), time.Second*60) + defer cancel() // avoid leak + err = sb.WaitUntilReady(ctx) + if err != nil { + return nil, err + } return gsbAdapter{sb}, nil } diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go new file mode 100644 index 000000000..569748346 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go @@ -0,0 +1,114 @@ +// Code generated by protoc-gen-go. +// source: github.com/golang/protobuf/ptypes/duration/duration.proto +// DO NOT EDIT! + +/* +Package duration is a generated protocol buffer package. + +It is generated from these files: + github.com/golang/protobuf/ptypes/duration/duration.proto + +It has these top-level messages: + Duration +*/ +package duration + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// 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.ProtoPackageIsVersion2 // please upgrade the proto package + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (durations.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +// +type Duration struct { + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. + Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` +} + +func (m *Duration) Reset() { *m = Duration{} } +func (m *Duration) String() string { return proto.CompactTextString(m) } +func (*Duration) ProtoMessage() {} +func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Duration) XXX_WellKnownType() string { return "Duration" } + +func init() { + proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") +} + +func init() { + proto.RegisterFile("github.com/golang/protobuf/ptypes/duration/duration.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 189 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4c, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, + 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0x29, + 0x2d, 0x4a, 0x2c, 0xc9, 0xcc, 0xcf, 0x83, 0x33, 0xf4, 0xc0, 0x2a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, + 0xd3, 0x73, 0x52, 0xf5, 0x60, 0xea, 0x95, 0xac, 0xb8, 0x38, 0x5c, 0xa0, 0x4a, 0x84, 0x24, 0xb8, + 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, + 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xd6, + 0x20, 0x08, 0xc7, 0xa9, 0x86, 0x4b, 0x38, 0x39, 0x3f, 0x57, 0x0f, 0xcd, 0x48, 0x27, 0x5e, 0x98, + 0x81, 0x01, 0x20, 0x91, 0x00, 0xc6, 0x28, 0x2d, 0xe2, 0xdd, 0xbb, 0x80, 0x91, 0x71, 0x11, 0x13, + 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xb9, 0x01, 0x50, 0xa5, 0x7a, 0xe1, 0xa9, + 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x2d, 0x49, 0x6c, 0x60, 0x33, 0x8c, 0x01, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x62, 0xfb, 0xb1, 0x51, 0x0e, 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto new file mode 100644 index 000000000..96c1796d6 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto @@ -0,0 +1,98 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "github.com/golang/protobuf/ptypes/duration"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DurationProto"; +option java_multiple_files = true; +option java_generate_equals_and_hash = true; +option objc_class_prefix = "GPB"; + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (durations.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +// +message Duration { + + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. + int64 seconds = 1; + + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + int32 nanos = 2; +} diff --git a/vendor/github.com/google/safebrowsing/.travis.yml b/vendor/github.com/google/safebrowsing/.travis.yml index 4f0430ca7..3b24a9018 100644 --- a/vendor/github.com/google/safebrowsing/.travis.yml +++ b/vendor/github.com/google/safebrowsing/.travis.yml @@ -1,10 +1,10 @@ language: go go: - - 1.6 - 1.7 + - 1.8 script: - test -z "$(gofmt -s -l $(find . -name '*.go' -type f -print) | tee /dev/stderr)" - - go test -v ./... - - go test -race -v ./... + - go test -v $(go list ./... | grep -v vendor) + - go test -race -v $(go list ./... | grep -v vendor) diff --git a/vendor/github.com/google/safebrowsing/api.go b/vendor/github.com/google/safebrowsing/api.go index 66680b999..6d83d032b 100644 --- a/vendor/github.com/google/safebrowsing/api.go +++ b/vendor/github.com/google/safebrowsing/api.go @@ -21,6 +21,7 @@ import ( "net/http" "net/url" "strings" + "time" pb "github.com/google/safebrowsing/internal/safebrowsing_proto" @@ -40,14 +41,14 @@ type api interface { // netAPI is an api object that talks to the server over HTTP. type netAPI struct { - client http.Client + client *http.Client url *url.URL } // newNetAPI creates a new netAPI object pointed at the provided root URL. // For every request, it will use the provided API key. // If the protocol is not specified in root, then this defaults to using HTTPS. -func newNetAPI(root string, key string) (*netAPI, error) { +func newNetAPI(root string, key string, timeout time.Duration) (*netAPI, error) { if !strings.Contains(root, "://") { root = "https://" + root } @@ -60,7 +61,7 @@ func newNetAPI(root string, key string) (*netAPI, error) { q.Set("key", key) q.Set("alt", "proto") u.RawQuery = q.Encode() - return &netAPI{url: u}, nil + return &netAPI{url: u, client: &http.Client{Timeout: timeout}}, nil } // doRequests performs a POST to requestPath. It uses the marshaled form of req diff --git a/vendor/github.com/google/safebrowsing/cache.go b/vendor/github.com/google/safebrowsing/cache.go index 54219aa6f..f5722dd40 100644 --- a/vendor/github.com/google/safebrowsing/cache.go +++ b/vendor/github.com/google/safebrowsing/cache.go @@ -80,7 +80,12 @@ func (c *cache) Update(req *pb.FindFullHashesRequest, resp *pb.FindFullHashesRes if c.pttls[fullHash] == nil { c.pttls[fullHash] = make(map[ThreatDescriptor]time.Time) } - dur := time.Duration(tm.GetCacheDuration().Seconds) * time.Second + var dur time.Duration + if tmCacheDur := tm.GetCacheDuration(); tmCacheDur != nil { + dur = time.Duration(tm.GetCacheDuration().Seconds) * time.Second + } else { + dur = 0 + } td := ThreatDescriptor{ ThreatType: ThreatType(tm.ThreatType), PlatformType: PlatformType(tm.PlatformType), diff --git a/vendor/github.com/google/safebrowsing/database.go b/vendor/github.com/google/safebrowsing/database.go index 85c74ae92..025cb7bd6 100644 --- a/vendor/github.com/google/safebrowsing/database.go +++ b/vendor/github.com/google/safebrowsing/database.go @@ -20,6 +20,7 @@ import ( "encoding/gob" "errors" "log" + "math/rand" "os" "sync" "time" @@ -30,7 +31,11 @@ import ( // jitter is the maximum amount of time that we expect an API list update to // actually take. We add this time to the update period time to give some // leeway before declaring the database as stale. -const jitter = 30 * time.Second +const ( + maxRetryDelay = 24 * time.Hour + baseRetryDelay = 15 * time.Minute + jitter = 30 * time.Second +) // database tracks the state of the threat lists published by the Safe Browsing // API. Since the global blacklist is constantly changing, the contents of the @@ -63,8 +68,10 @@ type database struct { tfl threatsForLookup ml sync.RWMutex // Protects tfl, err, and last - err error // Last error encountered - last time.Time // Last time the threat list were synced + err error // Last error encountered + readyCh chan struct{} // Used for waiting until not in an error state. + last time.Time // Last time the threat list were synced + updateAPIErrors uint // Number of times we attempted to contact the api and failed log *log.Logger } @@ -94,11 +101,14 @@ type databaseFormat struct { // Init initializes the database from the specified file in config.DBPath. // It reports true if the database was successfully loaded. func (db *database) Init(config *Config, logger *log.Logger) bool { + db.mu.Lock() + defer db.mu.Unlock() + db.setError(errors.New("not intialized")) db.config = config db.log = logger if db.config.DBPath == "" { db.log.Printf("no database file specified") - db.setError(errStale) + db.setError(errors.New("no database loaded")) return false } dbf, err := loadDatabase(db.config.DBPath) @@ -112,7 +122,9 @@ func (db *database) Init(config *Config, logger *log.Logger) bool { // superset of the specified configuration. if db.config.now().Sub(dbf.Time) > (db.config.UpdatePeriod + jitter) { db.log.Printf("database loaded is stale") - db.setError(errStale) + db.ml.Lock() + defer db.ml.Unlock() + db.setStale() return false } tfuNew := make(threatsForUpdate) @@ -120,8 +132,8 @@ func (db *database) Init(config *Config, logger *log.Logger) bool { if row, ok := dbf.Table[td]; ok { tfuNew[td] = row } else { - db.log.Printf("database configuration mismatch") - db.setError(errStale) + db.log.Printf("database configuration mismatch, missing %v", td) + db.setError(errors.New("database configuration mismatch")) return false } } @@ -140,15 +152,39 @@ func (db *database) Status() error { return db.err } if db.config.now().Sub(db.last) > (db.config.UpdatePeriod + jitter) { - return errStale + db.setStale() + return db.err } return nil } +// UpdateLag reports the amount of time in between when we expected to run +// a database update and the current time +func (db *database) UpdateLag() time.Duration { + lag := db.SinceLastUpdate() + if lag < db.config.UpdatePeriod { + return 0 + } + return lag - db.config.UpdatePeriod +} + +// SinceLastUpdate gives the duration since the last database update +func (db *database) SinceLastUpdate() time.Duration { + db.ml.RLock() + defer db.ml.RUnlock() + + return db.config.now().Sub(db.last) +} + +// Ready returns a channel that's closed when the database is ready for queries. +func (db *database) Ready() <-chan struct{} { + return db.readyCh +} + // Update synchronizes the local threat lists with those maintained by the // global Safe Browsing API servers. If the update is successful, Status should // report a nil error. -func (db *database) Update(api api) { +func (db *database) Update(api api) (time.Duration, bool) { db.mu.Lock() defer db.mu.Unlock() @@ -183,23 +219,42 @@ func (db *database) Update(api api) { last := db.config.now() resp, err := api.ListUpdate(req) if err != nil { - db.log.Printf("ListUpdate failure: %v", err) + db.log.Printf("ListUpdate failure (%d): %v", db.updateAPIErrors+1, err) db.setError(err) - return + // backoff strategy: MIN((2**N-1 * 15 minutes) * (RAND + 1), 24 hours) + n := 1 << db.updateAPIErrors + delay := time.Duration(float64(n) * (rand.Float64() + 1) * float64(baseRetryDelay)) + if delay > maxRetryDelay { + delay = maxRetryDelay + } + db.updateAPIErrors++ + return delay, false + } + db.updateAPIErrors = 0 + + // add jitter to wait time to avoid all servers lining up + nextUpdateWait := db.config.UpdatePeriod + time.Duration(rand.Int31n(60)-30)*time.Second + if resp.MinimumWaitDuration != nil { + serverMinWait := time.Duration(resp.MinimumWaitDuration.Seconds)*time.Second + time.Duration(resp.MinimumWaitDuration.Nanos) + if serverMinWait > nextUpdateWait { + nextUpdateWait = serverMinWait + db.log.Printf("Server requested next update in %v", nextUpdateWait) + } } if len(resp.ListUpdateResponses) != numTypes { + db.setError(errors.New("safebrowsing: threat list count mismatch")) db.log.Printf("invalid server response: got %d, want %d threat lists", len(resp.ListUpdateResponses), numTypes) - db.setError(errors.New("safebrowsing: threat list count mismatch")) - return + return nextUpdateWait, false } // Update the threat database with the response. db.generateThreatsForUpdate() if err := db.tfu.update(resp); err != nil { - db.log.Printf("update failure: %v", err) db.setError(err) - return + db.log.Printf("update failure: %v", err) + db.tfu = nil + return nextUpdateWait, false } dbf := databaseFormat{make(threatsForUpdate), last} for td, phs := range db.tfu { @@ -215,6 +270,8 @@ func (db *database) Update(api api) { db.log.Printf("save failure: %v", err) } } + + return nextUpdateWait, true } // Lookup looks up the full hash in the threat list and returns a partial @@ -242,10 +299,38 @@ func (db *database) setError(err error) { db.tfu = nil db.ml.Lock() + if db.err == nil { + db.readyCh = make(chan struct{}) + } db.tfl, db.err, db.last = nil, err, time.Time{} db.ml.Unlock() } +// setStale sets the error state to a stale message, without clearing +// the database state. +// +// This assumes that the db.ml lock is already held. +func (db *database) setStale() { + if db.err == nil { + db.readyCh = make(chan struct{}) + } + db.err = errStale +} + +// clearError clears the db error state, and unblocks any callers of +// WaitUntilReady. +// +// This assumes that the db.mu lock is already held. +func (db *database) clearError() { + db.ml.Lock() + defer db.ml.Unlock() + + if db.err != nil { + close(db.readyCh) + } + db.err = nil +} + // generateThreatsForUpdate regenerates the threatsForUpdate hashes from // the threatsForLookup. We do this to avoid holding onto the hash lists for // a long time, needlessly occupying lots of memory. @@ -284,10 +369,11 @@ func (db *database) generateThreatsForLookups(last time.Time) { db.ml.Lock() wasBad := db.err != nil - db.tfl, db.err, db.last = tfl, nil, last + db.tfl, db.last = tfl, last db.ml.Unlock() if wasBad { + db.clearError() db.log.Printf("database is now healthy") } } @@ -424,7 +510,9 @@ func (tfu threatsForUpdate) update(resp *pb.FetchThreatListUpdatesResponse) erro return err } - phs.SHA256 = m.GetChecksum().Sha256 + if cs := m.GetChecksum(); cs != nil { + phs.SHA256 = cs.Sha256 + } if !bytes.Equal(phs.SHA256, phs.Hashes.SHA256()) { return errors.New("safebrowsing: threat list SHA256 mismatch") } diff --git a/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.pb.go b/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.pb.go index 6c3283d40..d3bcad432 100644 --- a/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.pb.go +++ b/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.pb.go @@ -27,13 +27,13 @@ It has these top-level messages: ThreatEntryMetadata ThreatListDescriptor ListThreatListsResponse - Duration */ package safebrowsing_proto import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import google_protobuf "github.com/golang/protobuf/ptypes/duration" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -42,7 +42,9 @@ 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. -const _ = proto.ProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // Types of threats. type ThreatType int32 @@ -229,11 +231,11 @@ func (FetchThreatListUpdatesResponse_ListUpdateResponse_ResponseType) EnumDescri // checking for matches in threat lists. type ThreatInfo struct { // The threat types to be checked. - ThreatTypes []ThreatType `protobuf:"varint,1,rep,name=threat_types,json=threatTypes,enum=safebrowsing_proto.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,enum=safebrowsing_proto.ThreatType" json:"threat_types,omitempty"` // The platform types to be checked. - PlatformTypes []PlatformType `protobuf:"varint,2,rep,name=platform_types,json=platformTypes,enum=safebrowsing_proto.PlatformType" json:"platform_types,omitempty"` + PlatformTypes []PlatformType `protobuf:"varint,2,rep,packed,name=platform_types,json=platformTypes,enum=safebrowsing_proto.PlatformType" json:"platform_types,omitempty"` // The entry types to be checked. - ThreatEntryTypes []ThreatEntryType `protobuf:"varint,4,rep,name=threat_entry_types,json=threatEntryTypes,enum=safebrowsing_proto.ThreatEntryType" json:"threat_entry_types,omitempty"` + ThreatEntryTypes []ThreatEntryType `protobuf:"varint,4,rep,packed,name=threat_entry_types,json=threatEntryTypes,enum=safebrowsing_proto.ThreatEntryType" json:"threat_entry_types,omitempty"` // The threat entries to be checked. ThreatEntries []*ThreatEntry `protobuf:"bytes,3,rep,name=threat_entries,json=threatEntries" json:"threat_entries,omitempty"` } @@ -243,6 +245,27 @@ func (m *ThreatInfo) String() string { return proto.CompactTextString func (*ThreatInfo) ProtoMessage() {} func (*ThreatInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *ThreatInfo) GetThreatTypes() []ThreatType { + if m != nil { + return m.ThreatTypes + } + return nil +} + +func (m *ThreatInfo) GetPlatformTypes() []PlatformType { + if m != nil { + return m.PlatformTypes + } + return nil +} + +func (m *ThreatInfo) GetThreatEntryTypes() []ThreatEntryType { + if m != nil { + return m.ThreatEntryTypes + } + return nil +} + func (m *ThreatInfo) GetThreatEntries() []*ThreatEntry { if m != nil { return m.ThreatEntries @@ -264,7 +287,7 @@ type ThreatMatch struct { ThreatEntryMetadata *ThreatEntryMetadata `protobuf:"bytes,4,opt,name=threat_entry_metadata,json=threatEntryMetadata" json:"threat_entry_metadata,omitempty"` // The cache lifetime for the returned match. Clients must not cache this // response for more than this duration to avoid false positives. - CacheDuration *Duration `protobuf:"bytes,5,opt,name=cache_duration,json=cacheDuration" json:"cache_duration,omitempty"` + CacheDuration *google_protobuf.Duration `protobuf:"bytes,5,opt,name=cache_duration,json=cacheDuration" json:"cache_duration,omitempty"` } func (m *ThreatMatch) Reset() { *m = ThreatMatch{} } @@ -272,6 +295,27 @@ func (m *ThreatMatch) String() string { return proto.CompactTextStrin func (*ThreatMatch) ProtoMessage() {} func (*ThreatMatch) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *ThreatMatch) GetThreatType() ThreatType { + if m != nil { + return m.ThreatType + } + return ThreatType_THREAT_TYPE_UNSPECIFIED +} + +func (m *ThreatMatch) GetPlatformType() PlatformType { + if m != nil { + return m.PlatformType + } + return PlatformType_PLATFORM_TYPE_UNSPECIFIED +} + +func (m *ThreatMatch) GetThreatEntryType() ThreatEntryType { + if m != nil { + return m.ThreatEntryType + } + return ThreatEntryType_THREAT_ENTRY_TYPE_UNSPECIFIED +} + func (m *ThreatMatch) GetThreat() *ThreatEntry { if m != nil { return m.Threat @@ -286,7 +330,7 @@ func (m *ThreatMatch) GetThreatEntryMetadata() *ThreatEntryMetadata { return nil } -func (m *ThreatMatch) GetCacheDuration() *Duration { +func (m *ThreatMatch) GetCacheDuration() *google_protobuf.Duration { if m != nil { return m.CacheDuration } @@ -394,6 +438,34 @@ func (*FetchThreatListUpdatesRequest_ListUpdateRequest) Descriptor() ([]byte, [] return fileDescriptor0, []int{4, 0} } +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest) GetThreatType() ThreatType { + if m != nil { + return m.ThreatType + } + return ThreatType_THREAT_TYPE_UNSPECIFIED +} + +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest) GetPlatformType() PlatformType { + if m != nil { + return m.PlatformType + } + return PlatformType_PLATFORM_TYPE_UNSPECIFIED +} + +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest) GetThreatEntryType() ThreatEntryType { + if m != nil { + return m.ThreatEntryType + } + return ThreatEntryType_THREAT_ENTRY_TYPE_UNSPECIFIED +} + +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest) GetState() []byte { + if m != nil { + return m.State + } + return nil +} + func (m *FetchThreatListUpdatesRequest_ListUpdateRequest) GetConstraints() *FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints { if m != nil { return m.Constraints @@ -416,7 +488,7 @@ type FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints struct { // 3166-1 alpha-2 format. Region string `protobuf:"bytes,3,opt,name=region" json:"region,omitempty"` // The compression types supported by the client. - SupportedCompressions []CompressionType `protobuf:"varint,4,rep,name=supported_compressions,json=supportedCompressions,enum=safebrowsing_proto.CompressionType" json:"supported_compressions,omitempty"` + SupportedCompressions []CompressionType `protobuf:"varint,4,rep,packed,name=supported_compressions,json=supportedCompressions,enum=safebrowsing_proto.CompressionType" json:"supported_compressions,omitempty"` } func (m *FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints) Reset() { @@ -430,13 +502,41 @@ func (*FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints) Descriptor() return fileDescriptor0, []int{4, 0, 0} } +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints) GetMaxUpdateEntries() int32 { + if m != nil { + return m.MaxUpdateEntries + } + return 0 +} + +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints) GetMaxDatabaseEntries() int32 { + if m != nil { + return m.MaxDatabaseEntries + } + return 0 +} + +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints) GetRegion() string { + if m != nil { + return m.Region + } + return "" +} + +func (m *FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints) GetSupportedCompressions() []CompressionType { + if m != nil { + return m.SupportedCompressions + } + return nil +} + // Response type for threat list update requests. type FetchThreatListUpdatesResponse struct { // The list updates requested by the clients. ListUpdateResponses []*FetchThreatListUpdatesResponse_ListUpdateResponse `protobuf:"bytes,1,rep,name=list_update_responses,json=listUpdateResponses" json:"list_update_responses,omitempty"` // The minimum duration the client must wait before issuing any update // request. If this field is not set clients may update as soon as they want. - MinimumWaitDuration *Duration `protobuf:"bytes,2,opt,name=minimum_wait_duration,json=minimumWaitDuration" json:"minimum_wait_duration,omitempty"` + MinimumWaitDuration *google_protobuf.Duration `protobuf:"bytes,2,opt,name=minimum_wait_duration,json=minimumWaitDuration" json:"minimum_wait_duration,omitempty"` } func (m *FetchThreatListUpdatesResponse) Reset() { *m = FetchThreatListUpdatesResponse{} } @@ -451,7 +551,7 @@ func (m *FetchThreatListUpdatesResponse) GetListUpdateResponses() []*FetchThreat return nil } -func (m *FetchThreatListUpdatesResponse) GetMinimumWaitDuration() *Duration { +func (m *FetchThreatListUpdatesResponse) GetMinimumWaitDuration() *google_protobuf.Duration { if m != nil { return m.MinimumWaitDuration } @@ -496,6 +596,34 @@ func (*FetchThreatListUpdatesResponse_ListUpdateResponse) Descriptor() ([]byte, return fileDescriptor0, []int{5, 0} } +func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetThreatType() ThreatType { + if m != nil { + return m.ThreatType + } + return ThreatType_THREAT_TYPE_UNSPECIFIED +} + +func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetThreatEntryType() ThreatEntryType { + if m != nil { + return m.ThreatEntryType + } + return ThreatEntryType_THREAT_ENTRY_TYPE_UNSPECIFIED +} + +func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetPlatformType() PlatformType { + if m != nil { + return m.PlatformType + } + return PlatformType_PLATFORM_TYPE_UNSPECIFIED +} + +func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetResponseType() FetchThreatListUpdatesResponse_ListUpdateResponse_ResponseType { + if m != nil { + return m.ResponseType + } + return FetchThreatListUpdatesResponse_ListUpdateResponse_RESPONSE_TYPE_UNSPECIFIED +} + func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetAdditions() []*ThreatEntrySet { if m != nil { return m.Additions @@ -510,6 +638,13 @@ func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetRemovals() []*Thr return nil } +func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetNewClientState() []byte { + if m != nil { + return m.NewClientState + } + return nil +} + func (m *FetchThreatListUpdatesResponse_ListUpdateResponse) GetChecksum() *Checksum { if m != nil { return m.Checksum @@ -539,6 +674,13 @@ func (m *FindFullHashesRequest) GetClient() *ClientInfo { return nil } +func (m *FindFullHashesRequest) GetClientStates() [][]byte { + if m != nil { + return m.ClientStates + } + return nil +} + func (m *FindFullHashesRequest) GetThreatInfo() *ThreatInfo { if m != nil { return m.ThreatInfo @@ -553,10 +695,10 @@ type FindFullHashesResponse struct { // The minimum duration the client must wait before issuing any find hashes // request. If this field is not set, clients can issue a request as soon as // they want. - MinimumWaitDuration *Duration `protobuf:"bytes,2,opt,name=minimum_wait_duration,json=minimumWaitDuration" json:"minimum_wait_duration,omitempty"` + MinimumWaitDuration *google_protobuf.Duration `protobuf:"bytes,2,opt,name=minimum_wait_duration,json=minimumWaitDuration" json:"minimum_wait_duration,omitempty"` // For requested entities that did not match the threat list, how long to // cache the response. - NegativeCacheDuration *Duration `protobuf:"bytes,3,opt,name=negative_cache_duration,json=negativeCacheDuration" json:"negative_cache_duration,omitempty"` + NegativeCacheDuration *google_protobuf.Duration `protobuf:"bytes,3,opt,name=negative_cache_duration,json=negativeCacheDuration" json:"negative_cache_duration,omitempty"` } func (m *FindFullHashesResponse) Reset() { *m = FindFullHashesResponse{} } @@ -571,14 +713,14 @@ func (m *FindFullHashesResponse) GetMatches() []*ThreatMatch { return nil } -func (m *FindFullHashesResponse) GetMinimumWaitDuration() *Duration { +func (m *FindFullHashesResponse) GetMinimumWaitDuration() *google_protobuf.Duration { if m != nil { return m.MinimumWaitDuration } return nil } -func (m *FindFullHashesResponse) GetNegativeCacheDuration() *Duration { +func (m *FindFullHashesResponse) GetNegativeCacheDuration() *google_protobuf.Duration { if m != nil { return m.NegativeCacheDuration } @@ -599,6 +741,20 @@ func (m *ClientInfo) String() string { return proto.CompactTextString func (*ClientInfo) ProtoMessage() {} func (*ClientInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (m *ClientInfo) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *ClientInfo) GetClientVersion() string { + if m != nil { + return m.ClientVersion + } + return "" +} + // The expected state of a client's local database. type Checksum struct { // The SHA256 hash of the client state; that is, of the sorted list of all @@ -611,6 +767,13 @@ func (m *Checksum) String() string { return proto.CompactTextString(m func (*Checksum) ProtoMessage() {} func (*Checksum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (m *Checksum) GetSha256() []byte { + if m != nil { + return m.Sha256 + } + return nil +} + // An individual threat; for example, a malicious URL or its hash // representation. Only one of these fields should be set. type ThreatEntry struct { @@ -626,6 +789,20 @@ func (m *ThreatEntry) String() string { return proto.CompactTextStrin func (*ThreatEntry) ProtoMessage() {} func (*ThreatEntry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (m *ThreatEntry) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *ThreatEntry) GetUrl() string { + if m != nil { + return m.Url + } + return "" +} + // A set of threats that should be added or removed from a client's local // database. type ThreatEntrySet struct { @@ -648,6 +825,13 @@ func (m *ThreatEntrySet) String() string { return proto.CompactTextSt func (*ThreatEntrySet) ProtoMessage() {} func (*ThreatEntrySet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (m *ThreatEntrySet) GetCompressionType() CompressionType { + if m != nil { + return m.CompressionType + } + return CompressionType_COMPRESSION_TYPE_UNSPECIFIED +} + func (m *ThreatEntrySet) GetRawHashes() *RawHashes { if m != nil { return m.RawHashes @@ -679,7 +863,7 @@ func (m *ThreatEntrySet) GetRiceIndices() *RiceDeltaEncoding { // A set of raw indices to remove from a local list. type RawIndices struct { // The indices to remove from a lexicographically-sorted local list. - Indices []int32 `protobuf:"varint,1,rep,name=indices" json:"indices,omitempty"` + Indices []int32 `protobuf:"varint,1,rep,packed,name=indices" json:"indices,omitempty"` } func (m *RawIndices) Reset() { *m = RawIndices{} } @@ -687,6 +871,13 @@ func (m *RawIndices) String() string { return proto.CompactTextString func (*RawIndices) ProtoMessage() {} func (*RawIndices) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (m *RawIndices) GetIndices() []int32 { + if m != nil { + return m.Indices + } + return nil +} + // The uncompressed threat entries in hash format of a particular prefix length. // Hashes can be anywhere from 4 to 32 bytes in size. A large majority are 4 // bytes, but some hashes are lengthened if they collide with the hash of a @@ -708,6 +899,20 @@ func (m *RawHashes) String() string { return proto.CompactTextString( func (*RawHashes) ProtoMessage() {} func (*RawHashes) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (m *RawHashes) GetPrefixSize() int32 { + if m != nil { + return m.PrefixSize + } + return 0 +} + +func (m *RawHashes) GetRawHashes() []byte { + if m != nil { + return m.RawHashes + } + return nil +} + // The Rice-Golomb encoded data. Used for sending compressed 4-byte hashes or // compressed removal indices. type RiceDeltaEncoding struct { @@ -730,6 +935,34 @@ func (m *RiceDeltaEncoding) String() string { return proto.CompactTex func (*RiceDeltaEncoding) ProtoMessage() {} func (*RiceDeltaEncoding) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (m *RiceDeltaEncoding) GetFirstValue() int64 { + if m != nil { + return m.FirstValue + } + return 0 +} + +func (m *RiceDeltaEncoding) GetRiceParameter() int32 { + if m != nil { + return m.RiceParameter + } + return 0 +} + +func (m *RiceDeltaEncoding) GetNumEntries() int32 { + if m != nil { + return m.NumEntries + } + return 0 +} + +func (m *RiceDeltaEncoding) GetEncodedData() []byte { + if m != nil { + return m.EncodedData + } + return nil +} + // The metadata associated with a specific threat entry. The client is expected // to know the metadata key/value pairs associated with each threat type. type ThreatEntryMetadata struct { @@ -764,6 +997,20 @@ func (*ThreatEntryMetadata_MetadataEntry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15, 0} } +func (m *ThreatEntryMetadata_MetadataEntry) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *ThreatEntryMetadata_MetadataEntry) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + // Describes an individual threat list. A list is defined by three parameters: // the type of threat posed, the type of platform targeted by the threat, and // the type of entries in the list. @@ -781,6 +1028,27 @@ func (m *ThreatListDescriptor) String() string { return proto.Compact func (*ThreatListDescriptor) ProtoMessage() {} func (*ThreatListDescriptor) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (m *ThreatListDescriptor) GetThreatType() ThreatType { + if m != nil { + return m.ThreatType + } + return ThreatType_THREAT_TYPE_UNSPECIFIED +} + +func (m *ThreatListDescriptor) GetPlatformType() PlatformType { + if m != nil { + return m.PlatformType + } + return PlatformType_PLATFORM_TYPE_UNSPECIFIED +} + +func (m *ThreatListDescriptor) GetThreatEntryType() ThreatEntryType { + if m != nil { + return m.ThreatEntryType + } + return ThreatEntryType_THREAT_ENTRY_TYPE_UNSPECIFIED +} + // A collection of lists available for download by the client. type ListThreatListsResponse struct { // The lists available for download by the client. @@ -799,30 +1067,6 @@ func (m *ListThreatListsResponse) GetThreatLists() []*ThreatListDescriptor { return nil } -// A Duration represents a signed, fixed-length span of time represented -// as a count of seconds and fractions of seconds at nanosecond -// resolution. It is independent of any calendar and concepts like "day" -// or "month". It is related to Timestamp in that the difference between -// two Timestamp values is a Duration and it can be added or subtracted -// from a Timestamp. Range is approximately +-10,000 years. -type Duration struct { - // Signed seconds of the span of time. Must be from -315,576,000,000 - // to +315,576,000,000 inclusive. - Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` - // Signed fractions of a second at nanosecond resolution of the span - // of time. Durations less than one second are represented with a 0 - // `seconds` field and a positive or negative `nanos` field. For durations - // of one second or more, a non-zero value for the `nanos` field must be - // of the same sign as the `seconds` field. Must be from -999,999,999 - // to +999,999,999 inclusive. - Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` -} - -func (m *Duration) Reset() { *m = Duration{} } -func (m *Duration) String() string { return proto.CompactTextString(m) } -func (*Duration) ProtoMessage() {} -func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } - func init() { proto.RegisterType((*ThreatInfo)(nil), "safebrowsing_proto.ThreatInfo") proto.RegisterType((*ThreatMatch)(nil), "safebrowsing_proto.ThreatMatch") @@ -846,7 +1090,6 @@ func init() { proto.RegisterType((*ThreatEntryMetadata_MetadataEntry)(nil), "safebrowsing_proto.ThreatEntryMetadata.MetadataEntry") proto.RegisterType((*ThreatListDescriptor)(nil), "safebrowsing_proto.ThreatListDescriptor") proto.RegisterType((*ListThreatListsResponse)(nil), "safebrowsing_proto.ListThreatListsResponse") - proto.RegisterType((*Duration)(nil), "safebrowsing_proto.Duration") proto.RegisterEnum("safebrowsing_proto.ThreatType", ThreatType_name, ThreatType_value) proto.RegisterEnum("safebrowsing_proto.PlatformType", PlatformType_name, PlatformType_value) proto.RegisterEnum("safebrowsing_proto.CompressionType", CompressionType_name, CompressionType_value) @@ -854,108 +1097,111 @@ func init() { proto.RegisterEnum("safebrowsing_proto.FetchThreatListUpdatesResponse_ListUpdateResponse_ResponseType", FetchThreatListUpdatesResponse_ListUpdateResponse_ResponseType_name, FetchThreatListUpdatesResponse_ListUpdateResponse_ResponseType_value) } +func init() { proto.RegisterFile("safebrowsing.proto", fileDescriptor0) } + var fileDescriptor0 = []byte{ - // 1628 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x58, 0x5b, 0x6f, 0xdb, 0x46, - 0x16, 0x5e, 0x49, 0xd6, 0xed, 0x48, 0xb2, 0xe5, 0xf1, 0x25, 0x8e, 0x13, 0x27, 0x59, 0x06, 0xd9, - 0x0d, 0x8c, 0x85, 0xb1, 0x48, 0x90, 0x64, 0x77, 0xb1, 0xd8, 0x2d, 0x2b, 0x51, 0x36, 0x11, 0x99, - 0x52, 0x47, 0x72, 0x1c, 0xb7, 0x0f, 0x04, 0x23, 0xd1, 0x31, 0x11, 0xdd, 0x42, 0x52, 0x71, 0xdc, - 0x9f, 0xd0, 0xa7, 0x02, 0x45, 0x9f, 0xdb, 0xe7, 0xbe, 0x16, 0xfd, 0x01, 0xfd, 0x19, 0x7d, 0xec, - 0x2f, 0x28, 0xfa, 0xdc, 0x97, 0x9e, 0x19, 0xce, 0x88, 0xd4, 0xc5, 0x8e, 0x12, 0xfb, 0x21, 0x6f, - 0x33, 0x67, 0xce, 0x7c, 0x73, 0xf8, 0xcd, 0xb9, 0x0d, 0x81, 0x78, 0xd6, 0xb1, 0xfd, 0xc2, 0xed, - 0x9f, 0x7a, 0x4e, 0xef, 0xe5, 0xce, 0xc0, 0xed, 0xfb, 0x7d, 0x32, 0x26, 0x33, 0xb9, 0x4c, 0xf9, - 0x31, 0x0e, 0xd0, 0x3c, 0x71, 0x6d, 0xcb, 0xd7, 0x7b, 0xc7, 0x7d, 0xa2, 0x42, 0xde, 0xe7, 0x33, - 0xd3, 0x3f, 0x1b, 0xd8, 0xde, 0x46, 0xec, 0x4e, 0xe2, 0xfe, 0xe2, 0x83, 0x5b, 0x3b, 0xd3, 0x3b, - 0x77, 0x82, 0x5d, 0x4d, 0x54, 0xa3, 0x39, 0x7f, 0x34, 0xf6, 0xc8, 0x2e, 0x2c, 0x0e, 0x3a, 0x96, - 0x7f, 0xdc, 0x77, 0xbb, 0x02, 0x24, 0xce, 0x41, 0xee, 0xcc, 0x02, 0xa9, 0x0b, 0x4d, 0x0e, 0x53, - 0x18, 0x44, 0x66, 0x1e, 0xf9, 0x0c, 0x88, 0xb0, 0xc5, 0xee, 0xf9, 0xee, 0x99, 0x00, 0x5b, 0xe0, - 0x60, 0x77, 0xcf, 0xb7, 0x48, 0x63, 0xca, 0x1c, 0xaf, 0xe8, 0x8f, 0x0b, 0x3c, 0x52, 0x81, 0xc5, - 0x08, 0xa4, 0x83, 0x70, 0x09, 0x84, 0xcb, 0x3d, 0xb8, 0xfd, 0x0e, 0x38, 0x5a, 0x08, 0xa1, 0x70, - 0x97, 0xf2, 0x73, 0x02, 0x72, 0xc1, 0xf2, 0xbe, 0xe5, 0xb7, 0x4e, 0xc8, 0xff, 0x21, 0x17, 0xa1, - 0x0d, 0x59, 0x8b, 0xcd, 0xc1, 0x1a, 0x84, 0xac, 0x11, 0x0d, 0x0a, 0x63, 0xa4, 0x21, 0x67, 0xb1, - 0xb9, 0x38, 0xcb, 0x47, 0x39, 0x23, 0x35, 0x58, 0x9e, 0xa2, 0x6c, 0x23, 0xc5, 0xa1, 0xe6, 0x62, - 0x6c, 0x69, 0x82, 0x31, 0xf2, 0x04, 0x52, 0x81, 0x08, 0x89, 0x8a, 0xcd, 0x43, 0x94, 0x50, 0x27, - 0x5f, 0xc0, 0xda, 0x98, 0x25, 0x5d, 0xdb, 0xb7, 0xda, 0x96, 0x6f, 0xe1, 0xfd, 0x31, 0x9c, 0xbf, - 0xbf, 0x03, 0x67, 0x5f, 0xa8, 0xd3, 0x15, 0x7f, 0x5a, 0x48, 0x4a, 0xb0, 0xd8, 0xb2, 0x5a, 0x27, - 0xb6, 0xd9, 0x1e, 0xba, 0x96, 0xef, 0xf4, 0x7b, 0x1b, 0x49, 0x8e, 0x7a, 0x73, 0x16, 0x6a, 0x59, - 0xe8, 0xd0, 0x02, 0xdf, 0x23, 0xa7, 0xca, 0x37, 0x31, 0xd8, 0xa8, 0x38, 0xbd, 0x76, 0xe4, 0x1e, - 0x6d, 0x8f, 0xda, 0xaf, 0x87, 0xb6, 0xe7, 0x93, 0xc7, 0x90, 0x6a, 0x75, 0x1c, 0x34, 0x9d, 0xdf, - 0x65, 0x6e, 0xf6, 0x5d, 0x96, 0xb8, 0x06, 0x8b, 0x1b, 0x2a, 0xb4, 0x23, 0x8e, 0xe0, 0xa0, 0x98, - 0xdf, 0x62, 0xee, 0x22, 0x47, 0xe0, 0x9b, 0x85, 0x23, 0xb0, 0xb1, 0xf2, 0x0c, 0xae, 0xcf, 0x30, - 0xca, 0x1b, 0xf4, 0x7b, 0x9e, 0x4d, 0xfe, 0x0d, 0xe9, 0x6e, 0x20, 0xe2, 0x81, 0x79, 0xe1, 0x75, - 0xf0, 0xbd, 0x54, 0xea, 0x2b, 0x3f, 0xa4, 0x60, 0xab, 0x62, 0xe3, 0x38, 0x58, 0xad, 0x3a, 0x9e, - 0x7f, 0x30, 0x40, 0x32, 0x2f, 0xff, 0xc9, 0x43, 0x58, 0xed, 0x20, 0x9a, 0x39, 0xe4, 0x70, 0xa6, - 0x1b, 0xc0, 0xc9, 0xc8, 0x2a, 0xcd, 0x42, 0xb9, 0xd0, 0x90, 0x9d, 0x50, 0x24, 0x24, 0x94, 0x74, - 0x26, 0x45, 0xde, 0xe6, 0x2f, 0x0b, 0xb0, 0x3c, 0xa5, 0xf9, 0x71, 0x07, 0x62, 0xf2, 0x12, 0x81, - 0xb8, 0x0a, 0x49, 0xcf, 0xc7, 0x0f, 0xe5, 0x71, 0x98, 0xa7, 0xc1, 0x84, 0xbc, 0x86, 0x5c, 0x0b, - 0x3d, 0xc3, 0x77, 0x2d, 0xa7, 0xe7, 0x7b, 0x22, 0xb6, 0x6a, 0x57, 0x40, 0xf9, 0x4e, 0x29, 0x84, - 0xa5, 0xd1, 0x33, 0x36, 0x7f, 0x8d, 0x41, 0x2e, 0xb2, 0x48, 0xfe, 0x01, 0xa4, 0x6b, 0xbd, 0x95, - 0xb7, 0x2f, 0xd3, 0x2a, 0x23, 0x3e, 0x49, 0x8b, 0xb8, 0x12, 0xc0, 0x8a, 0xc4, 0x49, 0xfe, 0x09, - 0xab, 0x4c, 0x9b, 0x45, 0xf1, 0x0b, 0xcb, 0x0b, 0xf5, 0xe3, 0x5c, 0x9f, 0x21, 0x95, 0xc5, 0x92, - 0xdc, 0xb1, 0x0e, 0x29, 0xd7, 0x7e, 0xc9, 0x62, 0x9c, 0x7d, 0x79, 0x96, 0x8a, 0x19, 0xf9, 0x1c, - 0xd6, 0xbd, 0xe1, 0x60, 0xd0, 0x77, 0x7d, 0xbb, 0x6d, 0xb6, 0xfa, 0xdd, 0x81, 0x6b, 0x7b, 0x1e, - 0x2e, 0x5c, 0x58, 0x21, 0x4a, 0xa1, 0x1e, 0xa7, 0x79, 0x6d, 0x04, 0x11, 0x59, 0xf1, 0x94, 0xaf, - 0xd3, 0x70, 0xeb, 0x3c, 0xc2, 0x44, 0x28, 0x9e, 0xc1, 0xda, 0xb8, 0xd7, 0x07, 0x72, 0x19, 0x98, - 0xda, 0xfb, 0xdc, 0x41, 0xb0, 0x75, 0xec, 0x12, 0x02, 0x11, 0x5d, 0xe9, 0x4c, 0xc9, 0x3c, 0x52, - 0x87, 0xb5, 0xae, 0xd3, 0x73, 0xba, 0xc3, 0xae, 0x79, 0x6a, 0x39, 0x7e, 0x98, 0x04, 0xe3, 0x73, - 0x24, 0xc1, 0x15, 0xb1, 0xf5, 0x10, 0x77, 0x4a, 0xe1, 0xe6, 0xf7, 0x49, 0x20, 0xd3, 0xa7, 0x5f, - 0x3e, 0x98, 0x66, 0x46, 0x41, 0xfc, 0x12, 0x51, 0x30, 0x15, 0x9d, 0x89, 0x0f, 0x8a, 0xce, 0x53, - 0x28, 0xc8, 0x0b, 0x0b, 0x60, 0x16, 0x38, 0x0c, 0xbd, 0x92, 0x4b, 0xdb, 0x91, 0x83, 0xe0, 0x60, - 0x37, 0x32, 0x23, 0x9f, 0x40, 0xd6, 0x6a, 0xb7, 0x1d, 0x9f, 0xfb, 0x69, 0x92, 0x7b, 0x8a, 0xf2, - 0x0e, 0x22, 0x1a, 0xb6, 0x4f, 0xc3, 0x4d, 0xe4, 0x7f, 0x90, 0x71, 0xed, 0x6e, 0xff, 0x8d, 0xd5, - 0xf1, 0xb0, 0xb0, 0xcf, 0x0b, 0x30, 0xda, 0x43, 0xee, 0x43, 0xb1, 0x67, 0x9f, 0x9a, 0x41, 0xee, - 0x36, 0x83, 0x94, 0x92, 0xe6, 0x29, 0x65, 0x11, 0xe5, 0x41, 0x7a, 0x6f, 0xf0, 0xdc, 0xf2, 0x2f, - 0xc8, 0x60, 0xe5, 0x68, 0xbd, 0xf2, 0x86, 0xdd, 0x8d, 0xcc, 0xf9, 0x9e, 0x55, 0x12, 0x3a, 0x74, - 0xa4, 0xad, 0x50, 0xc8, 0x47, 0x39, 0x20, 0x5b, 0x70, 0x9d, 0x6a, 0x8d, 0x7a, 0xcd, 0x68, 0x68, - 0x66, 0xf3, 0xa8, 0xae, 0x99, 0x07, 0x46, 0xa3, 0xae, 0x95, 0xf4, 0x8a, 0xae, 0x95, 0x8b, 0x7f, - 0x21, 0x04, 0x16, 0xeb, 0x2a, 0x6d, 0xea, 0x6a, 0xd5, 0x3c, 0xa8, 0x97, 0xd5, 0xa6, 0x56, 0x8c, - 0x91, 0x25, 0xc8, 0x55, 0x0e, 0xaa, 0x23, 0x41, 0x5c, 0xf9, 0x29, 0x06, 0x6b, 0xac, 0x30, 0x56, - 0x86, 0x9d, 0xce, 0x9e, 0xe5, 0x5d, 0x41, 0xa9, 0xbe, 0x0b, 0x85, 0x28, 0x0b, 0x41, 0x9b, 0x9a, - 0xa7, 0xf9, 0x56, 0xc8, 0x81, 0x37, 0x59, 0xcf, 0x13, 0xef, 0x5d, 0xcf, 0xff, 0x88, 0xc1, 0xfa, - 0xa4, 0xdd, 0x97, 0xae, 0xe6, 0x57, 0x9f, 0x02, 0x48, 0x13, 0xae, 0xf5, 0xec, 0x97, 0x38, 0x7e, - 0x63, 0x9b, 0x13, 0xbd, 0x55, 0x62, 0x0e, 0xcc, 0x35, 0xb9, 0xb9, 0x34, 0xd6, 0x63, 0xd5, 0x01, - 0x42, 0xe6, 0xc9, 0x0d, 0xc8, 0x0a, 0xc6, 0x9d, 0x36, 0xbf, 0xac, 0x2c, 0x3a, 0x4d, 0xb0, 0xdc, - 0x26, 0xf7, 0xb0, 0xa7, 0x0b, 0x16, 0xdf, 0xd8, 0xae, 0x27, 0xbf, 0x25, 0x4b, 0xc5, 0x25, 0x3d, - 0x0b, 0x84, 0x8a, 0x02, 0x19, 0xe9, 0x71, 0xac, 0x34, 0x78, 0x27, 0xd6, 0x83, 0x47, 0x8f, 0x39, - 0x58, 0x9e, 0x8a, 0x99, 0xf2, 0x50, 0x36, 0xe7, 0xdc, 0xff, 0xd1, 0xbf, 0x16, 0x4e, 0x90, 0x79, - 0xa1, 0xc4, 0xc7, 0xa4, 0x08, 0x89, 0xa1, 0xdb, 0x11, 0x47, 0xb0, 0xa1, 0xf2, 0x7b, 0x1c, 0x16, - 0xc7, 0xa3, 0x86, 0x18, 0x50, 0x8c, 0x14, 0x96, 0x68, 0x12, 0x9c, 0xab, 0xb8, 0x2c, 0xb5, 0xc6, - 0x05, 0xe4, 0xbf, 0x00, 0xae, 0x75, 0x6a, 0x9e, 0x70, 0x37, 0x10, 0x57, 0xb5, 0x35, 0x0b, 0x89, - 0x5a, 0xa7, 0xc2, 0x57, 0xb2, 0xae, 0x1c, 0x32, 0x57, 0x64, 0xbb, 0xd1, 0x97, 0x9c, 0x16, 0x7f, - 0xb8, 0x9c, 0xeb, 0x8a, 0xb8, 0x5d, 0x0f, 0xb4, 0x28, 0x3b, 0x50, 0x8c, 0xf1, 0xf1, 0x93, 0x73, - 0x71, 0x20, 0xcf, 0x0f, 0x9a, 0x85, 0x7b, 0x33, 0x01, 0x50, 0xad, 0x6c, 0x77, 0x7c, 0x4b, 0xeb, - 0xb5, 0xfa, 0x6d, 0x94, 0x23, 0x0e, 0x8a, 0x84, 0x21, 0x7b, 0x90, 0xe7, 0x38, 0xd2, 0x92, 0xe4, - 0xfb, 0x00, 0x71, 0x13, 0x84, 0x45, 0xca, 0xdf, 0x00, 0x42, 0x5b, 0xc9, 0x06, 0xa4, 0x25, 0x24, - 0x8b, 0x87, 0x24, 0x95, 0x53, 0xe5, 0x29, 0x64, 0x47, 0x94, 0x90, 0xdb, 0x90, 0x43, 0x56, 0x8f, - 0x9d, 0xb7, 0xa6, 0xe7, 0x7c, 0x69, 0x8b, 0x4e, 0x03, 0x02, 0x51, 0x03, 0x25, 0x98, 0x6e, 0x26, - 0x69, 0xce, 0x47, 0x78, 0x54, 0xbe, 0x8b, 0xc1, 0xf2, 0x94, 0x5d, 0x0c, 0xf5, 0xd8, 0x71, 0xb1, - 0xa0, 0x63, 0x96, 0x1c, 0x06, 0xa8, 0x09, 0x0a, 0x5c, 0xf4, 0x8c, 0x49, 0x98, 0x7f, 0xf2, 0xaf, - 0x1e, 0x58, 0xae, 0x85, 0x8f, 0x19, 0xdb, 0x15, 0x3d, 0x4b, 0x81, 0x49, 0xeb, 0x52, 0xc8, 0x70, - 0x7a, 0x18, 0x95, 0xe1, 0xf3, 0x92, 0x5b, 0x87, 0x22, 0xd9, 0xcf, 0xfc, 0x15, 0xf2, 0x36, 0x3b, - 0x14, 0xbb, 0x96, 0xd1, 0x7b, 0x28, 0x4f, 0x73, 0x42, 0xc6, 0xba, 0x1f, 0x66, 0xe1, 0xca, 0x8c, - 0xb7, 0x10, 0x96, 0xd3, 0x74, 0xd8, 0x5f, 0xb1, 0x84, 0xf1, 0x68, 0xce, 0x57, 0xd4, 0x8e, 0x1c, - 0x04, 0x6f, 0x34, 0x89, 0xb2, 0xf9, 0x04, 0x0a, 0x63, 0x2b, 0x2c, 0x2c, 0x5e, 0xd9, 0x67, 0x22, - 0x52, 0xd8, 0x90, 0xf5, 0x9d, 0x01, 0x23, 0x01, 0x8f, 0xc1, 0x44, 0xf9, 0x2d, 0x06, 0xab, 0x61, - 0x4d, 0x2c, 0xdb, 0x5e, 0xcb, 0x75, 0x06, 0x7e, 0xdf, 0xfd, 0xb8, 0xfb, 0xef, 0xc4, 0x87, 0x77, - 0x1e, 0xca, 0x31, 0x5c, 0x63, 0x9f, 0x1a, 0x7e, 0x74, 0x98, 0xc7, 0x9f, 0x8e, 0xfe, 0x99, 0xb0, - 0x6e, 0x4d, 0xde, 0xcd, 0xfd, 0xf3, 0x8f, 0x19, 0xe7, 0x4c, 0xfe, 0x3d, 0xe1, 0xa0, 0xca, 0x7f, - 0x20, 0x33, 0xca, 0xc9, 0x18, 0x10, 0x9e, 0x8d, 0xbd, 0x77, 0xdb, 0x13, 0xfe, 0x28, 0xa7, 0xec, - 0x56, 0x7a, 0x56, 0xaf, 0x2f, 0xfb, 0xe6, 0x60, 0xb2, 0xfd, 0x55, 0x4c, 0xfe, 0xcb, 0xe1, 0x1c, - 0xdc, 0x80, 0x6b, 0xcd, 0x3d, 0xaa, 0xa9, 0xcd, 0x59, 0x45, 0x37, 0x07, 0xe9, 0x7d, 0xb5, 0x7a, - 0xa8, 0x52, 0x56, 0x6d, 0xd7, 0x81, 0x34, 0x6a, 0x25, 0x56, 0x80, 0x35, 0x63, 0x57, 0x37, 0x34, - 0x8d, 0xea, 0xc6, 0x6e, 0x31, 0x4e, 0xd6, 0x60, 0xf9, 0xc0, 0x38, 0x54, 0x8d, 0xa6, 0x56, 0x36, - 0x1b, 0xb5, 0x4a, 0x93, 0xab, 0x27, 0xb0, 0x72, 0xde, 0xae, 0xd7, 0x9a, 0x9a, 0xc1, 0x4a, 0x76, - 0xf5, 0xc8, 0xdc, 0x53, 0xe9, 0x3e, 0x16, 0x6b, 0x53, 0xad, 0xd7, 0xab, 0x7a, 0x49, 0x6d, 0xea, - 0x35, 0xa3, 0xb8, 0xb0, 0xfd, 0x6d, 0x0c, 0xf2, 0xd1, 0x0b, 0x62, 0x5d, 0x40, 0xbd, 0xaa, 0x36, - 0x2b, 0x35, 0xba, 0x7f, 0x8e, 0x41, 0x87, 0xba, 0x51, 0xae, 0x1d, 0x36, 0xd0, 0xa0, 0x2c, 0x24, - 0xab, 0xba, 0x71, 0xf0, 0x1c, 0x6d, 0x40, 0xb9, 0x6a, 0x94, 0x69, 0x4d, 0x2f, 0xe3, 0xc9, 0x69, - 0x48, 0xd4, 0x1a, 0xcf, 0x8b, 0x0b, 0x6c, 0xa0, 0xd7, 0x1a, 0xc5, 0x24, 0x7a, 0x6c, 0x5e, 0x35, - 0x8e, 0x4c, 0x89, 0x5c, 0x4c, 0x91, 0x65, 0x28, 0xa0, 0x59, 0x23, 0x49, 0xa3, 0x98, 0x26, 0x00, - 0xa9, 0xd2, 0x1e, 0xad, 0xed, 0x6b, 0xc5, 0xcc, 0x76, 0x05, 0x96, 0x26, 0x12, 0x35, 0xb9, 0x03, - 0x37, 0x4b, 0xb5, 0xfd, 0x3a, 0xf6, 0x28, 0x0d, 0xb4, 0x7d, 0x96, 0x71, 0x78, 0x1c, 0x55, 0x0f, - 0xd1, 0xb0, 0x0c, 0x2c, 0x50, 0xbd, 0x84, 0x0d, 0xc9, 0xb6, 0x03, 0x4b, 0x13, 0x4e, 0x83, 0xa1, - 0xbd, 0x25, 0x08, 0x47, 0x6e, 0xe8, 0xd1, 0x39, 0xbd, 0xce, 0x01, 0x45, 0x9a, 0x9f, 0xcb, 0xd3, - 0x10, 0x13, 0x0d, 0xfe, 0x54, 0x37, 0x54, 0xdc, 0x50, 0xd6, 0x77, 0xb5, 0x46, 0x13, 0x3f, 0x3a, - 0x0f, 0x19, 0xbd, 0x6e, 0x52, 0xd5, 0xd8, 0x45, 0xbe, 0x5f, 0xa4, 0xb8, 0xf3, 0x3c, 0xfc, 0x33, - 0x00, 0x00, 0xff, 0xff, 0x08, 0xe3, 0x60, 0x1f, 0xd4, 0x13, 0x00, 0x00, + // 1636 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x4f, 0x8f, 0xdb, 0xc6, + 0x15, 0x2f, 0xc5, 0x95, 0xb4, 0xfb, 0xf4, 0x67, 0xb9, 0x63, 0xaf, 0x2d, 0x6f, 0x62, 0x7b, 0x43, + 0x23, 0xad, 0x61, 0x14, 0x4a, 0xe1, 0x20, 0x49, 0x0b, 0x14, 0x6d, 0x58, 0x89, 0xf2, 0x12, 0xd1, + 0x92, 0xca, 0x48, 0xf2, 0xda, 0xcd, 0x81, 0xa0, 0xa9, 0xd1, 0x8a, 0x88, 0x44, 0x2a, 0x9c, 0x91, + 0xe5, 0xcd, 0x47, 0x28, 0xd0, 0x53, 0xd1, 0x73, 0x7b, 0xee, 0xb5, 0xe8, 0xb5, 0xdf, 0xa3, 0xc7, + 0x7e, 0x82, 0xa2, 0x87, 0xde, 0x8b, 0x19, 0x0e, 0x25, 0xea, 0xcf, 0x7a, 0xd7, 0x59, 0x1f, 0x72, + 0x9b, 0x79, 0x7c, 0xf3, 0x9b, 0xc7, 0xdf, 0xfb, 0x4b, 0x02, 0xa2, 0xde, 0x90, 0xbc, 0x8a, 0xa3, + 0x39, 0x0d, 0xc2, 0xf3, 0xfa, 0x34, 0x8e, 0x58, 0x84, 0x56, 0x64, 0xae, 0x90, 0x1d, 0x3d, 0x38, + 0x8f, 0xa2, 0xf3, 0x31, 0xf9, 0x44, 0xec, 0x5e, 0xcd, 0x86, 0x9f, 0x0c, 0x66, 0xb1, 0xc7, 0x82, + 0x28, 0x4c, 0xce, 0xe8, 0x7f, 0xcf, 0x01, 0xf4, 0x46, 0x31, 0xf1, 0x98, 0x15, 0x0e, 0x23, 0x64, + 0x40, 0x99, 0x89, 0x9d, 0xcb, 0x2e, 0xa6, 0x84, 0xd6, 0x94, 0x63, 0xf5, 0x71, 0xf5, 0xe9, 0x83, + 0xfa, 0x26, 0x72, 0x3d, 0x39, 0xd5, 0xbb, 0x98, 0x12, 0x5c, 0x62, 0x8b, 0x35, 0x45, 0xcf, 0xa0, + 0x3a, 0x1d, 0x7b, 0x6c, 0x18, 0xc5, 0x13, 0x09, 0x92, 0x13, 0x20, 0xc7, 0xdb, 0x40, 0x3a, 0x52, + 0x53, 0xc0, 0x54, 0xa6, 0x99, 0x1d, 0x45, 0x5f, 0x03, 0x92, 0xb6, 0x90, 0x90, 0xc5, 0x17, 0x12, + 0x6c, 0x47, 0x80, 0x3d, 0xba, 0xdc, 0x22, 0x93, 0x2b, 0x0b, 0x3c, 0x8d, 0xad, 0x0a, 0x28, 0x6a, + 0x41, 0x35, 0x03, 0x19, 0x10, 0x5a, 0x53, 0x8f, 0xd5, 0xc7, 0xa5, 0xa7, 0x0f, 0xaf, 0x80, 0xc3, + 0x95, 0x25, 0x54, 0x40, 0xa8, 0xfe, 0x4f, 0x15, 0x4a, 0xc9, 0xe3, 0x53, 0x8f, 0xf9, 0x23, 0xf4, + 0x5b, 0x28, 0x65, 0x68, 0xab, 0x29, 0xc7, 0xca, 0x35, 0x58, 0x83, 0x25, 0x6b, 0xc8, 0x84, 0xca, + 0x0a, 0x69, 0xb5, 0x9c, 0x80, 0xb8, 0x9a, 0xb3, 0x72, 0x96, 0x33, 0xe4, 0xc0, 0xc1, 0x06, 0x65, + 0xb5, 0x82, 0x80, 0xba, 0x16, 0x63, 0xfb, 0x6b, 0x8c, 0xa1, 0x2f, 0xa0, 0x90, 0x88, 0x6a, 0xea, + 0xb1, 0x72, 0x1d, 0xa2, 0xa4, 0x3a, 0xfa, 0x06, 0x0e, 0x57, 0x2c, 0x99, 0x10, 0xe6, 0x0d, 0x3c, + 0xe6, 0xd5, 0x76, 0x04, 0xce, 0xcf, 0xae, 0xc0, 0x39, 0x95, 0xea, 0xf8, 0x16, 0xdb, 0x14, 0xa2, + 0x2f, 0xa1, 0xea, 0x7b, 0xfe, 0x88, 0xb8, 0x69, 0x30, 0xd7, 0xf2, 0x02, 0xf5, 0x5e, 0x3d, 0x89, + 0xf6, 0x7a, 0x1a, 0xed, 0xf5, 0xa6, 0x54, 0xc0, 0x15, 0x71, 0x20, 0xdd, 0xea, 0x7f, 0x52, 0xa0, + 0xd6, 0x0a, 0xc2, 0x41, 0xc6, 0x89, 0x84, 0x62, 0xf2, 0xdd, 0x8c, 0x50, 0x86, 0x3e, 0x87, 0x82, + 0x3f, 0x0e, 0x48, 0xc8, 0x84, 0x23, 0x4b, 0xdb, 0x1d, 0xd9, 0x10, 0x1a, 0x3c, 0x69, 0xb0, 0xd4, + 0xce, 0x44, 0x41, 0x10, 0x0e, 0x23, 0xe1, 0xc2, 0xd2, 0xdb, 0xa2, 0x40, 0x1c, 0x96, 0x51, 0xc0, + 0xd7, 0xfa, 0x73, 0xb8, 0xb7, 0xc5, 0x28, 0x3a, 0x8d, 0x42, 0x4a, 0xd0, 0xaf, 0xa0, 0x38, 0x49, + 0x44, 0x22, 0x2b, 0xdf, 0xea, 0x0b, 0x71, 0x16, 0xa7, 0xfa, 0xfa, 0xdf, 0x0a, 0x70, 0xbf, 0x45, + 0x98, 0x3f, 0x4a, 0x9e, 0xb6, 0x03, 0xca, 0xfa, 0xd3, 0x81, 0xc7, 0x6e, 0xfe, 0xca, 0x33, 0xb8, + 0x3d, 0x0e, 0x28, 0x73, 0x67, 0x02, 0xce, 0x8d, 0x13, 0xb8, 0x34, 0xad, 0x1a, 0xdb, 0x50, 0xde, + 0x6a, 0x48, 0x7d, 0x29, 0x92, 0x12, 0x8c, 0xc6, 0xeb, 0x22, 0x7a, 0xf4, 0xaf, 0x1d, 0x38, 0xd8, + 0xd0, 0xfc, 0x71, 0x67, 0x61, 0xfe, 0x06, 0x59, 0x78, 0x1b, 0xf2, 0x94, 0x79, 0x8c, 0x88, 0x24, + 0x2c, 0xe3, 0x64, 0x83, 0xbe, 0x83, 0x92, 0x1f, 0x85, 0x94, 0xc5, 0x5e, 0x10, 0x32, 0x2a, 0x13, + 0xcb, 0x79, 0x0f, 0x94, 0xd7, 0x1b, 0x4b, 0x58, 0x9c, 0xbd, 0xe3, 0xe8, 0xdf, 0x0a, 0x94, 0x32, + 0x0f, 0xd1, 0xcf, 0x01, 0x4d, 0xbc, 0x37, 0xa9, 0xf7, 0xd3, 0x9a, 0xca, 0x89, 0xcf, 0x63, 0x6d, + 0xe2, 0xbd, 0x49, 0x60, 0x65, 0xd5, 0x44, 0xbf, 0x80, 0xdb, 0x5c, 0x9b, 0xa7, 0xf0, 0x2b, 0x8f, + 0x2e, 0xf5, 0x73, 0x42, 0x9f, 0x23, 0x35, 0xe5, 0xa3, 0xf4, 0xc4, 0x1d, 0x28, 0xc4, 0xe4, 0x9c, + 0x27, 0x38, 0x7f, 0xf3, 0x3d, 0x2c, 0x77, 0xe8, 0xf7, 0x70, 0x87, 0xce, 0xa6, 0xd3, 0x28, 0x66, + 0x64, 0xe0, 0xfa, 0xd1, 0x64, 0x1a, 0x13, 0x4a, 0x83, 0x28, 0x7c, 0x6b, 0x7b, 0x68, 0x2c, 0xf5, + 0x04, 0xcd, 0x87, 0x0b, 0x88, 0xcc, 0x13, 0xaa, 0xff, 0xb1, 0x08, 0x0f, 0x2e, 0x23, 0x4c, 0xa6, + 0xe2, 0x05, 0x1c, 0xae, 0x46, 0x7d, 0x22, 0x4f, 0x13, 0xd3, 0x7c, 0x17, 0x1f, 0x24, 0x47, 0x57, + 0x9c, 0x90, 0x88, 0xf0, 0xad, 0xf1, 0x86, 0x8c, 0xa2, 0x53, 0x38, 0x9c, 0x04, 0x61, 0x30, 0x99, + 0x4d, 0xdc, 0xb9, 0x17, 0xb0, 0x65, 0x05, 0xcc, 0x5d, 0x55, 0x01, 0x6f, 0xc9, 0x73, 0x67, 0x5e, + 0xc0, 0x52, 0xe1, 0xd1, 0x5f, 0xf3, 0x80, 0x36, 0xaf, 0xbe, 0x79, 0x26, 0x6d, 0x4d, 0x81, 0xdc, + 0x0d, 0x52, 0x60, 0x23, 0x35, 0xd5, 0x1f, 0x94, 0x9a, 0x73, 0xa8, 0xa4, 0xde, 0x4a, 0x60, 0x76, + 0x04, 0x0c, 0x7e, 0x2f, 0x1e, 0xab, 0xa7, 0x8b, 0xe4, 0xe2, 0x38, 0xb3, 0x43, 0x5f, 0xc2, 0x9e, + 0x37, 0x18, 0x04, 0x4c, 0x04, 0x69, 0x5e, 0x84, 0x89, 0x7e, 0x05, 0x11, 0x5d, 0xc2, 0xf0, 0xf2, + 0x10, 0xfa, 0x0d, 0xec, 0xc6, 0x64, 0x12, 0xbd, 0xf6, 0xc6, 0xb4, 0x56, 0xb8, 0x36, 0xc0, 0xe2, + 0x0c, 0x7a, 0x0c, 0x5a, 0x48, 0xe6, 0x6e, 0x52, 0xb8, 0xdd, 0xa4, 0x9e, 0x14, 0x45, 0x3d, 0xa9, + 0x86, 0x64, 0x9e, 0xd4, 0xf6, 0xae, 0x28, 0x2c, 0xbf, 0x84, 0x5d, 0x7f, 0x44, 0xfc, 0x6f, 0xe9, + 0x6c, 0x52, 0xdb, 0x15, 0x61, 0xf5, 0xe1, 0xd6, 0x7c, 0x92, 0x3a, 0x78, 0xa1, 0xad, 0x63, 0x28, + 0x67, 0x39, 0x40, 0xf7, 0xe1, 0x1e, 0x36, 0xbb, 0x1d, 0xc7, 0xee, 0x9a, 0x6e, 0xef, 0x65, 0xc7, + 0x74, 0xfb, 0x76, 0xb7, 0x63, 0x36, 0xac, 0x96, 0x65, 0x36, 0xb5, 0x9f, 0x20, 0x04, 0xd5, 0x8e, + 0x81, 0x7b, 0x96, 0xd1, 0x76, 0xfb, 0x9d, 0xa6, 0xd1, 0x33, 0x35, 0x05, 0xed, 0x43, 0xa9, 0xd5, + 0x6f, 0x2f, 0x04, 0x39, 0xfd, 0x1f, 0x0a, 0x1c, 0xf2, 0xae, 0xd8, 0x9a, 0x8d, 0xc7, 0x27, 0x1e, + 0x7d, 0x0f, 0x7d, 0xfa, 0x11, 0x54, 0xb2, 0x2c, 0x24, 0x03, 0x6a, 0x19, 0x97, 0xfd, 0x25, 0x07, + 0x74, 0xbd, 0x99, 0xab, 0xef, 0xdc, 0xcc, 0xff, 0xa7, 0xc0, 0x9d, 0x75, 0xbb, 0x6f, 0xdc, 0xca, + 0xdf, 0x73, 0xfe, 0xa3, 0xaf, 0xe1, 0x6e, 0x48, 0xce, 0x3d, 0x16, 0xbc, 0x26, 0xee, 0xda, 0x48, + 0xa5, 0x5e, 0x05, 0x78, 0x98, 0x9e, 0x6c, 0xac, 0x8c, 0x56, 0x1d, 0x80, 0x25, 0xe7, 0xe8, 0x03, + 0xd8, 0x93, 0x5c, 0x07, 0x03, 0xe1, 0xa6, 0x3d, 0xbc, 0x9b, 0x08, 0xac, 0x01, 0xfa, 0x18, 0xaa, + 0xf2, 0xe1, 0x6b, 0x12, 0xd3, 0xf4, 0x2d, 0xf6, 0xb0, 0x74, 0xcf, 0xf3, 0x44, 0xa8, 0xeb, 0xb0, + 0x9b, 0xc6, 0x1a, 0xef, 0x08, 0x74, 0xe4, 0x3d, 0xfd, 0xec, 0x73, 0x01, 0x56, 0xc6, 0x72, 0xa7, + 0x7f, 0x9a, 0x0e, 0xe4, 0x22, 0xf2, 0x11, 0x82, 0x9d, 0x91, 0x47, 0x47, 0x52, 0x49, 0xac, 0x91, + 0x06, 0xea, 0x2c, 0x1e, 0xcb, 0x2b, 0xf8, 0x52, 0xff, 0x6f, 0x0e, 0xaa, 0xab, 0xf9, 0x82, 0x6c, + 0xd0, 0x32, 0xfd, 0x24, 0x5b, 0xfe, 0xae, 0xd5, 0x53, 0xf6, 0xfd, 0x55, 0x01, 0xfa, 0x35, 0x40, + 0xec, 0xcd, 0xdd, 0x91, 0x08, 0x00, 0xe9, 0xa4, 0xfb, 0xdb, 0x90, 0xb0, 0x37, 0x97, 0x51, 0xb2, + 0x17, 0xa7, 0x4b, 0x1e, 0x84, 0xfc, 0x74, 0x10, 0x0e, 0x02, 0x5f, 0x7c, 0xac, 0x5c, 0x1a, 0x84, + 0xd8, 0x9b, 0x5b, 0x89, 0x16, 0xe6, 0x17, 0xca, 0x35, 0x6a, 0x41, 0x29, 0x0e, 0x7c, 0x92, 0xde, + 0x9f, 0xcc, 0x08, 0x1f, 0x6f, 0x05, 0x08, 0x7c, 0xd2, 0x24, 0x63, 0xe6, 0x99, 0xa1, 0x1f, 0x0d, + 0x82, 0xf0, 0x1c, 0x03, 0x3f, 0x29, 0x0d, 0x39, 0x81, 0xb2, 0xc0, 0x49, 0x2d, 0xc9, 0xbf, 0x0b, + 0x90, 0x30, 0x41, 0x5a, 0xa4, 0xff, 0x14, 0x60, 0x69, 0x2b, 0xaa, 0x41, 0x31, 0x85, 0xe4, 0x99, + 0x90, 0xc7, 0xe9, 0x56, 0xff, 0x0a, 0xf6, 0x16, 0x94, 0xa0, 0x87, 0x50, 0x9a, 0xc6, 0x64, 0x18, + 0xbc, 0x71, 0x69, 0xf0, 0x3d, 0x91, 0x03, 0x06, 0x24, 0xa2, 0x6e, 0xf0, 0x3d, 0x2f, 0x34, 0xeb, + 0x34, 0x97, 0x33, 0x3c, 0xea, 0x7f, 0x51, 0xe0, 0x60, 0xc3, 0x2e, 0x8e, 0x3a, 0x0c, 0x62, 0xca, + 0xdc, 0xd7, 0xde, 0x78, 0x96, 0xa0, 0xaa, 0x18, 0x84, 0xe8, 0x39, 0x97, 0xf0, 0xf8, 0x14, 0x6f, + 0x3d, 0xf5, 0x62, 0x6f, 0x42, 0x18, 0x89, 0xe5, 0xa8, 0x52, 0xe1, 0xd2, 0x4e, 0x2a, 0xe4, 0x38, + 0xe1, 0x6c, 0x92, 0xf9, 0xa4, 0x14, 0xd6, 0x85, 0xb3, 0x49, 0x3a, 0xc6, 0x7c, 0x04, 0x65, 0xc2, + 0x2f, 0x25, 0x03, 0x77, 0xf1, 0x0d, 0x54, 0xc6, 0x25, 0x29, 0xe3, 0x43, 0x0f, 0xb7, 0xf0, 0xd6, + 0x96, 0xef, 0x1f, 0xe4, 0x40, 0x71, 0x39, 0x56, 0xf1, 0x52, 0xf1, 0xd9, 0x35, 0xbf, 0x9c, 0xea, + 0xe9, 0x22, 0xf9, 0x2e, 0x4b, 0x51, 0x8e, 0xbe, 0x80, 0xca, 0xca, 0x13, 0x9e, 0x16, 0xdf, 0x92, + 0x0b, 0x99, 0x29, 0x7c, 0xc9, 0xc7, 0xcd, 0x84, 0x91, 0x84, 0xc7, 0x64, 0xa3, 0xff, 0x47, 0x81, + 0xdb, 0xcb, 0x6e, 0xd8, 0x24, 0xd4, 0x8f, 0x83, 0x29, 0x8b, 0xe2, 0x1f, 0xf7, 0xd8, 0xad, 0xfe, + 0xf0, 0x99, 0x43, 0x1f, 0xc2, 0x5d, 0xfe, 0xaa, 0xcb, 0x97, 0x5e, 0x56, 0xf0, 0xaf, 0x16, 0xff, + 0x49, 0xf8, 0x90, 0x96, 0xfa, 0xe6, 0xf1, 0xe5, 0xd7, 0xac, 0x72, 0x96, 0xfe, 0x31, 0x11, 0xa0, + 0x4f, 0xfe, 0xa0, 0xa4, 0xff, 0x60, 0xc4, 0x7b, 0x7c, 0x00, 0x77, 0x7b, 0x27, 0xd8, 0x34, 0x7a, + 0xdb, 0x5a, 0x66, 0x09, 0x8a, 0xa7, 0x46, 0xfb, 0xcc, 0xc0, 0xbc, 0x57, 0xde, 0x01, 0xd4, 0x75, + 0x1a, 0xbc, 0x7d, 0x9a, 0xf6, 0x33, 0xcb, 0x36, 0x4d, 0x6c, 0xd9, 0xcf, 0xb4, 0x1c, 0x3a, 0x84, + 0x83, 0xbe, 0x7d, 0x66, 0xd8, 0x3d, 0xb3, 0xe9, 0x76, 0x9d, 0x56, 0x4f, 0xa8, 0xab, 0xe8, 0x11, + 0x3c, 0xec, 0x38, 0x3d, 0xd3, 0xe6, 0x0d, 0xb7, 0xfd, 0xd2, 0x3d, 0x31, 0xf0, 0x69, 0xab, 0xdf, + 0x76, 0x8d, 0x4e, 0xa7, 0x6d, 0x35, 0x8c, 0x9e, 0xe5, 0xd8, 0xda, 0xce, 0x93, 0x3f, 0x2b, 0x50, + 0xce, 0x92, 0xcc, 0x7b, 0x78, 0xa7, 0x6d, 0xf4, 0x5a, 0x0e, 0x3e, 0xbd, 0xc4, 0xa0, 0x33, 0xcb, + 0x6e, 0x3a, 0x67, 0x5d, 0x4d, 0x41, 0x7b, 0x90, 0x6f, 0x5b, 0x76, 0xff, 0x85, 0x96, 0xe3, 0x72, + 0xc3, 0x6e, 0x62, 0xc7, 0x6a, 0x6a, 0x2a, 0x2a, 0x82, 0xea, 0x74, 0x5f, 0x68, 0x3b, 0x7c, 0x61, + 0x39, 0x5d, 0x2d, 0x8f, 0x34, 0x28, 0x1b, 0xf6, 0x4b, 0x37, 0x45, 0xd6, 0x0a, 0xe8, 0x00, 0x2a, + 0x46, 0xbb, 0xbd, 0x90, 0x74, 0xb5, 0x22, 0x02, 0x28, 0x34, 0x4e, 0xb0, 0x73, 0x6a, 0x6a, 0xbb, + 0x4f, 0x5a, 0xb0, 0xbf, 0x56, 0x6c, 0xd1, 0x31, 0x7c, 0xd8, 0x70, 0x4e, 0x3b, 0xd8, 0xec, 0x76, + 0x2d, 0xc7, 0xde, 0x66, 0x5c, 0x11, 0x54, 0x6c, 0x9c, 0x69, 0x0a, 0xda, 0x85, 0x1d, 0x6c, 0x35, + 0x4c, 0x2d, 0xf7, 0xe4, 0x1b, 0xd8, 0x5f, 0x73, 0x3c, 0xfa, 0x08, 0xee, 0x4b, 0xc2, 0x4d, 0xbb, + 0x87, 0x5f, 0x5e, 0x02, 0xd4, 0xc7, 0x6d, 0x4d, 0x41, 0x55, 0x00, 0xf3, 0x85, 0xd9, 0xe8, 0xf7, + 0x8c, 0xdf, 0xb5, 0x4d, 0x2d, 0x87, 0xca, 0xb0, 0x6b, 0x75, 0x5c, 0x6c, 0xd8, 0xcf, 0x4c, 0x4d, + 0x7d, 0x55, 0x10, 0x2e, 0xff, 0xf4, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x68, 0x6b, 0x92, 0x80, + 0x9e, 0x13, 0x00, 0x00, } diff --git a/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.proto b/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.proto index 9d273ed2c..4ad500607 100644 --- a/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.proto +++ b/vendor/github.com/google/safebrowsing/internal/safebrowsing_proto/safebrowsing.proto @@ -14,6 +14,8 @@ syntax = "proto3"; +import "google/protobuf/duration.proto"; + package safebrowsing_proto; // The Safe Browsing APIs enable clients to check web resources (most commonly @@ -81,7 +83,7 @@ message ThreatMatch { // The cache lifetime for the returned match. Clients must not cache this // response for more than this duration to avoid false positives. - Duration cache_duration = 5; + google.protobuf.Duration cache_duration = 5; } // Request to check entries against lists. @@ -208,7 +210,7 @@ message FetchThreatListUpdatesResponse { // The minimum duration the client must wait before issuing any update // request. If this field is not set clients may update as soon as they want. - Duration minimum_wait_duration = 2; + google.protobuf.Duration minimum_wait_duration = 2; } // Request to return full hashes matched by the provided hash prefixes. @@ -231,11 +233,11 @@ message FindFullHashesResponse { // The minimum duration the client must wait before issuing any find hashes // request. If this field is not set, clients can issue a request as soon as // they want. - Duration minimum_wait_duration = 2; + google.protobuf.Duration minimum_wait_duration = 2; // For requested entities that did not match the threat list, how long to // cache the response. - Duration negative_cache_duration = 3; + google.protobuf.Duration negative_cache_duration = 3; } @@ -444,24 +446,3 @@ message ListThreatListsResponse { // The lists available for download by the client. repeated ThreatListDescriptor threat_lists = 1; } - -// A Duration represents a signed, fixed-length span of time represented -// as a count of seconds and fractions of seconds at nanosecond -// resolution. It is independent of any calendar and concepts like "day" -// or "month". It is related to Timestamp in that the difference between -// two Timestamp values is a Duration and it can be added or subtracted -// from a Timestamp. Range is approximately +-10,000 years. -message Duration { - - // Signed seconds of the span of time. Must be from -315,576,000,000 - // to +315,576,000,000 inclusive. - int64 seconds = 1; - - // Signed fractions of a second at nanosecond resolution of the span - // of time. Durations less than one second are represented with a 0 - // `seconds` field and a positive or negative `nanos` field. For durations - // of one second or more, a non-zero value for the `nanos` field must be - // of the same sign as the `seconds` field. Must be from -999,999,999 - // to +999,999,999 inclusive. - int32 nanos = 2; -} diff --git a/vendor/github.com/google/safebrowsing/safebrowser.go b/vendor/github.com/google/safebrowsing/safebrowser.go index d6fbef7d9..f0cdfdb6f 100644 --- a/vendor/github.com/google/safebrowsing/safebrowser.go +++ b/vendor/github.com/google/safebrowsing/safebrowser.go @@ -72,6 +72,7 @@ package safebrowsing import ( + "context" "errors" "io" "io/ioutil" @@ -94,6 +95,10 @@ const ( // strings to send with every API call. DefaultID = "GoSafeBrowser" DefaultVersion = "1.0.0" + + // DefaultRequestTimeout is the default amount of time a single + // api request can take. + DefaultRequestTimeout = time.Minute ) // Errors specific to this package. @@ -207,6 +212,9 @@ type Config struct { // If empty, it defaults to DefaultThreatLists. ThreatLists []ThreatDescriptor + // RequestTimeout determines the timeout value for the http client. + RequestTimeout time.Duration + // Logger is an io.Writer that allows SafeBrowser to write debug information // intended for human consumption. // If empty, no logs will be written. @@ -231,6 +239,9 @@ func (c *Config) setDefaults() bool { if c.UpdatePeriod <= 0 { c.UpdatePeriod = DefaultUpdatePeriod } + if c.RequestTimeout <= 0 { + c.RequestTimeout = DefaultRequestTimeout + } if c.compressionTypes == nil { c.compressionTypes = []pb.CompressionType{pb.CompressionType_RAW, pb.CompressionType_RICE} } @@ -251,8 +262,8 @@ func (c Config) copy() Config { // local database and caching that would normally be needed to interact // with the API server. type SafeBrowser struct { + stats Stats // Must be first for 64-bit alignment on non 64-bit systems. config Config - stats Stats api api db database c cache @@ -267,10 +278,11 @@ type SafeBrowser struct { // Stats records statistics regarding SafeBrowser's operation. type Stats struct { - QueriesByDatabase int64 // Number of queries satisfied by the database alone - QueriesByCache int64 // Number of queries satisfied by the cache alone - QueriesByAPI int64 // Number of queries satisfied by an API call - QueriesFail int64 // Number of queries that could not be satisfied + QueriesByDatabase int64 // Number of queries satisfied by the database alone + QueriesByCache int64 // Number of queries satisfied by the cache alone + QueriesByAPI int64 // Number of queries satisfied by an API call + QueriesFail int64 // Number of queries that could not be satisfied + DatabaseUpdateLag time.Duration // Duration since last *missed* update. 0 if next update is in the future. } // NewSafeBrowser creates a new SafeBrowser. @@ -286,7 +298,7 @@ func NewSafeBrowser(conf Config) (*SafeBrowser, error) { // Create the SafeBrowsing object. if conf.api == nil { var err error - conf.api, err = newNetAPI(conf.ServerURL, conf.APIKey) + conf.api, err = newNetAPI(conf.ServerURL, conf.APIKey, conf.RequestTimeout) if err != nil { return nil, err } @@ -316,14 +328,19 @@ func NewSafeBrowser(conf Config) (*SafeBrowser, error) { } sb.log = log.New(w, "safebrowsing: ", log.Ldate|log.Ltime|log.Lshortfile) + delay := time.Duration(0) // If database file is provided, use that to initialize. if !sb.db.Init(&sb.config, sb.log) { - sb.db.Update(sb.api) + delay, _ = sb.db.Update(sb.api) + } else { + if age := sb.db.SinceLastUpdate(); age < sb.config.UpdatePeriod { + delay = sb.config.UpdatePeriod - age + } } // Start the background list updater. sb.done = make(chan bool) - go sb.updater(conf.UpdatePeriod) + go sb.updater(delay) return sb, nil } @@ -337,10 +354,28 @@ func (sb *SafeBrowser) Status() (Stats, error) { QueriesByCache: atomic.LoadInt64(&sb.stats.QueriesByCache), QueriesByAPI: atomic.LoadInt64(&sb.stats.QueriesByAPI), QueriesFail: atomic.LoadInt64(&sb.stats.QueriesFail), + DatabaseUpdateLag: sb.db.UpdateLag(), } return stats, sb.db.Status() } +// WaitUntilReady blocks until the database is not in an error state. +// Returns nil when the database is ready. Returns an error if the provided +// context is canceled or if the SafeBrowser instance is Closed. +func (sb *SafeBrowser) WaitUntilReady(ctx context.Context) error { + if atomic.LoadUint32(&sb.closed) == 1 { + return errClosed + } + select { + case <-sb.db.Ready(): + return nil + case <-ctx.Done(): + return ctx.Err() + case <-sb.done: + return errClosed + } +} + // LookupURLs looks up the provided URLs. It returns a list of threats, one for // every URL requested, and an error if any occurred. It is safe to call this // method concurrently. @@ -492,16 +527,17 @@ func (sb *SafeBrowser) LookupURLs(urls []string) (threats [][]URLThreat, err err // updater is a blocking method that periodically updates the local database. // This should be run as a separate goroutine and will be automatically stopped // when sb.Close is called. -func (sb *SafeBrowser) updater(period time.Duration) { - ticker := time.NewTicker(period) - defer ticker.Stop() - +func (sb *SafeBrowser) updater(delay time.Duration) { for { + sb.log.Printf("Next update in %v", delay) select { - case <-ticker.C: - sb.log.Printf("background threat list update") - sb.c.Purge() - sb.db.Update(sb.api) + case <-time.After(delay): + var ok bool + if delay, ok = sb.db.Update(sb.api); ok { + sb.log.Printf("background threat list updated") + sb.c.Purge() + } + case <-sb.done: return } diff --git a/vendor/github.com/google/safebrowsing/urls.go b/vendor/github.com/google/safebrowsing/urls.go index d9df95947..4f9957d88 100644 --- a/vendor/github.com/google/safebrowsing/urls.go +++ b/vendor/github.com/google/safebrowsing/urls.go @@ -426,13 +426,9 @@ func generateLookupHosts(urlStr string) ([]string, error) { return nil, err } // handle IPv4 and IPv6 addresses. - u, err := url.Parse(urlStr) - if err != nil { - return nil, err - } - ip := net.ParseIP(strings.Trim(u.Host, "[]")) + ip := net.ParseIP(strings.Trim(host, "[]")) if ip != nil { - return []string{u.Host}, nil + return []string{host}, nil } hostComponents := strings.Split(host, ".")