various: make AddressChooser an interface

See https://vanadium-review.googlesource.com/#/c/12694/ for rationale.

MultiPart: 3/4
Change-Id: Ibeb150e1dc5498d62e933ed4b29ca7f457ade9b4
diff --git a/runtime/factories/gce/gce.go b/runtime/factories/gce/gce.go
index 9fe80da..b38548b 100644
--- a/runtime/factories/gce/gce.go
+++ b/runtime/factories/gce/gce.go
@@ -58,9 +58,9 @@
 	if ip, err := gce.ExternalIPAddress(); err != nil {
 		return nil, nil, nil, err
 	} else {
-		listenSpec.AddressChooser = func(network string, addrs []net.Addr) ([]net.Addr, error) {
+		listenSpec.AddressChooser = netstate.AddressChooserFunc(func(network string, addrs []net.Addr) ([]net.Addr, error) {
 			return []net.Addr{netstate.NewNetAddr("wsh", ip.String())}, nil
-		}
+		})
 	}
 
 	runtime, ctx, shutdown, err := grt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), nil)
diff --git a/runtime/factories/generic/generic.go b/runtime/factories/generic/generic.go
index 9de2b92..eabda93 100644
--- a/runtime/factories/generic/generic.go
+++ b/runtime/factories/generic/generic.go
@@ -43,7 +43,7 @@
 	lf := commonFlags.ListenFlags()
 	listenSpec := rpc.ListenSpec{
 		Addrs:          rpc.ListenAddrs(lf.Addrs),
-		AddressChooser: internal.IPAddressChooser,
+		AddressChooser: internal.IPAddressChooser{},
 		Proxy:          lf.ListenProxy,
 	}
 
diff --git a/runtime/factories/roaming/roaming.go b/runtime/factories/roaming/roaming.go
index 40d82e0..5424691 100644
--- a/runtime/factories/roaming/roaming.go
+++ b/runtime/factories/roaming/roaming.go
@@ -71,12 +71,12 @@
 	// 1:1 NAT configuration.
 	if !internal.HasPublicIP(logger.Global()) {
 		if addr := internal.GCEPublicAddress(logger.Global()); addr != nil {
-			listenSpec.AddressChooser = func(string, []net.Addr) ([]net.Addr, error) {
+			listenSpec.AddressChooser = netstate.AddressChooserFunc(func(string, []net.Addr) ([]net.Addr, error) {
 				// TODO(cnicolaou): the protocol at least should
 				// be configurable, or maybe there's a RuntimeFactory specific
 				// flag to configure both the protocol and address.
 				return []net.Addr{netstate.NewNetAddr("wsh", addr.String())}, nil
-			}
+			})
 			runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), reservedDispatcher)
 			if err != nil {
 				return nil, nil, shutdown, err
@@ -117,7 +117,7 @@
 	cleanupCh := make(chan struct{})
 	watcherCh := make(chan struct{})
 
-	listenSpec.AddressChooser = internal.IPAddressChooser
+	listenSpec.AddressChooser = internal.IPAddressChooser{}
 
 	runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, publisher, SettingsStreamName, commonFlags.RuntimeFlags(), reservedDispatcher)
 	if err != nil {
@@ -175,7 +175,7 @@
 				ch <- irpc.NewRmAddrsSetting(removed.AsNetAddrs())
 			}
 			// We will always send the best currently available address
