/// <summary> /// Sends a directed Probe request and parses ProbeMatches responses. /// </summary> /// <param name="endpointAddress"> /// A string containing a Dpws devices transport endpoint address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="targetServiceAddress"> /// A string containing the target service address to probe for. /// 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> /// <remarks> /// A directed Probe is used to discover services on a network. The DirectedProbe method sends a /// HTTP request to the service specified endpointAddress parameter. A service at the endpoint that /// implements matching types specified in the filters parameter should respond with a ProbeMatches /// message. The ProbeMatches mesgage is returned as the response to the DirectedProbe request. /// If a null filter is supplied any Dpws complient service should reply with a ProbeMatches reponse. /// This method is used to directly ask for service endpoint information. /// </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> /// <exception cref="InvalidOperationException">If a fault response is received.</exception> public DpwsServiceDescriptions DirectedProbe(string endpointAddress, string targetServiceAddress, DpwsServiceTypes filters) { // Build the probe request message string messageID = null; byte[] probeRequest = BuildProbeRequest(targetServiceAddress, filters, out messageID); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending DirectedProbe:"); System.Ext.Console.Write(new string(new UTF8Encoding().GetChars(probeRequest))); System.Ext.Console.Write(""); // Create an http client and send the probe request. Use a WspHttpClient to get an array response. WsHttpClient httpClient = new WsHttpClient(); byte[] probeResponse = httpClient.SendRequest(probeRequest, endpointAddress, false, false); // Build probe matches collection DpwsServiceDescriptions probeMatches = new DpwsServiceDescriptions(); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); if (probeResponse != null) { System.Ext.Console.Write(""); System.Ext.Console.Write("ProbeMatches Response From: " + endpointAddress); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(probeResponse))); try { DpwsServiceDescriptions tempMatches = soapProcessor.ProcessProbeMatch(probeResponse, messageID, null, null); if (tempMatches != null) { int count = tempMatches.Count; for (int i = 0; i < count; i++) { probeMatches.Add(tempMatches[i]); } } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); } } if (probeMatches.Count == 0) { return(null); } else { return(probeMatches); } }
/// <summary> /// Sends a directed Resolve request and parses ResolveMatch response. /// </summary> /// <param name="endpointAddress"> /// A string containing a Dpws devices transport endpoint address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="serviceAddress"> /// A string containing the address of a service that will handle the resolve request. /// For example: urn:uuid:2bcdd1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="targetServiceAddress"> /// A string containing the address of a service that can process the resolve request. /// For example: urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <remarks> /// A Resolve is used to resolve the transport address of a know service. The request contains a service /// address aquired from configuration or a previous Resolve or Metadata Get request. /// The DirectedResolve method sends a Http request to the specified endpoint address. /// If the endpoint contains a device with this address receives the request, it must send a unicast ResolveMatches /// response back to the client that made the request. /// </remarks> /// <returns> /// A collection of ResolveMatches objects. A ResolveMatch object contains endpoint details used /// used to locate the actual service on a network and the types supported by the service. /// </returns> public DpwsServiceDescription DirectedResolve(string endpointAddress, string serviceAddress, string targetServiceAddress) { String messageID = ""; WsMessage resolveRequest = BuildResolveRequest(targetServiceAddress, serviceAddress, ref messageID); if (resolveRequest == null) { return(null); } System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Resolve:"); System.Ext.Console.Write(resolveRequest.Body as byte[]); // Create an http client and send the resolve request. Use a WspHttpClient to get an array response. WsHttpClient httpClient = new WsHttpClient(m_version); WsMessage resolveResponse = httpClient.SendRequest(resolveRequest, new Uri(endpointAddress)); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(m_version); DpwsServiceDescription resolveMatch = soapProcessor.ProcessResolveMatch(resolveResponse, messageID, null, null); return(resolveMatch); }
/// <summary> /// Sends a directed Resolve request and parses ResolveMatch response. /// </summary> /// <param name="endpointAddress"> /// A string containing a Dpws devices transport endpoint address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="serviceAddress"> /// A string containing the address of a service that will handle the resolve request. /// For example: urn:uuid:2bcdd1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="targetServiceAddress"> /// A string containing the address of a service that can process the resolve request. /// For example: urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <remarks> /// A Resolve is used to resolve the transport address of a know service. The request contains a service /// address aquired from configuration or a previous Resolve or Metadata Get request. /// The DirectedResolve method sends a Http request to the specified endpoint address. /// If the endpoint contains a device with this address receives the request, it must send a unicast ResolveMatches /// response back to the client that made the request. /// </remarks> /// <returns> /// A collection of ResolveMatches objects. A ResolveMatch object contains endpoint details used /// used to locate the actual service on a network and the types supported by the service. /// </returns> public DpwsServiceDescription DirectedResolve(string endpointAddress, string serviceAddress, string targetServiceAddress) { String messageID = ""; byte[] resolveRequest = BuildResolveRequest(targetServiceAddress, serviceAddress, ref messageID); if (resolveRequest == null) { return(null); } System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Resolve:"); System.Ext.Console.Write(new string(new UTF8Encoding().GetChars(resolveRequest))); // Create an http client and send the resolve request. Use a WspHttpClient to get an array response. WsHttpClient httpClient = new WsHttpClient(); byte[] resolveResponse = httpClient.SendRequest(resolveRequest, endpointAddress, false, false); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); DpwsServiceDescription resolveMatch = soapProcessor.ProcessResolveMatch(resolveResponse, messageID, null, null); return(resolveMatch); }
/// <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)) { IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()), m_discoResponsePort); udpClient.Bind(localEP); // Very important - Set default multicast interface for the underlying socket udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)WsNetworkServices.GetLocalIPV4AddressValue()); udpClient.ReceiveTimeout = m_receiveTimeout; // 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)) { IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()), m_discoResponsePort); udpClient.Bind(localEP); // Very important - Set default multicast interface for the underlying socket udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)WsNetworkServices.GetLocalIPV4AddressValue()); udpClient.ReceiveTimeout = timeout; // 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> /// Sends a directed Resolve request and parses ResolveMatch response. /// </summary> /// <param name="endpointAddress"> /// A string containing a Dpws devices transport endpoint address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="serviceAddress"> /// A string containing the address of a service that will handle the resolve request. /// For example: urn:uuid:2bcdd1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="targetServiceAddress"> /// A string containing the address of a service that can process the resolve request. /// For example: urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <remarks> /// A Resolve is used to resolve the transport address of a know service. The request contains a service /// address aquired from configuration or a previous Resolve or Metadata Get request. /// The DirectedResolve method sends a Http request to the specified endpoint address. /// If the endpoint contains a device with this address receives the request, it must send a unicast ResolveMatches /// response back to the client that made the request. /// </remarks> /// <returns> /// A collection of ResolveMatches objects. A ResolveMatch object contains endpoint details used /// used to locate the actual service on a network and the types supported by the service. /// </returns> public DpwsServiceDescription DirectedResolve(string endpointAddress, string serviceAddress, string targetServiceAddress) { String messageID = ""; WsMessage resolveRequest = BuildResolveRequest(targetServiceAddress, serviceAddress, ref messageID); if (resolveRequest == null) return null; System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Resolve:"); System.Ext.Console.Write(resolveRequest.Body as byte[]); // Create an http client and send the resolve request. Use a WspHttpClient to get an array response. WsHttpClient httpClient = new WsHttpClient(m_version); WsMessage resolveResponse = httpClient.SendRequest(resolveRequest, new Uri(endpointAddress)); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(m_version); DpwsServiceDescription resolveMatch = soapProcessor.ProcessResolveMatch(resolveResponse, messageID, null, null); return resolveMatch; }
/// <summary> /// Sends a directed Probe request and parses ProbeMatches responses. /// </summary> /// <param name="endpointAddress"> /// A string containing a Dpws devices transport endpoint address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="targetServiceAddress"> /// A string containing the target service address to probe for. /// 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> /// <remarks> /// A directed Probe is used to discover services on a network. The DirectedProbe method sends a /// HTTP request to the service specified endpointAddress parameter. A service at the endpoint that /// implements matching types specified in the filters parameter should respond with a ProbeMatches /// message. The ProbeMatches mesgage is returned as the response to the DirectedProbe request. /// If a null filter is supplied any Dpws complient service should reply with a ProbeMatches reponse. /// This method is used to directly ask for service endpoint information. /// </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> /// <exception cref="InvalidOperationException">If a fault response is received.</exception> public DpwsServiceDescriptions DirectedProbe(string endpointAddress, string targetServiceAddress, DpwsServiceTypes filters) { // Build the probe request message string messageID = null; WsMessage probeRequest = BuildProbeRequest(targetServiceAddress, filters, out messageID); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending DirectedProbe:"); System.Ext.Console.Write(probeRequest.Body as byte[]); System.Ext.Console.Write(""); // Create an http client and send the probe request. Use a WspHttpClient to get an array response. WsHttpClient httpClient = new WsHttpClient(m_version); WsMessage probeResponse = httpClient.SendRequest(probeRequest, new Uri(endpointAddress)); // Build probe matches collection DpwsServiceDescriptions probeMatches = new DpwsServiceDescriptions(); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(m_version); if (probeResponse != null) { System.Ext.Console.Write(""); System.Ext.Console.Write("ProbeMatches Response From: " + endpointAddress); System.Ext.Console.Write(probeResponse.Body as byte[]); try { DpwsServiceDescriptions tempMatches = soapProcessor.ProcessProbeMatch(probeResponse, messageID, null, null); if (tempMatches != null) { int count = tempMatches.Count; for (int i = 0; i < count; i++) { probeMatches.Add(tempMatches[i]); } } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); } } if (probeMatches.Count == 0) return null; else return probeMatches; }
/// <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 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(); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Resolve:"); System.Ext.Console.Write(new string(new UTF8Encoding().GetChars(message))); // Create a new UdpClient Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint localEP = new IPEndPoint(IPAddress.Any, m_discoResponsePort); udpClient.Bind(localEP); // Very important - Set default multicast interface for the underlying socket byte[] ipBytes = IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()).GetAddressBytes(); long longIP = (long)((ipBytes[0] + (ipBytes[1] << 0x08) + (ipBytes[2] << 0x10) + (ipBytes[3] << 0x18)) & 0xFFFFFFFF); udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)longIP); // Random back off implemented as per soap over udp specification // for unreliable multicast message exchange SendWithBackoff(message, udpClient); // Wait for resolve match as long a timeout has not expired DpwsServiceDescription resolveMatch = null; byte[] resolveResponse = new byte[c_MaxUdpPacketSize]; EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int responseLength; long endTime = (long)(DateTime.Now.Ticks + (timeout * 10000)); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); while (DateTime.Now.Ticks < endTime) { if (udpClient.Available > 0) { // 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 (se.ErrorCode == 10054) continue; throw se; } // If we received process resolve match if (responseLength > 0) { System.Ext.Console.Write(""); System.Ext.Console.Write("ResolveMatches Response From: " + ((IPEndPoint)remoteEP).Address.ToString()); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(resolveResponse))); try { resolveMatch = soapProcessor.ProcessResolveMatch(resolveResponse, messageID, (IPEndPoint)remoteEP, messageCheck); if (resolveMatch != null) break; } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); } } } Thread.Sleep(10); } udpClient.Close(); udpClient = null; // 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; byte[] probeRequest = BuildProbeRequest(DiscoVersion.WellKnownAddress, filters, out messageID); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Probe:"); System.Ext.Console.Write(new string(new UTF8Encoding().GetChars(probeRequest))); System.Ext.Console.Write(""); // Create a new UdpClient Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint localEP = new IPEndPoint(IPAddress.Any, m_discoResponsePort); udpClient.Bind(localEP); // Very important - Set default multicast interface for the underlying socket byte[] ipBytes = IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()).GetAddressBytes(); long longIP = (long)((ipBytes[0] + (ipBytes[1] << 0x08) + (ipBytes[2] << 0x10) + (ipBytes[3] << 0x18)) & 0xFFFFFFFF); udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)longIP); // Random back off implemented as per soap over udp specification // for unreliable multicast message exchange SendWithBackoff(probeRequest, udpClient); // Create probe matches collection and set expiration loop timer DpwsServiceDescriptions probeMatches = new DpwsServiceDescriptions(); byte[] probeResponse = new byte[c_MaxUdpPacketSize]; EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int responseLength; // Multiply receive time by 10000 to convert milliseconds to 100 nano ticks long endTime = (long)(DateTime.Now.Ticks + (timeout < 0 ? m_receiveTimeout * 10000 : timeout * 10000)); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); // Build probe matches collection as long as timeout has not expired int noReceived = 0; while (DateTime.Now.Ticks < endTime) { if (udpClient.Available > 0) { // If maxProbeRequest is set check count if (maxProbeMatches > 0) { if (noReceived > maxProbeMatches) break; } // 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 (se.ErrorCode == 10054) continue; 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(new String(System.Text.Encoding.UTF8.GetChars(probeResponse))); // Process the response try { DpwsServiceDescriptions tempMatches = soapProcessor.ProcessProbeMatch(probeResponse, messageID, (IPEndPoint)remoteEP, messageCheck); if (tempMatches != null) { int count = tempMatches.Count; for (int i = 0; i < count; i++) { probeMatches.Add(tempMatches[i]); } } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); } // Increment the number received counter ++noReceived; } } else { Thread.Sleep(1); } } udpClient.Close(); udpClient = null; // Display results if (probeMatches == null) System.Ext.Console.Write("Probe timed out."); else System.Ext.Console.Write("Received " + probeMatches.Count + " probeMatches matches."); return probeMatches; }
/// <summary> /// Sends a directed Resolve request and parses ResolveMatch response. /// </summary> /// <param name="endpointAddress"> /// A string containing a Dpws devices transport endpoint address. /// For example: http://192.168.0.1:8084/3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="serviceAddress"> /// A string containing the address of a service that will handle the resolve request. /// For example: urn:uuid:2bcdd1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <param name="targetServiceAddress"> /// A string containing the address of a service that can process the resolve request. /// For example: urn:uuid:3cb0d1ba-cc3a-46ce-b416-212ac2419b20 /// </param> /// <remarks> /// A Resolve is used to resolve the transport address of a know service. The request contains a service /// address aquired from configuration or a previous Resolve or Metadata Get request. /// The DirectedResolve method sends a Http request to the specified endpoint address. /// If the endpoint contains a device with this address receives the request, it must send a unicast ResolveMatches /// response back to the client that made the request. /// </remarks> /// <returns> /// A collection of ResolveMatches objects. A ResolveMatch object contains endpoint details used /// used to locate the actual service on a network and the types supported by the service. /// </returns> public DpwsServiceDescription DirectedResolve(string endpointAddress, string serviceAddress, string targetServiceAddress) { String messageID = ""; byte[] resolveRequest = BuildResolveRequest(targetServiceAddress, serviceAddress, ref messageID); if (resolveRequest == null) return null; System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Resolve:"); System.Ext.Console.Write(new string(new UTF8Encoding().GetChars(resolveRequest))); // Create an http client and send the resolve request. Use a WspHttpClient to get an array response. WsHttpClient httpClient = new WsHttpClient(); byte[] resolveResponse = httpClient.SendRequest(resolveRequest, endpointAddress, false, false); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); DpwsServiceDescription resolveMatch = soapProcessor.ProcessResolveMatch(resolveResponse, messageID, null, null); return resolveMatch; }
/// <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 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 m_version.AnonymousUri, // 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> /// 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(); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Resolve:"); System.Ext.Console.Write(new string(new UTF8Encoding().GetChars(message))); // Create a new UdpClient Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint localEP = new IPEndPoint(IPAddress.Any, m_discoResponsePort); udpClient.Bind(localEP); // Very important - Set default multicast interface for the underlying socket byte[] ipBytes = IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()).GetAddressBytes(); long longIP = (long)((ipBytes[0] + (ipBytes[1] << 0x08) + (ipBytes[2] << 0x10) + (ipBytes[3] << 0x18)) & 0xFFFFFFFF); udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)longIP); // Random back off implemented as per soap over udp specification // for unreliable multicast message exchange SendWithBackoff(message, udpClient); // Wait for resolve match as long a timeout has not expired DpwsServiceDescription resolveMatch = null; byte[] resolveResponse = new byte[c_MaxUdpPacketSize]; EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int responseLength; long endTime = (long)(DateTime.Now.Ticks + (timeout * 10000)); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); while (DateTime.Now.Ticks < endTime) { if (udpClient.Available > 0) { // 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 (se.ErrorCode == 10054) { continue; } throw se; } // If we received process resolve match if (responseLength > 0) { System.Ext.Console.Write(""); System.Ext.Console.Write("ResolveMatches Response From: " + ((IPEndPoint)remoteEP).Address.ToString()); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(resolveResponse))); try { resolveMatch = soapProcessor.ProcessResolveMatch(resolveResponse, messageID, (IPEndPoint)remoteEP, messageCheck); if (resolveMatch != null) { break; } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); } } } Thread.Sleep(10); } udpClient.Close(); udpClient = null; // 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; byte[] probeRequest = BuildProbeRequest(DiscoVersion.WellKnownAddress, filters, out messageID); System.Ext.Console.Write(""); System.Ext.Console.Write("Sending Probe:"); System.Ext.Console.Write(new string(new UTF8Encoding().GetChars(probeRequest))); System.Ext.Console.Write(""); // Create a new UdpClient Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint localEP = new IPEndPoint(IPAddress.Any, m_discoResponsePort); udpClient.Bind(localEP); // Very important - Set default multicast interface for the underlying socket byte[] ipBytes = IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address()).GetAddressBytes(); long longIP = (long)((ipBytes[0] + (ipBytes[1] << 0x08) + (ipBytes[2] << 0x10) + (ipBytes[3] << 0x18)) & 0xFFFFFFFF); udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)longIP); // Random back off implemented as per soap over udp specification // for unreliable multicast message exchange SendWithBackoff(probeRequest, udpClient); // Create probe matches collection and set expiration loop timer DpwsServiceDescriptions probeMatches = new DpwsServiceDescriptions(); byte[] probeResponse = new byte[c_MaxUdpPacketSize]; EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int responseLength; // Multiply receive time by 10000 to convert milliseconds to 100 nano ticks long endTime = (long)(DateTime.Now.Ticks + (timeout < 0 ? m_receiveTimeout * 10000 : timeout * 10000)); DpwsDiscoClientProcessor soapProcessor = new DpwsDiscoClientProcessor(); // Build probe matches collection as long as timeout has not expired int noReceived = 0; while (DateTime.Now.Ticks < endTime) { if (udpClient.Available > 0) { // If maxProbeRequest is set check count if (maxProbeMatches > 0) { if (noReceived > maxProbeMatches) { break; } } // 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 (se.ErrorCode == 10054) { continue; } 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(new String(System.Text.Encoding.UTF8.GetChars(probeResponse))); // Process the response try { DpwsServiceDescriptions tempMatches = soapProcessor.ProcessProbeMatch(probeResponse, messageID, (IPEndPoint)remoteEP, messageCheck); if (tempMatches != null) { int count = tempMatches.Count; for (int i = 0; i < count; i++) { probeMatches.Add(tempMatches[i]); } } } catch (Exception e) { System.Ext.Console.Write(""); System.Ext.Console.Write(e.Message); System.Ext.Console.Write(""); } // Increment the number received counter ++noReceived; } } else { Thread.Sleep(1); } } udpClient.Close(); udpClient = null; // Display results if (probeMatches == null) { System.Ext.Console.Write("Probe timed out."); } else { System.Ext.Console.Write("Received " + probeMatches.Count + " probeMatches matches."); } return(probeMatches); }
/// <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> /// 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> /// 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; } }