Пример #1
0
 //
 // Summary:
 //     Removes the first occurrence of a specific object from the eventsink list.
 //
 // Parameters:
 //   subscription:
 //     The eventsink object to remove from the eventsink list. The value
 //     can be null.
 //
 public void Remove(DpwsWseEventSink eventSink)
 {
     lock (m_threadLock)
     {
         m_sinkList.Remove(eventSink);
     }
 }
        /// <summary>
        /// Used by the subscription manager to send a subscription end message to a listening client.
        /// </summary>
        /// <param name="eventSink">An event sink object containing the client endpoint information.</param>
        /// <param name="subEndType">A string that specifies the reason fot the subscription end.</param>
        /// <param name="subMangerID">A id used by the client to identify this subcription.</param>
        /// <remarks>If an error occures when sending an event message this method is called to tell
        /// the client this subscription has been expired.
        /// </remarks>
        private void SendSubscriptionEnd(DpwsWseEventSink eventSink, string subEndType, string subMangerID)
        {
            // if we weren't given an EndTo, don't send
            if (eventSink.EndTo == null)
            {
                return;
            }

            SendEvent(SubscriptionEndResponse(eventSink, subEndType, subMangerID), eventSink.EndTo.Address);
        }
        /// <summary>
        /// Use this method to raise an event.
        /// </summary>
        /// <param name="hostedService">The hosted service that contains the event source.</param>
        /// <param name="eventSource">The event source that define the event.</param>
        /// <param name="eventMessage">The event message buffer.</param>
        /// <remarks>
        /// A device developer is responsible for building the event message buffer sent
        /// to clients that have an active event subscription with an event source. The subscription manager
        /// uses the hosted service parameter to access various properties of the service. The event source
        /// parameter is used to access the event sinks collection of the event source. Note: This method
        /// requires special provisions in order to properly build event message headers for each event sink.
        /// In order to send an event to a listening client the soap.header.To property must be changed for
        /// each listening client. In the future custom attribute support will solve this problem. For now
        /// however a search and replace mechanism is used to modifiy the header.To property. When a device
        /// developer builds the event message buffer they must use the search string WSDNOTIFYTOADDRESS for
        /// the To header property.
        /// </remarks>
        public void FireEvent(DpwsHostedService hostedService, DpwsWseEventSource eventSource, WsMessage msgEvt)
        {
            // Find the specified event source
            if (eventSource == null)
            {
                throw new ArgumentNullException();
            }

            DpwsWseEventSinks eventSinks = eventSource.EventSinks;

            // if there are event sources display message
            int count = eventSinks.Count;

            if (count > 0)
            {
                System.Ext.Console.Write("");
                System.Ext.Console.Write("Firing " + eventSource.Name);
                System.Ext.Console.Write("");
            }

            // Loop through event sinks and send the event message
            for (int i = count - 1; i >= 0; i--)
            {
                DpwsWseEventSink eventSink = eventSinks[i];

                // Try to send event. If attempt fails delete the subscription/eventSink
                try
                {
                    msgEvt.Header = new WsWsaHeader(msgEvt.Header.Action, msgEvt.Header.RelatesTo, eventSink.NotifyTo.Address.AbsoluteUri,
                                                    null, null, eventSink.NotifyTo.RefParameters);

                    SendEvent(msgEvt, eventSink.NotifyTo.Address);
                }
                catch (Exception e)
                {
                    System.Ext.Console.Write("");
                    System.Ext.Console.Write("FireEvent failed. Deleting EventSink! NotifyToAddress = " + eventSink.NotifyTo.Address + " Exception: " + e.Message);
                    System.Ext.Console.Write("");

                    if (!(e is WebException))
                    {
                        try
                        {
                            // Send oneway subscription end message
                            SendSubscriptionEnd(eventSink, "DeliveryFailure", hostedService.ServiceID);
                        }
                        catch { }
                    }

                    // Remove event sink from event source list
                    eventSinks.RemoveAt(i);
                }
            }
        }
        /// <summary>
        /// Used by the subscription manager to send a subscription end message to a listening client.
        /// </summary>
        /// <param name="eventSink">An event sink object containing the client endpoint information.</param>
        /// <param name="subEndType">A string that specifies the reason fot the subscription end.</param>
        /// <param name="subMangerID">A id used by the client to identify this subcription.</param>
        /// <remarks>If an error occures when sending an event message this method is called to tell
        /// the client this subscription has been expired.
        /// </remarks>
        private void SendSubscriptionEnd(DpwsWseEventSink eventSink, string subEndType, string subMangerID)
        {
            // if we weren't given an EndTo, don't send
            if (eventSink.EndTo == null)
            {
                return;
            }

            if (m_persistEventConnections)
            {
                eventSink.RequestChannel.Request(SubscriptionEndResponse(eventSink, subEndType, subMangerID));
            }
            else
            {
                eventSink.RequestChannel.Open();
                eventSink.RequestChannel.Request(SubscriptionEndResponse(eventSink, subEndType, subMangerID));
                eventSink.RequestChannel.Close();
            }
        }
