Skip to content

Commit 8a92d40

Browse files
umbynoscmaglie
authored andcommitted
add open() and close() implementation along with other useful stuff
1 parent 84133d0 commit 8a92d40

File tree

5 files changed

+135
-13
lines changed

5 files changed

+135
-13
lines changed

dummy-monitor/dummy_port.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"io"
5+
)
6+
7+
type dummyPort struct {
8+
echo chan string
9+
portName string
10+
}
11+
12+
func newDummyPort(portName string) *dummyPort {
13+
return &dummyPort{
14+
echo: make(chan string, 20),
15+
portName: portName,
16+
}
17+
}
18+
19+
func (d *dummyPort) Close() error {
20+
close(d.echo)
21+
return nil
22+
}
23+
24+
func (d *dummyPort) Read(p []byte) (int, error) {
25+
data, ok := <-d.echo
26+
if !ok {
27+
return 0, io.EOF
28+
}
29+
n := copy(p, []byte(data))
30+
// if p is too small data loss may happen.. ¯\_(ツ)_/¯
31+
return n, nil
32+
}
33+
34+
func (d *dummyPort) Write(p []byte) (int, error) {
35+
d.echo <- string(p)
36+
return len(p), nil
37+
}

dummy-monitor/main.go

+15-5
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
package main
1919

2020
import (
21+
"errors"
2122
"fmt"
23+
"io"
2224
"os"
2325

24-
"github.com/arduino/go-properties-orderedmap"
2526
monitor "github.com/arduino/pluggable-monitor-protocol-handler"
2627
"github.com/arduino/pluggable-monitor-protocol-handler/dummy-monitor/args"
2728
)
@@ -53,6 +54,8 @@ var settings = &monitor.PortDescriptor{
5354
},
5455
}
5556

57+
var openedPort *dummyPort
58+
5659
func main() {
5760
args.Parse()
5861
dummy := &dummyMonitor{}
@@ -87,13 +90,20 @@ func (d *dummyMonitor) Configure(parameterName string, value string) error {
8790
return fmt.Errorf("invalid value for parameter %s: %s", parameterName, value)
8891
}
8992

90-
//TODO implement
91-
func (d *dummyMonitor) Open(ipAddress string, boardPort string) error {
92-
return nil
93+
func (d *dummyMonitor) Open(boardPort string) (io.ReadWriter, error) {
94+
if openedPort != nil {
95+
return nil, fmt.Errorf("port already opened: %s", openedPort.portName)
96+
}
97+
openedPort = newDummyPort(boardPort)
98+
return openedPort, nil
9399
}
94100

95-
//TODO implement
96101
func (d *dummyMonitor) Close() error {
102+
if openedPort == nil {
103+
return errors.New("port already closed")
104+
}
105+
openedPort.Close()
106+
openedPort = nil
97107
return nil
98108
}
99109

go.mod

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ module github.com/arduino/pluggable-monitor-protocol-handler
22

33
go 1.16
44

5-
require github.com/arduino/go-properties-orderedmap v1.4.0
5+
require (
6+
github.com/arduino/go-properties-orderedmap v1.4.0
7+
github.com/hashicorp/go-multierror v1.1.1
8+
)

go.sum

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ github.com/arduino/go-properties-orderedmap v1.4.0 h1:YEbbzPqm1gXWDM/Jaq8tlvmh09
44
github.com/arduino/go-properties-orderedmap v1.4.0/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
55
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
66
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
8+
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
9+
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
10+
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
711
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
812
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
913
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

monitor.go

+75-7
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@ import (
3131
"encoding/json"
3232
"fmt"
3333
"io"
34+
"net"
3435
"regexp"
3536
"strconv"
3637
"strings"
38+
"sync"
3739

3840
"github.com/arduino/go-properties-orderedmap"
41+
"github.com/hashicorp/go-multierror"
3942
)
4043

4144
// Port is a descriptor for a board port
@@ -62,7 +65,7 @@ type Monitor interface {
6265
Configure(parameterName string, value string) error
6366

6467
// Open allows to open a communication with the board using TCP/IP
65-
Open(ipAddress string, boardPort string) error
68+
Open(boardPort string) (io.ReadWriter, error)
6669

6770
// Close will close the currently open port and TCP/IP connection
6871
Close() error
@@ -80,6 +83,8 @@ type Server struct {
8083
userAgent string
8184
reqProtocolVersion int
8285
initialized bool
86+
clientConn net.Conn
87+
closeFuncMutex sync.Mutex
8388
}
8489

8590
// NewServer creates a new monitor server backed by the
@@ -126,7 +131,7 @@ func (d *Server) Run(in io.Reader, out io.Writer) error {
126131
case "OPEN":
127132
d.open(fullCmd[5:])
128133
case "CLOSE":
129-
d.close()
134+
d.close("")
130135
case "QUIT":
131136
d.impl.Quit()
132137
d.outputChan <- messageOk("quit")
@@ -208,13 +213,76 @@ func (d *Server) configure(cmd string) {
208213
}
209214

210215
func (d *Server) open(cmd string) {
211-
212-
}
213-
214-
func (d *Server) close() {
215-
216+
if !d.initialized {
217+
d.outputChan <- messageError("open", "Monitor not initialized")
218+
return
219+
}
220+
parameters := strings.SplitN(cmd, " ", 2)
221+
if len(parameters) != 2 {
222+
d.outputChan <- messageError("open", "Invalid OPEN command")
223+
return
224+
}
225+
address := parameters[0]
226+
portName := parameters[1]
227+
port, err := d.impl.Open(portName)
228+
if err != nil {
229+
d.outputChan <- messageError("open", err.Error())
230+
return
231+
}
232+
d.clientConn, err = net.Dial("tcp", address)
233+
if err != nil {
234+
d.impl.Close()
235+
d.outputChan <- messageError("open", err.Error())
236+
return
237+
}
238+
// io.Copy is used to bridge the Client's TCP connection to the port one and vice versa
239+
go func() {
240+
_, err := io.Copy(port, d.clientConn) // Copy is blocking, so we run it insiede a gorutine
241+
if err != nil {
242+
d.close(err.Error())
243+
} else {
244+
d.close("lost TCP/IP connection with the client!")
245+
}
246+
}()
247+
go func() {
248+
_, err := io.Copy(d.clientConn, port) // Copy is blocking, so we run it insiede a gorutine
249+
if err != nil {
250+
d.close(err.Error())
251+
} else {
252+
d.close("lost connection with the port")
253+
}
254+
}()
255+
d.outputChan <- &message{
256+
EventType: "open",
257+
Message: "OK",
258+
}
216259
}
217260

261+
func (d *Server) close(messageErr string) {
262+
d.closeFuncMutex.Lock()
263+
defer d.closeFuncMutex.Unlock()
264+
if d.clientConn == nil {
265+
// TODO
266+
// d.outputChan <- messageError("close", "port already closed")
267+
return
268+
}
269+
connErr := d.clientConn.Close()
270+
portErr := d.impl.Close()
271+
d.clientConn = nil
272+
if messageErr != "" {
273+
d.outputChan <- messageError("port_closed", messageErr)
274+
return
275+
}
276+
if connErr != nil || portErr != nil {
277+
var errs *multierror.Error
278+
errs = multierror.Append(errs, connErr, portErr)
279+
d.outputChan <- messageError("close", errs.Error())
280+
return
281+
}
282+
d.outputChan <- &message{
283+
EventType: "close",
284+
Message: "OK",
285+
}
218286
}
219287

220288
func (d *Server) outputProcessor(outWriter io.Writer) {

0 commit comments

Comments
 (0)