package main import ( "context" "log/slog" "os" "os/signal" "path/filepath" "syscall" "sdns/internal/blocklist" "sdns/internal/cache" "sdns/internal/resolver" "sdns/internal/server" ) func main() { logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ Level: slog.LevelInfo, })) slog.SetDefault(logger) r := resolver.New() dbPath := os.Getenv("SDNS_CACHE_DB") if dbPath != "" { logger.Info("cache using sqlite", "path", dbPath) } else { logger.Info("cache using in-memory") } c, err := cache.NewCache(100000, dbPath) if err != nil { logger.Error("create cache failed", "err", err) os.Exit(1) } defer c.Stop() var bl *blocklist.Blocklist matches, _ := filepath.Glob("etc/blocklist/*.txt") if len(matches) > 0 { bl = blocklist.New(blocklist.ResponseZeroIP) for _, f := range matches { if err := bl.LoadFile(f); err != nil { logger.Error("load blocklist failed", "file", f, "err", err) os.Exit(1) } logger.Info("blocklist loaded", "file", f, "rules", bl.TotalRules) } } else { logger.Info("no blocklist files in etc/blocklist/, ad-blocking disabled") } udp := os.Getenv("SDNS_LISTEN_UDP") if udp == "" { udp = ":5353" } tcp := os.Getenv("SDNS_LISTEN_TCP") if tcp == "" { tcp = ":5353" } doh := os.Getenv("SDNS_LISTEN_DOH") if doh == "" { doh = ":8443" } ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() srv, err := server.New(udp, tcp, doh, logger, r, c, bl) if err != nil { logger.Error("create server failed", "err", err) os.Exit(1) } defer srv.Close() logger.Info("sdns starting", "udp", udp, "tcp", tcp, "doh", doh) if err := srv.Run(ctx); err != nil && err != context.Canceled { logger.Error("server stopped with error", "err", err) os.Exit(1) } logger.Info("sdns stopped cleanly") }