server_linux.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // +build linux
  2. package server
  3. import (
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "syscall"
  8. "github.com/docker/docker/engine"
  9. "github.com/docker/docker/pkg/systemd"
  10. "net"
  11. )
  12. type UnixHttpServer struct {
  13. srv *http.Server
  14. l net.Listener
  15. }
  16. func (s *UnixHttpServer) Serve() error {
  17. return s.srv.Serve(s.l)
  18. }
  19. func (s *UnixHttpServer) Close() error {
  20. if err := s.l.Close(); err != nil {
  21. return err
  22. }
  23. if _, err := os.Stat(s.srv.Addr); err != nil {
  24. return fmt.Errorf("Error removing unix socket %s: %s", s.srv.Addr, err.Error())
  25. }
  26. if err := os.Remove(s.srv.Addr); err != nil {
  27. return fmt.Errorf("Error removing unix socket %s: %s", s.srv.Addr, err.Error())
  28. }
  29. return nil
  30. }
  31. // NewServer sets up the required Server and does protocol specific checking.
  32. func NewServer(proto, addr string, job *engine.Job) (Server, error) {
  33. // Basic error and sanity checking
  34. switch proto {
  35. case "fd":
  36. return nil, serveFd(addr, job)
  37. case "tcp":
  38. return setupTcpHttp(addr, job)
  39. case "unix":
  40. return setupUnixHttp(addr, job)
  41. default:
  42. return nil, fmt.Errorf("Invalid protocol format.")
  43. }
  44. }
  45. func setupUnixHttp(addr string, job *engine.Job) (*UnixHttpServer, error) {
  46. r := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("CorsHeaders"), job.Getenv("Version"))
  47. if err := syscall.Unlink(addr); err != nil && !os.IsNotExist(err) {
  48. return nil, err
  49. }
  50. mask := syscall.Umask(0777)
  51. defer syscall.Umask(mask)
  52. l, err := newListener("unix", addr, job.GetenvBool("BufferRequests"))
  53. if err != nil {
  54. return nil, err
  55. }
  56. if err := setSocketGroup(addr, job.Getenv("SocketGroup")); err != nil {
  57. return nil, err
  58. }
  59. if err := os.Chmod(addr, 0660); err != nil {
  60. return nil, err
  61. }
  62. return &UnixHttpServer{&http.Server{Addr: addr, Handler: r}, l}, nil
  63. }
  64. // serveFd creates an http.Server and sets it up to serve given a socket activated
  65. // argument.
  66. func serveFd(addr string, job *engine.Job) error {
  67. r := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("CorsHeaders"), job.Getenv("Version"))
  68. ls, e := systemd.ListenFD(addr)
  69. if e != nil {
  70. return e
  71. }
  72. chErrors := make(chan error, len(ls))
  73. // We don't want to start serving on these sockets until the
  74. // daemon is initialized and installed. Otherwise required handlers
  75. // won't be ready.
  76. <-activationLock
  77. // Since ListenFD will return one or more sockets we have
  78. // to create a go func to spawn off multiple serves
  79. for i := range ls {
  80. listener := ls[i]
  81. go func() {
  82. httpSrv := http.Server{Handler: r}
  83. chErrors <- httpSrv.Serve(listener)
  84. }()
  85. }
  86. for i := 0; i < len(ls); i++ {
  87. err := <-chErrors
  88. if err != nil {
  89. return err
  90. }
  91. }
  92. return nil
  93. }
  94. // Called through eng.Job("acceptconnections")
  95. func AcceptConnections(job *engine.Job) engine.Status {
  96. // Tell the init daemon we are accepting requests
  97. go systemd.SdNotify("READY=1")
  98. // close the lock so the listeners start accepting connections
  99. if activationLock != nil {
  100. close(activationLock)
  101. }
  102. return engine.StatusOK
  103. }