Пример #5
0
        //
        // Summary:
        //     Adds an object to the end of the eventsink list.
        //
        // Parameters:
        //   value:
        //     The System.Object to be added to the end of the eventlist.
        //     The value can be null.
        //
        // Returns:
        //     The eventsink index at which the value has been added.
        //
        public int Add(DpwsWseEventSink value)
        {
            lock (m_threadLock)
            {
                // Ignore duplicate event sinks. Delete the current sink and add the new event sink.
                int    count    = m_sinkList.Count;
                String valueUri = value.NotifyTo.Address.AbsoluteUri.ToLower();
                for (int i = 0; i < count; i++)
                {
                    if (((DpwsWseEventSink)m_sinkList[i]).NotifyTo.Address.AbsoluteUri.ToLower() == valueUri)
                    {
                        m_sinkList.RemoveAt(i);
                        break;
                    }
                }

                return(m_sinkList.Add(value));
            }
        }
Пример #6
0
        /// <summary>
        /// This method build a subscription end message.
        /// </summary>
        /// <param name="eventSink">An event sink containing client endpoint information.</param>
        /// <param name="shutdownMessage">A string containing reason why the subscription is ending.</param>
        /// <param name="subMangerID">An id sent by the client that they use to reference a subscription.</param>
        /// <returns></returns>
        private byte[] SubscriptionEndResponse(DpwsWseEventSink eventSink, string shutdownMessage, string subMangerID)
        {
            MemoryStream soapStream = new MemoryStream();
            XmlWriter    xmlWriter  = XmlWriter.Create(soapStream);

            WsWsaHeader responseHeader = new WsWsaHeader(
                WsWellKnownUri.WseNamespaceUri + "/SubscriptionEnd",    // Action
                null,                                                   // RelatesTo
                eventSink.EndTo.Address.AbsoluteUri,                    // To
                null, null, eventSink.EndTo.RefProperties);             // ReplyTo, From, Any

            WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter,
                                                      WsSoapMessageWriter.Prefixes.Wse, // Prefix
                                                      null,                             // Additional Prefix
                                                      responseHeader,                   // Header
                                                      null);                            // AppSequence

            // write body
            xmlWriter.WriteStartElement("wse", "SubscriptionEnd", null);
            xmlWriter.WriteStartElement("wse", "SubscriptionManager", null);
            xmlWriter.WriteStartElement("wsa", "Address", null);
            xmlWriter.WriteString("http://" + Device.IPV4Address + ":" + Device.Port + "/" + subMangerID);
            xmlWriter.WriteEndElement(); // End Address
            xmlWriter.WriteStartElement("wsa", "ReferenceParameters", null);
            xmlWriter.WriteStartElement("wse", "Identifier", null);
            xmlWriter.WriteString(eventSink.ID);
            xmlWriter.WriteEndElement(); // End Identifier
            xmlWriter.WriteEndElement(); // End ReferenceParameters
            xmlWriter.WriteEndElement(); // End SubscriptionManager
            xmlWriter.WriteStartElement("wse", "Code", null);
            xmlWriter.WriteString("wse:" + shutdownMessage);
            xmlWriter.WriteEndElement(); // End Code
            xmlWriter.WriteEndElement(); // End SubscriptionEnd

            WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter);

            // Flush and close writer. Return stream buffer
            xmlWriter.Flush();
            xmlWriter.Close();
            return(soapStream.ToArray());
        }
        /// <summary>
        /// This method build a subscription end message.
        /// </summary>
        /// <param name="eventSink">An event sink containing client endpoint information.</param>
        /// <param name="shutdownMessage">A string containing reason why the subscription is ending.</param>
        /// <param name="subMangerID">An id sent by the client that they use to reference a subscription.</param>
        /// <returns></returns>
        private WsMessage SubscriptionEndResponse(DpwsWseEventSink eventSink, string shutdownMessage, string subMangerID)
        {
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                WsWsaHeader responseHeader = new WsWsaHeader(
                    WsWellKnownUri.WseNamespaceUri + "/SubscriptionEnd",    // Action
                    null,                                                   // RelatesTo
                    eventSink.EndTo.Address.AbsoluteUri,                    // To
                    null, null, eventSink.EndTo.RefProperties);             // ReplyTo, From, Any

                WsMessage msg = new WsMessage(responseHeader, null, WsPrefix.Wse, null, null);

                WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version);
                smw.WriteSoapMessageStart(xmlWriter, msg);

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscriptionEnd", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscriptionManager", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                xmlWriter.WriteString("http://" + Device.IPV4Address + ":" + Device.Port + "/" + subMangerID);
                xmlWriter.WriteEndElement(); // End Address
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "ReferenceParameters", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Identifier", null);
                xmlWriter.WriteString(eventSink.ID);
                xmlWriter.WriteEndElement(); // End Identifier
                xmlWriter.WriteEndElement(); // End ReferenceParameters
                xmlWriter.WriteEndElement(); // End SubscriptionManager
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Code", null);
                xmlWriter.WriteString(WsNamespacePrefix.Wse + ":" + shutdownMessage);
                xmlWriter.WriteEndElement(); // End Code
                xmlWriter.WriteEndElement(); // End SubscriptionEnd

                smw.WriteSoapMessageEnd(xmlWriter);

                msg.Body = xmlWriter.ToArray();

                // Return stream buffer
                return(msg);
            }
        }
        /// <summary>
        /// Method used to expire events and send EndTo notification to an event sink
        /// </summary>
        public void EventService(object arg)
        {
            DateTime curDateTime = DateTime.Now;

            try
            {
                // Loop through hosted services
                int servicesCount = Device.HostedServices.Count;
                for (int i = 0; i < servicesCount; i++)
                {
                    DpwsHostedService hostedService = (DpwsHostedService)Device.HostedServices[i];

                    // Loop through event sources
                    int eventSourcesCount = hostedService.EventSources.Count;
                    for (int j = 0; j < eventSourcesCount; j++)
                    {
                        DpwsWseEventSource eventSource = hostedService.EventSources[j];

                        // Loop through event sinks. Check expiration time. If an event has
                        // expired send subscription end message and delete event sink.
                        int eventSinkCount = eventSource.EventSinks.Count;
                        for (int k = eventSinkCount - 1; k >= 0; k--)
                        {
                            DpwsWseEventSink eventSink = eventSource.EventSinks[k];

                            // If time has expired delete event sink
                            if (eventSink.StartTime + eventSink.Expires > curDateTime.Ticks)
                            {
                                eventSource.EventSinks.RemoveAt(k);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                System.Ext.Console.Write("Event Queue Manager threw and exception. " + e.Message);
            }
        }
Пример #9
0
        /// <summary>
        /// Used by the subscription manager to send a subscription end message to a listening client.
        /// </summary>
        /// <param name="eventSink">An event sink object containing the client endpoint information.</param>
        /// <param name="subEndType">A string that specifies the reason fot the subscription end.</param>
        /// <param name="subMangerID">A id used by the client to identify this subcription.</param>
        /// <remarks>If an error occures when sending an event message this method is called to tell
        /// the client this subscription has been expired.
        /// </remarks>
        private void SendSubscriptionEnd(DpwsWseEventSink eventSink, string subEndType, string subMangerID)
        {
            // if we weren't given an EndTo, don't send
            if (eventSink.EndTo == null)
            {
                return;
            }

            // Parse the http transport address
            if (eventSink.EndTo.Address.Scheme == "http")
            {
                WsHttpClient httpClient = new WsHttpClient();
                httpClient.SendRequest(SubscriptionEndResponse(eventSink, subEndType, subMangerID), eventSink.EndTo.Address.AbsoluteUri, true, false);
            }
            else
            {
                System.Ext.Console.Write("");
                System.Ext.Console.Write("Unsupported transport address Subscription EndTo.Address: " + eventSink.EndTo.Address);
                System.Ext.Console.Write("");
                return;
            }
        }
Пример #10
0
        /// <summary>
        /// Used by the subscription manager to send a subscription end message to a listening client.
        /// </summary>
        /// <param name="eventSink">An event sink object containing the client endpoint information.</param>
        /// <param name="subEndType">A string that specifies the reason fot the subscription end.</param>
        /// <param name="subMangerID">A id used by the client to identify this subcription.</param>
        /// <remarks>If an error occures when sending an event message this method is called to tell
        /// the client this subscription has been expired.
        /// </remarks>
        private void SendSubscriptionEnd(DpwsWseEventSink eventSink, string subEndType, string subMangerID)
        {
            // if we weren't given an EndTo, don't send
            if (eventSink.EndTo == null)
            {
                return;
            }

            SendEvent(SubscriptionEndResponse(eventSink, subEndType, subMangerID), eventSink.EndTo.Address);
        }
Пример #11
0
        /// <summary>
        /// Use this method to raise an event.
        /// </summary>
        /// <param name="hostedService">The hosted service that contains the event source.</param>
        /// <param name="eventSource">The event source that define the event.</param>
        /// <param name="eventMessage">The event message buffer.</param>
        /// <remarks>
        /// A device developer is responsible for building the event message buffer sent
        /// to clients that have an active event subscription with an event source. The subscription manager
        /// uses the hosted service parameter to access various properties of the service. The event source
        /// parameter is used to access the event sinks collection of the event source. Note: This method
        /// requires special provisions in order to properly build event message headers for each event sink.
        /// In order to send an event to a listening client the soap.header.To property must be changed for
        /// each listening client. In the future custom attribute support will solve this problem. For now
        /// however a search and replace mechanism is used to modifiy the header.To property. When a device
        /// developer builds the event message buffer they must use the search string WSDNOTIFYTOADDRESS for
        /// the To header property.
        /// </remarks>
        public void FireEvent(DpwsHostedService hostedService, DpwsWseEventSource eventSource, WsWsaHeader eventHeader, String eventMessageBody)
        {
            // Find the specified event source
            if (eventSource == null)
            {
                throw new ArgumentNullException("FireEvent could not locate specified hosted service");
            }
            DpwsWseEventSinks eventSinks = eventSource.EventSinks;

            // if there are event sources display message
            int count = eventSinks.Count;

            if (count > 0)
            {
                System.Ext.Console.Write("");
                System.Ext.Console.Write("Firing " + eventSource.Name);
                System.Ext.Console.Write("");
            }

            // Loop through event sinks and send the event message
            for (int i = 0; i < count; i++)
            {
                DpwsWseEventSink eventSink = eventSinks[i];

                // Try to send event. If attempt fails delete the subscription/eventSink
                try
                {
                    MemoryStream soapStream = new MemoryStream();
                    XmlWriter    xmlWriter  = XmlWriter.Create(soapStream);

                    WsWsaHeader header = new WsWsaHeader(eventHeader.Action, eventHeader.RelatesTo, eventSink.NotifyTo.Address.AbsoluteUri,
                                                         null, null, eventSink.NotifyTo.RefParameters);

                    WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter, WsSoapMessageWriter.Prefixes.Wse, null, header, null);

                    if (eventMessageBody != null)
                    {
                        xmlWriter.WriteRaw(eventMessageBody);
                    }

                    WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter);

                    xmlWriter.Flush();
                    xmlWriter.Close();

                    SendEvent(soapStream.ToArray(), eventSink.NotifyTo.Address.AbsoluteUri);
                }
                catch (Exception e)
                {
                    System.Ext.Console.Write("");
                    System.Ext.Console.Write("FireEvent failed. Deleting EventSink! NotifyToAddress = " + eventSink.NotifyTo.Address + " Exception: " + e.Message);
                    System.Ext.Console.Write("");

                    // Send oneway subscription end message
                    try
                    {
                        SendSubscriptionEnd(eventSink, "DeliveryFailure", hostedService.ServiceID);
                    }
                    catch { }

                    // Remove event sink from event source list
                    eventSinks.Remove(eventSink);
                }
            }
        }
        /// <summary>
        /// Global eventing Subscribe stub.
        /// </summary>
        /// <param name="header">Header object.</param>
        /// <param name="reader">An XmlReader positioned at the begining of the Subscribe request body element.</param>
        /// <param name="serviceEndpoints">A Collection of serviceEndpoints used to determine what services contain the event source specified in the filter.</param>
        /// <returns>Byte array containing a Subscribe response.</returns>
        internal WsMessage Subscribe(WsWsaHeader header, XmlReader reader, WsServiceEndpoints serviceEndpoints)
        {
            WsMessage msg = null;

            // Parse Subscribe Request
            /////////////////////////////
            DpwsWseEventSink eventSink = new DpwsWseEventSink();

            try
            {
                reader.ReadStartElement("Subscribe", WsWellKnownUri.WseNamespaceUri);

                if (reader.IsStartElement("EndTo", WsWellKnownUri.WseNamespaceUri))
                {
                    eventSink.EndTo = new WsWsaEndpointRef(reader, m_version.AddressingNamespace);
                }

                reader.ReadStartElement("Delivery", WsWellKnownUri.WseNamespaceUri);
                if (reader.IsStartElement("NotifyTo", WsWellKnownUri.WseNamespaceUri))
                {
                    eventSink.NotifyTo = new WsWsaEndpointRef(reader, m_version.AddressingNamespace);
                }
                else
                {
                    throw new WsFaultException(header, WsFaultType.WseDeliverModeRequestedUnavailable);
                }

                reader.ReadEndElement();

                if (reader.IsStartElement("Expires", WsWellKnownUri.WseNamespaceUri))
                {
                    long expires = new WsDuration(reader.ReadElementString()).DurationInSeconds;

                    if (expires > 0)
                    {
                        eventSink.Expires = expires;
                    }
                    else
                    {
                        throw new WsFaultException(header, WsFaultType.WseInvalidExpirationTime);
                    }
                }
                else
                {
                    // Never Expires
                    eventSink.Expires = -1;
                }

                if (reader.IsStartElement("Filter", WsWellKnownUri.WseNamespaceUri))
                {
                    if (reader.MoveToAttribute("Dialect") == false || reader.Value != m_version.WsdpNamespaceUri + "/Action")
                    {
                        throw new WsFaultException(header, WsFaultType.WseFilteringRequestedUnavailable);
                    }

                    reader.MoveToElement();

                    String filters = reader.ReadElementString();

                    if (filters != String.Empty)
                    {
                        eventSink.Filters = filters.Split(' ');
                    }
                }

                XmlReaderHelper.SkipAllSiblings(reader);

                reader.ReadEndElement(); // Subscribe
            }
            catch (XmlException e)
            {
                throw new WsFaultException(header, WsFaultType.WseInvalidMessage, e.ToString());
            }

            // Parse urn:uuid from the To address
            string endpointAddress = FixToAddress(header.To);

            // Build a temporary collection of device services that match the specified endpoint address.
            WsServiceEndpoints matchingServices = new WsServiceEndpoints();

            for (int i = 0; i < serviceEndpoints.Count; ++i)
            {
                if (serviceEndpoints[i].EndpointAddress == endpointAddress)
                {
                    matchingServices.Add(serviceEndpoints[i]);
                }
            }

            // For each service with a matching endpoint and event sources add an event sink to the
            // event source collection
            for (int i = 0; i < matchingServices.Count; ++i)
            {
                DpwsWseEventSources eventSources = ((DpwsHostedService)matchingServices[i]).EventSources;

                // Set the EventSinkID
                eventSink.ID = "urn:uuid:" + Guid.NewGuid().ToString();

                // If subscribing to all event sources
                if (eventSink.Filters == null)
                {
                    int count = eventSources.Count;
                    for (int ii = 0; i < count; i++)
                    {
                        DpwsWseEventSource eventSource = eventSources[ii];
                        eventSink.StartTime = DateTime.Now.Ticks;
                        eventSource.EventSinks.Add(eventSink);
                    }
                }
                else
                {
                    // If subscribing to a specific event based on an event filter.
                    DpwsWseEventSource eventSource;
                    string[]           filterList = eventSink.Filters;
                    int length = filterList.Length;
                    for (int ii = 0; i < length; i++)
                    {
                        if ((eventSource = eventSources[filterList[ii]]) != null)
                        {
                            eventSink.StartTime = DateTime.Now.Ticks;
                            eventSource.EventSinks.Add(eventSink);
                        }
                        else
                        {
                            throw new Exception("Event source " + filterList[ii] + " was not found.");
                        }
                    }
                }
            }

            // Generate Response
            //////////////////////////
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                WsWsaHeader responseHeader = new WsWsaHeader(
                    WsWellKnownUri.WseNamespaceUri + "/SubscribeResponse",  // Action
                    header.MessageID,                                       // RelatesTo
                    header.ReplyTo.Address.AbsoluteUri,                     // To
                    null, null, null);                                      // ReplyTo, From, Any

                msg = new WsMessage(responseHeader, null, WsPrefix.Wse, null,
                                    new WsAppSequence(Device.AppSequence, Device.SequenceID, Device.MessageID));

                WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version);
                smw.WriteSoapMessageStart(xmlWriter, msg);

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscribeResponse", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscriptionManager", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                // Create a uri. Use the path (by default will be a uuid) for the sub manager endpoint
                Uri subMgrUri = new Uri(((DpwsHostedService)matchingServices[0]).EndpointAddress);
                xmlWriter.WriteString("http://" + Device.IPV4Address + ":" + Device.Port + "/" + subMgrUri.AbsolutePath);
                xmlWriter.WriteEndElement(); // End Address
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "ReferenceParameters", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Identifier", null);
                xmlWriter.WriteString(eventSink.ID);
                xmlWriter.WriteEndElement(); // End Identifier
                xmlWriter.WriteEndElement(); // End ReferenceParameters
                xmlWriter.WriteEndElement(); // End SubscriptionManager
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Expires", null);
                xmlWriter.WriteString(new WsDuration(eventSink.Expires).DurationString);
                xmlWriter.WriteEndElement(); // End Expires
                xmlWriter.WriteEndElement(); // End SubscribeResponse

                smw.WriteSoapMessageEnd(xmlWriter);

                // Return stream buffer
                msg.Body = xmlWriter.ToArray();
            }

            return(msg);
        }
