Skip to content

Commit a88fe8c

Browse files
committed
Added Debug gRPC adapter function
1 parent 6983673 commit a88fe8c

File tree

2 files changed

+69
-4
lines changed

2 files changed

+69
-4
lines changed

commands/service_debug.go

+65-3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616
package commands
1717

1818
import (
19+
"context"
1920
"errors"
2021
"os"
22+
"sync/atomic"
2123

2224
"github.com/arduino/arduino-cli/internal/i18n"
2325
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
26+
"google.golang.org/grpc/metadata"
2427

2528
"fmt"
2629
"io"
@@ -32,9 +35,68 @@ import (
3235
"github.com/sirupsen/logrus"
3336
)
3437

35-
// Debug returns a stream response that can be used to fetch data from the
36-
// target. The first message passed through the `Debug` request must
37-
// contain DebugRequest configuration params, not data.
38+
type debugServer struct {
39+
ctx context.Context
40+
req atomic.Pointer[rpc.GetDebugConfigRequest]
41+
in io.Reader
42+
out io.Writer
43+
resultCB func(*rpc.DebugResponse_Result)
44+
}
45+
46+
func (s *debugServer) Send(resp *rpc.DebugResponse) error {
47+
if len(resp.GetData()) > 0 {
48+
if _, err := s.out.Write(resp.GetData()); err != nil {
49+
return err
50+
}
51+
}
52+
if res := resp.GetResult(); res != nil {
53+
s.resultCB(res)
54+
}
55+
return nil
56+
}
57+
58+
func (s *debugServer) Recv() (r *rpc.DebugRequest, e error) {
59+
if conf := s.req.Swap(nil); conf != nil {
60+
return &rpc.DebugRequest{DebugRequest: conf}, nil
61+
}
62+
buff := make([]byte, 4096)
63+
n, err := s.in.Read(buff)
64+
if err != nil {
65+
return nil, err
66+
}
67+
return &rpc.DebugRequest{Data: buff[:n]}, nil
68+
}
69+
70+
func (s *debugServer) Context() context.Context { return s.ctx }
71+
func (s *debugServer) RecvMsg(m any) error { return nil }
72+
func (s *debugServer) SendHeader(metadata.MD) error { return nil }
73+
func (s *debugServer) SendMsg(m any) error { return nil }
74+
func (s *debugServer) SetHeader(metadata.MD) error { return nil }
75+
func (s *debugServer) SetTrailer(metadata.MD) {}
76+
77+
// DebugServerToStreams creates a debug server that proxies the data to the given io streams.
78+
// The GetDebugConfigRequest is used to configure the debbuger. sig is a channel that can be
79+
// used to send os.Interrupt to the debug process. resultCB is a callback function that will
80+
// receive the Debug result.
81+
func DebugServerToStreams(
82+
ctx context.Context,
83+
req *rpc.GetDebugConfigRequest,
84+
in io.Reader, out io.Writer,
85+
sig chan os.Signal,
86+
resultCB func(*rpc.DebugResponse_Result),
87+
) rpc.ArduinoCoreService_DebugServer {
88+
server := &debugServer{
89+
ctx: ctx,
90+
in: in,
91+
out: out,
92+
resultCB: resultCB,
93+
}
94+
server.req.Store(req)
95+
return server
96+
}
97+
98+
// Debug starts a debugging session. The first message passed through the `Debug` request must
99+
// contain DebugRequest configuration params and no data.
38100
func (s *arduinoCoreServerImpl) Debug(stream rpc.ArduinoCoreService_DebugServer) error {
39101
// Utility functions
40102
syncSend := NewSynchronizedSend(stream.Send)

internal/cli/debug/debug.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,10 @@ func runDebugCommand(ctx context.Context, srv rpc.ArduinoCoreServiceServer, args
142142
if err != nil {
143143
feedback.FatalError(err, feedback.ErrBadArgument)
144144
}
145-
if _, err := commands.Debug(ctx, debugConfigRequested, in, out, ctrlc); err != nil {
145+
146+
resultCB := func(dr *rpc.DebugResponse_Result) {}
147+
stream := commands.DebugServerToStreams(ctx, debugConfigRequested, in, out, ctrlc, resultCB)
148+
if err := srv.Debug(stream); err != nil {
146149
errcode := feedback.ErrGeneric
147150
if errors.Is(err, &cmderrors.MissingProgrammerError{}) {
148151
errcode = feedback.ErrMissingProgrammer

0 commit comments

Comments
 (0)