veyron/services: continue migration to ListenX and associated changes.

Change-Id: If6d35c782c79801a7c163671b2c241bb0dc96b83
diff --git a/profiles/internal/gce_linux.go b/profiles/internal/gce_linux.go
new file mode 100644
index 0000000..7e66c2b
--- /dev/null
+++ b/profiles/internal/gce_linux.go
@@ -0,0 +1,32 @@
+// +build linux
+
+package internal
+
+import (
+	"net"
+
+	"veyron.io/veyron/veyron2/vlog"
+
+	"veyron.io/veyron/veyron/profiles/internal/gce"
+)
+
+// GCEPublicAddress returns the public IP address of the GCE instance
+// it is run from, or nil if run from anywhere else. The returned address
+// is the public address of a 1:1 NAT tunnel to this host.
+func GCEPublicAddress(log vlog.Logger) *net.IPAddr {
+	if !gce.RunningOnGCE() {
+		return nil
+	}
+	var pub *net.IPAddr
+	// Determine the IP address from GCE's metadata
+	if ip, err := gce.ExternalIPAddress(); err != nil {
+		log.Infof("failed to query GCE metadata: %s", err)
+	} else {
+		// 1:1 NAT case, our network config will not change.
+		pub = &net.IPAddr{IP: ip}
+	}
+	if pub == nil {
+		log.Infof("failed to determine public IP address to publish with")
+	}
+	return pub
+}
diff --git a/profiles/internal/gce_other.go b/profiles/internal/gce_other.go
new file mode 100644
index 0000000..2494d29
--- /dev/null
+++ b/profiles/internal/gce_other.go
@@ -0,0 +1,16 @@
+// +build !linux
+
+package internal
+
+import (
+	"net"
+
+	"veyron.io/veyron/veyron2/vlog"
+)
+
+// GCEPublicAddress returns the public IP address of the GCE instance
+// it is run from, or nil if run from anywhere else. The returned address
+// is the public address of a 1:1 NAT tunnel to this host.
+func GCEPublicAddress(vlog.Logger) *net.IPAddr {
+	return nil
+}
diff --git a/profiles/internal/util.go b/profiles/internal/util.go
index 7af4da9..c3c53ce 100644
--- a/profiles/internal/util.go
+++ b/profiles/internal/util.go
@@ -4,6 +4,7 @@
 	"fmt"
 
 	"veyron.io/veyron/veyron2/ipc"
+	"veyron.io/veyron/veyron2/vlog"
 
 	"veyron.io/veyron/veyron/lib/netstate"
 )
@@ -39,3 +40,23 @@
 
 	return nil, fmt.Errorf("failed to find any usable address for %q", network)
 }
