예제 #1
0
        void HandleSubscribe(StanzaIQ Request)
        {
            XElement SubscribeElement = Request.Payload.Elements().First();

            try
            {
                string AccessToken = LWTSD.GetAccessToken(SubscribeElement);
                List <ResourceAccess> LimitedAccess = GetAccessRights(Request.From, AccessToken);

                Subscriber Subscription = new Subscriber();
                Subscription.SubscriptionID    = SubscribeElement.Attribute("subscriptionid").Value;
                Subscription.SubscriberAddress = Request.From;
                Subscription.AccessToken       = AccessToken;

                foreach (XElement WriteElement in SubscribeElement.Elements(LWTSD.Namespace + "trigger"))
                {
                    ResourcePath Path = WriteElement.Attribute("onresource").Value;

                    if (!ResourceAccess.AllowsRead(LimitedAccess, Path))
                    {
                        throw new AccessViolation();
                    }

                    if (!Resources.ContainsKey(Path))
                    {
                        throw new InvalidOperationException("Path does not exist: " + Path);                         // todo: explicit type to make it possible to set correct error code
                    }
                    Resource Res = Resources[Path];
                    if (!Res.SupportsRead)
                    {
                        throw new InvalidOperationException("Resource is not readable: " + Path);                         // todo: explicit type to make it possible to set correct error code
                    }
                    ResourceSubscription Trigger = new ResourceSubscription()
                    {
                        Path = Path
                    };

                    Subscription.Triggers.Add(Trigger);
                }

                if (Subscription.Triggers.Count == 0)
                {
                    throw new InvalidOperationException("No triggers");
                }

                Subscribers[GetSafeSubscriptionID(Request.From, Subscription.SubscriptionID)] = Subscription;

                StanzaIQ Response = new StanzaIQ(StanzaIQ.StanzaIQType.Result);
                Response.ID = Request.ID;
                Response.To = Request.From;
                Uplink.SendStanza(Response);
            }
            catch (System.Exception ex)
            {
                StanzaIQ ErrorResponse = new StanzaIQ(StanzaIQ.StanzaIQType.Error);
                ErrorResponse.ID = Request.ID;
                ErrorResponse.To = Request.From;
                XElement ErroReasonElement = new XElement(LWTSD.Namespace + "errorreason");
                ErroReasonElement.SetAttributeValue("reason", ErrorReason.InvalidData);
                ErroReasonElement.Value = ex.ToString();
                ErrorResponse.Payload.Add(ErroReasonElement);
                Uplink.SendStanza(ErrorResponse);
            }
        }
예제 #2
0
        public void InvalidateData(JID ExcludeJID)
        {
            List <string> SubscriptionsToRemove = new List <string>();

            foreach (string key in Subscribers.Keys)
            {
                Subscriber s = Subscribers[key];
                try
                {
                    if (ExcludeJID != null)
                    {
                        if (s.SubscriberAddress == ExcludeJID)
                        {
                            continue;
                        }
                    }

                    if (s.LastInvalidated > s.LastResubscribed)
                    {
                        continue;
                    }

                    List <ResourceAccess> LimitedAccess = GetAccessRights(s.SubscriberAddress, s.AccessToken);

                    bool Invalidate = false;
                    foreach (ResourceSubscription trigger in s.Triggers)
                    {
                        if (!ResourceAccess.AllowsRead(LimitedAccess, trigger.Path))
                        {
                            throw new AccessViolation();
                        }

                        Resource res = Resources[trigger.Path];
                        if (res.ModifiedAt > s.LastInvalidated)
                        {
                            Invalidate = true;
                            break;
                        }
                    }

                    if (!Invalidate)
                    {
                        continue;
                    }

                    // Invalidate
                    StanzaMessage InvalidateMessage = new StanzaMessage();
                    InvalidateMessage.MessageType = StanzaMessage.StanzaMessageType.Normal;
                    InvalidateMessage.To          = s.SubscriberAddress;
                    s.LastInvalidated             = DateTime.UtcNow;
                    XElement SubscriptionTriggeredElement = new XElement(LWTSD.Namespace + "subscription-triggered");
                    SubscriptionTriggeredElement.SetAttributeValue("subscriptionid", s.SubscriptionID);
                    InvalidateMessage.Payload.Add(SubscriptionTriggeredElement);
                    Uplink.SendStanza(InvalidateMessage);
                }
                catch (AccessViolation Violation)
                {
                    SubscriptionsToRemove.Add(key);
                }
            }
            foreach (string ToRemove in SubscriptionsToRemove)
            {
                Subscriber Temp;
                Subscribers.TryRemove(ToRemove, out Temp);
            }
        }
