@@ -84,7 +84,7 @@ func NewBackend(conf config.Config) (*Backend, error) {
84
84
scheme : "ws" ,
85
85
86
86
gateways : gateways {
87
- gateways : make (map [lorawan.EUI64 ]gateway ),
87
+ gateways : make (map [lorawan.EUI64 ]* connection ),
88
88
},
89
89
90
90
caCert : conf .Backend .BasicStation .CACert ,
@@ -312,11 +312,11 @@ func (b *Backend) Stop() error {
312
312
return b .ln .Close ()
313
313
}
314
314
315
- func (b * Backend ) handleRouterInfo (r * http.Request , c * websocket. Conn ) {
315
+ func (b * Backend ) handleRouterInfo (r * http.Request , conn * connection ) {
316
316
websocketReceiveCounter ("router_info" ).Inc ()
317
317
var req structs.RouterInfoRequest
318
318
319
- if err := c .ReadJSON (& req ); err != nil {
319
+ if err := conn . conn .ReadJSON (& req ); err != nil {
320
320
if websocket .IsUnexpectedCloseError (err , websocket .CloseNormalClosure , websocket .CloseGoingAway , websocket .CloseAbnormalClosure ) {
321
321
log .WithError (err ).Error ("backend/basicstation: read message error" )
322
322
}
@@ -345,8 +345,11 @@ func (b *Backend) handleRouterInfo(r *http.Request, c *websocket.Conn) {
345
345
return
346
346
}
347
347
348
- c .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
349
- if err := c .WriteMessage (websocket .TextMessage , bb ); err != nil {
348
+ conn .Lock ()
349
+ defer conn .Unlock ()
350
+
351
+ conn .conn .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
352
+ if err := conn .conn .WriteMessage (websocket .TextMessage , bb ); err != nil {
350
353
log .WithError (err ).Error ("backend/basicstation: websocket send message error" )
351
354
return
352
355
}
@@ -358,7 +361,7 @@ func (b *Backend) handleRouterInfo(r *http.Request, c *websocket.Conn) {
358
361
}).Info ("backend/basicstation: router-info request received" )
359
362
}
360
363
361
- func (b * Backend ) handleGateway (r * http.Request , c * websocket. Conn ) {
364
+ func (b * Backend ) handleGateway (r * http.Request , conn * connection ) {
362
365
// get the gateway id from the url
363
366
urlParts := strings .Split (r .URL .Path , "/" )
364
367
if len (urlParts ) < 2 {
@@ -391,7 +394,7 @@ func (b *Backend) handleGateway(r *http.Request, c *websocket.Conn) {
391
394
}
392
395
393
396
// set the gateway connection
394
- if err := b .gateways .set (gatewayID , gateway { conn : c } ); err != nil {
397
+ if err := b .gateways .set (gatewayID , conn ); err != nil {
395
398
log .WithError (err ).WithField ("gateway_id" , gatewayID ).Error ("backend/basicstation: set gateway error" )
396
399
}
397
400
log .WithFields (log.Fields {
@@ -466,7 +469,7 @@ func (b *Backend) handleGateway(r *http.Request, c *websocket.Conn) {
466
469
467
470
// receive data
468
471
for {
469
- mt , msg , err := c .ReadMessage ()
472
+ mt , msg , err := conn . conn .ReadMessage ()
470
473
if err != nil {
471
474
if websocket .IsUnexpectedCloseError (err , websocket .CloseNormalClosure , websocket .CloseGoingAway , websocket .CloseAbnormalClosure ) {
472
475
log .WithField ("gateway_id" , gatewayID ).WithError (err ).Error ("backend/basicstation: read message error" )
@@ -475,7 +478,7 @@ func (b *Backend) handleGateway(r *http.Request, c *websocket.Conn) {
475
478
}
476
479
477
480
// reset the read deadline as the Basic Station doesn't respond to PONG messages (yet)
478
- c .SetReadDeadline (time .Now ().Add (b .readTimeout ))
481
+ conn . conn .SetReadDeadline (time .Now ().Add (b .readTimeout ))
479
482
480
483
if mt == websocket .BinaryMessage {
481
484
log .WithFields (log.Fields {
@@ -768,11 +771,14 @@ func (b *Backend) handleTimeSync(gatewayID lorawan.EUI64, v structs.TimeSyncRequ
768
771
}
769
772
770
773
func (b * Backend ) sendToGateway (gatewayID lorawan.EUI64 , v interface {}) error {
771
- gw , err := b .gateways .get (gatewayID )
774
+ conn , err := b .gateways .get (gatewayID )
772
775
if err != nil {
773
776
return errors .Wrap (err , "get gateway error" )
774
777
}
775
778
779
+ conn .Lock ()
780
+ defer conn .Unlock ()
781
+
776
782
bb , err := json .Marshal (v )
777
783
if err != nil {
778
784
return errors .Wrap (err , "marshal json error" )
@@ -783,29 +789,32 @@ func (b *Backend) sendToGateway(gatewayID lorawan.EUI64, v interface{}) error {
783
789
"message" : string (bb ),
784
790
}).Debug ("sending message to gateway" )
785
791
786
- gw .conn .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
787
- if err := gw .conn .WriteMessage (websocket .TextMessage , bb ); err != nil {
792
+ conn .conn .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
793
+ if err := conn .conn .WriteMessage (websocket .TextMessage , bb ); err != nil {
788
794
return errors .Wrap (err , "send message to gateway error" )
789
795
}
790
796
791
797
return nil
792
798
}
793
799
794
800
func (b * Backend ) sendRawToGateway (gatewayID lorawan.EUI64 , messageType int , data []byte ) error {
795
- gw , err := b .gateways .get (gatewayID )
801
+ conn , err := b .gateways .get (gatewayID )
796
802
if err != nil {
797
803
return errors .Wrap (err , "get gateway error" )
798
804
}
799
805
800
- gw .conn .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
801
- if err := gw .conn .WriteMessage (messageType , data ); err != nil {
806
+ conn .Lock ()
807
+ defer conn .Unlock ()
808
+
809
+ conn .conn .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
810
+ if err := conn .conn .WriteMessage (messageType , data ); err != nil {
802
811
return errors .Wrap (err , "send message to gateway error" )
803
812
}
804
813
805
814
return nil
806
815
}
807
816
808
- func (b * Backend ) websocketWrap (handler func (* http.Request , * websocket. Conn ), w http.ResponseWriter , r * http.Request ) {
817
+ func (b * Backend ) websocketWrap (handler func (* http.Request , * connection ), w http.ResponseWriter , r * http.Request ) {
809
818
conn , err := upgrader .Upgrade (w , r , nil )
810
819
if err != nil {
811
820
log .WithError (err ).Error ("backend/basicstation: websocket upgrade error" )
@@ -824,23 +833,29 @@ func (b *Backend) websocketWrap(handler func(*http.Request, *websocket.Conn), w
824
833
defer ticker .Stop ()
825
834
done := make (chan struct {})
826
835
836
+ // Wrap the conn inside a gateway struct, so that we can lock it when writing
837
+ // data.
838
+ c := connection {conn : conn }
839
+
827
840
go func () {
828
841
for {
829
842
select {
830
843
case <- ticker .C :
844
+ c .Lock ()
831
845
websocketPingPongCounter ("ping" ).Inc ()
832
- conn .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
846
+ c . conn .SetWriteDeadline (time .Now ().Add (b .writeTimeout ))
833
847
if err := conn .WriteMessage (websocket .PingMessage , nil ); err != nil {
834
848
log .WithError (err ).Error ("backend/basicstation: send ping message error" )
835
- conn .Close ()
849
+ c . conn .Close ()
836
850
}
851
+ c .Unlock ()
837
852
case <- done :
838
853
return
839
854
}
840
855
}
841
856
}()
842
857
843
- handler (r , conn )
858
+ handler (r , & c )
844
859
done <- struct {}{}
845
860
}
846
861
0 commit comments