12 TypeUnknown SockAddrType = 0x0
17 // TypeIP is the union of TypeIPv4 and TypeIPv6
21 type SockAddr interface {
22 // CmpRFC returns 0 if SockAddr exactly matches one of the matched RFC
23 // networks, -1 if the receiver is contained within the RFC network, or
24 // 1 if the address is not contained within the RFC.
25 CmpRFC(rfcNum uint, sa SockAddr) int
27 // Contains returns true if the SockAddr arg is contained within the
29 Contains(SockAddr) bool
31 // Equal allows for the comparison of two SockAddrs
34 DialPacketArgs() (string, string)
35 DialStreamArgs() (string, string)
36 ListenPacketArgs() (string, string)
37 ListenStreamArgs() (string, string)
39 // String returns the string representation of SockAddr
42 // Type returns the SockAddrType
46 // sockAddrAttrMap is a map of the SockAddr type-specific attributes.
47 var sockAddrAttrMap map[AttrName]func(SockAddr) string
48 var sockAddrAttrs []AttrName
54 // New creates a new SockAddr from the string. The order in which New()
55 // attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix.
57 // NOTE: New() relies on the heuristic wherein if the path begins with either a
58 // '.' or '/' character before creating a new UnixSock. For UNIX sockets that
59 // are absolute paths or are nested within a sub-directory, this works as
60 // expected, however if the UNIX socket is contained in the current working
61 // directory, this will fail unless the path begins with "./"
62 // (e.g. "./my-local-socket"). Calls directly to NewUnixSock() do not suffer
63 // this limitation. Invalid IP addresses such as "256.0.0.0/-1" will run afoul
64 // of this heuristic and be assumed to be a valid UNIX socket path (which they
65 // are, but it is probably not what you want and you won't realize it until you
66 // stat(2) the file system to discover it doesn't exist).
67 func NewSockAddr(s string) (SockAddr, error) {
68 ipv4Addr, err := NewIPv4Addr(s)
73 ipv6Addr, err := NewIPv6Addr(s)
78 // Check to make sure the string begins with either a '.' or '/', or
80 if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) {
81 unixSock, err := NewUnixSock(s)
87 return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s)
90 // ToIPAddr returns an IPAddr type or nil if the type conversion fails.
91 func ToIPAddr(sa SockAddr) *IPAddr {
92 ipa, ok := sa.(IPAddr)
99 // ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails.
100 func ToIPv4Addr(sa SockAddr) *IPv4Addr {
101 switch v := sa.(type) {
109 // ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails.
110 func ToIPv6Addr(sa SockAddr) *IPv6Addr {
111 switch v := sa.(type) {
119 // ToUnixSock returns a UnixSock type or nil if the type conversion fails.
120 func ToUnixSock(sa SockAddr) *UnixSock {
121 switch v := sa.(type) {
129 // SockAddrAttr returns a string representation of an attribute for the given
131 func SockAddrAttr(sa SockAddr, selector AttrName) string {
132 fn, found := sockAddrAttrMap[selector]
140 // String() for SockAddrType returns a string representation of the
141 // SockAddrType (e.g. "IPv4", "IPv6", "UNIX", "IP", or "unknown").
142 func (sat SockAddrType) String() string {
148 // There is no concrete "IP" type. Leaving here as a reminder.
154 panic("unsupported type")
158 // sockAddrInit is called once at init()
159 func sockAddrInit() {
160 sockAddrAttrs = []AttrName{
161 "type", // type should be first
165 sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{
166 "string": func(sa SockAddr) string {
169 "type": func(sa SockAddr) string {
170 return sa.Type().String()
175 // UnixSockAttrs returns a list of attributes supported by the UnixSock type
176 func SockAddrAttrs() []AttrName {