11package basicstation
22
33import (
4+ "crypto/rand"
45 "crypto/tls"
56 "crypto/x509"
7+ "encoding/binary"
68 "encoding/json"
79 "fmt"
810 "io/ioutil"
@@ -12,6 +14,7 @@ import (
1214 "sync"
1315 "time"
1416
17+ "github.com/gofrs/uuid"
1518 "github.com/golang/protobuf/ptypes"
1619 "github.com/gorilla/websocket"
1720 "github.com/pkg/errors"
@@ -55,6 +58,11 @@ type Backend struct {
5558 joinEUIs [][2 ]lorawan.EUI64
5659 frequencyMin uint32
5760 frequencyMax uint32
61+
62+ // diidMap stores the mapping of diid to UUIDs. This should take ~ 1MB of
63+ // memory. Optionaly this could be optimized by letting keys expire after
64+ // a given time.
65+ diidMap map [uint16 ][]byte
5866}
5967
6068// NewBackend creates a new Backend.
@@ -79,6 +87,8 @@ func NewBackend(conf config.Config) (*Backend, error) {
7987 region : band .Name (conf .Backend .BasicStation .Region ),
8088 frequencyMin : conf .Backend .BasicStation .FrequencyMin ,
8189 frequencyMax : conf .Backend .BasicStation .FrequencyMax ,
90+
91+ diidMap : make (map [uint16 ][]byte ),
8292 }
8393
8494 for _ , n := range conf .Filters .NetIDs {
@@ -191,20 +201,41 @@ func (b *Backend) GetDisconnectChan() chan lorawan.EUI64 {
191201}
192202
193203func (b * Backend ) SendDownlinkFrame (df gw.DownlinkFrame ) error {
204+ b .Lock ()
205+ defer b .Unlock ()
206+
207+ // for backwards compatibility
208+ if df .Token == 0 {
209+ tokenB := make ([]byte , 2 )
210+ if _ , err := rand .Read (tokenB ); err != nil {
211+ return errors .Wrap (err , "read random bytes error" )
212+ }
213+
214+ df .Token = uint32 (binary .BigEndian .Uint16 (tokenB ))
215+ }
216+
194217 pl , err := structs .DownlinkFrameFromProto (b .band , df )
195218 if err != nil {
196219 return errors .Wrap (err , "downlink frame from proto error" )
197220 }
198221
199222 var gatewayID lorawan.EUI64
200- copy (gatewayID [:], df .TxInfo .GatewayId )
223+ var downID uuid.UUID
224+ copy (gatewayID [:], df .GetTxInfo ().GetGatewayId ())
225+ copy (downID [:], df .GetDownlinkId ())
226+
227+ // store token to UUID mapping
228+ b .diidMap [uint16 (df .Token )] = df .GetDownlinkId ()
201229
202230 websocketSendCounter ("dnmsg" ).Inc ()
203231 if err := b .sendToGateway (gatewayID , pl ); err != nil {
204232 return errors .Wrap (err , "send to gateway error" )
205233 }
206234
207- log .WithField ("gateway_id" , gatewayID ).Info ("backend/basicstation: downlink-frame message sent to gateway" )
235+ log .WithFields (log.Fields {
236+ "gateway_id" : gatewayID ,
237+ "downlink_id" : downID ,
238+ }).Info ("backend/basicstation: downlink-frame message sent to gateway" )
208239
209240 return nil
210241}
@@ -216,7 +247,7 @@ func (b *Backend) ApplyConfiguration(gwConfig gw.GatewayConfiguration) error {
216247 }
217248
218249 var gatewayID lorawan.EUI64
219- copy (gatewayID [:], gwConfig .GatewayId )
250+ copy (gatewayID [:], gwConfig .GetGatewayId () )
220251
221252 websocketSendCounter ("router_config" ).Inc ()
222253 if err := b .sendToGateway (gatewayID , rc ); err != nil {
@@ -292,14 +323,13 @@ func (b *Backend) handleGateway(r *http.Request, c *websocket.Conn) {
292323 var cn lorawan.EUI64
293324 if err := cn .UnmarshalText ([]byte (r .TLS .PeerCertificates [0 ].Subject .CommonName )); err != nil || cn != gatewayID {
294325 log .WithFields (log.Fields {
295- "gateway_id" : gatewayID ,
326+ "gateway_id" : gatewayID ,
296327 "common_name" : r .TLS .PeerCertificates [0 ].Subject .CommonName ,
297328 }).Error ("backend/basicstation: CommonName verification failed" )
298329 return
299330 }
300331 }
301332
302-
303333 // make sure we're not overwriting an existing connection
304334 _ , err := b .gateways .get (gatewayID )
305335 if err == nil {
@@ -459,10 +489,6 @@ func (b *Backend) handleVersion(gatewayID lorawan.EUI64, pl structs.Version) {
459489}
460490
461491func (b * Backend ) handleJoinRequest (gatewayID lorawan.EUI64 , v structs.JoinRequest ) {
462- log .WithFields (log.Fields {
463- "gateway_id" : gatewayID ,
464- }).Info ("backend/basicstation: join-request received" )
465-
466492 uplinkFrame , err := structs .JoinRequestToProto (b .band , gatewayID , v )
467493 if err != nil {
468494 log .WithError (err ).WithFields (log.Fields {
@@ -471,14 +497,25 @@ func (b *Backend) handleJoinRequest(gatewayID lorawan.EUI64, v structs.JoinReque
471497 return
472498 }
473499
474- b .uplinkFrameChan <- uplinkFrame
475- }
500+ // set uplink id
501+ uplinkID , err := uuid .NewV4 ()
502+ if err != nil {
503+ log .WithError (err ).WithFields (log.Fields {
504+ "gateway_id" : gatewayID ,
505+ }).Error ("backend/basicstation: get random uplink id error" )
506+ return
507+ }
508+ uplinkFrame .RxInfo .UplinkId = uplinkID [:]
476509
477- func (b * Backend ) handleProprietaryDataFrame (gatewayID lorawan.EUI64 , v structs.UplinkProprietaryFrame ) {
478510 log .WithFields (log.Fields {
479511 "gateway_id" : gatewayID ,
480- }).Info ("backend/basicstation: proprietary uplink frame received" )
512+ "uplink_id" : uplinkID ,
513+ }).Info ("backend/basicstation: join-request received" )
514+
515+ b .uplinkFrameChan <- uplinkFrame
516+ }
481517
518+ func (b * Backend ) handleProprietaryDataFrame (gatewayID lorawan.EUI64 , v structs.UplinkProprietaryFrame ) {
482519 uplinkFrame , err := structs .UplinkProprietaryFrameToProto (b .band , gatewayID , v )
483520 if err != nil {
484521 log .WithError (err ).WithFields (log.Fields {
@@ -487,13 +524,27 @@ func (b *Backend) handleProprietaryDataFrame(gatewayID lorawan.EUI64, v structs.
487524 return
488525 }
489526
527+ // set uplink id
528+ uplinkID , err := uuid .NewV4 ()
529+ if err != nil {
530+ log .WithError (err ).WithFields (log.Fields {
531+ "gateway_id" : gatewayID ,
532+ }).Error ("backend/basicstation: get random uplink id error" )
533+ return
534+ }
535+ uplinkFrame .RxInfo .UplinkId = uplinkID [:]
536+
537+ log .WithFields (log.Fields {
538+ "gateway_id" : gatewayID ,
539+ "uplink_id" : uplinkID ,
540+ }).Info ("backend/basicstation: proprietary uplink frame received" )
541+
490542 b .uplinkFrameChan <- uplinkFrame
491543}
492544
493545func (b * Backend ) handleDownlinkTransmittedMessage (gatewayID lorawan.EUI64 , v structs.DownlinkTransmitted ) {
494- log .WithFields (log.Fields {
495- "gateway_id" : gatewayID ,
496- }).Info ("backend/basicstation: downlink transmitted message received" )
546+ b .RLock ()
547+ defer b .RUnlock ()
497548
498549 txack , err := structs .DownlinkTransmittedToProto (gatewayID , v )
499550 if err != nil {
@@ -502,15 +553,20 @@ func (b *Backend) handleDownlinkTransmittedMessage(gatewayID lorawan.EUI64, v st
502553 }).Error ("backend/basicstation: error converting downlink transmitted to protobuf message" )
503554 return
504555 }
556+ txack .DownlinkId = b .diidMap [uint16 (v .DIID )]
557+
558+ var downID uuid.UUID
559+ copy (downID [:], txack .GetDownlinkId ())
560+
561+ log .WithFields (log.Fields {
562+ "gateway_id" : gatewayID ,
563+ "downlink_id" : downID ,
564+ }).Info ("backend/basicstation: downlink transmitted message received" )
505565
506566 b .downlinkTXAckChan <- txack
507567}
508568
509569func (b * Backend ) handleUplinkDataFrame (gatewayID lorawan.EUI64 , v structs.UplinkDataFrame ) {
510- log .WithFields (log.Fields {
511- "gateway_id" : gatewayID ,
512- }).Info ("backend/basicstation: uplink frame received" )
513-
514570 uplinkFrame , err := structs .UplinkDataFrameToProto (b .band , gatewayID , v )
515571 if err != nil {
516572 log .WithError (err ).WithFields (log.Fields {
@@ -519,6 +575,21 @@ func (b *Backend) handleUplinkDataFrame(gatewayID lorawan.EUI64, v structs.Uplin
519575 return
520576 }
521577
578+ // set uplink id
579+ uplinkID , err := uuid .NewV4 ()
580+ if err != nil {
581+ log .WithError (err ).WithFields (log.Fields {
582+ "gateway_id" : gatewayID ,
583+ }).Error ("backend/basicstation: get random uplink id error" )
584+ return
585+ }
586+ uplinkFrame .RxInfo .UplinkId = uplinkID [:]
587+
588+ log .WithFields (log.Fields {
589+ "gateway_id" : gatewayID ,
590+ "uplink_id" : uplinkID ,
591+ }).Info ("backend/basicstation: uplink frame received" )
592+
522593 b .uplinkFrameChan <- uplinkFrame
523594}
524595
0 commit comments