1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
Chris Telfer f155f828a2 bump libnetwork to 430c00a
Bump libnetwork to 430c00a6a6b3dfdd774f21e1abd4ad6b0216c629.  This
includes the following moby-affecting changes:

 * Update vendoring for go-sockaddr (8df9f31a)
 * Fix inconsistent subnet allocation by preventing allocation of
   overlapping subnets (8579c5d2)
 * Handle IPv6 literals correctly in port bindings (474fcaf4)
 * Update vendoring for miekg/dns (8f307ac8)
 * Avoid subnet reallocation until required (9756ff7ed)
 * Bump libnetwork build to use go version 1.10.2 (603d2c1a)
 * Unwrap error type returned by PluginGetter (aacec8e1)
 * Update vendored components to match moby (d768021dd)
 * Add retry field to cluster-peers probe (dbbd06a7)
 * Fix net driver response loss on createEndpoint (1ab6e506)
   (fixes https://github.com/docker/for-linux/issues/348)

Signed-off-by: Chris Telfer <ctelfer@docker.com>
2018-06-29 11:03:20 -04:00

206 lines
5.2 KiB
Go

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
}