remote_preview.go RawHistoryFolder
1package app
2
3import (
4 "context"
5 "encoding/base64"
6 "errors"
7 "fmt"
8 "os"
9
10 "github.com/bnema/vev/internal/adapters/ipc"
11 "github.com/bnema/vev/internal/ports"
12)
13
14// runRemotePreview is the hidden SSH-side carriage. The request is encoded in
15// one shell-safe argument, then the daemon returns one bounded binary response
16// whose payload is written verbatim to stdout; no viewport bytes are logged.
17func runRemotePreview(ctx context.Context, encoded string) error {
18 request, err := base64.RawURLEncoding.DecodeString(encoded)
19 if err != nil {
20 return fmt.Errorf("vev: invalid remote preview request: %w", err)
21 }
22 if _, err := ports.UnmarshalRemotePreviewRequest(request); err != nil {
23 return fmt.Errorf("vev: invalid remote preview request: %w", err)
24 }
25 transport, err := ipc.DialContext(ctx, ipc.SocketDir())
26 if err != nil {
27 if ctxErr := ctx.Err(); ctxErr != nil {
28 return ctxErr
29 }
30 return writeRemotePreviewStatus(ports.RemotePreviewUnavailable)
31 }
32 defer func() { _ = transport.Close() }()
33 if err := transport.Send(ports.Frame{Type: ports.MsgRemotePreviewRequest, Payload: request}); err != nil {
34 return fmt.Errorf("vev: sending remote preview request: %w", err)
35 }
36 frameCh := make(chan struct {
37 frame ports.Frame
38 err error
39 }, 1)
40 go func() {
41 frame, err := transport.Recv()
42 frameCh <- struct {
43 frame ports.Frame
44 err error
45 }{frame: frame, err: err}
46 }()
47 select {
48 case <-ctx.Done():
49 _ = transport.Close()
50 return ctx.Err()
51 case result := <-frameCh:
52 if result.err != nil {
53 return fmt.Errorf("vev: receiving remote preview: %w", result.err)
54 }
55 if result.frame.Type != ports.MsgRemotePreviewResponse {
56 return fmt.Errorf("vev: unexpected remote preview response %d", result.frame.Type)
57 }
58 if _, err := ports.UnmarshalRemotePreview(result.frame.Payload); err != nil {
59 return fmt.Errorf("vev: malformed remote preview response: %w", err)
60 }
61 _, err := os.Stdout.Write(result.frame.Payload)
62 return err
63 }
64}
65
66func writeRemotePreviewStatus(status ports.RemotePreviewStatus) error {
67 payload := ports.MarshalRemotePreview(ports.RemotePreview{Version: ports.RemotePreviewSchemaVersion, Status: status})
68 if payload == nil {
69 return errors.New("vev: failed to encode remote preview status")
70 }
71 if _, err := os.Stdout.Write(payload); err != nil {
72 return fmt.Errorf("vev: writing remote preview status: %w", err)
73 }
74 return nil
75}