@@ -3,35 +3,38 @@ package rct
33import (
44 "fmt"
55 "net"
6+ "sync"
67 "time"
78)
89
9- // DialTimeout is the default cache for connecting to a RCT device
10- var DialTimeout = time .Second * 5
10+ var (
11+ // DialTimeout is the default cache for connecting to a RCT device
12+ DialTimeout = time .Second * 5
13+
14+ // Map of active connections
15+ connectionCache = make (map [string ]* Connection )
16+ )
1117
1218// Connection to a RCT device
1319type Connection struct {
14- host string
15- conn net. Conn
16- builder * DatagramBuilder
17- parser * DatagramParser
18- cache * Cache
20+ mu sync. Mutex
21+ host string
22+ conn net. Conn
23+ parser * DatagramParser
24+ cache * Cache
1925}
2026
21- // Map of active connections
22- var connectionCache map [string ]* Connection = make (map [string ]* Connection )
23-
24- // Creates a new connection to a RCT device at the given address
27+ // Creates a new connection to a RCT device at the given address.
28+ // Must not be called concurrently.
2529func NewConnection (host string , cache time.Duration ) (* Connection , error ) {
2630 if conn , ok := connectionCache [host ]; ok {
2731 return conn , nil
2832 }
2933
3034 conn := & Connection {
31- host : host ,
32- builder : NewDatagramBuilder (),
33- parser : NewDatagramParser (),
34- cache : NewCache (cache ),
35+ host : host ,
36+ parser : NewDatagramParser (),
37+ cache : NewCache (cache ),
3538 }
3639
3740 if err := conn .connect (); err != nil {
@@ -57,6 +60,12 @@ func (c *Connection) Close() {
5760
5861// Sends the given RCT datagram via the connection
5962func (c * Connection ) Send (rdb * DatagramBuilder ) (n int , err error ) {
63+ c .mu .Lock ()
64+ defer c .mu .Unlock ()
65+ return c .send (rdb )
66+ }
67+
68+ func (c * Connection ) send (rdb * DatagramBuilder ) (n int , err error ) {
6069 // ensure active connection
6170 if c .conn == nil {
6271 if err := c .connect (); err != nil {
@@ -66,7 +75,6 @@ func (c *Connection) Send(rdb *DatagramBuilder) (n int, err error) {
6675
6776 // fmt.Printf("Sending %v\n", c.Builder.String())
6877 n , err = c .conn .Write (rdb .Bytes ())
69-
7078 // single retry on error when sending
7179 if err != nil {
7280 // fmt.Printf("Read %d bytes error %v\n", n, err)
@@ -83,6 +91,9 @@ func (c *Connection) Send(rdb *DatagramBuilder) (n int, err error) {
8391
8492// Receives an RCT response via the connection
8593func (c * Connection ) Receive () (dg * Datagram , err error ) {
94+ c .mu .Lock ()
95+ defer c .mu .Unlock ()
96+
8697 // ensure active connection
8798 if c .conn == nil {
8899 if err := c .connect (); err != nil {
@@ -106,11 +117,16 @@ func (c *Connection) Receive() (dg *Datagram, err error) {
106117
107118// Queries the given identifier on the RCT device, returning its value as a datagram
108119func (c * Connection ) Query (id Identifier ) (dg * Datagram , err error ) {
120+ c .mu .Lock ()
121+ defer c .mu .Unlock ()
122+
109123 if dg , ok := c .cache .Get (id ); ok {
110124 return dg , nil
111125 }
112- c .builder .Build (& Datagram {Read , id , nil })
113- _ , err = c .Send (c .builder )
126+
127+ builder := NewDatagramBuilder ()
128+ builder .Build (& Datagram {Read , id , nil })
129+ _ , err = c .send (builder )
114130 if err != nil {
115131 return nil , err
116132 }
0 commit comments