Skip to content

Commit 0e94012

Browse files
authored
Merge pull request #144 from SenseUnit/tidy-unix-sock
Tidy unix sock
2 parents 9141970 + 6052e67 commit 0e94012

File tree

2 files changed

+98
-31
lines changed

2 files changed

+98
-31
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,12 +455,16 @@ Usage of /home/user/go/bin/dumbproxy:
455455
enables in-memory cache for certificates
456456
-autocert-whitelist value
457457
restrict autocert domains to this comma-separated list
458-
-bind-address string
458+
-bind-address value
459459
HTTP proxy listen address. Set empty value to use systemd socket activation. (default ":8080")
460-
-bind-pprof string
460+
-bind-pprof value
461461
enables pprof debug endpoints
462+
-bind-pprof-unix-socket value
463+
enables pprof debug endpoints listening on Unix domain socket
462464
-bind-reuseport
463465
allow multiple server instances on the same port
466+
-bind-unix-socket value
467+
Unix domain socket to listen to, overrides bind-address if set.
464468
-bw-limit uint
465469
per-user bandwidth limit in bytes per second
466470
-bw-limit-buckets uint
@@ -523,6 +527,12 @@ Usage of /home/user/go/bin/dumbproxy:
523527
listen proxy protocol
524528
-req-header-timeout duration
525529
amount of time allowed to read request headers (default 30s)
530+
-shutdown-timeout duration
531+
grace period during server shutdown (default 1s)
532+
-unix-sock-mode value
533+
set file mode for bound unix socket
534+
-unix-sock-unlink
535+
delete file object located at Unix domain socket bind path before binding (default true)
526536
-user-ip-hints
527537
allow IP hints to be specified by user in X-Src-IP-Hints header
528538
-verbosity int

main.go

