Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow listening on a Unix Domain Socket #435

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -104,23 +106,27 @@ 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 {
port = 80
}
}

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)
Expand Down
5 changes: 5 additions & 0 deletions help.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion libwebsocketd/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
31 changes: 20 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package main

import (
"fmt"
"net"
"net/http"
"os"
"runtime"
Expand Down Expand Up @@ -70,24 +71,28 @@ 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 {
log.Info("server", "Developer console enabled : %s", handler.TellURL("http", addrSingle, "/"))
} 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) {
Expand All @@ -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)
Expand Down