Merge pull request #20 from lbryio/feature/6/jeffreypicard/hub-federation
Most of federation is written, need to finish udp and test
This commit is contained in:
commit
284f825d22
16 changed files with 2047 additions and 497 deletions
5
.github/workflows/build-short.yml
vendored
5
.github/workflows/build-short.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: 'Build Hub'
|
name: 'Build and Test Hub'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -10,4 +10,5 @@ jobs:
|
||||||
- uses: actions/setup-go@v2.1.3
|
- uses: actions/setup-go@v2.1.3
|
||||||
with:
|
with:
|
||||||
go-version: 1.16.5
|
go-version: 1.16.5
|
||||||
- run: go build .
|
- run: go build .
|
||||||
|
- run: cd server && go test -v -race
|
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: 'Build Hub'
|
name: 'Build and Test Hub'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -30,3 +30,4 @@ jobs:
|
||||||
- run: go get github.com/golang/protobuf/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
- run: go get github.com/golang/protobuf/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||||
- run: go build .
|
- run: go build .
|
||||||
- run: ./protobuf/build.sh
|
- run: ./protobuf/build.sh
|
||||||
|
- run: cd server && go test -v -race
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -8,10 +8,11 @@ require (
|
||||||
github.com/lbryio/lbry.go/v2 v2.7.2-0.20210625145058-2b155597bf57
|
github.com/lbryio/lbry.go/v2 v2.7.2-0.20210625145058-2b155597bf57
|
||||||
github.com/olivere/elastic/v7 v7.0.24
|
github.com/olivere/elastic/v7 v7.0.24
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
|
github.com/prometheus/client_model v0.2.0
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||||
golang.org/x/text v0.3.6
|
golang.org/x/text v0.3.6
|
||||||
google.golang.org/genproto v0.0.0-20210524171403-669157292da3 // indirect
|
google.golang.org/genproto v0.0.0-20210524171403-669157292da3 // indirect
|
||||||
google.golang.org/grpc v1.38.0
|
google.golang.org/grpc v1.38.0
|
||||||
google.golang.org/protobuf v1.26.0
|
google.golang.org/protobuf v1.27.1
|
||||||
gopkg.in/karalabe/cookiejar.v1 v1.0.0-20141109175019-e1490cae028c
|
gopkg.in/karalabe/cookiejar.v1 v1.0.0-20141109175019-e1490cae028c
|
||||||
)
|
)
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -313,8 +313,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
@ -22,5 +22,13 @@ var (
|
||||||
Help: "Histogram of query times",
|
Help: "Histogram of query times",
|
||||||
Buckets: HistogramBuckets,
|
Buckets: HistogramBuckets,
|
||||||
}, []string{"method"})
|
}, []string{"method"})
|
||||||
|
PeersKnown = promauto.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: "peers_known",
|
||||||
|
Help: "Number of peers we know about.",
|
||||||
|
})
|
||||||
|
PeersSubscribed = promauto.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: "peers_subbed",
|
||||||
|
Help: "Number of peers that are subscribed to us.",
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
192
main.go
192
main.go
|
@ -4,189 +4,45 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/akamensky/argparse"
|
|
||||||
pb "github.com/lbryio/hub/protobuf/go"
|
pb "github.com/lbryio/hub/protobuf/go"
|
||||||
"github.com/lbryio/hub/server"
|
"github.com/lbryio/hub/server"
|
||||||
"github.com/lbryio/lbry.go/v2/extras/util"
|
"github.com/lbryio/lbry.go/v2/extras/util"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/reflection"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
defaultHost = "0.0.0.0"
|
|
||||||
defaultPort = "50051"
|
|
||||||
defaultEsHost = "http://localhost"
|
|
||||||
defaultEsIndex = "claims"
|
|
||||||
defaultEsPort = "9200"
|
|
||||||
defaultRefreshDelta = 5
|
|
||||||
defaultCacheTTL = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetEnvironment(data []string, getkeyval func(item string) (key, val string)) map[string]string {
|
|
||||||
items := make(map[string]string)
|
|
||||||
for _, item := range data {
|
|
||||||
key, val := getkeyval(item)
|
|
||||||
items[key] = val
|
|
||||||
}
|
|
||||||
return items
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetEnvironmentStandard() map[string]string {
|
|
||||||
return GetEnvironment(os.Environ(), func(item string) (key, val string) {
|
|
||||||
splits := strings.Split(item, "=")
|
|
||||||
key = splits[0]
|
|
||||||
val = splits[1]
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func makeServeCmd(parser *argparse.Parser) *argparse.Command {
|
|
||||||
serveCmd := parser.NewCommand("serve", "start the hub server")
|
|
||||||
|
|
||||||
host := serveCmd.String("", "rpchost", &argparse.Options{Required: false, Help: "host", Default: defaultHost})
|
|
||||||
port := serveCmd.String("", "rpcport", &argparse.Options{Required: false, Help: "port", Default: defaultPort})
|
|
||||||
esHost := serveCmd.String("", "eshost", &argparse.Options{Required: false, Help: "host", Default: defaultEsHost})
|
|
||||||
esPort := serveCmd.String("", "esport", &argparse.Options{Required: false, Help: "port", Default: defaultEsPort})
|
|
||||||
dev := serveCmd.Flag("", "dev", &argparse.Options{Required: false, Help: "port", Default: false})
|
|
||||||
|
|
||||||
return serveCmd
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func parseArgs(searchRequest *pb.SearchRequest) *server.Args {
|
|
||||||
|
|
||||||
environment := GetEnvironmentStandard()
|
|
||||||
parser := argparse.NewParser("hub", "hub server and client")
|
|
||||||
|
|
||||||
serveCmd := parser.NewCommand("serve", "start the hub server")
|
|
||||||
searchCmd := parser.NewCommand("search", "claim search")
|
|
||||||
debug := parser.Flag("", "debug", &argparse.Options{Required: false, Help: "enable debug logging", Default: false})
|
|
||||||
|
|
||||||
host := parser.String("", "rpchost", &argparse.Options{Required: false, Help: "RPC host", Default: defaultHost})
|
|
||||||
port := parser.String("", "rpcport", &argparse.Options{Required: false, Help: "RPC port", Default: defaultPort})
|
|
||||||
esHost := parser.String("", "eshost", &argparse.Options{Required: false, Help: "elasticsearch host", Default: defaultEsHost})
|
|
||||||
esPort := parser.String("", "esport", &argparse.Options{Required: false, Help: "elasticsearch port", Default: defaultEsPort})
|
|
||||||
esIndex := parser.String("", "esindex", &argparse.Options{Required: false, Help: "elasticsearch index name", Default: defaultEsIndex})
|
|
||||||
refreshDelta := parser.Int("", "refresh-delta", &argparse.Options{Required: false, Help: "elasticsearch index refresh delta in seconds", Default: defaultRefreshDelta})
|
|
||||||
cacheTTL := parser.Int("", "cachettl", &argparse.Options{Required: false, Help: "Cache TTL in minutes", Default: defaultCacheTTL})
|
|
||||||
|
|
||||||
text := parser.String("", "text", &argparse.Options{Required: false, Help: "text query"})
|
|
||||||
name := parser.String("", "name", &argparse.Options{Required: false, Help: "name"})
|
|
||||||
claimType := parser.String("", "claim_type", &argparse.Options{Required: false, Help: "claim_type"})
|
|
||||||
id := parser.String("", "id", &argparse.Options{Required: false, Help: "id"})
|
|
||||||
author := parser.String("", "author", &argparse.Options{Required: false, Help: "author"})
|
|
||||||
title := parser.String("", "title", &argparse.Options{Required: false, Help: "title"})
|
|
||||||
description := parser.String("", "description", &argparse.Options{Required: false, Help: "description"})
|
|
||||||
channelId := parser.String("", "channel_id", &argparse.Options{Required: false, Help: "channel id"})
|
|
||||||
channelIds := parser.StringList("", "channel_ids", &argparse.Options{Required: false, Help: "channel ids"})
|
|
||||||
|
|
||||||
// Now parse the arguments
|
|
||||||
err := parser.Parse(os.Args)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(parser.Usage(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
args := &server.Args{
|
|
||||||
CmdType: server.SearchCmd,
|
|
||||||
Host: *host,
|
|
||||||
Port: ":" + *port,
|
|
||||||
EsHost: *esHost,
|
|
||||||
EsPort: *esPort,
|
|
||||||
EsIndex: *esIndex,
|
|
||||||
Debug: *debug,
|
|
||||||
RefreshDelta: *refreshDelta,
|
|
||||||
CacheTTL: *cacheTTL,
|
|
||||||
}
|
|
||||||
|
|
||||||
if esHost, ok := environment["ELASTIC_HOST"]; ok {
|
|
||||||
args.EsHost = esHost
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.HasPrefix(args.EsHost, "http") {
|
|
||||||
args.EsHost = "http://" + args.EsHost
|
|
||||||
}
|
|
||||||
|
|
||||||
if esPort, ok := environment["ELASTIC_PORT"]; ok {
|
|
||||||
args.EsPort = esPort
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Verify no invalid argument combinations
|
|
||||||
*/
|
|
||||||
if len(*channelIds) > 0 && *channelId != "" {
|
|
||||||
log.Fatal("Cannot specify both channel_id and channel_ids")
|
|
||||||
}
|
|
||||||
|
|
||||||
if serveCmd.Happened() {
|
|
||||||
args.CmdType = server.ServeCmd
|
|
||||||
} else if searchCmd.Happened() {
|
|
||||||
args.CmdType = server.SearchCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
if *text != "" {
|
|
||||||
searchRequest.Text = *text
|
|
||||||
}
|
|
||||||
if *name != "" {
|
|
||||||
searchRequest.ClaimName = *name
|
|
||||||
}
|
|
||||||
if *claimType != "" {
|
|
||||||
searchRequest.ClaimType = []string{*claimType}
|
|
||||||
}
|
|
||||||
if *id != "" {
|
|
||||||
searchRequest.ClaimId = &pb.InvertibleField{Invert: false, Value: []string{*id}}
|
|
||||||
}
|
|
||||||
if *author != "" {
|
|
||||||
searchRequest.Author = *author
|
|
||||||
}
|
|
||||||
if *title != "" {
|
|
||||||
searchRequest.Title = *title
|
|
||||||
}
|
|
||||||
if *description != "" {
|
|
||||||
searchRequest.Description = *description
|
|
||||||
}
|
|
||||||
if *channelId != "" {
|
|
||||||
searchRequest.ChannelId = &pb.InvertibleField{Invert: false, Value: []string{*channelId}}
|
|
||||||
}
|
|
||||||
if len(*channelIds) > 0 {
|
|
||||||
searchRequest.ChannelId = &pb.InvertibleField{Invert: false, Value: *channelIds}
|
|
||||||
}
|
|
||||||
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
searchRequest := &pb.SearchRequest{}
|
searchRequest := &pb.SearchRequest{}
|
||||||
|
|
||||||
args := parseArgs(searchRequest)
|
args := server.ParseArgs(searchRequest)
|
||||||
|
|
||||||
if args.CmdType == server.ServeCmd {
|
if args.CmdType == server.ServeCmd {
|
||||||
|
// This will cancel goroutines with the server finishes.
|
||||||
|
ctxWCancel, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
l, err := net.Listen("tcp", args.Port)
|
s := server.MakeHubServer(ctxWCancel, args)
|
||||||
if err != nil {
|
s.Run()
|
||||||
log.Fatalf("failed to listen: %v", err)
|
//l, err := net.Listen("tcp", ":"+args.Port)
|
||||||
}
|
//if err != nil {
|
||||||
|
// log.Fatalf("failed to listen: %v", err)
|
||||||
s := server.MakeHubServer(args)
|
//}
|
||||||
pb.RegisterHubServer(s.GrpcServer, s)
|
//
|
||||||
reflection.Register(s.GrpcServer)
|
//pb.RegisterHubServer(s.GrpcServer, s)
|
||||||
|
//reflection.Register(s.GrpcServer)
|
||||||
log.Printf("listening on %s\n", l.Addr().String())
|
//
|
||||||
log.Println(s.Args)
|
//log.Printf("listening on %s\n", l.Addr().String())
|
||||||
go s.PromethusEndpoint("2112", "metrics")
|
//log.Println(s.Args)
|
||||||
if err := s.GrpcServer.Serve(l); err != nil {
|
//if err := s.GrpcServer.Serve(l); err != nil {
|
||||||
log.Fatalf("failed to serve: %v", err)
|
// log.Fatalf("failed to serve: %v", err)
|
||||||
}
|
//}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := grpc.Dial("localhost"+args.Port,
|
conn, err := grpc.Dial("localhost:"+args.Port,
|
||||||
grpc.WithInsecure(),
|
grpc.WithInsecure(),
|
||||||
grpc.WithBlock(),
|
grpc.WithBlock(),
|
||||||
)
|
)
|
||||||
|
@ -197,13 +53,13 @@ func main() {
|
||||||
|
|
||||||
c := pb.NewHubClient(conn)
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
ctxWTimeout, cancelQuery := context.WithTimeout(ctx, time.Second)
|
||||||
defer cancel()
|
defer cancelQuery()
|
||||||
|
|
||||||
log.Println(args)
|
log.Println(args)
|
||||||
switch args.CmdType {
|
switch args.CmdType {
|
||||||
case server.SearchCmd:
|
case server.SearchCmd:
|
||||||
r, err := c.Search(ctx, searchRequest)
|
r, err := c.Search(ctxWTimeout, searchRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ package pb;
|
||||||
service Hub {
|
service Hub {
|
||||||
rpc Search (SearchRequest) returns (Outputs) {}
|
rpc Search (SearchRequest) returns (Outputs) {}
|
||||||
rpc Ping (EmptyMessage) returns (StringValue) {}
|
rpc Ping (EmptyMessage) returns (StringValue) {}
|
||||||
|
rpc Hello (HelloMessage) returns (HelloMessage) {}
|
||||||
|
rpc AddPeer (ServerMessage) returns (StringValue) {}
|
||||||
|
rpc PeerSubscribe (ServerMessage) returns (StringValue) {}
|
||||||
rpc Version (EmptyMessage) returns (StringValue) {}
|
rpc Version (EmptyMessage) returns (StringValue) {}
|
||||||
rpc Features (EmptyMessage) returns (StringValue) {}
|
rpc Features (EmptyMessage) returns (StringValue) {}
|
||||||
rpc Broadcast(EmptyMessage) returns (UInt32Value) {}
|
rpc Broadcast(EmptyMessage) returns (UInt32Value) {}
|
||||||
|
@ -15,6 +18,17 @@ service Hub {
|
||||||
|
|
||||||
message EmptyMessage {}
|
message EmptyMessage {}
|
||||||
|
|
||||||
|
message ServerMessage {
|
||||||
|
string address = 1;
|
||||||
|
string port = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HelloMessage {
|
||||||
|
string port = 1;
|
||||||
|
string host = 2;
|
||||||
|
repeated ServerMessage servers = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message InvertibleField {
|
message InvertibleField {
|
||||||
bool invert = 1;
|
bool invert = 1;
|
||||||
repeated string value = 2;
|
repeated string value = 2;
|
||||||
|
|
|
@ -72,7 +72,7 @@ func (x RangeField_Op) Number() protoreflect.EnumNumber {
|
||||||
|
|
||||||
// Deprecated: Use RangeField_Op.Descriptor instead.
|
// Deprecated: Use RangeField_Op.Descriptor instead.
|
||||||
func (RangeField_Op) EnumDescriptor() ([]byte, []int) {
|
func (RangeField_Op) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{5, 0}
|
return file_hub_proto_rawDescGZIP(), []int{7, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
type EmptyMessage struct {
|
type EmptyMessage struct {
|
||||||
|
@ -113,6 +113,124 @@ func (*EmptyMessage) Descriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{0}
|
return file_hub_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ServerMessage struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address"`
|
||||||
|
Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerMessage) Reset() {
|
||||||
|
*x = ServerMessage{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_hub_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerMessage) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ServerMessage) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ServerMessage) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_hub_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ServerMessage.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ServerMessage) Descriptor() ([]byte, []int) {
|
||||||
|
return file_hub_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerMessage) GetAddress() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Address
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerMessage) GetPort() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Port
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type HelloMessage struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Port string `protobuf:"bytes,1,opt,name=port,proto3" json:"port"`
|
||||||
|
Host string `protobuf:"bytes,2,opt,name=host,proto3" json:"host"`
|
||||||
|
Servers []*ServerMessage `protobuf:"bytes,3,rep,name=servers,proto3" json:"servers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HelloMessage) Reset() {
|
||||||
|
*x = HelloMessage{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_hub_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HelloMessage) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*HelloMessage) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *HelloMessage) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_hub_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use HelloMessage.ProtoReflect.Descriptor instead.
|
||||||
|
func (*HelloMessage) Descriptor() ([]byte, []int) {
|
||||||
|
return file_hub_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HelloMessage) GetPort() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Port
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HelloMessage) GetHost() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Host
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HelloMessage) GetServers() []*ServerMessage {
|
||||||
|
if x != nil {
|
||||||
|
return x.Servers
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type InvertibleField struct {
|
type InvertibleField struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@ -125,7 +243,7 @@ type InvertibleField struct {
|
||||||
func (x *InvertibleField) Reset() {
|
func (x *InvertibleField) Reset() {
|
||||||
*x = InvertibleField{}
|
*x = InvertibleField{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_hub_proto_msgTypes[1]
|
mi := &file_hub_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
@ -138,7 +256,7 @@ func (x *InvertibleField) String() string {
|
||||||
func (*InvertibleField) ProtoMessage() {}
|
func (*InvertibleField) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *InvertibleField) ProtoReflect() protoreflect.Message {
|
func (x *InvertibleField) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_hub_proto_msgTypes[1]
|
mi := &file_hub_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
@ -151,7 +269,7 @@ func (x *InvertibleField) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use InvertibleField.ProtoReflect.Descriptor instead.
|
// Deprecated: Use InvertibleField.ProtoReflect.Descriptor instead.
|
||||||
func (*InvertibleField) Descriptor() ([]byte, []int) {
|
func (*InvertibleField) Descriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{1}
|
return file_hub_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InvertibleField) GetInvert() bool {
|
func (x *InvertibleField) GetInvert() bool {
|
||||||
|
@ -179,7 +297,7 @@ type StringValue struct {
|
||||||
func (x *StringValue) Reset() {
|
func (x *StringValue) Reset() {
|
||||||
*x = StringValue{}
|
*x = StringValue{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_hub_proto_msgTypes[2]
|
mi := &file_hub_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
@ -192,7 +310,7 @@ func (x *StringValue) String() string {
|
||||||
func (*StringValue) ProtoMessage() {}
|
func (*StringValue) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *StringValue) ProtoReflect() protoreflect.Message {
|
func (x *StringValue) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_hub_proto_msgTypes[2]
|
mi := &file_hub_proto_msgTypes[4]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
@ -205,7 +323,7 @@ func (x *StringValue) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use StringValue.ProtoReflect.Descriptor instead.
|
// Deprecated: Use StringValue.ProtoReflect.Descriptor instead.
|
||||||
func (*StringValue) Descriptor() ([]byte, []int) {
|
func (*StringValue) Descriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{2}
|
return file_hub_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *StringValue) GetValue() string {
|
func (x *StringValue) GetValue() string {
|
||||||
|
@ -226,7 +344,7 @@ type BoolValue struct {
|
||||||
func (x *BoolValue) Reset() {
|
func (x *BoolValue) Reset() {
|
||||||
*x = BoolValue{}
|
*x = BoolValue{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_hub_proto_msgTypes[3]
|
mi := &file_hub_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
@ -239,7 +357,7 @@ func (x *BoolValue) String() string {
|
||||||
func (*BoolValue) ProtoMessage() {}
|
func (*BoolValue) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BoolValue) ProtoReflect() protoreflect.Message {
|
func (x *BoolValue) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_hub_proto_msgTypes[3]
|
mi := &file_hub_proto_msgTypes[5]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
@ -252,7 +370,7 @@ func (x *BoolValue) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use BoolValue.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BoolValue.ProtoReflect.Descriptor instead.
|
||||||
func (*BoolValue) Descriptor() ([]byte, []int) {
|
func (*BoolValue) Descriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{3}
|
return file_hub_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BoolValue) GetValue() bool {
|
func (x *BoolValue) GetValue() bool {
|
||||||
|
@ -273,7 +391,7 @@ type UInt32Value struct {
|
||||||
func (x *UInt32Value) Reset() {
|
func (x *UInt32Value) Reset() {
|
||||||
*x = UInt32Value{}
|
*x = UInt32Value{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_hub_proto_msgTypes[4]
|
mi := &file_hub_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
@ -286,7 +404,7 @@ func (x *UInt32Value) String() string {
|
||||||
func (*UInt32Value) ProtoMessage() {}
|
func (*UInt32Value) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UInt32Value) ProtoReflect() protoreflect.Message {
|
func (x *UInt32Value) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_hub_proto_msgTypes[4]
|
mi := &file_hub_proto_msgTypes[6]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
@ -299,7 +417,7 @@ func (x *UInt32Value) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use UInt32Value.ProtoReflect.Descriptor instead.
|
// Deprecated: Use UInt32Value.ProtoReflect.Descriptor instead.
|
||||||
func (*UInt32Value) Descriptor() ([]byte, []int) {
|
func (*UInt32Value) Descriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{4}
|
return file_hub_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *UInt32Value) GetValue() uint32 {
|
func (x *UInt32Value) GetValue() uint32 {
|
||||||
|
@ -321,7 +439,7 @@ type RangeField struct {
|
||||||
func (x *RangeField) Reset() {
|
func (x *RangeField) Reset() {
|
||||||
*x = RangeField{}
|
*x = RangeField{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_hub_proto_msgTypes[5]
|
mi := &file_hub_proto_msgTypes[7]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
@ -334,7 +452,7 @@ func (x *RangeField) String() string {
|
||||||
func (*RangeField) ProtoMessage() {}
|
func (*RangeField) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RangeField) ProtoReflect() protoreflect.Message {
|
func (x *RangeField) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_hub_proto_msgTypes[5]
|
mi := &file_hub_proto_msgTypes[7]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
@ -347,7 +465,7 @@ func (x *RangeField) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use RangeField.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RangeField.ProtoReflect.Descriptor instead.
|
||||||
func (*RangeField) Descriptor() ([]byte, []int) {
|
func (*RangeField) Descriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{5}
|
return file_hub_proto_rawDescGZIP(), []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RangeField) GetOp() RangeField_Op {
|
func (x *RangeField) GetOp() RangeField_Op {
|
||||||
|
@ -429,7 +547,7 @@ type SearchRequest struct {
|
||||||
func (x *SearchRequest) Reset() {
|
func (x *SearchRequest) Reset() {
|
||||||
*x = SearchRequest{}
|
*x = SearchRequest{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_hub_proto_msgTypes[6]
|
mi := &file_hub_proto_msgTypes[8]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
@ -442,7 +560,7 @@ func (x *SearchRequest) String() string {
|
||||||
func (*SearchRequest) ProtoMessage() {}
|
func (*SearchRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SearchRequest) ProtoReflect() protoreflect.Message {
|
func (x *SearchRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_hub_proto_msgTypes[6]
|
mi := &file_hub_proto_msgTypes[8]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
@ -455,7 +573,7 @@ func (x *SearchRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*SearchRequest) Descriptor() ([]byte, []int) {
|
func (*SearchRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_hub_proto_rawDescGZIP(), []int{6}
|
return file_hub_proto_rawDescGZIP(), []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SearchRequest) GetClaimId() *InvertibleField {
|
func (x *SearchRequest) GetClaimId() *InvertibleField {
|
||||||
|
@ -848,186 +966,206 @@ var File_hub_proto protoreflect.FileDescriptor
|
||||||
var file_hub_proto_rawDesc = []byte{
|
var file_hub_proto_rawDesc = []byte{
|
||||||
0x0a, 0x09, 0x68, 0x75, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a,
|
0x0a, 0x09, 0x68, 0x75, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a,
|
||||||
0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0e, 0x0a,
|
0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0e, 0x0a,
|
||||||
0x0c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3f, 0x0a,
|
0x0c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3d, 0x0a,
|
||||||
0x0f, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x52, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74,
|
||||||
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x63, 0x0a, 0x0c,
|
||||||
0x0a, 0x0b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a,
|
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74,
|
||||||
0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65,
|
0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||||
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
|
0x68, 0x6f, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18,
|
||||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32,
|
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01,
|
0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x75, 0x0a, 0x0a, 0x52,
|
0x73, 0x22, 0x3f, 0x0a, 0x0f, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x46,
|
||||||
0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x21, 0x0a, 0x02, 0x6f, 0x70, 0x18,
|
0x69, 0x65, 0x6c, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x01,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05,
|
||||||
0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x4f, 0x70, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x14, 0x0a, 0x05,
|
|
||||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
|
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
|
||||||
0x75, 0x65, 0x22, 0x2e, 0x0a, 0x02, 0x4f, 0x70, 0x12, 0x06, 0x0a, 0x02, 0x45, 0x51, 0x10, 0x00,
|
0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75,
|
||||||
0x12, 0x07, 0x0a, 0x03, 0x4c, 0x54, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x54, 0x45,
|
0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x10, 0x02, 0x12, 0x06, 0x0a, 0x02, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x06, 0x0a, 0x02, 0x47, 0x54,
|
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x6c, 0x56,
|
||||||
0x10, 0x04, 0x22, 0xe0, 0x11, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71,
|
0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x69, 0x64,
|
0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x55, 0x49,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x76, 0x65,
|
0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
||||||
0x72, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x63, 0x6c, 0x61,
|
0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
|
||||||
0x69, 0x6d, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f,
|
0x75, 0x0a, 0x0a, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x21, 0x0a,
|
||||||
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e,
|
0x02, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x52,
|
||||||
0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x09, 0x63,
|
0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x4f, 0x70, 0x52, 0x02, 0x6f, 0x70,
|
||||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74,
|
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x14, 0x0a, 0x05,
|
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2e, 0x0a, 0x02, 0x4f, 0x70, 0x12, 0x06, 0x0a, 0x02,
|
||||||
0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d,
|
0x45, 0x51, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x54, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a,
|
||||||
0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x05,
|
0x03, 0x47, 0x54, 0x45, 0x10, 0x02, 0x12, 0x06, 0x0a, 0x02, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x06,
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x16, 0x0a,
|
0x0a, 0x02, 0x47, 0x54, 0x10, 0x04, 0x22, 0xe0, 0x11, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63,
|
||||||
0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6f,
|
0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x63, 0x6c, 0x61, 0x69,
|
||||||
0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74,
|
0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x62, 0x2e,
|
||||||
0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69,
|
0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52,
|
||||||
0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x31, 0x0a, 0x15,
|
0x07, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e,
|
||||||
0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x6b, 0x65, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x68,
|
0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70,
|
||||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6c, 0x61, 0x73,
|
0x62, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x65, 0x6c,
|
||||||
0x74, 0x54, 0x61, 0x6b, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12,
|
0x64, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
|
||||||
0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20,
|
0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27,
|
0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||||
0x0a, 0x0f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d,
|
0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f,
|
||||||
0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69,
|
0x62, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42,
|
||||||
0x7a, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x74, 0x78, 0x5f, 0x70, 0x6f,
|
0x79, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||||
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70,
|
0x0d, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x73, 0x5f,
|
||||||
0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0a, 0x74, 0x78,
|
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||||
0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75,
|
0x08, 0x52, 0x0d, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67,
|
||||||
0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61,
|
0x12, 0x31, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x6b, 0x65, 0x5f, 0x6f, 0x76,
|
||||||
0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
0x65, 0x72, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x12, 0x2c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0d, 0x20,
|
0x12, 0x6c, 0x61, 0x73, 0x74, 0x54, 0x61, 0x6b, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x48, 0x65, 0x69,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69,
|
0x67, 0x68, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6e, 0x61, 0x6d,
|
||||||
0x65, 0x6c, 0x64, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3d,
|
0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x4e, 0x61,
|
||||||
0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73,
|
0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64,
|
||||||
0x74, 0x61, 0x6d, 0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e,
|
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x6f, 0x72,
|
||||||
0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x11, 0x63, 0x72, 0x65, 0x61,
|
0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x74,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x26, 0x0a,
|
0x78, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
|
0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
||||||
0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x68,
|
0x52, 0x0a, 0x74, 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x06,
|
||||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x37, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f,
|
0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70,
|
||||||
0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
|
0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x61, 0x6d,
|
||||||
0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0e,
|
0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||||
0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x3b,
|
0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e,
|
||||||
0x0a, 0x11, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69,
|
0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
|
||||||
0x67, 0x68, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52,
|
0x6d, 0x70, 0x12, 0x3d, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74,
|
||||||
0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x10, 0x61, 0x63, 0x74, 0x69, 0x76,
|
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x3b, 0x0a, 0x11, 0x65,
|
0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x11,
|
||||||
0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
|
0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||||
0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67,
|
0x70, 0x12, 0x26, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28,
|
||||||
0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x10, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69,
|
0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c,
|
||||||
0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x31, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x65,
|
0x64, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x37, 0x0a, 0x0f, 0x63, 0x72, 0x65,
|
||||||
0x61, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x10, 0x20, 0x01,
|
||||||
0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0b,
|
|
||||||
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73,
|
|
||||||
0x68, 0x6f, 0x72, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
|
||||||
0x73, 0x68, 0x6f, 0x72, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x61, 0x6e, 0x6f,
|
|
||||||
0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52,
|
|
||||||
0x0c, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a,
|
|
||||||
0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69,
|
|
||||||
0x74, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x17, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64,
|
|
||||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09,
|
|
||||||
0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a,
|
|
||||||
0x0a, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x19, 0x20, 0x03, 0x28,
|
|
||||||
0x09, 0x52, 0x09, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, 0x0c,
|
|
||||||
0x72, 0x65, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01,
|
|
||||||
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65,
|
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65,
|
||||||
0x6c, 0x64, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
|
0x6c, 0x64, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67,
|
||||||
0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x1b,
|
0x68, 0x74, 0x12, 0x3b, 0x0a, 0x11, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65,
|
0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
|
||||||
0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x1c,
|
0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x10, 0x61,
|
||||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12,
|
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12,
|
||||||
0x2d, 0x0a, 0x0a, 0x66, 0x65, 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1d, 0x20,
|
0x3b, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69,
|
0x69, 0x67, 0x68, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e,
|
||||||
0x65, 0x6c, 0x64, 0x52, 0x09, 0x66, 0x65, 0x65, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21,
|
0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x10, 0x65, 0x78, 0x70, 0x69,
|
||||||
0x0a, 0x0c, 0x66, 0x65, 0x65, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x1e,
|
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x31, 0x0a, 0x0c,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x65, 0x65, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
|
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x13, 0x20, 0x01,
|
||||||
0x79, 0x12, 0x2a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1f, 0x20,
|
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69,
|
0x6c, 0x64, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
|
||||||
0x65, 0x6c, 0x64, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a,
|
0x1b, 0x0a, 0x09, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x14, 0x20, 0x01,
|
||||||
0x11, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f,
|
0x28, 0x09, 0x52, 0x08, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d,
|
||||||
0x69, 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x74,
|
0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x15, 0x20,
|
||||||
0x65, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x0b, 0x63, 0x65, 0x6e,
|
0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x72,
|
||||||
0x73, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
|
0x6c, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0a,
|
0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f,
|
||||||
0x63, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6c,
|
0x72, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12,
|
||||||
0x61, 0x69, 0x6d, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18,
|
0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x18,
|
||||||
0x22, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x49, 0x6e, 0x43,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||||
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
|
||||||
0x6c, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70,
|
0x19, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x79, 0x70, 0x65,
|
||||||
0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0b, 0x63, 0x68,
|
0x12, 0x31, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||||
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x3b, 0x0a, 0x12, 0x69, 0x73, 0x5f,
|
0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67,
|
||||||
0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18,
|
0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x74, 0x43, 0x6f,
|
||||||
0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56,
|
0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x74, 0x79,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x52, 0x10, 0x69, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
0x70, 0x65, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
||||||
0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x10, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74,
|
0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x5f, 0x74, 0x79,
|
||||||
0x69, 0x76, 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b,
|
0x70, 0x65, 0x18, 0x1c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x54,
|
||||||
|
0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x0a, 0x66, 0x65, 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e,
|
||||||
|
0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e,
|
||||||
|
0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x09, 0x66, 0x65, 0x65, 0x41, 0x6d, 0x6f, 0x75,
|
||||||
|
0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x65, 0x65, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
||||||
|
0x63, 0x79, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x65, 0x65, 0x43, 0x75, 0x72,
|
||||||
|
0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e,
|
||||||
|
0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c,
|
||||||
|
0x61, 0x69, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65,
|
||||||
|
0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x49, 0x64, 0x12, 0x2f, 0x0a,
|
||||||
|
0x0b, 0x63, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x21, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65,
|
||||||
|
0x6c, 0x64, 0x52, 0x0a, 0x63, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a,
|
||||||
|
0x0a, 0x11, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e,
|
||||||
|
0x6e, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x69, 0x6d,
|
||||||
|
0x73, 0x49, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x68,
|
||||||
|
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
||||||
0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x6d, 0x6f, 0x75, 0x6e,
|
0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x3b, 0x0a,
|
||||||
0x74, 0x12, 0x35, 0x0a, 0x0e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x61, 0x6d, 0x6f,
|
0x12, 0x69, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x61,
|
||||||
0x75, 0x6e, 0x74, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52,
|
0x6c, 0x69, 0x64, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x42,
|
||||||
0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0d, 0x73, 0x75, 0x70, 0x70, 0x6f,
|
0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x10, 0x69, 0x73, 0x53, 0x69, 0x67, 0x6e,
|
||||||
0x72, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e,
|
0x61, 0x74, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x10, 0x65, 0x66,
|
||||||
0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b,
|
0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x25,
|
||||||
0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46,
|
||||||
0x52, 0x0d, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12,
|
0x69, 0x65, 0x6c, 0x64, 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41,
|
||||||
0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x0e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
|
||||||
0x74, 0x78, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x6e, 0x6f, 0x75, 0x74, 0x18,
|
0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
|
||||||
0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33,
|
0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0d, 0x73,
|
||||||
0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x74, 0x78, 0x4e, 0x6f, 0x75, 0x74, 0x12, 0x1c,
|
0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x0e,
|
||||||
0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28,
|
0x74, 0x72, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x27,
|
||||||
0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x29, 0x0a, 0x10,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x46,
|
||||||
0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74,
|
0x69, 0x65, 0x6c, 0x64, 0x52, 0x0d, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x63,
|
||||||
0x18, 0x2e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
0x6f, 0x72, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x2b, 0x20, 0x01,
|
||||||
0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x6e,
|
||||||
0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x2f, 0x20, 0x01, 0x28,
|
0x6f, 0x75, 0x74, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x55,
|
||||||
0x09, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x79, 0x74, 0x65,
|
0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x74, 0x78, 0x4e, 0x6f,
|
||||||
0x73, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f,
|
0x75, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18,
|
||||||
0x69, 0x64, 0x18, 0x30, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||||
0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6e, 0x79, 0x5f, 0x74, 0x61, 0x67,
|
0x12, 0x29, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x64, 0x69,
|
||||||
0x73, 0x18, 0x31, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x6e, 0x79, 0x54, 0x61, 0x67, 0x73,
|
0x67, 0x65, 0x73, 0x74, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e,
|
||||||
0x12, 0x19, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x32, 0x20, 0x03,
|
0x61, 0x74, 0x75, 0x72, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x70,
|
||||||
0x28, 0x09, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x54, 0x61, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6e,
|
0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
|
||||||
0x6f, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x33, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e,
|
0x2f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79,
|
||||||
0x6f, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x68, 0x61, 0x73, 0x5f, 0x63, 0x68,
|
0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
|
||||||
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18,
|
0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x30, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x75,
|
||||||
0x34, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x68, 0x61, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6e, 0x79,
|
||||||
0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x0a, 0x68, 0x61,
|
0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x31, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x6e, 0x79,
|
||||||
0x73, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d,
|
0x54, 0x61, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73,
|
||||||
0x2e, 0x70, 0x62, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x68,
|
0x18, 0x32, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x54, 0x61, 0x67, 0x73, 0x12,
|
||||||
0x61, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x6c, 0x69, 0x6d, 0x69,
|
0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x33, 0x20, 0x03, 0x28,
|
||||||
0x74, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61,
|
0x09, 0x52, 0x07, 0x6e, 0x6f, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x68, 0x61,
|
||||||
0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x36, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x6c, 0x69, 0x6d, 0x69,
|
0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74,
|
||||||
0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x50, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
0x75, 0x72, 0x65, 0x18, 0x34, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x68, 0x61, 0x73, 0x43, 0x68,
|
||||||
0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6e, 0x79, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
|
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x2c,
|
||||||
0x65, 0x73, 0x18, 0x37, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e, 0x79, 0x4c, 0x61, 0x6e,
|
0x0a, 0x0a, 0x68, 0x61, 0x73, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x35, 0x20, 0x01,
|
||||||
0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x5f, 0x6c, 0x61,
|
0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75,
|
||||||
0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x18, 0x38, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x61,
|
0x65, 0x52, 0x09, 0x68, 0x61, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x18,
|
||||||
0x6c, 0x6c, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x72,
|
0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x70, 0x65, 0x72,
|
||||||
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73,
|
0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x36, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15,
|
||||||
0x18, 0x39, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x75,
|
0x6c, 0x69, 0x6d, 0x69, 0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x50, 0x65, 0x72, 0x43, 0x68,
|
||||||
0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x5f, 0x74,
|
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6e, 0x79, 0x5f, 0x6c, 0x61, 0x6e,
|
||||||
0x6f, 0x74, 0x61, 0x6c, 0x73, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x54,
|
0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x18, 0x37, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e,
|
||||||
0x6f, 0x74, 0x61, 0x6c, 0x73, 0x32, 0xf1, 0x01, 0x0a, 0x03, 0x48, 0x75, 0x62, 0x12, 0x2a, 0x0a,
|
0x79, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c,
|
||||||
0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x61,
|
0x6c, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x18, 0x38, 0x20, 0x03, 0x28,
|
||||||
0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x70, 0x62, 0x2e,
|
0x09, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x12,
|
||||||
0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x04, 0x50, 0x69, 0x6e,
|
0x2b, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63,
|
||||||
0x67, 0x12, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73,
|
0x61, 0x74, 0x65, 0x73, 0x18, 0x39, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x6d, 0x6f,
|
||||||
0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56,
|
0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
0x6e, 0x6f, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x6e, 0x12, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73,
|
0x08, 0x6e, 0x6f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x73, 0x32, 0x88, 0x03, 0x0a, 0x03, 0x48, 0x75,
|
||||||
0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56,
|
0x62, 0x12, 0x2a, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x11, 0x2e, 0x70, 0x62,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x08, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
|
0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b,
|
||||||
0x65, 0x73, 0x12, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73,
|
0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x00, 0x12, 0x2b, 0x0a,
|
||||||
0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
|
0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
|
||||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x30, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72,
|
||||||
0x63, 0x61, 0x73, 0x74, 0x12, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d,
|
0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x05, 0x48, 0x65,
|
||||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x49, 0x6e, 0x74,
|
0x6c, 0x6c, 0x6f, 0x12, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x4d, 0x65,
|
||||||
0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74,
|
0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
|
||||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x62, 0x72, 0x79, 0x69, 0x6f, 0x2f, 0x68,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x07, 0x41, 0x64, 0x64,
|
||||||
0x75, 0x62, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x6f, 0x2f, 0x70,
|
0x50, 0x65, 0x65, 0x72, 0x12, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||||
0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72,
|
||||||
|
0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0d, 0x50, 0x65,
|
||||||
|
0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x11, 0x2e, 0x70, 0x62,
|
||||||
|
0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f,
|
||||||
|
0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22,
|
||||||
|
0x00, 0x12, 0x2e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x2e, 0x70,
|
||||||
|
0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f,
|
||||||
|
0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22,
|
||||||
|
0x00, 0x12, 0x2f, 0x0a, 0x08, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x10, 0x2e,
|
||||||
|
0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a,
|
||||||
|
0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65,
|
||||||
|
0x22, 0x00, 0x12, 0x30, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12,
|
||||||
|
0x10, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||||
|
0x65, 0x1a, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c,
|
||||||
|
0x75, 0x65, 0x22, 0x00, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||||
|
0x6f, 0x6d, 0x2f, 0x6c, 0x62, 0x72, 0x79, 0x69, 0x6f, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -1043,57 +1181,66 @@ func file_hub_proto_rawDescGZIP() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_hub_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
var file_hub_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
var file_hub_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
var file_hub_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||||
var file_hub_proto_goTypes = []interface{}{
|
var file_hub_proto_goTypes = []interface{}{
|
||||||
(RangeField_Op)(0), // 0: pb.RangeField.Op
|
(RangeField_Op)(0), // 0: pb.RangeField.Op
|
||||||
(*EmptyMessage)(nil), // 1: pb.EmptyMessage
|
(*EmptyMessage)(nil), // 1: pb.EmptyMessage
|
||||||
(*InvertibleField)(nil), // 2: pb.InvertibleField
|
(*ServerMessage)(nil), // 2: pb.ServerMessage
|
||||||
(*StringValue)(nil), // 3: pb.StringValue
|
(*HelloMessage)(nil), // 3: pb.HelloMessage
|
||||||
(*BoolValue)(nil), // 4: pb.BoolValue
|
(*InvertibleField)(nil), // 4: pb.InvertibleField
|
||||||
(*UInt32Value)(nil), // 5: pb.UInt32Value
|
(*StringValue)(nil), // 5: pb.StringValue
|
||||||
(*RangeField)(nil), // 6: pb.RangeField
|
(*BoolValue)(nil), // 6: pb.BoolValue
|
||||||
(*SearchRequest)(nil), // 7: pb.SearchRequest
|
(*UInt32Value)(nil), // 7: pb.UInt32Value
|
||||||
(*Outputs)(nil), // 8: pb.Outputs
|
(*RangeField)(nil), // 8: pb.RangeField
|
||||||
|
(*SearchRequest)(nil), // 9: pb.SearchRequest
|
||||||
|
(*Outputs)(nil), // 10: pb.Outputs
|
||||||
}
|
}
|
||||||
var file_hub_proto_depIdxs = []int32{
|
var file_hub_proto_depIdxs = []int32{
|
||||||
0, // 0: pb.RangeField.op:type_name -> pb.RangeField.Op
|
2, // 0: pb.HelloMessage.servers:type_name -> pb.ServerMessage
|
||||||
2, // 1: pb.SearchRequest.claim_id:type_name -> pb.InvertibleField
|
0, // 1: pb.RangeField.op:type_name -> pb.RangeField.Op
|
||||||
2, // 2: pb.SearchRequest.channel_id:type_name -> pb.InvertibleField
|
4, // 2: pb.SearchRequest.claim_id:type_name -> pb.InvertibleField
|
||||||
6, // 3: pb.SearchRequest.tx_position:type_name -> pb.RangeField
|
4, // 3: pb.SearchRequest.channel_id:type_name -> pb.InvertibleField
|
||||||
6, // 4: pb.SearchRequest.amount:type_name -> pb.RangeField
|
8, // 4: pb.SearchRequest.tx_position:type_name -> pb.RangeField
|
||||||
6, // 5: pb.SearchRequest.timestamp:type_name -> pb.RangeField
|
8, // 5: pb.SearchRequest.amount:type_name -> pb.RangeField
|
||||||
6, // 6: pb.SearchRequest.creation_timestamp:type_name -> pb.RangeField
|
8, // 6: pb.SearchRequest.timestamp:type_name -> pb.RangeField
|
||||||
6, // 7: pb.SearchRequest.height:type_name -> pb.RangeField
|
8, // 7: pb.SearchRequest.creation_timestamp:type_name -> pb.RangeField
|
||||||
6, // 8: pb.SearchRequest.creation_height:type_name -> pb.RangeField
|
8, // 8: pb.SearchRequest.height:type_name -> pb.RangeField
|
||||||
6, // 9: pb.SearchRequest.activation_height:type_name -> pb.RangeField
|
8, // 9: pb.SearchRequest.creation_height:type_name -> pb.RangeField
|
||||||
6, // 10: pb.SearchRequest.expiration_height:type_name -> pb.RangeField
|
8, // 10: pb.SearchRequest.activation_height:type_name -> pb.RangeField
|
||||||
6, // 11: pb.SearchRequest.release_time:type_name -> pb.RangeField
|
8, // 11: pb.SearchRequest.expiration_height:type_name -> pb.RangeField
|
||||||
6, // 12: pb.SearchRequest.repost_count:type_name -> pb.RangeField
|
8, // 12: pb.SearchRequest.release_time:type_name -> pb.RangeField
|
||||||
6, // 13: pb.SearchRequest.fee_amount:type_name -> pb.RangeField
|
8, // 13: pb.SearchRequest.repost_count:type_name -> pb.RangeField
|
||||||
6, // 14: pb.SearchRequest.duration:type_name -> pb.RangeField
|
8, // 14: pb.SearchRequest.fee_amount:type_name -> pb.RangeField
|
||||||
6, // 15: pb.SearchRequest.censor_type:type_name -> pb.RangeField
|
8, // 15: pb.SearchRequest.duration:type_name -> pb.RangeField
|
||||||
6, // 16: pb.SearchRequest.channel_join:type_name -> pb.RangeField
|
8, // 16: pb.SearchRequest.censor_type:type_name -> pb.RangeField
|
||||||
4, // 17: pb.SearchRequest.is_signature_valid:type_name -> pb.BoolValue
|
8, // 17: pb.SearchRequest.channel_join:type_name -> pb.RangeField
|
||||||
6, // 18: pb.SearchRequest.effective_amount:type_name -> pb.RangeField
|
6, // 18: pb.SearchRequest.is_signature_valid:type_name -> pb.BoolValue
|
||||||
6, // 19: pb.SearchRequest.support_amount:type_name -> pb.RangeField
|
8, // 19: pb.SearchRequest.effective_amount:type_name -> pb.RangeField
|
||||||
6, // 20: pb.SearchRequest.trending_score:type_name -> pb.RangeField
|
8, // 20: pb.SearchRequest.support_amount:type_name -> pb.RangeField
|
||||||
5, // 21: pb.SearchRequest.tx_nout:type_name -> pb.UInt32Value
|
8, // 21: pb.SearchRequest.trending_score:type_name -> pb.RangeField
|
||||||
4, // 22: pb.SearchRequest.has_source:type_name -> pb.BoolValue
|
7, // 22: pb.SearchRequest.tx_nout:type_name -> pb.UInt32Value
|
||||||
7, // 23: pb.Hub.Search:input_type -> pb.SearchRequest
|
6, // 23: pb.SearchRequest.has_source:type_name -> pb.BoolValue
|
||||||
1, // 24: pb.Hub.Ping:input_type -> pb.EmptyMessage
|
9, // 24: pb.Hub.Search:input_type -> pb.SearchRequest
|
||||||
1, // 25: pb.Hub.Version:input_type -> pb.EmptyMessage
|
1, // 25: pb.Hub.Ping:input_type -> pb.EmptyMessage
|
||||||
1, // 26: pb.Hub.Features:input_type -> pb.EmptyMessage
|
3, // 26: pb.Hub.Hello:input_type -> pb.HelloMessage
|
||||||
1, // 27: pb.Hub.Broadcast:input_type -> pb.EmptyMessage
|
2, // 27: pb.Hub.AddPeer:input_type -> pb.ServerMessage
|
||||||
8, // 28: pb.Hub.Search:output_type -> pb.Outputs
|
2, // 28: pb.Hub.PeerSubscribe:input_type -> pb.ServerMessage
|
||||||
3, // 29: pb.Hub.Ping:output_type -> pb.StringValue
|
1, // 29: pb.Hub.Version:input_type -> pb.EmptyMessage
|
||||||
3, // 30: pb.Hub.Version:output_type -> pb.StringValue
|
1, // 30: pb.Hub.Features:input_type -> pb.EmptyMessage
|
||||||
3, // 31: pb.Hub.Features:output_type -> pb.StringValue
|
1, // 31: pb.Hub.Broadcast:input_type -> pb.EmptyMessage
|
||||||
5, // 32: pb.Hub.Broadcast:output_type -> pb.UInt32Value
|
10, // 32: pb.Hub.Search:output_type -> pb.Outputs
|
||||||
28, // [28:33] is the sub-list for method output_type
|
5, // 33: pb.Hub.Ping:output_type -> pb.StringValue
|
||||||
23, // [23:28] is the sub-list for method input_type
|
3, // 34: pb.Hub.Hello:output_type -> pb.HelloMessage
|
||||||
23, // [23:23] is the sub-list for extension type_name
|
5, // 35: pb.Hub.AddPeer:output_type -> pb.StringValue
|
||||||
23, // [23:23] is the sub-list for extension extendee
|
5, // 36: pb.Hub.PeerSubscribe:output_type -> pb.StringValue
|
||||||
0, // [0:23] is the sub-list for field type_name
|
5, // 37: pb.Hub.Version:output_type -> pb.StringValue
|
||||||
|
5, // 38: pb.Hub.Features:output_type -> pb.StringValue
|
||||||
|
7, // 39: pb.Hub.Broadcast:output_type -> pb.UInt32Value
|
||||||
|
32, // [32:40] is the sub-list for method output_type
|
||||||
|
24, // [24:32] is the sub-list for method input_type
|
||||||
|
24, // [24:24] is the sub-list for extension type_name
|
||||||
|
24, // [24:24] is the sub-list for extension extendee
|
||||||
|
0, // [0:24] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_hub_proto_init() }
|
func init() { file_hub_proto_init() }
|
||||||
|
@ -1116,7 +1263,7 @@ func file_hub_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_hub_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
file_hub_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*InvertibleField); i {
|
switch v := v.(*ServerMessage); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1128,7 +1275,7 @@ func file_hub_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_hub_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
file_hub_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*StringValue); i {
|
switch v := v.(*HelloMessage); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1140,7 +1287,7 @@ func file_hub_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_hub_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
file_hub_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*BoolValue); i {
|
switch v := v.(*InvertibleField); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1152,7 +1299,7 @@ func file_hub_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_hub_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
file_hub_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*UInt32Value); i {
|
switch v := v.(*StringValue); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1164,7 +1311,7 @@ func file_hub_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_hub_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
file_hub_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*RangeField); i {
|
switch v := v.(*BoolValue); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1176,6 +1323,30 @@ func file_hub_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_hub_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
file_hub_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*UInt32Value); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_hub_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*RangeField); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_hub_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*SearchRequest); i {
|
switch v := v.(*SearchRequest); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
|
@ -1194,7 +1365,7 @@ func file_hub_proto_init() {
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_hub_proto_rawDesc,
|
RawDescriptor: file_hub_proto_rawDesc,
|
||||||
NumEnums: 1,
|
NumEnums: 1,
|
||||||
NumMessages: 7,
|
NumMessages: 9,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,6 +20,9 @@ const _ = grpc.SupportPackageIsVersion7
|
||||||
type HubClient interface {
|
type HubClient interface {
|
||||||
Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*Outputs, error)
|
Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*Outputs, error)
|
||||||
Ping(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error)
|
Ping(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error)
|
||||||
|
Hello(ctx context.Context, in *HelloMessage, opts ...grpc.CallOption) (*HelloMessage, error)
|
||||||
|
AddPeer(ctx context.Context, in *ServerMessage, opts ...grpc.CallOption) (*StringValue, error)
|
||||||
|
PeerSubscribe(ctx context.Context, in *ServerMessage, opts ...grpc.CallOption) (*StringValue, error)
|
||||||
Version(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error)
|
Version(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error)
|
||||||
Features(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error)
|
Features(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error)
|
||||||
Broadcast(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*UInt32Value, error)
|
Broadcast(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*UInt32Value, error)
|
||||||
|
@ -51,6 +54,33 @@ func (c *hubClient) Ping(ctx context.Context, in *EmptyMessage, opts ...grpc.Cal
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *hubClient) Hello(ctx context.Context, in *HelloMessage, opts ...grpc.CallOption) (*HelloMessage, error) {
|
||||||
|
out := new(HelloMessage)
|
||||||
|
err := c.cc.Invoke(ctx, "/pb.Hub/Hello", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *hubClient) AddPeer(ctx context.Context, in *ServerMessage, opts ...grpc.CallOption) (*StringValue, error) {
|
||||||
|
out := new(StringValue)
|
||||||
|
err := c.cc.Invoke(ctx, "/pb.Hub/AddPeer", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *hubClient) PeerSubscribe(ctx context.Context, in *ServerMessage, opts ...grpc.CallOption) (*StringValue, error) {
|
||||||
|
out := new(StringValue)
|
||||||
|
err := c.cc.Invoke(ctx, "/pb.Hub/PeerSubscribe", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *hubClient) Version(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error) {
|
func (c *hubClient) Version(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*StringValue, error) {
|
||||||
out := new(StringValue)
|
out := new(StringValue)
|
||||||
err := c.cc.Invoke(ctx, "/pb.Hub/Version", in, out, opts...)
|
err := c.cc.Invoke(ctx, "/pb.Hub/Version", in, out, opts...)
|
||||||
|
@ -84,6 +114,9 @@ func (c *hubClient) Broadcast(ctx context.Context, in *EmptyMessage, opts ...grp
|
||||||
type HubServer interface {
|
type HubServer interface {
|
||||||
Search(context.Context, *SearchRequest) (*Outputs, error)
|
Search(context.Context, *SearchRequest) (*Outputs, error)
|
||||||
Ping(context.Context, *EmptyMessage) (*StringValue, error)
|
Ping(context.Context, *EmptyMessage) (*StringValue, error)
|
||||||
|
Hello(context.Context, *HelloMessage) (*HelloMessage, error)
|
||||||
|
AddPeer(context.Context, *ServerMessage) (*StringValue, error)
|
||||||
|
PeerSubscribe(context.Context, *ServerMessage) (*StringValue, error)
|
||||||
Version(context.Context, *EmptyMessage) (*StringValue, error)
|
Version(context.Context, *EmptyMessage) (*StringValue, error)
|
||||||
Features(context.Context, *EmptyMessage) (*StringValue, error)
|
Features(context.Context, *EmptyMessage) (*StringValue, error)
|
||||||
Broadcast(context.Context, *EmptyMessage) (*UInt32Value, error)
|
Broadcast(context.Context, *EmptyMessage) (*UInt32Value, error)
|
||||||
|
@ -100,6 +133,15 @@ func (UnimplementedHubServer) Search(context.Context, *SearchRequest) (*Outputs,
|
||||||
func (UnimplementedHubServer) Ping(context.Context, *EmptyMessage) (*StringValue, error) {
|
func (UnimplementedHubServer) Ping(context.Context, *EmptyMessage) (*StringValue, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedHubServer) Hello(context.Context, *HelloMessage) (*HelloMessage, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Hello not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedHubServer) AddPeer(context.Context, *ServerMessage) (*StringValue, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method AddPeer not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedHubServer) PeerSubscribe(context.Context, *ServerMessage) (*StringValue, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method PeerSubscribe not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedHubServer) Version(context.Context, *EmptyMessage) (*StringValue, error) {
|
func (UnimplementedHubServer) Version(context.Context, *EmptyMessage) (*StringValue, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Version not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Version not implemented")
|
||||||
}
|
}
|
||||||
|
@ -158,6 +200,60 @@ func _Hub_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _Hub_Hello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(HelloMessage)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HubServer).Hello(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/pb.Hub/Hello",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HubServer).Hello(ctx, req.(*HelloMessage))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Hub_AddPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ServerMessage)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HubServer).AddPeer(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/pb.Hub/AddPeer",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HubServer).AddPeer(ctx, req.(*ServerMessage))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Hub_PeerSubscribe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ServerMessage)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HubServer).PeerSubscribe(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/pb.Hub/PeerSubscribe",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HubServer).PeerSubscribe(ctx, req.(*ServerMessage))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func _Hub_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _Hub_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(EmptyMessage)
|
in := new(EmptyMessage)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
|
@ -227,6 +323,18 @@ var Hub_ServiceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "Ping",
|
MethodName: "Ping",
|
||||||
Handler: _Hub_Ping_Handler,
|
Handler: _Hub_Ping_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Hello",
|
||||||
|
Handler: _Hub_Hello_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "AddPeer",
|
||||||
|
Handler: _Hub_AddPeer_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "PeerSubscribe",
|
||||||
|
Handler: _Hub_PeerSubscribe_Handler,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
MethodName: "Version",
|
MethodName: "Version",
|
||||||
Handler: _Hub_Version_Handler,
|
Handler: _Hub_Version_Handler,
|
||||||
|
|
|
@ -24,7 +24,11 @@ AREA_RENAME = {
|
||||||
|
|
||||||
def build_upload_binary(release: github3.repos.release.Release) -> None:
|
def build_upload_binary(release: github3.repos.release.Release) -> None:
|
||||||
# os.chdir(absolute_path)
|
# os.chdir(absolute_path)
|
||||||
os.system("go build .")
|
# os.system("go build .")
|
||||||
|
cmd = f'CGO_ENABLED=0 go build -v -ldflags "-X github.com/lbryio/hub/meta.Version={release.name}"'
|
||||||
|
print(cmd)
|
||||||
|
# os.system("go build .")
|
||||||
|
os.system(cmd)
|
||||||
with open("./hub", "rb") as f:
|
with open("./hub", "rb") as f:
|
||||||
release.upload_asset("binary", "hub", f)
|
release.upload_asset("binary", "hub", f)
|
||||||
|
|
||||||
|
@ -225,9 +229,11 @@ def release(args):
|
||||||
print(body.getvalue())
|
print(body.getvalue())
|
||||||
|
|
||||||
if unlabeled:
|
if unlabeled:
|
||||||
print('The following PRs were skipped and not included in changelog:')
|
w('')
|
||||||
for skipped in unlabeled:
|
print('The following PRs were unlabeled and *will* be included in changelog:')
|
||||||
print(skipped)
|
for notskipped in unlabeled:
|
||||||
|
print(notskipped)
|
||||||
|
w(notskipped)
|
||||||
|
|
||||||
if fixups:
|
if fixups:
|
||||||
print('The following PRs were marked as fixups and not included in changelog:')
|
print('The following PRs were marked as fixups and not included in changelog:')
|
||||||
|
|
201
server/args.go
Normal file
201
server/args.go
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/akamensky/argparse"
|
||||||
|
pb "github.com/lbryio/hub/protobuf/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ServeCmd = iota
|
||||||
|
SearchCmd = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// Args struct contains the arguments to the hub server.
|
||||||
|
type Args struct {
|
||||||
|
CmdType int
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
UDPPort string
|
||||||
|
EsHost string
|
||||||
|
EsPort string
|
||||||
|
PrometheusPort string
|
||||||
|
EsIndex string
|
||||||
|
RefreshDelta int
|
||||||
|
CacheTTL int
|
||||||
|
PeerFile string
|
||||||
|
Country string
|
||||||
|
DisableEs bool
|
||||||
|
Debug bool
|
||||||
|
LoadPeers bool
|
||||||
|
StartPrometheus bool
|
||||||
|
StartUDP bool
|
||||||
|
WritePeers bool
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultHost = "0.0.0.0"
|
||||||
|
DefaultPort = "50051"
|
||||||
|
DefaultUdpPort = "41119"
|
||||||
|
DefaultEsHost = "http://localhost"
|
||||||
|
DefaultEsIndex = "claims"
|
||||||
|
DefaultEsPort = "9200"
|
||||||
|
DefaultPrometheusPort = "2112"
|
||||||
|
DefaultRefreshDelta = 5
|
||||||
|
DefaultCacheTTL = 5
|
||||||
|
DefaultPeerFile = "peers.txt"
|
||||||
|
DefaultCountry = "US"
|
||||||
|
DefaultLoadPeers = true
|
||||||
|
DefaultStartPrometheus = true
|
||||||
|
DefaultStartUDP = true
|
||||||
|
DefaultWritePeers = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetEnvironment takes the environment variables as an array of strings
|
||||||
|
// and a getkeyval function to turn it into a map.
|
||||||
|
func GetEnvironment(data []string, getkeyval func(item string) (key, val string)) map[string]string {
|
||||||
|
items := make(map[string]string)
|
||||||
|
for _, item := range data {
|
||||||
|
key, val := getkeyval(item)
|
||||||
|
items[key] = val
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnvironmentStandard gets the environment variables as a map.
|
||||||
|
func GetEnvironmentStandard() map[string]string {
|
||||||
|
return GetEnvironment(os.Environ(), func(item string) (key, val string) {
|
||||||
|
splits := strings.Split(item, "=")
|
||||||
|
key = splits[0]
|
||||||
|
val = splits[1]
|
||||||
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseArgs parses the command line arguments when started the hub server.
|
||||||
|
func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
||||||
|
|
||||||
|
environment := GetEnvironmentStandard()
|
||||||
|
parser := argparse.NewParser("hub", "hub server and client")
|
||||||
|
|
||||||
|
serveCmd := parser.NewCommand("serve", "start the hub server")
|
||||||
|
searchCmd := parser.NewCommand("search", "claim search")
|
||||||
|
|
||||||
|
host := parser.String("", "rpchost", &argparse.Options{Required: false, Help: "RPC host", Default: DefaultHost})
|
||||||
|
port := parser.String("", "rpcport", &argparse.Options{Required: false, Help: "RPC port", Default: DefaultPort})
|
||||||
|
esHost := parser.String("", "eshost", &argparse.Options{Required: false, Help: "elasticsearch host", Default: DefaultEsHost})
|
||||||
|
esPort := parser.String("", "esport", &argparse.Options{Required: false, Help: "elasticsearch port", Default: DefaultEsPort})
|
||||||
|
udpPort := parser.String("", "uspport", &argparse.Options{Required: false, Help: "udp ping port", Default: DefaultUdpPort})
|
||||||
|
prometheusPort := parser.String("", "prometheus-port", &argparse.Options{Required: false, Help: "prometheus port", Default: DefaultPrometheusPort})
|
||||||
|
esIndex := parser.String("", "esindex", &argparse.Options{Required: false, Help: "elasticsearch index name", Default: DefaultEsIndex})
|
||||||
|
refreshDelta := parser.Int("", "refresh-delta", &argparse.Options{Required: false, Help: "elasticsearch index refresh delta in seconds", Default: DefaultRefreshDelta})
|
||||||
|
cacheTTL := parser.Int("", "cachettl", &argparse.Options{Required: false, Help: "Cache TTL in minutes", Default: DefaultCacheTTL})
|
||||||
|
peerFile := parser.String("", "peerfile", &argparse.Options{Required: false, Help: "Initial peer file for federation", Default: DefaultPeerFile})
|
||||||
|
country := parser.String("", "country", &argparse.Options{Required: false, Help: "Country this node is running in. Default US.", Default: DefaultCountry})
|
||||||
|
|
||||||
|
debug := parser.Flag("", "debug", &argparse.Options{Required: false, Help: "enable debug logging", Default: false})
|
||||||
|
disableEs := parser.Flag("", "disable-es", &argparse.Options{Required: false, Help: "Disable elastic search, for running/testing independently", Default: false})
|
||||||
|
loadPeers := parser.Flag("", "load-peers", &argparse.Options{Required: false, Help: "load peers from disk at startup", Default: DefaultLoadPeers})
|
||||||
|
startPrometheus := parser.Flag("", "start-prometheus", &argparse.Options{Required: false, Help: "Start prometheus server", Default: DefaultStartPrometheus})
|
||||||
|
startUdp := parser.Flag("", "start-udp", &argparse.Options{Required: false, Help: "Start UDP ping server", Default: DefaultStartUDP})
|
||||||
|
writePeers := parser.Flag("", "write-peers", &argparse.Options{Required: false, Help: "Write peer to disk as we learn about them", Default: DefaultWritePeers})
|
||||||
|
|
||||||
|
text := parser.String("", "text", &argparse.Options{Required: false, Help: "text query"})
|
||||||
|
name := parser.String("", "name", &argparse.Options{Required: false, Help: "name"})
|
||||||
|
claimType := parser.String("", "claim_type", &argparse.Options{Required: false, Help: "claim_type"})
|
||||||
|
id := parser.String("", "id", &argparse.Options{Required: false, Help: "id"})
|
||||||
|
author := parser.String("", "author", &argparse.Options{Required: false, Help: "author"})
|
||||||
|
title := parser.String("", "title", &argparse.Options{Required: false, Help: "title"})
|
||||||
|
description := parser.String("", "description", &argparse.Options{Required: false, Help: "description"})
|
||||||
|
channelId := parser.String("", "channel_id", &argparse.Options{Required: false, Help: "channel id"})
|
||||||
|
channelIds := parser.StringList("", "channel_ids", &argparse.Options{Required: false, Help: "channel ids"})
|
||||||
|
|
||||||
|
// Now parse the arguments
|
||||||
|
err := parser.Parse(os.Args)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(parser.Usage(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
args := &Args{
|
||||||
|
CmdType: SearchCmd,
|
||||||
|
Host: *host,
|
||||||
|
Port: *port,
|
||||||
|
EsHost: *esHost,
|
||||||
|
EsPort: *esPort,
|
||||||
|
UDPPort: *udpPort,
|
||||||
|
PrometheusPort: *prometheusPort,
|
||||||
|
EsIndex: *esIndex,
|
||||||
|
RefreshDelta: *refreshDelta,
|
||||||
|
CacheTTL: *cacheTTL,
|
||||||
|
PeerFile: *peerFile,
|
||||||
|
Country: *country,
|
||||||
|
DisableEs: *disableEs,
|
||||||
|
Debug: *debug,
|
||||||
|
LoadPeers: *loadPeers,
|
||||||
|
StartPrometheus: *startPrometheus,
|
||||||
|
StartUDP: *startUdp,
|
||||||
|
WritePeers: *writePeers,
|
||||||
|
}
|
||||||
|
|
||||||
|
if esHost, ok := environment["ELASTIC_HOST"]; ok {
|
||||||
|
args.EsHost = esHost
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(args.EsHost, "http") {
|
||||||
|
args.EsHost = "http://" + args.EsHost
|
||||||
|
}
|
||||||
|
|
||||||
|
if esPort, ok := environment["ELASTIC_PORT"]; ok {
|
||||||
|
args.EsPort = esPort
|
||||||
|
}
|
||||||
|
|
||||||
|
if prometheusPort, ok := environment["GOHUB_PROMETHEUS_PORT"]; ok {
|
||||||
|
args.PrometheusPort = prometheusPort
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Verify no invalid argument combinations
|
||||||
|
*/
|
||||||
|
if len(*channelIds) > 0 && *channelId != "" {
|
||||||
|
log.Fatal("Cannot specify both channel_id and channel_ids")
|
||||||
|
}
|
||||||
|
|
||||||
|
if serveCmd.Happened() {
|
||||||
|
args.CmdType = ServeCmd
|
||||||
|
} else if searchCmd.Happened() {
|
||||||
|
args.CmdType = SearchCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
if *text != "" {
|
||||||
|
searchRequest.Text = *text
|
||||||
|
}
|
||||||
|
if *name != "" {
|
||||||
|
searchRequest.ClaimName = *name
|
||||||
|
}
|
||||||
|
if *claimType != "" {
|
||||||
|
searchRequest.ClaimType = []string{*claimType}
|
||||||
|
}
|
||||||
|
if *id != "" {
|
||||||
|
searchRequest.ClaimId = &pb.InvertibleField{Invert: false, Value: []string{*id}}
|
||||||
|
}
|
||||||
|
if *author != "" {
|
||||||
|
searchRequest.Author = *author
|
||||||
|
}
|
||||||
|
if *title != "" {
|
||||||
|
searchRequest.Title = *title
|
||||||
|
}
|
||||||
|
if *description != "" {
|
||||||
|
searchRequest.Description = *description
|
||||||
|
}
|
||||||
|
if *channelId != "" {
|
||||||
|
searchRequest.ChannelId = &pb.InvertibleField{Invert: false, Value: []string{*channelId}}
|
||||||
|
}
|
||||||
|
if len(*channelIds) > 0 {
|
||||||
|
searchRequest.ChannelId = &pb.InvertibleField{Invert: false, Value: *channelIds}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
358
server/federation.go
Normal file
358
server/federation.go
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lbryio/hub/internal/metrics"
|
||||||
|
pb "github.com/lbryio/hub/protobuf/go"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FederatedServer hold relevant information about peers that we known about.
|
||||||
|
type FederatedServer struct {
|
||||||
|
Address string
|
||||||
|
Port string
|
||||||
|
Ts time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
localHosts = map[string]bool{
|
||||||
|
"127.0.0.1": true,
|
||||||
|
"0.0.0.0": true,
|
||||||
|
"localhost": true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// peerKey takes a ServerMessage object and returns the key that for that peer
|
||||||
|
// in our peer table.
|
||||||
|
func peerKey(msg *pb.ServerMessage) string {
|
||||||
|
return msg.Address + ":" + msg.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
// peerKey is a function on a FederatedServer struct to return the key for that
|
||||||
|
// peer is out peer table.
|
||||||
|
func (peer *FederatedServer) peerKey() string {
|
||||||
|
return peer.Address + ":" + peer.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) incNumPeers() {
|
||||||
|
atomic.AddInt64(s.NumPeerServers, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) decNumPeers() {
|
||||||
|
atomic.AddInt64(s.NumPeerServers, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) getNumPeers() int64 {
|
||||||
|
return *s.NumPeerServers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) incNumSubs() {
|
||||||
|
atomic.AddInt64(s.NumPeerSubs, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) decNumSubs() {
|
||||||
|
atomic.AddInt64(s.NumPeerSubs, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) getNumSubs() int64 {
|
||||||
|
return *s.NumPeerSubs
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadPeers takes the arguments given to the hub at startup and loads the
|
||||||
|
// previously known peers from disk and verifies their existence before
|
||||||
|
// storing them as known peers. Returns a map of peerKey -> object
|
||||||
|
func (s *Server) loadPeers() error {
|
||||||
|
peerFile := s.Args.PeerFile
|
||||||
|
port := s.Args.Port
|
||||||
|
|
||||||
|
f, err := os.Open(peerFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
scanner.Split(bufio.ScanLines)
|
||||||
|
var text []string
|
||||||
|
for scanner.Scan() {
|
||||||
|
text = append(text, scanner.Text())
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("peer file failed to close: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range text {
|
||||||
|
ipPort := strings.Split(line,":")
|
||||||
|
if len(ipPort) != 2 {
|
||||||
|
log.Println("Malformed entry in peer file")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If the peer is us, skip
|
||||||
|
log.Println(ipPort)
|
||||||
|
if ipPort[1] == port && localHosts[ipPort[0]] {
|
||||||
|
log.Println("Self peer, skipping ...")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
srvMsg := &pb.ServerMessage{
|
||||||
|
Address: ipPort[0],
|
||||||
|
Port: ipPort[1],
|
||||||
|
}
|
||||||
|
log.Printf("pinging peer %+v\n", srvMsg)
|
||||||
|
err := s.addPeer(srvMsg, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Returning from loadPeers")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// subscribeToPeer subscribes us to a peer to we'll get updates about their
|
||||||
|
// known peers.
|
||||||
|
func (s *Server) subscribeToPeer(peer *FederatedServer) error {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
conn, err := grpc.DialContext(ctx,
|
||||||
|
peer.Address+":"+peer.Port,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
msg := &pb.ServerMessage{
|
||||||
|
Address: s.Args.Host,
|
||||||
|
Port: s.Args.Port,
|
||||||
|
}
|
||||||
|
|
||||||
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
|
log.Printf("%s:%s subscribing to %+v\n", s.Args.Host, s.Args.Port, peer)
|
||||||
|
_, err = c.PeerSubscribe(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Subscribed = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// helloPeer takes a peer to say hello to and sends a hello message
|
||||||
|
// containing all the peers we know about and information about us.
|
||||||
|
// This is used to confirm existence of peers on start and let them
|
||||||
|
// know about us. Returns the response from the server on success,
|
||||||
|
// nil otherwise.
|
||||||
|
func (s *Server) helloPeer(server *FederatedServer) (*pb.HelloMessage, error) {
|
||||||
|
log.Println("In helloPeer")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
conn, err := grpc.DialContext(ctx,
|
||||||
|
server.Address+":"+server.Port,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
|
msg := &pb.HelloMessage{
|
||||||
|
Port: s.Args.Port,
|
||||||
|
Host: s.Args.Host,
|
||||||
|
Servers: []*pb.ServerMessage{},
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("%s:%s saying hello to %+v\n", s.Args.Host, s.Args.Port, server)
|
||||||
|
res, err := c.Hello(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(res)
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writePeers writes our current known peers to disk.
|
||||||
|
func (s *Server) writePeers() {
|
||||||
|
if !s.Args.WritePeers {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f, err := os.Create(s.Args.PeerFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writer := bufio.NewWriter(f)
|
||||||
|
|
||||||
|
for key, _ := range s.PeerServers {
|
||||||
|
line := key + "\n"
|
||||||
|
_, err := writer.WriteString(line)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writer.Flush()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// notifyPeer takes a peer to notify and a new peer we just learned about
|
||||||
|
// and calls AddPeer on the first.
|
||||||
|
func notifyPeer(peerToNotify *FederatedServer, newPeer *FederatedServer) error {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
conn, err := grpc.DialContext(ctx,
|
||||||
|
peerToNotify.Address+":"+peerToNotify.Port,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
msg := &pb.ServerMessage{
|
||||||
|
Address: newPeer.Address,
|
||||||
|
Port: newPeer.Port,
|
||||||
|
}
|
||||||
|
|
||||||
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
|
_, err = c.AddPeer(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// notifyPeerSubs takes a new peer server we just learned about and notifies
|
||||||
|
// all the peers that have subscribed to us about it.
|
||||||
|
func (s *Server) notifyPeerSubs(newServer *FederatedServer) {
|
||||||
|
var unsubscribe []string
|
||||||
|
s.PeerSubsMut.RLock()
|
||||||
|
for key, peer := range s.PeerSubs {
|
||||||
|
log.Printf("Notifying peer %s of new node %+v\n", key, newServer)
|
||||||
|
err := notifyPeer(peer, newServer)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Failed to send data to ", key)
|
||||||
|
log.Println(err)
|
||||||
|
unsubscribe = append(unsubscribe, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.PeerSubsMut.RUnlock()
|
||||||
|
|
||||||
|
s.PeerSubsMut.Lock()
|
||||||
|
for _, key := range unsubscribe {
|
||||||
|
if _, ok := s.PeerSubs[key]; ok {
|
||||||
|
delete(s.PeerSubs, key)
|
||||||
|
s.decNumSubs()
|
||||||
|
metrics.PeersSubscribed.Dec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.PeerSubsMut.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// addPeer takes a new peer as a pb.ServerMessage, optionally checks to see
|
||||||
|
// if they're online, and adds them to our list of peer. If we're not currently
|
||||||
|
// subscribed to a peer, it will also subscribe to it.
|
||||||
|
func (s *Server) addPeer(msg *pb.ServerMessage, ping bool) error {
|
||||||
|
if s.Args.Port == msg.Port &&
|
||||||
|
(localHosts[msg.Address] || msg.Address == s.Args.Host) {
|
||||||
|
log.Printf("%s:%s addPeer: Self peer, skipping...\n", s.Args.Host, s.Args.Port)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
k := peerKey(msg)
|
||||||
|
newServer := &FederatedServer{
|
||||||
|
Address: msg.Address,
|
||||||
|
Port: msg.Port,
|
||||||
|
Ts: time.Now(),
|
||||||
|
}
|
||||||
|
log.Printf("%s:%s adding peer %+v\n", s.Args.Host, s.Args.Port, msg)
|
||||||
|
if oldServer, loaded := s.PeerServersLoadOrStore(newServer); !loaded {
|
||||||
|
if ping {
|
||||||
|
_, err := s.helloPeer(newServer)
|
||||||
|
if err != nil {
|
||||||
|
s.PeerServersMut.Lock()
|
||||||
|
delete(s.PeerServers, k)
|
||||||
|
s.PeerServersMut.Unlock()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.incNumPeers()
|
||||||
|
metrics.PeersKnown.Inc()
|
||||||
|
s.writePeers()
|
||||||
|
s.notifyPeerSubs(newServer)
|
||||||
|
|
||||||
|
// Subscribe to all our peers for now
|
||||||
|
err := s.subscribeToPeer(newServer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
s.Subscribed = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oldServer.Ts = time.Now()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeFederatedServers is an internal convenience function to add a list of
|
||||||
|
// peers.
|
||||||
|
func (s *Server) mergeFederatedServers(servers []*pb.ServerMessage) {
|
||||||
|
for _, srvMsg := range servers {
|
||||||
|
err := s.addPeer(srvMsg, false)
|
||||||
|
// This shouldn't happen because we're not pinging them.
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeHelloMessage makes a message for this hub to call the Hello endpoint
|
||||||
|
// on another hub.
|
||||||
|
func (s *Server) makeHelloMessage() *pb.HelloMessage {
|
||||||
|
servers := make([]*pb.ServerMessage, 0, 10)
|
||||||
|
|
||||||
|
s.PeerServersMut.RLock()
|
||||||
|
for _, peer := range s.PeerServers {
|
||||||
|
servers = append(servers, &pb.ServerMessage{
|
||||||
|
Address: peer.Address,
|
||||||
|
Port: peer.Port,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
s.PeerServersMut.RUnlock()
|
||||||
|
|
||||||
|
return &pb.HelloMessage{
|
||||||
|
Port: s.Args.Port,
|
||||||
|
Host: s.Args.Host,
|
||||||
|
Servers: servers,
|
||||||
|
}
|
||||||
|
}
|
427
server/federation_test.go
Normal file
427
server/federation_test.go
Normal file
|
@ -0,0 +1,427 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lbryio/hub/internal/metrics"
|
||||||
|
pb "github.com/lbryio/hub/protobuf/go"
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// lineCountFile takes a fileName and counts the number of lines in it.
|
||||||
|
func lineCountFile(fileName string) int {
|
||||||
|
f, err := os.Open(fileName)
|
||||||
|
defer f.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
scanner.Split(bufio.ScanLines)
|
||||||
|
var lineCount = 0
|
||||||
|
for scanner.Scan() {
|
||||||
|
scanner.Text()
|
||||||
|
lineCount = lineCount + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return lineCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeFile removes a file.
|
||||||
|
func removeFile(fileName string) {
|
||||||
|
err := os.Remove(fileName)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeDefaultArgs() *Args {
|
||||||
|
args := &Args{
|
||||||
|
CmdType: ServeCmd,
|
||||||
|
Host: DefaultHost,
|
||||||
|
Port: DefaultPort,
|
||||||
|
EsHost: DefaultEsHost,
|
||||||
|
EsPort: DefaultEsPort,
|
||||||
|
UDPPort: DefaultUdpPort,
|
||||||
|
PrometheusPort: DefaultPrometheusPort,
|
||||||
|
EsIndex: DefaultEsIndex,
|
||||||
|
RefreshDelta: DefaultRefreshDelta,
|
||||||
|
CacheTTL: DefaultCacheTTL,
|
||||||
|
PeerFile: DefaultPeerFile,
|
||||||
|
Country: DefaultCountry,
|
||||||
|
DisableEs: true,
|
||||||
|
Debug: true,
|
||||||
|
LoadPeers: false,
|
||||||
|
StartPrometheus: false,
|
||||||
|
StartUDP: false,
|
||||||
|
WritePeers: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAddPeer tests the ability to add peers
|
||||||
|
func TestAddPeer(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
args := makeDefaultArgs()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
want int
|
||||||
|
} {
|
||||||
|
{
|
||||||
|
name: "Add 10 peers",
|
||||||
|
want: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Add 10 peers, 1 unique",
|
||||||
|
want: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T){
|
||||||
|
server := MakeHubServer(ctx, args)
|
||||||
|
server.Subscribed = true
|
||||||
|
metrics.PeersKnown.Set(0)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
var msg *pb.ServerMessage
|
||||||
|
if strings.Contains(tt.name, "1 unique") {
|
||||||
|
msg = &pb.ServerMessage{
|
||||||
|
Address: "1.1.1.1",
|
||||||
|
Port: "50051",
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x := i + 1
|
||||||
|
msg = &pb.ServerMessage{
|
||||||
|
Address: fmt.Sprintf("%d.%d.%d.%d", x, x, x, x),
|
||||||
|
Port: "50051",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log.Printf("Adding peer %+v\n", msg)
|
||||||
|
err := server.addPeer(msg, false)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var m = &dto.Metric{}
|
||||||
|
if err := metrics.PeersKnown.Write(m); err != nil {
|
||||||
|
t.Errorf("Error getting metrics %+v\n", err)
|
||||||
|
}
|
||||||
|
got := int(*m.Gauge.Value)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("len(server.PeerServers) = %d, want %d\n", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPeerWriter tests that peers get written properly
|
||||||
|
func TestPeerWriter(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
args := makeDefaultArgs()
|
||||||
|
args.WritePeers = true
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
want int
|
||||||
|
} {
|
||||||
|
{
|
||||||
|
name: "Add 10 peers",
|
||||||
|
want: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Add 10 peers, 1 unique",
|
||||||
|
want: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T){
|
||||||
|
server := MakeHubServer(ctx, args)
|
||||||
|
server.Subscribed = true
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
var msg *pb.ServerMessage
|
||||||
|
if strings.Contains(tt.name, "1 unique") {
|
||||||
|
msg = &pb.ServerMessage{
|
||||||
|
Address: "1.1.1.1",
|
||||||
|
Port: "50051",
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x := i + 1
|
||||||
|
msg = &pb.ServerMessage{
|
||||||
|
Address: fmt.Sprintf("%d.%d.%d.%d", x, x, x, x),
|
||||||
|
Port: "50051",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log.Printf("Adding peer %+v\n", msg)
|
||||||
|
err := server.addPeer(msg, false)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log.Println("Counting lines...")
|
||||||
|
got := lineCountFile(server.Args.PeerFile)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("lineCountFile(peers.txt) = %d, want %d", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFile(args.PeerFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAddPeerEndpoint tests the ability to add peers
|
||||||
|
func TestAddPeerEndpoint(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
args := makeDefaultArgs()
|
||||||
|
args2 := makeDefaultArgs()
|
||||||
|
args2.Port = "50052"
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
wantServerOne int64
|
||||||
|
wantServerTwo int64
|
||||||
|
} {
|
||||||
|
{
|
||||||
|
// outside -> server1.AddPeer(server2, ping=true) : server1 = 1, server2 = 0
|
||||||
|
// server1 -> server2.Hello(server1) : server1 = 1, server2 = 0
|
||||||
|
// server2 -> server2.addPeer(server1, ping=false) : server1 = 1, server2 = 1
|
||||||
|
// server2 -> server1.PeerSubscribe(server2) : server1 = 1, server2 = 1
|
||||||
|
// server1 <- server2.makeHelloMessage() : server1 = 1, server2 = 1
|
||||||
|
// server1.notifyPeer() : server1 = 1, server2 = 1
|
||||||
|
// server1 -> server2.AddPeer(server2) : server1 = 1, server2 = 1
|
||||||
|
// server2 self peer, skipping : server1 = 1, server2 = 1
|
||||||
|
// server1 -> server2.PeerSubscribe(server1) : server1 = 1, server2 = 1
|
||||||
|
name: "Add 1 peer",
|
||||||
|
wantServerOne: 1,
|
||||||
|
wantServerTwo: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T){
|
||||||
|
server := MakeHubServer(ctx, args)
|
||||||
|
server2 := MakeHubServer(ctx, args2)
|
||||||
|
metrics.PeersKnown.Set(0)
|
||||||
|
go server.Run()
|
||||||
|
go server2.Run()
|
||||||
|
//go server.Run()
|
||||||
|
conn, err := grpc.Dial("localhost:"+args.Port,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("did not connect: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
|
msg := &pb.ServerMessage{
|
||||||
|
Address: "0.0.0.0",
|
||||||
|
Port: "50052",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.AddPeer(context.Background(), msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.GrpcServer.GracefulStop()
|
||||||
|
server2.GrpcServer.GracefulStop()
|
||||||
|
got1 := server.getNumPeers()
|
||||||
|
got2 := server2.getNumPeers()
|
||||||
|
if got1 != tt.wantServerOne {
|
||||||
|
t.Errorf("len(server.PeerServers) = %d, want %d\n", got1, tt.wantServerOne)
|
||||||
|
}
|
||||||
|
if got2 != tt.wantServerTwo {
|
||||||
|
t.Errorf("len(server2.PeerServers) = %d, want %d\n", got2, tt.wantServerTwo)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAddPeerEndpoint2 tests the ability to add peers
|
||||||
|
func TestAddPeerEndpoint2(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
args := makeDefaultArgs()
|
||||||
|
args2 := makeDefaultArgs()
|
||||||
|
args3 := makeDefaultArgs()
|
||||||
|
args2.Port = "50052"
|
||||||
|
args3.Port = "50053"
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
wantServerOne int64
|
||||||
|
wantServerTwo int64
|
||||||
|
wantServerThree int64
|
||||||
|
} {
|
||||||
|
{
|
||||||
|
name: "Add 2 peers",
|
||||||
|
wantServerOne: 2,
|
||||||
|
wantServerTwo: 2,
|
||||||
|
wantServerThree: 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T){
|
||||||
|
server := MakeHubServer(ctx, args)
|
||||||
|
server2 := MakeHubServer(ctx, args2)
|
||||||
|
server3 := MakeHubServer(ctx, args3)
|
||||||
|
metrics.PeersKnown.Set(0)
|
||||||
|
go server.Run()
|
||||||
|
go server2.Run()
|
||||||
|
go server3.Run()
|
||||||
|
conn, err := grpc.Dial("localhost:"+args.Port,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("did not connect: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
|
msg := &pb.ServerMessage{
|
||||||
|
Address: "0.0.0.0",
|
||||||
|
Port: "50052",
|
||||||
|
}
|
||||||
|
|
||||||
|
msg2 := &pb.ServerMessage{
|
||||||
|
Address: "0.0.0.0",
|
||||||
|
Port: "50053",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.AddPeer(context.Background(), msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
_, err = c.AddPeer(context.Background(), msg2)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.GrpcServer.GracefulStop()
|
||||||
|
server2.GrpcServer.GracefulStop()
|
||||||
|
server3.GrpcServer.GracefulStop()
|
||||||
|
got1 := server.getNumPeers()
|
||||||
|
got2 := server2.getNumPeers()
|
||||||
|
got3 := server3.getNumPeers()
|
||||||
|
if got1 != tt.wantServerOne {
|
||||||
|
t.Errorf("len(server.PeerServers) = %d, want %d\n", got1, tt.wantServerOne)
|
||||||
|
}
|
||||||
|
if got2 != tt.wantServerTwo {
|
||||||
|
t.Errorf("len(server2.PeerServers) = %d, want %d\n", got2, tt.wantServerTwo)
|
||||||
|
}
|
||||||
|
if got3 != tt.wantServerThree {
|
||||||
|
t.Errorf("len(server3.PeerServers) = %d, want %d\n", got3, tt.wantServerThree)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TestAddPeerEndpoint3 tests the ability to add peers
|
||||||
|
func TestAddPeerEndpoint3(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
args := makeDefaultArgs()
|
||||||
|
args2 := makeDefaultArgs()
|
||||||
|
args3 := makeDefaultArgs()
|
||||||
|
args2.Port = "50052"
|
||||||
|
args3.Port = "50053"
|
||||||
|
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
wantServerOne int64
|
||||||
|
wantServerTwo int64
|
||||||
|
wantServerThree int64
|
||||||
|
} {
|
||||||
|
{
|
||||||
|
name: "Add 1 peer to each",
|
||||||
|
wantServerOne: 2,
|
||||||
|
wantServerTwo: 2,
|
||||||
|
wantServerThree: 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T){
|
||||||
|
server := MakeHubServer(ctx, args)
|
||||||
|
server2 := MakeHubServer(ctx, args2)
|
||||||
|
server3 := MakeHubServer(ctx, args3)
|
||||||
|
metrics.PeersKnown.Set(0)
|
||||||
|
go server.Run()
|
||||||
|
go server2.Run()
|
||||||
|
go server3.Run()
|
||||||
|
conn, err := grpc.Dial("localhost:"+args.Port,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("did not connect: %v", err)
|
||||||
|
}
|
||||||
|
conn2, err := grpc.Dial("localhost:50052",
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("did not connect: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := pb.NewHubClient(conn)
|
||||||
|
c2 := pb.NewHubClient(conn2)
|
||||||
|
|
||||||
|
msg := &pb.ServerMessage{
|
||||||
|
Address: "0.0.0.0",
|
||||||
|
Port: "50052",
|
||||||
|
}
|
||||||
|
|
||||||
|
msg2 := &pb.ServerMessage{
|
||||||
|
Address: "0.0.0.0",
|
||||||
|
Port: "50053",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.AddPeer(context.Background(), msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
_, err = c2.AddPeer(context.Background(), msg2)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.GrpcServer.GracefulStop()
|
||||||
|
server2.GrpcServer.GracefulStop()
|
||||||
|
server3.GrpcServer.GracefulStop()
|
||||||
|
got1 := server.getNumPeers()
|
||||||
|
got2 := server2.getNumPeers()
|
||||||
|
got3 := server3.getNumPeers()
|
||||||
|
if got1 != tt.wantServerOne {
|
||||||
|
t.Errorf("len(server.PeerServers) = %d, want %d\n", got1, tt.wantServerOne)
|
||||||
|
}
|
||||||
|
if got2 != tt.wantServerTwo {
|
||||||
|
t.Errorf("len(server2.PeerServers) = %d, want %d\n", got2, tt.wantServerTwo)
|
||||||
|
}
|
||||||
|
if got3 != tt.wantServerThree {
|
||||||
|
t.Errorf("len(server3.PeerServers) = %d, want %d\n", got3, tt.wantServerThree)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,8 +11,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
//"github.com/lbryio/hub/schema"
|
|
||||||
|
|
||||||
"github.com/lbryio/hub/internal/metrics"
|
"github.com/lbryio/hub/internal/metrics"
|
||||||
pb "github.com/lbryio/hub/protobuf/go"
|
pb "github.com/lbryio/hub/protobuf/go"
|
||||||
"github.com/lbryio/lbry.go/v2/extras/util"
|
"github.com/lbryio/lbry.go/v2/extras/util"
|
||||||
|
@ -24,8 +22,11 @@ import (
|
||||||
"gopkg.in/karalabe/cookiejar.v1/collections/deque"
|
"gopkg.in/karalabe/cookiejar.v1/collections/deque"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultSearchSize is the default max number of items an
|
||||||
|
// es search will return.
|
||||||
const DefaultSearchSize = 1000
|
const DefaultSearchSize = 1000
|
||||||
|
|
||||||
|
// record is a struct for the response from es.
|
||||||
type record struct {
|
type record struct {
|
||||||
Txid string `json:"tx_id"`
|
Txid string `json:"tx_id"`
|
||||||
Nout uint32 `json:"tx_nout"`
|
Nout uint32 `json:"tx_nout"`
|
||||||
|
@ -50,11 +51,14 @@ type record struct {
|
||||||
ClaimName string `json:"claim_name"`
|
ClaimName string `json:"claim_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// orderField is struct for specifying ordering of es search results.
|
||||||
type orderField struct {
|
type orderField struct {
|
||||||
Field string
|
Field string
|
||||||
IsAsc bool
|
IsAsc bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StrArrToInterface takes an array of strings and returns them as an array of
|
||||||
|
// interfaces.
|
||||||
func StrArrToInterface(arr []string) []interface{} {
|
func StrArrToInterface(arr []string) []interface{} {
|
||||||
searchVals := make([]interface{}, len(arr))
|
searchVals := make([]interface{}, len(arr))
|
||||||
for i := 0; i < len(arr); i++ {
|
for i := 0; i < len(arr); i++ {
|
||||||
|
@ -63,6 +67,9 @@ func StrArrToInterface(arr []string) []interface{} {
|
||||||
return searchVals
|
return searchVals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddTermsField takes an es bool query, array of string values and a term
|
||||||
|
// name and adds a TermsQuery for that name matching those values to the
|
||||||
|
// bool query.
|
||||||
func AddTermsField(q *elastic.BoolQuery, arr []string, name string) *elastic.BoolQuery {
|
func AddTermsField(q *elastic.BoolQuery, arr []string, name string) *elastic.BoolQuery {
|
||||||
if len(arr) == 0 {
|
if len(arr) == 0 {
|
||||||
return q
|
return q
|
||||||
|
@ -71,6 +78,9 @@ func AddTermsField(q *elastic.BoolQuery, arr []string, name string) *elastic.Boo
|
||||||
return q.Must(elastic.NewTermsQuery(name, searchVals...))
|
return q.Must(elastic.NewTermsQuery(name, searchVals...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddTermField takes an es bool query, a string value and a term name
|
||||||
|
// and adds a TermQuery for that name matching that value to the bool
|
||||||
|
// query.
|
||||||
func AddTermField(q *elastic.BoolQuery, value string, name string) *elastic.BoolQuery {
|
func AddTermField(q *elastic.BoolQuery, value string, name string) *elastic.BoolQuery {
|
||||||
if value != "" {
|
if value != "" {
|
||||||
return q.Must(elastic.NewTermQuery(name, value))
|
return q.Must(elastic.NewTermQuery(name, value))
|
||||||
|
@ -78,6 +88,9 @@ func AddTermField(q *elastic.BoolQuery, value string, name string) *elastic.Bool
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddIndividualTermFields takes a bool query, an array of string values
|
||||||
|
// a term name, and a bool to invert the query, and adds multiple individual
|
||||||
|
// TermQuerys for that name matching each of the values.
|
||||||
func AddIndividualTermFields(q *elastic.BoolQuery, arr []string, name string, invert bool) *elastic.BoolQuery {
|
func AddIndividualTermFields(q *elastic.BoolQuery, arr []string, name string, invert bool) *elastic.BoolQuery {
|
||||||
for _, x := range arr {
|
for _, x := range arr {
|
||||||
if invert {
|
if invert {
|
||||||
|
@ -89,6 +102,8 @@ func AddIndividualTermFields(q *elastic.BoolQuery, arr []string, name string, in
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRangeField takes a bool query, a range field struct and a term name
|
||||||
|
// and adds a term query for that name matching that range field.
|
||||||
func AddRangeField(q *elastic.BoolQuery, rq *pb.RangeField, name string) *elastic.BoolQuery {
|
func AddRangeField(q *elastic.BoolQuery, rq *pb.RangeField, name string) *elastic.BoolQuery {
|
||||||
if rq == nil {
|
if rq == nil {
|
||||||
return q
|
return q
|
||||||
|
@ -112,6 +127,8 @@ func AddRangeField(q *elastic.BoolQuery, rq *pb.RangeField, name string) *elasti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddInvertibleField takes a bool query, an invertible field and a term name
|
||||||
|
// and adds a term query for that name matching that invertible field.
|
||||||
func AddInvertibleField(q *elastic.BoolQuery, field *pb.InvertibleField, name string) *elastic.BoolQuery {
|
func AddInvertibleField(q *elastic.BoolQuery, field *pb.InvertibleField, name string) *elastic.BoolQuery {
|
||||||
if field == nil {
|
if field == nil {
|
||||||
return q
|
return q
|
||||||
|
@ -128,11 +145,16 @@ func AddInvertibleField(q *elastic.BoolQuery, field *pb.InvertibleField, name st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recordErrorAndDie is for fatal errors. It takes an error, increments the
|
||||||
|
// fatal error metric in prometheus and prints a fatal error message.
|
||||||
func (s *Server) recordErrorAndDie(err error) {
|
func (s *Server) recordErrorAndDie(err error) {
|
||||||
metrics.ErrorsCounter.With(prometheus.Labels{"error_type": "fatal"}).Inc()
|
metrics.ErrorsCounter.With(prometheus.Labels{"error_type": "fatal"}).Inc()
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RoundUpReleaseTime take a bool query, a range query and a term name
|
||||||
|
// and adds a term query for that name (this is for the release time
|
||||||
|
// field) with the value rounded up.
|
||||||
func RoundUpReleaseTime(q *elastic.BoolQuery, rq *pb.RangeField, name string) *elastic.BoolQuery {
|
func RoundUpReleaseTime(q *elastic.BoolQuery, rq *pb.RangeField, name string) *elastic.BoolQuery {
|
||||||
if rq == nil {
|
if rq == nil {
|
||||||
return q
|
return q
|
||||||
|
@ -170,6 +192,11 @@ func RoundUpReleaseTime(q *elastic.BoolQuery, rq *pb.RangeField, name string) *e
|
||||||
// 8) return streams referenced by repost and all channel referenced in extra_txos
|
// 8) return streams referenced by repost and all channel referenced in extra_txos
|
||||||
//*/
|
//*/
|
||||||
func (s *Server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.Outputs, error) {
|
func (s *Server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.Outputs, error) {
|
||||||
|
if s.Args.DisableEs {
|
||||||
|
log.Println("ElasticSearch disable, return nil to search")
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
metrics.RequestsCount.With(prometheus.Labels{"method": "search"}).Inc()
|
metrics.RequestsCount.With(prometheus.Labels{"method": "search"}).Inc()
|
||||||
defer func(t time.Time) {
|
defer func(t time.Time) {
|
||||||
delta := time.Since(t).Seconds()
|
delta := time.Since(t).Seconds()
|
||||||
|
@ -301,6 +328,7 @@ func (s *Server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.Outputs,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// normalizeTag takes a string and normalizes it for search in es.
|
||||||
func (s *Server) normalizeTag(tag string) string {
|
func (s *Server) normalizeTag(tag string) string {
|
||||||
c := cases.Lower(language.English)
|
c := cases.Lower(language.English)
|
||||||
res := s.MultiSpaceRe.ReplaceAll(
|
res := s.MultiSpaceRe.ReplaceAll(
|
||||||
|
@ -312,6 +340,7 @@ func (s *Server) normalizeTag(tag string) string {
|
||||||
return string(res)
|
return string(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cleanTags takes an array of tags and normalizes them.
|
||||||
func (s *Server) cleanTags(tags []string) []string {
|
func (s *Server) cleanTags(tags []string) []string {
|
||||||
cleanedTags := make([]string, len(tags))
|
cleanedTags := make([]string, len(tags))
|
||||||
for i, tag := range tags {
|
for i, tag := range tags {
|
||||||
|
@ -320,6 +349,8 @@ func (s *Server) cleanTags(tags []string) []string {
|
||||||
return cleanedTags
|
return cleanedTags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// searchResultToRecords takes an elastic.SearchResult object and converts
|
||||||
|
// them to internal record structures.
|
||||||
func (s *Server) searchResultToRecords(
|
func (s *Server) searchResultToRecords(
|
||||||
searchResult *elastic.SearchResult) []*record {
|
searchResult *elastic.SearchResult) []*record {
|
||||||
records := make([]*record, 0, searchResult.TotalHits())
|
records := make([]*record, 0, searchResult.TotalHits())
|
||||||
|
@ -334,6 +365,9 @@ func (s *Server) searchResultToRecords(
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// postProcessResults takes es search result records and runs our
|
||||||
|
// post processing on them.
|
||||||
|
// TODO: more in depth description.
|
||||||
func (s *Server) postProcessResults(
|
func (s *Server) postProcessResults(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
client *elastic.Client,
|
client *elastic.Client,
|
||||||
|
@ -397,6 +431,8 @@ func (s *Server) postProcessResults(
|
||||||
return txos, extraTxos, blocked
|
return txos, extraTxos, blocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkQuery takes a search request and does a sanity check on it for
|
||||||
|
// validity.
|
||||||
func (s *Server) checkQuery(in *pb.SearchRequest) error {
|
func (s *Server) checkQuery(in *pb.SearchRequest) error {
|
||||||
limit := 2048
|
limit := 2048
|
||||||
checks := map[string]bool{
|
checks := map[string]bool{
|
||||||
|
@ -418,6 +454,8 @@ func (s *Server) checkQuery(in *pb.SearchRequest) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setPageVars takes a search request and pointers to the local pageSize
|
||||||
|
// and from variables and sets them from the struct.
|
||||||
func setPageVars(in *pb.SearchRequest, pageSize *int, from *int) {
|
func setPageVars(in *pb.SearchRequest, pageSize *int, from *int) {
|
||||||
if in.Limit > 0 {
|
if in.Limit > 0 {
|
||||||
log.Printf("############ limit: %d\n", in.Limit)
|
log.Printf("############ limit: %d\n", in.Limit)
|
||||||
|
@ -429,6 +467,8 @@ func setPageVars(in *pb.SearchRequest, pageSize *int, from *int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setupEsQuery takes an elastic.BoolQuery, pb.SearchRequest and orderField
|
||||||
|
// and adds the search request terms to the bool query.
|
||||||
func (s *Server) setupEsQuery(
|
func (s *Server) setupEsQuery(
|
||||||
q *elastic.BoolQuery,
|
q *elastic.BoolQuery,
|
||||||
in *pb.SearchRequest,
|
in *pb.SearchRequest,
|
||||||
|
@ -625,6 +665,8 @@ func (s *Server) setupEsQuery(
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getUniqueChannels takes the record results from the es search and returns
|
||||||
|
// the unique channels from those records as a list and a map.
|
||||||
func (s *Server) getUniqueChannels(records []*record, client *elastic.Client, ctx context.Context, searchIndices []string) ([]*pb.Output, map[string]*pb.Output) {
|
func (s *Server) getUniqueChannels(records []*record, client *elastic.Client, ctx context.Context, searchIndices []string) ([]*pb.Output, map[string]*pb.Output) {
|
||||||
channels := make(map[string]*pb.Output)
|
channels := make(map[string]*pb.Output)
|
||||||
channelsSet := make(map[string]bool)
|
channelsSet := make(map[string]bool)
|
||||||
|
@ -678,6 +720,9 @@ func (s *Server) getUniqueChannels(records []*record, client *elastic.Client, ct
|
||||||
return channelTxos, channels
|
return channelTxos, channels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getClaimsForReposts takes the record results from the es query and returns
|
||||||
|
// an array and map of the reposted records as well as an array of those
|
||||||
|
// records.
|
||||||
func (s *Server) getClaimsForReposts(ctx context.Context, client *elastic.Client, records []*record, searchIndices []string) ([]*pb.Output, []*record, map[string]*pb.Output) {
|
func (s *Server) getClaimsForReposts(ctx context.Context, client *elastic.Client, records []*record, searchIndices []string) ([]*pb.Output, []*record, map[string]*pb.Output) {
|
||||||
|
|
||||||
var totalReposted = 0
|
var totalReposted = 0
|
||||||
|
@ -731,10 +776,8 @@ func (s *Server) getClaimsForReposts(ctx context.Context, client *elastic.Client
|
||||||
return claims, repostedRecords, respostedMap
|
return claims, repostedRecords, respostedMap
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// serializeSearchRequest takes a search request and serializes it into a key
|
||||||
Takes a search request and serializes into a string for use as a key into the
|
// for use in the internal cache for the hub.
|
||||||
internal cache for the hub.
|
|
||||||
*/
|
|
||||||
func (s *Server) serializeSearchRequest(request *pb.SearchRequest) string {
|
func (s *Server) serializeSearchRequest(request *pb.SearchRequest) string {
|
||||||
// Save the offest / limit and set to zero, cache hits should happen regardless
|
// Save the offest / limit and set to zero, cache hits should happen regardless
|
||||||
// and they're used in post processing
|
// and they're used in post processing
|
||||||
|
@ -754,6 +797,8 @@ func (s *Server) serializeSearchRequest(request *pb.SearchRequest) string {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// searchAhead takes an array of record results, the pageSize and
|
||||||
|
// perChannelPerPage value and returns the hits for this page.
|
||||||
func searchAhead(searchHits []*record, pageSize int, perChannelPerPage int) []*record {
|
func searchAhead(searchHits []*record, pageSize int, perChannelPerPage int) []*record {
|
||||||
finalHits := make([]*record, 0, len(searchHits))
|
finalHits := make([]*record, 0, len(searchHits))
|
||||||
var channelCounters map[string]int
|
var channelCounters map[string]int
|
||||||
|
@ -796,6 +841,8 @@ func searchAhead(searchHits []*record, pageSize int, perChannelPerPage int) []*r
|
||||||
return finalHits
|
return finalHits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recordToOutput is a function on a record struct to turn it into a pb.Output
|
||||||
|
// struct.
|
||||||
func (r *record) recordToOutput() *pb.Output {
|
func (r *record) recordToOutput() *pb.Output {
|
||||||
return &pb.Output{
|
return &pb.Output{
|
||||||
TxHash: util.TxIdToTxHash(r.Txid),
|
TxHash: util.TxIdToTxHash(r.Txid),
|
||||||
|
@ -822,6 +869,8 @@ func (r *record) recordToOutput() *pb.Output {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getHitId is a function on the record struct to get the id for the search
|
||||||
|
// hit.
|
||||||
func (r *record) getHitId() string {
|
func (r *record) getHitId() string {
|
||||||
if r.RepostedClaimId != "" {
|
if r.RepostedClaimId != "" {
|
||||||
return r.RepostedClaimId
|
return r.RepostedClaimId
|
||||||
|
@ -830,6 +879,7 @@ func (r *record) getHitId() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removeDuplicates takes an array of record results and remove duplicates.
|
||||||
func removeDuplicates(searchHits []*record) []*record {
|
func removeDuplicates(searchHits []*record) []*record {
|
||||||
dropped := make(map[*record]bool)
|
dropped := make(map[*record]bool)
|
||||||
// claim_id -> (creation_height, hit_id), where hit_id is either reposted claim id or original
|
// claim_id -> (creation_height, hit_id), where hit_id is either reposted claim id or original
|
||||||
|
@ -865,6 +915,8 @@ func removeDuplicates(searchHits []*record) []*record {
|
||||||
return deduped
|
return deduped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removeBlocked takes an array of record results from the es search
|
||||||
|
// and removes blocked records.
|
||||||
func removeBlocked(searchHits []*record) ([]*record, []*record, map[string]*pb.Blocked) {
|
func removeBlocked(searchHits []*record) ([]*record, []*record, map[string]*pb.Blocked) {
|
||||||
newHits := make([]*record, 0, len(searchHits))
|
newHits := make([]*record, 0, len(searchHits))
|
||||||
blockedHits := make([]*record, 0, len(searchHits))
|
blockedHits := make([]*record, 0, len(searchHits))
|
||||||
|
|
251
server/server.go
251
server/server.go
|
@ -6,9 +6,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ReneKroon/ttlcache/v2"
|
"github.com/ReneKroon/ttlcache/v2"
|
||||||
|
@ -19,47 +21,30 @@ import (
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/reflection"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
GrpcServer *grpc.Server
|
GrpcServer *grpc.Server
|
||||||
Args *Args
|
Args *Args
|
||||||
MultiSpaceRe *regexp.Regexp
|
MultiSpaceRe *regexp.Regexp
|
||||||
WeirdCharsRe *regexp.Regexp
|
WeirdCharsRe *regexp.Regexp
|
||||||
EsClient *elastic.Client
|
EsClient *elastic.Client
|
||||||
Servers []*FederatedServer
|
QueryCache *ttlcache.Cache
|
||||||
QueryCache *ttlcache.Cache
|
S256 *hash.Hash
|
||||||
S256 *hash.Hash
|
|
||||||
LastRefreshCheck time.Time
|
LastRefreshCheck time.Time
|
||||||
RefreshDelta time.Duration
|
RefreshDelta time.Duration
|
||||||
NumESRefreshes int64
|
NumESRefreshes int64
|
||||||
|
PeerServers map[string]*FederatedServer
|
||||||
|
PeerServersMut sync.RWMutex
|
||||||
|
NumPeerServers *int64
|
||||||
|
PeerSubs map[string]*FederatedServer
|
||||||
|
PeerSubsMut sync.RWMutex
|
||||||
|
NumPeerSubs *int64
|
||||||
|
Subscribed bool
|
||||||
pb.UnimplementedHubServer
|
pb.UnimplementedHubServer
|
||||||
}
|
}
|
||||||
|
|
||||||
type FederatedServer struct {
|
|
||||||
Address string
|
|
||||||
Port string
|
|
||||||
Ts time.Time
|
|
||||||
Ping int //?
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
ServeCmd = iota
|
|
||||||
SearchCmd = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
type Args struct {
|
|
||||||
// TODO Make command types an enum
|
|
||||||
CmdType int
|
|
||||||
Host string
|
|
||||||
Port string
|
|
||||||
EsHost string
|
|
||||||
EsPort string
|
|
||||||
EsIndex string
|
|
||||||
Debug bool
|
|
||||||
RefreshDelta int
|
|
||||||
CacheTTL int
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVersion() string {
|
func getVersion() string {
|
||||||
return meta.Version
|
return meta.Version
|
||||||
|
@ -104,7 +89,56 @@ func getVersion() string {
|
||||||
'blockchain.address.unsubscribe'
|
'blockchain.address.unsubscribe'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func MakeHubServer(args *Args) *Server {
|
func (s *Server) PeerSubsLoadOrStore(peer *FederatedServer) (actual *FederatedServer, loaded bool) {
|
||||||
|
key := peer.peerKey()
|
||||||
|
s.PeerSubsMut.RLock()
|
||||||
|
if actual, ok := s.PeerSubs[key]; ok {
|
||||||
|
s.PeerSubsMut.RUnlock()
|
||||||
|
return actual, true
|
||||||
|
} else {
|
||||||
|
s.PeerSubsMut.RUnlock()
|
||||||
|
s.PeerSubsMut.Lock()
|
||||||
|
s.PeerSubs[key] = peer
|
||||||
|
s.PeerSubsMut.Unlock()
|
||||||
|
return peer, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) PeerServersLoadOrStore(peer *FederatedServer) (actual *FederatedServer, loaded bool) {
|
||||||
|
key := peer.peerKey()
|
||||||
|
s.PeerServersMut.RLock()
|
||||||
|
if actual, ok := s.PeerServers[key]; ok {
|
||||||
|
s.PeerServersMut.RUnlock()
|
||||||
|
return actual, true
|
||||||
|
} else {
|
||||||
|
s.PeerServersMut.RUnlock()
|
||||||
|
s.PeerServersMut.Lock()
|
||||||
|
s.PeerServers[key] = peer
|
||||||
|
s.PeerServersMut.Unlock()
|
||||||
|
return peer, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Run() {
|
||||||
|
l, err := net.Listen("tcp", ":"+s.Args.Port)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to listen: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pb.RegisterHubServer(s.GrpcServer, s)
|
||||||
|
reflection.Register(s.GrpcServer)
|
||||||
|
|
||||||
|
log.Printf("listening on %s\n", l.Addr().String())
|
||||||
|
log.Println(s.Args)
|
||||||
|
if err := s.GrpcServer.Serve(l); err != nil {
|
||||||
|
log.Fatalf("failed to serve: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeHubServer takes the arguments given to a hub when it's started and
|
||||||
|
// initializes everything. It loads information about previously known peers,
|
||||||
|
// creates needed internal data structures, and initializes goroutines.
|
||||||
|
func MakeHubServer(ctx context.Context, args *Args) *Server {
|
||||||
grpcServer := grpc.NewServer(grpc.NumStreamWorkers(10))
|
grpcServer := grpc.NewServer(grpc.NumStreamWorkers(10))
|
||||||
|
|
||||||
multiSpaceRe, err := regexp.Compile(`\s{2,}`)
|
multiSpaceRe, err := regexp.Compile(`\s{2,}`)
|
||||||
|
@ -116,23 +150,23 @@ func MakeHubServer(args *Args) *Server {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
self := &FederatedServer{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: args.Port,
|
|
||||||
Ts: time.Now(),
|
|
||||||
Ping: 0,
|
|
||||||
}
|
|
||||||
servers := make([]*FederatedServer, 10)
|
|
||||||
servers = append(servers, self)
|
|
||||||
|
|
||||||
esUrl := args.EsHost + ":" + args.EsPort
|
var client *elastic.Client = nil
|
||||||
opts := []elastic.ClientOptionFunc{elastic.SetSniff(false), elastic.SetURL(esUrl)}
|
if !args.DisableEs {
|
||||||
if args.Debug {
|
esUrl := args.EsHost + ":" + args.EsPort
|
||||||
opts = append(opts, elastic.SetTraceLog(log.New(os.Stderr, "[[ELASTIC]]", 0)))
|
opts := []elastic.ClientOptionFunc{
|
||||||
}
|
elastic.SetSniff(true),
|
||||||
client, err := elastic.NewClient(opts...)
|
elastic.SetSnifferTimeoutStartup(time.Second * 60),
|
||||||
if err != nil {
|
elastic.SetSnifferTimeout(time.Second * 60),
|
||||||
log.Fatal(err)
|
elastic.SetURL(esUrl),
|
||||||
|
}
|
||||||
|
if args.Debug {
|
||||||
|
opts = append(opts, elastic.SetTraceLog(log.New(os.Stderr, "[[ELASTIC]]", 0)))
|
||||||
|
}
|
||||||
|
client, err = elastic.NewClient(opts...)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cache := ttlcache.NewCache()
|
cache := ttlcache.NewCache()
|
||||||
|
@ -146,45 +180,130 @@ func MakeHubServer(args *Args) *Server {
|
||||||
refreshDelta = time.Second * 0
|
refreshDelta = time.Second * 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
numPeers := new(int64)
|
||||||
|
*numPeers = 0
|
||||||
|
numSubs := new(int64)
|
||||||
|
*numSubs = 0
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
GrpcServer: grpcServer,
|
GrpcServer: grpcServer,
|
||||||
Args: args,
|
Args: args,
|
||||||
MultiSpaceRe: multiSpaceRe,
|
MultiSpaceRe: multiSpaceRe,
|
||||||
WeirdCharsRe: weirdCharsRe,
|
WeirdCharsRe: weirdCharsRe,
|
||||||
EsClient: client,
|
EsClient: client,
|
||||||
QueryCache: cache,
|
QueryCache: cache,
|
||||||
S256: &s256,
|
S256: &s256,
|
||||||
LastRefreshCheck: time.Now(),
|
LastRefreshCheck: time.Now(),
|
||||||
RefreshDelta: refreshDelta,
|
RefreshDelta: refreshDelta,
|
||||||
NumESRefreshes: 0,
|
NumESRefreshes: 0,
|
||||||
|
PeerServers: make(map[string]*FederatedServer),
|
||||||
|
PeerServersMut: sync.RWMutex{},
|
||||||
|
NumPeerServers: numPeers,
|
||||||
|
PeerSubs: make(map[string]*FederatedServer),
|
||||||
|
PeerSubsMut: sync.RWMutex{},
|
||||||
|
NumPeerSubs: numSubs,
|
||||||
|
Subscribed: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start up our background services
|
||||||
|
if args.StartPrometheus {
|
||||||
|
go s.prometheusEndpoint(s.Args.PrometheusPort, "metrics")
|
||||||
|
}
|
||||||
|
if args.StartUDP {
|
||||||
|
go func() {
|
||||||
|
err := UDPServer(args)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("UDP Server failed!", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
// Load peers from disk and subscribe to one if there are any
|
||||||
|
if args.LoadPeers {
|
||||||
|
err = s.loadPeers()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PromethusEndpoint(port string, endpoint string) error {
|
// prometheusEndpoint is a goroutine which start up a prometheus endpoint
|
||||||
|
// for this hub to allow for metric tracking.
|
||||||
|
func (s *Server) prometheusEndpoint(port string, endpoint string) {
|
||||||
http.Handle("/"+endpoint, promhttp.Handler())
|
http.Handle("/"+endpoint, promhttp.Handler())
|
||||||
log.Println(fmt.Sprintf("listening on :%s /%s", port, endpoint))
|
log.Println(fmt.Sprintf("listening on :%s /%s", port, endpoint))
|
||||||
err := http.ListenAndServe(":"+port, nil)
|
err := http.ListenAndServe(":"+port, nil)
|
||||||
if err != nil {
|
log.Fatalln("Shouldn't happen??!?!", err)
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
// Hello is a grpc endpoint to allow another hub to tell us about itself.
|
||||||
|
// The passed message includes information about the other hub, and all
|
||||||
|
// of its peers which are added to the knowledge of this hub.
|
||||||
|
func (s *Server) Hello(ctx context.Context, args *pb.HelloMessage) (*pb.HelloMessage, error) {
|
||||||
|
metrics.RequestsCount.With(prometheus.Labels{"method": "hello"}).Inc()
|
||||||
|
port := args.Port
|
||||||
|
host := args.Host
|
||||||
|
server := &FederatedServer{
|
||||||
|
Address: host,
|
||||||
|
Port: port,
|
||||||
|
Ts: time.Now(),
|
||||||
}
|
}
|
||||||
log.Fatalln("Shouldn't happen??!?!")
|
log.Println(server)
|
||||||
return nil
|
|
||||||
|
err := s.addPeer(&pb.ServerMessage{Address: host, Port: port}, false)
|
||||||
|
// They just contacted us, so this shouldn't happen
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
s.mergeFederatedServers(args.Servers)
|
||||||
|
s.writePeers()
|
||||||
|
s.notifyPeerSubs(server)
|
||||||
|
|
||||||
|
return s.makeHelloMessage(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Hello(context context.Context, args *FederatedServer) (*FederatedServer, error) {
|
// PeerSubscribe adds a peer hub to the list of subscribers to update about
|
||||||
s.Servers = append(s.Servers, args)
|
// new peers.
|
||||||
|
func (s *Server) PeerSubscribe(ctx context.Context, in *pb.ServerMessage) (*pb.StringValue, error) {
|
||||||
|
metrics.RequestsCount.With(prometheus.Labels{"method": "peer_subscribe"}).Inc()
|
||||||
|
var msg = "Success"
|
||||||
|
peer := &FederatedServer{
|
||||||
|
Address: in.Address,
|
||||||
|
Port: in.Port,
|
||||||
|
Ts: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
return s.Servers[0], nil
|
if _, loaded := s.PeerSubsLoadOrStore(peer); !loaded {
|
||||||
|
s.incNumSubs()
|
||||||
|
metrics.PeersSubscribed.Inc()
|
||||||
|
} else {
|
||||||
|
msg = "Already subscribed"
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.StringValue{Value: msg}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Ping(context context.Context, args *pb.EmptyMessage) (*pb.StringValue, error) {
|
// AddPeer is a grpc endpoint to tell this hub about another hub in the network.
|
||||||
|
func (s *Server) AddPeer(ctx context.Context, args *pb.ServerMessage) (*pb.StringValue, error) {
|
||||||
|
metrics.RequestsCount.With(prometheus.Labels{"method": "add_peer"}).Inc()
|
||||||
|
var msg = "Success"
|
||||||
|
err := s.addPeer(args, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
msg = "Failed"
|
||||||
|
}
|
||||||
|
return &pb.StringValue{Value: msg}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping is a grpc endpoint that returns a short message.
|
||||||
|
func (s *Server) Ping(ctx context.Context, args *pb.EmptyMessage) (*pb.StringValue, error) {
|
||||||
metrics.RequestsCount.With(prometheus.Labels{"method": "ping"}).Inc()
|
metrics.RequestsCount.With(prometheus.Labels{"method": "ping"}).Inc()
|
||||||
return &pb.StringValue{Value: "Hello, world!"}, nil
|
return &pb.StringValue{Value: "Hello, world!"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Version(context context.Context, args *pb.EmptyMessage) (*pb.StringValue, error) {
|
// Version is a grpc endpoint to get this hub's version.
|
||||||
|
func (s *Server) Version(ctx context.Context, args *pb.EmptyMessage) (*pb.StringValue, error) {
|
||||||
metrics.RequestsCount.With(prometheus.Labels{"method": "version"}).Inc()
|
metrics.RequestsCount.With(prometheus.Labels{"method": "version"}).Inc()
|
||||||
return &pb.StringValue{Value: getVersion()}, nil
|
return &pb.StringValue{Value: getVersion()}, nil
|
||||||
}
|
}
|
||||||
|
|
226
server/udp.go
Normal file
226
server/udp.go
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const maxBufferSize = 1024
|
||||||
|
// genesis blocktime (which is actually wrong)
|
||||||
|
const magic = 1446058291
|
||||||
|
const protocolVersion = 1
|
||||||
|
|
||||||
|
// SPVPing is a struct for the format of how to ping another hub over udp.
|
||||||
|
// format b'!lB64s'
|
||||||
|
type SPVPing struct {
|
||||||
|
magic uint32
|
||||||
|
version byte
|
||||||
|
padding []byte //64
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPVPong is a struct for the return pong from another hub server.
|
||||||
|
// format b'!BBL32s4sH'
|
||||||
|
type SPVPong struct {
|
||||||
|
protocolVersion byte
|
||||||
|
flags byte
|
||||||
|
height uint32
|
||||||
|
tip []byte // 32
|
||||||
|
srcAddrRaw []byte // 4
|
||||||
|
country uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeSPVPing creates a slice of bytes to ping another hub with
|
||||||
|
// over udp.
|
||||||
|
func encodeSPVPing() []byte {
|
||||||
|
data := make([]byte, 69)
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint32(data, magic)
|
||||||
|
data[4] = protocolVersion
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeSPVPing takes a slice of bytes and decodes an SPVPing struct from them.
|
||||||
|
func decodeSPVPing(data []byte) *SPVPing {
|
||||||
|
if len(data) < 69 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedMagic := binary.BigEndian.Uint32(data)
|
||||||
|
parsedProtocalVersion := data[4]
|
||||||
|
return &SPVPing{
|
||||||
|
magic: parsedMagic,
|
||||||
|
version: parsedProtocalVersion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode is a function for SPVPong structs to encode them into bytes for
|
||||||
|
// sending over udp.
|
||||||
|
func (pong *SPVPong) Encode() []byte {
|
||||||
|
data := make([]byte, 44)
|
||||||
|
|
||||||
|
data[0] = pong.protocolVersion
|
||||||
|
data[1] = pong.flags
|
||||||
|
binary.BigEndian.PutUint32(data[2:], pong.height)
|
||||||
|
copy(data[6:], pong.tip)
|
||||||
|
copy(data[38:], pong.srcAddrRaw)
|
||||||
|
binary.BigEndian.PutUint16(data[42:], pong.country)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeSPVPong creates an SPVPong struct according to given parameters.
|
||||||
|
// FIXME: Currently, does not correctly encode the country.
|
||||||
|
func makeSPVPong(flags int, height int, tip []byte, sourceAddr string, country string) *SPVPong {
|
||||||
|
byteAddr := EncodeAddress(sourceAddr)
|
||||||
|
countryInt := 1
|
||||||
|
return &SPVPong{
|
||||||
|
protocolVersion: protocolVersion,
|
||||||
|
flags: byte(flags),
|
||||||
|
height: uint32(height),
|
||||||
|
tip: tip,
|
||||||
|
srcAddrRaw: byteAddr,
|
||||||
|
country: uint16(countryInt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeSPVPong takes a slice of bytes and decodes an SPVPong struct
|
||||||
|
// from it.
|
||||||
|
func decodeSPVPong(data []byte) *SPVPong {
|
||||||
|
if len(data) < 44 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedProtocalVersion := data[0]
|
||||||
|
flags := data[1]
|
||||||
|
height := binary.BigEndian.Uint32(data[:2])
|
||||||
|
tip := make([]byte, 32)
|
||||||
|
copy(tip, data[6:38])
|
||||||
|
srcRawAddr := make([]byte, 4)
|
||||||
|
copy(srcRawAddr, data[38:42])
|
||||||
|
country := binary.BigEndian.Uint16(data[:42])
|
||||||
|
return &SPVPong{
|
||||||
|
protocolVersion: parsedProtocalVersion,
|
||||||
|
flags: flags,
|
||||||
|
height: height,
|
||||||
|
tip: tip,
|
||||||
|
srcAddrRaw: srcRawAddr,
|
||||||
|
country: country,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeAddress takes an ipv4 address and encodes it into bytes for the hub
|
||||||
|
// Ping/Pong protocol.
|
||||||
|
func EncodeAddress(addr string) []byte {
|
||||||
|
parts := strings.Split(addr, ".")
|
||||||
|
|
||||||
|
if len(parts) != 4 {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]byte, 4)
|
||||||
|
for i, part := range parts {
|
||||||
|
x, err := strconv.Atoi(part)
|
||||||
|
if err != nil || x > 255 {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
data[i] = byte(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeAddress gets the string ipv4 address from an SPVPong struct.
|
||||||
|
func (pong *SPVPong) DecodeAddress() string {
|
||||||
|
return fmt.Sprintf("%d.%d.%d.%d",
|
||||||
|
pong.srcAddrRaw[0],
|
||||||
|
pong.srcAddrRaw[1],
|
||||||
|
pong.srcAddrRaw[2],
|
||||||
|
pong.srcAddrRaw[3],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDPPing sends a ping over udp to another hub and returns the ip address of
|
||||||
|
// this hub.
|
||||||
|
func UDPPing(address string) (string, error) {
|
||||||
|
addr, err := net.ResolveUDPAddr("udp", address)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.DialUDP("udp", nil, addr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
_, err = conn.Write(encodeSPVPing())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := make([]byte, maxBufferSize)
|
||||||
|
deadline := time.Now().Add(time.Second)
|
||||||
|
err = conn.SetReadDeadline(deadline)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
n, _, err := conn.ReadFromUDP(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
pong := decodeSPVPong(buffer[:n])
|
||||||
|
|
||||||
|
if pong == nil {
|
||||||
|
return "", errors.Base("Pong decoding failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
myAddr := pong.DecodeAddress()
|
||||||
|
|
||||||
|
return myAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDPServer is a goroutine that starts an udp server that implements the hubs
|
||||||
|
// Ping/Pong protocol to find out about each other without making full TCP
|
||||||
|
// connections.
|
||||||
|
func UDPServer(args *Args) error {
|
||||||
|
address := ":" + args.UDPPort
|
||||||
|
tip := make([]byte, 32)
|
||||||
|
addr, err := net.ResolveUDPAddr("udp", address)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.ListenUDP("udp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
buffer := make([]byte, maxBufferSize)
|
||||||
|
for {
|
||||||
|
//TODO verify ping
|
||||||
|
_, addr, err := conn.ReadFromUDP(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sAddr := addr.IP.String()
|
||||||
|
pong := makeSPVPong(0,0, tip, sAddr, args.Country)
|
||||||
|
data := pong.Encode()
|
||||||
|
|
||||||
|
_, err = conn.WriteToUDP(data, addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue