/// <summary> /// Method used to send a soap request over http to a service endpoint. /// </summary> /// <param name="soapMessage">A byte array contining a soap request message.</param> /// <param name="endpointAddress">A string containing the endpoint address of a service that will receive /// the request. This must be a transport address in the format http://ip_address:port/service_address.</param> /// <param name="isOneway">True = don't wait for response, false means wait for a response.</param> /// <param name="isChuncked">If true true the message will be chunk encoded.</param> /// <returns> /// A DpwSoapResponse object containing a WsWsaHeader and a XmlReader or null if no response is received /// or parsing fails. /// </returns> public DpwsSoapResponse SendRequest(byte[] soapMessage, string endpointAddress, bool isOneway, bool isChuncked) { System.Ext.Console.Write(new string(System.Text.UTF8Encoding.UTF8.GetChars(soapMessage))); WsMessage response = SendRequest(soapMessage, endpointAddress, isOneway, isChuncked, null); if (isOneway) { return(null); } XmlReader reader; WsWsaHeader header; try { reader = WsSoapMessageParser.ParseSoapMessage(response.Message, out header); } catch { System.Ext.Console.Write("ParseSoapMessage failed."); return(null); } return(new DpwsSoapResponse(header, reader)); }
/// <summary> /// Parses a Udp transport message and builds a header object and envelope document then calls processRequest /// on a service endpoint contained. /// </summary> /// <param name="soapRequest">A byte array containing a raw soap request message. If null no check is performed.</param> /// <param name="messageCheck">A WsMessageCheck objct used to test for duplicate request.</param> /// <param name="remoteEP">The remote endpoint address of the requestor.</param> /// <returns>A byte array containing a soap response message returned from a service endpoint.</returns> public byte[] ProcessRequestMessage() { Debug.Assert(m_messageCheck != null && m_remoteEP != null); // Parse and validate the soap message WsWsaHeader header; XmlReader reader; try { reader = WsSoapMessageParser.ParseSoapMessage(m_soapMessage, out header); } catch { return(null); } try { if (m_messageCheck.IsDuplicate(header.MessageID, m_remoteEP.ToString()) == true) { System.Ext.Console.Write("Duplicate \"" + header.Action + "\" request received"); System.Ext.Console.Write("Request Ignored."); return(null); } // Check Udp service endpoints collection for a target service. IWsServiceEndpoint serviceEndpoint = m_serviceEndpoints[header.To]; if (serviceEndpoint != null && serviceEndpoint.ServiceOperations[header.Action] != null) { // Don't block discovery processes. serviceEndpoint.BlockingCall = false; try { return(serviceEndpoint.ProcessRequest(header, reader)); } catch { return(null); } } // Return null if service endpoint was not found System.Ext.Console.Write("Udp service endpoint was not found."); System.Ext.Console.Write(" Endpoint Address: " + header.To); System.Ext.Console.Write(" Action: " + header.Action); return(null); } finally { reader.Close(); } }
/// <summary> /// Parses a GetResponse message. /// </summary> /// <param name="soapResponse">A byte array containing a response message.</param> /// <param name="messageID">The message ID sent in the original request.</param> /// <returns> /// A DpwsMetadata object containing a details about a service endpoint. /// </returns> internal DpwsMetadata ProcessGetResponse(byte[] soapResponse, string messageID) { // Parse and build header WsWsaHeader header = new WsWsaHeader(); XmlReader reader; try { reader = WsSoapMessageParser.ParseSoapMessage(soapResponse, ref header, m_version); } catch { return(null); } try { // Make sure this is a get response if (header.Action != WsWellKnownUri.WstNamespaceUri + "/GetResponse") { return(null); } // Make sure the messageID matches the request ID if (header.RelatesTo != messageID) { return(null); } #if DEBUG int depth = reader.Depth; #endif DpwsMetadata metaData = new DpwsMetadata(reader, m_version); #if DEBUG Microsoft.SPOT.Debug.Assert(XmlReaderHelper.HasReadCompleteNode(depth, reader)); #endif return(metaData); } finally { reader.Close(); } }
/// <summary> /// Send an Http request to an endpoint and waits for a response. /// </summary> /// <param name="soapMessage">A byte array containing the soap message to be sent.</param> /// <param name="remoteEndpoint">A sting containing the name of a remote listening endpoint.</param> /// <returns> /// A WsMessage containing a soap response to the request. This array will be null for OneWay request. /// </returns> public WsMessage SendRequest(WsMessage request, Uri remoteEndpoint) { WsMessage response = new WsMessage(new WsWsaHeader(), null, WsPrefix.None); HttpTransportBindingElement httpClient = new HttpTransportBindingElement(new HttpTransportBindingConfig(remoteEndpoint)); ClientBindingContext ctx = new ClientBindingContext(m_version); ctx.ReceiveTimeout = new TimeSpan(0, 0, 0, 0, ReceiveTimeout); ctx.OpenTimeout = new TimeSpan(0, 0, 0, 0, RequestTimeout); ctx.SendTimeout = new TimeSpan(0, 0, 0, 0, SendTimeout); httpClient.EndpointAddress = remoteEndpoint; Stream stream = null; try { httpClient.Open(ref stream, ctx); httpClient.ProcessOutputMessage(ref request, ctx); ctx.BindingProperties.Clear(); httpClient.ProcessInputMessage(ref response, ctx); ctx.BindingProperties.Clear(); if (response.Body is byte[]) { response.Reader = WsSoapMessageParser.ParseSoapMessage((byte[])response.Body, ref response.Header, m_version); } } finally { httpClient.Close(stream, ctx); } return(response); }
private XmlReader ProcessResponse(byte[] response, String messageID, String action) { WsWsaHeader header = new WsWsaHeader(); XmlReader reader = WsSoapMessageParser.ParseSoapMessage(response, ref header, m_version); if (header.Action == m_version.AddressingNamespace + "/fault") { WsFault.ParseFaultResponseAndThrow(reader); } else if (header.Action != m_version.EventingNamespace + "/" + action) { throw new XmlException(); } // Make sure this response matches the request if (header.RelatesTo != messageID) { throw new XmlException(); } return(reader); }
private XmlReader ProcessResponse(byte[] response, String messageID, String action) { WsWsaHeader header; XmlReader reader; reader = WsSoapMessageParser.ParseSoapMessage(response, out header); try { if ( (header.Action == WsWellKnownUri.WsaNamespaceUri_2004_08 + "/fault") || (header.Action == WsWellKnownUri.WsaNamespaceUri_2005_08 + "/fault") ) { WsFault.ParseFaultResponseAndThrow(reader); } else if (header.Action != WsWellKnownUri.WseNamespaceUri + "/" + action) { throw new XmlException(); } // Make sure this response matches the request if (header.RelatesTo != messageID) { throw new XmlException("Invalid message ID in response. Id does not match request ID."); } return(reader); } catch { // if something's wrong, close the reader, and rethrow the exception reader.Close(); throw; } }
/// <summary> /// Send an Http request containing an mtom message to an endpoint and waits for a response. /// </summary> /// <param name="bodyParts">A reference to the WsMtomBodyParts collection used to generate a mime multipart message.</param> /// <param name="endpointAddress">A string containing the endpoint address of a service that will receive /// <param name="isOneway">True = don't wait for response, false means wait for a response.</param> /// <param name="isChuncked">If true true the message will be chunk encoded.</param> /// <returns> /// A DpwSoapResponse object containing a WsWsaHeader and an XmlReader or null if no response is received /// or parsing fails. /// </returns> public DpwsSoapResponse SendRequest(ref WsMtomBodyParts bodyParts, string endpointAddress, bool isOneWay, bool isChuncked) { WsMtomParams mtomParams = new WsMtomParams(); if (bodyParts.Boundary == null) { bodyParts.Boundary = Guid.NewGuid().ToString() + '-' + Guid.NewGuid().ToString().Substring(0, 33); } mtomParams.start = bodyParts.Start; mtomParams.boundary = bodyParts.Boundary; WsMtom mtom = new WsMtom(); byte[] message = mtom.CreateMessage(bodyParts); WsMessage response = SendRequest(message, endpointAddress, isOneWay, isChuncked, mtomParams); if (isOneWay) { return(null); } XmlReader reader; WsWsaHeader header; try { reader = WsSoapMessageParser.ParseSoapMessage(response.Message, out header); bodyParts = response.BodyParts; } catch { System.Ext.Console.Write("ParseSoapMessage failed."); return(null); } return(new DpwsSoapResponse(header, reader)); }
/// <summary> /// Use to send a resolve request to the ws-discovery address and receive a resolve match. /// </summary> /// <param name="message">A byte array containing a the resolve message.</param> /// <param name="messageID"> /// A string containing the message ID of a resolve request. This ID will be used to validate against /// a ResolveMatch received if it don't match, the ResolveMatch is discarded. /// </param> /// <param name="timeout"> /// A DateTime value containing the length of time this request will wait for resolve match. /// until the timeout value has expired. /// </param> /// <returns>A resolve match object.</returns> private DpwsServiceDescription SendResolveRequest(byte[] message, string messageID, long timeout) { WsMessageCheck messageCheck = new WsMessageCheck(); DpwsServiceDescription resolveMatch = null; System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Resolve:"); System.Ext.Console.Write(message); // Create a new UdpClient using (Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { uint ipLocal = WsNetworkServices.GetLocalIPV4AddressValue(); IPAddress localIP = IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()); IPEndPoint localEP = new IPEndPoint(localIP, 0); // Very important - Set default multicast interface for the underlying socket udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)ipLocal); udpClient.ReceiveTimeout = (int)timeout; udpClient.Bind(localEP); // Random back off implemented as per soap over udp specification // for unreliable multicast message exchange Thread th = SendWithBackoff(message, udpClient); // Wait for resolve match as long a timeout has not expired byte[] resolveResponse = new byte[c_MaxUdpPacketSize]; EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int responseLength; DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(m_version); while (true) { // Since MF sockets does not have an IOControl method catch 10054 to get around the problem // with Upd and ICMP. try { // Wait for response responseLength = udpClient.ReceiveFrom(resolveResponse, c_MaxUdpPacketSize, SocketFlags.None, ref remoteEP); } catch (SocketException se) { if ((SocketError)se.ErrorCode == SocketError.ConnectionReset) { Thread.Sleep(100); continue; } if ((SocketError)se.ErrorCode == SocketError.TimedOut) { break; } throw se; } // If we received process resolve match if (responseLength > 0) { System.Ext.Console.Write("ResolveMatches Response From: " + ((IPEndPoint)remoteEP).Address.ToString()); System.Ext.Console.Write(resolveResponse); try { WsWsaHeader header = new WsWsaHeader(); XmlReader reader = WsSoapMessageParser.ParseSoapMessage(resolveResponse, ref header, m_version); WsMessage msg = new WsMessage(header, null, WsPrefix.Wsdp); msg.Reader = reader; resolveMatch = soapProcessor.ProcessResolveMatch(msg, messageID, (IPEndPoint)remoteEP, messageCheck); if (resolveMatch != null) { break; } } catch (Exception e) { System.Ext.Console.Write(e.Message); } } } th.Join(); } // Display results if (resolveMatch == null) { System.Ext.Console.Write("Resolve timed out."); } return(resolveMatch); }
/// <summary> /// Sends a Probe request and parses ProbeMatches responses. /// </summary> /// <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="maxProbeMatches"> /// An integer representing the maximum number of matches to reveive within the timout period. Pass 0 to receive /// as many matches as possible before the timeout expires. /// </param> /// <param name="timeout"> /// An integer specifying a request timeout in milliseconds. Pass -1 to wait ReceiveTimeout. /// </param> /// <remarks> /// A Probe is used to discover services on a network. The Probe method sends a UDP request to the /// Dpws multicast address, 239.255.255.250:3702. Any service that implements types specified in the /// filters parameter should respond with a ProbeMatches message. The ProbeMatches mesgage is unicast /// back to the that client that made the request. If a null filter is supplied any Dpws complient /// service should reply with a ProbeMatches reponse. Probe waits DpwsDiceoveryCleint.ReceiveTimout /// for probe matches. /// </remarks> /// <returns> /// A collection of ProbeMatches objects. A ProbeMatch object contains endpoint details used /// used to locate the actual service on a network and the types supported by the service. /// </returns> public DpwsServiceDescriptions Probe(DpwsServiceTypes filters, int maxProbeMatches, int timeout) { // Build the probe request message WsMessageCheck messageCheck = new WsMessageCheck(); string messageID = null; WsMessage probeRequest = BuildProbeRequest(DiscoVersion.DiscoveryWellKnownAddress, filters, out messageID); DpwsServiceDescriptions probeMatches = new DpwsServiceDescriptions(); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Probe:"); System.Ext.Console.Write(probeRequest.Body as byte[]); System.Ext.Console.Write(""); // Create a new UdpClient using (Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { // Very important - Set default multicast interface for the underlying socket uint ipLocal = WsNetworkServices.GetLocalIPV4AddressValue(); IPAddress localIP = IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()); IPEndPoint localEP = new IPEndPoint(localIP, 0); udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)ipLocal); udpClient.ReceiveTimeout = timeout; udpClient.Bind(localEP); // Random back off implemented as per soap over udp specification // for unreliable multicast message exchange Thread th = SendWithBackoff((byte[])probeRequest.Body, udpClient); // Create probe matches collection and set expiration loop timer byte[] probeResponse = new byte[c_MaxUdpPacketSize]; EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int responseLength; DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(m_version); while (true) { // Since MF sockets does not have an IOControl method catch 10054 to get around the problem // with Upd and ICMP. try { // Wait for response responseLength = udpClient.ReceiveFrom(probeResponse, c_MaxUdpPacketSize, SocketFlags.None, ref remoteEP); } catch (SocketException se) { if ((SocketError)se.ErrorCode == SocketError.ConnectionReset) { Thread.Sleep(100); continue; } // Timeout if ((SocketError)se.ErrorCode == SocketError.TimedOut) { break; } throw se; } // If we received process probe match if (responseLength > 0) { System.Ext.Console.Write(""); System.Ext.Console.Write("ProbeMatches Response From: " + ((IPEndPoint)remoteEP).Address.ToString()); System.Ext.Console.Write(probeResponse); // Process the response try { WsWsaHeader header = new WsWsaHeader(); XmlReader reader = WsSoapMessageParser.ParseSoapMessage(probeResponse, ref header, m_version); WsMessage msg = new WsMessage(header, null, WsPrefix.Wsdp); msg.Reader = reader; DpwsServiceDescriptions tempMatches = soapProcessor.ProcessProbeMatch(msg, messageID, (IPEndPoint)remoteEP, messageCheck); if (tempMatches != null) { int count = maxProbeMatches < tempMatches.Count ? maxProbeMatches : tempMatches.Count; for (int i = 0; i < count; i++) { probeMatches.Add(tempMatches[i]); } maxProbeMatches -= count; } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); } // If maxProbeRequest is set check count if (maxProbeMatches <= 0) { break; } } } th.Join(); } // Display results if (probeMatches.Count == 0) { System.Ext.Console.Write("Probe timed out."); } else { System.Ext.Console.Write("Received " + probeMatches.Count + " probeMatches matches."); } return(probeMatches); }
/// <summary> /// Parses a transport message and builds a header object and envelope document then calls processRequest /// on a service endpoint. /// </summary> /// <param name="soapRequest">WsRequestMessage object containing a raw soap message or mtom soap request.</param> /// <returns>WsResponseMessage object containing the soap response returned from a service endpoint.</returns> private WsMessage ProcessRequestMessage(WsMessage soapRequest) { // Parse and validate the soap message WsWsaHeader header; XmlReader reader; try { reader = WsSoapMessageParser.ParseSoapMessage(soapRequest.Message, out header); } catch (WsFaultException e) { return(WsFault.GenerateFaultResponse(e)); } try { // Now check for implementation specific service endpoints. IWsServiceEndpoint serviceEndpoint = null; string endpointAddress = null; // If this is Uri convert it if (header.To.IndexOf("urn") == 0 || header.To.IndexOf("http") == 0) { // Convert to address to Uri Uri toUri; try { toUri = new Uri(header.To); } catch { System.Ext.Console.Write("Unsupported Header.To Uri format: " + header.To); return(WsFault.GenerateFaultResponse(header, WsFaultType.ArgumentException, "Unsupported Header.To Uri format")); } // Convert the to address to a Urn:uuid if it is an Http endpoint if (toUri.Scheme == "urn") { endpointAddress = toUri.AbsoluteUri; } else if (toUri.Scheme == "http") { endpointAddress = "urn:uuid:" + toUri.AbsoluteUri.Substring(1); } else { endpointAddress = header.To; } } else { endpointAddress = "urn:uuid:" + header.To; } // Look for a service at the requested endpoint that contains an operation matching the Action // This hack is required because service spec writers determined that more than one service type // can live at a single endpoint address. Why you would want to break the object model and allow // this feature is unknown so for now we must hack. bool eventingReqFlag = true; for (int i = 0; i < m_serviceEndpoints.Count; ++i) { if (m_serviceEndpoints[i].EndpointAddress == endpointAddress) { if (m_serviceEndpoints[i].ServiceOperations[header.Action] != null) { serviceEndpoint = m_serviceEndpoints[i]; eventingReqFlag = false; break; } } } // Worst part of the hack: If no matching endpoint is found assume this is an event subscription // request and call the base eventing methods on any class. They had to be Global because of this feature. // Now the subscription manager must determine globally that a suitable web service is found. Yuch!! if (eventingReqFlag) { serviceEndpoint = m_serviceEndpoints[0]; } // If a matching service endpoint is found call operation if (serviceEndpoint != null) { // If this is mtom, copy the requests body parts to the hosted services body parts // prior to making the call if (soapRequest.MessageType == WsMessageType.Mtom) { serviceEndpoint.BodyParts = soapRequest.BodyParts; } // Process the request byte[] response; try { response = serviceEndpoint.ProcessRequest(header, reader); } catch (WsFaultException e) { return(WsFault.GenerateFaultResponse(e)); } catch (Exception e) { return(WsFault.GenerateFaultResponse(header, WsFaultType.Exception, e.ToString())); } // If the message response type is Soap return a SoapMessage type if (serviceEndpoint.MessageType == WsMessageType.Soap) { if (response == null) { return(null); } return(new WsMessage(response)); } // If the response is Mtom build an mtom response message else // if (serviceEndpoint.MessageType == WsMessageType.Mtom) { return(new WsMessage(serviceEndpoint.BodyParts)); } } // Unreachable endpoint requested. Generate fault response return(WsFault.GenerateFaultResponse(header, WsFaultType.WsaDestinationUnreachable, "Unknown service endpoint")); } finally { reader.Close(); } }
private DpwsServiceDescriptions ProcessMatch(DpwsServiceDescription.ServiceDescriptionType type, byte[] response, string messageID, IPEndPoint remoteEP, WsMessageCheck messageCheck) { Microsoft.SPOT.Debug.Assert(type == DpwsServiceDescription.ServiceDescriptionType.ProbeMatch || type == DpwsServiceDescription.ServiceDescriptionType.ResolveMatch); // Parse and build header WsWsaHeader header; XmlReader reader; try { reader = WsSoapMessageParser.ParseSoapMessage(response, out header); } catch { return(null); } try { // Make sure this is a probe matches response String headerAction = (type == DpwsServiceDescription.ServiceDescriptionType.ProbeMatch) ? WsWellKnownUri.WsdNamespaceUri + "/ProbeMatches" : WsWellKnownUri.WsdNamespaceUri + "/ResolveMatches"; if (header.Action != headerAction) { return(null); } // Make sure this is not a duplicate probe response if (messageCheck != null) { if (messageCheck.IsDuplicate(header.MessageID, remoteEP.ToString()) == true) { System.Ext.Console.Write("ProbeMatches / ResolveMatches - Duplicate response - " + header.Action + " received"); return(null); } } // Make sure the messageID matches the request ID if (header.RelatesTo != messageID) { return(null); } // Process the probe matches #if DEBUG int depth = reader.Depth; #endif DpwsServiceDescriptions matches = new DpwsServiceDescriptions(reader, type); #if DEBUG Microsoft.SPOT.Debug.Assert(XmlReaderHelper.HasReadCompleteNode(depth, reader)); #endif return(matches); } finally { reader.Close(); } }