Merge "v23/config: move it to x/lib/pubsub."
diff --git a/netstate/.api b/netstate/.api
index 181595f..03726fb 100644
--- a/netstate/.api
+++ b/netstate/.api
@@ -1,48 +1,75 @@
+pkg netstate, func AddressFromAddr(net.Addr) (Address, error)
+pkg netstate, func AddressFromIP(net.IP) (Address, error)
 pkg netstate, func AsIP(net.Addr) net.IP
 pkg netstate, func AsIPAddr(net.Addr) *net.IPAddr
-pkg netstate, func ConvertAccessibleIPHost(rpc.Address) rpc.Address
-pkg netstate, func ConvertToIPHost(rpc.Address) rpc.Address
+pkg netstate, func ConvertToAddresses([]net.Addr) AddrList
 pkg netstate, func FindAdded(AddrList, AddrList) AddrList
 pkg netstate, func FindRemoved(AddrList, AddrList) AddrList
 pkg netstate, func GetAccessibleIPs() (AddrList, error)
-pkg netstate, func GetAll() (AddrList, error)
-pkg netstate, func GetInterfaces() (InterfaceList, error)
-pkg netstate, func GetRoutes() IPRouteList
-pkg netstate, func IsAccessibleIP(rpc.Address) bool
+pkg netstate, func GetAllAddresses() (AddrList, error)
+pkg netstate, func GetAllInterfaces() (InterfaceList, error)
+pkg netstate, func GetNetState() ([]NetworkInterface, RouteTable, error)
+pkg netstate, func InvalidateCache()
+pkg netstate, func IsAccessibleIP(Address) bool
 pkg netstate, func IsDefaultRoute(*netconfig.IPRoute) bool
 pkg netstate, func IsGloballyRoutableIP(net.IP) bool
 pkg netstate, func IsIPProtocol(string) bool
-pkg netstate, func IsLoopbackIP(rpc.Address) bool
-pkg netstate, func IsOnDefaultRoute(rpc.Address) bool
-pkg netstate, func IsPublicUnicastIP(rpc.Address) bool
-pkg netstate, func IsPublicUnicastIPv4(rpc.Address) bool
-pkg netstate, func IsPublicUnicastIPv6(rpc.Address) bool
-pkg netstate, func IsUnicastIP(rpc.Address) bool
-pkg netstate, func IsUnicastIPv4(rpc.Address) bool
-pkg netstate, func IsUnicastIPv6(rpc.Address) bool
-pkg netstate, func IsUnspecifiedIP(rpc.Address) bool
+pkg netstate, func IsLoopbackIP(Address) bool
+pkg netstate, func IsOnDefaultRoute(Address) bool
+pkg netstate, func IsPublicUnicastIP(Address) bool
+pkg netstate, func IsPublicUnicastIPv4(Address) bool
+pkg netstate, func IsPublicUnicastIPv6(Address) bool
+pkg netstate, func IsUnicastIP(Address) bool
+pkg netstate, func IsUnicastIPv4(Address) bool
+pkg netstate, func IsUnicastIPv6(Address) bool
+pkg netstate, func IsUnspecifiedIP(Address) bool
+pkg netstate, func LoopbackIPv4AddressChooser(string, []net.Addr) ([]net.Addr, error)
+pkg netstate, func NewNetAddr(string, string) net.Addr
+pkg netstate, func PossibleAddresses(string, string, AddressChooser) ([]net.Addr, bool, error)
 pkg netstate, func SameMachine(net.Addr) (bool, error)
-pkg netstate, method (*AddrIfc) Address() net.Addr
-pkg netstate, method (*AddrIfc) InterfaceIndex() int
-pkg netstate, method (*AddrIfc) InterfaceName() string
-pkg netstate, method (*AddrIfc) Networks() []net.Addr
-pkg netstate, method (*AddrIfc) String() string
+pkg netstate, func WithIPHost(Address) Address
+pkg netstate, func WithIPHostAndPort(Address, string) Address
+pkg netstate, method (AddrList) AsNetAddrs() []net.Addr
 pkg netstate, method (AddrList) Filter(AddressPredicate) AddrList
 pkg netstate, method (AddrList) Map(Mapper) AddrList
 pkg netstate, method (AddrList) String() string
 pkg netstate, method (IPRouteList) Filter(RoutePredicate) IPRouteList
 pkg netstate, method (IPRouteList) String() string
 pkg netstate, method (InterfaceList) String() string
