github.com/a4a881d4/docker@v1.9.0-rc2/api/server/server_unix.go (about)

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