Esempio n. 1
0
        public Task <bool> HandleAsync(MqttPublishInfo publishInfo)
        {
            try
            {
                var match = Regex.Match(publishInfo.Topic, RpcAckPattern);
                if (match.Success)
                {
                    this.HandleRpcAck(match.Groups["guid"].Value);
                    return(Task.FromResult(true));
                }

                match = Regex.Match(publishInfo.Topic, TwinGetResponsePattern);
                if (match.Success)
                {
                    this.HandleTwinResponse(this.GetIdFromMatch(match), match.Groups["res"].Value, match.Groups["rid"].Value, publishInfo.Payload);
                    return(Task.FromResult(true));
                }

                match = Regex.Match(publishInfo.Topic, TwinSubscriptionForPatchPattern);
                if (match.Success)
                {
                    this.HandleDesiredProperyUpdate(this.GetIdFromMatch(match), match.Groups["version"].Value, publishInfo.Payload);
                    return(Task.FromResult(true));
                }

                match = Regex.Match(publishInfo.Topic, MethodCallPattern);
                if (match.Success)
                {
                    this.HandleDirectMethodCall(this.GetIdFromMatch(match), match.Groups["mname"].Value, match.Groups["rid"].Value, publishInfo.Payload);
                    return(Task.FromResult(true));
                }

                if (ConnectivityTopic.Equals(publishInfo.Topic))
                {
                    this.HandleConnectivityEvent(publishInfo.Payload);
                    return(Task.FromResult(true));
                }
            }
            catch (Exception e)
            {
                Events.ErrorHandlingDownstreamMessage(publishInfo.Topic, e);
            }

            return(Task.FromResult(false));
        }
Esempio n. 2
0
        Option <List <IIdentity> > GetIdentitiesFromUpdateMessage(MqttPublishInfo mqttPublishInfo)
        {
            var identityList = default(List <string>);

            try
            {
                var payloadAsString = Encoding.UTF8.GetString(mqttPublishInfo.Payload);
                identityList = JsonConvert.DeserializeObject <List <string> >(payloadAsString);
            }
            catch (Exception e)
            {
                Events.BadPayloadFormat(e);
                return(Option.None <List <IIdentity> >());
            }

            var result = new List <IIdentity>();

            foreach (var id in identityList)
            {
                if (this.systemComponentIdProvider.IsSystemComponent(id))
                {
                    continue;
                }

                var identityComponents = id.Split(identitySegmentSeparator, StringSplitOptions.RemoveEmptyEntries);

                switch (identityComponents.Length)
                {
                case 1:
                    result.Add(this.identityProvider.Create(identityComponents[0]));
                    break;

                case 2:
                    result.Add(this.identityProvider.Create(identityComponents[0], identityComponents[1]));
                    break;

                default:
                    Events.BadIdentityFormat(id);
                    continue;
                }
            }

            return(Option.Some(result));
        }
Esempio n. 3
0
        async Task <bool> HandleTelemetry(Match match, MqttPublishInfo publishInfo)
        {
            var id1 = match.Groups["id1"];
            var id2 = match.Groups["id2"];
            var bag = match.Groups["bag"];

            var isDirect = string.Equals(match.Groups["dialect"].Value, MqttBrokerAdapterConstants.DirectTopicPrefix);

            var identity = id2.Success
                                ? this.identityProvider.Create(id1.Value, id2.Value)
                                : this.identityProvider.Create(id1.Value);

            var maybeListener = await this.connectionRegistry.GetOrCreateDeviceListenerAsync(identity, isDirect);

            var listener = default(IDeviceListener);

            try
            {
                listener = maybeListener.Expect(() => new Exception($"No device listener found for {identity.Id}"));
            }
            catch (Exception)
            {
                Events.MissingListener(identity.Id);
                return(false);
            }

            var message = default(IMessage);

            try
            {
                message = ConvertToInternalMessage(publishInfo, id1.Value, id2.Success ? Option.Some(id2.Value) : Option.None <string>(), bag.Value);
            }
            catch (Exception e)
            {
                Events.UnexpectedMessageFormat(e, publishInfo.Topic);
                return(false);
            }

            await listener.ProcessDeviceMessageAsync(message);

            Events.TelemetryMessage(identity.Id, publishInfo.Payload.Length);

            return(true);
        }
