github.com/ncdc/docker@v0.10.1-0.20160129113957-6c6729ef5b74/api/server/server_unix.go (about)

     1  // +build freebsd linux
     2  
     3  package server
     4  
     5  import (
     6  	"crypto/tls"
     7  	"fmt"
     8  	"net"
     9  	"net/http"
    10  	"strconv"
    11  
    12  	"github.com/Sirupsen/logrus"
    13  	"github.com/docker/go-connections/sockets"
    14  	"github.com/docker/libnetwork/portallocator"
    15  
    16  	systemdActivation "github.com/coreos/go-systemd/activation"
    17  )
    18  
    19  // newServer sets up the required HTTPServers and does protocol specific checking.
    20  // newServer does not set any muxers, you should set it later to Handler field
    21  func (s *Server) newServer(proto, addr string) ([]*HTTPServer, error) {
    22  	var (
    23  		err error
    24  		ls  []net.Listener
    25  	)
    26  	switch proto {
    27  	case "fd":
    28  		ls, err = listenFD(addr, s.cfg.TLSConfig)
    29  		if err != nil {
    30  			return nil, err
    31  		}
    32  	case "tcp":
    33  		l, err := s.initTCPSocket(addr)
    34  		if err != nil {
    35  			return nil, err
    36  		}
    37  		ls = append(ls, l)
    38  	case "unix":
    39  		l, err := sockets.NewUnixSocket(addr, s.cfg.SocketGroup)
    40  		if err != nil {
    41  			return nil, fmt.Errorf("can't create unix socket %s: %v", addr, err)
    42  		}
    43  		ls = append(ls, l)
    44  	default:
    45  		return nil, fmt.Errorf("Invalid protocol format: %q", proto)
    46  	}
    47  	var res []*HTTPServer
    48  	for _, l := range ls {
    49  		res = append(res, &HTTPServer{
    50  			&http.Server{
    51  				Addr: addr,
    52  			},
    53  			l,
    54  		})
    55  	}
    56  	return res, nil
    57  }
    58  
    59  func allocateDaemonPort(addr string) error {
    60  	host, port, err := net.SplitHostPort(addr)
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	intPort, err := strconv.Atoi(port)
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	var hostIPs []net.IP
    71  	if parsedIP := net.ParseIP(host); parsedIP != nil {
    72  		hostIPs = append(hostIPs, parsedIP)
    73  	} else if hostIPs, err = net.LookupIP(host); err != nil {
    74  		return fmt.Errorf("failed to lookup %s address in host specification", host)
    75  	}
    76  
    77  	pa := portallocator.Get()
    78  	for _, hostIP := range hostIPs {
    79  		if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
    80  			return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
    81  		}
    82  	}
    83  	return nil
    84  }
    85  
    86  // listenFD returns the specified socket activated files as a slice of
    87  // net.Listeners or all of the activated files if "*" is given.
    88  func listenFD(addr string, tlsConfig *tls.Config) ([]net.Listener, error) {
    89  	var (
    90  		err       error
    91  		listeners []net.Listener
    92  	)
    93  	// socket activation
    94  	if tlsConfig != nil {
    95  		listeners, err = systemdActivation.TLSListeners(false, tlsConfig)
    96  	} else {
    97  		listeners, err = systemdActivation.Listeners(false)
    98  	}
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	if len(listeners) == 0 {
   104  		return nil, fmt.Errorf("No sockets found")
   105  	}
   106  
   107  	// default to all fds just like unix:// and tcp://
   108  	if addr == "" || addr == "*" {
   109  		return listeners, nil
   110  	}
   111  
   112  	fdNum, err := strconv.Atoi(addr)
   113  	if err != nil {
   114  		return nil, fmt.Errorf("failed to parse systemd address, should be number: %v", err)
   115  	}
   116  	fdOffset := fdNum - 3
   117  	if len(listeners) < int(fdOffset)+1 {
   118  		return nil, fmt.Errorf("Too few socket activated files passed in")
   119  	}
   120  	if listeners[fdOffset] == nil {
   121  		return nil, fmt.Errorf("failed to listen on systemd activated file at fd %d", fdOffset+3)
   122  	}
   123  	for i, ls := range listeners {
   124  		if i == fdOffset || ls == nil {
   125  			continue
   126  		}
   127  		if err := ls.Close(); err != nil {
   128  			logrus.Errorf("Failed to close systemd activated file at fd %d: %v", fdOffset+3, err)
   129  		}
   130  	}
   131  	return []net.Listener{listeners[fdOffset]}, nil
   132  }