Merge pull request #24 from lbryio/feature/18/jeffreypicard/udp-endpoint
UDPServer / ip address resolution
This commit is contained in:
commit
516b95d96b
13 changed files with 6563 additions and 265 deletions
2
.github/workflows/build-short.yml
vendored
2
.github/workflows/build-short.yml
vendored
|
@ -11,4 +11,4 @@ jobs:
|
||||||
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
|
- run: go test -v -race ./...
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -30,4 +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
|
- run: go test -v -race ./...
|
||||||
|
|
|
@ -18,8 +18,8 @@ var (
|
||||||
Help: "Number of errors by type",
|
Help: "Number of errors by type",
|
||||||
}, []string{"error_type"})
|
}, []string{"error_type"})
|
||||||
QueryTime = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
QueryTime = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
Name: "query_time",
|
Name: "query_time",
|
||||||
Help: "Histogram of query times",
|
Help: "Histogram of query times",
|
||||||
Buckets: HistogramBuckets,
|
Buckets: HistogramBuckets,
|
||||||
}, []string{"method"})
|
}, []string{"method"})
|
||||||
PeersKnown = promauto.NewGauge(prometheus.GaugeOpts{
|
PeersKnown = promauto.NewGauge(prometheus.GaugeOpts{
|
||||||
|
@ -31,4 +31,3 @@ var (
|
||||||
Help: "Number of peers that are subscribed to us.",
|
Help: "Number of peers that are subscribed to us.",
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
14
main.go
14
main.go
|
@ -26,19 +26,7 @@ func main() {
|
||||||
|
|
||||||
s := server.MakeHubServer(ctxWCancel, args)
|
s := server.MakeHubServer(ctxWCancel, args)
|
||||||
s.Run()
|
s.Run()
|
||||||
//l, err := net.Listen("tcp", ":"+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)
|
|
||||||
//}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1051
protobuf/definitions/claim.proto
Normal file
1051
protobuf/definitions/claim.proto
Normal file
File diff suppressed because it is too large
Load diff
5031
protobuf/go/claim.pb.go
Normal file
5031
protobuf/go/claim.pb.go
Normal file
File diff suppressed because it is too large
Load diff
114
server/args.go
114
server/args.go
|
@ -16,42 +16,42 @@ const (
|
||||||
|
|
||||||
// Args struct contains the arguments to the hub server.
|
// Args struct contains the arguments to the hub server.
|
||||||
type Args struct {
|
type Args struct {
|
||||||
CmdType int
|
CmdType int
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port string
|
||||||
UDPPort string
|
EsHost string
|
||||||
EsHost string
|
EsPort string
|
||||||
EsPort string
|
PrometheusPort string
|
||||||
PrometheusPort string
|
EsIndex string
|
||||||
EsIndex string
|
RefreshDelta int
|
||||||
RefreshDelta int
|
CacheTTL int
|
||||||
CacheTTL int
|
PeerFile string
|
||||||
PeerFile string
|
Country string
|
||||||
Country string
|
DisableEs bool
|
||||||
DisableEs bool
|
Debug bool
|
||||||
Debug bool
|
DisableLoadPeers bool
|
||||||
LoadPeers bool
|
DisableStartPrometheus bool
|
||||||
StartPrometheus bool
|
DisableStartUDP bool
|
||||||
StartUDP bool
|
DisableWritePeers bool
|
||||||
WritePeers bool
|
DisableFederation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultHost = "0.0.0.0"
|
DefaultHost = "0.0.0.0"
|
||||||
DefaultPort = "50051"
|
DefaultPort = "50051"
|
||||||
DefaultUdpPort = "41119"
|
DefaultEsHost = "http://localhost"
|
||||||
DefaultEsHost = "http://localhost"
|
DefaultEsIndex = "claims"
|
||||||
DefaultEsIndex = "claims"
|
DefaultEsPort = "9200"
|
||||||
DefaultEsPort = "9200"
|
DefaultPrometheusPort = "2112"
|
||||||
DefaultPrometheusPort = "2112"
|
DefaultRefreshDelta = 5
|
||||||
DefaultRefreshDelta = 5
|
DefaultCacheTTL = 5
|
||||||
DefaultCacheTTL = 5
|
DefaultPeerFile = "peers.txt"
|
||||||
DefaultPeerFile = "peers.txt"
|
DefaultCountry = "US"
|
||||||
DefaultCountry = "US"
|
DefaultDisableLoadPeers = false
|
||||||
DefaultLoadPeers = true
|
DefaultDisableStartPrometheus = false
|
||||||
DefaultStartPrometheus = true
|
DefaultDisableStartUDP = false
|
||||||
DefaultStartUDP = true
|
DefaultDisableWritePeers = false
|
||||||
DefaultWritePeers = true
|
DefaultDisableFederation = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetEnvironment takes the environment variables as an array of strings
|
// GetEnvironment takes the environment variables as an array of strings
|
||||||
|
@ -88,7 +88,6 @@ func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
||||||
port := parser.String("", "rpcport", &argparse.Options{Required: false, Help: "RPC port", Default: DefaultPort})
|
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})
|
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})
|
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})
|
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})
|
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})
|
refreshDelta := parser.Int("", "refresh-delta", &argparse.Options{Required: false, Help: "elasticsearch index refresh delta in seconds", Default: DefaultRefreshDelta})
|
||||||
|
@ -98,10 +97,11 @@ func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
||||||
|
|
||||||
debug := parser.Flag("", "debug", &argparse.Options{Required: false, Help: "enable debug logging", Default: false})
|
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})
|
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})
|
disableLoadPeers := parser.Flag("", "disable-load-peers", &argparse.Options{Required: false, Help: "Disable load peers from disk at startup", Default: DefaultDisableLoadPeers})
|
||||||
startPrometheus := parser.Flag("", "start-prometheus", &argparse.Options{Required: false, Help: "Start prometheus server", Default: DefaultStartPrometheus})
|
disableStartPrometheus := parser.Flag("", "disable-start-prometheus", &argparse.Options{Required: false, Help: "Disable start prometheus server", Default: DefaultDisableStartPrometheus})
|
||||||
startUdp := parser.Flag("", "start-udp", &argparse.Options{Required: false, Help: "Start UDP ping server", Default: DefaultStartUDP})
|
disableStartUdp := parser.Flag("", "disable-start-udp", &argparse.Options{Required: false, Help: "Disable start UDP ping server", Default: DefaultDisableStartUDP})
|
||||||
writePeers := parser.Flag("", "write-peers", &argparse.Options{Required: false, Help: "Write peer to disk as we learn about them", Default: DefaultWritePeers})
|
disableWritePeers := parser.Flag("", "disable-write-peers", &argparse.Options{Required: false, Help: "Disable write peer to disk as we learn about them", Default: DefaultDisableWritePeers})
|
||||||
|
disableFederation := parser.Flag("", "disable-federation", &argparse.Options{Required: false, Help: "Disable server federation", Default: DefaultDisableFederation})
|
||||||
|
|
||||||
text := parser.String("", "text", &argparse.Options{Required: false, Help: "text query"})
|
text := parser.String("", "text", &argparse.Options{Required: false, Help: "text query"})
|
||||||
name := parser.String("", "name", &argparse.Options{Required: false, Help: "name"})
|
name := parser.String("", "name", &argparse.Options{Required: false, Help: "name"})
|
||||||
|
@ -120,24 +120,24 @@ func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
||||||
}
|
}
|
||||||
|
|
||||||
args := &Args{
|
args := &Args{
|
||||||
CmdType: SearchCmd,
|
CmdType: SearchCmd,
|
||||||
Host: *host,
|
Host: *host,
|
||||||
Port: *port,
|
Port: *port,
|
||||||
EsHost: *esHost,
|
EsHost: *esHost,
|
||||||
EsPort: *esPort,
|
EsPort: *esPort,
|
||||||
UDPPort: *udpPort,
|
PrometheusPort: *prometheusPort,
|
||||||
PrometheusPort: *prometheusPort,
|
EsIndex: *esIndex,
|
||||||
EsIndex: *esIndex,
|
RefreshDelta: *refreshDelta,
|
||||||
RefreshDelta: *refreshDelta,
|
CacheTTL: *cacheTTL,
|
||||||
CacheTTL: *cacheTTL,
|
PeerFile: *peerFile,
|
||||||
PeerFile: *peerFile,
|
Country: *country,
|
||||||
Country: *country,
|
DisableEs: *disableEs,
|
||||||
DisableEs: *disableEs,
|
Debug: *debug,
|
||||||
Debug: *debug,
|
DisableLoadPeers: *disableLoadPeers,
|
||||||
LoadPeers: *loadPeers,
|
DisableStartPrometheus: *disableStartPrometheus,
|
||||||
StartPrometheus: *startPrometheus,
|
DisableStartUDP: *disableStartUdp,
|
||||||
StartUDP: *startUdp,
|
DisableWritePeers: *disableWritePeers,
|
||||||
WritePeers: *writePeers,
|
DisableFederation: *disableFederation,
|
||||||
}
|
}
|
||||||
|
|
||||||
if esHost, ok := environment["ELASTIC_HOST"]; ok {
|
if esHost, ok := environment["ELASTIC_HOST"]; ok {
|
||||||
|
@ -157,7 +157,7 @@ func ParseArgs(searchRequest *pb.SearchRequest) *Args {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Verify no invalid argument combinations
|
Verify no invalid argument combinations
|
||||||
*/
|
*/
|
||||||
if len(*channelIds) > 0 && *channelId != "" {
|
if len(*channelIds) > 0 && *channelId != "" {
|
||||||
log.Fatal("Cannot specify both channel_id and channel_ids")
|
log.Fatal("Cannot specify both channel_id and channel_ids")
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -14,31 +16,31 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FederatedServer hold relevant information about peers that we known about.
|
// Peer holds relevant information about peers that we know about.
|
||||||
type FederatedServer struct {
|
type Peer struct {
|
||||||
Address string
|
Address string
|
||||||
Port string
|
Port string
|
||||||
Ts time.Time
|
LastSeen time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
localHosts = map[string]bool{
|
localHosts = map[string]bool{
|
||||||
"127.0.0.1": true,
|
"127.0.0.1": true,
|
||||||
"0.0.0.0": true,
|
"0.0.0.0": true,
|
||||||
"localhost": true,
|
"localhost": true,
|
||||||
|
"<nil>": true, // Empty net.IP turned into a string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// peerKey takes a peer and returns the key that for that peer
|
||||||
// peerKey takes a ServerMessage object and returns the key that for that peer
|
|
||||||
// in our peer table.
|
// in our peer table.
|
||||||
func peerKey(msg *pb.ServerMessage) string {
|
func peerKey(peer *Peer) string {
|
||||||
return msg.Address + ":" + msg.Port
|
return peer.Address + ":" + peer.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
// peerKey is a function on a FederatedServer struct to return the key for that
|
// peerKey is a function on a FederatedServer struct to return the key for that
|
||||||
// peer is out peer table.
|
// peer is out peer table.
|
||||||
func (peer *FederatedServer) peerKey() string {
|
func (peer *Peer) peerKey() string {
|
||||||
return peer.Address + ":" + peer.Port
|
return peer.Address + ":" + peer.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +68,19 @@ func (s *Server) getNumSubs() int64 {
|
||||||
return *s.NumPeerSubs
|
return *s.NumPeerSubs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAndSetExternalIp detects the server's external IP and stores it.
|
||||||
|
func (s *Server) getAndSetExternalIp(ip, port string) error {
|
||||||
|
pong, err := UDPPing(ip, port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
myIp := pong.DecodeAddress()
|
||||||
|
log.Println("my ip: ", myIp)
|
||||||
|
s.ExternalIP = myIp
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// loadPeers takes the arguments given to the hub at startup and loads the
|
// loadPeers takes the arguments given to the hub at startup and loads the
|
||||||
// previously known peers from disk and verifies their existence before
|
// previously known peers from disk and verifies their existence before
|
||||||
// storing them as known peers. Returns a map of peerKey -> object
|
// storing them as known peers. Returns a map of peerKey -> object
|
||||||
|
@ -73,6 +88,32 @@ func (s *Server) loadPeers() error {
|
||||||
peerFile := s.Args.PeerFile
|
peerFile := s.Args.PeerFile
|
||||||
port := s.Args.Port
|
port := s.Args.Port
|
||||||
|
|
||||||
|
// First we make sure our server has come up, so we can answer back to peers.
|
||||||
|
var failures = 0
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
retry:
|
||||||
|
time.Sleep(time.Second * time.Duration(math.Pow(float64(failures), 2)))
|
||||||
|
conn, err := grpc.DialContext(ctx,
|
||||||
|
"0.0.0.0:"+port,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithBlock(),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if failures > 3 {
|
||||||
|
log.Println("Warning! Our endpoint doesn't seem to have come up, didn't load peers")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
failures += 1
|
||||||
|
goto retry
|
||||||
|
}
|
||||||
|
if err = conn.Close(); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
cancel()
|
||||||
|
|
||||||
f, err := os.Open(peerFile)
|
f, err := os.Open(peerFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -90,26 +131,30 @@ func (s *Server) loadPeers() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, line := range text {
|
for _, line := range text {
|
||||||
ipPort := strings.Split(line,":")
|
ipPort := strings.Split(line, ":")
|
||||||
if len(ipPort) != 2 {
|
if len(ipPort) != 2 {
|
||||||
log.Println("Malformed entry in peer file")
|
log.Println("Malformed entry in peer file")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// If the peer is us, skip
|
// If the peer is us, skip
|
||||||
log.Println(ipPort)
|
log.Println(ipPort)
|
||||||
if ipPort[1] == port && localHosts[ipPort[0]] {
|
if ipPort[1] == port &&
|
||||||
|
(localHosts[ipPort[0]] || ipPort[0] == s.ExternalIP.String()) {
|
||||||
log.Println("Self peer, skipping ...")
|
log.Println("Self peer, skipping ...")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
srvMsg := &pb.ServerMessage{
|
|
||||||
Address: ipPort[0],
|
newPeer := &Peer{
|
||||||
Port: ipPort[1],
|
Address: ipPort[0],
|
||||||
|
Port: ipPort[1],
|
||||||
|
LastSeen: time.Now(),
|
||||||
}
|
}
|
||||||
log.Printf("pinging peer %+v\n", srvMsg)
|
log.Printf("pinging peer %+v\n", newPeer)
|
||||||
err := s.addPeer(srvMsg, true)
|
err = s.addPeer(newPeer, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Returning from loadPeers")
|
log.Println("Returning from loadPeers")
|
||||||
|
@ -118,7 +163,7 @@ func (s *Server) loadPeers() error {
|
||||||
|
|
||||||
// subscribeToPeer subscribes us to a peer to we'll get updates about their
|
// subscribeToPeer subscribes us to a peer to we'll get updates about their
|
||||||
// known peers.
|
// known peers.
|
||||||
func (s *Server) subscribeToPeer(peer *FederatedServer) error {
|
func (s *Server) subscribeToPeer(peer *Peer) error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -133,20 +178,18 @@ func (s *Server) subscribeToPeer(peer *FederatedServer) error {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
msg := &pb.ServerMessage{
|
msg := &pb.ServerMessage{
|
||||||
Address: s.Args.Host,
|
Address: s.ExternalIP.String(),
|
||||||
Port: s.Args.Port,
|
Port: s.Args.Port,
|
||||||
}
|
}
|
||||||
|
|
||||||
c := pb.NewHubClient(conn)
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
log.Printf("%s:%s subscribing to %+v\n", s.Args.Host, s.Args.Port, peer)
|
log.Printf("%s:%s subscribing to %+v\n", s.ExternalIP, s.Args.Port, peer)
|
||||||
_, err = c.PeerSubscribe(ctx, msg)
|
_, err = c.PeerSubscribe(ctx, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Subscribed = true
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,13 +198,13 @@ func (s *Server) subscribeToPeer(peer *FederatedServer) error {
|
||||||
// This is used to confirm existence of peers on start and let them
|
// This is used to confirm existence of peers on start and let them
|
||||||
// know about us. Returns the response from the server on success,
|
// know about us. Returns the response from the server on success,
|
||||||
// nil otherwise.
|
// nil otherwise.
|
||||||
func (s *Server) helloPeer(server *FederatedServer) (*pb.HelloMessage, error) {
|
func (s *Server) helloPeer(peer *Peer) (*pb.HelloMessage, error) {
|
||||||
log.Println("In helloPeer")
|
log.Println("In helloPeer")
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
conn, err := grpc.DialContext(ctx,
|
conn, err := grpc.DialContext(ctx,
|
||||||
server.Address+":"+server.Port,
|
peer.Address+":"+peer.Port,
|
||||||
grpc.WithInsecure(),
|
grpc.WithInsecure(),
|
||||||
grpc.WithBlock(),
|
grpc.WithBlock(),
|
||||||
)
|
)
|
||||||
|
@ -174,12 +217,12 @@ func (s *Server) helloPeer(server *FederatedServer) (*pb.HelloMessage, error) {
|
||||||
c := pb.NewHubClient(conn)
|
c := pb.NewHubClient(conn)
|
||||||
|
|
||||||
msg := &pb.HelloMessage{
|
msg := &pb.HelloMessage{
|
||||||
Port: s.Args.Port,
|
Port: s.Args.Port,
|
||||||
Host: s.Args.Host,
|
Host: s.ExternalIP.String(),
|
||||||
Servers: []*pb.ServerMessage{},
|
Servers: []*pb.ServerMessage{},
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("%s:%s saying hello to %+v\n", s.Args.Host, s.Args.Port, server)
|
log.Printf("%s:%s saying hello to %+v\n", s.ExternalIP, s.Args.Port, peer)
|
||||||
res, err := c.Hello(ctx, msg)
|
res, err := c.Hello(ctx, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -193,7 +236,7 @@ func (s *Server) helloPeer(server *FederatedServer) (*pb.HelloMessage, error) {
|
||||||
|
|
||||||
// writePeers writes our current known peers to disk.
|
// writePeers writes our current known peers to disk.
|
||||||
func (s *Server) writePeers() {
|
func (s *Server) writePeers() {
|
||||||
if !s.Args.WritePeers {
|
if s.Args.DisableWritePeers {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f, err := os.Create(s.Args.PeerFile)
|
f, err := os.Create(s.Args.PeerFile)
|
||||||
|
@ -222,8 +265,11 @@ func (s *Server) writePeers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// notifyPeer takes a peer to notify and a new peer we just learned about
|
// notifyPeer takes a peer to notify and a new peer we just learned about
|
||||||
// and calls AddPeer on the first.
|
// and informs the already known peer about the new peer.
|
||||||
func notifyPeer(peerToNotify *FederatedServer, newPeer *FederatedServer) error {
|
func (s *Server) notifyPeer(peerToNotify *Peer, newPeer *Peer) error {
|
||||||
|
if s.Args.DisableFederation {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -254,12 +300,12 @@ func notifyPeer(peerToNotify *FederatedServer, newPeer *FederatedServer) error {
|
||||||
|
|
||||||
// notifyPeerSubs takes a new peer server we just learned about and notifies
|
// notifyPeerSubs takes a new peer server we just learned about and notifies
|
||||||
// all the peers that have subscribed to us about it.
|
// all the peers that have subscribed to us about it.
|
||||||
func (s *Server) notifyPeerSubs(newServer *FederatedServer) {
|
func (s *Server) notifyPeerSubs(newPeer *Peer) {
|
||||||
var unsubscribe []string
|
var unsubscribe []string
|
||||||
s.PeerSubsMut.RLock()
|
s.PeerSubsMut.RLock()
|
||||||
for key, peer := range s.PeerSubs {
|
for key, peer := range s.PeerSubs {
|
||||||
log.Printf("Notifying peer %s of new node %+v\n", key, newServer)
|
log.Printf("Notifying peer %s of new node %+v\n", key, newPeer)
|
||||||
err := notifyPeer(peer, newServer)
|
err := s.notifyPeer(peer, newPeer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Failed to send data to ", key)
|
log.Println("Failed to send data to ", key)
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -279,25 +325,36 @@ func (s *Server) notifyPeerSubs(newServer *FederatedServer) {
|
||||||
s.PeerSubsMut.Unlock()
|
s.PeerSubsMut.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// addPeer takes a new peer as a pb.ServerMessage, optionally checks to see
|
// addPeer takes a new peer, optionally checks to see if they're online, and
|
||||||
// if they're online, and adds them to our list of peer. If we're not currently
|
// adds them to our list of peers. It will also optionally subscribe to it.
|
||||||
// subscribed to a peer, it will also subscribe to it.
|
func (s *Server) addPeer(newPeer *Peer, ping bool, subscribe bool) error {
|
||||||
func (s *Server) addPeer(msg *pb.ServerMessage, ping bool) error {
|
if s.Args.DisableFederation {
|
||||||
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
|
return nil
|
||||||
}
|
}
|
||||||
k := peerKey(msg)
|
// First thing we get our external ip if we don't have it, otherwise we
|
||||||
newServer := &FederatedServer{
|
// could end up subscribed to our self, which is silly.
|
||||||
Address: msg.Address,
|
nilIP := net.IP{}
|
||||||
Port: msg.Port,
|
localIP1 := net.IPv4(127, 0, 0, 1)
|
||||||
Ts: time.Now(),
|
if s.ExternalIP.Equal(nilIP) || s.ExternalIP.Equal(localIP1) {
|
||||||
|
err := s.getAndSetExternalIp(newPeer.Address, newPeer.Port)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
log.Println("WARNING: can't determine external IP, continuing with ", s.Args.Host)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Printf("%s:%s adding peer %+v\n", s.Args.Host, s.Args.Port, msg)
|
|
||||||
if oldServer, loaded := s.PeerServersLoadOrStore(newServer); !loaded {
|
if s.Args.Port == newPeer.Port &&
|
||||||
|
(localHosts[newPeer.Address] || newPeer.Address == s.ExternalIP.String()) {
|
||||||
|
log.Printf("%s:%s addPeer: Self peer, skipping...\n", s.ExternalIP, s.Args.Port)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
k := peerKey(newPeer)
|
||||||
|
|
||||||
|
log.Printf("%s:%s adding peer %+v\n", s.ExternalIP, s.Args.Port, newPeer)
|
||||||
|
if oldServer, loaded := s.PeerServersLoadOrStore(newPeer); !loaded {
|
||||||
if ping {
|
if ping {
|
||||||
_, err := s.helloPeer(newServer)
|
_, err := s.helloPeer(newPeer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.PeerServersMut.Lock()
|
s.PeerServersMut.Lock()
|
||||||
delete(s.PeerServers, k)
|
delete(s.PeerServers, k)
|
||||||
|
@ -309,26 +366,31 @@ func (s *Server) addPeer(msg *pb.ServerMessage, ping bool) error {
|
||||||
s.incNumPeers()
|
s.incNumPeers()
|
||||||
metrics.PeersKnown.Inc()
|
metrics.PeersKnown.Inc()
|
||||||
s.writePeers()
|
s.writePeers()
|
||||||
s.notifyPeerSubs(newServer)
|
s.notifyPeerSubs(newPeer)
|
||||||
|
|
||||||
// Subscribe to all our peers for now
|
// Subscribe to all our peers for now
|
||||||
err := s.subscribeToPeer(newServer)
|
if subscribe {
|
||||||
if err != nil {
|
err := s.subscribeToPeer(newPeer)
|
||||||
return err
|
if err != nil {
|
||||||
} else {
|
return err
|
||||||
s.Subscribed = true
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oldServer.Ts = time.Now()
|
oldServer.LastSeen = time.Now()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// mergeFederatedServers is an internal convenience function to add a list of
|
// mergePeers is an internal convenience function to add a list of
|
||||||
// peers.
|
// peers.
|
||||||
func (s *Server) mergeFederatedServers(servers []*pb.ServerMessage) {
|
func (s *Server) mergePeers(servers []*pb.ServerMessage) {
|
||||||
for _, srvMsg := range servers {
|
for _, srvMsg := range servers {
|
||||||
err := s.addPeer(srvMsg, false)
|
newPeer := &Peer{
|
||||||
|
Address: srvMsg.Address,
|
||||||
|
Port: srvMsg.Port,
|
||||||
|
LastSeen: time.Now(),
|
||||||
|
}
|
||||||
|
err := s.addPeer(newPeer, false, true)
|
||||||
// This shouldn't happen because we're not pinging them.
|
// This shouldn't happen because we're not pinging them.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -345,14 +407,14 @@ func (s *Server) makeHelloMessage() *pb.HelloMessage {
|
||||||
for _, peer := range s.PeerServers {
|
for _, peer := range s.PeerServers {
|
||||||
servers = append(servers, &pb.ServerMessage{
|
servers = append(servers, &pb.ServerMessage{
|
||||||
Address: peer.Address,
|
Address: peer.Address,
|
||||||
Port: peer.Port,
|
Port: peer.Port,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
s.PeerServersMut.RUnlock()
|
s.PeerServersMut.RUnlock()
|
||||||
|
|
||||||
return &pb.HelloMessage{
|
return &pb.HelloMessage{
|
||||||
Port: s.Args.Port,
|
Port: s.Args.Port,
|
||||||
Host: s.Args.Host,
|
Host: s.ExternalIP.String(),
|
||||||
Servers: servers,
|
Servers: servers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -44,24 +45,23 @@ func removeFile(fileName string) {
|
||||||
|
|
||||||
func makeDefaultArgs() *Args {
|
func makeDefaultArgs() *Args {
|
||||||
args := &Args{
|
args := &Args{
|
||||||
CmdType: ServeCmd,
|
CmdType: ServeCmd,
|
||||||
Host: DefaultHost,
|
Host: DefaultHost,
|
||||||
Port: DefaultPort,
|
Port: DefaultPort,
|
||||||
EsHost: DefaultEsHost,
|
EsHost: DefaultEsHost,
|
||||||
EsPort: DefaultEsPort,
|
EsPort: DefaultEsPort,
|
||||||
UDPPort: DefaultUdpPort,
|
PrometheusPort: DefaultPrometheusPort,
|
||||||
PrometheusPort: DefaultPrometheusPort,
|
EsIndex: DefaultEsIndex,
|
||||||
EsIndex: DefaultEsIndex,
|
RefreshDelta: DefaultRefreshDelta,
|
||||||
RefreshDelta: DefaultRefreshDelta,
|
CacheTTL: DefaultCacheTTL,
|
||||||
CacheTTL: DefaultCacheTTL,
|
PeerFile: DefaultPeerFile,
|
||||||
PeerFile: DefaultPeerFile,
|
Country: DefaultCountry,
|
||||||
Country: DefaultCountry,
|
DisableEs: true,
|
||||||
DisableEs: true,
|
Debug: true,
|
||||||
Debug: true,
|
DisableLoadPeers: true,
|
||||||
LoadPeers: false,
|
DisableStartPrometheus: true,
|
||||||
StartPrometheus: false,
|
DisableStartUDP: true,
|
||||||
StartUDP: false,
|
DisableWritePeers: true,
|
||||||
WritePeers: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
@ -75,7 +75,7 @@ func TestAddPeer(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
want int
|
want int
|
||||||
} {
|
}{
|
||||||
{
|
{
|
||||||
name: "Add 10 peers",
|
name: "Add 10 peers",
|
||||||
want: 10,
|
want: 10,
|
||||||
|
@ -87,27 +87,27 @@ func TestAddPeer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T){
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
server := MakeHubServer(ctx, args)
|
server := MakeHubServer(ctx, args)
|
||||||
server.Subscribed = true
|
server.ExternalIP = net.IPv4(0, 0, 0, 0)
|
||||||
metrics.PeersKnown.Set(0)
|
metrics.PeersKnown.Set(0)
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
var msg *pb.ServerMessage
|
var peer *Peer
|
||||||
if strings.Contains(tt.name, "1 unique") {
|
if strings.Contains(tt.name, "1 unique") {
|
||||||
msg = &pb.ServerMessage{
|
peer = &Peer{
|
||||||
Address: "1.1.1.1",
|
Address: "1.1.1.1",
|
||||||
Port: "50051",
|
Port: "50051",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x := i + 1
|
x := i + 1
|
||||||
msg = &pb.ServerMessage{
|
peer = &Peer{
|
||||||
Address: fmt.Sprintf("%d.%d.%d.%d", x, x, x, x),
|
Address: fmt.Sprintf("%d.%d.%d.%d", x, x, x, x),
|
||||||
Port: "50051",
|
Port: "50051",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//log.Printf("Adding peer %+v\n", msg)
|
//log.Printf("Adding peer %+v\n", msg)
|
||||||
err := server.addPeer(msg, false)
|
err := server.addPeer(peer, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
@ -129,12 +129,12 @@ func TestAddPeer(t *testing.T) {
|
||||||
func TestPeerWriter(t *testing.T) {
|
func TestPeerWriter(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
args := makeDefaultArgs()
|
args := makeDefaultArgs()
|
||||||
args.WritePeers = true
|
args.DisableWritePeers = false
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
want int
|
want int
|
||||||
} {
|
}{
|
||||||
{
|
{
|
||||||
name: "Add 10 peers",
|
name: "Add 10 peers",
|
||||||
want: 10,
|
want: 10,
|
||||||
|
@ -146,26 +146,26 @@ func TestPeerWriter(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T){
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
server := MakeHubServer(ctx, args)
|
server := MakeHubServer(ctx, args)
|
||||||
server.Subscribed = true
|
server.ExternalIP = net.IPv4(0, 0, 0, 0)
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
var msg *pb.ServerMessage
|
var peer *Peer
|
||||||
if strings.Contains(tt.name, "1 unique") {
|
if strings.Contains(tt.name, "1 unique") {
|
||||||
msg = &pb.ServerMessage{
|
peer = &Peer{
|
||||||
Address: "1.1.1.1",
|
Address: "1.1.1.1",
|
||||||
Port: "50051",
|
Port: "50051",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x := i + 1
|
x := i + 1
|
||||||
msg = &pb.ServerMessage{
|
peer = &Peer{
|
||||||
Address: fmt.Sprintf("%d.%d.%d.%d", x, x, x, x),
|
Address: fmt.Sprintf("%d.%d.%d.%d", x, x, x, x),
|
||||||
Port: "50051",
|
Port: "50051",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//log.Printf("Adding peer %+v\n", msg)
|
//log.Printf("Adding peer %+v\n", peer)
|
||||||
err := server.addPeer(msg, false)
|
err := server.addPeer(peer, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
@ -188,12 +188,11 @@ func TestAddPeerEndpoint(t *testing.T) {
|
||||||
args2 := makeDefaultArgs()
|
args2 := makeDefaultArgs()
|
||||||
args2.Port = "50052"
|
args2.Port = "50052"
|
||||||
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
wantServerOne int64
|
wantServerOne int64
|
||||||
wantServerTwo int64
|
wantServerTwo int64
|
||||||
} {
|
}{
|
||||||
{
|
{
|
||||||
// outside -> server1.AddPeer(server2, ping=true) : server1 = 1, server2 = 0
|
// outside -> server1.AddPeer(server2, ping=true) : server1 = 1, server2 = 0
|
||||||
// server1 -> server2.Hello(server1) : server1 = 1, server2 = 0
|
// server1 -> server2.Hello(server1) : server1 = 1, server2 = 0
|
||||||
|
@ -204,14 +203,14 @@ func TestAddPeerEndpoint(t *testing.T) {
|
||||||
// server1 -> server2.AddPeer(server2) : server1 = 1, server2 = 1
|
// server1 -> server2.AddPeer(server2) : server1 = 1, server2 = 1
|
||||||
// server2 self peer, skipping : server1 = 1, server2 = 1
|
// server2 self peer, skipping : server1 = 1, server2 = 1
|
||||||
// server1 -> server2.PeerSubscribe(server1) : server1 = 1, server2 = 1
|
// server1 -> server2.PeerSubscribe(server1) : server1 = 1, server2 = 1
|
||||||
name: "Add 1 peer",
|
name: "Add 1 peer",
|
||||||
wantServerOne: 1,
|
wantServerOne: 1,
|
||||||
wantServerTwo: 1,
|
wantServerTwo: 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T){
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
server := MakeHubServer(ctx, args)
|
server := MakeHubServer(ctx, args)
|
||||||
server2 := MakeHubServer(ctx, args2)
|
server2 := MakeHubServer(ctx, args2)
|
||||||
metrics.PeersKnown.Set(0)
|
metrics.PeersKnown.Set(0)
|
||||||
|
@ -262,15 +261,14 @@ func TestAddPeerEndpoint2(t *testing.T) {
|
||||||
args2.Port = "50052"
|
args2.Port = "50052"
|
||||||
args3.Port = "50053"
|
args3.Port = "50053"
|
||||||
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
wantServerOne int64
|
wantServerOne int64
|
||||||
wantServerTwo int64
|
wantServerTwo int64
|
||||||
wantServerThree int64
|
wantServerThree int64
|
||||||
} {
|
}{
|
||||||
{
|
{
|
||||||
name: "Add 2 peers",
|
name: "Add 2 peers",
|
||||||
wantServerOne: 2,
|
wantServerOne: 2,
|
||||||
wantServerTwo: 2,
|
wantServerTwo: 2,
|
||||||
wantServerThree: 2,
|
wantServerThree: 2,
|
||||||
|
@ -278,7 +276,7 @@ func TestAddPeerEndpoint2(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T){
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
server := MakeHubServer(ctx, args)
|
server := MakeHubServer(ctx, args)
|
||||||
server2 := MakeHubServer(ctx, args2)
|
server2 := MakeHubServer(ctx, args2)
|
||||||
server3 := MakeHubServer(ctx, args3)
|
server3 := MakeHubServer(ctx, args3)
|
||||||
|
@ -335,7 +333,6 @@ func TestAddPeerEndpoint2(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TestAddPeerEndpoint3 tests the ability to add peers
|
// TestAddPeerEndpoint3 tests the ability to add peers
|
||||||
func TestAddPeerEndpoint3(t *testing.T) {
|
func TestAddPeerEndpoint3(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
@ -345,15 +342,14 @@ func TestAddPeerEndpoint3(t *testing.T) {
|
||||||
args2.Port = "50052"
|
args2.Port = "50052"
|
||||||
args3.Port = "50053"
|
args3.Port = "50053"
|
||||||
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
wantServerOne int64
|
wantServerOne int64
|
||||||
wantServerTwo int64
|
wantServerTwo int64
|
||||||
wantServerThree int64
|
wantServerThree int64
|
||||||
} {
|
}{
|
||||||
{
|
{
|
||||||
name: "Add 1 peer to each",
|
name: "Add 1 peer to each",
|
||||||
wantServerOne: 2,
|
wantServerOne: 2,
|
||||||
wantServerTwo: 2,
|
wantServerTwo: 2,
|
||||||
wantServerThree: 2,
|
wantServerThree: 2,
|
||||||
|
@ -361,7 +357,7 @@ func TestAddPeerEndpoint3(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T){
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
server := MakeHubServer(ctx, args)
|
server := MakeHubServer(ctx, args)
|
||||||
server2 := MakeHubServer(ctx, args2)
|
server2 := MakeHubServer(ctx, args2)
|
||||||
server3 := MakeHubServer(ctx, args3)
|
server3 := MakeHubServer(ctx, args3)
|
||||||
|
@ -425,3 +421,58 @@ func TestAddPeerEndpoint3(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestAddPeer tests the ability to add peers
|
||||||
|
func TestUDPServer(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
args := makeDefaultArgs()
|
||||||
|
args.DisableStartUDP = false
|
||||||
|
args2 := makeDefaultArgs()
|
||||||
|
args2.Port = "50052"
|
||||||
|
args2.DisableStartUDP = false
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "hubs server external ip",
|
||||||
|
want: "127.0.0.1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
server := MakeHubServer(ctx, args)
|
||||||
|
server2 := MakeHubServer(ctx, args2)
|
||||||
|
go server.Run()
|
||||||
|
go server2.Run()
|
||||||
|
metrics.PeersKnown.Set(0)
|
||||||
|
|
||||||
|
peer := &Peer{
|
||||||
|
Address: "0.0.0.0",
|
||||||
|
Port: "50052",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := server.addPeer(peer, true, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.GrpcServer.GracefulStop()
|
||||||
|
server2.GrpcServer.GracefulStop()
|
||||||
|
|
||||||
|
got1 := server.ExternalIP.String()
|
||||||
|
if got1 != tt.want {
|
||||||
|
t.Errorf("server.ExternalIP = %s, want %s\n", got1, tt.want)
|
||||||
|
t.Errorf("server.Args.Port = %s\n", server.Args.Port)
|
||||||
|
}
|
||||||
|
got2 := server2.ExternalIP.String()
|
||||||
|
if got2 != tt.want {
|
||||||
|
t.Errorf("server2.ExternalIP = %s, want %s\n", got2, tt.want)
|
||||||
|
t.Errorf("server2.Args.Port = %s\n", server2.Args.Port)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -275,16 +275,16 @@ func (s *Server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.Outputs,
|
||||||
setPageVars(in, &pageSize, &from)
|
setPageVars(in, &pageSize, &from)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
cache based on search request params
|
cache based on search request params
|
||||||
include from value and number of results.
|
include from value and number of results.
|
||||||
When another search request comes in with same search params
|
When another search request comes in with same search params
|
||||||
and same or increased offset (which we currently don't even use?)
|
and same or increased offset (which we currently don't even use?)
|
||||||
that will be a cache hit.
|
that will be a cache hit.
|
||||||
FIXME: For now the cache is turned off when in debugging mode
|
FIXME: For now the cache is turned off when in debugging mode
|
||||||
(for unit tests) because it breaks on some of them.
|
(for unit tests) because it breaks on some of them.
|
||||||
FIXME: Currently the cache just skips the initial search,
|
FIXME: Currently the cache just skips the initial search,
|
||||||
the mgets and post processing are still done. There's probably
|
the mgets and post processing are still done. There's probably
|
||||||
a more efficient way to store the final result.
|
a more efficient way to store the final result.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if val, err := s.QueryCache.Get(cacheKey); err != nil {
|
if val, err := s.QueryCache.Get(cacheKey); err != nil {
|
||||||
|
@ -518,15 +518,15 @@ func (s *Server) setupEsQuery(
|
||||||
}
|
}
|
||||||
|
|
||||||
replacements := map[string]string{
|
replacements := map[string]string{
|
||||||
"name": "normalized_name",
|
"name": "normalized_name",
|
||||||
"normalized": "normalized_name",
|
"normalized": "normalized_name",
|
||||||
"claim_name": "normalized_name",
|
"claim_name": "normalized_name",
|
||||||
"txid": "tx_id",
|
"txid": "tx_id",
|
||||||
"nout": "tx_nout",
|
"nout": "tx_nout",
|
||||||
"reposted": "repost_count",
|
"reposted": "repost_count",
|
||||||
"valid_channel_signature": "is_signature_valid",
|
"valid_channel_signature": "is_signature_valid",
|
||||||
"claim_id": "_id",
|
"claim_id": "_id",
|
||||||
"signature_digest": "signature",
|
"signature_digest": "signature",
|
||||||
}
|
}
|
||||||
|
|
||||||
textFields := map[string]bool{
|
textFields := map[string]bool{
|
||||||
|
@ -967,4 +967,3 @@ func removeBlocked(searchHits []*record) ([]*record, []*record, map[string]*pb.B
|
||||||
|
|
||||||
return newHits, blockedHits, blockedChannels
|
return newHits, blockedHits, blockedChannels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,17 +35,16 @@ type Server struct {
|
||||||
LastRefreshCheck time.Time
|
LastRefreshCheck time.Time
|
||||||
RefreshDelta time.Duration
|
RefreshDelta time.Duration
|
||||||
NumESRefreshes int64
|
NumESRefreshes int64
|
||||||
PeerServers map[string]*FederatedServer
|
PeerServers map[string]*Peer
|
||||||
PeerServersMut sync.RWMutex
|
PeerServersMut sync.RWMutex
|
||||||
NumPeerServers *int64
|
NumPeerServers *int64
|
||||||
PeerSubs map[string]*FederatedServer
|
PeerSubs map[string]*Peer
|
||||||
PeerSubsMut sync.RWMutex
|
PeerSubsMut sync.RWMutex
|
||||||
NumPeerSubs *int64
|
NumPeerSubs *int64
|
||||||
Subscribed bool
|
ExternalIP net.IP
|
||||||
pb.UnimplementedHubServer
|
pb.UnimplementedHubServer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func getVersion() string {
|
func getVersion() string {
|
||||||
return meta.Version
|
return meta.Version
|
||||||
}
|
}
|
||||||
|
@ -89,7 +88,7 @@ func getVersion() string {
|
||||||
'blockchain.address.unsubscribe'
|
'blockchain.address.unsubscribe'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (s *Server) PeerSubsLoadOrStore(peer *FederatedServer) (actual *FederatedServer, loaded bool) {
|
func (s *Server) PeerSubsLoadOrStore(peer *Peer) (actual *Peer, loaded bool) {
|
||||||
key := peer.peerKey()
|
key := peer.peerKey()
|
||||||
s.PeerSubsMut.RLock()
|
s.PeerSubsMut.RLock()
|
||||||
if actual, ok := s.PeerSubs[key]; ok {
|
if actual, ok := s.PeerSubs[key]; ok {
|
||||||
|
@ -104,7 +103,7 @@ func (s *Server) PeerSubsLoadOrStore(peer *FederatedServer) (actual *FederatedSe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PeerServersLoadOrStore(peer *FederatedServer) (actual *FederatedServer, loaded bool) {
|
func (s *Server) PeerServersLoadOrStore(peer *Peer) (actual *Peer, loaded bool) {
|
||||||
key := peer.peerKey()
|
key := peer.peerKey()
|
||||||
s.PeerServersMut.RLock()
|
s.PeerServersMut.RLock()
|
||||||
if actual, ok := s.PeerServers[key]; ok {
|
if actual, ok := s.PeerServers[key]; ok {
|
||||||
|
@ -196,20 +195,20 @@ func MakeHubServer(ctx context.Context, args *Args) *Server {
|
||||||
LastRefreshCheck: time.Now(),
|
LastRefreshCheck: time.Now(),
|
||||||
RefreshDelta: refreshDelta,
|
RefreshDelta: refreshDelta,
|
||||||
NumESRefreshes: 0,
|
NumESRefreshes: 0,
|
||||||
PeerServers: make(map[string]*FederatedServer),
|
PeerServers: make(map[string]*Peer),
|
||||||
PeerServersMut: sync.RWMutex{},
|
PeerServersMut: sync.RWMutex{},
|
||||||
NumPeerServers: numPeers,
|
NumPeerServers: numPeers,
|
||||||
PeerSubs: make(map[string]*FederatedServer),
|
PeerSubs: make(map[string]*Peer),
|
||||||
PeerSubsMut: sync.RWMutex{},
|
PeerSubsMut: sync.RWMutex{},
|
||||||
NumPeerSubs: numSubs,
|
NumPeerSubs: numSubs,
|
||||||
Subscribed: false,
|
ExternalIP: net.IPv4(127, 0, 0, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start up our background services
|
// Start up our background services
|
||||||
if args.StartPrometheus {
|
if !args.DisableStartPrometheus {
|
||||||
go s.prometheusEndpoint(s.Args.PrometheusPort, "metrics")
|
go s.prometheusEndpoint(s.Args.PrometheusPort, "metrics")
|
||||||
}
|
}
|
||||||
if args.StartUDP {
|
if !args.DisableStartUDP {
|
||||||
go func() {
|
go func() {
|
||||||
err := UDPServer(args)
|
err := UDPServer(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -218,11 +217,13 @@ func MakeHubServer(ctx context.Context, args *Args) *Server {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
// Load peers from disk and subscribe to one if there are any
|
// Load peers from disk and subscribe to one if there are any
|
||||||
if args.LoadPeers {
|
if !args.DisableLoadPeers {
|
||||||
err = s.loadPeers()
|
go func() {
|
||||||
if err != nil {
|
err := s.loadPeers()
|
||||||
log.Println(err)
|
if err != nil {
|
||||||
}
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
@ -244,21 +245,21 @@ func (s *Server) Hello(ctx context.Context, args *pb.HelloMessage) (*pb.HelloMes
|
||||||
metrics.RequestsCount.With(prometheus.Labels{"method": "hello"}).Inc()
|
metrics.RequestsCount.With(prometheus.Labels{"method": "hello"}).Inc()
|
||||||
port := args.Port
|
port := args.Port
|
||||||
host := args.Host
|
host := args.Host
|
||||||
server := &FederatedServer{
|
newPeer := &Peer{
|
||||||
Address: host,
|
Address: host,
|
||||||
Port: port,
|
Port: port,
|
||||||
Ts: time.Now(),
|
LastSeen: time.Now(),
|
||||||
}
|
}
|
||||||
log.Println(server)
|
log.Println(newPeer)
|
||||||
|
|
||||||
err := s.addPeer(&pb.ServerMessage{Address: host, Port: port}, false)
|
err := s.addPeer(newPeer, false, true)
|
||||||
// They just contacted us, so this shouldn't happen
|
// They just contacted us, so this shouldn't happen
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
s.mergeFederatedServers(args.Servers)
|
s.mergePeers(args.Servers)
|
||||||
s.writePeers()
|
s.writePeers()
|
||||||
s.notifyPeerSubs(server)
|
s.notifyPeerSubs(newPeer)
|
||||||
|
|
||||||
return s.makeHelloMessage(), nil
|
return s.makeHelloMessage(), nil
|
||||||
}
|
}
|
||||||
|
@ -268,10 +269,10 @@ func (s *Server) Hello(ctx context.Context, args *pb.HelloMessage) (*pb.HelloMes
|
||||||
func (s *Server) PeerSubscribe(ctx context.Context, in *pb.ServerMessage) (*pb.StringValue, error) {
|
func (s *Server) PeerSubscribe(ctx context.Context, in *pb.ServerMessage) (*pb.StringValue, error) {
|
||||||
metrics.RequestsCount.With(prometheus.Labels{"method": "peer_subscribe"}).Inc()
|
metrics.RequestsCount.With(prometheus.Labels{"method": "peer_subscribe"}).Inc()
|
||||||
var msg = "Success"
|
var msg = "Success"
|
||||||
peer := &FederatedServer{
|
peer := &Peer{
|
||||||
Address: in.Address,
|
Address: in.Address,
|
||||||
Port: in.Port,
|
Port: in.Port,
|
||||||
Ts: time.Now(),
|
LastSeen: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, loaded := s.PeerSubsLoadOrStore(peer); !loaded {
|
if _, loaded := s.PeerSubsLoadOrStore(peer); !loaded {
|
||||||
|
@ -288,7 +289,12 @@ func (s *Server) PeerSubscribe(ctx context.Context, in *pb.ServerMessage) (*pb.S
|
||||||
func (s *Server) AddPeer(ctx context.Context, args *pb.ServerMessage) (*pb.StringValue, error) {
|
func (s *Server) AddPeer(ctx context.Context, args *pb.ServerMessage) (*pb.StringValue, error) {
|
||||||
metrics.RequestsCount.With(prometheus.Labels{"method": "add_peer"}).Inc()
|
metrics.RequestsCount.With(prometheus.Labels{"method": "add_peer"}).Inc()
|
||||||
var msg = "Success"
|
var msg = "Success"
|
||||||
err := s.addPeer(args, true)
|
newPeer := &Peer{
|
||||||
|
Address: args.Address,
|
||||||
|
Port: args.Port,
|
||||||
|
LastSeen: time.Now(),
|
||||||
|
}
|
||||||
|
err := s.addPeer(newPeer, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
msg = "Failed"
|
msg = "Failed"
|
||||||
|
|
|
@ -2,19 +2,25 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
pb "github.com/lbryio/hub/protobuf/go"
|
||||||
"github.com/lbryio/lbry.go/v2/extras/errors"
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxBufferSize = 1024
|
const maxBufferSize = 1024
|
||||||
|
|
||||||
// genesis blocktime (which is actually wrong)
|
// genesis blocktime (which is actually wrong)
|
||||||
const magic = 1446058291
|
// magic constant for the UDPPing protocol. The above comment is taken from
|
||||||
|
// the python code this was implemented off of.
|
||||||
|
// https://github.com/lbryio/lbry-sdk/blob/7d49b046d44a4b7067d5dc1d6cd65ff0475c71c8/lbry/wallet/server/udp.py#L12
|
||||||
|
const magic = 1446058291
|
||||||
const protocolVersion = 1
|
const protocolVersion = 1
|
||||||
|
const defaultFlags = 0b00000000
|
||||||
|
const availableFlag = 0b00000001
|
||||||
|
|
||||||
// SPVPing is a struct for the format of how to ping another hub over udp.
|
// SPVPing is a struct for the format of how to ping another hub over udp.
|
||||||
// format b'!lB64s'
|
// format b'!lB64s'
|
||||||
|
@ -31,7 +37,7 @@ type SPVPong struct {
|
||||||
flags byte
|
flags byte
|
||||||
height uint32
|
height uint32
|
||||||
tip []byte // 32
|
tip []byte // 32
|
||||||
srcAddrRaw []byte // 4
|
srcAddrRaw []byte // 4
|
||||||
country uint16
|
country uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +61,7 @@ func decodeSPVPing(data []byte) *SPVPing {
|
||||||
parsedMagic := binary.BigEndian.Uint32(data)
|
parsedMagic := binary.BigEndian.Uint32(data)
|
||||||
parsedProtocalVersion := data[4]
|
parsedProtocalVersion := data[4]
|
||||||
return &SPVPing{
|
return &SPVPing{
|
||||||
magic: parsedMagic,
|
magic: parsedMagic,
|
||||||
version: parsedProtocalVersion,
|
version: parsedProtocalVersion,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +71,7 @@ func decodeSPVPing(data []byte) *SPVPing {
|
||||||
func (pong *SPVPong) Encode() []byte {
|
func (pong *SPVPong) Encode() []byte {
|
||||||
data := make([]byte, 44)
|
data := make([]byte, 44)
|
||||||
|
|
||||||
data[0] = pong.protocolVersion
|
data[0] = pong.protocolVersion
|
||||||
data[1] = pong.flags
|
data[1] = pong.flags
|
||||||
binary.BigEndian.PutUint32(data[2:], pong.height)
|
binary.BigEndian.PutUint32(data[2:], pong.height)
|
||||||
copy(data[6:], pong.tip)
|
copy(data[6:], pong.tip)
|
||||||
|
@ -76,10 +82,13 @@ func (pong *SPVPong) Encode() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeSPVPong creates an SPVPong struct according to given parameters.
|
// 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 {
|
func makeSPVPong(flags int, height int, tip []byte, sourceAddr string, country string) *SPVPong {
|
||||||
byteAddr := EncodeAddress(sourceAddr)
|
byteAddr := EncodeAddress(sourceAddr)
|
||||||
countryInt := 1
|
var countryInt int32
|
||||||
|
var ok bool
|
||||||
|
if countryInt, ok = pb.Location_Country_value[country]; !ok {
|
||||||
|
countryInt = int32(pb.Location_UNKNOWN_COUNTRY)
|
||||||
|
}
|
||||||
return &SPVPong{
|
return &SPVPong{
|
||||||
protocolVersion: protocolVersion,
|
protocolVersion: protocolVersion,
|
||||||
flags: byte(flags),
|
flags: byte(flags),
|
||||||
|
@ -99,19 +108,19 @@ func decodeSPVPong(data []byte) *SPVPong {
|
||||||
|
|
||||||
parsedProtocalVersion := data[0]
|
parsedProtocalVersion := data[0]
|
||||||
flags := data[1]
|
flags := data[1]
|
||||||
height := binary.BigEndian.Uint32(data[:2])
|
height := binary.BigEndian.Uint32(data[2:])
|
||||||
tip := make([]byte, 32)
|
tip := make([]byte, 32)
|
||||||
copy(tip, data[6:38])
|
copy(tip, data[6:38])
|
||||||
srcRawAddr := make([]byte, 4)
|
srcRawAddr := make([]byte, 4)
|
||||||
copy(srcRawAddr, data[38:42])
|
copy(srcRawAddr, data[38:42])
|
||||||
country := binary.BigEndian.Uint16(data[:42])
|
country := binary.BigEndian.Uint16(data[42:])
|
||||||
return &SPVPong{
|
return &SPVPong{
|
||||||
protocolVersion: parsedProtocalVersion,
|
protocolVersion: parsedProtocalVersion,
|
||||||
flags: flags,
|
flags: flags,
|
||||||
height: height,
|
height: height,
|
||||||
tip: tip,
|
tip: tip,
|
||||||
srcAddrRaw: srcRawAddr,
|
srcAddrRaw: srcRawAddr,
|
||||||
country: country,
|
country: country,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,8 +146,8 @@ func EncodeAddress(addr string) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeAddress gets the string ipv4 address from an SPVPong struct.
|
// DecodeAddress gets the string ipv4 address from an SPVPong struct.
|
||||||
func (pong *SPVPong) DecodeAddress() string {
|
func (pong *SPVPong) DecodeAddress() net.IP {
|
||||||
return fmt.Sprintf("%d.%d.%d.%d",
|
return net.IPv4(
|
||||||
pong.srcAddrRaw[0],
|
pong.srcAddrRaw[0],
|
||||||
pong.srcAddrRaw[1],
|
pong.srcAddrRaw[1],
|
||||||
pong.srcAddrRaw[2],
|
pong.srcAddrRaw[2],
|
||||||
|
@ -146,53 +155,72 @@ func (pong *SPVPong) DecodeAddress() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pong *SPVPong) DecodeCountry() string {
|
||||||
|
return pb.Location_Country_name[int32(pong.country)]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pong *SPVPong) DecodeProtocolVersion() int {
|
||||||
|
return int(pong.protocolVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pong *SPVPong) DecodeHeight() int {
|
||||||
|
return int(pong.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pong *SPVPong) DecodeTip() []byte {
|
||||||
|
return pong.tip
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pong *SPVPong) DecodeFlags() byte {
|
||||||
|
return pong.flags
|
||||||
|
}
|
||||||
|
|
||||||
// UDPPing sends a ping over udp to another hub and returns the ip address of
|
// UDPPing sends a ping over udp to another hub and returns the ip address of
|
||||||
// this hub.
|
// this hub.
|
||||||
func UDPPing(address string) (string, error) {
|
func UDPPing(ip, port string) (*SPVPong, error) {
|
||||||
|
address := ip + ":" + port
|
||||||
addr, err := net.ResolveUDPAddr("udp", address)
|
addr, err := net.ResolveUDPAddr("udp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := net.DialUDP("udp", nil, addr)
|
conn, err := net.DialUDP("udp", nil, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
_, err = conn.Write(encodeSPVPing())
|
_, err = conn.Write(encodeSPVPing())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer := make([]byte, maxBufferSize)
|
buffer := make([]byte, maxBufferSize)
|
||||||
deadline := time.Now().Add(time.Second)
|
deadline := time.Now().Add(time.Second)
|
||||||
err = conn.SetReadDeadline(deadline)
|
err = conn.SetReadDeadline(deadline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
n, _, err := conn.ReadFromUDP(buffer)
|
n, _, err := conn.ReadFromUDP(buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pong := decodeSPVPong(buffer[:n])
|
pong := decodeSPVPong(buffer[:n])
|
||||||
|
|
||||||
if pong == nil {
|
if pong == nil {
|
||||||
return "", errors.Base("Pong decoding failed")
|
return nil, errors.Base("Pong decoding failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
myAddr := pong.DecodeAddress()
|
return pong, nil
|
||||||
|
|
||||||
return myAddr, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDPServer is a goroutine that starts an udp server that implements the hubs
|
// 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
|
// Ping/Pong protocol to find out about each other without making full TCP
|
||||||
// connections.
|
// connections.
|
||||||
func UDPServer(args *Args) error {
|
func UDPServer(args *Args) error {
|
||||||
address := ":" + args.UDPPort
|
address := ":" + args.Port
|
||||||
tip := make([]byte, 32)
|
tip := make([]byte, 32)
|
||||||
addr, err := net.ResolveUDPAddr("udp", address)
|
addr, err := net.ResolveUDPAddr("udp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -215,7 +243,7 @@ func UDPServer(args *Args) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
sAddr := addr.IP.String()
|
sAddr := addr.IP.String()
|
||||||
pong := makeSPVPong(0,0, tip, sAddr, args.Country)
|
pong := makeSPVPong(defaultFlags|availableFlag, 0, tip, sAddr, args.Country)
|
||||||
data := pong.Encode()
|
data := pong.Encode()
|
||||||
|
|
||||||
_, err = conn.WriteToUDP(data, addr)
|
_, err = conn.WriteToUDP(data, addr)
|
||||||
|
|
83
server/udp_test.go
Normal file
83
server/udp_test.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestUDPPing tests UDPPing correctness against prod server.
|
||||||
|
func TestUDPPing(t *testing.T) {
|
||||||
|
args := makeDefaultArgs()
|
||||||
|
args.DisableStartUDP = true
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
wantIP string
|
||||||
|
wantCountry string
|
||||||
|
wantProtocolVersion int
|
||||||
|
wantHeightMin int
|
||||||
|
wantFlags byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Correctly parse information from production server.",
|
||||||
|
wantIP: "SETME",
|
||||||
|
wantCountry: "US",
|
||||||
|
wantProtocolVersion: 1,
|
||||||
|
wantHeightMin: 1060000,
|
||||||
|
wantFlags: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
toAddr := "spv16.lbry.com"
|
||||||
|
toPort := "50001"
|
||||||
|
|
||||||
|
pong, err := UDPPing(toAddr, toPort)
|
||||||
|
gotCountry := pong.DecodeCountry()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := exec.Command("dig", "@resolver4.opendns.com", "myip.opendns.com", "+short").Output()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
digIP := strings.TrimSpace(string(res))
|
||||||
|
udpIP := pong.DecodeAddress().String()
|
||||||
|
tt.wantIP = digIP
|
||||||
|
|
||||||
|
log.Println("Height:", pong.DecodeHeight())
|
||||||
|
log.Printf("Flags: %x\n", pong.DecodeFlags())
|
||||||
|
log.Println("ProtocolVersion:", pong.DecodeProtocolVersion())
|
||||||
|
log.Printf("Tip: %x\n", pong.DecodeTip())
|
||||||
|
|
||||||
|
gotHeight := pong.DecodeHeight()
|
||||||
|
gotProtocolVersion := pong.DecodeProtocolVersion()
|
||||||
|
gotFlags := pong.DecodeFlags()
|
||||||
|
gotIP := udpIP
|
||||||
|
|
||||||
|
if gotIP != tt.wantIP {
|
||||||
|
t.Errorf("ip: got: '%s', want: '%s'\n", gotIP, tt.wantIP)
|
||||||
|
}
|
||||||
|
if gotCountry != tt.wantCountry {
|
||||||
|
t.Errorf("country: got: '%s', want: '%s'\n", gotCountry, tt.wantCountry)
|
||||||
|
}
|
||||||
|
if gotHeight < tt.wantHeightMin {
|
||||||
|
t.Errorf("height: got: %d, want >=: %d\n", gotHeight, tt.wantHeightMin)
|
||||||
|
}
|
||||||
|
if gotProtocolVersion != tt.wantProtocolVersion {
|
||||||
|
t.Errorf("protocolVersion: got: %d, want: %d\n", gotProtocolVersion, tt.wantProtocolVersion)
|
||||||
|
}
|
||||||
|
if gotFlags != tt.wantFlags {
|
||||||
|
t.Errorf("flags: got: %d, want: %d\n", gotFlags, tt.wantFlags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue