16
16
package commands
17
17
18
18
import (
19
+ "context"
19
20
"errors"
20
21
"os"
22
+ "sync/atomic"
21
23
22
24
"github.com/arduino/arduino-cli/internal/i18n"
23
25
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
26
+ "google.golang.org/grpc/metadata"
24
27
25
28
"fmt"
26
29
"io"
@@ -32,9 +35,68 @@ import (
32
35
"github.com/sirupsen/logrus"
33
36
)
34
37
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.
38
100
func (s * arduinoCoreServerImpl ) Debug (stream rpc.ArduinoCoreService_DebugServer ) error {
39
101
// Utility functions
40
102
syncSend := NewSynchronizedSend (stream .Send )
0 commit comments