Пример #13
0
        /// <summary>
        /// This method build a subscription end message.
        /// </summary>
        /// <param name="eventSink">An event sink containing client endpoint information.</param>
        /// <param name="shutdownMessage">A string containing reason why the subscription is ending.</param>
        /// <param name="subMangerID">An id sent by the client that they use to reference a subscription.</param>
        /// <returns></returns>
        private WsMessage SubscriptionEndResponse(DpwsWseEventSink eventSink, string shutdownMessage, string subMangerID)
        {
            using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                WsWsaHeader responseHeader = new WsWsaHeader(
                    WsWellKnownUri.WseNamespaceUri + "/SubscriptionEnd",    // Action
                    null,                                                   // RelatesTo
                    eventSink.EndTo.Address.AbsoluteUri,                    // To
                    null, null, eventSink.EndTo.RefProperties);             // ReplyTo, From, Any

                WsMessage msg = new WsMessage(responseHeader, null, WsPrefix.Wse, null, null);

                WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version);
                smw.WriteSoapMessageStart(xmlWriter, msg);

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscriptionEnd", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscriptionManager", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                xmlWriter.WriteString("http://" + Device.IPV4Address + ":" + Device.Port + "/" + subMangerID);
                xmlWriter.WriteEndElement(); // End Address
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "ReferenceParameters", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Identifier", null);
                xmlWriter.WriteString(eventSink.ID);
                xmlWriter.WriteEndElement(); // End Identifier
                xmlWriter.WriteEndElement(); // End ReferenceParameters
                xmlWriter.WriteEndElement(); // End SubscriptionManager
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Code", null);
                xmlWriter.WriteString(WsNamespacePrefix.Wse + ":" + shutdownMessage);
                xmlWriter.WriteEndElement(); // End Code
                xmlWriter.WriteEndElement(); // End SubscriptionEnd

                smw.WriteSoapMessageEnd(xmlWriter);

                msg.Body = xmlWriter.ToArray();

                // Return stream buffer
                return msg;
            }
        }