Lines changed: 86 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"flag"
1414
"fmt"
1515
"io"
16+
"io/fs"
1617
"log"
1718
"net"
1819
"net/http"
@@ -22,6 +23,7 @@ import (
2223
"os/signal"
2324
"path/filepath"
2425
"runtime"
26+
"strconv"
2527
"strings"
2628
"syscall"
2729
"time"
@@ -160,6 +162,25 @@ func (a *hexArg) Value() []byte {
160162
return a.value
161163
}
162164

165+
type modeArg fs.FileMode
166+
167+
func (a *modeArg) String() string {
168+
return fmt.Sprintf("%#o", uint32(*a))
169+
}
170+
171+
func (a *modeArg) Set(s string) error {
172+
p, err := strconv.ParseUint(s, 8, 32)
173+
if err != nil {
174+
return err
175+
}
176+
*a = modeArg(p)
177+
return nil
178+
}
179+
180+
func (a *modeArg) Value() fs.FileMode {
181+
return fs.FileMode(*a)
182+
}
183+
163184
type cacheKind int
164185

165186
const (
@@ -175,11 +196,17 @@ type autocertCache struct {
175196

176197
const envCacheEncKey = "DUMBPROXY_CACHE_ENC_KEY"
177198

199+
type bindSpec struct {
200+
af string
201+
address string
202+
}
203+
178204
type CLIArgs struct {
179-
bindAddress string
180-
bindUnixSocket string
205+
bind bindSpec
181206
bindReusePort bool
182-
bindPprof string
207+
bindPprof bindSpec
208+
unixSockUnlink bool
209+
unixSockMode modeArg
183210
auth string
184211
verbosity int
185212
cert, key, cafile string
@@ -244,20 +271,35 @@ func parse_args() CLIArgs {
244271
kind: cacheKindDir,
245272
value: filepath.Join(home, ".dumbproxy", "autocert"),
246273
},
274+
bind: bindSpec{
275+
address: ":8080",
276+
af: "tcp",
277+
},
247278
}
248279
args.autocertCacheEncKey.Set(os.Getenv(envCacheEncKey))
249-
flag.Func("bind-address", "HTTP proxy listen address. Set empty value to use systemd socket activation.", func(p string) error {
250-
args.bindAddress = p
251-
args.bindUnixSocket = ""
280+
flag.Func("bind-address", "HTTP proxy listen address. Set empty value to use systemd socket activation. (default \":8080\")", func(p string) error {
281+
args.bind.address = p
282+
args.bind.af = "tcp"
252283
return nil
253284
})
254285
flag.Func("bind-unix-socket", "Unix domain socket to listen to, overrides bind-address if set.", func(p string) error {
255-
args.bindAddress = ""
256-
args.bindUnixSocket = p
286+
args.bind.address = p
287+
args.bind.af = "unix"
257288
return nil
258289
})
259290
flag.BoolVar(&args.bindReusePort, "bind-reuseport", false, "allow multiple server instances on the same port")
260-
flag.StringVar(&args.bindPprof, "bind-pprof", "", "enables pprof debug endpoints")
291+
flag.Func("bind-pprof", "enables pprof debug endpoints", func(p string) error {
292+
args.bindPprof.address = p
293+
args.bindPprof.af = "tcp"
294+
return nil
295+
})
296+
flag.Func("bind-pprof-unix-socket", "enables pprof debug endpoints listening on Unix domain socket", func(p string) error {
297+
args.bindPprof.address = p
298+
args.bindPprof.af = "unix"
299+
return nil
300+
})
301+
flag.BoolVar(&args.unixSockUnlink, "unix-sock-unlink", true, "delete file object located at Unix domain socket bind path before binding")
302+
flag.Var(&args.unixSockMode, "unix-sock-mode", "set file mode for bound unix socket")
261303
flag.StringVar(&args.auth, "auth", "none://", "auth parameters")
262304
flag.IntVar(&args.verbosity, "verbosity", 20, "logging verbosity "+
263305
"(10 - debug, 20 - info, 30 - warning, 40 - error, 50 - critical)")
@@ -496,7 +538,6 @@ func run() int {
496538

497539
stopContext, _ := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
498540
server := http.Server{
499-
Addr: args.bindAddress,
500541
Handler: handler.NewProxyHandler(&handler.Config{
501542
Dialer: dialerRoot,
502543
Auth: auth,
@@ -526,17 +567,38 @@ func run() int {
526567
}
527568

528569
mainLogger.Info("Starting proxy server...")
529-
var listener net.Listener
530-
if args.bindUnixSocket != "" {
531-
newListener, err := net.Listen("unix", args.bindUnixSocket)
532570

533-
if err != nil {
534-
mainLogger.Critical("listen failed: %v", err)
535-
return 3
571+
listenerFactory := net.Listen
572+
if args.bindReusePort {
573+
if reuseport.Available() {
574+
listenerFactory = reuseport.Listen
575+
} else {
576+
mainLogger.Warning("reuseport was requested but not available!")
536577
}
578+
}
579+
if args.unixSockUnlink {
580+
listenerFactory = func(orig func(string, string) (net.Listener, error)) func(string, string) (net.Listener, error) {
581+
return func(network, address string) (net.Listener, error) {
582+
if (network == "unix" || network == "unixdgram") && len(address) > 0 && address[0] != '@' {
583+
os.Remove(address)
584+
}
585+
return orig(network, address)
586+
}
587+
}(listenerFactory)
588+
}
589+
if args.unixSockMode != 0 {
590+
listenerFactory = func(orig func(string, string) (net.Listener, error)) func(string, string) (net.Listener, error) {
591+
return func(network, address string) (net.Listener, error) {
592+
if (network == "unix" || network == "unixdgram") && len(address) > 0 && address[0] != '@' {
593+
defer os.Chmod(address, args.unixSockMode.Value())
594+
}
595+
return orig(network, address)
596+
}
597+
}(listenerFactory)
598+
}
537599

538-
listener = newListener
539-
} else if args.bindAddress == "" {
600+
var listener net.Listener
601+
if args.bind.address == "" {
540602
// socket activation
541603
listeners, err := activation.Listeners()
542604
if err != nil {
@@ -554,15 +616,7 @@ func run() int {
554616
}
555617
listener = listeners[0]
556618
} else {
557-
listenerFactory := net.Listen
558-
if args.bindReusePort {
559-
if reuseport.Available() {
560-
listenerFactory = reuseport.Listen
561-
} else {
562-
mainLogger.Warning("reuseport was requested but not available!")
563-
}
564-
}
565-
newListener, err := listenerFactory("tcp", args.bindAddress)
619+
newListener, err := listenerFactory(args.bind.af, args.bind.address)
566620
if err != nil {
567621
mainLogger.Critical("listen failed: %v", err)
568622
return 3
@@ -648,14 +702,17 @@ func run() int {
648702
defer listener.Close()
649703

650704
// debug endpoints setup
651-
if args.bindPprof != "" {
705+
if args.bindPprof.address != "" {
652706
mux := http.NewServeMux()
653707
mux.HandleFunc("/debug/pprof/", pprof.Index)
654708
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
655709
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
656710
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
657711
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
658-
go func() { log.Fatal(http.ListenAndServe(args.bindPprof, mux)) }()
712+
pprofListener, err := listenerFactory(args.bindPprof.af, args.bindPprof.address)
713+
if err == nil {
714+
go func() { log.Fatal(http.Serve(pprofListener, mux)) }()
715+
}
659716
}
660717

661718
mainLogger.Info("Proxy server started.")

0 commit comments

Comments
 (0)