From 90369861568d38737001f1d7e1304e6914675359 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Fri, 17 Apr 2026 16:46:49 +0900 Subject: [PATCH] cmd/mbf: optionally ignore reply An acknowledgement is not always required in this use case. This change also adds 64 bits of connection configuration for future expansion. Signed-off-by: Ophestra --- cmd/mbf/daemon.go | 47 ++++++++++++++++++++++++++++++------------ cmd/mbf/daemon_test.go | 11 +++++++--- cmd/mbf/main.go | 21 +++++++++++++------ 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/cmd/mbf/daemon.go b/cmd/mbf/daemon.go index 22eeb72b..d64643d2 100644 --- a/cmd/mbf/daemon.go +++ b/cmd/mbf/daemon.go @@ -2,6 +2,7 @@ package main import ( "context" + "encoding/binary" "errors" "io" "log" @@ -27,21 +28,28 @@ func daemonDeadline() time.Time { return time.Now().Add(daemonTimeout) } +const ( + // remoteNoReply notifies that the client will not receive a cure reply. + remoteNoReply = 1 << iota +) + // cureFromIR services an IR curing request. func cureFromIR( ctx context.Context, cache *pkg.Cache, conn net.Conn, ) (pkg.Artifact, error) { - go func() { - <-ctx.Done() - _ = conn.SetDeadline(time.Now()) - }() - + go func() { <-ctx.Done(); _ = conn.SetDeadline(time.Now()) }() if err := conn.SetReadDeadline(daemonDeadline()); err != nil { return nil, errors.Join(err, conn.Close()) } + var flagsWire [8]byte + if _, err := io.ReadFull(conn, flagsWire[:]); err != nil { + return nil, errors.Join(err, conn.Close()) + } + flags := binary.LittleEndian.Uint64(flagsWire[:]) + a, decodeErr := cache.NewDecoder(conn).Decode() if decodeErr != nil { _, err := conn.Write([]byte("\x00" + decodeErr.Error())) @@ -49,10 +57,11 @@ func cureFromIR( } pathname, _, cureErr := cache.Cure(a) + if flags&remoteNoReply != 0 { + return a, errors.Join(cureErr, conn.Close()) + } if err := conn.SetWriteDeadline(daemonDeadline()); err != nil { - if !testing.Testing() || !errors.Is(err, io.ErrClosedPipe) { - return a, errors.Join(err, conn.Close()) - } + return a, errors.Join(cureErr, err, conn.Close()) } if cureErr != nil { _, err := conn.Write([]byte("\x00" + cureErr.Error())) @@ -66,7 +75,12 @@ func cureFromIR( } // serve services connections from a [net.UnixListener]. -func serve(ctx context.Context, log *log.Logger, cm *cache, ul *net.UnixListener) error { +func serve( + ctx context.Context, + log *log.Logger, + cm *cache, + ul *net.UnixListener, +) error { ul.SetUnlinkOnClose(true) if cm.c == nil { if err := cm.open(); err != nil { @@ -116,16 +130,19 @@ func cureRemote( ctx context.Context, addr *net.UnixAddr, a pkg.Artifact, + flags uint64, ) (*check.Absolute, error) { conn, err := net.DialUnix("unix", nil, addr) if err != nil { return nil, err } + go func() { <-ctx.Done(); _ = conn.SetDeadline(time.Now()) }() - go func() { - <-ctx.Done() - _ = conn.SetDeadline(time.Now()) - }() + if n, flagErr := conn.Write(binary.LittleEndian.AppendUint64(nil, flags)); flagErr != nil { + return nil, errors.Join(flagErr, conn.Close()) + } else if n != 8 { + return nil, errors.Join(io.ErrShortWrite, conn.Close()) + } if err = pkg.NewIR().EncodeAll(conn, a); err != nil { return nil, errors.Join(err, conn.Close()) @@ -133,6 +150,10 @@ func cureRemote( return nil, errors.Join(err, conn.Close()) } + if flags&remoteNoReply != 0 { + return nil, conn.Close() + } + payload, recvErr := io.ReadAll(conn) if err = errors.Join(recvErr, conn.Close()); err != nil { if errors.Is(err, os.ErrDeadlineExceeded) { diff --git a/cmd/mbf/daemon_test.go b/cmd/mbf/daemon_test.go index cf67059a..2ec2e76a 100644 --- a/cmd/mbf/daemon_test.go +++ b/cmd/mbf/daemon_test.go @@ -3,6 +3,7 @@ package main import ( "bytes" "context" + "encoding/binary" "errors" "io" "log" @@ -17,7 +18,7 @@ import ( "hakurei.app/message" ) -func TestCureFromIR(t *testing.T) { +func TestNoReply(t *testing.T) { t.Parallel() if !daemonDeadline().IsZero() { t.Fatal("daemonDeadline did not return the zero value") @@ -45,7 +46,11 @@ func TestCureFromIR(t *testing.T) { } }() - if _err := c.EncodeAll( + if _, _err := client.Write( + binary.LittleEndian.AppendUint64(nil, remoteNoReply), + ); _err != nil { + panic(_err) + } else if _err = c.EncodeAll( client, pkg.NewFile("check", []byte{0}), ); _err != nil { @@ -105,7 +110,7 @@ func TestDaemon(t *testing.T) { }() var p *check.Absolute - p, err = cureRemote(ctx, &addr, pkg.NewFile("check", []byte{0})) + p, err = cureRemote(ctx, &addr, pkg.NewFile("check", []byte{0}), 0) if err != nil { t.Fatalf("cureRemote: error = %v", err) } diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go index abdc5e94..bee97b01 100644 --- a/cmd/mbf/main.go +++ b/cmd/mbf/main.go @@ -392,10 +392,11 @@ func main() { { var ( - flagDump string - flagEnter bool - flagExport string - flagRemote bool + flagDump string + flagEnter bool + flagExport string + flagRemote bool + flagNoReply bool ) c.NewCommand( "cure", @@ -474,8 +475,12 @@ func main() { }) case flagRemote: - pathname, err := cureRemote(ctx, &addr, rosa.Std.Load(p)) - if err == nil { + var flags uint64 + if flagNoReply { + flags |= remoteNoReply + } + pathname, err := cureRemote(ctx, &addr, rosa.Std.Load(p), flags) + if !flagNoReply && err == nil { log.Println(pathname) } return err @@ -497,6 +502,10 @@ func main() { &flagRemote, "daemon", command.BoolFlag(false), "Cure artifact on the daemon", + ).Flag( + &flagNoReply, + "no-reply", command.BoolFlag(false), + "Do not receive a reply from the daemon", ) }