-pkg netstate, type AddrIfc struct
-pkg netstate, type AddrIfc struct, Addr net.Addr
-pkg netstate, type AddrIfc struct, IPRoutes []*netconfig.IPRoute
-pkg netstate, type AddrIfc struct, Name string
-pkg netstate, type AddrList []rpc.Address
-pkg netstate, type AddressPredicate func(a rpc.Address) bool
+pkg netstate, type AddrList []Address
+pkg netstate, type Address interface { DebugString, Interface, Network, String }
+pkg netstate, type Address interface, DebugString() string
+pkg netstate, type Address interface, Interface() NetworkInterface
+pkg netstate, type Address interface, Network() string
+pkg netstate, type Address interface, String() string
+pkg netstate, type AddressChooser func(protocol string, candidates []net.Addr) ([]net.Addr, error)
+pkg netstate, type AddressPredicate func(a Address) bool
+pkg netstate, type IPNetworkInterface interface { Addrs, Flags, HardwareAddr, IPRoutes, Index, MTU, Name, Networks, String }
+pkg netstate, type IPNetworkInterface interface, Addrs() []net.Addr
+pkg netstate, type IPNetworkInterface interface, Flags() net.Flags
+pkg netstate, type IPNetworkInterface interface, HardwareAddr() net.HardwareAddr
+pkg netstate, type IPNetworkInterface interface, IPRoutes() IPRouteList
+pkg netstate, type IPNetworkInterface interface, Index() int
+pkg netstate, type IPNetworkInterface interface, MTU() int
+pkg netstate, type IPNetworkInterface interface, Name() string
+pkg netstate, type IPNetworkInterface interface, Networks() []net.Addr
+pkg netstate, type IPNetworkInterface interface, String() string
 pkg netstate, type IPRouteList []*netconfig.IPRoute
-pkg netstate, type Interface struct
-pkg netstate, type Interface struct, Index int
-pkg netstate, type Interface struct, Name string
-pkg netstate, type InterfaceList []*Interface
-pkg netstate, type Mapper func(a rpc.Address) rpc.Address
+pkg netstate, type InterfaceList []NetworkInterface
+pkg netstate, type Mapper func(a Address) Address
+pkg netstate, type NetworkInterface interface { Addrs, Flags, HardwareAddr, Index, MTU, Name, Networks, String }
+pkg netstate, type NetworkInterface interface, Addrs() []net.Addr
+pkg netstate, type NetworkInterface interface, Flags() net.Flags
+pkg netstate, type NetworkInterface interface, HardwareAddr() net.HardwareAddr
+pkg netstate, type NetworkInterface interface, Index() int
+pkg netstate, type NetworkInterface interface, MTU() int
+pkg netstate, type NetworkInterface interface, Name() string
+pkg netstate, type NetworkInterface interface, Networks() []net.Addr
+pkg netstate, type NetworkInterface interface, String() string
 pkg netstate, type RoutePredicate func(r *netconfig.IPRoute) bool
+pkg netstate, type RouteTable map[int]IPRouteList
+pkg netstate, var ErrFailedToFindInterface error
+pkg netstate, var ErrFailedToParseIPAddr error
+pkg netstate, var ErrNotAnIPProtocol error
+pkg netstate, var ErrUnspecifiedIPAddr error
+pkg netstate, var ErrUnsupportedProtocol error
diff --git a/netstate/chooser.go b/netstate/chooser.go
index 26357f7..07665af 100644
--- a/netstate/chooser.go
+++ b/netstate/chooser.go
@@ -83,6 +83,13 @@
 			return []net.Addr{address}, unspecified, nil
 		}
 	}
+	if len(port) > 0 {
+		addPort := func(a Address) Address {
+			return WithIPHostAndPort(a, port)
+		}
+		withPort := ConvertToAddresses(chosen).Map(addPort)
+		chosen = withPort.AsNetAddrs()
+	}
 	return chosen, unspecified, nil
 }
 
diff --git a/netstate/chooser_test.go b/netstate/chooser_test.go
index 076e826..2207666 100644
--- a/netstate/chooser_test.go
+++ b/netstate/chooser_test.go
@@ -73,6 +73,55 @@
 	}
 }
 
+func TestChooserWithPorts(t *testing.T) {
+	_, ifcs, rt := mockInterfacesAndRouteTable()
+	cleanup := netstate.CreateAndUseMockCache(ifcs, rt)
+	defer cleanup()
+
+	chooser := func(protocol string, addrs []net.Addr) ([]net.Addr, error) {
+		return addrs, nil
+	}
+
+	addrs, unspecified, err := netstate.PossibleAddresses("tcp", "0.0.0.0:30", chooser)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got, want := unspecified, true; got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+
+	if got, want := len(addrs), 7; got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+
+	for _, a := range addrs {
+		_, port, _ := net.SplitHostPort(a.String())
+		if got, want := port, "30"; got != want {
+			t.Errorf("got %v, want %v", got, want)
+		}
+	}
+
+	addrs, unspecified, err = netstate.PossibleAddresses("tcp", "192.168.1.10:31", chooser)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got, want := unspecified, false; got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+
+	if got, want := len(addrs), 1; got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+
+	for _, a := range addrs {
+		_, port, _ := net.SplitHostPort(a.String())
+		if got, want := port, "31"; got != want {
+			t.Errorf("got %v, want %v", got, want)
+		}
+	}
+
+}
+
 func TestChooserNoMatches(t *testing.T) {
 	_, ifcs, rt := mockInterfacesAndRouteTable()
 	cleanup := netstate.CreateAndUseMockCache(ifcs, rt)