aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-sockaddr/sockaddr.go')
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/sockaddr.go206
1 files changed, 206 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
new file mode 100644
index 0000000..826c91c
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
@@ -0,0 +1,206 @@
+package sockaddr
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type SockAddrType int
+type AttrName string
+
+const (
+ TypeUnknown SockAddrType = 0x0
+ TypeUnix = 0x1
+ TypeIPv4 = 0x2
+ TypeIPv6 = 0x4
+
+ // TypeIP is the union of TypeIPv4 and TypeIPv6
+ TypeIP = 0x6
+)
+
+type SockAddr interface {
+ // CmpRFC returns 0 if SockAddr exactly matches one of the matched RFC
+ // networks, -1 if the receiver is contained within the RFC network, or
+ // 1 if the address is not contained within the RFC.
+ CmpRFC(rfcNum uint, sa SockAddr) int
+
+ // Contains returns true if the SockAddr arg is contained within the
+ // receiver
+ Contains(SockAddr) bool
+
+ // Equal allows for the comparison of two SockAddrs
+ Equal(SockAddr) bool
+
+ DialPacketArgs() (string, string)
+ DialStreamArgs() (string, string)
+ ListenPacketArgs() (string, string)
+ ListenStreamArgs() (string, string)
+
+ // String returns the string representation of SockAddr
+ String() string
+
+ // Type returns the SockAddrType
+ Type() SockAddrType
+}
+
+// sockAddrAttrMap is a map of the SockAddr type-specific attributes.
+var sockAddrAttrMap map[AttrName]func(SockAddr) string
+var sockAddrAttrs []AttrName
+
+func init() {
+ sockAddrInit()
+}
+
+// New creates a new SockAddr from the string. The order in which New()
+// attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix.
+//
+// NOTE: New() relies on the heuristic wherein if the path begins with either a
+// '.' or '/' character before creating a new UnixSock. For UNIX sockets that
+// are absolute paths or are nested within a sub-directory, this works as
+// expected, however if the UNIX socket is contained in the current working
+// directory, this will fail unless the path begins with "./"
+// (e.g. "./my-local-socket"). Calls directly to NewUnixSock() do not suffer
+// this limitation. Invalid IP addresses such as "256.0.0.0/-1" will run afoul
+// of this heuristic and be assumed to be a valid UNIX socket path (which they
+// are, but it is probably not what you want and you won't realize it until you
+// stat(2) the file system to discover it doesn't exist).
+func NewSockAddr(s string) (SockAddr, error) {
+ ipv4Addr, err := NewIPv4Addr(s)
+ if err == nil {
+ return ipv4Addr, nil
+ }
+
+ ipv6Addr, err := NewIPv6Addr(s)
+ if err == nil {
+ return ipv6Addr, nil
+ }
+
+ // Check to make sure the string begins with either a '.' or '/', or
+ // contains a '/'.
+ if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) {
+ unixSock, err := NewUnixSock(s)
+ if err == nil {
+ return unixSock, nil
+ }
+ }
+
+ return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s)
+}
+
+// ToIPAddr returns an IPAddr type or nil if the type conversion fails.
+func ToIPAddr(sa SockAddr) *IPAddr {
+ ipa, ok := sa.(IPAddr)
+ if !ok {
+ return nil
+ }
+ return &ipa
+}
+
+// ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails.
+func ToIPv4Addr(sa SockAddr) *IPv4Addr {
+ switch v := sa.(type) {
+ case IPv4Addr:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails.
+func ToIPv6Addr(sa SockAddr) *IPv6Addr {
+ switch v := sa.(type) {
+ case IPv6Addr:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// ToUnixSock returns a UnixSock type or nil if the type conversion fails.
+func ToUnixSock(sa SockAddr) *UnixSock {
+ switch v := sa.(type) {
+ case UnixSock:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// SockAddrAttr returns a string representation of an attribute for the given
+// SockAddr.
+func SockAddrAttr(sa SockAddr, selector AttrName) string {
+ fn, found := sockAddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(sa)
+}
+
+// String() for SockAddrType returns a string representation of the
+// SockAddrType (e.g. "IPv4", "IPv6", "UNIX", "IP", or "unknown").
+func (sat SockAddrType) String() string {
+ switch sat {
+ case TypeIPv4:
+ return "IPv4"
+ case TypeIPv6:
+ return "IPv6"
+ // There is no concrete "IP" type. Leaving here as a reminder.
+ // case TypeIP:
+ // return "IP"
+ case TypeUnix:
+ return "UNIX"
+ default:
+ panic("unsupported type")
+ }
+}
+
+// sockAddrInit is called once at init()
+func sockAddrInit() {
+ sockAddrAttrs = []AttrName{
+ "type", // type should be first
+ "string",
+ }
+
+ sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{
+ "string": func(sa SockAddr) string {
+ return sa.String()
+ },
+ "type": func(sa SockAddr) string {
+ return sa.Type().String()
+ },
+ }
+}
+
+// UnixSockAttrs returns a list of attributes supported by the UnixSock type
+func SockAddrAttrs() []AttrName {
+ return sockAddrAttrs
+}
+
+// Although this is pretty trivial to do in a program, having the logic here is
+// useful all around. Note that this marshals into a *string* -- the underlying
+// string representation of the sockaddr. If you then unmarshal into this type
+// in Go, all will work as expected, but externally you can take what comes out
+// and use the string value directly.
+type SockAddrMarshaler struct {
+ SockAddr
+}
+
+func (s *SockAddrMarshaler) MarshalJSON() ([]byte, error) {
+ return json.Marshal(s.SockAddr.String())
+}
+
+func (s *SockAddrMarshaler) UnmarshalJSON(in []byte) error {
+ var str string
+ err := json.Unmarshal(in, &str)
+ if err != nil {
+ return err
+ }
+ sa, err := NewSockAddr(str)
+ if err != nil {
+ return err
+ }
+ s.SockAddr = sa
+ return nil
+}