Example #1
0
// Decode decodes the payload using the Decoder function into a map
func (f *UplinkFunctions) Decode(payload []byte, port uint8) (map[string]interface{}, error) {
	if f.Decoder == "" {
		return nil, errors.NewErrInternal("Decoder function not set")
	}

	env := map[string]interface{}{
		"payload": payload,
		"port":    port,
	}
	code := fmt.Sprintf(`
		%s;
		Decoder(payload.slice(0), port);
	`, f.Decoder)

	value, err := functions.RunCode("decoder", code, env, timeOut, f.Logger)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Decoder", "does not return an object")
	}

	v, _ := value.Export()
	m, ok := v.(map[string]interface{})
	if !ok {
		return nil, errors.NewErrInvalidArgument("Decoder", "does not return an object")
	}
	return m, nil
}
Example #2
0
// Convert converts the values in the specified map to a another map using the
// Converter function. If the Converter function is not set, this function
// returns the data as-is
func (f *UplinkFunctions) Convert(fields map[string]interface{}, port uint8) (map[string]interface{}, error) {
	if f.Converter == "" {
		return fields, nil
	}

	env := map[string]interface{}{
		"fields": fields,
		"port":   port,
	}

	code := fmt.Sprintf(`
		%s;
		Converter(fields, port)
	`, f.Converter)

	value, err := functions.RunCode("converter", code, env, timeOut, f.Logger)
	if err != nil {
		return nil, err
	}

	if !value.IsObject() {
		return nil, errors.NewErrInvalidArgument("Converter", "does not return an object")
	}

	v, _ := value.Export()
	m, ok := v.(map[string]interface{})
	if !ok {
		return nil, errors.NewErrInvalidArgument("Converter", "does not return an object")
	}

	return m, nil
}
Example #3
0
func (s *networkServerRPC) ValidateContext(ctx context.Context) error {
	md, ok := metadata.FromContext(ctx)
	if !ok {
		return errors.NewErrInternal("Could not get metadata from context")
	}
	var id, token string
	if ids, ok := md["id"]; ok && len(ids) == 1 {
		id = ids[0]
	}
	if id == "" {
		return errors.NewErrInvalidArgument("Metadata", "id missing")
	}
	if tokens, ok := md["token"]; ok && len(tokens) == 1 {
		token = tokens[0]
	}
	if token == "" {
		return errors.NewErrInvalidArgument("Metadata", "token missing")
	}
	var claims *jwt.StandardClaims
	claims, err := security.ValidateJWT(token, []byte(s.networkServer.(*networkServer).Identity.PublicKey))
	if err != nil {
		return err
	}
	if claims.Subject != id {
		return errors.NewErrInvalidArgument("Metadata", "token was issued for a different component id")
	}
	return nil
}
Example #4
0
// ValidateNetworkContext validates the context of a network request (router-broker, broker-handler, etc)
func (c *Component) ValidateNetworkContext(ctx context.Context) (component *pb_discovery.Announcement, err error) {
	defer func() {
		if err != nil {
			time.Sleep(time.Second)
		}
	}()

	md, ok := metadata.FromContext(ctx)
	if !ok {
		err = errors.NewErrInternal("Could not get metadata from context")
		return
	}
	var id, serviceName, token string
	if ids, ok := md["id"]; ok && len(ids) == 1 {
		id = ids[0]
	}
	if id == "" {
		err = errors.NewErrInvalidArgument("Metadata", "id missing")
		return
	}
	if serviceNames, ok := md["service-name"]; ok && len(serviceNames) == 1 {
		serviceName = serviceNames[0]
	}
	if serviceName == "" {
		err = errors.NewErrInvalidArgument("Metadata", "service-name missing")
		return
	}
	if tokens, ok := md["token"]; ok && len(tokens) == 1 {
		token = tokens[0]
	}

	var announcement *pb_discovery.Announcement
	announcement, err = c.Discover(serviceName, id)
	if err != nil {
		return
	}

	if announcement.PublicKey == "" {
		return announcement, nil
	}

	if token == "" {
		err = errors.NewErrInvalidArgument("Metadata", "token missing")
		return
	}

	var claims *jwt.StandardClaims
	claims, err = security.ValidateJWT(token, []byte(announcement.PublicKey))
	if err != nil {
		return
	}
	if claims.Issuer != id {
		err = errors.NewErrInvalidArgument("Metadata", "token was issued by different component id")
		return
	}

	return announcement, nil
}
Example #5
0
// Validate implements the api.Validator interface
func (m *RxMetadata) Validate() error {
	if m.Protocol == nil {
		return errors.NewErrInvalidArgument("Protocol", "can not be empty")
	}
	if err := api.Validate(m.Protocol); err != nil {
		return errors.NewErrInvalidArgument("Protocol", err.Error())
	}
	return nil
}
Example #6
0
// Validate implements the api.Validator interface
func (m *DeviceIdentifier) Validate() error {
	if m.AppEui == nil || m.AppEui.IsEmpty() {
		return errors.NewErrInvalidArgument("AppEui", "can not be empty")
	}
	if m.DevEui == nil || m.DevEui.IsEmpty() {
		return errors.NewErrInvalidArgument("DevEui", "can not be empty")
	}
	return nil
}
Example #7
0
// NotEmptyAndValidID checks if the ID is not empty AND has a valid format
func NotEmptyAndValidID(id string, argument string) error {
	if id == "" {
		return errors.NewErrInvalidArgument(argument, "can not be empty")
	}
	if !ValidID(id) {
		return errors.NewErrInvalidArgument(argument, "has wrong format "+id)
	}
	return nil
}
Example #8
0
// Validate implements the api.Validator interface
func (m *JoinRequestPayload) Validate() error {
	if m.AppEui.IsEmpty() {
		return errors.NewErrInvalidArgument("AppEui", "can not be empty")
	}
	if m.DevEui.IsEmpty() {
		return errors.NewErrInvalidArgument("DevEui", "can not be empty")
	}

	return nil
}
Example #9
0
func (n *networkServer) UsePrefix(prefix types.DevAddrPrefix, usage []string) error {
	if prefix.Length < 7 {
		return errors.NewErrInvalidArgument("Prefix", "invalid length")
	}
	if prefix.DevAddr[0]>>1 != n.netID[2] {
		return errors.NewErrInvalidArgument("Prefix", "invalid netID")
	}
	n.prefixes[prefix] = usage
	return nil
}
Example #10
0
func (n *networkServer) HandleDownlink(message *pb_broker.DownlinkMessage) (*pb_broker.DownlinkMessage, error) {
	// Get Device
	dev, err := n.devices.Get(*message.AppEui, *message.DevEui)
	if err != nil {
		return nil, err
	}

	n.status.downlink.Mark(1)

	dev.StartUpdate()

	if dev.AppID != message.AppId || dev.DevID != message.DevId {
		return nil, errors.NewErrInvalidArgument("Downlink", "AppID and DevID do not match AppEUI and DevEUI")
	}

	// Unmarshal LoRaWAN Payload
	var phyPayload lorawan.PHYPayload
	err = phyPayload.UnmarshalBinary(message.Payload)
	if err != nil {
		return nil, err
	}
	macPayload, ok := phyPayload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return nil, errors.NewErrInvalidArgument("Downlink", "does not contain a MAC payload")
	}

	// Set DevAddr
	macPayload.FHDR.DevAddr = lorawan.DevAddr(dev.DevAddr)

	// FIRST set and THEN increment FCntDown
	// TODO: For confirmed downlink, FCntDown should be incremented AFTER ACK
	macPayload.FHDR.FCnt = dev.FCntDown
	dev.FCntDown++
	err = n.devices.Set(dev)
	if err != nil {
		return nil, err
	}

	// Sign MIC
	phyPayload.SetMIC(lorawan.AES128Key(dev.NwkSKey))

	// Update message
	bytes, err := phyPayload.MarshalBinary()
	if err != nil {
		return nil, err
	}
	message.Payload = bytes

	return message, nil
}
Example #11
0
// Validate implements the api.Validator interface
func (m *Message) Validate() error {
	if m.Major != Major_LORAWAN_R1 {
		return errors.NewErrInvalidArgument("Major", "invalid value "+Major_LORAWAN_R1.String())
	}
	switch m.MType {
	case MType_JOIN_REQUEST:
		if m.GetJoinRequestPayload() == nil {
			return errors.NewErrInvalidArgument("JoinRequestPayload", "can not be empty")
		}
		if err := m.GetJoinRequestPayload().Validate(); err != nil {
			return errors.NewErrInvalidArgument("JoinRequestPayload", err.Error())
		}
	case MType_JOIN_ACCEPT:
		if m.GetJoinAcceptPayload() == nil {
			return errors.NewErrInvalidArgument("JoinAcceptPayload", "can not be empty")
		}
		if err := m.GetJoinAcceptPayload().Validate(); err != nil {
			return errors.NewErrInvalidArgument("JoinAcceptPayload", err.Error())
		}
	case MType_UNCONFIRMED_UP, MType_UNCONFIRMED_DOWN, MType_CONFIRMED_UP, MType_CONFIRMED_DOWN:
		if m.GetMacPayload() == nil {
			return errors.NewErrInvalidArgument("MacPayload", "can not be empty")
		}
		if err := m.GetMacPayload().Validate(); err != nil {
			return errors.NewErrInvalidArgument("MacPayload", err.Error())
		}
	default:
		return errors.NewErrInvalidArgument("MType", "unknown type "+m.MType.String())
	}

	return nil
}
Example #12
0
// Validate implements the api.Validator interface
func (m *ActivationMetadata) Validate() error {
	if m.AppEui == nil || m.AppEui.IsEmpty() {
		return errors.NewErrInvalidArgument("AppEui", "can not be empty")
	}
	if m.DevEui == nil || m.DevEui.IsEmpty() {
		return errors.NewErrInvalidArgument("DevEui", "can not be empty")
	}
	if m.DevAddr != nil && m.DevAddr.IsEmpty() {
		return errors.NewErrInvalidArgument("DevAddr", "can not be empty")
	}
	if m.NwkSKey != nil && m.NwkSKey.IsEmpty() {
		return errors.NewErrInvalidArgument("NwkSKey", "can not be empty")
	}
	return nil
}
Example #13
0
// Validate implements the api.Validator interface
func (m *Device) Validate() error {
	if m.AppEui == nil || m.AppEui.IsEmpty() {
		return errors.NewErrInvalidArgument("AppEui", "can not be empty")
	}
	if m.DevEui == nil || m.DevEui.IsEmpty() {
		return errors.NewErrInvalidArgument("DevEui", "can not be empty")
	}
	if err := api.NotEmptyAndValidID(m.AppId, "AppId"); err != nil {
		return err
	}
	if err := api.NotEmptyAndValidID(m.DevId, "DevId"); err != nil {
		return err
	}
	return nil
}
Example #14
0
// Validate implements the api.Validator interface
func (m *DownlinkOption) Validate() error {
	if m.Identifier == "" {
		return errors.NewErrInvalidArgument("Identifier", "can not be empty")
	}
	if m.GatewayId == "" {
		return errors.NewErrInvalidArgument("GatewayId", "can not be empty")
	}
	if err := api.NotNilAndValid(m.ProtocolConfig, "ProtocolConfig"); err != nil {
		return err
	}
	if err := api.NotNilAndValid(m.GatewayConfig, "GatewayConfig"); err != nil {
		return err
	}
	return nil
}
Example #15
0
func (n *networkServer) HandleActivate(activation *pb_handler.DeviceActivationResponse) (*pb_handler.DeviceActivationResponse, error) {
	meta := activation.GetActivationMetadata()
	if meta == nil {
		return nil, errors.NewErrInvalidArgument("Activation", "missing ActivationMetadata")
	}
	lorawan := meta.GetLorawan()
	if lorawan == nil {
		return nil, errors.NewErrInvalidArgument("Activation", "missing LoRaWAN ActivationMetadata")
	}
	n.status.activations.Mark(1)
	err := n.devices.Activate(*lorawan.AppEui, *lorawan.DevEui, *lorawan.DevAddr, *lorawan.NwkSKey)
	if err != nil {
		return nil, err
	}
	return activation, nil
}
Example #16
0
// Validate implements the api.Validator interface
func (m *TxConfiguration) Validate() error {
	switch m.Modulation {
	case Modulation_LORA:
		if m.DataRate == "" {
			return errors.NewErrInvalidArgument("DataRate", "can not be empty")
		}
	case Modulation_FSK:
		if m.BitRate == 0 {
			return errors.NewErrInvalidArgument("BitRate", "can not be empty")
		}
	}
	if m.CodingRate == "" {
		return errors.NewErrInvalidArgument("CodingRate", "can not be empty")
	}
	return nil
}
Example #17
0
func (h *handlerManager) validateTTNAuthAppContext(ctx context.Context, appID string) (context.Context, *claims.Claims, error) {
	md, err := api.MetadataFromContext(ctx)
	if err != nil {
		return ctx, nil, err
	}
	// If token is empty, try to get the access key and convert it into a token
	token, err := api.TokenFromMetadata(md)
	if err != nil || token == "" {
		key, err := api.KeyFromMetadata(md)
		if err != nil {
			return ctx, nil, errors.NewErrInvalidArgument("Metadata", "neither token nor key present")
		}
		token, err := h.handler.Component.ExchangeAppKeyForToken(appID, key)
		if err != nil {
			return ctx, nil, err
		}
		md = metadata.Join(md, metadata.Pairs("token", token))
		ctx = metadata.NewContext(ctx, md)
	}
	claims, err := h.handler.Component.ValidateTTNAuthContext(ctx)
	if err != nil {
		return ctx, nil, err
	}
	if h.clientRate.Limit(claims.Subject) {
		return ctx, claims, grpc.Errorf(codes.ResourceExhausted, "Rate limit for client reached")
	}
	if h.applicationRate.Limit(appID) {
		return ctx, claims, grpc.Errorf(codes.ResourceExhausted, "Rate limit for application reached")
	}
	return ctx, claims, nil
}
Example #18
0
// ConvertFieldsUp converts the payload to fields using payload functions
func (h *handler) ConvertFieldsUp(ctx log.Interface, ttnUp *pb_broker.DeduplicatedUplinkMessage, appUp *types.UplinkMessage) error {
	// Find Application
	app, err := h.applications.Get(ttnUp.AppId)
	if err != nil {
		return nil // Do not process if application not found
	}

	functions := &UplinkFunctions{
		Decoder:   app.Decoder,
		Converter: app.Converter,
		Validator: app.Validator,
		Logger:    functions.Ignore,
	}

	fields, valid, err := functions.Process(appUp.PayloadRaw, appUp.FPort)
	if err != nil {
		return nil // Do not set fields if processing failed
	}

	if !valid {
		return errors.NewErrInvalidArgument("Payload", "payload validator function returned false")
	}

	appUp.PayloadFields = fields

	return nil
}
Example #19
0
// ConvertFieldsDown converts the fields into a payload
func (h *handler) ConvertFieldsDown(ctx log.Interface, appDown *types.DownlinkMessage, ttnDown *pb_broker.DownlinkMessage) error {
	if appDown.PayloadFields == nil || len(appDown.PayloadFields) == 0 {
		return nil
	}

	if appDown.PayloadRaw != nil {
		return errors.NewErrInvalidArgument("Downlink", "Both Fields and Payload provided")
	}

	app, err := h.applications.Get(appDown.AppID)
	if err != nil {
		return nil
	}

	functions := &DownlinkFunctions{
		Encoder: app.Encoder,
		Logger:  functions.Ignore,
	}

	message, _, err := functions.Process(appDown.PayloadFields, appDown.FPort)
	if err != nil {
		return err
	}

	appDown.PayloadRaw = message

	return nil
}
Example #20
0
// Validate validates the values in the specified map using the Validator
// function. If the Validator function is not set, this function returns true
func (f *UplinkFunctions) Validate(fields map[string]interface{}, port uint8) (bool, error) {
	if f.Validator == "" {
		return true, nil
	}

	env := map[string]interface{}{
		"fields": fields,
		"port":   port,
	}
	code := fmt.Sprintf(`
		%s;
		Validator(fields, port)
	`, f.Validator)

	value, err := functions.RunCode("valdator", code, env, timeOut, f.Logger)
	if err != nil {
		return false, err
	}

	if !value.IsBoolean() {
		return false, errors.NewErrInvalidArgument("Validator", "does not return a boolean")
	}

	return value.ToBoolean()
}
Example #21
0
// Validate implements the api.Validator interface
func (m *JoinAcceptPayload) Validate() error {
	if len(m.Encrypted) != 0 {
		return nil
	}

	if m.CfList != nil && len(m.CfList.Freq) != 5 {
		return errors.NewErrInvalidArgument("CfList.Freq", "length must be 5")
	}

	if m.DevAddr.IsEmpty() {
		return errors.NewErrInvalidArgument("DevAddr", "can not be empty")
	}
	if m.NetId.IsEmpty() {
		return errors.NewErrInvalidArgument("NetId", "can not be empty")
	}

	return nil
}
Example #22
0
// Validate implements the api.Validator interface
func (m *ApplicationHandlerRegistration) Validate() error {
	if err := api.NotEmptyAndValidID(m.AppId, "AppId"); err != nil {
		return err
	}
	if m.HandlerId == "" {
		return errors.NewErrInvalidArgument("HandlerId", "can not be empty")
	}
	return nil
}
Example #23
0
// Validate implements the api.Validator interface
func (m *DeduplicatedDeviceActivationRequest) Validate() error {
	if err := api.NotNilAndValid(m.ProtocolMetadata, "ProtocolMetadata"); err != nil {
		return err
	}
	if m.Message != nil {
		if err := m.Message.Validate(); err != nil {
			return errors.NewErrInvalidArgument("Message", err.Error())
		}
	}
	return nil
}
Example #24
0
// Validate implements the api.Validator interface
func (m *Announcement) Validate() error {
	if err := api.NotEmptyAndValidID(m.Id, "Id"); err != nil {
		return err
	}
	switch m.ServiceName {
	case "router", "broker", "handler":
	default:
		return errors.NewErrInvalidArgument("ServiceName", "expected one of router, broker, handler but was "+m.ServiceName)
	}
	return nil
}
Example #25
0
// Announce the component to TTN discovery
func (c *Component) Announce() error {
	if c.Identity.Id == "" {
		return errors.NewErrInvalidArgument("Component ID", "can not be empty")
	}
	err := c.Discovery.Announce(c.AccessToken)
	if err != nil {
		return errors.Wrapf(errors.FromGRPCError(err), "Failed to announce this component to TTN discovery: %s", err.Error())
	}
	c.Ctx.Info("ttn: Announced to TTN discovery")

	return nil
}
Example #26
0
// Validate implements the api.Validator interface
func (m *DeduplicatedUplinkMessage) Validate() error {
	if err := api.NotEmptyAndValidID(m.AppId, "AppId"); err != nil {
		return err
	}
	if err := api.NotEmptyAndValidID(m.DevId, "DevId"); err != nil {
		return err
	}
	if err := api.NotNilAndValid(m.ProtocolMetadata, "ProtocolMetadata"); err != nil {
		return err
	}
	if m.ResponseTemplate != nil {
		if err := m.ResponseTemplate.Validate(); err != nil {
			return errors.NewErrInvalidArgument("ResponseTemplate", err.Error())
		}
	}
	if m.Message != nil {
		if err := m.Message.Validate(); err != nil {
			return errors.NewErrInvalidArgument("Message", err.Error())
		}
	}
	return nil
}
Example #27
0
// Validate implements the api.Validator interface
func (m *UplinkMessage) Validate() error {
	if err := api.NotNilAndValid(m.GatewayMetadata, "GatewayMetadata"); err != nil {
		return err
	}
	if err := api.NotNilAndValid(m.ProtocolMetadata, "ProtocolMetadata"); err != nil {
		return err
	}
	if m.Message != nil {
		if err := m.Message.Validate(); err != nil {
			return errors.NewErrInvalidArgument("Message", err.Error())
		}
	}
	return nil
}
Example #28
0
// Validate implements the api.Validator interface
func (m *DownlinkMessage) Validate() error {
	if err := api.NotNilAndValid(m.ProtocolConfiguration, "ProtocolConfiguration"); err != nil {
		return err
	}
	if err := api.NotNilAndValid(m.GatewayConfiguration, "GatewayConfiguration"); err != nil {
		return err
	}
	if m.Message != nil {
		if err := m.Message.Validate(); err != nil {
			return errors.NewErrInvalidArgument("Message", err.Error())
		}
	}
	return nil
}
Example #29
0
// Validate implements the api.Validator interface
func (m *DeviceActivationResponse) Validate() error {
	if err := api.NotNilAndValid(m.DownlinkOption, "DownlinkOption"); err != nil {
		return err
	}
	if err := api.NotNilAndValid(m.ActivationMetadata, "ActivationMetadata"); err != nil {
		return err
	}
	if m.Message != nil {
		if err := m.Message.Validate(); err != nil {
			return errors.NewErrInvalidArgument("Message", err.Error())
		}
	}
	return nil
}
Example #30
0
// Validate implements the api.Validator interface
func (m *DownlinkMessage) Validate() error {
	if err := api.NotEmptyAndValidID(m.DevId, "DevId"); err != nil {
		return err
	}
	if err := api.NotEmptyAndValidID(m.AppId, "AppId"); err != nil {
		return err
	}

	if err := api.NotNilAndValid(m.DownlinkOption, "DownlinkOption"); err != nil {
		return err
	}
	if m.Message != nil {
		if err := m.Message.Validate(); err != nil {
			return errors.NewErrInvalidArgument("Message", err.Error())
		}
	}
	return nil
}