Пример #14
0
 //
 // Summary:
 //     Removes the first occurrence of a specific object from the eventsink list.
 //
 // Parameters:
 //   subscription:
 //     The eventsink object to remove from the eventsink list. The value
 //     can be null.
 //
 public void Remove(DpwsWseEventSink eventSink)
 {
     lock (m_threadLock)
     {
         m_sinkList.Remove(eventSink);
     }
 }
Пример #15
0
        //
        // Summary:
        //     Adds an object to the end of the eventsink list.
        //
        // Parameters:
        //   value:
        //     The System.Object to be added to the end of the eventlist.
        //     The value can be null.
        //
        // Returns:
        //     The eventsink index at which the value has been added.
        //
        public int Add(DpwsWseEventSink value)
        {
            lock (m_threadLock)
            {
                // Ignore duplicate event sinks. Delete the current sink and add the new event sink.
                int count = m_sinkList.Count;
                String valueUri = value.NotifyTo.Address.AbsoluteUri.ToLower();
                for (int i = 0; i < count; i++)
                {
                    if (((DpwsWseEventSink)m_sinkList[i]).NotifyTo.Address.AbsoluteUri.ToLower() == valueUri)
                    {
                        m_sinkList.RemoveAt(i);
                        break;
                    }
                }

                return m_sinkList.Add(value);
            }
        }
