/// <summary> /// This method is called by the process manager to process a request. /// </summary> public void ProcessRequest() { // Performance debuging DebugTiming timeDebuger = new DebugTiming(); timeDebuger.ResetStartTime("***Request Debug timer started"); // Process the message WsMessage response = ProcessRequestMessage(m_request.Message); // If response is null the requested service is not implemented so just ignore this request if (response == null) return; // Performance debuging timeDebuger.PrintElapsedTime("***ProcessMessage Took"); // Send the response m_request.Reply(response); // Performance Debuging timeDebuger.PrintElapsedTime("***Send Message Took"); }
/// <summary> /// Http servers message processor. This method reads a message from a socket and calls downstream /// processes that parse the request, dispatch to a method and returns a response. /// </summary> /// <remarks>The parameters should always be set to null. See IWsTransportMessageProcessor for details.</remarks> public void ProcessRequest() { try { // Retrieval of Request causes reading of data from network and parsing request. m_httpRequest = m_httpContext.Request; m_httpResponse = m_httpContext.Response; System.Ext.Console.Write("Request From: " + m_httpRequest.RemoteEndPoint.ToString()); // Checks and process headers important for DPWS if (!ProcessKnownHeaders()) { return; } byte[] messageBuffer = null; int messageLength = (int)m_httpRequest.ContentLength64; if (messageLength > 0) { // If there is content length for the message, we read it complete. messageBuffer = new byte[messageLength]; for ( int offset = 0; offset < messageLength; ) { int noRead = m_httpRequest.InputStream.Read(messageBuffer, offset, messageLength - offset); if (noRead == 0) { throw new IOException("Http server got only " + offset + " bytes. Expected to read " + messageLength + " bytes."); } offset += noRead; } } else { // In this case the message is chunk encoded, but m_httpRequest.InputStream actually does processing. // So we we read until zero bytes are read. bool readComplete = false; int bufferSize = ReadPayload; messageBuffer = new byte[bufferSize]; int offset = 0; while (!readComplete) { while (offset < ReadPayload) { int noRead = m_httpRequest.InputStream.Read(messageBuffer, offset, messageLength - offset); // If we read zero bytes - means this is end of message. This is how InputStream.Read for chunked encoded data. if (noRead == 0) { readComplete = true; break; } offset += noRead; } // If read was not complete - increase the buffer. if (!readComplete) { bufferSize += ReadPayload; byte[] newMessageBuf = new byte[bufferSize]; Array.Copy(messageBuffer, newMessageBuf, offset); messageBuffer = newMessageBuf; } } m_chunked = false; } // Process the soap request. try { // Message byte buffer byte[] soapRequest; byte[] soapResponse = null; // If this is an mtom message process attachments, else process the raw message if (m_mtomHeader != null) { // Process the message WsMessage response = ProcessRequestMessage(new WsMessage(messageBuffer, m_mtomHeader.boundary, m_mtomHeader.start)); if (response != null) { soapResponse = response.Message; if (response.MessageType == WsMessageType.Mtom) { m_mtomHeader.boundary = response.BodyParts.Boundary; m_mtomHeader.start = response.BodyParts.Start; } } } else { // Convert the message buffer to a byte array soapRequest = messageBuffer; // Performance debuging DebugTiming timeDebuger = new DebugTiming(); timeDebuger.ResetStartTime("***Request Debug timer started"); // Process the message WsMessage response = ProcessRequestMessage(new WsMessage(soapRequest)); if (response != null) soapResponse = response.Message; // Performance debuging timeDebuger.PrintElapsedTime("***ProcessMessage Took"); } // Display remote endpoint System.Ext.Console.Write("Response To: " + m_httpRequest.RemoteEndPoint.ToString()); // Send the response SendResponse(soapResponse); } catch (Exception e) { System.Ext.Console.Write(e.Message + " " + e.InnerException); SendError(400, "Bad Request"); } } catch { System.Ext.Console.Write("Invalid request format. Request ignored."); SendError(400, "Bad Request"); } finally { m_httpResponse.Close(); } }
/// <summary> /// Builds a probe request message based on the filters parameter. /// </summary> /// <param name="serviceAddress"> /// A string containing the target service address. /// For example: urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="filters"> /// A DpwsServiceTypes object containing a collection of types a service must support to signal a match. /// Null = any type. /// </param> /// <param name="messageID"> /// A string used to return the messageID assigned to this message. /// </param> /// <returns>A byte array containing the probe message or null if an error occures.</returns> private WsMessage BuildProbeRequest(string serviceAddress, DpwsServiceTypes filters, out String messageID) { // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); WsMessage msg = null; // Build Probe request using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create()) { WsWsaHeader header = new WsWsaHeader( m_version.DiscoveryNamespace + "/Probe", // Action null, // RelatesTo serviceAddress, // To m_version.AnonymousUri, null, null); // ReplyTo, From, Any header.MustUnderstand = true; // If filters are supplied, write filter namespaces if prefixed. Build filter list for use later WsXmlNamespaces namespaces = new WsXmlNamespaces(); // Prefix hack for now: int i = 0; string prefix; string filterList = ""; bool spaceFlag = false; if (filters != null) { int count = filters.Count; for (int j = 0; j < count; j++) { DpwsServiceType serviceType = filters[j]; prefix = namespaces.LookupPrefix(serviceType.NamespaceUri); if (prefix == null) { prefix = "dp" + (i++); namespaces.Add(new WsXmlNamespace(prefix, serviceType.NamespaceUri)); } filterList = filterList + ((spaceFlag == true) ? " " : "") + prefix + ":" + serviceType.TypeName; spaceFlag = true; } } msg = new WsMessage(header, null, WsPrefix.Wsd, namespaces, null); WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version); messageID = smw.WriteSoapMessageStart(xmlWriter, msg); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "Probe", null); // If filter is supplied add filter types tag else write blank string to probe body, force an empty tag if (filterList.Length != 0) { xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "Types", null); xmlWriter.WriteString(filterList); xmlWriter.WriteEndElement(); // End Filter } else xmlWriter.WriteString(""); xmlWriter.WriteEndElement(); // End Probe // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); smw.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Probe Message Build Took"); // return the probe message msg.Body = xmlWriter.ToArray(); } return msg; }
/// <summary> /// Use to get the status of an event subscription. /// </summary> /// <param name="endpointAddress"> /// A Uri containing the endpoint address of the service or subscription manager that is currently /// maintaining this event subscription on behalf of the device. This address is an http uri /// (i.e. http://ip_address:port/serviceID). /// </param> /// <param name="subscriptionID"> /// A subscription ID returned from a previous subscribe response. The device uses this ID /// to identify a specific event source subscription. /// </param> /// <returns> /// A WsDuration object containing the remaining subscription time for this event subscription, null = infinite. /// </returns> public WsDuration GetStatus(Uri endpointAddress, string subscriptionID) { // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Renew request using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create()) { WsXmlNodeList nodeList = new WsXmlNodeList(); nodeList.Add(new WsXmlNode(WsNamespacePrefix.Wse, "Identifier", null, subscriptionID)); WsWsaHeader header = new WsWsaHeader( m_version.EventingNamespace + "/GetStatus", // Action null, // RelatesTo endpointAddress.AbsoluteUri, // To null, null, nodeList); // ReplyTo, From, Any WsMessage msg = new WsMessage(header, null, WsPrefix.Wse, null, null); WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version); String messageID = smw.WriteSoapMessageStart(xmlWriter, msg); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Body", null); xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "GetStatus", null); xmlWriter.WriteString(""); xmlWriter.WriteEndElement(); // End GetStatus // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); smw.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Renew Message Build Took"); // Create an Http client and send GetStatus request WsHttpClient httpClient = new WsHttpClient(m_version); msg.Body = xmlWriter.ToString(); WsMessage getStatusResponse = httpClient.SendRequest(msg, endpointAddress); // If a GetStatus response is received validate the messageID and action and get the remaining // event subscription time. If a fault is received print exception and go on. if (getStatusResponse == null) { System.Ext.Console.Write(""); System.Ext.Console.Write("Renew response is null."); return null; } else { System.Ext.Console.Write(""); System.Ext.Console.Write("Response From: " + endpointAddress.Host); System.Ext.Console.Write(getStatusResponse.Body as byte[]); // Note: Since the response is the same for GetStatus ans it is for Renew reuse the // Renew response parser. try { return ProcessRenewResponse((byte[])getStatusResponse.Body, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Unsubscribe response parsing failed."); System.Ext.Console.Write(e.Message); } } } return null; }
public virtual byte[] ProbeMatch(WsWsaHeader header, XmlReader reader) { // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build ProbeMatch MemoryStream soapStream = new MemoryStream(); XmlWriter xmlWriter = XmlWriter.Create(soapStream); // If a Host exist write the Host namespace WsXmlNamespaces additionalPrefixes = null; if (Device.Host != null) { additionalPrefixes = new WsXmlNamespaces(); additionalPrefixes.Add(Device.Host.ServiceNamespace); } WsWsaHeader matchHeader = new WsWsaHeader( WsWellKnownUri.WsdNamespaceUri + "/ProbeMatches", // Action header.MessageID, // RelatesTo WsWellKnownUri.WsaAnonymousUri, // To null, null, null); // ReplyTo, From, Any WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter, WsSoapMessageWriter.Prefixes.Wsd | WsSoapMessageWriter.Prefixes.Wsdp, // Prefix additionalPrefixes, // Additional Prefixes matchHeader, // Header new WsSoapMessageWriter.AppSequence(Device.AppSequence, Device.SequenceID, Device.MessageID)); // AppSequence // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement("wsd", "ProbeMatches", WsWellKnownUri.WsdNamespaceUri); xmlWriter.WriteStartElement("wsd", "ProbeMatch", WsWellKnownUri.WsdNamespaceUri); xmlWriter.WriteStartElement("wsa", "EndpointReference", WsWellKnownUri.WsaNamespaceUri_2005_08); xmlWriter.WriteStartElement("wsa", "Address", WsWellKnownUri.WsaNamespaceUri_2005_08); xmlWriter.WriteString(Device.EndpointAddress); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); // Write hosted service types xmlWriter.WriteStartElement("wsd", "Types", WsWellKnownUri.WsdNamespaceUri); WriteDeviceServiceTypes(xmlWriter); xmlWriter.WriteEndElement(); // End Types xmlWriter.WriteStartElement("wsd", "XAddrs", WsWellKnownUri.WsdNamespaceUri); xmlWriter.WriteString(Device.TransportAddress); xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("wsd", "MetadataVersion", WsWellKnownUri.WsdNamespaceUri); xmlWriter.WriteString(Device.MetadataVersion.ToString()); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); // Create return buffer and close writer // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***ProbeMatch Took"); // Flush and close writer. Return stream buffer xmlWriter.Flush(); xmlWriter.Close(); // Delay probe match as per Ws-Discovery specification Thread.Sleep(new Random().Next(Device.ProbeMatchDelay)); return soapStream.ToArray(); }
/// <summary> /// Use to subscribe to a devices, hosted service event sources. /// </summary> /// <param name="subscriptionRequest"> /// A DpwsSubscriptionRequest object containing the address of the service hosting the desired event, /// the address where the event is sent, an optional address where subscription end messages are sent, /// A subscription expiration (in duration format) and an optional user defined identifier. /// </param> /// <returns> /// A DpwsEventSubscription containing the the subscription managers address, the time when the subscription /// expires (duration) and optional reference parameters and properties. Per spec the /// sub mananger may assign a different duration value than that specified in the request. /// </returns> /// <exception cref="ArgumentNullException">If required subscription parameters are not set.</exception> public DpwsEventSubscription Subscribe(DpwsSubscribeRequest subscriptionRequest) { if ((subscriptionRequest.SubscriptionType == null) || (subscriptionRequest.SubscriptionType.TypeName == null) || (subscriptionRequest.SubscriptionType.NamespaceUri == null) || (subscriptionRequest.EndpointAddress == null) || (subscriptionRequest.NotifyTo == null) || (subscriptionRequest.NotifyTo.Address == null)) { throw new ArgumentNullException(); } // Convert the address string to a Uri Uri serviceUri = null; try { serviceUri = subscriptionRequest.EndpointAddress; if (serviceUri.Scheme != "http") { System.Ext.Console.Write(""); System.Ext.Console.Write("Invalid endpoint address. Must be a Uri. Http Uri schemes only."); System.Ext.Console.Write(""); return null; } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); return null; } // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); WsMessage subscribeResponse = null; // Build Subscribe Request using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create()) { WsWsaHeader header = new WsWsaHeader( m_version.EventingNamespace + "/Subscribe", // Action null, // RelatesTo serviceUri.AbsoluteUri, // To m_version.AnonymousUri, // ReplyTo null, null); // From, Any WsXmlNamespaces additionalPrefixes = new WsXmlNamespaces(); additionalPrefixes.Add(new WsXmlNamespace("myPrefix", subscriptionRequest.SubscriptionType.NamespaceUri)); WsMessage msg = new WsMessage(header, null, WsPrefix.Wsd | WsPrefix.Wse, additionalPrefixes, null); WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version); String messageID = smw.WriteSoapMessageStart(xmlWriter, msg); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Subscribe", null); // If EndTo is set write it if (subscriptionRequest.EndTo != null) WriteEndpointRef(xmlWriter, subscriptionRequest.EndTo, "EndTo"); // Add the delivery element and NotifyTo endpoint xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Delivery", null); xmlWriter.WriteAttributeString("Mode", m_version.EventingNamespace + "/DeliveryModes/Push"); // Writer the notify to endpoint WriteEndpointRef(xmlWriter, subscriptionRequest.NotifyTo, "NotifyTo"); xmlWriter.WriteEndElement(); // End Delivery // Write Expiration time if (subscriptionRequest.Expires != null) { xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Expires", null); xmlWriter.WriteString(subscriptionRequest.Expires.DurationString); xmlWriter.WriteEndElement(); // End Expires } // Write Filter element specifying the event to subscribe to. xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Filter", null); xmlWriter.WriteAttributeString("Dialect", m_version.WsdpNamespaceUri + "/Action"); xmlWriter.WriteString(subscriptionRequest.SubscriptionType.NamespaceUri + "/" + subscriptionRequest.SubscriptionType.TypeName); xmlWriter.WriteEndElement(); // End Filter xmlWriter.WriteEndElement(); // End Subscribe smw.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Subscribe Message Build Took"); // Create an Http client and send Subscribe request WsHttpClient httpClient = new WsHttpClient(m_version); msg.Body = xmlWriter.ToArray(); subscribeResponse = httpClient.SendRequest(msg, subscriptionRequest.EndpointAddress); // If a subscribe response is received process it and return expiration time the subscription manager // actually assigned. // If a parsing fault is received print exception and go on. DpwsEventSubscription response = null; if (subscribeResponse == null) { System.Ext.Console.Write(""); System.Ext.Console.Write("Subscribe response is null."); return null; } else { byte[] responseBytes = subscribeResponse.Body as byte[]; // It is ok for the service to return a 202 and a 0 length response // if thi is the case just return null if(responseBytes == null || responseBytes.Length == 0) return null; System.Ext.Console.Write(""); System.Ext.Console.Write("Response From: " + subscriptionRequest.EndpointAddress.Host); System.Ext.Console.Write(responseBytes); try { response = ProcessSubscribeResponse(responseBytes, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Subscription response parsing failed."); System.Ext.Console.Write(e.Message); } } return response; } }
/// <summary> /// Use to unsubscribe from a devices event source. /// </summary> /// <param name="endpointAddress"> /// A Uri containing the endpoint address of the service or subscription manager that is currently /// maintaining this event subscription on behalf of the device. This address is an http uri /// (i.e. http://ip_address:port/serviceID). /// </param> /// <param name="subscription">An event subscription returned from a previous subscribe call. /// The subscription contains among other things a subscription ID used by the subscription manager /// to identify a specific event source subscription and the endpoint address of the subscription manager. /// </param> /// <returns>True if the Unsubscribe request was successful.</returns> public bool Unsubscribe(Uri endpointAddress, DpwsEventSubscription subscription) { // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Unsubscribe Request using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create()) { WsXmlNodeList nodeList = new WsXmlNodeList(); nodeList.Add(new WsXmlNode(null, "identifier", WsWellKnownUri.WseNamespaceUri, subscription.SubscriptionID)); WsWsaHeader header = new WsWsaHeader( m_version.EventingNamespace + "/Unsubscribe", // Action null, // RelatesTo endpointAddress.AbsoluteUri, // To m_version.AddressingNamespace, // ReplyTo subscription.SubscriptionManager.Address.AbsoluteUri, // From nodeList); // Identifier WsMessage msg = new WsMessage(header, null, WsPrefix.Wse, null, null); WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version); String messageID = smw.WriteSoapMessageStart(xmlWriter, msg); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Unsubscribe", null); xmlWriter.WriteString(""); xmlWriter.WriteEndElement(); // End Unsubscribe // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); smw.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Unsubscribe Message Build Took"); // Create an Http client and send Unsubscribe request WsHttpClient httpClient = new WsHttpClient(m_version); msg.Body = xmlWriter.ToArray(); WsMessage unsubscribeResponse = httpClient.SendRequest(msg, endpointAddress); // If a unsubscribe response is received simple validate that the messageID and action are correct and // If a parsing fault is received print exception and go on. if (unsubscribeResponse == null) { System.Ext.Console.Write(""); System.Ext.Console.Write("Unsubscribe response is null."); return false; } else { System.Ext.Console.Write(""); System.Ext.Console.Write("Response From: " + endpointAddress.Host); System.Ext.Console.Write(unsubscribeResponse.Body as byte[]); try { return ProcessUnsubscribeResponse((byte[])unsubscribeResponse.Body, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Unsubscribe response parsing failed."); System.Ext.Console.Write(e.Message); return false; } } } }
/// <summary> /// Use to unsubscribe from a devices event source. /// </summary> /// <param name="endpointAddress"> /// A Uri containing the endpoint address of the service or subscription manager that is currently /// maintaining this event subscription on behalf of the device. This address is an http uri /// (i.e. http://ip_address:port/serviceID). /// </param> /// <param name="subscription">An event subscription returned from a previous subscribe call. /// The subscription contains among other things a subscription ID used by the subscription manager /// to identify a specific event source subscription and the endpoint address of the subscription manager. /// </param> /// <returns>True if the Unsubscribe request was successful.</returns> public bool Unsubscribe(Uri endpointAddress, DpwsEventSubscription subscription) { // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Unsubscribe Request MemoryStream soapStream = new MemoryStream(); XmlWriter xmlWriter = XmlWriter.Create(soapStream); WsXmlNodeList nodeList = new WsXmlNodeList(); nodeList.Add(new WsXmlNode(null, "identifier", WsWellKnownUri.WseNamespaceUri, subscription.SubscriptionID)); WsWsaHeader header = new WsWsaHeader( WsWellKnownUri.WseNamespaceUri + "/Unsubscribe", // Action null, // RelatesTo endpointAddress.AbsoluteUri, // To WsWellKnownUri.WsaAnonymousUri, // ReplyTo subscription.SubscriptionManager.Address.AbsoluteUri, // From nodeList); // Identifier String messageID = WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter, WsSoapMessageWriter.Prefixes.Wse, null, header, null); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement("wse", "Unsubscribe", null); xmlWriter.WriteString(""); xmlWriter.WriteEndElement(); // End Unsubscribe // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Unsubscribe Message Build Took"); // Flush and close writer xmlWriter.Flush(); xmlWriter.Close(); // Create an Http client and send Unsubscribe request WsHttpClient httpClient = new WsHttpClient(); byte[] unsubscribeResponse = null; try { unsubscribeResponse = httpClient.SendRequest(soapStream.ToArray(), endpointAddress.ToString(), false, false); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Unsubscribe failed. " + e.Message); return false; } // If a unsubscribe response is received simple validate that the messageID and action are correct and // If a parsing fault is received print exception and go on. if (unsubscribeResponse == null) { System.Ext.Console.Write(""); System.Ext.Console.Write("Unsubscribe response is null."); return false; } else { System.Ext.Console.Write(""); System.Ext.Console.Write("Response From: " + endpointAddress.Host); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(unsubscribeResponse))); try { return ProcessUnsubscribeResponse(unsubscribeResponse, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Unsubscribe response parsing failed."); System.Ext.Console.Write(e.Message); return false; } } }
/// <summary> /// Use to get the status of an event subscription. /// </summary> /// <param name="endpointAddress"> /// A Uri containing the endpoint address of the service or subscription manager that is currently /// maintaining this event subscription on behalf of the device. This address is an http uri /// (i.e. http://ip_address:port/serviceID). /// </param> /// <param name="subscriptionID"> /// A subscription ID returned from a previous subscribe response. The device uses this ID /// to identify a specific event source subscription. /// </param> /// <returns> /// A WsDuration object containing the remaining subscription time for this event subscription, null = infinite. /// </returns> public WsDuration GetStatus(Uri endpointAddress, string subscriptionID) { // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Renew request MemoryStream soapStream = new MemoryStream(); XmlWriter xmlWriter = XmlWriter.Create(soapStream); WsXmlNodeList nodeList = new WsXmlNodeList(); nodeList.Add(new WsXmlNode("wse", "Identifier", null, subscriptionID)); WsWsaHeader header = new WsWsaHeader( WsWellKnownUri.WseNamespaceUri + "/GetStatus", // Action null, // RelatesTo endpointAddress.AbsoluteUri, // To null, null, nodeList); // ReplyTo, From, Any String messageID = WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter, WsSoapMessageWriter.Prefixes.Wse, null, header, null); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement("soap", "Body", null); xmlWriter.WriteStartElement("wse", "GetStatus", null); xmlWriter.WriteString(""); xmlWriter.WriteEndElement(); // End GetStatus // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Renew Message Build Took"); // Flush and close writer xmlWriter.Flush(); xmlWriter.Close(); // Create an Http client and send GetStatus request WsHttpClient httpClient = new WsHttpClient(); byte[] getStatusResponse = null; try { getStatusResponse = httpClient.SendRequest(soapStream.ToArray(), endpointAddress.ToString(), false, false); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("GetStatus failed. " + e.Message); return null; } // If a GetStatus response is received validate the messageID and action and get the remaining // event subscription time. If a fault is received print exception and go on. if (getStatusResponse == null) { System.Ext.Console.Write(""); System.Ext.Console.Write("Renew response is null."); return null; } else { System.Ext.Console.Write(""); System.Ext.Console.Write("Response From: " + endpointAddress.Host); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(getStatusResponse))); // Note: Since the response is the same for GetStatus ans it is for Renew reuse the // Renew response parser. try { return ProcessRenewResponse(getStatusResponse, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Unsubscribe response parsing failed."); System.Ext.Console.Write(e.Message); } } return null; }
/// <summary> /// Use to request metadata from a devices hosted service endpoint. /// </summary> /// <param name="serviceAddress"> /// A string containing the transport address of a service endpoint. For Dpws the address represents /// a devices transport address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <returns> /// A collection of DpwsMetadata objects containing endpoint details about services hosted by a device. /// </returns> public DpwsMetadata Get(string serviceAddress) { // Convert the address string to a Uri Uri serviceUri = null; try { serviceUri = new Uri(serviceAddress); if (serviceUri.Scheme != "http") { System.Ext.Console.Write(""); System.Ext.Console.Write("Invalid serviceAddress. Must be a Uri. Http Uri schemes only."); System.Ext.Console.Write(""); return null; } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); return null; } // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Get Request MemoryStream soapStream = new MemoryStream(); XmlWriter xmlWriter = XmlWriter.Create(soapStream); WsWsaHeader header = new WsWsaHeader( WsWellKnownUri.WstNamespaceUri + "/Get", // Action null, // RelatesTo "urn:uuid:" + serviceUri.AbsolutePath.Substring(1), // To WsWellKnownUri.WsaAnonymousUri, // ReplyTo null, null); // From, Any String messageID = WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter, WsSoapMessageWriter.Prefixes.None, null, header, null); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Get Message Build Took"); // Flush and close writer xmlWriter.Flush(); xmlWriter.Close(); // Create an Http client and send Get request WsHttpClient httpClient = new WsHttpClient(); byte[] getResponse = null; try { System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Get to: " + serviceAddress); getResponse = httpClient.SendRequest(soapStream.ToArray(), serviceAddress, false, false); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Get failed. " + e.Message); return null; } // If a get response is received process it and return DpwsMetadata object DpwsMetadata metadata = null; if (getResponse == null) return null; else { System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(getResponse))); System.Ext.Console.Write(""); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); try { metadata = soapProcessor.ProcessGetResponse(getResponse, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Get response parser threw an exception. " + e.Message); return null; } } return metadata; }
/// <summary> /// Use to subscribe to a devices, hosted service event sources. /// </summary> /// <param name="subscriptionRequest"> /// A DpwsSubscriptionRequest object containing the address of the service hosting the desired event, /// the address where the event is sent, an optional address where subscription end messages are sent, /// A subscription expiration (in duration format) and an optional user defined identifier. /// </param> /// <returns> /// A DpwsEventSubscription containing the the subscription managers address, the time when the subscription /// expires (duration) and optional reference parameters and properties. Per spec the /// sub mananger may assign a different duration value than that specified in the request. /// </returns> /// <exception cref="ArgumentNullException">If required subscription parameters are not set.</exception> public DpwsEventSubscription Subscribe(DpwsSubscribeRequest subscriptionRequest) { if (subscriptionRequest.SubscriptionType == null) throw new ArgumentNullException("Subscribe - SubscriptionType must not be null"); if (subscriptionRequest.SubscriptionType.TypeName == null) throw new ArgumentNullException("Subscribe - SubscriptionType.TypeName must not be null"); if (subscriptionRequest.SubscriptionType.NamespaceUri == null) throw new ArgumentNullException("Subscribe - SubscriptionType.NamespaceUri must not be null"); if (subscriptionRequest.EndpointAddress == null) throw new ArgumentNullException("Subscribe - EndpointAddress property must not be null."); if (subscriptionRequest.NotifyTo == null) throw new ArgumentNullException("Subscribe - NotifyTo must not be null."); if (subscriptionRequest.NotifyTo.Address == null) throw new ArgumentNullException("Subscribe - NotifyTo.Address must not be null."); // Convert the address string to a Uri Uri serviceUri = null; try { serviceUri = subscriptionRequest.EndpointAddress; if (serviceUri.Scheme != "http") { System.Ext.Console.Write(""); System.Ext.Console.Write("Invalid endpoint address. Must be a Uri. Http Uri schemes only."); System.Ext.Console.Write(""); return null; } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); return null; } // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Subscribe Request MemoryStream soapStream = new MemoryStream(); XmlWriter xmlWriter = XmlWriter.Create(soapStream); WsWsaHeader header = new WsWsaHeader( WsWellKnownUri.WseNamespaceUri + "/Subscribe", // Action null, // RelatesTo serviceUri.AbsoluteUri, // To WsWellKnownUri.WsaAnonymousUri, // ReplyTo null, null); // From, Any WsXmlNamespaces additionalPrefixes = new WsXmlNamespaces(); additionalPrefixes.Add(new WsXmlNamespace("myPrefix", subscriptionRequest.SubscriptionType.NamespaceUri)); String messageID = WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter, WsSoapMessageWriter.Prefixes.Wsd | WsSoapMessageWriter.Prefixes.Wse, additionalPrefixes, header, null); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement("wse", "Subscribe", null); // If EndTo is set write it if (subscriptionRequest.EndTo != null) WriteEndpointRef(ref xmlWriter, subscriptionRequest.EndTo, "EndTo"); // Add the delivery element and NotifyTo endpoint xmlWriter.WriteStartElement("wse", "Delivery", null); xmlWriter.WriteAttributeString("Mode", "http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/Push"); // Writer the notify to endpoint WriteEndpointRef(ref xmlWriter, subscriptionRequest.NotifyTo, "NotifyTo"); xmlWriter.WriteEndElement(); // End Delivery // Write Expiration time if (subscriptionRequest.Expires != null) { xmlWriter.WriteStartElement("wse", "Expires", null); xmlWriter.WriteString(subscriptionRequest.Expires.DurationString); xmlWriter.WriteEndElement(); // End Expires } // Write Filter element specifying the event to subscribe to. xmlWriter.WriteStartElement("wse", "Filter", null); xmlWriter.WriteAttributeString("Dialect", "http://schemas.xmlsoap.org/ws/2006/02/devprof/Action"); xmlWriter.WriteString(subscriptionRequest.SubscriptionType.NamespaceUri + "/" + subscriptionRequest.SubscriptionType.TypeName); xmlWriter.WriteEndElement(); // End Filter xmlWriter.WriteEndElement(); // End Subscribe WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Subscribe Message Build Took"); // Flush and close writer xmlWriter.Flush(); xmlWriter.Close(); // Create an Http client and send Subscribe request WsHttpClient httpClient = new WsHttpClient(); byte[] subscribeResponse = null; try { subscribeResponse = httpClient.SendRequest(soapStream.ToArray(), subscriptionRequest.EndpointAddress.AbsoluteUri, false, false); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Subscribe failed. " + e.Message); return null; } // If a subscribe response is received process it and return expiration time the subscription manager // actually assigned. // If a parsing fault is received print exception and go on. DpwsEventSubscription response = null; if (subscribeResponse == null) { System.Ext.Console.Write(""); System.Ext.Console.Write("Subscribe response is null."); return null; } else { System.Ext.Console.Write(""); System.Ext.Console.Write("Response From: " + subscriptionRequest.EndpointAddress.Host); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(subscribeResponse))); try { // It is ok for the service to return a 202 and a 0 length response // if thi is the case just return null if (subscribeResponse.Length == 0) return null; response = ProcessSubscribeResponse(subscribeResponse, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Subscription response parsing failed."); System.Ext.Console.Write(e.Message); } } return response; }
public virtual WsMessage ProbeMatch(WsMessage probe, DpwsHostedService matchedService) { XmlReader reader = probe.Reader; WsWsaHeader header = probe.Header; // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build ProbeMatch using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create()) { // If a Host exist write the Host namespace WsXmlNamespaces additionalPrefixes = null; if (Device.Host != null) { additionalPrefixes = new WsXmlNamespaces(); additionalPrefixes.Add(Device.Host.ServiceNamespace); } WsWsaHeader matchHeader = new WsWsaHeader( this.Version.DiscoveryNamespace + "/ProbeMatches", // Action header.MessageID, // RelatesTo this.Version.AnonymousUri, // To null, null, null); // ReplyTo, From, Any WsMessage msg = new WsMessage(matchHeader, null, WsPrefix.Wsd | WsPrefix.Wsdp, additionalPrefixes, new WsAppSequence(Device.AppSequence, Device.SequenceID, Device.MessageID)); WsSoapMessageWriter smw = new WsSoapMessageWriter(this.Version); smw.WriteSoapMessageStart(xmlWriter, msg); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "ProbeMatches", null); xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "ProbeMatch", null); xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "EndpointReference", null); xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null); xmlWriter.WriteString(matchedService == null ? Device.EndpointAddress : matchedService.EndpointAddress); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); // Write hosted service types xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "Types", null); WriteDeviceServiceTypes(xmlWriter); xmlWriter.WriteEndElement(); // End Types xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "XAddrs", null); string transport = Device.TransportAddress; if(matchedService != null) { int idx = transport.LastIndexOf('/'); if(idx != -1) { transport = transport.Substring(0, idx + 1); transport += matchedService.EndpointAddress.Substring(matchedService.EndpointAddress.IndexOf("urn:uuid:") + 9); } } int idx2 = transport.ToLower().IndexOf("localhost"); if(idx2 != -1) { transport = transport.Substring(0, idx2) + WsNetworkServices.GetLocalIPV4Address() + transport.Substring(idx2 + 9 /*localhost*/); } xmlWriter.WriteString(transport); xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "MetadataVersion", null); xmlWriter.WriteString(Device.MetadataVersion.ToString()); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); smw.WriteSoapMessageEnd(xmlWriter); msg.Body = xmlWriter.ToArray(); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***ProbeMatch Took"); // Delay probe match as per Ws-Discovery specification (2.4 Protocol Assignments) Thread.Sleep(new Random().Next(Device.ProbeMatchDelay)); // Return stream buffer return msg; } }
/// <summary> /// Use to request metadata from a devices hosted service endpoint. /// </summary> /// <param name="serviceAddress"> /// A string containing the transport address of a service endpoint. For Dpws the address represents /// a devices transport address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <returns> /// A collection of DpwsMetadata objects containing endpoint details about services hosted by a device. /// </returns> public DpwsMetadata Get(string serviceAddress) { // Convert the address string to a Uri Uri serviceUri = null; try { serviceUri = new Uri(serviceAddress); if (serviceUri.Scheme != "http") { System.Ext.Console.Write(""); System.Ext.Console.Write("Invalid serviceAddress. Must be a Uri. Http Uri schemes only."); System.Ext.Console.Write(""); return null; } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); return null; } // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Get Request using(XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create()) { WsWsaHeader header = new WsWsaHeader( WsWellKnownUri.WstNamespaceUri + "/Get", // Action null, // RelatesTo "urn:uuid:" + serviceUri.AbsolutePath.Substring(1), // To //TODO: should be ROLE??? m_version.AnonymousRoleUri, // ReplyTo null, null); // From, Any WsMessage msg = new WsMessage(header, null, WsPrefix.None, null, null); WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version); String messageID = smw.WriteSoapMessageStart(xmlWriter, msg); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); smw.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Get Message Build Took"); // Create an Http client and send Get request WsHttpClient httpClient = new WsHttpClient(m_version); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Get to: " + serviceAddress); msg.Body = xmlWriter.ToArray(); WsMessage getResponse = httpClient.SendRequest(msg, new Uri(serviceAddress)); // If a get response is received process it and return DpwsMetadata object DpwsMetadata metadata = null; if (getResponse == null || getResponse.Body == null) { return null; } else { DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(m_version); try { System.Ext.Console.Write(getResponse.Body as byte[]); System.Ext.Console.Write(""); metadata = soapProcessor.ProcessGetResponse((byte[])getResponse.Body, messageID); } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write("Get response parser threw an exception. " + e.Message); return null; } } return metadata; } }
/// <summary> /// This method is called by the process manager to process a request. /// </summary> public void ProcessRequest() { // Performance debuging DebugTiming timeDebuger = new DebugTiming(); timeDebuger.ResetStartTime("***Request Debug timer started"); // Process the message byte[] soapResponse = ProcessRequestMessage(); // If response is null the requested service is not implemented so just ignore this request if (soapResponse == null) return; // Performance debuging timeDebuger.PrintElapsedTime("***ProcessMessage Took"); // Send the response WsUdpServiceHost.SendMessage(m_remoteEP, soapResponse); // Performance Debuging timeDebuger.PrintElapsedTime("***Send Message Took"); System.Ext.Console.Write("Response To: " + m_remoteEP.ToString()); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(soapResponse))); return; }
/// <summary> /// Builds a probe request message based on the filters parameter. /// </summary> /// <param name="serviceAddress"> /// A string containing the target service address. /// For example: urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="filters"> /// A DpwsServiceTypes object containing a collection of types a service must support to signal a match. /// Null = any type. /// </param> /// <param name="messageID"> /// A string used to return the messageID assigned to this message. /// </param> /// <returns>A byte array containing the probe message or null if an error occures.</returns> private byte[] BuildProbeRequest(string serviceAddress, DpwsServiceTypes filters, out String messageID) { // Performance debugging DebugTiming timeDebuger = new DebugTiming(); long startTime = timeDebuger.ResetStartTime(""); // Build Probe request MemoryStream soapStream = new MemoryStream(); XmlWriter xmlWriter = XmlWriter.Create(soapStream); WsWsaHeader header = new WsWsaHeader( WsWellKnownUri.WsdNamespaceUri + "/Probe", // Action null, // RelatesTo serviceAddress, // To null, null, null); // ReplyTo, From, Any // If filters are supplied, write filter namespaces if prefixed. Build filter list for use later, // include wsdp:device. WsXmlNamespaces namespaces = new WsXmlNamespaces(); // Prefix hack for now: int i = 0; string prefix; string filterList = ""; bool spaceFlag = false; if (filters != null) { int count = filters.Count; for (int j = 0; j < count; j++) { DpwsServiceType serviceType = filters[j]; prefix = namespaces.LookupPrefix(serviceType.NamespaceUri); if (prefix == null) { prefix = "MyPrefix" + (i++); namespaces.Add(new WsXmlNamespace(prefix, serviceType.NamespaceUri)); } filterList = filterList + ((spaceFlag == true) ? " " : "") + prefix + ":" + serviceType.TypeName; spaceFlag = true; } } messageID = WsSoapMessageWriter.WriteSoapMessageStart(xmlWriter, WsSoapMessageWriter.Prefixes.Wsd, namespaces, header, null); // Performance debuging timeDebuger.PrintElapsedTime("*****Write Header Took"); // write body xmlWriter.WriteStartElement("wsd", "Probe", null); // If filter is supplied add filter types tag else write blank string to probe body, force an empty tag if (filterList.Length != 0) { xmlWriter.WriteStartElement("wsd", "Types", null); xmlWriter.WriteString(filterList); xmlWriter.WriteEndElement(); // End Filter } else xmlWriter.WriteString(""); xmlWriter.WriteEndElement(); // End Probe // Performance debuging timeDebuger.PrintElapsedTime("*****Write Body Took"); WsSoapMessageWriter.WriteSoapMessageEnd(xmlWriter); // Performance debuging timeDebuger.PrintTotalTime(startTime, "***Probe Message Build Took"); // Flush and close writer xmlWriter.Flush(); xmlWriter.Close(); // return the probe message return soapStream.ToArray(); }
/// <summary> /// Method prototype that defines a transports message processing method. /// </summary> public void ProcessRequest() { RequestContext request; Interlocked.Increment(ref s_threadCnt); while(true) { if (s_exit || (s_requests.Count == 0 && !s_requestEvent.WaitOne(1000, false))) break; lock (s_requests) { if (s_requests.Count == 0) { continue; } request = (RequestContext)s_requests.Dequeue(); } if(request.Message != null) { // Performance debuging DebugTiming timeDebuger = new DebugTiming(); timeDebuger.ResetStartTime("***Request Debug timer started"); // Process the message WsMessage response = ProcessRequestMessage(request); // If response is null the requested service is not implemented so just ignore this request if (response != null) { // Performance debuging timeDebuger.PrintElapsedTime("***ProcessMessage Took"); // Send the response request.Reply(response); // Performance Debuging timeDebuger.PrintElapsedTime("***Send Message Took"); } } } Interlocked.Decrement(ref s_threadCnt); }