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