[mqtt] Implements mqtt publish tooling
This commit is contained in:
		
							
								
								
									
										191
									
								
								vendor/github.com/docker/go-connections/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/docker/go-connections/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
 | 
			
		||||
                                 Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        https://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
   Copyright 2015 Docker, Inc.
 | 
			
		||||
 | 
			
		||||
   Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
   you may not use this file except in compliance with the License.
 | 
			
		||||
   You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
       https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
   Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
   distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
   See the License for the specific language governing permissions and
 | 
			
		||||
   limitations under the License.
 | 
			
		||||
							
								
								
									
										242
									
								
								vendor/github.com/docker/go-connections/nat/nat.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								vendor/github.com/docker/go-connections/nat/nat.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,242 @@
 | 
			
		||||
// Package nat is a convenience package for manipulation of strings describing network ports.
 | 
			
		||||
package nat
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// portSpecTemplate is the expected format for port specifications
 | 
			
		||||
	portSpecTemplate = "ip:hostPort:containerPort"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PortBinding represents a binding between a Host IP address and a Host Port
 | 
			
		||||
type PortBinding struct {
 | 
			
		||||
	// HostIP is the host IP Address
 | 
			
		||||
	HostIP string `json:"HostIp"`
 | 
			
		||||
	// HostPort is the host port number
 | 
			
		||||
	HostPort string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PortMap is a collection of PortBinding indexed by Port
 | 
			
		||||
type PortMap map[Port][]PortBinding
 | 
			
		||||
 | 
			
		||||
// PortSet is a collection of structs indexed by Port
 | 
			
		||||
type PortSet map[Port]struct{}
 | 
			
		||||
 | 
			
		||||
// Port is a string containing port number and protocol in the format "80/tcp"
 | 
			
		||||
type Port string
 | 
			
		||||
 | 
			
		||||
// NewPort creates a new instance of a Port given a protocol and port number or port range
 | 
			
		||||
func NewPort(proto, port string) (Port, error) {
 | 
			
		||||
	// Check for parsing issues on "port" now so we can avoid having
 | 
			
		||||
	// to check it later on.
 | 
			
		||||
 | 
			
		||||
	portStartInt, portEndInt, err := ParsePortRangeToInt(port)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if portStartInt == portEndInt {
 | 
			
		||||
		return Port(fmt.Sprintf("%d/%s", portStartInt, proto)), nil
 | 
			
		||||
	}
 | 
			
		||||
	return Port(fmt.Sprintf("%d-%d/%s", portStartInt, portEndInt, proto)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParsePort parses the port number string and returns an int
 | 
			
		||||
func ParsePort(rawPort string) (int, error) {
 | 
			
		||||
	if len(rawPort) == 0 {
 | 
			
		||||
		return 0, nil
 | 
			
		||||
	}
 | 
			
		||||
	port, err := strconv.ParseUint(rawPort, 10, 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return int(port), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParsePortRangeToInt parses the port range string and returns start/end ints
 | 
			
		||||
func ParsePortRangeToInt(rawPort string) (int, int, error) {
 | 
			
		||||
	if len(rawPort) == 0 {
 | 
			
		||||
		return 0, 0, nil
 | 
			
		||||
	}
 | 
			
		||||
	start, end, err := ParsePortRange(rawPort)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return int(start), int(end), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Proto returns the protocol of a Port
 | 
			
		||||
func (p Port) Proto() string {
 | 
			
		||||
	proto, _ := SplitProtoPort(string(p))
 | 
			
		||||
	return proto
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Port returns the port number of a Port
 | 
			
		||||
func (p Port) Port() string {
 | 
			
		||||
	_, port := SplitProtoPort(string(p))
 | 
			
		||||
	return port
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int returns the port number of a Port as an int
 | 
			
		||||
func (p Port) Int() int {
 | 
			
		||||
	portStr := p.Port()
 | 
			
		||||
	// We don't need to check for an error because we're going to
 | 
			
		||||
	// assume that any error would have been found, and reported, in NewPort()
 | 
			
		||||
	port, _ := ParsePort(portStr)
 | 
			
		||||
	return port
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Range returns the start/end port numbers of a Port range as ints
 | 
			
		||||
func (p Port) Range() (int, int, error) {
 | 
			
		||||
	return ParsePortRangeToInt(p.Port())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SplitProtoPort splits a port in the format of proto/port
 | 
			
		||||
func SplitProtoPort(rawPort string) (string, string) {
 | 
			
		||||
	parts := strings.Split(rawPort, "/")
 | 
			
		||||
	l := len(parts)
 | 
			
		||||
	if len(rawPort) == 0 || l == 0 || len(parts[0]) == 0 {
 | 
			
		||||
		return "", ""
 | 
			
		||||
	}
 | 
			
		||||
	if l == 1 {
 | 
			
		||||
		return "tcp", rawPort
 | 
			
		||||
	}
 | 
			
		||||
	if len(parts[1]) == 0 {
 | 
			
		||||
		return "tcp", parts[0]
 | 
			
		||||
	}
 | 
			
		||||
	return parts[1], parts[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateProto(proto string) bool {
 | 
			
		||||
	for _, availableProto := range []string{"tcp", "udp", "sctp"} {
 | 
			
		||||
		if availableProto == proto {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParsePortSpecs receives port specs in the format of ip:public:private/proto and parses
 | 
			
		||||
// these in to the internal types
 | 
			
		||||
func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		exposedPorts = make(map[Port]struct{}, len(ports))
 | 
			
		||||
		bindings     = make(map[Port][]PortBinding)
 | 
			
		||||
	)
 | 
			
		||||
	for _, rawPort := range ports {
 | 
			
		||||
		portMappings, err := ParsePortSpec(rawPort)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, portMapping := range portMappings {
 | 
			
		||||
			port := portMapping.Port
 | 
			
		||||
			if _, exists := exposedPorts[port]; !exists {
 | 
			
		||||
				exposedPorts[port] = struct{}{}
 | 
			
		||||
			}
 | 
			
		||||
			bslice, exists := bindings[port]
 | 
			
		||||
			if !exists {
 | 
			
		||||
				bslice = []PortBinding{}
 | 
			
		||||
			}
 | 
			
		||||
			bindings[port] = append(bslice, portMapping.Binding)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return exposedPorts, bindings, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PortMapping is a data object mapping a Port to a PortBinding
 | 
			
		||||
type PortMapping struct {
 | 
			
		||||
	Port    Port
 | 
			
		||||
	Binding PortBinding
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func splitParts(rawport string) (string, string, string) {
 | 
			
		||||
	parts := strings.Split(rawport, ":")
 | 
			
		||||
	n := len(parts)
 | 
			
		||||
	containerport := parts[n-1]
 | 
			
		||||
 | 
			
		||||
	switch n {
 | 
			
		||||
	case 1:
 | 
			
		||||
		return "", "", containerport
 | 
			
		||||
	case 2:
 | 
			
		||||
		return "", parts[0], containerport
 | 
			
		||||
	case 3:
 | 
			
		||||
		return parts[0], parts[1], containerport
 | 
			
		||||
	default:
 | 
			
		||||
		return strings.Join(parts[:n-2], ":"), parts[n-2], containerport
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParsePortSpec parses a port specification string into a slice of PortMappings
 | 
			
		||||
func ParsePortSpec(rawPort string) ([]PortMapping, error) {
 | 
			
		||||
	var proto string
 | 
			
		||||
	rawIP, hostPort, containerPort := splitParts(rawPort)
 | 
			
		||||
	proto, containerPort = SplitProtoPort(containerPort)
 | 
			
		||||
 | 
			
		||||
	// Strip [] from IPV6 addresses
 | 
			
		||||
	ip, _, err := net.SplitHostPort(rawIP + ":")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Invalid ip address %v: %s", rawIP, err)
 | 
			
		||||
	}
 | 
			
		||||
	if ip != "" && net.ParseIP(ip) == nil {
 | 
			
		||||
		return nil, fmt.Errorf("Invalid ip address: %s", ip)
 | 
			
		||||
	}
 | 
			
		||||
	if containerPort == "" {
 | 
			
		||||
		return nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	startPort, endPort, err := ParsePortRange(containerPort)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var startHostPort, endHostPort uint64 = 0, 0
 | 
			
		||||
	if len(hostPort) > 0 {
 | 
			
		||||
		startHostPort, endHostPort, err = ParsePortRange(hostPort)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) {
 | 
			
		||||
		// Allow host port range iff containerPort is not a range.
 | 
			
		||||
		// In this case, use the host port range as the dynamic
 | 
			
		||||
		// host port range to allocate into.
 | 
			
		||||
		if endPort != startPort {
 | 
			
		||||
			return nil, fmt.Errorf("Invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !validateProto(strings.ToLower(proto)) {
 | 
			
		||||
		return nil, fmt.Errorf("Invalid proto: %s", proto)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ports := []PortMapping{}
 | 
			
		||||
	for i := uint64(0); i <= (endPort - startPort); i++ {
 | 
			
		||||
		containerPort = strconv.FormatUint(startPort+i, 10)
 | 
			
		||||
		if len(hostPort) > 0 {
 | 
			
		||||
			hostPort = strconv.FormatUint(startHostPort+i, 10)
 | 
			
		||||
		}
 | 
			
		||||
		// Set hostPort to a range only if there is a single container port
 | 
			
		||||
		// and a dynamic host port.
 | 
			
		||||
		if startPort == endPort && startHostPort != endHostPort {
 | 
			
		||||
			hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10))
 | 
			
		||||
		}
 | 
			
		||||
		port, err := NewPort(strings.ToLower(proto), containerPort)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		binding := PortBinding{
 | 
			
		||||
			HostIP:   ip,
 | 
			
		||||
			HostPort: hostPort,
 | 
			
		||||
		}
 | 
			
		||||
		ports = append(ports, PortMapping{Port: port, Binding: binding})
 | 
			
		||||
	}
 | 
			
		||||
	return ports, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								vendor/github.com/docker/go-connections/nat/parse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								vendor/github.com/docker/go-connections/nat/parse.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
package nat
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PartParser parses and validates the specified string (data) using the specified template
 | 
			
		||||
// e.g. ip:public:private -> 192.168.0.1:80:8000
 | 
			
		||||
// DEPRECATED: do not use, this function may be removed in a future version
 | 
			
		||||
func PartParser(template, data string) (map[string]string, error) {
 | 
			
		||||
	// ip:public:private
 | 
			
		||||
	var (
 | 
			
		||||
		templateParts = strings.Split(template, ":")
 | 
			
		||||
		parts         = strings.Split(data, ":")
 | 
			
		||||
		out           = make(map[string]string, len(templateParts))
 | 
			
		||||
	)
 | 
			
		||||
	if len(parts) != len(templateParts) {
 | 
			
		||||
		return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, t := range templateParts {
 | 
			
		||||
		value := ""
 | 
			
		||||
		if len(parts) > i {
 | 
			
		||||
			value = parts[i]
 | 
			
		||||
		}
 | 
			
		||||
		out[t] = value
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParsePortRange parses and validates the specified string as a port-range (8000-9000)
 | 
			
		||||
func ParsePortRange(ports string) (uint64, uint64, error) {
 | 
			
		||||
	if ports == "" {
 | 
			
		||||
		return 0, 0, fmt.Errorf("Empty string specified for ports.")
 | 
			
		||||
	}
 | 
			
		||||
	if !strings.Contains(ports, "-") {
 | 
			
		||||
		start, err := strconv.ParseUint(ports, 10, 16)
 | 
			
		||||
		end := start
 | 
			
		||||
		return start, end, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parts := strings.Split(ports, "-")
 | 
			
		||||
	start, err := strconv.ParseUint(parts[0], 10, 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	end, err := strconv.ParseUint(parts[1], 10, 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if end < start {
 | 
			
		||||
		return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports)
 | 
			
		||||
	}
 | 
			
		||||
	return start, end, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								vendor/github.com/docker/go-connections/nat/sort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								vendor/github.com/docker/go-connections/nat/sort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
package nat
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type portSorter struct {
 | 
			
		||||
	ports []Port
 | 
			
		||||
	by    func(i, j Port) bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *portSorter) Len() int {
 | 
			
		||||
	return len(s.ports)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *portSorter) Swap(i, j int) {
 | 
			
		||||
	s.ports[i], s.ports[j] = s.ports[j], s.ports[i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *portSorter) Less(i, j int) bool {
 | 
			
		||||
	ip := s.ports[i]
 | 
			
		||||
	jp := s.ports[j]
 | 
			
		||||
 | 
			
		||||
	return s.by(ip, jp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sort sorts a list of ports using the provided predicate
 | 
			
		||||
// This function should compare `i` and `j`, returning true if `i` is
 | 
			
		||||
// considered to be less than `j`
 | 
			
		||||
func Sort(ports []Port, predicate func(i, j Port) bool) {
 | 
			
		||||
	s := &portSorter{ports, predicate}
 | 
			
		||||
	sort.Sort(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type portMapEntry struct {
 | 
			
		||||
	port    Port
 | 
			
		||||
	binding PortBinding
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type portMapSorter []portMapEntry
 | 
			
		||||
 | 
			
		||||
func (s portMapSorter) Len() int      { return len(s) }
 | 
			
		||||
func (s portMapSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
 | 
			
		||||
 | 
			
		||||
// sort the port so that the order is:
 | 
			
		||||
// 1. port with larger specified bindings
 | 
			
		||||
// 2. larger port
 | 
			
		||||
// 3. port with tcp protocol
 | 
			
		||||
func (s portMapSorter) Less(i, j int) bool {
 | 
			
		||||
	pi, pj := s[i].port, s[j].port
 | 
			
		||||
	hpi, hpj := toInt(s[i].binding.HostPort), toInt(s[j].binding.HostPort)
 | 
			
		||||
	return hpi > hpj || pi.Int() > pj.Int() || (pi.Int() == pj.Int() && strings.ToLower(pi.Proto()) == "tcp")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SortPortMap sorts the list of ports and their respected mapping. The ports
 | 
			
		||||
// will explicit HostPort will be placed first.
 | 
			
		||||
func SortPortMap(ports []Port, bindings PortMap) {
 | 
			
		||||
	s := portMapSorter{}
 | 
			
		||||
	for _, p := range ports {
 | 
			
		||||
		if binding, ok := bindings[p]; ok {
 | 
			
		||||
			for _, b := range binding {
 | 
			
		||||
				s = append(s, portMapEntry{port: p, binding: b})
 | 
			
		||||
			}
 | 
			
		||||
			bindings[p] = []PortBinding{}
 | 
			
		||||
		} else {
 | 
			
		||||
			s = append(s, portMapEntry{port: p})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Sort(s)
 | 
			
		||||
	var (
 | 
			
		||||
		i  int
 | 
			
		||||
		pm = make(map[Port]struct{})
 | 
			
		||||
	)
 | 
			
		||||
	// reorder ports
 | 
			
		||||
	for _, entry := range s {
 | 
			
		||||
		if _, ok := pm[entry.port]; !ok {
 | 
			
		||||
			ports[i] = entry.port
 | 
			
		||||
			pm[entry.port] = struct{}{}
 | 
			
		||||
			i++
 | 
			
		||||
		}
 | 
			
		||||
		// reorder bindings for this port
 | 
			
		||||
		if _, ok := bindings[entry.port]; ok {
 | 
			
		||||
			bindings[entry.port] = append(bindings[entry.port], entry.binding)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toInt(s string) uint64 {
 | 
			
		||||
	i, _, err := ParsePortRange(s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		i = 0
 | 
			
		||||
	}
 | 
			
		||||
	return i
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										0
									
								
								vendor/github.com/docker/go-connections/sockets/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								vendor/github.com/docker/go-connections/sockets/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										81
									
								
								vendor/github.com/docker/go-connections/sockets/inmem_socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/github.com/docker/go-connections/sockets/inmem_socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var errClosed = errors.New("use of closed network connection")
 | 
			
		||||
 | 
			
		||||
// InmemSocket implements net.Listener using in-memory only connections.
 | 
			
		||||
type InmemSocket struct {
 | 
			
		||||
	chConn  chan net.Conn
 | 
			
		||||
	chClose chan struct{}
 | 
			
		||||
	addr    string
 | 
			
		||||
	mu      sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dummyAddr is used to satisfy net.Addr for the in-mem socket
 | 
			
		||||
// it is just stored as a string and returns the string for all calls
 | 
			
		||||
type dummyAddr string
 | 
			
		||||
 | 
			
		||||
// NewInmemSocket creates an in-memory only net.Listener
 | 
			
		||||
// The addr argument can be any string, but is used to satisfy the `Addr()` part
 | 
			
		||||
// of the net.Listener interface
 | 
			
		||||
func NewInmemSocket(addr string, bufSize int) *InmemSocket {
 | 
			
		||||
	return &InmemSocket{
 | 
			
		||||
		chConn:  make(chan net.Conn, bufSize),
 | 
			
		||||
		chClose: make(chan struct{}),
 | 
			
		||||
		addr:    addr,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Addr returns the socket's addr string to satisfy net.Listener
 | 
			
		||||
func (s *InmemSocket) Addr() net.Addr {
 | 
			
		||||
	return dummyAddr(s.addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
 | 
			
		||||
func (s *InmemSocket) Accept() (net.Conn, error) {
 | 
			
		||||
	select {
 | 
			
		||||
	case conn := <-s.chConn:
 | 
			
		||||
		return conn, nil
 | 
			
		||||
	case <-s.chClose:
 | 
			
		||||
		return nil, errClosed
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close closes the listener. It will be unavailable for use once closed.
 | 
			
		||||
func (s *InmemSocket) Close() error {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
	select {
 | 
			
		||||
	case <-s.chClose:
 | 
			
		||||
	default:
 | 
			
		||||
		close(s.chClose)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dial is used to establish a connection with the in-mem server
 | 
			
		||||
func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) {
 | 
			
		||||
	srvConn, clientConn := net.Pipe()
 | 
			
		||||
	select {
 | 
			
		||||
	case s.chConn <- srvConn:
 | 
			
		||||
	case <-s.chClose:
 | 
			
		||||
		return nil, errClosed
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return clientConn, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Network returns the addr string, satisfies net.Addr
 | 
			
		||||
func (a dummyAddr) Network() string {
 | 
			
		||||
	return string(a)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns the string form
 | 
			
		||||
func (a dummyAddr) String() string {
 | 
			
		||||
	return string(a)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/github.com/docker/go-connections/sockets/proxy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/docker/go-connections/sockets/proxy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/proxy"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetProxyEnv allows access to the uppercase and the lowercase forms of
 | 
			
		||||
// proxy-related variables.  See the Go specification for details on these
 | 
			
		||||
// variables. https://golang.org/pkg/net/http/
 | 
			
		||||
func GetProxyEnv(key string) string {
 | 
			
		||||
	proxyValue := os.Getenv(strings.ToUpper(key))
 | 
			
		||||
	if proxyValue == "" {
 | 
			
		||||
		return os.Getenv(strings.ToLower(key))
 | 
			
		||||
	}
 | 
			
		||||
	return proxyValue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DialerFromEnvironment takes in a "direct" *net.Dialer and returns a
 | 
			
		||||
// proxy.Dialer which will route the connections through the proxy using the
 | 
			
		||||
// given dialer.
 | 
			
		||||
func DialerFromEnvironment(direct *net.Dialer) (proxy.Dialer, error) {
 | 
			
		||||
	allProxy := GetProxyEnv("all_proxy")
 | 
			
		||||
	if len(allProxy) == 0 {
 | 
			
		||||
		return direct, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proxyURL, err := url.Parse(allProxy)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return direct, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proxyFromURL, err := proxy.FromURL(proxyURL, direct)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return direct, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	noProxy := GetProxyEnv("no_proxy")
 | 
			
		||||
	if len(noProxy) == 0 {
 | 
			
		||||
		return proxyFromURL, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	perHost := proxy.NewPerHost(proxyFromURL, direct)
 | 
			
		||||
	perHost.AddFromString(noProxy)
 | 
			
		||||
 | 
			
		||||
	return perHost, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								vendor/github.com/docker/go-connections/sockets/sockets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/docker/go-connections/sockets/sockets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
// Package sockets provides helper functions to create and configure Unix or TCP sockets.
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Why 32? See https://github.com/docker/docker/pull/8035.
 | 
			
		||||
const defaultTimeout = 32 * time.Second
 | 
			
		||||
 | 
			
		||||
// ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system.
 | 
			
		||||
var ErrProtocolNotAvailable = errors.New("protocol not available")
 | 
			
		||||
 | 
			
		||||
// ConfigureTransport configures the specified Transport according to the
 | 
			
		||||
// specified proto and addr.
 | 
			
		||||
// If the proto is unix (using a unix socket to communicate) or npipe the
 | 
			
		||||
// compression is disabled.
 | 
			
		||||
func ConfigureTransport(tr *http.Transport, proto, addr string) error {
 | 
			
		||||
	switch proto {
 | 
			
		||||
	case "unix":
 | 
			
		||||
		return configureUnixTransport(tr, proto, addr)
 | 
			
		||||
	case "npipe":
 | 
			
		||||
		return configureNpipeTransport(tr, proto, addr)
 | 
			
		||||
	default:
 | 
			
		||||
		tr.Proxy = http.ProxyFromEnvironment
 | 
			
		||||
		dialer, err := DialerFromEnvironment(&net.Dialer{
 | 
			
		||||
			Timeout: defaultTimeout,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		tr.Dial = dialer.Dial
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								vendor/github.com/docker/go-connections/sockets/sockets_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/docker/go-connections/sockets/sockets_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
 | 
			
		||||
 | 
			
		||||
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
 | 
			
		||||
	if len(addr) > maxUnixSocketPathSize {
 | 
			
		||||
		return fmt.Errorf("Unix socket path %q is too long", addr)
 | 
			
		||||
	}
 | 
			
		||||
	// No need for compression in local communications.
 | 
			
		||||
	tr.DisableCompression = true
 | 
			
		||||
	tr.Dial = func(_, _ string) (net.Conn, error) {
 | 
			
		||||
		return net.DialTimeout(proto, addr, defaultTimeout)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
 | 
			
		||||
	return ErrProtocolNotAvailable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DialPipe connects to a Windows named pipe.
 | 
			
		||||
// This is not supported on other OSes.
 | 
			
		||||
func DialPipe(_ string, _ time.Duration) (net.Conn, error) {
 | 
			
		||||
	return nil, syscall.EAFNOSUPPORT
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/github.com/docker/go-connections/sockets/sockets_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/docker/go-connections/sockets/sockets_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/Microsoft/go-winio"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
 | 
			
		||||
	return ErrProtocolNotAvailable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
 | 
			
		||||
	// No need for compression in local communications.
 | 
			
		||||
	tr.DisableCompression = true
 | 
			
		||||
	tr.Dial = func(_, _ string) (net.Conn, error) {
 | 
			
		||||
		return DialPipe(addr, defaultTimeout)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DialPipe connects to a Windows named pipe.
 | 
			
		||||
func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
 | 
			
		||||
	return winio.DialPipe(addr, &timeout)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/docker/go-connections/sockets/tcp_socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/docker/go-connections/sockets/tcp_socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
// Package sockets provides helper functions to create and configure Unix or TCP sockets.
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewTCPSocket creates a TCP socket listener with the specified address and
 | 
			
		||||
// the specified tls configuration. If TLSConfig is set, will encapsulate the
 | 
			
		||||
// TCP listener inside a TLS one.
 | 
			
		||||
func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
 | 
			
		||||
	l, err := net.Listen("tcp", addr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if tlsConfig != nil {
 | 
			
		||||
		tlsConfig.NextProtos = []string{"http/1.1"}
 | 
			
		||||
		l = tls.NewListener(l, tlsConfig)
 | 
			
		||||
	}
 | 
			
		||||
	return l, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/github.com/docker/go-connections/sockets/unix_socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/docker/go-connections/sockets/unix_socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewUnixSocket creates a unix socket with the specified path and group.
 | 
			
		||||
func NewUnixSocket(path string, gid int) (net.Listener, error) {
 | 
			
		||||
	if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	mask := syscall.Umask(0777)
 | 
			
		||||
	defer syscall.Umask(mask)
 | 
			
		||||
 | 
			
		||||
	l, err := net.Listen("unix", path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := os.Chown(path, 0, gid); err != nil {
 | 
			
		||||
		l.Close()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := os.Chmod(path, 0660); err != nil {
 | 
			
		||||
		l.Close()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return l, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/docker/go-connections/tlsconfig/certpool_go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
// +build go1.7
 | 
			
		||||
 | 
			
		||||
package tlsconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SystemCertPool returns a copy of the system cert pool,
 | 
			
		||||
// returns an error if failed to load or empty pool on windows.
 | 
			
		||||
func SystemCertPool() (*x509.CertPool, error) {
 | 
			
		||||
	certpool, err := x509.SystemCertPool()
 | 
			
		||||
	if err != nil && runtime.GOOS == "windows" {
 | 
			
		||||
		return x509.NewCertPool(), nil
 | 
			
		||||
	}
 | 
			
		||||
	return certpool, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/docker/go-connections/tlsconfig/certpool_other.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
// +build !go1.7
 | 
			
		||||
 | 
			
		||||
package tlsconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SystemCertPool returns an new empty cert pool,
 | 
			
		||||
// accessing system cert pool is supported in go 1.7
 | 
			
		||||
func SystemCertPool() (*x509.CertPool, error) {
 | 
			
		||||
	return x509.NewCertPool(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										254
									
								
								vendor/github.com/docker/go-connections/tlsconfig/config.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								vendor/github.com/docker/go-connections/tlsconfig/config.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
 | 
			
		||||
//
 | 
			
		||||
// As a reminder from https://golang.org/pkg/crypto/tls/#Config:
 | 
			
		||||
//	A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified.
 | 
			
		||||
//	A Config may be reused; the tls package will also not modify it.
 | 
			
		||||
package tlsconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"encoding/pem"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Options represents the information needed to create client and server TLS configurations.
 | 
			
		||||
type Options struct {
 | 
			
		||||
	CAFile string
 | 
			
		||||
 | 
			
		||||
	// If either CertFile or KeyFile is empty, Client() will not load them
 | 
			
		||||
	// preventing the client from authenticating to the server.
 | 
			
		||||
	// However, Server() requires them and will error out if they are empty.
 | 
			
		||||
	CertFile string
 | 
			
		||||
	KeyFile  string
 | 
			
		||||
 | 
			
		||||
	// client-only option
 | 
			
		||||
	InsecureSkipVerify bool
 | 
			
		||||
	// server-only option
 | 
			
		||||
	ClientAuth tls.ClientAuthType
 | 
			
		||||
	// If ExclusiveRootPools is set, then if a CA file is provided, the root pool used for TLS
 | 
			
		||||
	// creds will include exclusively the roots in that CA file.  If no CA file is provided,
 | 
			
		||||
	// the system pool will be used.
 | 
			
		||||
	ExclusiveRootPools bool
 | 
			
		||||
	MinVersion         uint16
 | 
			
		||||
	// If Passphrase is set, it will be used to decrypt a TLS private key
 | 
			
		||||
	// if the key is encrypted
 | 
			
		||||
	Passphrase string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extra (server-side) accepted CBC cipher suites - will phase out in the future
 | 
			
		||||
var acceptedCBCCiphers = []uint16{
 | 
			
		||||
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
 | 
			
		||||
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
 | 
			
		||||
	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
 | 
			
		||||
	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls
 | 
			
		||||
// options struct but wants to use a commonly accepted set of TLS cipher suites, with
 | 
			
		||||
// known weak algorithms removed.
 | 
			
		||||
var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
 | 
			
		||||
 | 
			
		||||
// allTLSVersions lists all the TLS versions and is used by the code that validates
 | 
			
		||||
// a uint16 value as a TLS version.
 | 
			
		||||
var allTLSVersions = map[uint16]struct{}{
 | 
			
		||||
	tls.VersionSSL30: {},
 | 
			
		||||
	tls.VersionTLS10: {},
 | 
			
		||||
	tls.VersionTLS11: {},
 | 
			
		||||
	tls.VersionTLS12: {},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
 | 
			
		||||
func ServerDefault(ops ...func(*tls.Config)) *tls.Config {
 | 
			
		||||
	tlsconfig := &tls.Config{
 | 
			
		||||
		// Avoid fallback by default to SSL protocols < TLS1.2
 | 
			
		||||
		MinVersion:               tls.VersionTLS12,
 | 
			
		||||
		PreferServerCipherSuites: true,
 | 
			
		||||
		CipherSuites:             DefaultServerAcceptedCiphers,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, op := range ops {
 | 
			
		||||
		op(tlsconfig)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tlsconfig
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClientDefault returns a secure-enough TLS configuration for the client TLS configuration.
 | 
			
		||||
func ClientDefault(ops ...func(*tls.Config)) *tls.Config {
 | 
			
		||||
	tlsconfig := &tls.Config{
 | 
			
		||||
		// Prefer TLS1.2 as the client minimum
 | 
			
		||||
		MinVersion:   tls.VersionTLS12,
 | 
			
		||||
		CipherSuites: clientCipherSuites,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, op := range ops {
 | 
			
		||||
		op(tlsconfig)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tlsconfig
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
 | 
			
		||||
func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
 | 
			
		||||
	// If we should verify the server, we need to load a trusted ca
 | 
			
		||||
	var (
 | 
			
		||||
		certPool *x509.CertPool
 | 
			
		||||
		err      error
 | 
			
		||||
	)
 | 
			
		||||
	if exclusivePool {
 | 
			
		||||
		certPool = x509.NewCertPool()
 | 
			
		||||
	} else {
 | 
			
		||||
		certPool, err = SystemCertPool()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("failed to read system certificates: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	pem, err := ioutil.ReadFile(caFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
 | 
			
		||||
	}
 | 
			
		||||
	if !certPool.AppendCertsFromPEM(pem) {
 | 
			
		||||
		return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
 | 
			
		||||
	}
 | 
			
		||||
	return certPool, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// isValidMinVersion checks that the input value is a valid tls minimum version
 | 
			
		||||
func isValidMinVersion(version uint16) bool {
 | 
			
		||||
	_, ok := allTLSVersions[version]
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// adjustMinVersion sets the MinVersion on `config`, the input configuration.
 | 
			
		||||
// It assumes the current MinVersion on the `config` is the lowest allowed.
 | 
			
		||||
func adjustMinVersion(options Options, config *tls.Config) error {
 | 
			
		||||
	if options.MinVersion > 0 {
 | 
			
		||||
		if !isValidMinVersion(options.MinVersion) {
 | 
			
		||||
			return fmt.Errorf("Invalid minimum TLS version: %x", options.MinVersion)
 | 
			
		||||
		}
 | 
			
		||||
		if options.MinVersion < config.MinVersion {
 | 
			
		||||
			return fmt.Errorf("Requested minimum TLS version is too low. Should be at-least: %x", config.MinVersion)
 | 
			
		||||
		}
 | 
			
		||||
		config.MinVersion = options.MinVersion
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrEncryptedKey returns true if the 'err' is an error of incorrect
 | 
			
		||||
// password when tryin to decrypt a TLS private key
 | 
			
		||||
func IsErrEncryptedKey(err error) bool {
 | 
			
		||||
	return errors.Cause(err) == x509.IncorrectPasswordError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format.
 | 
			
		||||
// If the private key is encrypted, 'passphrase' is used to decrypted the
 | 
			
		||||
// private key.
 | 
			
		||||
func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) {
 | 
			
		||||
	// this section makes some small changes to code from notary/tuf/utils/x509.go
 | 
			
		||||
	pemBlock, _ := pem.Decode(keyBytes)
 | 
			
		||||
	if pemBlock == nil {
 | 
			
		||||
		return nil, fmt.Errorf("no valid private key found")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	if x509.IsEncryptedPEMBlock(pemBlock) {
 | 
			
		||||
		keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, errors.Wrap(err, "private key is encrypted, but could not decrypt it")
 | 
			
		||||
		}
 | 
			
		||||
		keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return keyBytes, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getCert returns a Certificate from the CertFile and KeyFile in 'options',
 | 
			
		||||
// if the key is encrypted, the Passphrase in 'options' will be used to
 | 
			
		||||
// decrypt it.
 | 
			
		||||
func getCert(options Options) ([]tls.Certificate, error) {
 | 
			
		||||
	if options.CertFile == "" && options.KeyFile == "" {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	errMessage := "Could not load X509 key pair"
 | 
			
		||||
 | 
			
		||||
	cert, err := ioutil.ReadFile(options.CertFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, errMessage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prKeyBytes, err := ioutil.ReadFile(options.KeyFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, errMessage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, errMessage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tlsCert, err := tls.X509KeyPair(cert, prKeyBytes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, errMessage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return []tls.Certificate{tlsCert}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client returns a TLS configuration meant to be used by a client.
 | 
			
		||||
func Client(options Options) (*tls.Config, error) {
 | 
			
		||||
	tlsConfig := ClientDefault()
 | 
			
		||||
	tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
 | 
			
		||||
	if !options.InsecureSkipVerify && options.CAFile != "" {
 | 
			
		||||
		CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		tlsConfig.RootCAs = CAs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tlsCerts, err := getCert(options)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	tlsConfig.Certificates = tlsCerts
 | 
			
		||||
 | 
			
		||||
	if err := adjustMinVersion(options, tlsConfig); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tlsConfig, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Server returns a TLS configuration meant to be used by a server.
 | 
			
		||||
func Server(options Options) (*tls.Config, error) {
 | 
			
		||||
	tlsConfig := ServerDefault()
 | 
			
		||||
	tlsConfig.ClientAuth = options.ClientAuth
 | 
			
		||||
	tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if os.IsNotExist(err) {
 | 
			
		||||
			return nil, fmt.Errorf("Could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, fmt.Errorf("Error reading X509 key pair (cert: %q, key: %q): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err)
 | 
			
		||||
	}
 | 
			
		||||
	tlsConfig.Certificates = []tls.Certificate{tlsCert}
 | 
			
		||||
	if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" {
 | 
			
		||||
		CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		tlsConfig.ClientCAs = CAs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := adjustMinVersion(options, tlsConfig); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tlsConfig, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
// +build go1.5
 | 
			
		||||
 | 
			
		||||
// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
 | 
			
		||||
//
 | 
			
		||||
package tlsconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
 | 
			
		||||
var clientCipherSuites = []uint16{
 | 
			
		||||
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
 | 
			
		||||
	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
 | 
			
		||||
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 | 
			
		||||
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
// +build !go1.5
 | 
			
		||||
 | 
			
		||||
// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
 | 
			
		||||
//
 | 
			
		||||
package tlsconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
 | 
			
		||||
var clientCipherSuites = []uint16{
 | 
			
		||||
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 | 
			
		||||
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user