예제 #3
0
        void HandleReadData(StanzaIQ Request)
        {
            XElement ReadDataElement = Request.Payload.Elements().First();

            try
            {
                List <ResourceAccess> LimitedAccess = GetAccessRights(Request.From, LWTSD.GetAccessToken(ReadDataElement));

                int       maxpoints   = XmlConvert.ToInt32(ReadDataElement.Attribute("maxpoints").Value);
                int       startindex  = XmlConvert.ToInt32(ReadDataElement.Attribute("startindex").Value);
                SortOrder OrderByTime = SortOrder.None;
                if (ReadDataElement.Attribute("orderedbytime") != null)
                {
                    OrderByTime = SortOrderMethods.LoadFromString(ReadDataElement.Attribute("orderedbytime").Value);
                }

                StanzaIQ Response = new StanzaIQ(StanzaIQ.StanzaIQType.Result);
                Response.ID = Request.ID;
                Response.To = Request.From;

                XElement DataElement = new XElement(LWTSD.Namespace + "data");

                List <Resource> MatchingResources = new List <Resource>();

                foreach (XElement ReadElement in ReadDataElement.Elements(LWTSD.Namespace + "read"))
                {
                    if (ReadElement.Attribute("maxpoints") != null)
                    {
                        if (XmlConvert.ToInt32(ReadElement.Attribute("maxpoints").Value) < 1)
                        {
                            throw new InvalidOperationException("Maxpoints < 0 in read");
                        }
                    }
                    if (ReadElement.Attribute("startindex") != null)
                    {
                        int localstartindex = XmlConvert.ToInt32(ReadElement.Attribute("startindex").Value);
                        if (localstartindex < 1)
                        {
                            throw new InvalidOperationException("startindex < 0 in read");
                        }
                        if (localstartindex > 1)
                        {
                            continue; // We only have one point / resource
                        }
                    }

                    ResourcePath Path = ReadElement.Attribute("resource-path").Value;

                    if (!ResourceAccess.AllowsRead(LimitedAccess, Path))
                    {
                        throw new AccessViolation();
                    }

                    if (!Resources.ContainsKey(Path))
                    {
                        // Todo: Explicit exception to set proper error code
                        throw new Exception("Path does not exist: " + Path);
                    }

                    Resource Res = Resources[Path];
                    if (!Res.SupportsRead)
                    {
                        throw new InvalidOperationException("Resource does not support read: " + Path);
                    }

                    MatchingResources.Add(Res);
                }

                lock (Schema)
                {
                    int Index          = 0;
                    int ReturnedPoints = 0;

                    foreach (Resource Res in MatchingResources)
                    {
                        if (Index < startindex)
                        {
                            Index++;
                            continue;
                        }
                        if ((Index - startindex) >= maxpoints)
                        {
                            Index++;
                            break;
                        }

                        Index++;
                        ReturnedPoints++;

                        XElement ResourceElement = new XElement(LWTSD.Namespace + "resource");
                        ResourceElement.SetAttributeValue("path", Res.Path);
                        ResourceElement.SetAttributeValue("returnedpoints", "1");
                        ResourceElement.SetAttributeValue("totalpoints", "1");
                        XElement PointElement = Res.GetPoint();
                        ResourceElement.Add(PointElement);

                        DataElement.Add(ResourceElement);
                    }

                    DataElement.SetAttributeValue("schemaversion", Schema.GetVersion());
                    DataElement.SetAttributeValue("returnedpoints", XmlConvert.ToString(ReturnedPoints));
                    DataElement.SetAttributeValue("totalpoints", XmlConvert.ToString(MatchingResources.Count));
                }

                foreach (XElement ReSubscribeElement in ReadDataElement.Elements(LWTSD.Namespace + "re-subscribe"))
                {
                    string localsid = ReSubscribeElement.Attribute("subscriptionid").Value;
                    string sid      = GetSafeSubscriptionID(Request.From, localsid);

                    if (!Subscribers.ContainsKey(sid))
                    {
                        throw new InvalidOperationException("Subscription ID does not exist: " + localsid);
                    }

                    Subscriber Subscription = Subscribers[sid];
                    Subscription.LastResubscribed = DateTime.UtcNow;
                }

                Response.Payload.Add(DataElement);
                Uplink.SendStanza(Response);
            }
            catch (System.Exception ex)
            {
                StanzaIQ ErrorResponse = new StanzaIQ(StanzaIQ.StanzaIQType.Error);
                ErrorResponse.ID = Request.ID;
                ErrorResponse.To = Request.From;
                XElement ErroReasonElement = new XElement(LWTSD.Namespace + "errorreason");
                ErroReasonElement.SetAttributeValue("reason", ErrorReason.InvalidData);
                ErroReasonElement.Value = ex.ToString();
                ErrorResponse.Payload.Add(ErroReasonElement);
                Uplink.SendStanza(ErrorResponse);
            }
        }