Esempio n. 4
0
        public async Task <bool> HandleAsync(MqttPublishInfo publishInfo)
        {
            if (string.Equals(publishInfo.Topic, TopicDeviceConnected))
            {
                try
                {
                    await this.HandleDeviceConnectedAsync(publishInfo);

                    return(true);
                }
                catch (Exception e)
                {
                    Events.ErrorProcessingNotification(e);
                    return(false);
                }
            }

            return(false);
        }
        public async Task <bool> HandleAsync(MqttPublishInfo publishInfo)
        {
            if (publishInfo.Topic.Equals(MessageDelivered))
            {
                try
                {
                    var originalTopic = Encoding.UTF8.GetString(publishInfo.Payload);
                    var match         = Regex.Match(originalTopic, FeedbackMessagePattern);
                    if (match.Success)
                    {
                        var id1       = match.Groups["id1"];
                        var id2       = match.Groups["id2"];
                        var lockToken = match.Groups["token"].Value;

                        var identity = this.identityProvider.Create(id1.Value, id2.Value);

                        if (this.pendingMessages.TryRemove(lockToken, out var _))
                        {
                            await this.ConfirmMessageAsync(lockToken, identity);
                        }
                        else
                        {
                            Events.CannotFindMessageToConfirm(identity.Id);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Events.CannotDecodeConfirmation(ex);
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Esempio n. 6
0
        public async Task <bool> HandleAsync(MqttPublishInfo publishInfo)
        {
            var match = Regex.Match(publishInfo.Topic, SubscriptionChangePattern);

            if (!match.Success)
            {
                return(false);
            }

            // After this point we know that this was a subscription change and will return 'true'
            // even in a case of error
            var subscriptionList = default(List <string>);

            try
            {
                var payloadAsString = Encoding.UTF8.GetString(publishInfo.Payload);
                subscriptionList = JsonConvert.DeserializeObject <List <string> >(payloadAsString);

                Events.HandlingSubscriptionChange(payloadAsString);
            }
            catch (Exception e)
            {
                Events.BadPayloadFormat(e);
                return(true);
            }

            if (subscriptionList == null)
            {
                // This case is valid and sent by the broker (as an empty string) when a client disconnects.
                // The meaning of the message is to remove subscriptions, but as the client is disconnecting
                // in a moment, we don't do anything. In fact, the disconnect message is supposed to arrive
                // first, and then this change notification gets ignored as it does not have related client.
                return(true);
            }

            var id1 = match.Groups["id1"];
            var id2 = match.Groups["id2"];

            var identity = id2.Success
                                ? this.identityProvider.Create(id1.Value, id2.Value)
                                : this.identityProvider.Create(id1.Value);

            var listener      = default(IDeviceListener);
            var maybeListener = await this.connectionRegistry.GetDeviceListenerAsync(identity);

            if (!maybeListener.HasValue)
            {
                return(true);
            }
            else
            {
                listener = maybeListener.Expect(() => new Exception($"No device listener found for {identity.Id}"));
            }

            foreach (var subscriptionPattern in this.subscriptionPatterns)
            {
                var subscribes = false;

                foreach (var subscription in subscriptionList)
                {
                    var subscriptionMatch = Regex.Match(subscription, subscriptionPattern.Pattern);
                    if (IsMatchWithIds(subscriptionMatch, id1, id2))
                    {
                        subscribes = true;
                        break;
                    }
                }

                try
                {
                    await AddOrRemoveSubscription(listener, subscribes, subscriptionPattern.Subscrition);
                }
                catch (Exception e)
                {
                    Events.FailedToChangeSubscriptionState(e, subscriptionPattern.Subscrition.ToString(), identity.Id);
                }
            }

            return(true);
        }
Esempio n. 7
0
 async Task HandleDeviceConnectedAsync(MqttPublishInfo mqttPublishInfo)
 {
     var updatedIdentities = this.GetIdentitiesFromUpdateMessage(mqttPublishInfo);
     await updatedIdentities.ForEachAsync(async i => await this.ReconcileConnectionsAsync(new HashSet <IIdentity>(i)));
 }
Esempio n. 8
0
        async Task <bool> HandleUpstreamRequest(Func <IDeviceListener, string, Task> action, Match match, MqttPublishInfo publishInfo)
        {
            var id1 = match.Groups["id1"];
            var id2 = match.Groups["id2"];
            var rid = match.Groups["rid"];

            var identity = id2.Success
                                ? this.identityProvider.Create(id1.Value, id2.Value)
                                : this.identityProvider.Create(id1.Value);

            var maybeListener = await this.connectionRegistry.GetDeviceListenerAsync(identity);

            var listener = default(IDeviceListener);

            try
            {
                listener = maybeListener.Expect(() => new Exception($"No device listener found for {identity.Id}"));
            }
            catch (Exception)
            {
                Events.MissingListener(identity.Id);
                return(false);
            }

            var message = new EdgeMessage.Builder(publishInfo.Payload).Build();

            _ = action(listener, rid.Value);

            return(true);
        }
        public async Task <bool> HandleAsync(MqttPublishInfo publishInfo)
        {
            var match = Regex.Match(publishInfo.Topic, SubscriptionChangePattern);

            if (!match.Success)
            {
                return(false);
            }

            // After this point we know that this was a subscription change and will return 'true'
            // even in a case of error
            var subscriptionList = default(List <string>);

            try
            {
                var payloadAsString = Encoding.UTF8.GetString(publishInfo.Payload);
                subscriptionList = JsonConvert.DeserializeObject <List <string> >(payloadAsString);

                Events.HandlingSubscriptionChange(payloadAsString);
            }
            catch (Exception e)
            {
                Events.BadPayloadFormat(e);
                return(true);
            }

            if (subscriptionList == null)
            {
                // This case is valid and sent by the broker (as an empty string) when a client disconnects.
                // The meaning of the message is to remove subscriptions, but as the client is disconnecting
                // in a moment, we don't do anything. In fact, the disconnect message is supposed to arrive
                // first, and then this change notification gets ignored as it does not have related client.
                return(true);
            }

            // TODO: the following solution is to unblock the case when in a nested scenario a child edgehub
            // subscribes in the name of a device/module. However changes needed to support unsubscribe
            foreach (var subscriptionPattern in this.subscriptionPatterns)
            {
                foreach (var subscription in subscriptionList)
                {
                    var subscriptionMatch = Regex.Match(subscription, subscriptionPattern.Pattern);
                    if (subscriptionMatch.Success)
                    {
                        var id1      = subscriptionMatch.Groups["id1"];
                        var id2      = subscriptionMatch.Groups["id2"];
                        var isDirect = string.Equals(subscriptionMatch.Groups["dialect"].Value, DirectConnectionDialect);

                        var identity = id2.Success
                                            ? this.identityProvider.Create(id1.Value, id2.Value)
                                            : this.identityProvider.Create(id1.Value);

                        var maybeListener = await this.connectionRegistry.GetDeviceListenerAsync(identity, isDirect);

                        if (maybeListener.HasValue)
                        {
                            try
                            {
                                var listener = maybeListener.Expect(() => new Exception($"No device listener found for {identity.Id}"));
                                await AddOrRemoveSubscription(listener, true, subscriptionPattern.Subscrition);
                            }
                            catch (Exception e)
                            {
                                Events.FailedToChangeSubscriptionState(e, subscriptionPattern.Subscrition.ToString(), identity.Id);
                            }
                        }
                        else
                        {
                            Events.CouldNotObtainListener(subscriptionPattern.Subscrition.ToString(), identity.Id);
                        }
                    }
                }
            }

            return(true);
        }