server_linux.go 2.5 KB

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