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 }