+
+// HasPublicIP returns true if the host has at least one public IP address.
+func HasPublicIP(log vlog.Logger) bool {
+	state, err := netstate.GetAccessibleIPs()
+	if err != nil {
+		log.Infof("failed to determine network state: %s", err)
+		return false
+	}
+	any := state.Filter(netstate.IsUnicastIP)
+	if len(any) == 0 {
+		log.Infof("failed to find any usable IP addresses at startup")
+		return false
+	}
+	for _, a := range any {
+		if netstate.IsPublicUnicastIPv4(a) {
+			return true
+		}
+	}
+	return false
+}
diff --git a/profiles/roaming/gce_linux.go b/profiles/roaming/gce_linux.go
deleted file mode 100644
index efd3598..0000000
--- a/profiles/roaming/gce_linux.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// +build linux
-
-package roaming
-
-import (
-	"net"
-
-	"veyron.io/veyron/veyron2"
-	"veyron.io/veyron/veyron2/config"
-
-	"veyron.io/veyron/veyron/profiles/internal/gce"
-)
-
-func handleGCE(rt veyron2.Runtime, publisher *config.Publisher) *net.IPAddr {
-	log := rt.Logger()
-	if gce.RunningOnGCE() {
-		var pub *net.IPAddr
-		// Determine the IP address from GCE's metadata
-		if ip, err := gce.ExternalIPAddress(); err != nil {
-			log.Infof("failed to query GCE metadata: %s", err)
-		} else {
-			// 1:1 NAT case, our network config will not change.
-			pub = &net.IPAddr{IP: ip}
-		}
-		if pub == nil {
-			log.Infof("failed to determine public IP address to publish with")
-			return nil
-		}
-
-		ch := make(chan config.Setting)
-		defer close(ch)
-		stop, err := publisher.CreateStream(SettingsStreamName, "dhcp", ch)
-		if err != nil {
-			return nil
-		}
-
-		_ = stop
-		// TODO(cnicolaou): stop should be used by the soon to be added
-		// Cleanup method.
-		return pub
-	}
-	return nil
-}
diff --git a/profiles/roaming/gce_other.go b/profiles/roaming/gce_other.go
deleted file mode 100644
index 9d77604..0000000
--- a/profiles/roaming/gce_other.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// +build !linux
-
-package roaming
-
-import (
-	"net"
-
-	"veyron.io/veyron/veyron2"
-	"veyron.io/veyron/veyron2/config"
-)
-
-func handleGCE(veyron2.Runtime, *config.Publisher) *net.IPAddr {
-	return nil
-}
diff --git a/profiles/roaming/net_watcher.go b/profiles/roaming/net_watcher.go
index 6e810ad..4e54d72 100644
--- a/profiles/roaming/net_watcher.go
+++ b/profiles/roaming/net_watcher.go
@@ -4,7 +4,6 @@
 
 import (
 	"fmt"
-	"os"
 	"strings"
 
 	"veyron.io/veyron/veyron2/config"
@@ -38,7 +37,6 @@
 		fmt.Printf("Chosen:\n%s\n", strings.Replace(al.String(), ") ", ")\n", -1))
 	}
 
-	os.Exit(0)
 	ch := make(chan config.Setting, 10)
 	settings, err := r.Publisher().ForkStream(roaming.SettingsStreamName, ch)
 	if err != nil {
diff --git a/profiles/roaming/init.go b/profiles/roaming/roaming.go
similarity index 83%
rename from profiles/roaming/init.go
rename to profiles/roaming/roaming.go
index 7a06306..dab60d0 100644
--- a/profiles/roaming/init.go
+++ b/profiles/roaming/roaming.go
@@ -80,25 +80,10 @@
 		Proxy:    listenProxyFlag,
 	}
 
-	state, err := netstate.GetAccessibleIPs()
-	if err != nil {
-		log.Infof("failed to determine network state")
-		return err
-	}
-	any := state.Filter(netstate.IsUnicastIP)
-	if len(any) == 0 {
-		log.Infof("failed to find any usable IP addresses at startup")
-	}
-	public := netstate.IsPublicUnicastIPv4(any[0])
-
-	// We now know that there is an IP address to listen on, and whether
-	// it's public or private.
-
 	// Our address is private, so we test for running on GCE and for its
