/// <summary> /// Creates an instance of a DpwsClient class with a specified eventing callback port number. /// </summary> public DpwsClient(Binding localBinding, ProtocolVersion v) { m_threadLock = new object(); m_eventClient = new DpwsEventingClient(v); m_mexClient = new DpwsMexClient(v); m_eventCallbacks = new WsServiceOperations(); m_callbackServiceEndpoints = new WsServiceEndpoints(); m_blockingCall = true; m_ignoreRequestFromThisIP = true; m_localBinding = localBinding; m_version = v; m_discoClient = new DpwsDiscoveryClient(this, v); // Add the Hello and Bye discovery disco services ClientDiscoveryService = new DpwsDiscoClientService(this, v); // Start a Udp discovery service host WsUdpServiceHost.Instance.AddServiceEndpoint(ClientDiscoveryService); WsUdpServiceHost.Instance.IgnoreRequestFromThisIP = m_ignoreRequestFromThisIP; WsUdpServiceHost.Instance.MaxThreadCount = 5; WsUdpServiceHost.Instance.Start(new ServerBindingContext(v)); // Add eventing SubscriptionEnd ServiceOperations. By default Subscription End call back // to this client ServiceOperations.Add(new WsServiceOperation(WsWellKnownUri.WseNamespaceUri, "SubscriptionEnd")); // Add callbacks implemented by this client m_callbackServiceEndpoints.Add(this); // Start the Http service host m_httpServiceHost = new WsHttpServiceHost(m_localBinding, m_callbackServiceEndpoints); m_httpServiceHost.MaxThreadCount = m_callbackServiceEndpoints.Count; m_httpServiceHost.Start(new ServerBindingContext(v)); System.Ext.Console.Write("Http service host started..."); }
/// <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; }