package worker import ( "context" "io" "log/slog" "net/http" "path/filepath" "git.lastassault.de/speatzle/morffix/rpc" "os" "os/signal" "time" "git.lastassault.de/speatzle/morffix/config" "git.lastassault.de/speatzle/morffix/constants" "github.com/google/uuid" "nhooyr.io/websocket" ) var conf config.Config var rpcServer = rpc.NewServer() func Start(_conf config.Config) { conf = _conf ctx, cancel := context.WithCancel(context.Background()) defer cancel() // TODO Generate and Save a ID if the Config has none //uuid := uuid.New() uuid, err := uuid.Parse(conf.Worker.ID) if err != nil { slog.Error("Cannot Parse ID", "err", err) return } slog.InfoContext(ctx, "Cleaning tmp Files...") files, err := filepath.Glob("/tmp/morffix-*") if err != nil { slog.Error("Get tmp Files", "err", err) return } for _, f := range files { slog.InfoContext(ctx, "Deleting File", "path", f) if err := os.Remove(f); err != nil { slog.Error("Deleting tmp File", "err", err, "path", f) return } } sigs := make(chan os.Signal, 1) signal.Notify(sigs, os.Interrupt) exit := false go func() { <-sigs slog.InfoContext(ctx, "Got Signal...") exit = true cancel() }() go calcUsage() for { if exit { slog.InfoContext(ctx, "Done") return } connectToServer(ctx, uuid) if exit { slog.InfoContext(ctx, "Done") return } time.Sleep(time.Second) } } func connectToServer(ctx context.Context, uuid uuid.UUID) { slog.InfoContext(ctx, "Connecting to Server...", "Address", conf.Worker.Address) headers := http.Header{} headers.Add(constants.SHARED_SECRET_HEADER, conf.SharedSecret) headers.Add(constants.NAME_HEADER, conf.Worker.Name) headers.Add(constants.UUID_HEADER, uuid.String()) headers.Add(constants.WORKER_VERSION_HEADER, constants.WORKER_VERSION) c, res, err := websocket.Dial(ctx, conf.Worker.Address+"/worker", &websocket.DialOptions{ HTTPHeader: headers, }) if err != nil { if res != nil { b, _ := io.ReadAll(res.Body) slog.ErrorContext(ctx, "Error Connecting to Server", "err", err, "code", res.Status, "body", b) } else { slog.ErrorContext(ctx, "Error Connecting to Server", "err", err) } return } slog.InfoContext(ctx, "Waiting for Messages") for { err = readMessage(ctx, c) if websocket.CloseStatus(err) == websocket.StatusNormalClosure || websocket.CloseStatus(err) == websocket.StatusAbnormalClosure || websocket.CloseStatus(err) == websocket.StatusGoingAway { slog.InfoContext(ctx, "Websocket Closed") return } if err != nil { slog.ErrorContext(ctx, "Error Reading Websocket Message", "err", err) return } } } func readMessage(ctx context.Context, c *websocket.Conn) error { t, data, err := c.Read(ctx) if err != nil { return err } slog.DebugContext(ctx, "Got Websocket Message", "type", t.String(), "data", data) rpcServer.HandleMessage(ctx, c, data) return nil }