Пример #16
0
        /// <summary>
        /// Used by the subscription manager to send a subscription end message to a listening client.
        /// </summary>
        /// <param name="eventSink">An event sink object containing the client endpoint information.</param>
        /// <param name="subEndType">A string that specifies the reason fot the subscription end.</param>
        /// <param name="subMangerID">A id used by the client to identify this subcription.</param>
        /// <remarks>If an error occures when sending an event message this method is called to tell
        /// the client this subscription has been expired.
        /// </remarks>
        private void SendSubscriptionEnd(DpwsWseEventSink eventSink, string subEndType, string subMangerID)
        {
            // if we weren't given an EndTo, don't send
            if (eventSink.EndTo == null)
            {
                return;
            }

            if(m_persistEventConnections)
            {
                eventSink.RequestChannel.Request(SubscriptionEndResponse(eventSink, subEndType, subMangerID));
            }
            else
            {
                eventSink.RequestChannel.Open();
                eventSink.RequestChannel.Request(SubscriptionEndResponse(eventSink, subEndType, subMangerID));
                eventSink.RequestChannel.Close();
            }
        }
Пример #17
0
        /// <summary>
        /// This method build a subscription end message.
        /// </summary>
        /// <param name="eventSink">An event sink containing client endpoint information.</param>
        /// <param name="shutdownMessage">A string containing reason why the subscription is ending.</param>
        /// <param name="subMangerID">An id sent by the client that they use to reference a subscription.</param>
        /// <returns></returns>
        private byte[] SubscriptionEndResponse(DpwsWseEventSink eventSink, string shutdownMessage, string subMangerID)
        {

            MemoryStream soapStream = new MemoryStream();
            XmlWriter xmlWriter = XmlWriter.Create(soapStream);

            WsWsaHeader responseHeader = new WsWsaHeader(
                WsWellKnownUri.WseNamespaceUri + "/SubscriptionEnd",    // Action
                null,                                                   // RelatesTo
                eventSink.EndTo.Address.AbsoluteUri,                    // To
                null, null, eventSink.EndTo.RefProperties);             // ReplyTo, From, Any

            WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter,
                WsSoapMessageWriter.Prefixes.Wse,                       // Prefix
                null,                                                   // Additional Prefix
                responseHeader,                                         // Header
                null);                                                  // AppSequence

            // write body
            xmlWriter.WriteStartElement("wse", "SubscriptionEnd", null);
            xmlWriter.WriteStartElement("wse", "SubscriptionManager", null);
            xmlWriter.WriteStartElement("wsa", "Address", null);
            xmlWriter.WriteString("http://" + Device.IPV4Address + ":" + Device.Port + "/" + subMangerID);
            xmlWriter.WriteEndElement(); // End Address
            xmlWriter.WriteStartElement("wsa", "ReferenceParameters", null);
            xmlWriter.WriteStartElement("wse", "Identifier", null);
            xmlWriter.WriteString(eventSink.ID);
            xmlWriter.WriteEndElement(); // End Identifier
            xmlWriter.WriteEndElement(); // End ReferenceParameters
            xmlWriter.WriteEndElement(); // End SubscriptionManager
            xmlWriter.WriteStartElement("wse", "Code", null);
            xmlWriter.WriteString("wse:" + shutdownMessage);
            xmlWriter.WriteEndElement(); // End Code
            xmlWriter.WriteEndElement(); // End SubscriptionEnd

            WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter);

            // Flush and close writer. Return stream buffer
            xmlWriter.Flush();
            xmlWriter.Close();
            return soapStream.ToArray();
        }
