From 33fca0976f95eac7ddce424080db9e381ec7388e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 5 May 2016 13:16:32 +0100 Subject: Allow -listen-http, -listen-https and -listen-proxy to be given more than once Per issue #13, sometimes you want to listen on more than one port for each type of listener. This commit adds support for that. --- app.go | 25 +++++++++++++------------ app_config.go | 6 +++--- daemon.go | 25 +++++++++++++++---------- main.go | 28 +++++++++++++++------------- multi_string_flag.go | 22 ++++++++++++++++++++++ 5 files changed, 68 insertions(+), 38 deletions(-) create mode 100644 multi_string_flag.go diff --git a/app.go b/app.go index aa0438ff..35b661cc 100644 --- a/app.go +++ b/app.go @@ -85,39 +85,40 @@ func (a *theApp) UpdateDomains(domains domains) { func (a *theApp) Run() { var wg sync.WaitGroup - if a.ListenHTTP != 0 { + // Listen for HTTP + for _, fd := range a.ListenHTTP { wg.Add(1) - go func() { + go func(fd uintptr) { defer wg.Done() - err := listenAndServe(a.ListenHTTP, a.ServeHTTP, a.HTTP2, nil) + err := listenAndServe(fd, a.ServeHTTP, a.HTTP2, nil) if err != nil { log.Fatal(err) } - }() + }(fd) } // Listen for HTTPS - if a.ListenHTTPS != 0 { + for _, fd := range a.ListenHTTPS { wg.Add(1) - go func() { + go func(fd uintptr) { defer wg.Done() - err := listenAndServeTLS(a.ListenHTTPS, a.RootCertificate, a.RootKey, a.ServeHTTP, a.ServeTLS, a.HTTP2) + err := listenAndServeTLS(fd, a.RootCertificate, a.RootKey, a.ServeHTTP, a.ServeTLS, a.HTTP2) if err != nil { log.Fatal(err) } - }() + }(fd) } // Listen for HTTP proxy requests - if a.ListenProxy != 0 { + for _, fd := range a.ListenProxy { wg.Add(1) - go func() { + go func(fd uintptr) { defer wg.Done() - err := listenAndServe(a.ListenProxy, a.ServeProxy, a.HTTP2, nil) + err := listenAndServe(fd, a.ServeProxy, a.HTTP2, nil) if err != nil { log.Fatal(err) } - }() + }(fd) } go watchDomains(a.Domain, a.UpdateDomains, time.Second) diff --git a/app_config.go b/app_config.go index 8da2437a..7ffa1e76 100644 --- a/app_config.go +++ b/app_config.go @@ -6,9 +6,9 @@ type appConfig struct { RootCertificate []byte RootKey []byte - ListenHTTP uintptr - ListenHTTPS uintptr - ListenProxy uintptr + ListenHTTP []uintptr + ListenHTTPS []uintptr + ListenProxy []uintptr HTTP2 bool RedirectHTTP bool diff --git a/daemon.go b/daemon.go index de6ce4a3..69feed1c 100644 --- a/daemon.go +++ b/daemon.go @@ -56,15 +56,20 @@ func daemonReexec(uid, gid uint, args ...string) (cmd *exec.Cmd, err error) { return } -func daemonUpdateFd(cmd *exec.Cmd, fd *uintptr) { - if *fd == 0 { - return - } +func daemonUpdateFd(cmd *exec.Cmd, fd uintptr) (childFd uintptr) { + file := os.NewFile(fd, "[socket]") - file := os.NewFile(*fd, "[socket]") // we add 3 since, we have a 3 predefined FDs - *fd = uintptr(3 + len(cmd.ExtraFiles)) + childFd = uintptr(3 + len(cmd.ExtraFiles)) cmd.ExtraFiles = append(cmd.ExtraFiles, file) + + return +} + +func daemonUpdateFds(cmd *exec.Cmd, fds []uintptr) { + for idx, fd := range fds { + fds[idx] = daemonUpdateFd(cmd, fd) + } } func killProcess(cmd *exec.Cmd) { @@ -196,10 +201,10 @@ func daemonize(config appConfig, uid, gid uint) { defer configWriter.Close() cmd.ExtraFiles = append(cmd.ExtraFiles, configReader) - // Create a new file and store the FD - daemonUpdateFd(cmd, &config.ListenHTTP) - daemonUpdateFd(cmd, &config.ListenHTTPS) - daemonUpdateFd(cmd, &config.ListenProxy) + // Create a new file and store the FD for each listener + daemonUpdateFds(cmd, config.ListenHTTP) + daemonUpdateFds(cmd, config.ListenHTTPS) + daemonUpdateFds(cmd, config.ListenProxy) // Start the process if err = cmd.Start(); err != nil { diff --git a/main.go b/main.go index ba7a25db..62d28e0e 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,6 @@ package main import ( "flag" "log" - "net" "os" "strings" ) @@ -16,9 +15,12 @@ var REVISION = "HEAD" func appMain() { var showVersion = flag.Bool("version", false, "Show version") - var listenHTTP = flag.String("listen-http", "", "The address to listen for HTTP requests") - var listenHTTPS = flag.String("listen-https", "", "The address to listen for HTTPS requests") - var listenProxy = flag.String("listen-proxy", "", "The address to listen for proxy requests") + var listenHTTP, listenHTTPS, listenProxy MultiStringFlag + + flag.Var(&listenHTTP, "listen-http", "The address(es) to listen on for HTTP requests") + flag.Var(&listenHTTPS, "listen-https", "The address(es) to listen on for HTTPS requests") + flag.Var(&listenProxy, "listen-proxy", "The address(es) to listen on for proxy requests") + var pagesRootCert = flag.String("root-cert", "", "The default path to file certificate to serve static pages") var pagesRootKey = flag.String("root-key", "", "The default path to file certificate to serve static pages") var redirectHTTP = flag.Bool("redirect-http", true, "Serve the pages under HTTP") @@ -53,22 +55,22 @@ func appMain() { config.RootKey = readFile(*pagesRootKey) } - if *listenHTTP != "" { - var l net.Listener - l, config.ListenHTTP = createSocket(*listenHTTP) + for _, addr := range listenHTTP { + l, fd := createSocket(addr) defer l.Close() + config.ListenHTTP = append(config.ListenHTTP, fd) } - if *listenHTTPS != "" { - var l net.Listener - l, config.ListenHTTPS = createSocket(*listenHTTPS) + for _, addr := range listenHTTPS { + l, fd := createSocket(addr) defer l.Close() + config.ListenHTTPS = append(config.ListenHTTPS, fd) } - if *listenProxy != "" { - var l net.Listener - l, config.ListenProxy = createSocket(*listenProxy) + for _, addr := range listenProxy { + l, fd := createSocket(addr) defer l.Close() + config.ListenProxy = append(config.ListenProxy, fd) } if *daemonUID != 0 || *daemonGID != 0 { diff --git a/multi_string_flag.go b/multi_string_flag.go new file mode 100644 index 00000000..ba6d92ea --- /dev/null +++ b/multi_string_flag.go @@ -0,0 +1,22 @@ +package main + +import ( + "strings" +) + +// MultiStringFlag implements the flag.Value interface and allows a string flag +// to be specified multiple times on the command line. +// +// e.g.: -listen-http 127.0.0.1:80 -listen-http [::1]:80 +type MultiStringFlag []string + +// String returns the list of parameters joined with a commas (",") +func (s *MultiStringFlag) String() string { + return strings.Join(*s, ",") +} + +// Set appends the value to the list of parameters +func (s *MultiStringFlag) Set(value string) error { + *s = append(*s, value) + return nil +} -- cgit v1.2.3