-	// 1:1 NAT configuration. handleGCE returns a non-nil addr
-	// if we are indeed running on GCE.
-	if !public {
-		if addr := handleGCE(rt, publisher); addr != nil {
+	// 1:1 NAT configuration.
+	if !internal.HasPublicIP(log) {
+		if addr := internal.GCEPublicAddress(log); addr != nil {
 			ListenSpec.AddressChooser = func(string, []ipc.Address) ([]ipc.Address, error) {
 				return []ipc.Address{&netstate.AddrIfc{addr, "nat", nil}}, nil
 			}
@@ -116,22 +101,27 @@
 		return err
 	}
 
-	protocol := listenProtocolFlag.Protocol
 	ListenSpec.StreamPublisher = publisher
 	ListenSpec.StreamName = SettingsStreamName
 	ListenSpec.AddressChooser = internal.IPAddressChooser
-	log.VI(2).Infof("Initial Network Settings: %s %s available: %s", protocol, listenAddressFlag, state)
-	go monitorNetworkSettings(rt, stop, ch, state, ListenSpec)
+	go monitorNetworkSettings(rt, stop, ch, ListenSpec)
 	return nil
 }
 
 // monitorNetworkSettings will monitor network configuration changes and
 // publish subsequent Settings to reflect any changes detected.
 func monitorNetworkSettings(rt veyron2.Runtime, stop <-chan struct{},
-	ch chan<- config.Setting, prev netstate.AddrList, listenSpec *ipc.ListenSpec) {
+	ch chan<- config.Setting, listenSpec *ipc.ListenSpec) {
 	defer close(ch)
 
 	log := rt.Logger()
+	prev, err := netstate.GetAccessibleIPs()
+	if err != nil {
+		// TODO(cnicolaou): add support for shutting down profiles
+		//<-stop
+		log.VI(2).Infof("failed to determine network state")
+		return
+	}
 
 	// Start the dhcp watcher.
 	watcher, err := netconfig.NewNetConfigWatcher()
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 9ca7299..33499c7 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -17,6 +17,7 @@
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/verror"
 	"veyron.io/veyron/veyron2/vlog"
 
 	"veyron.io/veyron/veyron/lib/signals"
@@ -29,7 +30,6 @@
 	"veyron.io/veyron/veyron/services/identity/revocation"
 	services "veyron.io/veyron/veyron/services/security"
 	"veyron.io/veyron/veyron/services/security/discharger"
-	"veyron.io/veyron/veyron2/verror"
 )
 
 var (
diff --git a/services/mgmt/debug/server.go b/services/mgmt/debug/server.go
index 7feb173..c36d972 100644
--- a/services/mgmt/debug/server.go
+++ b/services/mgmt/debug/server.go
@@ -6,12 +6,13 @@
 	"fmt"
 
 	"veyron.io/veyron/veyron2"
+	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vlog"
 )
 
 // StartDebugServer starts a debug server.
-func StartDebugServer(rt veyron2.Runtime, address, logsDir string, auth security.Authorizer) (string, func(), error) {
+func StartDebugServer(rt veyron2.Runtime, listenSpec *ipc.ListenSpec, logsDir string, auth security.Authorizer) (string, func(), error) {
 	if len(logsDir) == 0 {
 		return "", nil, fmt.Errorf("logs directory missing")
 	}
@@ -20,9 +21,9 @@
 	if err != nil {
 		return "", nil, fmt.Errorf("failed to start debug server: %v", err)
 	}
-	endpoint, err := server.Listen("tcp", address)
+	endpoint, err := server.ListenX(listenSpec)
 	if err != nil {
-		return "", nil, fmt.Errorf("failed to listen on %v: %v", address, err)
+		return "", nil, fmt.Errorf("failed to listen on %s: %v", listenSpec, err)
 	}
 	if err := server.Serve("", disp); err != nil {
 		return "", nil, err
diff --git a/services/mgmt/debug/server_test.go b/services/mgmt/debug/server_test.go
index 120a481..baa824f 100644
--- a/services/mgmt/debug/server_test.go
+++ b/services/mgmt/debug/server_test.go
@@ -10,15 +10,16 @@
 	"testing"
 	"time"
 
-	libstats "veyron.io/veyron/veyron/lib/stats"
-	"veyron.io/veyron/veyron/services/mgmt/debug"
-
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/logreader"
 	"veyron.io/veyron/veyron2/services/mgmt/stats"
 	"veyron.io/veyron/veyron2/services/mounttable"
 	"veyron.io/veyron/veyron2/verror"
+
+	libstats "veyron.io/veyron/veyron/lib/stats"
+	"veyron.io/veyron/veyron/profiles"
+	"veyron.io/veyron/veyron/services/mgmt/debug"
 )
 
 func TestDebugServer(t *testing.T) {
@@ -33,7 +34,7 @@
 		t.Fatalf("ioutil.WriteFile failed: %v", err)
 	}
 
-	endpoint, stop, err := debug.StartDebugServer(runtime, "localhost:0", workdir, nil)
+	endpoint, stop, err := debug.StartDebugServer(runtime, profiles.LocalListenSpec, workdir, nil)
 	if err != nil {
 		t.Fatalf("StartDebugServer failed: %v", err)
 	}