Пример #18
0
        /// <summary>
        /// Used by the subscription manager to send a subscription end message to a listening client.
        /// </summary>
        /// <param name="eventSink">An event sink object containing the client endpoint information.</param>
        /// <param name="subEndType">A string that specifies the reason fot the subscription end.</param>
        /// <param name="subMangerID">A id used by the client to identify this subcription.</param>
        /// <remarks>If an error occures when sending an event message this method is called to tell
        /// the client this subscription has been expired.
        /// </remarks>
        private void SendSubscriptionEnd(DpwsWseEventSink eventSink, string subEndType, string subMangerID)
        {
            // if we weren't given an EndTo, don't send
            if (eventSink.EndTo == null)
            {
                return;
            }

            // Parse the http transport address
            if (eventSink.EndTo.Address.Scheme == "http")
            {
                WsHttpClient httpClient = new WsHttpClient();
                httpClient.SendRequest(SubscriptionEndResponse(eventSink, subEndType, subMangerID), eventSink.EndTo.Address.AbsoluteUri, true, false);
            }
            else
            {
                System.Ext.Console.Write("");
                System.Ext.Console.Write("Unsupported transport address Subscription EndTo.Address: " + eventSink.EndTo.Address);
                System.Ext.Console.Write("");
                return;
            }
        }
