package main import ( "context" "embed" "flag" "fmt" "io/fs" "log" "net/http" "os" "os/signal" "path/filepath" "syscall" "forge-mesh/internal/api" "forge-mesh/internal/config" "forge-mesh/internal/db" "forge-mesh/internal/forge" "forge-mesh/internal/stratum" ) //go:embed webroot/* var webroot embed.FS const version = "0.1.0-dev" func main() { configPath := flag.String("config", "data/config.json", "path to config.json") installTmpl := flag.String("install-tmpl", "scripts/install.sh.tpl", "install.sh template path") flag.Parse() cfg, err := config.Load(*configPath) if err != nil { log.Fatalf("config: %v", err) } if err := cfg.EnsureDataDirs(); err != nil { log.Fatalf("data dirs: %v", err) } conn, err := db.Open(cfg.DatabasePath) if err != nil { log.Fatalf("database: %v", err) } defer conn.Close() keyPair, err := forge.LoadOrCreateKey(cfg.Forge.SigningKeyPath) if err != nil { log.Fatalf("signing key: %v", err) } staticFS, err := fs.Sub(webroot, "webroot") if err != nil { log.Fatalf("webroot: %v", err) } srv, err := api.NewServer(cfg, conn, staticFS, version, *installTmpl, keyPair.PublicKeyHex()) if err != nil { log.Fatalf("server: %v", err) } stratumProxy := stratum.New(cfg.Stratum) if err := stratumProxy.Start(); err != nil { log.Printf("stratum (non-fatal): %v", err) } else { defer stratumProxy.Close() log.Printf("stratum: XMR %s RVN %s", cfg.Stratum.XMRListen, cfg.Stratum.RVNListen) } addr := cfg.ListenAddr log.Printf("forge-mesh-server %s listening on %s (config: %s, db: %s)", version, addr, absPath(*configPath), cfg.DatabasePath) httpSrv := &http.Server{Addr: addr, Handler: srv.Handler()} go func() { if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed { fmt.Fprintf(os.Stderr, "server: %v\n", err) os.Exit(1) } }() sigCtx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() <-sigCtx.Done() log.Println("shutting down...") _ = httpSrv.Shutdown(context.Background()) } func absPath(p string) string { abs, err := filepath.Abs(p) if err != nil { return p } return abs }