@@ -20,12 +20,16 @@ package main
20
20
import (
21
21
"context"
22
22
"fmt"
23
+ "io/ioutil"
24
+ "log"
23
25
"os"
24
26
"strconv"
27
+ "strings"
28
+ "time"
25
29
26
30
properties "github.com/arduino/go-properties-orderedmap"
27
31
discovery "github.com/arduino/pluggable-discovery-protocol-handler"
28
- "github.com/brutella/dnssd "
32
+ "github.com/hashicorp/mdns "
29
33
)
30
34
31
35
func main () {
@@ -39,15 +43,18 @@ func main() {
39
43
40
44
}
41
45
42
- const mdnsServiceName = "_arduino._tcp.local. "
46
+ const mdnsServiceName = "_arduino._tcp"
43
47
44
48
// MDNSDiscovery is the implementation of the network pluggable-discovery
45
49
type MDNSDiscovery struct {
46
- cancelFunc func ()
50
+ cancelFunc func ()
51
+ entriesChan chan * mdns.ServiceEntry
47
52
}
48
53
49
54
// Hello handles the pluggable-discovery HELLO command
50
55
func (d * MDNSDiscovery ) Hello (userAgent string , protocolVersion int ) error {
56
+ // The mdns library used has some logs statement that we must disable
57
+ log .SetOutput (ioutil .Discard )
51
58
return nil
52
59
}
53
60
@@ -57,52 +64,87 @@ func (d *MDNSDiscovery) Stop() error {
57
64
d .cancelFunc ()
58
65
d .cancelFunc = nil
59
66
}
67
+ if d .entriesChan != nil {
68
+ close (d .entriesChan )
69
+ d .entriesChan = nil
70
+ }
60
71
return nil
61
72
}
62
73
63
74
// Quit handles the pluggable-discovery QUIT command
64
75
func (d * MDNSDiscovery ) Quit () {
76
+ close (d .entriesChan )
65
77
}
66
78
67
79
// StartSync handles the pluggable-discovery START_SYNC command
68
80
func (d * MDNSDiscovery ) StartSync (eventCB discovery.EventCallback , errorCB discovery.ErrorCallback ) error {
69
- addFn := func ( srv dnssd. Service ) {
70
- eventCB ( "add" , newBoardPortJSON ( & srv ) )
81
+ if d . entriesChan != nil {
82
+ return fmt . Errorf ( "already syncing" )
71
83
}
72
- remFn := func (srv dnssd.Service ) {
73
- eventCB ("remove" , newBoardPortJSON (& srv ))
84
+
85
+ d .entriesChan = make (chan * mdns.ServiceEntry , 4 )
86
+ var receiver <- chan * mdns.ServiceEntry = d .entriesChan
87
+ var sender chan <- * mdns.ServiceEntry = d .entriesChan
88
+
89
+ go func () {
90
+ for entry := range receiver {
91
+ eventCB ("add" , toDiscoveryPort (entry ))
92
+ }
93
+ }()
94
+
95
+ params := & mdns.QueryParam {
96
+ Service : mdnsServiceName ,
97
+ Domain : "local" ,
98
+ Timeout : time .Second * 15 ,
99
+ Entries : sender ,
100
+ WantUnicastResponse : false ,
74
101
}
75
- ctx , cancel := context .WithCancel (context .Background ())
76
102
103
+ ctx , cancel := context .WithCancel (context .Background ())
77
104
go func () {
78
- if err := dnssd .LookupType (ctx , mdnsServiceName , addFn , remFn ); err != nil {
79
- errorCB ("mdns lookup error: " + err .Error ())
105
+ for {
106
+ if err := mdns .Query (params ); err != nil {
107
+ errorCB ("mdns lookup error: " + err .Error ())
108
+ }
109
+ select {
110
+ default :
111
+ case <- ctx .Done ():
112
+ return
113
+ }
80
114
}
81
115
}()
82
116
d .cancelFunc = cancel
83
117
return nil
84
118
}
85
119
86
- func newBoardPortJSON (port * dnssd.Service ) * discovery.Port {
87
- ip := "127.0.0.1"
88
- if len (port .IPs ) > 0 {
89
- ip = port .IPs [0 ].String ()
120
+ func toDiscoveryPort (entry * mdns.ServiceEntry ) * discovery.Port {
121
+ ip := ""
122
+ if len (entry .AddrV4 ) > 0 {
123
+ ip = entry .AddrV4 .String ()
124
+ } else if len (entry .AddrV6 ) > 0 {
125
+ ip = entry .AddrV6 .String ()
90
126
}
91
127
92
128
props := properties .NewMap ()
93
- props .Set ("ttl" , strconv .Itoa (int (port .TTL .Seconds ())))
94
- props .Set ("hostname" , port .Hostname ())
95
- props .Set ("port" , strconv .Itoa (port .Port ))
96
- for key , value := range port .Text {
129
+ props .Set ("hostname" , entry .Host )
130
+ props .Set ("port" , strconv .Itoa (entry .Port ))
131
+
132
+ for _ , field := range entry .InfoFields {
133
+ split := strings .Split (field , "=" )
134
+ if len (split ) != 2 {
135
+ continue
136
+ }
137
+ key , value := split [0 ], split [1 ]
97
138
props .Set (key , value )
98
139
if key == "board" {
99
140
// duplicate for backwards compatibility
100
141
props .Set ("." , value )
101
142
}
102
143
}
144
+
103
145
return & discovery.Port {
104
146
Address : ip ,
105
- AddressLabel : port . Name + " at " + ip ,
147
+ AddressLabel : fmt . Sprintf ( "%s at %s" , entry . Name , ip ) ,
106
148
Protocol : "network" ,
107
149
ProtocolLabel : "Network Port" ,
108
150
Properties : props ,
0 commit comments