Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / hashicorp / go-sockaddr / sockaddr.go
1 package sockaddr
2
3 import (
4         "fmt"
5         "strings"
6 )
7
8 type SockAddrType int
9 type AttrName string
10
11 const (
12         TypeUnknown SockAddrType = 0x0
13         TypeUnix                 = 0x1
14         TypeIPv4                 = 0x2
15         TypeIPv6                 = 0x4
16
17         // TypeIP is the union of TypeIPv4 and TypeIPv6
18         TypeIP = 0x6
19 )
20
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
26
27         // Contains returns true if the SockAddr arg is contained within the
28         // receiver
29         Contains(SockAddr) bool
30
31         // Equal allows for the comparison of two SockAddrs
32         Equal(SockAddr) bool
33
34         DialPacketArgs() (string, string)
35         DialStreamArgs() (string, string)
36         ListenPacketArgs() (string, string)
37         ListenStreamArgs() (string, string)
38
39         // String returns the string representation of SockAddr
40         String() string
41
42         // Type returns the SockAddrType
43         Type() SockAddrType
44 }
45
46 // sockAddrAttrMap is a map of the SockAddr type-specific attributes.
47 var sockAddrAttrMap map[AttrName]func(SockAddr) string
48 var sockAddrAttrs []AttrName
49
50 func init() {
51         sockAddrInit()
52 }
53
54 // New creates a new SockAddr from the string.  The order in which New()
55 // attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix.
56 //
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)
69         if err == nil {
70                 return ipv4Addr, nil
71         }
72
73         ipv6Addr, err := NewIPv6Addr(s)
74         if err == nil {
75                 return ipv6Addr, nil
76         }
77
78         // Check to make sure the string begins with either a '.' or '/', or
79         // contains a '/'.
80         if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) {
81                 unixSock, err := NewUnixSock(s)
82                 if err == nil {
83                         return unixSock, nil
84                 }
85         }
86
87         return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s)
88 }
89
90 // ToIPAddr returns an IPAddr type or nil if the type conversion fails.
91 func ToIPAddr(sa SockAddr) *IPAddr {
92         ipa, ok := sa.(IPAddr)
93         if !ok {
94                 return nil
95         }
96         return &ipa
97 }
98
99 // ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails.
100 func ToIPv4Addr(sa SockAddr) *IPv4Addr {
101         switch v := sa.(type) {
102         case IPv4Addr:
103                 return &v
104         default:
105                 return nil
106         }
107 }
108
109 // ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails.
110 func ToIPv6Addr(sa SockAddr) *IPv6Addr {
111         switch v := sa.(type) {
112         case IPv6Addr:
113                 return &v
114         default:
115                 return nil
116         }
117 }
118
119 // ToUnixSock returns a UnixSock type or nil if the type conversion fails.
120 func ToUnixSock(sa SockAddr) *UnixSock {
121         switch v := sa.(type) {
122         case UnixSock:
123                 return &v
124         default:
125                 return nil
126         }
127 }
128
129 // SockAddrAttr returns a string representation of an attribute for the given
130 // SockAddr.
131 func SockAddrAttr(sa SockAddr, selector AttrName) string {
132         fn, found := sockAddrAttrMap[selector]
133         if !found {
134                 return ""
135         }
136
137         return fn(sa)
138 }
139
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 {
143         switch sat {
144         case TypeIPv4:
145                 return "IPv4"
146         case TypeIPv6:
147                 return "IPv6"
148         // There is no concrete "IP" type.  Leaving here as a reminder.
149         // case TypeIP:
150         //      return "IP"
151         case TypeUnix:
152                 return "UNIX"
153         default:
154                 panic("unsupported type")
155         }
156 }
157
158 // sockAddrInit is called once at init()
159 func sockAddrInit() {
160         sockAddrAttrs = []AttrName{
161                 "type", // type should be first
162                 "string",
163         }
164
165         sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{
166                 "string": func(sa SockAddr) string {
167                         return sa.String()
168                 },
169                 "type": func(sa SockAddr) string {
170                         return sa.Type().String()
171                 },
172         }
173 }
174
175 // UnixSockAttrs returns a list of attributes supported by the UnixSock type
176 func SockAddrAttrs() []AttrName {
177         return sockAddrAttrs
178 }