github.com/hms58/moby@v1.13.1/pkg/listeners/listeners_unix.go (about) 1 // +build !windows,!solaris 2 3 package listeners 4 5 import ( 6 "crypto/tls" 7 "fmt" 8 "net" 9 "strconv" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/coreos/go-systemd/activation" 13 "github.com/docker/go-connections/sockets" 14 ) 15 16 // Init creates new listeners for the server. 17 // TODO: Clean up the fact that socketGroup and tlsConfig aren't always used. 18 func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) ([]net.Listener, error) { 19 ls := []net.Listener{} 20 21 switch proto { 22 case "fd": 23 fds, err := listenFD(addr, tlsConfig) 24 if err != nil { 25 return nil, err 26 } 27 ls = append(ls, fds...) 28 case "tcp": 29 l, err := sockets.NewTCPSocket(addr, tlsConfig) 30 if err != nil { 31 return nil, err 32 } 33 ls = append(ls, l) 34 case "unix": 35 l, err := sockets.NewUnixSocket(addr, socketGroup) 36 if err != nil { 37 return nil, fmt.Errorf("can't create unix socket %s: %v", addr, err) 38 } 39 ls = append(ls, l) 40 default: 41 return nil, fmt.Errorf("invalid protocol format: %q", proto) 42 } 43 44 return ls, nil 45 } 46 47 // listenFD returns the specified socket activated files as a slice of 48 // net.Listeners or all of the activated files if "*" is given. 49 func listenFD(addr string, tlsConfig *tls.Config) ([]net.Listener, error) { 50 var ( 51 err error 52 listeners []net.Listener 53 ) 54 // socket activation 55 if tlsConfig != nil { 56 listeners, err = activation.TLSListeners(false, tlsConfig) 57 } else { 58 listeners, err = activation.Listeners(false) 59 } 60 if err != nil { 61 return nil, err 62 } 63 64 if len(listeners) == 0 { 65 return nil, fmt.Errorf("no sockets found via socket activation: make sure the service was started by systemd") 66 } 67 68 // default to all fds just like unix:// and tcp:// 69 if addr == "" || addr == "*" { 70 return listeners, nil 71 } 72 73 fdNum, err := strconv.Atoi(addr) 74 if err != nil { 75 return nil, fmt.Errorf("failed to parse systemd fd address: should be a number: %v", addr) 76 } 77 fdOffset := fdNum - 3 78 if len(listeners) < int(fdOffset)+1 { 79 return nil, fmt.Errorf("too few socket activated files passed in by systemd") 80 } 81 if listeners[fdOffset] == nil { 82 return nil, fmt.Errorf("failed to listen on systemd activated file: fd %d", fdOffset+3) 83 } 84 for i, ls := range listeners { 85 if i == fdOffset || ls == nil { 86 continue 87 } 88 if err := ls.Close(); err != nil { 89 // TODO: We shouldn't log inside a library. Remove this or error out. 90 logrus.Errorf("failed to close systemd activated file: fd %d: %v", fdOffset+3, err) 91 } 92 } 93 return []net.Listener{listeners[fdOffset]}, nil 94 }