Пример #19
0
        /// <summary>
        /// Global eventing Subscribe stub.
        /// </summary>
        /// <param name="header">Header object.</param>
        /// <param name="reader">An XmlReader positioned at the begining of the Subscribe request body element.</param>
        /// <param name="serviceEndpoints">A Collection of serviceEndpoints used to determine what services contain the event source specified in the filter.</param>
        /// <returns>Byte array containing a Subscribe response.</returns>
        internal WsMessage Subscribe(WsWsaHeader header, XmlReader reader, WsServiceEndpoints serviceEndpoints)
        {
            WsMessage msg = null;

            // Parse Subscribe Request
            /////////////////////////////
            DpwsWseEventSink eventSink = new DpwsWseEventSink();
            try
            {
                reader.ReadStartElement("Subscribe", WsWellKnownUri.WseNamespaceUri);

                if (reader.IsStartElement("EndTo", WsWellKnownUri.WseNamespaceUri))
                {
                    eventSink.EndTo = new WsWsaEndpointRef(reader, m_version.AddressingNamespace);
                }

                reader.ReadStartElement("Delivery", WsWellKnownUri.WseNamespaceUri);
                if (reader.IsStartElement("NotifyTo", WsWellKnownUri.WseNamespaceUri))
                {
                    eventSink.NotifyTo = new WsWsaEndpointRef(reader, m_version.AddressingNamespace);
                }
                else
                {
                    throw new WsFaultException(header, WsFaultType.WseDeliverModeRequestedUnavailable);
                }

                reader.ReadEndElement();

                if (reader.IsStartElement("Expires", WsWellKnownUri.WseNamespaceUri))
                {
                    long expires = new WsDuration(reader.ReadElementString()).DurationInSeconds;

                    if (expires > 0)
                    {
                        eventSink.Expires = expires;
                    }
                    else
                    {
                        throw new WsFaultException(header, WsFaultType.WseInvalidExpirationTime);
                    }
                }
                else
                {
                    // Never Expires
                    eventSink.Expires = -1;
                }

                if (reader.IsStartElement("Filter", WsWellKnownUri.WseNamespaceUri))
                {
                    if (reader.MoveToAttribute("Dialect") == false || reader.Value != m_version.WsdpNamespaceUri + "/Action")
                    {
                        throw new WsFaultException(header, WsFaultType.WseFilteringRequestedUnavailable);
                    }

                    reader.MoveToElement();

                    String filters = reader.ReadElementString();

                    if (filters != String.Empty)
                    {
                        eventSink.Filters = filters.Split(' ');
                    }
                }

                XmlReaderHelper.SkipAllSiblings(reader);

                reader.ReadEndElement(); // Subscribe
            }
            catch (XmlException e)
            {
                throw new WsFaultException(header, WsFaultType.WseInvalidMessage, e.ToString());
            }

            // Parse urn:uuid from the To address
            string endpointAddress = FixToAddress(header.To);

            // Build a temporary collection of device services that match the specified endpoint address.
            WsServiceEndpoints matchingServices = new WsServiceEndpoints();
            for (int i = 0; i < serviceEndpoints.Count; ++i)
            {
                if (serviceEndpoints[i].EndpointAddress == endpointAddress)
                    matchingServices.Add(serviceEndpoints[i]);
            }

            // For each service with a matching endpoint and event sources add an event sink to the
            // event source collection
            for (int i = 0; i < matchingServices.Count; ++i)
            {
                DpwsWseEventSources eventSources = ((DpwsHostedService)matchingServices[i]).EventSources;

                // Set the EventSinkID
                eventSink.ID = "urn:uuid:" + Guid.NewGuid().ToString();

                // If subscribing to all event sources
                if (eventSink.Filters == null)
                {
                    int count = eventSources.Count;
                    for (int ii = 0; i < count; i++)
                    {
                        DpwsWseEventSource eventSource = eventSources[ii];
                        eventSink.StartTime = DateTime.Now.Ticks;
                        eventSource.EventSinks.Add(eventSink);
                    }
                }
                else
                {
                    // If subscribing to a specific event based on an event filter.
                    DpwsWseEventSource eventSource;
                    string[] filterList = eventSink.Filters;
                    int length = filterList.Length;
                    for (int ii = 0; i < length; i++)
                    {
                        if ((eventSource = eventSources[filterList[ii]]) != null)
                        {
                            eventSink.StartTime = DateTime.Now.Ticks;
                            eventSource.EventSinks.Add(eventSink);
                        }
                        else
                        {
                            throw new Exception("Event source " + filterList[ii] + " was not found.");
                        }
                    }
                }
            }

            // Generate Response
            //////////////////////////
            using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                WsWsaHeader responseHeader = new WsWsaHeader(
                    WsWellKnownUri.WseNamespaceUri + "/SubscribeResponse",  // Action
                    header.MessageID,                                       // RelatesTo
                    header.ReplyTo.Address.AbsoluteUri,                     // To
                    null, null, null);                                      // ReplyTo, From, Any

                msg = new WsMessage(responseHeader, null, WsPrefix.Wse, null, 
                    new WsAppSequence(Device.AppSequence, Device.SequenceID, Device.MessageID));

                WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version);
                smw.WriteSoapMessageStart(xmlWriter, msg);

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscribeResponse", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "SubscriptionManager", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                // Create a uri. Use the path (by default will be a uuid) for the sub manager endpoint
                Uri subMgrUri = new Uri(((DpwsHostedService)matchingServices[0]).EndpointAddress);
                xmlWriter.WriteString("http://" + Device.IPV4Address + ":" + Device.Port + "/" + subMgrUri.AbsolutePath);
                xmlWriter.WriteEndElement(); // End Address
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "ReferenceParameters", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Identifier", null);
                xmlWriter.WriteString(eventSink.ID);
                xmlWriter.WriteEndElement(); // End Identifier
                xmlWriter.WriteEndElement(); // End ReferenceParameters
                xmlWriter.WriteEndElement(); // End SubscriptionManager
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Expires", null);
                xmlWriter.WriteString(new WsDuration(eventSink.Expires).DurationString);
                xmlWriter.WriteEndElement(); // End Expires
                xmlWriter.WriteEndElement(); // End SubscribeResponse

                smw.WriteSoapMessageEnd(xmlWriter);

                // Return stream buffer
                msg.Body = xmlWriter.ToArray();
            }

            return msg;
        }
