Files
gronod 7bed99cc4c fix: keep robot listeners if health port is busy (v0.1.2)
ServeHealth bind failures (common on HAOS when OTBR owns 8080) are
logged and ignored. Lookup, firmware, and XMPP stay up. Log each
successful listen address so add-on logs show the sockets.
2026-09-24 16:17:30 +00:00

58 lines
1.4 KiB
Go

package httpx
import (
"context"
"fmt"
"log/slog"
"net"
"net/http"
"time"
"git.i3omb.com/gronod/ha-n95-local-control/internal/config"
)
// ServeFirmware runs the firmware 404 listener until ctx is cancelled.
func ServeFirmware(ctx context.Context, cfg config.Config) error {
mux := http.NewServeMux()
mux.HandleFunc("/", firmwareHandler)
mux.HandleFunc("/products/wukong/class/155/firmware/latest.json", firmwareHandler)
addr := net.JoinHostPort(cfg.BindAddress, fmt.Sprintf("%d", cfg.PortFirmware))
ln, err := net.Listen("tcp", addr)
if err != nil {
return fmt.Errorf("%s: %w", addr, err)
}
slog.Info("firmware listening", "addr", addr)
srv := &http.Server{
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
srv.SetKeepAlivesEnabled(false)
errCh := make(chan error, 1)
go func() {
errCh <- srv.Serve(ln)
}()
select {
case <-ctx.Done():
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = srv.Shutdown(shutdownCtx)
return nil
case err := <-errCh:
return err
}
}
func firmwareHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.Header().Set("Content-Length", "9")
w.Header().Set("Connection", "close")
w.WriteHeader(http.StatusNotFound)
_, _ = w.Write([]byte("Not Found"))
}