From 37eb65e6662a09de57f324d4a16182827f91ce07 Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Thu, 11 Apr 2019 14:00:20 +0100
Subject: [PATCH] Use net.IPs to build Endpoints

---
 coordination/presence/presence.go     | 16 ++++---------
 coordination/presence/registration.go | 30 +++++++++++++----------
 proto/presence.go                     | 34 +++++++--------------------
 3 files changed, 31 insertions(+), 49 deletions(-)

diff --git a/coordination/presence/presence.go b/coordination/presence/presence.go
index 6e77e20e..3f5e9e51 100644
--- a/coordination/presence/presence.go
+++ b/coordination/presence/presence.go
@@ -2,10 +2,8 @@ package presence
 
 import (
 	"context"
-	"crypto/rand"
-	"encoding/hex"
 	"log"
-	mrand "math/rand"
+	"math/rand"
 	"sync"
 
 	"github.com/golang/protobuf/proto"
@@ -15,12 +13,6 @@ import (
 	pb "git.autistici.org/ale/autoradio/proto"
 )
 
-func getUniqueToken() string {
-	var b [16]byte
-	rand.Read(b[:]) // nolint
-	return hex.EncodeToString(b[:])
-}
-
 // EndpointSet is a container of Endpoints that is synchronizable with
 // the contents of a presence tree as created by Register().
 type EndpointSet struct {
@@ -123,7 +115,7 @@ func (n *EndpointSet) RandomEndpoint() *pb.Endpoint {
 	if len(n.epl) == 0 {
 		return nil
 	}
-	return n.epl[mrand.Intn(len(n.epl))]
+	return n.epl[rand.Intn(len(n.epl))]
 }
 
 // RandomEndpointExcluding returns a randomly selected Endpoint except
@@ -145,13 +137,13 @@ func (n *EndpointSet) RandomEndpointExcluding(name string) *pb.Endpoint {
 	}
 	// Is the excluded element not in the list?
 	if found < 0 {
-		return n.epl[mrand.Intn(l)]
+		return n.epl[rand.Intn(l)]
 	}
 	// Is the list empty once we exclude the item?
 	if l == 1 {
 		return nil
 	}
-	i := mrand.Intn(l - 1)
+	i := rand.Intn(l - 1)
 	if i >= found {
 		i++
 	}
diff --git a/coordination/presence/registration.go b/coordination/presence/registration.go
index f378ae28..4fffb6a6 100644
--- a/coordination/presence/registration.go
+++ b/coordination/presence/registration.go
@@ -2,6 +2,9 @@ package presence
 
 import (
 	"context"
+	"crypto/rand"
+	"encoding/hex"
+	"net"
 	"strings"
 
 	pb "git.autistici.org/ale/autoradio/proto"
@@ -14,17 +17,17 @@ import (
 // endpoint registration. Addresses without ports will use the
 // DefaultPort.
 type EndpointRegistration struct {
-	Prefix      string
-	Addrs       string
-	DefaultPort int
+	Prefix string
+	Addrs  []net.IP
+	Port   int
 }
 
 // NewRegistration creates a new EndpointRegistration.
-func NewRegistration(prefix, addrs string, port int) EndpointRegistration {
+func NewRegistration(prefix string, addrs []net.IP, port int) EndpointRegistration {
 	return EndpointRegistration{
-		Prefix:      prefix,
-		Addrs:       addrs,
-		DefaultPort: port,
+		Prefix: prefix,
+		Addrs:  addrs,
+		Port:   port,
 	}
 }
 
@@ -33,11 +36,8 @@ func NewRegistration(prefix, addrs string, port int) EndpointRegistration {
 func Register(ctx context.Context, session *concurrency.Session, name string, regs ...EndpointRegistration) ([]*pb.Endpoint, error) {
 	var endpoints []*pb.Endpoint
 	for _, r := range regs {
-		ep, err := pb.ParseEndpoint(name, r.Addrs, r.DefaultPort)
-		if err != nil {
-			return nil, err
-		}
-		if err = registerEndpoint(ctx, session, r.Prefix, ep); err != nil {
+		ep := pb.NewEndpointWithIPAndPort(name, r.Addrs, r.Port)
+		if err := registerEndpoint(ctx, session, r.Prefix, ep); err != nil {
 			return nil, err
 		}
 		endpoints = append(endpoints, ep)
@@ -61,3 +61,9 @@ func registerEndpoint(ctx context.Context, session *concurrency.Session, prefix
 	)
 	return err
 }
+
+func getUniqueToken() string {
+	var b [16]byte
+	rand.Read(b[:]) // nolint
+	return hex.EncodeToString(b[:])
+}
diff --git a/proto/presence.go b/proto/presence.go
index 381233b2..bc87f9b2 100644
--- a/proto/presence.go
+++ b/proto/presence.go
@@ -1,35 +1,19 @@
 package autoradio
 
 import (
-	"errors"
-	"fmt"
 	"net"
 	"strconv"
-	"strings"
 )
 
-// ParseEndpoint creates an Endpoint with the specified name and
-// address. If the address does not specify a port, defaultPort is
-// used.
-func ParseEndpoint(name, s string, defaultPort int) (*Endpoint, error) {
-	if s == "" {
-		return nil, errors.New("empty endpoint spec")
+// NewEndpointWithIPAndPort creates an Endpoint with the specified IP
+// address and port.
+func NewEndpointWithIPAndPort(name string, ips []net.IP, port int) *Endpoint {
+	ep := Endpoint{
+		Name: name,
 	}
-	addrs := strings.Split(s, ",")
-	var ep Endpoint
-	ep.Name = name
-	for _, addr := range addrs {
-		host, port, err := net.SplitHostPort(addr)
-		if err != nil {
-			return nil, fmt.Errorf("parsing '%s': %v", addr, err)
-		}
-		if port == "" {
-			port = strconv.Itoa(defaultPort)
-		}
-		if ip := net.ParseIP(host); ip == nil {
-			return nil, fmt.Errorf("parsing '%s': bad IP address", host)
-		}
-		ep.Addrs = append(ep.Addrs, net.JoinHostPort(host, port))
+	sport := strconv.Itoa(port)
+	for _, ip := range ips {
+		ep.Addrs = append(ep.Addrs, net.JoinHostPort(ip.String(), sport))
 	}
-	return &ep, nil
+	return &ep
 }
-- 
GitLab