Example #1
0
// NewRedisNetworkServer creates a new Redis-backed NetworkServer
func NewRedisNetworkServer(client *redis.Client, netID int) NetworkServer {
	ns := &networkServer{
		devices:  device.NewRedisDeviceStore(client, "ns"),
		prefixes: map[types.DevAddrPrefix][]string{},
	}
	ns.netID = [3]byte{byte(netID >> 16), byte(netID >> 8), byte(netID)}
	return ns
}
Example #2
0
func TestHandleActivate(t *testing.T) {
	a := New(t)
	ns := &networkServer{
		devices: device.NewRedisDeviceStore(GetRedisClient(), "test-handle-activate"),
	}
	ns.InitStatus()

	dev := &device.Device{
		AppEUI: types.AppEUI(getEUI(0, 0, 0, 0, 0, 0, 3, 1)),
		DevEUI: types.DevEUI(getEUI(0, 0, 0, 0, 0, 0, 3, 1)),
	}
	a.So(ns.devices.Set(dev), ShouldBeNil)
	defer func() {
		ns.devices.Delete(types.AppEUI(getEUI(0, 0, 0, 0, 0, 0, 3, 1)), types.DevEUI(getEUI(0, 0, 0, 0, 0, 0, 3, 1)))
	}()

	_, err := ns.HandleActivate(&pb_handler.DeviceActivationResponse{})
	a.So(err, ShouldNotBeNil)

	_, err = ns.HandleActivate(&pb_handler.DeviceActivationResponse{
		ActivationMetadata: &pb_protocol.ActivationMetadata{},
	})
	a.So(err, ShouldNotBeNil)

	devAddr := getDevAddr(0, 0, 3, 1)
	var nwkSKey types.NwkSKey
	copy(nwkSKey[:], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1})
	appEUI := types.AppEUI(getEUI(0, 0, 0, 0, 0, 0, 3, 1))
	devEUI := types.DevEUI(getEUI(0, 0, 0, 0, 0, 0, 3, 1))
	_, err = ns.HandleActivate(&pb_handler.DeviceActivationResponse{
		ActivationMetadata: &pb_protocol.ActivationMetadata{Protocol: &pb_protocol.ActivationMetadata_Lorawan{
			Lorawan: &pb_lorawan.ActivationMetadata{
				AppEui:  &appEUI,
				DevEui:  &devEUI,
				DevAddr: &devAddr,
				NwkSKey: &nwkSKey,
			},
		}},
	})
	a.So(err, ShouldBeNil)
}
Example #3
0
func TestHandleDownlink(t *testing.T) {
	a := New(t)
	ns := &networkServer{
		devices: device.NewRedisDeviceStore(GetRedisClient(), "test-handle-downlink"),
	}
	ns.InitStatus()

	appEUI := types.AppEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8))
	devEUI := types.DevEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8))
	devAddr := getDevAddr(1, 2, 3, 4)

	// Device Not Found
	message := &pb_broker.DownlinkMessage{
		AppEui:  &appEUI,
		DevEui:  &devEUI,
		Payload: []byte{},
	}
	_, err := ns.HandleDownlink(message)
	a.So(err, ShouldNotBeNil)

	ns.devices.Set(&device.Device{
		DevAddr: devAddr,
		AppEUI:  appEUI,
		DevEUI:  devEUI,
	})
	defer func() {
		ns.devices.Delete(appEUI, devEUI)
	}()

	// Invalid Payload
	message = &pb_broker.DownlinkMessage{
		AppEui:  &appEUI,
		DevEui:  &devEUI,
		Payload: []byte{},
	}
	_, err = ns.HandleDownlink(message)
	a.So(err, ShouldNotBeNil)

	fPort := uint8(3)
	phy := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.UnconfirmedDataDown,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.MACPayload{
			FPort: &fPort,
			FHDR: lorawan.FHDR{
				FCtrl: lorawan.FCtrl{
					ACK: true,
				},
			},
		},
	}
	bytes, _ := phy.MarshalBinary()

	message = &pb_broker.DownlinkMessage{
		AppEui:  &appEUI,
		DevEui:  &devEUI,
		Payload: bytes,
	}
	res, err := ns.HandleDownlink(message)
	a.So(err, ShouldBeNil)

	var phyPayload lorawan.PHYPayload
	phyPayload.UnmarshalBinary(res.Payload)
	macPayload, _ := phyPayload.MACPayload.(*lorawan.MACPayload)
	a.So(*macPayload.FPort, ShouldEqual, 3)
	a.So(macPayload.FHDR.DevAddr, ShouldEqual, lorawan.DevAddr{1, 2, 3, 4})
	a.So(macPayload.FHDR.FCnt, ShouldEqual, 0)                // The first Frame counter is zero
	a.So(phyPayload.MIC, ShouldNotEqual, [4]byte{0, 0, 0, 0}) // MIC should be set, we'll check it with actual examples in the integration test

	dev, _ := ns.devices.Get(appEUI, devEUI)
	a.So(dev.FCntDown, ShouldEqual, 1)

}
Example #4
0
func TestHandlePrepareActivation(t *testing.T) {
	a := New(t)
	ns := &networkServer{
		netID: [3]byte{0x00, 0x00, 0x13},
		prefixes: map[types.DevAddrPrefix][]string{
			types.DevAddrPrefix{DevAddr: [4]byte{0x26, 0x00, 0x00, 0x00}, Length: 7}: []string{
				"otaa",
				"local",
			},
		},
		devices: device.NewRedisDeviceStore(GetRedisClient(), "test-handle-prepare-activation"),
	}

	appEUI := types.AppEUI(getEUI(2, 2, 3, 4, 5, 6, 7, 8))
	devEUI := types.DevEUI(getEUI(2, 2, 3, 4, 5, 6, 7, 8))

	// Device not registered
	resp, err := ns.HandlePrepareActivation(&pb_broker.DeduplicatedDeviceActivationRequest{
		ActivationMetadata: &pb_protocol.ActivationMetadata{Protocol: &pb_protocol.ActivationMetadata_Lorawan{
			Lorawan: &pb_lorawan.ActivationMetadata{
				CfList: &pb_lorawan.CFList{Freq: []uint32{867100000, 867300000, 867500000, 867700000, 867900000}},
			},
		}},
		ResponseTemplate: &pb_broker.DeviceActivationResponse{},
	})
	a.So(err, ShouldNotBeNil)

	dev := &device.Device{AppEUI: appEUI, DevEUI: devEUI, Options: device.Options{
		ActivationConstraints: "private",
	}}
	a.So(ns.devices.Set(dev), ShouldBeNil)

	defer func() {
		ns.devices.Delete(appEUI, devEUI)
	}()

	// Constrained Device
	resp, err = ns.HandlePrepareActivation(&pb_broker.DeduplicatedDeviceActivationRequest{
		DevEui: &devEUI,
		AppEui: &appEUI,
		ActivationMetadata: &pb_protocol.ActivationMetadata{Protocol: &pb_protocol.ActivationMetadata_Lorawan{
			Lorawan: &pb_lorawan.ActivationMetadata{
				CfList: &pb_lorawan.CFList{Freq: []uint32{867100000, 867300000, 867500000, 867700000, 867900000}},
			},
		}},
		ResponseTemplate: &pb_broker.DeviceActivationResponse{},
	})
	a.So(err, ShouldNotBeNil)

	dev.StartUpdate()
	dev.Options = device.Options{}
	a.So(ns.devices.Set(dev), ShouldBeNil)

	// Device registered
	resp, err = ns.HandlePrepareActivation(&pb_broker.DeduplicatedDeviceActivationRequest{
		DevEui: &devEUI,
		AppEui: &appEUI,
		ActivationMetadata: &pb_protocol.ActivationMetadata{Protocol: &pb_protocol.ActivationMetadata_Lorawan{
			Lorawan: &pb_lorawan.ActivationMetadata{
				CfList: &pb_lorawan.CFList{Freq: []uint32{867100000, 867300000, 867500000, 867700000, 867900000}},
			},
		}},
		ResponseTemplate: &pb_broker.DeviceActivationResponse{},
	})
	a.So(err, ShouldBeNil)
	devAddr := resp.ActivationMetadata.GetLorawan().DevAddr
	a.So(devAddr.IsEmpty(), ShouldBeFalse)
	a.So(devAddr[0]&254, ShouldEqual, 19<<1) // 7 MSB should be NetID

	var resPHY lorawan.PHYPayload
	resPHY.UnmarshalBinary(resp.ResponseTemplate.Payload)
	resMAC, _ := resPHY.MACPayload.(*lorawan.DataPayload)
	joinAccept := &lorawan.JoinAcceptPayload{}
	joinAccept.UnmarshalBinary(false, resMAC.Bytes)

	a.So(joinAccept.DevAddr[0]&254, ShouldEqual, 19<<1)
	a.So(*joinAccept.CFList, ShouldEqual, lorawan.CFList{867100000, 867300000, 867500000, 867700000, 867900000})
}
Example #5
0
func TestHandleUplink(t *testing.T) {
	a := New(t)
	ns := &networkServer{
		devices: device.NewRedisDeviceStore(GetRedisClient(), "ns-test-handle-uplink"),
	}
	ns.InitStatus()

	appEUI := types.AppEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8))
	devEUI := types.DevEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8))
	devAddr := getDevAddr(1, 2, 3, 4)

	// Device Not Found
	message := &pb_broker.DeduplicatedUplinkMessage{
		AppEui:  &appEUI,
		DevEui:  &devEUI,
		Payload: []byte{},
	}
	_, err := ns.HandleUplink(message)
	a.So(err, ShouldNotBeNil)

	ns.devices.Set(&device.Device{
		DevAddr: devAddr,
		AppEUI:  appEUI,
		DevEUI:  devEUI,
	})
	defer func() {
		ns.devices.Delete(appEUI, devEUI)
	}()

	// Invalid Payload
	message = &pb_broker.DeduplicatedUplinkMessage{
		AppEui:  &appEUI,
		DevEui:  &devEUI,
		Payload: []byte{},
	}
	_, err = ns.HandleUplink(message)
	a.So(err, ShouldNotBeNil)

	phy := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.UnconfirmedDataUp,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.MACPayload{
			FHDR: lorawan.FHDR{
				DevAddr: lorawan.DevAddr([4]byte{1, 2, 3, 4}),
				FCnt:    1,
				FCtrl: lorawan.FCtrl{
					ADR:       true,
					ADRACKReq: true,
				},
				FOpts: []lorawan.MACCommand{
					lorawan.MACCommand{CID: lorawan.LinkCheckReq},
				},
			},
		},
	}
	bytes, _ := phy.MarshalBinary()

	// Valid Uplink
	message = &pb_broker.DeduplicatedUplinkMessage{
		AppEui:           &appEUI,
		DevEui:           &devEUI,
		Payload:          bytes,
		ResponseTemplate: &pb_broker.DownlinkMessage{},
		GatewayMetadata: []*pb_gateway.RxMetadata{
			&pb_gateway.RxMetadata{},
		},
		ProtocolMetadata: &pb_protocol.RxMetadata{Protocol: &pb_protocol.RxMetadata_Lorawan{
			Lorawan: &pb_lorawan.Metadata{
				DataRate: "SF7BW125",
			},
		}},
	}
	res, err := ns.HandleUplink(message)
	a.So(err, ShouldBeNil)
	a.So(res.ResponseTemplate, ShouldNotBeNil)

	// LoRaWAN: Unmarshal
	var phyPayload lorawan.PHYPayload
	phyPayload.UnmarshalBinary(res.ResponseTemplate.Payload)
	macPayload, _ := phyPayload.MACPayload.(*lorawan.MACPayload)

	// ResponseTemplate DevAddr should match
	a.So([4]byte(macPayload.FHDR.DevAddr), ShouldEqual, [4]byte(devAddr))

	// ResponseTemplate should ACK the ADRACKReq
	a.So(macPayload.FHDR.FCtrl.ACK, ShouldBeTrue)
	a.So(macPayload.FHDR.FOpts, ShouldHaveLength, 1)
	a.So(macPayload.FHDR.FOpts[0].Payload, ShouldResemble, &lorawan.LinkCheckAnsPayload{GwCnt: 1, Margin: 7})

	// Frame Counter should have been updated
	dev, _ := ns.devices.Get(appEUI, devEUI)
	a.So(dev.FCntUp, ShouldEqual, 1)
	a.So(time.Now().Sub(dev.LastSeen), ShouldBeLessThan, 1*time.Second)
}
Example #6
0
func TestHandleGetDevices(t *testing.T) {
	a := New(t)

	ns := &networkServer{
		devices: device.NewRedisDeviceStore(GetRedisClient(), "ns-test-handle-get-devices"),
	}

	nwkSKey := types.NwkSKey{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}

	// No Devices
	devAddr1 := getDevAddr(1, 2, 3, 4)
	res, err := ns.HandleGetDevices(&pb.DevicesRequest{
		DevAddr: &devAddr1,
		FCnt:    5,
	})
	a.So(err, ShouldBeNil)
	a.So(res.Results, ShouldBeEmpty)

	// Matching Device
	ns.devices.Set(&device.Device{
		DevAddr: getDevAddr(1, 2, 3, 4),
		AppEUI:  types.AppEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8)),
		DevEUI:  types.DevEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8)),
		NwkSKey: nwkSKey,
		FCntUp:  5,
	})
	defer func() {
		ns.devices.Delete(types.AppEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8)), types.DevEUI(getEUI(1, 2, 3, 4, 5, 6, 7, 8)))
	}()

	res, err = ns.HandleGetDevices(&pb.DevicesRequest{
		DevAddr: &devAddr1,
		FCnt:    5,
	})
	a.So(err, ShouldBeNil)
	a.So(res.Results, ShouldHaveLength, 1)

	// Non-Matching DevAddr
	devAddr2 := getDevAddr(5, 6, 7, 8)
	res, err = ns.HandleGetDevices(&pb.DevicesRequest{
		DevAddr: &devAddr2,
		FCnt:    5,
	})
	a.So(err, ShouldBeNil)
	a.So(res.Results, ShouldHaveLength, 0)

	// Non-Matching FCnt
	res, err = ns.HandleGetDevices(&pb.DevicesRequest{
		DevAddr: &devAddr1,
		FCnt:    4,
	})
	a.So(err, ShouldBeNil)
	a.So(res.Results, ShouldHaveLength, 0)

	// Non-Matching FCnt, but FCnt Check Disabled
	ns.devices.Set(&device.Device{
		DevAddr: getDevAddr(5, 6, 7, 8),
		AppEUI:  types.AppEUI(getEUI(5, 6, 7, 8, 1, 2, 3, 4)),
		DevEUI:  types.DevEUI(getEUI(5, 6, 7, 8, 1, 2, 3, 4)),
		NwkSKey: nwkSKey,
		FCntUp:  5,
		Options: device.Options{
			DisableFCntCheck: true,
		},
	})
	defer func() {
		ns.devices.Delete(types.AppEUI(getEUI(5, 6, 7, 8, 1, 2, 3, 4)), types.DevEUI(getEUI(5, 6, 7, 8, 1, 2, 3, 4)))
	}()
	res, err = ns.HandleGetDevices(&pb.DevicesRequest{
		DevAddr: &devAddr2,
		FCnt:    4,
	})
	a.So(err, ShouldBeNil)
	a.So(res.Results, ShouldHaveLength, 1)

	// 32 Bit Frame Counter (A)
	ns.devices.Set(&device.Device{
		DevAddr: getDevAddr(2, 2, 3, 4),
		AppEUI:  types.AppEUI(getEUI(2, 2, 3, 4, 5, 6, 7, 8)),
		DevEUI:  types.DevEUI(getEUI(2, 2, 3, 4, 5, 6, 7, 8)),
		NwkSKey: nwkSKey,
		FCntUp:  5 + (2 << 16),
		Options: device.Options{
			Uses32BitFCnt: true,
		},
	})
	defer func() {
		ns.devices.Delete(types.AppEUI(getEUI(2, 2, 3, 4, 5, 6, 7, 8)), types.DevEUI(getEUI(2, 2, 3, 4, 5, 6, 7, 8)))
	}()
	devAddr3 := getDevAddr(2, 2, 3, 4)
	res, err = ns.HandleGetDevices(&pb.DevicesRequest{
		DevAddr: &devAddr3,
		FCnt:    5,
	})
	a.So(err, ShouldBeNil)
	a.So(res.Results, ShouldHaveLength, 1)

	// 32 Bit Frame Counter (B)
	ns.devices.Set(&device.Device{
		DevAddr: getDevAddr(2, 2, 3, 5),
		AppEUI:  types.AppEUI(getEUI(2, 2, 3, 4, 5, 3, 7, 8)),
		DevEUI:  types.DevEUI(getEUI(2, 2, 3, 4, 5, 3, 7, 8)),
		NwkSKey: nwkSKey,
		FCntUp:  (2 << 16) - 1,
		Options: device.Options{
			Uses32BitFCnt: true,
		},
	})
	defer func() {
		ns.devices.Delete(types.AppEUI(getEUI(2, 2, 3, 4, 5, 3, 7, 8)), types.DevEUI(getEUI(2, 2, 3, 4, 5, 3, 7, 8)))
	}()
	devAddr4 := getDevAddr(2, 2, 3, 5)
	res, err = ns.HandleGetDevices(&pb.DevicesRequest{
		DevAddr: &devAddr4,
		FCnt:    5,
	})
	a.So(err, ShouldBeNil)
	a.So(res.Results, ShouldHaveLength, 1)

}