Пример #20
0
        /// <summary>
        /// Method used to expire events and send EndTo notification to an event sink
        /// </summary>
        public void EventService()
        {
            DateTime curDateTime;

            while (m_requestStop == false)
            {
                curDateTime = DateTime.Now;

                try
                {
                    // Loop through hosted services
                    int servicesCount = Device.HostedServices.Count;
                    for (int i = 0; i < servicesCount; i++)
                    {
                        if (m_requestStop == true)
                        {
                            break;
                        }

                        DpwsHostedService hostedService = (DpwsHostedService)Device.HostedServices[i];

                        // Loop through event sources
                        int eventSourcesCount = hostedService.EventSources.Count;
                        for (int j = 0; j < eventSourcesCount; j++)
                        {
                            if (m_requestStop == true)
                            {
                                break;
                            }

                            DpwsWseEventSource eventSource = hostedService.EventSources[j];

                            // Loop through event sinks. Check expiration time. If an event has
                            // expired send subscription end message and delete event sink.
                            int eventSinkCount = eventSource.EventSinks.Count;
                            for (int k = 0; k < eventSinkCount; k++)
                            {
                                if (m_requestStop == true)
                                {
                                    break;
                                }

                                DpwsWseEventSink eventSink = eventSource.EventSinks[k];

                                // If time has expired delete event sink
                                if (eventSink.StartTime + eventSink.Expires > curDateTime.Ticks)
                                {
                                    eventSource.EventSinks.Remove(eventSink);
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    System.Ext.Console.Write("");
                    System.Ext.Console.Write("Event Queue Manager threw and exception. " + e.Message);
                    System.Ext.Console.Write("");
                }

                Thread.Sleep(5000);
            }
        }