-			if chosen, err := listenSpec.AddressChooser(listenSpec.Addrs[0].Protocol, cur.AsNetAddrs()); err == nil && chosen != nil {
+			if chosen, err := listenSpec.AddressChooser.ChooseAddress(listenSpec.Addrs[0].Protocol, cur.AsNetAddrs()); err == nil && chosen != nil {
 				vlog.VI(2).Infof("Sending added and chosen: %s", chosen)
 				ch <- irpc.NewAddAddrsSetting(chosen)
 			} else {
diff --git a/runtime/factories/static/static.go b/runtime/factories/static/static.go
index c0873bb..c92732b 100644
--- a/runtime/factories/static/static.go
+++ b/runtime/factories/static/static.go
@@ -53,9 +53,9 @@
 	// running on GCE.
 	if !internal.HasPublicIP(logger.Global()) {
 		if addr := internal.GCEPublicAddress(logger.Global()); addr != nil {
-			listenSpec.AddressChooser = func(string, []net.Addr) ([]net.Addr, error) {
+			listenSpec.AddressChooser = rpc.AddressChooserFunc(func(string, []net.Addr) ([]net.Addr, error) {
 				return []net.Addr{addr}, nil
-			}
+			})
 			runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), reservedDispatcher)
 			if err != nil {
 				return nil, nil, nil, err
@@ -67,7 +67,7 @@
 			return runtime, ctx, runtimeFactoryShutdown, nil
 		}
 	}
-	listenSpec.AddressChooser = internal.IPAddressChooser
+	listenSpec.AddressChooser = internal.IPAddressChooser{}
 
 	runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), reservedDispatcher)
 	if err != nil {
diff --git a/runtime/internal/rpc/full_test.go b/runtime/internal/rpc/full_test.go
index f1c08a8..f60009b 100644
--- a/runtime/internal/rpc/full_test.go
+++ b/runtime/internal/rpc/full_test.go
@@ -1539,9 +1539,9 @@
 	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 	defer sm.Shutdown()
 	ns := tnaming.NewSimpleNamespace()
-	pa := func(string, []net.Addr) ([]net.Addr, error) {
+	pa := netstate.AddressChooserFunc(func(string, []net.Addr) ([]net.Addr, error) {
 		return []net.Addr{netstate.NewNetAddr("tcp", "1.1.1.1")}, nil
-	}
+	})
 	server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("server"))
 	if err != nil {
 		t.Errorf("InternalNewServer failed: %v", err)
@@ -1582,9 +1582,9 @@
 	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 	defer sm.Shutdown()
 	ns := tnaming.NewSimpleNamespace()
-	paerr := func(_ string, a []net.Addr) ([]net.Addr, error) {
+	paerr := netstate.AddressChooserFunc(func(_ string, a []net.Addr) ([]net.Addr, error) {
 		return nil, fmt.Errorf("oops")
-	}
+	})
 	server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("server"))
 	if err != nil {
 		t.Errorf("InternalNewServer failed: %v", err)
diff --git a/runtime/internal/rpc/server_test.go b/runtime/internal/rpc/server_test.go
index 5f2c5c4..77680c2 100644
--- a/runtime/internal/rpc/server_test.go
+++ b/runtime/internal/rpc/server_test.go
@@ -442,12 +442,12 @@
 	}
 	defer server.Stop()
 
-	ipv4And6 := func(network string, addrs []net.Addr) ([]net.Addr, error) {
+	ipv4And6 := netstate.AddressChooserFunc(func(network string, addrs []net.Addr) ([]net.Addr, error) {
 		accessible := netstate.ConvertToAddresses(addrs)
 		ipv4 := accessible.Filter(netstate.IsUnicastIPv4)
 		ipv6 := accessible.Filter(netstate.IsUnicastIPv6)
 		return append(ipv4.AsNetAddrs(), ipv6.AsNetAddrs()...), nil
-	}
+	})
 	spec := rpc.ListenSpec{
 		Addrs: rpc.ListenAddrs{
 			{"tcp", "*:0"},
diff --git a/runtime/internal/util.go b/runtime/internal/util.go
index 6a49e50..4df3db4 100644
--- a/runtime/internal/util.go
+++ b/runtime/internal/util.go
@@ -46,7 +46,9 @@
 // IPAddressChooser returns the preferred IP address, which is,
 // a public IPv4 address, then any non-loopback IPv4, then a public
 // IPv6 address and finally any non-loopback/link-local IPv6
-func IPAddressChooser(network string, addrs []net.Addr) ([]net.Addr, error) {
+type IPAddressChooser struct{}
+
+func (IPAddressChooser) ChooseAddress(network string, addrs []net.Addr) ([]net.Addr, error) {
 	if !netstate.IsIPProtocol(network) {
 		return nil, fmt.Errorf("can't support network protocol %q", network)
 	}
diff --git a/services/binary/binaryd/main.go b/services/binary/binaryd/main.go
index 883f080..5854f1b 100644
--- a/services/binary/binaryd/main.go
+++ b/services/binary/binaryd/main.go
@@ -62,7 +62,7 @@
 		ips, err := netstate.GetAccessibleIPs()
 		if err == nil {
 			ls := v23.GetListenSpec(ctx)
-			if a, err := ls.AddressChooser("tcp", ips.AsNetAddrs()); err == nil && len(a) > 0 {
+			if a, err := ls.AddressChooser.ChooseAddress("tcp", ips.AsNetAddrs()); err == nil && len(a) > 0 {
 				host = a[0].String()
 			}
 		}