server_unix.go 2.9 KB

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