diff --git a/config.go b/config.go index e6750ad..b349a27 100644 --- a/config.go +++ b/config.go @@ -20,6 +20,7 @@ import ( type Config struct { Addr []string // TCP addresses to listen on. e.g. ":1234", "1.2.3.4:1234" or "[::1]:1234" + Uds string // Unix Domain Socket to listen on MaxForks int // Number of allowable concurrent forks LogLevel libwebsocketd.LogLevel RedirPort int @@ -65,6 +66,7 @@ func parseCommandLine() *Config { // server config options portFlag := flag.Int("port", 0, "HTTP port to listen on") + udsFlag := flag.String("uds", "", "Path of the Unix Domain Socket to listen on") versionFlag := flag.Bool("version", false, "Print version and exit") licenseFlag := flag.Bool("license", false, "Print license and exit") logLevelFlag := flag.String("loglevel", "access", "Log level, one of: debug, trace, access, info, error, fatal") @@ -104,8 +106,11 @@ func parseCommandLine() *Config { } } + ipSocknum := len(addrlist) port := *portFlag - if port == 0 { + udsOnly := *udsFlag != "" && ipSocknum == 0 && port == 0 && *redirPortFlag == 0 + + if port == 0 && !udsOnly { if *sslFlag { port = 443 } else { @@ -113,14 +118,15 @@ func parseCommandLine() *Config { } } - if socknum := len(addrlist); socknum != 0 { - mainConfig.Addr = make([]string, socknum) + if ipSocknum != 0 { + mainConfig.Addr = make([]string, ipSocknum) for i, addrSingle := range addrlist { mainConfig.Addr[i] = fmt.Sprintf("%s:%d", addrSingle, port) } - } else { + } else if !udsOnly { mainConfig.Addr = []string{fmt.Sprintf(":%d", port)} } + mainConfig.Uds = *udsFlag mainConfig.MaxForks = *maxForksFlag mainConfig.RedirPort = *redirPortFlag mainConfig.LogLevel = libwebsocketd.LevelFromString(*logLevelFlag) diff --git a/help.go b/help.go index 0c4aef4..ffe870c 100644 --- a/help.go +++ b/help.go @@ -36,6 +36,11 @@ Options: Use square brackets to specify IPv6 address. Default: "" (all) + --uds=PATH Path to create a Unix Domain Socket to listen + on. If this is specified and no IP-specific + flags are specified, do not listen on IP. + Default: "" (do not serve on UDS) + --sameorigin={true,false} Restrict (HTTP 403) protocol upgrades if the Origin header does not match to requested HTTP Host. Default: false. diff --git a/libwebsocketd/handler.go b/libwebsocketd/handler.go index 9b208ef..02a4448 100644 --- a/libwebsocketd/handler.go +++ b/libwebsocketd/handler.go @@ -35,8 +35,9 @@ func NewWebsocketdHandler(s *WebsocketdServer, req *http.Request, log *LogScope) wsh.RemoteInfo, err = GetRemoteInfo(req.RemoteAddr, s.Config.ReverseLookup) if err != nil { + // This occurs when serving over Unix Domain Sockets. log.Error("session", "Could not understand remote address '%s': %s", req.RemoteAddr, err) - return nil, err + wsh.RemoteInfo = &RemoteInfo{Addr: "unknown_host", Host: "unknown_host", Port: ""} } log.Associate("remote", wsh.RemoteInfo.Host) diff --git a/main.go b/main.go index 636bec0..f5eb34a 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ package main import ( "fmt" + "net" "net/http" "os" "runtime" @@ -70,6 +71,20 @@ func main() { } rejects := make(chan error, 1) + + // Serve and ServeTLS, called by the serve function below, do not return + // except on error. Let's run serve in a go routine, reporting result to + // control channel. This allows us to have multiple serve addresses. + serve := func(network, address string) { + if listener, err := net.Listen(network, address); err != nil { + rejects <- err + } else if config.Ssl { + rejects <- http.ServeTLS(listener, nil, config.CertFile, config.KeyFile) + } else { + rejects <- http.Serve(listener, nil) + } + } + for _, addrSingle := range config.Addr { log.Info("server", "Starting WebSocket server : %s", handler.TellURL("ws", addrSingle, "/")) if config.DevConsole { @@ -77,17 +92,7 @@ func main() { } else if config.StaticDir != "" || config.CgiDir != "" { log.Info("server", "Serving CGI or static files : %s", handler.TellURL("http", addrSingle, "/")) } - // ListenAndServe is blocking function. Let's run it in - // go routine, reporting result to control channel. - // Since it's blocking it'll never return non-error. - - go func(addr string) { - if config.Ssl { - rejects <- http.ListenAndServeTLS(addr, config.CertFile, config.KeyFile, nil) - } else { - rejects <- http.ListenAndServe(addr, nil) - } - }(addrSingle) + go serve("tcp", addrSingle) if config.RedirPort != 0 { go func(addr string) { @@ -112,6 +117,10 @@ func main() { }(addrSingle) } } + if config.Uds != "" { + log.Info("server", "Starting WebSocket server on Unix Domain Socket: %s", config.Uds) + go serve("unix", config.Uds) + } err := <-rejects if err != nil { log.Fatal("server", "Can't start server: %s", err)