/// <summary> /// Adds an event source to the end of the event source collection. /// </summary> /// <param name="value"> /// The event source object to be added to the end of the event sources collection. The value can be null. /// </param> /// <returns> /// The event source index at which the value has been added. /// </returns> public int Add(DpwsWseEventSource value) { lock (m_threadLock) { return(m_sourceList.Add(value)); } }
/// <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> /// 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); } } }
// Constructor sets service properties and defines operations and adds event sources public SimpleService(ProtocolVersion version) : base(version) { // Add ServiceNamespace. Set ServiceID and ServiceTypeName ServiceNamespace = new WsXmlNamespace("sim", "http://schemas.example.org/SimpleService"); ServiceID = "urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b90"; ServiceTypeName = "SimpleService"; // Add service operations ServiceOperations.Add(new WsServiceOperation("http://schemas.example.org/SimpleService", "OneWay")); ServiceOperations.Add(new WsServiceOperation("http://schemas.example.org/SimpleService", "TwoWayRequest")); // Add event sources DpwsWseEventSource SimpleEvent = new DpwsWseEventSource("sim", "http://schemas.example.org/EventingService", "SimpleEvent"); EventSources.Add(SimpleEvent); this.AddEventServices(); }
public EventingService() { // The client filters devices when probing using the ServiceTypeName property this.ServiceTypeName = "EventingServiceType"; // Add a unique namespace for our service this.ServiceNamespace = new WsXmlNamespace("eventing", // prefix c_namespaceUri); // URI // Unique ID to access the service this.ServiceID = "urn:uuid:93252386-0724-c8ca-bd31-000000732d93"; // Add event source DpwsWseEventSource eventSource = new DpwsWseEventSource(this.ServiceNamespace.Prefix, this.ServiceNamespace.NamespaceURI, "SimpleEvent"); // event name this.EventSources.Add(eventSource); }
public TestService(string guid, ProtocolVersion version) : base(version) { // Add ServiceNamespace. Set ServiceID and ServiceTypeName ServiceNamespace = new WsXmlNamespace("sim", "http://schemas.example.org/SimpleService"); ServiceID = "urn:uuid:" + guid; ServiceTypeName = "TestService"; // Add additional namesapces if needed // example: Namespaces.Add("someprefix", "http://some/Namespace"); // Add service operations ServiceOperations.Add(new WsServiceOperation("http://schemas.example.org/SimpleService", "OneWay")); ServiceOperations.Add(new WsServiceOperation("http://schemas.example.org/SimpleService", "TwoWayRequest")); // Add event sources DpwsWseEventSource SimpleEvent = new DpwsWseEventSource("sim", "http://schemas.example.org/EventingService", "SimpleEvent"); EventSources.Add(SimpleEvent); this.AddEventServices(); }
public DpwsWseEventSource this[string eventSourceName] { get { lock (m_threadLock) { int count = m_sourceList.Count; for (int i = 0; i < count; i++) { DpwsWseEventSource sourceType = (DpwsWseEventSource)m_sourceList[i]; if (sourceType.Operation == eventSourceName || sourceType.Name == eventSourceName) { return(sourceType); } } return(null); } } }
/// <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); } }
public MFTestResults ServicesTest3_DpwsWseEventSource() { /// <summary> /// 1. Gets and verifies each of the properties of a DpwsWseEventSource object /// 2. Sets and re-verifies all properties /// </summary> /// bool testResult = true; try { DpwsWseEventSource testDWES = new DpwsWseEventSource( "testPrefix", "urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b51", "testName"); if (testDWES.Name == null || testDWES.Name.GetType() != Type.GetType("System.String") || testDWES.Name != "testName") throw new Exception("Name did not set correctly"); if (testDWES.NamespaceURI == null || testDWES.NamespaceURI.GetType() != Type.GetType("System.String") || testDWES.NamespaceURI != "urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b51") throw new Exception("NamespaceURI did not set correctly"); if (testDWES.Operation == null || testDWES.Operation.GetType() != Type.GetType("System.String") || testDWES.Operation != "urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b51" + "/testName") throw new Exception("Operation did not set correctly"); if (testDWES.Prefix == null || testDWES.Prefix.GetType() != Type.GetType("System.String") || testDWES.Prefix != "testPrefix") throw new Exception("Prefix did not set correctly"); } catch (Exception e) { testResult = false; Log.Comment("Incorrect exception caught: " + e.Message); } return (testResult ? MFTestResults.Pass : MFTestResults.Fail); }
/// <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); }
/// <summary> /// Adds an event source to the end of the event source collection. /// </summary> /// <param name="value"> /// The event source object to be added to the end of the event sources collection. The value can be null. /// </param> /// <returns> /// The event source index at which the value has been added. /// </returns> public int Add(DpwsWseEventSource value) { lock (m_threadLock) { return m_sourceList.Add(value); } }
/// <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> /// 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> /// 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); } }