github.com/johngossman/docker@v1.6.0-rc5/api/server/server_linux.go (about)

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